diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2014-04-01 11:08:43 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2014-04-01 11:08:43 -0400 |
commit | c0d268c3661efdfc76dde90ff2bc12806410cd0a (patch) | |
tree | c5db188c6ce105b26d392099e15635fa7c9e419d /fs/ext4 | |
parent | da1ce0670c14d8380e423a3239e562a1dc15fa9e (diff) |
ext4: rename: create ext4_renament structure for local vars
Need to split up ext4_rename() into helpers but there are too many local
variables involved, so create a new structure. This also, apparently,
makes the generated code size slightly smaller.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Reviewed-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/namei.c | 211 |
1 files changed, 114 insertions, 97 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 5f19171b3e1f..7193cea805ff 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -3000,6 +3000,22 @@ static struct buffer_head *ext4_get_first_dir_block(handle_t *handle, | |||
3000 | return ext4_get_first_inline_block(inode, parent_de, retval); | 3000 | return ext4_get_first_inline_block(inode, parent_de, retval); |
3001 | } | 3001 | } |
3002 | 3002 | ||
3003 | struct ext4_renament { | ||
3004 | struct inode *dir; | ||
3005 | struct dentry *dentry; | ||
3006 | struct inode *inode; | ||
3007 | |||
3008 | /* entry for "dentry" */ | ||
3009 | struct buffer_head *bh; | ||
3010 | struct ext4_dir_entry_2 *de; | ||
3011 | int inlined; | ||
3012 | |||
3013 | /* entry for ".." in inode if it's a directory */ | ||
3014 | struct buffer_head *dir_bh; | ||
3015 | struct ext4_dir_entry_2 *parent_de; | ||
3016 | int dir_inlined; | ||
3017 | }; | ||
3018 | |||
3003 | /* | 3019 | /* |
3004 | * Anybody can rename anything with this: the permission checks are left to the | 3020 | * Anybody can rename anything with this: the permission checks are left to the |
3005 | * higher-level routines. | 3021 | * higher-level routines. |
@@ -3012,193 +3028,194 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
3012 | struct inode *new_dir, struct dentry *new_dentry) | 3028 | struct inode *new_dir, struct dentry *new_dentry) |
3013 | { | 3029 | { |
3014 | handle_t *handle = NULL; | 3030 | handle_t *handle = NULL; |
3015 | struct inode *old_inode, *new_inode; | 3031 | struct ext4_renament old = { |
3016 | struct buffer_head *old_bh, *new_bh, *dir_bh; | 3032 | .dir = old_dir, |
3017 | struct ext4_dir_entry_2 *old_de, *new_de; | 3033 | .dentry = old_dentry, |
3034 | .inode = old_dentry->d_inode, | ||
3035 | }; | ||
3036 | struct ext4_renament new = { | ||
3037 | .dir = new_dir, | ||
3038 | .dentry = new_dentry, | ||
3039 | .inode = new_dentry->d_inode, | ||
3040 | }; | ||
3018 | int retval; | 3041 | int retval; |
3019 | int inlined = 0, new_inlined = 0; | ||
3020 | struct ext4_dir_entry_2 *parent_de; | ||
3021 | |||
3022 | dquot_initialize(old_dir); | ||
3023 | dquot_initialize(new_dir); | ||
3024 | 3042 | ||
3025 | old_bh = new_bh = dir_bh = NULL; | 3043 | dquot_initialize(old.dir); |
3044 | dquot_initialize(new.dir); | ||
3026 | 3045 | ||
3027 | /* Initialize quotas before so that eventual writes go | 3046 | /* Initialize quotas before so that eventual writes go |
3028 | * in separate transaction */ | 3047 | * in separate transaction */ |
3029 | if (new_dentry->d_inode) | 3048 | if (new.inode) |
3030 | dquot_initialize(new_dentry->d_inode); | 3049 | dquot_initialize(new.inode); |
3031 | 3050 | ||
3032 | old_bh = ext4_find_entry(old_dir, &old_dentry->d_name, &old_de, NULL); | 3051 | old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL); |
3033 | /* | 3052 | /* |
3034 | * Check for inode number is _not_ due to possible IO errors. | 3053 | * Check for inode number is _not_ due to possible IO errors. |
3035 | * We might rmdir the source, keep it as pwd of some process | 3054 | * We might rmdir the source, keep it as pwd of some process |
3036 | * and merrily kill the link to whatever was created under the | 3055 | * and merrily kill the link to whatever was created under the |
3037 | * same name. Goodbye sticky bit ;-< | 3056 | * same name. Goodbye sticky bit ;-< |
3038 | */ | 3057 | */ |
3039 | old_inode = old_dentry->d_inode; | ||
3040 | retval = -ENOENT; | 3058 | retval = -ENOENT; |
3041 | if (!old_bh || le32_to_cpu(old_de->inode) != old_inode->i_ino) | 3059 | if (!old.bh || le32_to_cpu(old.de->inode) != old.inode->i_ino) |
3042 | goto end_rename; | 3060 | goto end_rename; |
3043 | 3061 | ||
3044 | new_inode = new_dentry->d_inode; | 3062 | new.bh = ext4_find_entry(new.dir, &new.dentry->d_name, |
3045 | new_bh = ext4_find_entry(new_dir, &new_dentry->d_name, | 3063 | &new.de, &new.inlined); |
3046 | &new_de, &new_inlined); | 3064 | if (new.bh) { |
3047 | if (new_bh) { | 3065 | if (!new.inode) { |
3048 | if (!new_inode) { | 3066 | brelse(new.bh); |
3049 | brelse(new_bh); | 3067 | new.bh = NULL; |
3050 | new_bh = NULL; | ||
3051 | } | 3068 | } |
3052 | } | 3069 | } |
3053 | if (new_inode && !test_opt(new_dir->i_sb, NO_AUTO_DA_ALLOC)) | 3070 | if (new.inode && !test_opt(new.dir->i_sb, NO_AUTO_DA_ALLOC)) |
3054 | ext4_alloc_da_blocks(old_inode); | 3071 | ext4_alloc_da_blocks(old.inode); |
3055 | 3072 | ||
3056 | handle = ext4_journal_start(old_dir, EXT4_HT_DIR, | 3073 | handle = ext4_journal_start(old.dir, EXT4_HT_DIR, |
3057 | (2 * EXT4_DATA_TRANS_BLOCKS(old_dir->i_sb) + | 3074 | (2 * EXT4_DATA_TRANS_BLOCKS(old.dir->i_sb) + |
3058 | EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2)); | 3075 | EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2)); |
3059 | if (IS_ERR(handle)) | 3076 | if (IS_ERR(handle)) |
3060 | return PTR_ERR(handle); | 3077 | return PTR_ERR(handle); |
3061 | 3078 | ||
3062 | if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir)) | 3079 | if (IS_DIRSYNC(old.dir) || IS_DIRSYNC(new.dir)) |
3063 | ext4_handle_sync(handle); | 3080 | ext4_handle_sync(handle); |
3064 | 3081 | ||
3065 | if (S_ISDIR(old_inode->i_mode)) { | 3082 | if (S_ISDIR(old.inode->i_mode)) { |
3066 | if (new_inode) { | 3083 | if (new.inode) { |
3067 | retval = -ENOTEMPTY; | 3084 | retval = -ENOTEMPTY; |
3068 | if (!empty_dir(new_inode)) | 3085 | if (!empty_dir(new.inode)) |
3069 | goto end_rename; | 3086 | goto end_rename; |
3070 | } | 3087 | } |
3071 | retval = -EIO; | 3088 | retval = -EIO; |
3072 | dir_bh = ext4_get_first_dir_block(handle, old_inode, | 3089 | old.dir_bh = ext4_get_first_dir_block(handle, old.inode, |
3073 | &retval, &parent_de, | 3090 | &retval, &old.parent_de, |
3074 | &inlined); | 3091 | &old.dir_inlined); |
3075 | if (!dir_bh) | 3092 | if (!old.dir_bh) |
3076 | goto end_rename; | 3093 | goto end_rename; |
3077 | if (le32_to_cpu(parent_de->inode) != old_dir->i_ino) | 3094 | if (le32_to_cpu(old.parent_de->inode) != old.dir->i_ino) |
3078 | goto end_rename; | 3095 | goto end_rename; |
3079 | retval = -EMLINK; | 3096 | retval = -EMLINK; |
3080 | if (!new_inode && new_dir != old_dir && | 3097 | if (!new.inode && new.dir != old.dir && |
3081 | EXT4_DIR_LINK_MAX(new_dir)) | 3098 | EXT4_DIR_LINK_MAX(new.dir)) |
3082 | goto end_rename; | 3099 | goto end_rename; |
3083 | BUFFER_TRACE(dir_bh, "get_write_access"); | 3100 | BUFFER_TRACE(old.dir_bh, "get_write_access"); |
3084 | retval = ext4_journal_get_write_access(handle, dir_bh); | 3101 | retval = ext4_journal_get_write_access(handle, old.dir_bh); |
3085 | if (retval) | 3102 | if (retval) |
3086 | goto end_rename; | 3103 | goto end_rename; |
3087 | } | 3104 | } |
3088 | if (!new_bh) { | 3105 | if (!new.bh) { |
3089 | retval = ext4_add_entry(handle, new_dentry, old_inode); | 3106 | retval = ext4_add_entry(handle, new.dentry, old.inode); |
3090 | if (retval) | 3107 | if (retval) |
3091 | goto end_rename; | 3108 | goto end_rename; |
3092 | } else { | 3109 | } else { |
3093 | BUFFER_TRACE(new_bh, "get write access"); | 3110 | BUFFER_TRACE(new.bh, "get write access"); |
3094 | retval = ext4_journal_get_write_access(handle, new_bh); | 3111 | retval = ext4_journal_get_write_access(handle, new.bh); |
3095 | if (retval) | 3112 | if (retval) |
3096 | goto end_rename; | 3113 | goto end_rename; |
3097 | new_de->inode = cpu_to_le32(old_inode->i_ino); | 3114 | new.de->inode = cpu_to_le32(old.inode->i_ino); |
3098 | if (EXT4_HAS_INCOMPAT_FEATURE(new_dir->i_sb, | 3115 | if (EXT4_HAS_INCOMPAT_FEATURE(new.dir->i_sb, |
3099 | EXT4_FEATURE_INCOMPAT_FILETYPE)) | 3116 | EXT4_FEATURE_INCOMPAT_FILETYPE)) |
3100 | new_de->file_type = old_de->file_type; | 3117 | new.de->file_type = old.de->file_type; |
3101 | new_dir->i_version++; | 3118 | new.dir->i_version++; |
3102 | new_dir->i_ctime = new_dir->i_mtime = | 3119 | new.dir->i_ctime = new.dir->i_mtime = |
3103 | ext4_current_time(new_dir); | 3120 | ext4_current_time(new.dir); |
3104 | ext4_mark_inode_dirty(handle, new_dir); | 3121 | ext4_mark_inode_dirty(handle, new.dir); |
3105 | BUFFER_TRACE(new_bh, "call ext4_handle_dirty_metadata"); | 3122 | BUFFER_TRACE(new.bh, "call ext4_handle_dirty_metadata"); |
3106 | if (!new_inlined) { | 3123 | if (!new.inlined) { |
3107 | retval = ext4_handle_dirty_dirent_node(handle, | 3124 | retval = ext4_handle_dirty_dirent_node(handle, |
3108 | new_dir, new_bh); | 3125 | new.dir, new.bh); |
3109 | if (unlikely(retval)) { | 3126 | if (unlikely(retval)) { |
3110 | ext4_std_error(new_dir->i_sb, retval); | 3127 | ext4_std_error(new.dir->i_sb, retval); |
3111 | goto end_rename; | 3128 | goto end_rename; |
3112 | } | 3129 | } |
3113 | } | 3130 | } |
3114 | brelse(new_bh); | 3131 | brelse(new.bh); |
3115 | new_bh = NULL; | 3132 | new.bh = NULL; |
3116 | } | 3133 | } |
3117 | 3134 | ||
3118 | /* | 3135 | /* |
3119 | * Like most other Unix systems, set the ctime for inodes on a | 3136 | * Like most other Unix systems, set the ctime for inodes on a |
3120 | * rename. | 3137 | * rename. |
3121 | */ | 3138 | */ |
3122 | old_inode->i_ctime = ext4_current_time(old_inode); | 3139 | old.inode->i_ctime = ext4_current_time(old.inode); |
3123 | ext4_mark_inode_dirty(handle, old_inode); | 3140 | ext4_mark_inode_dirty(handle, old.inode); |
3124 | 3141 | ||
3125 | /* | 3142 | /* |
3126 | * ok, that's it | 3143 | * ok, that's it |
3127 | */ | 3144 | */ |
3128 | if (le32_to_cpu(old_de->inode) != old_inode->i_ino || | 3145 | if (le32_to_cpu(old.de->inode) != old.inode->i_ino || |
3129 | old_de->name_len != old_dentry->d_name.len || | 3146 | old.de->name_len != old.dentry->d_name.len || |
3130 | strncmp(old_de->name, old_dentry->d_name.name, old_de->name_len) || | 3147 | strncmp(old.de->name, old.dentry->d_name.name, old.de->name_len) || |
3131 | (retval = ext4_delete_entry(handle, old_dir, | 3148 | (retval = ext4_delete_entry(handle, old.dir, |
3132 | old_de, old_bh)) == -ENOENT) { | 3149 | old.de, old.bh)) == -ENOENT) { |
3133 | /* old_de could have moved from under us during htree split, so | 3150 | /* old.de could have moved from under us during htree split, so |
3134 | * make sure that we are deleting the right entry. We might | 3151 | * make sure that we are deleting the right entry. We might |
3135 | * also be pointing to a stale entry in the unused part of | 3152 | * also be pointing to a stale entry in the unused part of |
3136 | * old_bh so just checking inum and the name isn't enough. */ | 3153 | * old.bh so just checking inum and the name isn't enough. */ |
3137 | struct buffer_head *old_bh2; | 3154 | struct buffer_head *old_bh2; |
3138 | struct ext4_dir_entry_2 *old_de2; | 3155 | struct ext4_dir_entry_2 *old_de2; |
3139 | 3156 | ||
3140 | old_bh2 = ext4_find_entry(old_dir, &old_dentry->d_name, | 3157 | old_bh2 = ext4_find_entry(old.dir, &old.dentry->d_name, |
3141 | &old_de2, NULL); | 3158 | &old_de2, NULL); |
3142 | if (old_bh2) { | 3159 | if (old_bh2) { |
3143 | retval = ext4_delete_entry(handle, old_dir, | 3160 | retval = ext4_delete_entry(handle, old.dir, |
3144 | old_de2, old_bh2); | 3161 | old_de2, old_bh2); |
3145 | brelse(old_bh2); | 3162 | brelse(old_bh2); |
3146 | } | 3163 | } |
3147 | } | 3164 | } |
3148 | if (retval) { | 3165 | if (retval) { |
3149 | ext4_warning(old_dir->i_sb, | 3166 | ext4_warning(old.dir->i_sb, |
3150 | "Deleting old file (%lu), %d, error=%d", | 3167 | "Deleting old file (%lu), %d, error=%d", |
3151 | old_dir->i_ino, old_dir->i_nlink, retval); | 3168 | old.dir->i_ino, old.dir->i_nlink, retval); |
3152 | } | 3169 | } |
3153 | 3170 | ||
3154 | if (new_inode) { | 3171 | if (new.inode) { |
3155 | ext4_dec_count(handle, new_inode); | 3172 | ext4_dec_count(handle, new.inode); |
3156 | new_inode->i_ctime = ext4_current_time(new_inode); | 3173 | new.inode->i_ctime = ext4_current_time(new.inode); |
3157 | } | 3174 | } |
3158 | old_dir->i_ctime = old_dir->i_mtime = ext4_current_time(old_dir); | 3175 | old.dir->i_ctime = old.dir->i_mtime = ext4_current_time(old.dir); |
3159 | ext4_update_dx_flag(old_dir); | 3176 | ext4_update_dx_flag(old.dir); |
3160 | if (dir_bh) { | 3177 | if (old.dir_bh) { |
3161 | parent_de->inode = cpu_to_le32(new_dir->i_ino); | 3178 | old.parent_de->inode = cpu_to_le32(new.dir->i_ino); |
3162 | BUFFER_TRACE(dir_bh, "call ext4_handle_dirty_metadata"); | 3179 | BUFFER_TRACE(old.dir_bh, "call ext4_handle_dirty_metadata"); |
3163 | if (!inlined) { | 3180 | if (!old.dir_inlined) { |
3164 | if (is_dx(old_inode)) { | 3181 | if (is_dx(old.inode)) { |
3165 | retval = ext4_handle_dirty_dx_node(handle, | 3182 | retval = ext4_handle_dirty_dx_node(handle, |
3166 | old_inode, | 3183 | old.inode, |
3167 | dir_bh); | 3184 | old.dir_bh); |
3168 | } else { | 3185 | } else { |
3169 | retval = ext4_handle_dirty_dirent_node(handle, | 3186 | retval = ext4_handle_dirty_dirent_node(handle, |
3170 | old_inode, dir_bh); | 3187 | old.inode, old.dir_bh); |
3171 | } | 3188 | } |
3172 | } else { | 3189 | } else { |
3173 | retval = ext4_mark_inode_dirty(handle, old_inode); | 3190 | retval = ext4_mark_inode_dirty(handle, old.inode); |
3174 | } | 3191 | } |
3175 | if (retval) { | 3192 | if (retval) { |
3176 | ext4_std_error(old_dir->i_sb, retval); | 3193 | ext4_std_error(old.dir->i_sb, retval); |
3177 | goto end_rename; | 3194 | goto end_rename; |
3178 | } | 3195 | } |
3179 | ext4_dec_count(handle, old_dir); | 3196 | ext4_dec_count(handle, old.dir); |
3180 | if (new_inode) { | 3197 | if (new.inode) { |
3181 | /* checked empty_dir above, can't have another parent, | 3198 | /* checked empty_dir above, can't have another parent, |
3182 | * ext4_dec_count() won't work for many-linked dirs */ | 3199 | * ext4_dec_count() won't work for many-linked dirs */ |
3183 | clear_nlink(new_inode); | 3200 | clear_nlink(new.inode); |
3184 | } else { | 3201 | } else { |
3185 | ext4_inc_count(handle, new_dir); | 3202 | ext4_inc_count(handle, new.dir); |
3186 | ext4_update_dx_flag(new_dir); | 3203 | ext4_update_dx_flag(new.dir); |
3187 | ext4_mark_inode_dirty(handle, new_dir); | 3204 | ext4_mark_inode_dirty(handle, new.dir); |
3188 | } | 3205 | } |
3189 | } | 3206 | } |
3190 | ext4_mark_inode_dirty(handle, old_dir); | 3207 | ext4_mark_inode_dirty(handle, old.dir); |
3191 | if (new_inode) { | 3208 | if (new.inode) { |
3192 | ext4_mark_inode_dirty(handle, new_inode); | 3209 | ext4_mark_inode_dirty(handle, new.inode); |
3193 | if (!new_inode->i_nlink) | 3210 | if (!new.inode->i_nlink) |
3194 | ext4_orphan_add(handle, new_inode); | 3211 | ext4_orphan_add(handle, new.inode); |
3195 | } | 3212 | } |
3196 | retval = 0; | 3213 | retval = 0; |
3197 | 3214 | ||
3198 | end_rename: | 3215 | end_rename: |
3199 | brelse(dir_bh); | 3216 | brelse(old.dir_bh); |
3200 | brelse(old_bh); | 3217 | brelse(old.bh); |
3201 | brelse(new_bh); | 3218 | brelse(new.bh); |
3202 | if (handle) | 3219 | if (handle) |
3203 | ext4_journal_stop(handle); | 3220 | ext4_journal_stop(handle); |
3204 | return retval; | 3221 | return retval; |