/* LOOKUP */ int nfs3svc_encode_diropres(struct svc_rqst *rqstp, u32 *p, struct nfsd3_diropres *resp) { if (resp->status == 0) { p = encode_fh(p, &resp->fh); p = encode_post_op_attr(rqstp, p, &resp->fh); } p = encode_post_op_attr(rqstp, p, &resp->dirfh); return xdr_ressize_check(rqstp, p); }
/* LINK */ int nfs3svc_encode_linkres(struct svc_rqst *rqstp, u32 *p, struct nfsd3_linkres *resp) { p = encode_post_op_attr(rqstp, p, &resp->fh); p = encode_wcc_data(rqstp, p, &resp->tfh); return xdr_ressize_check(rqstp, p); }
/* ACCESS */ int nfs3svc_encode_accessres(struct svc_rqst *rqstp, u32 *p, struct nfsd3_accessres *resp) { p = encode_post_op_attr(rqstp, p, &resp->fh); if (resp->status == 0) *p++ = htonl(resp->access); return xdr_ressize_check(rqstp, p); }
/* READLINK */ int nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p, struct nfsd3_readlinkres *resp) { p = encode_post_op_attr(rqstp, p, &resp->fh); if (resp->status == 0) { *p++ = htonl(resp->len); p += XDR_QUADLEN(resp->len); } return xdr_ressize_check(rqstp, p); }
/* READDIR */ int nfs3svc_encode_readdirres(struct svc_rqst *rqstp, u32 *p, struct nfsd3_readdirres *resp) { p = encode_post_op_attr(rqstp, p, &resp->fh); if (resp->status == 0) { /* stupid readdir cookie */ memcpy(p, resp->verf, 8); p += 2; p += XDR_QUADLEN(resp->count); } return xdr_ressize_check(rqstp, p); }
/* READ */ int nfs3svc_encode_readres(struct svc_rqst *rqstp, u32 *p, struct nfsd3_readres *resp) { p = encode_post_op_attr(rqstp, p, &resp->fh); if (resp->status == 0) { *p++ = htonl(resp->count); *p++ = htonl(resp->eof); *p++ = htonl(resp->count); /* xdr opaque count */ p += XDR_QUADLEN(resp->count); } return xdr_ressize_check(rqstp, p); }
/* CREATE, MKDIR, SYMLINK, MKNOD */ int nfs3svc_encode_createres(struct svc_rqst *rqstp, __be32 *p) { struct nfsd3_diropres *resp = rqstp->rq_resp; if (resp->status == 0) { *p++ = xdr_one; p = encode_fh(p, &resp->fh); p = encode_post_op_attr(rqstp, p, &resp->fh); } p = encode_wcc_data(rqstp, p, &resp->dirfh); return xdr_ressize_check(rqstp, p); }
static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen, u64 ino) { struct svc_fh *fh = &cd->scratch; __be32 err; fh_init(fh, NFS3_FHSIZE); err = compose_entry_fh(cd, fh, name, namlen, ino); if (err) { *p++ = 0; *p++ = 0; goto out; } p = encode_post_op_attr(cd->rqstp, p, fh); *p++ = xdr_one; /* yes, a file handle follows */ p = encode_fh(p, fh); out: fh_put(fh); return p; }
/* * Enocde weak cache consistency data */ static u32 * encode_wcc_data(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) { struct dentry *dentry = fhp->fh_dentry; if (dentry && dentry->d_inode && fhp->fh_post_saved) { if (fhp->fh_pre_saved) { *p++ = xdr_one; p = xdr_encode_hyper(p, (u64) fhp->fh_pre_size); p = encode_time3(p, fhp->fh_pre_mtime); p = encode_time3(p, fhp->fh_pre_ctime); } else { *p++ = xdr_zero; } return encode_saved_post_attr(rqstp, p, fhp); } /* no pre- or post-attrs */ *p++ = xdr_zero; return encode_post_op_attr(rqstp, p, fhp); }
/* READLINK */ int nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p) { struct nfsd3_readlinkres *resp = rqstp->rq_resp; p = encode_post_op_attr(rqstp, p, &resp->fh); if (resp->status == 0) { *p++ = htonl(resp->len); xdr_ressize_check(rqstp, p); rqstp->rq_res.page_len = resp->len; if (resp->len & 3) { /* need to pad the tail */ rqstp->rq_res.tail[0].iov_base = p; *p = 0; rqstp->rq_res.tail[0].iov_len = 4 - (resp->len&3); } return 1; } else return xdr_ressize_check(rqstp, p); }
/* READ */ int nfs3svc_encode_readres(struct svc_rqst *rqstp, __be32 *p) { struct nfsd3_readres *resp = rqstp->rq_resp; p = encode_post_op_attr(rqstp, p, &resp->fh); if (resp->status == 0) { *p++ = htonl(resp->count); *p++ = htonl(resp->eof); *p++ = htonl(resp->count); /* xdr opaque count */ xdr_ressize_check(rqstp, p); /* now update rqstp->rq_res to reflect data as well */ rqstp->rq_res.page_len = resp->count; if (resp->count & 3) { /* need to pad the tail */ rqstp->rq_res.tail[0].iov_base = p; *p = 0; rqstp->rq_res.tail[0].iov_len = 4 - (resp->count & 3); } return 1; } else return xdr_ressize_check(rqstp, p); }
/* READDIR */ int nfs3svc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p) { struct nfsd3_readdirres *resp = rqstp->rq_resp; p = encode_post_op_attr(rqstp, p, &resp->fh); if (resp->status == 0) { /* stupid readdir cookie */ memcpy(p, resp->verf, 8); p += 2; xdr_ressize_check(rqstp, p); if (rqstp->rq_res.head[0].iov_len + (2<<2) > PAGE_SIZE) return 1; /*No room for trailer */ rqstp->rq_res.page_len = (resp->count) << 2; /* add the 'tail' to the end of the 'head' page - page 0. */ rqstp->rq_res.tail[0].iov_base = p; *p++ = 0; /* no more entries */ *p++ = htonl(resp->common.err == nfserr_eof); rqstp->rq_res.tail[0].iov_len = 2<<2; return 1; } else return xdr_ressize_check(rqstp, p); }
static int encode_entry(struct readdir_cd *cd, const char *name, int namlen, off_t offset, ino_t ino, unsigned int d_type, int plus) { u32 *p = cd->buffer; int buflen, slen, elen; if (cd->offset) xdr_encode_hyper(cd->offset, (u64) offset); /* nfsd_readdir calls us with name == 0 when it wants us to * set the last offset entry. */ if (name == 0) return 0; /* dprintk("encode_entry(%.*s @%ld%s)\n", namlen, name, (long) offset, plus? " plus" : ""); */ /* truncate filename if too long */ if (namlen > NFS3_MAXNAMLEN) namlen = NFS3_MAXNAMLEN; slen = XDR_QUADLEN(namlen); elen = slen + NFS3_ENTRY_BAGGAGE + (plus? NFS3_ENTRYPLUS_BAGGAGE : 0); if ((buflen = cd->buflen - elen) < 0) { cd->eob = 1; return -EINVAL; } *p++ = xdr_one; /* mark entry present */ p = xdr_encode_hyper(p, ino); /* file id */ p = xdr_encode_array(p, name, namlen);/* name length & name */ cd->offset = p; /* remember pointer */ p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */ /* throw in readdirplus baggage */ if (plus) { struct svc_fh fh; struct svc_export *exp; struct dentry *dparent, *dchild; dparent = cd->dirfh->fh_dentry; exp = cd->dirfh->fh_export; fh_init(&fh, NFS3_FHSIZE); if (isdotent(name, namlen)) { dchild = dparent; if (namlen == 2) dchild = dchild->d_parent; dchild = dget(dchild); } else dchild = lookup_one_len(name, dparent,namlen); if (IS_ERR(dchild)) goto noexec; if (fh_compose(&fh, exp, dchild, cd->dirfh) != 0 || !dchild->d_inode) goto noexec; p = encode_post_op_attr(cd->rqstp, p, &fh); *p++ = xdr_one; /* yes, a file handle follows */ p = encode_fh(p, &fh); fh_put(&fh); } out: cd->buflen = buflen; cd->buffer = p; return 0; noexec: *p++ = 0; *p++ = 0; goto out; }
/* Helper for NFSv3 ACLs */ __be32 * nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) { return encode_post_op_attr(rqstp, p, fhp); }