Skip to content

Commit

Permalink
Merge tag 'nfs-for-5.17-2' of git://git.linux-nfs.org/projects/anna/l…
Browse files Browse the repository at this point in the history
…inux-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
  • Loading branch information
Linus Torvalds committed Feb 8, 2022
2 parents 555f3d7 + b49ea67 commit e6251ab
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 11 deletions.
2 changes: 1 addition & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -13571,7 +13571,7 @@ F: tools/testing/selftests/nci/

NFS, SUNRPC, AND LOCKD CLIENTS
M: Trond Myklebust <trond.myklebust@hammerspace.com>
M: Anna Schumaker <anna.schumaker@netapp.com>
M: Anna Schumaker <anna@kernel.org>
L: linux-nfs@vger.kernel.org
S: Maintained
W: http://client.linux-nfs.org
Expand Down
2 changes: 1 addition & 1 deletion fs/nfs/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
INIT_LIST_HEAD(&clp->cl_superblocks);
clp->cl_rpcclient = ERR_PTR(-EINVAL);

clp->cl_flags = cl_init->init_flags;
clp->cl_proto = cl_init->proto;
clp->cl_nconnect = cl_init->nconnect;
clp->cl_max_connect = cl_init->max_connect ? cl_init->max_connect : 1;
Expand Down Expand Up @@ -423,7 +424,6 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init)
list_add_tail(&new->cl_share_link,
&nn->nfs_client_list);
spin_unlock(&nn->nfs_client_lock);
new->cl_flags = cl_init->init_flags;
return rpc_ops->init_client(new, cl_init);
}

Expand Down
24 changes: 18 additions & 6 deletions fs/nfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir
ctx->dir_cookie = 0;
ctx->dup_cookie = 0;
ctx->page_index = 0;
ctx->eof = false;
spin_lock(&dir->i_lock);
if (list_empty(&nfsi->open_files) &&
(nfsi->cache_validity & NFS_INO_DATA_INVAL_DEFER))
Expand Down Expand Up @@ -168,6 +169,7 @@ struct nfs_readdir_descriptor {
unsigned int cache_entry_index;
signed char duped;
bool plus;
bool eob;
bool eof;
};

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

status = nfs_readdir_page_filler(desc, entry, pages, pglen,
arrays, narrays);
} while (!status && nfs_readdir_page_needs_filling(page));
} while (!status && nfs_readdir_page_needs_filling(page) &&
page_mapping(page));

nfs_readdir_free_pages(pages, array_size);
out:
Expand Down Expand Up @@ -988,7 +991,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc,
ent = &array->array[i];
if (!dir_emit(desc->ctx, ent->name, ent->name_len,
nfs_compat_user_ino64(ent->ino), ent->d_type)) {
desc->eof = true;
desc->eob = true;
break;
}
memcpy(desc->verf, verf, sizeof(desc->verf));
Expand All @@ -1004,7 +1007,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc,
desc->duped = 1;
}
if (array->page_is_eof)
desc->eof = true;
desc->eof = !desc->eob;

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

desc->page_index = 0;
desc->cache_entry_index = 0;
desc->last_cookie = desc->dir_cookie;
desc->duped = 0;

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

for (i = 0; !desc->eof && i < sz && arrays[i]; i++) {
for (i = 0; !desc->eob && i < sz && arrays[i]; i++) {
desc->page = arrays[i];
nfs_do_filldir(desc, verf);
}
Expand Down Expand Up @@ -1105,9 +1109,15 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
desc->duped = dir_ctx->duped;
page_index = dir_ctx->page_index;
desc->attr_gencount = dir_ctx->attr_gencount;
desc->eof = dir_ctx->eof;
memcpy(desc->verf, dir_ctx->verf, sizeof(desc->verf));
spin_unlock(&file->f_lock);

if (desc->eof) {
res = 0;
goto out_free;
}

if (test_and_clear_bit(NFS_INO_FORCE_READDIR, &nfsi->flags) &&
list_is_singular(&nfsi->open_files))
invalidate_mapping_pages(inode->i_mapping, page_index + 1, -1);
Expand Down Expand Up @@ -1141,17 +1151,18 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)

