diff options
-rw-r--r-- | fs/ocfs2/alloc.c | 16 | ||||
-rw-r--r-- | fs/ocfs2/alloc.h | 1 | ||||
-rw-r--r-- | fs/ocfs2/dir.c | 618 | ||||
-rw-r--r-- | fs/ocfs2/namei.c | 57 |
4 files changed, 594 insertions, 98 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 72cefe25382b..4ba7f0bdc248 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -5835,6 +5835,15 @@ static void ocfs2_zero_dinode_id2(struct inode *inode, struct ocfs2_dinode *di) | |||
5835 | memset(&di->id2, 0, blocksize - offsetof(struct ocfs2_dinode, id2)); | 5835 | memset(&di->id2, 0, blocksize - offsetof(struct ocfs2_dinode, id2)); |
5836 | } | 5836 | } |
5837 | 5837 | ||
5838 | void ocfs2_dinode_new_extent_list(struct inode *inode, | ||
5839 | struct ocfs2_dinode *di) | ||
5840 | { | ||
5841 | ocfs2_zero_dinode_id2(inode, di); | ||
5842 | di->id2.i_list.l_tree_depth = 0; | ||
5843 | di->id2.i_list.l_next_free_rec = 0; | ||
5844 | di->id2.i_list.l_count = cpu_to_le16(ocfs2_extent_recs_per_inode(inode->i_sb)); | ||
5845 | } | ||
5846 | |||
5838 | void ocfs2_set_inode_data_inline(struct inode *inode, struct ocfs2_dinode *di) | 5847 | void ocfs2_set_inode_data_inline(struct inode *inode, struct ocfs2_dinode *di) |
5839 | { | 5848 | { |
5840 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | 5849 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
@@ -5863,7 +5872,6 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode, | |||
5863 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | 5872 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
5864 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 5873 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
5865 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | 5874 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; |
5866 | struct ocfs2_extent_list *el = &di->id2.i_list; | ||
5867 | struct ocfs2_alloc_context *data_ac = NULL; | 5875 | struct ocfs2_alloc_context *data_ac = NULL; |
5868 | struct page **pages = NULL; | 5876 | struct page **pages = NULL; |
5869 | loff_t end = osb->s_clustersize; | 5877 | loff_t end = osb->s_clustersize; |
@@ -5956,11 +5964,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode, | |||
5956 | di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features); | 5964 | di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features); |
5957 | spin_unlock(&oi->ip_lock); | 5965 | spin_unlock(&oi->ip_lock); |
5958 | 5966 | ||
5959 | ocfs2_zero_dinode_id2(inode, di); | 5967 | ocfs2_dinode_new_extent_list(inode, di); |
5960 | |||
5961 | el->l_tree_depth = 0; | ||
5962 | el->l_next_free_rec = 0; | ||
5963 | el->l_count = cpu_to_le16(ocfs2_extent_recs_per_inode(inode->i_sb)); | ||
5964 | 5968 | ||
5965 | ocfs2_journal_dirty(handle, di_bh); | 5969 | ocfs2_journal_dirty(handle, di_bh); |
5966 | 5970 | ||
diff --git a/fs/ocfs2/alloc.h b/fs/ocfs2/alloc.h index 826e0a6cf5c7..42ff94bd8011 100644 --- a/fs/ocfs2/alloc.h +++ b/fs/ocfs2/alloc.h | |||
@@ -62,6 +62,7 @@ static inline int ocfs2_extend_meta_needed(struct ocfs2_dinode *fe) | |||
62 | return le16_to_cpu(fe->id2.i_list.l_tree_depth) + 2; | 62 | return le16_to_cpu(fe->id2.i_list.l_tree_depth) + 2; |
63 | } | 63 | } |
64 | 64 | ||
65 | void ocfs2_dinode_new_extent_list(struct inode *inode, struct ocfs2_dinode *di); | ||
65 | void ocfs2_set_inode_data_inline(struct inode *inode, struct ocfs2_dinode *di); | 66 | void ocfs2_set_inode_data_inline(struct inode *inode, struct ocfs2_dinode *di); |
66 | int ocfs2_convert_inline_data_to_extents(struct inode *inode, | 67 | int ocfs2_convert_inline_data_to_extents(struct inode *inode, |
67 | struct buffer_head *di_bh); | 68 | struct buffer_head *di_bh); |
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 8deed89330c7..e15351338417 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
@@ -72,6 +72,7 @@ static unsigned char ocfs2_filetype_table[] = { | |||
72 | static int ocfs2_extend_dir(struct ocfs2_super *osb, | 72 | static int ocfs2_extend_dir(struct ocfs2_super *osb, |
73 | struct inode *dir, | 73 | struct inode *dir, |
74 | struct buffer_head *parent_fe_bh, | 74 | struct buffer_head *parent_fe_bh, |
75 | unsigned int blocks_wanted, | ||
75 | struct buffer_head **new_de_bh); | 76 | struct buffer_head **new_de_bh); |
76 | static int ocfs2_do_extend_dir(struct super_block *sb, | 77 | static int ocfs2_do_extend_dir(struct super_block *sb, |
77 | handle_t *handle, | 78 | handle_t *handle, |
@@ -331,12 +332,20 @@ struct buffer_head *ocfs2_find_entry(const char *name, int namelen, | |||
331 | return ocfs2_find_entry_el(name, namelen, dir, res_dir); | 332 | return ocfs2_find_entry_el(name, namelen, dir, res_dir); |
332 | } | 333 | } |
333 | 334 | ||
335 | /* | ||
336 | * Update inode number and type of a previously found directory entry. | ||
337 | */ | ||
334 | int ocfs2_update_entry(struct inode *dir, handle_t *handle, | 338 | int ocfs2_update_entry(struct inode *dir, handle_t *handle, |
335 | struct buffer_head *de_bh, struct ocfs2_dir_entry *de, | 339 | struct buffer_head *de_bh, struct ocfs2_dir_entry *de, |
336 | struct inode *new_entry_inode) | 340 | struct inode *new_entry_inode) |
337 | { | 341 | { |
338 | int ret; | 342 | int ret; |
339 | 343 | ||
344 | /* | ||
345 | * The same code works fine for both inline-data and extent | ||
346 | * based directories, so no need to split this up. | ||
347 | */ | ||
348 | |||
340 | ret = ocfs2_journal_access(handle, dir, de_bh, | 349 | ret = ocfs2_journal_access(handle, dir, de_bh, |
341 | OCFS2_JOURNAL_ACCESS_WRITE); | 350 | OCFS2_JOURNAL_ACCESS_WRITE); |
342 | if (ret) { | 351 | if (ret) { |
@@ -353,14 +362,10 @@ out: | |||
353 | return ret; | 362 | return ret; |
354 | } | 363 | } |
355 | 364 | ||
356 | /* | 365 | static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir, |
357 | * ocfs2_delete_entry deletes a directory entry by merging it with the | 366 | struct ocfs2_dir_entry *de_del, |
358 | * previous entry | 367 | struct buffer_head *bh, char *first_de, |
359 | */ | 368 | unsigned int bytes) |
360 | int ocfs2_delete_entry(handle_t *handle, | ||
361 | struct inode *dir, | ||
362 | struct ocfs2_dir_entry *de_del, | ||
363 | struct buffer_head *bh) | ||
364 | { | 369 | { |
365 | struct ocfs2_dir_entry *de, *pde; | 370 | struct ocfs2_dir_entry *de, *pde; |
366 | int i, status = -ENOENT; | 371 | int i, status = -ENOENT; |
@@ -369,8 +374,8 @@ int ocfs2_delete_entry(handle_t *handle, | |||
369 | 374 | ||
370 | i = 0; | 375 | i = 0; |
371 | pde = NULL; | 376 | pde = NULL; |
372 | de = (struct ocfs2_dir_entry *) bh->b_data; | 377 | de = (struct ocfs2_dir_entry *) first_de; |
373 | while (i < bh->b_size) { | 378 | while (i < bytes) { |
374 | if (!ocfs2_check_dir_entry(dir, de, bh, i)) { | 379 | if (!ocfs2_check_dir_entry(dir, de, bh, i)) { |
375 | status = -EIO; | 380 | status = -EIO; |
376 | mlog_errno(status); | 381 | mlog_errno(status); |
@@ -403,6 +408,58 @@ bail: | |||
403 | return status; | 408 | return status; |
404 | } | 409 | } |
405 | 410 | ||
411 | static inline int ocfs2_delete_entry_id(handle_t *handle, | ||
412 | struct inode *dir, | ||
413 | struct ocfs2_dir_entry *de_del, | ||
414 | struct buffer_head *bh) | ||
415 | { | ||
416 | int ret; | ||
417 | struct buffer_head *di_bh = NULL; | ||
418 | struct ocfs2_dinode *di; | ||
419 | struct ocfs2_inline_data *data; | ||
420 | |||
421 | ret = ocfs2_read_block(OCFS2_SB(dir->i_sb), OCFS2_I(dir)->ip_blkno, | ||
422 | &di_bh, OCFS2_BH_CACHED, dir); | ||
423 | if (ret) { | ||
424 | mlog_errno(ret); | ||
425 | goto out; | ||
426 | } | ||
427 | |||
428 | di = (struct ocfs2_dinode *)di_bh->b_data; | ||
429 | data = &di->id2.i_data; | ||
430 | |||
431 | ret = __ocfs2_delete_entry(handle, dir, de_del, bh, data->id_data, | ||
432 | i_size_read(dir)); | ||
433 | |||
434 | brelse(di_bh); | ||
435 | out: | ||
436 | return ret; | ||
437 | } | ||
438 | |||
439 | static inline int ocfs2_delete_entry_el(handle_t *handle, | ||
440 | struct inode *dir, | ||
441 | struct ocfs2_dir_entry *de_del, | ||
442 | struct buffer_head *bh) | ||
443 | { | ||
444 | return __ocfs2_delete_entry(handle, dir, de_del, bh, bh->b_data, | ||
445 | bh->b_size); | ||
446 | } | ||
447 | |||
448 | /* | ||
449 | * ocfs2_delete_entry deletes a directory entry by merging it with the | ||
450 | * previous entry | ||
451 | */ | ||
452 | int ocfs2_delete_entry(handle_t *handle, | ||
453 | struct inode *dir, | ||
454 | struct ocfs2_dir_entry *de_del, | ||
455 | struct buffer_head *bh) | ||
456 | { | ||
457 | if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) | ||
458 | return ocfs2_delete_entry_id(handle, dir, de_del, bh); | ||
459 | |||
460 | return ocfs2_delete_entry_el(handle, dir, de_del, bh); | ||
461 | } | ||
462 | |||
406 | /* | 463 | /* |
407 | * Check whether 'de' has enough room to hold an entry of | 464 | * Check whether 'de' has enough room to hold an entry of |
408 | * 'new_rec_len' bytes. | 465 | * 'new_rec_len' bytes. |
@@ -444,21 +501,30 @@ int __ocfs2_add_entry(handle_t *handle, | |||
444 | unsigned long offset; | 501 | unsigned long offset; |
445 | unsigned short rec_len; | 502 | unsigned short rec_len; |
446 | struct ocfs2_dir_entry *de, *de1; | 503 | struct ocfs2_dir_entry *de, *de1; |
447 | struct super_block *sb; | 504 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)parent_fe_bh->b_data; |
505 | struct super_block *sb = dir->i_sb; | ||
448 | int retval, status; | 506 | int retval, status; |
507 | unsigned int size = sb->s_blocksize; | ||
508 | char *data_start = insert_bh->b_data; | ||
449 | 509 | ||
450 | mlog_entry_void(); | 510 | mlog_entry_void(); |
451 | 511 | ||
452 | sb = dir->i_sb; | ||
453 | |||
454 | if (!namelen) | 512 | if (!namelen) |
455 | return -EINVAL; | 513 | return -EINVAL; |
456 | 514 | ||
515 | if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
516 | data_start = di->id2.i_data.id_data; | ||
517 | size = i_size_read(dir); | ||
518 | |||
519 | BUG_ON(insert_bh != parent_fe_bh); | ||
520 | } | ||
521 | |||
457 | rec_len = OCFS2_DIR_REC_LEN(namelen); | 522 | rec_len = OCFS2_DIR_REC_LEN(namelen); |
458 | offset = 0; | 523 | offset = 0; |
459 | de = (struct ocfs2_dir_entry *) insert_bh->b_data; | 524 | de = (struct ocfs2_dir_entry *) data_start; |
460 | while (1) { | 525 | while (1) { |
461 | BUG_ON((char *)de >= sb->s_blocksize + insert_bh->b_data); | 526 | BUG_ON((char *)de >= (size + data_start)); |
527 | |||
462 | /* These checks should've already been passed by the | 528 | /* These checks should've already been passed by the |
463 | * prepare function, but I guess we can leave them | 529 | * prepare function, but I guess we can leave them |
464 | * here anyway. */ | 530 | * here anyway. */ |
@@ -939,16 +1005,78 @@ int ocfs2_empty_dir(struct inode *inode) | |||
939 | return !priv.seen_other; | 1005 | return !priv.seen_other; |
940 | } | 1006 | } |
941 | 1007 | ||
942 | int ocfs2_fill_new_dir(struct ocfs2_super *osb, | 1008 | static void ocfs2_fill_initial_dirents(struct inode *inode, |
943 | handle_t *handle, | 1009 | struct inode *parent, |
944 | struct inode *parent, | 1010 | char *start, unsigned int size) |
945 | struct inode *inode, | 1011 | { |
946 | struct buffer_head *fe_bh, | 1012 | struct ocfs2_dir_entry *de = (struct ocfs2_dir_entry *)start; |
947 | struct ocfs2_alloc_context *data_ac) | 1013 | |
1014 | de->inode = cpu_to_le64(OCFS2_I(inode)->ip_blkno); | ||
1015 | de->name_len = 1; | ||
1016 | de->rec_len = | ||
1017 | cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len)); | ||
1018 | strcpy(de->name, "."); | ||
1019 | ocfs2_set_de_type(de, S_IFDIR); | ||
1020 | |||
1021 | de = (struct ocfs2_dir_entry *) ((char *)de + le16_to_cpu(de->rec_len)); | ||
1022 | de->inode = cpu_to_le64(OCFS2_I(parent)->ip_blkno); | ||
1023 | de->rec_len = cpu_to_le16(size - OCFS2_DIR_REC_LEN(1)); | ||
1024 | de->name_len = 2; | ||
1025 | strcpy(de->name, ".."); | ||
1026 | ocfs2_set_de_type(de, S_IFDIR); | ||
1027 | } | ||
1028 | |||
1029 | /* | ||
1030 | * This works together with code in ocfs2_mknod_locked() which sets | ||
1031 | * the inline-data flag and initializes the inline-data section. | ||
1032 | */ | ||
1033 | static int ocfs2_fill_new_dir_id(struct ocfs2_super *osb, | ||
1034 | handle_t *handle, | ||
1035 | struct inode *parent, | ||
1036 | struct inode *inode, | ||
1037 | struct buffer_head *di_bh) | ||
1038 | { | ||
1039 | int ret; | ||
1040 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | ||
1041 | struct ocfs2_inline_data *data = &di->id2.i_data; | ||
1042 | unsigned int size = le16_to_cpu(data->id_count); | ||
1043 | |||
1044 | ret = ocfs2_journal_access(handle, inode, di_bh, | ||
1045 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
1046 | if (ret) { | ||
1047 | mlog_errno(ret); | ||
1048 | goto out; | ||
1049 | } | ||
1050 | |||
1051 | ocfs2_fill_initial_dirents(inode, parent, data->id_data, size); | ||
1052 | |||
1053 | ocfs2_journal_dirty(handle, di_bh); | ||
1054 | if (ret) { | ||
1055 | mlog_errno(ret); | ||
1056 | goto out; | ||
1057 | } | ||
1058 | |||
1059 | i_size_write(inode, size); | ||
1060 | inode->i_nlink = 2; | ||
1061 | inode->i_blocks = ocfs2_inode_sector_count(inode); | ||
1062 | |||
1063 | ret = ocfs2_mark_inode_dirty(handle, inode, di_bh); | ||
1064 | if (ret < 0) | ||
1065 | mlog_errno(ret); | ||
1066 | |||
1067 | out: | ||
1068 | return ret; | ||
1069 | } | ||
1070 | |||
1071 | static int ocfs2_fill_new_dir_el(struct ocfs2_super *osb, | ||
1072 | handle_t *handle, | ||
1073 | struct inode *parent, | ||
1074 | struct inode *inode, | ||
1075 | struct buffer_head *fe_bh, | ||
1076 | struct ocfs2_alloc_context *data_ac) | ||
948 | { | 1077 | { |
949 | int status; | 1078 | int status; |
950 | struct buffer_head *new_bh = NULL; | 1079 | struct buffer_head *new_bh = NULL; |
951 | struct ocfs2_dir_entry *de = NULL; | ||
952 | 1080 | ||
953 | mlog_entry_void(); | 1081 | mlog_entry_void(); |
954 | 1082 | ||
@@ -969,20 +1097,8 @@ int ocfs2_fill_new_dir(struct ocfs2_super *osb, | |||
969 | } | 1097 | } |
970 | memset(new_bh->b_data, 0, osb->sb->s_blocksize); | 1098 | memset(new_bh->b_data, 0, osb->sb->s_blocksize); |
971 | 1099 | ||
972 | de = (struct ocfs2_dir_entry *) new_bh->b_data; | 1100 | ocfs2_fill_initial_dirents(inode, parent, new_bh->b_data, |
973 | de->inode = cpu_to_le64(OCFS2_I(inode)->ip_blkno); | 1101 | osb->sb->s_blocksize); |
974 | de->name_len = 1; | ||
975 | de->rec_len = | ||
976 | cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len)); | ||
977 | strcpy(de->name, "."); | ||
978 | ocfs2_set_de_type(de, S_IFDIR); | ||
979 | de = (struct ocfs2_dir_entry *) ((char *)de + le16_to_cpu(de->rec_len)); | ||
980 | de->inode = cpu_to_le64(OCFS2_I(parent)->ip_blkno); | ||
981 | de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize - | ||
982 | OCFS2_DIR_REC_LEN(1)); | ||
983 | de->name_len = 2; | ||
984 | strcpy(de->name, ".."); | ||
985 | ocfs2_set_de_type(de, S_IFDIR); | ||
986 | 1102 | ||
987 | status = ocfs2_journal_dirty(handle, new_bh); | 1103 | status = ocfs2_journal_dirty(handle, new_bh); |
988 | if (status < 0) { | 1104 | if (status < 0) { |
@@ -1008,6 +1124,230 @@ bail: | |||
1008 | return status; | 1124 | return status; |
1009 | } | 1125 | } |
1010 | 1126 | ||
1127 | int ocfs2_fill_new_dir(struct ocfs2_super *osb, | ||
1128 | handle_t *handle, | ||
1129 | struct inode *parent, | ||
1130 | struct inode *inode, | ||
1131 | struct buffer_head *fe_bh, | ||
1132 | struct ocfs2_alloc_context *data_ac) | ||
1133 | { | ||
1134 | BUG_ON(!ocfs2_supports_inline_data(osb) && data_ac == NULL); | ||
1135 | |||
1136 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) | ||
1137 | return ocfs2_fill_new_dir_id(osb, handle, parent, inode, fe_bh); | ||
1138 | |||
1139 | return ocfs2_fill_new_dir_el(osb, handle, parent, inode, fe_bh, | ||
1140 | data_ac); | ||
1141 | } | ||
1142 | |||
1143 | static void ocfs2_expand_last_dirent(char *start, unsigned int old_size, | ||
1144 | unsigned int new_size) | ||
1145 | { | ||
1146 | struct ocfs2_dir_entry *de; | ||
1147 | struct ocfs2_dir_entry *prev_de; | ||
1148 | char *de_buf, *limit; | ||
1149 | unsigned int bytes = new_size - old_size; | ||
1150 | |||
1151 | limit = start + old_size; | ||
1152 | de_buf = start; | ||
1153 | de = (struct ocfs2_dir_entry *)de_buf; | ||
1154 | do { | ||
1155 | prev_de = de; | ||
1156 | de_buf += le16_to_cpu(de->rec_len); | ||
1157 | de = (struct ocfs2_dir_entry *)de_buf; | ||
1158 | } while (de_buf < limit); | ||
1159 | |||
1160 | le16_add_cpu(&prev_de->rec_len, bytes); | ||
1161 | } | ||
1162 | |||
1163 | /* | ||
1164 | * We allocate enough clusters to fulfill "blocks_wanted", but set | ||
1165 | * i_size to exactly one block. Ocfs2_extend_dir() will handle the | ||
1166 | * rest automatically for us. | ||
1167 | * | ||
1168 | * *first_block_bh is a pointer to the 1st data block allocated to the | ||
1169 | * directory. | ||
1170 | */ | ||
1171 | static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, | ||
1172 | unsigned int blocks_wanted, | ||
1173 | struct buffer_head **first_block_bh) | ||
1174 | { | ||
1175 | int ret, credits = OCFS2_INLINE_TO_EXTENTS_CREDITS; | ||
1176 | u32 alloc, bit_off, len; | ||
1177 | struct super_block *sb = dir->i_sb; | ||
1178 | u64 blkno, bytes = blocks_wanted << sb->s_blocksize_bits; | ||
1179 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); | ||
1180 | struct ocfs2_inode_info *oi = OCFS2_I(dir); | ||
1181 | struct ocfs2_alloc_context *data_ac; | ||
1182 | struct buffer_head *dirdata_bh = NULL; | ||
1183 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | ||
1184 | handle_t *handle; | ||
1185 | |||
1186 | alloc = ocfs2_clusters_for_bytes(sb, bytes); | ||
1187 | |||
1188 | /* | ||
1189 | * We should never need more than 2 clusters for this - | ||
1190 | * maximum dirent size is far less than one block. In fact, | ||
1191 | * the only time we'd need more than one cluster is if | ||
1192 | * blocksize == clustersize and the dirent won't fit in the | ||
1193 | * extra space that the expansion to a single block gives. As | ||
1194 | * of today, that only happens on 4k/4k file systems. | ||
1195 | */ | ||
1196 | BUG_ON(alloc > 2); | ||
1197 | |||
1198 | ret = ocfs2_reserve_clusters(osb, alloc, &data_ac); | ||
1199 | if (ret) { | ||
1200 | mlog_errno(ret); | ||
1201 | goto out; | ||
1202 | } | ||
1203 | |||
1204 | down_write(&oi->ip_alloc_sem); | ||
1205 | |||
1206 | /* | ||
1207 | * Prepare for worst case allocation scenario of two seperate | ||
1208 | * extents. | ||
1209 | */ | ||
1210 | if (alloc == 2) | ||
1211 | credits += OCFS2_SUBALLOC_ALLOC; | ||
1212 | |||
1213 | handle = ocfs2_start_trans(osb, credits); | ||
1214 | if (IS_ERR(handle)) { | ||
1215 | ret = PTR_ERR(handle); | ||
1216 | mlog_errno(ret); | ||
1217 | goto out_sem; | ||
1218 | } | ||
1219 | |||
1220 | /* | ||
1221 | * Try to claim as many clusters as the bitmap can give though | ||
1222 | * if we only get one now, that's enough to continue. The rest | ||
1223 | * will be claimed after the conversion to extents. | ||
1224 | */ | ||
1225 | ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off, &len); | ||
1226 | if (ret) { | ||
1227 | mlog_errno(ret); | ||
1228 | goto out_commit; | ||
1229 | } | ||
1230 | |||
1231 | /* | ||
1232 | * Operations are carefully ordered so that we set up the new | ||
1233 | * data block first. The conversion from inline data to | ||
1234 | * extents follows. | ||
1235 | */ | ||
1236 | blkno = ocfs2_clusters_to_blocks(dir->i_sb, bit_off); | ||
1237 | dirdata_bh = sb_getblk(sb, blkno); | ||
1238 | if (!dirdata_bh) { | ||
1239 | ret = -EIO; | ||
1240 | mlog_errno(ret); | ||
1241 | goto out_commit; | ||
1242 | } | ||
1243 | |||
1244 | ocfs2_set_new_buffer_uptodate(dir, dirdata_bh); | ||
1245 | |||
1246 | ret = ocfs2_journal_access(handle, dir, dirdata_bh, | ||
1247 | OCFS2_JOURNAL_ACCESS_CREATE); | ||
1248 | if (ret) { | ||
1249 | mlog_errno(ret); | ||
1250 | goto out_commit; | ||
1251 | } | ||
1252 | |||
1253 | memcpy(dirdata_bh->b_data, di->id2.i_data.id_data, i_size_read(dir)); | ||
1254 | memset(dirdata_bh->b_data + i_size_read(dir), 0, | ||
1255 | sb->s_blocksize - i_size_read(dir)); | ||
1256 | ocfs2_expand_last_dirent(dirdata_bh->b_data, i_size_read(dir), | ||
1257 | sb->s_blocksize); | ||
1258 | |||
1259 | ret = ocfs2_journal_dirty(handle, dirdata_bh); | ||
1260 | if (ret) { | ||
1261 | mlog_errno(ret); | ||
1262 | goto out_commit; | ||
1263 | } | ||
1264 | |||
1265 | /* | ||
1266 | * Set extent, i_size, etc on the directory. After this, the | ||
1267 | * inode should contain the same exact dirents as before and | ||
1268 | * be fully accessible from system calls. | ||
1269 | * | ||
1270 | * We let the later dirent insert modify c/mtime - to the user | ||
1271 | * the data hasn't changed. | ||
1272 | */ | ||
1273 | ret = ocfs2_journal_access(handle, dir, di_bh, | ||
1274 | OCFS2_JOURNAL_ACCESS_CREATE); | ||
1275 | if (ret) { | ||
1276 | mlog_errno(ret); | ||
1277 | goto out_commit; | ||
1278 | } | ||
1279 | |||
1280 | spin_lock(&oi->ip_lock); | ||
1281 | oi->ip_dyn_features &= ~OCFS2_INLINE_DATA_FL; | ||
1282 | di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features); | ||
1283 | spin_unlock(&oi->ip_lock); | ||
1284 | |||
1285 | ocfs2_dinode_new_extent_list(dir, di); | ||
1286 | |||
1287 | i_size_write(dir, sb->s_blocksize); | ||
1288 | dir->i_mtime = dir->i_ctime = CURRENT_TIME; | ||
1289 | |||
1290 | di->i_size = cpu_to_le64(sb->s_blocksize); | ||
1291 | di->i_ctime = di->i_mtime = cpu_to_le64(dir->i_ctime.tv_sec); | ||
1292 | di->i_ctime_nsec = di->i_mtime_nsec = cpu_to_le32(dir->i_ctime.tv_nsec); | ||
1293 | dir->i_blocks = ocfs2_inode_sector_count(dir); | ||
1294 | |||
1295 | /* | ||
1296 | * This should never fail as our extent list is empty and all | ||
1297 | * related blocks have been journaled already. | ||
1298 | */ | ||
1299 | ret = ocfs2_insert_extent(osb, handle, dir, di_bh, 0, blkno, len, 0, | ||
1300 | NULL); | ||
1301 | if (ret) { | ||
1302 | mlog_errno(ret); | ||
1303 | goto out; | ||
1304 | } | ||
1305 | |||
1306 | ret = ocfs2_journal_dirty(handle, di_bh); | ||
1307 | if (ret) { | ||
1308 | mlog_errno(ret); | ||
1309 | goto out_commit; | ||
1310 | } | ||
1311 | |||
1312 | /* | ||
1313 | * We asked for two clusters, but only got one in the 1st | ||
1314 | * pass. Claim the 2nd cluster as a separate extent. | ||
1315 | */ | ||
1316 | if (alloc > len) { | ||
1317 | ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off, | ||
1318 | &len); | ||
1319 | if (ret) { | ||
1320 | mlog_errno(ret); | ||
1321 | goto out_commit; | ||
1322 | } | ||
1323 | blkno = ocfs2_clusters_to_blocks(dir->i_sb, bit_off); | ||
1324 | |||
1325 | ret = ocfs2_insert_extent(osb, handle, dir, di_bh, 1, blkno, | ||
1326 | len, 0, NULL); | ||
1327 | if (ret) { | ||
1328 | mlog_errno(ret); | ||
1329 | goto out; | ||
1330 | } | ||
1331 | } | ||
1332 | |||
1333 | *first_block_bh = dirdata_bh; | ||
1334 | dirdata_bh = NULL; | ||
1335 | |||
1336 | out_commit: | ||
1337 | ocfs2_commit_trans(osb, handle); | ||
1338 | |||
1339 | out_sem: | ||
1340 | up_write(&oi->ip_alloc_sem); | ||
1341 | |||
1342 | out: | ||
1343 | if (data_ac) | ||
1344 | ocfs2_free_alloc_context(data_ac); | ||
1345 | |||
1346 | brelse(dirdata_bh); | ||
1347 | |||
1348 | return ret; | ||
1349 | } | ||
1350 | |||
1011 | /* returns a bh of the 1st new block in the allocation. */ | 1351 | /* returns a bh of the 1st new block in the allocation. */ |
1012 | static int ocfs2_do_extend_dir(struct super_block *sb, | 1352 | static int ocfs2_do_extend_dir(struct super_block *sb, |
1013 | handle_t *handle, | 1353 | handle_t *handle, |
@@ -1057,10 +1397,18 @@ bail: | |||
1057 | return status; | 1397 | return status; |
1058 | } | 1398 | } |
1059 | 1399 | ||
1060 | /* assumes you already have a cluster lock on the directory. */ | 1400 | /* |
1401 | * Assumes you already have a cluster lock on the directory. | ||
1402 | * | ||
1403 | * 'blocks_wanted' is only used if we have an inline directory which | ||
1404 | * is to be turned into an extent based one. The size of the dirent to | ||
1405 | * insert might be larger than the space gained by growing to just one | ||
1406 | * block, so we may have to grow the inode by two blocks in that case. | ||
1407 | */ | ||
1061 | static int ocfs2_extend_dir(struct ocfs2_super *osb, | 1408 | static int ocfs2_extend_dir(struct ocfs2_super *osb, |
1062 | struct inode *dir, | 1409 | struct inode *dir, |
1063 | struct buffer_head *parent_fe_bh, | 1410 | struct buffer_head *parent_fe_bh, |
1411 | unsigned int blocks_wanted, | ||
1064 | struct buffer_head **new_de_bh) | 1412 | struct buffer_head **new_de_bh) |
1065 | { | 1413 | { |
1066 | int status = 0; | 1414 | int status = 0; |
@@ -1076,6 +1424,38 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, | |||
1076 | 1424 | ||
1077 | mlog_entry_void(); | 1425 | mlog_entry_void(); |
1078 | 1426 | ||
1427 | if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
1428 | status = ocfs2_expand_inline_dir(dir, parent_fe_bh, | ||
1429 | blocks_wanted, &new_bh); | ||
1430 | if (status) { | ||
1431 | mlog_errno(status); | ||
1432 | goto bail; | ||
1433 | } | ||
1434 | |||
1435 | if (blocks_wanted == 1) { | ||
1436 | /* | ||
1437 | * If the new dirent will fit inside the space | ||
1438 | * created by pushing out to one block, then | ||
1439 | * we can complete the operation | ||
1440 | * here. Otherwise we have to expand i_size | ||
1441 | * and format the 2nd block below. | ||
1442 | */ | ||
1443 | BUG_ON(new_bh == NULL); | ||
1444 | goto bail_bh; | ||
1445 | } | ||
1446 | |||
1447 | /* | ||
1448 | * Get rid of 'new_bh' - we want to format the 2nd | ||
1449 | * data block and return that instead. | ||
1450 | */ | ||
1451 | brelse(new_bh); | ||
1452 | new_bh = NULL; | ||
1453 | |||
1454 | dir_i_size = i_size_read(dir); | ||
1455 | credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS; | ||
1456 | goto do_extend; | ||
1457 | } | ||
1458 | |||
1079 | dir_i_size = i_size_read(dir); | 1459 | dir_i_size = i_size_read(dir); |
1080 | mlog(0, "extending dir %llu (i_size = %lld)\n", | 1460 | mlog(0, "extending dir %llu (i_size = %lld)\n", |
1081 | (unsigned long long)OCFS2_I(dir)->ip_blkno, dir_i_size); | 1461 | (unsigned long long)OCFS2_I(dir)->ip_blkno, dir_i_size); |
@@ -1113,6 +1493,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, | |||
1113 | credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS; | 1493 | credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS; |
1114 | } | 1494 | } |
1115 | 1495 | ||
1496 | do_extend: | ||
1116 | down_write(&OCFS2_I(dir)->ip_alloc_sem); | 1497 | down_write(&OCFS2_I(dir)->ip_alloc_sem); |
1117 | drop_alloc_sem = 1; | 1498 | drop_alloc_sem = 1; |
1118 | 1499 | ||
@@ -1158,6 +1539,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, | |||
1158 | goto bail; | 1539 | goto bail; |
1159 | } | 1540 | } |
1160 | 1541 | ||
1542 | bail_bh: | ||
1161 | *new_de_bh = new_bh; | 1543 | *new_de_bh = new_bh; |
1162 | get_bh(*new_de_bh); | 1544 | get_bh(*new_de_bh); |
1163 | bail: | 1545 | bail: |
@@ -1178,41 +1560,71 @@ bail: | |||
1178 | return status; | 1560 | return status; |
1179 | } | 1561 | } |
1180 | 1562 | ||
1181 | /* | 1563 | static int ocfs2_find_dir_space_id(struct inode *dir, struct buffer_head *di_bh, |
1182 | * Search the dir for a good spot, extending it if necessary. The | 1564 | const char *name, int namelen, |
1183 | * block containing an appropriate record is returned in ret_de_bh. | 1565 | struct buffer_head **ret_de_bh, |
1184 | */ | 1566 | unsigned int *blocks_wanted) |
1185 | int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, | ||
1186 | struct inode *dir, | ||
1187 | struct buffer_head *parent_fe_bh, | ||
1188 | const char *name, | ||
1189 | int namelen, | ||
1190 | struct buffer_head **ret_de_bh) | ||
1191 | { | 1567 | { |
1192 | unsigned long offset; | 1568 | int ret; |
1193 | struct buffer_head * bh = NULL; | 1569 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; |
1194 | unsigned short rec_len; | 1570 | struct ocfs2_dir_entry *de, *last_de = NULL; |
1195 | struct ocfs2_dinode *fe; | 1571 | char *de_buf, *limit; |
1196 | struct ocfs2_dir_entry *de; | 1572 | unsigned long offset = 0; |
1197 | struct super_block *sb; | 1573 | unsigned int rec_len, new_rec_len; |
1198 | int status; | 1574 | |
1575 | de_buf = di->id2.i_data.id_data; | ||
1576 | limit = de_buf + i_size_read(dir); | ||
1577 | rec_len = OCFS2_DIR_REC_LEN(namelen); | ||
1199 | 1578 | ||
1200 | mlog_entry_void(); | 1579 | while (de_buf < limit) { |
1580 | de = (struct ocfs2_dir_entry *)de_buf; | ||
1201 | 1581 | ||
1202 | mlog(0, "getting ready to insert namelen %d into dir %llu\n", | 1582 | if (!ocfs2_check_dir_entry(dir, de, di_bh, offset)) { |
1203 | namelen, (unsigned long long)OCFS2_I(dir)->ip_blkno); | 1583 | ret = -ENOENT; |
1584 | goto out; | ||
1585 | } | ||
1586 | if (ocfs2_match(namelen, name, de)) { | ||
1587 | ret = -EEXIST; | ||
1588 | goto out; | ||
1589 | } | ||
1590 | if (ocfs2_dirent_would_fit(de, rec_len)) { | ||
1591 | /* Ok, we found a spot. Return this bh and let | ||
1592 | * the caller actually fill it in. */ | ||
1593 | *ret_de_bh = di_bh; | ||
1594 | get_bh(*ret_de_bh); | ||
1595 | ret = 0; | ||
1596 | goto out; | ||
1597 | } | ||
1204 | 1598 | ||
1205 | BUG_ON(!S_ISDIR(dir->i_mode)); | 1599 | last_de = de; |
1206 | fe = (struct ocfs2_dinode *) parent_fe_bh->b_data; | 1600 | de_buf += le16_to_cpu(de->rec_len); |
1207 | BUG_ON(le64_to_cpu(fe->i_size) != i_size_read(dir)); | 1601 | offset += le16_to_cpu(de->rec_len); |
1602 | } | ||
1208 | 1603 | ||
1209 | sb = dir->i_sb; | 1604 | /* |
1605 | * We're going to require expansion of the directory - figure | ||
1606 | * out how many blocks we'll need so that a place for the | ||
1607 | * dirent can be found. | ||
1608 | */ | ||
1609 | *blocks_wanted = 1; | ||
1610 | new_rec_len = le16_to_cpu(last_de->rec_len) + (dir->i_sb->s_blocksize - i_size_read(dir)); | ||
1611 | if (new_rec_len < (rec_len + OCFS2_DIR_REC_LEN(last_de->name_len))) | ||
1612 | *blocks_wanted = 2; | ||
1210 | 1613 | ||
1211 | if (!namelen) { | 1614 | ret = -ENOSPC; |
1212 | status = -EINVAL; | 1615 | out: |
1213 | mlog_errno(status); | 1616 | return ret; |
1214 | goto bail; | 1617 | } |
1215 | } | 1618 | |
1619 | static int ocfs2_find_dir_space_el(struct inode *dir, const char *name, | ||
1620 | int namelen, struct buffer_head **ret_de_bh) | ||
1621 | { | ||
1622 | unsigned long offset; | ||
1623 | struct buffer_head *bh = NULL; | ||
1624 | unsigned short rec_len; | ||
1625 | struct ocfs2_dir_entry *de; | ||
1626 | struct super_block *sb = dir->i_sb; | ||
1627 | int status; | ||
1216 | 1628 | ||
1217 | bh = ocfs2_bread(dir, 0, &status, 0); | 1629 | bh = ocfs2_bread(dir, 0, &status, 0); |
1218 | if (!bh) { | 1630 | if (!bh) { |
@@ -1229,17 +1641,11 @@ int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, | |||
1229 | bh = NULL; | 1641 | bh = NULL; |
1230 | 1642 | ||
1231 | if (i_size_read(dir) <= offset) { | 1643 | if (i_size_read(dir) <= offset) { |
1232 | status = ocfs2_extend_dir(osb, | 1644 | /* |
1233 | dir, | 1645 | * Caller will have to expand this |
1234 | parent_fe_bh, | 1646 | * directory. |
1235 | &bh); | 1647 | */ |
1236 | if (status < 0) { | 1648 | status = -ENOSPC; |
1237 | mlog_errno(status); | ||
1238 | goto bail; | ||
1239 | } | ||
1240 | BUG_ON(!bh); | ||
1241 | *ret_de_bh = bh; | ||
1242 | get_bh(*ret_de_bh); | ||
1243 | goto bail; | 1649 | goto bail; |
1244 | } | 1650 | } |
1245 | bh = ocfs2_bread(dir, | 1651 | bh = ocfs2_bread(dir, |
@@ -1281,3 +1687,61 @@ bail: | |||
1281 | mlog_exit(status); | 1687 | mlog_exit(status); |
1282 | return status; | 1688 | return status; |
1283 | } | 1689 | } |
1690 | |||
1691 | int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, | ||
1692 | struct inode *dir, | ||
1693 | struct buffer_head *parent_fe_bh, | ||
1694 | const char *name, | ||
1695 | int namelen, | ||
1696 | struct buffer_head **ret_de_bh) | ||
1697 | { | ||
1698 | int ret; | ||
1699 | unsigned int blocks_wanted = 1; | ||
1700 | struct buffer_head *bh = NULL; | ||
1701 | |||
1702 | mlog(0, "getting ready to insert namelen %d into dir %llu\n", | ||
1703 | namelen, (unsigned long long)OCFS2_I(dir)->ip_blkno); | ||
1704 | |||
1705 | *ret_de_bh = NULL; | ||
1706 | |||
1707 | if (!namelen) { | ||
1708 | ret = -EINVAL; | ||
1709 | mlog_errno(ret); | ||
1710 | goto out; | ||
1711 | } | ||
1712 | |||
1713 | if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
1714 | ret = ocfs2_find_dir_space_id(dir, parent_fe_bh, name, | ||
1715 | namelen, &bh, &blocks_wanted); | ||
1716 | } else | ||
1717 | ret = ocfs2_find_dir_space_el(dir, name, namelen, &bh); | ||
1718 | |||
1719 | if (ret && ret != -ENOSPC) { | ||
1720 | mlog_errno(ret); | ||
1721 | goto out; | ||
1722 | } | ||
1723 | |||
1724 | if (ret == -ENOSPC) { | ||
1725 | /* | ||
1726 | * We have to expand the directory to add this name. | ||
1727 | */ | ||
1728 | BUG_ON(bh); | ||
1729 | |||
1730 | ret = ocfs2_extend_dir(osb, dir, parent_fe_bh, blocks_wanted, | ||
1731 | &bh); | ||
1732 | if (ret) { | ||
1733 | if (ret != -ENOSPC) | ||
1734 | mlog_errno(ret); | ||
1735 | goto out; | ||
1736 | } | ||
1737 | |||
1738 | BUG_ON(!bh); | ||
1739 | } | ||
1740 | |||
1741 | *ret_de_bh = bh; | ||
1742 | bh = NULL; | ||
1743 | out: | ||
1744 | if (bh) | ||
1745 | brelse(bh); | ||
1746 | return ret; | ||
1747 | } | ||
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index d2f03355d127..729259016c18 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -250,9 +250,8 @@ static int ocfs2_mknod(struct inode *dir, | |||
250 | goto leave; | 250 | goto leave; |
251 | } | 251 | } |
252 | 252 | ||
253 | /* are we making a directory? If so, reserve a cluster for his | 253 | /* Reserve a cluster if creating an extent based directory. */ |
254 | * 1st extent. */ | 254 | if (S_ISDIR(mode) && !ocfs2_supports_inline_data(osb)) { |
255 | if (S_ISDIR(mode)) { | ||
256 | status = ocfs2_reserve_clusters(osb, 1, &data_ac); | 255 | status = ocfs2_reserve_clusters(osb, 1, &data_ac); |
257 | if (status < 0) { | 256 | if (status < 0) { |
258 | if (status != -ENOSPC) | 257 | if (status != -ENOSPC) |
@@ -449,10 +448,21 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, | |||
449 | cpu_to_le32(CURRENT_TIME.tv_nsec); | 448 | cpu_to_le32(CURRENT_TIME.tv_nsec); |
450 | fe->i_dtime = 0; | 449 | fe->i_dtime = 0; |
451 | 450 | ||
452 | fel = &fe->id2.i_list; | 451 | /* |
453 | fel->l_tree_depth = 0; | 452 | * If supported, directories start with inline data. |
454 | fel->l_next_free_rec = 0; | 453 | */ |
455 | fel->l_count = cpu_to_le16(ocfs2_extent_recs_per_inode(osb->sb)); | 454 | if (S_ISDIR(mode) && ocfs2_supports_inline_data(osb)) { |
455 | u16 feat = le16_to_cpu(fe->i_dyn_features); | ||
456 | |||
457 | fe->i_dyn_features = cpu_to_le16(feat | OCFS2_INLINE_DATA_FL); | ||
458 | |||
459 | fe->id2.i_data.id_count = cpu_to_le16(ocfs2_max_inline_data(osb->sb)); | ||
460 | } else { | ||
461 | fel = &fe->id2.i_list; | ||
462 | fel->l_tree_depth = 0; | ||
463 | fel->l_next_free_rec = 0; | ||
464 | fel->l_count = cpu_to_le16(ocfs2_extent_recs_per_inode(osb->sb)); | ||
465 | } | ||
456 | 466 | ||
457 | status = ocfs2_journal_dirty(handle, *new_fe_bh); | 467 | status = ocfs2_journal_dirty(handle, *new_fe_bh); |
458 | if (status < 0) { | 468 | if (status < 0) { |
@@ -950,7 +960,7 @@ static int ocfs2_rename(struct inode *old_dir, | |||
950 | struct buffer_head *old_inode_bh = NULL; | 960 | struct buffer_head *old_inode_bh = NULL; |
951 | struct buffer_head *insert_entry_bh = NULL; | 961 | struct buffer_head *insert_entry_bh = NULL; |
952 | struct ocfs2_super *osb = NULL; | 962 | struct ocfs2_super *osb = NULL; |
953 | u64 newfe_blkno; | 963 | u64 newfe_blkno, old_de_ino; |
954 | handle_t *handle = NULL; | 964 | handle_t *handle = NULL; |
955 | struct buffer_head *old_dir_bh = NULL; | 965 | struct buffer_head *old_dir_bh = NULL; |
956 | struct buffer_head *new_dir_bh = NULL; | 966 | struct buffer_head *new_dir_bh = NULL; |
@@ -1061,12 +1071,13 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1061 | } | 1071 | } |
1062 | } | 1072 | } |
1063 | 1073 | ||
1064 | status = -ENOENT; | 1074 | status = ocfs2_lookup_ino_from_name(old_dir, old_dentry->d_name.name, |
1065 | old_de_bh = ocfs2_find_entry(old_dentry->d_name.name, | 1075 | old_dentry->d_name.len, |
1066 | old_dentry->d_name.len, | 1076 | &old_de_ino); |
1067 | old_dir, &old_de); | 1077 | if (status) { |
1068 | if (!old_de_bh) | 1078 | status = -ENOENT; |
1069 | goto bail; | 1079 | goto bail; |
1080 | } | ||
1070 | 1081 | ||
1071 | /* | 1082 | /* |
1072 | * Check for inode number is _not_ due to possible IO errors. | 1083 | * Check for inode number is _not_ due to possible IO errors. |
@@ -1074,8 +1085,10 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1074 | * and merrily kill the link to whatever was created under the | 1085 | * and merrily kill the link to whatever was created under the |
1075 | * same name. Goodbye sticky bit ;-< | 1086 | * same name. Goodbye sticky bit ;-< |
1076 | */ | 1087 | */ |
1077 | if (le64_to_cpu(old_de->inode) != OCFS2_I(old_inode)->ip_blkno) | 1088 | if (old_de_ino != OCFS2_I(old_inode)->ip_blkno) { |
1089 | status = -ENOENT; | ||
1078 | goto bail; | 1090 | goto bail; |
1091 | } | ||
1079 | 1092 | ||
1080 | /* check if the target already exists (in which case we need | 1093 | /* check if the target already exists (in which case we need |
1081 | * to delete it */ | 1094 | * to delete it */ |
@@ -1250,7 +1263,21 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1250 | } else | 1263 | } else |
1251 | mlog_errno(status); | 1264 | mlog_errno(status); |
1252 | 1265 | ||
1253 | /* now that the name has been added to new_dir, remove the old name */ | 1266 | /* |
1267 | * Now that the name has been added to new_dir, remove the old name. | ||
1268 | * | ||
1269 | * We don't keep any directory entry context around until now | ||
1270 | * because the insert might have changed the type of directory | ||
1271 | * we're dealing with. | ||
1272 | */ | ||
1273 | old_de_bh = ocfs2_find_entry(old_dentry->d_name.name, | ||
1274 | old_dentry->d_name.len, | ||
1275 | old_dir, &old_de); | ||
1276 | if (!old_de_bh) { | ||
1277 | status = -EIO; | ||
1278 | goto bail; | ||
1279 | } | ||
1280 | |||
1254 | status = ocfs2_delete_entry(handle, old_dir, old_de, old_de_bh); | 1281 | status = ocfs2_delete_entry(handle, old_dir, old_de, old_de_bh); |
1255 | if (status < 0) { | 1282 | if (status < 0) { |
1256 | mlog_errno(status); | 1283 | mlog_errno(status); |