fs/nfs/nfs4proc.c | 250 +++++++++++++++++------------------------------- fs/nfs/nfs4xdr.c | 130 +++++++++++++++--------- include/linux/nfs4.h | 1 include/linux/nfs_xdr.h | 35 +++--- 4 files changed, 190 insertions(+), 226 deletions(-) diff -u --recursive --new-file --show-c-function linux-2.6.5-21-decompoundify_link/fs/nfs/nfs4proc.c linux-2.6.5-22-decompoundify_create/fs/nfs/nfs4proc.c --- linux-2.6.5-21-decompoundify_link/fs/nfs/nfs4proc.c 2004-03-24 00:48:24.000000000 -0500 +++ linux-2.6.5-22-decompoundify_create/fs/nfs/nfs4proc.c 2004-03-24 00:48:32.000000000 -0500 @@ -81,76 +81,6 @@ nfs4_setup_compound(struct nfs4_compound 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. */ @@ -228,17 +158,6 @@ nfs4_setup_pathconf(struct nfs4_compound } 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 nfs4_setup_putfh(struct nfs4_compound *cp, struct nfs_fh *fhandle) { struct nfs4_putfh *putfh = GET_OP(cp, putfh); @@ -334,20 +253,6 @@ nfs4_setup_remove(struct nfs4_compound * } 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 renew_lease(struct nfs_server *server, unsigned long timestamp) { struct nfs4_client *clp = server->nfs4_state; @@ -1308,64 +1213,68 @@ static int nfs4_proc_link(struct inode * return nfs4_map_errors(status); } -static int -nfs4_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path, - struct iattr *sattr, struct nfs_fh *fhandle, - struct nfs_fattr *fattr) +static int nfs4_proc_symlink(struct inode *dir, struct qstr *name, + struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle, + struct nfs_fattr *fattr) { - struct nfs4_compound compound; - struct nfs4_op ops[7]; - struct nfs_fattr dir_attr; - struct nfs4_change_info dir_cinfo; + struct nfs4_create_arg arg = { + .dir_fh = NFS_FH(dir), + .server = NFS_SERVER(dir), + .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; - dir_attr.valid = 0; + arg.u.symlink = path; fattr->valid = 0; - nfs4_setup_compound(&compound, ops, NFS_SERVER(dir), "symlink"); - nfs4_setup_putfh(&compound, NFS_FH(dir)); - nfs4_setup_savefh(&compound); - 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); - } + status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); + if (!status) + update_changeattr(dir, &res.dir_cinfo); return nfs4_map_errors(status); } -static int -nfs4_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr, - struct nfs_fh *fhandle, struct nfs_fattr *fattr) +static int nfs4_proc_mkdir(struct inode *dir, struct qstr *name, + struct iattr *sattr, struct nfs_fh *fhandle, + struct nfs_fattr *fattr) { - struct nfs4_compound compound; - struct nfs4_op ops[7]; - struct nfs_fattr dir_attr; - struct nfs4_change_info dir_cinfo; + struct nfs4_create_arg arg = { + .dir_fh = NFS_FH(dir), + .server = NFS_SERVER(dir), + .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; - dir_attr.valid = 0; fattr->valid = 0; - nfs4_setup_compound(&compound, ops, NFS_SERVER(dir), "mkdir"); - nfs4_setup_putfh(&compound, NFS_FH(dir)); - nfs4_setup_savefh(&compound); - 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); - } + status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); + if (!status) + update_changeattr(dir, &res.dir_cinfo); return nfs4_map_errors(status); } @@ -1391,33 +1300,52 @@ nfs4_proc_readdir(struct dentry *dentry, return nfs4_map_errors(status); } -static int -nfs4_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr, - dev_t rdev, struct nfs_fh *fh, struct nfs_fattr *fattr) +static int nfs4_proc_mknod(struct inode *dir, struct qstr *name, + struct iattr *sattr, dev_t rdev, struct nfs_fh *fh, + struct nfs_fattr *fattr) { - struct nfs4_compound compound; - struct nfs4_op ops[7]; - struct nfs_fattr dir_attr; - struct nfs4_change_info dir_cinfo; + struct nfs4_create_arg arg = { + .dir_fh = NFS_FH(dir), + .server = NFS_SERVER(dir), + .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 mode = sattr->ia_mode; - dir_attr.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) { - process_cinfo(&dir_cinfo, &dir_attr); - nfs_refresh_inode(dir, &dir_attr); + 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)) + 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); } diff -u --recursive --new-file --show-c-function linux-2.6.5-21-decompoundify_link/fs/nfs/nfs4xdr.c linux-2.6.5-22-decompoundify_create/fs/nfs/nfs4xdr.c --- linux-2.6.5-21-decompoundify_link/fs/nfs/nfs4xdr.c 2004-03-24 00:48:24.000000000 -0500 +++ linux-2.6.5-22-decompoundify_create/fs/nfs/nfs4xdr.c 2004-03-24 00:48:32.000000000 -0500 @@ -83,7 +83,8 @@ static int nfs_stat_to_errno(int); #define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \ ((3+NFS4_FHSIZE) >> 2)) #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 + \ nfs4_fattr_bitmap_maxsz) #define encode_savefh_maxsz (op_encode_hdr_maxsz) @@ -112,13 +113,17 @@ static int nfs_stat_to_errno(int); #define encode_lookup_maxsz (op_encode_hdr_maxsz + \ 1 + ((3 + NFS4_FHSIZE) >> 2)) #define encode_remove_maxsz (op_encode_hdr_maxsz + \ - 1 + ((3 + NFS4_MAXNAMLEN) >> 2)) + nfs4_name_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 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 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_dec_compound_sz (1024) /* XXX: large enough? */ #define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \ @@ -304,6 +309,16 @@ static int nfs_stat_to_errno(int); decode_savefh_maxsz + \ decode_putfh_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 *x return 0; } -static int -encode_attrs(struct xdr_stream *xdr, struct iattr *iap, - struct nfs_server *server) +static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs_server *server) { char owner_name[IDMAP_NAMESZ]; char owner_group[IDMAP_NAMESZ]; @@ -536,38 +549,36 @@ encode_commit(struct xdr_stream *xdr, st return 0; } -static int -encode_create(struct xdr_stream *xdr, struct nfs4_create *create, - struct nfs_server *server) +static int encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create) { uint32_t *p; RESERVE_SPACE(8); WRITE32(OP_CREATE); - WRITE32(create->cr_ftype); + WRITE32(create->ftype); - switch (create->cr_ftype) { + switch (create->ftype) { case NF4LNK: - RESERVE_SPACE(4 + create->cr_textlen); - WRITE32(create->cr_textlen); - WRITEMEM(create->cr_text, create->cr_textlen); + RESERVE_SPACE(4 + create->u.symlink->len); + WRITE32(create->u.symlink->len); + WRITEMEM(create->u.symlink->name, create->u.symlink->len); break; case NF4BLK: case NF4CHR: RESERVE_SPACE(8); - WRITE32(create->cr_specdata1); - WRITE32(create->cr_specdata2); + WRITE32(create->u.device.specdata1); + WRITE32(create->u.device.specdata2); break; default: break; } - RESERVE_SPACE(4 + create->cr_namelen); - WRITE32(create->cr_namelen); - WRITEMEM(create->cr_name, create->cr_namelen); + RESERVE_SPACE(4 + create->name->len); + WRITE32(create->name->len); + 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 @@ -1115,15 +1126,9 @@ encode_compound(struct xdr_stream *xdr, for (i = 0; i < cp->req_nops; i++) { switch (cp->ops[i].opnum) { - case OP_CREATE: - status = encode_create(xdr, &cp->ops[i].u.create, cp->server); - break; case OP_GETATTR: status = encode_getattr(xdr, &cp->ops[i].u.getattr); break; - case OP_GETFH: - status = encode_getfh(xdr); - break; case OP_PUTFH: status = encode_putfh(xdr, cp->ops[i].u.putfh.pf_fhandle); break; @@ -1136,12 +1141,6 @@ encode_compound(struct xdr_stream *xdr, case OP_REMOVE: status = encode_remove(xdr, cp->ops[i].u.remove.name); break; - case OP_RESTOREFH: - status = encode_restorefh(xdr); - break; - case OP_SAVEFH: - status = encode_savefh(xdr); - break; default: BUG(); } @@ -1300,6 +1299,30 @@ out: } /* + * 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 */ static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, uint32_t *p, const struct nfs4_getattr_arg *args) @@ -2147,8 +2170,7 @@ decode_commit(struct xdr_stream *xdr, st return 0; } -static int -decode_create(struct xdr_stream *xdr, struct nfs4_create *create) +static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) { uint32_t *p; uint32_t bmlen; @@ -2157,7 +2179,7 @@ decode_create(struct xdr_stream *xdr, st status = decode_op_hdr(xdr, OP_CREATE); if (status) return status; - if ((status = decode_change_info(xdr, create->cr_cinfo))) + if ((status = decode_change_info(xdr, cinfo))) return status; READ_BUF(4); READ32(bmlen); @@ -3004,15 +3026,9 @@ decode_compound(struct xdr_stream *xdr, op = &cp->ops[0]; for (cp->nops = 0; cp->nops < cp->resp_nops; cp->nops++, op++) { switch (op->opnum) { - case OP_CREATE: - status = decode_create(xdr, &op->u.create); - break; case OP_GETATTR: status = decode_getattr(xdr, &op->u.getattr, cp->server); break; - case OP_GETFH: - status = decode_getfh(xdr, op->u.getfh.gf_fhandle); - break; case OP_PUTFH: status = decode_putfh(xdr); break; @@ -3022,15 +3038,9 @@ decode_compound(struct xdr_stream *xdr, case OP_READLINK: status = decode_readlink(xdr, req, &op->u.readlink); break; - case OP_RESTOREFH: - status = decode_restorefh(xdr); - break; case OP_REMOVE: status = decode_remove(xdr, op->u.remove.rm_cinfo); break; - case OP_SAVEFH: - status = decode_savefh(xdr); - break; default: BUG(); return -EIO; @@ -3215,6 +3225,29 @@ out: } /* + * 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 */ static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_getattr_res *res) @@ -3728,6 +3761,7 @@ struct rpc_procinfo nfs4_procedures[] = PROC(REMOVE, enc_remove, dec_remove), PROC(RENAME, enc_rename, dec_rename), PROC(LINK, enc_link, dec_link), + PROC(CREATE, enc_create, dec_create), }; struct rpc_version nfs_version4 = { diff -u --recursive --new-file --show-c-function linux-2.6.5-21-decompoundify_link/include/linux/nfs4.h linux-2.6.5-22-decompoundify_create/include/linux/nfs4.h --- linux-2.6.5-21-decompoundify_link/include/linux/nfs4.h 2004-03-24 00:48:24.000000000 -0500 +++ linux-2.6.5-22-decompoundify_create/include/linux/nfs4.h 2004-03-24 00:48:32.000000000 -0500 @@ -310,6 +310,7 @@ enum { NFSPROC4_CLNT_REMOVE, NFSPROC4_CLNT_RENAME, NFSPROC4_CLNT_LINK, + NFSPROC4_CLNT_CREATE, }; #endif diff -u --recursive --new-file --show-c-function linux-2.6.5-21-decompoundify_link/include/linux/nfs_xdr.h linux-2.6.5-22-decompoundify_create/include/linux/nfs_xdr.h --- linux-2.6.5-21-decompoundify_link/include/linux/nfs_xdr.h 2004-03-24 00:48:24.000000000 -0500 +++ linux-2.6.5-22-decompoundify_create/include/linux/nfs_xdr.h 2004-03-24 00:48:32.000000000 -0500 @@ -501,23 +501,30 @@ struct nfs4_close { u32 cl_seqid; /* request */ }; -struct nfs4_create { - u32 cr_ftype; /* request */ - union { /* request */ - struct { - u32 textlen; - const char * text; - } symlink; /* NF4LNK */ +struct nfs4_create_arg { + u32 ftype; + union { + struct qstr * symlink; /* NF4LNK */ struct { u32 specdata1; u32 specdata2; } device; /* NF4BLK, NF4CHR */ } u; - u32 cr_namelen; /* request */ - const char * cr_name; /* request */ - struct iattr * cr_attrs; /* request */ - struct nfs4_change_info * cr_cinfo; /* response */ + const struct qstr * name; + const struct nfs_server * server; + const struct iattr * attrs; + 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_text u.symlink.text #define cr_specdata1 u.device.specdata1 @@ -540,10 +547,6 @@ struct nfs4_getattr_res { struct nfs_fattr * fattr; }; -struct nfs4_getfh { - struct nfs_fh * gf_fhandle; /* response */ -}; - struct nfs4_link_arg { const struct nfs_fh * fh; const struct nfs_fh * dir_fh; @@ -647,9 +650,7 @@ struct nfs4_op { u32 opnum; union { struct nfs4_close close; - struct nfs4_create create; struct nfs4_getattr getattr; - struct nfs4_getfh getfh; struct nfs4_open open; struct nfs4_open_confirm open_confirm; struct nfs4_putfh putfh;