Merge tag 'nfs-for-3.20-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 21 Feb 2015 22:02:59 +0000 (14:02 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 21 Feb 2015 22:02:59 +0000 (14:02 -0800)
Pull more NFS client updates from Trond Myklebust:
 "Highlights include:

   - Fix a use-after-free in decode_cb_sequence_args()
   - Fix a compile error when #undef CONFIG_PROC_FS
   - NFSv4.1 backchannel spinlocking issue
   - Cleanups in the NFS unstable write code requested by Linus
   - NFSv4.1 fix issues when the server denies our backchannel request
   - Cleanups in create_session and bind_conn_to_session"

* tag 'nfs-for-3.20-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  NFSv4.1: Clean up bind_conn_to_session
  NFSv4.1: Always set up a forward channel when binding the session
  NFSv4.1: Don't set up a backchannel if the server didn't agree to do so
  NFSv4.1: Clean up create_session
  pnfs: Refactor the *_layout_mark_request_commit to use pnfs_layout_mark_request_commit
  NFSv4: Kill unused nfs_inode->delegation_state field
  NFS: struct nfs_commit_info.lock must always point to inode->i_lock
  nfs: Can call nfs_clear_page_commit() instead
  nfs: Provide and use helper functions for marking a page as unstable
  SUNRPC: Always manipulate rpc_rqst::rq_bc_pa_list under xprt->bc_pa_lock
  SUNRPC: Fix a compile error when #undef CONFIG_PROC_FS
  NFSv4.1: Convert open-coded array allocation calls to kmalloc_array()
  NFSv4.1: Fix a kfree() of uninitialised pointers in decode_cb_sequence_args

19 files changed:
fs/nfs/callback_proc.c
fs/nfs/callback_xdr.c
fs/nfs/delegation.c
fs/nfs/direct.c
fs/nfs/filelayout/filelayout.c
fs/nfs/flexfilelayout/flexfilelayout.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/nfs4proc.c
fs/nfs/nfs4session.c
fs/nfs/nfs4session.h
fs/nfs/nfs4xdr.c
fs/nfs/pnfs.h
fs/nfs/pnfs_nfs.c
fs/nfs/write.c
include/linux/nfs_fs.h
include/linux/nfs_xdr.h
include/linux/sunrpc/metrics.h
net/sunrpc/backchannel_rqst.c

index e36a9d78ea49adc63329253a0a94cb22d6be933a..197806fb87ffb459c19f3c4bbc8da50c58c870dc 100644 (file)
@@ -427,6 +427,8 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
        if (clp == NULL)
                goto out;
 
+       if (!(clp->cl_session->flags & SESSION4_BACK_CHAN))
+               goto out;
        tbl = &clp->cl_session->bc_slot_table;
 
        spin_lock(&tbl->slot_tbl_lock);
index f4ccfe6521ec80f80fd4b9096bcc7ed49ab7d795..19ca95cdfd9b0f26aedbbc23f036babf2aeca67a 100644 (file)
@@ -313,7 +313,7 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp,
                goto out;
        }
 
