diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-01-16 15:15:59 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-01-16 15:15:59 -0500 |
| commit | 5cf7a0f3442b2312326c39f571d637669a478235 (patch) | |
| tree | 098175ce049b7ec57cdf3bcbb827a7282d2e1997 /fs | |
| parent | 2eabb8b8d68bc9c7779ba8b04bec8d4f8baed0bc (diff) | |
| parent | c6180a6237174f481dc856ed6e890d8196b6f0fb (diff) | |
Merge tag 'nfs-for-4.10-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes from Trond Myklebust:
- fix invalid fget()/fput() calls when doing file locking
- fix multiple directory cache invalidation issues due to the client
failing to recognise that the directory wasn't changed
- fix client recovery when server reboots multiple times
* tag 'nfs-for-4.10-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
NFSv4: Fix client recovery when server reboots multiple times
NFSv4: update_changeattr should update the attribute timestamp
NFSv4: Don't call update_changeattr() unless the unlink is successful
NFSv4: Don't apply change_info4 twice on rename within a directory
NFSv4: Call update_changeattr() from _nfs4_proc_open only if a file was created
nfs: Don't take a reference on fl->fl_file for LOCK operation
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/nfs/nfs4proc.c | 29 | ||||
| -rw-r--r-- | fs/nfs/nfs4state.c | 1 |
2 files changed, 18 insertions, 12 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 6dcbc5defb7a..ecc151697fd4 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -38,7 +38,6 @@ | |||
| 38 | #include <linux/mm.h> | 38 | #include <linux/mm.h> |
| 39 | #include <linux/delay.h> | 39 | #include <linux/delay.h> |
| 40 | #include <linux/errno.h> | 40 | #include <linux/errno.h> |
| 41 | #include <linux/file.h> | ||
| 42 | #include <linux/string.h> | 41 | #include <linux/string.h> |
| 43 | #include <linux/ratelimit.h> | 42 | #include <linux/ratelimit.h> |
| 44 | #include <linux/printk.h> | 43 | #include <linux/printk.h> |
| @@ -1083,7 +1082,8 @@ int nfs4_call_sync(struct rpc_clnt *clnt, | |||
| 1083 | return nfs4_call_sync_sequence(clnt, server, msg, args, res); | 1082 | return nfs4_call_sync_sequence(clnt, server, msg, args, res); |
| 1084 | } | 1083 | } |
| 1085 | 1084 | ||
| 1086 | static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) | 1085 | static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo, |
| 1086 | unsigned long timestamp) | ||
| 1087 | { | 1087 | { |
| 1088 | struct nfs_inode *nfsi = NFS_I(dir); | 1088 | struct nfs_inode *nfsi = NFS_I(dir); |
| 1089 | 1089 | ||
| @@ -1099,6 +1099,7 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) | |||
| 1099 | NFS_INO_INVALID_ACL; | 1099 | NFS_INO_INVALID_ACL; |
| 1100 | } | 1100 | } |
| 1101 | dir->i_version = cinfo->after; | 1101 | dir->i_version = cinfo->after; |
| 1102 | nfsi->read_cache_jiffies = timestamp; | ||
| 1102 | nfsi->attr_gencount = nfs_inc_attr_generation_counter(); | 1103 | nfsi->attr_gencount = nfs_inc_attr_generation_counter(); |
| 1103 | nfs_fscache_invalidate(dir); | 1104 | nfs_fscache_invalidate(dir); |
| 1104 | spin_unlock(&dir->i_lock); | 1105 | spin_unlock(&dir->i_lock); |
| @@ -2391,11 +2392,13 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) | |||
| 2391 | nfs_fattr_map_and_free_names(server, &data->f_attr); | 2392 | nfs_fattr_map_and_free_names(server, &data->f_attr); |
| 2392 | 2393 | ||
| 2393 | if (o_arg->open_flags & O_CREAT) { | 2394 | if (o_arg->open_flags & O_CREAT) { |
| 2394 | update_changeattr(dir, &o_res->cinfo); | ||
| 2395 | if (o_arg->open_flags & O_EXCL) | 2395 | if (o_arg->open_flags & O_EXCL) |
| 2396 | data->file_created = 1; | 2396 | data->file_created = 1; |
| 2397 | else if (o_res->cinfo.before != o_res->cinfo.after) | 2397 | else if (o_res->cinfo.before != o_res->cinfo.after) |
| 2398 | data->file_created = 1; | 2398 | data->file_created = 1; |
| 2399 | if (data->file_created || dir->i_version != o_res->cinfo.after) | ||
| 2400 | update_changeattr(dir, &o_res->cinfo, | ||
| 2401 | o_res->f_attr->time_start); | ||
| 2399 | } | 2402 | } |
| 2400 | if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0) | 2403 | if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0) |
| 2401 | server->caps &= ~NFS_CAP_POSIX_LOCK; | 2404 | server->caps &= ~NFS_CAP_POSIX_LOCK; |
| @@ -4073,11 +4076,12 @@ static int _nfs4_proc_remove(struct inode *dir, const struct qstr *name) | |||
| 4073 | .rpc_argp = &args, | 4076 | .rpc_argp = &args, |
| 4074 | .rpc_resp = &res, | 4077 | .rpc_resp = &res, |
| 4075 | }; | 4078 | }; |
| 4079 | unsigned long timestamp = jiffies; | ||
| 4076 | int status; | 4080 | int status; |
| 4077 | 4081 | ||
| 4078 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 1); | 4082 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 1); |
| 4079 | if (status == 0) | 4083 | if (status == 0) |
| 4080 | update_changeattr(dir, &res.cinfo); | 4084 | update_changeattr(dir, &res.cinfo, timestamp); |
| 4081 | return status; | 4085 | return status; |
| 4082 | } | 4086 | } |
| 4083 | 4087 | ||
| @@ -4125,7 +4129,8 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) | |||
| 4125 | if (nfs4_async_handle_error(task, res->server, NULL, | 4129 | if (nfs4_async_handle_error(task, res->server, NULL, |
| 4126 | &data->timeout) == -EAGAIN) | 4130 | &data->timeout) == -EAGAIN) |
| 4127 | return 0; | 4131 | return 0; |
| 4128 | update_changeattr(dir, &res->cinfo); | 4132 | if (task->tk_status == 0) |
| 4133 | update_changeattr(dir, &res->cinfo, res->dir_attr->time_start); | ||
| 4129 | return 1; | 4134 | return 1; |
| 4130 | } | 4135 | } |
| 4131 | 4136 | ||
| @@ -4159,8 +4164,11 @@ static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir, | |||
| 4159 | if (nfs4_async_handle_error(task, res->server, NULL, &data->timeout) == -EAGAIN) | 4164 | if (nfs4_async_handle_error(task, res->server, NULL, &data->timeout) == -EAGAIN) |
| 4160 | return 0; | 4165 | return 0; |
| 4161 | 4166 | ||
| 4162 | update_changeattr(old_dir, &res->old_cinfo); | 4167 | if (task->tk_status == 0) { |
| 4163 | update_changeattr(new_dir, &res->new_cinfo); | 4168 | update_changeattr(old_dir, &res->old_cinfo, res->old_fattr->time_start); |
| 4169 | if (new_dir != old_dir) | ||
| 4170 | update_changeattr(new_dir, &res->new_cinfo, res->new_fattr->time_start); | ||
| 4171 | } | ||
| 4164 | return 1; | 4172 | return 1; |
| 4165 | } | 4173 | } |
| 4166 | 4174 | ||
| @@ -4197,7 +4205,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, const struct | |||
| 4197 | 4205 | ||
| 4198 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); | 4206 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
| 4199 | if (!status) { | 4207 | if (!status) { |
| 4200 | update_changeattr(dir, &res.cinfo); | 4208 | update_changeattr(dir, &res.cinfo, res.fattr->time_start); |
| 4201 | status = nfs_post_op_update_inode(inode, res.fattr); | 4209 | status = nfs_post_op_update_inode(inode, res.fattr); |
| 4202 | if (!status) | 4210 | if (!status) |
| 4203 | nfs_setsecurity(inode, res.fattr, res.label); | 4211 | nfs_setsecurity(inode, res.fattr, res.label); |
| @@ -4272,7 +4280,8 @@ static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_ | |||
| 4272 | int status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &data->msg, | 4280 | int status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &data->msg, |
| 4273 | &data->arg.seq_args, &data->res.seq_res, 1); | 4281 | &data->arg.seq_args, &data->res.seq_res, 1); |
| 4274 | if (status == 0) { | 4282 | if (status == 0) { |
| 4275 | update_changeattr(dir, &data->res.dir_cinfo); | 4283 | update_changeattr(dir, &data->res.dir_cinfo, |
| 4284 | data->res.fattr->time_start); | ||
| 4276 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, data->res.label); | 4285 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, data->res.label); |
| 4277 | } | 4286 | } |
| 4278 | return status; | 4287 | return status; |
| @@ -6127,7 +6136,6 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, | |||
| 6127 | p->server = server; | 6136 | p->server = server; |
| 6128 | atomic_inc(&lsp->ls_count); | 6137 | atomic_inc(&lsp->ls_count); |
| 6129 | p->ctx = get_nfs_open_context(ctx); | 6138 | p->ctx = get_nfs_open_context(ctx); |
| 6130 | get_file(fl->fl_file); | ||
| 6131 | memcpy(&p->fl, fl, sizeof(p->fl)); | 6139 | memcpy(&p->fl, fl, sizeof(p->fl)); |
| 6132 | return p; | 6140 | return p; |
| 6133 | out_free_seqid: | 6141 | out_free_seqid: |
| @@ -6240,7 +6248,6 @@ static void nfs4_lock_release(void *calldata) | |||
| 6240 | nfs_free_seqid(data->arg.lock_seqid); | 6248 | nfs_free_seqid(data->arg.lock_seqid); |
| 6241 | nfs4_put_lock_state(data->lsp); | 6249 | nfs4_put_lock_state(data->lsp); |
| 6242 | put_nfs_open_context(data->ctx); | 6250 | put_nfs_open_context(data->ctx); |
| 6243 | fput(data->fl.fl_file); | ||
| 6244 | kfree(data); | 6251 | kfree(data); |
| 6245 | dprintk("%s: done!\n", __func__); | 6252 | dprintk("%s: done!\n", __func__); |
| 6246 | } | 6253 | } |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 1d152f4470cd..90e6193ce6be 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
| @@ -1729,7 +1729,6 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) | |||
| 1729 | break; | 1729 | break; |
| 1730 | case -NFS4ERR_STALE_CLIENTID: | 1730 | case -NFS4ERR_STALE_CLIENTID: |
| 1731 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | 1731 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); |
| 1732 | nfs4_state_clear_reclaim_reboot(clp); | ||
| 1733 | nfs4_state_start_reclaim_reboot(clp); | 1732 | nfs4_state_start_reclaim_reboot(clp); |
| 1734 | break; | 1733 | break; |
| 1735 | case -NFS4ERR_EXPIRED: | 1734 | case -NFS4ERR_EXPIRED: |
