]> err.no Git - linux-2.6/blobdiff - fs/nfs/nfs4xdr.c
Merge mulgrave-w:git/linux-2.6
[linux-2.6] / fs / nfs / nfs4xdr.c
index f6a1ea7df3742196236c80812316303c08d1ce2b..3dd413f52da11d28e1b08ca4edbaca2bdca33864 100644 (file)
@@ -58,7 +58,7 @@
 /* Mapping from NFS error code to "errno" error code. */
 #define errno_NFSERR_IO                EIO
 
-static int nfs_stat_to_errno(int);
+static int nfs4_stat_to_errno(int);
 
 /* NFSv4 COMPOUND tags are only wanted for debugging purposes */
 #ifdef DEBUG
@@ -128,7 +128,7 @@ static int nfs_stat_to_errno(int);
 #define decode_link_maxsz      (op_decode_hdr_maxsz + 5)
 #define encode_symlink_maxsz   (op_encode_hdr_maxsz + \
                                1 + nfs4_name_maxsz + \
-                               nfs4_path_maxsz + \
+                               1 + \
                                nfs4_fattr_maxsz)
 #define decode_symlink_maxsz   (op_decode_hdr_maxsz + 8)
 #define encode_create_maxsz    (op_encode_hdr_maxsz + \
@@ -529,7 +529,7 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s
        if (iap->ia_valid & ATTR_MODE)
                len += 4;
        if (iap->ia_valid & ATTR_UID) {
-               owner_namelen = nfs_map_uid_to_name(server->nfs4_state, iap->ia_uid, owner_name);
+               owner_namelen = nfs_map_uid_to_name(server->nfs_client, iap->ia_uid, owner_name);
                if (owner_namelen < 0) {
                        printk(KERN_WARNING "nfs: couldn't resolve uid %d to string\n",
                               iap->ia_uid);
@@ -541,7 +541,7 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s
                len += 4 + (XDR_QUADLEN(owner_namelen) << 2);
        }
        if (iap->ia_valid & ATTR_GID) {
-               owner_grouplen = nfs_map_gid_to_group(server->nfs4_state, iap->ia_gid, owner_group);
+               owner_grouplen = nfs_map_gid_to_group(server->nfs_client, iap->ia_gid, owner_group);
                if (owner_grouplen < 0) {
                        printk(KERN_WARNING "nfs4: couldn't resolve gid %d to string\n",
                               iap->ia_gid);
@@ -673,9 +673,9 @@ static int encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *c
 
        switch (create->ftype) {
        case NF4LNK:
-               RESERVE_SPACE(4 + create->u.symlink->len);
-               WRITE32(create->u.symlink->len);
-               WRITEMEM(create->u.symlink->name, create->u.symlink->len);
+               RESERVE_SPACE(4);
+               WRITE32(create->u.symlink.len);
+               xdr_write_pages(xdr, create->u.symlink.pages, 0, create->u.symlink.len);
                break;
 
        case NF4BLK: case NF4CHR:
@@ -731,6 +731,13 @@ static int encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask)
                        bitmask[1] & nfs4_fsinfo_bitmap[1]);
 }
 
+static int encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask)
+{
+       return encode_getattr_two(xdr,
+                                 bitmask[0] & nfs4_fs_locations_bitmap[0],
+                                 bitmask[1] & nfs4_fs_locations_bitmap[1]);
+}
+
 static int encode_getfh(struct xdr_stream *xdr)
 {
        uint32_t *p;
@@ -1153,7 +1160,7 @@ static int encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, con
        return 0;
 }
 
-static int encode_renew(struct xdr_stream *xdr, const struct nfs4_client *client_stateid)
+static int encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid)
 {
        uint32_t *p;
 
@@ -1239,7 +1246,7 @@ static int encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclien
        return 0;
 }
 
