aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2011-09-12 19:37:06 -0400
committerJ. Bruce Fields <bfields@redhat.com>2011-09-13 22:43:42 -0400
commited748aacb8e3318fa2cf24e1c197d35b5fd29605 (patch)
treecee8fdf89ec8019b0dd3cd3e10eca4df05e6c4e5 /fs/nfsd
parentee626a77d3725a129391b1c85edd46f3b470cca9 (diff)
NFSD: Cleanup for nfsd4_path()
The current code is sort of hackish in that it assumes a referral is always matched to an export. When we add support for junctions that may not be the case. We can replace nfsd4_path() with a function that encodes the components directly from the dentries. Since nfsd4_path is currently the only user of the 'ex_pathname' field in struct svc_export, this has the added benefit of allowing us to get rid of that. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/export.c4
-rw-r--r--fs/nfsd/nfs4xdr.c106
2 files changed, 80 insertions, 30 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index d491421cd708..99229b0c153e 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -1009,7 +1009,7 @@ rqst_exp_parent(struct svc_rqst *rqstp, struct path *path)
1009 return exp; 1009 return exp;
1010} 1010}
1011 1011
1012static struct svc_export *find_fsidzero_export(struct svc_rqst *rqstp) 1012struct svc_export *rqst_find_fsidzero_export(struct svc_rqst *rqstp)
1013{ 1013{
1014 u32 fsidv[2]; 1014 u32 fsidv[2];
1015 1015
@@ -1029,7 +1029,7 @@ exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp)
1029 struct svc_export *exp; 1029 struct svc_export *exp;
1030 __be32 rv; 1030 __be32 rv;
1031 1031
1032 exp = find_fsidzero_export(rqstp); 1032 exp = rqst_find_fsidzero_export(rqstp);
1033 if (IS_ERR(exp)) 1033 if (IS_ERR(exp))
1034 return nfserrno(PTR_ERR(exp)); 1034 return nfserrno(PTR_ERR(exp));
1035 rv = fh_compose(fhp, exp, exp->ex_path.dentry, NULL); 1035 rv = fh_compose(fhp, exp, exp->ex_path.dentry, NULL);
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 182570bed472..5252d6681960 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1696,36 +1696,89 @@ static __be32 nfsd4_encode_fs_location4(struct nfsd4_fs_location *location,
1696} 1696}
1697 1697
1698/* 1698/*
1699 * Return the path to an export point in the pseudo filesystem namespace 1699 * Encode a path in RFC3530 'pathname4' format
1700 * Returned string is safe to use as long as the caller holds a reference
1701 * to @exp.
1702 */ 1700 */
1703static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, __be32 *stat) 1701static __be32 nfsd4_encode_path(const struct path *root,
1702 const struct path *path, __be32 **pp, int *buflen)
1704{ 1703{
1705 struct svc_fh tmp_fh; 1704 struct path cur = {
1706 char *path = NULL, *rootpath; 1705 .mnt = path->mnt,
1707 size_t rootlen; 1706 .dentry = path->dentry,
1707 };
1708 __be32 *p = *pp;
1709 struct dentry **components = NULL;
1710 unsigned int ncomponents = 0;
1711 __be32 err = nfserr_jukebox;
1708 1712
1709 fh_init(&tmp_fh, NFS4_FHSIZE); 1713 dprintk("nfsd4_encode_components(");
1710 *stat = exp_pseudoroot(rqstp, &tmp_fh);
1711 if (*stat)
1712 return NULL;
1713 rootpath = tmp_fh.fh_export->ex_pathname;
1714 1714
1715 path = exp->ex_pathname; 1715 path_get(&cur);
1716 /* First walk the path up to the nfsd root, and store the
1717 * dentries/path components in an array.
1718 */
1719 for (;;) {
1720 if (cur.dentry == root->dentry && cur.mnt == root->mnt)
1721 break;
1722 if (cur.dentry == cur.mnt->mnt_root) {
1723 if (follow_up(&cur))
1724 continue;
1725 goto out_free;
1726 }
1727 if ((ncomponents & 15) == 0) {
1728 struct dentry **new;
1729 new = krealloc(components,
1730 sizeof(*new) * (ncomponents + 16),
1731 GFP_KERNEL);
1732 if (!new)
1733 goto out_free;
1734 components = new;
1735 }
1736 components[ncomponents++] = cur.dentry;
1737 cur.dentry = dget_parent(cur.dentry);
1738 }
1716 1739
1717 rootlen = strlen(rootpath); 1740 *buflen -= 4;
1718 if (strncmp(path, rootpath, rootlen)) { 1741 if (*buflen < 0)
1719 dprintk("nfsd: fs_locations failed;" 1742 goto out_free;
1720 "%s is not contained in %s\n", path, rootpath); 1743 WRITE32(ncomponents);
1721 *stat = nfserr_notsupp; 1744
1722 path = NULL; 1745 while (ncomponents) {
1723 goto out; 1746 struct dentry *dentry = components[ncomponents - 1];
1747 unsigned int len = dentry->d_name.len;
1748
1749 *buflen -= 4 + (XDR_QUADLEN(len) << 2);
1750 if (*buflen < 0)
1751 goto out_free;
1752 WRITE32(len);
1753 WRITEMEM(dentry->d_name.name, len);
1754 dprintk("/%s", dentry->d_name.name);
1755 dput(dentry);
1756 ncomponents--;
1724 } 1757 }
1725 path += rootlen; 1758
1726out: 1759 *pp = p;
1727 fh_put(&tmp_fh); 1760 err = 0;
1728 return path; 1761out_free:
1762 dprintk(")\n");
1763 while (ncomponents)
1764 dput(components[--ncomponents]);
1765 kfree(components);
1766 path_put(&cur);
1767 return err;
1768}
1769
1770static __be32 nfsd4_encode_fsloc_fsroot(struct svc_rqst *rqstp,
1771 const struct path *path, __be32 **pp, int *buflen)
1772{
1773 struct svc_export *exp_ps;
1774 __be32 res;
1775
1776 exp_ps = rqst_find_fsidzero_export(rqstp);
1777 if (IS_ERR(exp_ps))
1778 return nfserrno(PTR_ERR(exp_ps));
1779 res = nfsd4_encode_path(&exp_ps->ex_path, path, pp, buflen);
1780 exp_put(exp_ps);
1781 return res;
1729} 1782}
1730 1783
1731/* 1784/*
@@ -1739,11 +1792,8 @@ static __be32 nfsd4_encode_fs_locations(struct svc_rqst *rqstp,
1739 int i; 1792 int i;
1740 __be32 *p = *pp; 1793 __be32 *p = *pp;
1741 struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs; 1794 struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs;
1742 char *root = nfsd4_path(rqstp, exp, &status);
1743 1795
1744 if (status) 1796 status = nfsd4_encode_fsloc_fsroot(rqstp, &exp->ex_path, &p, buflen);
1745 return status;
1746 status = nfsd4_encode_components('/', root, &p, buflen);
1747 if (status) 1797 if (status)
1748 return status; 1798 return status;
1749 if ((*buflen -= 4) < 0) 1799 if ((*buflen -= 4) < 0)