NFS: Introduce struct nfs_removeargs+nfs_removeres

We need a common structure for setting up an unlink() rpc call in order to
fix the asynchronous unlink code.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
Trond Myklebust 2007-07-14 15:39:57 -04:00
parent 3062c532ad
commit 4fdc17b2a7
7 changed files with 99 additions and 64 deletions

View File

@ -43,6 +43,7 @@
#define NFS_entry_sz (NFS_filename_sz+3) #define NFS_entry_sz (NFS_filename_sz+3)
#define NFS_diropargs_sz (NFS_fhandle_sz+NFS_filename_sz) #define NFS_diropargs_sz (NFS_fhandle_sz+NFS_filename_sz)
#define NFS_removeargs_sz (NFS_fhandle_sz+NFS_filename_sz)
#define NFS_sattrargs_sz (NFS_fhandle_sz+NFS_sattr_sz) #define NFS_sattrargs_sz (NFS_fhandle_sz+NFS_sattr_sz)
#define NFS_readlinkargs_sz (NFS_fhandle_sz) #define NFS_readlinkargs_sz (NFS_fhandle_sz)
#define NFS_readargs_sz (NFS_fhandle_sz+3) #define NFS_readargs_sz (NFS_fhandle_sz+3)
@ -66,7 +67,7 @@
* Common NFS XDR functions as inlines * Common NFS XDR functions as inlines
*/ */
static inline __be32 * static inline __be32 *
xdr_encode_fhandle(__be32 *p, struct nfs_fh *fhandle) xdr_encode_fhandle(__be32 *p, const struct nfs_fh *fhandle)
{ {
memcpy(p, fhandle->data, NFS2_FHSIZE); memcpy(p, fhandle->data, NFS2_FHSIZE);
return p + XDR_QUADLEN(NFS2_FHSIZE); return p + XDR_QUADLEN(NFS2_FHSIZE);
@ -204,7 +205,7 @@ nfs_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs_sattrargs *args)
/* /*
* Encode directory ops argument * Encode directory ops argument
* LOOKUP, REMOVE, RMDIR * LOOKUP, RMDIR
*/ */
static int static int
nfs_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs_diropargs *args) nfs_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs_diropargs *args)
@ -215,6 +216,18 @@ nfs_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs_diropargs *args)
return 0; return 0;
} }
/*
* Encode REMOVE argument
*/
static int
nfs_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
{
p = xdr_encode_fhandle(p, args->fh);
p = xdr_encode_array(p, args->name.name, args->name.len);
req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
return 0;
}
/* /*
* Arguments to a READ call. Since we read data directly into the page * Arguments to a READ call. Since we read data directly into the page
* cache, we also set up the reply iovec here so that iov[1] points * cache, we also set up the reply iovec here so that iov[1] points
@ -705,7 +718,7 @@ struct rpc_procinfo nfs_procedures[] = {
PROC(READ, readargs, readres, 3), PROC(READ, readargs, readres, 3),
PROC(WRITE, writeargs, writeres, 4), PROC(WRITE, writeargs, writeres, 4),
PROC(CREATE, createargs, diropres, 0), PROC(CREATE, createargs, diropres, 0),
PROC(REMOVE, diropargs, stat, 0), PROC(REMOVE, removeargs, stat, 0),
PROC(RENAME, renameargs, stat, 0), PROC(RENAME, renameargs, stat, 0),
PROC(LINK, linkargs, stat, 0), PROC(LINK, linkargs, stat, 0),
PROC(SYMLINK, symlinkargs, stat, 0), PROC(SYMLINK, symlinkargs, stat, 0),

View File

@ -349,23 +349,23 @@ out:
static int static int
nfs3_proc_remove(struct inode *dir, struct qstr *name) nfs3_proc_remove(struct inode *dir, struct qstr *name)
{ {
struct nfs_fattr dir_attr; struct nfs_removeargs arg = {
struct nfs3_diropargs arg = { .fh = NFS_FH(dir),
.fh = NFS_FH(dir), .name.len = name->len,
.name = name->name, .name.name = name->name,
.len = name->len
}; };
struct rpc_message msg = { struct nfs_removeres res;
.rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE], struct rpc_message msg = {
.rpc_argp = &arg, .rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE],
.rpc_resp = &dir_attr, .rpc_argp = &arg,
.rpc_resp = &res,
}; };
int status; int status;
dprintk("NFS call remove %s\n", name->name); dprintk("NFS call remove %s\n", name->name);
nfs_fattr_init(&dir_attr); nfs_fattr_init(&res.dir_attr);
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
nfs_post_op_update_inode(dir, &dir_attr); nfs_post_op_update_inode(dir, &res.dir_attr);
dprintk("NFS reply remove: %d\n", status); dprintk("NFS reply remove: %d\n", status);
return status; return status;
} }
@ -374,17 +374,17 @@ static int
nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *name) nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *name)
{ {
struct unlinkxdr { struct unlinkxdr {
struct nfs3_diropargs arg; struct nfs_removeargs arg;
struct nfs_fattr res; struct nfs_removeres res;
} *ptr; } *ptr;
ptr = kmalloc(sizeof(*ptr), GFP_KERNEL); ptr = kmalloc(sizeof(*ptr), GFP_KERNEL);
if (!ptr) if (!ptr)
return -ENOMEM; return -ENOMEM;
ptr->arg.fh = NFS_FH(dir->d_inode); ptr->arg.fh = NFS_FH(dir->d_inode);
ptr->arg.name = name->name; ptr->arg.name.name = name->name;
ptr->arg.len = name->len; ptr->arg.name.len = name->len;
nfs_fattr_init(&ptr->res); nfs_fattr_init(&ptr->res.dir_attr);
msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE]; msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE];
msg->rpc_argp = &ptr->arg; msg->rpc_argp = &ptr->arg;
msg->rpc_resp = &ptr->res; msg->rpc_resp = &ptr->res;
@ -400,7 +400,7 @@ nfs3_proc_unlink_done(struct dentry *dir, struct rpc_task *task)
if (nfs3_async_handle_jukebox(task, dir->d_inode)) if (nfs3_async_handle_jukebox(task, dir->d_inode))
return 1; return 1;
if (msg->rpc_argp) { if (msg->rpc_argp) {
dir_attr = (struct nfs_fattr*)msg->rpc_resp; dir_attr = &((struct nfs_removeres*)msg->rpc_resp)->dir_attr;
nfs_post_op_update_inode(dir->d_inode, dir_attr); nfs_post_op_update_inode(dir->d_inode, dir_attr);
kfree(msg->rpc_argp); kfree(msg->rpc_argp);
} }

View File

@ -50,6 +50,7 @@
#define NFS3_sattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3) #define NFS3_sattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3)
#define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz) #define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz)
#define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz)
#define NFS3_accessargs_sz (NFS3_fh_sz+1) #define NFS3_accessargs_sz (NFS3_fh_sz+1)
#define NFS3_readlinkargs_sz (NFS3_fh_sz) #define NFS3_readlinkargs_sz (NFS3_fh_sz)
#define NFS3_readargs_sz (NFS3_fh_sz+3) #define NFS3_readargs_sz (NFS3_fh_sz+3)
@ -65,6 +66,7 @@
#define NFS3_attrstat_sz (1+NFS3_fattr_sz) #define NFS3_attrstat_sz (1+NFS3_fattr_sz)
#define NFS3_wccstat_sz (1+NFS3_wcc_data_sz) #define NFS3_wccstat_sz (1+NFS3_wcc_data_sz)
#define NFS3_removeres_sz (NFS3_wccstat_sz)
#define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz)) #define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
#define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1) #define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1)
#define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1) #define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1)
@ -106,7 +108,7 @@ static struct {
* Common NFS XDR functions as inlines * Common NFS XDR functions as inlines
*/ */
static inline __be32 * static inline __be32 *
xdr_encode_fhandle(__be32 *p, struct nfs_fh *fh) xdr_encode_fhandle(__be32 *p, const struct nfs_fh *fh)
{ {
return xdr_encode_array(p, fh->data, fh->size); return xdr_encode_array(p, fh->data, fh->size);
} }
@ -299,6 +301,18 @@ nfs3_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs3_diropargs *args)
return 0; return 0;
} }
/*
* Encode REMOVE argument
*/
static int
nfs3_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
{
p = xdr_encode_fhandle(p, args->fh);
p = xdr_encode_array(p, args->name.name, args->name.len);
req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
return 0;
}
/* /*
* Encode access() argument * Encode access() argument
*/ */
@ -736,6 +750,12 @@ nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
return status; return status;
} }
static int
nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res)
{
return nfs3_xdr_wccstat(req, p, &res->dir_attr);
}
/* /*
* Decode LOOKUP reply * Decode LOOKUP reply
*/ */
@ -1126,7 +1146,7 @@ struct rpc_procinfo nfs3_procedures[] = {
PROC(MKDIR, mkdirargs, createres, 0), PROC(MKDIR, mkdirargs, createres, 0),
PROC(SYMLINK, symlinkargs, createres, 0), PROC(SYMLINK, symlinkargs, createres, 0),
PROC(MKNOD, mknodargs, createres, 0), PROC(MKNOD, mknodargs, createres, 0),
PROC(REMOVE, diropargs, wccstat, 0), PROC(REMOVE, removeargs, removeres, 0),
PROC(RMDIR, diropargs, wccstat, 0), PROC(RMDIR, diropargs, wccstat, 0),
PROC(RENAME, renameargs, renameres, 0), PROC(RENAME, renameargs, renameres, 0),
PROC(LINK, linkargs, linkres, 0), PROC(LINK, linkargs, linkres, 0),

View File

@ -1925,28 +1925,27 @@ out:
static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
{ {
struct nfs_server *server = NFS_SERVER(dir); struct nfs_server *server = NFS_SERVER(dir);
struct nfs4_remove_arg args = { struct nfs_removeargs args = {
.fh = NFS_FH(dir), .fh = NFS_FH(dir),
.name = name, .name.len = name->len,
.name.name = name->name,
.bitmask = server->attr_bitmask, .bitmask = server->attr_bitmask,
}; };
struct nfs_fattr dir_attr; struct nfs_removeres res = {
struct nfs4_remove_res res = {
.server = server, .server = server,
.dir_attr = &dir_attr,
}; };
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE], .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE],
.rpc_argp = &args, .rpc_argp = &args,
.rpc_resp = &res, .rpc_resp = &res,
}; };
int status; int status;
nfs_fattr_init(res.dir_attr); nfs_fattr_init(&res.dir_attr);
status = rpc_call_sync(server->client, &msg, 0); status = rpc_call_sync(server->client, &msg, 0);
if (status == 0) { if (status == 0) {
update_changeattr(dir, &res.cinfo); update_changeattr(dir, &res.cinfo);
nfs_post_op_update_inode(dir, res.dir_attr); nfs_post_op_update_inode(dir, &res.dir_attr);
} }
return status; return status;
} }
@ -1964,9 +1963,8 @@ static int nfs4_proc_remove(struct inode *dir, struct qstr *name)
} }
struct unlink_desc { struct unlink_desc {
struct nfs4_remove_arg args; struct nfs_removeargs args;
struct nfs4_remove_res res; struct nfs_removeres res;
struct nfs_fattr dir_attr;
}; };
static int nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, static int nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir,
@ -1980,10 +1978,11 @@ static int nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir,
return -ENOMEM; return -ENOMEM;
up->args.fh = NFS_FH(dir->d_inode); up->args.fh = NFS_FH(dir->d_inode);
up->args.name = name; up->args.name.len = name->len;
up->args.name.name = name->name;
up->args.bitmask = server->attr_bitmask; up->args.bitmask = server->attr_bitmask;
up->res.server = server; up->res.server = server;
up->res.dir_attr = &up->dir_attr; nfs_fattr_init(&up->res.dir_attr);
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
msg->rpc_argp = &up->args; msg->rpc_argp = &up->args;
@ -1999,7 +1998,7 @@ static int nfs4_proc_unlink_done(struct dentry *dir, struct rpc_task *task)
if (msg->rpc_resp != NULL) { if (msg->rpc_resp != NULL) {
up = container_of(msg->rpc_resp, struct unlink_desc, res); up = container_of(msg->rpc_resp, struct unlink_desc, res);
update_changeattr(dir->d_inode, &up->res.cinfo); update_changeattr(dir->d_inode, &up->res.cinfo);
nfs_post_op_update_inode(dir->d_inode, up->res.dir_attr); nfs_post_op_update_inode(dir->d_inode, &up->res.dir_attr);
kfree(up); kfree(up);
msg->rpc_resp = NULL; msg->rpc_resp = NULL;
msg->rpc_argp = NULL; msg->rpc_argp = NULL;

View File

@ -1435,7 +1435,7 @@ out:
/* /*
* Encode REMOVE request * Encode REMOVE request
*/ */
static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs4_remove_arg *args) static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
{ {
struct xdr_stream xdr; struct xdr_stream xdr;
struct compound_hdr hdr = { struct compound_hdr hdr = {
@ -1447,7 +1447,7 @@ static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs
encode_compound_hdr(&xdr, &hdr); encode_compound_hdr(&xdr, &hdr);
if ((status = encode_putfh(&xdr, args->fh)) != 0) if ((status = encode_putfh(&xdr, args->fh)) != 0)
goto out; goto out;
if ((status = encode_remove(&xdr, args->name)) != 0) if ((status = encode_remove(&xdr, &args->name)) != 0)
goto out; goto out;
status = encode_getfattr(&xdr, args->bitmask); status = encode_getfattr(&xdr, args->bitmask);
out: out:
@ -3835,7 +3835,7 @@ out:
/* /*
* Decode REMOVE response * Decode REMOVE response
*/ */
static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_remove_res *res) static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p, struct nfs_removeres *res)
{ {
struct xdr_stream xdr; struct xdr_stream xdr;
struct compound_hdr hdr; struct compound_hdr hdr;
@ -3848,7 +3848,7 @@ static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_re
goto out; goto out;
if ((status = decode_remove(&xdr, &res->cinfo)) != 0) if ((status = decode_remove(&xdr, &res->cinfo)) != 0)
goto out; goto out;
decode_getfattr(&xdr, res->dir_attr, res->server); decode_getfattr(&xdr, &res->dir_attr, res->server);
out: out:
return status; return status;
} }

View File

@ -272,14 +272,14 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
static int static int
nfs_proc_remove(struct inode *dir, struct qstr *name) nfs_proc_remove(struct inode *dir, struct qstr *name)
{ {
struct nfs_diropargs arg = { struct nfs_removeargs arg = {
.fh = NFS_FH(dir), .fh = NFS_FH(dir),
.name = name->name, .name.len = name->len,
.len = name->len .name.name = name->name,
}; };
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs_procedures[NFSPROC_REMOVE], .rpc_proc = &nfs_procedures[NFSPROC_REMOVE],
.rpc_argp = &arg, .rpc_argp = &arg,
}; };
int status; int status;
@ -294,14 +294,14 @@ nfs_proc_remove(struct inode *dir, struct qstr *name)
static int static int
nfs_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *name) nfs_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *name)
{ {
struct nfs_diropargs *arg; struct nfs_removeargs *arg;
arg = kmalloc(sizeof(*arg), GFP_KERNEL); arg = kmalloc(sizeof(*arg), GFP_KERNEL);
if (!arg) if (!arg)
return -ENOMEM; return -ENOMEM;
arg->fh = NFS_FH(dir->d_inode); arg->fh = NFS_FH(dir->d_inode);
arg->name = name->name; arg->name.name = name->name;
arg->len = name->len; arg->name.len = name->len;
msg->rpc_proc = &nfs_procedures[NFSPROC_REMOVE]; msg->rpc_proc = &nfs_procedures[NFSPROC_REMOVE];
msg->rpc_argp = arg; msg->rpc_argp = arg;
return 0; return 0;

View File

@ -277,6 +277,21 @@ struct nfs_writeres {
const struct nfs_server *server; const struct nfs_server *server;
}; };
/*
* Common arguments to the unlink call
*/
struct nfs_removeargs {
const struct nfs_fh *fh;
struct qstr name;
const u32 * bitmask;
};
struct nfs_removeres {
const struct nfs_server *server;
struct nfs4_change_info cinfo;
struct nfs_fattr dir_attr;
};
/* /*
* Argument struct for decode_entry function * Argument struct for decode_entry function
*/ */
@ -631,18 +646,6 @@ struct nfs4_readlink {
struct page ** pages; /* zero-copy data */ struct page ** pages; /* zero-copy data */
}; };
struct nfs4_remove_arg {
const struct nfs_fh * fh;
const struct qstr * name;
const u32 * bitmask;
};
struct nfs4_remove_res {
const struct nfs_server * server;
struct nfs4_change_info cinfo;
struct nfs_fattr * dir_attr;
};
struct nfs4_rename_arg { struct nfs4_rename_arg {
const struct nfs_fh * old_dir; const struct nfs_fh * old_dir;
const struct nfs_fh * new_dir; const struct nfs_fh * new_dir;