-static int encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4_client *client_state)
+static int encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_client *client_state)
 {
         uint32_t *p;
 
@@ -1938,7 +1945,7 @@ static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, uint32_t *p, const str
 /*
  * a RENEW request
  */
-static int nfs4_xdr_enc_renew(struct rpc_rqst *req, uint32_t *p, struct nfs4_client *clp)
+static int nfs4_xdr_enc_renew(struct rpc_rqst *req, uint32_t *p, struct nfs_client *clp)
 {
        struct xdr_stream xdr;
        struct compound_hdr hdr = {
@@ -1968,7 +1975,7 @@ static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, uint32_t *p, struct nf
 /*
  * a SETCLIENTID_CONFIRM request
  */
-static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, struct nfs4_client *clp)
+static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, struct nfs_client *clp)
 {
        struct xdr_stream xdr;
        struct compound_hdr hdr = {
@@ -2030,10 +2037,10 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, uint32_t *p, struct n
                goto out;
        if ((status = encode_lookup(&xdr, args->name)) != 0)
                goto out;
-       if ((status = encode_getfattr(&xdr, args->bitmask)) != 0)
+       if ((status = encode_fs_locations(&xdr, args->bitmask)) != 0)
                goto out;
        /* set up reply
-        *   toplevel_status + taglen + rescount + OP_PUTFH + status
+        *   toplevel_status + OP_PUTFH + status
         *   + OP_LOOKUP + status + OP_GETATTR + status = 7
         */
        replen = (RPC_REPHDRSIZE + auth->au_rslack + 7) << 2;
@@ -2120,12 +2127,12 @@ static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
        }
        READ32(nfserr);
        if (nfserr != NFS_OK)
-               return -nfs_stat_to_errno(nfserr);
+               return -nfs4_stat_to_errno(nfserr);
        return 0;
 }
 
 /* Dummy routine */
-static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs4_client *clp)
+static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs_client *clp)
 {
        uint32_t *p;
        unsigned int strlen;
@@ -2326,6 +2333,22 @@ static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t
        return 0;
 }
 
+static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
+{
+       uint32_t *p;
+
+       *fileid = 0;
+       if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U)))
+               return -EIO;
+       if (likely(bitmap[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) {
+               READ_BUF(8);
+               READ64(*fileid);
+               bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
+       }
+       dprintk("%s: fileid=%Lu\n", __FUNCTION__, (unsigned long long)*fileid);
+       return 0;
+}
+
 static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
 {
        uint32_t *p;
@@ -2385,8 +2408,10 @@ static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
 
        READ_BUF(4);
        READ32(n);
-       if (n <= 0)
+       if (n < 0)
                goto out_eio;
+       if (n == 0)
+               goto root_path;
        dprintk("path ");
        path->ncomponents = 0;
        while (path->ncomponents < n) {
@@ -2407,6 +2432,13 @@ static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
 out:
        dprintk("\n");
        return status;
+root_path:
+/* a root pathname is sent as a zero component4 */
+       path->ncomponents = 1;
+       path->components[0].len=0;
+       path->components[0].data=NULL;
+       dprintk("path /\n");
+       goto out;
 out_eio:
        dprintk(" status %d", status);
        status = -EIO;
@@ -2604,7 +2636,7 @@ static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t
        return 0;
 }
 
-static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_client *clp, int32_t *uid)
+static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, int32_t *uid)
 {
        uint32_t len, *p;
 
@@ -2628,7 +2660,7 @@ static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nf
        return 0;
 }
 
-static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_client *clp, int32_t *gid)
+static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, int32_t *gid)
 {
        uint32_t len, *p;
 
@@ -2983,6 +3015,7 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons
                 bitmap[2] = {0},
                 type;
        int status, fmode = 0;
+       uint64_t fileid;
 
        if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
                goto xdr_error;
@@ -3018,9 +3051,9 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons
        fattr->mode |= fmode;
        if ((status = decode_attr_nlink(xdr, bitmap, &fattr->nlink)) != 0)
                goto xdr_error;
-       if ((status = decode_attr_owner(xdr, bitmap, server->nfs4_state, &fattr->uid)) != 0)
+       if ((status = decode_attr_owner(xdr, bitmap, server->nfs_client, &fattr->uid)) != 0)
                goto xdr_error;
-       if ((status = decode_attr_group(xdr, bitmap, server->nfs4_state, &fattr->gid)) != 0)
+       if ((status = decode_attr_group(xdr, bitmap, server->nfs_client, &fattr->gid)) != 0)
                goto xdr_error;
        if ((status = decode_attr_rdev(xdr, bitmap, &fattr->rdev)) != 0)
                goto xdr_error;
@@ -3032,6 +3065,10 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons
                goto xdr_error;
        if ((status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime)) != 0)
                goto xdr_error;
+       if ((status = decode_attr_mounted_on_fileid(xdr, bitmap, &fileid)) != 0)
+               goto xdr_error;
+       if (fattr->fileid == 0 && fileid != 0)
+               fattr->fileid = fileid;
        if ((status = verify_attr_len(xdr, savep, attrlen)) == 0)
                fattr->valid = NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4;
 xdr_error:
