diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index d3675dbbcdaf91079430ed41bcd3d847cd696750..3c168164e6cbbe81aec40487e96e06531dfa9637 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -956,30 +956,31 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, return status; } -static int -nfs4_proc_lookup(struct inode *dir, struct qstr *name, - struct nfs_fh *fhandle, struct nfs_fattr *fattr) +static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, + struct nfs_fh *fhandle, struct nfs_fattr *fattr) { - struct nfs4_compound compound; - struct nfs4_op ops[5]; - struct nfs_fattr dir_attr; - int status; - - dir_attr.valid = 0; + int status; + struct nfs4_lookup_arg args = { + .bitmask = nfs4_fattr_bitmap, + .dir_fh = NFS_FH(dir), + .name = name, + }; + struct nfs4_lookup_res res = { + .server = NFS_SERVER(dir), + .fattr = fattr, + .fh = fhandle, + }; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP], + .rpc_argp = &args, + .rpc_resp = &res, + }; + fattr->valid = 0; dprintk("NFS call lookup %s\n", name->name); - nfs4_setup_compound(&compound, ops, NFS_SERVER(dir), "lookup"); - nfs4_setup_putfh(&compound, NFS_FH(dir)); - nfs4_setup_getattr(&compound, &dir_attr); - nfs4_setup_lookup(&compound, name); - nfs4_setup_getattr(&compound, fattr); - nfs4_setup_getfh(&compound, fhandle); - status = nfs4_call_compound(&compound, NULL, 0); + status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); dprintk("NFS reply lookup: %d\n", status); - - if (status >= 0) - status = nfs_refresh_inode(dir, &dir_attr); return nfs4_map_errors(status); } diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 5baa7cb627e0a668007c94797faef6138cb1d5e5..c707a4ad1267d297b218cc54a6831072bb79fde7 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -81,7 +81,7 @@ static int nfs_stat_to_errno(int); #define decode_putrootfh_maxsz (op_decode_hdr_maxsz) #define encode_getfh_maxsz (op_encode_hdr_maxsz) #define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \ - (NFS4_FHSIZE >> 2)) + ((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 decode_getattr_maxsz (op_decode_hdr_maxsz + 3 + \ @@ -109,7 +109,8 @@ static int nfs_stat_to_errno(int); 3 + (NFS4_VERIFIER_SIZE >> 2)) #define decode_setclientid_confirm_maxsz \ (op_decode_hdr_maxsz) - +#define encode_lookup_maxsz (op_encode_hdr_maxsz + \ + 1 + ((3 + NFS4_FHSIZE) >> 2)) #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 + \ @@ -251,6 +252,16 @@ static int nfs_stat_to_errno(int); #define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \ decode_putfh_maxsz + \ decode_getattr_maxsz) +#define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \ + encode_putfh_maxsz + \ + encode_lookup_maxsz + \ + encode_getattr_maxsz + \ + encode_getfh_maxsz) +#define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \ + decode_putfh_maxsz + \ + op_decode_hdr_maxsz + \ + decode_getattr_maxsz + \ + decode_getfh_maxsz) @@ -665,16 +676,15 @@ encode_locku(struct xdr_stream *xdr, struct nfs_lockargs *arg) return 0; } -static int -encode_lookup(struct xdr_stream *xdr, struct nfs4_lookup *lookup) +static int encode_lookup(struct xdr_stream *xdr, const struct qstr *name) { - int len = lookup->lo_name->len; + int len = name->len; uint32_t *p; RESERVE_SPACE(8 + len); WRITE32(OP_LOOKUP); WRITE32(len); - WRITEMEM(lookup->lo_name->name, len); + WRITEMEM(name->name, len); return 0; } @@ -1079,7 +1089,7 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs status = encode_link(xdr, &cp->ops[i].u.link); break; case OP_LOOKUP: - status = encode_lookup(xdr, &cp->ops[i].u.lookup); + status = encode_lookup(xdr, cp->ops[i].u.lookup.lo_name); break; case OP_PUTFH: status = encode_putfh(xdr, cp->ops[i].u.putfh.pf_fhandle); @@ -1151,6 +1161,30 @@ static int nfs4_xdr_enc_access(struct rpc_rqst *req, uint32_t *p, const struct n return status; } +/* + * Encode LOOKUP request + */ +static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, uint32_t *p, const struct nfs4_lookup_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_lookup(&xdr, args->name)) != 0) + goto out; + if ((status = encode_getfh(&xdr)) != 0) + goto out; + status = encode_getfattr(&xdr, args->bitmask); +out: + return status; +} + /* * Encode GETATTR request */ @@ -2376,10 +2410,8 @@ decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) return -EIO; } -static int -decode_getfh(struct xdr_stream *xdr, struct nfs4_getfh *getfh) +static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh) { - struct nfs_fh *fh = getfh->gf_fhandle; uint32_t *p; uint32_t len; int status; @@ -2392,7 +2424,7 @@ decode_getfh(struct xdr_stream *xdr, struct nfs4_getfh *getfh) READ_BUF(4); READ32(len); - if (len > NFS_MAXFHSIZE) + if (len > NFS4_FHSIZE) return -EIO; fh->size = len; READ_BUF(len); @@ -2865,7 +2897,7 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs status = decode_getattr(xdr, &op->u.getattr, cp->server); break; case OP_GETFH: - status = decode_getfh(xdr, &op->u.getfh); + status = decode_getfh(xdr, op->u.getfh.gf_fhandle); break; case OP_LINK: status = decode_link(xdr, &op->u.link); @@ -2973,6 +3005,29 @@ static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_ return status; } +/* + * Decode LOOKUP response + */ +static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_lookup_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_lookup(&xdr)) != 0) + goto out; + if ((status = decode_getfh(&xdr, res->fh)) != 0) + goto out; + status = decode_getfattr(&xdr, res->fattr, res->server); +out: + return status; +} + /* * Decode GETATTR response */ @@ -3026,9 +3081,6 @@ nfs4_xdr_dec_open(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_openres *res) { struct xdr_stream xdr; struct compound_hdr hdr; - struct nfs4_getfh gfh = { - .gf_fhandle = &res->fh, - }; int status; xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); @@ -3047,7 +3099,7 @@ nfs4_xdr_dec_open(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_openres *res) status = decode_getattr(&xdr, res->f_getattr, res->server); if (status) goto out; - status = decode_getfh(&xdr, &gfh); + status = decode_getfh(&xdr, &res->fh); if (status) goto out; status = decode_restorefh(&xdr); @@ -3485,6 +3537,7 @@ struct rpc_procinfo nfs4_procedures[] = { PROC(LOCKU, enc_locku, dec_locku), PROC(ACCESS, enc_access, dec_access), PROC(GETATTR, enc_getattr, dec_getattr), + PROC(LOOKUP, enc_lookup, dec_lookup), }; struct rpc_version nfs_version4 = { diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index 33bdd9a0d85cfed35e4af1b1d378fe236583aecd..185998ba896c7ac3f48ef81c636986ab4f728215 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h @@ -305,6 +305,7 @@ enum { NFSPROC4_CLNT_LOCKU, NFSPROC4_CLNT_ACCESS, NFSPROC4_CLNT_GETATTR, + NFSPROC4_CLNT_LOOKUP, }; #endif diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 65c6b94504e8766d3a9acd2e342f14568fa50d15..b94596199ecb08a85ae47882d24f4610767522b5 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -554,6 +554,18 @@ struct nfs4_lookup { struct qstr * lo_name; /* request */ }; +struct nfs4_lookup_arg { + const struct nfs_fh * dir_fh; + const struct qstr * name; + const u32 * bitmask; +}; + +struct nfs4_lookup_res { + const struct nfs_server * server; + struct nfs_fattr * fattr; + struct nfs_fh * fh; +}; + struct nfs4_open { struct nfs4_client * op_client_state; /* request */ u32 op_share_access; /* request */