Skip to content

Commit e6251ab

Browse files
committed
Merge tag 'nfs-for-5.17-2' of git://git.linux-nfs.org/projects/anna/linux-nfs
Pull NFS client fixes from Anna Schumaker: "Stable Fixes: - Fix initialization of nfs_client cl_flags Other Fixes: - Fix performance issues with uncached readdir calls - Fix potential pointer dereferences in rpcrdma_ep_create - Fix nfs4_proc_get_locations() kernel-doc comment - Fix locking during sunrpc sysfs reads - Update my email address in the MAINTAINERS file to my new kernel.org email" * tag 'nfs-for-5.17-2' of git://git.linux-nfs.org/projects/anna/linux-nfs: SUNRPC: lock against ->sock changing during sysfs read MAINTAINERS: Update my email address NFS: Fix nfs4_proc_get_locations() kernel-doc comment xprtrdma: fix pointer derefs in error cases of rpcrdma_ep_create NFS: Fix initialisation of nfs_client cl_flags field NFS: Avoid duplicate uncached readdir calls on eof NFS: Don't skip directory entries when doing uncached readdir NFS: Don't overfill uncached readdir pages
2 parents 555f3d7 + b49ea67 commit e6251ab

File tree

8 files changed

+36
-11
lines changed

8 files changed

+36
-11
lines changed

MAINTAINERS

+1-1
Original file line numberDiff line numberDiff line change
@@ -13571,7 +13571,7 @@ F: tools/testing/selftests/nci/
1357113571

1357213572
NFS, SUNRPC, AND LOCKD CLIENTS
1357313573
M: Trond Myklebust <[email protected]>
13574-
M: Anna Schumaker <anna[email protected]>
13574+
M: Anna Schumaker <anna@kernel.org>
1357513575
1357613576
S: Maintained
1357713577
W: http://client.linux-nfs.org

fs/nfs/client.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
177177
INIT_LIST_HEAD(&clp->cl_superblocks);
178178
clp->cl_rpcclient = ERR_PTR(-EINVAL);
179179

180+
clp->cl_flags = cl_init->init_flags;
180181
clp->cl_proto = cl_init->proto;
181182
clp->cl_nconnect = cl_init->nconnect;
182183
clp->cl_max_connect = cl_init->max_connect ? cl_init->max_connect : 1;
@@ -423,7 +424,6 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init)
423424
list_add_tail(&new->cl_share_link,
424425
&nn->nfs_client_list);
425426
spin_unlock(&nn->nfs_client_lock);
426-
new->cl_flags = cl_init->init_flags;
427427
return rpc_ops->init_client(new, cl_init);
428428
}
429429

fs/nfs/dir.c

+18-6
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir
8080
ctx->dir_cookie = 0;
8181
ctx->dup_cookie = 0;
8282
ctx->page_index = 0;
83+
ctx->eof = false;
8384
spin_lock(&dir->i_lock);
8485
if (list_empty(&nfsi->open_files) &&
8586
(nfsi->cache_validity & NFS_INO_DATA_INVAL_DEFER))
@@ -168,6 +169,7 @@ struct nfs_readdir_descriptor {
168169
unsigned int cache_entry_index;
169170
signed char duped;
170171
bool plus;
172+
bool eob;
171173
bool eof;
172174
};
173175

@@ -867,7 +869,8 @@ static int nfs_readdir_xdr_to_array(struct nfs_readdir_descriptor *desc,
867869

868870
status = nfs_readdir_page_filler(desc, entry, pages, pglen,
869871
arrays, narrays);
870-
} while (!status && nfs_readdir_page_needs_filling(page));
872+
} while (!status && nfs_readdir_page_needs_filling(page) &&
873+
page_mapping(page));
871874

872875
nfs_readdir_free_pages(pages, array_size);
873876
out:
@@ -988,7 +991,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc,
988991
ent = &array->array[i];
989992
if (!dir_emit(desc->ctx, ent->name, ent->name_len,
990993
nfs_compat_user_ino64(ent->ino), ent->d_type)) {
991-
desc->eof = true;
994+
desc->eob = true;
992995
break;
993996
}
994997
memcpy(desc->verf, verf, sizeof(desc->verf));
@@ -1004,7 +1007,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc,
10041007
desc->duped = 1;
10051008
}
10061009
if (array->page_is_eof)
1007-
desc->eof = true;
1010+
desc->eof = !desc->eob;
10081011

10091012
kunmap(desc->page);
10101013
dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %llu\n",
@@ -1041,12 +1044,13 @@ static int uncached_readdir(struct nfs_readdir_descriptor *desc)
10411044
goto out;
10421045

10431046
desc->page_index = 0;
1047+
desc->cache_entry_index = 0;
10441048
desc->last_cookie = desc->dir_cookie;
10451049
desc->duped = 0;
10461050

10471051
status = nfs_readdir_xdr_to_array(desc, desc->verf, verf, arrays, sz);
10481052

