aboutsummaryrefslogtreecommitdiffstats
path: root/fs
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
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')
-rw-r--r--fs/gfs2/bmap.c1
-rw-r--r--fs/gfs2/dir.c412
-rw-r--r--fs/gfs2/dir.h15
-rw-r--r--fs/gfs2/incore.h3
-rw-r--r--fs/gfs2/inode.c14
-rw-r--r--fs/gfs2/log.c34
-rw-r--r--fs/gfs2/ops_dentry.c1
-rw-r--r--fs/gfs2/ops_export.c8
-rw-r--r--fs/gfs2/ops_file.c219
-rw-r--r--fs/gfs2/ops_fstype.c4
-rw-r--r--fs/gfs2/ops_inode.c13
-rw-r--r--fs/gfs2/recovery.c2
-rw-r--r--fs/gfs2/super.c1
-rw-r--r--fs/gfs2/util.c5
-rw-r--r--fs/gfs2/util.h2
15 files changed, 416 insertions, 318 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index cd5e4d863ce2..c7723119acb6 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -13,6 +13,7 @@
13#include <linux/completion.h> 13#include <linux/completion.h>
14#include <linux/buffer_head.h> 14#include <linux/buffer_head.h>
15#include <linux/gfs2_ondisk.h> 15#include <linux/gfs2_ondisk.h>
16#include <linux/crc32.h>
16#include <asm/semaphore.h> 17#include <asm/semaphore.h>
17 18
18#include "gfs2.h" 19#include "gfs2.h"
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
diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h
index 8fd4dc0f700e..42b3a1f34deb 100644
--- a/fs/gfs2/dir.h
+++ b/fs/gfs2/dir.h
@@ -32,7 +32,7 @@ int gfs2_dir_search(struct inode *dir, const struct qstr *filename,
32int gfs2_dir_add(struct inode *inode, const struct qstr *filename, 32int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
33 const struct gfs2_inum *inum, unsigned int type); 33 const struct gfs2_inum *inum, unsigned int type);
34int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename); 34int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename);
35int gfs2_dir_read(struct gfs2_inode *dip, uint64_t * offset, void *opaque, 35int gfs2_dir_read(struct inode *inode, uint64_t * offset, void *opaque,
36 gfs2_filldir_t filldir); 36 gfs2_filldir_t filldir);
37int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, 37int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
38 struct gfs2_inum *new_inum, unsigned int new_type); 38 struct gfs2_inum *new_inum, unsigned int new_type);
@@ -44,6 +44,19 @@ int gfs2_diradd_alloc_required(struct inode *dir,
44int gfs2_dir_get_buffer(struct gfs2_inode *ip, uint64_t block, int new, 44int gfs2_dir_get_buffer(struct gfs2_inode *ip, uint64_t block, int new,
45 struct buffer_head **bhp); 45 struct buffer_head **bhp);
46 46
47static inline uint32_t gfs2_disk_hash(const char *data, int len)
48{
49 return crc32_le(0xFFFFFFFF, data, len) ^ 0xFFFFFFFF;
50}
51
52
53static inline void gfs2_str2qstr(struct qstr *name, const char *fname)
54{
55 name->name = fname;
56 name->len = strlen(fname);
57 name->hash = gfs2_disk_hash(name->name, name->len);
58}
59
47/* N.B. This probably ought to take inum & type as args as well */ 60/* N.B. This probably ought to take inum & type as args as well */
48static inline void gfs2_qstr2dirent(const struct qstr *name, u16 reclen, struct gfs2_dirent *dent) 61static inline void gfs2_qstr2dirent(const struct qstr *name, u16 reclen, struct gfs2_dirent *dent)
49{ 62{
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 62f109e553c4..be307185f492 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -634,8 +634,7 @@ struct gfs2_sbd {
634 struct list_head sd_log_le_databuf; 634 struct list_head sd_log_le_databuf;
635 635
636 unsigned int sd_log_blks_free; 636 unsigned int sd_log_blks_free;
637 struct list_head sd_log_blks_list; 637 struct mutex sd_log_reserve_mutex;
638 wait_queue_head_t sd_log_blks_wait;
639 638
640 uint64_t sd_log_sequence; 639 uint64_t sd_log_sequence;
641 unsigned int sd_log_head; 640 unsigned int sd_log_head;
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index d403d51d5b0f..6140c2434e85 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -15,6 +15,7 @@
15#include <linux/posix_acl.h> 15#include <linux/posix_acl.h>
16#include <linux/sort.h> 16#include <linux/sort.h>
17#include <linux/gfs2_ondisk.h> 17#include <linux/gfs2_ondisk.h>
18#include <linux/crc32.h>
18#include <asm/semaphore.h> 19#include <asm/semaphore.h>
19 20
20#include "gfs2.h" 21#include "gfs2.h"
@@ -701,9 +702,7 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff)
701struct inode *gfs2_lookup_simple(struct inode *dip, const char *name) 702struct inode *gfs2_lookup_simple(struct inode *dip, const char *name)
702{ 703{
703 struct qstr qstr; 704 struct qstr qstr;
704 qstr.name = name; 705 gfs2_str2qstr(&qstr, name);
705 qstr.len = strlen(name);
706 qstr.hash = gfs2_disk_hash(qstr.name, qstr.len);
707 return gfs2_lookupi(dip, &qstr, 1, NULL); 706 return gfs2_lookupi(dip, &qstr, 1, NULL);
708} 707}
709 708
@@ -1389,9 +1388,7 @@ int gfs2_rmdiri(struct gfs2_inode *dip, struct qstr *name,
1389 if (error) 1388 if (error)
1390 return error; 1389 return error;
1391 1390
1392 dotname.len = 1; 1391 gfs2_str2qstr(&dotname, ".");
1393 dotname.name = ".";
1394 dotname.hash = gfs2_disk_hash(dotname.name, dotname.len);
1395 error = gfs2_dir_del(ip, &dotname); 1392 error = gfs2_dir_del(ip, &dotname);
1396 if (error) 1393 if (error)
1397 return error; 1394 return error;
@@ -1487,10 +1484,7 @@ int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
1487 struct qstr dotdot; 1484 struct qstr dotdot;
1488 int error = 0; 1485 int error = 0;
1489 1486
1490 memset(&dotdot, 0, sizeof(struct qstr)); 1487 gfs2_str2qstr(&dotdot, "..");
1491 dotdot.name = "..";
1492 dotdot.len = 2;
1493 dotdot.hash = gfs2_disk_hash(dotdot.name, dotdot.len);
1494 1488
1495 igrab(dir); 1489 igrab(dir);
1496 1490
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index e6a84f7a9b71..16c14441a371 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -13,6 +13,7 @@
13#include <linux/completion.h> 13#include <linux/completion.h>
14#include <linux/buffer_head.h> 14#include <linux/buffer_head.h>
15#include <linux/gfs2_ondisk.h> 15#include <linux/gfs2_ondisk.h>
16#include <linux/crc32.h>
16#include <asm/semaphore.h> 17#include <asm/semaphore.h>
17 18
18#include "gfs2.h" 19#include "gfs2.h"
@@ -24,18 +25,13 @@
24#include "lops.h" 25#include "lops.h"
25#include "meta_io.h" 26#include "meta_io.h"
26#include "util.h" 27#include "util.h"
28#include "dir.h"
27 29
28#define PULL 1 30#define PULL 1
29 31
30static void do_lock_wait(struct gfs2_sbd *sdp, wait_queue_head_t *wq,
31 atomic_t *a)
32{
33 wait_event(*wq, atomic_read(a) ? 0 : 1);
34}
35
36static void lock_for_trans(struct gfs2_sbd *sdp) 32static void lock_for_trans(struct gfs2_sbd *sdp)
37{ 33{
38 do_lock_wait(sdp, &sdp->sd_log_trans_wq, &sdp->sd_log_flush_count); 34 wait_event(sdp->sd_log_trans_wq, atomic_read(&sdp->sd_log_flush_count) ? 0 : 1);
39 atomic_inc(&sdp->sd_log_trans_count); 35 atomic_inc(&sdp->sd_log_trans_count);
40} 36}
41 37
@@ -49,7 +45,7 @@ static void unlock_from_trans(struct gfs2_sbd *sdp)
49static void gfs2_lock_for_flush(struct gfs2_sbd *sdp) 45static void gfs2_lock_for_flush(struct gfs2_sbd *sdp)
50{ 46{
51 atomic_inc(&sdp->sd_log_flush_count); 47 atomic_inc(&sdp->sd_log_flush_count);
52 do_lock_wait(sdp, &sdp->sd_log_flush_wq, &sdp->sd_log_trans_count); 48 wait_event(sdp->sd_log_flush_wq, atomic_read(&sdp->sd_log_trans_count) ? 0 : 1);
53} 49}
54 50
55static void gfs2_unlock_from_flush(struct gfs2_sbd *sdp) 51static void gfs2_unlock_from_flush(struct gfs2_sbd *sdp)
@@ -191,37 +187,19 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail)
191 187
192int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) 188int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
193{ 189{
194 LIST_HEAD(list);
195 unsigned int try = 0; 190 unsigned int try = 0;
196 191
197 if (gfs2_assert_warn(sdp, blks) || 192 if (gfs2_assert_warn(sdp, blks) ||
198 gfs2_assert_warn(sdp, blks <= sdp->sd_jdesc->jd_blocks)) 193 gfs2_assert_warn(sdp, blks <= sdp->sd_jdesc->jd_blocks))
199 return -EINVAL; 194 return -EINVAL;
200 195
196 mutex_lock(&sdp->sd_log_reserve_mutex);
201 for (;;) { 197 for (;;) {
202 gfs2_log_lock(sdp); 198 gfs2_log_lock(sdp);
203 if (list_empty(&list)) {
204 list_add_tail(&list, &sdp->sd_log_blks_list);
205 while (sdp->sd_log_blks_list.next != &list) {
206 DECLARE_WAITQUEUE(__wait_chan, current);
207 set_current_state(TASK_UNINTERRUPTIBLE);
208 add_wait_queue(&sdp->sd_log_blks_wait,
209 &__wait_chan);
210 gfs2_log_unlock(sdp);
211 schedule();
212 gfs2_log_lock(sdp);
213 remove_wait_queue(&sdp->sd_log_blks_wait,
214 &__wait_chan);
215 set_current_state(TASK_RUNNING);
216 }
217 }
218 /* Never give away the last block so we can
219 always pull the tail if we need to. */
220 if (sdp->sd_log_blks_free > blks) { 199 if (sdp->sd_log_blks_free > blks) {
221 sdp->sd_log_blks_free -= blks; 200 sdp->sd_log_blks_free -= blks;
222 list_del(&list);
223 gfs2_log_unlock(sdp); 201 gfs2_log_unlock(sdp);
224 wake_up(&sdp->sd_log_blks_wait); 202 mutex_unlock(&sdp->sd_log_reserve_mutex);
225 break; 203 break;
226 } 204 }
227 205
diff --git a/fs/gfs2/ops_dentry.c b/fs/gfs2/ops_dentry.c
index b54608f9df50..958371076093 100644
--- a/fs/gfs2/ops_dentry.c
+++ b/fs/gfs2/ops_dentry.c
@@ -14,6 +14,7 @@
14#include <linux/buffer_head.h> 14#include <linux/buffer_head.h>
15#include <linux/smp_lock.h> 15#include <linux/smp_lock.h>
16#include <linux/gfs2_ondisk.h> 16#include <linux/gfs2_ondisk.h>
17#include <linux/crc32.h>
17#include <asm/semaphore.h> 18#include <asm/semaphore.h>
18 19
19#include "gfs2.h" 20#include "gfs2.h"
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c
index b27bce74a795..be16c68263d1 100644
--- a/fs/gfs2/ops_export.c
+++ b/fs/gfs2/ops_export.c
@@ -13,6 +13,7 @@
13#include <linux/completion.h> 13#include <linux/completion.h>
14#include <linux/buffer_head.h> 14#include <linux/buffer_head.h>
15#include <linux/gfs2_ondisk.h> 15#include <linux/gfs2_ondisk.h>
16#include <linux/crc32.h>
16#include <asm/semaphore.h> 17#include <asm/semaphore.h>
17 18
18#include "gfs2.h" 19#include "gfs2.h"
@@ -153,7 +154,7 @@ static int gfs2_get_name(struct dentry *parent, char *name,
153 if (error) 154 if (error)
154 return error; 155 return error;
155 156
156 error = gfs2_dir_read(dip, &offset, &gnfd, get_name_filldir); 157 error = gfs2_dir_read(dir, &offset, &gnfd, get_name_filldir);
157 158
158 gfs2_glock_dq_uninit(&gh); 159 gfs2_glock_dq_uninit(&gh);
159 160
@@ -165,12 +166,11 @@ static int gfs2_get_name(struct dentry *parent, char *name,
165 166
166static struct dentry *gfs2_get_parent(struct dentry *child) 167static struct dentry *gfs2_get_parent(struct dentry *child)
167{ 168{
168 struct qstr dotdot = { .name = "..", .len = 2 }; 169 struct qstr dotdot;
169 struct inode *inode; 170 struct inode *inode;
170 struct dentry *dentry; 171 struct dentry *dentry;
171 172
172 dotdot.hash = gfs2_disk_hash(dotdot.name, dotdot.len); 173 gfs2_str2qstr(&dotdot, "..");
173
174 inode = gfs2_lookupi(child->d_inode, &dotdot, 1, NULL); 174 inode = gfs2_lookupi(child->d_inode, &dotdot, 1, NULL);
175 175
176 if (!inode) 176 if (!inode)
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index 6333a14cf77a..ac8e1238cb6f 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -19,6 +19,8 @@
19#include <linux/smp_lock.h> 19#include <linux/smp_lock.h>
20#include <linux/fs.h> 20#include <linux/fs.h>
21#include <linux/gfs2_ondisk.h> 21#include <linux/gfs2_ondisk.h>
22#include <linux/ext2_fs.h>
23#include <linux/crc32.h>
22#include <asm/semaphore.h> 24#include <asm/semaphore.h>
23#include <asm/uaccess.h> 25#include <asm/uaccess.h>
24 26
@@ -39,6 +41,7 @@
39#include "rgrp.h" 41#include "rgrp.h"
40#include "trans.h" 42#include "trans.h"
41#include "util.h" 43#include "util.h"
44#include "eaops.h"
42 45
43/* "bad" is for NFS support */ 46/* "bad" is for NFS support */
44struct filldir_bad_entry { 47struct filldir_bad_entry {
@@ -357,7 +360,8 @@ static int filldir_reg_func(void *opaque, const char *name, unsigned int length,
357 360
358static int readdir_reg(struct file *file, void *dirent, filldir_t filldir) 361static int readdir_reg(struct file *file, void *dirent, filldir_t filldir)
359{ 362{
360 struct gfs2_inode *dip = file->f_mapping->host->u.generic_ip; 363 struct inode *dir = file->f_mapping->host;
364 struct gfs2_inode *dip = dir->u.generic_ip;
361 struct filldir_reg fdr; 365 struct filldir_reg fdr;
362 struct gfs2_holder d_gh; 366 struct gfs2_holder d_gh;
363 uint64_t offset = file->f_pos; 367 uint64_t offset = file->f_pos;
@@ -375,7 +379,7 @@ static int readdir_reg(struct file *file, void *dirent, filldir_t filldir)
375 return error; 379 return error;
376 } 380 }
377 381
378 error = gfs2_dir_read(dip, &offset, &fdr, filldir_reg_func); 382 error = gfs2_dir_read(dir, &offset, &fdr, filldir_reg_func);
379 383
380 gfs2_glock_dq_uninit(&d_gh); 384 gfs2_glock_dq_uninit(&d_gh);
381 385
@@ -446,7 +450,8 @@ static int filldir_bad_func(void *opaque, const char *name, unsigned int length,
446 450
447static int readdir_bad(struct file *file, void *dirent, filldir_t filldir) 451static int readdir_bad(struct file *file, void *dirent, filldir_t filldir)
448{ 452{
449 struct gfs2_inode *dip = file->f_mapping->host->u.generic_ip; 453 struct inode *dir = file->f_mapping->host;
454 struct gfs2_inode *dip = dir->u.generic_ip;
450 struct gfs2_sbd *sdp = dip->i_sbd; 455 struct gfs2_sbd *sdp = dip->i_sbd;
451 struct filldir_reg fdr; 456 struct filldir_reg fdr;
452 unsigned int entries, size; 457 unsigned int entries, size;
@@ -479,7 +484,7 @@ static int readdir_bad(struct file *file, void *dirent, filldir_t filldir)
479 goto out; 484 goto out;
480 } 485 }
481 486
482 error = gfs2_dir_read(dip, &offset, fdb, filldir_bad_func); 487 error = gfs2_dir_read(dir, &offset, fdb, filldir_bad_func);
483 488
484 gfs2_glock_dq_uninit(&d_gh); 489 gfs2_glock_dq_uninit(&d_gh);
485 490
@@ -531,6 +536,210 @@ static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir)
531 return error; 536 return error;
532} 537}
533 538
539const struct gfs2_flag_eattr {
540 u32 flag;
541 u32 ext2;
542} gfs2_flag_eattrs[] = {
543 {
544 .flag = GFS2_DIF_IMMUTABLE,
545 .ext2 = EXT2_IMMUTABLE_FL,
546 }, {
547 .flag = GFS2_DIF_APPENDONLY,
548 .ext2 = EXT2_APPEND_FL,
549 }, {
550 .flag = GFS2_DIF_JDATA,
551 .ext2 = EXT2_JOURNAL_DATA_FL,
552 }, {
553 .flag = GFS2_DIF_EXHASH,
554 .ext2 = EXT2_INDEX_FL,
555 }, {
556 .flag = GFS2_DIF_EA_INDIRECT,
557 }, {
558 .flag = GFS2_DIF_DIRECTIO,
559 }, {
560 .flag = GFS2_DIF_NOATIME,
561 .ext2 = EXT2_NOATIME_FL,
562 }, {
563 .flag = GFS2_DIF_SYNC,
564 .ext2 = EXT2_SYNC_FL,
565 }, {
566 .flag = GFS2_DIF_SYSTEM,
567 }, {
568 .flag = GFS2_DIF_TRUNC_IN_PROG,
569 }, {
570 .flag = GFS2_DIF_INHERIT_JDATA,
571 }, {
572 .flag = GFS2_DIF_INHERIT_DIRECTIO,
573 }, {
574 },
575};
576
577static const struct gfs2_flag_eattr *get_by_ext2(u32 ext2)
578{
579 const struct gfs2_flag_eattr *p = gfs2_flag_eattrs;
580 for(; p->flag; p++) {
581 if (ext2 == p->ext2)
582 return p;
583 }
584 return NULL;
585}
586
587static const struct gfs2_flag_eattr *get_by_gfs2(u32 gfs2)
588{
589 const struct gfs2_flag_eattr *p = gfs2_flag_eattrs;
590 for(; p->flag; p++) {
591 if (gfs2 == p->flag)
592 return p;
593 }
594 return NULL;
595}
596
597static u32 gfs2_flags_to_ext2(u32 gfs2)
598{
599 const struct gfs2_flag_eattr *ea;
600 u32 ext2 = 0;
601 u32 mask = 1;
602
603 for(; mask != 0; mask <<=1) {
604 if (mask & gfs2) {
605 ea = get_by_gfs2(mask);
606 if (ea)
607 ext2 |= ea->ext2;
608 }
609 }
610 return ext2;
611}
612
613static int gfs2_flags_from_ext2(u32 *gfs2, u32 ext2)
614{
615 const struct gfs2_flag_eattr *ea;
616 u32 mask = 1;
617
618 for(; mask != 0; mask <<= 1) {
619 if (mask & ext2) {
620 ea = get_by_ext2(mask);
621 if (ea == NULL)
622 return -EINVAL;
623 *gfs2 |= ea->flag;
624 }
625 }
626 return 0;
627}
628
629static int get_ext2_flags(struct inode *inode, u32 __user *ptr)
630{
631 struct gfs2_inode *ip = inode->u.generic_ip;
632 struct gfs2_holder gh;
633 int error;
634 u32 ext2;
635
636 gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
637 error = gfs2_glock_nq_m_atime(1, &gh);
638 if (error)
639 return error;
640
641 ext2 = gfs2_flags_to_ext2(ip->i_di.di_flags);
642 if (put_user(ext2, ptr))
643 error = -EFAULT;
644
645 gfs2_glock_dq_m(1, &gh);
646 gfs2_holder_uninit(&gh);
647 return error;
648}
649
650/* Flags that can be set by user space */
651#define GFS2_FLAGS_USER_SET (GFS2_DIF_JDATA| \
652 GFS2_DIF_DIRECTIO| \
653 GFS2_DIF_IMMUTABLE| \
654 GFS2_DIF_APPENDONLY| \
655 GFS2_DIF_NOATIME| \
656 GFS2_DIF_SYNC| \
657 GFS2_DIF_SYSTEM| \
658 GFS2_DIF_INHERIT_DIRECTIO| \
659 GFS2_DIF_INHERIT_JDATA)
660
661/**
662 * gfs2_set_flags - set flags on an inode
663 * @inode: The inode
664 * @flags: The flags to set
665 * @mask: Indicates which flags are valid
666 *
667 */
668static int gfs2_set_flags(struct inode *inode, u32 flags, u32 mask)
669{
670 struct gfs2_inode *ip = inode->u.generic_ip;
671 struct buffer_head *bh;
672 struct gfs2_holder gh;
673 int error;
674 u32 new_flags;
675
676 gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
677 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
678 if (error)
679 return error;
680
681 new_flags = (ip->i_di.di_flags & ~mask) | (flags & mask);
682 if ((new_flags ^ flags) == 0)
683 goto out;
684
685 error = -EINVAL;
686 if ((new_flags ^ flags) & ~GFS2_FLAGS_USER_SET)
687 goto out;
688
689 if (S_ISDIR(inode->i_mode)) {
690 if ((new_flags ^ flags) & (GFS2_DIF_JDATA | GFS2_DIF_DIRECTIO))
691 goto out;
692 } else if (S_ISREG(inode->i_mode)) {
693 if ((new_flags ^ flags) & (GFS2_DIF_INHERIT_DIRECTIO|
694 GFS2_DIF_INHERIT_JDATA))
695 goto out;
696 } else
697 goto out;
698
699 error = -EPERM;
700 if (IS_IMMUTABLE(inode) && (new_flags & GFS2_DIF_IMMUTABLE))
701 goto out;
702 if (IS_APPEND(inode) && (new_flags & GFS2_DIF_APPENDONLY))
703 goto out;
704 error = gfs2_repermission(inode, MAY_WRITE, NULL);
705 if (error)
706 goto out;
707
708 error = gfs2_meta_inode_buffer(ip, &bh);
709 if (error)
710 goto out;
711 gfs2_trans_add_bh(ip->i_gl, bh, 1);
712 ip->i_di.di_flags = new_flags;
713 gfs2_dinode_out(&ip->i_di, bh->b_data);
714 brelse(bh);
715out:
716 gfs2_glock_dq_uninit(&gh);
717 return error;
718}
719
720static int set_ext2_flags(struct inode *inode, u32 __user *ptr)
721{
722 u32 ext2, gfs2;
723 if (get_user(ext2, ptr))
724 return -EFAULT;
725 if (gfs2_flags_from_ext2(&gfs2, ext2))
726 return -EINVAL;
727 return gfs2_set_flags(inode, gfs2, ~0);
728}
729
730int gfs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
731 unsigned long arg)
732{
733 switch(cmd) {
734 case EXT2_IOC_GETFLAGS:
735 return get_ext2_flags(inode, (u32 __user *)arg);
736 case EXT2_IOC_SETFLAGS:
737 return set_ext2_flags(inode, (u32 __user *)arg);
738 }
739 return -ENOTTY;
740}
741
742
534/** 743/**
535 * gfs2_mmap - 744 * gfs2_mmap -
536 * @file: The file to map 745 * @file: The file to map
@@ -832,6 +1041,7 @@ struct file_operations gfs2_file_fops = {
832 .write = generic_file_write, 1041 .write = generic_file_write,
833 .writev = generic_file_writev, 1042 .writev = generic_file_writev,
834 .aio_write = generic_file_aio_write, 1043 .aio_write = generic_file_aio_write,
1044 .ioctl = gfs2_ioctl,
835 .mmap = gfs2_mmap, 1045 .mmap = gfs2_mmap,
836 .open = gfs2_open, 1046 .open = gfs2_open,
837 .release = gfs2_close, 1047 .release = gfs2_close,
@@ -843,6 +1053,7 @@ struct file_operations gfs2_file_fops = {
843 1053
844struct file_operations gfs2_dir_fops = { 1054struct file_operations gfs2_dir_fops = {
845 .readdir = gfs2_readdir, 1055 .readdir = gfs2_readdir,
1056 .ioctl = gfs2_ioctl,
846 .open = gfs2_open, 1057 .open = gfs2_open,
847 .release = gfs2_close, 1058 .release = gfs2_close,
848 .fsync = gfs2_fsync, 1059 .fsync = gfs2_fsync,
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 8d2c557b3ff4..2628bf326334 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -97,9 +97,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
97 INIT_LIST_HEAD(&sdp->sd_log_le_rg); 97 INIT_LIST_HEAD(&sdp->sd_log_le_rg);
98 INIT_LIST_HEAD(&sdp->sd_log_le_databuf); 98 INIT_LIST_HEAD(&sdp->sd_log_le_databuf);
99 99
100 INIT_LIST_HEAD(&sdp->sd_log_blks_list); 100 mutex_init(&sdp->sd_log_reserve_mutex);
101 init_waitqueue_head(&sdp->sd_log_blks_wait);
102
103 INIT_LIST_HEAD(&sdp->sd_ail1_list); 101 INIT_LIST_HEAD(&sdp->sd_ail1_list);
104 INIT_LIST_HEAD(&sdp->sd_ail2_list); 102 INIT_LIST_HEAD(&sdp->sd_ail2_list);
105 103
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index e8ab9d254b76..1e2b709711ae 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -18,6 +18,7 @@
18#include <linux/xattr.h> 18#include <linux/xattr.h>
19#include <linux/posix_acl.h> 19#include <linux/posix_acl.h>
20#include <linux/gfs2_ondisk.h> 20#include <linux/gfs2_ondisk.h>
21#include <linux/crc32.h>
21#include <asm/semaphore.h> 22#include <asm/semaphore.h>
22#include <asm/uaccess.h> 23#include <asm/uaccess.h>
23 24
@@ -417,18 +418,16 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
417 if (!gfs2_assert_withdraw(sdp, !error)) { 418 if (!gfs2_assert_withdraw(sdp, !error)) {
418 struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data; 419 struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data;
419 struct gfs2_dirent *dent = (struct gfs2_dirent *)(di+1); 420 struct gfs2_dirent *dent = (struct gfs2_dirent *)(di+1);
420 struct qstr str = { .name = ".", .len = 1 }; 421 struct qstr str;
421 str.hash = gfs2_disk_hash(str.name, str.len);
422 422
423 gfs2_str2qstr(&str, ".");
423 gfs2_trans_add_bh(ip->i_gl, dibh, 1); 424 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
424 gfs2_qstr2dirent(&str, GFS2_DIRENT_SIZE(str.len), dent); 425 gfs2_qstr2dirent(&str, GFS2_DIRENT_SIZE(str.len), dent);
425 dent->de_inum = di->di_num; /* already GFS2 endian */ 426 dent->de_inum = di->di_num; /* already GFS2 endian */
426 dent->de_type = DT_DIR; 427 dent->de_type = DT_DIR;
427 di->di_entries = cpu_to_be32(1); 428 di->di_entries = cpu_to_be32(1);
428 429
429 str.name = ".."; 430 gfs2_str2qstr(&str, "..");
430 str.len = 2;
431 str.hash = gfs2_disk_hash(str.name, str.len);
432 dent = (struct gfs2_dirent *)((char*)dent + GFS2_DIRENT_SIZE(1)); 431 dent = (struct gfs2_dirent *)((char*)dent + GFS2_DIRENT_SIZE(1));
433 gfs2_qstr2dirent(&str, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent); 432 gfs2_qstr2dirent(&str, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent);
434 433
@@ -772,9 +771,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
772 771
773 if (dir_rename) { 772 if (dir_rename) {
774 struct qstr name; 773 struct qstr name;
775 name.len = 2; 774 gfs2_str2qstr(&name, "..");
776 name.name = "..";
777 name.hash = gfs2_disk_hash(name.name, name.len);
778 775
779 error = gfs2_change_nlink(ndip, +1); 776 error = gfs2_change_nlink(ndip, +1);
780 if (error) 777 if (error)
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index 2df450e2f433..6c7e2e880e32 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -13,6 +13,7 @@
13#include <linux/completion.h> 13#include <linux/completion.h>
14#include <linux/buffer_head.h> 14#include <linux/buffer_head.h>
15#include <linux/gfs2_ondisk.h> 15#include <linux/gfs2_ondisk.h>
16#include <linux/crc32.h>
16#include <asm/semaphore.h> 17#include <asm/semaphore.h>
17 18
18#include "gfs2.h" 19#include "gfs2.h"
@@ -27,6 +28,7 @@
27#include "recovery.h" 28#include "recovery.h"
28#include "super.h" 29#include "super.h"
29#include "util.h" 30#include "util.h"
31#include "dir.h"
30 32
31int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk, 33int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk,
32 struct buffer_head **bh) 34 struct buffer_head **bh)
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 71cca7629403..a4da649d086f 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -12,6 +12,7 @@
12#include <linux/spinlock.h> 12#include <linux/spinlock.h>
13#include <linux/completion.h> 13#include <linux/completion.h>
14#include <linux/buffer_head.h> 14#include <linux/buffer_head.h>
15#include <linux/crc32.h>
15#include <linux/gfs2_ondisk.h> 16#include <linux/gfs2_ondisk.h>
16#include <asm/semaphore.h> 17#include <asm/semaphore.h>
17 18
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c
index 8b22fa91bd14..7cd9e25639c4 100644
--- a/fs/gfs2/util.c
+++ b/fs/gfs2/util.c
@@ -28,11 +28,6 @@ kmem_cache_t *gfs2_glock_cachep __read_mostly;
28kmem_cache_t *gfs2_inode_cachep __read_mostly; 28kmem_cache_t *gfs2_inode_cachep __read_mostly;
29kmem_cache_t *gfs2_bufdata_cachep __read_mostly; 29kmem_cache_t *gfs2_bufdata_cachep __read_mostly;
30 30
31uint32_t gfs2_disk_hash(const char *data, int len)
32{
33 return crc32_le(0xFFFFFFFF, data, len) ^ 0xFFFFFFFF;
34}
35
36void gfs2_assert_i(struct gfs2_sbd *sdp) 31void gfs2_assert_i(struct gfs2_sbd *sdp)
37{ 32{
38 printk(KERN_EMERG "GFS2: fsid=%s: fatal assertion failed\n", 33 printk(KERN_EMERG "GFS2: fsid=%s: fatal assertion failed\n",
diff --git a/fs/gfs2/util.h b/fs/gfs2/util.h
index 8d6eba3bdf0a..addbe304993e 100644
--- a/fs/gfs2/util.h
+++ b/fs/gfs2/util.h
@@ -10,8 +10,6 @@
10#ifndef __UTIL_DOT_H__ 10#ifndef __UTIL_DOT_H__
11#define __UTIL_DOT_H__ 11#define __UTIL_DOT_H__
12 12
13uint32_t gfs2_disk_hash(const char *data, int len);
14
15 13
16#define fs_printk(level, fs, fmt, arg...) \ 14#define fs_printk(level, fs, fmt, arg...) \
17 printk(level "GFS2: fsid=%s: " fmt , (fs)->sd_fsname , ## arg) 15 printk(level "GFS2: fsid=%s: " fmt , (fs)->sd_fsname , ## arg)