patch for 2.1.109 knfsd filehandles

Bill Hawes (whawes@star.net)
Tue, 21 Jul 1998 09:55:25 -0400


This is a multi-part message in MIME format.
--------------B9AA237865D85A26BFA60902
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

The attached patch redefines the fields in the knfsd filehandle to avoid
present and future problems related to type size changes.

The patch uses fixed size __u32 fields for all inode number and device
number fields, leaving only the dentry cookie as a pointer. This will
give a maximum size of 5*4+8=28 bytes to guarantee a fit in the 32 byte
limit.

I've defined conversion functions to go to/from the u32 fields, e.g.
u32_to_kdev_t(). These are currently just casts, but can be easily
changed as needed. For example, if kdev_t becomes a pointer to a table
entry, the conversion functions can be changed to add or subtract the
table base.

The casts from 64-bit ino_t fields will work OK as long as the
filesystems in question don't go beyond using the low-order 32 bits.
I've added a load-time warning if sizeof(ino_t) is > 4.

I've tested it here and all is working OK, but would appreciate some
testing on 64-bit systems.

Regards,
Bill
--------------B9AA237865D85A26BFA60902
Content-Type: text/plain; charset=us-ascii; name="nfsd_109-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="nfsd_109-patch"

--- linux-2.1.109/include/linux/nfsd/nfsfh.h.old Fri Jul 17 13:22:46 1998
+++ linux-2.1.109/include/linux/nfsd/nfsfh.h Mon Jul 20 18:52:07 1998
@@ -27,12 +27,12 @@
* ino/dev of the exported inode.
*/
struct nfs_fhbase {
- struct dentry * fb_dentry; /* dentry cookie */
- ino_t fb_ino; /* our inode number */
- ino_t fb_dirino; /* dir inode number */
- kdev_t fb_dev; /* our device */
- kdev_t fb_xdev;
- ino_t fb_xino;
+ struct dentry * fb_dentry; /* dentry cookie */
+ __u32 fb_ino; /* our inode number */
+ __u32 fb_dirino; /* dir inode number */
+ __u32 fb_dev; /* our device */
+ __u32 fb_xdev;
+ __u32 fb_xino;
};

#define NFS_FH_PADDING (NFS_FHSIZE - sizeof(struct nfs_fhbase))
@@ -49,6 +49,29 @@
#define fh_xino fh_base.fb_xino

#ifdef __KERNEL__
+
+/*
+ * Conversion macros for the filehandle fields.
+ */
+extern inline __u32 kdev_t_to_u32(kdev_t dev)
+{
+ return (__u32) dev;
+}
+
+extern inline kdev_t u32_to_kdev_t(__u32 udev)
+{
+ return (kdev_t) udev;
+}
+
+extern inline __u32 ino_t_to_u32(ino_t ino)
+{
+ return (__u32) ino;
+}
+
+extern inline ino_t u32_to_ino_t(__u32 uino)
+{
+ return (ino_t) uino;
+}

/*
* This is the internal representation of an NFS handle used in knfsd.
--- linux-2.1.109/fs/nfsd/nfsfh.c.old Fri Jul 3 10:32:32 1998
+++ linux-2.1.109/fs/nfsd/nfsfh.c Mon Jul 20 21:05:02 1998
@@ -98,7 +98,9 @@
{
struct nfsd_fixup *fp;

- fp = find_cached_lookup(fh->fh_dev, fh->fh_dirino, fh->fh_ino);
+ fp = find_cached_lookup(u32_to_kdev_t(fh->fh_dev),
+ u32_to_ino_t(fh->fh_dirino),
+ u32_to_ino_t(fh->fh_ino));
if (fp) {
fp->dentry = dentry;
return;
@@ -111,9 +113,9 @@
*/
fp = kmalloc(sizeof(struct nfsd_fixup), GFP_KERNEL);
if (fp) {
- fp->dir = fh->fh_dirino;
- fp->ino = fh->fh_ino;
- fp->dev = fh->fh_dev;
+ fp->dir = u32_to_kdev_t(fh->fh_dirino);
+ fp->ino = u32_to_ino_t(fh->fh_ino);
+ fp->dev = u32_to_ino_t(fh->fh_dev);
fp->dentry = dentry;
fp->reftime = jiffies;
list_add(&fp->lru, &fixup_head);
@@ -763,7 +765,9 @@
#endif
goto out;
}
- if (inode->i_ino != fh->fh_ino || inode->i_dev != fh->fh_dev)
+ if (inode->i_ino != u32_to_ino_t(fh->fh_ino))
+ goto out;
+ if (inode->i_dev != u32_to_kdev_t(fh->fh_dev))
goto out;

