diff options
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/bmap.c | 1 | ||||
-rw-r--r-- | fs/gfs2/dir.c | 412 | ||||
-rw-r--r-- | fs/gfs2/dir.h | 15 | ||||
-rw-r--r-- | fs/gfs2/incore.h | 3 | ||||
-rw-r--r-- | fs/gfs2/inode.c | 14 | ||||
-rw-r--r-- | fs/gfs2/log.c | 34 | ||||
-rw-r--r-- | fs/gfs2/ops_dentry.c | 1 | ||||
-rw-r--r-- | fs/gfs2/ops_export.c | 8 | ||||
-rw-r--r-- | fs/gfs2/ops_file.c | 219 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 4 | ||||
-rw-r--r-- | fs/gfs2/ops_inode.c | 13 | ||||
-rw-r--r-- | fs/gfs2/recovery.c | 2 | ||||
-rw-r--r-- | fs/gfs2/super.c | 1 | ||||
-rw-r--r-- | fs/gfs2/util.c | 5 | ||||
-rw-r--r-- | fs/gfs2/util.h | 2 |
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 | ||
346 | typedef int (*gfs2_dscan_t)(const struct gfs2_dirent *dent, | 347 | typedef int (*gfs2_dscan_t)(const struct gfs2_dirent *dent, |
347 | const struct qstr *name); | 348 | const struct qstr *name, |
349 | void *opaque); | ||
348 | 350 | ||
349 | static inline int __gfs2_dirent_find(const struct gfs2_dirent *dent, | 351 | static 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 | ||
360 | static int gfs2_dirent_find(const struct gfs2_dirent *dent, | 362 | static 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 | ||
366 | static int gfs2_dirent_prev(const struct gfs2_dirent *dent, | 369 | static 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 | */ |
376 | static int gfs2_dirent_last(const struct gfs2_dirent *dent, | 380 | static 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 | ||
386 | static int gfs2_dirent_find_space(const struct gfs2_dirent *dent, | 391 | static 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 | ||
406 | struct dirent_gather { | ||
407 | const struct gfs2_dirent **pdent; | ||
408 | unsigned offset; | ||
409 | }; | ||
410 | |||
411 | static 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 | ||
434 | static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode, | 458 | static 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; | ||
476 | wrong_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 | ||
482 | static 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 | ||
490 | wrong_type: | ||
491 | printk(KERN_WARNING "gfs2_scan_dirent: %p wrong block type %u\n", scan, | ||
492 | be16_to_cpu(h->mh_type)); | ||
493 | consist_inode: | 529 | consist_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); |
755 | got_dent: | 792 | got_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 | ||
1155 | static int do_filldir_main(struct gfs2_inode *dip, uint64_t *offset, | 1188 | static 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 | /** | 1252 | static 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 | |||
1232 | static 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 | |||
1288 | static 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 | 1315 | out_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 | 1319 | out: | |
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 | ||
1415 | static int dir_e_read(struct gfs2_inode *dip, uint64_t *offset, void *opaque, | 1333 | static 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: | 1385 | out: |
1484 | kfree(lp); | 1386 | kfree(lp); |
1485 | 1387 | if (error > 0) | |
1388 | error = 0; | ||
1486 | return error; | 1389 | return error; |
1487 | } | 1390 | } |
1488 | 1391 | ||
1489 | static int dir_l_read(struct gfs2_inode *dip, uint64_t *offset, void *opaque, | 1392 | int 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); | ||
1431 | out: | ||
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 | ||
1727 | int 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, | |||
32 | int gfs2_dir_add(struct inode *inode, const struct qstr *filename, | 32 | int 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); |
34 | int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename); | 34 | int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename); |
35 | int gfs2_dir_read(struct gfs2_inode *dip, uint64_t * offset, void *opaque, | 35 | int gfs2_dir_read(struct inode *inode, uint64_t * offset, void *opaque, |
36 | gfs2_filldir_t filldir); | 36 | gfs2_filldir_t filldir); |
37 | int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, | 37 | int 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, | |||
44 | int gfs2_dir_get_buffer(struct gfs2_inode *ip, uint64_t block, int new, | 44 | int 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 | ||
47 | static inline uint32_t gfs2_disk_hash(const char *data, int len) | ||
48 | { | ||
49 | return crc32_le(0xFFFFFFFF, data, len) ^ 0xFFFFFFFF; | ||
50 | } | ||
51 | |||
52 | |||
53 | static 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 */ |
48 | static inline void gfs2_qstr2dirent(const struct qstr *name, u16 reclen, struct gfs2_dirent *dent) | 61 | static 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) | |||
701 | struct inode *gfs2_lookup_simple(struct inode *dip, const char *name) | 702 | struct 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 | ||
30 | static 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 | |||
36 | static void lock_for_trans(struct gfs2_sbd *sdp) | 32 | static 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) | |||
49 | static void gfs2_lock_for_flush(struct gfs2_sbd *sdp) | 45 | static 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 | ||
55 | static void gfs2_unlock_from_flush(struct gfs2_sbd *sdp) | 51 | static 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 | ||
192 | int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) | 188 | int 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 | ||
166 | static struct dentry *gfs2_get_parent(struct dentry *child) | 167 | static 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 */ |
44 | struct filldir_bad_entry { | 47 | struct filldir_bad_entry { |
@@ -357,7 +360,8 @@ static int filldir_reg_func(void *opaque, const char *name, unsigned int length, | |||
357 | 360 | ||
358 | static int readdir_reg(struct file *file, void *dirent, filldir_t filldir) | 361 | static 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 | ||
447 | static int readdir_bad(struct file *file, void *dirent, filldir_t filldir) | 451 | static 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 | ||
539 | const 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 | |||
577 | static 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 | |||
587 | static 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 | |||
597 | static 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 | |||
613 | static 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 | |||
629 | static 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 | */ | ||
668 | static 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); | ||
715 | out: | ||
716 | gfs2_glock_dq_uninit(&gh); | ||
717 | return error; | ||
718 | } | ||
719 | |||
720 | static 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 | |||
730 | int 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 | ||
844 | struct file_operations gfs2_dir_fops = { | 1054 | struct 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 | ||
31 | int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk, | 33 | int 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; | |||
28 | kmem_cache_t *gfs2_inode_cachep __read_mostly; | 28 | kmem_cache_t *gfs2_inode_cachep __read_mostly; |
29 | kmem_cache_t *gfs2_bufdata_cachep __read_mostly; | 29 | kmem_cache_t *gfs2_bufdata_cachep __read_mostly; |
30 | 30 | ||
31 | uint32_t gfs2_disk_hash(const char *data, int len) | ||
32 | { | ||
33 | return crc32_le(0xFFFFFFFF, data, len) ^ 0xFFFFFFFF; | ||
34 | } | ||
35 | |||
36 | void gfs2_assert_i(struct gfs2_sbd *sdp) | 31 | void 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 | ||
13 | uint32_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) |