Skip to content

Commit 25c6d98

Browse files
jankaratytso
authored andcommitted
ext4: Move orphan inode handling into a separate file
Move functions for handling orphan inodes into a new file fs/ext4/orphan.c to have them in one place and somewhat reduce size of other files. No code changes. Reviewed-by: Andreas Dilger <[email protected]> Reviewed-by: Theodore Ts'o <[email protected]> Signed-off-by: Jan Kara <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Theodore Ts'o <[email protected]>
1 parent 188c299 commit 25c6d98

File tree

5 files changed

+375
-363
lines changed

5 files changed

+375
-363
lines changed

fs/ext4/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ ext4-y := balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \
1010
indirect.o inline.o inode.o ioctl.o mballoc.o migrate.o \
1111
mmp.o move_extent.o namei.o page-io.o readpage.o resize.o \
1212
super.o symlink.o sysfs.o xattr.o xattr_hurd.o xattr_trusted.o \
13-
xattr_user.o fast_commit.o
13+
xattr_user.o fast_commit.o orphan.o
1414

1515
ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o
1616
ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o

fs/ext4/ext4.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2171,6 +2171,8 @@ static inline bool ext4_has_incompat_features(struct super_block *sb)
21712171
return (EXT4_SB(sb)->s_es->s_feature_incompat != 0);
21722172
}
21732173

2174+
extern int ext4_feature_set_ok(struct super_block *sb, int readonly);
2175+
21742176
/*
21752177
* Superblock flags
21762178
*/
@@ -3031,8 +3033,6 @@ extern int ext4_init_new_dir(handle_t *handle, struct inode *dir,
30313033
struct inode *inode);
30323034
extern int ext4_dirblock_csum_verify(struct inode *inode,
30333035
struct buffer_head *bh);
3034-
extern int ext4_orphan_add(handle_t *, struct inode *);
3035-
extern int ext4_orphan_del(handle_t *, struct inode *);
30363036
extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
30373037
__u32 start_minor_hash, __u32 *next_hash);
30383038
extern int ext4_search_dir(struct buffer_head *bh,
@@ -3501,6 +3501,7 @@ static inline bool ext4_is_quota_journalled(struct super_block *sb)
35013501
return (ext4_has_feature_quota(sb) ||
35023502
sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]);
35033503
}
3504+
int ext4_enable_quotas(struct super_block *sb);
35043505
#endif
35053506

35063507
/*
@@ -3762,6 +3763,12 @@ extern void ext4_stop_mmpd(struct ext4_sb_info *sbi);
37623763
/* verity.c */
37633764
extern const struct fsverity_operations ext4_verityops;
37643765