-       args->devs = kmalloc(n * sizeof(*args->devs), GFP_KERNEL);
+       args->devs = kmalloc_array(n, sizeof(*args->devs), GFP_KERNEL);
        if (!args->devs) {
                status = htonl(NFS4ERR_DELAY);
                goto out;
@@ -415,7 +415,7 @@ static __be32 decode_rc_list(struct xdr_stream *xdr,
                             rc_list->rcl_nrefcalls * 2 * sizeof(uint32_t));
                if (unlikely(p == NULL))
                        goto out;
-               rc_list->rcl_refcalls = kmalloc(rc_list->rcl_nrefcalls *
+               rc_list->rcl_refcalls = kmalloc_array(rc_list->rcl_nrefcalls,
                                                sizeof(*rc_list->rcl_refcalls),
                                                GFP_KERNEL);
                if (unlikely(rc_list->rcl_refcalls == NULL))
@@ -464,8 +464,10 @@ static __be32 decode_cb_sequence_args(struct svc_rqst *rqstp,
 
                for (i = 0; i < args->csa_nrclists; i++) {
                        status = decode_rc_list(xdr, &args->csa_rclists[i]);
-                       if (status)
+                       if (status) {
+                               args->csa_nrclists = i;
                                goto out_free;
+                       }
                }
        }
        status = 0;
index da5433230bb1960bc78bafc17ced89f3bca76b65..a1f0685b42ff7d2e42eed249e178ecdbbee7befc 100644 (file)
@@ -180,7 +180,6 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred,
                        delegation->cred = get_rpccred(cred);
                        clear_bit(NFS_DELEGATION_NEED_RECLAIM,
                                  &delegation->flags);
-                       NFS_I(inode)->delegation_state = delegation->type;
                        spin_unlock(&delegation->lock);
                        put_rpccred(oldcred);
                        rcu_read_unlock();
@@ -275,7 +274,6 @@ nfs_detach_delegation_locked(struct nfs_inode *nfsi,
        set_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
        list_del_rcu(&delegation->super_list);
        delegation->inode = NULL;
-       nfsi->delegation_state = 0;
        rcu_assign_pointer(nfsi->delegation, NULL);
        spin_unlock(&delegation->lock);
        return delegation;
@@ -355,7 +353,6 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
                                        &delegation->stateid)) {
                        nfs_update_inplace_delegation(old_delegation,
                                        delegation);
-                       nfsi->delegation_state = old_delegation->type;
                        goto out;
                }
                /*
@@ -379,7 +376,6 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
                        goto out;
        }
        list_add_rcu(&delegation->super_list, &server->delegations);
-       nfsi->delegation_state = delegation->type;
        rcu_assign_pointer(nfsi->delegation, delegation);
        delegation = NULL;
 
index 7077521acdf4609cc57f54da4ce11bb331493632..e907c8cf732e3cff6bc9711ccf0b20c9261cdca2 100644 (file)
@@ -283,7 +283,7 @@ static void nfs_direct_release_pages(struct page **pages, unsigned int npages)
 void nfs_init_cinfo_from_dreq(struct nfs_commit_info *cinfo,
                              struct nfs_direct_req *dreq)
 {
-       cinfo->lock = &dreq->lock;
+       cinfo->lock = &dreq->inode->i_lock;
        cinfo->mds = &dreq->mds_cinfo;
        cinfo->ds = &dreq->ds_cinfo;
        cinfo->dreq = dreq;
index 7ae1c263c5cf03b8d63f1fec359d794174564020..91e88a7ecef0c64354b0278fc01381e0970d2086 100644 (file)
@@ -960,52 +960,19 @@ filelayout_mark_request_commit(struct nfs_page *req,
 {
        struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg);
        u32 i, j;
-       struct list_head *list;
-       struct pnfs_commit_bucket *buckets;
 
        if (fl->commit_through_mds) {
-               list = &cinfo->mds->list;
-               spin_lock(cinfo->lock);
-               goto mds_commit;
-       }
-
-       /* Note that we are calling nfs4_fl_calc_j_index on each page
-        * that ends up being committed to a data server.  An attractive
-        * alternative is to add a field to nfs_write_data and nfs_page
-        * to store the value calculated in filelayout_write_pagelist
-        * and just use that here.
-        */
-       j = nfs4_fl_calc_j_index(lseg, req_offset(req));
-       i = select_bucket_index(fl, j);
-       spin_lock(cinfo->lock);
-       buckets = cinfo->ds->buckets;
-       list = &buckets[i].written;
-       if (list_empty(list)) {
-               /* Non-empty buckets hold a reference on the lseg.  That ref
-                * is normally transferred to the COMMIT call and released
-                * there.  It could also be released if the last req is pulled
-                * off due to a rewrite, in which case it will be done in
-                * pnfs_generic_clear_request_commit
+               nfs_request_add_commit_list(req, &cinfo->mds->list, cinfo);
+       } else {
+               /* Note that we are calling nfs4_fl_calc_j_index on each page
+                * that ends up being committed to a data server.  An attractive
+                * alternative is to add a field to nfs_write_data and nfs_page
+                * to store the value calculated in filelayout_write_pagelist
+                * and just use that here.
                 */
-               buckets[i].wlseg = pnfs_get_lseg(lseg);
-       }
-       set_bit(PG_COMMIT_TO_DS, &req->wb_flags);
-       cinfo->ds->nwritten++;
-
-mds_commit:
-       /* nfs_request_add_commit_list(). We need to add req to list without
-        * dropping cinfo lock.
-        */
-       set_bit(PG_CLEAN, &(req)->wb_flags);
-       nfs_list_add_request(req, list);
-       cinfo->mds->ncommit++;
-       spin_unlock(cinfo->lock);
-       if (!cinfo->dreq) {
-               inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
-               inc_bdi_stat(inode_to_bdi(page_file_mapping(req->wb_page)->host),
-                            BDI_RECLAIMABLE);
-               __mark_inode_dirty(req->wb_context->dentry->d_inode,
-                                  I_DIRTY_DATASYNC);
+               j = nfs4_fl_calc_j_index(lseg, req_offset(req));
+               i = select_bucket_index(fl, j);
+               pnfs_layout_mark_request_commit(req, lseg, cinfo, i);
        }
 }
 
