aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2014-04-01 11:08:43 -0400
committerMiklos Szeredi <mszeredi@suse.cz>2014-04-01 11:08:43 -0400
commitc0d268c3661efdfc76dde90ff2bc12806410cd0a (patch)
treec5db188c6ce105b26d392099e15635fa7c9e419d /fs/ext4
parentda1ce0670c14d8380e423a3239e562a1dc15fa9e (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.c211
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
3003struct 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
3198end_rename: 3215end_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;