Skip to content

Commit fd88e18

Browse files
committed
Merge tag 'nfs-for-6.10-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client fixes from Trond Myklebust: "Bugfixes: - NFSv4.2: Fix a memory leak in nfs4_set_security_label - NFSv2/v3: abort nfs_atomic_open_v23 if the name is too long. - NFS: Add appropriate memory barriers to the sillyrename code - Propagate readlink errors in nfs_symlink_filler - NFS: don't invalidate dentries on transient errors - NFS: fix unnecessary synchronous writes in random write workloads - NFSv4.1: enforce rootpath check when deciding whether or not to trunk Other: - Change email address for Trond Myklebust due to email server concerns" * tag 'nfs-for-6.10-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFS: add barriers when testing for NFS_FSDATA_BLOCKED SUNRPC: return proper error from gss_wrap_req_priv NFSv4.1 enforce rootpath check in fs_location query NFS: abort nfs_atomic_open_v23 if name is too long. nfs: don't invalidate dentries on transient errors nfs: Avoid flushing many pages with NFS_FILE_SYNC nfs: propagate readlink errors in nfs_symlink_filler MAINTAINERS: Change email address for Trond Myklebust NFSv4: Fix memory leak in nfs4_set_security_label
2 parents 3572597 + 99bc9f2 commit fd88e18

File tree

6 files changed

+81
-33
lines changed

6 files changed

+81
-33
lines changed

MAINTAINERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15825,7 +15825,7 @@ F: drivers/nfc/virtual_ncidev.c
1582515825
F: tools/testing/selftests/nci/
1582615826

1582715827
NFS, SUNRPC, AND LOCKD CLIENTS
15828-
M: Trond Myklebust <trond.myklebust@hammerspace.com>
15828+
M: Trond Myklebust <trondmy@kernel.org>
1582915829
M: Anna Schumaker <anna@kernel.org>
1583015830
L: linux-nfs@vger.kernel.org
1583115831
S: Maintained

fs/nfs/dir.c

Lines changed: 48 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1627,7 +1627,16 @@ nfs_lookup_revalidate_done(struct inode *dir, struct dentry *dentry,
16271627
switch (error) {
16281628
case 1:
16291629
break;
1630-
case 0:
1630+
case -ETIMEDOUT:
1631+
if (inode && (IS_ROOT(dentry) ||
1632+
NFS_SERVER(inode)->flags & NFS_MOUNT_SOFTREVAL))
1633+
error = 1;
1634+
break;
1635+
case -ESTALE:
1636+
case -ENOENT:
1637+
error = 0;
1638+
fallthrough;
1639+
default:
16311640
/*
16321641
* We can't d_drop the root of a disconnected tree:
16331642
* its d_hash is on the s_anon list and d_drop() would hide
@@ -1682,18 +1691,8 @@ static int nfs_lookup_revalidate_dentry(struct inode *dir,
16821691

16831692
dir_verifier = nfs_save_change_attribute(dir);
16841693
ret = NFS_PROTO(dir)->lookup(dir, dentry, fhandle, fattr);
1685-
if (ret < 0) {
1686-
switch (ret) {
1687-
case -ESTALE:
1688-
case -ENOENT:
1689-
ret = 0;
1690-
break;
1691-
case -ETIMEDOUT:
1692-
if (NFS_SERVER(inode)->flags & NFS_MOUNT_SOFTREVAL)
1693-
ret = 1;
1694-
}
1694+
if (ret < 0)
16951695
goto out;
1696-
}
16971696

16981697
/* Request help from readdirplus */
16991698
nfs_lookup_advise_force_readdirplus(dir, flags);
@@ -1737,7 +1736,7 @@ nfs_do_lookup_revalidate(struct inode *dir, struct dentry *dentry,
17371736
unsigned int flags)
17381737
{
17391738
struct inode *inode;
1740-
int error;
1739+
int error = 0;
17411740

17421741
nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE);
17431742
inode = d_inode(dentry);
@@ -1782,7 +1781,7 @@ nfs_do_lookup_revalidate(struct inode *dir, struct dentry *dentry,
17821781
out_bad:
17831782
if (flags & LOOKUP_RCU)
17841783
return -ECHILD;
1785-
return nfs_lookup_revalidate_done(dir, dentry, inode, 0);
1784+
return nfs_lookup_revalidate_done(dir, dentry, inode, error);
17861785
}
17871786

17881787
static int
@@ -1804,9 +1803,10 @@ __nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags,
18041803
if (parent != READ_ONCE(dentry->d_parent))
18051804
return -ECHILD;
18061805
} else {
1807-
/* Wait for unlink to complete */
1806+
/* Wait for unlink to complete - see unblock_revalidate() */
18081807
wait_var_event(&dentry->d_fsdata,
1809-
dentry->d_fsdata != NFS_FSDATA_BLOCKED);
1808+
smp_load_acquire(&dentry->d_fsdata)
1809+
!= NFS_FSDATA_BLOCKED);
18101810
parent = dget_parent(dentry);
18111811
ret = reval(d_inode(parent), dentry, flags);
18121812
dput(parent);
@@ -1819,6 +1819,29 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
18191819
return __nfs_lookup_revalidate(dentry, flags, nfs_do_lookup_revalidate);
18201820
}
18211821

