Hi Linus,

  The following patch separates the representation of NFS filehandles
in the nfs mount structure from the internal kernel representation.

  The motivation for doing this is Russell's complaint about alignment
issues on PPC architectures when casting from the generic filehandle
to knfsd filehandles.

  This patch ensures that both the internal generic NFS filehandle and
the knfsd filehandles have integer alignment, thus rendering the cast
portable across architectures. It makes sure that we preserve the
current alignment within the nfs mount structure, hence we don't break
the userland mount programs.

Cheers,
  Trond

diff -u --recursive --new-file linux-2.4.1-pre2/fs/nfs/inode.c 
linux-2.4.1-fix_ppc/fs/nfs/inode.c
--- linux-2.4.1-pre2/fs/nfs/inode.c     Tue Dec 12 02:46:04 2000
+++ linux-2.4.1-fix_ppc/fs/nfs/inode.c  Fri Jan 12 01:07:38 2001
@@ -239,7 +239,7 @@
        struct nfs_server       *server;
        struct rpc_xprt         *xprt = NULL;
        struct rpc_clnt         *clnt = NULL;
-       struct nfs_fh           *root = &data->root, fh;
+       struct nfs_fh           fh;
        struct inode            *root_inode = NULL;
        unsigned int            authflavor;
        struct sockaddr_in      srvaddr;
@@ -251,7 +251,6 @@
        if (!data)
                goto out_miss_args;
 
-       memset(&fh, 0, sizeof(fh));
        if (data->version != NFS_MOUNT_VERSION) {
                printk("nfs warning: mount version %s than kernel\n",
                        data->version < NFS_MOUNT_VERSION ? "older" : "newer");
@@ -259,12 +258,21 @@
                        data->namlen = 0;
                if (data->version < 3)
                        data->bsize  = 0;
-               if (data->version < 4) {
+               if (data->version < 4)
                        data->flags &= ~NFS_MOUNT_VER3;
-                       root = &fh;
-                       root->size = NFS2_FHSIZE;
-                       memcpy(root->data, data->old_root.data, NFS2_FHSIZE);
+       }
+
+       memset(&fh, 0, sizeof(fh));
+       if (data->version < 4) {
+               fh.size = NFS2_FHSIZE;
+               memcpy(fh.data, data->old_root.data, NFS2_FHSIZE);
+       } else {
+               fh.size = (data->flags & NFS_MOUNT_VER3) ? data->root.size : 
+NFS2_FHSIZE;
+               if (fh.size > sizeof(fh.data)) {
+                       printk(KERN_WARNING "NFS: mount program passes invalid 
+filehandle!\n");
+                       goto out_no_remote;
                }
+               memcpy(fh.data, data->root.data, fh.size);
        }
 
        /* We now require that the mount process passes the remote address */
@@ -363,9 +371,10 @@
         * the root fh attributes.
         */
        /* Did getting the root inode fail? */
-       if (!(root_inode = nfs_get_root(sb, root))
+       if (!(root_inode = nfs_get_root(sb, &fh))
            && (data->flags & NFS_MOUNT_VER3)) {
                data->flags &= ~NFS_MOUNT_VER3;
+               fh.size = NFS2_FHSIZE;
                rpciod_down();
                rpc_shutdown_client(server->client);
                goto nfsv3_try_again;
@@ -380,7 +389,7 @@
        sb->s_root->d_op = &nfs_dentry_operations;
 
        /* Get some general file system info */
-        if (server->rpc_ops->statfs(server, root, &fsinfo) >= 0) {
+        if (server->rpc_ops->statfs(server, &fh, &fsinfo) >= 0) {
                if (server->namelen == 0)
                        server->namelen = fsinfo.namelen;
        } else {
diff -u --recursive --new-file linux-2.4.1-pre2/include/linux/nfs.h 
linux-2.4.1-fix_ppc/include/linux/nfs.h
--- linux-2.4.1-pre2/include/linux/nfs.h        Sat Apr  1 18:04:27 2000
+++ linux-2.4.1-fix_ppc/include/linux/nfs.h     Fri Jan 12 01:09:59 2001
@@ -93,8 +93,8 @@
  */
 #define NFS_MAXFHSIZE          64
 struct nfs_fh {
-       unsigned short          size;
-       unsigned char           data[NFS_MAXFHSIZE];
+       unsigned int            size;
+       unsigned int            data[NFS_MAXFHSIZE / sizeof(int)];
 };
 
 /*
diff -u --recursive --new-file linux-2.4.1-pre2/include/linux/nfs3.h 
linux-2.4.1-fix_ppc/include/linux/nfs3.h
--- linux-2.4.1-pre2/include/linux/nfs3.h       Sat Apr  1 18:04:27 2000
+++ linux-2.4.1-fix_ppc/include/linux/nfs3.h    Fri Jan 12 01:09:35 2001
@@ -58,6 +58,11 @@
        NF3BAD  = 8
 };
 
+struct nfs3_fh {
+       unsigned short          size;
+       unsigned char           data[NFS3_FHSIZE];
+};
+
 #define NFS3_VERSION           3
 #define NFS3PROC_NULL          0
 #define NFS3PROC_GETATTR       1
diff -u --recursive --new-file linux-2.4.1-pre2/include/linux/nfs_mount.h 
linux-2.4.1-fix_ppc/include/linux/nfs_mount.h
--- linux-2.4.1-pre2/include/linux/nfs_mount.h  Fri Jan  5 21:55:12 2001
+++ linux-2.4.1-fix_ppc/include/linux/nfs_mount.h       Fri Jan 12 01:34:12 2001
@@ -9,7 +9,8 @@
  *  structure passed from user-space to kernel-space during an nfs mount
  */
 #include <linux/in.h>
-#include <linux/nfs.h>
+#include <linux/nfs2.h>
+#include <linux/nfs3.h>
 
 /*
  * WARNING!  Do not delete or change the order of these fields.  If
@@ -37,7 +38,7 @@
        char            hostname[256];          /* 1 */
        int             namlen;                 /* 2 */
        unsigned int    bsize;                  /* 3 */
-       struct nfs_fh   root;                   /* 4 */
+       struct nfs3_fh  root;                   /* 4 */
 };
 
 /* bits in the flags field */
diff -u --recursive --new-file linux-2.4.1-pre2/include/linux/nfsd/nfsfh.h 
linux-2.4.1-fix_ppc/include/linux/nfsd/nfsfh.h
--- linux-2.4.1-pre2/include/linux/nfsd/nfsfh.h Fri Jan  5 22:32:31 2001
+++ linux-2.4.1-fix_ppc/include/linux/nfsd/nfsfh.h      Fri Jan 12 02:16:14 2001
@@ -31,7 +31,7 @@
  * ino/dev of the exported inode.
  */
 struct nfs_fhbase_old {
-       struct dentry * fb_dentry;      /* dentry cookie - always 0xfeebbaca */
+       __u32           fb_dcookie;     /* dentry cookie - always 0xfeebbaca */
        __u32           fb_ino;         /* our inode number */
        __u32           fb_dirino;      /* dir inode number, 0 for directories */
        __u32           fb_dev;         /* our device */
@@ -101,7 +101,7 @@
        } fh_base;
 };
 
-#define ofh_dcookie            fh_base.fh_old.fb_dentry
+#define ofh_dcookie            fh_base.fh_old.fb_dcookie
 #define ofh_ino                        fh_base.fh_old.fb_ino
 #define ofh_dirino             fh_base.fh_old.fb_dirino
 #define ofh_dev                        fh_base.fh_old.fb_dev

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/

Reply via email to