Disable .zfs directory on 32-bit systems

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>
This commit is contained in:
Brian Behlendorf 2012-07-19 14:50:25 -07:00
parent 2a4a9dc2f0
commit fc173c8589

View 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 */
}
/*