aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-09-15 15:36:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-09-15 15:36:01 -0400
commit17d8428e4c911f7877d8470bca7a09a4b2aa2d57 (patch)
treef5d28b15f08b04172380d43f3a9181e2d760a047 /fs
parentfa758702c298c98674ec641e9252e507ddaa29be (diff)
parentfb2088ccc139ffbf1cf359216883712dab4ae43d (diff)
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
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/nfs4_fs.h8
-rw-r--r--fs/nfs/nfs4proc.c20
-rw-r--r--fs/nfs/nfs4renewd.c12
-rw-r--r--fs/nfs/nfs4state.c6
-rw-r--r--fs/nfs/super.c23
-rw-r--r--fs/nfs/write.c2
6 files changed, 55 insertions, 16 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 1ec1a85fa71c..3e93e9a1bee1 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -56,6 +56,9 @@ enum nfs4_session_state {
56 NFS4_SESSION_DRAINING, 56 NFS4_SESSION_DRAINING,
57}; 57};
58 58
59#define NFS4_RENEW_TIMEOUT 0x01
60#define NFS4_RENEW_DELEGATION_CB 0x02
61
59struct nfs4_minor_version_ops { 62struct nfs4_minor_version_ops {
60 u32 minor_version; 63 u32 minor_version;
61 64
@@ -225,7 +228,7 @@ struct nfs4_state_recovery_ops {
225}; 228};
226 229
227struct nfs4_state_maintenance_ops { 230struct nfs4_state_maintenance_ops {
228 int (*sched_state_renewal)(struct nfs_client *, struct rpc_cred *); 231 int (*sched_state_renewal)(struct nfs_client *, struct rpc_cred *, unsigned);
229 struct rpc_cred * (*get_state_renewal_cred_locked)(struct nfs_client *); 232 struct rpc_cred * (*get_state_renewal_cred_locked)(struct nfs_client *);
230 int (*renew_lease)(struct nfs_client *, struct rpc_cred *); 233 int (*renew_lease)(struct nfs_client *, struct rpc_cred *);
231}; 234};
@@ -237,8 +240,6 @@ extern const struct inode_operations nfs4_dir_inode_operations;
237extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *); 240extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *);
238extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *); 241extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *);
239extern int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred); 242extern int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred);
240extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *);
241extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
242extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *); 243extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);
243extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *); 244extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *);
244extern int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc); 245extern 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);
349extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t); 350extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t);
350extern void nfs4_schedule_lease_recovery(struct nfs_client *); 351extern void nfs4_schedule_lease_recovery(struct nfs_client *);
351extern void nfs4_schedule_state_manager(struct nfs_client *); 352extern void nfs4_schedule_state_manager(struct nfs_client *);
353extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp);
352extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *); 354extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *);
353extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); 355extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags);
354extern void nfs41_handle_recall_slot(struct nfs_client *clp); 356extern void nfs41_handle_recall_slot(struct nfs_client *clp);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 8c77039e7a81..4700fae1ada0 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3374,9 +3374,13 @@ static void nfs4_renew_done(struct rpc_task *task, void *calldata)
3374 3374
3375 if (task->tk_status < 0) { 3375 if (task->tk_status < 0) {
3376 /* Unless we're shutting down, schedule state recovery! */ 3376 /* Unless we're shutting down, schedule state recovery! */
3377 if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) != 0) 3377 if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) == 0)
3378 return;
3379 if (task->tk_status != NFS4ERR_CB_PATH_DOWN) {
3378 nfs4_schedule_lease_recovery(clp); 3380 nfs4_schedule_lease_recovery(clp);
3379 return; 3381 return;
3382 }
3383 nfs4_schedule_path_down_recovery(clp);
3380 } 3384 }
3381 do_renew_lease(clp, timestamp); 3385 do_renew_lease(clp, timestamp);
3382} 3386}
@@ -3386,7 +3390,7 @@ static const struct rpc_call_ops nfs4_renew_ops = {
3386 .rpc_release = nfs4_renew_release, 3390 .rpc_release = nfs4_renew_release,
3387}; 3391};
3388 3392
3389int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred) 3393static int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred, unsigned renew_flags)
3390{ 3394{
3391 struct rpc_message msg = { 3395 struct rpc_message msg = {
3392 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW], 3396 .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 }; 3399 };
3396 struct nfs4_renewdata *data; 3400 struct nfs4_renewdata *data;
3397 3401
3402 if (renew_flags == 0)
3403 return 0;
3398 if (!atomic_inc_not_zero(&clp->cl_count)) 3404 if (!atomic_inc_not_zero(&clp->cl_count))
3399 return -EIO; 3405 return -EIO;
3400 data = kmalloc(sizeof(*data), GFP_KERNEL); 3406 data = kmalloc(sizeof(*data), GFP_NOFS);
3401 if (data == NULL) 3407 if (data == NULL)
3402 return -ENOMEM; 3408 return -ENOMEM;
3403 data->client = clp; 3409 data->client = clp;
@@ -3406,7 +3412,7 @@ int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred)
3406 &nfs4_renew_ops, data); 3412 &nfs4_renew_ops, data);
3407} 3413}
3408 3414
3409int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred) 3415static int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred)
3410{ 3416{
3411 struct rpc_message msg = { 3417 struct rpc_message msg = {
3412 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW], 3418 .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 return rpc_run_task(&task_setup_data); 5510 return rpc_run_task(&task_setup_data);
5505} 5511}
5506 5512
5507static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cred) 5513static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cred, unsigned renew_flags)
5508{ 5514{
5509 struct rpc_task *task; 5515 struct rpc_task *task;
5510 int ret = 0; 5516 int ret = 0;
5511 5517
5518 if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0)
5519 return 0;
5512 task = _nfs41_proc_sequence(clp, cred); 5520 task = _nfs41_proc_sequence(clp, cred);
5513 if (IS_ERR(task)) 5521 if (IS_ERR(task))
5514 ret = PTR_ERR(task); 5522 ret = PTR_ERR(task);
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index df8e7f3ca56d..dc484c0eae7f 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -60,6 +60,7 @@ nfs4_renew_state(struct work_struct *work)
60 struct rpc_cred *cred; 60 struct rpc_cred *cred;
61 long lease; 61 long lease;
62 unsigned long last, now; 62 unsigned long last, now;
63 unsigned renew_flags = 0;
63 64
64 ops = clp->cl_mvops->state_renewal_ops; 65 ops = clp->cl_mvops->state_renewal_ops;
65 dprintk("%s: start\n", __func__); 66 dprintk("%s: start\n", __func__);
@@ -72,18 +73,23 @@ nfs4_renew_state(struct work_struct *work)
72 last = clp->cl_last_renewal; 73 last = clp->cl_last_renewal;
73 now = jiffies; 74 now = jiffies;
74 /* Are we close to a lease timeout? */ 75 /* Are we close to a lease timeout? */
75 if (time_after(now, last + lease/3)) { 76 if (time_after(now, last + lease/3))
77 renew_flags |= NFS4_RENEW_TIMEOUT;
78 if (nfs_delegations_present(clp))
79 renew_flags |= NFS4_RENEW_DELEGATION_CB;
80
81 if (renew_flags != 0) {
76 cred = ops->get_state_renewal_cred_locked(clp); 82 cred = ops->get_state_renewal_cred_locked(clp);
77 spin_unlock(&clp->cl_lock); 83 spin_unlock(&clp->cl_lock);
78 if (cred == NULL) { 84 if (cred == NULL) {
79 if (!nfs_delegations_present(clp)) { 85 if (!(renew_flags & NFS4_RENEW_DELEGATION_CB)) {
80 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); 86 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
81 goto out; 87 goto out;
82 } 88 }
83 nfs_expire_all_delegations(clp); 89 nfs_expire_all_delegations(clp);
84 } else { 90 } else {
85 /* Queue an asynchronous RENEW. */ 91 /* Queue an asynchronous RENEW. */
86 ops->sched_state_renewal(clp, cred); 92 ops->sched_state_renewal(clp, cred, renew_flags);
87 put_rpccred(cred); 93 put_rpccred(cred);
88 goto out_exp; 94 goto out_exp;
89 } 95 }
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 72ab97ef3d61..39914be40b03 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1038,6 +1038,12 @@ void nfs4_schedule_lease_recovery(struct nfs_client *clp)
1038 nfs4_schedule_state_manager(clp); 1038 nfs4_schedule_state_manager(clp);
1039} 1039}
1040 1040
1041void nfs4_schedule_path_down_recovery(struct nfs_client *clp)
1042{
1043 nfs_handle_cb_pathdown(clp);
1044 nfs4_schedule_state_manager(clp);
1045}
1046
1041static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) 1047static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state)
1042{ 1048{
1043 1049
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index b961ceac66b4..9b7dd7013b15 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2035,9 +2035,6 @@ static inline void nfs_initialise_sb(struct super_block *sb)
2035 sb->s_blocksize = nfs_block_bits(server->wsize, 2035 sb->s_blocksize = nfs_block_bits(server->wsize,
2036 &sb->s_blocksize_bits); 2036 &sb->s_blocksize_bits);
2037 2037
2038 if (server->flags & NFS_MOUNT_NOAC)
2039 sb->s_flags |= MS_SYNCHRONOUS;
2040
2041 sb->s_bdi = &server->backing_dev_info; 2038 sb->s_bdi = &server->backing_dev_info;
2042 2039
2043 nfs_super_set_maxbytes(sb, server->maxfilesize); 2040 nfs_super_set_maxbytes(sb, server->maxfilesize);
@@ -2249,6 +2246,10 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
2249 if (server->flags & NFS_MOUNT_UNSHARED) 2246 if (server->flags & NFS_MOUNT_UNSHARED)
2250 compare_super = NULL; 2247 compare_super = NULL;
2251 2248
2249 /* -o noac implies -o sync */
2250 if (server->flags & NFS_MOUNT_NOAC)
2251 sb_mntdata.mntflags |= MS_SYNCHRONOUS;
2252
2252 /* Get a superblock - note that we may end up sharing one that already exists */ 2253 /* Get a superblock - note that we may end up sharing one that already exists */
2253 s = sget(fs_type, compare_super, nfs_set_super, &sb_mntdata); 2254 s = sget(fs_type, compare_super, nfs_set_super, &sb_mntdata);
2254 if (IS_ERR(s)) { 2255 if (IS_ERR(s)) {
@@ -2361,6 +2362,10 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
2361 if (server->flags & NFS_MOUNT_UNSHARED) 2362 if (server->flags & NFS_MOUNT_UNSHARED)
2362 compare_super = NULL; 2363 compare_super = NULL;
2363 2364
2365 /* -o noac implies -o sync */
2366 if (server->flags & NFS_MOUNT_NOAC)
2367 sb_mntdata.mntflags |= MS_SYNCHRONOUS;
2368
2364 /* Get a superblock - note that we may end up sharing one that already exists */ 2369 /* Get a superblock - note that we may end up sharing one that already exists */
2365 s = sget(&nfs_fs_type, compare_super, nfs_set_super, &sb_mntdata); 2370 s = sget(&nfs_fs_type, compare_super, nfs_set_super, &sb_mntdata);
2366 if (IS_ERR(s)) { 2371 if (IS_ERR(s)) {
@@ -2628,6 +2633,10 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags,
2628 if (server->flags & NFS4_MOUNT_UNSHARED) 2633 if (server->flags & NFS4_MOUNT_UNSHARED)
2629 compare_super = NULL; 2634 compare_super = NULL;
2630 2635
2636 /* -o noac implies -o sync */
2637 if (server->flags & NFS_MOUNT_NOAC)
2638 sb_mntdata.mntflags |= MS_SYNCHRONOUS;
2639
2631 /* Get a superblock - note that we may end up sharing one that already exists */ 2640 /* Get a superblock - note that we may end up sharing one that already exists */
2632 s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata); 2641 s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);
2633 if (IS_ERR(s)) { 2642 if (IS_ERR(s)) {
@@ -2916,6 +2925,10 @@ nfs4_xdev_mount(struct file_system_type *fs_type, int flags,
2916 if (server->flags & NFS4_MOUNT_UNSHARED) 2925 if (server->flags & NFS4_MOUNT_UNSHARED)
2917 compare_super = NULL; 2926 compare_super = NULL;
2918 2927
2928 /* -o noac implies -o sync */
2929 if (server->flags & NFS_MOUNT_NOAC)
2930 sb_mntdata.mntflags |= MS_SYNCHRONOUS;
2931
2919 /* Get a superblock - note that we may end up sharing one that already exists */ 2932 /* Get a superblock - note that we may end up sharing one that already exists */
2920 s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata); 2933 s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);
2921 if (IS_ERR(s)) { 2934 if (IS_ERR(s)) {
@@ -3003,6 +3016,10 @@ nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
3003 if (server->flags & NFS4_MOUNT_UNSHARED) 3016 if (server->flags & NFS4_MOUNT_UNSHARED)
3004 compare_super = NULL; 3017 compare_super = NULL;
3005 3018
3019 /* -o noac implies -o sync */
3020 if (server->flags & NFS_MOUNT_NOAC)
3021 sb_mntdata.mntflags |= MS_SYNCHRONOUS;
3022
3006 /* Get a superblock - note that we may end up sharing one that already exists */ 3023 /* Get a superblock - note that we may end up sharing one that already exists */
3007 s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata); 3024 s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);
3008 if (IS_ERR(s)) { 3025 if (IS_ERR(s)) {
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index b39b37f80913..c9bd2a6b7d4b 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -958,7 +958,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc, struct list_head
958 if (!data) 958 if (!data)
959 goto out_bad; 959 goto out_bad;
960 data->pagevec[0] = page; 960 data->pagevec[0] = page;
961 nfs_write_rpcsetup(req, data, wsize, offset, desc->pg_ioflags); 961 nfs_write_rpcsetup(req, data, len, offset, desc->pg_ioflags);
962 list_add(&data->list, res); 962 list_add(&data->list, res);
963 requests++; 963 requests++;
964 nbytes -= len; 964 nbytes -= len;