aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/dir.c
diff options
context:
space:
mode:
authorMark Fasheh <mfasheh@suse.com>2008-11-24 20:02:08 -0500
committerMark Fasheh <mfasheh@suse.com>2009-04-03 14:39:16 -0400
commit4ed8a6bb083bfcc21f1ed66a474b03c0386e4b34 (patch)
tree89cc2629bed3949e980edcae3d807e71718a9028 /fs/ocfs2/dir.c
parent9b7895efac906d66d19856194e1ba61f37e231a4 (diff)
ocfs2: Store dir index records inline
Allow us to store a small number of directory index records in the ocfs2_dx_root_block. This saves us a disk read on small to medium sized directories (less than about 250 entries). The inline root is automatically turned into a root block with extents if the directory size increases beyond it's capacity. Signed-off-by: Mark Fasheh <mfasheh@suse.com> Acked-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs/ocfs2/dir.c')
-rw-r--r--fs/ocfs2/dir.c572
1 files changed, 434 insertions, 138 deletions
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index 0b8c88b47a4e..47de64988b11 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -151,6 +151,7 @@ static void ocfs2_init_dir_trailer(struct inode *inode,
151 151
152void ocfs2_free_dir_lookup_result(struct ocfs2_dir_lookup_result *res) 152void ocfs2_free_dir_lookup_result(struct ocfs2_dir_lookup_result *res)
153{ 153{
154 brelse(res->dl_dx_root_bh);
154 brelse(res->dl_leaf_bh); 155 brelse(res->dl_leaf_bh);
155 brelse(res->dl_dx_leaf_bh); 156 brelse(res->dl_dx_leaf_bh);
156} 157}
@@ -162,6 +163,11 @@ static int ocfs2_dir_indexed(struct inode *inode)
162 return 0; 163 return 0;
163} 164}
164 165
166static inline int ocfs2_dx_root_inline(struct ocfs2_dx_root_block *dx_root)
167{
168 return dx_root->dr_flags & OCFS2_DX_FLAG_INLINE;
169}
170
165/* 171/*
166 * Hashing code adapted from ext3 172 * Hashing code adapted from ext3
167 */ 173 */
@@ -799,13 +805,18 @@ out:
799 * Returns the block index, from the start of the cluster which this 805 * Returns the block index, from the start of the cluster which this
800 * hash belongs too. 806 * hash belongs too.
801 */ 807 */
802static unsigned int ocfs2_dx_dir_hash_idx(struct ocfs2_super *osb, 808static inline unsigned int __ocfs2_dx_dir_hash_idx(struct ocfs2_super *osb,
803 struct ocfs2_dx_hinfo *hinfo) 809 u32 minor_hash)
804{ 810{
805 u32 minor_hash = hinfo->minor_hash;
806 return minor_hash & osb->osb_dx_mask; 811 return minor_hash & osb->osb_dx_mask;
807} 812}
808 813
814static inline unsigned int ocfs2_dx_dir_hash_idx(struct ocfs2_super *osb,
815 struct ocfs2_dx_hinfo *hinfo)
816{
817 return __ocfs2_dx_dir_hash_idx(osb, hinfo->minor_hash);
818}
819
809static int ocfs2_dx_dir_lookup(struct inode *inode, 820static int ocfs2_dx_dir_lookup(struct inode *inode,
810 struct ocfs2_extent_list *el, 821 struct ocfs2_extent_list *el,
811 struct ocfs2_dx_hinfo *hinfo, 822 struct ocfs2_dx_hinfo *hinfo,
@@ -855,7 +866,7 @@ out:
855 866
856static int ocfs2_dx_dir_search(const char *name, int namelen, 867static int ocfs2_dx_dir_search(const char *name, int namelen,
857 struct inode *dir, 868 struct inode *dir,
858 struct ocfs2_extent_list *dr_el, 869 struct ocfs2_dx_root_block *dx_root,
859 struct ocfs2_dir_lookup_result *res) 870 struct ocfs2_dir_lookup_result *res)
860{ 871{
861 int ret, i, found; 872 int ret, i, found;
@@ -866,9 +877,18 @@ static int ocfs2_dx_dir_search(const char *name, int namelen,
866 struct buffer_head *dir_ent_bh = NULL; 877 struct buffer_head *dir_ent_bh = NULL;
867 struct ocfs2_dir_entry *dir_ent = NULL; 878 struct ocfs2_dir_entry *dir_ent = NULL;
868 struct ocfs2_dx_hinfo *hinfo = &res->dl_hinfo; 879 struct ocfs2_dx_hinfo *hinfo = &res->dl_hinfo;
880 struct ocfs2_extent_list *dr_el;
881 struct ocfs2_dx_entry_list *entry_list;
869 882
870 ocfs2_dx_dir_name_hash(dir, name, namelen, &res->dl_hinfo); 883 ocfs2_dx_dir_name_hash(dir, name, namelen, &res->dl_hinfo);
871 884
885 if (ocfs2_dx_root_inline(dx_root)) {
886 entry_list = &dx_root->dr_entries;
887 goto search;
888 }
889
890 dr_el = &dx_root->dr_list;
891
872 ret = ocfs2_dx_dir_lookup(dir, dr_el, hinfo, NULL, &phys); 892 ret = ocfs2_dx_dir_lookup(dir, dr_el, hinfo, NULL, &phys);
873 if (ret) { 893 if (ret) {
874 mlog_errno(ret); 894 mlog_errno(ret);
@@ -893,12 +913,15 @@ static int ocfs2_dx_dir_search(const char *name, int namelen,
893 le16_to_cpu(dx_leaf->dl_list.de_num_used), 913 le16_to_cpu(dx_leaf->dl_list.de_num_used),
894 le16_to_cpu(dx_leaf->dl_list.de_count)); 914 le16_to_cpu(dx_leaf->dl_list.de_count));
895 915
916 entry_list = &dx_leaf->dl_list;
917
918search:
896 /* 919 /*
897 * Empty leaf is legal, so no need to check for that. 920 * Empty leaf is legal, so no need to check for that.
898 */ 921 */
899 found = 0; 922 found = 0;
900 for (i = 0; i < le16_to_cpu(dx_leaf->dl_list.de_num_used); i++) { 923 for (i = 0; i < le16_to_cpu(entry_list->de_num_used); i++) {
901 dx_entry = &dx_leaf->dl_list.de_entries[i]; 924 dx_entry = &entry_list->de_entries[i];
902 925
903 if (hinfo->major_hash != le32_to_cpu(dx_entry->dx_major_hash) 926 if (hinfo->major_hash != le32_to_cpu(dx_entry->dx_major_hash)
904 || hinfo->minor_hash != le32_to_cpu(dx_entry->dx_minor_hash)) 927 || hinfo->minor_hash != le32_to_cpu(dx_entry->dx_minor_hash))
@@ -982,14 +1005,15 @@ static int ocfs2_find_entry_dx(const char *name, int namelen,
982 } 1005 }
983 dx_root = (struct ocfs2_dx_root_block *) dx_root_bh->b_data; 1006 dx_root = (struct ocfs2_dx_root_block *) dx_root_bh->b_data;
984 1007
985 ret = ocfs2_dx_dir_search(name, namelen, dir, &dx_root->dr_list, 1008 ret = ocfs2_dx_dir_search(name, namelen, dir, dx_root, lookup);
986 lookup);
987 if (ret) { 1009 if (ret) {
988 if (ret != -ENOENT) 1010 if (ret != -ENOENT)
989 mlog_errno(ret); 1011 mlog_errno(ret);
990 goto out; 1012 goto out;
991 } 1013 }
992 1014
1015 lookup->dl_dx_root_bh = dx_root_bh;
1016 dx_root_bh = NULL;
993out: 1017out:
994 brelse(di_bh); 1018 brelse(di_bh);
995 brelse(dx_root_bh); 1019 brelse(dx_root_bh);
@@ -1126,64 +1150,88 @@ bail:
1126 return status; 1150 return status;
1127} 1151}
1128 1152
1129static void ocfs2_dx_leaf_remove_entry(struct ocfs2_dx_leaf *dx_leaf, int index) 1153static void ocfs2_dx_list_remove_entry(struct ocfs2_dx_entry_list *entry_list,
1154 int index)
1130{ 1155{
1131 struct ocfs2_dx_entry_list *dl_list = &dx_leaf->dl_list; 1156 int num_used = le16_to_cpu(entry_list->de_num_used);
1132 int num_used = le16_to_cpu(dl_list->de_num_used);
1133 1157
1134 if (num_used == 1 || index == (num_used - 1)) 1158 if (num_used == 1 || index == (num_used - 1))
1135 goto clear; 1159 goto clear;
1136 1160
1137 memmove(&dl_list->de_entries[index], &dl_list->de_entries[index + 1], 1161 memmove(&entry_list->de_entries[index],
1162 &entry_list->de_entries[index + 1],
1138 (num_used - index - 1)*sizeof(struct ocfs2_dx_entry)); 1163 (num_used - index - 1)*sizeof(struct ocfs2_dx_entry));
1139clear: 1164clear:
1140 num_used--; 1165 num_used--;
1141 memset(&dl_list->de_entries[num_used], 0, 1166 memset(&entry_list->de_entries[num_used], 0,
1142 sizeof(struct ocfs2_dx_entry)); 1167 sizeof(struct ocfs2_dx_entry));
1143 dl_list->de_num_used = cpu_to_le16(num_used); 1168 entry_list->de_num_used = cpu_to_le16(num_used);
1144} 1169}
1145 1170
1146static int ocfs2_delete_entry_dx(handle_t *handle, struct inode *dir, 1171static int ocfs2_delete_entry_dx(handle_t *handle, struct inode *dir,
1147 struct ocfs2_dir_lookup_result *lookup) 1172 struct ocfs2_dir_lookup_result *lookup)
1148{ 1173{
1149 int ret, index; 1174 int ret, index;
1175 struct buffer_head *dx_root_bh = lookup->dl_dx_root_bh;
1150 struct buffer_head *leaf_bh = lookup->dl_leaf_bh; 1176 struct buffer_head *leaf_bh = lookup->dl_leaf_bh;
1151 struct ocfs2_dx_leaf *dx_leaf; 1177 struct ocfs2_dx_leaf *dx_leaf;
1152 struct ocfs2_dx_entry *dx_entry = lookup->dl_dx_entry; 1178 struct ocfs2_dx_entry *dx_entry = lookup->dl_dx_entry;
1179 struct ocfs2_dx_root_block *dx_root;
1180 struct ocfs2_dx_entry_list *entry_list;
1181
1182 dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
1183 if (ocfs2_dx_root_inline(dx_root)) {
1184 entry_list = &dx_root->dr_entries;
1185 } else {
1186 dx_leaf = (struct ocfs2_dx_leaf *) lookup->dl_dx_leaf_bh->b_data;
1187 entry_list = &dx_leaf->dl_list;
1188 }
1153 1189
1154 dx_leaf = (struct ocfs2_dx_leaf *) lookup->dl_dx_leaf_bh->b_data;
1155 /* Neither of these are a disk corruption - that should have 1190 /* Neither of these are a disk corruption - that should have
1156 * been caught by lookup, before we got here. */ 1191 * been caught by lookup, before we got here. */
1157 BUG_ON(le16_to_cpu(dx_leaf->dl_list.de_count) <= 0); 1192 BUG_ON(le16_to_cpu(entry_list->de_count) <= 0);
1158 BUG_ON(le16_to_cpu(dx_leaf->dl_list.de_num_used) <= 0); 1193 BUG_ON(le16_to_cpu(entry_list->de_num_used) <= 0);
1159 1194
1160 index = (char *)dx_entry - (char *)dx_leaf->dl_list.de_entries; 1195 index = (char *)dx_entry - (char *)entry_list->de_entries;
1161 index /= sizeof(*dx_entry); 1196 index /= sizeof(*dx_entry);
1162 1197
1163 if (index >= le16_to_cpu(dx_leaf->dl_list.de_num_used)) { 1198 if (index >= le16_to_cpu(entry_list->de_num_used)) {
1164 mlog(ML_ERROR, "Dir %llu: Bad dx_entry ptr idx %d, (%p, %p)\n", 1199 mlog(ML_ERROR, "Dir %llu: Bad dx_entry ptr idx %d, (%p, %p)\n",
1165 (unsigned long long)OCFS2_I(dir)->ip_blkno, index, dx_leaf, 1200 (unsigned long long)OCFS2_I(dir)->ip_blkno, index,
1166 dx_entry); 1201 entry_list, dx_entry);
1167 return -EIO; 1202 return -EIO;
1168 } 1203 }
1169 1204
1170 mlog(0, "Dir %llu: delete entry at index: %d\n",
1171 (unsigned long long)OCFS2_I(dir)->ip_blkno, index);
1172
1173 /* 1205 /*
1174 * Add the index leaf into the journal before removing the 1206 * Add the block holding our index into the journal before
1175 * unindexed entry. If we get an error return from 1207 * removing the unindexed entry. If we get an error return
1176 * __ocfs2_delete_entry(), then it hasn't removed the entry 1208 * from __ocfs2_delete_entry(), then it hasn't removed the
1177 * yet. Likewise, successful return means we *must* remove the 1209 * entry yet. Likewise, successful return means we *must*
1178 * indexed entry. 1210 * remove the indexed entry.
1211 *
1212 * We're also careful to journal the root tree block here if
1213 * we're going to be adding to the start of the free list.
1179 */ 1214 */
1180 ret = ocfs2_journal_access_dl(handle, dir, lookup->dl_dx_leaf_bh, 1215 if (ocfs2_dx_root_inline(dx_root)) {
1181 OCFS2_JOURNAL_ACCESS_WRITE); 1216 ret = ocfs2_journal_access_dr(handle, dir, dx_root_bh,
1182 if (ret) { 1217 OCFS2_JOURNAL_ACCESS_WRITE);
1183 mlog_errno(ret); 1218 if (ret) {
1184 goto out; 1219 mlog_errno(ret);
1220 goto out;
1221 }
1222 } else {
1223 ret = ocfs2_journal_access_dl(handle, dir,
1224 lookup->dl_dx_leaf_bh,
1225 OCFS2_JOURNAL_ACCESS_WRITE);
1226 if (ret) {
1227 mlog_errno(ret);
1228 goto out;
1229 }
1185 } 1230 }
1186 1231
1232 mlog(0, "Dir %llu: delete entry at index: %d\n",
1233 (unsigned long long)OCFS2_I(dir)->ip_blkno, index);
1234
1187 ret = __ocfs2_delete_entry(handle, dir, lookup->dl_entry, 1235 ret = __ocfs2_delete_entry(handle, dir, lookup->dl_entry,
1188 leaf_bh, leaf_bh->b_data, leaf_bh->b_size); 1236 leaf_bh, leaf_bh->b_data, leaf_bh->b_size);
1189 if (ret) { 1237 if (ret) {
@@ -1191,9 +1239,12 @@ static int ocfs2_delete_entry_dx(handle_t *handle, struct inode *dir,
1191 goto out; 1239 goto out;
1192 } 1240 }
1193 1241
1194 ocfs2_dx_leaf_remove_entry(dx_leaf, index); 1242 ocfs2_dx_list_remove_entry(entry_list, index);
1195 1243
1196 ocfs2_journal_dirty(handle, lookup->dl_dx_leaf_bh); 1244 if (ocfs2_dx_root_inline(dx_root))
1245 ocfs2_journal_dirty(handle, dx_root_bh);
1246 else
1247 ocfs2_journal_dirty(handle, lookup->dl_dx_leaf_bh);
1197 1248
1198out: 1249out:
1199 return ret; 1250 return ret;
@@ -1290,13 +1341,30 @@ static void ocfs2_dx_dir_leaf_insert_tail(struct ocfs2_dx_leaf *dx_leaf,
1290 le16_add_cpu(&dx_leaf->dl_list.de_num_used, 1); 1341 le16_add_cpu(&dx_leaf->dl_list.de_num_used, 1);
1291} 1342}
1292 1343
1344static void ocfs2_dx_entry_list_insert(struct ocfs2_dx_entry_list *entry_list,
1345 struct ocfs2_dx_hinfo *hinfo,
1346 u64 dirent_blk)
1347{
1348 int i;
1349 struct ocfs2_dx_entry *dx_entry;
1350
1351 i = le16_to_cpu(entry_list->de_num_used);
1352 dx_entry = &entry_list->de_entries[i];
1353
1354 memset(dx_entry, 0, sizeof(*dx_entry));
1355 dx_entry->dx_major_hash = cpu_to_le32(hinfo->major_hash);
1356 dx_entry->dx_minor_hash = cpu_to_le32(hinfo->minor_hash);
1357 dx_entry->dx_dirent_blk = cpu_to_le64(dirent_blk);
1358
1359 le16_add_cpu(&entry_list->de_num_used, 1);
1360}
1361
1293static int __ocfs2_dx_dir_leaf_insert(struct inode *dir, handle_t *handle, 1362static int __ocfs2_dx_dir_leaf_insert(struct inode *dir, handle_t *handle,
1294 struct ocfs2_dx_hinfo *hinfo, 1363 struct ocfs2_dx_hinfo *hinfo,
1295 u64 dirent_blk, 1364 u64 dirent_blk,
1296 struct buffer_head *dx_leaf_bh) 1365 struct buffer_head *dx_leaf_bh)
1297{ 1366{
1298 int ret, i; 1367 int ret;
1299 struct ocfs2_dx_entry *dx_entry;
1300 struct ocfs2_dx_leaf *dx_leaf; 1368 struct ocfs2_dx_leaf *dx_leaf;
1301 1369
1302 ret = ocfs2_journal_access_dl(handle, dir, dx_leaf_bh, 1370 ret = ocfs2_journal_access_dl(handle, dir, dx_leaf_bh,
@@ -1307,25 +1375,48 @@ static int __ocfs2_dx_dir_leaf_insert(struct inode *dir, handle_t *handle,
1307 } 1375 }
1308 1376
1309 dx_leaf = (struct ocfs2_dx_leaf *)dx_leaf_bh->b_data; 1377 dx_leaf = (struct ocfs2_dx_leaf *)dx_leaf_bh->b_data;
1310 i = le16_to_cpu(dx_leaf->dl_list.de_num_used); 1378 ocfs2_dx_entry_list_insert(&dx_leaf->dl_list, hinfo, dirent_blk);
1311 dx_entry = &dx_leaf->dl_list.de_entries[i]; 1379 ocfs2_journal_dirty(handle, dx_leaf_bh);
1312 1380
1313 memset(dx_entry, 0, sizeof(*dx_entry)); 1381out:
1314 dx_entry->dx_major_hash = cpu_to_le32(hinfo->major_hash); 1382 return ret;
1315 dx_entry->dx_minor_hash = cpu_to_le32(hinfo->minor_hash); 1383}
1316 dx_entry->dx_dirent_blk = cpu_to_le64(dirent_blk);
1317 1384
1318 le16_add_cpu(&dx_leaf->dl_list.de_num_used, 1); 1385static int ocfs2_dx_inline_root_insert(struct inode *dir, handle_t *handle,
1386 struct ocfs2_dx_hinfo *hinfo,
1387 u64 dirent_blk,
1388 struct buffer_head *dx_root_bh)
1389{
1390 int ret;
1391 struct ocfs2_dx_root_block *dx_root;
1319 1392
1320 ocfs2_journal_dirty(handle, dx_leaf_bh); 1393 ret = ocfs2_journal_access_dr(handle, dir, dx_root_bh,
1394 OCFS2_JOURNAL_ACCESS_WRITE);
1395 if (ret) {
1396 mlog_errno(ret);
1397 goto out;
1398 }
1399
1400 dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
1401 ocfs2_dx_entry_list_insert(&dx_root->dr_entries, hinfo, dirent_blk);
1402 ocfs2_journal_dirty(handle, dx_root_bh);
1321 1403
1322out: 1404out:
1323 return ret; 1405 return ret;
1324} 1406}
1325 1407
1326static int ocfs2_dx_dir_leaf_insert(struct inode *dir, handle_t *handle, 1408static int ocfs2_dx_dir_insert(struct inode *dir, handle_t *handle,
1327 struct ocfs2_dir_lookup_result *lookup) 1409 struct ocfs2_dir_lookup_result *lookup)
1328{ 1410{
1411 struct ocfs2_dx_root_block *dx_root;
1412
1413 dx_root = (struct ocfs2_dx_root_block *)lookup->dl_dx_root_bh->b_data;
1414 if (ocfs2_dx_root_inline(dx_root))
1415 return ocfs2_dx_inline_root_insert(dir, handle,
1416 &lookup->dl_hinfo,
1417 lookup->dl_leaf_bh->b_blocknr,
1418 lookup->dl_dx_root_bh);
1419
1329 return __ocfs2_dx_dir_leaf_insert(dir, handle, &lookup->dl_hinfo, 1420 return __ocfs2_dx_dir_leaf_insert(dir, handle, &lookup->dl_hinfo,
1330 lookup->dl_leaf_bh->b_blocknr, 1421 lookup->dl_leaf_bh->b_blocknr,
1331 lookup->dl_dx_leaf_bh); 1422 lookup->dl_dx_leaf_bh);
@@ -1409,11 +1500,12 @@ int __ocfs2_add_entry(handle_t *handle,
1409 else { 1500 else {
1410 status = ocfs2_journal_access_db(handle, dir, 1501 status = ocfs2_journal_access_db(handle, dir,
1411 insert_bh, 1502 insert_bh,
1412 OCFS2_JOURNAL_ACCESS_WRITE); 1503 OCFS2_JOURNAL_ACCESS_WRITE);
1504
1413 if (ocfs2_dir_indexed(dir)) { 1505 if (ocfs2_dir_indexed(dir)) {
1414 status = ocfs2_dx_dir_leaf_insert(dir, 1506 status = ocfs2_dx_dir_insert(dir,
1415 handle, 1507 handle,
1416 lookup); 1508 lookup);
1417 if (status) { 1509 if (status) {
1418 mlog_errno(status); 1510 mlog_errno(status);
1419 goto bail; 1511 goto bail;
@@ -2019,6 +2111,7 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb,
2019 handle_t *handle, struct inode *dir, 2111 handle_t *handle, struct inode *dir,
2020 struct buffer_head *di_bh, 2112 struct buffer_head *di_bh,
2021 struct ocfs2_alloc_context *meta_ac, 2113 struct ocfs2_alloc_context *meta_ac,
2114 int dx_inline,
2022 struct buffer_head **ret_dx_root_bh) 2115 struct buffer_head **ret_dx_root_bh)
2023{ 2116{
2024 int ret; 2117 int ret;
@@ -2062,8 +2155,15 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb,
2062 dx_root->dr_fs_generation = cpu_to_le32(osb->fs_generation); 2155 dx_root->dr_fs_generation = cpu_to_le32(osb->fs_generation);
2063 dx_root->dr_blkno = cpu_to_le64(dr_blkno); 2156 dx_root->dr_blkno = cpu_to_le64(dr_blkno);
2064 dx_root->dr_dir_blkno = cpu_to_le64(OCFS2_I(dir)->ip_blkno); 2157 dx_root->dr_dir_blkno = cpu_to_le64(OCFS2_I(dir)->ip_blkno);
2065 dx_root->dr_list.l_count = 2158
2066 cpu_to_le16(ocfs2_extent_recs_per_dx_root(osb->sb)); 2159 if (dx_inline) {
2160 dx_root->dr_flags |= OCFS2_DX_FLAG_INLINE;
2161 dx_root->dr_entries.de_count =
2162 cpu_to_le16(ocfs2_dx_entries_per_root(osb->sb));
2163 } else {
2164 dx_root->dr_list.l_count =
2165 cpu_to_le16(ocfs2_extent_recs_per_dx_root(osb->sb));
2166 }
2067 2167
2068 ret = ocfs2_journal_dirty(handle, dx_root_bh); 2168 ret = ocfs2_journal_dirty(handle, dx_root_bh);
2069 if (ret) 2169 if (ret)
@@ -2236,20 +2336,12 @@ static int ocfs2_fill_new_dir_dx(struct ocfs2_super *osb,
2236 struct ocfs2_alloc_context *data_ac, 2336 struct ocfs2_alloc_context *data_ac,
2237 struct ocfs2_alloc_context *meta_ac) 2337 struct ocfs2_alloc_context *meta_ac)
2238{ 2338{
2239 int ret, num_dx_leaves, i; 2339 int ret;
2240 struct buffer_head *leaf_bh = NULL; 2340 struct buffer_head *leaf_bh = NULL;
2241 struct buffer_head *dx_root_bh = NULL; 2341 struct buffer_head *dx_root_bh = NULL;
2242 struct buffer_head **dx_leaves = NULL;
2243 struct ocfs2_extent_tree et;
2244 struct ocfs2_dx_hinfo hinfo; 2342 struct ocfs2_dx_hinfo hinfo;
2245 u64 insert_blkno; 2343 struct ocfs2_dx_root_block *dx_root;
2246 2344 struct ocfs2_dx_entry_list *entry_list;
2247 dx_leaves = ocfs2_dx_dir_kmalloc_leaves(osb->sb, &num_dx_leaves);
2248 if (!dx_leaves) {
2249 ret = -ENOMEM;
2250 mlog_errno(ret);
2251 goto out;
2252 }
2253 2345
2254 /* 2346 /*
2255 * Our strategy is to create the directory as though it were 2347 * Our strategy is to create the directory as though it were
@@ -2258,7 +2350,8 @@ static int ocfs2_fill_new_dir_dx(struct ocfs2_super *osb,
2258 * very well known quantity. 2350 * very well known quantity.
2259 * 2351 *
2260 * Essentially, we have two dirents ("." and ".."), in the 1st 2352 * Essentially, we have two dirents ("." and ".."), in the 1st
2261 * block which need indexing. 2353 * block which need indexing. These are easily inserted into
2354 * the index block.
2262 */ 2355 */
2263 2356
2264 ret = ocfs2_fill_new_dir_el(osb, handle, parent, inode, di_bh, 2357 ret = ocfs2_fill_new_dir_el(osb, handle, parent, inode, di_bh,
@@ -2268,61 +2361,22 @@ static int ocfs2_fill_new_dir_dx(struct ocfs2_super *osb,
2268 goto out; 2361 goto out;
2269 } 2362 }
2270 2363
2271 /* 2364 ret = ocfs2_dx_dir_attach_index(osb, handle, inode, di_bh,
2272 * Allocate and format the index leaf first, before attaching 2365 meta_ac, 1, &dx_root_bh);
2273 * the index root. That way we're sure that the main bitmap
2274 * won't -enospc on us with a half-created dir index.
2275 *
2276 * The meta data allocation for our index block will not
2277 * -enospc on us unless there is a disk corruption.
2278 */
2279
2280 ret = __ocfs2_dx_dir_new_cluster(inode, 0, handle, data_ac, dx_leaves,
2281 num_dx_leaves, &insert_blkno);
2282 if (ret) { 2366 if (ret) {
2283 mlog_errno(ret); 2367 mlog_errno(ret);
2284 goto out; 2368 goto out;
2285 } 2369 }
2370 dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
2371 entry_list = &dx_root->dr_entries;
2286 2372
2287 ocfs2_dx_dir_name_hash(inode, ".", 1, &hinfo); 2373 /* Buffer has been journaled for us by ocfs2_dx_dir_attach_index */
2288 i = ocfs2_dx_dir_hash_idx(osb, &hinfo); 2374 ocfs2_dx_entry_list_insert(entry_list, &hinfo, leaf_bh->b_blocknr);
2289 ret = __ocfs2_dx_dir_leaf_insert(inode, handle, &hinfo,
2290 leaf_bh->b_blocknr, dx_leaves[i]);
2291 if (ret) {
2292 mlog_errno(ret);
2293 goto out;
2294 }
2295 2375
2296 ocfs2_dx_dir_name_hash(inode, "..", 2, &hinfo); 2376 ocfs2_dx_dir_name_hash(inode, "..", 2, &hinfo);
2297 i = ocfs2_dx_dir_hash_idx(osb, &hinfo); 2377 ocfs2_dx_entry_list_insert(entry_list, &hinfo, leaf_bh->b_blocknr);
2298 ret = __ocfs2_dx_dir_leaf_insert(inode, handle, &hinfo,
2299 leaf_bh->b_blocknr, dx_leaves[i]);
2300 if (ret) {
2301 mlog_errno(ret);
2302 goto out;
2303 }
2304
2305 ret = ocfs2_dx_dir_attach_index(osb, handle, inode, di_bh, meta_ac,
2306 &dx_root_bh);
2307 if (ret) {
2308 mlog_errno(ret);
2309 goto out;
2310 }
2311
2312 /* This should never fail considering we start with an empty
2313 * dx_root. */
2314 ocfs2_init_dx_root_extent_tree(&et, inode, dx_root_bh);
2315 ret = ocfs2_insert_extent(osb, handle, inode, &et, 0,
2316 insert_blkno, 1, 0, NULL);
2317 if (ret)
2318 mlog_errno(ret);
2319 2378
2320out: 2379out:
2321 if (dx_leaves) {
2322 for (i = 0; i < num_dx_leaves; i++)
2323 brelse(dx_leaves[i]);
2324 kfree(dx_leaves);
2325 }
2326 brelse(dx_root_bh); 2380 brelse(dx_root_bh);
2327 brelse(leaf_bh); 2381 brelse(leaf_bh);
2328 return ret; 2382 return ret;
@@ -2392,6 +2446,74 @@ inc:
2392out: 2446out:
2393 return ret; 2447 return ret;
2394} 2448}
2449 /*
2450 * XXX: This expects dx_root_bh to already be part of the transaction.
2451 */
2452static void ocfs2_dx_dir_index_root_block(struct inode *dir,
2453 struct buffer_head *dx_root_bh,
2454 struct buffer_head *dirent_bh)
2455{
2456 char *de_buf, *limit;
2457 struct ocfs2_dx_root_block *dx_root;
2458 struct ocfs2_dir_entry *de;
2459 struct ocfs2_dx_hinfo hinfo;
2460 u64 dirent_blk = dirent_bh->b_blocknr;
2461
2462 dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
2463
2464 de_buf = dirent_bh->b_data;
2465 limit = de_buf + dir->i_sb->s_blocksize;
2466
2467 while (de_buf < limit) {
2468 de = (struct ocfs2_dir_entry *)de_buf;
2469
2470 if (!de->name_len || !de->inode)
2471 goto inc;
2472
2473 ocfs2_dx_dir_name_hash(dir, de->name, de->name_len, &hinfo);
2474
2475 mlog(0,
2476 "dir: %llu, major: 0x%x minor: 0x%x, index: %u, name: %.*s\n",
2477 (unsigned long long)dir->i_ino, hinfo.major_hash,
2478 hinfo.minor_hash,
2479 le16_to_cpu(dx_root->dr_entries.de_num_used),
2480 de->name_len, de->name);
2481
2482 ocfs2_dx_entry_list_insert(&dx_root->dr_entries, &hinfo,
2483 dirent_blk);
2484inc:
2485 de_buf += le16_to_cpu(de->rec_len);
2486 }
2487}
2488
2489/*
2490 * Count the number of inline directory entries in di_bh and compare
2491 * them against the number of entries we can hold in an inline dx root
2492 * block.
2493 */
2494static int ocfs2_new_dx_should_be_inline(struct inode *dir,
2495 struct buffer_head *di_bh)
2496{
2497 int dirent_count = 0;
2498 char *de_buf, *limit;
2499 struct ocfs2_dir_entry *de;
2500 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
2501
2502 de_buf = di->id2.i_data.id_data;
2503 limit = de_buf + i_size_read(dir);
2504
2505 while (de_buf < limit) {
2506 de = (struct ocfs2_dir_entry *)de_buf;
2507
2508 if (de->name_len && de->inode)
2509 dirent_count++;
2510
2511 de_buf += le16_to_cpu(de->rec_len);
2512 }
2513
2514 /* We are careful to leave room for one extra record. */
2515 return dirent_count < ocfs2_dx_entries_per_root(dir->i_sb);
2516}
2395 2517
2396/* 2518/*
2397 * Expand rec_len of the rightmost dirent in a directory block so that it 2519 * Expand rec_len of the rightmost dirent in a directory block so that it
@@ -2442,7 +2564,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
2442{ 2564{
2443 u32 alloc, dx_alloc, bit_off, len; 2565 u32 alloc, dx_alloc, bit_off, len;
2444 struct super_block *sb = dir->i_sb; 2566 struct super_block *sb = dir->i_sb;
2445 int ret, i, num_dx_leaves = 0, 2567 int ret, i, num_dx_leaves = 0, dx_inline = 0,
2446 credits = ocfs2_inline_to_extents_credits(sb); 2568 credits = ocfs2_inline_to_extents_credits(sb);
2447 u64 dx_insert_blkno, blkno, 2569 u64 dx_insert_blkno, blkno,
2448 bytes = blocks_wanted << sb->s_blocksize_bits; 2570 bytes = blocks_wanted << sb->s_blocksize_bits;
@@ -2465,15 +2587,19 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
2465 dx_alloc = 0; 2587 dx_alloc = 0;
2466 2588
2467 if (ocfs2_supports_indexed_dirs(osb)) { 2589 if (ocfs2_supports_indexed_dirs(osb)) {
2468 /* Add one more cluster for an index leaf */
2469 dx_alloc++;
2470 credits += ocfs2_add_dir_index_credits(sb); 2590 credits += ocfs2_add_dir_index_credits(sb);
2471 2591
2472 dx_leaves = ocfs2_dx_dir_kmalloc_leaves(sb, &num_dx_leaves); 2592 dx_inline = ocfs2_new_dx_should_be_inline(dir, di_bh);
2473 if (!dx_leaves) { 2593 if (!dx_inline) {
2474 ret = -ENOMEM; 2594 /* Add one more cluster for an index leaf */
2475 mlog_errno(ret); 2595 dx_alloc++;
2476 goto out; 2596 dx_leaves = ocfs2_dx_dir_kmalloc_leaves(sb,
2597 &num_dx_leaves);
2598 if (!dx_leaves) {
2599 ret = -ENOMEM;
2600 mlog_errno(ret);
2601 goto out;
2602 }
2477 } 2603 }
2478 2604
2479 /* This gets us the dx_root */ 2605 /* This gets us the dx_root */
@@ -2524,7 +2650,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
2524 } 2650 }
2525 did_quota = 1; 2651 did_quota = 1;
2526 2652
2527 if (ocfs2_supports_indexed_dirs(osb)) { 2653 if (ocfs2_supports_indexed_dirs(osb) && !dx_inline) {
2528 /* 2654 /*
2529 * Allocate our index cluster first, to maximize the 2655 * Allocate our index cluster first, to maximize the
2530 * possibility that unindexed leaves grow 2656 * possibility that unindexed leaves grow
@@ -2587,7 +2713,12 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
2587 goto out_commit; 2713 goto out_commit;
2588 } 2714 }
2589 2715
2590 if (ocfs2_supports_indexed_dirs(osb)) { 2716 if (ocfs2_supports_indexed_dirs(osb) && !dx_inline) {
2717 /*
2718 * Dx dirs with an external cluster need to do this up
2719 * front. Inline dx root's get handled later, after
2720 * we've allocated our root block.
2721 */
2591 ret = ocfs2_dx_dir_index_block(dir, handle, dx_leaves, 2722 ret = ocfs2_dx_dir_index_block(dir, handle, dx_leaves,
2592 num_dx_leaves, dirdata_bh); 2723 num_dx_leaves, dirdata_bh);
2593 if (ret) { 2724 if (ret) {
@@ -2650,17 +2781,23 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
2650 2781
2651 if (ocfs2_supports_indexed_dirs(osb)) { 2782 if (ocfs2_supports_indexed_dirs(osb)) {
2652 ret = ocfs2_dx_dir_attach_index(osb, handle, dir, di_bh, 2783 ret = ocfs2_dx_dir_attach_index(osb, handle, dir, di_bh,
2653 meta_ac, &dx_root_bh); 2784 meta_ac, dx_inline,
2785 &dx_root_bh);
2654 if (ret) { 2786 if (ret) {
2655 mlog_errno(ret); 2787 mlog_errno(ret);
2656 goto out_commit; 2788 goto out_commit;
2657 } 2789 }
2658 2790
2659 ocfs2_init_dx_root_extent_tree(&dx_et, dir, dx_root_bh); 2791 if (dx_inline) {
2660 ret = ocfs2_insert_extent(osb, handle, dir, &dx_et, 0, 2792 ocfs2_dx_dir_index_root_block(dir, dx_root_bh,
2661 dx_insert_blkno, 1, 0, NULL); 2793 dirdata_bh);
2662 if (ret) 2794 } else {
2663 mlog_errno(ret); 2795 ocfs2_init_dx_root_extent_tree(&dx_et, dir, dx_root_bh);
2796 ret = ocfs2_insert_extent(osb, handle, dir, &dx_et, 0,
2797 dx_insert_blkno, 1, 0, NULL);
2798 if (ret)
2799 mlog_errno(ret);
2800 }
2664 } 2801 }
2665 2802
2666 /* 2803 /*
@@ -2690,14 +2827,18 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
2690 if (ocfs2_supports_indexed_dirs(osb)) { 2827 if (ocfs2_supports_indexed_dirs(osb)) {
2691 unsigned int off; 2828 unsigned int off;
2692 2829
2693 /* 2830 if (!dx_inline) {
2694 * We need to return the correct block within the 2831 /*
2695 * cluster which should hold our entry. 2832 * We need to return the correct block within the
2696 */ 2833 * cluster which should hold our entry.
2697 off = ocfs2_dx_dir_hash_idx(OCFS2_SB(dir->i_sb), 2834 */
2698 &lookup->dl_hinfo); 2835 off = ocfs2_dx_dir_hash_idx(OCFS2_SB(dir->i_sb),
2699 get_bh(dx_leaves[off]); 2836 &lookup->dl_hinfo);
2700 lookup->dl_dx_leaf_bh = dx_leaves[off]; 2837 get_bh(dx_leaves[off]);
2838 lookup->dl_dx_leaf_bh = dx_leaves[off];
2839 }
2840 lookup->dl_dx_root_bh = dx_root_bh;
2841 dx_root_bh = NULL;
2701 } 2842 }
2702 2843
2703out_commit: 2844out_commit:
@@ -3506,6 +3647,138 @@ out:
3506 return ret; 3647 return ret;
3507} 3648}
3508 3649
3650static int ocfs2_expand_inline_dx_root(struct inode *dir,
3651 struct buffer_head *dx_root_bh)
3652{
3653 int ret, num_dx_leaves, i, j, did_quota = 0;
3654 struct buffer_head **dx_leaves = NULL;
3655 struct ocfs2_extent_tree et;
3656 u64 insert_blkno;
3657 struct ocfs2_alloc_context *data_ac = NULL;
3658 struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
3659 handle_t *handle = NULL;
3660 struct ocfs2_dx_root_block *dx_root;
3661 struct ocfs2_dx_entry_list *entry_list;
3662 struct ocfs2_dx_entry *dx_entry;
3663 struct ocfs2_dx_leaf *target_leaf;
3664
3665 ret = ocfs2_reserve_clusters(osb, 1, &data_ac);
3666 if (ret) {
3667 mlog_errno(ret);
3668 goto out;
3669 }
3670
3671 dx_leaves = ocfs2_dx_dir_kmalloc_leaves(osb->sb, &num_dx_leaves);
3672 if (!dx_leaves) {
3673 ret = -ENOMEM;
3674 mlog_errno(ret);
3675 goto out;
3676 }
3677
3678 handle = ocfs2_start_trans(osb, ocfs2_calc_dxi_expand_credits(osb->sb));
3679 if (IS_ERR(handle)) {
3680 ret = PTR_ERR(handle);
3681 mlog_errno(ret);
3682 goto out;
3683 }
3684
3685 if (vfs_dq_alloc_space_nodirty(dir,
3686 ocfs2_clusters_to_bytes(osb->sb, 1))) {
3687 ret = -EDQUOT;
3688 goto out_commit;
3689 }
3690 did_quota = 1;
3691
3692 /*
3693 * We do this up front, before the allocation, so that a
3694 * failure to add the dx_root_bh to the journal won't result
3695 * us losing clusters.
3696 */
3697 ret = ocfs2_journal_access_dr(handle, dir, dx_root_bh,
3698 OCFS2_JOURNAL_ACCESS_WRITE);
3699 if (ret) {
3700 mlog_errno(ret);
3701 goto out_commit;
3702 }
3703
3704 ret = __ocfs2_dx_dir_new_cluster(dir, 0, handle, data_ac, dx_leaves,
3705 num_dx_leaves, &insert_blkno);
3706 if (ret) {
3707 mlog_errno(ret);
3708 goto out_commit;
3709 }
3710
3711 /*
3712 * Transfer the entries from our dx_root into the appropriate
3713 * block
3714 */
3715 dx_root = (struct ocfs2_dx_root_block *) dx_root_bh->b_data;
3716 entry_list = &dx_root->dr_entries;
3717
3718 for (i = 0; i < le16_to_cpu(entry_list->de_num_used); i++) {
3719 dx_entry = &entry_list->de_entries[i];
3720
3721 j = __ocfs2_dx_dir_hash_idx(osb,
3722 le32_to_cpu(dx_entry->dx_minor_hash));
3723 target_leaf = (struct ocfs2_dx_leaf *)dx_leaves[j]->b_data;
3724
3725 ocfs2_dx_dir_leaf_insert_tail(target_leaf, dx_entry);
3726
3727 /* Each leaf has been passed to the journal already
3728 * via __ocfs2_dx_dir_new_cluster() */
3729 }
3730
3731 dx_root->dr_flags &= ~OCFS2_DX_FLAG_INLINE;
3732 memset(&dx_root->dr_list, 0, osb->sb->s_blocksize -
3733 offsetof(struct ocfs2_dx_root_block, dr_list));
3734 dx_root->dr_list.l_count =
3735 cpu_to_le16(ocfs2_extent_recs_per_dx_root(osb->sb));
3736
3737 /* This should never fail considering we start with an empty
3738 * dx_root. */
3739 ocfs2_init_dx_root_extent_tree(&et, dir, dx_root_bh);
3740 ret = ocfs2_insert_extent(osb, handle, dir, &et, 0,
3741 insert_blkno, 1, 0, NULL);
3742 if (ret)
3743 mlog_errno(ret);
3744 did_quota = 0;
3745
3746 ocfs2_journal_dirty(handle, dx_root_bh);
3747
3748out_commit:
3749 if (ret < 0 && did_quota)
3750 vfs_dq_free_space_nodirty(dir,
3751 ocfs2_clusters_to_bytes(dir->i_sb, 1));
3752
3753 ocfs2_commit_trans(osb, handle);
3754
3755out:
3756 if (data_ac)
3757 ocfs2_free_alloc_context(data_ac);
3758
3759 if (dx_leaves) {
3760 for (i = 0; i < num_dx_leaves; i++)
3761 brelse(dx_leaves[i]);
3762 kfree(dx_leaves);
3763 }
3764 return ret;
3765}
3766
3767static int ocfs2_inline_dx_has_space(struct buffer_head *dx_root_bh)
3768{
3769 struct ocfs2_dx_root_block *dx_root;
3770 struct ocfs2_dx_entry_list *entry_list;
3771
3772 dx_root = (struct ocfs2_dx_root_block *) dx_root_bh->b_data;
3773 entry_list = &dx_root->dr_entries;
3774
3775 if (le16_to_cpu(entry_list->de_num_used) >=
3776 le16_to_cpu(entry_list->de_count))
3777 return -ENOSPC;
3778
3779 return 0;
3780}
3781
3509static int ocfs2_find_dir_space_dx(struct ocfs2_super *osb, struct inode *dir, 3782static int ocfs2_find_dir_space_dx(struct ocfs2_super *osb, struct inode *dir,
3510 struct buffer_head *di_bh, const char *name, 3783 struct buffer_head *di_bh, const char *name,
3511 int namelen, 3784 int namelen,
@@ -3527,6 +3800,23 @@ static int ocfs2_find_dir_space_dx(struct ocfs2_super *osb, struct inode *dir,
3527 } 3800 }
3528 3801
3529 dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data; 3802 dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
3803 if (ocfs2_dx_root_inline(dx_root)) {
3804 ret = ocfs2_inline_dx_has_space(dx_root_bh);
3805
3806 if (ret == 0)
3807 goto search_el;
3808
3809 /*
3810 * We ran out of room in the root block. Expand it to
3811 * an extent, then allow ocfs2_find_dir_space_dx to do
3812 * the rest.
3813 */
3814 ret = ocfs2_expand_inline_dx_root(dir, dx_root_bh);
3815 if (ret) {
3816 mlog_errno(ret);
3817 goto out;
3818 }
3819 }
3530 3820
3531restart_search: 3821restart_search:
3532 ret = ocfs2_dx_dir_lookup(dir, &dx_root->dr_list, &lookup->dl_hinfo, 3822 ret = ocfs2_dx_dir_lookup(dir, &dx_root->dr_list, &lookup->dl_hinfo,
@@ -3578,8 +3868,11 @@ restart_search:
3578 goto restart_search; 3868 goto restart_search;
3579 } 3869 }
3580 3870
3871search_el:
3581 lookup->dl_dx_leaf_bh = dx_leaf_bh; 3872 lookup->dl_dx_leaf_bh = dx_leaf_bh;
3582 dx_leaf_bh = NULL; 3873 dx_leaf_bh = NULL;
3874 lookup->dl_dx_root_bh = dx_root_bh;
3875 dx_root_bh = NULL;
3583 3876
3584out: 3877out:
3585 brelse(dx_leaf_bh); 3878 brelse(dx_leaf_bh);
@@ -3774,10 +4067,12 @@ int ocfs2_dx_dir_truncate(struct inode *dir, struct buffer_head *di_bh)
3774 mlog_errno(ret); 4067 mlog_errno(ret);
3775 goto out; 4068 goto out;
3776 } 4069 }
4070 dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
3777 4071
3778 ocfs2_init_dx_root_extent_tree(&et, dir, dx_root_bh); 4072 if (ocfs2_dx_root_inline(dx_root))
4073 goto remove_index;
3779 4074
3780 dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data; 4075 ocfs2_init_dx_root_extent_tree(&et, dir, dx_root_bh);
3781 4076
3782 /* XXX: What if dr_clusters is too large? */ 4077 /* XXX: What if dr_clusters is too large? */
3783 while (le32_to_cpu(dx_root->dr_clusters)) { 4078 while (le32_to_cpu(dx_root->dr_clusters)) {
@@ -3803,6 +4098,7 @@ int ocfs2_dx_dir_truncate(struct inode *dir, struct buffer_head *di_bh)
3803 major_hash = cpos - 1; 4098 major_hash = cpos - 1;
3804 } 4099 }
3805 4100
4101remove_index:
3806 ret = ocfs2_dx_dir_remove_index(dir, di_bh, dx_root_bh); 4102 ret = ocfs2_dx_dir_remove_index(dir, di_bh, dx_root_bh);
3807 if (ret) { 4103 if (ret) {
3808 mlog_errno(ret); 4104 mlog_errno(ret);