Commit 4e55f94b authored by Trond Myklebust's avatar Trond Myklebust

NFSv4: use the (more efficient) NFSv2/v3-like XDR scheme for generating

CREATE RPC calls.
parent 4e7473b8
...@@ -81,76 +81,6 @@ nfs4_setup_compound(struct nfs4_compound *cp, struct nfs4_op *ops, ...@@ -81,76 +81,6 @@ nfs4_setup_compound(struct nfs4_compound *cp, struct nfs4_op *ops,
cp->server = server; cp->server = server;
} }
static void
nfs4_setup_create_dir(struct nfs4_compound *cp, struct qstr *name,
struct iattr *sattr, struct nfs4_change_info *info)
{
struct nfs4_create *create = GET_OP(cp, create);
create->cr_ftype = NF4DIR;
create->cr_namelen = name->len;
create->cr_name = name->name;
create->cr_attrs = sattr;
create->cr_cinfo = info;
OPNUM(cp) = OP_CREATE;
cp->req_nops++;
}
static void
nfs4_setup_create_symlink(struct nfs4_compound *cp, struct qstr *name,
struct qstr *linktext, struct iattr *sattr,
struct nfs4_change_info *info)
{
struct nfs4_create *create = GET_OP(cp, create);
create->cr_ftype = NF4LNK;
create->cr_textlen = linktext->len;
create->cr_text = linktext->name;
create->cr_namelen = name->len;
create->cr_name = name->name;
create->cr_attrs = sattr;
create->cr_cinfo = info;
OPNUM(cp) = OP_CREATE;
cp->req_nops++;
}
static void
nfs4_setup_create_special(struct nfs4_compound *cp, struct qstr *name,
dev_t dev, struct iattr *sattr,
struct nfs4_change_info *info)
{
int mode = sattr->ia_mode;
struct nfs4_create *create = GET_OP(cp, create);
BUG_ON(!(sattr->ia_valid & ATTR_MODE));
BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode));
if (S_ISFIFO(mode))
create->cr_ftype = NF4FIFO;
else if (S_ISBLK(mode)) {
create->cr_ftype = NF4BLK;
create->cr_specdata1 = MAJOR(dev);
create->cr_specdata2 = MINOR(dev);
}
else if (S_ISCHR(mode)) {
create->cr_ftype = NF4CHR;
create->cr_specdata1 = MAJOR(dev);
create->cr_specdata2 = MINOR(dev);
}
else
create->cr_ftype = NF4SOCK;
create->cr_namelen = name->len;
create->cr_name = name->name;
create->cr_attrs = sattr;
create->cr_cinfo = info;
OPNUM(cp) = OP_CREATE;
cp->req_nops++;
}
/* /*
* This is our standard bitmap for GETATTR requests. * This is our standard bitmap for GETATTR requests.
*/ */
...@@ -227,17 +157,6 @@ nfs4_setup_pathconf(struct nfs4_compound *cp, ...@@ -227,17 +157,6 @@ nfs4_setup_pathconf(struct nfs4_compound *cp,
NULL, NULL, pathconf); NULL, NULL, pathconf);
} }
static void
nfs4_setup_getfh(struct nfs4_compound *cp, struct nfs_fh *fhandle)
{
struct nfs4_getfh *getfh = GET_OP(cp, getfh);
getfh->gf_fhandle = fhandle;
OPNUM(cp) = OP_GETFH;
cp->req_nops++;
}
static void static void
nfs4_setup_putfh(struct nfs4_compound *cp, struct nfs_fh *fhandle) nfs4_setup_putfh(struct nfs4_compound *cp, struct nfs_fh *fhandle)
{ {
...@@ -333,20 +252,6 @@ nfs4_setup_remove(struct nfs4_compound *cp, struct qstr *name, struct nfs4_chang ...@@ -333,20 +252,6 @@ nfs4_setup_remove(struct nfs4_compound *cp, struct qstr *name, struct nfs4_chang
cp->req_nops++; cp->req_nops++;
} }
static void
nfs4_setup_restorefh(struct nfs4_compound *cp)
{
OPNUM(cp) = OP_RESTOREFH;
cp->req_nops++;
}
static void
nfs4_setup_savefh(struct nfs4_compound *cp)
{
OPNUM(cp) = OP_SAVEFH;
cp->req_nops++;
}
static void static void
renew_lease(struct nfs_server *server, unsigned long timestamp) renew_lease(struct nfs_server *server, unsigned long timestamp)
{ {
...@@ -1308,64 +1213,68 @@ static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *n ...@@ -1308,64 +1213,68 @@ static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *n
return nfs4_map_errors(status); return nfs4_map_errors(status);
} }
static int static int nfs4_proc_symlink(struct inode *dir, struct qstr *name,
nfs4_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path, struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle,
struct iattr *sattr, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
struct nfs_fattr *fattr)
{ {
struct nfs4_compound compound; struct nfs4_create_arg arg = {
struct nfs4_op ops[7]; .dir_fh = NFS_FH(dir),
struct nfs_fattr dir_attr; .server = NFS_SERVER(dir),
struct nfs4_change_info dir_cinfo; .name = name,
.attrs = sattr,
.ftype = NF4LNK,
.bitmask = nfs4_fattr_bitmap,
};
struct nfs4_create_res res = {
.server = NFS_SERVER(dir),
.fh = fhandle,
.fattr = fattr,
};
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
.rpc_argp = &arg,
.rpc_resp = &res,
};
int status; int status;
dir_attr.valid = 0; arg.u.symlink = path;
fattr->valid = 0; fattr->valid = 0;
nfs4_setup_compound(&compound, ops, NFS_SERVER(dir), "symlink"); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
nfs4_setup_putfh(&compound, NFS_FH(dir)); if (!status)
nfs4_setup_savefh(&compound); update_changeattr(dir, &res.dir_cinfo);
nfs4_setup_create_symlink(&compound, name, path, sattr, &dir_cinfo);
nfs4_setup_getattr(&compound, fattr);
nfs4_setup_getfh(&compound, fhandle);
nfs4_setup_restorefh(&compound);
nfs4_setup_getattr(&compound, &dir_attr);
status = nfs4_call_compound(&compound, NULL, 0);
if (!status) {
process_cinfo(&dir_cinfo, &dir_attr);
nfs_refresh_inode(dir, &dir_attr);
}
return nfs4_map_errors(status); return nfs4_map_errors(status);
} }
static int static int nfs4_proc_mkdir(struct inode *dir, struct qstr *name,
nfs4_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr, struct iattr *sattr, struct nfs_fh *fhandle,
struct nfs_fh *fhandle, struct nfs_fattr *fattr) struct nfs_fattr *fattr)
{ {
struct nfs4_compound compound; struct nfs4_create_arg arg = {
struct nfs4_op ops[7]; .dir_fh = NFS_FH(dir),
struct nfs_fattr dir_attr; .server = NFS_SERVER(dir),
struct nfs4_change_info dir_cinfo; .name = name,
.attrs = sattr,
.ftype = NF4DIR,
.bitmask = nfs4_fattr_bitmap,
};
struct nfs4_create_res res = {
.server = NFS_SERVER(dir),
.fh = fhandle,
.fattr = fattr,
};
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
.rpc_argp = &arg,
.rpc_resp = &res,
};
int status; int status;
dir_attr.valid = 0;
fattr->valid = 0; fattr->valid = 0;
nfs4_setup_compound(&compound, ops, NFS_SERVER(dir), "mkdir"); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
nfs4_setup_putfh(&compound, NFS_FH(dir)); if (!status)
nfs4_setup_savefh(&compound); update_changeattr(dir, &res.dir_cinfo);
nfs4_setup_create_dir(&compound, name, sattr, &dir_cinfo);
nfs4_setup_getattr(&compound, fattr);
nfs4_setup_getfh(&compound, fhandle);
nfs4_setup_restorefh(&compound);
nfs4_setup_getattr(&compound, &dir_attr);
status = nfs4_call_compound(&compound, NULL, 0);
if (!status) {
process_cinfo(&dir_cinfo, &dir_attr);
nfs_refresh_inode(dir, &dir_attr);
}
return nfs4_map_errors(status); return nfs4_map_errors(status);
} }
...@@ -1391,33 +1300,52 @@ nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, ...@@ -1391,33 +1300,52 @@ nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
return nfs4_map_errors(status); return nfs4_map_errors(status);
} }
static int static int nfs4_proc_mknod(struct inode *dir, struct qstr *name,
nfs4_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr, struct iattr *sattr, dev_t rdev, struct nfs_fh *fh,
dev_t rdev, struct nfs_fh *fh, struct nfs_fattr *fattr) struct nfs_fattr *fattr)
{ {
struct nfs4_compound compound; struct nfs4_create_arg arg = {
struct nfs4_op ops[7]; .dir_fh = NFS_FH(dir),
struct nfs_fattr dir_attr; .server = NFS_SERVER(dir),
struct nfs4_change_info dir_cinfo; .name = name,
.attrs = sattr,
.bitmask = nfs4_fattr_bitmap,
};
struct nfs4_create_res res = {
.server = NFS_SERVER(dir),
.fh = fh,
.fattr = fattr,
};
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
.rpc_argp = &arg,
.rpc_resp = &res,
};
int status; int status;
int mode = sattr->ia_mode;
dir_attr.valid = 0;
fattr->valid = 0; fattr->valid = 0;
nfs4_setup_compound(&compound, ops, NFS_SERVER(dir), "mknod");
nfs4_setup_putfh(&compound, NFS_FH(dir));
nfs4_setup_savefh(&compound);
nfs4_setup_create_special(&compound, name, rdev,sattr, &dir_cinfo);
nfs4_setup_getattr(&compound, fattr);
nfs4_setup_getfh(&compound, fh);
nfs4_setup_restorefh(&compound);
nfs4_setup_getattr(&compound, &dir_attr);
status = nfs4_call_compound(&compound, NULL, 0);
if (!status) { BUG_ON(!(sattr->ia_valid & ATTR_MODE));
process_cinfo(&dir_cinfo, &dir_attr); BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode));
nfs_refresh_inode(dir, &dir_attr); if (S_ISFIFO(mode))
arg.ftype = NF4FIFO;
else if (S_ISBLK(mode)) {
arg.ftype = NF4BLK;
arg.u.device.specdata1 = MAJOR(rdev);
arg.u.device.specdata2 = MINOR(rdev);
}
else if (S_ISCHR(mode)) {
arg.ftype = NF4CHR;
arg.u.device.specdata1 = MAJOR(rdev);
arg.u.device.specdata2 = MINOR(rdev);
} }
else
arg.ftype = NF4SOCK;
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
if (!status)
update_changeattr(dir, &res.dir_cinfo);
return nfs4_map_errors(status); return nfs4_map_errors(status);
} }
......
...@@ -83,7 +83,8 @@ static int nfs_stat_to_errno(int); ...@@ -83,7 +83,8 @@ static int nfs_stat_to_errno(int);
#define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \ #define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \
((3+NFS4_FHSIZE) >> 2)) ((3+NFS4_FHSIZE) >> 2))
#define encode_getattr_maxsz (op_encode_hdr_maxsz + 3) #define encode_getattr_maxsz (op_encode_hdr_maxsz + 3)
#define nfs4_fattr_bitmap_maxsz (26 + 2 * ((NFS4_MAXNAMLEN +1) >> 2)) #define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2))
#define nfs4_fattr_bitmap_maxsz (36 + 2 * nfs4_name_maxsz)
#define decode_getattr_maxsz (op_decode_hdr_maxsz + 3 + \ #define decode_getattr_maxsz (op_decode_hdr_maxsz + 3 + \
nfs4_fattr_bitmap_maxsz) nfs4_fattr_bitmap_maxsz)
#define encode_savefh_maxsz (op_encode_hdr_maxsz) #define encode_savefh_maxsz (op_encode_hdr_maxsz)
...@@ -112,13 +113,17 @@ static int nfs_stat_to_errno(int); ...@@ -112,13 +113,17 @@ static int nfs_stat_to_errno(int);
#define encode_lookup_maxsz (op_encode_hdr_maxsz + \ #define encode_lookup_maxsz (op_encode_hdr_maxsz + \
1 + ((3 + NFS4_FHSIZE) >> 2)) 1 + ((3 + NFS4_FHSIZE) >> 2))
#define encode_remove_maxsz (op_encode_hdr_maxsz + \ #define encode_remove_maxsz (op_encode_hdr_maxsz + \
1 + ((3 + NFS4_MAXNAMLEN) >> 2)) nfs4_name_maxsz)
#define encode_rename_maxsz (op_encode_hdr_maxsz + \ #define encode_rename_maxsz (op_encode_hdr_maxsz + \
2 * (1 + ((3 + NFS4_MAXNAMLEN) >> 2))) 2 * nfs4_name_maxsz)
#define decode_rename_maxsz (op_decode_hdr_maxsz + 5 + 5) #define decode_rename_maxsz (op_decode_hdr_maxsz + 5 + 5)
#define encode_link_maxsz (op_encode_hdr_maxsz + \ #define encode_link_maxsz (op_encode_hdr_maxsz + \
1 + ((3 + NFS4_MAXNAMLEN) >> 2)) nfs4_name_maxsz)
#define decode_link_maxsz (op_decode_hdr_maxsz + 5) #define decode_link_maxsz (op_decode_hdr_maxsz + 5)
#define encode_create_maxsz (op_encode_hdr_maxsz + \
2 + 2 * nfs4_name_maxsz + \
nfs4_fattr_bitmap_maxsz)
#define decode_create_maxsz (op_decode_hdr_maxsz + 8)
#define NFS4_enc_compound_sz (1024) /* XXX: large enough? */ #define NFS4_enc_compound_sz (1024) /* XXX: large enough? */
#define NFS4_dec_compound_sz (1024) /* XXX: large enough? */ #define NFS4_dec_compound_sz (1024) /* XXX: large enough? */
#define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \ #define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \
...@@ -304,6 +309,16 @@ static int nfs_stat_to_errno(int); ...@@ -304,6 +309,16 @@ static int nfs_stat_to_errno(int);
decode_savefh_maxsz + \ decode_savefh_maxsz + \
decode_putfh_maxsz + \ decode_putfh_maxsz + \
decode_link_maxsz) decode_link_maxsz)
#define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_create_maxsz + \
encode_getattr_maxsz + \
encode_getfh_maxsz)
#define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
decode_create_maxsz + \
decode_getattr_maxsz + \
decode_getfh_maxsz)
...@@ -370,9 +385,7 @@ encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr) ...@@ -370,9 +385,7 @@ encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
return 0; return 0;
} }
static int static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs_server *server)
encode_attrs(struct xdr_stream *xdr, struct iattr *iap,
struct nfs_server *server)
{ {
char owner_name[IDMAP_NAMESZ]; char owner_name[IDMAP_NAMESZ];
char owner_group[IDMAP_NAMESZ]; char owner_group[IDMAP_NAMESZ];
...@@ -536,38 +549,36 @@ encode_commit(struct xdr_stream *xdr, struct nfs_writeargs *args) ...@@ -536,38 +549,36 @@ encode_commit(struct xdr_stream *xdr, struct nfs_writeargs *args)
return 0; return 0;
} }
static int static int encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create)
encode_create(struct xdr_stream *xdr, struct nfs4_create *create,
struct nfs_server *server)
{ {
uint32_t *p; uint32_t *p;
RESERVE_SPACE(8); RESERVE_SPACE(8);
WRITE32(OP_CREATE); WRITE32(OP_CREATE);
WRITE32(create->cr_ftype); WRITE32(create->ftype);
switch (create->cr_ftype) { switch (create->ftype) {
case NF4LNK: case NF4LNK:
RESERVE_SPACE(4 + create->cr_textlen); RESERVE_SPACE(4 + create->u.symlink->len);
WRITE32(create->cr_textlen); WRITE32(create->u.symlink->len);
WRITEMEM(create->cr_text, create->cr_textlen); WRITEMEM(create->u.symlink->name, create->u.symlink->len);
break; break;
case NF4BLK: case NF4CHR: case NF4BLK: case NF4CHR:
RESERVE_SPACE(8); RESERVE_SPACE(8);
WRITE32(create->cr_specdata1); WRITE32(create->u.device.specdata1);
WRITE32(create->cr_specdata2); WRITE32(create->u.device.specdata2);
break; break;
default: default:
break; break;
} }
RESERVE_SPACE(4 + create->cr_namelen); RESERVE_SPACE(4 + create->name->len);
WRITE32(create->cr_namelen); WRITE32(create->name->len);
WRITEMEM(create->cr_name, create->cr_namelen); WRITEMEM(create->name->name, create->name->len);
return encode_attrs(xdr, create->cr_attrs, server); return encode_attrs(xdr, create->attrs, create->server);
} }
static int static int
...@@ -1115,15 +1126,9 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs ...@@ -1115,15 +1126,9 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
for (i = 0; i < cp->req_nops; i++) { for (i = 0; i < cp->req_nops; i++) {
switch (cp->ops[i].opnum) { switch (cp->ops[i].opnum) {
case OP_CREATE:
status = encode_create(xdr, &cp->ops[i].u.create, cp->server);
break;
case OP_GETATTR: case OP_GETATTR:
status = encode_getattr(xdr, &cp->ops[i].u.getattr); status = encode_getattr(xdr, &cp->ops[i].u.getattr);
break; break;
case OP_GETFH:
status = encode_getfh(xdr);
break;
case OP_PUTFH: case OP_PUTFH:
status = encode_putfh(xdr, cp->ops[i].u.putfh.pf_fhandle); status = encode_putfh(xdr, cp->ops[i].u.putfh.pf_fhandle);
break; break;
...@@ -1136,12 +1141,6 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs ...@@ -1136,12 +1141,6 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
case OP_REMOVE: case OP_REMOVE:
status = encode_remove(xdr, cp->ops[i].u.remove.name); status = encode_remove(xdr, cp->ops[i].u.remove.name);
break; break;
case OP_RESTOREFH:
status = encode_restorefh(xdr);
break;
case OP_SAVEFH:
status = encode_savefh(xdr);
break;
default: default:
BUG(); BUG();
} }
...@@ -1299,6 +1298,30 @@ static int nfs4_xdr_enc_link(struct rpc_rqst *req, uint32_t *p, const struct nfs ...@@ -1299,6 +1298,30 @@ static int nfs4_xdr_enc_link(struct rpc_rqst *req, uint32_t *p, const struct nfs
return status; return status;
} }
/*
* Encode CREATE request
*/
static int nfs4_xdr_enc_create(struct rpc_rqst *req, uint32_t *p, const struct nfs4_create_arg *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
.nops = 4,
};
int status;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
encode_compound_hdr(&xdr, &hdr);
if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
goto out;
if ((status = encode_create(&xdr, args)) != 0)
goto out;
if ((status = encode_getfattr(&xdr, args->bitmask)) != 0)
goto out;
status = encode_getfh(&xdr);
out:
return status;
}
/* /*
* Encode GETATTR request * Encode GETATTR request
*/ */
...@@ -2143,8 +2166,7 @@ decode_commit(struct xdr_stream *xdr, struct nfs_writeres *res) ...@@ -2143,8 +2166,7 @@ decode_commit(struct xdr_stream *xdr, struct nfs_writeres *res)
return 0; return 0;
} }
static int static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
decode_create(struct xdr_stream *xdr, struct nfs4_create *create)
{ {
uint32_t *p; uint32_t *p;
uint32_t bmlen; uint32_t bmlen;
...@@ -2153,7 +2175,7 @@ decode_create(struct xdr_stream *xdr, struct nfs4_create *create) ...@@ -2153,7 +2175,7 @@ decode_create(struct xdr_stream *xdr, struct nfs4_create *create)
status = decode_op_hdr(xdr, OP_CREATE); status = decode_op_hdr(xdr, OP_CREATE);
if (status) if (status)
return status; return status;
if ((status = decode_change_info(xdr, create->cr_cinfo))) if ((status = decode_change_info(xdr, cinfo)))
return status; return status;
READ_BUF(4); READ_BUF(4);
READ32(bmlen); READ32(bmlen);
...@@ -3000,15 +3022,9 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs ...@@ -3000,15 +3022,9 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
op = &cp->ops[0]; op = &cp->ops[0];
for (cp->nops = 0; cp->nops < cp->resp_nops; cp->nops++, op++) { for (cp->nops = 0; cp->nops < cp->resp_nops; cp->nops++, op++) {
switch (op->opnum) { switch (op->opnum) {
case OP_CREATE:
status = decode_create(xdr, &op->u.create);
break;
case OP_GETATTR: case OP_GETATTR:
status = decode_getattr(xdr, &op->u.getattr, cp->server); status = decode_getattr(xdr, &op->u.getattr, cp->server);
break; break;
case OP_GETFH:
status = decode_getfh(xdr, op->u.getfh.gf_fhandle);
break;
case OP_PUTFH: case OP_PUTFH:
status = decode_putfh(xdr); status = decode_putfh(xdr);
break; break;
...@@ -3018,15 +3034,9 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs ...@@ -3018,15 +3034,9 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
case OP_READLINK: case OP_READLINK:
status = decode_readlink(xdr, req, &op->u.readlink); status = decode_readlink(xdr, req, &op->u.readlink);
break; break;
case OP_RESTOREFH:
status = decode_restorefh(xdr);
break;
case OP_REMOVE: case OP_REMOVE:
status = decode_remove(xdr, op->u.remove.rm_cinfo); status = decode_remove(xdr, op->u.remove.rm_cinfo);
break; break;
case OP_SAVEFH:
status = decode_savefh(xdr);
break;
default: default:
BUG(); BUG();
return -EIO; return -EIO;
...@@ -3210,6 +3220,29 @@ static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_ch ...@@ -3210,6 +3220,29 @@ static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_ch
return status; return status;
} }
/*
* Decode CREATE response
*/
static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_create_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
int status;
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
goto out;
if ((status = decode_putfh(&xdr)) != 0)
goto out;
if ((status = decode_create(&xdr,&res->dir_cinfo)) != 0)
goto out;
if ((status = decode_getfattr(&xdr, res->fattr, res->server)) != 0)
goto out;
status = decode_getfh(&xdr, res->fh);
out:
return status;
}
/* /*
* Decode GETATTR response * Decode GETATTR response
*/ */
...@@ -3724,6 +3757,7 @@ struct rpc_procinfo nfs4_procedures[] = { ...@@ -3724,6 +3757,7 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC(REMOVE, enc_remove, dec_remove), PROC(REMOVE, enc_remove, dec_remove),
PROC(RENAME, enc_rename, dec_rename), PROC(RENAME, enc_rename, dec_rename),
PROC(LINK, enc_link, dec_link), PROC(LINK, enc_link, dec_link),
PROC(CREATE, enc_create, dec_create),
}; };
struct rpc_version nfs_version4 = { struct rpc_version nfs_version4 = {
......
...@@ -310,6 +310,7 @@ enum { ...@@ -310,6 +310,7 @@ enum {
NFSPROC4_CLNT_REMOVE, NFSPROC4_CLNT_REMOVE,
NFSPROC4_CLNT_RENAME, NFSPROC4_CLNT_RENAME,
NFSPROC4_CLNT_LINK, NFSPROC4_CLNT_LINK,
NFSPROC4_CLNT_CREATE,
}; };
#endif #endif
......
...@@ -501,23 +501,30 @@ struct nfs4_close { ...@@ -501,23 +501,30 @@ struct nfs4_close {
u32 cl_seqid; /* request */ u32 cl_seqid; /* request */
}; };
struct nfs4_create { struct nfs4_create_arg {
u32 cr_ftype; /* request */ u32 ftype;
union { /* request */ union {
struct { struct qstr * symlink; /* NF4LNK */
u32 textlen;
const char * text;
} symlink; /* NF4LNK */
struct { struct {
u32 specdata1; u32 specdata1;
u32 specdata2; u32 specdata2;
} device; /* NF4BLK, NF4CHR */ } device; /* NF4BLK, NF4CHR */
} u; } u;
u32 cr_namelen; /* request */ const struct qstr * name;
const char * cr_name; /* request */ const struct nfs_server * server;
struct iattr * cr_attrs; /* request */ const struct iattr * attrs;
struct nfs4_change_info * cr_cinfo; /* response */ const struct nfs_fh * dir_fh;
const u32 * bitmask;
}; };
struct nfs4_create_res {
const struct nfs_server * server;
struct nfs_fh * fh;
struct nfs_fattr * fattr;
struct nfs4_change_info dir_cinfo;
};
#define cr_textlen u.symlink.textlen #define cr_textlen u.symlink.textlen
#define cr_text u.symlink.text #define cr_text u.symlink.text
#define cr_specdata1 u.device.specdata1 #define cr_specdata1 u.device.specdata1
...@@ -540,10 +547,6 @@ struct nfs4_getattr_res { ...@@ -540,10 +547,6 @@ struct nfs4_getattr_res {
struct nfs_fattr * fattr; struct nfs_fattr * fattr;
}; };
struct nfs4_getfh {
struct nfs_fh * gf_fhandle; /* response */
};
struct nfs4_link_arg { struct nfs4_link_arg {
const struct nfs_fh * fh; const struct nfs_fh * fh;
const struct nfs_fh * dir_fh; const struct nfs_fh * dir_fh;
...@@ -647,9 +650,7 @@ struct nfs4_op { ...@@ -647,9 +650,7 @@ struct nfs4_op {
u32 opnum; u32 opnum;
union { union {
struct nfs4_close close; struct nfs4_close close;
struct nfs4_create create;
struct nfs4_getattr getattr; struct nfs4_getattr getattr;
struct nfs4_getfh getfh;
struct nfs4_open open; struct nfs4_open open;
struct nfs4_open_confirm open_confirm; struct nfs4_open_confirm open_confirm;
struct nfs4_putfh putfh; struct nfs4_putfh putfh;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment