Merge tag 'v4.4.75' into linux-linaro-lsk-v4.4
[firefly-linux-kernel-4.4.55.git] / fs / nfs / nfs4proc.c
index 765a035593638cfd17b4aedd646c0362068343c6..4e3679b25b9b5849436eb1ca2b2366a88c601f59 100644 (file)
@@ -1385,6 +1385,7 @@ static void __update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_s
         * Protect the call to nfs4_state_set_mode_locked and
         * serialise the stateid update
         */
+       spin_lock(&state->owner->so_lock);
        write_seqlock(&state->seqlock);
        if (deleg_stateid != NULL) {
                nfs4_stateid_copy(&state->stateid, deleg_stateid);
@@ -1393,7 +1394,6 @@ static void __update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_s
        if (open_stateid != NULL)
                nfs_set_open_stateid_locked(state, open_stateid, fmode);
        write_sequnlock(&state->seqlock);
-       spin_lock(&state->owner->so_lock);
        update_open_stateflags(state, fmode);
        spin_unlock(&state->owner->so_lock);
 }
@@ -2422,7 +2422,8 @@ static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata,
                sattr->ia_valid |= ATTR_MTIME;
 
        /* Except MODE, it seems harmless of setting twice. */
-       if ((attrset[1] & FATTR4_WORD1_MODE))
+       if (opendata->o_arg.createmode != NFS4_CREATE_EXCLUSIVE &&
+               attrset[1] & FATTR4_WORD1_MODE)
                sattr->ia_valid &= ~ATTR_MODE;
 
        if (attrset[2] & FATTR4_WORD2_SECURITY_LABEL)
@@ -2451,6 +2452,7 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
        ret = PTR_ERR(state);
        if (IS_ERR(state))
                goto out;
+       ctx->state = state;
        if (server->caps & NFS_CAP_POSIX_LOCK)
                set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
 
@@ -2461,9 +2463,9 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
                dentry = d_add_unique(dentry, igrab(state->inode));
                if (dentry == NULL) {
                        dentry = opendata->dentry;
-               } else if (dentry != ctx->dentry) {
+               } else {
                        dput(ctx->dentry);
-                       ctx->dentry = dget(dentry);
+                       ctx->dentry = dentry;
                }
                nfs_set_verifier(dentry,
                                nfs_save_change_attribute(d_inode(opendata->dir)));
@@ -2473,7 +2475,6 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
        if (ret != 0)
                goto out;
 
-       ctx->state = state;
        if (d_inode(dentry) == state->inode) {
                nfs_inode_attach_open_context(ctx);
                if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
@@ -2854,12 +2855,11 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
                        call_close |= is_wronly;
                else if (is_wronly)
                        calldata->arg.fmode |= FMODE_WRITE;
+               if (calldata->arg.fmode != (FMODE_READ|FMODE_WRITE))
+                       call_close |= is_rdwr;
        } else if (is_rdwr)
                calldata->arg.fmode |= FMODE_READ|FMODE_WRITE;
 
-       if (calldata->arg.fmode == 0)
-               call_close |= is_rdwr;
-
        if (!nfs4_valid_open_stateid(state))
                call_close = 0;
        spin_unlock(&state->owner->so_lock);
@@ -4711,7 +4711,7 @@ out:
  */
 static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
 {
-       struct page *pages[NFS4ACL_MAXPAGES] = {NULL, };
+       struct page *pages[NFS4ACL_MAXPAGES + 1] = {NULL, };
        struct nfs_getaclargs args = {
                .fh = NFS_FH(inode),
                .acl_pages = pages,
@@ -4725,13 +4725,9 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
                .rpc_argp = &args,
                .rpc_resp = &res,
        };
-       unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE);
+       unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE) + 1;
        int ret = -ENOMEM, i;
 
-       /* As long as we're doing a round trip to the server anyway,
-        * let's be prepared for a page of acl data. */
-       if (npages == 0)
-               npages = 1;
        if (npages > ARRAY_SIZE(pages))
                return -ERANGE;
 
@@ -7425,12 +7421,20 @@ static int _nfs4_proc_create_session(struct nfs_client *clp,
        status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
        trace_nfs4_create_session(clp, status);
 
+       switch (status) {
+       case -NFS4ERR_STALE_CLIENTID:
+       case -NFS4ERR_DELAY:
+       case -ETIMEDOUT:
+       case -EACCES:
+       case -EAGAIN:
+               goto out;
+       };
+
+       clp->cl_seqid++;
        if (!status) {
                /* Verify the session's negotiated channel_attrs values */
                status = nfs4_verify_channel_attrs(&args, &res);
                /* Increment the clientid slot sequence id */
-               if (clp->cl_seqid == res.seqid)
-                       clp->cl_seqid++;
                if (status)
                        goto out;
                nfs4_update_session(session, &res);
@@ -7866,7 +7870,7 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
                        spin_unlock(&inode->i_lock);
                goto out_restart;
        }
-       if (nfs4_async_handle_error(task, server, state, NULL) == -EAGAIN)
+       if (nfs4_async_handle_error(task, server, state, &lgp->timeout) == -EAGAIN)
                goto out_restart;
 out:
        dprintk("<-- %s\n", __func__);
@@ -8054,7 +8058,6 @@ static void nfs4_layoutreturn_release(void *calldata)
                pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
        pnfs_mark_matching_lsegs_invalid(lo, &freeme, &lrp->args.range);
        pnfs_clear_layoutreturn_waitbit(lo);
-       lo->plh_block_lgets--;
        spin_unlock(&lo->plh_inode->i_lock);
        pnfs_free_lseg_list(&freeme);
        pnfs_put_layout_hdr(lrp->args.layout);