1049-
for (i = 0; !desc->eof && i < sz && arrays[i]; i++) {
1053+
for (i = 0; !desc->eob && i < sz && arrays[i]; i++) {
10501054
desc->page = arrays[i];
10511055
nfs_do_filldir(desc, verf);
10521056
}
@@ -1105,9 +1109,15 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
11051109
desc->duped = dir_ctx->duped;
11061110
page_index = dir_ctx->page_index;
11071111
desc->attr_gencount = dir_ctx->attr_gencount;
1112+
desc->eof = dir_ctx->eof;
11081113
memcpy(desc->verf, dir_ctx->verf, sizeof(desc->verf));
11091114
spin_unlock(&file->f_lock);
11101115

1116+
if (desc->eof) {
1117+
res = 0;
1118+
goto out_free;
1119+
}
1120+
11111121
if (test_and_clear_bit(NFS_INO_FORCE_READDIR, &nfsi->flags) &&
11121122
list_is_singular(&nfsi->open_files))
11131123
invalidate_mapping_pages(inode->i_mapping, page_index + 1, -1);
@@ -1141,17 +1151,18 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
11411151

11421152
nfs_do_filldir(desc, nfsi->cookieverf);
11431153
nfs_readdir_page_unlock_and_put_cached(desc);
1144-
} while (!desc->eof);
1154+
} while (!desc->eob && !desc->eof);
11451155

11461156
spin_lock(&file->f_lock);
11471157
dir_ctx->dir_cookie = desc->dir_cookie;
11481158
dir_ctx->dup_cookie = desc->dup_cookie;
11491159
dir_ctx->duped = desc->duped;
11501160
dir_ctx->attr_gencount = desc->attr_gencount;
11511161
dir_ctx->page_index = desc->page_index;
1162+
dir_ctx->eof = desc->eof;
11521163
memcpy(dir_ctx->verf, desc->verf, sizeof(dir_ctx->verf));
11531164
spin_unlock(&file->f_lock);
1154-
1165+
out_free:
11551166
kfree(desc);
11561167

11571168
out:
@@ -1193,6 +1204,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int whence)
11931204
if (offset == 0)
11941205
memset(dir_ctx->verf, 0, sizeof(dir_ctx->verf));
11951206
dir_ctx->duped = 0;
1207+
dir_ctx->eof = false;
11961208
}
11971209
spin_unlock(&filp->f_lock);
11981210
return offset;

fs/nfs/nfs4proc.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -8032,7 +8032,8 @@ static int _nfs41_proc_get_locations(struct nfs_server *server,
80328032

80338033
/**
80348034
* nfs4_proc_get_locations - discover locations for a migrated FSID
8035-
* @inode: inode on FSID that is migrating
8035+
* @server: pointer to nfs_server to process
8036+
* @fhandle: pointer to the kernel NFS client file handle
80368037
* @locations: result of query
80378038
* @page: buffer
80388039
* @cred: credential to use for this operation

include/linux/nfs_fs.h

+1
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ struct nfs_open_dir_context {
107107
__u64 dup_cookie;
108108
pgoff_t page_index;
109109
signed char duped;
110+
bool eof;
110111
};
111112

112113
/*

net/sunrpc/sysfs.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,14 @@ static ssize_t rpc_sysfs_xprt_srcaddr_show(struct kobject *kobj,
115115
}
116116

117117
sock = container_of(xprt, struct sock_xprt, xprt);
118-
if (kernel_getsockname(sock->sock, (struct sockaddr *)&saddr) < 0)
118+
mutex_lock(&sock->recv_mutex);
119+
if (sock->sock == NULL ||
120+
kernel_getsockname(sock->sock, (struct sockaddr *)&saddr) < 0)
119121
goto out;
120122

121123
ret = sprintf(buf, "%pISc\n", &saddr);
122124
out:
125+
mutex_unlock(&sock->recv_mutex);
123126
xprt_put(xprt);
124127
return ret + 1;
125128
}

net/sunrpc/xprtrdma/verbs.c

+3
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
413413
IB_POLL_WORKQUEUE);
414414
if (IS_ERR(ep->re_attr.send_cq)) {
415415
rc = PTR_ERR(ep->re_attr.send_cq);
416+
ep->re_attr.send_cq = NULL;
416417
goto out_destroy;
417418
}
418419

@@ -421,6 +422,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
421422
IB_POLL_WORKQUEUE);
422423
if (IS_ERR(ep->re_attr.recv_cq)) {
423424
rc = PTR_ERR(ep->re_attr.recv_cq);
425+
ep->re_attr.recv_cq = NULL;
424426
goto out_destroy;
425427
}
426428
ep->re_receive_count = 0;
@@ -459,6 +461,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
459461
ep->re_pd = ib_alloc_pd(device, 0);
460462
if (IS_ERR(ep->re_pd)) {
461463
rc = PTR_ERR(ep->re_pd);
464+
ep->re_pd = NULL;
462465
goto out_destroy;
463466
}
464467

net/sunrpc/xprtsock.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -1641,7 +1641,12 @@ static int xs_get_srcport(struct sock_xprt *transport)
16411641
unsigned short get_srcport(struct rpc_xprt *xprt)
16421642
{
16431643
struct sock_xprt *sock = container_of(xprt, struct sock_xprt, xprt);
1644-
return xs_sock_getport(sock->sock);
1644+
unsigned short ret = 0;
1645+
mutex_lock(&sock->recv_mutex);
1646+
if (sock->sock)
1647+
ret = xs_sock_getport(sock->sock);
1648+
mutex_unlock(&sock->recv_mutex);
1649+
return ret;
16451650
}
16461651
EXPORT_SYMBOL(get_srcport);
16471652

0 commit comments

Comments
 (0)