1822+
static void block_revalidate(struct dentry *dentry)
1823+
{
1824+
/* old devname - just in case */
1825+
kfree(dentry->d_fsdata);
1826+
1827+
/* Any new reference that could lead to an open
1828+
* will take ->d_lock in lookup_open() -> d_lookup().
1829+
* Holding this lock ensures we cannot race with
1830+
* __nfs_lookup_revalidate() and removes and need
1831+
* for further barriers.
1832+
*/
1833+
lockdep_assert_held(&dentry->d_lock);
1834+
1835+
dentry->d_fsdata = NFS_FSDATA_BLOCKED;
1836+
}
1837+
1838+
static void unblock_revalidate(struct dentry *dentry)
1839+
{
1840+
/* store_release ensures wait_var_event() sees the update */
1841+
smp_store_release(&dentry->d_fsdata, NULL);
1842+
wake_up_var(&dentry->d_fsdata);
1843+
}
1844+
18221845
/*
18231846
* A weaker form of d_revalidate for revalidating just the d_inode(dentry)
18241847
* when we don't really care about the dentry name. This is called when a
@@ -2255,6 +2278,9 @@ int nfs_atomic_open_v23(struct inode *dir, struct dentry *dentry,
22552278
*/
22562279
int error = 0;
22572280

2281+
if (dentry->d_name.len > NFS_SERVER(dir)->namelen)
2282+
return -ENAMETOOLONG;
2283+
22582284
if (open_flags & O_CREAT) {
22592285
file->f_mode |= FMODE_CREATED;
22602286
error = nfs_do_create(dir, dentry, mode, open_flags);
@@ -2549,15 +2575,12 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry)
25492575
spin_unlock(&dentry->d_lock);
25502576
goto out;
25512577
}
2552-
/* old devname */
2553-
kfree(dentry->d_fsdata);
2554-
dentry->d_fsdata = NFS_FSDATA_BLOCKED;
2578+
block_revalidate(dentry);
25552579

25562580
spin_unlock(&dentry->d_lock);
25572581
error = nfs_safe_remove(dentry);
25582582
nfs_dentry_remove_handle_error(dir, dentry, error);
2559-
dentry->d_fsdata = NULL;
2560-
wake_up_var(&dentry->d_fsdata);
2583+
unblock_revalidate(dentry);
25612584
out:
25622585
trace_nfs_unlink_exit(dir, dentry, error);
25632586
return error;
@@ -2664,8 +2687,7 @@ nfs_unblock_rename(struct rpc_task *task, struct nfs_renamedata *data)
26642687
{
26652688
struct dentry *new_dentry = data->new_dentry;
26662689

2667-
new_dentry->d_fsdata = NULL;
2668-
wake_up_var(&new_dentry->d_fsdata);
2690+
unblock_revalidate(new_dentry);
26692691
}
26702692

26712693
/*
@@ -2727,11 +2749,6 @@ int nfs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
27272749
if (WARN_ON(new_dentry->d_flags & DCACHE_NFSFS_RENAMED) ||
27282750
WARN_ON(new_dentry->d_fsdata == NFS_FSDATA_BLOCKED))
27292751
goto out;
2730-
if (new_dentry->d_fsdata) {
2731-
/* old devname */
2732-
kfree(new_dentry->d_fsdata);
2733-
new_dentry->d_fsdata = NULL;
2734-
}
27352752