index c22ecaa86c1c27cc2138f1853c27757b11104f17..315cc68945b9d1d3ad00b04e2597e38d7b7c4cab 100644 (file)
@@ -1332,47 +1332,6 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
        return PNFS_ATTEMPTED;
 }
 
-static void
-ff_layout_mark_request_commit(struct nfs_page *req,
-                             struct pnfs_layout_segment *lseg,
-                             struct nfs_commit_info *cinfo,
-                             u32 ds_commit_idx)
-{
-       struct list_head *list;
-       struct pnfs_commit_bucket *buckets;
-
-       spin_lock(cinfo->lock);
-       buckets = cinfo->ds->buckets;
-       list = &buckets[ds_commit_idx].written;
-       if (list_empty(list)) {
-               /* Non-empty buckets hold a reference on the lseg.  That ref
-                * is normally transferred to the COMMIT call and released
-                * there.  It could also be released if the last req is pulled
-                * off due to a rewrite, in which case it will be done in
-                * pnfs_common_clear_request_commit
-                */
-               WARN_ON_ONCE(buckets[ds_commit_idx].wlseg != NULL);
-               buckets[ds_commit_idx].wlseg = pnfs_get_lseg(lseg);
-       }
-       set_bit(PG_COMMIT_TO_DS, &req->wb_flags);
-       cinfo->ds->nwritten++;
-
-       /* nfs_request_add_commit_list(). We need to add req to list without
-        * dropping cinfo lock.
-        */
-       set_bit(PG_CLEAN, &(req)->wb_flags);
-       nfs_list_add_request(req, list);
-       cinfo->mds->ncommit++;
-       spin_unlock(cinfo->lock);
-       if (!cinfo->dreq) {
-               inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
-               inc_bdi_stat(inode_to_bdi(page_file_mapping(req->wb_page)->host),
-                            BDI_RECLAIMABLE);
-               __mark_inode_dirty(req->wb_context->dentry->d_inode,
-                                  I_DIRTY_DATASYNC);
-       }
-}
-
 static u32 calc_ds_index_from_commit(struct pnfs_layout_segment *lseg, u32 i)
 {
        return i;
@@ -1540,7 +1499,7 @@ static struct pnfs_layoutdriver_type flexfilelayout_type = {
        .pg_write_ops           = &ff_layout_pg_write_ops,
        .get_ds_info            = ff_layout_get_ds_info,
        .free_deviceid_node     = ff_layout_free_deveiceid_node,
-       .mark_request_commit    = ff_layout_mark_request_commit,
+       .mark_request_commit    = pnfs_layout_mark_request_commit,
        .clear_request_commit   = pnfs_generic_clear_request_commit,
        .scan_commit_lists      = pnfs_generic_scan_commit_lists,
        .recover_commit_reqs    = pnfs_generic_recover_commit_reqs,
index e4f0dcef8f5455e60676bf70d9d0489107ad7c79..83107be3dd0109ab54c5f2b0c72fa59c64dd8d57 100644 (file)
@@ -1775,7 +1775,6 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi)
 #if IS_ENABLED(CONFIG_NFS_V4)
        INIT_LIST_HEAD(&nfsi->open_states);
        nfsi->delegation = NULL;
-       nfsi->delegation_state = 0;
        init_rwsem(&nfsi->rwsem);
        nfsi->layout = NULL;
 #endif
index 212b8c883d22881b4258c2c7f7e611d9d85f0427..b802fb3a2d99ffd76a57aecc6ce6739ca104e515 100644 (file)
@@ -597,6 +597,19 @@ void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize)
                sb->s_maxbytes = MAX_LFS_FILESIZE;
 }
 
