aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/dir.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-03-28 14:14:04 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2006-03-28 14:14:04 -0500
commit71b86f562b5eb6f94ea00bba060caa64d0137969 (patch)
tree63d982e09a9cb934fe656afe115031c0a9dc5e4a /fs/gfs2/dir.c
parent94aabbd99370f738da4f6cb4ea0b94cd9024002f (diff)
[GFS2] Further updates to dir and logging code
This reduces the size of the directory code by about 3k and gets readdir() to use the functions which were introduced in the previous directory code update. Two memory allocations are merged into one. Eliminates zeroing of some buffers which were never used before they were initialised by other data. There is still scope for further improvement in the directory code. On the logging side, a hand created mutex has been replaced by a standard Linux mutex in the log allocation code. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/dir.c')
-rw-r--r--fs/gfs2/dir.c412
1 files changed, 161 insertions, 251 deletions
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index f31f163da1a1..ba3438553f33 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -60,6 +60,7 @@
60#include <linux/buffer_head.h> 60#include <linux/buffer_head.h>
61#include <linux/sort.h> 61#include <linux/sort.h>
62#include <linux/gfs2_ondisk.h> 62#include <linux/gfs2_ondisk.h>
63#include <linux/crc32.h>
63#include <asm/semaphore.h> 64#include <asm/semaphore.h>
64 65
65#include "gfs2.h" 66#include "gfs2.h"
@@ -344,7 +345,8 @@ fail:
344} 345}
345 346
346typedef int (*gfs2_dscan_t)(const struct gfs2_dirent *dent, 347typedef int (*gfs2_dscan_t)(const struct gfs2_dirent *dent,
347 const struct qstr *name); 348 const struct qstr *name,
349 void *opaque);
348 350
349static inline int __gfs2_dirent_find(const struct gfs2_dirent *dent, 351static inline int __gfs2_dirent_find(const struct gfs2_dirent *dent,
350 const struct qstr *name, int ret) 352 const struct qstr *name, int ret)
@@ -358,13 +360,15 @@ static inline int __gfs2_dirent_find(const struct gfs2_dirent *dent,
358} 360}
359 361
360static int gfs2_dirent_find(const struct gfs2_dirent *dent, 362static int gfs2_dirent_find(const struct gfs2_dirent *dent,
361 const struct qstr *name) 363 const struct qstr *name,
364 void *opaque)
362{ 365{
363 return __gfs2_dirent_find(dent, name, 1); 366 return __gfs2_dirent_find(dent, name, 1);
364} 367}
365 368
366static int gfs2_dirent_prev(const struct gfs2_dirent *dent, 369static int gfs2_dirent_prev(const struct gfs2_dirent *dent,
367 const struct qstr *name) 370 const struct qstr *name,
371 void *opaque)
368{ 372{
369 return __gfs2_dirent_find(dent, name, 2); 373 return __gfs2_dirent_find(dent, name, 2);
370} 374}
@@ -374,7 +378,8 @@ static int gfs2_dirent_prev(const struct gfs2_dirent *dent,
374 * name->len holds size of block. 378 * name->len holds size of block.
375 */ 379 */
376static int gfs2_dirent_last(const struct gfs2_dirent *dent, 380static int gfs2_dirent_last(const struct gfs2_dirent *dent,
377 const struct qstr *name) 381 const struct qstr *name,
382 void *opaque)
378{ 383{
379 const char *start = name->name; 384 const char *start = name->name;
380 const char *end = (const char *)dent + be16_to_cpu(dent->de_rec_len); 385 const char *end = (const char *)dent + be16_to_cpu(dent->de_rec_len);
@@ -384,17 +389,36 @@ static int gfs2_dirent_last(const struct gfs2_dirent *dent,
384} 389}
385 390
386static int gfs2_dirent_find_space(const struct gfs2_dirent *dent, 391static int gfs2_dirent_find_space(const struct gfs2_dirent *dent,
387 const struct qstr *name) 392 const struct qstr *name,
393 void *opaque)
388{ 394{
389 unsigned required = GFS2_DIRENT_SIZE(name->len); 395 unsigned required = GFS2_DIRENT_SIZE(name->len);
390 unsigned actual = GFS2_DIRENT_SIZE(be16_to_cpu(dent->de_name_len)); 396 unsigned actual = GFS2_DIRENT_SIZE(be16_to_cpu(dent->de_name_len));
391 unsigned totlen = be16_to_cpu(dent->de_rec_len); 397 unsigned totlen = be16_to_cpu(dent->de_rec_len);
392 398
399 if (!dent->de_inum.no_addr)
400 actual = GFS2_DIRENT_SIZE(0);
393 if ((totlen - actual) >= required) 401 if ((totlen - actual) >= required)
394 return 1; 402 return 1;
395 return 0; 403 return 0;
396} 404}
397 405
406struct dirent_gather {
407 const struct gfs2_dirent **pdent;
408 unsigned offset;
409};
410
411static int gfs2_dirent_gather(const struct gfs2_dirent *dent,
412 const struct qstr *name,
413 void *opaque)
414{
415 struct dirent_gather *g = opaque;
416 if (dent->de_inum.no_addr) {
417 g->pdent[g->offset++] = dent;
418 }
419 return 0;
420}
421
398/* 422/*
399 * Other possible things to check: 423 * Other possible things to check:
400 * - Inode located within filesystem size (and on valid block) 424 * - Inode located within filesystem size (and on valid block)
@@ -431,19 +455,12 @@ error:
431 return -EIO; 455 return -EIO;
432} 456}
433 457
434static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode, 458static int gfs2_dirent_offset(const void *buf)
435 void *buf,
436 unsigned int len, gfs2_dscan_t scan,
437 const struct qstr *name)
438{ 459{
439 struct gfs2_meta_header *h = buf; 460 const struct gfs2_meta_header *h = buf;
440 struct gfs2_dirent *dent, *prev; 461 int offset;
441 unsigned offset;
442 unsigned size;
443 int ret = 0;
444 462
445 BUG_ON(buf == NULL); 463 BUG_ON(buf == NULL);
446 BUG_ON(name == NULL);
447 464
448 switch(be16_to_cpu(h->mh_type)) { 465 switch(be16_to_cpu(h->mh_type)) {
449 case GFS2_METATYPE_LF: 466 case GFS2_METATYPE_LF:
@@ -455,14 +472,36 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode,
455 default: 472 default:
456 goto wrong_type; 473 goto wrong_type;
457 } 474 }
475 return offset;
476wrong_type:
477 printk(KERN_WARNING "gfs2_scan_dirent: wrong block type %u\n",
478 be16_to_cpu(h->mh_type));
479 return -1;
480}
458 481
482static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode,
483 void *buf,
484 unsigned int len, gfs2_dscan_t scan,
485 const struct qstr *name,
486 void *opaque)
487{
488 struct gfs2_dirent *dent, *prev;
489 unsigned offset;
490 unsigned size;
491 int ret = 0;
492
493 ret = gfs2_dirent_offset(buf);
494 if (ret < 0)
495 goto consist_inode;
496
497 offset = ret;
459 prev = NULL; 498 prev = NULL;
460 dent = (struct gfs2_dirent *)(buf + offset); 499 dent = (struct gfs2_dirent *)(buf + offset);
461 size = be16_to_cpu(dent->de_rec_len); 500 size = be16_to_cpu(dent->de_rec_len);
462 if (gfs2_check_dirent(dent, offset, size, len, 1)) 501 if (gfs2_check_dirent(dent, offset, size, len, 1))
463 goto consist_inode; 502 goto consist_inode;
464 do { 503 do {
465 ret = scan(dent, name); 504 ret = scan(dent, name, opaque);
466 if (ret) 505 if (ret)
467 break; 506 break;
468 offset += size; 507 offset += size;
@@ -487,9 +526,6 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode,
487 return ERR_PTR(ret); 526 return ERR_PTR(ret);
488 } 527 }
489 528
490wrong_type:
491 printk(KERN_WARNING "gfs2_scan_dirent: %p wrong block type %u\n", scan,
492 be16_to_cpu(h->mh_type));
493consist_inode: 529consist_inode:
494 gfs2_consist_inode(inode->u.generic_ip); 530 gfs2_consist_inode(inode->u.generic_ip);
495 return ERR_PTR(-EIO); 531 return ERR_PTR(-EIO);
@@ -651,7 +687,8 @@ static struct gfs2_dirent *gfs2_dirent_alloc(struct inode *inode,
651 const struct qstr *name) 687 const struct qstr *name)
652{ 688{
653 struct gfs2_dirent *dent; 689 struct gfs2_dirent *dent;
654 dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size, gfs2_dirent_find_space, name); 690 dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size,
691 gfs2_dirent_find_space, name, NULL);
655 if (!dent || IS_ERR(dent)) 692 if (!dent || IS_ERR(dent))
656 return dent; 693 return dent;
657 return gfs2_init_dirent(inode, dent, name, bh); 694 return gfs2_init_dirent(inode, dent, name, bh);
@@ -734,7 +771,7 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode,
734 return ERR_PTR(error); 771 return ERR_PTR(error);
735 do { 772 do {
736 dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size, 773 dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size,
737 scan, name); 774 scan, name, NULL);
738 if (dent) 775 if (dent)
739 goto got_dent; 776 goto got_dent;
740 leaf = (struct gfs2_leaf *)bh->b_data; 777 leaf = (struct gfs2_leaf *)bh->b_data;
@@ -751,7 +788,7 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode,
751 error = gfs2_meta_inode_buffer(ip, &bh); 788 error = gfs2_meta_inode_buffer(ip, &bh);
752 if (error) 789 if (error)
753 return ERR_PTR(error); 790 return ERR_PTR(error);
754 dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size, scan, name); 791 dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size, scan, name, NULL);
755got_dent: 792got_dent:
756 *pbh = bh; 793 *pbh = bh;
757 return dent; 794 return dent;
@@ -764,6 +801,7 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh,
764 struct buffer_head *bh = gfs2_meta_new(ip->i_gl, bn); 801 struct buffer_head *bh = gfs2_meta_new(ip->i_gl, bn);
765 struct gfs2_leaf *leaf; 802 struct gfs2_leaf *leaf;
766 struct gfs2_dirent *dent; 803 struct gfs2_dirent *dent;
804 struct qstr name = { .name = "", .len = 0, .hash = 0 };
767 if (!bh) 805 if (!bh)
768 return NULL; 806 return NULL;
769 gfs2_trans_add_bh(ip->i_gl, bh, 1); 807 gfs2_trans_add_bh(ip->i_gl, bh, 1);
@@ -775,12 +813,7 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh,
775 leaf->lf_next = cpu_to_be64(0); 813 leaf->lf_next = cpu_to_be64(0);
776 memset(leaf->lf_reserved, 0, sizeof(leaf->lf_reserved)); 814 memset(leaf->lf_reserved, 0, sizeof(leaf->lf_reserved));
777 dent = (struct gfs2_dirent *)(leaf+1); 815 dent = (struct gfs2_dirent *)(leaf+1);
778 dent->de_inum.no_formal_ino = cpu_to_be64(0); 816 gfs2_qstr2dirent(&name, bh->b_size - sizeof(struct gfs2_leaf), dent);
779 dent->de_inum.no_addr = cpu_to_be64(0);
780 dent->de_hash = cpu_to_be32(0);
781 dent->de_rec_len = cpu_to_be16(bh->b_size - sizeof(struct gfs2_leaf));
782 dent->de_name_len = cpu_to_be16(0);
783 dent->de_type = cpu_to_be16(0);
784 *pbh = bh; 817 *pbh = bh;
785 return leaf; 818 return leaf;
786} 819}
@@ -831,7 +864,7 @@ static int dir_make_exhash(struct inode *inode)
831 sizeof(struct gfs2_leaf); 864 sizeof(struct gfs2_leaf);
832 args.name = bh->b_data; 865 args.name = bh->b_data;
833 dent = gfs2_dirent_scan(dip->i_vnode, bh->b_data, bh->b_size, 866 dent = gfs2_dirent_scan(dip->i_vnode, bh->b_data, bh->b_size,
834 gfs2_dirent_last, &args); 867 gfs2_dirent_last, &args, NULL);
835 if (!dent) { 868 if (!dent) {
836 brelse(bh); 869 brelse(bh);
837 brelse(dibh); 870 brelse(dibh);
@@ -939,7 +972,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
939 lp[x] = cpu_to_be64(bn); 972 lp[x] = cpu_to_be64(bn);
940 973
941 error = gfs2_dir_write_data(dip, (char *)lp, start * sizeof(uint64_t), 974 error = gfs2_dir_write_data(dip, (char *)lp, start * sizeof(uint64_t),
942 half_len * sizeof(uint64_t)); 975 half_len * sizeof(uint64_t));
943 if (error != half_len * sizeof(uint64_t)) { 976 if (error != half_len * sizeof(uint64_t)) {
944 if (error >= 0) 977 if (error >= 0)
945 error = -EIO; 978 error = -EIO;
@@ -965,7 +998,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
965 str.name = (char*)(dent+1); 998 str.name = (char*)(dent+1);
966 str.len = be16_to_cpu(dent->de_name_len); 999 str.len = be16_to_cpu(dent->de_name_len);
967 str.hash = be32_to_cpu(dent->de_hash); 1000 str.hash = be32_to_cpu(dent->de_hash);
968 new = gfs2_dirent_alloc(dip->i_vnode, nbh, &str); 1001 new = gfs2_dirent_alloc(inode, nbh, &str);
969 if (IS_ERR(new)) { 1002 if (IS_ERR(new)) {
970 error = PTR_ERR(new); 1003 error = PTR_ERR(new);
971 break; 1004 break;
@@ -1154,10 +1187,10 @@ static int compare_dents(const void *a, const void *b)
1154 1187
1155static int do_filldir_main(struct gfs2_inode *dip, uint64_t *offset, 1188static int do_filldir_main(struct gfs2_inode *dip, uint64_t *offset,
1156 void *opaque, gfs2_filldir_t filldir, 1189 void *opaque, gfs2_filldir_t filldir,
1157 struct gfs2_dirent **darr, uint32_t entries, 1190 const struct gfs2_dirent **darr, uint32_t entries,
1158 int *copied) 1191 int *copied)
1159{ 1192{
1160 struct gfs2_dirent *dent, *dent_next; 1193 const struct gfs2_dirent *dent, *dent_next;
1161 struct gfs2_inum inum; 1194 struct gfs2_inum inum;
1162 uint64_t off, off_next; 1195 uint64_t off, off_next;
1163 unsigned int x, y; 1196 unsigned int x, y;
@@ -1216,189 +1249,74 @@ static int do_filldir_main(struct gfs2_inode *dip, uint64_t *offset,
1216 return 0; 1249 return 0;
1217} 1250}
1218 1251
1219/** 1252static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
1220 * do_filldir_single - Read directory entries out of a single block 1253 gfs2_filldir_t filldir, int *copied,
1221 * @dip: The GFS2 inode 1254 unsigned *depth, u64 leaf_no)
1222 * @offset: The offset in the file to read from
1223 * @opaque: opaque data to pass to filldir
1224 * @filldir: The function to pass entries to
1225 * @bh: the block
1226 * @entries: the number of entries in the block
1227 * @copied: pointer to int that's non-zero if a entry has been copied out
1228 *
1229 * Returns: errno, >0 on exception from filldir
1230 */
1231
1232static int do_filldir_single(struct gfs2_inode *dip, uint64_t *offset,
1233 void *opaque, gfs2_filldir_t filldir,
1234 struct buffer_head *bh, uint32_t entries,
1235 int *copied)
1236{ 1255{
1237 struct gfs2_dirent **darr; 1256 struct gfs2_inode *ip = inode->u.generic_ip;
1238 struct gfs2_dirent *de; 1257 struct buffer_head *bh;
1239 unsigned int e = 0; 1258 struct gfs2_leaf *lf;
1240 int error; 1259 unsigned entries = 0;
1241 1260 unsigned leaves = 0;
1242 if (!entries) 1261 const struct gfs2_dirent **darr, *dent;
1243 return 0; 1262 struct dirent_gather g;
1244 1263 struct buffer_head **larr;
1245 darr = kcalloc(entries, sizeof(struct gfs2_dirent *), GFP_KERNEL); 1264 int leaf = 0;
1246 if (!darr) 1265 int error, i;
1247 return -ENOMEM; 1266 u64 lfn = leaf_no;
1248 1267
1249 dirent_first(dip, bh, &de);
1250 do { 1268 do {
1251 if (!de->de_inum.no_addr) 1269 error = get_leaf(ip, lfn, &bh);
1252 continue;
1253 if (e >= entries) {
1254 gfs2_consist_inode(dip);
1255 error = -EIO;
1256 goto out;
1257 }
1258 darr[e++] = de;
1259 } while (dirent_next(dip, bh, &de) == 0);
1260
1261 if (e != entries) {
1262 gfs2_consist_inode(dip);
1263 error = -EIO;
1264 goto out;
1265 }
1266
1267 error = do_filldir_main(dip, offset, opaque, filldir, darr,
1268 entries, copied);
1269
1270 out:
1271 kfree(darr);
1272
1273 return error;
1274}
1275
1276/**
1277 * do_filldir_multi - Read directory entries out of a linked leaf list
1278 * @dip: The GFS2 inode
1279 * @offset: The offset in the file to read from
1280 * @opaque: opaque data to pass to filldir
1281 * @filldir: The function to pass entries to
1282 * @bh: the first leaf in the list
1283 * @copied: pointer to int that's non-zero if a entry has been copied out
1284 *
1285 * Returns: errno, >0 on exception from filldir
1286 */
1287
1288static int do_filldir_multi(struct gfs2_inode *dip, uint64_t *offset,
1289 void *opaque, gfs2_filldir_t filldir,
1290 struct buffer_head *bh, int *copied)
1291{
1292 struct buffer_head **larr = NULL;
1293 struct gfs2_dirent **darr;
1294 struct gfs2_leaf *leaf;
1295 struct buffer_head *tmp_bh;
1296 struct gfs2_dirent *de;
1297 unsigned int entries, e = 0;
1298 unsigned int leaves = 0, l = 0;
1299 unsigned int x;
1300 uint64_t ln;
1301 int error = 0;
1302
1303 /* Count leaves and entries */
1304
1305 leaf = (struct gfs2_leaf *)bh->b_data;
1306 entries = be16_to_cpu(leaf->lf_entries);
1307 ln = be64_to_cpu(leaf->lf_next);
1308
1309 while (ln) {
1310 error = get_leaf(dip, ln, &tmp_bh);
1311 if (error) 1270 if (error)
1312 return error; 1271 goto out;
1313 1272 lf = (struct gfs2_leaf *)bh->b_data;
1314 leaf = (struct gfs2_leaf *)tmp_bh->b_data; 1273 if (leaves == 0)
1315 if (leaf->lf_entries) { 1274 *depth = be16_to_cpu(lf->lf_depth);
1316 entries += be16_to_cpu(leaf->lf_entries); 1275 entries += be16_to_cpu(lf->lf_entries);
1317 leaves++; 1276 leaves++;
1318 } 1277 lfn = be64_to_cpu(lf->lf_next);
1319 ln = be64_to_cpu(leaf->lf_next); 1278 brelse(bh);
1320 1279 } while(lfn);
1321 brelse(tmp_bh);
1322 }
1323 1280
1324 if (!entries) 1281 if (!entries)
1325 return 0; 1282 return 0;
1326 1283
1327 if (leaves) { 1284 error = -ENOMEM;
1328 larr = kcalloc(leaves, sizeof(struct buffer_head *),GFP_KERNEL); 1285 larr = kmalloc((leaves + entries) * sizeof(void*), GFP_KERNEL);
1329 if (!larr) 1286 if (!larr)
1330 return -ENOMEM; 1287 goto out;
1331 } 1288 darr = (const struct gfs2_dirent **)(larr + leaves);
1332 1289 g.pdent = darr;
1333 darr = kcalloc(entries, sizeof(struct gfs2_dirent *), GFP_KERNEL); 1290 g.offset = 0;
1334 if (!darr) { 1291 lfn = leaf_no;
1335 kfree(larr);
1336 return -ENOMEM;
1337 }
1338
1339 leaf = (struct gfs2_leaf *)bh->b_data;
1340 if (leaf->lf_entries) {
1341 dirent_first(dip, bh, &de);
1342 do {
1343 if (!de->de_inum.no_addr)
1344 continue;
1345 if (e >= entries) {
1346 gfs2_consist_inode(dip);
1347 error = -EIO;
1348 goto out;
1349 }
1350 darr[e++] = de;
1351 } while (dirent_next(dip, bh, &de) == 0);
1352 }
1353 ln = be64_to_cpu(leaf->lf_next);
1354 1292
1355 while (ln) { 1293 do {
1356 error = get_leaf(dip, ln, &tmp_bh); 1294 error = get_leaf(ip, lfn, &bh);
1357 if (error) 1295 if (error)
1358 goto out; 1296 goto out_kfree;
1359 1297 lf = (struct gfs2_leaf *)bh->b_data;
1360 leaf = (struct gfs2_leaf *)tmp_bh->b_data; 1298 lfn = be64_to_cpu(lf->lf_next);
1361 if (leaf->lf_entries) { 1299 if (lf->lf_entries) {
1362 dirent_first(dip, tmp_bh, &de); 1300 dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size,
1363 do { 1301 gfs2_dirent_gather, NULL, &g);
1364 if (!de->de_inum.no_addr) 1302 error = PTR_ERR(dent);
1365 continue; 1303 if (IS_ERR(dent)) {
1366 if (e >= entries) { 1304 goto out_kfree;
1367 gfs2_consist_inode(dip); 1305 }
1368 error = -EIO; 1306 error = 0;
1369 goto out; 1307 larr[leaf++] = bh;
1370 }
1371 darr[e++] = de;
1372 } while (dirent_next(dip, tmp_bh, &de) == 0);
1373
1374 larr[l++] = tmp_bh;
1375
1376 ln = be64_to_cpu(leaf->lf_next);
1377 } else { 1308 } else {
1378 ln = be64_to_cpu(leaf->lf_next); 1309 brelse(bh);
1379 brelse(tmp_bh);
1380 } 1310 }
1381 } 1311 } while(lfn);
1382 1312
1383 if (gfs2_assert_withdraw(dip->i_sbd, l == leaves)) { 1313 error = do_filldir_main(ip, offset, opaque, filldir, darr,
1384 error = -EIO;
1385 goto out;
1386 }
1387 if (e != entries) {
1388 gfs2_consist_inode(dip);
1389 error = -EIO;
1390 goto out;
1391 }
1392
1393 error = do_filldir_main(dip, offset, opaque, filldir, darr,
1394 entries, copied); 1314 entries, copied);
1395 1315out_kfree:
1396 out: 1316 for(i = 0; i < leaf; i++)
1397 kfree(darr); 1317 brelse(larr[i]);
1398 for (x = 0; x < l; x++)
1399 brelse(larr[x]);
1400 kfree(larr); 1318 kfree(larr);
1401 1319out:
1402 return error; 1320 return error;
1403} 1321}
1404 1322
@@ -1412,18 +1330,18 @@ static int do_filldir_multi(struct gfs2_inode *dip, uint64_t *offset,
1412 * Returns: errno 1330 * Returns: errno
1413 */ 1331 */
1414 1332
1415static int dir_e_read(struct gfs2_inode *dip, uint64_t *offset, void *opaque, 1333static int dir_e_read(struct inode *inode, uint64_t *offset, void *opaque,
1416 gfs2_filldir_t filldir) 1334 gfs2_filldir_t filldir)
1417{ 1335{
1336 struct gfs2_inode *dip = inode->u.generic_ip;
1418 struct gfs2_sbd *sdp = dip->i_sbd; 1337 struct gfs2_sbd *sdp = dip->i_sbd;
1419 struct buffer_head *bh; 1338 uint32_t hsize, len = 0;
1420 struct gfs2_leaf *leaf;
1421 uint32_t hsize, len;
1422 uint32_t ht_offset, lp_offset, ht_offset_cur = -1; 1339 uint32_t ht_offset, lp_offset, ht_offset_cur = -1;
1423 uint32_t hash, index; 1340 uint32_t hash, index;
1424 uint64_t *lp; 1341 uint64_t *lp;
1425 int copied = 0; 1342 int copied = 0;
1426 int error = 0; 1343 int error = 0;
1344 unsigned depth;
1427 1345
1428 hsize = 1 << dip->i_di.di_depth; 1346 hsize = 1 << dip->i_di.di_depth;
1429 if (hsize * sizeof(uint64_t) != dip->i_di.di_size) { 1347 if (hsize * sizeof(uint64_t) != dip->i_di.di_size) {
@@ -1454,61 +1372,66 @@ static int dir_e_read(struct gfs2_inode *dip, uint64_t *offset, void *opaque,
1454 ht_offset_cur = ht_offset; 1372 ht_offset_cur = ht_offset;
1455 } 1373 }
1456 1374
1457 error = get_leaf(dip, be64_to_cpu(lp[lp_offset]), &bh); 1375 error = gfs2_dir_read_leaf(inode, offset, opaque, filldir,
1376 &copied, &depth,
1377 be64_to_cpu(lp[lp_offset]));
1458 if (error) 1378 if (error)
1459 goto out; 1379 break;
1460
1461 leaf = (struct gfs2_leaf *)bh->b_data;
1462 if (leaf->lf_next)
1463 error = do_filldir_multi(dip, offset, opaque, filldir,
1464 bh, &copied);
1465 else
1466 error = do_filldir_single(dip, offset, opaque, filldir,
1467 bh,
1468 be16_to_cpu(leaf->lf_entries),
1469 &copied);
1470
1471 brelse(bh);
1472
1473 if (error) {
1474 if (error > 0)
1475 error = 0;
1476 goto out;
1477 }
1478 1380
1479 len = 1 << (dip->i_di.di_depth - be16_to_cpu(leaf->lf_depth)); 1381 len = 1 << (dip->i_di.di_depth - depth);
1480 index = (index & ~(len - 1)) + len; 1382 index = (index & ~(len - 1)) + len;
1481 } 1383 }
1482 1384
1483 out: 1385out:
1484 kfree(lp); 1386 kfree(lp);
1485 1387 if (error > 0)
1388 error = 0;
1486 return error; 1389 return error;
1487} 1390}
1488 1391
1489static int dir_l_read(struct gfs2_inode *dip, uint64_t *offset, void *opaque, 1392int gfs2_dir_read(struct inode *inode, uint64_t *offset, void *opaque,
1490 gfs2_filldir_t filldir) 1393 gfs2_filldir_t filldir)
1491{ 1394{
1395 struct gfs2_inode *dip = inode->u.generic_ip;
1396 struct dirent_gather g;
1397 const struct gfs2_dirent **darr, *dent;
1492 struct buffer_head *dibh; 1398 struct buffer_head *dibh;
1493 int copied = 0; 1399 int copied = 0;
1494 int error; 1400 int error;
1495 1401
1402 if (!dip->i_di.di_entries)
1403 return 0;
1404
1405 if (dip->i_di.di_flags & GFS2_DIF_EXHASH)
1406 return dir_e_read(inode, offset, opaque, filldir);
1407
1496 if (!gfs2_is_stuffed(dip)) { 1408 if (!gfs2_is_stuffed(dip)) {
1497 gfs2_consist_inode(dip); 1409 gfs2_consist_inode(dip);
1498 return -EIO; 1410 return -EIO;
1499 } 1411 }
1500 1412
1501 if (!dip->i_di.di_entries)
1502 return 0;
1503
1504 error = gfs2_meta_inode_buffer(dip, &dibh); 1413 error = gfs2_meta_inode_buffer(dip, &dibh);
1505 if (error) 1414 if (error)
1506 return error; 1415 return error;
1507 1416
1508 error = do_filldir_single(dip, offset, 1417 error = -ENOMEM;
1509 opaque, filldir, 1418 darr = kmalloc(dip->i_di.di_entries * sizeof(struct gfs2_dirent *),
1510 dibh, dip->i_di.di_entries, 1419 GFP_KERNEL);
1511 &copied); 1420 if (darr) {
1421 g.pdent = darr;
1422 g.offset = 0;
1423 dent = gfs2_dirent_scan(inode, dibh->b_data, dibh->b_size,
1424 gfs2_dirent_gather, NULL, &g);
1425 if (IS_ERR(dent)) {
1426 error = PTR_ERR(dent);
1427 goto out;
1428 }
1429 error = do_filldir_main(dip, offset, opaque, filldir, darr,
1430 dip->i_di.di_entries, &copied);
1431out:
1432 kfree(darr);
1433 }
1434
1512 if (error > 0) 1435 if (error > 0)
1513 error = 0; 1436 error = 0;
1514 1437
@@ -1694,7 +1617,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name)
1694 return PTR_ERR(dent); 1617 return PTR_ERR(dent);
1695 } 1618 }
1696 /* If not first in block, adjust pointers accordingly */ 1619 /* If not first in block, adjust pointers accordingly */
1697 if (gfs2_dirent_find(dent, name) == 0) { 1620 if (gfs2_dirent_find(dent, name, NULL) == 0) {
1698 prev = dent; 1621 prev = dent;
1699 dent = (struct gfs2_dirent *)((char *)dent + be16_to_cpu(prev->de_rec_len)); 1622 dent = (struct gfs2_dirent *)((char *)dent + be16_to_cpu(prev->de_rec_len));
1700 } 1623 }
@@ -1724,19 +1647,6 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name)
1724 return error; 1647 return error;
1725} 1648}
1726 1649
1727int gfs2_dir_read(struct gfs2_inode *dip, uint64_t *offset, void *opaque,
1728 gfs2_filldir_t filldir)
1729{
1730 int error;
1731
1732 if (dip->i_di.di_flags & GFS2_DIF_EXHASH)
1733 error = dir_e_read(dip, offset, opaque, filldir);
1734 else
1735 error = dir_l_read(dip, offset, opaque, filldir);
1736
1737 return error;
1738}
1739
1740/** 1650/**
1741 * gfs2_dir_mvino - Change inode number of directory entry 1651 * gfs2_dir_mvino - Change inode number of directory entry
1742 * @dip: The GFS2 inode 1652 * @dip: The GFS2 inode