3766+
/* orphan.c */
3767+
extern int ext4_orphan_add(handle_t *, struct inode *);
3768+
extern int ext4_orphan_del(handle_t *, struct inode *);
3769+
extern void ext4_orphan_cleanup(struct super_block *sb,
3770+
struct ext4_super_block *es);
3771+
37653772
/*
37663773
* Add new method to test whether block and inode bitmaps are properly
37673774
* initialized. With uninit_bg reading the block from disk is not enough

fs/ext4/namei.c

Lines changed: 0 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -3054,188 +3054,6 @@ bool ext4_empty_dir(struct inode *inode)
30543054
return true;
30553055
}
30563056

3057-
/*
3058-
* ext4_orphan_add() links an unlinked or truncated inode into a list of
3059-
* such inodes, starting at the superblock, in case we crash before the
3060-
* file is closed/deleted, or in case the inode truncate spans multiple
3061-
* transactions and the last transaction is not recovered after a crash.
3062-
*
3063-
* At filesystem recovery time, we walk this list deleting unlinked
3064-
* inodes and truncating linked inodes in ext4_orphan_cleanup().
3065-
*
3066-
* Orphan list manipulation functions must be called under i_mutex unless
3067-
* we are just creating the inode or deleting it.
3068-
*/
3069-
int ext4_orphan_add(handle_t *handle, struct inode *inode)
3070-
{
3071-
struct super_block *sb = inode->i_sb;
3072-
struct ext4_sb_info *sbi = EXT4_SB(sb);
3073-
struct ext4_iloc iloc;
3074-
int err = 0, rc;
3075-
bool dirty = false;
3076-
3077-
if (!sbi->s_journal || is_bad_inode(inode))
3078-
return 0;
3079-
3080-
WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) &&
3081-
!inode_is_locked(inode));
3082-
/*
3083-
* Exit early if inode already is on orphan list. This is a big speedup
3084-
* since we don't have to contend on the global s_orphan_lock.
3085-
*/
3086-
if (!list_empty(&EXT4_I(inode)->i_orphan))
3087-
return 0;
3088-
3089-
/*
3090-
* Orphan handling is only valid for files with data blocks
3091-
* being truncated, or files being unlinked. Note that we either
3092-
* hold i_mutex, or the inode can not be referenced from outside,
3093-
* so i_nlink should not be bumped due to race
3094-
*/
3095-
ASSERT((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
3096-
S_ISLNK(inode->i_mode)) || inode->i_nlink == 0);
3097-
3098-
BUFFER_TRACE(sbi->s_sbh, "get_write_access");
3099-
err = ext4_journal_get_write_access(handle, sb, sbi->s_sbh,
3100-
EXT4_JTR_NONE);
3101-
if (err)
3102-
goto out;
3103-
3104-
err = ext4_reserve_inode_write(handle, inode, &iloc);
3105-
if (err)
3106-
goto out;
3107-
3108-
mutex_lock(&sbi->s_orphan_lock);
3109-
/*
3110-
* Due to previous errors inode may be already a part of on-disk
3111-
* orphan list. If so skip on-disk list modification.
3112-
*/
3113-
if (!NEXT_ORPHAN(inode) || NEXT_ORPHAN(inode) >
3114-
(le32_to_cpu(sbi->s_es->s_inodes_count))) {
3115-
/* Insert this inode at the head of the on-disk orphan list */
3116-
NEXT_ORPHAN(inode) = le32_to_cpu(sbi->s_es->s_last_orphan);
3117-
lock_buffer(sbi->s_sbh);
3118-
sbi->s_es->s_last_orphan = cpu_to_le32(inode->i_ino);
3119-
ext4_superblock_csum_set(sb);
3120-
unlock_buffer(sbi->s_sbh);
3121-
dirty = true;
3122-
}
3123-
list_add(&EXT4_I(inode)->i_orphan, &sbi->s_orphan);
3124-
mutex_unlock(&sbi->s_orphan_lock);
3125-
3126-
if (dirty) {
3127-
err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
3128-
rc = ext4_mark_iloc_dirty(handle, inode, &iloc);
3129-
if (!err)
3130-
err = rc;
3131-
if (err) {
3132-
/*
3133-
* We have to remove inode from in-memory list if
3134-
* addition to on disk orphan list failed. Stray orphan
3135-
* list entries can cause panics at unmount time.
3136-
*/
3137-
mutex_lock(&sbi->s_orphan_lock);
3138-
list_del_init(&EXT4_I(inode)->i_orphan);
3139-
mutex_unlock(&sbi->s_orphan_lock);
3140-
}
3141-
} else
3142-
brelse(iloc.bh);
3143-
3144-
jbd_debug(4, "superblock will point to %lu\n", inode->i_ino);
3145-
jbd_debug(4, "orphan inode %lu will point to %d\n",
3146-
inode->i_ino, NEXT_ORPHAN(inode));
3147-
out:
3148-
ext4_std_error(sb, err);
3149-
return err;
3150-
}
3151-
3152-
/*
3153-
* ext4_orphan_del() removes an unlinked or truncated inode from the list
3154-
* of such inodes stored on disk, because it is finally being cleaned up.
3155-
*/
3156-
int ext4_orphan_del(handle_t *handle, struct inode *inode)
3157-
{
3158-
struct list_head *prev;
3159-
struct ext4_inode_info *ei = EXT4_I(inode);
3160-
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
3161-
__u32 ino_next;
3162-
struct ext4_iloc iloc;
3163-
int err = 0;
3164-
3165-
if (!sbi->s_journal && !(sbi->s_mount_state & EXT4_ORPHAN_FS))
3166-
return 0;
3167-
3168-
WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) &&
3169-
!inode_is_locked(inode));
3170-
/* Do this quick check before taking global s_orphan_lock. */
3171-
if (list_empty(&ei->i_orphan))
3172-
return 0;
3173-
3174-
if (handle) {
3175-
/* Grab inode buffer early before taking global s_orphan_lock */
3176-
err = ext4_reserve_inode_write(handle, inode, &iloc);
3177-
}
3178-
3179-
mutex_lock(&sbi->s_orphan_lock);
3180-
jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino);
3181-
3182-
prev = ei->i_orphan.prev;
3183-
list_del_init(&ei->i_orphan);
3184-
3185-
/* If we're on an error path, we may not have a valid
3186-
* transaction handle with which to update the orphan list on
3187-
* disk, but we still need to remove the inode from the linked
3188-
* list in memory. */
3189-
if (!handle || err) {
3190-
mutex_unlock(&sbi->s_orphan_lock);
3191-
goto out_err;
3192-
}
3193-
3194-
ino_next = NEXT_ORPHAN(inode);
3195-
if (prev == &sbi->s_orphan) {
3196-
jbd_debug(4, "superblock will point to %u\n", ino_next);
3197-
BUFFER_TRACE(sbi->s_sbh, "get_write_access");
3198-
err = ext4_journal_get_write_access(handle, inode->i_sb,
3199-
sbi->s_sbh, EXT4_JTR_NONE);
3200-
if (err) {
3201-
mutex_unlock(&sbi->s_orphan_lock);
3202-
goto out_brelse;
3203-
}
3204-
lock_buffer(sbi->s_sbh);
3205-
sbi->s_es->s_last_orphan = cpu_to_le32(ino_next);
3206-
ext4_superblock_csum_set(inode->i_sb);
3207-
unlock_buffer(sbi->s_sbh);
3208-
mutex_unlock(&sbi->s_orphan_lock);
3209-
err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
3210-
} else {
3211-
struct ext4_iloc iloc2;
3212-
struct inode *i_prev =
3213-
&list_entry(prev, struct ext4_inode_info, i_orphan)->vfs_inode;
3214-
3215-
jbd_debug(4, "orphan inode %lu will point to %u\n",
3216-
i_prev->i_ino, ino_next);
3217-
err = ext4_reserve_inode_write(handle, i_prev, &iloc2);
3218-
if (err) {
3219-
mutex_unlock(&sbi->s_orphan_lock);
3220-
goto out_brelse;
3221-
}
3222-
NEXT_ORPHAN(i_prev) = ino_next;
3223-
err = ext4_mark_iloc_dirty(handle, i_prev, &iloc2);
3224-
mutex_unlock(&sbi->s_orphan_lock);
3225-
}
3226-
if (err)
3227-
goto out_brelse;
3228-
NEXT_ORPHAN(inode) = 0;
3229-
err = ext4_mark_iloc_dirty(handle, inode, &iloc);
3230-
out_err:
3231-
ext4_std_error(inode->i_sb, err);
3232-
return err;
3233-
3234-
out_brelse:
3235-
brelse(iloc.bh);
3236-
goto out_err;
3237-
}
3238-
32393057
static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
32403058
{
32413059
int retval;

0 commit comments

Comments
 (0)