+/*
+ * Record the page as unstable and mark its inode as dirty.
+ */
+static inline
+void nfs_mark_page_unstable(struct page *page)
+{
+       struct inode *inode = page_file_mapping(page)->host;
+
+       inc_zone_page_state(page, NR_UNSTABLE_NFS);
+       inc_bdi_stat(inode_to_bdi(inode), BDI_RECLAIMABLE);
+        __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
+}
+
 /*
  * Determine the number of bytes of data the page contains
  */
index 2e7c9f7a6f7cc8369bfcefda7a202d34f7a9dbe5..88180ac5ea0eebdf34aa333130e69d7a7b49c38e 100644 (file)
@@ -6648,47 +6648,47 @@ nfs41_same_server_scope(struct nfs41_server_scope *a,
 int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred)
 {
        int status;
+       struct nfs41_bind_conn_to_session_args args = {
+               .client = clp,
+               .dir = NFS4_CDFC4_FORE_OR_BOTH,
+       };
        struct nfs41_bind_conn_to_session_res res;
        struct rpc_message msg = {
                .rpc_proc =
                        &nfs4_procedures[NFSPROC4_CLNT_BIND_CONN_TO_SESSION],
-               .rpc_argp = clp,
+               .rpc_argp = &args,
                .rpc_resp = &res,
                .rpc_cred = cred,
        };
 
        dprintk("--> %s\n", __func__);
 
-       res.session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS);
-       if (unlikely(res.session == NULL)) {
-               status = -ENOMEM;
-               goto out;
-       }
+       nfs4_copy_sessionid(&args.sessionid, &clp->cl_session->sess_id);
+       if (!(clp->cl_session->flags & SESSION4_BACK_CHAN))
+               args.dir = NFS4_CDFC4_FORE;
 
        status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
        trace_nfs4_bind_conn_to_session(clp, status);
        if (status == 0) {
-               if (memcmp(res.session->sess_id.data,
+               if (memcmp(res.sessionid.data,
                    clp->cl_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) {
                        dprintk("NFS: %s: Session ID mismatch\n", __func__);
                        status = -EIO;
-                       goto out_session;
+                       goto out;
                }
-               if (res.dir != NFS4_CDFS4_BOTH) {
+               if ((res.dir & args.dir) != res.dir || res.dir == 0) {
                        dprintk("NFS: %s: Unexpected direction from server\n",
                                __func__);
                        status = -EIO;
-                       goto out_session;
+                       goto out;
                }
-               if (res.use_conn_in_rdma_mode) {
+               if (res.use_conn_in_rdma_mode != args.use_conn_in_rdma_mode) {
                        dprintk("NFS: %s: Server returned RDMA mode = true\n",
                                __func__);
                        status = -EIO;
-                       goto out_session;
+                       goto out;
                }
        }
-out_session:
-       kfree(res.session);
 out:
        dprintk("<-- %s status= %d\n", __func__, status);
        return status;
@@ -7166,10 +7166,11 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
                args->bc_attrs.max_reqs);
 }
 
-static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session)
+static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args,
+               struct nfs41_create_session_res *res)
 {
        struct nfs4_channel_attrs *sent = &args->fc_attrs;
-       struct nfs4_channel_attrs *rcvd = &session->fc_attrs;
+       struct nfs4_channel_attrs *rcvd = &res->fc_attrs;
 
        if (rcvd->max_resp_sz > sent->max_resp_sz)
                return -EINVAL;
@@ -7188,11 +7189,14 @@ static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args
        return 0;
 }
 
-static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session)
+static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args,
+               struct nfs41_create_session_res *res)
 {
        struct nfs4_channel_attrs *sent = &args->bc_attrs;
-       struct nfs4_channel_attrs *rcvd = &session->bc_attrs;
+       struct nfs4_channel_attrs *rcvd = &res->bc_attrs;
 
+       if (!(res->flags & SESSION4_BACK_CHAN))
+               goto out;
        if (rcvd->max_rqst_sz > sent->max_rqst_sz)
                return -EINVAL;
        if (rcvd->max_resp_sz < sent->max_resp_sz)
@@ -7204,18 +7208,30 @@ static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args
                return -EINVAL;
        if (rcvd->max_reqs != sent->max_reqs)
                return -EINVAL;
+out:
        return 0;
 }
 
 static int nfs4_verify_channel_attrs(struct nfs41_create_session_args *args,
-                                    struct nfs4_session *session)
+                                    struct nfs41_create_session_res *res)
 {
        int ret;
 
-       ret = nfs4_verify_fore_channel_attrs(args, session);
+       ret = nfs4_verify_fore_channel_attrs(args, res);
        if (ret)
                return ret;
-       return nfs4_verify_back_channel_attrs(args, session);
+       return nfs4_verify_back_channel_attrs(args, res);
+}
+
+static void nfs4_update_session(struct nfs4_session *session,
+               struct nfs41_create_session_res *res)
+{
+       nfs4_copy_sessionid(&session->sess_id, &res->sessionid);
+       session->flags = res->flags;
+       memcpy(&session->fc_attrs, &res->fc_attrs, sizeof(session->fc_attrs));
+       if (res->flags & SESSION4_BACK_CHAN)
+               memcpy(&session->bc_attrs, &res->bc_attrs,
+                               sizeof(session->bc_attrs));
 }
 
 static int _nfs4_proc_create_session(struct nfs_client *clp,
@@ -7224,11 +7240,12 @@ static int _nfs4_proc_create_session(struct nfs_client *clp,
        struct nfs4_session *session = clp->cl_session;
        struct nfs41_create_session_args args = {
                .client = clp,
+               .clientid = clp->cl_clientid,
+               .seqid = clp->cl_seqid,
                .cb_program = NFS4_CALLBACK,
        };
-       struct nfs41_create_session_res res = {
-               .client = clp,
-       };
+       struct nfs41_create_session_res res;
+
        struct rpc_message msg = {
                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE_SESSION],
                .rpc_argp = &args,
@@ -7245,11 +7262,15 @@ static int _nfs4_proc_create_session(struct nfs_client *clp,
 
        if (!status) {
                /* Verify the session's negotiated channel_attrs values */
-               status = nfs4_verify_channel_attrs(&args, session);
+               status = nfs4_verify_channel_attrs(&args, &res);
                /* Increment the clientid slot sequence id */
-               clp->cl_seqid++;
+               if (clp->cl_seqid == res.seqid)
+                       clp->cl_seqid++;
+               if (status)
+                       goto out;
+               nfs4_update_session(session, &res);
        }
-
+out:
        return status;
 }
 
index e799dc3c3b1db9f7681199907bff5e7bffb3f853..e23366effcfb1e43bcb81983bcbaeacf2e512002 100644 (file)
@@ -450,7 +450,7 @@ int nfs4_setup_session_slot_tables(struct nfs4_session *ses)
        tbl = &ses->fc_slot_table;
        tbl->session = ses;
        status = nfs4_realloc_slot_table(tbl, ses->fc_attrs.max_reqs, 1);
-       if (status) /* -ENOMEM */
+       if (status || !(ses->flags & SESSION4_BACK_CHAN)) /* -ENOMEM */
                return status;
        /* Back channel */
        tbl = &ses->bc_slot_table;
index b34ada9bc6a2d03a677e46cc5ab8c4eb7c1fd838..fc46c745589863425bff271942b76f7812db5aea 100644 (file)
@@ -118,6 +118,12 @@ static inline int nfs4_has_persistent_session(const struct nfs_client *clp)
        return 0;
 }
 
+static inline void nfs4_copy_sessionid(struct nfs4_sessionid *dst,
+               const struct nfs4_sessionid *src)
+{
+       memcpy(dst->data, src->data, NFS4_MAX_SESSIONID_LEN);
+}
+
 #ifdef CONFIG_CRC32
 /*
  * nfs_session_id_hash - calculate the crc32 hash for the session id
index e23a0a664e12d5130162bc320e80a57a5264bc9b..5c399ec41079687791d2fb668d5f6543ce374a2f 100644 (file)
@@ -1715,17 +1715,17 @@ static void encode_secinfo(struct xdr_stream *xdr, const struct qstr *name, stru
 #if defined(CONFIG_NFS_V4_1)
 /* NFSv4.1 operations */
 static void encode_bind_conn_to_session(struct xdr_stream *xdr,
-                                  struct nfs4_session *session,
+                                  struct nfs41_bind_conn_to_session_args *args,
                                   struct compound_hdr *hdr)
 {
        __be32 *p;
 
        encode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION,
                decode_bind_conn_to_session_maxsz, hdr);
-       encode_opaque_fixed(xdr, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
+       encode_opaque_fixed(xdr, args->sessionid.data, NFS4_MAX_SESSIONID_LEN);
        p = xdr_reserve_space(xdr, 8);
-       *p++ = cpu_to_be32(NFS4_CDFC4_BACK_OR_BOTH);
-       *p = 0; /* use_conn_in_rdma_mode = False */
+       *p++ = cpu_to_be32(args->dir);
+       *p = (args->use_conn_in_rdma_mode) ? cpu_to_be32(1) : cpu_to_be32(0);
 }
 
 static void encode_op_map(struct xdr_stream *xdr, struct nfs4_op_map *op_map)
@@ -1806,8 +1806,8 @@ static void encode_create_session(struct xdr_stream *xdr,
 
        encode_op_hdr(xdr, OP_CREATE_SESSION, decode_create_session_maxsz, hdr);
        p = reserve_space(xdr, 16 + 2*28 + 20 + clnt->cl_nodelen + 12);
-       p = xdr_encode_hyper(p, clp->cl_clientid);
-       *p++ = cpu_to_be32(clp->cl_seqid);                      /*Sequence id */
+       p = xdr_encode_hyper(p, args->clientid);
+       *p++ = cpu_to_be32(args->seqid);                        /*Sequence id */
        *p++ = cpu_to_be32(args->flags);                        /*flags */
 
        /* Fore Channel */
@@ -2734,14 +2734,14 @@ static void nfs4_xdr_enc_fsid_present(struct rpc_rqst *req,
  */
 static void nfs4_xdr_enc_bind_conn_to_session(struct rpc_rqst *req,
                                struct xdr_stream *xdr,
-                               struct nfs_client *clp)
+                               struct nfs41_bind_conn_to_session_args *args)
 {
        struct compound_hdr hdr = {
-               .minorversion = clp->cl_mvops->minor_version,
+               .minorversion = args->client->cl_mvops->minor_version,
        };
 
        encode_compound_hdr(xdr, req, &hdr);
-       encode_bind_conn_to_session(xdr, clp->cl_session, &hdr);
+       encode_bind_conn_to_session(xdr, args, &hdr);
        encode_nops(&hdr);
 }
 
@@ -5613,7 +5613,7 @@ static int decode_bind_conn_to_session(struct xdr_stream *xdr,
 
        status = decode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION);
        if (!status)
-               status = decode_sessionid(xdr, &res->session->sess_id);
+               status = decode_sessionid(xdr, &res->sessionid);
        if (unlikely(status))
                return status;
 
@@ -5641,12 +5641,10 @@ static int decode_create_session(struct xdr_stream *xdr,
 {
        __be32 *p;
        int status;
-       struct nfs_client *clp = res->client;
-       struct nfs4_session *session = clp->cl_session;
 
        status = decode_op_hdr(xdr, OP_CREATE_SESSION);
        if (!status)
-               status = decode_sessionid(xdr, &session->sess_id);
+               status = decode_sessionid(xdr, &res->sessionid);
        if (unlikely(status))
                return status;
 
@@ -5654,13 +5652,13 @@ static int decode_create_session(struct xdr_stream *xdr,
        p = xdr_inline_decode(xdr, 8);
        if (unlikely(!p))
                goto out_overflow;
-       clp->cl_seqid = be32_to_cpup(p++);
-       session->flags = be32_to_cpup(p);
+       res->seqid = be32_to_cpup(p++);
+       res->flags = be32_to_cpup(p);
 
        /* Channel attributes */
-       status = decode_chan_attrs(xdr, &session->fc_attrs);
+       status = decode_chan_attrs(xdr, &res->fc_attrs);
        if (!status)
-               status = decode_chan_attrs(xdr, &session->bc_attrs);
+               status = decode_chan_attrs(xdr, &res->bc_attrs);
        return status;
 out_overflow:
        print_overflow_msg(__func__, xdr);
index 797cd6253adf74d809510151080d1d06439f378d..635f0865671cf38b27eea4a49261c9405a4a4731 100644 (file)
@@ -344,6 +344,10 @@ void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
 struct nfs4_pnfs_ds_addr *nfs4_decode_mp_ds_addr(struct net *net,
                                                 struct xdr_stream *xdr,
                                                 gfp_t gfp_flags);
+void pnfs_layout_mark_request_commit(struct nfs_page *req,
+                                    struct pnfs_layout_segment *lseg,
+                                    struct nfs_commit_info *cinfo,
+                                    u32 ds_commit_idx);
 
 static inline bool nfs_have_layout(struct inode *inode)
 {
index fdc4f6562bb7efc65179f970053dfec6a9c38705..54e36b38fb5f89310287635e0838601ad07cf34a 100644 (file)
@@ -838,3 +838,33 @@ out_err:
        return NULL;
 }
 EXPORT_SYMBOL_GPL(nfs4_decode_mp_ds_addr);
+
+void
+pnfs_layout_mark_request_commit(struct nfs_page *req,
+                               struct pnfs_layout_segment *lseg,
+                               struct nfs_commit_info *cinfo,
+                               u32 ds_commit_idx)
+{
+       struct list_head *list;
+       struct pnfs_commit_bucket *buckets;
+
+       spin_lock(cinfo->lock);
+       buckets = cinfo->ds->buckets;
+       list = &buckets[ds_commit_idx].written;
+       if (list_empty(list)) {
+               /* Non-empty buckets hold a reference on the lseg.  That ref
+                * is normally transferred to the COMMIT call and released
+                * there.  It could also be released if the last req is pulled
+                * off due to a rewrite, in which case it will be done in
+                * pnfs_common_clear_request_commit
+                */
+               WARN_ON_ONCE(buckets[ds_commit_idx].wlseg != NULL);
+               buckets[ds_commit_idx].wlseg = pnfs_get_lseg(lseg);
+       }
+       set_bit(PG_COMMIT_TO_DS, &req->wb_flags);
+       cinfo->ds->nwritten++;
+       spin_unlock(cinfo->lock);
+
+       nfs_request_add_commit_list(req, list, cinfo);
+}
+EXPORT_SYMBOL_GPL(pnfs_layout_mark_request_commit);
index 88a6d2196ece3bf5ce7a94027dd96e8f25bc9792..595d81e354d18950a21615862b134ca8993f4c6e 100644 (file)
@@ -789,13 +789,8 @@ nfs_request_add_commit_list(struct nfs_page *req, struct list_head *dst,
        nfs_list_add_request(req, dst);
        cinfo->mds->ncommit++;
        spin_unlock(cinfo->lock);
-       if (!cinfo->dreq) {
-               inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
-               inc_bdi_stat(inode_to_bdi(page_file_mapping(req->wb_page)->host),
-                            BDI_RECLAIMABLE);
-               __mark_inode_dirty(req->wb_context->dentry->d_inode,
-                                  I_DIRTY_DATASYNC);
-       }
+       if (!cinfo->dreq)
+               nfs_mark_page_unstable(req->wb_page);
 }
 EXPORT_SYMBOL_GPL(nfs_request_add_commit_list);
 
@@ -1605,11 +1600,8 @@ void nfs_retry_commit(struct list_head *page_list,
                req = nfs_list_entry(page_list->next);
                nfs_list_remove_request(req);
                nfs_mark_request_commit(req, lseg, cinfo, ds_commit_idx);
-               if (!cinfo->dreq) {
-                       dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
-                       dec_bdi_stat(inode_to_bdi(page_file_mapping(req->wb_page)->host),
-                                    BDI_RECLAIMABLE);
-               }
+               if (!cinfo->dreq)
+                       nfs_clear_page_commit(req->wb_page);
                nfs_unlock_and_release_request(req);
        }
 }
index 6d627b92df537ada3886af5850c0fabbac53b66a..2f77e0c651c89874a641c8a04a723aaf60dd2837 100644 (file)
@@ -180,7 +180,6 @@ struct nfs_inode {
         /* NFSv4 state */
        struct list_head        open_states;
        struct nfs_delegation __rcu *delegation;
-       fmode_t                  delegation_state;
        struct rw_semaphore     rwsem;
 
        /* pNFS layout information */
index 38d96ba935c2d7fd91aaf444a598b832b1c0ee4e..4cb3eaa89cf708a57038049db0df75144155d920 100644 (file)
@@ -1167,8 +1167,15 @@ struct nfs41_impl_id {
        struct nfstime4                 date;
 };
 
+struct nfs41_bind_conn_to_session_args {
+       struct nfs_client               *client;
+       struct nfs4_sessionid           sessionid;
+       u32                             dir;
+       bool                            use_conn_in_rdma_mode;
+};
+
 struct nfs41_bind_conn_to_session_res {
-       struct nfs4_session             *session;
+       struct nfs4_sessionid           sessionid;
        u32                             dir;
        bool                            use_conn_in_rdma_mode;
 };
@@ -1185,6 +1192,8 @@ struct nfs41_exchange_id_res {
 
 struct nfs41_create_session_args {
        struct nfs_client              *client;
+       u64                             clientid;
+       uint32_t                        seqid;
        uint32_t                        flags;
        uint32_t                        cb_program;
        struct nfs4_channel_attrs       fc_attrs;       /* Fore Channel */
@@ -1192,7 +1201,11 @@ struct nfs41_create_session_args {
 };
 
 struct nfs41_create_session_res {
-       struct nfs_client              *client;
+       struct nfs4_sessionid           sessionid;
+       uint32_t                        seqid;
+       uint32_t                        flags;
+       struct nfs4_channel_attrs       fc_attrs;       /* Fore Channel */
+       struct nfs4_channel_attrs       bc_attrs;       /* Back Channel */
 };
 
 struct nfs41_reclaim_complete_args {
@@ -1351,7 +1364,7 @@ struct nfs_commit_completion_ops {
 };
 
 struct nfs_commit_info {
-       spinlock_t                      *lock;
+       spinlock_t                      *lock;  /* inode->i_lock */
        struct nfs_mds_commit_info      *mds;
        struct pnfs_ds_commit_info      *ds;
        struct nfs_direct_req           *dreq;  /* O_DIRECT request */
index 7e61a17030a4843bf0f80fda4dc2ae9f379409ef..694eecb2f1b5dffd8fe7f43c2979528ae2639042 100644 (file)
@@ -89,8 +89,11 @@ void                 rpc_free_iostats(struct rpc_iostats *);
 static inline struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt) { return NULL; }
 static inline void rpc_count_iostats(const struct rpc_task *task,
                                     struct rpc_iostats *stats) {}
-static inline void rpc_count_iostats_metrics(const struct rpc_task *,
-                                            struct rpc_iostats *) {}
+static inline void rpc_count_iostats_metrics(const struct rpc_task *task,
+                                            struct rpc_iostats *stats)
+{
+}
+
 static inline void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) {}
 static inline void rpc_free_iostats(struct rpc_iostats *stats) {}
 
index 651f49ab601fbdd75eed30ddc0a29c9cb4369e54..9dd0ea8db463acc9daba0c51be89b1f17ec8f17d 100644 (file)
@@ -309,12 +309,15 @@ void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied)
        struct rpc_xprt *xprt = req->rq_xprt;
        struct svc_serv *bc_serv = xprt->bc_serv;
 
+       spin_lock(&xprt->bc_pa_lock);
+       list_del(&req->rq_bc_pa_list);
+       spin_unlock(&xprt->bc_pa_lock);
+
        req->rq_private_buf.len = copied;
        set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
 
        dprintk("RPC:       add callback request to list\n");
        spin_lock(&bc_serv->sv_cb_lock);
-       list_del(&req->rq_bc_pa_list);
        list_add(&req->rq_bc_list, &bc_serv->sv_cb_list);
        wake_up(&bc_serv->sv_cb_waitq);
        spin_unlock(&bc_serv->sv_cb_lock);