27362753
spin_lock(&new_dentry->d_lock);
27372754
if (d_count(new_dentry) > 2) {
@@ -2753,7 +2770,7 @@ int nfs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
27532770
new_dentry = dentry;
27542771
new_inode = NULL;
27552772
} else {
2756-
new_dentry->d_fsdata = NFS_FSDATA_BLOCKED;
2773+
block_revalidate(new_dentry);
27572774
must_unblock = true;
27582775
spin_unlock(&new_dentry->d_lock);
27592776
}
@@ -2765,6 +2782,8 @@ int nfs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
27652782
task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry,
27662783
must_unblock ? nfs_unblock_rename : NULL);
27672784
if (IS_ERR(task)) {
2785+
if (must_unblock)
2786+
unblock_revalidate(new_dentry);
27682787
error = PTR_ERR(task);
27692788
goto out;
27702789
}

fs/nfs/nfs4proc.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4023,6 +4023,23 @@ static void test_fs_location_for_trunking(struct nfs4_fs_location *location,
40234023
}
40244024
}
40254025

4026+
static bool _is_same_nfs4_pathname(struct nfs4_pathname *path1,
4027+
struct nfs4_pathname *path2)
4028+
{
4029+
int i;
4030+
4031+
if (path1->ncomponents != path2->ncomponents)
4032+
return false;
4033+
for (i = 0; i < path1->ncomponents; i++) {
4034+
if (path1->components[i].len != path2->components[i].len)
4035+
return false;
4036+
if (memcmp(path1->components[i].data, path2->components[i].data,
4037+
path1->components[i].len))
4038+
return false;
4039+
}
4040+
return true;
4041+
}
4042+
40264043
static int _nfs4_discover_trunking(struct nfs_server *server,
40274044
struct nfs_fh *fhandle)
40284045
{
@@ -4056,9 +4073,13 @@ static int _nfs4_discover_trunking(struct nfs_server *server,
40564073
if (status)
40574074
goto out_free_3;
40584075

4059-
for (i = 0; i < locations->nlocations; i++)
4076+
for (i = 0; i < locations->nlocations; i++) {
4077+
if (!_is_same_nfs4_pathname(&locations->fs_path,
4078+
&locations->locations[i].rootpath))
4079+
continue;
40604080
test_fs_location_for_trunking(&locations->locations[i], clp,
40614081
server);
4082+
}
40624083
out_free_3:
40634084
kfree(locations->fattr);
40644085
out_free_2:
@@ -6268,6 +6289,7 @@ nfs4_set_security_label(struct inode *inode, const void *buf, size_t buflen)
62686289
if (status == 0)
62696290
nfs_setsecurity(inode, fattr);
62706291

6292+
nfs_free_fattr(fattr);
62716293
return status;
62726294
}
62736295
#endif /* CONFIG_NFS_V4_SECURITY_LABEL */

fs/nfs/pagelist.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,6 +1545,11 @@ void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *desc, pgoff_t index)
15451545
continue;
15461546
} else if (index == prev->wb_index + 1)
15471547
continue;
1548+
/*
1549+
* We will submit more requests after these. Indicate
1550+
* this to the underlying layers.
1551+
*/
1552+
desc->pg_moreio = 1;
15481553
nfs_pageio_complete(desc);
15491554
break;
15501555
}

fs/nfs/symlink.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ static int nfs_symlink_filler(struct file *file, struct folio *folio)
4141
error:
4242
folio_set_error(folio);
4343
folio_unlock(folio);
44-
return -EIO;
44+
return error;
4545
}
4646

4747
static const char *nfs_get_link(struct dentry *dentry,

net/sunrpc/auth_gss/auth_gss.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1875,8 +1875,10 @@ gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
18751875
offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base;
18761876
maj_stat = gss_wrap(ctx->gc_gss_ctx, offset, snd_buf, inpages);
18771877
/* slack space should prevent this ever happening: */
1878-
if (unlikely(snd_buf->len > snd_buf->buflen))
1878+
if (unlikely(snd_buf->len > snd_buf->buflen)) {
1879+
status = -EIO;
18791880
goto wrap_failed;
1881+
}
18801882
/* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was
18811883
* done anyway, so it's safe to put the request on the wire: */
18821884
if (maj_stat == GSS_S_CONTEXT_EXPIRED)

0 commit comments

Comments
 (0)