aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-08-09 11:38:14 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-08-09 11:38:14 -0400
commit8b80fc02b829a59602b0f53eb9393ffb2db2659d (patch)
tree9cce02e07ed1b30d6f6bd236a2d6015e5681eeb9 /fs
parent6a0ed91e361a93ee1efb4c20c4967024ed2a8dd7 (diff)
parent4011cd97886dd04b90fef8b671b9936cd39ab983 (diff)
Merge git://git.linux-nfs.org/pub/linux/nfs-2.6
* git://git.linux-nfs.org/pub/linux/nfs-2.6: SUNRPC: Replace flush_workqueue() with cancel_work_sync() and friends NFS: Replace flush_scheduled_work with cancel_work_sync() and friends SUNRPC: Don't call gss_delete_sec_context() from an rcu context NFSv4: Don't call put_rpccred() from an rcu callback NFS: Fix NFSv4 open stateid regressions NFSv4: Fix a locking regression in nfs4_set_mode_locked() NFS: Fix put_nfs_open_context SUNRPC: Fix a race in rpciod_down()
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/delegation.c21
-rw-r--r--fs/nfs/inode.c24
-rw-r--r--fs/nfs/namespace.c6
-rw-r--r--fs/nfs/nfs4proc.c16
-rw-r--r--fs/nfs/nfs4renewd.c5
-rw-r--r--fs/nfs/nfs4state.c5
6 files changed, 35 insertions, 42 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 20ac403469a0..c55a761c22bb 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -20,10 +20,8 @@
20#include "delegation.h" 20#include "delegation.h"
21#include "internal.h" 21#include "internal.h"
22 22
23static void nfs_free_delegation(struct nfs_delegation *delegation) 23static void nfs_do_free_delegation(struct nfs_delegation *delegation)
24{ 24{
25 if (delegation->cred)
26 put_rpccred(delegation->cred);
27 kfree(delegation); 25 kfree(delegation);
28} 26}
29 27
@@ -31,7 +29,18 @@ static void nfs_free_delegation_callback(struct rcu_head *head)
31{ 29{
32 struct nfs_delegation *delegation = container_of(head, struct nfs_delegation, rcu); 30 struct nfs_delegation *delegation = container_of(head, struct nfs_delegation, rcu);
33 31
34 nfs_free_delegation(delegation); 32 nfs_do_free_delegation(delegation);
33}
34
35static void nfs_free_delegation(struct nfs_delegation *delegation)
36{
37 struct rpc_cred *cred;
38
39 cred = rcu_dereference(delegation->cred);
40 rcu_assign_pointer(delegation->cred, NULL);
41 call_rcu(&delegation->rcu, nfs_free_delegation_callback);
42 if (cred)
43 put_rpccred(cred);
35} 44}
36 45
37static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state) 46static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state)
@@ -166,7 +175,7 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *
166 int res = 0; 175 int res = 0;
167 176
168 res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid); 177 res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid);
169 call_rcu(&delegation->rcu, nfs_free_delegation_callback); 178 nfs_free_delegation(delegation);
170 return res; 179 return res;
171} 180}
172 181
@@ -448,7 +457,7 @@ restart:
448 spin_unlock(&clp->cl_lock); 457 spin_unlock(&clp->cl_lock);
449 rcu_read_unlock(); 458 rcu_read_unlock();
450 if (delegation != NULL) 459 if (delegation != NULL)
451 call_rcu(&delegation->rcu, nfs_free_delegation_callback); 460 nfs_free_delegation(delegation);
452 goto restart; 461 goto restart;
453 } 462 }
454 rcu_read_unlock(); 463 rcu_read_unlock();
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index bca6cdcb9f0d..71a49c3acabd 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -468,7 +468,7 @@ static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, str
468 ctx->lockowner = current->files; 468 ctx->lockowner = current->files;
469 ctx->error = 0; 469 ctx->error = 0;
470 ctx->dir_cookie = 0; 470 ctx->dir_cookie = 0;
471 kref_init(&ctx->kref); 471 atomic_set(&ctx->count, 1);
472 } 472 }
473 return ctx; 473 return ctx;
474} 474}
@@ -476,21 +476,18 @@ static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, str
476struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx) 476struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
477{ 477{
478 if (ctx != NULL) 478 if (ctx != NULL)
479 kref_get(&ctx->kref); 479 atomic_inc(&ctx->count);
480 return ctx; 480 return ctx;
481} 481}
482 482
483static void nfs_free_open_context(struct kref *kref) 483void put_nfs_open_context(struct nfs_open_context *ctx)
484{ 484{
485 struct nfs_open_context *ctx = container_of(kref, 485 struct inode *inode = ctx->path.dentry->d_inode;
486 struct nfs_open_context, kref);
487 486
488 if (!list_empty(&ctx->list)) { 487 if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock))
489 struct inode *inode = ctx->path.dentry->d_inode; 488 return;
490 spin_lock(&inode->i_lock); 489 list_del(&ctx->list);
491 list_del(&ctx->list); 490 spin_unlock(&inode->i_lock);
492 spin_unlock(&inode->i_lock);
493 }
494 if (ctx->state != NULL) 491 if (ctx->state != NULL)
495 nfs4_close_state(&ctx->path, ctx->state, ctx->mode); 492 nfs4_close_state(&ctx->path, ctx->state, ctx->mode);
496 if (ctx->cred != NULL) 493 if (ctx->cred != NULL)
@@ -500,11 +497,6 @@ static void nfs_free_open_context(struct kref *kref)
500 kfree(ctx); 497 kfree(ctx);
501} 498}
502 499
503void put_nfs_open_context(struct nfs_open_context *ctx)
504{
505 kref_put(&ctx->kref, nfs_free_open_context);
506}
507
508/* 500/*
509 * Ensure that mmap has a recent RPC credential for use when writing out 501 * Ensure that mmap has a recent RPC credential for use when writing out
510 * shared pages 502 * shared pages
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 7f86e65182e4..aea76d0e5fbd 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -175,10 +175,8 @@ static void nfs_expire_automounts(struct work_struct *work)
175 175
176void nfs_release_automount_timer(void) 176void nfs_release_automount_timer(void)
177{ 177{
178 if (list_empty(&nfs_automount_list)) { 178 if (list_empty(&nfs_automount_list))
179 cancel_delayed_work(&nfs_automount_task); 179 cancel_delayed_work_sync(&nfs_automount_task);
180 flush_scheduled_work();
181 }
182} 180}
183 181
184/* 182/*
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 6ca2795ccd9c..62b3ae280310 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -332,11 +332,9 @@ static int can_open_cached(struct nfs4_state *state, int mode)
332 switch (mode & (FMODE_READ|FMODE_WRITE|O_EXCL)) { 332 switch (mode & (FMODE_READ|FMODE_WRITE|O_EXCL)) {
333 case FMODE_READ: 333 case FMODE_READ:
334 ret |= test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0; 334 ret |= test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0;
335 ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0;
336 break; 335 break;
337 case FMODE_WRITE: 336 case FMODE_WRITE:
338 ret |= test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0; 337 ret |= test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0;
339 ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0;
340 break; 338 break;
341 case FMODE_READ|FMODE_WRITE: 339 case FMODE_READ|FMODE_WRITE:
342 ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0; 340 ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0;
@@ -1260,7 +1258,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
1260 nfs_increment_open_seqid(task->tk_status, calldata->arg.seqid); 1258 nfs_increment_open_seqid(task->tk_status, calldata->arg.seqid);
1261 switch (task->tk_status) { 1259 switch (task->tk_status) {
1262 case 0: 1260 case 0:
1263 nfs_set_open_stateid(state, &calldata->res.stateid, calldata->arg.open_flags); 1261 nfs_set_open_stateid(state, &calldata->res.stateid, 0);
1264 renew_lease(server, calldata->timestamp); 1262 renew_lease(server, calldata->timestamp);
1265 break; 1263 break;
1266 case -NFS4ERR_STALE_STATEID: 1264 case -NFS4ERR_STALE_STATEID:
@@ -1286,23 +1284,19 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
1286 .rpc_cred = state->owner->so_cred, 1284 .rpc_cred = state->owner->so_cred,
1287 }; 1285 };
1288 int clear_rd, clear_wr, clear_rdwr; 1286 int clear_rd, clear_wr, clear_rdwr;
1289 int mode;
1290 1287
1291 if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) 1288 if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
1292 return; 1289 return;
1293 1290
1294 mode = FMODE_READ|FMODE_WRITE;
1295 clear_rd = clear_wr = clear_rdwr = 0; 1291 clear_rd = clear_wr = clear_rdwr = 0;
1296 spin_lock(&state->owner->so_lock); 1292 spin_lock(&state->owner->so_lock);
1297 /* Calculate the change in open mode */ 1293 /* Calculate the change in open mode */
1298 if (state->n_rdwr == 0) { 1294 if (state->n_rdwr == 0) {
1299 if (state->n_rdonly == 0) { 1295 if (state->n_rdonly == 0) {
1300 mode &= ~FMODE_READ;
1301 clear_rd |= test_and_clear_bit(NFS_O_RDONLY_STATE, &state->flags); 1296 clear_rd |= test_and_clear_bit(NFS_O_RDONLY_STATE, &state->flags);
1302 clear_rdwr |= test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags); 1297 clear_rdwr |= test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags);
1303 } 1298 }
1304 if (state->n_wronly == 0) { 1299 if (state->n_wronly == 0) {
1305 mode &= ~FMODE_WRITE;
1306 clear_wr |= test_and_clear_bit(NFS_O_WRONLY_STATE, &state->flags); 1300 clear_wr |= test_and_clear_bit(NFS_O_WRONLY_STATE, &state->flags);
1307 clear_rdwr |= test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags); 1301 clear_rdwr |= test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags);
1308 } 1302 }
@@ -1314,9 +1308,13 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
1314 return; 1308 return;
1315 } 1309 }
1316 nfs_fattr_init(calldata->res.fattr); 1310 nfs_fattr_init(calldata->res.fattr);
1317 if (mode != 0) 1311 if (test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0) {
1318 msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; 1312 msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
1319 calldata->arg.open_flags = mode; 1313 calldata->arg.open_flags = FMODE_READ;
1314 } else if (test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0) {
1315 msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
1316 calldata->arg.open_flags = FMODE_WRITE;
1317 }
1320 calldata->timestamp = jiffies; 1318 calldata->timestamp = jiffies;
1321 rpc_call_setup(task, &msg, 0); 1319 rpc_call_setup(task, &msg, 0);
1322} 1320}
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index 0505ca124034..3ea352d82eba 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -127,16 +127,15 @@ nfs4_schedule_state_renewal(struct nfs_client *clp)
127void 127void
128nfs4_renewd_prepare_shutdown(struct nfs_server *server) 128nfs4_renewd_prepare_shutdown(struct nfs_server *server)
129{ 129{
130 flush_scheduled_work(); 130 cancel_delayed_work(&server->nfs_client->cl_renewd);
131} 131}
132 132
133void 133void
134nfs4_kill_renewd(struct nfs_client *clp) 134nfs4_kill_renewd(struct nfs_client *clp)
135{ 135{
136 down_read(&clp->cl_sem); 136 down_read(&clp->cl_sem);
137 cancel_delayed_work(&clp->cl_renewd); 137 cancel_delayed_work_sync(&clp->cl_renewd);
138 up_read(&clp->cl_sem); 138 up_read(&clp->cl_sem);
139 flush_scheduled_work();
140} 139}
141 140
142/* 141/*
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index e9662ba81d86..3e4adf8c8312 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -341,8 +341,6 @@ nfs4_state_set_mode_locked(struct nfs4_state *state, mode_t mode)
341 else 341 else
342 list_move_tail(&state->open_states, &state->owner->so_states); 342 list_move_tail(&state->open_states, &state->owner->so_states);
343 } 343 }
344 if (mode == 0)
345 list_del_init(&state->inode_states);
346 state->state = mode; 344 state->state = mode;
347} 345}
348 346
@@ -415,8 +413,7 @@ void nfs4_put_open_state(struct nfs4_state *state)
415 if (!atomic_dec_and_lock(&state->count, &owner->so_lock)) 413 if (!atomic_dec_and_lock(&state->count, &owner->so_lock))
416 return; 414 return;
417 spin_lock(&inode->i_lock); 415 spin_lock(&inode->i_lock);
418 if (!list_empty(&state->inode_states)) 416 list_del(&state->inode_states);
419 list_del(&state->inode_states);
420 list_del(&state->open_states); 417 list_del(&state->open_states);
421 spin_unlock(&inode->i_lock); 418 spin_unlock(&inode->i_lock);
422 spin_unlock(&owner->so_lock); 419 spin_unlock(&owner->so_lock);