patch-2.1.32 linux/fs/nfsd/nfs3xdr.c
Next file: linux/fs/nfsd/nfscache.c
Previous file: linux/fs/nfsd/nfs3proc.c
Back to the patch index
Back to the overall index
- Lines: 786
- Date:
Fri Apr 4 11:06:02 1997
- Orig file:
v2.1.31/linux/fs/nfsd/nfs3xdr.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.1.31/linux/fs/nfsd/nfs3xdr.c linux/fs/nfsd/nfs3xdr.c
@@ -0,0 +1,785 @@
+/*
+ * linux/fs/nfsd/nfs3xdr.c
+ *
+ * XDR support for nfsd/protocol version 3.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/nfs3.h>
+
+#include <linux/sunrpc/xdr.h>
+#include <linux/sunrpc/svc.h>
+#include <linux/nfsd/nfsd.h>
+#include <linux/nfsd/xdr3.h>
+
+#define NFSDDBG_FACILITY NFSDDBG_XDR
+
+u32 nfs_ok, nfserr_perm, nfserr_noent, nfserr_io, nfserr_nxio,
+ nfserr_acces, nfserr_exist, nfserr_nodev, nfserr_notdir,
+ nfserr_isdir, nfserr_fbig, nfserr_nospc, nfserr_rofs,
+ nfserr_nametoolong, nfserr_dquot, nfserr_stale;
+
+#ifdef NFSD_OPTIMIZE_SPACE
+# define inline
+#endif
+
+/*
+ * Mapping of S_IF* types to NFS file types
+ */
+static u32 nfs3_ftypes[] = {
+ NF3NON, NF3FIFO, NF3CHR, NF3BAD,
+ NF3DIR, NF3BAD, NF3BLK, NF3BAD,
+ NF3REG, NF3BAD, NF3LNK, NF3BAD,
+ NF3SOCK, NF3BAD, NF3LNK, NF3BAD,
+};
+
+/*
+ * Initialization of NFS status variables
+ */
+void
+nfs3xdr_init(void)
+{
+ static int inited = 0;
+
+ if (inited)
+ return;
+
+ nfs_ok = htonl(NFS_OK);
+ nfserr_perm = htonl(NFSERR_PERM);
+ nfserr_noent = htonl(NFSERR_NOENT);
+ nfserr_io = htonl(NFSERR_IO);
+ nfserr_nxio = htonl(NFSERR_NXIO);
+ nfserr_acces = htonl(NFSERR_ACCES);
+ nfserr_exist = htonl(NFSERR_EXIST);
+ nfserr_nodev = htonl(NFSERR_NODEV);
+ nfserr_notdir = htonl(NFSERR_NOTDIR);
+ nfserr_isdir = htonl(NFSERR_ISDIR);
+ nfserr_fbig = htonl(NFSERR_FBIG);
+ nfserr_nospc = htonl(NFSERR_NOSPC);
+ nfserr_rofs = htonl(NFSERR_ROFS);
+ nfserr_nametoolong = htonl(NFSERR_NAMETOOLONG);
+ nfserr_dquot = htonl(NFSERR_DQUOT);
+ nfserr_stale = htonl(NFSERR_STALE);
+
+ inited = 1;
+}
+
+/*
+ * XDR functions for basic NFS types
+ */
+static inline u32 *
+enc64(u32 *p, u64 val)
+{
+ *p++ = (val >> 32);
+ *p++ = (val & 0xffffffff);
+ return p;
+}
+
+static inline u32 *
+dec64(u32 *p, u64 *valp)
+{
+ *valp = ((u64) ntohl(*p++)) << 32;
+ *valp |= ntohl(*p++);
+ return p;
+}
+
+static inline u32 *
+encode_time3(u32 *p, time_t secs)
+{
+ *p++ = htonl((u32) secs); *p++ = 0;
+ return p;
+}
+
+static inline u32 *
+decode_time3(u32 *p, time_t *secp)
+{
+ *secp = ntohl(*p++);
+ return p + 1;
+}
+
+static inline u32 *
+decode_fh(u32 *p, struct svc_fh *fhp)
+{
+ if (*p++ != sizeof(struct knfs_fh))
+ return NULL;
+
+ memcpy(&fhp->fh_handle, p, sizeof(struct knfs_fh));
+ fhp->fh_inode = NULL;
+ fhp->fh_export = NULL;
+
+ return p + (sizeof(struct knfs_fh) >> 2);
+}
+
+static inline u32 *
+encode_fh(u32 *p, struct svc_fh *fhp)
+{
+ *p++ = htonl(sizeof(struct knfs_fh));
+ memcpy(p, &fhp->fh_handle, sizeof(struct knfs_fh));
+ return p + (sizeof(struct knfs_fh) >> 2);
+}
+
+/*
+ * Decode a file name and make sure that the path contains
+ * no slashes or null bytes.
+ */
+static inline u32 *
+decode_filename(u32 *p, char **namp, int *lenp)
+{
+ char *name;
+ int i;
+
+ if ((p = xdr_decode_string(p, namp, lenp, NFS3_MAXNAMLEN)) != NULL) {
+ for (i = 0, name = *namp; i < *lenp; i++, name++) {
+ if (*name == '\0' || *name == '/')
+ return NULL;
+ }
+ *name = '\0';
+ }
+
+ return p;
+}
+
+static inline u32 *
+decode_pathname(u32 *p, char **namp, int *lenp)
+{
+ char *name;
+ int i;
+
+ if ((p = xdr_decode_string(p, namp, lenp, NFS3_MAXPATHLEN)) != NULL) {
+ for (i = 0, name = *namp; i < *lenp; i++, name++) {
+ if (*name == '\0')
+ return NULL;
+ }
+ *name = '\0';
+ }
+
+ return p;
+}
+
+static inline u32 *
+decode_sattr3(u32 *p, struct iattr *iap)
+{
+ u32 tmp;
+
+ iap->ia_valid = 0;
+
+ if (*p++) {
+ iap->ia_valid |= ATTR_MODE;
+ iap->ia_mode = ntohl(*p++);
+ }
+ if (*p++) {
+ iap->ia_valid |= ATTR_UID;
+ iap->ia_uid = ntohl(*p++);
+ }
+ if (*p++) {
+ iap->ia_valid |= ATTR_GID;
+ iap->ia_gid = ntohl(*p++);
+ }
+ if (*p++) {
+ iap->ia_valid |= ATTR_SIZE;
+ iap->ia_size = ntohl(*p++);
+ }
+ if ((tmp = *p++) == 1) {
+ iap->ia_valid |= ATTR_ATIME;
+ } else if (tmp == 2) {
+ iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
+ iap->ia_atime = ntohl(*p++), p++;
+ }
+ if ((tmp = *p++) != 0) {
+ iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
+ } else if (tmp == 2) {
+ iap->ia_valid |= ATTR_MTIME;
+ iap->ia_mtime = ntohl(*p++), p++;
+ }
+ return p;
+}
+
+static inline u32 *
+encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct inode *inode)
+{
+ if (!inode) {
+ printk("nfsd: NULL inode in %s:%d", __FILE__, __LINE__);
+ return NULL;
+ }
+
+ *p++ = htonl(nfs3_ftypes[(inode->i_mode & S_IFMT) >> 12]);
+ *p++ = htonl((u32) inode->i_mode);
+ *p++ = htonl((u32) inode->i_nlink);
+ *p++ = htonl((u32) nfsd_ruid(rqstp, inode->i_uid));
+ *p++ = htonl((u32) nfsd_rgid(rqstp, inode->i_gid));
+ if (S_ISLNK(inode->i_mode) && inode->i_size > NFS3_MAXPATHLEN) {
+ p = enc64(p, (u64) NFS3_MAXPATHLEN);
+ } else {
+ p = enc64(p, (u64) inode->i_size);
+ }
+ p = enc64(p, inode->i_blksize * inode->i_blocks);
+ *p++ = htonl((u32) MAJOR(inode->i_rdev));
+ *p++ = htonl((u32) MINOR(inode->i_rdev));
+ p = enc64(p, (u64) inode->i_dev);
+ p = enc64(p, (u64) inode->i_ino);
+ p = encode_time3(p, inode->i_atime);
+ p = encode_time3(p, inode->i_mtime);
+ p = encode_time3(p, inode->i_ctime);
+
+ return p;
+}
+
+/*
+ * Encode post-operation attributes.
+ * The inode may be NULL if the call failed because of a stale file
+ * handle. In this case, no attributes are returned.
+ */
+static u32 *
+encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct inode *inode)
+{
+ if (inode == NULL) {
+ *p++ = xdr_zero;
+ return p;
+ }
+ return encode_fattr3(rqstp, p, inode);
+}
+
+/*
+ * Enocde weak cache consistency data
+ */
+static u32 *
+encode_wcc_data(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
+{
+ struct inode *inode = fhp->fh_inode;
+
+ if (fhp->fh_post_version == inode->i_version) {
+ *p++ = xdr_one;
+ p = enc64(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_post_op_attr(rqstp, p, inode);
+}
+
+/*
+ * Check buffer bounds after decoding arguments
+ */
+static inline int
+xdr_argsize_check(struct svc_rqst *rqstp, u32 *p)
+{
+ struct svc_buf *buf = &rqstp->rq_argbuf;
+
+ return p - buf->base <= buf->buflen;
+}
+
+static inline int
+xdr_ressize_check(struct svc_rqst *rqstp, u32 *p)
+{
+ struct svc_buf *buf = &rqstp->rq_resbuf;
+
+ buf->len = p - buf->base;
+ dprintk("nfsd: ressize_check p %p base %p len %d\n",
+ p, buf->base, buf->buflen);
+ return (buf->len <= buf->buflen);
+}
+
+/*
+ * XDR decode functions
+ */
+int
+nfs3svc_decode_fhandle(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
+{
+ if (!(p = decode_fh(p, fhp)))
+ return 0;
+ return xdr_argsize_check(rqstp, p);
+}
+
+int
+nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_sattrargs *args)
+{
+ if (!(p = decode_fh(p, &args->fh))
+ || !(p = decode_sattr3(p, &args->attrs))
+ || (*p++ && !(p = decode_time3(p, &args->guardtime))))
+ return 0;
+
+ return xdr_argsize_check(rqstp, p);
+}
+
+int
+nfs3svc_decode_diropargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_diropargs *args)
+{
+ if (!(p = decode_fh(p, &args->fh))
+ || !(p = decode_filename(p, &args->name, &args->len)))
+ return 0;
+
+ return xdr_argsize_check(rqstp, p);
+}
+
+int
+nfs3svc_decode_accessargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_accessargs *args)
+{
+ if (!(p = decode_fh(p, &args->fh)))
+ return 0;
+ args->access = ntohl(*p++);
+
+ return xdr_argsize_check(rqstp, p);
+}
+
+int
+nfs3svc_decode_readargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_readargs *args)
+{
+ if (!(p = decode_fh(p, &args->fh))
+ || !(p = dec64(p, &args->offset))
+ || !(p = dec64(p, &args->count)))
+ return 0;
+
+ return xdr_argsize_check(rqstp, p);
+}
+
+int
+nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_writeargs *args)
+{
+ if (!(p = decode_fh(p, &args->fh))
+ || !(p = dec64(p, &args->offset))
+ || !(p = dec64(p, &args->count)))
+ return 0;
+
+ args->stable = ntohl(*p++);
+ args->len = ntohl(*p++);
+ args->data = (char *) p;
+ p += (args->len + 3) >> 2;
+
+ return xdr_argsize_check(rqstp, p);
+}
+
+int
+nfs3svc_decode_createargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_createargs *args)
+{
+ if (!(p = decode_fh(p, &args->fh))
+ || !(p = decode_filename(p, &args->name, &args->len)))
+ return 0;
+
+ switch (args->createmode = ntohl(*p++)) {
+ case 0: case 1:
+ if (!(p = decode_sattr3(p, &args->attrs)))
+ return 0;
+ break;
+ case 2:
+ args->verf = p;
+ p += 2;
+ break;
+ default:
+ return 0;
+ }
+
+ return xdr_argsize_check(rqstp, p);
+}
+int
+nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_createargs *args)
+{
+ if (!(p = decode_fh(p, &args->fh))
+ || !(p = decode_filename(p, &args->name, &args->len))
+ || !(p = decode_sattr3(p, &args->attrs)))
+ return 0;
+
+ return xdr_argsize_check(rqstp, p);
+}
+
+int
+nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_symlinkargs *args)
+{
+ if (!(p = decode_fh(p, &args->ffh))
+ || !(p = decode_filename(p, &args->fname, &args->flen))
+ || !(p = decode_sattr3(p, &args->attrs))
+ || !(p = decode_pathname(p, &args->tname, &args->tlen)))
+ return 0;
+
+ return xdr_argsize_check(rqstp, p);
+}
+
+int
+nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_mknodargs *args)
+{
+ if (!(p = decode_fh(p, &args->fh))
+ || !(p = decode_filename(p, &args->name, &args->len)))
+ return 0;
+
+ args->ftype = ntohl(*p++);
+
+ if (args->ftype == NF3BLK || args->ftype == NF3CHR
+ || args->ftype == NF3SOCK || args->ftype == NF3FIFO) {
+ if (!(p = decode_sattr3(p, &args->attrs)))
+ return 0;
+ }
+
+ if (args->ftype == NF3BLK || args->ftype == NF3CHR) {
+ args->major = ntohl(*p++);
+ args->minor = ntohl(*p++);
+ }
+
+ return xdr_argsize_check(rqstp, p);
+}
+
+int
+nfs3svc_decode_renameargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_renameargs *args)
+{
+ if (!(p = decode_fh(p, &args->ffh))
+ || !(p = decode_filename(p, &args->fname, &args->flen))
+ || !(p = decode_fh(p, &args->tfh))
+ || !(p = decode_filename(p, &args->tname, &args->tlen)))
+ return 0;
+
+ return xdr_argsize_check(rqstp, p);
+}
+
+int
+nfs3svc_decode_linkargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_linkargs *args)
+{
+ if (!(p = decode_fh(p, &args->ffh))
+ || !(p = decode_fh(p, &args->tfh))
+ || !(p = decode_filename(p, &args->tname, &args->tlen)))
+ return 0;
+
+ return xdr_argsize_check(rqstp, p);
+}
+
+int
+nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_readdirargs *args)
+{
+ if (!(p = decode_fh(p, &args->fh)))
+ return 0;
+ args->cookie = ntohl(*p++);
+ args->verf = p; p += 2;
+ args->count = ntohl(*p++);
+
+ return xdr_argsize_check(rqstp, p);
+}
+
+int
+nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_readdirargs *args)
+{
+ if (!(p = decode_fh(p, &args->fh)))
+ return 0;
+ args->cookie = ntohl(*p++);
+ args->verf = p; p += 2;
+ args->dircount = ntohl(*p++);
+ args->count = ntohl(*p++);
+
+ return xdr_argsize_check(rqstp, p);
+}
+
+int
+nfs3svc_decode_commitargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_commitargs *args)
+{
+ if (!(p = decode_fh(p, &args->fh))
+ || !(p = dec64(p, &args->offset)))
+ return 0;
+ args->count = ntohl(*p++);
+
+ return xdr_argsize_check(rqstp, p);
+}
+
+/*
+ * XDR encode functions
+ */
+/* GETATTR */
+int
+nfs3svc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_attrstat *resp)
+{
+ if (!(p = encode_fattr3(rqstp, p, resp->fh.fh_inode)))
+ return 0;
+ return xdr_ressize_check(rqstp, p);
+}
+
+/* SETATTR, REMOVE, RMDIR */
+int
+nfs3svc_encode_wccstat(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_attrstat *resp)
+{
+ if (!(p = encode_wcc_data(rqstp, p, &resp->fh)))
+ return 0;
+ return xdr_ressize_check(rqstp, p);
+}
+
+/* LOOKUP */
+int
+nfs3svc_encode_lookupres(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_lookupres *resp)
+{
+ if (resp->status == 0) {
+ p = encode_fh(p, &resp->fh);
+ if (!(p = encode_fattr3(rqstp, p, resp->fh.fh_inode)))
+ return 0;
+ }
+ p = encode_post_op_attr(rqstp, p, resp->dirfh.fh_inode);
+ 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.fh_inode);
+ 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.fh_inode);
+ if (resp->status == 0) {
+ *p++ = htonl(resp->len);
+ p += XDR_QUADLEN(resp->len);
+ }
+ 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.fh_inode);
+ 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);
+}
+
+/* WRITE */
+int
+nfs3svc_encode_writeres(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_writeres *resp)
+{
+ p = encode_wcc_data(rqstp, p, &resp->fh);
+ if (resp->status == 0) {
+ *p++ = htonl(resp->count);
+ *p++ = htonl(resp->committed);
+ *p++ = htonl(nfssvc_boot.tv_sec);
+ *p++ = htonl(nfssvc_boot.tv_usec);
+ }
+ return xdr_ressize_check(rqstp, p);
+}
+
+/* CREATE, MKDIR, SYMLINK, MKNOD */
+int
+nfs3svc_encode_createres(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_createres *resp)
+{
+ if (resp->status == 0) {
+ p = encode_fh(p, &resp->fh);
+ p = encode_post_op_attr(rqstp, p, resp->fh.fh_inode);
+ }
+ p = encode_wcc_data(rqstp, p, &resp->dirfh);
+ return xdr_ressize_check(rqstp, p);
+}
+
+/* RENAME */
+int
+nfs3svc_encode_renameres(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_renameres *resp)
+{
+ p = encode_wcc_data(rqstp, p, &resp->ffh);
+ p = encode_wcc_data(rqstp, p, &resp->tfh);
+ 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.fh_inode);
+ p = encode_wcc_data(rqstp, p, &resp->tfh);
+ 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.fh_inode);
+ if (resp->status == 0) {
+ /* stupid readdir cookie */
+ *p++ = ntohl(resp->fh.fh_inode->i_mtime);
+ *p++ = xdr_zero;
+ p = resp->list_end;
+ }
+
+ return xdr_ressize_check(rqstp, p);
+}
+
+#define NFS3_ENTRYPLUS_BAGGAGE ((1 + 20 + 1 + NFS3_FHSIZE) << 2)
+int
+nfs3svc_encode_entry(struct readdir_cd *cd, const char *name,
+ int namlen, unsigned long offset, ino_t ino)
+{
+ u32 *p = cd->buffer;
+ int buflen, slen, elen;
+ struct svc_fh fh;
+
+ if (offset > ~((u64) 0))
+ return -EINVAL;
+ if (cd->offset)
+ *cd->offset = htonl(offset);
+
+ /* For readdirplus, look up the inode */
+ if (cd->plus && nfsd_lookup(cd->rqstp, cd->dirfh, name, namlen, &fh))
+ return 0;
+
+ /* truncate filename if too long */
+ if (namlen > NFS3_MAXNAMLEN)
+ namlen = NFS3_MAXNAMLEN;
+
+ slen = XDR_QUADLEN(namlen);
+ elen = slen + (cd->plus? NFS3_ENTRYPLUS_BAGGAGE : 0);
+ if ((buflen = cd->buflen - elen - 4) < 0) {
+ cd->eob = 1;
+ if (cd->plus)
+ fh_put(&fh);
+ return -EINVAL;
+ }
+ *p++ = xdr_one; /* mark entry present */
+ *p++ = xdr_zero; /* file id (64 bit) */
+ *p++ = htonl((u32) ino);
+ *p++ = htonl((u32) namlen); /* name length & name */
+ memcpy(p, name, namlen);
+ p += slen;
+
+ /* throw in readdirplus baggage */
+ if (cd->plus) {
+ p = encode_post_op_attr(cd->rqstp, p, fh.fh_inode);
+ p = encode_fh(p, &fh);
+ fh_put(&fh);
+ }
+
+ cd->offset = p; /* remember pointer */
+ p = enc64(p, ~(u64) 0); /* offset of next entry */
+
+ cd->buflen = buflen;
+ cd->buffer = p;
+ return 0;
+}
+
+/* FSSTAT */
+int
+nfs3svc_encode_statfsres(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_statfsres *resp)
+{
+ struct statfs *s = &resp->stats;
+ u64 bs = s->f_bsize;
+
+ *p++ = xdr_zero; /* no post_op_attr */
+
+ if (resp->status == 0) {
+ p = enc64(p, bs * s->f_blocks); /* total bytes */
+ p = enc64(p, bs * s->f_bfree); /* free bytes */
+ p = enc64(p, bs * s->f_bavail); /* user available bytes */
+ p = enc64(p, s->f_files); /* total inodes */
+ p = enc64(p, s->f_ffree); /* free inodes */
+ p = enc64(p, s->f_ffree); /* user available inodes */
+ *p++ = htonl(resp->invarsec); /* mean unchanged time */
+ }
+ return xdr_ressize_check(rqstp, p);
+}
+
+/* FSINFO */
+int
+nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_fsinfores *resp)
+{
+ *p++ = xdr_zero; /* no post_op_attr */
+
+ if (resp->status == 0) {
+ *p++ = htonl(resp->f_rtmax);
+ *p++ = htonl(resp->f_rtpref);
+ *p++ = htonl(resp->f_rtmult);
+ *p++ = htonl(resp->f_wtmax);
+ *p++ = htonl(resp->f_wtpref);
+ *p++ = htonl(resp->f_wtmult);
+ *p++ = htonl(resp->f_dtpref);
+ *p++ = htonl(resp->f_maxfilesize);
+ *p++ = xdr_zero;
+ *p++ = htonl(1000000000 / HZ);
+ *p++ = htonl(resp->f_properties);
+ }
+
+ return xdr_ressize_check(rqstp, p);
+}
+
+/* PATHCONF */
+int
+nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_pathconfres *resp)
+{
+ *p++ = xdr_zero; /* no post_op_attr */
+
+ if (resp->status == 0) {
+ *p++ = htonl(resp->p_link_max);
+ *p++ = htonl(resp->p_name_max);
+ *p++ = xdr_one; /* always reject long file names */
+ *p++ = xdr_one; /* chown restricted */
+ *p++ = htonl(resp->p_case_insensitive);
+ *p++ = htonl(resp->p_case_preserving);
+ }
+
+ return xdr_ressize_check(rqstp, p);
+}
+
+/* COMMIT */
+int
+nfs3svc_encode_commitres(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_commitres *resp)
+{
+ p = encode_wcc_data(rqstp, p, &resp->fh);
+ /* Write verifier */
+ if (resp->status == 0) {
+ *p++ = htonl(nfssvc_boot.tv_sec);
+ *p++ = htonl(nfssvc_boot.tv_usec);
+ }
+ return xdr_ressize_check(rqstp, p);
+}
+
+/*
+ * XDR release functions
+ */
+int
+nfs3svc_release_fhandle(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd_fhandle *resp)
+{
+ fh_put(&resp->fh);
+ return 1;
+}
+
+int
+nfs3svc_release_fhandle2(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_fhandle2 *resp)
+{
+ fh_put(&resp->fh1);
+ fh_put(&resp->fh2);
+ return 1;
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov