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:
parent
2a4a9dc2f0
commit
fc173c8589
|
@ -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.
|
* Lookup the inode with given id, it will be allocated if needed.
|
||||||
*/
|
*/
|
||||||
static struct inode *
|
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)
|
const struct file_operations *fops, const struct inode_operations *ops)
|
||||||
{
|
{
|
||||||
struct inode *ip = NULL;
|
struct inode *ip = NULL;
|
||||||
|
|
||||||
while (ip == NULL) {
|
while (ip == NULL) {
|
||||||
ip = ilookup(zsb->z_sb, id);
|
ip = ilookup(zsb->z_sb, (unsigned long)id);
|
||||||
if (ip)
|
if (ip)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -267,10 +267,14 @@ zfsctl_inode_inactive(struct inode *ip)
|
||||||
* therefore checks against a vfs_count of 2 instead of 1. This reference
|
* 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
|
* is removed when the ctldir is destroyed in the unmount. All other entities
|
||||||
* under the '.zfs' directory are created dynamically as needed.
|
* 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
|
int
|
||||||
zfsctl_create(zfs_sb_t *zsb)
|
zfsctl_create(zfs_sb_t *zsb)
|
||||||
{
|
{
|
||||||
|
#if defined(CONFIG_64BIT)
|
||||||
ASSERT(zsb->z_ctldir == NULL);
|
ASSERT(zsb->z_ctldir == NULL);
|
||||||
|
|
||||||
zsb->z_ctldir = zfsctl_inode_alloc(zsb, ZFSCTL_INO_ROOT,
|
zsb->z_ctldir = zfsctl_inode_alloc(zsb, ZFSCTL_INO_ROOT,
|
||||||
|
@ -279,6 +283,9 @@ zfsctl_create(zfs_sb_t *zsb)
|
||||||
return (ENOENT);
|
return (ENOENT);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
#else
|
||||||
|
return (EOPNOTSUPP);
|
||||||
|
#endif /* CONFIG_64BIT */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue