diff options
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index bf1e792a65a0..b0592e7c378d 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -1453,7 +1453,7 @@ static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err) | |||
1453 | __be32 | 1453 | __be32 |
1454 | nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | 1454 | nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, |
1455 | struct dentry *dentry, __be32 *buffer, int *countp, u32 *bmval, | 1455 | struct dentry *dentry, __be32 *buffer, int *countp, u32 *bmval, |
1456 | struct svc_rqst *rqstp) | 1456 | struct svc_rqst *rqstp, int ignore_crossmnt) |
1457 | { | 1457 | { |
1458 | u32 bmval0 = bmval[0]; | 1458 | u32 bmval0 = bmval[0]; |
1459 | u32 bmval1 = bmval[1]; | 1459 | u32 bmval1 = bmval[1]; |
@@ -1833,7 +1833,12 @@ out_acl: | |||
1833 | if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { | 1833 | if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { |
1834 | if ((buflen -= 8) < 0) | 1834 | if ((buflen -= 8) < 0) |
1835 | goto out_resource; | 1835 | goto out_resource; |
1836 | if (exp->ex_mnt->mnt_root->d_inode == dentry->d_inode) { | 1836 | /* |
1837 | * Get parent's attributes if not ignoring crossmount | ||
1838 | * and this is the root of a cross-mounted filesystem. | ||
1839 | */ | ||
1840 | if (ignore_crossmnt == 0 && | ||
1841 | exp->ex_mnt->mnt_root->d_inode == dentry->d_inode) { | ||
1837 | err = vfs_getattr(exp->ex_mnt->mnt_parent, | 1842 | err = vfs_getattr(exp->ex_mnt->mnt_parent, |
1838 | exp->ex_mnt->mnt_mountpoint, &stat); | 1843 | exp->ex_mnt->mnt_mountpoint, &stat); |
1839 | if (err) | 1844 | if (err) |
@@ -1869,13 +1874,25 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd, | |||
1869 | struct svc_export *exp = cd->rd_fhp->fh_export; | 1874 | struct svc_export *exp = cd->rd_fhp->fh_export; |
1870 | struct dentry *dentry; | 1875 | struct dentry *dentry; |
1871 | __be32 nfserr; | 1876 | __be32 nfserr; |
1877 | int ignore_crossmnt = 0; | ||
1872 | 1878 | ||
1873 | dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen); | 1879 | dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen); |
1874 | if (IS_ERR(dentry)) | 1880 | if (IS_ERR(dentry)) |
1875 | return nfserrno(PTR_ERR(dentry)); | 1881 | return nfserrno(PTR_ERR(dentry)); |
1876 | 1882 | ||
1877 | exp_get(exp); | 1883 | exp_get(exp); |
1878 | if (d_mountpoint(dentry)) { | 1884 | /* |
1885 | * In the case of a mountpoint, the client may be asking for | ||
1886 | * attributes that are only properties of the underlying filesystem | ||
1887 | * as opposed to the cross-mounted file system. In such a case, | ||
1888 | * we will not follow the cross mount and will fill the attribtutes | ||
1889 | * directly from the mountpoint dentry. | ||
1890 | */ | ||
1891 | if (d_mountpoint(dentry) && | ||
1892 | (cd->rd_bmval[0] & ~FATTR4_WORD0_RDATTR_ERROR) == 0 && | ||
1893 | (cd->rd_bmval[1] & ~FATTR4_WORD1_MOUNTED_ON_FILEID) == 0) | ||
1894 | ignore_crossmnt = 1; | ||
1895 | else if (d_mountpoint(dentry)) { | ||
1879 | int err; | 1896 | int err; |
1880 | 1897 | ||
1881 | /* | 1898 | /* |
@@ -1894,7 +1911,7 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd, | |||
1894 | 1911 | ||
1895 | } | 1912 | } |
1896 | nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval, | 1913 | nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval, |
1897 | cd->rd_rqstp); | 1914 | cd->rd_rqstp, ignore_crossmnt); |
1898 | out_put: | 1915 | out_put: |
1899 | dput(dentry); | 1916 | dput(dentry); |
1900 | exp_put(exp); | 1917 | exp_put(exp); |
@@ -2048,7 +2065,7 @@ nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4 | |||
2048 | buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2); | 2065 | buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2); |
2049 | nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry, | 2066 | nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry, |
2050 | resp->p, &buflen, getattr->ga_bmval, | 2067 | resp->p, &buflen, getattr->ga_bmval, |
2051 | resp->rqstp); | 2068 | resp->rqstp, 0); |
2052 | if (!nfserr) | 2069 | if (!nfserr) |
2053 | resp->p += buflen; | 2070 | resp->p += buflen; |
2054 | return nfserr; | 2071 | return nfserr; |