diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 279 |
1 files changed, 102 insertions, 177 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 089da5b5d20a..e87fe612ca18 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -129,7 +129,7 @@ const u32 nfs4_fsinfo_bitmap[2] = { FATTR4_WORD0_MAXFILESIZE | |||
129 | | FATTR4_WORD0_MAXREAD | 129 | | FATTR4_WORD0_MAXREAD |
130 | | FATTR4_WORD0_MAXWRITE | 130 | | FATTR4_WORD0_MAXWRITE |
131 | | FATTR4_WORD0_LEASE_TIME, | 131 | | FATTR4_WORD0_LEASE_TIME, |
132 | 0 | 132 | FATTR4_WORD1_TIME_DELTA |
133 | }; | 133 | }; |
134 | 134 | ||
135 | const u32 nfs4_fs_locations_bitmap[2] = { | 135 | const u32 nfs4_fs_locations_bitmap[2] = { |
@@ -255,9 +255,6 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, | |||
255 | nfs4_state_mark_reclaim_nograce(clp, state); | 255 | nfs4_state_mark_reclaim_nograce(clp, state); |
256 | goto do_state_recovery; | 256 | goto do_state_recovery; |
257 | case -NFS4ERR_STALE_STATEID: | 257 | case -NFS4ERR_STALE_STATEID: |
258 | if (state == NULL) | ||
259 | break; | ||
260 | nfs4_state_mark_reclaim_reboot(clp, state); | ||
261 | case -NFS4ERR_STALE_CLIENTID: | 258 | case -NFS4ERR_STALE_CLIENTID: |
262 | case -NFS4ERR_EXPIRED: | 259 | case -NFS4ERR_EXPIRED: |
263 | goto do_state_recovery; | 260 | goto do_state_recovery; |
@@ -334,10 +331,12 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp | |||
334 | * Must be called while holding tbl->slot_tbl_lock | 331 | * Must be called while holding tbl->slot_tbl_lock |
335 | */ | 332 | */ |
336 | static void | 333 | static void |
337 | nfs4_free_slot(struct nfs4_slot_table *tbl, u8 free_slotid) | 334 | nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *free_slot) |
338 | { | 335 | { |
336 | int free_slotid = free_slot - tbl->slots; | ||
339 | int slotid = free_slotid; | 337 | int slotid = free_slotid; |
340 | 338 | ||
339 | BUG_ON(slotid < 0 || slotid >= NFS4_MAX_SLOT_TABLE); | ||
341 | /* clear used bit in bitmap */ | 340 | /* clear used bit in bitmap */ |
342 | __clear_bit(slotid, tbl->used_slots); | 341 | __clear_bit(slotid, tbl->used_slots); |
343 | 342 | ||
@@ -379,7 +378,7 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) | |||
379 | struct nfs4_slot_table *tbl; | 378 | struct nfs4_slot_table *tbl; |
380 | 379 | ||
381 | tbl = &res->sr_session->fc_slot_table; | 380 | tbl = &res->sr_session->fc_slot_table; |
382 | if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) { | 381 | if (!res->sr_slot) { |
383 | /* just wake up the next guy waiting since | 382 | /* just wake up the next guy waiting since |
384 | * we may have not consumed a slot after all */ | 383 | * we may have not consumed a slot after all */ |
385 | dprintk("%s: No slot\n", __func__); | 384 | dprintk("%s: No slot\n", __func__); |
@@ -387,17 +386,15 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) | |||
387 | } | 386 | } |
388 | 387 | ||
389 | spin_lock(&tbl->slot_tbl_lock); | 388 | spin_lock(&tbl->slot_tbl_lock); |
390 | nfs4_free_slot(tbl, res->sr_slotid); | 389 | nfs4_free_slot(tbl, res->sr_slot); |
391 | nfs41_check_drain_session_complete(res->sr_session); | 390 | nfs41_check_drain_session_complete(res->sr_session); |
392 | spin_unlock(&tbl->slot_tbl_lock); | 391 | spin_unlock(&tbl->slot_tbl_lock); |
393 | res->sr_slotid = NFS4_MAX_SLOT_TABLE; | 392 | res->sr_slot = NULL; |
394 | } | 393 | } |
395 | 394 | ||
396 | static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) | 395 | static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) |
397 | { | 396 | { |
398 | unsigned long timestamp; | 397 | unsigned long timestamp; |
399 | struct nfs4_slot_table *tbl; | ||
400 | struct nfs4_slot *slot; | ||
401 | struct nfs_client *clp; | 398 | struct nfs_client *clp; |
402 | 399 | ||
403 | /* | 400 | /* |
@@ -410,17 +407,14 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res * | |||
410 | res->sr_status = NFS_OK; | 407 | res->sr_status = NFS_OK; |
411 | 408 | ||
412 | /* -ERESTARTSYS can result in skipping nfs41_sequence_setup */ | 409 | /* -ERESTARTSYS can result in skipping nfs41_sequence_setup */ |
413 | if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) | 410 | if (!res->sr_slot) |
414 | goto out; | 411 | goto out; |
415 | 412 | ||
416 | tbl = &res->sr_session->fc_slot_table; | ||
417 | slot = tbl->slots + res->sr_slotid; | ||
418 | |||
419 | /* Check the SEQUENCE operation status */ | 413 | /* Check the SEQUENCE operation status */ |
420 | switch (res->sr_status) { | 414 | switch (res->sr_status) { |
421 | case 0: | 415 | case 0: |
422 | /* Update the slot's sequence and clientid lease timer */ | 416 | /* Update the slot's sequence and clientid lease timer */ |
423 | ++slot->seq_nr; | 417 | ++res->sr_slot->seq_nr; |
424 | timestamp = res->sr_renewal_time; | 418 | timestamp = res->sr_renewal_time; |
425 | clp = res->sr_session->clp; | 419 | clp = res->sr_session->clp; |
426 | do_renew_lease(clp, timestamp); | 420 | do_renew_lease(clp, timestamp); |
@@ -433,12 +427,14 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res * | |||
433 | * returned NFS4ERR_DELAY as per Section 2.10.6.2 | 427 | * returned NFS4ERR_DELAY as per Section 2.10.6.2 |
434 | * of RFC5661. | 428 | * of RFC5661. |
435 | */ | 429 | */ |
436 | dprintk("%s: slot=%d seq=%d: Operation in progress\n", | 430 | dprintk("%s: slot=%ld seq=%d: Operation in progress\n", |
437 | __func__, res->sr_slotid, slot->seq_nr); | 431 | __func__, |
432 | res->sr_slot - res->sr_session->fc_slot_table.slots, | ||
433 | res->sr_slot->seq_nr); | ||
438 | goto out_retry; | 434 | goto out_retry; |
439 | default: | 435 | default: |
440 | /* Just update the slot sequence no. */ | 436 | /* Just update the slot sequence no. */ |
441 | ++slot->seq_nr; | 437 | ++res->sr_slot->seq_nr; |
442 | } | 438 | } |
443 | out: | 439 | out: |
444 | /* The session may be reset by one of the error handlers. */ | 440 | /* The session may be reset by one of the error handlers. */ |
@@ -505,10 +501,9 @@ static int nfs41_setup_sequence(struct nfs4_session *session, | |||
505 | 501 | ||
506 | dprintk("--> %s\n", __func__); | 502 | dprintk("--> %s\n", __func__); |
507 | /* slot already allocated? */ | 503 | /* slot already allocated? */ |
508 | if (res->sr_slotid != NFS4_MAX_SLOT_TABLE) | 504 | if (res->sr_slot != NULL) |
509 | return 0; | 505 | return 0; |
510 | 506 | ||
511 | res->sr_slotid = NFS4_MAX_SLOT_TABLE; | ||
512 | tbl = &session->fc_slot_table; | 507 | tbl = &session->fc_slot_table; |
513 | 508 | ||
514 | spin_lock(&tbl->slot_tbl_lock); | 509 | spin_lock(&tbl->slot_tbl_lock); |
@@ -550,7 +545,7 @@ static int nfs41_setup_sequence(struct nfs4_session *session, | |||
550 | dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr); | 545 | dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr); |
551 | 546 | ||
552 | res->sr_session = session; | 547 | res->sr_session = session; |
553 | res->sr_slotid = slotid; | 548 | res->sr_slot = slot; |
554 | res->sr_renewal_time = jiffies; | 549 | res->sr_renewal_time = jiffies; |
555 | res->sr_status_flags = 0; | 550 | res->sr_status_flags = 0; |
556 | /* | 551 | /* |
@@ -576,8 +571,9 @@ int nfs4_setup_sequence(const struct nfs_server *server, | |||
576 | goto out; | 571 | goto out; |
577 | } | 572 | } |
578 | 573 | ||
579 | dprintk("--> %s clp %p session %p sr_slotid %d\n", | 574 | dprintk("--> %s clp %p session %p sr_slot %ld\n", |
580 | __func__, session->clp, session, res->sr_slotid); | 575 | __func__, session->clp, session, res->sr_slot ? |
576 | res->sr_slot - session->fc_slot_table.slots : -1); | ||
581 | 577 | ||
582 | ret = nfs41_setup_sequence(session, args, res, cache_reply, | 578 | ret = nfs41_setup_sequence(session, args, res, cache_reply, |
583 | task); | 579 | task); |
@@ -650,7 +646,7 @@ static int nfs4_call_sync_sequence(struct nfs_server *server, | |||
650 | .callback_data = &data | 646 | .callback_data = &data |
651 | }; | 647 | }; |
652 | 648 | ||
653 | res->sr_slotid = NFS4_MAX_SLOT_TABLE; | 649 | res->sr_slot = NULL; |
654 | if (privileged) | 650 | if (privileged) |
655 | task_setup.callback_ops = &nfs41_call_priv_sync_ops; | 651 | task_setup.callback_ops = &nfs41_call_priv_sync_ops; |
656 | task = rpc_run_task(&task_setup); | 652 | task = rpc_run_task(&task_setup); |
@@ -735,7 +731,6 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p) | |||
735 | p->o_res.server = p->o_arg.server; | 731 | p->o_res.server = p->o_arg.server; |
736 | nfs_fattr_init(&p->f_attr); | 732 | nfs_fattr_init(&p->f_attr); |
737 | nfs_fattr_init(&p->dir_attr); | 733 | nfs_fattr_init(&p->dir_attr); |
738 | p->o_res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; | ||
739 | } | 734 | } |
740 | 735 | ||
741 | static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path, | 736 | static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path, |
@@ -1120,6 +1115,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state * | |||
1120 | clear_bit(NFS_DELEGATED_STATE, &state->flags); | 1115 | clear_bit(NFS_DELEGATED_STATE, &state->flags); |
1121 | smp_rmb(); | 1116 | smp_rmb(); |
1122 | if (state->n_rdwr != 0) { | 1117 | if (state->n_rdwr != 0) { |
1118 | clear_bit(NFS_O_RDWR_STATE, &state->flags); | ||
1123 | ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate); | 1119 | ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate); |
1124 | if (ret != 0) | 1120 | if (ret != 0) |
1125 | return ret; | 1121 | return ret; |
@@ -1127,6 +1123,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state * | |||
1127 | return -ESTALE; | 1123 | return -ESTALE; |
1128 | } | 1124 | } |
1129 | if (state->n_wronly != 0) { | 1125 | if (state->n_wronly != 0) { |
1126 | clear_bit(NFS_O_WRONLY_STATE, &state->flags); | ||
1130 | ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate); | 1127 | ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate); |
1131 | if (ret != 0) | 1128 | if (ret != 0) |
1132 | return ret; | 1129 | return ret; |
@@ -1134,6 +1131,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state * | |||
1134 | return -ESTALE; | 1131 | return -ESTALE; |
1135 | } | 1132 | } |
1136 | if (state->n_rdonly != 0) { | 1133 | if (state->n_rdonly != 0) { |
1134 | clear_bit(NFS_O_RDONLY_STATE, &state->flags); | ||
1137 | ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate); | 1135 | ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate); |
1138 | if (ret != 0) | 1136 | if (ret != 0) |
1139 | return ret; | 1137 | return ret; |
@@ -1188,7 +1186,7 @@ static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state | |||
1188 | int err; | 1186 | int err; |
1189 | do { | 1187 | do { |
1190 | err = _nfs4_do_open_reclaim(ctx, state); | 1188 | err = _nfs4_do_open_reclaim(ctx, state); |
1191 | if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED) | 1189 | if (err != -NFS4ERR_DELAY) |
1192 | break; | 1190 | break; |
1193 | nfs4_handle_exception(server, err, &exception); | 1191 | nfs4_handle_exception(server, err, &exception); |
1194 | } while (exception.retry); | 1192 | } while (exception.retry); |
@@ -1258,6 +1256,13 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state | |||
1258 | case -NFS4ERR_ADMIN_REVOKED: | 1256 | case -NFS4ERR_ADMIN_REVOKED: |
1259 | case -NFS4ERR_BAD_STATEID: | 1257 | case -NFS4ERR_BAD_STATEID: |
1260 | nfs4_state_mark_reclaim_nograce(server->nfs_client, state); | 1258 | nfs4_state_mark_reclaim_nograce(server->nfs_client, state); |
1259 | case -EKEYEXPIRED: | ||
1260 | /* | ||
1261 | * User RPCSEC_GSS context has expired. | ||
1262 | * We cannot recover this stateid now, so | ||
1263 | * skip it and allow recovery thread to | ||
1264 | * proceed. | ||
1265 | */ | ||
1261 | case -ENOMEM: | 1266 | case -ENOMEM: |
1262 | err = 0; | 1267 | err = 0; |
1263 | goto out; | 1268 | goto out; |
@@ -1605,7 +1610,6 @@ static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state | |||
1605 | goto out; | 1610 | goto out; |
1606 | case -NFS4ERR_GRACE: | 1611 | case -NFS4ERR_GRACE: |
1607 | case -NFS4ERR_DELAY: | 1612 | case -NFS4ERR_DELAY: |
1608 | case -EKEYEXPIRED: | ||
1609 | nfs4_handle_exception(server, err, &exception); | 1613 | nfs4_handle_exception(server, err, &exception); |
1610 | err = 0; | 1614 | err = 0; |
1611 | } | 1615 | } |
@@ -1975,7 +1979,6 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, i | |||
1975 | calldata->res.fattr = &calldata->fattr; | 1979 | calldata->res.fattr = &calldata->fattr; |
1976 | calldata->res.seqid = calldata->arg.seqid; | 1980 | calldata->res.seqid = calldata->arg.seqid; |
1977 | calldata->res.server = server; | 1981 | calldata->res.server = server; |
1978 | calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; | ||
1979 | path_get(path); | 1982 | path_get(path); |
1980 | calldata->path = *path; | 1983 | calldata->path = *path; |
1981 | 1984 | ||
@@ -1998,120 +2001,17 @@ out: | |||
1998 | return status; | 2001 | return status; |
1999 | } | 2002 | } |
2000 | 2003 | ||
2001 | static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct nfs4_state *state, fmode_t fmode) | 2004 | static struct inode * |
2002 | { | 2005 | nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr) |
2003 | struct file *filp; | ||
2004 | int ret; | ||
2005 | |||
2006 | /* If the open_intent is for execute, we have an extra check to make */ | ||
2007 | if (fmode & FMODE_EXEC) { | ||
2008 | ret = nfs_may_open(state->inode, | ||
2009 | state->owner->so_cred, | ||
2010 | nd->intent.open.flags); | ||
2011 | if (ret < 0) | ||
2012 | goto out_close; | ||
2013 | } | ||
2014 | filp = lookup_instantiate_filp(nd, path->dentry, NULL); | ||
2015 | if (!IS_ERR(filp)) { | ||
2016 | struct nfs_open_context *ctx; | ||
2017 | ctx = nfs_file_open_context(filp); | ||
2018 | ctx->state = state; | ||
2019 | return 0; | ||
2020 | } | ||
2021 | ret = PTR_ERR(filp); | ||
2022 | out_close: | ||
2023 | nfs4_close_sync(path, state, fmode & (FMODE_READ|FMODE_WRITE)); | ||
2024 | return ret; | ||
2025 | } | ||
2026 | |||
2027 | struct dentry * | ||
2028 | nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | ||
2029 | { | 2006 | { |
2030 | struct path path = { | ||
2031 | .mnt = nd->path.mnt, | ||
2032 | .dentry = dentry, | ||
2033 | }; | ||
2034 | struct dentry *parent; | ||
2035 | struct iattr attr; | ||
2036 | struct rpc_cred *cred; | ||
2037 | struct nfs4_state *state; | 2007 | struct nfs4_state *state; |
2038 | struct dentry *res; | ||
2039 | int open_flags = nd->intent.open.flags; | ||
2040 | fmode_t fmode = open_flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC); | ||
2041 | |||
2042 | if (nd->flags & LOOKUP_CREATE) { | ||
2043 | attr.ia_mode = nd->intent.open.create_mode; | ||
2044 | attr.ia_valid = ATTR_MODE; | ||
2045 | if (!IS_POSIXACL(dir)) | ||
2046 | attr.ia_mode &= ~current_umask(); | ||
2047 | } else { | ||
2048 | open_flags &= ~O_EXCL; | ||
2049 | attr.ia_valid = 0; | ||
2050 | BUG_ON(open_flags & O_CREAT); | ||
2051 | } | ||
2052 | 2008 | ||
2053 | cred = rpc_lookup_cred(); | ||
2054 | if (IS_ERR(cred)) | ||
2055 | return (struct dentry *)cred; | ||
2056 | parent = dentry->d_parent; | ||
2057 | /* Protect against concurrent sillydeletes */ | 2009 | /* Protect against concurrent sillydeletes */ |
2058 | nfs_block_sillyrename(parent); | 2010 | state = nfs4_do_open(dir, &ctx->path, ctx->mode, open_flags, attr, ctx->cred); |
2059 | state = nfs4_do_open(dir, &path, fmode, open_flags, &attr, cred); | 2011 | if (IS_ERR(state)) |
2060 | put_rpccred(cred); | 2012 | return ERR_CAST(state); |
2061 | if (IS_ERR(state)) { | 2013 | ctx->state = state; |
2062 | if (PTR_ERR(state) == -ENOENT) { | 2014 | return igrab(state->inode); |
2063 | d_add(dentry, NULL); | ||
2064 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
2065 | } | ||
2066 | nfs_unblock_sillyrename(parent); | ||
2067 | return (struct dentry *)state; | ||
2068 | } | ||
2069 | res = d_add_unique(dentry, igrab(state->inode)); | ||
2070 | if (res != NULL) | ||
2071 | path.dentry = res; | ||
2072 | nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir)); | ||
2073 | nfs_unblock_sillyrename(parent); | ||
2074 | nfs4_intent_set_file(nd, &path, state, fmode); | ||
2075 | return res; | ||
2076 | } | ||
2077 | |||
2078 | int | ||
2079 | nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, struct nameidata *nd) | ||
2080 | { | ||
2081 | struct path path = { | ||
2082 | .mnt = nd->path.mnt, | ||
2083 | .dentry = dentry, | ||
2084 | }; | ||
2085 | struct rpc_cred *cred; | ||
2086 | struct nfs4_state *state; | ||
2087 | fmode_t fmode = openflags & (FMODE_READ | FMODE_WRITE); | ||
2088 | |||
2089 | cred = rpc_lookup_cred(); | ||
2090 | if (IS_ERR(cred)) | ||
2091 | return PTR_ERR(cred); | ||
2092 | state = nfs4_do_open(dir, &path, fmode, openflags, NULL, cred); | ||
2093 | put_rpccred(cred); | ||
2094 | if (IS_ERR(state)) { | ||
2095 | switch (PTR_ERR(state)) { | ||
2096 | case -EPERM: | ||
2097 | case -EACCES: | ||
2098 | case -EDQUOT: | ||
2099 | case -ENOSPC: | ||
2100 | case -EROFS: | ||
2101 | return PTR_ERR(state); | ||
2102 | default: | ||
2103 | goto out_drop; | ||
2104 | } | ||
2105 | } | ||
2106 | if (state->inode == dentry->d_inode) { | ||
2107 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
2108 | nfs4_intent_set_file(nd, &path, state, fmode); | ||
2109 | return 1; | ||
2110 | } | ||
2111 | nfs4_close_sync(&path, state, fmode); | ||
2112 | out_drop: | ||
2113 | d_drop(dentry); | ||
2114 | return 0; | ||
2115 | } | 2015 | } |
2116 | 2016 | ||
2117 | static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) | 2017 | static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) |
@@ -2568,36 +2468,34 @@ static int nfs4_proc_readlink(struct inode *inode, struct page *page, | |||
2568 | 2468 | ||
2569 | static int | 2469 | static int |
2570 | nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 2470 | nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
2571 | int flags, struct nameidata *nd) | 2471 | int flags, struct nfs_open_context *ctx) |
2572 | { | 2472 | { |
2573 | struct path path = { | 2473 | struct path my_path = { |
2574 | .mnt = nd->path.mnt, | ||
2575 | .dentry = dentry, | 2474 | .dentry = dentry, |
2576 | }; | 2475 | }; |
2476 | struct path *path = &my_path; | ||
2577 | struct nfs4_state *state; | 2477 | struct nfs4_state *state; |
2578 | struct rpc_cred *cred; | 2478 | struct rpc_cred *cred = NULL; |
2579 | fmode_t fmode = flags & (FMODE_READ | FMODE_WRITE); | 2479 | fmode_t fmode = 0; |
2580 | int status = 0; | 2480 | int status = 0; |
2581 | 2481 | ||
2582 | cred = rpc_lookup_cred(); | 2482 | if (ctx != NULL) { |
2583 | if (IS_ERR(cred)) { | 2483 | cred = ctx->cred; |
2584 | status = PTR_ERR(cred); | 2484 | path = &ctx->path; |
2585 | goto out; | 2485 | fmode = ctx->mode; |
2586 | } | 2486 | } |
2587 | state = nfs4_do_open(dir, &path, fmode, flags, sattr, cred); | 2487 | state = nfs4_do_open(dir, path, fmode, flags, sattr, cred); |
2588 | d_drop(dentry); | 2488 | d_drop(dentry); |
2589 | if (IS_ERR(state)) { | 2489 | if (IS_ERR(state)) { |
2590 | status = PTR_ERR(state); | 2490 | status = PTR_ERR(state); |
2591 | goto out_putcred; | 2491 | goto out; |
2592 | } | 2492 | } |
2593 | d_add(dentry, igrab(state->inode)); | 2493 | d_add(dentry, igrab(state->inode)); |
2594 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 2494 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
2595 | if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0) | 2495 | if (ctx != NULL) |
2596 | status = nfs4_intent_set_file(nd, &path, state, fmode); | 2496 | ctx->state = state; |
2597 | else | 2497 | else |
2598 | nfs4_close_sync(&path, state, fmode); | 2498 | nfs4_close_sync(path, state, fmode); |
2599 | out_putcred: | ||
2600 | put_rpccred(cred); | ||
2601 | out: | 2499 | out: |
2602 | return status; | 2500 | return status; |
2603 | } | 2501 | } |
@@ -2655,6 +2553,7 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir) | |||
2655 | 2553 | ||
2656 | args->bitmask = server->cache_consistency_bitmask; | 2554 | args->bitmask = server->cache_consistency_bitmask; |
2657 | res->server = server; | 2555 | res->server = server; |
2556 | res->seq_res.sr_slot = NULL; | ||
2658 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; | 2557 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; |
2659 | } | 2558 | } |
2660 | 2559 | ||
@@ -2671,18 +2570,46 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) | |||
2671 | return 1; | 2570 | return 1; |
2672 | } | 2571 | } |
2673 | 2572 | ||
2573 | static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir) | ||
2574 | { | ||
2575 | struct nfs_server *server = NFS_SERVER(dir); | ||
2576 | struct nfs_renameargs *arg = msg->rpc_argp; | ||
2577 | struct nfs_renameres *res = msg->rpc_resp; | ||
2578 | |||
2579 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME]; | ||
2580 | arg->bitmask = server->attr_bitmask; | ||
2581 | res->server = server; | ||
2582 | } | ||
2583 | |||
2584 | static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir, | ||
2585 | struct inode *new_dir) | ||
2586 | { | ||
2587 | struct nfs_renameres *res = task->tk_msg.rpc_resp; | ||
2588 | |||
2589 | if (!nfs4_sequence_done(task, &res->seq_res)) | ||
2590 | return 0; | ||
2591 | if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN) | ||
2592 | return 0; | ||
2593 | |||
2594 | update_changeattr(old_dir, &res->old_cinfo); | ||
2595 | nfs_post_op_update_inode(old_dir, res->old_fattr); | ||
2596 | update_changeattr(new_dir, &res->new_cinfo); | ||
2597 | nfs_post_op_update_inode(new_dir, res->new_fattr); | ||
2598 | return 1; | ||
2599 | } | ||
2600 | |||
2674 | static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | 2601 | static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, |
2675 | struct inode *new_dir, struct qstr *new_name) | 2602 | struct inode *new_dir, struct qstr *new_name) |
2676 | { | 2603 | { |
2677 | struct nfs_server *server = NFS_SERVER(old_dir); | 2604 | struct nfs_server *server = NFS_SERVER(old_dir); |
2678 | struct nfs4_rename_arg arg = { | 2605 | struct nfs_renameargs arg = { |
2679 | .old_dir = NFS_FH(old_dir), | 2606 | .old_dir = NFS_FH(old_dir), |
2680 | .new_dir = NFS_FH(new_dir), | 2607 | .new_dir = NFS_FH(new_dir), |
2681 | .old_name = old_name, | 2608 | .old_name = old_name, |
2682 | .new_name = new_name, | 2609 | .new_name = new_name, |
2683 | .bitmask = server->attr_bitmask, | 2610 | .bitmask = server->attr_bitmask, |
2684 | }; | 2611 | }; |
2685 | struct nfs4_rename_res res = { | 2612 | struct nfs_renameres res = { |
2686 | .server = server, | 2613 | .server = server, |
2687 | }; | 2614 | }; |
2688 | struct rpc_message msg = { | 2615 | struct rpc_message msg = { |
@@ -2896,15 +2823,16 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
2896 | } | 2823 | } |
2897 | 2824 | ||
2898 | static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | 2825 | static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, |
2899 | u64 cookie, struct page *page, unsigned int count, int plus) | 2826 | u64 cookie, struct page **pages, unsigned int count, int plus) |
2900 | { | 2827 | { |
2901 | struct inode *dir = dentry->d_inode; | 2828 | struct inode *dir = dentry->d_inode; |
2902 | struct nfs4_readdir_arg args = { | 2829 | struct nfs4_readdir_arg args = { |
2903 | .fh = NFS_FH(dir), | 2830 | .fh = NFS_FH(dir), |
2904 | .pages = &page, | 2831 | .pages = pages, |
2905 | .pgbase = 0, | 2832 | .pgbase = 0, |
2906 | .count = count, | 2833 | .count = count, |
2907 | .bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask, | 2834 | .bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask, |
2835 | .plus = plus, | ||
2908 | }; | 2836 | }; |
2909 | struct nfs4_readdir_res res; | 2837 | struct nfs4_readdir_res res; |
2910 | struct rpc_message msg = { | 2838 | struct rpc_message msg = { |
@@ -2932,14 +2860,14 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
2932 | } | 2860 | } |
2933 | 2861 | ||
2934 | static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | 2862 | static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, |
2935 | u64 cookie, struct page *page, unsigned int count, int plus) | 2863 | u64 cookie, struct page **pages, unsigned int count, int plus) |
2936 | { | 2864 | { |
2937 | struct nfs4_exception exception = { }; | 2865 | struct nfs4_exception exception = { }; |
2938 | int err; | 2866 | int err; |
2939 | do { | 2867 | do { |
2940 | err = nfs4_handle_exception(NFS_SERVER(dentry->d_inode), | 2868 | err = nfs4_handle_exception(NFS_SERVER(dentry->d_inode), |
2941 | _nfs4_proc_readdir(dentry, cred, cookie, | 2869 | _nfs4_proc_readdir(dentry, cred, cookie, |
2942 | page, count, plus), | 2870 | pages, count, plus), |
2943 | &exception); | 2871 | &exception); |
2944 | } while (exception.retry); | 2872 | } while (exception.retry); |
2945 | return err; | 2873 | return err; |
@@ -3490,9 +3418,6 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
3490 | nfs4_state_mark_reclaim_nograce(clp, state); | 3418 | nfs4_state_mark_reclaim_nograce(clp, state); |
3491 | goto do_state_recovery; | 3419 | goto do_state_recovery; |
3492 | case -NFS4ERR_STALE_STATEID: | 3420 | case -NFS4ERR_STALE_STATEID: |
3493 | if (state == NULL) | ||
3494 | break; | ||
3495 | nfs4_state_mark_reclaim_reboot(clp, state); | ||
3496 | case -NFS4ERR_STALE_CLIENTID: | 3421 | case -NFS4ERR_STALE_CLIENTID: |
3497 | case -NFS4ERR_EXPIRED: | 3422 | case -NFS4ERR_EXPIRED: |
3498 | goto do_state_recovery; | 3423 | goto do_state_recovery; |
@@ -3626,7 +3551,6 @@ int nfs4_proc_setclientid_confirm(struct nfs_client *clp, | |||
3626 | case -NFS4ERR_RESOURCE: | 3551 | case -NFS4ERR_RESOURCE: |
3627 | /* The IBM lawyers misread another document! */ | 3552 | /* The IBM lawyers misread another document! */ |
3628 | case -NFS4ERR_DELAY: | 3553 | case -NFS4ERR_DELAY: |
3629 | case -EKEYEXPIRED: | ||
3630 | err = nfs4_delay(clp->cl_rpcclient, &timeout); | 3554 | err = nfs4_delay(clp->cl_rpcclient, &timeout); |
3631 | } | 3555 | } |
3632 | } while (err == 0); | 3556 | } while (err == 0); |
@@ -3721,7 +3645,6 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co | |||
3721 | memcpy(&data->stateid, stateid, sizeof(data->stateid)); | 3645 | memcpy(&data->stateid, stateid, sizeof(data->stateid)); |
3722 | data->res.fattr = &data->fattr; | 3646 | data->res.fattr = &data->fattr; |
3723 | data->res.server = server; | 3647 | data->res.server = server; |
3724 | data->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; | ||
3725 | nfs_fattr_init(data->res.fattr); | 3648 | nfs_fattr_init(data->res.fattr); |
3726 | data->timestamp = jiffies; | 3649 | data->timestamp = jiffies; |
3727 | data->rpc_status = 0; | 3650 | data->rpc_status = 0; |
@@ -3874,7 +3797,6 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, | |||
3874 | p->arg.fl = &p->fl; | 3797 | p->arg.fl = &p->fl; |
3875 | p->arg.seqid = seqid; | 3798 | p->arg.seqid = seqid; |
3876 | p->res.seqid = seqid; | 3799 | p->res.seqid = seqid; |
3877 | p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; | ||
3878 | p->arg.stateid = &lsp->ls_stateid; | 3800 | p->arg.stateid = &lsp->ls_stateid; |
3879 | p->lsp = lsp; | 3801 | p->lsp = lsp; |
3880 | atomic_inc(&lsp->ls_count); | 3802 | atomic_inc(&lsp->ls_count); |
@@ -4054,7 +3976,6 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, | |||
4054 | p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; | 3976 | p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; |
4055 | p->arg.lock_owner.id = lsp->ls_id.id; | 3977 | p->arg.lock_owner.id = lsp->ls_id.id; |
4056 | p->res.lock_seqid = p->arg.lock_seqid; | 3978 | p->res.lock_seqid = p->arg.lock_seqid; |
4057 | p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; | ||
4058 | p->lsp = lsp; | 3979 | p->lsp = lsp; |
4059 | p->server = server; | 3980 | p->server = server; |
4060 | atomic_inc(&lsp->ls_count); | 3981 | atomic_inc(&lsp->ls_count); |
@@ -4241,7 +4162,7 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request | |||
4241 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) | 4162 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) |
4242 | return 0; | 4163 | return 0; |
4243 | err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM); | 4164 | err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM); |
4244 | if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED) | 4165 | if (err != -NFS4ERR_DELAY) |
4245 | break; | 4166 | break; |
4246 | nfs4_handle_exception(server, err, &exception); | 4167 | nfs4_handle_exception(server, err, &exception); |
4247 | } while (exception.retry); | 4168 | } while (exception.retry); |
@@ -4266,7 +4187,6 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request | |||
4266 | goto out; | 4187 | goto out; |
4267 | case -NFS4ERR_GRACE: | 4188 | case -NFS4ERR_GRACE: |
4268 | case -NFS4ERR_DELAY: | 4189 | case -NFS4ERR_DELAY: |
4269 | case -EKEYEXPIRED: | ||
4270 | nfs4_handle_exception(server, err, &exception); | 4190 | nfs4_handle_exception(server, err, &exception); |
4271 | err = 0; | 4191 | err = 0; |
4272 | } | 4192 | } |
@@ -4412,13 +4332,21 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) | |||
4412 | nfs4_state_mark_reclaim_nograce(server->nfs_client, state); | 4332 | nfs4_state_mark_reclaim_nograce(server->nfs_client, state); |
4413 | err = 0; | 4333 | err = 0; |
4414 | goto out; | 4334 | goto out; |
4335 | case -EKEYEXPIRED: | ||
4336 | /* | ||
4337 | * User RPCSEC_GSS context has expired. | ||
4338 | * We cannot recover this stateid now, so | ||
4339 | * skip it and allow recovery thread to | ||
4340 | * proceed. | ||
4341 | */ | ||
4342 | err = 0; | ||
4343 | goto out; | ||
4415 | case -ENOMEM: | 4344 | case -ENOMEM: |
4416 | case -NFS4ERR_DENIED: | 4345 | case -NFS4ERR_DENIED: |
4417 | /* kill_proc(fl->fl_pid, SIGLOST, 1); */ | 4346 | /* kill_proc(fl->fl_pid, SIGLOST, 1); */ |
4418 | err = 0; | 4347 | err = 0; |
4419 | goto out; | 4348 | goto out; |
4420 | case -NFS4ERR_DELAY: | 4349 | case -NFS4ERR_DELAY: |
4421 | case -EKEYEXPIRED: | ||
4422 | break; | 4350 | break; |
4423 | } | 4351 | } |
4424 | err = nfs4_handle_exception(server, err, &exception); | 4352 | err = nfs4_handle_exception(server, err, &exception); |
@@ -4647,7 +4575,6 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata) | |||
4647 | switch (task->tk_status) { | 4575 | switch (task->tk_status) { |
4648 | case -NFS4ERR_DELAY: | 4576 | case -NFS4ERR_DELAY: |
4649 | case -NFS4ERR_GRACE: | 4577 | case -NFS4ERR_GRACE: |
4650 | case -EKEYEXPIRED: | ||
4651 | dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status); | 4578 | dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status); |
4652 | rpc_delay(task, NFS4_POLL_RETRY_MIN); | 4579 | rpc_delay(task, NFS4_POLL_RETRY_MIN); |
4653 | task->tk_status = 0; | 4580 | task->tk_status = 0; |
@@ -4687,7 +4614,6 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) | |||
4687 | }; | 4614 | }; |
4688 | int status; | 4615 | int status; |
4689 | 4616 | ||
4690 | res.lr_seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; | ||
4691 | dprintk("--> %s\n", __func__); | 4617 | dprintk("--> %s\n", __func__); |
4692 | task = rpc_run_task(&task_setup); | 4618 | task = rpc_run_task(&task_setup); |
4693 | 4619 | ||
@@ -5111,7 +5037,6 @@ static int nfs41_sequence_handle_errors(struct rpc_task *task, struct nfs_client | |||
5111 | { | 5037 | { |
5112 | switch(task->tk_status) { | 5038 | switch(task->tk_status) { |
5113 | case -NFS4ERR_DELAY: | 5039 | case -NFS4ERR_DELAY: |
5114 | case -EKEYEXPIRED: | ||
5115 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 5040 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
5116 | return -EAGAIN; | 5041 | return -EAGAIN; |
5117 | default: | 5042 | default: |
@@ -5180,12 +5105,11 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_ | |||
5180 | 5105 | ||
5181 | if (!atomic_inc_not_zero(&clp->cl_count)) | 5106 | if (!atomic_inc_not_zero(&clp->cl_count)) |
5182 | return ERR_PTR(-EIO); | 5107 | return ERR_PTR(-EIO); |
5183 | calldata = kmalloc(sizeof(*calldata), GFP_NOFS); | 5108 | calldata = kzalloc(sizeof(*calldata), GFP_NOFS); |
5184 | if (calldata == NULL) { | 5109 | if (calldata == NULL) { |
5185 | nfs_put_client(clp); | 5110 | nfs_put_client(clp); |
5186 | return ERR_PTR(-ENOMEM); | 5111 | return ERR_PTR(-ENOMEM); |
5187 | } | 5112 | } |
5188 | calldata->res.sr_slotid = NFS4_MAX_SLOT_TABLE; | ||
5189 | msg.rpc_argp = &calldata->args; | 5113 | msg.rpc_argp = &calldata->args; |
5190 | msg.rpc_resp = &calldata->res; | 5114 | msg.rpc_resp = &calldata->res; |
5191 | calldata->clp = clp; | 5115 | calldata->clp = clp; |
@@ -5254,7 +5178,6 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf | |||
5254 | case -NFS4ERR_WRONG_CRED: /* What to do here? */ | 5178 | case -NFS4ERR_WRONG_CRED: /* What to do here? */ |
5255 | break; | 5179 | break; |
5256 | case -NFS4ERR_DELAY: | 5180 | case -NFS4ERR_DELAY: |
5257 | case -EKEYEXPIRED: | ||
5258 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 5181 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
5259 | return -EAGAIN; | 5182 | return -EAGAIN; |
5260 | default: | 5183 | default: |
@@ -5317,7 +5240,6 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp) | |||
5317 | goto out; | 5240 | goto out; |
5318 | calldata->clp = clp; | 5241 | calldata->clp = clp; |
5319 | calldata->arg.one_fs = 0; | 5242 | calldata->arg.one_fs = 0; |
5320 | calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; | ||
5321 | 5243 | ||
5322 | msg.rpc_argp = &calldata->arg; | 5244 | msg.rpc_argp = &calldata->arg; |
5323 | msg.rpc_resp = &calldata->res; | 5245 | msg.rpc_resp = &calldata->res; |
@@ -5443,6 +5365,8 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
5443 | .unlink_setup = nfs4_proc_unlink_setup, | 5365 | .unlink_setup = nfs4_proc_unlink_setup, |
5444 | .unlink_done = nfs4_proc_unlink_done, | 5366 | .unlink_done = nfs4_proc_unlink_done, |
5445 | .rename = nfs4_proc_rename, | 5367 | .rename = nfs4_proc_rename, |
5368 | .rename_setup = nfs4_proc_rename_setup, | ||
5369 | .rename_done = nfs4_proc_rename_done, | ||
5446 | .link = nfs4_proc_link, | 5370 | .link = nfs4_proc_link, |
5447 | .symlink = nfs4_proc_symlink, | 5371 | .symlink = nfs4_proc_symlink, |
5448 | .mkdir = nfs4_proc_mkdir, | 5372 | .mkdir = nfs4_proc_mkdir, |
@@ -5463,6 +5387,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
5463 | .lock = nfs4_proc_lock, | 5387 | .lock = nfs4_proc_lock, |
5464 | .clear_acl_cache = nfs4_zap_acl_attr, | 5388 | .clear_acl_cache = nfs4_zap_acl_attr, |
5465 | .close_context = nfs4_close_context, | 5389 | .close_context = nfs4_close_context, |
5390 | .open_context = nfs4_atomic_open, | ||
5466 | }; | 5391 | }; |
5467 | 5392 | ||
5468 | /* | 5393 | /* |