diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-04-07 13:20:54 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-04-19 16:53:15 -0400 |
commit | c1d519312dcdf11532fed9f99a8ecc3547ffd9d6 (patch) | |
tree | f91e0d8df3fc424aaa6eddbc54aaf55bdbfb245b /fs | |
parent | 35d05778e25ee16dbddb60331be0bc1309efba19 (diff) |
NFSv4: Only increment the sequence id if the server saw it
It is quite possible that the OPEN, CLOSE, LOCK, LOCKU,... compounds fail
before the actual stateful operation has been executed (for instance in the
PUTFH call). There is no way to tell from the overall status result which
operations were executed from the COMPOUND.
The fix is to move incrementing of the sequence id into the XDR layer,
so that we do it as we process the results from the stateful operation.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/nfs4proc.c | 12 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 18 |
2 files changed, 23 insertions, 7 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 424aa206470f..9f2759da74eb 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -240,6 +240,8 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p) | |||
240 | { | 240 | { |
241 | p->o_res.f_attr = &p->f_attr; | 241 | p->o_res.f_attr = &p->f_attr; |
242 | p->o_res.dir_attr = &p->dir_attr; | 242 | p->o_res.dir_attr = &p->dir_attr; |
243 | p->o_res.seqid = p->o_arg.seqid; | ||
244 | p->c_res.seqid = p->c_arg.seqid; | ||
243 | p->o_res.server = p->o_arg.server; | 245 | p->o_res.server = p->o_arg.server; |
244 | nfs_fattr_init(&p->f_attr); | 246 | nfs_fattr_init(&p->f_attr); |
245 | nfs_fattr_init(&p->dir_attr); | 247 | nfs_fattr_init(&p->dir_attr); |
@@ -730,7 +732,6 @@ static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) | |||
730 | renew_lease(data->o_res.server, data->timestamp); | 732 | renew_lease(data->o_res.server, data->timestamp); |
731 | data->rpc_done = 1; | 733 | data->rpc_done = 1; |
732 | } | 734 | } |
733 | nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid); | ||
734 | } | 735 | } |
735 | 736 | ||
736 | static void nfs4_open_confirm_release(void *calldata) | 737 | static void nfs4_open_confirm_release(void *calldata) |
@@ -860,7 +861,6 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata) | |||
860 | if (!(data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM)) | 861 | if (!(data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM)) |
861 | nfs_confirm_seqid(&data->owner->so_seqid, 0); | 862 | nfs_confirm_seqid(&data->owner->so_seqid, 0); |
862 | } | 863 | } |
863 | nfs_increment_open_seqid(data->rpc_status, data->o_arg.seqid); | ||
864 | data->rpc_done = 1; | 864 | data->rpc_done = 1; |
865 | } | 865 | } |
866 | 866 | ||
@@ -1226,7 +1226,6 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
1226 | /* hmm. we are done with the inode, and in the process of freeing | 1226 | /* hmm. we are done with the inode, and in the process of freeing |
1227 | * the state_owner. we keep this around to process errors | 1227 | * the state_owner. we keep this around to process errors |
1228 | */ | 1228 | */ |
1229 | nfs_increment_open_seqid(task->tk_status, calldata->arg.seqid); | ||
1230 | switch (task->tk_status) { | 1229 | switch (task->tk_status) { |
1231 | case 0: | 1230 | case 0: |
1232 | nfs_set_open_stateid(state, &calldata->res.stateid, 0); | 1231 | nfs_set_open_stateid(state, &calldata->res.stateid, 0); |
@@ -1333,6 +1332,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) | |||
1333 | goto out_free_calldata; | 1332 | goto out_free_calldata; |
1334 | calldata->arg.bitmask = server->attr_bitmask; | 1333 | calldata->arg.bitmask = server->attr_bitmask; |
1335 | calldata->res.fattr = &calldata->fattr; | 1334 | calldata->res.fattr = &calldata->fattr; |
1335 | calldata->res.seqid = calldata->arg.seqid; | ||
1336 | calldata->res.server = server; | 1336 | calldata->res.server = server; |
1337 | calldata->path.mnt = mntget(path->mnt); | 1337 | calldata->path.mnt = mntget(path->mnt); |
1338 | calldata->path.dentry = dget(path->dentry); | 1338 | calldata->path.dentry = dget(path->dentry); |
@@ -3159,6 +3159,7 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, | |||
3159 | p->arg.fh = NFS_FH(inode); | 3159 | p->arg.fh = NFS_FH(inode); |
3160 | p->arg.fl = &p->fl; | 3160 | p->arg.fl = &p->fl; |
3161 | p->arg.seqid = seqid; | 3161 | p->arg.seqid = seqid; |
3162 | p->res.seqid = seqid; | ||
3162 | p->arg.stateid = &lsp->ls_stateid; | 3163 | p->arg.stateid = &lsp->ls_stateid; |
3163 | p->lsp = lsp; | 3164 | p->lsp = lsp; |
3164 | atomic_inc(&lsp->ls_count); | 3165 | atomic_inc(&lsp->ls_count); |
@@ -3184,7 +3185,6 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) | |||
3184 | 3185 | ||
3185 | if (RPC_ASSASSINATED(task)) | 3186 | if (RPC_ASSASSINATED(task)) |
3186 | return; | 3187 | return; |
3187 | nfs_increment_lock_seqid(task->tk_status, calldata->arg.seqid); | ||
3188 | switch (task->tk_status) { | 3188 | switch (task->tk_status) { |
3189 | case 0: | 3189 | case 0: |
3190 | memcpy(calldata->lsp->ls_stateid.data, | 3190 | memcpy(calldata->lsp->ls_stateid.data, |
@@ -3322,6 +3322,7 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, | |||
3322 | p->arg.lock_stateid = &lsp->ls_stateid; | 3322 | p->arg.lock_stateid = &lsp->ls_stateid; |
3323 | p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; | 3323 | p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; |
3324 | p->arg.lock_owner.id = lsp->ls_id.id; | 3324 | p->arg.lock_owner.id = lsp->ls_id.id; |
3325 | p->res.lock_seqid = p->arg.lock_seqid; | ||
3325 | p->lsp = lsp; | 3326 | p->lsp = lsp; |
3326 | atomic_inc(&lsp->ls_count); | 3327 | atomic_inc(&lsp->ls_count); |
3327 | p->ctx = get_nfs_open_context(ctx); | 3328 | p->ctx = get_nfs_open_context(ctx); |
@@ -3348,6 +3349,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) | |||
3348 | return; | 3349 | return; |
3349 | data->arg.open_stateid = &state->stateid; | 3350 | data->arg.open_stateid = &state->stateid; |
3350 | data->arg.new_lock_owner = 1; | 3351 | data->arg.new_lock_owner = 1; |
3352 | data->res.open_seqid = data->arg.open_seqid; | ||
3351 | } else | 3353 | } else |
3352 | data->arg.new_lock_owner = 0; | 3354 | data->arg.new_lock_owner = 0; |
3353 | data->timestamp = jiffies; | 3355 | data->timestamp = jiffies; |
@@ -3365,7 +3367,6 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata) | |||
3365 | if (RPC_ASSASSINATED(task)) | 3367 | if (RPC_ASSASSINATED(task)) |
3366 | goto out; | 3368 | goto out; |
3367 | if (data->arg.new_lock_owner != 0) { | 3369 | if (data->arg.new_lock_owner != 0) { |
3368 | nfs_increment_open_seqid(data->rpc_status, data->arg.open_seqid); | ||
3369 | if (data->rpc_status == 0) | 3370 | if (data->rpc_status == 0) |
3370 | nfs_confirm_seqid(&data->lsp->ls_seqid, 0); | 3371 | nfs_confirm_seqid(&data->lsp->ls_seqid, 0); |
3371 | else | 3372 | else |
@@ -3377,7 +3378,6 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata) | |||
3377 | data->lsp->ls_flags |= NFS_LOCK_INITIALIZED; | 3378 | data->lsp->ls_flags |= NFS_LOCK_INITIALIZED; |
3378 | renew_lease(NFS_SERVER(data->ctx->path.dentry->d_inode), data->timestamp); | 3379 | renew_lease(NFS_SERVER(data->ctx->path.dentry->d_inode), data->timestamp); |
3379 | } | 3380 | } |
3380 | nfs_increment_lock_seqid(data->rpc_status, data->arg.lock_seqid); | ||
3381 | out: | 3381 | out: |
3382 | dprintk("%s: done, ret = %d!\n", __FUNCTION__, data->rpc_status); | 3382 | dprintk("%s: done, ret = %d!\n", __FUNCTION__, data->rpc_status); |
3383 | } | 3383 | } |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 2b519f6325f9..b8b2e391d183 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -3005,6 +3005,8 @@ static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res) | |||
3005 | int status; | 3005 | int status; |
3006 | 3006 | ||
3007 | status = decode_op_hdr(xdr, OP_CLOSE); | 3007 | status = decode_op_hdr(xdr, OP_CLOSE); |
3008 | if (status != -EIO) | ||
3009 | nfs_increment_open_seqid(status, res->seqid); | ||
3008 | if (status) | 3010 | if (status) |
3009 | return status; | 3011 | return status; |
3010 | READ_BUF(NFS4_STATEID_SIZE); | 3012 | READ_BUF(NFS4_STATEID_SIZE); |
@@ -3296,11 +3298,17 @@ static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res) | |||
3296 | int status; | 3298 | int status; |
3297 | 3299 | ||
3298 | status = decode_op_hdr(xdr, OP_LOCK); | 3300 | status = decode_op_hdr(xdr, OP_LOCK); |
3301 | if (status == -EIO) | ||
3302 | goto out; | ||
3299 | if (status == 0) { | 3303 | if (status == 0) { |
3300 | READ_BUF(NFS4_STATEID_SIZE); | 3304 | READ_BUF(NFS4_STATEID_SIZE); |
3301 | COPYMEM(res->stateid.data, NFS4_STATEID_SIZE); | 3305 | COPYMEM(res->stateid.data, NFS4_STATEID_SIZE); |
3302 | } else if (status == -NFS4ERR_DENIED) | 3306 | } else if (status == -NFS4ERR_DENIED) |
3303 | return decode_lock_denied(xdr, NULL); | 3307 | status = decode_lock_denied(xdr, NULL); |
3308 | if (res->open_seqid != NULL) | ||
3309 | nfs_increment_open_seqid(status, res->open_seqid); | ||
3310 | nfs_increment_lock_seqid(status, res->lock_seqid); | ||
3311 | out: | ||
3304 | return status; | 3312 | return status; |
3305 | } | 3313 | } |
3306 | 3314 | ||
@@ -3319,6 +3327,8 @@ static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res) | |||
3319 | int status; | 3327 | int status; |
3320 | 3328 | ||
3321 | status = decode_op_hdr(xdr, OP_LOCKU); | 3329 | status = decode_op_hdr(xdr, OP_LOCKU); |
3330 | if (status != -EIO) | ||
3331 | nfs_increment_lock_seqid(status, res->seqid); | ||
3322 | if (status == 0) { | 3332 | if (status == 0) { |
3323 | READ_BUF(NFS4_STATEID_SIZE); | 3333 | READ_BUF(NFS4_STATEID_SIZE); |
3324 | COPYMEM(res->stateid.data, NFS4_STATEID_SIZE); | 3334 | COPYMEM(res->stateid.data, NFS4_STATEID_SIZE); |
@@ -3384,6 +3394,8 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) | |||
3384 | int status; | 3394 | int status; |
3385 | 3395 | ||
3386 | status = decode_op_hdr(xdr, OP_OPEN); | 3396 | status = decode_op_hdr(xdr, OP_OPEN); |
3397 | if (status != -EIO) | ||
3398 | nfs_increment_open_seqid(status, res->seqid); | ||
3387 | if (status) | 3399 | if (status) |
3388 | return status; | 3400 | return status; |
3389 | READ_BUF(NFS4_STATEID_SIZE); | 3401 | READ_BUF(NFS4_STATEID_SIZE); |
@@ -3416,6 +3428,8 @@ static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmre | |||
3416 | int status; | 3428 | int status; |
3417 | 3429 | ||
3418 | status = decode_op_hdr(xdr, OP_OPEN_CONFIRM); | 3430 | status = decode_op_hdr(xdr, OP_OPEN_CONFIRM); |
3431 | if (status != -EIO) | ||
3432 | nfs_increment_open_seqid(status, res->seqid); | ||
3419 | if (status) | 3433 | if (status) |
3420 | return status; | 3434 | return status; |
3421 | READ_BUF(NFS4_STATEID_SIZE); | 3435 | READ_BUF(NFS4_STATEID_SIZE); |
@@ -3429,6 +3443,8 @@ static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *re | |||
3429 | int status; | 3443 | int status; |
3430 | 3444 | ||
3431 | status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE); | 3445 | status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE); |
3446 | if (status != -EIO) | ||
3447 | nfs_increment_open_seqid(status, res->seqid); | ||
3432 | if (status) | 3448 | if (status) |
3433 | return status; | 3449 | return status; |
3434 | READ_BUF(NFS4_STATEID_SIZE); | 3450 | READ_BUF(NFS4_STATEID_SIZE); |