@@ -3217,7 +3254,7 @@ static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
                        if (decode_space_limit(xdr, &res->maxsize) < 0)
                                return -EIO;
        }
-       return decode_ace(xdr, NULL, res->server->nfs4_state);
+       return decode_ace(xdr, NULL, res->server->nfs_client);
 }
 
 static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
@@ -3318,7 +3355,7 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
        struct kvec     *iov = rcvbuf->head;
        unsigned int    nr, pglen = rcvbuf->page_len;
        uint32_t        *end, *entry, *p, *kaddr;
-       uint32_t        len, attrlen;
+       uint32_t        len, attrlen, xlen;
        int             hdrlen, recvd, status;
 
        status = decode_op_hdr(xdr, OP_READDIR);
@@ -3340,10 +3377,10 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
 
        BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE);
        kaddr = p = (uint32_t *) kmap_atomic(page, KM_USER0);
-       end = (uint32_t *) ((char *)p + pglen + readdir->pgbase);
+       end = p + ((pglen + readdir->pgbase) >> 2);
        entry = p;
        for (nr = 0; *p++; nr++) {
-               if (p + 3 > end)
+               if (end - p < 3)
                        goto short_pkt;
                dprintk("cookie = %Lu, ", *((unsigned long long *)p));
                p += 2;                 /* cookie */
@@ -3352,18 +3389,19 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
                        printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len);
                        goto err_unmap;
                }
-               dprintk("filename = %*s\n", len, (char *)p);
-               p += XDR_QUADLEN(len);
-               if (p + 1 > end)
+               xlen = XDR_QUADLEN(len);
+               if (end - p < xlen + 1)
                        goto short_pkt;
+               dprintk("filename = %*s\n", len, (char *)p);
+               p += xlen;
                len = ntohl(*p++);      /* bitmap length */
-               p += len;
-               if (p + 1 > end)
+               if (end - p < len + 1)
                        goto short_pkt;
+               p += len;
                attrlen = XDR_QUADLEN(ntohl(*p++));
-               p += attrlen;           /* attributes */
-               if (p + 2 > end)
+               if (end - p < attrlen + 2)
                        goto short_pkt;
+               p += attrlen;           /* attributes */
                entry = p;
        }
        if (!nr && (entry[0] != 0 || entry[1] == 0))
@@ -3527,7 +3565,7 @@ static int decode_setattr(struct xdr_stream *xdr, struct nfs_setattrres *res)
        return 0;
 }
 
-static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_client *clp)
+static int decode_setclientid(struct xdr_stream *xdr, struct nfs_client *clp)
 {
        uint32_t *p;
        uint32_t opnum;
@@ -3560,7 +3598,7 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_client *clp)
                READ_BUF(len);
                return -NFSERR_CLID_INUSE;
        } else
-               return -nfs_stat_to_errno(nfserr);
+               return -nfs4_stat_to_errno(nfserr);
 
        return 0;
 }
@@ -4218,7 +4256,7 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, uint32_t *p, struct nfs_fsi
        if (!status)
                status = decode_fsinfo(&xdr, fsinfo);
        if (!status)
-               status = -nfs_stat_to_errno(hdr.status);
+               status = -nfs4_stat_to_errno(hdr.status);
        return status;
 }
 
@@ -4297,7 +4335,7 @@ static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, uint32_t *p, void *dummy)
  * a SETCLIENTID request
  */
 static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, uint32_t *p,
-               struct nfs4_client *clp)
+               struct nfs_client *clp)
 {
        struct xdr_stream xdr;
        struct compound_hdr hdr;
@@ -4308,7 +4346,7 @@ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, uint32_t *p,
        if (!status)
                status = decode_setclientid(&xdr, clp);
        if (!status)
-               status = -nfs_stat_to_errno(hdr.status);
+               status = -nfs4_stat_to_errno(hdr.status);
        return status;
 }
 
@@ -4330,7 +4368,7 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, s
        if (!status)
                status = decode_fsinfo(&xdr, fsinfo);
        if (!status)
-               status = -nfs_stat_to_errno(hdr.status);
+               status = -nfs4_stat_to_errno(hdr.status);
        return status;
 }
 
@@ -4483,7 +4521,7 @@ static struct {
  * This one is used jointly by NFSv2 and NFSv3.
  */
 static int
-nfs_stat_to_errno(int stat)
+nfs4_stat_to_errno(int stat)
 {
        int i;
        for (i = 0; nfs_errtbl[i].stat != -1; i++) {