diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-11-04 15:33:38 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-11-04 15:33:38 -0500 |
commit | d530838bfa507d67b40d13b00d9cbd7a46a47e78 (patch) | |
tree | f4b2be26c0a7b9ed3233a2be016b7e97427f8705 /fs/nfs/nfs4proc.c | |
parent | 4cecb76ff86db46d2823550256c828b6597f418e (diff) |
NFSv4: Fix problem with OPEN_DOWNGRADE
RFC 3530 states that for OPEN_DOWNGRADE "The share_access and share_deny
bits specified must be exactly equal to the union of the share_access and
share_deny bits specified for some subset of the OPENs in effect for
current openowner on the current file.
Setattr is currently violating the NFSv4 rules for OPEN_DOWNGRADE in that
it may cause a downgrade from OPEN4_SHARE_ACCESS_BOTH to
OPEN4_SHARE_ACCESS_WRITE despite the fact that there exists no open file
with O_WRONLY access mode.
Fix the problem by replacing nfs4_find_state() with a modified version of
nfs_find_open_context().
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 23 |
1 files changed, 10 insertions, 13 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 02fddd0e27e8..9e492c2261c0 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -214,7 +214,7 @@ static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, | |||
214 | struct inode *inode = state->inode; | 214 | struct inode *inode = state->inode; |
215 | 215 | ||
216 | open_flags &= (FMODE_READ|FMODE_WRITE); | 216 | open_flags &= (FMODE_READ|FMODE_WRITE); |
217 | /* Protect against nfs4_find_state() */ | 217 | /* Protect against nfs4_find_state_byowner() */ |
218 | spin_lock(&state->owner->so_lock); | 218 | spin_lock(&state->owner->so_lock); |
219 | spin_lock(&inode->i_lock); | 219 | spin_lock(&inode->i_lock); |
220 | memcpy(&state->stateid, stateid, sizeof(state->stateid)); | 220 | memcpy(&state->stateid, stateid, sizeof(state->stateid)); |
@@ -1274,7 +1274,8 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
1274 | { | 1274 | { |
1275 | struct rpc_cred *cred; | 1275 | struct rpc_cred *cred; |
1276 | struct inode *inode = dentry->d_inode; | 1276 | struct inode *inode = dentry->d_inode; |
1277 | struct nfs4_state *state; | 1277 | struct nfs_open_context *ctx; |
1278 | struct nfs4_state *state = NULL; | ||
1278 | int status; | 1279 | int status; |
1279 | 1280 | ||
1280 | nfs_fattr_init(fattr); | 1281 | nfs_fattr_init(fattr); |
@@ -1282,22 +1283,18 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
1282 | cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); | 1283 | cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); |
1283 | if (IS_ERR(cred)) | 1284 | if (IS_ERR(cred)) |
1284 | return PTR_ERR(cred); | 1285 | return PTR_ERR(cred); |
1285 | /* Search for an existing WRITE delegation first */ | 1286 | |
1286 | state = nfs4_open_delegated(inode, FMODE_WRITE, cred); | 1287 | /* Search for an existing open(O_WRITE) file */ |
1287 | if (!IS_ERR(state)) { | 1288 | ctx = nfs_find_open_context(inode, cred, FMODE_WRITE); |
1288 | /* NB: nfs4_open_delegated() bumps the inode->i_count */ | 1289 | if (ctx != NULL) |
1289 | iput(inode); | 1290 | state = ctx->state; |
1290 | } else { | ||
1291 | /* Search for an existing open(O_WRITE) stateid */ | ||
1292 | state = nfs4_find_state(inode, cred, FMODE_WRITE); | ||
1293 | } | ||
1294 | 1291 | ||
1295 | status = nfs4_do_setattr(NFS_SERVER(inode), fattr, | 1292 | status = nfs4_do_setattr(NFS_SERVER(inode), fattr, |
1296 | NFS_FH(inode), sattr, state); | 1293 | NFS_FH(inode), sattr, state); |
1297 | if (status == 0) | 1294 | if (status == 0) |
1298 | nfs_setattr_update_inode(inode, sattr); | 1295 | nfs_setattr_update_inode(inode, sattr); |
1299 | if (state != NULL) | 1296 | if (ctx != NULL) |
1300 | nfs4_close_state(state, FMODE_WRITE); | 1297 | put_nfs_open_context(ctx); |
1301 | put_rpccred(cred); | 1298 | put_rpccred(cred); |
1302 | return status; | 1299 | return status; |
1303 | } | 1300 | } |