diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2006-11-17 12:27:44 -0500 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-11-30 10:36:20 -0500 |
commit | 5e7d65cd9d3819512b059f4260de0119b985454c (patch) | |
tree | f6e09c9eff9dfa4197cc6da8d153f314737026db /fs/gfs2/dir.c | |
parent | dcd2479959c79d44f5dd77e71672e70f1f8b1f06 (diff) |
[GFS2] Make sentinel dirents compatible with gfs1
When deleting directory entries, we set the inum.no_addr to zero
in a dirent when its the first dirent in a block and thus cannot
be merged into the previous dirent as is the usual case. In gfs1,
inum.no_formal_ino was used instead.
This patch changes gfs2 to set both inum.no_addr and inum.no_formal_ino
to zero. It also changes the test from just looking at inum.no_addr to
look at both inum.no_addr and inum.no_formal_ino and a sentinel is
now considered to be a dirent in which _either_ (or both) of them
is set to zero.
This resolves Red Hat bugzillas: #215809, #211465
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/dir.c')
-rw-r--r-- | fs/gfs2/dir.c | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index a2923fb91bba..0fdcb7713cd9 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -340,10 +340,15 @@ fail: | |||
340 | return (copied) ? copied : error; | 340 | return (copied) ? copied : error; |
341 | } | 341 | } |
342 | 342 | ||
343 | static inline int gfs2_dirent_sentinel(const struct gfs2_dirent *dent) | ||
344 | { | ||
345 | return dent->de_inum.no_addr == 0 || dent->de_inum.no_formal_ino == 0; | ||
346 | } | ||
347 | |||
343 | static inline int __gfs2_dirent_find(const struct gfs2_dirent *dent, | 348 | static inline int __gfs2_dirent_find(const struct gfs2_dirent *dent, |
344 | const struct qstr *name, int ret) | 349 | const struct qstr *name, int ret) |
345 | { | 350 | { |
346 | if (dent->de_inum.no_addr != 0 && | 351 | if (!gfs2_dirent_sentinel(dent) && |
347 | be32_to_cpu(dent->de_hash) == name->hash && | 352 | be32_to_cpu(dent->de_hash) == name->hash && |
348 | be16_to_cpu(dent->de_name_len) == name->len && | 353 | be16_to_cpu(dent->de_name_len) == name->len && |
349 | memcmp(dent+1, name->name, name->len) == 0) | 354 | memcmp(dent+1, name->name, name->len) == 0) |
@@ -388,7 +393,7 @@ static int gfs2_dirent_find_space(const struct gfs2_dirent *dent, | |||
388 | unsigned actual = GFS2_DIRENT_SIZE(be16_to_cpu(dent->de_name_len)); | 393 | unsigned actual = GFS2_DIRENT_SIZE(be16_to_cpu(dent->de_name_len)); |
389 | unsigned totlen = be16_to_cpu(dent->de_rec_len); | 394 | unsigned totlen = be16_to_cpu(dent->de_rec_len); |
390 | 395 | ||
391 | if (!dent->de_inum.no_addr) | 396 | if (gfs2_dirent_sentinel(dent)) |
392 | actual = GFS2_DIRENT_SIZE(0); | 397 | actual = GFS2_DIRENT_SIZE(0); |
393 | if (totlen - actual >= required) | 398 | if (totlen - actual >= required) |
394 | return 1; | 399 | return 1; |
@@ -405,7 +410,7 @@ static int gfs2_dirent_gather(const struct gfs2_dirent *dent, | |||
405 | void *opaque) | 410 | void *opaque) |
406 | { | 411 | { |
407 | struct dirent_gather *g = opaque; | 412 | struct dirent_gather *g = opaque; |
408 | if (dent->de_inum.no_addr) { | 413 | if (!gfs2_dirent_sentinel(dent)) { |
409 | g->pdent[g->offset++] = dent; | 414 | g->pdent[g->offset++] = dent; |
410 | } | 415 | } |
411 | return 0; | 416 | return 0; |
@@ -433,10 +438,10 @@ static int gfs2_check_dirent(struct gfs2_dirent *dent, unsigned int offset, | |||
433 | if (unlikely(offset + size > len)) | 438 | if (unlikely(offset + size > len)) |
434 | goto error; | 439 | goto error; |
435 | msg = "zero inode number"; | 440 | msg = "zero inode number"; |
436 | if (unlikely(!first && !dent->de_inum.no_addr)) | 441 | if (unlikely(!first && gfs2_dirent_sentinel(dent))) |
437 | goto error; | 442 | goto error; |
438 | msg = "name length is greater than space in dirent"; | 443 | msg = "name length is greater than space in dirent"; |
439 | if (dent->de_inum.no_addr && | 444 | if (!gfs2_dirent_sentinel(dent) && |
440 | unlikely(sizeof(struct gfs2_dirent)+be16_to_cpu(dent->de_name_len) > | 445 | unlikely(sizeof(struct gfs2_dirent)+be16_to_cpu(dent->de_name_len) > |
441 | size)) | 446 | size)) |
442 | goto error; | 447 | goto error; |
@@ -598,7 +603,7 @@ static int dirent_next(struct gfs2_inode *dip, struct buffer_head *bh, | |||
598 | return ret; | 603 | return ret; |
599 | 604 | ||
600 | /* Only the first dent could ever have de_inum.no_addr == 0 */ | 605 | /* Only the first dent could ever have de_inum.no_addr == 0 */ |
601 | if (!tmp->de_inum.no_addr) { | 606 | if (gfs2_dirent_sentinel(tmp)) { |
602 | gfs2_consist_inode(dip); | 607 | gfs2_consist_inode(dip); |
603 | return -EIO; | 608 | return -EIO; |
604 | } | 609 | } |
@@ -621,7 +626,7 @@ static void dirent_del(struct gfs2_inode *dip, struct buffer_head *bh, | |||
621 | { | 626 | { |
622 | u16 cur_rec_len, prev_rec_len; | 627 | u16 cur_rec_len, prev_rec_len; |
623 | 628 | ||
624 | if (!cur->de_inum.no_addr) { | 629 | if (gfs2_dirent_sentinel(cur)) { |
625 | gfs2_consist_inode(dip); | 630 | gfs2_consist_inode(dip); |
626 | return; | 631 | return; |
627 | } | 632 | } |
@@ -633,7 +638,8 @@ static void dirent_del(struct gfs2_inode *dip, struct buffer_head *bh, | |||
633 | out the inode number and return. */ | 638 | out the inode number and return. */ |
634 | 639 | ||
635 | if (!prev) { | 640 | if (!prev) { |
636 | cur->de_inum.no_addr = 0; /* No endianess worries */ | 641 | cur->de_inum.no_addr = 0; |
642 | cur->de_inum.no_formal_ino = 0; | ||
637 | return; | 643 | return; |
638 | } | 644 | } |
639 | 645 | ||
@@ -664,7 +670,7 @@ static struct gfs2_dirent *gfs2_init_dirent(struct inode *inode, | |||
664 | struct gfs2_dirent *ndent; | 670 | struct gfs2_dirent *ndent; |
665 | unsigned offset = 0, totlen; | 671 | unsigned offset = 0, totlen; |
666 | 672 | ||
667 | if (dent->de_inum.no_addr) | 673 | if (!gfs2_dirent_sentinel(dent)) |
668 | offset = GFS2_DIRENT_SIZE(be16_to_cpu(dent->de_name_len)); | 674 | offset = GFS2_DIRENT_SIZE(be16_to_cpu(dent->de_name_len)); |
669 | totlen = be16_to_cpu(dent->de_rec_len); | 675 | totlen = be16_to_cpu(dent->de_rec_len); |
670 | BUG_ON(offset + name->len > totlen); | 676 | BUG_ON(offset + name->len > totlen); |
@@ -1002,7 +1008,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) | |||
1002 | if (dirent_next(dip, obh, &next)) | 1008 | if (dirent_next(dip, obh, &next)) |
1003 | next = NULL; | 1009 | next = NULL; |
1004 | 1010 | ||
1005 | if (dent->de_inum.no_addr && | 1011 | if (!gfs2_dirent_sentinel(dent) && |
1006 | be32_to_cpu(dent->de_hash) < divider) { | 1012 | be32_to_cpu(dent->de_hash) < divider) { |
1007 | struct qstr str; | 1013 | struct qstr str; |
1008 | str.name = (char*)(dent+1); | 1014 | str.name = (char*)(dent+1); |