fhe->dentry = NULL;
@@ -839,7 +843,9 @@
{
struct nfsd_fixup *fp;

- fp = find_cached_lookup(fh->fh_dev, fh->fh_dirino, fh->fh_ino);
+ fp = find_cached_lookup(u32_to_kdev_t(fh->fh_dev),
+ u32_to_ino_t(fh->fh_dirino),
+ u32_to_ino_t(fh->fh_ino));
if (fp)
return fp->dentry;
return NULL;
@@ -893,13 +899,14 @@
if (nfsd_d_validate(dentry)) {
struct inode * dir = dentry->d_parent->d_inode;

- if (dir->i_ino == fh->fh_dirino && dir->i_dev == fh->fh_dev) {
+ if (dir->i_ino == u32_to_ino_t(fh->fh_dirino) &&
+ dir->i_dev == u32_to_kdev_t(fh->fh_dev)) {
struct inode * inode = dentry->d_inode;
/*
* NFS file handles must always have an inode,
* so we won't accept a negative dentry.
*/
- if (inode && inode->i_ino == fh->fh_ino) {
+ if (inode && inode->i_ino == u32_to_ino_t(fh->fh_ino)) {
dget(dentry);
#ifdef NFSD_DEBUG_VERBOSE
printk("find_fh_dentry: validated %s/%s, ino=%ld\n",
@@ -932,14 +939,16 @@
* numbers. This should work for all Unix-like filesystems.
*/
looked_up = 1;
- dentry = lookup_inode(fh->fh_dev, fh->fh_dirino, fh->fh_ino);
+ dentry = lookup_inode(u32_to_kdev_t(fh->fh_dev),
+ u32_to_ino_t(fh->fh_dirino),
+ u32_to_ino_t(fh->fh_ino));
if (!IS_ERR(dentry)) {
struct inode * inode = dentry->d_inode;
#ifdef NFSD_DEBUG_VERBOSE
printk("find_fh_dentry: looked up %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
#endif
- if (inode && inode->i_ino == fh->fh_ino) {
+ if (inode && inode->i_ino == u32_to_ino_t(fh->fh_ino)) {
nfsdstats.fh_lookup++;
goto out;
}
@@ -953,12 +962,13 @@
/*
* Stage 4: Look for the parent dentry in the fhcache ...
*/
- parent = find_dentry_by_ino(fh->fh_dev, fh->fh_dirino);
+ parent = find_dentry_by_ino(u32_to_kdev_t(fh->fh_dev),
+ u32_to_ino_t(fh->fh_dirino));
if (parent) {
/*
* ... then search for the inode in the parent directory.
*/
- dentry = lookup_by_inode(parent, fh->fh_ino);
+ dentry = lookup_by_inode(parent, u32_to_ino_t(fh->fh_ino));
dput(parent);
if (dentry)
goto out;
@@ -968,8 +978,8 @@
* Stage 5: Search the whole volume.
*/
#ifdef NFSD_PARANOIA
-printk("find_fh_dentry: %s, %ld/%ld not found -- need full search!\n",
-kdevname(fh->fh_dev), fh->fh_dirino, fh->fh_ino);
+printk("find_fh_dentry: %s, %u/%u not found -- need full search!\n",
+kdevname(u32_to_kdev_t(fh->fh_dev)), fh->fh_dirino, fh->fh_ino);
#endif
dentry = NULL;
nfsdstats.fh_stale++;
@@ -1006,7 +1016,7 @@
struct inode *inode;
u32 error = 0;

- dprintk("nfsd: fh_verify(exp %x/%ld cookie %p)\n",
+ dprintk("nfsd: fh_verify(exp %x/%u cookie %p)\n",
fh->fh_xdev, fh->fh_xino, fh->fh_dcookie);

if(fhp->fh_dverified)
@@ -1015,7 +1025,9 @@
* Look up the export entry.
*/
error = nfserr_stale;
- exp = exp_get(rqstp->rq_client, fh->fh_xdev, fh->fh_xino);
+ exp = exp_get(rqstp->rq_client,
+ u32_to_kdev_t(fh->fh_xdev),
+ u32_to_ino_t(fh->fh_xino));
if (!exp) /* export entry revoked */
goto out;

@@ -1091,6 +1103,7 @@
fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry)
{
struct inode * inode = dentry->d_inode;
+ struct dentry *parent = dentry->d_parent;

dprintk("nfsd: fh_compose(exp %x/%ld %s/%s, ino=%ld)\n",
exp->ex_dev, exp->ex_ino,
@@ -1105,12 +1118,12 @@
fh_init(fhp);
fhp->fh_handle.fh_dcookie = dentry;
if (inode) {
- fhp->fh_handle.fh_ino = inode->i_ino;
+ fhp->fh_handle.fh_ino = ino_t_to_u32(inode->i_ino);
}
- fhp->fh_handle.fh_dirino = dentry->d_parent->d_inode->i_ino;
- fhp->fh_handle.fh_dev = dentry->d_parent->d_inode->i_dev;
- fhp->fh_handle.fh_xdev = exp->ex_dev;
- fhp->fh_handle.fh_xino = exp->ex_ino;
+ fhp->fh_handle.fh_dirino = ino_t_to_u32(parent->d_inode->i_ino);
+ fhp->fh_handle.fh_dev = kdev_t_to_u32(parent->d_inode->i_dev);
+ fhp->fh_handle.fh_xdev = kdev_t_to_u32(exp->ex_dev);
+ fhp->fh_handle.fh_xino = ino_t_to_u32(exp->ex_ino);

fhp->fh_dentry = dentry; /* our internal copy */
fhp->fh_export = exp;
@@ -1129,21 +1142,24 @@
struct dentry *dentry;
struct inode *inode;

- if (!fhp->fh_dverified) {
- printk(KERN_DEBUG "fh_update: fh not verified!\n");
- goto out;
- }
+ if (!fhp->fh_dverified)
+ goto out_bad;

dentry = fhp->fh_dentry;
inode = dentry->d_inode;
- if (!inode) {
- printk(KERN_DEBUG "fh_update: %s/%s still negative!\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
- goto out;
- }
- fhp->fh_handle.fh_ino = inode->i_ino;
+ if (!inode)
+ goto out_negative;
+ fhp->fh_handle.fh_ino = ino_t_to_u32(inode->i_ino);
out:
return;
+
+out_bad:
+ printk(KERN_ERR "fh_update: fh not verified!\n");
+ goto out;
+out_negative:
+ printk(KERN_ERR "fh_update: %s/%s still negative!\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name);
+ goto out;
}

/*
@@ -1153,20 +1169,23 @@
void
fh_put(struct svc_fh *fhp)
{
+ struct dentry * dentry = fhp->fh_dentry;
if (fhp->fh_dverified) {
- struct dentry * dentry = fhp->fh_dentry;
fh_unlock(fhp);
fhp->fh_dverified = 0;
- if (!dentry->d_count) {
- printk(KERN_DEBUG "fh_put: %s/%s has d_count 0!\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
- return;
- }
+ if (!dentry->d_count)
+ goto out_bad;
if (!dentry->d_inode || !add_to_fhcache(dentry, 0)) {
dput(dentry);
nfsd_nr_put++;
}
}
+ return;
+
+out_bad:
+ printk(KERN_ERR "fh_put: %s/%s has d_count 0!\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name);
+ return;
}

/*
@@ -1288,5 +1307,13 @@
INIT_LIST_HEAD(&path_inuse);
INIT_LIST_HEAD(&fixup_head);

- printk(KERN_DEBUG "nfsd_init: initialized fhcache, entries=%lu\n", NFSD_MAXFH);
+ printk(KERN_DEBUG
+ "nfsd_init: initialized fhcache, entries=%lu\n", NFSD_MAXFH);
+ /*
+ * Display a warning if the ino_t is larger than 32 bits.
+ */
+ if (sizeof(ino_t) > sizeof(__u32))
+ printk(KERN_INFO
+ "NFSD: ino_t is %d bytes, using lower 4 bytes\n",
+ sizeof(ino_t));
}
--- linux-2.1.109/fs/lockd/svcsubs.c.old Wed Dec 10 00:12:14 1997
+++ linux-2.1.109/fs/lockd/svcsubs.c Mon Jul 20 19:36:15 1998
@@ -48,13 +48,15 @@
nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
struct nfs_fh *f)
{
- struct nlm_file *file;
struct knfs_fh *fh = (struct knfs_fh *) f;
- unsigned int hash = file_hash(fh->fh_dev, fh->fh_ino);
+ struct nlm_file *file;
+ unsigned int hash;
u32 nfserr;

- dprintk("lockd: nlm_file_lookup(%s/%ld)\n",
- kdevname(fh->fh_dev), fh->fh_ino);
+ dprintk("lockd: nlm_file_lookup(%s/%u)\n",
+ kdevname(u32_to_kdev_t(fh->fh_dev)), fh->fh_ino);
+
+ hash = file_hash(u32_to_kdev_t(fh->fh_dev), u32_to_ino_t(fh->fh_ino));

/* Lock file table */
down(&nlm_file_sema);
@@ -65,8 +67,8 @@
goto found;
}

- dprintk("lockd: creating file for %s/%ld\n",
- kdevname(fh->fh_dev), fh->fh_ino);
+ dprintk("lockd: creating file for %s/%u\n",
+ kdevname(u32_to_kdev_t(fh->fh_dev)), fh->fh_ino);
nfserr = nlm_lck_denied_nolocks;
file = (struct nlm_file *) kmalloc(sizeof(*file), GFP_KERNEL);
if (!file)

--------------B9AA237865D85A26BFA60902--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.altern.org/andrebalsa/doc/lkml-faq.html