aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/namei.c
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2014-04-01 11:08:44 -0400
committerMiklos Szeredi <mszeredi@suse.cz>2014-04-01 11:08:44 -0400
commitbd1af145b99311242673b32dff4599ce614352be (patch)
tree23fdc9a377faf39e963169dc5dc7b3535f23b71a /fs/ext4/namei.c
parent0d7d5d678bf9e07dffe22b018cf035d511d9e86e (diff)
ext4: rename: split out helper functions
Cross rename (exchange source and dest) will need to call some of these helpers for both source and dest, while overwriting rename currently only calls them for one or the other. This also makes the code easier to follow. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Reviewed-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/ext4/namei.c')
-rw-r--r--fs/ext4/namei.c199
1 files changed, 126 insertions, 73 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 87a8a6e613ba..75f1bde43dcc 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -3016,6 +3016,125 @@ struct ext4_renament {
3016 int dir_inlined; 3016 int dir_inlined;
3017}; 3017};
3018 3018
3019static int ext4_rename_dir_prepare(handle_t *handle, struct ext4_renament *ent)
3020{
3021 int retval;
3022
3023 ent->dir_bh = ext4_get_first_dir_block(handle, ent->inode,
3024 &retval, &ent->parent_de,
3025 &ent->dir_inlined);
3026 if (!ent->dir_bh)
3027 return retval;
3028 if (le32_to_cpu(ent->parent_de->inode) != ent->dir->i_ino)
3029 return -EIO;
3030 BUFFER_TRACE(ent->dir_bh, "get_write_access");
3031 return ext4_journal_get_write_access(handle, ent->dir_bh);
3032}
3033
3034static int ext4_rename_dir_finish(handle_t *handle, struct ext4_renament *ent,
3035 unsigned dir_ino)
3036{
3037 int retval;
3038
3039 ent->parent_de->inode = cpu_to_le32(dir_ino);
3040 BUFFER_TRACE(ent->dir_bh, "call ext4_handle_dirty_metadata");
3041 if (!ent->dir_inlined) {
3042 if (is_dx(ent->inode)) {
3043 retval = ext4_handle_dirty_dx_node(handle,
3044 ent->inode,
3045 ent->dir_bh);
3046 } else {
3047 retval = ext4_handle_dirty_dirent_node(handle,
3048 ent->inode,
3049 ent->dir_bh);
3050 }
3051 } else {
3052 retval = ext4_mark_inode_dirty(handle, ent->inode);
3053 }
3054 if (retval) {
3055 ext4_std_error(ent->dir->i_sb, retval);
3056 return retval;
3057 }
3058 return 0;
3059}
3060
3061static int ext4_setent(handle_t *handle, struct ext4_renament *ent,
3062 unsigned ino, unsigned file_type)
3063{
3064 int retval;
3065
3066 BUFFER_TRACE(ent->bh, "get write access");
3067 retval = ext4_journal_get_write_access(handle, ent->bh);
3068 if (retval)
3069 return retval;
3070 ent->de->inode = cpu_to_le32(ino);
3071 if (EXT4_HAS_INCOMPAT_FEATURE(ent->dir->i_sb,
3072 EXT4_FEATURE_INCOMPAT_FILETYPE))
3073 ent->de->file_type = file_type;
3074 ent->dir->i_version++;
3075 ent->dir->i_ctime = ent->dir->i_mtime =
3076 ext4_current_time(ent->dir);
3077 ext4_mark_inode_dirty(handle, ent->dir);
3078 BUFFER_TRACE(ent->bh, "call ext4_handle_dirty_metadata");
3079 if (!ent->inlined) {
3080 retval = ext4_handle_dirty_dirent_node(handle,
3081 ent->dir, ent->bh);
3082 if (unlikely(retval)) {
3083 ext4_std_error(ent->dir->i_sb, retval);
3084 return retval;
3085 }
3086 }
3087 brelse(ent->bh);
3088 ent->bh = NULL;
3089
3090 return 0;
3091}
3092
3093static int ext4_find_delete_entry(handle_t *handle, struct inode *dir,
3094 const struct qstr *d_name)
3095{
3096 int retval = -ENOENT;
3097 struct buffer_head *bh;
3098 struct ext4_dir_entry_2 *de;
3099
3100 bh = ext4_find_entry(dir, d_name, &de, NULL);
3101 if (bh) {
3102 retval = ext4_delete_entry(handle, dir, de, bh);
3103 brelse(bh);
3104 }
3105 return retval;
3106}
3107
3108static void ext4_rename_delete(handle_t *handle, struct ext4_renament *ent)
3109{
3110 int retval;
3111 /*
3112 * ent->de could have moved from under us during htree split, so make
3113 * sure that we are deleting the right entry. We might also be pointing
3114 * to a stale entry in the unused part of ent->bh so just checking inum
3115 * and the name isn't enough.
3116 */
3117 if (le32_to_cpu(ent->de->inode) != ent->inode->i_ino ||
3118 ent->de->name_len != ent->dentry->d_name.len ||
3119 strncmp(ent->de->name, ent->dentry->d_name.name,
3120 ent->de->name_len)) {
3121 retval = ext4_find_delete_entry(handle, ent->dir,
3122 &ent->dentry->d_name);
3123 } else {
3124 retval = ext4_delete_entry(handle, ent->dir, ent->de, ent->bh);
3125 if (retval == -ENOENT) {
3126 retval = ext4_find_delete_entry(handle, ent->dir,
3127 &ent->dentry->d_name);
3128 }
3129 }
3130
3131 if (retval) {
3132 ext4_warning(ent->dir->i_sb,
3133 "Deleting old file (%lu), %d, error=%d",
3134 ent->dir->i_ino, ent->dir->i_nlink, retval);
3135 }
3136}
3137
3019/* 3138/*
3020 * Anybody can rename anything with this: the permission checks are left to the 3139 * Anybody can rename anything with this: the permission checks are left to the
3021 * higher-level routines. 3140 * higher-level routines.
@@ -3089,16 +3208,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
3089 if (new.dir != old.dir && EXT4_DIR_LINK_MAX(new.dir)) 3208 if (new.dir != old.dir && EXT4_DIR_LINK_MAX(new.dir))
3090 goto end_rename; 3209 goto end_rename;
3091 } 3210 }
3092 retval = -EIO; 3211 retval = ext4_rename_dir_prepare(handle, &old);
3093 old.dir_bh = ext4_get_first_dir_block(handle, old.inode,
3094 &retval, &old.parent_de,
3095 &old.dir_inlined);
3096 if (!old.dir_bh)
3097 goto end_rename;
3098 if (le32_to_cpu(old.parent_de->inode) != old.dir->i_ino)
3099 goto end_rename;
3100 BUFFER_TRACE(old.dir_bh, "get_write_access");
3101 retval = ext4_journal_get_write_access(handle, old.dir_bh);
3102 if (retval) 3212 if (retval)
3103 goto end_rename; 3213 goto end_rename;
3104 } 3214 }
@@ -3107,29 +3217,10 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
3107 if (retval) 3217 if (retval)
3108 goto end_rename; 3218 goto end_rename;
3109 } else { 3219 } else {
3110 BUFFER_TRACE(new.bh, "get write access"); 3220 retval = ext4_setent(handle, &new,
3111 retval = ext4_journal_get_write_access(handle, new.bh); 3221 old.inode->i_ino, old.de->file_type);
3112 if (retval) 3222 if (retval)
3113 goto end_rename; 3223 goto end_rename;
3114 new.de->inode = cpu_to_le32(old.inode->i_ino);
3115 if (EXT4_HAS_INCOMPAT_FEATURE(new.dir->i_sb,
3116 EXT4_FEATURE_INCOMPAT_FILETYPE))
3117 new.de->file_type = old.de->file_type;
3118 new.dir->i_version++;
3119 new.dir->i_ctime = new.dir->i_mtime =
3120 ext4_current_time(new.dir);
3121 ext4_mark_inode_dirty(handle, new.dir);
3122 BUFFER_TRACE(new.bh, "call ext4_handle_dirty_metadata");
3123 if (!new.inlined) {
3124 retval = ext4_handle_dirty_dirent_node(handle,
3125 new.dir, new.bh);
3126 if (unlikely(retval)) {
3127 ext4_std_error(new.dir->i_sb, retval);
3128 goto end_rename;
3129 }
3130 }
3131 brelse(new.bh);
3132 new.bh = NULL;
3133 } 3224 }
3134 3225
3135 /* 3226 /*
@@ -3142,31 +3233,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
3142 /* 3233 /*
3143 * ok, that's it 3234 * ok, that's it
3144 */ 3235 */
3145 if (le32_to_cpu(old.de->inode) != old.inode->i_ino || 3236 ext4_rename_delete(handle, &old);
3146 old.de->name_len != old.dentry->d_name.len ||
3147 strncmp(old.de->name, old.dentry->d_name.name, old.de->name_len) ||
3148 (retval = ext4_delete_entry(handle, old.dir,
3149 old.de, old.bh)) == -ENOENT) {
3150 /* old.de could have moved from under us during htree split, so
3151 * make sure that we are deleting the right entry. We might
3152 * also be pointing to a stale entry in the unused part of
3153 * old.bh so just checking inum and the name isn't enough. */
3154 struct buffer_head *old_bh2;
3155 struct ext4_dir_entry_2 *old_de2;
3156
3157 old_bh2 = ext4_find_entry(old.dir, &old.dentry->d_name,
3158 &old_de2, NULL);
3159 if (old_bh2) {
3160 retval = ext4_delete_entry(handle, old.dir,
3161 old_de2, old_bh2);
3162 brelse(old_bh2);
3163 }
3164 }
3165 if (retval) {
3166 ext4_warning(old.dir->i_sb,
3167 "Deleting old file (%lu), %d, error=%d",
3168 old.dir->i_ino, old.dir->i_nlink, retval);
3169 }
3170 3237
3171 if (new.inode) { 3238 if (new.inode) {
3172 ext4_dec_count(handle, new.inode); 3239 ext4_dec_count(handle, new.inode);
@@ -3175,24 +3242,10 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
3175 old.dir->i_ctime = old.dir->i_mtime = ext4_current_time(old.dir); 3242 old.dir->i_ctime = old.dir->i_mtime = ext4_current_time(old.dir);
3176 ext4_update_dx_flag(old.dir); 3243 ext4_update_dx_flag(old.dir);
3177 if (old.dir_bh) { 3244 if (old.dir_bh) {
3178 old.parent_de->inode = cpu_to_le32(new.dir->i_ino); 3245 retval = ext4_rename_dir_finish(handle, &old, new.dir->i_ino);
3179 BUFFER_TRACE(old.dir_bh, "call ext4_handle_dirty_metadata"); 3246 if (retval)
3180 if (!old.dir_inlined) {
3181 if (is_dx(old.inode)) {
3182 retval = ext4_handle_dirty_dx_node(handle,
3183 old.inode,
3184 old.dir_bh);
3185 } else {
3186 retval = ext4_handle_dirty_dirent_node(handle,
3187 old.inode, old.dir_bh);
3188 }
3189 } else {
3190 retval = ext4_mark_inode_dirty(handle, old.inode);
3191 }
3192 if (retval) {
3193 ext4_std_error(old.dir->i_sb, retval);
3194 goto end_rename; 3247 goto end_rename;
3195 } 3248
3196 ext4_dec_count(handle, old.dir); 3249 ext4_dec_count(handle, old.dir);
3197 if (new.inode) { 3250 if (new.inode) {
3198 /* checked empty_dir above, can't have another parent, 3251 /* checked empty_dir above, can't have another parent,