nfs_do_filldir(desc, nfsi->cookieverf);
nfs_readdir_page_unlock_and_put_cached(desc);
} while (!desc->eof);
} while (!desc->eob && !desc->eof);

spin_lock(&file->f_lock);
dir_ctx->dir_cookie = desc->dir_cookie;
dir_ctx->dup_cookie = desc->dup_cookie;
dir_ctx->duped = desc->duped;
dir_ctx->attr_gencount = desc->attr_gencount;
dir_ctx->page_index = desc->page_index;
dir_ctx->eof = desc->eof;
memcpy(dir_ctx->verf, desc->verf, sizeof(dir_ctx->verf));
spin_unlock(&file->f_lock);

out_free:
kfree(desc);

out:
Expand Down Expand Up @@ -1193,6 +1204,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int whence)
if (offset == 0)
memset(dir_ctx->verf, 0, sizeof(dir_ctx->verf));
dir_ctx->duped = 0;
dir_ctx->eof = false;
}
spin_unlock(&filp->f_lock);
return offset;
Expand Down
3 changes: 2 additions & 1 deletion fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -8032,7 +8032,8 @@ static int _nfs41_proc_get_locations(struct nfs_server *server,

/**
* nfs4_proc_get_locations - discover locations for a migrated FSID
* @inode: inode on FSID that is migrating
* @server: pointer to nfs_server to process
* @fhandle: pointer to the kernel NFS client file handle
* @locations: result of query
* @page: buffer
* @cred: credential to use for this operation
Expand Down
1 change: 1 addition & 0 deletions include/linux/nfs_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ struct nfs_open_dir_context {
__u64 dup_cookie;
pgoff_t page_index;
signed char duped;
bool eof;
};

/*
Expand Down
5 changes: 4 additions & 1 deletion net/sunrpc/sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,14 @@ static ssize_t rpc_sysfs_xprt_srcaddr_show(struct kobject *kobj,
}

sock = container_of(xprt, struct sock_xprt, xprt);
if (kernel_getsockname(sock->sock, (struct sockaddr *)&saddr) < 0)
mutex_lock(&sock->recv_mutex);
if (sock->sock == NULL ||
kernel_getsockname(sock->sock, (struct sockaddr *)&saddr) < 0)
goto out;

ret = sprintf(buf, "%pISc\n", &saddr);
out:
mutex_unlock(&sock->recv_mutex);
xprt_put(xprt);
return ret + 1;
}
Expand Down
3 changes: 3 additions & 0 deletions net/sunrpc/xprtrdma/verbs.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
IB_POLL_WORKQUEUE);
if (IS_ERR(ep->re_attr.send_cq)) {
rc = PTR_ERR(ep->re_attr.send_cq);
ep->re_attr.send_cq = NULL;
goto out_destroy;
}

Expand All @@ -421,6 +422,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
IB_POLL_WORKQUEUE);
if (IS_ERR(ep->re_attr.recv_cq)) {
rc = PTR_ERR(ep->re_attr.recv_cq);
ep->re_attr.recv_cq = NULL;
goto out_destroy;
}
ep->re_receive_count = 0;
Expand Down Expand Up @@ -459,6 +461,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
ep->re_pd = ib_alloc_pd(device, 0);
if (IS_ERR(ep->re_pd)) {
rc = PTR_ERR(ep->re_pd);
ep->re_pd = NULL;
goto out_destroy;
}

Expand Down
7 changes: 6 additions & 1 deletion net/sunrpc/xprtsock.c
Original file line number Diff line number Diff line change
Expand Up @@ -1641,7 +1641,12 @@ static int xs_get_srcport(struct sock_xprt *transport)
unsigned short get_srcport(struct rpc_xprt *xprt)
{
struct sock_xprt *sock = container_of(xprt, struct sock_xprt, xprt);
return xs_sock_getport(sock->sock);
unsigned short ret = 0;
mutex_lock(&sock->recv_mutex);
if (sock->sock)
ret = xs_sock_getport(sock->sock);
mutex_unlock(&sock->recv_mutex);
return ret;
}
EXPORT_SYMBOL(get_srcport);

Expand Down

0 comments on commit e6251ab

Please sign in to comment.