Commit 17d8428e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

* 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  nfs: Do not allow multiple mounts on same mountpoint when using -o noac
  NFS: Fix a typo in nfs_flush_multi
  NFSv4: renewd needs to be able to handle the NFS4ERR_CB_PATH_DOWN error
  NFSv4: The NFSv4.0 client must send RENEW calls if it holds a delegation
  NFSv4: nfs4_proc_renew should be declared static
  NFSv4: nfs4_proc_async_renew should use a GFP_NOFS allocation
parents fa758702 fb2088cc
...@@ -56,6 +56,9 @@ enum nfs4_session_state { ...@@ -56,6 +56,9 @@ enum nfs4_session_state {
NFS4_SESSION_DRAINING, NFS4_SESSION_DRAINING,
}; };
#define NFS4_RENEW_TIMEOUT 0x01
#define NFS4_RENEW_DELEGATION_CB 0x02
struct nfs4_minor_version_ops { struct nfs4_minor_version_ops {
u32 minor_version; u32 minor_version;
...@@ -225,7 +228,7 @@ struct nfs4_state_recovery_ops { ...@@ -225,7 +228,7 @@ struct nfs4_state_recovery_ops {
}; };
struct nfs4_state_maintenance_ops { struct nfs4_state_maintenance_ops {
int (*sched_state_renewal)(struct nfs_client *, struct rpc_cred *); int (*sched_state_renewal)(struct nfs_client *, struct rpc_cred *, unsigned);
struct rpc_cred * (*get_state_renewal_cred_locked)(struct nfs_client *); struct rpc_cred * (*get_state_renewal_cred_locked)(struct nfs_client *);
int (*renew_lease)(struct nfs_client *, struct rpc_cred *); int (*renew_lease)(struct nfs_client *, struct rpc_cred *);
}; };
...@@ -237,8 +240,6 @@ extern const struct inode_operations nfs4_dir_inode_operations; ...@@ -237,8 +240,6 @@ extern const struct inode_operations nfs4_dir_inode_operations;
extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *); extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *);
extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *); extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *);
extern int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred); extern int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred);
extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *);
extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *); extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);
extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *); extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *);
extern int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc); extern int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc);
...@@ -349,6 +350,7 @@ extern void nfs4_close_sync(struct nfs4_state *, fmode_t); ...@@ -349,6 +350,7 @@ extern void nfs4_close_sync(struct nfs4_state *, fmode_t);
extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t); extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t);
extern void nfs4_schedule_lease_recovery(struct nfs_client *); extern void nfs4_schedule_lease_recovery(struct nfs_client *);
extern void nfs4_schedule_state_manager(struct nfs_client *); extern void nfs4_schedule_state_manager(struct nfs_client *);
extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp);
extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *); extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *);
extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags);
extern void nfs41_handle_recall_slot(struct nfs_client *clp); extern void nfs41_handle_recall_slot(struct nfs_client *clp);
......
...@@ -3374,9 +3374,13 @@ static void nfs4_renew_done(struct rpc_task *task, void *calldata) ...@@ -3374,9 +3374,13 @@ static void nfs4_renew_done(struct rpc_task *task, void *calldata)
if (task->tk_status < 0) { if (task->tk_status < 0) {
/* Unless we're shutting down, schedule state recovery! */ /* Unless we're shutting down, schedule state recovery! */
if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) != 0) if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) == 0)
return;
if (task->tk_status != NFS4ERR_CB_PATH_DOWN) {
nfs4_schedule_lease_recovery(clp); nfs4_schedule_lease_recovery(clp);
return; return;
}
nfs4_schedule_path_down_recovery(clp);
} }
do_renew_lease(clp, timestamp); do_renew_lease(clp, timestamp);
} }
...@@ -3386,7 +3390,7 @@ static const struct rpc_call_ops nfs4_renew_ops = { ...@@ -3386,7 +3390,7 @@ static const struct rpc_call_ops nfs4_renew_ops = {
.rpc_release = nfs4_renew_release, .rpc_release = nfs4_renew_release,
}; };
int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred) static int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred, unsigned renew_flags)
{ {
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW], .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW],
...@@ -3395,9 +3399,11 @@ int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred) ...@@ -3395,9 +3399,11 @@ int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred)
}; };
struct nfs4_renewdata *data; struct nfs4_renewdata *data;
if (renew_flags == 0)
return 0;
if (!atomic_inc_not_zero(&clp->cl_count)) if (!atomic_inc_not_zero(&clp->cl_count))
return -EIO; return -EIO;
data = kmalloc(sizeof(*data), GFP_KERNEL); data = kmalloc(sizeof(*data), GFP_NOFS);
if (data == NULL) if (data == NULL)
return -ENOMEM; return -ENOMEM;
data->client = clp; data->client = clp;
...@@ -3406,7 +3412,7 @@ int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred) ...@@ -3406,7 +3412,7 @@ int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred)
&nfs4_renew_ops, data); &nfs4_renew_ops, data);
} }
int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred) static int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred)
{ {
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW], .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW],
...@@ -5504,11 +5510,13 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_ ...@@ -5504,11 +5510,13 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_
return rpc_run_task(&task_setup_data); return rpc_run_task(&task_setup_data);
} }
static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cred) static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cred, unsigned renew_flags)
{ {
struct rpc_task *task; struct rpc_task *task;
int ret = 0; int ret = 0;
if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0)
return 0;
task = _nfs41_proc_sequence(clp, cred); task = _nfs41_proc_sequence(clp, cred);
if (IS_ERR(task)) if (IS_ERR(task))
ret = PTR_ERR(task); ret = PTR_ERR(task);
......
...@@ -60,6 +60,7 @@ nfs4_renew_state(struct work_struct *work) ...@@ -60,6 +60,7 @@ nfs4_renew_state(struct work_struct *work)
struct rpc_cred *cred; struct rpc_cred *cred;
long lease; long lease;
unsigned long last, now; unsigned long last, now;
unsigned renew_flags = 0;
ops = clp->cl_mvops->state_renewal_ops; ops = clp->cl_mvops->state_renewal_ops;
dprintk("%s: start\n", __func__); dprintk("%s: start\n", __func__);
...@@ -72,18 +73,23 @@ nfs4_renew_state(struct work_struct *work) ...@@ -72,18 +73,23 @@ nfs4_renew_state(struct work_struct *work)
last = clp->cl_last_renewal; last = clp->cl_last_renewal;
now = jiffies; now = jiffies;
/* Are we close to a lease timeout? */ /* Are we close to a lease timeout? */
if (time_after(now, last + lease/3)) { if (time_after(now, last + lease/3))
renew_flags |= NFS4_RENEW_TIMEOUT;
if (nfs_delegations_present(clp))
renew_flags |= NFS4_RENEW_DELEGATION_CB;
if (renew_flags != 0) {
cred = ops->get_state_renewal_cred_locked(clp); cred = ops->get_state_renewal_cred_locked(clp);
spin_unlock(&clp->cl_lock); spin_unlock(&clp->cl_lock);
if (cred == NULL) { if (cred == NULL) {
if (!nfs_delegations_present(clp)) { if (!(renew_flags & NFS4_RENEW_DELEGATION_CB)) {
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
goto out; goto out;
} }
nfs_expire_all_delegations(clp); nfs_expire_all_delegations(clp);
} else { } else {
/* Queue an asynchronous RENEW. */ /* Queue an asynchronous RENEW. */
ops->sched_state_renewal(clp, cred); ops->sched_state_renewal(clp, cred, renew_flags);
put_rpccred(cred); put_rpccred(cred);
goto out_exp; goto out_exp;
} }
......
...@@ -1038,6 +1038,12 @@ void nfs4_schedule_lease_recovery(struct nfs_client *clp) ...@@ -1038,6 +1038,12 @@ void nfs4_schedule_lease_recovery(struct nfs_client *clp)
nfs4_schedule_state_manager(clp); nfs4_schedule_state_manager(clp);
} }
void nfs4_schedule_path_down_recovery(struct nfs_client *clp)
{
nfs_handle_cb_pathdown(clp);
nfs4_schedule_state_manager(clp);
}
static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state)
{ {
......
...@@ -2035,9 +2035,6 @@ static inline void nfs_initialise_sb(struct super_block *sb) ...@@ -2035,9 +2035,6 @@ static inline void nfs_initialise_sb(struct super_block *sb)
sb->s_blocksize = nfs_block_bits(server->wsize, sb->s_blocksize = nfs_block_bits(server->wsize,
&sb->s_blocksize_bits); &sb->s_blocksize_bits);
if (server->flags & NFS_MOUNT_NOAC)
sb->s_flags |= MS_SYNCHRONOUS;
sb->s_bdi = &server->backing_dev_info; sb->s_bdi = &server->backing_dev_info;
nfs_super_set_maxbytes(sb, server->maxfilesize); nfs_super_set_maxbytes(sb, server->maxfilesize);
...@@ -2249,6 +2246,10 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type, ...@@ -2249,6 +2246,10 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
if (server->flags & NFS_MOUNT_UNSHARED) if (server->flags & NFS_MOUNT_UNSHARED)
compare_super = NULL; compare_super = NULL;
/* -o noac implies -o sync */
if (server->flags & NFS_MOUNT_NOAC)
sb_mntdata.mntflags |= MS_SYNCHRONOUS;
/* Get a superblock - note that we may end up sharing one that already exists */ /* Get a superblock - note that we may end up sharing one that already exists */
s = sget(fs_type, compare_super, nfs_set_super, &sb_mntdata); s = sget(fs_type, compare_super, nfs_set_super, &sb_mntdata);
if (IS_ERR(s)) { if (IS_ERR(s)) {
...@@ -2361,6 +2362,10 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags, ...@@ -2361,6 +2362,10 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
if (server->flags & NFS_MOUNT_UNSHARED) if (server->flags & NFS_MOUNT_UNSHARED)
compare_super = NULL; compare_super = NULL;
/* -o noac implies -o sync */
if (server->flags & NFS_MOUNT_NOAC)
sb_mntdata.mntflags |= MS_SYNCHRONOUS;
/* Get a superblock - note that we may end up sharing one that already exists */ /* Get a superblock - note that we may end up sharing one that already exists */
s = sget(&nfs_fs_type, compare_super, nfs_set_super, &sb_mntdata); s = sget(&nfs_fs_type, compare_super, nfs_set_super, &sb_mntdata);
if (IS_ERR(s)) { if (IS_ERR(s)) {
...@@ -2628,6 +2633,10 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags, ...@@ -2628,6 +2633,10 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags,
if (server->flags & NFS4_MOUNT_UNSHARED) if (server->flags & NFS4_MOUNT_UNSHARED)
compare_super = NULL; compare_super = NULL;
/* -o noac implies -o sync */
if (server->flags & NFS_MOUNT_NOAC)
sb_mntdata.mntflags |= MS_SYNCHRONOUS;
/* Get a superblock - note that we may end up sharing one that already exists */ /* Get a superblock - note that we may end up sharing one that already exists */
s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata); s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);
if (IS_ERR(s)) { if (IS_ERR(s)) {
...@@ -2916,6 +2925,10 @@ nfs4_xdev_mount(struct file_system_type *fs_type, int flags, ...@@ -2916,6 +2925,10 @@ nfs4_xdev_mount(struct file_system_type *fs_type, int flags,
if (server->flags & NFS4_MOUNT_UNSHARED) if (server->flags & NFS4_MOUNT_UNSHARED)
compare_super = NULL; compare_super = NULL;
/* -o noac implies -o sync */
if (server->flags & NFS_MOUNT_NOAC)
sb_mntdata.mntflags |= MS_SYNCHRONOUS;
/* Get a superblock - note that we may end up sharing one that already exists */ /* Get a superblock - note that we may end up sharing one that already exists */
s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata); s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);
if (IS_ERR(s)) { if (IS_ERR(s)) {
...@@ -3003,6 +3016,10 @@ nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags, ...@@ -3003,6 +3016,10 @@ nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
if (server->flags & NFS4_MOUNT_UNSHARED) if (server->flags & NFS4_MOUNT_UNSHARED)
compare_super = NULL; compare_super = NULL;
/* -o noac implies -o sync */
if (server->flags & NFS_MOUNT_NOAC)
sb_mntdata.mntflags |= MS_SYNCHRONOUS;
/* Get a superblock - note that we may end up sharing one that already exists */ /* Get a superblock - note that we may end up sharing one that already exists */
s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata); s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);
if (IS_ERR(s)) { if (IS_ERR(s)) {
......
...@@ -958,7 +958,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc, struct list_head ...@@ -958,7 +958,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc, struct list_head
if (!data) if (!data)
goto out_bad; goto out_bad;
data->pagevec[0] = page; data->pagevec[0] = page;
nfs_write_rpcsetup(req, data, wsize, offset, desc->pg_ioflags); nfs_write_rpcsetup(req, data, len, offset, desc->pg_ioflags);
list_add(&data->list, res); list_add(&data->list, res);
requests++; requests++;
nbytes -= len; nbytes -= len;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment