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:
Ernesto A. Fernández committed 2019-09-10 00:55:16 -03:00
1 parent 930ac1900e
commit 652bc7e61e
6 files changed
+33 -38

No files matched your search

+3 -5
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;