Merge tag 'nfs-for-5.13-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
[linux-block.git] / fs / nfs / nfs4proc.c
index 545010d6cbf3c0bcc408d293d876da2ab9979db4..87d04f2c93852b28a8f7ce9c34d1ef627715ba56 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,
@@ -1169,14 +1169,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 +1198,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 +1226,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 +1234,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
@@ -3344,12 +3369,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) {
@@ -3591,6 +3621,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 +3678,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 +3868,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,25 +3878,29 @@ 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;
+               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;
 #ifdef CONFIG_NFS_V4_SECURITY_LABEL
-               if (res.attr_bitmask[2] & FATTR4_WORD2_SECURITY_LABEL)
-                       server->caps |= NFS_CAP_SECURITY_LABEL;
+               if (!(res.attr_bitmask[2] & FATTR4_WORD2_SECURITY_LABEL))
+                       server->fattr_valid &= ~NFS_ATTR_FATTR_V4_SECURITY_LABEL;
 #endif
                memcpy(server->attr_bitmask_nl, res.attr_bitmask,
                                sizeof(server->attr_bitmask));
@@ -4154,8 +4188,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 +4615,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 +4748,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 +4794,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 +4878,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 +5450,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 +5495,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 +5896,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)
@@ -6502,8 +6540,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;
@@ -7250,22 +7290,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 +7316,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 +7647,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 +7678,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;