rpms/kernel/devel linux-2.6-nfsd4-proots.patch, NONE, 1.1 kernel.spec, 1.1611, 1.1612
Steve Dickson
steved at fedoraproject.org
Wed Jul 8 13:27:36 UTC 2009
Author: steved
Update of /cvs/pkgs/rpms/kernel/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv27785
Modified Files:
kernel.spec
Added Files:
linux-2.6-nfsd4-proots.patch
Log Message:
- Added NFSD v4 dynamic pseudo root patch which allows
NFS v3 exports to be mounted by v4 clients.
linux-2.6-nfsd4-proots.patch:
--- NEW FILE linux-2.6-nfsd4-proots.patch ---
diff -up linux-2.6.30.noarch/fs/nfsd/export.c.save linux-2.6.30.noarch/fs/nfsd/export.c
--- linux-2.6.30.noarch/fs/nfsd/export.c.save 2009-07-02 11:34:38.000000000 -0400
+++ linux-2.6.30.noarch/fs/nfsd/export.c 2009-07-02 11:35:44.000000000 -0400
@@ -104,6 +104,7 @@ static int expkey_parse(struct cache_det
if (mesg[mlen-1] != '\n')
return -EINVAL;
mesg[mlen-1] = 0;
+ dprintk("expkey_parse: '%s'\n", mesg);
buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
err = -ENOMEM;
@@ -181,6 +182,8 @@ static int expkey_parse(struct cache_det
if (dom)
auth_domain_put(dom);
kfree(buf);
+ if (err)
+ dprintk("expkey_parse: err %d\n", err);
return err;
}
@@ -351,7 +354,10 @@ static void svc_export_request(struct ca
(*bpp)[0] = '\n';
return;
}
+
qword_add(bpp, blen, pth);
+ dprintk("svc_export_request: pth %s\n", pth);
+
(*bpp)[-1] = '\n';
}
@@ -500,6 +506,7 @@ static int svc_export_parse(struct cache
if (mesg[mlen-1] != '\n')
return -EINVAL;
mesg[mlen-1] = 0;
+ dprintk("svc_export_parse: '%s'\n", mesg);
buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!buf)
@@ -619,6 +626,8 @@ out1:
auth_domain_put(dom);
out:
kfree(buf);
+ if (err)
+ dprintk("svc_export_parse: err %d\n", err);
return err;
}
@@ -1413,6 +1422,7 @@ static struct flags {
{ NFSEXP_CROSSMOUNT, {"crossmnt", ""}},
{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
{ NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
+ { NFSEXP_V4ROOT, {"v4root", ""}},
#ifdef MSNFS
{ NFSEXP_MSNFS, {"msnfs", ""}},
#endif
@@ -1493,7 +1503,7 @@ static int e_show(struct seq_file *m, vo
struct svc_export *exp = container_of(cp, struct svc_export, h);
if (p == SEQ_START_TOKEN) {
- seq_puts(m, "# Version 1.1\n");
+ seq_puts(m, "# Version 1.2\n");
seq_puts(m, "# Path Client(Flags) # IPs\n");
return 0;
}
diff -up linux-2.6.30.noarch/fs/nfsd/nfs4xdr.c.save linux-2.6.30.noarch/fs/nfsd/nfs4xdr.c
--- linux-2.6.30.noarch/fs/nfsd/nfs4xdr.c.save 2009-07-02 11:34:38.000000000 -0400
+++ linux-2.6.30.noarch/fs/nfsd/nfs4xdr.c 2009-07-02 11:35:31.000000000 -0400
@@ -2176,28 +2176,62 @@ static inline int attributes_need_mount(
return 0;
}
-static __be32
-nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
- const char *name, int namlen, __be32 *p, int *buflen)
+struct dentry *
+nfsd_check_export(struct nfsd4_readdir *cd, const char *name, int namlen)
{
struct svc_export *exp = cd->rd_fhp->fh_export;
struct dentry *dentry;
- __be32 nfserr;
- int ignore_crossmnt = 0;
+ int err;
dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen);
if (IS_ERR(dentry))
- return nfserrno(PTR_ERR(dentry));
+ return dentry;
if (!dentry->d_inode) {
- /*
- * nfsd_buffered_readdir drops the i_mutex between
- * readdir and calling this callback, leaving a window
- * where this directory entry could have gone away.
- */
dput(dentry);
- return nfserr_noent;
+ return ERR_PTR(-ENOENT);
+ }
+
+ /*
+ * Check to see if this dentry is part
+ * of the psuedo root
+ */
+ if ((exp->ex_flags & NFSEXP_V4ROOT) == 0)
+ return dentry;
+
+ /*
+ * Only exported directories are visable
+ * on psuedo exports
+ */
+ if (!S_ISDIR(dentry->d_inode->i_mode)) {
+ dput(dentry);
+ return ERR_PTR(-ENOENT);
}
+ /*
+ * Make the upcall to see if this directory
+ * is exported.
+ */
+ exp_get(exp);
+ err = nfsd_export_lookup(cd->rd_rqstp, dentry, exp);
+ if (err) {
+ exp_put(exp);
+ dput(dentry);
+ return ERR_PTR(err);
+ }
+ exp_put(exp);
+
+ return dentry;
+}
+
+static __be32
+nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
+ struct dentry *dentry, __be32 *p, int *buflen)
+{
+ struct svc_export *exp = cd->rd_fhp->fh_export;
+ __be32 nfserr;
+ int ignore_crossmnt = 0;
+ int err, v4root = (exp->ex_flags & NFSEXP_V4ROOT);
+
exp_get(exp);
/*
* In the case of a mountpoint, the client may be asking for
@@ -2208,18 +2242,29 @@ nfsd4_encode_dirent_fattr(struct nfsd4_r
*/
if (d_mountpoint(dentry) && !attributes_need_mount(cd->rd_bmval))
ignore_crossmnt = 1;
- else if (d_mountpoint(dentry)) {
- int err;
-
+ else if (d_mountpoint(dentry) || v4root) {
+ /*
+ * Make sure the dentry is viewable on the psuedo export
+ */
+ v4root = (dentry->d_inode && v4root);
+ if (v4root) {
+ err = nfsd_export_lookup(cd->rd_rqstp, dentry, exp);
+ if (err) {
+ nfserr = nfserrno(err);
+ goto out_put;
+ }
+ }
/*
* Why the heck aren't we just using nfsd_lookup??
* Different "."/".." handling? Something else?
* At least, add a comment here to explain....
*/
- err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
- if (err) {
- nfserr = nfserrno(err);
- goto out_put;
+ if (d_mountpoint(dentry) || v4root) {
+ err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
+ if (err) {
+ nfserr = nfserrno(err);
+ goto out_put;
+ }
}
nfserr = check_nfsd_access(exp, cd->rd_rqstp);
if (nfserr)
@@ -2258,6 +2303,7 @@ nfsd4_encode_dirent(void *ccdv, const ch
struct readdir_cd *ccd = ccdv;
struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common);
int buflen;
+ struct dentry *dentry;
__be32 *p = cd->buffer;
__be32 *cookiep;
__be32 nfserr = nfserr_toosmall;
@@ -2268,19 +2314,40 @@ nfsd4_encode_dirent(void *ccdv, const ch
return 0;
}
+ /*
+ * Do the lookup and make sure the dentry is
+ * visible on the exported directory
+ */
+ dentry = nfsd_check_export(cd, name, namlen);
+ if (IS_ERR(dentry)) {
+ if (PTR_ERR(dentry) == -ENOENT) {
+ cd->common.err = nfs_ok;
+ return 0;
+ }
+ cd->common.err = nfserrno(PTR_ERR(dentry));
+ return -EINVAL;
+ }
+
if (cd->offset)
xdr_encode_hyper(cd->offset, (u64) offset);
buflen = cd->buflen - 4 - XDR_QUADLEN(namlen);
- if (buflen < 0)
+ if (buflen < 0) {
+ dput(dentry);
goto fail;
+ }
*p++ = xdr_one; /* mark entry present */
cookiep = p;
p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */
p = xdr_encode_array(p, name, namlen); /* name length & name */
- nfserr = nfsd4_encode_dirent_fattr(cd, name, namlen, p, &buflen);
+ /*
+ * Note: the dput() on the dentry is done in
+ * nfsd4_encode_dirent_fattr() since the dentry can
+ * change when crossing a mount point.
+ */
+ nfserr = nfsd4_encode_dirent_fattr(cd, dentry, p, &buflen);
switch (nfserr) {
case nfs_ok:
p += buflen;
diff -up linux-2.6.30.noarch/fs/nfsd/nfsfh.c.save linux-2.6.30.noarch/fs/nfsd/nfsfh.c
--- linux-2.6.30.noarch/fs/nfsd/nfsfh.c.save 2009-07-02 11:34:38.000000000 -0400
+++ linux-2.6.30.noarch/fs/nfsd/nfsfh.c 2009-07-02 11:35:48.000000000 -0400
@@ -109,6 +109,34 @@ static __be32 nfsd_setuser_and_check_por
return nfserrno(nfsd_setuser(rqstp, exp));
}
+static inline __be32 check_pseudo_root(struct svc_rqst *rqstp,
+ struct dentry *dentry, struct svc_export *exp)
+{
+ int error;
+
+ /*
+ * Only interested in pseudo roots
+ */
+ if (!(exp->ex_flags & NFSEXP_V4ROOT))
+ return nfs_ok;
+
+ /*
+ * Only directories should be on the pseudo root
+ */
+ if (unlikely(!S_ISDIR(dentry->d_inode->i_mode)))
+ return nfserr_stale;
+ /*
+ * Check non-root directories to make sure
+ * they are truly exported
+ */
+ if (unlikely(dentry->d_name.len > 1)) {
+ error = nfsd_export_lookup(rqstp, dentry, exp);
+ return nfserrno(error);
+ }
+
+ return nfs_ok;
+}
+
/*
* Use the given filehandle to look up the corresponding export and
* dentry. On success, the results are used to set fh_export and
@@ -315,6 +343,14 @@ fh_verify(struct svc_rqst *rqstp, struct
error = nfsd_setuser_and_check_port(rqstp, exp);
if (error)
goto out;
+
+ /*
+ * Do some spoof checking if we are on the pseudo root
+ */
+ error = check_pseudo_root(rqstp, dentry, exp);
+ if (error)
+ goto out;
+
}
error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type);
diff -up linux-2.6.30.noarch/fs/nfsd/vfs.c.save linux-2.6.30.noarch/fs/nfsd/vfs.c
--- linux-2.6.30.noarch/fs/nfsd/vfs.c.save 2009-07-02 11:34:38.000000000 -0400
+++ linux-2.6.30.noarch/fs/nfsd/vfs.c 2009-07-02 11:35:39.000000000 -0400
@@ -89,6 +89,12 @@ struct raparm_hbucket {
#define RAPARM_HASH_MASK (RAPARM_HASH_SIZE-1)
static struct raparm_hbucket raparm_hash[RAPARM_HASH_SIZE];
+static inline int
+nfsd_v4client(struct svc_rqst *rq)
+{
+ return((rq->rq_prog == NFS_PROGRAM) && (rq->rq_vers == 4));
+}
+
/*
* Called from nfsd_lookup and encode_dirent. Check if we have crossed
* a mount point.
@@ -115,7 +121,8 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, s
path_put(&path);
goto out;
}
- if ((exp->ex_flags & NFSEXP_CROSSMOUNT) || EX_NOHIDE(exp2)) {
+ if (nfsd_v4client(rqstp) ||
+ (exp->ex_flags & NFSEXP_CROSSMOUNT) || EX_NOHIDE(exp2)) {
/* successfully crossed mount point */
/*
* This is subtle: path.dentry is *not* on path.mnt
@@ -134,6 +141,55 @@ out:
return err;
}
+/*
+ * Lookup the export the dentry is on. To be
+ * viewable on an pseudo export, the dentry
+ * has to be an exported directory.
+ */
+int
+nfsd_export_lookup(struct svc_rqst *rqstp, struct dentry *dentry,
+ struct svc_export *exp)
+{
+ struct svc_export *exp2 = NULL;
+ struct path path;
+ int err = 0;
+
+ if ((exp->ex_flags & NFSEXP_V4ROOT) == 0)
+ return 0;
+
+ /*
+ * Make sure the export is the parent of the dentry
+ */
+ if (dentry->d_parent != exp->ex_path.dentry)
+ return 0;
+
+ /*
+ * Only directories are seen on psuedo exports
+ */
+ if (!S_ISDIR(dentry->d_inode->i_mode))
+ return -ENOENT;
+
+ /*
+ * Make the upcall
+ */
+ path.mnt = mntget(exp->ex_path.mnt);
+ path.dentry = dget(dentry);
+ while (d_mountpoint(path.dentry) && follow_down(&path));
+
+ exp2 = rqst_exp_get_by_name(rqstp, &path);
+ if (IS_ERR(exp2))
+ err = PTR_ERR(exp2);
+ else {
+ /*
+ * The export exist so allow the access
+ */
+ exp_put(exp2);
+ }
+
+ dput(path.dentry);
+ mntput(path.mnt);
+ return err;
+}
__be32
nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
const char *name, unsigned int len,
@@ -143,7 +199,7 @@ nfsd_lookup_dentry(struct svc_rqst *rqst
struct dentry *dparent;
struct dentry *dentry;
__be32 err;
- int host_err;
+ int host_err, v4root;
dprintk("nfsd: nfsd_lookup(fh %s, %.*s)\n", SVCFH_fmt(fhp), len,name);
@@ -155,6 +211,7 @@ nfsd_lookup_dentry(struct svc_rqst *rqst
dparent = fhp->fh_dentry;
exp = fhp->fh_export;
exp_get(exp);
+ v4root = (exp->ex_flags & NFSEXP_V4ROOT);
/* Lookup the name, but don't follow links */
if (isdotent(name, len)) {
@@ -199,9 +256,21 @@ nfsd_lookup_dentry(struct svc_rqst *rqst
if (IS_ERR(dentry))
goto out_nfserr;
/*
+ * The export is a pseudo one, make sure the
+ * dentry is accessible
+ */
+ v4root = (dentry->d_inode && v4root);
+ if (v4root) {
+ host_err = nfsd_export_lookup(rqstp, dentry, exp);
+ if (host_err) {
+ dput(dentry);
+ goto out_nfserr;
+ }
+ }
+ /*
* check if we have crossed a mount point ...
*/
- if (d_mountpoint(dentry)) {
+ if (d_mountpoint(dentry) || v4root) {
if ((host_err = nfsd_cross_mnt(rqstp, &dentry, &exp))) {
dput(dentry);
goto out_nfserr;
diff -up linux-2.6.30.noarch/include/linux/nfsd/export.h.save linux-2.6.30.noarch/include/linux/nfsd/export.h
--- linux-2.6.30.noarch/include/linux/nfsd/export.h.save 2009-07-02 11:34:38.000000000 -0400
+++ linux-2.6.30.noarch/include/linux/nfsd/export.h 2009-07-02 11:35:22.000000000 -0400
@@ -39,7 +39,8 @@
#define NFSEXP_FSID 0x2000
#define NFSEXP_CROSSMOUNT 0x4000
#define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */
-#define NFSEXP_ALLFLAGS 0xFE3F
+#define NFSEXP_V4ROOT 0x10000
+#define NFSEXP_ALLFLAGS 0x1FE3F
/* The flags that may vary depending on security flavor: */
#define NFSEXP_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
diff -up linux-2.6.30.noarch/include/linux/nfsd/nfsd.h.save linux-2.6.30.noarch/include/linux/nfsd/nfsd.h
--- linux-2.6.30.noarch/include/linux/nfsd/nfsd.h.save 2009-07-02 11:34:38.000000000 -0400
+++ linux-2.6.30.noarch/include/linux/nfsd/nfsd.h 2009-07-02 11:35:27.000000000 -0400
@@ -76,6 +76,8 @@ int nfsd_racache_init(int);
void nfsd_racache_shutdown(void);
int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
struct svc_export **expp);
+int nfsd_export_lookup(struct svc_rqst *rqstp, struct dentry *dpp,
+ struct svc_export *exp);
__be32 nfsd_lookup(struct svc_rqst *, struct svc_fh *,
const char *, unsigned int, struct svc_fh *);
__be32 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *,
Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/kernel.spec,v
retrieving revision 1.1611
retrieving revision 1.1612
diff -u -p -r1.1611 -r1.1612
--- kernel.spec 8 Jul 2009 02:13:19 -0000 1.1611
+++ kernel.spec 8 Jul 2009 13:27:06 -0000 1.1612
@@ -677,6 +677,9 @@ Patch2903: linux-2.6-revert-dvb-net-kabi
# fs fixes
Patch3000: linux-2.6-btrfs-experimental-branch.patch
+# NFSv4
+Patch3050: linux-2.6-nfsd4-proots.patch
+
#snmp fixes
Patch10000: linux-2.6-missing-rfc2465-stats.patch
@@ -1137,6 +1140,9 @@ ApplyPatch linux-2.6-execshield.patch
# btrfs
#ApplyPatch linux-2.6-btrfs-experimental-branch.patch
+# NFSv4
+ApplyPatch linux-2.6-nfsd4-proots.patch
+
# USB
# ACPI
@@ -1843,6 +1849,10 @@ fi
# and build.
%changelog
+* Wed Jul 08 2009 Steve Dickson <steved at redhat.com>
+- Added NFSD v4 dynamic pseudo root patch which allows
+ NFS v3 exports to be mounted by v4 clients.
+
* Tue Jul 07 2009 Jarod Wilson <jarod at redhat.com>
- See if we can't make lirc_streamzap behave better... (#508952)
More information about the fedora-extras-commits
mailing list