diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-09-12 19:37:06 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2011-09-13 22:43:42 -0400 |
commit | ed748aacb8e3318fa2cf24e1c197d35b5fd29605 (patch) | |
tree | cee8fdf89ec8019b0dd3cd3e10eca4df05e6c4e5 /fs/nfsd | |
parent | ee626a77d3725a129391b1c85edd46f3b470cca9 (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.c | 4 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 106 |
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 | ||
1012 | static struct svc_export *find_fsidzero_export(struct svc_rqst *rqstp) | 1012 | struct 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 | */ |
1703 | static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, __be32 *stat) | 1701 | static __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 | |
1726 | out: | 1759 | *pp = p; |
1727 | fh_put(&tmp_fh); | 1760 | err = 0; |
1728 | return path; | 1761 | out_free: |
1762 | dprintk(")\n"); | ||
1763 | while (ncomponents) | ||
1764 | dput(components[--ncomponents]); | ||
1765 | kfree(components); | ||
1766 | path_put(&cur); | ||
1767 | return err; | ||
1768 | } | ||
1769 | |||
1770 | static __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) |