aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2013-08-27 21:32:25 -0400
committerJ. Bruce Fields <bfields@redhat.com>2014-05-28 14:52:34 -0400
commitddd1ea56367202f6c99135cd59de7a97af4c4ffd (patch)
tree623a164aed98fb1d4a3d7ecc337acc88a5b27fec
parent5f4ab9458755eddc66912a15319363bf311f7fc8 (diff)
nfsd4: use xdr_reserve_space in attribute encoding
This is a cosmetic change for now; no change in behavior. Note we're just depending on xdr_reserve_space to do the bounds checking for us, we're not really depending on its adjustment of iovec or xdr_buf lengths yet, as those are fixed up by as necessary after the fact by read-link operations and by nfs4svc_encode_compoundres. However we do have to update xdr->iov on read-like operations to prevent xdr_reserve_space from messing with the already-fixed-up length of the the head. When the attribute encoding fails partway through we have to undo the length adjustments made so far. We do it manually for now, but later patches will add an xdr_truncate_encode() helper to handle cases like this. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r--fs/nfsd/acl.h2
-rw-r--r--fs/nfsd/idmap.h4
-rw-r--r--fs/nfsd/nfs4acl.c11
-rw-r--r--fs/nfsd/nfs4idmap.c42
-rw-r--r--fs/nfsd/nfs4proc.c1
-rw-r--r--fs/nfsd/nfs4xdr.c288
6 files changed, 203 insertions, 145 deletions
diff --git a/fs/nfsd/acl.h b/fs/nfsd/acl.h
index b481e1f5eecc..a986ceb6fd0d 100644
--- a/fs/nfsd/acl.h
+++ b/fs/nfsd/acl.h
@@ -49,7 +49,7 @@ struct svc_rqst;
49 49
50struct nfs4_acl *nfs4_acl_new(int); 50struct nfs4_acl *nfs4_acl_new(int);
51int nfs4_acl_get_whotype(char *, u32); 51int nfs4_acl_get_whotype(char *, u32);
52__be32 nfs4_acl_write_who(int who, __be32 **p, int *len); 52__be32 nfs4_acl_write_who(struct xdr_stream *xdr, int who);
53 53
54int nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, 54int nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
55 struct nfs4_acl **acl); 55 struct nfs4_acl **acl);
diff --git a/fs/nfsd/idmap.h b/fs/nfsd/idmap.h
index 66e58db01936..a3f34900091f 100644
--- a/fs/nfsd/idmap.h
+++ b/fs/nfsd/idmap.h
@@ -56,7 +56,7 @@ static inline void nfsd_idmap_shutdown(struct net *net)
56 56
57__be32 nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, kuid_t *); 57__be32 nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, kuid_t *);
58__be32 nfsd_map_name_to_gid(struct svc_rqst *, const char *, size_t, kgid_t *); 58__be32 nfsd_map_name_to_gid(struct svc_rqst *, const char *, size_t, kgid_t *);
59__be32 nfsd4_encode_user(struct svc_rqst *, kuid_t, __be32 **, int *); 59__be32 nfsd4_encode_user(struct xdr_stream *, struct svc_rqst *, kuid_t);
60__be32 nfsd4_encode_group(struct svc_rqst *, kgid_t, __be32 **, int *); 60__be32 nfsd4_encode_group(struct xdr_stream *, struct svc_rqst *, kgid_t);
61 61
62#endif /* LINUX_NFSD_IDMAP_H */ 62#endif /* LINUX_NFSD_IDMAP_H */
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 7c7c02554a81..d714156a19fd 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -919,20 +919,19 @@ nfs4_acl_get_whotype(char *p, u32 len)
919 return NFS4_ACL_WHO_NAMED; 919 return NFS4_ACL_WHO_NAMED;
920} 920}
921 921
922__be32 nfs4_acl_write_who(int who, __be32 **p, int *len) 922__be32 nfs4_acl_write_who(struct xdr_stream *xdr, int who)
923{ 923{
924 __be32 *p;
924 int i; 925 int i;
925 int bytes;
926 926
927 for (i = 0; i < ARRAY_SIZE(s2t_map); i++) { 927 for (i = 0; i < ARRAY_SIZE(s2t_map); i++) {
928 if (s2t_map[i].type != who) 928 if (s2t_map[i].type != who)
929 continue; 929 continue;
930 bytes = 4 + (XDR_QUADLEN(s2t_map[i].stringlen) << 2); 930 p = xdr_reserve_space(xdr, s2t_map[i].stringlen + 4);
931 if (bytes > *len) 931 if (!p)
932 return nfserr_resource; 932 return nfserr_resource;
933 *p = xdr_encode_opaque(*p, s2t_map[i].string, 933 p = xdr_encode_opaque(p, s2t_map[i].string,
934 s2t_map[i].stringlen); 934 s2t_map[i].stringlen);
935 *len -= bytes;
936 return 0; 935 return 0;
937 } 936 }
938 WARN_ON_ONCE(1); 937 WARN_ON_ONCE(1);
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index c0dfde68742e..a0ab0a847d69 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -551,44 +551,43 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen
551 return 0; 551 return 0;
552} 552}
553 553
554static __be32 encode_ascii_id(u32 id, __be32 **p, int *buflen) 554static __be32 encode_ascii_id(struct xdr_stream *xdr, u32 id)
555{ 555{
556 char buf[11]; 556 char buf[11];
557 int len; 557 int len;
558 int bytes; 558 __be32 *p;
559 559
560 len = sprintf(buf, "%u", id); 560 len = sprintf(buf, "%u", id);
561 bytes = 4 + (XDR_QUADLEN(len) << 2); 561 p = xdr_reserve_space(xdr, len + 4);
562 if (bytes > *buflen) 562 if (!p)
563 return nfserr_resource; 563 return nfserr_resource;
564 *p = xdr_encode_opaque(*p, buf, len); 564 p = xdr_encode_opaque(p, buf, len);
565 *buflen -= bytes;
566 return 0; 565 return 0;
567} 566}
568 567
569static __be32 idmap_id_to_name(struct svc_rqst *rqstp, int type, u32 id, __be32 **p, int *buflen) 568static __be32 idmap_id_to_name(struct xdr_stream *xdr,
569 struct svc_rqst *rqstp, int type, u32 id)
570{ 570{
571 struct ent *item, key = { 571 struct ent *item, key = {
572 .id = id, 572 .id = id,
573 .type = type, 573 .type = type,
574 }; 574 };
575 __be32 *p;
575 int ret; 576 int ret;
576 int bytes;
577 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 577 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
578 578
579 strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); 579 strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
580 ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item); 580 ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item);
581 if (ret == -ENOENT) 581 if (ret == -ENOENT)
582 return encode_ascii_id(id, p, buflen); 582 return encode_ascii_id(xdr, id);
583 if (ret) 583 if (ret)
584 return nfserrno(ret); 584 return nfserrno(ret);
585 ret = strlen(item->name); 585 ret = strlen(item->name);
586 WARN_ON_ONCE(ret > IDMAP_NAMESZ); 586 WARN_ON_ONCE(ret > IDMAP_NAMESZ);
587 bytes = 4 + (XDR_QUADLEN(ret) << 2); 587 p = xdr_reserve_space(xdr, ret + 4);
588 if (bytes > *buflen) 588 if (!p)
589 return nfserr_resource; 589 return nfserr_resource;
590 *p = xdr_encode_opaque(*p, item->name, ret); 590 p = xdr_encode_opaque(p, item->name, ret);
591 *buflen -= bytes;
592 cache_put(&item->h, nn->idtoname_cache); 591 cache_put(&item->h, nn->idtoname_cache);
593 return 0; 592 return 0;
594} 593}
@@ -622,11 +621,12 @@ do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, u
622 return idmap_name_to_id(rqstp, type, name, namelen, id); 621 return idmap_name_to_id(rqstp, type, name, namelen, id);
623} 622}
624 623
625static __be32 encode_name_from_id(struct svc_rqst *rqstp, int type, u32 id, __be32 **p, int *buflen) 624static __be32 encode_name_from_id(struct xdr_stream *xdr,
625 struct svc_rqst *rqstp, int type, u32 id)
626{ 626{
627 if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS) 627 if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS)
628 return encode_ascii_id(id, p, buflen); 628 return encode_ascii_id(xdr, id);
629 return idmap_id_to_name(rqstp, type, id, p, buflen); 629 return idmap_id_to_name(xdr, rqstp, type, id);
630} 630}
631 631
632__be32 632__be32
@@ -655,14 +655,16 @@ nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
655 return status; 655 return status;
656} 656}
657 657
658__be32 nfsd4_encode_user(struct svc_rqst *rqstp, kuid_t uid, __be32 **p, int *buflen) 658__be32 nfsd4_encode_user(struct xdr_stream *xdr, struct svc_rqst *rqstp,
659 kuid_t uid)
659{ 660{
660 u32 id = from_kuid(&init_user_ns, uid); 661 u32 id = from_kuid(&init_user_ns, uid);
661 return encode_name_from_id(rqstp, IDMAP_TYPE_USER, id, p, buflen); 662 return encode_name_from_id(xdr, rqstp, IDMAP_TYPE_USER, id);
662} 663}
663 664
664__be32 nfsd4_encode_group(struct svc_rqst *rqstp, kgid_t gid, __be32 **p, int *buflen) 665__be32 nfsd4_encode_group(struct xdr_stream *xdr, struct svc_rqst *rqstp,
666 kgid_t gid)
665{ 667{
666 u32 id = from_kgid(&init_user_ns, gid); 668 u32 id = from_kgid(&init_user_ns, gid);
667 return encode_name_from_id(rqstp, IDMAP_TYPE_GROUP, id, p, buflen); 669 return encode_name_from_id(xdr, rqstp, IDMAP_TYPE_GROUP, id);
668} 670}
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index bf8cddfdd3be..41c7c0a3ddd0 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1259,6 +1259,7 @@ static void svcxdr_init_encode(struct svc_rqst *rqstp,
1259 struct kvec *head = buf->head; 1259 struct kvec *head = buf->head;
1260 1260
1261 xdr->buf = buf; 1261 xdr->buf = buf;
1262 xdr->iov = head;
1262 xdr->p = head->iov_base + head->iov_len; 1263 xdr->p = head->iov_base + head->iov_len;
1263 xdr->end = head->iov_base + PAGE_SIZE - 2 * RPC_MAX_AUTH_SIZE; 1264 xdr->end = head->iov_base + PAGE_SIZE - 2 * RPC_MAX_AUTH_SIZE;
1264} 1265}
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 2ed803662b09..27d1e94f12fb 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1755,18 +1755,20 @@ static void write_cinfo(__be32 **p, struct nfsd4_change_info *c)
1755/* Encode as an array of strings the string given with components 1755/* Encode as an array of strings the string given with components
1756 * separated @sep, escaped with esc_enter and esc_exit. 1756 * separated @sep, escaped with esc_enter and esc_exit.
1757 */ 1757 */
1758static __be32 nfsd4_encode_components_esc(char sep, char *components, 1758static __be32 nfsd4_encode_components_esc(struct xdr_stream *xdr, char sep,
1759 __be32 **pp, int *buflen, 1759 char *components, char esc_enter,
1760 char esc_enter, char esc_exit) 1760 char esc_exit)
1761{ 1761{
1762 __be32 *p = *pp; 1762 __be32 *p;
1763 __be32 *countp = p; 1763 __be32 *countp;
1764 int strlen, count=0; 1764 int strlen, count=0;
1765 char *str, *end, *next; 1765 char *str, *end, *next;
1766 1766
1767 dprintk("nfsd4_encode_components(%s)\n", components); 1767 dprintk("nfsd4_encode_components(%s)\n", components);
1768 if ((*buflen -= 4) < 0) 1768 p = xdr_reserve_space(xdr, 4);
1769 if (!p)
1769 return nfserr_resource; 1770 return nfserr_resource;
1771 countp = p;
1770 WRITE32(0); /* We will fill this in with @count later */ 1772 WRITE32(0); /* We will fill this in with @count later */
1771 end = str = components; 1773 end = str = components;
1772 while (*end) { 1774 while (*end) {
@@ -1789,7 +1791,8 @@ static __be32 nfsd4_encode_components_esc(char sep, char *components,
1789 1791
1790 strlen = end - str; 1792 strlen = end - str;
1791 if (strlen) { 1793 if (strlen) {
1792 if ((*buflen -= ((XDR_QUADLEN(strlen) << 2) + 4)) < 0) 1794 p = xdr_reserve_space(xdr, strlen + 4);
1795 if (!p)
1793 return nfserr_resource; 1796 return nfserr_resource;
1794 WRITE32(strlen); 1797 WRITE32(strlen);
1795 WRITEMEM(str, strlen); 1798 WRITEMEM(str, strlen);
@@ -1799,7 +1802,6 @@ static __be32 nfsd4_encode_components_esc(char sep, char *components,
1799 end++; 1802 end++;
1800 str = end; 1803 str = end;
1801 } 1804 }
1802 *pp = p;
1803 p = countp; 1805 p = countp;
1804 WRITE32(count); 1806 WRITE32(count);
1805 return 0; 1807 return 0;
@@ -1808,40 +1810,39 @@ static __be32 nfsd4_encode_components_esc(char sep, char *components,
1808/* Encode as an array of strings the string given with components 1810/* Encode as an array of strings the string given with components
1809 * separated @sep. 1811 * separated @sep.
1810 */ 1812 */
1811static __be32 nfsd4_encode_components(char sep, char *components, 1813static __be32 nfsd4_encode_components(struct xdr_stream *xdr, char sep,
1812 __be32 **pp, int *buflen) 1814 char *components)
1813{ 1815{
1814 return nfsd4_encode_components_esc(sep, components, pp, buflen, 0, 0); 1816 return nfsd4_encode_components_esc(xdr, sep, components, 0, 0);
1815} 1817}
1816 1818
1817/* 1819/*
1818 * encode a location element of a fs_locations structure 1820 * encode a location element of a fs_locations structure
1819 */ 1821 */
1820static __be32 nfsd4_encode_fs_location4(struct nfsd4_fs_location *location, 1822static __be32 nfsd4_encode_fs_location4(struct xdr_stream *xdr,
1821 __be32 **pp, int *buflen) 1823 struct nfsd4_fs_location *location)
1822{ 1824{
1823 __be32 status; 1825 __be32 status;
1824 __be32 *p = *pp;
1825 1826
1826 status = nfsd4_encode_components_esc(':', location->hosts, &p, buflen, 1827 status = nfsd4_encode_components_esc(xdr, ':', location->hosts,
1827 '[', ']'); 1828 '[', ']');
1828 if (status) 1829 if (status)
1829 return status; 1830 return status;
1830 status = nfsd4_encode_components('/', location->path, &p, buflen); 1831 status = nfsd4_encode_components(xdr, '/', location->path);
1831 if (status) 1832 if (status)
1832 return status; 1833 return status;
1833 *pp = p;
1834 return 0; 1834 return 0;
1835} 1835}
1836 1836
1837/* 1837/*
1838 * Encode a path in RFC3530 'pathname4' format 1838 * Encode a path in RFC3530 'pathname4' format
1839 */ 1839 */
1840static __be32 nfsd4_encode_path(const struct path *root, 1840static __be32 nfsd4_encode_path(struct xdr_stream *xdr,
1841 const struct path *path, __be32 **pp, int *buflen) 1841 const struct path *root,
1842 const struct path *path)
1842{ 1843{
1843 struct path cur = *path; 1844 struct path cur = *path;
1844 __be32 *p = *pp; 1845 __be32 *p;
1845 struct dentry **components = NULL; 1846 struct dentry **components = NULL;
1846 unsigned int ncomponents = 0; 1847 unsigned int ncomponents = 0;
1847 __be32 err = nfserr_jukebox; 1848 __be32 err = nfserr_jukebox;
@@ -1872,9 +1873,9 @@ static __be32 nfsd4_encode_path(const struct path *root,
1872 components[ncomponents++] = cur.dentry; 1873 components[ncomponents++] = cur.dentry;
1873 cur.dentry = dget_parent(cur.dentry); 1874 cur.dentry = dget_parent(cur.dentry);
1874 } 1875 }
1875 1876 err = nfserr_resource;
1876 *buflen -= 4; 1877 p = xdr_reserve_space(xdr, 4);
1877 if (*buflen < 0) 1878 if (!p)
1878 goto out_free; 1879 goto out_free;
1879 WRITE32(ncomponents); 1880 WRITE32(ncomponents);
1880 1881
@@ -1884,8 +1885,8 @@ static __be32 nfsd4_encode_path(const struct path *root,
1884 1885
1885 spin_lock(&dentry->d_lock); 1886 spin_lock(&dentry->d_lock);
1886 len = dentry->d_name.len; 1887 len = dentry->d_name.len;
1887 *buflen -= 4 + (XDR_QUADLEN(len) << 2); 1888 p = xdr_reserve_space(xdr, len + 4);
1888 if (*buflen < 0) { 1889 if (!p) {
1889 spin_unlock(&dentry->d_lock); 1890 spin_unlock(&dentry->d_lock);
1890 goto out_free; 1891 goto out_free;
1891 } 1892 }
@@ -1897,7 +1898,6 @@ static __be32 nfsd4_encode_path(const struct path *root,
1897 ncomponents--; 1898 ncomponents--;
1898 } 1899 }
1899 1900
1900 *pp = p;
1901 err = 0; 1901 err = 0;
1902out_free: 1902out_free:
1903 dprintk(")\n"); 1903 dprintk(")\n");
@@ -1908,8 +1908,8 @@ out_free:
1908 return err; 1908 return err;
1909} 1909}
1910 1910
1911static __be32 nfsd4_encode_fsloc_fsroot(struct svc_rqst *rqstp, 1911static __be32 nfsd4_encode_fsloc_fsroot(struct xdr_stream *xdr,
1912 const struct path *path, __be32 **pp, int *buflen) 1912 struct svc_rqst *rqstp, const struct path *path)
1913{ 1913{
1914 struct svc_export *exp_ps; 1914 struct svc_export *exp_ps;
1915 __be32 res; 1915 __be32 res;
@@ -1917,7 +1917,7 @@ static __be32 nfsd4_encode_fsloc_fsroot(struct svc_rqst *rqstp,
1917 exp_ps = rqst_find_fsidzero_export(rqstp); 1917 exp_ps = rqst_find_fsidzero_export(rqstp);
1918 if (IS_ERR(exp_ps)) 1918 if (IS_ERR(exp_ps))
1919 return nfserrno(PTR_ERR(exp_ps)); 1919 return nfserrno(PTR_ERR(exp_ps));
1920 res = nfsd4_encode_path(&exp_ps->ex_path, path, pp, buflen); 1920 res = nfsd4_encode_path(xdr, &exp_ps->ex_path, path);
1921 exp_put(exp_ps); 1921 exp_put(exp_ps);
1922 return res; 1922 return res;
1923} 1923}
@@ -1925,28 +1925,26 @@ static __be32 nfsd4_encode_fsloc_fsroot(struct svc_rqst *rqstp,
1925/* 1925/*
1926 * encode a fs_locations structure 1926 * encode a fs_locations structure
1927 */ 1927 */
1928static __be32 nfsd4_encode_fs_locations(struct svc_rqst *rqstp, 1928static __be32 nfsd4_encode_fs_locations(struct xdr_stream *xdr,
1929 struct svc_export *exp, 1929 struct svc_rqst *rqstp, struct svc_export *exp)
1930 __be32 **pp, int *buflen)
1931{ 1930{
1932 __be32 status; 1931 __be32 status;
1933 int i; 1932 int i;
1934 __be32 *p = *pp; 1933 __be32 *p;
1935 struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs; 1934 struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs;
1936 1935
1937 status = nfsd4_encode_fsloc_fsroot(rqstp, &exp->ex_path, &p, buflen); 1936 status = nfsd4_encode_fsloc_fsroot(xdr, rqstp, &exp->ex_path);
1938 if (status) 1937 if (status)
1939 return status; 1938 return status;
1940 if ((*buflen -= 4) < 0) 1939 p = xdr_reserve_space(xdr, 4);
1940 if (!p)
1941 return nfserr_resource; 1941 return nfserr_resource;
1942 WRITE32(fslocs->locations_count); 1942 WRITE32(fslocs->locations_count);
1943 for (i=0; i<fslocs->locations_count; i++) { 1943 for (i=0; i<fslocs->locations_count; i++) {
1944 status = nfsd4_encode_fs_location4(&fslocs->locations[i], 1944 status = nfsd4_encode_fs_location4(xdr, &fslocs->locations[i]);
1945 &p, buflen);
1946 if (status) 1945 if (status)
1947 return status; 1946 return status;
1948 } 1947 }
1949 *pp = p;
1950 return 0; 1948 return 0;
1951} 1949}
1952 1950
@@ -1965,15 +1963,15 @@ static u32 nfs4_file_type(umode_t mode)
1965} 1963}
1966 1964
1967static inline __be32 1965static inline __be32
1968nfsd4_encode_aclname(struct svc_rqst *rqstp, struct nfs4_ace *ace, 1966nfsd4_encode_aclname(struct xdr_stream *xdr, struct svc_rqst *rqstp,
1969 __be32 **p, int *buflen) 1967 struct nfs4_ace *ace)
1970{ 1968{
1971 if (ace->whotype != NFS4_ACL_WHO_NAMED) 1969 if (ace->whotype != NFS4_ACL_WHO_NAMED)
1972 return nfs4_acl_write_who(ace->whotype, p, buflen); 1970 return nfs4_acl_write_who(xdr, ace->whotype);
1973 else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP) 1971 else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
1974 return nfsd4_encode_group(rqstp, ace->who_gid, p, buflen); 1972 return nfsd4_encode_group(xdr, rqstp, ace->who_gid);
1975 else 1973 else
1976 return nfsd4_encode_user(rqstp, ace->who_uid, p, buflen); 1974 return nfsd4_encode_user(xdr, rqstp, ace->who_uid);
1977} 1975}
1978 1976
1979#define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \ 1977#define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \
@@ -1982,31 +1980,28 @@ nfsd4_encode_aclname(struct svc_rqst *rqstp, struct nfs4_ace *ace,
1982 1980
1983#ifdef CONFIG_NFSD_V4_SECURITY_LABEL 1981#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
1984static inline __be32 1982static inline __be32
1985nfsd4_encode_security_label(struct svc_rqst *rqstp, void *context, int len, __be32 **pp, int *buflen) 1983nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
1984 void *context, int len)
1986{ 1985{
1987 __be32 *p = *pp; 1986 __be32 *p;
1988 1987
1989 if (*buflen < ((XDR_QUADLEN(len) << 2) + 4 + 4 + 4)) 1988 p = xdr_reserve_space(xdr, len + 4 + 4 + 4);
1989 if (!p)
1990 return nfserr_resource; 1990 return nfserr_resource;
1991 1991
1992 /* 1992 /*
1993 * For now we use a 0 here to indicate the null translation; in 1993 * For now we use a 0 here to indicate the null translation; in
1994 * the future we may place a call to translation code here. 1994 * the future we may place a call to translation code here.
1995 */ 1995 */
1996 if ((*buflen -= 8) < 0)
1997 return nfserr_resource;
1998
1999 WRITE32(0); /* lfs */ 1996 WRITE32(0); /* lfs */
2000 WRITE32(0); /* pi */ 1997 WRITE32(0); /* pi */
2001 p = xdr_encode_opaque(p, context, len); 1998 p = xdr_encode_opaque(p, context, len);
2002 *buflen -= (XDR_QUADLEN(len) << 2) + 4;
2003
2004 *pp = p;
2005 return 0; 1999 return 0;
2006} 2000}
2007#else 2001#else
2008static inline __be32 2002static inline __be32
2009nfsd4_encode_security_label(struct svc_rqst *rqstp, void *context, int len, __be32 **pp, int *buflen) 2003nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
2004 void *context, int len)
2010{ return 0; } 2005{ return 0; }
2011#endif 2006#endif
2012 2007
@@ -2058,8 +2053,8 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
2058 struct kstat stat; 2053 struct kstat stat;
2059 struct svc_fh *tempfh = NULL; 2054 struct svc_fh *tempfh = NULL;
2060 struct kstatfs statfs; 2055 struct kstatfs statfs;
2061 __be32 *p = xdr->p; 2056 __be32 *p;
2062 int buflen = xdr->buf->buflen; 2057 __be32 *start = xdr->p;
2063 __be32 *attrlenp; 2058 __be32 *attrlenp;
2064 u32 dummy; 2059 u32 dummy;
2065 u64 dummy64; 2060 u64 dummy64;
@@ -2144,24 +2139,30 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
2144#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */ 2139#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
2145 2140
2146 if (bmval2) { 2141 if (bmval2) {
2147 if ((buflen -= 16) < 0) 2142 p = xdr_reserve_space(xdr, 16);
2143 if (!p)
2148 goto out_resource; 2144 goto out_resource;
2149 WRITE32(3); 2145 WRITE32(3);
2150 WRITE32(bmval0); 2146 WRITE32(bmval0);
2151 WRITE32(bmval1); 2147 WRITE32(bmval1);
2152 WRITE32(bmval2); 2148 WRITE32(bmval2);
2153 } else if (bmval1) { 2149 } else if (bmval1) {
2154 if ((buflen -= 12) < 0) 2150 p = xdr_reserve_space(xdr, 12);
2151 if (!p)
2155 goto out_resource; 2152 goto out_resource;
2156 WRITE32(2); 2153 WRITE32(2);
2157 WRITE32(bmval0); 2154 WRITE32(bmval0);
2158 WRITE32(bmval1); 2155 WRITE32(bmval1);
2159 } else { 2156 } else {
2160 if ((buflen -= 8) < 0) 2157 p = xdr_reserve_space(xdr, 8);
2158 if (!p)
2161 goto out_resource; 2159 goto out_resource;
2162 WRITE32(1); 2160 WRITE32(1);
2163 WRITE32(bmval0); 2161 WRITE32(bmval0);
2164 } 2162 }
2163 p = xdr_reserve_space(xdr, 4);
2164 if (!p)
2165 goto out_resource;
2165 attrlenp = p++; /* to be backfilled later */ 2166 attrlenp = p++; /* to be backfilled later */
2166 2167
2167 if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) { 2168 if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
@@ -2174,13 +2175,15 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
2174 if (!contextsupport) 2175 if (!contextsupport)
2175 word2 &= ~FATTR4_WORD2_SECURITY_LABEL; 2176 word2 &= ~FATTR4_WORD2_SECURITY_LABEL;
2176 if (!word2) { 2177 if (!word2) {
2177 if ((buflen -= 12) < 0) 2178 p = xdr_reserve_space(xdr, 12);
2179 if (!p)
2178 goto out_resource; 2180 goto out_resource;
2179 WRITE32(2); 2181 WRITE32(2);
2180 WRITE32(word0); 2182 WRITE32(word0);
2181 WRITE32(word1); 2183 WRITE32(word1);
2182 } else { 2184 } else {
2183 if ((buflen -= 16) < 0) 2185 p = xdr_reserve_space(xdr, 16);
2186 if (!p)
2184 goto out_resource; 2187 goto out_resource;
2185 WRITE32(3); 2188 WRITE32(3);
2186 WRITE32(word0); 2189 WRITE32(word0);
@@ -2189,7 +2192,8 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
2189 } 2192 }
2190 } 2193 }
2191 if (bmval0 & FATTR4_WORD0_TYPE) { 2194 if (bmval0 & FATTR4_WORD0_TYPE) {
2192 if ((buflen -= 4) < 0) 2195 p = xdr_reserve_space(xdr, 4);
2196 if (!p)
2193 goto out_resource; 2197 goto out_resource;
2194 dummy = nfs4_file_type(stat.mode); 2198 dummy = nfs4_file_type(stat.mode);
2195 if (dummy == NF4BAD) { 2199 if (dummy == NF4BAD) {
@@ -2199,7 +2203,8 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
2199 WRITE32(dummy); 2203 WRITE32(dummy);
2200 } 2204 }
2201 if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) { 2205 if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) {
2202 if ((buflen -= 4) < 0) 2206 p = xdr_reserve_space(xdr, 4);
2207 if (!p)
2203 goto out_resource; 2208 goto out_resource;
2204 if (exp->ex_flags & NFSEXP_NOSUBTREECHECK) 2209 if (exp->ex_flags & NFSEXP_NOSUBTREECHECK)
2205 WRITE32(NFS4_FH_PERSISTENT); 2210 WRITE32(NFS4_FH_PERSISTENT);
@@ -2207,32 +2212,38 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
2207 WRITE32(NFS4_FH_PERSISTENT|NFS4_FH_VOL_RENAME); 2212 WRITE32(NFS4_FH_PERSISTENT|NFS4_FH_VOL_RENAME);
2208 } 2213 }
2209 if (bmval0 & FATTR4_WORD0_CHANGE) { 2214 if (bmval0 & FATTR4_WORD0_CHANGE) {
2210 if ((buflen -= 8) < 0) 2215 p = xdr_reserve_space(xdr, 8);
2216 if (!p)
2211 goto out_resource; 2217 goto out_resource;
2212 write_change(&p, &stat, dentry->d_inode); 2218 write_change(&p, &stat, dentry->d_inode);
2213 } 2219 }
2214 if (bmval0 & FATTR4_WORD0_SIZE) { 2220 if (bmval0 & FATTR4_WORD0_SIZE) {
2215 if ((buflen -= 8) < 0) 2221 p = xdr_reserve_space(xdr, 8);
2222 if (!p)
2216 goto out_resource; 2223 goto out_resource;
2217 WRITE64(stat.size); 2224 WRITE64(stat.size);
2218 } 2225 }
2219 if (bmval0 & FATTR4_WORD0_LINK_SUPPORT) { 2226 if (bmval0 & FATTR4_WORD0_LINK_SUPPORT) {
2220 if ((buflen -= 4) < 0) 2227 p = xdr_reserve_space(xdr, 4);
2228 if (!p)
2221 goto out_resource; 2229 goto out_resource;
2222 WRITE32(1); 2230 WRITE32(1);
2223 } 2231 }
2224 if (bmval0 & FATTR4_WORD0_SYMLINK_SUPPORT) { 2232 if (bmval0 & FATTR4_WORD0_SYMLINK_SUPPORT) {
2225 if ((buflen -= 4) < 0) 2233 p = xdr_reserve_space(xdr, 4);
2234 if (!p)
2226 goto out_resource; 2235 goto out_resource;
2227 WRITE32(1); 2236 WRITE32(1);
2228 } 2237 }
2229 if (bmval0 & FATTR4_WORD0_NAMED_ATTR) { 2238 if (bmval0 & FATTR4_WORD0_NAMED_ATTR) {
2230 if ((buflen -= 4) < 0) 2239 p = xdr_reserve_space(xdr, 4);
2240 if (!p)
2231 goto out_resource; 2241 goto out_resource;
2232 WRITE32(0); 2242 WRITE32(0);
2233 } 2243 }
2234 if (bmval0 & FATTR4_WORD0_FSID) { 2244 if (bmval0 & FATTR4_WORD0_FSID) {
2235 if ((buflen -= 16) < 0) 2245 p = xdr_reserve_space(xdr, 16);
2246 if (!p)
2236 goto out_resource; 2247 goto out_resource;
2237 if (exp->ex_fslocs.migrated) { 2248 if (exp->ex_fslocs.migrated) {
2238 WRITE64(NFS4_REFERRAL_FSID_MAJOR); 2249 WRITE64(NFS4_REFERRAL_FSID_MAJOR);
@@ -2254,17 +2265,20 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
2254 } 2265 }
2255 } 2266 }
2256 if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) { 2267 if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) {
2257 if ((buflen -= 4) < 0) 2268 p = xdr_reserve_space(xdr, 4);
2269 if (!p)
2258 goto out_resource; 2270 goto out_resource;
2259 WRITE32(0); 2271 WRITE32(0);
2260 } 2272 }
2261 if (bmval0 & FATTR4_WORD0_LEASE_TIME) { 2273 if (bmval0 & FATTR4_WORD0_LEASE_TIME) {
2262 if ((buflen -= 4) < 0) 2274 p = xdr_reserve_space(xdr, 4);
2275 if (!p)
2263 goto out_resource; 2276 goto out_resource;
2264 WRITE32(nn->nfsd4_lease); 2277 WRITE32(nn->nfsd4_lease);
2265 } 2278 }
2266 if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) { 2279 if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) {
2267 if ((buflen -= 4) < 0) 2280 p = xdr_reserve_space(xdr, 4);
2281 if (!p)
2268 goto out_resource; 2282 goto out_resource;
2269 WRITE32(rdattr_err); 2283 WRITE32(rdattr_err);
2270 } 2284 }
@@ -2272,198 +2286,229 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
2272 struct nfs4_ace *ace; 2286 struct nfs4_ace *ace;
2273 2287
2274 if (acl == NULL) { 2288 if (acl == NULL) {
2275 if ((buflen -= 4) < 0) 2289 p = xdr_reserve_space(xdr, 4);
2290 if (!p)
2276 goto out_resource; 2291 goto out_resource;
2277 2292
2278 WRITE32(0); 2293 WRITE32(0);
2279 goto out_acl; 2294 goto out_acl;
2280 } 2295 }
2281 if ((buflen -= 4) < 0) 2296 p = xdr_reserve_space(xdr, 4);
2297 if (!p)
2282 goto out_resource; 2298 goto out_resource;
2283 WRITE32(acl->naces); 2299 WRITE32(acl->naces);
2284 2300
2285 for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) { 2301 for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
2286 if ((buflen -= 4*3) < 0) 2302 p = xdr_reserve_space(xdr, 4*3);
2303 if (!p)
2287 goto out_resource; 2304 goto out_resource;
2288 WRITE32(ace->type); 2305 WRITE32(ace->type);
2289 WRITE32(ace->flag); 2306 WRITE32(ace->flag);
2290 WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL); 2307 WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL);
2291 status = nfsd4_encode_aclname(rqstp, ace, &p, &buflen); 2308 status = nfsd4_encode_aclname(xdr, rqstp, ace);
2292 if (status) 2309 if (status)
2293 goto out; 2310 goto out;
2294 } 2311 }
2295 } 2312 }
2296out_acl: 2313out_acl:
2297 if (bmval0 & FATTR4_WORD0_ACLSUPPORT) { 2314 if (bmval0 & FATTR4_WORD0_ACLSUPPORT) {
2298 if ((buflen -= 4) < 0) 2315 p = xdr_reserve_space(xdr, 4);
2316 if (!p)
2299 goto out_resource; 2317 goto out_resource;
2300 WRITE32(aclsupport ? 2318 WRITE32(aclsupport ?
2301 ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL : 0); 2319 ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL : 0);
2302 } 2320 }
2303 if (bmval0 & FATTR4_WORD0_CANSETTIME) { 2321 if (bmval0 & FATTR4_WORD0_CANSETTIME) {
2304 if ((buflen -= 4) < 0) 2322 p = xdr_reserve_space(xdr, 4);
2323 if (!p)
2305 goto out_resource; 2324 goto out_resource;
2306 WRITE32(1); 2325 WRITE32(1);
2307 } 2326 }
2308 if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) { 2327 if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) {
2309 if ((buflen -= 4) < 0) 2328 p = xdr_reserve_space(xdr, 4);
2329 if (!p)
2310 goto out_resource; 2330 goto out_resource;
2311 WRITE32(0); 2331 WRITE32(0);
2312 } 2332 }
2313 if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) { 2333 if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) {
2314 if ((buflen -= 4) < 0) 2334 p = xdr_reserve_space(xdr, 4);
2335 if (!p)
2315 goto out_resource; 2336 goto out_resource;
2316 WRITE32(1); 2337 WRITE32(1);
2317 } 2338 }
2318 if (bmval0 & FATTR4_WORD0_CHOWN_RESTRICTED) { 2339 if (bmval0 & FATTR4_WORD0_CHOWN_RESTRICTED) {
2319 if ((buflen -= 4) < 0) 2340 p = xdr_reserve_space(xdr, 4);
2341 if (!p)
2320 goto out_resource; 2342 goto out_resource;
2321 WRITE32(1); 2343 WRITE32(1);
2322 } 2344 }
2323 if (bmval0 & FATTR4_WORD0_FILEHANDLE) { 2345 if (bmval0 & FATTR4_WORD0_FILEHANDLE) {
2324 buflen -= (XDR_QUADLEN(fhp->fh_handle.fh_size) << 2) + 4; 2346 p = xdr_reserve_space(xdr, fhp->fh_handle.fh_size + 4);
2325 if (buflen < 0) 2347 if (!p)
2326 goto out_resource; 2348 goto out_resource;
2327 WRITE32(fhp->fh_handle.fh_size); 2349 WRITE32(fhp->fh_handle.fh_size);
2328 WRITEMEM(&fhp->fh_handle.fh_base, fhp->fh_handle.fh_size); 2350 WRITEMEM(&fhp->fh_handle.fh_base, fhp->fh_handle.fh_size);
2329 } 2351 }
2330 if (bmval0 & FATTR4_WORD0_FILEID) { 2352 if (bmval0 & FATTR4_WORD0_FILEID) {
2331 if ((buflen -= 8) < 0) 2353 p = xdr_reserve_space(xdr, 8);
2354 if (!p)
2332 goto out_resource; 2355 goto out_resource;
2333 WRITE64(stat.ino); 2356 WRITE64(stat.ino);
2334 } 2357 }
2335 if (bmval0 & FATTR4_WORD0_FILES_AVAIL) { 2358 if (bmval0 & FATTR4_WORD0_FILES_AVAIL) {
2336 if ((buflen -= 8) < 0) 2359 p = xdr_reserve_space(xdr, 8);
2360 if (!p)
2337 goto out_resource; 2361 goto out_resource;
2338 WRITE64((u64) statfs.f_ffree); 2362 WRITE64((u64) statfs.f_ffree);
2339 } 2363 }
2340 if (bmval0 & FATTR4_WORD0_FILES_FREE) { 2364 if (bmval0 & FATTR4_WORD0_FILES_FREE) {
2341 if ((buflen -= 8) < 0) 2365 p = xdr_reserve_space(xdr, 8);
2366 if (!p)
2342 goto out_resource; 2367 goto out_resource;
2343 WRITE64((u64) statfs.f_ffree); 2368 WRITE64((u64) statfs.f_ffree);
2344 } 2369 }
2345 if (bmval0 & FATTR4_WORD0_FILES_TOTAL) { 2370 if (bmval0 & FATTR4_WORD0_FILES_TOTAL) {
2346 if ((buflen -= 8) < 0) 2371 p = xdr_reserve_space(xdr, 8);
2372 if (!p)
2347 goto out_resource; 2373 goto out_resource;
2348 WRITE64((u64) statfs.f_files); 2374 WRITE64((u64) statfs.f_files);
2349 } 2375 }
2350 if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) { 2376 if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) {
2351 status = nfsd4_encode_fs_locations(rqstp, exp, &p, &buflen); 2377 status = nfsd4_encode_fs_locations(xdr, rqstp, exp);
2352 if (status) 2378 if (status)
2353 goto out; 2379 goto out;
2354 } 2380 }
2355 if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) { 2381 if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) {
2356 if ((buflen -= 4) < 0) 2382 p = xdr_reserve_space(xdr, 4);
2383 if (!p)
2357 goto out_resource; 2384 goto out_resource;
2358 WRITE32(1); 2385 WRITE32(1);
2359 } 2386 }
2360 if (bmval0 & FATTR4_WORD0_MAXFILESIZE) { 2387 if (bmval0 & FATTR4_WORD0_MAXFILESIZE) {
2361 if ((buflen -= 8) < 0) 2388 p = xdr_reserve_space(xdr, 8);
2389 if (!p)
2362 goto out_resource; 2390 goto out_resource;
2363 WRITE64(exp->ex_path.mnt->mnt_sb->s_maxbytes); 2391 WRITE64(exp->ex_path.mnt->mnt_sb->s_maxbytes);
2364 } 2392 }
2365 if (bmval0 & FATTR4_WORD0_MAXLINK) { 2393 if (bmval0 & FATTR4_WORD0_MAXLINK) {
2366 if ((buflen -= 4) < 0) 2394 p = xdr_reserve_space(xdr, 4);
2395 if (!p)
2367 goto out_resource; 2396 goto out_resource;
2368 WRITE32(255); 2397 WRITE32(255);
2369 } 2398 }
2370 if (bmval0 & FATTR4_WORD0_MAXNAME) { 2399 if (bmval0 & FATTR4_WORD0_MAXNAME) {
2371 if ((buflen -= 4) < 0) 2400 p = xdr_reserve_space(xdr, 4);
2401 if (!p)
2372 goto out_resource; 2402 goto out_resource;
2373 WRITE32(statfs.f_namelen); 2403 WRITE32(statfs.f_namelen);
2374 } 2404 }
2375 if (bmval0 & FATTR4_WORD0_MAXREAD) { 2405 if (bmval0 & FATTR4_WORD0_MAXREAD) {
2376 if ((buflen -= 8) < 0) 2406 p = xdr_reserve_space(xdr, 8);
2407 if (!p)
2377 goto out_resource; 2408 goto out_resource;
2378 WRITE64((u64) svc_max_payload(rqstp)); 2409 WRITE64((u64) svc_max_payload(rqstp));
2379 } 2410 }
2380 if (bmval0 & FATTR4_WORD0_MAXWRITE) { 2411 if (bmval0 & FATTR4_WORD0_MAXWRITE) {
2381 if ((buflen -= 8) < 0) 2412 p = xdr_reserve_space(xdr, 8);
2413 if (!p)
2382 goto out_resource; 2414 goto out_resource;
2383 WRITE64((u64) svc_max_payload(rqstp)); 2415 WRITE64((u64) svc_max_payload(rqstp));
2384 } 2416 }
2385 if (bmval1 & FATTR4_WORD1_MODE) { 2417 if (bmval1 & FATTR4_WORD1_MODE) {
2386 if ((buflen -= 4) < 0) 2418 p = xdr_reserve_space(xdr, 4);
2419 if (!p)
2387 goto out_resource; 2420 goto out_resource;
2388 WRITE32(stat.mode & S_IALLUGO); 2421 WRITE32(stat.mode & S_IALLUGO);
2389 } 2422 }
2390 if (bmval1 & FATTR4_WORD1_NO_TRUNC) { 2423 if (bmval1 & FATTR4_WORD1_NO_TRUNC) {
2391 if ((buflen -= 4) < 0) 2424 p = xdr_reserve_space(xdr, 4);
2425 if (!p)
2392 goto out_resource; 2426 goto out_resource;
2393 WRITE32(1); 2427 WRITE32(1);
2394 } 2428 }
2395 if (bmval1 & FATTR4_WORD1_NUMLINKS) { 2429 if (bmval1 & FATTR4_WORD1_NUMLINKS) {
2396 if ((buflen -= 4) < 0) 2430 p = xdr_reserve_space(xdr, 4);
2431 if (!p)
2397 goto out_resource; 2432 goto out_resource;
2398 WRITE32(stat.nlink); 2433 WRITE32(stat.nlink);
2399 } 2434 }
2400 if (bmval1 & FATTR4_WORD1_OWNER) { 2435 if (bmval1 & FATTR4_WORD1_OWNER) {
2401 status = nfsd4_encode_user(rqstp, stat.uid, &p, &buflen); 2436 status = nfsd4_encode_user(xdr, rqstp, stat.uid);
2402 if (status) 2437 if (status)
2403 goto out; 2438 goto out;
2404 } 2439 }
2405 if (bmval1 & FATTR4_WORD1_OWNER_GROUP) { 2440 if (bmval1 & FATTR4_WORD1_OWNER_GROUP) {
2406 status = nfsd4_encode_group(rqstp, stat.gid, &p, &buflen); 2441 status = nfsd4_encode_group(xdr, rqstp, stat.gid);
2407 if (status) 2442 if (status)
2408 goto out; 2443 goto out;
2409 } 2444 }
2410 if (bmval1 & FATTR4_WORD1_RAWDEV) { 2445 if (bmval1 & FATTR4_WORD1_RAWDEV) {
2411 if ((buflen -= 8) < 0) 2446 p = xdr_reserve_space(xdr, 8);
2447 if (!p)
2412 goto out_resource; 2448 goto out_resource;
2413 WRITE32((u32) MAJOR(stat.rdev)); 2449 WRITE32((u32) MAJOR(stat.rdev));
2414 WRITE32((u32) MINOR(stat.rdev)); 2450 WRITE32((u32) MINOR(stat.rdev));
2415 } 2451 }
2416 if (bmval1 & FATTR4_WORD1_SPACE_AVAIL) { 2452 if (bmval1 & FATTR4_WORD1_SPACE_AVAIL) {
2417 if ((buflen -= 8) < 0) 2453 p = xdr_reserve_space(xdr, 8);
2454 if (!p)
2418 goto out_resource; 2455 goto out_resource;
2419 dummy64 = (u64)statfs.f_bavail * (u64)statfs.f_bsize; 2456 dummy64 = (u64)statfs.f_bavail * (u64)statfs.f_bsize;
2420 WRITE64(dummy64); 2457 WRITE64(dummy64);
2421 } 2458 }
2422 if (bmval1 & FATTR4_WORD1_SPACE_FREE) { 2459 if (bmval1 & FATTR4_WORD1_SPACE_FREE) {
2423 if ((buflen -= 8) < 0) 2460 p = xdr_reserve_space(xdr, 8);
2461 if (!p)
2424 goto out_resource; 2462 goto out_resource;
2425 dummy64 = (u64)statfs.f_bfree * (u64)statfs.f_bsize; 2463 dummy64 = (u64)statfs.f_bfree * (u64)statfs.f_bsize;
2426 WRITE64(dummy64); 2464 WRITE64(dummy64);
2427 } 2465 }
2428 if (bmval1 & FATTR4_WORD1_SPACE_TOTAL) { 2466 if (bmval1 & FATTR4_WORD1_SPACE_TOTAL) {
2429 if ((buflen -= 8) < 0) 2467 p = xdr_reserve_space(xdr, 8);
2468 if (!p)
2430 goto out_resource; 2469 goto out_resource;
2431 dummy64 = (u64)statfs.f_blocks * (u64)statfs.f_bsize; 2470 dummy64 = (u64)statfs.f_blocks * (u64)statfs.f_bsize;
2432 WRITE64(dummy64); 2471 WRITE64(dummy64);
2433 } 2472 }
2434 if (bmval1 & FATTR4_WORD1_SPACE_USED) { 2473 if (bmval1 & FATTR4_WORD1_SPACE_USED) {
2435 if ((buflen -= 8) < 0) 2474 p = xdr_reserve_space(xdr, 8);
2475 if (!p)
2436 goto out_resource; 2476 goto out_resource;
2437 dummy64 = (u64)stat.blocks << 9; 2477 dummy64 = (u64)stat.blocks << 9;
2438 WRITE64(dummy64); 2478 WRITE64(dummy64);
2439 } 2479 }
2440 if (bmval1 & FATTR4_WORD1_TIME_ACCESS) { 2480 if (bmval1 & FATTR4_WORD1_TIME_ACCESS) {
2441 if ((buflen -= 12) < 0) 2481 p = xdr_reserve_space(xdr, 12);
2482 if (!p)
2442 goto out_resource; 2483 goto out_resource;
2443 WRITE64((s64)stat.atime.tv_sec); 2484 WRITE64((s64)stat.atime.tv_sec);
2444 WRITE32(stat.atime.tv_nsec); 2485 WRITE32(stat.atime.tv_nsec);
2445 } 2486 }
2446 if (bmval1 & FATTR4_WORD1_TIME_DELTA) { 2487 if (bmval1 & FATTR4_WORD1_TIME_DELTA) {
2447 if ((buflen -= 12) < 0) 2488 p = xdr_reserve_space(xdr, 12);
2489 if (!p)
2448 goto out_resource; 2490 goto out_resource;
2449 WRITE32(0); 2491 WRITE32(0);
2450 WRITE32(1); 2492 WRITE32(1);
2451 WRITE32(0); 2493 WRITE32(0);
2452 } 2494 }
2453 if (bmval1 & FATTR4_WORD1_TIME_METADATA) { 2495 if (bmval1 & FATTR4_WORD1_TIME_METADATA) {
2454 if ((buflen -= 12) < 0) 2496 p = xdr_reserve_space(xdr, 12);
2497 if (!p)
2455 goto out_resource; 2498 goto out_resource;
2456 WRITE64((s64)stat.ctime.tv_sec); 2499 WRITE64((s64)stat.ctime.tv_sec);
2457 WRITE32(stat.ctime.tv_nsec); 2500 WRITE32(stat.ctime.tv_nsec);
2458 } 2501 }
2459 if (bmval1 & FATTR4_WORD1_TIME_MODIFY) { 2502 if (bmval1 & FATTR4_WORD1_TIME_MODIFY) {
2460 if ((buflen -= 12) < 0) 2503 p = xdr_reserve_space(xdr, 12);
2504 if (!p)
2461 goto out_resource; 2505 goto out_resource;
2462 WRITE64((s64)stat.mtime.tv_sec); 2506 WRITE64((s64)stat.mtime.tv_sec);
2463 WRITE32(stat.mtime.tv_nsec); 2507 WRITE32(stat.mtime.tv_nsec);
2464 } 2508 }
2465 if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { 2509 if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) {
2466 if ((buflen -= 8) < 0) 2510 p = xdr_reserve_space(xdr, 8);
2511 if (!p)
2467 goto out_resource; 2512 goto out_resource;
2468 /* 2513 /*
2469 * Get parent's attributes if not ignoring crossmount 2514 * Get parent's attributes if not ignoring crossmount
@@ -2475,13 +2520,14 @@ out_acl:
2475 WRITE64(stat.ino); 2520 WRITE64(stat.ino);
2476 } 2521 }
2477 if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) { 2522 if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
2478 status = nfsd4_encode_security_label(rqstp, context, 2523 status = nfsd4_encode_security_label(xdr, rqstp, context,
2479 contextlen, &p, &buflen); 2524 contextlen);
2480 if (status) 2525 if (status)
2481 goto out; 2526 goto out;
2482 } 2527 }
2483 if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) { 2528 if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
2484 if ((buflen -= 16) < 0) 2529 p = xdr_reserve_space(xdr, 16);
2530 if (!p)
2485 goto out_resource; 2531 goto out_resource;
2486 WRITE32(3); 2532 WRITE32(3);
2487 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0); 2533 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0);
@@ -2489,8 +2535,7 @@ out_acl:
2489 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD2); 2535 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD2);
2490 } 2536 }
2491 2537
2492 *attrlenp = htonl((char *)p - (char *)attrlenp - 4); 2538 *attrlenp = htonl((char *)xdr->p - (char *)attrlenp - 4);
2493 xdr->p = p;
2494 status = nfs_ok; 2539 status = nfs_ok;
2495 2540
2496out: 2541out:
@@ -2503,6 +2548,13 @@ out:
2503 fh_put(tempfh); 2548 fh_put(tempfh);
2504 kfree(tempfh); 2549 kfree(tempfh);
2505 } 2550 }
2551 if (status) {
2552 int nbytes = (char *)xdr->p - (char *)start;
2553 /* open code what *should* be xdr_truncate(xdr, len); */
2554 xdr->iov->iov_len -= nbytes;
2555 xdr->buf->len -= nbytes;
2556 xdr->p = start;
2557 }
2506 return status; 2558 return status;
2507out_nfserr: 2559out_nfserr:
2508 status = nfserrno(err); 2560 status = nfserrno(err);
@@ -2768,13 +2820,10 @@ nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
2768{ 2820{
2769 struct svc_fh *fhp = getattr->ga_fhp; 2821 struct svc_fh *fhp = getattr->ga_fhp;
2770 struct xdr_stream *xdr = &resp->xdr; 2822 struct xdr_stream *xdr = &resp->xdr;
2771 struct xdr_buf *buf = resp->xdr.buf;
2772 2823
2773 if (nfserr) 2824 if (nfserr)
2774 return nfserr; 2825 return nfserr;
2775 2826
2776 buf->buflen = (void *)resp->xdr.end - (void *)resp->xdr.p
2777 - COMPOUND_ERR_SLACK_SPACE;
2778 nfserr = nfsd4_encode_fattr(xdr, fhp, fhp->fh_export, fhp->fh_dentry, 2827 nfserr = nfsd4_encode_fattr(xdr, fhp, fhp->fh_export, fhp->fh_dentry,
2779 getattr->ga_bmval, 2828 getattr->ga_bmval,
2780 resp->rqstp, 0); 2829 resp->rqstp, 0);
@@ -2971,6 +3020,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
2971 int v; 3020 int v;
2972 struct page *page; 3021 struct page *page;
2973 unsigned long maxcount; 3022 unsigned long maxcount;
3023 struct xdr_stream *xdr = &resp->xdr;
2974 long len; 3024 long len;
2975 __be32 *p; 3025 __be32 *p;
2976 3026
@@ -3017,6 +3067,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
3017 resp->xdr.buf->head[0].iov_len = (char *)p 3067 resp->xdr.buf->head[0].iov_len = (char *)p
3018 - (char *)resp->xdr.buf->head[0].iov_base; 3068 - (char *)resp->xdr.buf->head[0].iov_base;
3019 resp->xdr.buf->page_len = maxcount; 3069 resp->xdr.buf->page_len = maxcount;
3070 xdr->iov = xdr->buf->tail;
3020 3071
3021 /* Use rest of head for padding and remaining ops: */ 3072 /* Use rest of head for padding and remaining ops: */
3022 resp->xdr.buf->tail[0].iov_base = p; 3073 resp->xdr.buf->tail[0].iov_base = p;
@@ -3035,6 +3086,7 @@ static __be32
3035nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readlink *readlink) 3086nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readlink *readlink)
3036{ 3087{
3037 int maxcount; 3088 int maxcount;
3089 struct xdr_stream *xdr = &resp->xdr;
3038 char *page; 3090 char *page;
3039 __be32 *p; 3091 __be32 *p;
3040 3092
@@ -3067,6 +3119,7 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd
3067 resp->xdr.buf->head[0].iov_len = (char *)p 3119 resp->xdr.buf->head[0].iov_len = (char *)p
3068 - (char *)resp->xdr.buf->head[0].iov_base; 3120 - (char *)resp->xdr.buf->head[0].iov_base;
3069 resp->xdr.buf->page_len = maxcount; 3121 resp->xdr.buf->page_len = maxcount;
3122 xdr->iov = xdr->buf->tail;
3070 3123
3071 /* Use rest of head for padding and remaining ops: */ 3124 /* Use rest of head for padding and remaining ops: */
3072 resp->xdr.buf->tail[0].iov_base = p; 3125 resp->xdr.buf->tail[0].iov_base = p;
@@ -3086,6 +3139,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
3086{ 3139{
3087 int maxcount; 3140 int maxcount;
3088 loff_t offset; 3141 loff_t offset;
3142 struct xdr_stream *xdr = &resp->xdr;
3089 __be32 *page, *savep, *tailbase; 3143 __be32 *page, *savep, *tailbase;
3090 __be32 *p; 3144 __be32 *p;
3091 3145
@@ -3148,6 +3202,8 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
3148 resp->xdr.buf->page_len = ((char *)p) - 3202 resp->xdr.buf->page_len = ((char *)p) -
3149 (char*)page_address(*(resp->rqstp->rq_next_page-1)); 3203 (char*)page_address(*(resp->rqstp->rq_next_page-1));
3150 3204
3205 xdr->iov = xdr->buf->tail;
3206
3151 /* Use rest of head for padding and remaining ops: */ 3207 /* Use rest of head for padding and remaining ops: */
3152 resp->xdr.buf->tail[0].iov_base = tailbase; 3208 resp->xdr.buf->tail[0].iov_base = tailbase;
3153 resp->xdr.buf->tail[0].iov_len = 0; 3209 resp->xdr.buf->tail[0].iov_len = 0;