diff options
Diffstat (limited to 'fs/ocfs2/dir.c')
-rw-r--r-- | fs/ocfs2/dir.c | 109 |
1 files changed, 73 insertions, 36 deletions
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 9cce563fd627..026e6eb85187 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
@@ -82,6 +82,49 @@ static int ocfs2_do_extend_dir(struct super_block *sb, | |||
82 | struct ocfs2_alloc_context *meta_ac, | 82 | struct ocfs2_alloc_context *meta_ac, |
83 | struct buffer_head **new_bh); | 83 | struct buffer_head **new_bh); |
84 | 84 | ||
85 | static struct buffer_head *ocfs2_bread(struct inode *inode, | ||
86 | int block, int *err, int reada) | ||
87 | { | ||
88 | struct buffer_head *bh = NULL; | ||
89 | int tmperr; | ||
90 | u64 p_blkno; | ||
91 | int readflags = 0; | ||
92 | |||
93 | if (reada) | ||
94 | readflags |= OCFS2_BH_READAHEAD; | ||
95 | |||
96 | if (((u64)block << inode->i_sb->s_blocksize_bits) >= | ||
97 | i_size_read(inode)) { | ||
98 | BUG_ON(!reada); | ||
99 | return NULL; | ||
100 | } | ||
101 | |||
102 | down_read(&OCFS2_I(inode)->ip_alloc_sem); | ||
103 | tmperr = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL, | ||
104 | NULL); | ||
105 | up_read(&OCFS2_I(inode)->ip_alloc_sem); | ||
106 | if (tmperr < 0) { | ||
107 | mlog_errno(tmperr); | ||
108 | goto fail; | ||
109 | } | ||
110 | |||
111 | tmperr = ocfs2_read_blocks(inode, p_blkno, 1, &bh, readflags); | ||
112 | if (tmperr < 0) | ||
113 | goto fail; | ||
114 | |||
115 | tmperr = 0; | ||
116 | |||
117 | *err = 0; | ||
118 | return bh; | ||
119 | |||
120 | fail: | ||
121 | brelse(bh); | ||
122 | bh = NULL; | ||
123 | |||
124 | *err = -EIO; | ||
125 | return NULL; | ||
126 | } | ||
127 | |||
85 | /* | 128 | /* |
86 | * bh passed here can be an inode block or a dir data block, depending | 129 | * bh passed here can be an inode block or a dir data block, depending |
87 | * on the inode inline data flag. | 130 | * on the inode inline data flag. |
@@ -188,8 +231,7 @@ static struct buffer_head *ocfs2_find_entry_id(const char *name, | |||
188 | struct ocfs2_dinode *di; | 231 | struct ocfs2_dinode *di; |
189 | struct ocfs2_inline_data *data; | 232 | struct ocfs2_inline_data *data; |
190 | 233 | ||
191 | ret = ocfs2_read_block(OCFS2_SB(dir->i_sb), OCFS2_I(dir)->ip_blkno, | 234 | ret = ocfs2_read_block(dir, OCFS2_I(dir)->ip_blkno, &di_bh); |
192 | &di_bh, OCFS2_BH_CACHED, dir); | ||
193 | if (ret) { | 235 | if (ret) { |
194 | mlog_errno(ret); | 236 | mlog_errno(ret); |
195 | goto out; | 237 | goto out; |
@@ -260,14 +302,13 @@ restart: | |||
260 | } | 302 | } |
261 | if ((bh = bh_use[ra_ptr++]) == NULL) | 303 | if ((bh = bh_use[ra_ptr++]) == NULL) |
262 | goto next; | 304 | goto next; |
263 | wait_on_buffer(bh); | 305 | if (ocfs2_read_block(dir, block, &bh)) { |
264 | if (!buffer_uptodate(bh)) { | 306 | /* read error, skip block & hope for the best. |
265 | /* read error, skip block & hope for the best */ | 307 | * ocfs2_read_block() has released the bh. */ |
266 | ocfs2_error(dir->i_sb, "reading directory %llu, " | 308 | ocfs2_error(dir->i_sb, "reading directory %llu, " |
267 | "offset %lu\n", | 309 | "offset %lu\n", |
268 | (unsigned long long)OCFS2_I(dir)->ip_blkno, | 310 | (unsigned long long)OCFS2_I(dir)->ip_blkno, |
269 | block); | 311 | block); |
270 | brelse(bh); | ||
271 | goto next; | 312 | goto next; |
272 | } | 313 | } |
273 | i = ocfs2_search_dirblock(bh, dir, name, namelen, | 314 | i = ocfs2_search_dirblock(bh, dir, name, namelen, |
@@ -417,8 +458,7 @@ static inline int ocfs2_delete_entry_id(handle_t *handle, | |||
417 | struct ocfs2_dinode *di; | 458 | struct ocfs2_dinode *di; |
418 | struct ocfs2_inline_data *data; | 459 | struct ocfs2_inline_data *data; |
419 | 460 | ||
420 | ret = ocfs2_read_block(OCFS2_SB(dir->i_sb), OCFS2_I(dir)->ip_blkno, | 461 | ret = ocfs2_read_block(dir, OCFS2_I(dir)->ip_blkno, &di_bh); |
421 | &di_bh, OCFS2_BH_CACHED, dir); | ||
422 | if (ret) { | 462 | if (ret) { |
423 | mlog_errno(ret); | 463 | mlog_errno(ret); |
424 | goto out; | 464 | goto out; |
@@ -596,8 +636,7 @@ static int ocfs2_dir_foreach_blk_id(struct inode *inode, | |||
596 | struct ocfs2_inline_data *data; | 636 | struct ocfs2_inline_data *data; |
597 | struct ocfs2_dir_entry *de; | 637 | struct ocfs2_dir_entry *de; |
598 | 638 | ||
599 | ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), OCFS2_I(inode)->ip_blkno, | 639 | ret = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &di_bh); |
600 | &di_bh, OCFS2_BH_CACHED, inode); | ||
601 | if (ret) { | 640 | if (ret) { |
602 | mlog(ML_ERROR, "Unable to read inode block for dir %llu\n", | 641 | mlog(ML_ERROR, "Unable to read inode block for dir %llu\n", |
603 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | 642 | (unsigned long long)OCFS2_I(inode)->ip_blkno); |
@@ -716,8 +755,7 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode, | |||
716 | for (i = ra_sectors >> (sb->s_blocksize_bits - 9); | 755 | for (i = ra_sectors >> (sb->s_blocksize_bits - 9); |
717 | i > 0; i--) { | 756 | i > 0; i--) { |
718 | tmp = ocfs2_bread(inode, ++blk, &err, 1); | 757 | tmp = ocfs2_bread(inode, ++blk, &err, 1); |
719 | if (tmp) | 758 | brelse(tmp); |
720 | brelse(tmp); | ||
721 | } | 759 | } |
722 | last_ra_blk = blk; | 760 | last_ra_blk = blk; |
723 | ra_sectors = 8; | 761 | ra_sectors = 8; |
@@ -899,10 +937,8 @@ int ocfs2_find_files_on_disk(const char *name, | |||
899 | leave: | 937 | leave: |
900 | if (status < 0) { | 938 | if (status < 0) { |
901 | *dirent = NULL; | 939 | *dirent = NULL; |
902 | if (*dirent_bh) { | 940 | brelse(*dirent_bh); |
903 | brelse(*dirent_bh); | 941 | *dirent_bh = NULL; |
904 | *dirent_bh = NULL; | ||
905 | } | ||
906 | } | 942 | } |
907 | 943 | ||
908 | mlog_exit(status); | 944 | mlog_exit(status); |
@@ -951,8 +987,7 @@ int ocfs2_check_dir_for_entry(struct inode *dir, | |||
951 | 987 | ||
952 | ret = 0; | 988 | ret = 0; |
953 | bail: | 989 | bail: |
954 | if (dirent_bh) | 990 | brelse(dirent_bh); |
955 | brelse(dirent_bh); | ||
956 | 991 | ||
957 | mlog_exit(ret); | 992 | mlog_exit(ret); |
958 | return ret; | 993 | return ret; |
@@ -1127,8 +1162,7 @@ static int ocfs2_fill_new_dir_el(struct ocfs2_super *osb, | |||
1127 | 1162 | ||
1128 | status = 0; | 1163 | status = 0; |
1129 | bail: | 1164 | bail: |
1130 | if (new_bh) | 1165 | brelse(new_bh); |
1131 | brelse(new_bh); | ||
1132 | 1166 | ||
1133 | mlog_exit(status); | 1167 | mlog_exit(status); |
1134 | return status; | 1168 | return status; |
@@ -1192,6 +1226,9 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, | |||
1192 | struct buffer_head *dirdata_bh = NULL; | 1226 | struct buffer_head *dirdata_bh = NULL; |
1193 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | 1227 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; |
1194 | handle_t *handle; | 1228 | handle_t *handle; |
1229 | struct ocfs2_extent_tree et; | ||
1230 | |||
1231 | ocfs2_init_dinode_extent_tree(&et, dir, di_bh); | ||
1195 | 1232 | ||
1196 | alloc = ocfs2_clusters_for_bytes(sb, bytes); | 1233 | alloc = ocfs2_clusters_for_bytes(sb, bytes); |
1197 | 1234 | ||
@@ -1305,8 +1342,8 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, | |||
1305 | * This should never fail as our extent list is empty and all | 1342 | * This should never fail as our extent list is empty and all |
1306 | * related blocks have been journaled already. | 1343 | * related blocks have been journaled already. |
1307 | */ | 1344 | */ |
1308 | ret = ocfs2_insert_extent(osb, handle, dir, di_bh, 0, blkno, len, 0, | 1345 | ret = ocfs2_insert_extent(osb, handle, dir, &et, 0, blkno, len, |
1309 | NULL); | 1346 | 0, NULL); |
1310 | if (ret) { | 1347 | if (ret) { |
1311 | mlog_errno(ret); | 1348 | mlog_errno(ret); |
1312 | goto out_commit; | 1349 | goto out_commit; |
@@ -1337,8 +1374,8 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, | |||
1337 | } | 1374 | } |
1338 | blkno = ocfs2_clusters_to_blocks(dir->i_sb, bit_off); | 1375 | blkno = ocfs2_clusters_to_blocks(dir->i_sb, bit_off); |
1339 | 1376 | ||
1340 | ret = ocfs2_insert_extent(osb, handle, dir, di_bh, 1, blkno, | 1377 | ret = ocfs2_insert_extent(osb, handle, dir, &et, 1, |
1341 | len, 0, NULL); | 1378 | blkno, len, 0, NULL); |
1342 | if (ret) { | 1379 | if (ret) { |
1343 | mlog_errno(ret); | 1380 | mlog_errno(ret); |
1344 | goto out_commit; | 1381 | goto out_commit; |
@@ -1383,9 +1420,9 @@ static int ocfs2_do_extend_dir(struct super_block *sb, | |||
1383 | if (extend) { | 1420 | if (extend) { |
1384 | u32 offset = OCFS2_I(dir)->ip_clusters; | 1421 | u32 offset = OCFS2_I(dir)->ip_clusters; |
1385 | 1422 | ||
1386 | status = ocfs2_do_extend_allocation(OCFS2_SB(sb), dir, &offset, | 1423 | status = ocfs2_add_inode_data(OCFS2_SB(sb), dir, &offset, |
1387 | 1, 0, parent_fe_bh, handle, | 1424 | 1, 0, parent_fe_bh, handle, |
1388 | data_ac, meta_ac, NULL); | 1425 | data_ac, meta_ac, NULL); |
1389 | BUG_ON(status == -EAGAIN); | 1426 | BUG_ON(status == -EAGAIN); |
1390 | if (status < 0) { | 1427 | if (status < 0) { |
1391 | mlog_errno(status); | 1428 | mlog_errno(status); |
@@ -1430,12 +1467,14 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, | |||
1430 | int credits, num_free_extents, drop_alloc_sem = 0; | 1467 | int credits, num_free_extents, drop_alloc_sem = 0; |
1431 | loff_t dir_i_size; | 1468 | loff_t dir_i_size; |
1432 | struct ocfs2_dinode *fe = (struct ocfs2_dinode *) parent_fe_bh->b_data; | 1469 | struct ocfs2_dinode *fe = (struct ocfs2_dinode *) parent_fe_bh->b_data; |
1470 | struct ocfs2_extent_list *el = &fe->id2.i_list; | ||
1433 | struct ocfs2_alloc_context *data_ac = NULL; | 1471 | struct ocfs2_alloc_context *data_ac = NULL; |
1434 | struct ocfs2_alloc_context *meta_ac = NULL; | 1472 | struct ocfs2_alloc_context *meta_ac = NULL; |
1435 | handle_t *handle = NULL; | 1473 | handle_t *handle = NULL; |
1436 | struct buffer_head *new_bh = NULL; | 1474 | struct buffer_head *new_bh = NULL; |
1437 | struct ocfs2_dir_entry * de; | 1475 | struct ocfs2_dir_entry * de; |
1438 | struct super_block *sb = osb->sb; | 1476 | struct super_block *sb = osb->sb; |
1477 | struct ocfs2_extent_tree et; | ||
1439 | 1478 | ||
1440 | mlog_entry_void(); | 1479 | mlog_entry_void(); |
1441 | 1480 | ||
@@ -1479,7 +1518,8 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, | |||
1479 | spin_lock(&OCFS2_I(dir)->ip_lock); | 1518 | spin_lock(&OCFS2_I(dir)->ip_lock); |
1480 | if (dir_i_size == ocfs2_clusters_to_bytes(sb, OCFS2_I(dir)->ip_clusters)) { | 1519 | if (dir_i_size == ocfs2_clusters_to_bytes(sb, OCFS2_I(dir)->ip_clusters)) { |
1481 | spin_unlock(&OCFS2_I(dir)->ip_lock); | 1520 | spin_unlock(&OCFS2_I(dir)->ip_lock); |
1482 | num_free_extents = ocfs2_num_free_extents(osb, dir, fe); | 1521 | ocfs2_init_dinode_extent_tree(&et, dir, parent_fe_bh); |
1522 | num_free_extents = ocfs2_num_free_extents(osb, dir, &et); | ||
1483 | if (num_free_extents < 0) { | 1523 | if (num_free_extents < 0) { |
1484 | status = num_free_extents; | 1524 | status = num_free_extents; |
1485 | mlog_errno(status); | 1525 | mlog_errno(status); |
@@ -1487,7 +1527,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, | |||
1487 | } | 1527 | } |
1488 | 1528 | ||
1489 | if (!num_free_extents) { | 1529 | if (!num_free_extents) { |
1490 | status = ocfs2_reserve_new_metadata(osb, fe, &meta_ac); | 1530 | status = ocfs2_reserve_new_metadata(osb, el, &meta_ac); |
1491 | if (status < 0) { | 1531 | if (status < 0) { |
1492 | if (status != -ENOSPC) | 1532 | if (status != -ENOSPC) |
1493 | mlog_errno(status); | 1533 | mlog_errno(status); |
@@ -1502,7 +1542,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, | |||
1502 | goto bail; | 1542 | goto bail; |
1503 | } | 1543 | } |
1504 | 1544 | ||
1505 | credits = ocfs2_calc_extend_credits(sb, fe, 1); | 1545 | credits = ocfs2_calc_extend_credits(sb, el, 1); |
1506 | } else { | 1546 | } else { |
1507 | spin_unlock(&OCFS2_I(dir)->ip_lock); | 1547 | spin_unlock(&OCFS2_I(dir)->ip_lock); |
1508 | credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS; | 1548 | credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS; |
@@ -1568,8 +1608,7 @@ bail: | |||
1568 | if (meta_ac) | 1608 | if (meta_ac) |
1569 | ocfs2_free_alloc_context(meta_ac); | 1609 | ocfs2_free_alloc_context(meta_ac); |
1570 | 1610 | ||
1571 | if (new_bh) | 1611 | brelse(new_bh); |
1572 | brelse(new_bh); | ||
1573 | 1612 | ||
1574 | mlog_exit(status); | 1613 | mlog_exit(status); |
1575 | return status; | 1614 | return status; |
@@ -1696,8 +1735,7 @@ static int ocfs2_find_dir_space_el(struct inode *dir, const char *name, | |||
1696 | 1735 | ||
1697 | status = 0; | 1736 | status = 0; |
1698 | bail: | 1737 | bail: |
1699 | if (bh) | 1738 | brelse(bh); |
1700 | brelse(bh); | ||
1701 | 1739 | ||
1702 | mlog_exit(status); | 1740 | mlog_exit(status); |
1703 | return status; | 1741 | return status; |
@@ -1756,7 +1794,6 @@ int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, | |||
1756 | *ret_de_bh = bh; | 1794 | *ret_de_bh = bh; |
1757 | bh = NULL; | 1795 | bh = NULL; |
1758 | out: | 1796 | out: |
1759 | if (bh) | 1797 | brelse(bh); |
1760 | brelse(bh); | ||
1761 | return ret; | 1798 | return ret; |
1762 | } | 1799 | } |