Disable .zfs directory on 32-bit systems
authorBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 19 Jul 2012 21:50:25 +0000 (14:50 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 20 Jul 2012 19:20:57 +0000 (12:20 -0700)
The .zfs control directory implementation currently relies on
the fact that there is a direct 1:1 mapping from an object id
to its inode number.  This works well as long as the system
uses a 64-bit value to store the inode number.

Unfortunately, the Linux kernel defines the inode number as
an 'unsigned long' type.  This means that for 32-bit systems
will only have 32-bit inode numbers but we still have 64-bit
object ids.

This problem is particularly acute for the .zfs directories
which leverage those upper 32-bits.  This is done to avoid
conflicting with object ids which are allocated monotonically
starting from 0.  This is likely to also be a problem for
datasets on 32-bit systems with more than ~2 billion files.

The right long term fix must remove the simple 1:1 mapping.
Until that's done the only safe thing to do is to disable the
.zfs directory on 32-bit systems.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
module/zfs/zfs_ctldir.c

index 1923934..c49d717 100644 (file)
@@ -225,13 +225,13 @@ zfsctl_inode_alloc(zfs_sb_t *zsb, uint64_t id,
  * Lookup the inode with given id, it will be allocated if needed.
  */
 static struct inode *
-zfsctl_inode_lookup(zfs_sb_t *zsb, unsigned long id,
+zfsctl_inode_lookup(zfs_sb_t *zsb, uint64_t id,
     const struct file_operations *fops, const struct inode_operations *ops)
 {
        struct inode *ip = NULL;
 
        while (ip == NULL) {
-               ip = ilookup(zsb->z_sb, id);
+               ip = ilookup(zsb->z_sb, (unsigned long)id);
                if (ip)
                        break;
 
@@ -267,10 +267,14 @@ zfsctl_inode_inactive(struct inode *ip)
  * therefore checks against a vfs_count of 2 instead of 1.  This reference
  * is removed when the ctldir is destroyed in the unmount.  All other entities
  * under the '.zfs' directory are created dynamically as needed.
+ *
+ * Because the dynamically created '.zfs' directory entries assume the use
+ * of 64-bit inode numbers this support must be disabled on 32-bit systems.
  */
 int
 zfsctl_create(zfs_sb_t *zsb)
 {
+#if defined(CONFIG_64BIT)
        ASSERT(zsb->z_ctldir == NULL);
 
        zsb->z_ctldir = zfsctl_inode_alloc(zsb, ZFSCTL_INO_ROOT,
@@ -279,6 +283,9 @@ zfsctl_create(zfs_sb_t *zsb)
                return (ENOENT);
 
        return (0);
+#else
+       return (EOPNOTSUPP);
+#endif /* CONFIG_64BIT */
 }
 
 /*