NFS client bugfixes for Linux 4.10
Bugfixes: - 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 -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJYfSXZAAoJEGcL54qWCgDy3K8P/0YGi1J5VoWkcMD5+Ljh2H3O AV1oZ3EWLXH2jlJZmX7A1A9ReOEmsYmCX+8QM2ZWbBZI+vIzEJEWd7fU+nhtgfiq pcw29CSpeBhfcqSswlRE6ouxKpmufnzhwbuGcy9WUTyGYaz1k05/4YHTunyxiZr6 QRHL2Y0YkU0cWD1FHwoOkQr8ft7kdQ4iXHru9utttdYsb4vJnX9ShLpaLW5MDBqS hPd1ivJHPlWiOVEzLSlTHBvTvw8j5PjhsRQ/q5UwiDvQQDoWL7/qnP4nxZee44mh MQ+61/0WxS+ohMkIYrZ6hPezk2QX/i7JRQvBPNU07U/+TqtsWX/F5+OerCeQ4/6W RhP7XDjJV8TpeeJcUU58r1aoEpaWRt9cmtwBWMKBu9tTHCFyRXHsaIh1ZR+Hy85e HUiiaD4rPldr+ZbCcTwR5bSSkF96WaRF9B3L8Nvgys9v4wwO6LuTnHv5uY8H7ct5 I66nL14drrA+jC01D+SuMl0AnFhrCp7mJyJbrZDvXBJ9hxzzgEj/Jz3IC0mc0SxI ZjFhQoG2NjV2oJ0PTu9RMUw+Fex0yz6PsXoHLKr45VXkkwQL3Uldq6SVWfkkzqUk SPFTYD49i9TqCHhGZEzm7kGNM6ASUDKQtAloiUA2QvL6v178RLwG2sjYxy2kEApz s208kzh8He79iMLEkphR =K8F7 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
5cf7a0f344
@ -38,7 +38,6 @@
|
|||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/file.h>
|
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/ratelimit.h>
|
#include <linux/ratelimit.h>
|
||||||
#include <linux/printk.h>
|
#include <linux/printk.h>
|
||||||
@ -1083,7 +1082,8 @@ int nfs4_call_sync(struct rpc_clnt *clnt,
|
|||||||
return nfs4_call_sync_sequence(clnt, server, msg, args, res);
|
return nfs4_call_sync_sequence(clnt, server, msg, args, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
|
static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo,
|
||||||
|
unsigned long timestamp)
|
||||||
{
|
{
|
||||||
struct nfs_inode *nfsi = NFS_I(dir);
|
struct nfs_inode *nfsi = NFS_I(dir);
|
||||||
|
|
||||||
@ -1099,6 +1099,7 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
|
|||||||
NFS_INO_INVALID_ACL;
|
NFS_INO_INVALID_ACL;
|
||||||
}
|
}
|
||||||
dir->i_version = cinfo->after;
|
dir->i_version = cinfo->after;
|
||||||
|
nfsi->read_cache_jiffies = timestamp;
|
||||||
nfsi->attr_gencount = nfs_inc_attr_generation_counter();
|
nfsi->attr_gencount = nfs_inc_attr_generation_counter();
|
||||||
nfs_fscache_invalidate(dir);
|
nfs_fscache_invalidate(dir);
|
||||||
spin_unlock(&dir->i_lock);
|
spin_unlock(&dir->i_lock);
|
||||||
@ -2391,11 +2392,13 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
|
|||||||
nfs_fattr_map_and_free_names(server, &data->f_attr);
|
nfs_fattr_map_and_free_names(server, &data->f_attr);
|
||||||
|
|
||||||
if (o_arg->open_flags & O_CREAT) {
|
if (o_arg->open_flags & O_CREAT) {
|
||||||
update_changeattr(dir, &o_res->cinfo);
|
|
||||||
if (o_arg->open_flags & O_EXCL)
|
if (o_arg->open_flags & O_EXCL)
|
||||||
data->file_created = 1;
|
data->file_created = 1;
|
||||||
else if (o_res->cinfo.before != o_res->cinfo.after)
|
else if (o_res->cinfo.before != o_res->cinfo.after)
|
||||||
data->file_created = 1;
|
data->file_created = 1;
|
||||||
|
if (data->file_created || dir->i_version != o_res->cinfo.after)
|
||||||
|
update_changeattr(dir, &o_res->cinfo,
|
||||||
|
o_res->f_attr->time_start);
|
||||||
}
|
}
|
||||||
if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0)
|
if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0)
|
||||||
server->caps &= ~NFS_CAP_POSIX_LOCK;
|
server->caps &= ~NFS_CAP_POSIX_LOCK;
|
||||||
@ -4073,11 +4076,12 @@ static int _nfs4_proc_remove(struct inode *dir, const struct qstr *name)
|
|||||||
.rpc_argp = &args,
|
.rpc_argp = &args,
|
||||||
.rpc_resp = &res,
|
.rpc_resp = &res,
|
||||||
};
|
};
|
||||||
|
unsigned long timestamp = jiffies;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 1);
|
status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 1);
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
update_changeattr(dir, &res.cinfo);
|
update_changeattr(dir, &res.cinfo, timestamp);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4125,7 +4129,8 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
|
|||||||
if (nfs4_async_handle_error(task, res->server, NULL,
|
if (nfs4_async_handle_error(task, res->server, NULL,
|
||||||
&data->timeout) == -EAGAIN)
|
&data->timeout) == -EAGAIN)
|
||||||
return 0;
|
return 0;
|
||||||
update_changeattr(dir, &res->cinfo);
|
if (task->tk_status == 0)
|
||||||
|
update_changeattr(dir, &res->cinfo, res->dir_attr->time_start);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4159,8 +4164,11 @@ static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
|
|||||||
if (nfs4_async_handle_error(task, res->server, NULL, &data->timeout) == -EAGAIN)
|
if (nfs4_async_handle_error(task, res->server, NULL, &data->timeout) == -EAGAIN)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
update_changeattr(old_dir, &res->old_cinfo);
|
if (task->tk_status == 0) {
|
||||||
update_changeattr(new_dir, &res->new_cinfo);
|
update_changeattr(old_dir, &res->old_cinfo, res->old_fattr->time_start);
|
||||||
|
if (new_dir != old_dir)
|
||||||
|
update_changeattr(new_dir, &res->new_cinfo, res->new_fattr->time_start);
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4197,7 +4205,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, const struct
|
|||||||
|
|
||||||
status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
|
status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
|
||||||
if (!status) {
|
if (!status) {
|
||||||
update_changeattr(dir, &res.cinfo);
|
update_changeattr(dir, &res.cinfo, res.fattr->time_start);
|
||||||
status = nfs_post_op_update_inode(inode, res.fattr);
|
status = nfs_post_op_update_inode(inode, res.fattr);
|
||||||
if (!status)
|
if (!status)
|
||||||
nfs_setsecurity(inode, res.fattr, res.label);
|
nfs_setsecurity(inode, res.fattr, res.label);
|
||||||
@ -4272,7 +4280,8 @@ static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_
|
|||||||
int status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &data->msg,
|
int status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &data->msg,
|
||||||
&data->arg.seq_args, &data->res.seq_res, 1);
|
&data->arg.seq_args, &data->res.seq_res, 1);
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
update_changeattr(dir, &data->res.dir_cinfo);
|
update_changeattr(dir, &data->res.dir_cinfo,
|
||||||
|
data->res.fattr->time_start);
|
||||||
status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, data->res.label);
|
status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, data->res.label);
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
@ -6127,7 +6136,6 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
|
|||||||
p->server = server;
|
p->server = server;
|
||||||
atomic_inc(&lsp->ls_count);
|
atomic_inc(&lsp->ls_count);
|
||||||
p->ctx = get_nfs_open_context(ctx);
|
p->ctx = get_nfs_open_context(ctx);
|
||||||
get_file(fl->fl_file);
|
|
||||||
memcpy(&p->fl, fl, sizeof(p->fl));
|
memcpy(&p->fl, fl, sizeof(p->fl));
|
||||||
return p;
|
return p;
|
||||||
out_free_seqid:
|
out_free_seqid:
|
||||||
@ -6240,7 +6248,6 @@ static void nfs4_lock_release(void *calldata)
|
|||||||
nfs_free_seqid(data->arg.lock_seqid);
|
nfs_free_seqid(data->arg.lock_seqid);
|
||||||
nfs4_put_lock_state(data->lsp);
|
nfs4_put_lock_state(data->lsp);
|
||||||
put_nfs_open_context(data->ctx);
|
put_nfs_open_context(data->ctx);
|
||||||
fput(data->fl.fl_file);
|
|
||||||
kfree(data);
|
kfree(data);
|
||||||
dprintk("%s: done!\n", __func__);
|
dprintk("%s: done!\n", __func__);
|
||||||
}
|
}
|
||||||
|
@ -1729,7 +1729,6 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
|
|||||||
break;
|
break;
|
||||||
case -NFS4ERR_STALE_CLIENTID:
|
case -NFS4ERR_STALE_CLIENTID:
|
||||||
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
|
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
|
||||||
nfs4_state_clear_reclaim_reboot(clp);
|
|
||||||
nfs4_state_start_reclaim_reboot(clp);
|
nfs4_state_start_reclaim_reboot(clp);
|
||||||
break;
|
break;
|
||||||
case -NFS4ERR_EXPIRED:
|
case -NFS4ERR_EXPIRED:
|
||||||
|
Loading…
Reference in New Issue
Block a user