NFS: Use cached page as buffer for NFS symlink requests
[powerpc.git] / fs / nfs / nfs2xdr.c
index 59049e8..b49501f 100644 (file)
 #include <linux/nfs.h>
 #include <linux/nfs2.h>
 #include <linux/nfs_fs.h>
+#include "internal.h"
 
 #define NFSDBG_FACILITY                NFSDBG_XDR
 /* #define NFS_PARANOIA 1 */
 
-extern int                     nfs_stat_to_errno(int stat);
-
 /* Mapping from NFS error code to "errno" error code. */
 #define errno_NFSERR_IO                EIO
 
@@ -52,7 +51,7 @@ extern int                    nfs_stat_to_errno(int stat);
 #define NFS_createargs_sz      (NFS_diropargs_sz+NFS_sattr_sz)
 #define NFS_renameargs_sz      (NFS_diropargs_sz+NFS_diropargs_sz)
 #define NFS_linkargs_sz                (NFS_fhandle_sz+NFS_diropargs_sz)
-#define NFS_symlinkargs_sz     (NFS_diropargs_sz+NFS_path_sz+NFS_sattr_sz)
+#define NFS_symlinkargs_sz     (NFS_diropargs_sz+1+NFS_sattr_sz)
 #define NFS_readdirargs_sz     (NFS_fhandle_sz+2)
 
 #define NFS_attrstat_sz                (1+NFS_fattr_sz)
@@ -131,7 +130,8 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
        fattr->du.nfs2.blocksize = ntohl(*p++);
        rdev = ntohl(*p++);
        fattr->du.nfs2.blocks = ntohl(*p++);
-       fattr->fsid_u.nfs3 = ntohl(*p++);
+       fattr->fsid.major = ntohl(*p++);
+       fattr->fsid.minor = 0;
        fattr->fileid = ntohl(*p++);
        p = xdr_decode_time(p, &fattr->atime);
        p = xdr_decode_time(p, &fattr->mtime);
@@ -146,23 +146,23 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
        return p;
 }
 
-#define SATTR(p, attr, flag, field) \
-        *p++ = (attr->ia_valid & flag) ? htonl(attr->field) : ~(u32) 0
 static inline u32 *
 xdr_encode_sattr(u32 *p, struct iattr *attr)
 {
-       SATTR(p, attr, ATTR_MODE, ia_mode);
-       SATTR(p, attr, ATTR_UID, ia_uid);
-       SATTR(p, attr, ATTR_GID, ia_gid);
-       SATTR(p, attr, ATTR_SIZE, ia_size);
+       const u32 not_set = __constant_htonl(0xFFFFFFFF);
+
+       *p++ = (attr->ia_valid & ATTR_MODE) ? htonl(attr->ia_mode) : not_set;
+       *p++ = (attr->ia_valid & ATTR_UID) ? htonl(attr->ia_uid) : not_set;
+       *p++ = (attr->ia_valid & ATTR_GID) ? htonl(attr->ia_gid) : not_set;
+       *p++ = (attr->ia_valid & ATTR_SIZE) ? htonl(attr->ia_size) : not_set;
 
        if (attr->ia_valid & ATTR_ATIME_SET) {
                p = xdr_encode_time(p, &attr->ia_atime);
        } else if (attr->ia_valid & ATTR_ATIME) {
                p = xdr_encode_current_server_time(p, &attr->ia_atime);
        } else {
-               *p++ = ~(u32) 0;
-               *p++ = ~(u32) 0;
+               *p++ = not_set;
+               *p++ = not_set;
        }
 
        if (attr->ia_valid & ATTR_MTIME_SET) {
@@ -170,12 +170,11 @@ xdr_encode_sattr(u32 *p, struct iattr *attr)
        } else if (attr->ia_valid & ATTR_MTIME) {
                p = xdr_encode_current_server_time(p, &attr->ia_mtime);
        } else {
-               *p++ = ~(u32) 0;        
-               *p++ = ~(u32) 0;
+               *p++ = not_set; 
+               *p++ = not_set;
        }
        return p;
 }
-#undef SATTR
 
 /*
  * NFS encode functions
@@ -352,11 +351,26 @@ nfs_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs_linkargs *args)
 static int
 nfs_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_symlinkargs *args)
 {
+       struct xdr_buf *sndbuf = &req->rq_snd_buf;
+       size_t pad;
+
        p = xdr_encode_fhandle(p, args->fromfh);
        p = xdr_encode_array(p, args->fromname, args->fromlen);
-       p = xdr_encode_array(p, args->topath, args->tolen);
+       *p++ = htonl(args->pathlen);
+       sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
+
+       xdr_encode_pages(sndbuf, args->pages, 0, args->pathlen);
+
+       /*
+        * xdr_encode_pages may have added a few bytes to ensure the
+        * pathname ends on a 4-byte boundary.  Start encoding the
+        * attributes after the pad bytes.
+        */
+       pad = sndbuf->tail->iov_len;
+       if (pad > 0)
+               p++;
        p = xdr_encode_sattr(p, args->sattr);
-       req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+       sndbuf->len += xdr_adjust_iovec(sndbuf->tail, p) - pad;
        return 0;
 }
 
@@ -683,7 +697,9 @@ nfs_stat_to_errno(int stat)
        .p_encode   =  (kxdrproc_t) nfs_xdr_##argtype,                  \
        .p_decode   =  (kxdrproc_t) nfs_xdr_##restype,                  \
        .p_bufsiz   =  MAX(NFS_##argtype##_sz,NFS_##restype##_sz) << 2, \
-       .p_timer    =  timer                                            \
+       .p_timer    =  timer,                                           \
+       .p_statidx  =  NFSPROC_##proc,                                  \
+       .p_name     =  #proc,                                           \
        }
 struct rpc_procinfo    nfs_procedures[] = {
     PROC(GETATTR,      fhandle,        attrstat, 1),
@@ -705,6 +721,6 @@ struct rpc_procinfo nfs_procedures[] = {
 
 struct rpc_version             nfs_version2 = {
        .number                 = 2,
-       .nrprocs                = sizeof(nfs_procedures)/sizeof(nfs_procedures[0]),
+       .nrprocs                = ARRAY_SIZE(nfs_procedures),
        .procs                  = nfs_procedures
 };