Merge remote-tracking branch 'torvalds/master' into perf/core
[linux-2.6-microblaze.git] / fs / nfs / nfs4proc.c
index c65c4b4..e653654 100644 (file)
@@ -108,9 +108,10 @@ static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *,
 static int nfs41_free_stateid(struct nfs_server *, const nfs4_stateid *,
                const struct cred *, bool);
 #endif
-static void nfs4_bitmask_adjust(__u32 *bitmask, struct inode *inode,
-               struct nfs_server *server,
-               struct nfs4_label *label);
+static void nfs4_bitmask_set(__u32 bitmask[NFS4_BITMASK_SZ],
+                            const __u32 *src, struct inode *inode,
+                            struct nfs_server *server,
+                            struct nfs4_label *label);
 
 #ifdef CONFIG_NFS_V4_SECURITY_LABEL
 static inline struct nfs4_label *
@@ -263,6 +264,7 @@ const u32 nfs4_fsinfo_bitmap[3] = { FATTR4_WORD0_MAXFILESIZE
                        | FATTR4_WORD1_FS_LAYOUT_TYPES,
                        FATTR4_WORD2_LAYOUT_BLKSIZE
                        | FATTR4_WORD2_CLONE_BLKSIZE
+                       | FATTR4_WORD2_CHANGE_ATTR_TYPE
                        | FATTR4_WORD2_XATTR_SUPPORT
 };
 
@@ -283,7 +285,7 @@ const u32 nfs4_fs_locations_bitmap[3] = {
 };
 
 static void nfs4_bitmap_copy_adjust(__u32 *dst, const __u32 *src,
-               struct inode *inode)
+                                   struct inode *inode, unsigned long flags)
 {
        unsigned long cache_validity;
 
@@ -291,22 +293,20 @@ static void nfs4_bitmap_copy_adjust(__u32 *dst, const __u32 *src,
        if (!inode || !nfs4_have_delegation(inode, FMODE_READ))
                return;
 
-       cache_validity = READ_ONCE(NFS_I(inode)->cache_validity);
-       if (!(cache_validity & NFS_INO_REVAL_FORCED))
-               cache_validity &= ~(NFS_INO_INVALID_CHANGE
-                               | NFS_INO_INVALID_SIZE);
+       cache_validity = READ_ONCE(NFS_I(inode)->cache_validity) | flags;
 
+       /* Remove the attributes over which we have full control */
+       dst[1] &= ~FATTR4_WORD1_RAWDEV;
        if (!(cache_validity & NFS_INO_INVALID_SIZE))
                dst[0] &= ~FATTR4_WORD0_SIZE;
 
        if (!(cache_validity & NFS_INO_INVALID_CHANGE))
                dst[0] &= ~FATTR4_WORD0_CHANGE;
-}
 
-static void nfs4_bitmap_copy_adjust_setattr(__u32 *dst,
-               const __u32 *src, struct inode *inode)
-{
-       nfs4_bitmap_copy_adjust(dst, src, inode);
+       if (!(cache_validity & NFS_INO_INVALID_MODE))
+               dst[1] &= ~FATTR4_WORD1_MODE;
+       if (!(cache_validity & NFS_INO_INVALID_OTHER))
+               dst[1] &= ~(FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP);
 }
 
 static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry,
@@ -589,6 +589,8 @@ int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_
                goto out_retry;
        }
        if (exception->recovering) {
+               if (exception->task_is_privileged)
+                       return -EDEADLOCK;
                ret = nfs4_wait_clnt_recover(clp);
                if (test_bit(NFS_MIG_FAILED, &server->mig_status))
                        return -EIO;
@@ -614,6 +616,8 @@ nfs4_async_handle_exception(struct rpc_task *task, struct nfs_server *server,
                goto out_retry;
        }
        if (exception->recovering) {
+               if (exception->task_is_privileged)
+                       return -EDEADLOCK;
                rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
                if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
                        rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
@@ -1169,14 +1173,26 @@ int nfs4_call_sync(struct rpc_clnt *clnt,
 static void
 nfs4_inc_nlink_locked(struct inode *inode)
 {
-       nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER);
+       nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE |
+                                            NFS_INO_INVALID_CTIME |
+                                            NFS_INO_INVALID_NLINK);
        inc_nlink(inode);
 }
 
+static void
+nfs4_inc_nlink(struct inode *inode)
+{
+       spin_lock(&inode->i_lock);
+       nfs4_inc_nlink_locked(inode);
+       spin_unlock(&inode->i_lock);
+}
+
 static void
 nfs4_dec_nlink_locked(struct inode *inode)
 {
-       nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER);
+       nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE |
+                                            NFS_INO_INVALID_CTIME |
+                                            NFS_INO_INVALID_NLINK);
        drop_nlink(inode);
 }
 
@@ -1186,11 +1202,23 @@ nfs4_update_changeattr_locked(struct inode *inode,
                unsigned long timestamp, unsigned long cache_validity)
 {
        struct nfs_inode *nfsi = NFS_I(inode);
+       u64 change_attr = inode_peek_iversion_raw(inode);
 
        cache_validity |= NFS_INO_INVALID_CTIME | NFS_INO_INVALID_MTIME;
 
-       if (cinfo->atomic && cinfo->before == inode_peek_iversion_raw(inode)) {
-               nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
+       switch (NFS_SERVER(inode)->change_attr_type) {
+       case NFS4_CHANGE_TYPE_IS_UNDEFINED:
+               break;
+       case NFS4_CHANGE_TYPE_IS_TIME_METADATA:
+               if ((s64)(change_attr - cinfo->after) > 0)
+                       goto out;
+               break;
+       default:
+               if ((s64)(change_attr - cinfo->after) >= 0)
+                       goto out;
+       }
+
+       if (cinfo->atomic && cinfo->before == change_attr) {
                nfsi->attrtimeo_timestamp = jiffies;
        } else {
                if (S_ISDIR(inode->i_mode)) {
@@ -1202,7 +1230,7 @@ nfs4_update_changeattr_locked(struct inode *inode,
                                cache_validity |= NFS_INO_REVAL_PAGECACHE;
                }
 
-               if (cinfo->before != inode_peek_iversion_raw(inode))
+               if (cinfo->before != change_attr)
                        cache_validity |= NFS_INO_INVALID_ACCESS |
                                          NFS_INO_INVALID_ACL |
                                          NFS_INO_INVALID_XATTR;
@@ -1210,8 +1238,9 @@ nfs4_update_changeattr_locked(struct inode *inode,
        inode_set_iversion_raw(inode, cinfo->after);
        nfsi->read_cache_jiffies = timestamp;
        nfsi->attr_gencount = nfs_inc_attr_generation_counter();
-       nfs_set_cache_invalid(inode, cache_validity);
        nfsi->cache_validity &= ~NFS_INO_INVALID_CHANGE;
+out:
+       nfs_set_cache_invalid(inode, cache_validity);
 }
 
 void
@@ -1681,7 +1710,7 @@ static void nfs_set_open_stateid_locked(struct nfs4_state *state,
                rcu_read_unlock();
                trace_nfs4_open_stateid_update_wait(state->inode, stateid, 0);
 
-               if (!signal_pending(current)) {
+               if (!fatal_signal_pending(current)) {
                        if (schedule_timeout(5*HZ) == 0)
                                status = -EAGAIN;
                        else
@@ -3344,12 +3373,17 @@ static int nfs4_do_setattr(struct inode *inode, const struct cred *cred,
                .inode = inode,
                .stateid = &arg.stateid,
        };
+       unsigned long adjust_flags = NFS_INO_INVALID_CHANGE;
        int err;
 
+       if (sattr->ia_valid & (ATTR_MODE | ATTR_KILL_SUID | ATTR_KILL_SGID))
+               adjust_flags |= NFS_INO_INVALID_MODE;
+       if (sattr->ia_valid & (ATTR_UID | ATTR_GID))
+               adjust_flags |= NFS_INO_INVALID_OTHER;
+
        do {
-               nfs4_bitmap_copy_adjust_setattr(bitmask,
-                               nfs4_bitmask(server, olabel),
-                               inode);
+               nfs4_bitmap_copy_adjust(bitmask, nfs4_bitmask(server, olabel),
+                                       inode, adjust_flags);
 
                err = _nfs4_do_setattr(inode, &arg, &res, cred, ctx);
                switch (err) {
@@ -3457,7 +3491,7 @@ static bool nfs4_refresh_open_old_stateid(nfs4_stateid *dst,
                write_sequnlock(&state->seqlock);
                trace_nfs4_close_stateid_update_wait(state->inode, dst, 0);
 
-               if (signal_pending(current))
+               if (fatal_signal_pending(current))
                        status = -EINTR;
                else
                        if (schedule_timeout(5*HZ) != 0)
@@ -3591,6 +3625,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
        struct nfs4_closedata *calldata = data;
        struct nfs4_state *state = calldata->state;
        struct inode *inode = calldata->inode;
+       struct nfs_server *server = NFS_SERVER(inode);
        struct pnfs_layout_hdr *lo;
        bool is_rdonly, is_wronly, is_rdwr;
        int call_close = 0;
@@ -3647,8 +3682,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
        if (calldata->arg.fmode == 0 || calldata->arg.fmode == FMODE_READ) {
                /* Close-to-open cache consistency revalidation */
                if (!nfs4_have_delegation(inode, FMODE_READ)) {
-                       calldata->arg.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask;
-                       nfs4_bitmask_adjust(calldata->arg.bitmask, inode, NFS_SERVER(inode), NULL);
+                       nfs4_bitmask_set(calldata->arg.bitmask_store,
+                                        server->cache_consistency_bitmask,
+                                        inode, server, NULL);
+                       calldata->arg.bitmask = calldata->arg.bitmask_store;
                } else
                        calldata->arg.bitmask = NULL;
        }
@@ -3835,12 +3872,9 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
                        res.attr_bitmask[2] &= FATTR4_WORD2_NFS42_MASK;
                }
                memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask));
-               server->caps &= ~(NFS_CAP_ACLS|NFS_CAP_HARDLINKS|
-                               NFS_CAP_SYMLINKS|NFS_CAP_FILEID|
-                               NFS_CAP_MODE|NFS_CAP_NLINK|NFS_CAP_OWNER|
-                               NFS_CAP_OWNER_GROUP|NFS_CAP_ATIME|
-                               NFS_CAP_CTIME|NFS_CAP_MTIME|
-                               NFS_CAP_SECURITY_LABEL);
+               server->caps &= ~(NFS_CAP_ACLS | NFS_CAP_HARDLINKS |
+                                 NFS_CAP_SYMLINKS| NFS_CAP_SECURITY_LABEL);
+               server->fattr_valid = NFS_ATTR_FATTR_V4;
                if (res.attr_bitmask[0] & FATTR4_WORD0_ACL &&
                                res.acl_bitmask & ACL4_SUPPORT_ALLOW_ACL)
                        server->caps |= NFS_CAP_ACLS;
@@ -3848,26 +3882,30 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
                        server->caps |= NFS_CAP_HARDLINKS;
                if (res.has_symlinks != 0)
                        server->caps |= NFS_CAP_SYMLINKS;
-               if (res.attr_bitmask[0] & FATTR4_WORD0_FILEID)
-                       server->caps |= NFS_CAP_FILEID;
-               if (res.attr_bitmask[1] & FATTR4_WORD1_MODE)
-                       server->caps |= NFS_CAP_MODE;
-               if (res.attr_bitmask[1] & FATTR4_WORD1_NUMLINKS)
-                       server->caps |= NFS_CAP_NLINK;
-               if (res.attr_bitmask[1] & FATTR4_WORD1_OWNER)
-                       server->caps |= NFS_CAP_OWNER;
-               if (res.attr_bitmask[1] & FATTR4_WORD1_OWNER_GROUP)
-                       server->caps |= NFS_CAP_OWNER_GROUP;
-               if (res.attr_bitmask[1] & FATTR4_WORD1_TIME_ACCESS)
-                       server->caps |= NFS_CAP_ATIME;
-               if (res.attr_bitmask[1] & FATTR4_WORD1_TIME_METADATA)
-                       server->caps |= NFS_CAP_CTIME;
-               if (res.attr_bitmask[1] & FATTR4_WORD1_TIME_MODIFY)
-                       server->caps |= NFS_CAP_MTIME;
 #ifdef CONFIG_NFS_V4_SECURITY_LABEL
                if (res.attr_bitmask[2] & FATTR4_WORD2_SECURITY_LABEL)
                        server->caps |= NFS_CAP_SECURITY_LABEL;
 #endif
+               if (!(res.attr_bitmask[0] & FATTR4_WORD0_FILEID))
+                       server->fattr_valid &= ~NFS_ATTR_FATTR_FILEID;
+               if (!(res.attr_bitmask[1] & FATTR4_WORD1_MODE))
+                       server->fattr_valid &= ~NFS_ATTR_FATTR_MODE;
+               if (!(res.attr_bitmask[1] & FATTR4_WORD1_NUMLINKS))
+                       server->fattr_valid &= ~NFS_ATTR_FATTR_NLINK;
+               if (!(res.attr_bitmask[1] & FATTR4_WORD1_OWNER))
+                       server->fattr_valid &= ~(NFS_ATTR_FATTR_OWNER |
+                               NFS_ATTR_FATTR_OWNER_NAME);
+               if (!(res.attr_bitmask[1] & FATTR4_WORD1_OWNER_GROUP))
+                       server->fattr_valid &= ~(NFS_ATTR_FATTR_GROUP |
+                               NFS_ATTR_FATTR_GROUP_NAME);
+               if (!(res.attr_bitmask[1] & FATTR4_WORD1_SPACE_USED))
+                       server->fattr_valid &= ~NFS_ATTR_FATTR_SPACE_USED;
+               if (!(res.attr_bitmask[1] & FATTR4_WORD1_TIME_ACCESS))
+                       server->fattr_valid &= ~NFS_ATTR_FATTR_ATIME;
+               if (!(res.attr_bitmask[1] & FATTR4_WORD1_TIME_METADATA))
+                       server->fattr_valid &= ~NFS_ATTR_FATTR_CTIME;
+               if (!(res.attr_bitmask[1] & FATTR4_WORD1_TIME_MODIFY))
+                       server->fattr_valid &= ~NFS_ATTR_FATTR_MTIME;
                memcpy(server->attr_bitmask_nl, res.attr_bitmask,
                                sizeof(server->attr_bitmask));
                server->attr_bitmask_nl[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
@@ -4154,8 +4192,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
        if (inode && (server->flags & NFS_MOUNT_SOFTREVAL))
                task_flags |= RPC_TASK_TIMEOUT;
 
-       nfs4_bitmap_copy_adjust(bitmask, nfs4_bitmask(server, label), inode);
-
+       nfs4_bitmap_copy_adjust(bitmask, nfs4_bitmask(server, label), inode, 0);
        nfs_fattr_init(fattr);
        nfs4_init_sequence(&args.seq_args, &res.seq_res, 0, 0);
        return nfs4_do_call_sync(server->client, server, &msg,
@@ -4582,11 +4619,11 @@ _nfs4_proc_remove(struct inode *dir, const struct qstr *name, u32 ftype)
        status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 1);
        if (status == 0) {
                spin_lock(&dir->i_lock);
-               nfs4_update_changeattr_locked(dir, &res.cinfo, timestamp,
-                                             NFS_INO_INVALID_DATA);
                /* Removing a directory decrements nlink in the parent */
                if (ftype == NF4DIR && dir->i_nlink > 2)
                        nfs4_dec_nlink_locked(dir);
+               nfs4_update_changeattr_locked(dir, &res.cinfo, timestamp,
+                                             NFS_INO_INVALID_DATA);
                spin_unlock(&dir->i_lock);
        }
        return status;
@@ -4715,11 +4752,11 @@ static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
                        /* Note: If we moved a directory, nlink will change */
                        nfs4_update_changeattr(old_dir, &res->old_cinfo,
                                        res->old_fattr->time_start,
-                                       NFS_INO_INVALID_OTHER |
+                                       NFS_INO_INVALID_NLINK |
                                            NFS_INO_INVALID_DATA);
                        nfs4_update_changeattr(new_dir, &res->new_cinfo,
                                        res->new_fattr->time_start,
-                                       NFS_INO_INVALID_OTHER |
+                                       NFS_INO_INVALID_NLINK |
                                            NFS_INO_INVALID_DATA);
                } else
                        nfs4_update_changeattr(old_dir, &res->old_cinfo,
@@ -4761,12 +4798,13 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, const struct
        }
 
        nfs4_inode_make_writeable(inode);
-       nfs4_bitmap_copy_adjust_setattr(bitmask, nfs4_bitmask(server, res.label), inode);
-
+       nfs4_bitmap_copy_adjust(bitmask, nfs4_bitmask(server, res.label), inode,
+                               NFS_INO_INVALID_CHANGE);
        status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
        if (!status) {
                nfs4_update_changeattr(dir, &res.cinfo, res.fattr->time_start,
                                       NFS_INO_INVALID_DATA);
+               nfs4_inc_nlink(inode);
                status = nfs_post_op_update_inode(inode, res.fattr);
                if (!status)
                        nfs_setsecurity(inode, res.fattr, res.label);
@@ -4844,12 +4882,12 @@ static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_
                                    &data->arg.seq_args, &data->res.seq_res, 1);
        if (status == 0) {
                spin_lock(&dir->i_lock);
-               nfs4_update_changeattr_locked(dir, &data->res.dir_cinfo,
-                               data->res.fattr->time_start,
-                               NFS_INO_INVALID_DATA);
                /* Creating a directory bumps nlink in the parent */
                if (data->arg.ftype == NF4DIR)
                        nfs4_inc_nlink_locked(dir);
+               nfs4_update_changeattr_locked(dir, &data->res.dir_cinfo,
+                                             data->res.fattr->time_start,
+                                             NFS_INO_INVALID_DATA);
                spin_unlock(&dir->i_lock);
                status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, data->res.label);
        }
@@ -5416,37 +5454,39 @@ bool nfs4_write_need_cache_consistency_data(struct nfs_pgio_header *hdr)
        return nfs4_have_delegation(hdr->inode, FMODE_READ) == 0;
 }
 
-static void nfs4_bitmask_adjust(__u32 *bitmask, struct inode *inode,
-                               struct nfs_server *server,
-                               struct nfs4_label *label)
+static void nfs4_bitmask_set(__u32 bitmask[NFS4_BITMASK_SZ], const __u32 *src,
+                            struct inode *inode, struct nfs_server *server,
+                            struct nfs4_label *label)
 {
-
        unsigned long cache_validity = READ_ONCE(NFS_I(inode)->cache_validity);
+       unsigned int i;
 
-       if ((cache_validity & NFS_INO_INVALID_DATA) ||
-               (cache_validity & NFS_INO_REVAL_PAGECACHE) ||
-               (cache_validity & NFS_INO_REVAL_FORCED) ||
-               (cache_validity & NFS_INO_INVALID_OTHER))
-               nfs4_bitmap_copy_adjust(bitmask, nfs4_bitmask(server, label), inode);
+       memcpy(bitmask, src, sizeof(*bitmask) * NFS4_BITMASK_SZ);
 
+       if (cache_validity & NFS_INO_INVALID_CHANGE)
+               bitmask[0] |= FATTR4_WORD0_CHANGE;
        if (cache_validity & NFS_INO_INVALID_ATIME)
                bitmask[1] |= FATTR4_WORD1_TIME_ACCESS;
+       if (cache_validity & NFS_INO_INVALID_MODE)
+               bitmask[1] |= FATTR4_WORD1_MODE;
        if (cache_validity & NFS_INO_INVALID_OTHER)
-               bitmask[1] |= FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER |
-                               FATTR4_WORD1_OWNER_GROUP |
-                               FATTR4_WORD1_NUMLINKS;
+               bitmask[1] |= FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP;
+       if (cache_validity & NFS_INO_INVALID_NLINK)
+               bitmask[1] |= FATTR4_WORD1_NUMLINKS;
        if (label && label->len && cache_validity & NFS_INO_INVALID_LABEL)
                bitmask[2] |= FATTR4_WORD2_SECURITY_LABEL;
-       if (cache_validity & NFS_INO_INVALID_CHANGE)
-               bitmask[0] |= FATTR4_WORD0_CHANGE;
        if (cache_validity & NFS_INO_INVALID_CTIME)
                bitmask[1] |= FATTR4_WORD1_TIME_METADATA;
        if (cache_validity & NFS_INO_INVALID_MTIME)
                bitmask[1] |= FATTR4_WORD1_TIME_MODIFY;
-       if (cache_validity & NFS_INO_INVALID_SIZE)
-               bitmask[0] |= FATTR4_WORD0_SIZE;
        if (cache_validity & NFS_INO_INVALID_BLOCKS)
                bitmask[1] |= FATTR4_WORD1_SPACE_USED;
+
+       if (cache_validity & NFS_INO_INVALID_SIZE)
+               bitmask[0] |= FATTR4_WORD0_SIZE;
+
+       for (i = 0; i < NFS4_BITMASK_SZ; i++)
+               bitmask[i] &= server->attr_bitmask[i];
 }
 
 static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr,
@@ -5459,8 +5499,10 @@ static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr,
                hdr->args.bitmask = NULL;
                hdr->res.fattr = NULL;
        } else {
-               hdr->args.bitmask = server->cache_consistency_bitmask;
-               nfs4_bitmask_adjust(hdr->args.bitmask, hdr->inode, server, NULL);
+               nfs4_bitmask_set(hdr->args.bitmask_store,
+                                server->cache_consistency_bitmask,
+                                hdr->inode, server, NULL);
+               hdr->args.bitmask = hdr->args.bitmask_store;
        }
 
        if (!hdr->pgio_done_cb)
@@ -5858,7 +5900,7 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
 
        if (!nfs4_server_supports_acls(server))
                return -EOPNOTSUPP;
-       ret = nfs_revalidate_inode(server, inode);
+       ret = nfs_revalidate_inode(inode, NFS_INO_INVALID_CHANGE);
        if (ret < 0)
                return ret;
        if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL)
@@ -5930,6 +5972,14 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen
        do {
                err = __nfs4_proc_set_acl(inode, buf, buflen);
                trace_nfs4_set_acl(inode, err);
+               if (err == -NFS4ERR_BADOWNER || err == -NFS4ERR_BADNAME) {
+                       /*
+                        * no need to retry since the kernel
+                        * isn't involved in encoding the ACEs.
+                        */
+                       err = -EINVAL;
+                       break;
+               }
                err = nfs4_handle_exception(NFS_SERVER(inode), err,
                                &exception);
        } while (exception.retry);
@@ -6371,6 +6421,7 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
        struct nfs4_exception exception = {
                .inode = data->inode,
                .stateid = &data->stateid,
+               .task_is_privileged = data->args.seq_args.sa_privileged,
        };
 
        if (!nfs4_sequence_done(task, &data->res.seq_res))
@@ -6494,7 +6545,6 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
        data = kzalloc(sizeof(*data), GFP_NOFS);
        if (data == NULL)
                return -ENOMEM;
-       nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1, 0);
 
        nfs4_state_protect(server->nfs_client,
                        NFS_SP4_MACH_CRED_CLEANUP,
@@ -6502,8 +6552,10 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
 
        data->args.fhandle = &data->fh;
        data->args.stateid = &data->stateid;
-       data->args.bitmask = server->cache_consistency_bitmask;
-       nfs4_bitmask_adjust(data->args.bitmask, inode, server, NULL);
+       nfs4_bitmask_set(data->args.bitmask_store,
+                        server->cache_consistency_bitmask, inode, server,
+                        NULL);
+       data->args.bitmask = data->args.bitmask_store;
        nfs_copy_fh(&data->fh, NFS_FH(inode));
        nfs4_stateid_copy(&data->stateid, stateid);
        data->res.fattr = &data->fattr;
@@ -6523,6 +6575,12 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
                }
        }
 
+       if (!data->inode)
+               nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1,
+                                  1);
+       else
+               nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1,
+                                  0);
        task_setup_data.callback_data = data;
        msg.rpc_argp = &data->args;
        msg.rpc_resp = &data->res;
@@ -7250,22 +7308,22 @@ nfs4_retry_setlk_simple(struct nfs4_state *state, int cmd,
 
 #ifdef CONFIG_NFS_V4_1
 struct nfs4_lock_waiter {
-       struct task_struct      *task;
        struct inode            *inode;
-       struct nfs_lowner       *owner;
+       struct nfs_lowner       owner;
+       wait_queue_entry_t      wait;
 };
 
 static int
 nfs4_wake_lock_waiter(wait_queue_entry_t *wait, unsigned int mode, int flags, void *key)
 {
-       int ret;
-       struct nfs4_lock_waiter *waiter = wait->private;
+       struct nfs4_lock_waiter *waiter =
+               container_of(wait, struct nfs4_lock_waiter, wait);
 
        /* NULL key means to wake up everyone */
        if (key) {
                struct cb_notify_lock_args      *cbnl = key;
                struct nfs_lowner               *lowner = &cbnl->cbnl_owner,
-                                               *wowner = waiter->owner;
+                                               *wowner = &waiter->owner;
 
                /* Only wake if the callback was for the same owner. */
                if (lowner->id != wowner->id || lowner->s_dev != wowner->s_dev)
@@ -7276,53 +7334,45 @@ nfs4_wake_lock_waiter(wait_queue_entry_t *wait, unsigned int mode, int flags, vo
                        return 0;
        }
 
-       /* override "private" so we can use default_wake_function */
-       wait->private = waiter->task;
-       ret = woken_wake_function(wait, mode, flags, key);
-       if (ret)
-               list_del_init(&wait->entry);
-       wait->private = waiter;
-       return ret;
+       return woken_wake_function(wait, mode, flags, key);
 }
 
 static int
 nfs4_retry_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
 {
-       int status = -ERESTARTSYS;
        struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner;
        struct nfs_server *server = NFS_SERVER(state->inode);
        struct nfs_client *clp = server->nfs_client;
        wait_queue_head_t *q = &clp->cl_lock_waitq;
-       struct nfs_lowner owner = { .clientid = clp->cl_clientid,
-                                   .id = lsp->ls_seqid.owner_id,
-                                   .s_dev = server->s_dev };
-       struct nfs4_lock_waiter waiter = { .task  = current,
-                                          .inode = state->inode,
-                                          .owner = &owner};
-       wait_queue_entry_t wait;
+       struct nfs4_lock_waiter waiter = {
+               .inode = state->inode,
+               .owner = { .clientid = clp->cl_clientid,
+                          .id = lsp->ls_seqid.owner_id,
+                          .s_dev = server->s_dev },
+       };
+       int status;
 
        /* Don't bother with waitqueue if we don't expect a callback */
        if (!test_bit(NFS_STATE_MAY_NOTIFY_LOCK, &state->flags))
                return nfs4_retry_setlk_simple(state, cmd, request);
 
-       init_wait(&wait);
-       wait.private = &waiter;
-       wait.func = nfs4_wake_lock_waiter;
+       init_wait(&waiter.wait);
+       waiter.wait.func = nfs4_wake_lock_waiter;
+       add_wait_queue(q, &waiter.wait);
 
-       while(!signalled()) {
-               add_wait_queue(q, &wait);
+       do {
                status = nfs4_proc_setlk(state, cmd, request);
-               if ((status != -EAGAIN) || IS_SETLK(cmd)) {
-                       finish_wait(q, &wait);
+               if (status != -EAGAIN || IS_SETLK(cmd))
                        break;
-               }
 
                status = -ERESTARTSYS;
                freezer_do_not_count();
-               wait_woken(&wait, TASK_INTERRUPTIBLE, NFS4_LOCK_MAXTIMEOUT);
+               wait_woken(&waiter.wait, TASK_INTERRUPTIBLE,
+                          NFS4_LOCK_MAXTIMEOUT);
                freezer_count();
-               finish_wait(q, &wait);
-       }
+       } while (!signalled());
+
+       remove_wait_queue(q, &waiter.wait);
 
        return status;
 }
@@ -7615,7 +7665,7 @@ static int nfs4_xattr_get_nfs4_user(const struct xattr_handler *handler,
                        return -EACCES;
        }
 
-       ret = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+       ret = nfs_revalidate_inode(inode, NFS_INO_INVALID_CHANGE);
        if (ret)
                return ret;
 
@@ -7646,7 +7696,7 @@ nfs4_listxattr_nfs4_user(struct inode *inode, char *list, size_t list_len)
                        return 0;
        }
 
-       ret = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+       ret = nfs_revalidate_inode(inode, NFS_INO_INVALID_CHANGE);
        if (ret)
                return ret;
 
@@ -9608,15 +9658,20 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp, bool sync)
                        &task_setup_data.rpc_client, &msg);
 
        dprintk("--> %s\n", __func__);
+       lrp->inode = nfs_igrab_and_active(lrp->args.inode);
        if (!sync) {
-               lrp->inode = nfs_igrab_and_active(lrp->args.inode);
                if (!lrp->inode) {
                        nfs4_layoutreturn_release(lrp);
                        return -EAGAIN;
                }
                task_setup_data.flags |= RPC_TASK_ASYNC;
        }
-       nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1, 0);
+       if (!lrp->inode)
+               nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1,
+                                  1);
+       else
+               nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1,
+                                  0);
        task = rpc_run_task(&task_setup_data);
        if (IS_ERR(task))
                return PTR_ERR(task);
@@ -10427,9 +10482,3 @@ const struct xattr_handler *nfs4_xattr_handlers[] = {
 #endif
        NULL
 };
-
-/*
- * Local variables:
- *  c-basic-offset: 8
- * End:
- */