aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2009-12-03 16:01:51 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2009-12-03 16:01:51 -0500
commit0b08b07507d5ae733408fd4ebda1cd89d3a840ef (patch)
treec91d8b77610f640cd930f62407b9fc5fec283773 /fs/nfs
parent22763c5cf3690a681551162c15d34d935308c8d7 (diff)
parent1185a552e3d78807031f4021c5edb60d3e8838f1 (diff)
Merge branch 'bugfixes' into nfs-for-next
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/delegation.c42
-rw-r--r--fs/nfs/delegation.h2
-rw-r--r--fs/nfs/dns_resolve.c4
-rw-r--r--fs/nfs/nfs4proc.c28
-rw-r--r--fs/nfs/nfs4state.c67
-rw-r--r--fs/nfs/nfs4xdr.c2
6 files changed, 83 insertions, 62 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 6dd48a4405b4..eeecd69c130c 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -92,7 +92,7 @@ out:
92 return status; 92 return status;
93} 93}
94 94
95static void nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid) 95static int nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid)
96{ 96{
97 struct nfs_inode *nfsi = NFS_I(inode); 97 struct nfs_inode *nfsi = NFS_I(inode);
98 struct nfs_open_context *ctx; 98 struct nfs_open_context *ctx;
@@ -116,10 +116,11 @@ again:
116 err = nfs_delegation_claim_locks(ctx, state); 116 err = nfs_delegation_claim_locks(ctx, state);
117 put_nfs_open_context(ctx); 117 put_nfs_open_context(ctx);
118 if (err != 0) 118 if (err != 0)
119 return; 119 return err;
120 goto again; 120 goto again;
121 } 121 }
122 spin_unlock(&inode->i_lock); 122 spin_unlock(&inode->i_lock);
123 return 0;
123} 124}
124 125
125/* 126/*
@@ -261,30 +262,34 @@ static void nfs_msync_inode(struct inode *inode)
261/* 262/*
262 * Basic procedure for returning a delegation to the server 263 * Basic procedure for returning a delegation to the server
263 */ 264 */
264static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation) 265static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync)
265{ 266{
266 struct nfs_inode *nfsi = NFS_I(inode); 267 struct nfs_inode *nfsi = NFS_I(inode);
268 int err;
267 269
268 nfs_msync_inode(inode);
269 /* 270 /*
270 * Guard against new delegated open/lock/unlock calls and against 271 * Guard against new delegated open/lock/unlock calls and against
271 * state recovery 272 * state recovery
272 */ 273 */
273 down_write(&nfsi->rwsem); 274 down_write(&nfsi->rwsem);
274 nfs_delegation_claim_opens(inode, &delegation->stateid); 275 err = nfs_delegation_claim_opens(inode, &delegation->stateid);
275 up_write(&nfsi->rwsem); 276 up_write(&nfsi->rwsem);
276 nfs_msync_inode(inode); 277 if (err)
278 goto out;
277 279
278 return nfs_do_return_delegation(inode, delegation, 1); 280 err = nfs_do_return_delegation(inode, delegation, issync);
281out:
282 return err;
279} 283}
280 284
281/* 285/*
282 * Return all delegations that have been marked for return 286 * Return all delegations that have been marked for return
283 */ 287 */
284void nfs_client_return_marked_delegations(struct nfs_client *clp) 288int nfs_client_return_marked_delegations(struct nfs_client *clp)
285{ 289{
286 struct nfs_delegation *delegation; 290 struct nfs_delegation *delegation;
287 struct inode *inode; 291 struct inode *inode;
292 int err = 0;
288 293
289restart: 294restart:
290 rcu_read_lock(); 295 rcu_read_lock();
@@ -298,12 +303,18 @@ restart:
298 delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL); 303 delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
299 spin_unlock(&clp->cl_lock); 304 spin_unlock(&clp->cl_lock);
300 rcu_read_unlock(); 305 rcu_read_unlock();
301 if (delegation != NULL) 306 if (delegation != NULL) {
302 __nfs_inode_return_delegation(inode, delegation); 307 filemap_flush(inode->i_mapping);
308 err = __nfs_inode_return_delegation(inode, delegation, 0);
309 }
303 iput(inode); 310 iput(inode);
304 goto restart; 311 if (!err)
312 goto restart;
313 set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
314 return err;
305 } 315 }
306 rcu_read_unlock(); 316 rcu_read_unlock();
317 return 0;
307} 318}
308 319
309/* 320/*
@@ -338,8 +349,10 @@ int nfs_inode_return_delegation(struct inode *inode)
338 spin_lock(&clp->cl_lock); 349 spin_lock(&clp->cl_lock);
339 delegation = nfs_detach_delegation_locked(nfsi, NULL); 350 delegation = nfs_detach_delegation_locked(nfsi, NULL);
340 spin_unlock(&clp->cl_lock); 351 spin_unlock(&clp->cl_lock);
341 if (delegation != NULL) 352 if (delegation != NULL) {
342 err = __nfs_inode_return_delegation(inode, delegation); 353 nfs_msync_inode(inode);
354 err = __nfs_inode_return_delegation(inode, delegation, 1);
355 }
343 } 356 }
344 return err; 357 return err;
345} 358}
@@ -368,7 +381,8 @@ void nfs_super_return_all_delegations(struct super_block *sb)
368 spin_unlock(&delegation->lock); 381 spin_unlock(&delegation->lock);
369 } 382 }
370 rcu_read_unlock(); 383 rcu_read_unlock();
371 nfs_client_return_marked_delegations(clp); 384 if (nfs_client_return_marked_delegations(clp) != 0)
385 nfs4_schedule_state_manager(clp);
372} 386}
373 387
374static void nfs_client_mark_return_all_delegations(struct nfs_client *clp) 388static void nfs_client_mark_return_all_delegations(struct nfs_client *clp)
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 09f383795174..e225a1290127 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -42,7 +42,7 @@ void nfs_super_return_all_delegations(struct super_block *sb);
42void nfs_expire_all_delegations(struct nfs_client *clp); 42void nfs_expire_all_delegations(struct nfs_client *clp);
43void nfs_expire_unreferenced_delegations(struct nfs_client *clp); 43void nfs_expire_unreferenced_delegations(struct nfs_client *clp);
44void nfs_handle_cb_pathdown(struct nfs_client *clp); 44void nfs_handle_cb_pathdown(struct nfs_client *clp);
45void nfs_client_return_marked_delegations(struct nfs_client *clp); 45int nfs_client_return_marked_delegations(struct nfs_client *clp);
46 46
47void nfs_delegation_mark_reclaim(struct nfs_client *clp); 47void nfs_delegation_mark_reclaim(struct nfs_client *clp);
48void nfs_delegation_reap_unclaimed(struct nfs_client *clp); 48void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c
index f4d54ba97cc6..95e1ca765d47 100644
--- a/fs/nfs/dns_resolve.c
+++ b/fs/nfs/dns_resolve.c
@@ -146,7 +146,7 @@ static int nfs_dns_show(struct seq_file *m, struct cache_detail *cd,
146 return 0; 146 return 0;
147} 147}
148 148
149struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd, 149static struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd,
150 struct nfs_dns_ent *key) 150 struct nfs_dns_ent *key)
151{ 151{
152 struct cache_head *ch; 152 struct cache_head *ch;
@@ -159,7 +159,7 @@ struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd,
159 return container_of(ch, struct nfs_dns_ent, h); 159 return container_of(ch, struct nfs_dns_ent, h);
160} 160}
161 161
162struct nfs_dns_ent *nfs_dns_update(struct cache_detail *cd, 162static struct nfs_dns_ent *nfs_dns_update(struct cache_detail *cd,
163 struct nfs_dns_ent *new, 163 struct nfs_dns_ent *new,
164 struct nfs_dns_ent *key) 164 struct nfs_dns_ent *key)
165{ 165{
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 741a562177fc..df8a734f1c05 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1488,7 +1488,7 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s
1488 return ret; 1488 return ret;
1489} 1489}
1490 1490
1491static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state) 1491static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
1492{ 1492{
1493 struct nfs_server *server = NFS_SERVER(state->inode); 1493 struct nfs_server *server = NFS_SERVER(state->inode);
1494 struct nfs4_exception exception = { }; 1494 struct nfs4_exception exception = { };
@@ -1496,10 +1496,16 @@ static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4
1496 1496
1497 do { 1497 do {
1498 err = _nfs4_open_expired(ctx, state); 1498 err = _nfs4_open_expired(ctx, state);
1499 if (err != -NFS4ERR_DELAY) 1499 switch (err) {
1500 break; 1500 default:
1501 nfs4_handle_exception(server, err, &exception); 1501 goto out;
1502 case -NFS4ERR_GRACE:
1503 case -NFS4ERR_DELAY:
1504 nfs4_handle_exception(server, err, &exception);
1505 err = 0;
1506 }
1502 } while (exception.retry); 1507 } while (exception.retry);
1508out:
1503 return err; 1509 return err;
1504} 1510}
1505 1511
@@ -1981,7 +1987,7 @@ out_drop:
1981 return 0; 1987 return 0;
1982} 1988}
1983 1989
1984void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) 1990static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)
1985{ 1991{
1986 if (ctx->state == NULL) 1992 if (ctx->state == NULL)
1987 return; 1993 return;
@@ -4049,10 +4055,16 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
4049 if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) 4055 if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
4050 return 0; 4056 return 0;
4051 err = _nfs4_do_setlk(state, F_SETLK, request, 0); 4057 err = _nfs4_do_setlk(state, F_SETLK, request, 0);
4052 if (err != -NFS4ERR_DELAY) 4058 switch (err) {
4053 break; 4059 default:
4054 nfs4_handle_exception(server, err, &exception); 4060 goto out;
4061 case -NFS4ERR_GRACE:
4062 case -NFS4ERR_DELAY:
4063 nfs4_handle_exception(server, err, &exception);
4064 err = 0;
4065 }
4055 } while (exception.retry); 4066 } while (exception.retry);
4067out:
4056 return err; 4068 return err;
4057} 4069}
4058 4070
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 2ef4fecf3984..62927879572f 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1046,20 +1046,19 @@ static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp)
1046 nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce); 1046 nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce);
1047} 1047}
1048 1048
1049static void nfs4_state_end_reclaim_nograce(struct nfs_client *clp) 1049static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
1050{
1051 clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
1052}
1053
1054static void nfs4_recovery_handle_error(struct nfs_client *clp, int error)
1055{ 1050{
1056 switch (error) { 1051 switch (error) {
1057 case -NFS4ERR_CB_PATH_DOWN: 1052 case -NFS4ERR_CB_PATH_DOWN:
1058 nfs_handle_cb_pathdown(clp); 1053 nfs_handle_cb_pathdown(clp);
1059 break; 1054 return 0;
1055 case -NFS4ERR_NO_GRACE:
1056 nfs4_state_end_reclaim_reboot(clp);
1057 return 0;
1060 case -NFS4ERR_STALE_CLIENTID: 1058 case -NFS4ERR_STALE_CLIENTID:
1061 case -NFS4ERR_LEASE_MOVED: 1059 case -NFS4ERR_LEASE_MOVED:
1062 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); 1060 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
1061 nfs4_state_end_reclaim_reboot(clp);
1063 nfs4_state_start_reclaim_reboot(clp); 1062 nfs4_state_start_reclaim_reboot(clp);
1064 break; 1063 break;
1065 case -NFS4ERR_EXPIRED: 1064 case -NFS4ERR_EXPIRED:
@@ -1074,6 +1073,7 @@ static void nfs4_recovery_handle_error(struct nfs_client *clp, int error)
1074 case -NFS4ERR_SEQ_MISORDERED: 1073 case -NFS4ERR_SEQ_MISORDERED:
1075 set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state); 1074 set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
1076 } 1075 }
1076 return error;
1077} 1077}
1078 1078
1079static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops) 1079static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops)
@@ -1093,8 +1093,7 @@ restart:
1093 if (status < 0) { 1093 if (status < 0) {
1094 set_bit(ops->owner_flag_bit, &sp->so_flags); 1094 set_bit(ops->owner_flag_bit, &sp->so_flags);
1095 nfs4_put_state_owner(sp); 1095 nfs4_put_state_owner(sp);
1096 nfs4_recovery_handle_error(clp, status); 1096 return nfs4_recovery_handle_error(clp, status);
1097 return status;
1098 } 1097 }
1099 nfs4_put_state_owner(sp); 1098 nfs4_put_state_owner(sp);
1100 goto restart; 1099 goto restart;
@@ -1124,8 +1123,7 @@ static int nfs4_check_lease(struct nfs_client *clp)
1124 status = ops->renew_lease(clp, cred); 1123 status = ops->renew_lease(clp, cred);
1125 put_rpccred(cred); 1124 put_rpccred(cred);
1126out: 1125out:
1127 nfs4_recovery_handle_error(clp, status); 1126 return nfs4_recovery_handle_error(clp, status);
1128 return status;
1129} 1127}
1130 1128
1131static int nfs4_reclaim_lease(struct nfs_client *clp) 1129static int nfs4_reclaim_lease(struct nfs_client *clp)
@@ -1234,7 +1232,8 @@ static void nfs4_state_manager(struct nfs_client *clp)
1234 status = nfs4_reclaim_lease(clp); 1232 status = nfs4_reclaim_lease(clp);
1235 if (status) { 1233 if (status) {
1236 nfs4_set_lease_expired(clp, status); 1234 nfs4_set_lease_expired(clp, status);
1237 if (status == -EAGAIN) 1235 if (test_bit(NFS4CLNT_LEASE_EXPIRED,
1236 &clp->cl_state))
1238 continue; 1237 continue;
1239 if (clp->cl_cons_state == 1238 if (clp->cl_cons_state ==
1240 NFS_CS_SESSION_INITING) 1239 NFS_CS_SESSION_INITING)
@@ -1246,9 +1245,12 @@ static void nfs4_state_manager(struct nfs_client *clp)
1246 1245
1247 if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { 1246 if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) {
1248 status = nfs4_check_lease(clp); 1247 status = nfs4_check_lease(clp);
1249 if (status != 0) 1248 if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
1250 continue; 1249 continue;
1250 if (status < 0 && status != -NFS4ERR_CB_PATH_DOWN)
1251 goto out_error;
1251 } 1252 }
1253
1252 /* Initialize or reset the session */ 1254 /* Initialize or reset the session */
1253 if (test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state) 1255 if (test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)
1254 && nfs4_has_session(clp)) { 1256 && nfs4_has_session(clp)) {
@@ -1256,41 +1258,36 @@ static void nfs4_state_manager(struct nfs_client *clp)
1256 status = nfs4_initialize_session(clp); 1258 status = nfs4_initialize_session(clp);
1257 else 1259 else
1258 status = nfs4_reset_session(clp); 1260 status = nfs4_reset_session(clp);
1259 if (status) { 1261 if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
1260 if (status == -NFS4ERR_STALE_CLIENTID) 1262 continue;
1261 continue; 1263 if (status < 0)
1262 goto out_error; 1264 goto out_error;
1263 }
1264 } 1265 }
1266
1265 /* First recover reboot state... */ 1267 /* First recover reboot state... */
1266 if (test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { 1268 if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) {
1267 status = nfs4_do_reclaim(clp, 1269 status = nfs4_do_reclaim(clp,
1268 nfs4_reboot_recovery_ops[clp->cl_minorversion]); 1270 nfs4_reboot_recovery_ops[clp->cl_minorversion]);
1269 if (status == -NFS4ERR_STALE_CLIENTID) 1271 if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) ||
1270 continue; 1272 test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state))
1271 if (test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state))
1272 continue; 1273 continue;
1273 nfs4_state_end_reclaim_reboot(clp); 1274 nfs4_state_end_reclaim_reboot(clp);
1274 continue; 1275 if (test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state))
1276 continue;
1277 if (status < 0)
1278 goto out_error;
1275 } 1279 }
1276 1280
1277 /* Now recover expired state... */ 1281 /* Now recover expired state... */
1278 if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) { 1282 if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) {
1279 status = nfs4_do_reclaim(clp, 1283 status = nfs4_do_reclaim(clp,
1280 nfs4_nograce_recovery_ops[clp->cl_minorversion]); 1284 nfs4_nograce_recovery_ops[clp->cl_minorversion]);
1281 if (status < 0) { 1285 if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) ||
1282 set_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state); 1286 test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state) ||
1283 if (status == -NFS4ERR_STALE_CLIENTID) 1287 test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
1284 continue; 1288 continue;
1285 if (status == -NFS4ERR_EXPIRED) 1289 if (status < 0)
1286 continue;
1287 if (test_bit(NFS4CLNT_SESSION_SETUP,
1288 &clp->cl_state))
1289 continue;
1290 goto out_error; 1290 goto out_error;
1291 } else
1292 nfs4_state_end_reclaim_nograce(clp);
1293 continue;
1294 } 1291 }
1295 1292
1296 if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { 1293 if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) {
@@ -1309,8 +1306,6 @@ static void nfs4_state_manager(struct nfs_client *clp)
1309out_error: 1306out_error:
1310 printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s" 1307 printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s"
1311 " with error %d\n", clp->cl_hostname, -status); 1308 " with error %d\n", clp->cl_hostname, -status);
1312 if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
1313 nfs4_state_end_reclaim_reboot(clp);
1314 nfs4_clear_state_manager_bit(clp); 1309 nfs4_clear_state_manager_bit(clp);
1315} 1310}
1316 1311
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 20b4e30e6c82..3a71b40a990a 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -2096,7 +2096,7 @@ nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p,
2096 encode_compound_hdr(&xdr, req, &hdr); 2096 encode_compound_hdr(&xdr, req, &hdr);
2097 encode_sequence(&xdr, &args->seq_args, &hdr); 2097 encode_sequence(&xdr, &args->seq_args, &hdr);
2098 encode_putfh(&xdr, args->fh, &hdr); 2098 encode_putfh(&xdr, args->fh, &hdr);
2099 replen = hdr.replen + nfs4_fattr_bitmap_maxsz + 1; 2099 replen = hdr.replen + op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz + 1;
2100 encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0, &hdr); 2100 encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0, &hdr);
2101 2101
2102 xdr_inline_pages(&req->rq_rcv_buf, replen << 2, 2102 xdr_inline_pages(&req->rq_rcv_buf, replen << 2,