|
@@ -129,7 +129,7 @@ const u32 nfs4_fsinfo_bitmap[2] = { FATTR4_WORD0_MAXFILESIZE
|
|
|
| FATTR4_WORD0_MAXREAD
|
|
|
| FATTR4_WORD0_MAXWRITE
|
|
|
| FATTR4_WORD0_LEASE_TIME,
|
|
|
- 0
|
|
|
+ FATTR4_WORD1_TIME_DELTA
|
|
|
};
|
|
|
|
|
|
const u32 nfs4_fs_locations_bitmap[2] = {
|
|
@@ -255,9 +255,6 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
|
|
|
nfs4_state_mark_reclaim_nograce(clp, state);
|
|
|
goto do_state_recovery;
|
|
|
case -NFS4ERR_STALE_STATEID:
|
|
|
- if (state == NULL)
|
|
|
- break;
|
|
|
- nfs4_state_mark_reclaim_reboot(clp, state);
|
|
|
case -NFS4ERR_STALE_CLIENTID:
|
|
|
case -NFS4ERR_EXPIRED:
|
|
|
goto do_state_recovery;
|
|
@@ -334,10 +331,12 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp
|
|
|
* Must be called while holding tbl->slot_tbl_lock
|
|
|
*/
|
|
|
static void
|
|
|
-nfs4_free_slot(struct nfs4_slot_table *tbl, u8 free_slotid)
|
|
|
+nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *free_slot)
|
|
|
{
|
|
|
+ int free_slotid = free_slot - tbl->slots;
|
|
|
int slotid = free_slotid;
|
|
|
|
|
|
+ BUG_ON(slotid < 0 || slotid >= NFS4_MAX_SLOT_TABLE);
|
|
|
/* clear used bit in bitmap */
|
|
|
__clear_bit(slotid, tbl->used_slots);
|
|
|
|
|
@@ -379,7 +378,7 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
|
|
|
struct nfs4_slot_table *tbl;
|
|
|
|
|
|
tbl = &res->sr_session->fc_slot_table;
|
|
|
- if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) {
|
|
|
+ if (!res->sr_slot) {
|
|
|
/* just wake up the next guy waiting since
|
|
|
* we may have not consumed a slot after all */
|
|
|
dprintk("%s: No slot\n", __func__);
|
|
@@ -387,17 +386,15 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
|
|
|
}
|
|
|
|
|
|
spin_lock(&tbl->slot_tbl_lock);
|
|
|
- nfs4_free_slot(tbl, res->sr_slotid);
|
|
|
+ nfs4_free_slot(tbl, res->sr_slot);
|
|
|
nfs41_check_drain_session_complete(res->sr_session);
|
|
|
spin_unlock(&tbl->slot_tbl_lock);
|
|
|
- res->sr_slotid = NFS4_MAX_SLOT_TABLE;
|
|
|
+ res->sr_slot = NULL;
|
|
|
}
|
|
|
|
|
|
static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
|
|
|
{
|
|
|
unsigned long timestamp;
|
|
|
- struct nfs4_slot_table *tbl;
|
|
|
- struct nfs4_slot *slot;
|
|
|
struct nfs_client *clp;
|
|
|
|
|
|
/*
|
|
@@ -410,17 +407,14 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
|
|
|
res->sr_status = NFS_OK;
|
|
|
|
|
|
/* -ERESTARTSYS can result in skipping nfs41_sequence_setup */
|
|
|
- if (res->sr_slotid == NFS4_MAX_SLOT_TABLE)
|
|
|
+ if (!res->sr_slot)
|
|
|
goto out;
|
|
|
|
|
|
- tbl = &res->sr_session->fc_slot_table;
|
|
|
- slot = tbl->slots + res->sr_slotid;
|
|
|
-
|
|
|
/* Check the SEQUENCE operation status */
|
|
|
switch (res->sr_status) {
|
|
|
case 0:
|
|
|
/* Update the slot's sequence and clientid lease timer */
|
|
|
- ++slot->seq_nr;
|
|
|
+ ++res->sr_slot->seq_nr;
|
|
|
timestamp = res->sr_renewal_time;
|
|
|
clp = res->sr_session->clp;
|
|
|
do_renew_lease(clp, timestamp);
|
|
@@ -433,12 +427,14 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
|
|
|
* returned NFS4ERR_DELAY as per Section 2.10.6.2
|
|
|
* of RFC5661.
|
|
|
*/
|
|
|
- dprintk("%s: slot=%d seq=%d: Operation in progress\n",
|
|
|
- __func__, res->sr_slotid, slot->seq_nr);
|
|
|
+ dprintk("%s: slot=%ld seq=%d: Operation in progress\n",
|
|
|
+ __func__,
|
|
|
+ res->sr_slot - res->sr_session->fc_slot_table.slots,
|
|
|
+ res->sr_slot->seq_nr);
|
|
|
goto out_retry;
|
|
|
default:
|
|
|
/* Just update the slot sequence no. */
|
|
|
- ++slot->seq_nr;
|
|
|
+ ++res->sr_slot->seq_nr;
|
|
|
}
|
|
|
out:
|
|
|
/* The session may be reset by one of the error handlers. */
|
|
@@ -505,10 +501,9 @@ static int nfs41_setup_sequence(struct nfs4_session *session,
|
|
|
|
|
|
dprintk("--> %s\n", __func__);
|
|
|
/* slot already allocated? */
|
|
|
- if (res->sr_slotid != NFS4_MAX_SLOT_TABLE)
|
|
|
+ if (res->sr_slot != NULL)
|
|
|
return 0;
|
|
|
|
|
|
- res->sr_slotid = NFS4_MAX_SLOT_TABLE;
|
|
|
tbl = &session->fc_slot_table;
|
|
|
|
|
|
spin_lock(&tbl->slot_tbl_lock);
|
|
@@ -550,7 +545,7 @@ static int nfs41_setup_sequence(struct nfs4_session *session,
|
|
|
dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr);
|
|
|
|
|
|
res->sr_session = session;
|
|
|
- res->sr_slotid = slotid;
|
|
|
+ res->sr_slot = slot;
|
|
|
res->sr_renewal_time = jiffies;
|
|
|
res->sr_status_flags = 0;
|
|
|
/*
|
|
@@ -576,8 +571,9 @@ int nfs4_setup_sequence(const struct nfs_server *server,
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- dprintk("--> %s clp %p session %p sr_slotid %d\n",
|
|
|
- __func__, session->clp, session, res->sr_slotid);
|
|
|
+ dprintk("--> %s clp %p session %p sr_slot %ld\n",
|
|
|
+ __func__, session->clp, session, res->sr_slot ?
|
|
|
+ res->sr_slot - session->fc_slot_table.slots : -1);
|
|
|
|
|
|
ret = nfs41_setup_sequence(session, args, res, cache_reply,
|
|
|
task);
|
|
@@ -650,7 +646,7 @@ static int nfs4_call_sync_sequence(struct nfs_server *server,
|
|
|
.callback_data = &data
|
|
|
};
|
|
|
|
|
|
- res->sr_slotid = NFS4_MAX_SLOT_TABLE;
|
|
|
+ res->sr_slot = NULL;
|
|
|
if (privileged)
|
|
|
task_setup.callback_ops = &nfs41_call_priv_sync_ops;
|
|
|
task = rpc_run_task(&task_setup);
|
|
@@ -735,7 +731,6 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p)
|
|
|
p->o_res.server = p->o_arg.server;
|
|
|
nfs_fattr_init(&p->f_attr);
|
|
|
nfs_fattr_init(&p->dir_attr);
|
|
|
- p->o_res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
|
|
|
}
|
|
|
|
|
|
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 *
|
|
|
clear_bit(NFS_DELEGATED_STATE, &state->flags);
|
|
|
smp_rmb();
|
|
|
if (state->n_rdwr != 0) {
|
|
|
+ clear_bit(NFS_O_RDWR_STATE, &state->flags);
|
|
|
ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate);
|
|
|
if (ret != 0)
|
|
|
return ret;
|
|
@@ -1127,6 +1123,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
|
|
|
return -ESTALE;
|
|
|
}
|
|
|
if (state->n_wronly != 0) {
|
|
|
+ clear_bit(NFS_O_WRONLY_STATE, &state->flags);
|
|
|
ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate);
|
|
|
if (ret != 0)
|
|
|
return ret;
|
|
@@ -1134,6 +1131,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
|
|
|
return -ESTALE;
|
|
|
}
|
|
|
if (state->n_rdonly != 0) {
|
|
|
+ clear_bit(NFS_O_RDONLY_STATE, &state->flags);
|
|
|
ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate);
|
|
|
if (ret != 0)
|
|
|
return ret;
|
|
@@ -1188,7 +1186,7 @@ static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state
|
|
|
int err;
|
|
|
do {
|
|
|
err = _nfs4_do_open_reclaim(ctx, state);
|
|
|
- if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED)
|
|
|
+ if (err != -NFS4ERR_DELAY)
|
|
|
break;
|
|
|
nfs4_handle_exception(server, err, &exception);
|
|
|
} while (exception.retry);
|
|
@@ -1258,6 +1256,13 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state
|
|
|
case -NFS4ERR_ADMIN_REVOKED:
|
|
|
case -NFS4ERR_BAD_STATEID:
|
|
|
nfs4_state_mark_reclaim_nograce(server->nfs_client, state);
|
|
|
+ case -EKEYEXPIRED:
|
|
|
+ /*
|
|
|
+ * User RPCSEC_GSS context has expired.
|
|
|
+ * We cannot recover this stateid now, so
|
|
|
+ * skip it and allow recovery thread to
|
|
|
+ * proceed.
|
|
|
+ */
|
|
|
case -ENOMEM:
|
|
|
err = 0;
|
|
|
goto out;
|
|
@@ -1605,7 +1610,6 @@ static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state
|
|
|
goto out;
|
|
|
case -NFS4ERR_GRACE:
|
|
|
case -NFS4ERR_DELAY:
|
|
|
- case -EKEYEXPIRED:
|
|
|
nfs4_handle_exception(server, err, &exception);
|
|
|
err = 0;
|
|
|
}
|
|
@@ -1975,7 +1979,6 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, i
|
|
|
calldata->res.fattr = &calldata->fattr;
|
|
|
calldata->res.seqid = calldata->arg.seqid;
|
|
|
calldata->res.server = server;
|
|
|
- calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
|
|
|
path_get(path);
|
|
|
calldata->path = *path;
|
|
|
|
|
@@ -1998,120 +2001,17 @@ out:
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
-static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct nfs4_state *state, fmode_t fmode)
|
|
|
-{
|
|
|
- struct file *filp;
|
|
|
- int ret;
|
|
|
-
|
|
|
- /* If the open_intent is for execute, we have an extra check to make */
|
|
|
- if (fmode & FMODE_EXEC) {
|
|
|
- ret = nfs_may_open(state->inode,
|
|
|
- state->owner->so_cred,
|
|
|
- nd->intent.open.flags);
|
|
|
- if (ret < 0)
|
|
|
- goto out_close;
|
|
|
- }
|
|
|
- filp = lookup_instantiate_filp(nd, path->dentry, NULL);
|
|
|
- if (!IS_ERR(filp)) {
|
|
|
- struct nfs_open_context *ctx;
|
|
|
- ctx = nfs_file_open_context(filp);
|
|
|
- ctx->state = state;
|
|
|
- return 0;
|
|
|
- }
|
|
|
- ret = PTR_ERR(filp);
|
|
|
-out_close:
|
|
|
- nfs4_close_sync(path, state, fmode & (FMODE_READ|FMODE_WRITE));
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-struct dentry *
|
|
|
-nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
|
|
|
+static struct inode *
|
|
|
+nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr)
|
|
|
{
|
|
|
- struct path path = {
|
|
|
- .mnt = nd->path.mnt,
|
|
|
- .dentry = dentry,
|
|
|
- };
|
|
|
- struct dentry *parent;
|
|
|
- struct iattr attr;
|
|
|
- struct rpc_cred *cred;
|
|
|
struct nfs4_state *state;
|
|
|
- struct dentry *res;
|
|
|
- int open_flags = nd->intent.open.flags;
|
|
|
- fmode_t fmode = open_flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);
|
|
|
-
|
|
|
- if (nd->flags & LOOKUP_CREATE) {
|
|
|
- attr.ia_mode = nd->intent.open.create_mode;
|
|
|
- attr.ia_valid = ATTR_MODE;
|
|
|
- if (!IS_POSIXACL(dir))
|
|
|
- attr.ia_mode &= ~current_umask();
|
|
|
- } else {
|
|
|
- open_flags &= ~O_EXCL;
|
|
|
- attr.ia_valid = 0;
|
|
|
- BUG_ON(open_flags & O_CREAT);
|
|
|
- }
|
|
|
|
|
|
- cred = rpc_lookup_cred();
|
|
|
- if (IS_ERR(cred))
|
|
|
- return (struct dentry *)cred;
|
|
|
- parent = dentry->d_parent;
|
|
|
/* Protect against concurrent sillydeletes */
|
|
|
- nfs_block_sillyrename(parent);
|
|
|
- state = nfs4_do_open(dir, &path, fmode, open_flags, &attr, cred);
|
|
|
- put_rpccred(cred);
|
|
|
- if (IS_ERR(state)) {
|
|
|
- if (PTR_ERR(state) == -ENOENT) {
|
|
|
- d_add(dentry, NULL);
|
|
|
- nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
|
|
|
- }
|
|
|
- nfs_unblock_sillyrename(parent);
|
|
|
- return (struct dentry *)state;
|
|
|
- }
|
|
|
- res = d_add_unique(dentry, igrab(state->inode));
|
|
|
- if (res != NULL)
|
|
|
- path.dentry = res;
|
|
|
- nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir));
|
|
|
- nfs_unblock_sillyrename(parent);
|
|
|
- nfs4_intent_set_file(nd, &path, state, fmode);
|
|
|
- return res;
|
|
|
-}
|
|
|
-
|
|
|
-int
|
|
|
-nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, struct nameidata *nd)
|
|
|
-{
|
|
|
- struct path path = {
|
|
|
- .mnt = nd->path.mnt,
|
|
|
- .dentry = dentry,
|
|
|
- };
|
|
|
- struct rpc_cred *cred;
|
|
|
- struct nfs4_state *state;
|
|
|
- fmode_t fmode = openflags & (FMODE_READ | FMODE_WRITE);
|
|
|
-
|
|
|
- cred = rpc_lookup_cred();
|
|
|
- if (IS_ERR(cred))
|
|
|
- return PTR_ERR(cred);
|
|
|
- state = nfs4_do_open(dir, &path, fmode, openflags, NULL, cred);
|
|
|
- put_rpccred(cred);
|
|
|
- if (IS_ERR(state)) {
|
|
|
- switch (PTR_ERR(state)) {
|
|
|
- case -EPERM:
|
|
|
- case -EACCES:
|
|
|
- case -EDQUOT:
|
|
|
- case -ENOSPC:
|
|
|
- case -EROFS:
|
|
|
- return PTR_ERR(state);
|
|
|
- default:
|
|
|
- goto out_drop;
|
|
|
- }
|
|
|
- }
|
|
|
- if (state->inode == dentry->d_inode) {
|
|
|
- nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
|
|
|
- nfs4_intent_set_file(nd, &path, state, fmode);
|
|
|
- return 1;
|
|
|
- }
|
|
|
- nfs4_close_sync(&path, state, fmode);
|
|
|
-out_drop:
|
|
|
- d_drop(dentry);
|
|
|
- return 0;
|
|
|
+ state = nfs4_do_open(dir, &ctx->path, ctx->mode, open_flags, attr, ctx->cred);
|
|
|
+ if (IS_ERR(state))
|
|
|
+ return ERR_CAST(state);
|
|
|
+ ctx->state = state;
|
|
|
+ return igrab(state->inode);
|
|
|
}
|
|
|
|
|
|
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,
|
|
|
|
|
|
static int
|
|
|
nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
|
|
- int flags, struct nameidata *nd)
|
|
|
+ int flags, struct nfs_open_context *ctx)
|
|
|
{
|
|
|
- struct path path = {
|
|
|
- .mnt = nd->path.mnt,
|
|
|
+ struct path my_path = {
|
|
|
.dentry = dentry,
|
|
|
};
|
|
|
+ struct path *path = &my_path;
|
|
|
struct nfs4_state *state;
|
|
|
- struct rpc_cred *cred;
|
|
|
- fmode_t fmode = flags & (FMODE_READ | FMODE_WRITE);
|
|
|
+ struct rpc_cred *cred = NULL;
|
|
|
+ fmode_t fmode = 0;
|
|
|
int status = 0;
|
|
|
|
|
|
- cred = rpc_lookup_cred();
|
|
|
- if (IS_ERR(cred)) {
|
|
|
- status = PTR_ERR(cred);
|
|
|
- goto out;
|
|
|
+ if (ctx != NULL) {
|
|
|
+ cred = ctx->cred;
|
|
|
+ path = &ctx->path;
|
|
|
+ fmode = ctx->mode;
|
|
|
}
|
|
|
- state = nfs4_do_open(dir, &path, fmode, flags, sattr, cred);
|
|
|
+ state = nfs4_do_open(dir, path, fmode, flags, sattr, cred);
|
|
|
d_drop(dentry);
|
|
|
if (IS_ERR(state)) {
|
|
|
status = PTR_ERR(state);
|
|
|
- goto out_putcred;
|
|
|
+ goto out;
|
|
|
}
|
|
|
d_add(dentry, igrab(state->inode));
|
|
|
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
|
|
|
- if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
|
|
|
- status = nfs4_intent_set_file(nd, &path, state, fmode);
|
|
|
+ if (ctx != NULL)
|
|
|
+ ctx->state = state;
|
|
|
else
|
|
|
- nfs4_close_sync(&path, state, fmode);
|
|
|
-out_putcred:
|
|
|
- put_rpccred(cred);
|
|
|
+ nfs4_close_sync(path, state, fmode);
|
|
|
out:
|
|
|
return status;
|
|
|
}
|
|
@@ -2655,6 +2553,7 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
|
|
|
|
|
|
args->bitmask = server->cache_consistency_bitmask;
|
|
|
res->server = server;
|
|
|
+ res->seq_res.sr_slot = NULL;
|
|
|
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
|
|
|
}
|
|
|
|
|
@@ -2671,18 +2570,46 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
+static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
|
|
|
+{
|
|
|
+ struct nfs_server *server = NFS_SERVER(dir);
|
|
|
+ struct nfs_renameargs *arg = msg->rpc_argp;
|
|
|
+ struct nfs_renameres *res = msg->rpc_resp;
|
|
|
+
|
|
|
+ msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME];
|
|
|
+ arg->bitmask = server->attr_bitmask;
|
|
|
+ res->server = server;
|
|
|
+}
|
|
|
+
|
|
|
+static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
|
|
|
+ struct inode *new_dir)
|
|
|
+{
|
|
|
+ struct nfs_renameres *res = task->tk_msg.rpc_resp;
|
|
|
+
|
|
|
+ if (!nfs4_sequence_done(task, &res->seq_res))
|
|
|
+ return 0;
|
|
|
+ if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ update_changeattr(old_dir, &res->old_cinfo);
|
|
|
+ nfs_post_op_update_inode(old_dir, res->old_fattr);
|
|
|
+ update_changeattr(new_dir, &res->new_cinfo);
|
|
|
+ nfs_post_op_update_inode(new_dir, res->new_fattr);
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
|
|
|
struct inode *new_dir, struct qstr *new_name)
|
|
|
{
|
|
|
struct nfs_server *server = NFS_SERVER(old_dir);
|
|
|
- struct nfs4_rename_arg arg = {
|
|
|
+ struct nfs_renameargs arg = {
|
|
|
.old_dir = NFS_FH(old_dir),
|
|
|
.new_dir = NFS_FH(new_dir),
|
|
|
.old_name = old_name,
|
|
|
.new_name = new_name,
|
|
|
.bitmask = server->attr_bitmask,
|
|
|
};
|
|
|
- struct nfs4_rename_res res = {
|
|
|
+ struct nfs_renameres res = {
|
|
|
.server = server,
|
|
|
};
|
|
|
struct rpc_message msg = {
|
|
@@ -2896,15 +2823,16 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
|
|
|
}
|
|
|
|
|
|
static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
|
|
|
- u64 cookie, struct page *page, unsigned int count, int plus)
|
|
|
+ u64 cookie, struct page **pages, unsigned int count, int plus)
|
|
|
{
|
|
|
struct inode *dir = dentry->d_inode;
|
|
|
struct nfs4_readdir_arg args = {
|
|
|
.fh = NFS_FH(dir),
|
|
|
- .pages = &page,
|
|
|
+ .pages = pages,
|
|
|
.pgbase = 0,
|
|
|
.count = count,
|
|
|
.bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask,
|
|
|
+ .plus = plus,
|
|
|
};
|
|
|
struct nfs4_readdir_res res;
|
|
|
struct rpc_message msg = {
|
|
@@ -2932,14 +2860,14 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
|
|
|
}
|
|
|
|
|
|
static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
|
|
|
- u64 cookie, struct page *page, unsigned int count, int plus)
|
|
|
+ u64 cookie, struct page **pages, unsigned int count, int plus)
|
|
|
{
|
|
|
struct nfs4_exception exception = { };
|
|
|
int err;
|
|
|
do {
|
|
|
err = nfs4_handle_exception(NFS_SERVER(dentry->d_inode),
|
|
|
_nfs4_proc_readdir(dentry, cred, cookie,
|
|
|
- page, count, plus),
|
|
|
+ pages, count, plus),
|
|
|
&exception);
|
|
|
} while (exception.retry);
|
|
|
return err;
|
|
@@ -3490,9 +3418,6 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
|
|
|
nfs4_state_mark_reclaim_nograce(clp, state);
|
|
|
goto do_state_recovery;
|
|
|
case -NFS4ERR_STALE_STATEID:
|
|
|
- if (state == NULL)
|
|
|
- break;
|
|
|
- nfs4_state_mark_reclaim_reboot(clp, state);
|
|
|
case -NFS4ERR_STALE_CLIENTID:
|
|
|
case -NFS4ERR_EXPIRED:
|
|
|
goto do_state_recovery;
|
|
@@ -3626,7 +3551,6 @@ int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
|
|
|
case -NFS4ERR_RESOURCE:
|
|
|
/* The IBM lawyers misread another document! */
|
|
|
case -NFS4ERR_DELAY:
|
|
|
- case -EKEYEXPIRED:
|
|
|
err = nfs4_delay(clp->cl_rpcclient, &timeout);
|
|
|
}
|
|
|
} while (err == 0);
|
|
@@ -3721,7 +3645,6 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
|
|
|
memcpy(&data->stateid, stateid, sizeof(data->stateid));
|
|
|
data->res.fattr = &data->fattr;
|
|
|
data->res.server = server;
|
|
|
- data->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
|
|
|
nfs_fattr_init(data->res.fattr);
|
|
|
data->timestamp = jiffies;
|
|
|
data->rpc_status = 0;
|
|
@@ -3874,7 +3797,6 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
|
|
|
p->arg.fl = &p->fl;
|
|
|
p->arg.seqid = seqid;
|
|
|
p->res.seqid = seqid;
|
|
|
- p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
|
|
|
p->arg.stateid = &lsp->ls_stateid;
|
|
|
p->lsp = lsp;
|
|
|
atomic_inc(&lsp->ls_count);
|
|
@@ -4054,7 +3976,6 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
|
|
|
p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
|
|
|
p->arg.lock_owner.id = lsp->ls_id.id;
|
|
|
p->res.lock_seqid = p->arg.lock_seqid;
|
|
|
- p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
|
|
|
p->lsp = lsp;
|
|
|
p->server = server;
|
|
|
atomic_inc(&lsp->ls_count);
|
|
@@ -4241,7 +4162,7 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request
|
|
|
if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
|
|
|
return 0;
|
|
|
err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM);
|
|
|
- if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED)
|
|
|
+ if (err != -NFS4ERR_DELAY)
|
|
|
break;
|
|
|
nfs4_handle_exception(server, err, &exception);
|
|
|
} while (exception.retry);
|
|
@@ -4266,7 +4187,6 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
|
|
|
goto out;
|
|
|
case -NFS4ERR_GRACE:
|
|
|
case -NFS4ERR_DELAY:
|
|
|
- case -EKEYEXPIRED:
|
|
|
nfs4_handle_exception(server, err, &exception);
|
|
|
err = 0;
|
|
|
}
|
|
@@ -4412,13 +4332,21 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
|
|
|
nfs4_state_mark_reclaim_nograce(server->nfs_client, state);
|
|
|
err = 0;
|
|
|
goto out;
|
|
|
+ case -EKEYEXPIRED:
|
|
|
+ /*
|
|
|
+ * User RPCSEC_GSS context has expired.
|
|
|
+ * We cannot recover this stateid now, so
|
|
|
+ * skip it and allow recovery thread to
|
|
|
+ * proceed.
|
|
|
+ */
|
|
|
+ err = 0;
|
|
|
+ goto out;
|
|
|
case -ENOMEM:
|
|
|
case -NFS4ERR_DENIED:
|
|
|
/* kill_proc(fl->fl_pid, SIGLOST, 1); */
|
|
|
err = 0;
|
|
|
goto out;
|
|
|
case -NFS4ERR_DELAY:
|
|
|
- case -EKEYEXPIRED:
|
|
|
break;
|
|
|
}
|
|
|
err = nfs4_handle_exception(server, err, &exception);
|
|
@@ -4647,7 +4575,6 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata)
|
|
|
switch (task->tk_status) {
|
|
|
case -NFS4ERR_DELAY:
|
|
|
case -NFS4ERR_GRACE:
|
|
|
- case -EKEYEXPIRED:
|
|
|
dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status);
|
|
|
rpc_delay(task, NFS4_POLL_RETRY_MIN);
|
|
|
task->tk_status = 0;
|
|
@@ -4687,7 +4614,6 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
|
|
|
};
|
|
|
int status;
|
|
|
|
|
|
- res.lr_seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
|
|
|
dprintk("--> %s\n", __func__);
|
|
|
task = rpc_run_task(&task_setup);
|
|
|
|
|
@@ -5111,7 +5037,6 @@ static int nfs41_sequence_handle_errors(struct rpc_task *task, struct nfs_client
|
|
|
{
|
|
|
switch(task->tk_status) {
|
|
|
case -NFS4ERR_DELAY:
|
|
|
- case -EKEYEXPIRED:
|
|
|
rpc_delay(task, NFS4_POLL_RETRY_MAX);
|
|
|
return -EAGAIN;
|
|
|
default:
|
|
@@ -5180,12 +5105,11 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_
|
|
|
|
|
|
if (!atomic_inc_not_zero(&clp->cl_count))
|
|
|
return ERR_PTR(-EIO);
|
|
|
- calldata = kmalloc(sizeof(*calldata), GFP_NOFS);
|
|
|
+ calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
|
|
|
if (calldata == NULL) {
|
|
|
nfs_put_client(clp);
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
}
|
|
|
- calldata->res.sr_slotid = NFS4_MAX_SLOT_TABLE;
|
|
|
msg.rpc_argp = &calldata->args;
|
|
|
msg.rpc_resp = &calldata->res;
|
|
|
calldata->clp = clp;
|
|
@@ -5254,7 +5178,6 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf
|
|
|
case -NFS4ERR_WRONG_CRED: /* What to do here? */
|
|
|
break;
|
|
|
case -NFS4ERR_DELAY:
|
|
|
- case -EKEYEXPIRED:
|
|
|
rpc_delay(task, NFS4_POLL_RETRY_MAX);
|
|
|
return -EAGAIN;
|
|
|
default:
|
|
@@ -5317,7 +5240,6 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp)
|
|
|
goto out;
|
|
|
calldata->clp = clp;
|
|
|
calldata->arg.one_fs = 0;
|
|
|
- calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
|
|
|
|
|
|
msg.rpc_argp = &calldata->arg;
|
|
|
msg.rpc_resp = &calldata->res;
|
|
@@ -5443,6 +5365,8 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
|
|
|
.unlink_setup = nfs4_proc_unlink_setup,
|
|
|
.unlink_done = nfs4_proc_unlink_done,
|
|
|
.rename = nfs4_proc_rename,
|
|
|
+ .rename_setup = nfs4_proc_rename_setup,
|
|
|
+ .rename_done = nfs4_proc_rename_done,
|
|
|
.link = nfs4_proc_link,
|
|
|
.symlink = nfs4_proc_symlink,
|
|
|
.mkdir = nfs4_proc_mkdir,
|
|
@@ -5463,6 +5387,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
|
|
|
.lock = nfs4_proc_lock,
|
|
|
.clear_acl_cache = nfs4_zap_acl_attr,
|
|
|
.close_context = nfs4_close_context,
|
|
|
+ .open_context = nfs4_atomic_open,
|
|
|
};
|
|
|
|
|
|
/*
|