aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/dir.c
diff options
context:
space:
mode:
authorMark Fasheh <mark.fasheh@oracle.com>2007-09-13 19:33:54 -0400
committerMark Fasheh <mark.fasheh@oracle.com>2007-10-12 14:54:41 -0400
commit5b6a3a2b4a5f071d170f8122038dd647a84810a8 (patch)
treedd50e12c6670f950889e24401d0bcee900bbba2a /fs/ocfs2/dir.c
parent23193e513d1cd69411469f028d56fd175d4a6b07 (diff)
ocfs2: Write support for directories with inline data
Create all new directories with OCFS2_INLINE_DATA_FL and the inline data bytes formatted as an empty directory. Inode size field reflects the actual amount of inline data available, which makes searching for dirent space very similar to the regular directory search. Inline-data directories are automatically pushed out to extents on any insert request which is too large for the available space. Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com> Reviewed-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs/ocfs2/dir.c')
-rw-r--r--fs/ocfs2/dir.c618
1 files changed, 541 insertions, 77 deletions
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[] = {
72static int ocfs2_extend_dir(struct ocfs2_super *osb, 72static 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);
76static int ocfs2_do_extend_dir(struct super_block *sb, 77static 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 */
334int ocfs2_update_entry(struct inode *dir, handle_t *handle, 338int 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/* 365static 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)
360int 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
411static 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);
435out:
436 return ret;
437}
438
439static 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 */
452int 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
942int ocfs2_fill_new_dir(struct ocfs2_super *osb, 1008static 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 */
1033static 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
1067out:
1068 return ret;
1069}
1070
1071static 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
1127int 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
1143static 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 */
1171static 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
1336out_commit:
1337 ocfs2_commit_trans(osb, handle);
1338
1339out_sem:
1340 up_write(&oi->ip_alloc_sem);
1341
1342out:
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. */
1012static int ocfs2_do_extend_dir(struct super_block *sb, 1352static 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 */
1061static int ocfs2_extend_dir(struct ocfs2_super *osb, 1408static 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
1496do_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
1542bail_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);
1163bail: 1545bail:
@@ -1178,41 +1560,71 @@ bail:
1178 return status; 1560 return status;
1179} 1561}
1180 1562
1181/* 1563static 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)
1185int 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; 1615out:
1213 mlog_errno(status); 1616 return ret;
1214 goto bail; 1617}
1215 } 1618
1619static 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
1691int 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;
1743out:
1744 if (bh)
1745 brelse(bh);
1746 return ret;
1747}