Commit 125f42b0 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'nfs-for-4.12-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull NFS client bugfixes from Trond Myklebust:
 "Bugfixes include:

   - Fix a typo in commit e0926934 ("NFS append COMMIT after
     synchronous COPY") that breaks copy offload

   - Fix the connect error propagation in xs_tcp_setup_socket()

   - Fix a lock leak in nfs40_walk_client_list

   - Verify that pNFS requests lie within the offset range of the layout
     segment"

* tag 'nfs-for-4.12-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  nfs: Mark unnecessarily extern functions as static
  SUNRPC: ensure correct error is reported by xs_tcp_setup_socket()
  NFSv4.0: Fix a lock leak in nfs40_walk_client_list
  pnfs: Fix the check for requests in range of layout segment
  xprtrdma: Delete an error message for a failed memory allocation in xprt_rdma_bc_setup()
  pNFS/flexfiles: missing error code in ff_layout_alloc_lseg()
  NFS fix COMMIT after COPY
parents 3c06e6cb 4f253e1e
...@@ -454,6 +454,7 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh, ...@@ -454,6 +454,7 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh,
goto out_err_free; goto out_err_free;
/* fh */ /* fh */
rc = -EIO;
p = xdr_inline_decode(&stream, 4); p = xdr_inline_decode(&stream, 4);
if (!p) if (!p)
goto out_err_free; goto out_err_free;
......
...@@ -398,7 +398,6 @@ extern struct file_system_type nfs4_referral_fs_type; ...@@ -398,7 +398,6 @@ extern struct file_system_type nfs4_referral_fs_type;
bool nfs_auth_info_match(const struct nfs_auth_info *, rpc_authflavor_t); bool nfs_auth_info_match(const struct nfs_auth_info *, rpc_authflavor_t);
struct dentry *nfs_try_mount(int, const char *, struct nfs_mount_info *, struct dentry *nfs_try_mount(int, const char *, struct nfs_mount_info *,
struct nfs_subversion *); struct nfs_subversion *);
void nfs_initialise_sb(struct super_block *);
int nfs_set_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *); int nfs_set_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
int nfs_clone_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *); int nfs_clone_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
struct dentry *nfs_fs_mount_common(struct nfs_server *, int, const char *, struct dentry *nfs_fs_mount_common(struct nfs_server *, int, const char *,
...@@ -458,7 +457,6 @@ extern void nfs_read_prepare(struct rpc_task *task, void *calldata); ...@@ -458,7 +457,6 @@ extern void nfs_read_prepare(struct rpc_task *task, void *calldata);
extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);
/* super.c */ /* super.c */
void nfs_clone_super(struct super_block *, struct nfs_mount_info *);
void nfs_umount_begin(struct super_block *); void nfs_umount_begin(struct super_block *);
int nfs_statfs(struct dentry *, struct kstatfs *); int nfs_statfs(struct dentry *, struct kstatfs *);
int nfs_show_options(struct seq_file *, struct dentry *); int nfs_show_options(struct seq_file *, struct dentry *);
......
...@@ -177,7 +177,7 @@ static ssize_t _nfs42_proc_copy(struct file *src, ...@@ -177,7 +177,7 @@ static ssize_t _nfs42_proc_copy(struct file *src,
if (status) if (status)
goto out; goto out;
if (!nfs_write_verifier_cmp(&res->write_res.verifier.verifier, if (nfs_write_verifier_cmp(&res->write_res.verifier.verifier,
&res->commit_res.verf->verifier)) { &res->commit_res.verf->verifier)) {
status = -EAGAIN; status = -EAGAIN;
goto out; goto out;
......
...@@ -582,7 +582,6 @@ int nfs40_walk_client_list(struct nfs_client *new, ...@@ -582,7 +582,6 @@ int nfs40_walk_client_list(struct nfs_client *new,
*/ */
nfs4_schedule_path_down_recovery(pos); nfs4_schedule_path_down_recovery(pos);
default: default:
spin_lock(&nn->nfs_client_lock);
goto out; goto out;
} }
......
...@@ -2094,12 +2094,26 @@ pnfs_generic_pg_check_layout(struct nfs_pageio_descriptor *pgio) ...@@ -2094,12 +2094,26 @@ pnfs_generic_pg_check_layout(struct nfs_pageio_descriptor *pgio)
} }
EXPORT_SYMBOL_GPL(pnfs_generic_pg_check_layout); EXPORT_SYMBOL_GPL(pnfs_generic_pg_check_layout);
/*
* Check for any intersection between the request and the pgio->pg_lseg,
* and if none, put this pgio->pg_lseg away.
*/
static void
pnfs_generic_pg_check_range(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
{
if (pgio->pg_lseg && !pnfs_lseg_request_intersecting(pgio->pg_lseg, req)) {
pnfs_put_lseg(pgio->pg_lseg);
pgio->pg_lseg = NULL;
}
}
void void
pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
{ {
u64 rd_size = req->wb_bytes; u64 rd_size = req->wb_bytes;
pnfs_generic_pg_check_layout(pgio); pnfs_generic_pg_check_layout(pgio);
pnfs_generic_pg_check_range(pgio, req);
if (pgio->pg_lseg == NULL) { if (pgio->pg_lseg == NULL) {
if (pgio->pg_dreq == NULL) if (pgio->pg_dreq == NULL)
rd_size = i_size_read(pgio->pg_inode) - req_offset(req); rd_size = i_size_read(pgio->pg_inode) - req_offset(req);
...@@ -2131,6 +2145,7 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, ...@@ -2131,6 +2145,7 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio,
struct nfs_page *req, u64 wb_size) struct nfs_page *req, u64 wb_size)
{ {
pnfs_generic_pg_check_layout(pgio); pnfs_generic_pg_check_layout(pgio);
pnfs_generic_pg_check_range(pgio, req);
if (pgio->pg_lseg == NULL) { if (pgio->pg_lseg == NULL) {
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
req->wb_context, req->wb_context,
...@@ -2191,16 +2206,10 @@ pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, ...@@ -2191,16 +2206,10 @@ pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio,
seg_end = pnfs_end_offset(pgio->pg_lseg->pls_range.offset, seg_end = pnfs_end_offset(pgio->pg_lseg->pls_range.offset,
pgio->pg_lseg->pls_range.length); pgio->pg_lseg->pls_range.length);
req_start = req_offset(req); req_start = req_offset(req);
WARN_ON_ONCE(req_start >= seg_end);
/* start of request is past the last byte of this segment */ /* start of request is past the last byte of this segment */
if (req_start >= seg_end) { if (req_start >= seg_end)
/* reference the new lseg */
if (pgio->pg_ops->pg_cleanup)
pgio->pg_ops->pg_cleanup(pgio);
if (pgio->pg_ops->pg_init)
pgio->pg_ops->pg_init(pgio, req);
return 0; return 0;
}
/* adjust 'size' iff there are fewer bytes left in the /* adjust 'size' iff there are fewer bytes left in the
* segment than what nfs_generic_pg_test returned */ * segment than what nfs_generic_pg_test returned */
......
...@@ -593,6 +593,16 @@ pnfs_lseg_range_intersecting(const struct pnfs_layout_range *l1, ...@@ -593,6 +593,16 @@ pnfs_lseg_range_intersecting(const struct pnfs_layout_range *l1,
return pnfs_is_range_intersecting(l1->offset, end1, l2->offset, end2); return pnfs_is_range_intersecting(l1->offset, end1, l2->offset, end2);
} }
static inline bool
pnfs_lseg_request_intersecting(struct pnfs_layout_segment *lseg, struct nfs_page *req)
{
u64 seg_last = pnfs_end_offset(lseg->pls_range.offset, lseg->pls_range.length);
u64 req_last = req_offset(req) + req->wb_bytes;
return pnfs_is_range_intersecting(lseg->pls_range.offset, seg_last,
req_offset(req), req_last);
}
extern unsigned int layoutstats_timer; extern unsigned int layoutstats_timer;
#ifdef NFS_DEBUG #ifdef NFS_DEBUG
......
...@@ -2301,7 +2301,7 @@ EXPORT_SYMBOL_GPL(nfs_remount); ...@@ -2301,7 +2301,7 @@ EXPORT_SYMBOL_GPL(nfs_remount);
/* /*
* Initialise the common bits of the superblock * Initialise the common bits of the superblock
*/ */
inline void nfs_initialise_sb(struct super_block *sb) static void nfs_initialise_sb(struct super_block *sb)
{ {
struct nfs_server *server = NFS_SB(sb); struct nfs_server *server = NFS_SB(sb);
...@@ -2348,7 +2348,8 @@ EXPORT_SYMBOL_GPL(nfs_fill_super); ...@@ -2348,7 +2348,8 @@ EXPORT_SYMBOL_GPL(nfs_fill_super);
/* /*
* Finish setting up a cloned NFS2/3/4 superblock * Finish setting up a cloned NFS2/3/4 superblock
*/ */
void nfs_clone_super(struct super_block *sb, struct nfs_mount_info *mount_info) static void nfs_clone_super(struct super_block *sb,
struct nfs_mount_info *mount_info)
{ {
const struct super_block *old_sb = mount_info->cloned->sb; const struct super_block *old_sb = mount_info->cloned->sb;
struct nfs_server *server = NFS_SB(sb); struct nfs_server *server = NFS_SB(sb);
......
...@@ -119,11 +119,9 @@ int xprt_rdma_bc_setup(struct rpc_xprt *xprt, unsigned int reqs) ...@@ -119,11 +119,9 @@ int xprt_rdma_bc_setup(struct rpc_xprt *xprt, unsigned int reqs)
for (i = 0; i < (reqs << 1); i++) { for (i = 0; i < (reqs << 1); i++) {
rqst = kzalloc(sizeof(*rqst), GFP_KERNEL); rqst = kzalloc(sizeof(*rqst), GFP_KERNEL);
if (!rqst) { if (!rqst)
pr_err("RPC: %s: Failed to create bc rpc_rqst\n",
__func__);
goto out_free; goto out_free;
}
dprintk("RPC: %s: new rqst %p\n", __func__, rqst); dprintk("RPC: %s: new rqst %p\n", __func__, rqst);
rqst->rq_xprt = &r_xprt->rx_xprt; rqst->rq_xprt = &r_xprt->rx_xprt;
......
...@@ -2432,7 +2432,12 @@ static void xs_tcp_setup_socket(struct work_struct *work) ...@@ -2432,7 +2432,12 @@ static void xs_tcp_setup_socket(struct work_struct *work)
case -ENETUNREACH: case -ENETUNREACH:
case -EADDRINUSE: case -EADDRINUSE:
case -ENOBUFS: case -ENOBUFS:
/* retry with existing socket, after a delay */ /*
* xs_tcp_force_close() wakes tasks with -EIO.
* We need to wake them first to ensure the
* correct error code.
*/
xprt_wake_pending_tasks(xprt, status);
xs_tcp_force_close(xprt); xs_tcp_force_close(xprt);
goto out; goto out;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment