aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4state.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-01-03 03:55:13 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-01-06 14:58:43 -0500
commite761692381f294ea079d2e869fcd7c0afc79e394 (patch)
tree34ebc00c001cddc94866936c460547d311e5dabb /fs/nfs/nfs4state.c
parentcdd4e68b5f0ed12c64b3e2be83655d2a47588a74 (diff)
NFSv4: Make nfs4_state track O_RDWR, O_RDONLY and O_WRONLY separately
A closer reading of RFC3530 reveals that OPEN_DOWNGRADE must always specify a access modes that have been the argument of a previous OPEN operation. IOW: doing OPEN(O_RDWR) and then OPEN_DOWNGRADE(O_WRONLY) is forbidden unless the user called OPEN(O_WRONLY) In order to fix that, we really need to track the three possible open states separately. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r--fs/nfs/nfs4state.c31
1 files changed, 17 insertions, 14 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 5ef4c57618fe..41a5f1a8a984 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -349,14 +349,9 @@ nfs4_alloc_open_state(void)
349{ 349{
350 struct nfs4_state *state; 350 struct nfs4_state *state;
351 351
352 state = kmalloc(sizeof(*state), GFP_KERNEL); 352 state = kzalloc(sizeof(*state), GFP_KERNEL);
353 if (!state) 353 if (!state)
354 return NULL; 354 return NULL;
355 state->state = 0;
356 state->nreaders = 0;
357 state->nwriters = 0;
358 state->flags = 0;
359 memset(state->stateid.data, 0, sizeof(state->stateid.data));
360 atomic_set(&state->count, 1); 355 atomic_set(&state->count, 1);
361 INIT_LIST_HEAD(&state->lock_states); 356 INIT_LIST_HEAD(&state->lock_states);
362 spin_lock_init(&state->state_lock); 357 spin_lock_init(&state->state_lock);
@@ -475,15 +470,23 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
475 /* Protect against nfs4_find_state() */ 470 /* Protect against nfs4_find_state() */
476 spin_lock(&owner->so_lock); 471 spin_lock(&owner->so_lock);
477 spin_lock(&inode->i_lock); 472 spin_lock(&inode->i_lock);
478 if (mode & FMODE_READ) 473 switch (mode & (FMODE_READ | FMODE_WRITE)) {
479 state->nreaders--; 474 case FMODE_READ:
480 if (mode & FMODE_WRITE) 475 state->n_rdonly--;
481 state->nwriters--; 476 break;
477 case FMODE_WRITE:
478 state->n_wronly--;
479 break;
480 case FMODE_READ|FMODE_WRITE:
481 state->n_rdwr--;
482 }
482 oldstate = newstate = state->state; 483 oldstate = newstate = state->state;
483 if (state->nreaders == 0) 484 if (state->n_rdwr == 0) {
484 newstate &= ~FMODE_READ; 485 if (state->n_rdonly == 0)
485 if (state->nwriters == 0) 486 newstate &= ~FMODE_READ;
486 newstate &= ~FMODE_WRITE; 487 if (state->n_wronly == 0)
488 newstate &= ~FMODE_WRITE;
489 }
487 if (test_bit(NFS_DELEGATED_STATE, &state->flags)) { 490 if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
488 nfs4_state_set_mode_locked(state, newstate); 491 nfs4_state_set_mode_locked(state, newstate);
489 oldstate = newstate; 492 oldstate = newstate;