mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-08-18 02:22:47 -07:00
apfs: clean up mess for 64-bit inode numbers
Having separate code to deal with inode numbers in 32-bit architectures has proved unwise; there is no verified performance benefit from this and now, after several commits with no testing, the 32-bit code won't even build. Fix this with a new const qualifier in the argument to APFS_I(), and from now on just use the 32-bit version of everything. It's important to always read the inode number with apfs_ino(), to avoid getting confused and working with the potentially overflowing i_ino; remove a few remaining instances of this bug. Also start setting the number by means of apfs_set_inode(), but don't touch the hacky code for private-dir; I intend to turn it into a real inode in the future. Finally, deal with the TODO regarding insert_inode_locked(): define apfs_insert_inode_locked() as a wrapper to insert_inode_locked4(), implementing the same functionality as insert_inode_locked() but with full support for 32-bit architectures. Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
This commit is contained in:
1 parent
930ac1900e
commit
652bc7e61e
6 files changed
+33
-38
No files matched your search
+3
-5
@@ -97,7 +97,7 @@ static struct apfs_query *apfs_dentry_lookup(struct inode *dir,
|
||||
struct apfs_sb_info *sbi = APFS_SB(sb);
|
||||
struct apfs_key key;
|
||||
struct apfs_query *query;
|
||||
u64 cnid = dir->i_ino;
|
||||
u64 cnid = apfs_ino(dir);
|
||||
int err;
|
||||
|
||||
apfs_init_drec_hashed_key(sb, cnid, child->name, &key);
|
||||
@@ -167,7 +167,7 @@ static int apfs_readdir(struct file *file, struct dir_context *ctx)
|
||||
struct apfs_sb_info *sbi = APFS_SB(sb);
|
||||
struct apfs_key key;
|
||||
struct apfs_query *query;
|
||||
u64 cnid = inode->i_ino;
|
||||
u64 cnid = apfs_ino(inode);
|
||||
loff_t pos;
|
||||
int err = 0;
|
||||
|
||||
@@ -1025,9 +1025,7 @@ int apfs_delete_orphan_link(struct inode *inode)
|
||||
*/
|
||||
parent_info.vfs_inode.i_sb = sb;
|
||||
parent_info.vfs_inode.i_ino = APFS_PRIV_DIR_INO_NUM;
|
||||
#if BITS_PER_LONG == 32
|
||||
parent_info.i_ino = APFS_PRIV_DIR_INO_NUM;
|
||||
#endif
|
||||
parent_info.i_ino64 = APFS_PRIV_DIR_INO_NUM;
|
||||
|
||||
query = apfs_dentry_lookup(&parent_info.vfs_inode, &qname, &drec);
|
||||
if (IS_ERR(query)) {
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ static int apfs_extent_read(struct inode *inode, sector_t iblock,
|
||||
ret = apfs_extent_from_query(query, extent);
|
||||
if (ret) {
|
||||
apfs_alert(sb, "bad extent record for inode 0x%llx",
|
||||
(unsigned long long) inode->i_ino);
|
||||
apfs_ino(inode));
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
+22
-18
@@ -172,7 +172,7 @@ corrupted:
|
||||
* apfs_inode_lookup - Lookup an inode record in the catalog b-tree
|
||||
* @inode: vfs inode to lookup
|
||||
*
|
||||
* Runs a catalog query for the @inode->i_ino inode record; returns a pointer
|
||||
* Runs a catalog query for the apfs_ino(@inode) inode record; returns a pointer
|
||||
* to the query structure on success, or an error pointer in case of failure.
|
||||
*/
|
||||
static struct apfs_query *apfs_inode_lookup(const struct inode *inode)
|
||||
@@ -199,10 +199,6 @@ static struct apfs_query *apfs_inode_lookup(const struct inode *inode)
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
#if BITS_PER_LONG == 64
|
||||
#define apfs_iget_locked iget_locked
|
||||
#else /* 64-bit inode numbers may not fit in the vfs inode */
|
||||
|
||||
/**
|
||||
* apfs_test_inode - Check if the inode matches a 64-bit inode number
|
||||
* @inode: inode to test
|
||||
@@ -210,10 +206,9 @@ static struct apfs_query *apfs_inode_lookup(const struct inode *inode)
|
||||
*/
|
||||
static int apfs_test_inode(struct inode *inode, void *cnid)
|
||||
{
|
||||
struct apfs_inode_info *ai = APFS_I(inode);
|
||||
u64 *ino = cnid;
|
||||
|
||||
return ai->i_ino == *ino;
|
||||
return apfs_ino(inode) == *ino;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -226,7 +221,7 @@ static int apfs_set_inode(struct inode *inode, void *cnid)
|
||||
struct apfs_inode_info *ai = APFS_I(inode);
|
||||
u64 *ino = cnid;
|
||||
|
||||
ai->i_ino = *ino;
|
||||
ai->i_ino64 = *ino;
|
||||
inode->i_ino = *ino; /* Just discard the higher bits here... */
|
||||
return 0;
|
||||
}
|
||||
@@ -236,15 +231,14 @@ static int apfs_set_inode(struct inode *inode, void *cnid)
|
||||
* @sb: filesystem superblock
|
||||
* @cnid: 64-bit inode number
|
||||
*
|
||||
* Works the same as iget_locked(), but supports 64-bit inode numbers.
|
||||
* Works the same as iget_locked(), but can handle 64-bit inode numbers on
|
||||
* 32-bit architectures.
|
||||
*/
|
||||
static struct inode *apfs_iget_locked(struct super_block *sb, u64 cnid)
|
||||
{
|
||||
return iget5_locked(sb, cnid, apfs_test_inode, apfs_set_inode, &cnid);
|
||||
}
|
||||
|
||||
#endif /* BITS_PER_LONG == 64 */
|
||||
|
||||
/**
|
||||
* apfs_iget - Populate inode structures with metadata from disk
|
||||
* @sb: filesystem superblock
|
||||
@@ -357,7 +351,7 @@ static int apfs_build_inode_val(struct inode *inode, struct qstr *qname,
|
||||
return -ENOMEM;
|
||||
|
||||
val->parent_id = cpu_to_le64(APFS_I(inode)->i_parent_id);
|
||||
val->private_id = cpu_to_le64(inode->i_ino);
|
||||
val->private_id = cpu_to_le64(apfs_ino(inode));
|
||||
|
||||
val->mod_time = apfs_timestamp(inode->i_mtime);
|
||||
val->create_time = val->change_time = val->access_time = val->mod_time;
|
||||
@@ -573,6 +567,20 @@ out_clear:
|
||||
clear_inode(inode);
|
||||
}
|
||||
|
||||
/**
|
||||
* apfs_insert_inode_locked - Wrapper for insert_inode_locked4()
|
||||
* @inode: vfs inode to insert in cache
|
||||
*
|
||||
* Works the same as insert_inode_locked(), but can handle 64-bit inode numbers
|
||||
* on 32-bit architectures.
|
||||
*/
|
||||
static int apfs_insert_inode_locked(struct inode *inode)
|
||||
{
|
||||
u64 cnid = apfs_ino(inode);
|
||||
|
||||
return insert_inode_locked4(inode, cnid, apfs_test_inode, &cnid);
|
||||
}
|
||||
|
||||
/**
|
||||
* apfs_new_inode - Create a new in-memory inode
|
||||
* @dir: parent inode
|
||||
@@ -601,10 +609,7 @@ struct inode *apfs_new_inode(struct inode *dir, umode_t mode, dev_t rdev)
|
||||
|
||||
cnid = le64_to_cpu(vsb_raw->apfs_next_obj_id);
|
||||
le64_add_cpu(&vsb_raw->apfs_next_obj_id, 1);
|
||||
inode->i_ino = cnid;
|
||||
#if BITS_PER_LONG == 32
|
||||
ai->ino = cnid;
|
||||
#endif
|
||||
apfs_set_inode(inode, &cnid);
|
||||
inode_init_owner(inode, dir, mode); /* TODO: handle override */
|
||||
ai->i_parent_id = apfs_ino(dir);
|
||||
set_nlink(inode, 1);
|
||||
@@ -623,8 +628,7 @@ struct inode *apfs_new_inode(struct inode *dir, umode_t mode, dev_t rdev)
|
||||
else
|
||||
le64_add_cpu(&vsb_raw->apfs_num_other_fsobjects, 1);
|
||||
|
||||
/* TODO: use insert_inode_locked4() on 32-bit architectures */
|
||||
if (insert_inode_locked(inode)) {
|
||||
if (apfs_insert_inode_locked(inode)) {
|
||||
/* The inode number should have been free, but wasn't */
|
||||
make_bad_inode(inode);
|
||||
iput(inode);
|
||||
|
||||
+3
-10
@@ -117,6 +117,7 @@ struct apfs_dstream {
|
||||
* APFS inode data in memory
|
||||
*/
|
||||
struct apfs_inode_info {
|
||||
u64 i_ino64; /* 32-bit-safe inode number */
|
||||
u64 i_parent_id; /* ID of primary parent */
|
||||
u64 i_extent_id; /* ID of the extent records */
|
||||
struct apfs_file_extent i_cached_extent; /* Latest extent record */
|
||||
@@ -124,14 +125,10 @@ struct apfs_inode_info {
|
||||
struct timespec64 i_crtime; /* Time of creation */
|
||||
u32 i_nchildren; /* Child count for directory */
|
||||
|
||||
#if BITS_PER_LONG == 32
|
||||
/* This is the actual inode number; vfs_inode.i_ino could overflow */
|
||||
u64 i_ino;
|
||||
#endif
|
||||
struct inode vfs_inode;
|
||||
};
|
||||
|
||||
static inline struct apfs_inode_info *APFS_I(struct inode *inode)
|
||||
static inline struct apfs_inode_info *APFS_I(const struct inode *inode)
|
||||
{
|
||||
return container_of(inode, struct apfs_inode_info, vfs_inode);
|
||||
}
|
||||
@@ -144,11 +141,7 @@ static inline struct apfs_inode_info *APFS_I(struct inode *inode)
|
||||
*/
|
||||
static inline u64 apfs_ino(const struct inode *inode)
|
||||
{
|
||||
#if BITS_PER_LONG == 64
|
||||
return inode->i_ino;
|
||||
#else
|
||||
return APFS_I(inode)->i_ino;
|
||||
#endif
|
||||
return APFS_I(inode)->i_ino64;
|
||||
}
|
||||
|
||||
extern struct inode *apfs_iget(struct super_block *sb, u64 cnid);
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ static const char *apfs_get_link(struct dentry *dentry, struct inode *inode,
|
||||
if (size == 0 || *(target + size - 1) != 0) {
|
||||
/* Target path must be NULL-terminated */
|
||||
apfs_alert(sb, "bad link target in inode 0x%llx",
|
||||
(unsigned long long) inode->i_ino);
|
||||
apfs_ino(inode));
|
||||
err = -EFSCORRUPTED;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
+3
-3
@@ -137,7 +137,7 @@ static int apfs_xattr_extents_read(struct inode *parent,
|
||||
err = apfs_extent_from_query(query, &ext);
|
||||
if (err) {
|
||||
apfs_alert(sb, "bad extent for xattr in inode 0x%llx",
|
||||
(unsigned long long) parent->i_ino);
|
||||
apfs_ino(parent));
|
||||
ret = err;
|
||||
goto done;
|
||||
}
|
||||
@@ -213,7 +213,7 @@ int __apfs_xattr_get(struct inode *inode, const char *name, void *buffer,
|
||||
struct apfs_key key;
|
||||
struct apfs_query *query;
|
||||
struct apfs_xattr xattr;
|
||||
u64 cnid = inode->i_ino;
|
||||
u64 cnid = apfs_ino(inode);
|
||||
int ret;
|
||||
|
||||
apfs_init_xattr_key(cnid, name, &key);
|
||||
@@ -296,7 +296,7 @@ ssize_t apfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
||||
struct apfs_sb_info *sbi = APFS_SB(sb);
|
||||
struct apfs_key key;
|
||||
struct apfs_query *query;
|
||||
u64 cnid = inode->i_ino;
|
||||
u64 cnid = apfs_ino(inode);
|
||||
size_t free = size;
|
||||
ssize_t ret;
|
||||
|
||||
|
||||
Reference in new issue
Block a user