From e6b4f8da3a88457148038bc952043e99a7fdba64 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 6 Dec 2006 20:33:14 -0800 Subject: [PATCH] slab: remove SLAB_NOFS SLAB_NOFS is an alias of GFP_NOFS. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/ext3') diff --git a/fs/ext3/super.c b/fs/ext3/super.c index afc2d4f42d77..0cf633f0cfa3 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -445,7 +445,7 @@ static struct inode *ext3_alloc_inode(struct super_block *sb) { struct ext3_inode_info *ei; - ei = kmem_cache_alloc(ext3_inode_cachep, SLAB_NOFS); + ei = kmem_cache_alloc(ext3_inode_cachep, GFP_NOFS); if (!ei) return NULL; #ifdef CONFIG_EXT3_FS_POSIX_ACL -- cgit v1.2.1 From e18b890bb0881bbab6f4f1a6cd20d9c60d66b003 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 6 Dec 2006 20:33:20 -0800 Subject: [PATCH] slab: remove kmem_cache_t Replace all uses of kmem_cache_t with struct kmem_cache. The patch was generated using the following script: #!/bin/sh # # Replace one string by another in all the kernel sources. # set -e for file in `find * -name "*.c" -o -name "*.h"|xargs grep -l $1`; do quilt add $file sed -e "1,\$s/$1/$2/g" $file >/tmp/$$ mv /tmp/$$ $file quilt refresh done The script was run like this sh replace kmem_cache_t "struct kmem_cache" Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/super.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/ext3') diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 0cf633f0cfa3..9856565d4ddc 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -436,7 +436,7 @@ static void ext3_put_super (struct super_block * sb) return; } -static kmem_cache_t *ext3_inode_cachep; +static struct kmem_cache *ext3_inode_cachep; /* * Called inside transaction, so use GFP_NOFS @@ -462,7 +462,7 @@ static void ext3_destroy_inode(struct inode *inode) kmem_cache_free(ext3_inode_cachep, EXT3_I(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct ext3_inode_info *ei = (struct ext3_inode_info *) foo; -- cgit v1.2.1 From 50ee0a32b192902e32a2b596df7ec3496c4bf485 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Wed, 6 Dec 2006 20:35:28 -0800 Subject: [PATCH] ext3: fsid for statvfs Update ext3_statfs to return an FSID that is a 64 bit XOR of the 128 bit filesystem UUID as suggested by Andreas Dilger. See the following Bugzilla entry for details: http://bugzilla.kernel.org/show_bug.cgi?id=136 Cc: Andreas Dilger Cc: Stephen Tweedie Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/super.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'fs/ext3') diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 9856565d4ddc..8ab198133357 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -2387,6 +2387,7 @@ static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf) struct ext3_super_block *es = sbi->s_es; ext3_fsblk_t overhead; int i; + u64 fsid; if (test_opt (sb, MINIX_DF)) overhead = 0; @@ -2433,6 +2434,10 @@ static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf) buf->f_files = le32_to_cpu(es->s_inodes_count); buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter); buf->f_namelen = EXT3_NAME_LEN; + fsid = le64_to_cpup((void *)es->s_uuid) ^ + le64_to_cpup((void *)es->s_uuid + sizeof(u64)); + buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL; + buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL; return 0; } -- cgit v1.2.1 From ed2908f31398049c4371de9b100700e80704e95f Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Wed, 6 Dec 2006 20:36:16 -0800 Subject: [PATCH] Remove superfluous lock_super() in extN xattr code lock_super() is unnecessary for setting super-block feature flags. Use the provided *_SET_COMPAT_FEATURE() macros as well. Signed-off-by: Andreas Gruenbacher Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/xattr.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'fs/ext3') diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index f86f2482f01d..99857a400f4b 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c @@ -459,14 +459,11 @@ static void ext3_xattr_update_super_block(handle_t *handle, if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR)) return; - lock_super(sb); if (ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh) == 0) { - EXT3_SB(sb)->s_es->s_feature_compat |= - cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR); + EXT3_SET_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR); sb->s_dirt = 1; ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); } - unlock_super(sb); } /* -- cgit v1.2.1 From 40b851348fe9bf49c26025b34261d25142269b60 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 6 Dec 2006 20:36:26 -0800 Subject: [PATCH] handle ext3 directory corruption better I've been using Steve Grubb's purely evil "fsfuzzer" tool, at http://people.redhat.com/sgrubb/files/fsfuzzer-0.4.tar.gz Basically it makes a filesystem, splats some random bits over it, then tries to mount it and do some simple filesystem actions. At best, the filesystem catches the corruption gracefully. At worst, things spin out of control. As you might guess, we found a couple places in ext3 where things spin out of control :) First, we had a corrupted directory that was never checked for consistency... it was corrupt, and pointed to another bad "entry" of length 0. The for() loop looped forever, since the length of ext3_next_entry(de) was 0, and we kept looking at the same pointer over and over and over and over... I modeled this check and subsequent action on what is done for other directory types in ext3_readdir... (adding this check adds some computational expense; I am testing a followup patch to reduce the number of times we check and re-check these directory entries, in all cases. Thanks for the idea, Andreas). Next we had a root directory inode which had a corrupted size, claimed to be > 200M on a 4M filesystem. There was only really 1 block in the directory, but because the size was so large, readdir kept coming back for more, spewing thousands of printk's along the way. Per Andreas' suggestion, if we're in this read error condition and we're trying to read an offset which is greater than i_blocks worth of bytes, stop trying, and break out of the loop. With these two changes fsfuzz test survives quite well on ext3. Signed-off-by: Eric Sandeen Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/dir.c | 3 +++ fs/ext3/namei.c | 9 +++++++++ 2 files changed, 12 insertions(+) (limited to 'fs/ext3') diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index d0b54f30b914..5a9313ecd4ef 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c @@ -154,6 +154,9 @@ static int ext3_readdir(struct file * filp, ext3_error (sb, "ext3_readdir", "directory #%lu contains a hole at offset %lu", inode->i_ino, (unsigned long)filp->f_pos); + /* corrupt size? Maybe no more blocks to read */ + if (filp->f_pos > inode->i_blocks << 9) + break; filp->f_pos += sb->s_blocksize - offset; continue; } diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 906731a20f1a..60d2f9dbdb00 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -552,6 +552,15 @@ static int htree_dirblock_to_tree(struct file *dir_file, dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(0)); for (; de < top; de = ext3_next_entry(de)) { + if (!ext3_check_dir_entry("htree_dirblock_to_tree", dir, de, bh, + (block<i_sb)) + +((char *)de - bh->b_data))) { + /* On error, skip the f_pos to the next block. */ + dir_file->f_pos = (dir_file->f_pos | + (dir->i_sb->s_blocksize - 1)) + 1; + brelse (bh); + return count; + } ext3fs_dirhash(de->name, de->name_len, hinfo); if ((hinfo->hash < start_hash) || ((hinfo->hash == start_hash) && -- cgit v1.2.1 From 3a229b39eb8497ae5f8077f81f7c8c3e1aacd624 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 6 Dec 2006 20:37:14 -0800 Subject: [PATCH] ext3: uninline large functions Saves nearly 4kbytes on x86. Cc: Arnaldo Carvalho de Melo Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/Makefile | 2 +- fs/ext3/ext3_jbd.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 fs/ext3/ext3_jbd.c (limited to 'fs/ext3') diff --git a/fs/ext3/Makefile b/fs/ext3/Makefile index 704cd44a40c2..e77766a8b3f0 100644 --- a/fs/ext3/Makefile +++ b/fs/ext3/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_EXT3_FS) += ext3.o ext3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ - ioctl.o namei.o super.o symlink.o hash.o resize.o + ioctl.o namei.o super.o symlink.o hash.o resize.o ext3_jbd.o ext3-$(CONFIG_EXT3_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o diff --git a/fs/ext3/ext3_jbd.c b/fs/ext3/ext3_jbd.c new file mode 100644 index 000000000000..e1f91fd26a93 --- /dev/null +++ b/fs/ext3/ext3_jbd.c @@ -0,0 +1,59 @@ +/* + * Interface between ext3 and JBD + */ + +#include + +int __ext3_journal_get_undo_access(const char *where, handle_t *handle, + struct buffer_head *bh) +{ + int err = journal_get_undo_access(handle, bh); + if (err) + ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err); + return err; +} + +int __ext3_journal_get_write_access(const char *where, handle_t *handle, + struct buffer_head *bh) +{ + int err = journal_get_write_access(handle, bh); + if (err) + ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err); + return err; +} + +int __ext3_journal_forget(const char *where, handle_t *handle, + struct buffer_head *bh) +{ + int err = journal_forget(handle, bh); + if (err) + ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err); + return err; +} + +int __ext3_journal_revoke(const char *where, handle_t *handle, + unsigned long blocknr, struct buffer_head *bh) +{ + int err = journal_revoke(handle, blocknr, bh); + if (err) + ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err); + return err; +} + +int __ext3_journal_get_create_access(const char *where, + handle_t *handle, struct buffer_head *bh) +{ + int err = journal_get_create_access(handle, bh); + if (err) + ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err); + return err; +} + +int __ext3_journal_dirty_metadata(const char *where, + handle_t *handle, struct buffer_head *bh) +{ + int err = journal_dirty_metadata(handle, bh); + if (err) + ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err); + return err; +} -- cgit v1.2.1 From e92a4d595b464c4aae64be39ca61a9ffe9c8b278 Mon Sep 17 00:00:00 2001 From: Andrey Savochkin Date: Wed, 6 Dec 2006 20:37:34 -0800 Subject: [PATCH] retries in ext3_prepare_write() violate ordering requirements In journal=ordered or journal=data mode retry in ext3_prepare_write() breaks the requirements of journaling of data with respect to metadata. The fix is to call commit_write to commit allocated zero blocks before retry. Signed-off-by: Kirill Korotaev Cc: Ingo Molnar Cc: Ken Chen Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/inode.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 75 insertions(+), 10 deletions(-) (limited to 'fs/ext3') diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 03ba5bcab186..beaf25f5112f 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -1148,37 +1148,102 @@ static int do_journal_get_write_access(handle_t *handle, return ext3_journal_get_write_access(handle, bh); } +/* + * The idea of this helper function is following: + * if prepare_write has allocated some blocks, but not all of them, the + * transaction must include the content of the newly allocated blocks. + * This content is expected to be set to zeroes by block_prepare_write(). + * 2006/10/14 SAW + */ +static int ext3_prepare_failure(struct file *file, struct page *page, + unsigned from, unsigned to) +{ + struct address_space *mapping; + struct buffer_head *bh, *head, *next; + unsigned block_start, block_end; + unsigned blocksize; + int ret; + handle_t *handle = ext3_journal_current_handle(); + + mapping = page->mapping; + if (ext3_should_writeback_data(mapping->host)) { + /* optimization: no constraints about data */ +skip: + return ext3_journal_stop(handle); + } + + head = page_buffers(page); + blocksize = head->b_size; + for ( bh = head, block_start = 0; + bh != head || !block_start; + block_start = block_end, bh = next) + { + next = bh->b_this_page; + block_end = block_start + blocksize; + if (block_end <= from) + continue; + if (block_start >= to) { + block_start = to; + break; + } + if (!buffer_mapped(bh)) + /* prepare_write failed on this bh */ + break; + if (ext3_should_journal_data(mapping->host)) { + ret = do_journal_get_write_access(handle, bh); + if (ret) { + ext3_journal_stop(handle); + return ret; + } + } + /* + * block_start here becomes the first block where the current iteration + * of prepare_write failed. + */ + } + if (block_start <= from) + goto skip; + + /* commit allocated and zeroed buffers */ + return mapping->a_ops->commit_write(file, page, from, block_start); +} + static int ext3_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) { struct inode *inode = page->mapping->host; - int ret, needed_blocks = ext3_writepage_trans_blocks(inode); + int ret, ret2; + int needed_blocks = ext3_writepage_trans_blocks(inode); handle_t *handle; int retries = 0; retry: handle = ext3_journal_start(inode, needed_blocks); - if (IS_ERR(handle)) { - ret = PTR_ERR(handle); - goto out; - } + if (IS_ERR(handle)) + return PTR_ERR(handle); if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode)) ret = nobh_prepare_write(page, from, to, ext3_get_block); else ret = block_prepare_write(page, from, to, ext3_get_block); if (ret) - goto prepare_write_failed; + goto failure; if (ext3_should_journal_data(inode)) { ret = walk_page_buffers(handle, page_buffers(page), from, to, NULL, do_journal_get_write_access); + if (ret) + /* fatal error, just put the handle and return */ + journal_stop(handle); } -prepare_write_failed: - if (ret) - ext3_journal_stop(handle); + return ret; + +failure: + ret2 = ext3_prepare_failure(file, page, from, to); + if (ret2 < 0) + return ret2; if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries)) goto retry; -out: + /* retry number exceeded, or other error like -EDQUOT */ return ret; } -- cgit v1.2.1 From 2bd94bd79e5bfa217714f78e5d6d7b6517ca546f Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Wed, 6 Dec 2006 20:38:18 -0800 Subject: [PATCH] ext3: fix reservation extension Hugh Dickins wrote: > Not found anything relevant, but I keep noticing these lines > in ext2_try_to_allocate_with_rsv(), ext3 and ext4 similar: > > } else if (grp_goal > 0 && > (my_rsv->rsv_end - grp_goal + 1) < *count) > try_to_extend_reservation(my_rsv, sb, > *count-my_rsv->rsv_end + grp_goal - 1); > > They're wrong, a no-op in most groups, aren't they? rsv_end is an > absolute block number, whereas grp_goal is group-relative, so the > calculation ought to bring in group_first_block? Or I'm confused. > Signed-off-by: Mingming Cao Cc: "linux-ext4@vger.kernel.org" Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/balloc.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'fs/ext3') diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index b41a7d7e20f0..f96c40a90e2e 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -1307,10 +1307,14 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, if (!goal_in_my_reservation(&my_rsv->rsv_window, grp_goal, group, sb)) grp_goal = -1; - } else if (grp_goal > 0 && - (my_rsv->rsv_end-grp_goal+1) < *count) - try_to_extend_reservation(my_rsv, sb, - *count-my_rsv->rsv_end + grp_goal - 1); + } else if (grp_goal > 0) { + int curr = my_rsv->rsv_end - + (grp_goal + group_first_block) + 1; + + if (curr < *count) + try_to_extend_reservation(my_rsv, sb, + *count - curr); + } if ((my_rsv->rsv_start > group_last_block) || (my_rsv->rsv_end < group_first_block)) { -- cgit v1.2.1 From a8f48a95619cbce8f85423480e7d0a1bf971a62b Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 6 Dec 2006 20:40:13 -0800 Subject: [PATCH] ext3/4: don't do orphan processing on readonly devices If you do something like: # touch foo # tail -f foo & # rm foo # # you'll panic, because ext3/4 tries to do orphan list processing on the readonly snapshot device, and: kernel: journal commit I/O error kernel: Assertion failure in journal_flush_Rsmp_e2f189ce() at journal.c:1356: "!journal->j_checkpoint_transactions" kernel: Kernel panic: Fatal exception for a truly readonly underlying device, it's reasonable and necessary to just skip orphan list processing. Signed-off-by: Eric Sandeen Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/super.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'fs/ext3') diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 8ab198133357..580b8a6ca979 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -1264,6 +1264,12 @@ static void ext3_orphan_cleanup (struct super_block * sb, return; } + if (bdev_read_only(sb->s_bdev)) { + printk(KERN_ERR "EXT3-fs: write access " + "unavailable, skipping orphan cleanup.\n"); + return; + } + if (EXT3_SB(sb)->s_mount_state & EXT3_ERROR_FS) { if (es->s_last_orphan) jbd_debug(1, "Errors on filesystem, " -- cgit v1.2.1 From ef5036782e619ab394daaec5c00876fa6b17d7a1 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 6 Dec 2006 20:41:23 -0800 Subject: [PATCH] ext3 balloc: reset windowsz when full ext3_new_blocks should reset the reservation window size to 0 when squeezing the last blocks out of an almost full filesystem, so the retry doesn't skip any groups with less than half that free, reporting ENOSPC too soon. Signed-off-by: Mingming Cao Signed-off-by: Hugh Dickins Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/balloc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/ext3') diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index f96c40a90e2e..db8ca34d102a 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -1552,6 +1552,7 @@ retry_alloc: */ if (my_rsv) { my_rsv = NULL; + windowsz = 0; group_no = goal_group; goto retry_alloc; } -- cgit v1.2.1 From 1650242324a0c19d629a8be0d5a8ecdc174d31f8 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 6 Dec 2006 20:41:25 -0800 Subject: [PATCH] ext3 balloc: fix off-by-one against grp_goal grp_goal 0 is a genuine goal (unlike -1), so ext3_try_to_allocate_with_rsv should treat it as such. Signed-off-by: Mingming Cao Signed-off-by: Hugh Dickins Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/balloc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/ext3') diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index db8ca34d102a..0706a45d3c07 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -1271,7 +1271,7 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, } /* * grp_goal is a group relative block number (if there is a goal) - * 0 < grp_goal < EXT3_BLOCKS_PER_GROUP(sb) + * 0 <= grp_goal < EXT3_BLOCKS_PER_GROUP(sb) * first block is a filesystem wide block number * first block is the block number of the first block in this group */ @@ -1307,7 +1307,7 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, if (!goal_in_my_reservation(&my_rsv->rsv_window, grp_goal, group, sb)) grp_goal = -1; - } else if (grp_goal > 0) { + } else if (grp_goal >= 0) { int curr = my_rsv->rsv_end - (grp_goal + group_first_block) + 1; -- cgit v1.2.1 From ff50dc562bf6de00fec264b11531e2745209ba12 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 6 Dec 2006 20:41:25 -0800 Subject: [PATCH] ext3 balloc: fix off-by-one against rsv_end rsv_end is the last block within the reservation, so alloc_new_reservation should accept start_block == rsv_end as success. Signed-off-by: Mingming Cao Signed-off-by: Hugh Dickins Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/balloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/ext3') diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 0706a45d3c07..57cf47a9420e 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -1148,7 +1148,7 @@ retry: * check if the first free block is within the * free space we just reserved */ - if (start_block >= my_rsv->rsv_start && start_block < my_rsv->rsv_end) + if (start_block >= my_rsv->rsv_start && start_block <= my_rsv->rsv_end) return 0; /* success */ /* * if the first free bit we found is out of the reservable space -- cgit v1.2.1 From c56d2561f7189762c4fce854630d4f7f6d64ccee Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 6 Dec 2006 20:41:27 -0800 Subject: [PATCH] ext3 balloc: say rb_entry not list_entry The reservations tree is an rb_tree not a list, so it's less confusing to use rb_entry() than list_entry() - though they're both just container_of(). Signed-off-by: Mingming Cao Signed-off-by: Hugh Dickins Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/balloc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs/ext3') diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 57cf47a9420e..03d39b6fd305 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -144,7 +144,7 @@ restart: printk("Block Allocation Reservation Windows Map (%s):\n", fn); while (n) { - rsv = list_entry(n, struct ext3_reserve_window_node, rsv_node); + rsv = rb_entry(n, struct ext3_reserve_window_node, rsv_node); if (verbose) printk("reservation window 0x%p " "start: %lu, end: %lu\n", @@ -949,7 +949,7 @@ static int find_next_reservable_window( prev = rsv; next = rb_next(&rsv->rsv_node); - rsv = list_entry(next,struct ext3_reserve_window_node,rsv_node); + rsv = rb_entry(next,struct ext3_reserve_window_node,rsv_node); /* * Reached the last reservation, we can just append to the @@ -1193,7 +1193,7 @@ static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv, if (!next) my_rsv->rsv_end += size; else { - next_rsv = list_entry(next, struct ext3_reserve_window_node, rsv_node); + next_rsv = rb_entry(next, struct ext3_reserve_window_node, rsv_node); if ((next_rsv->rsv_start - my_rsv->rsv_end - 1) >= size) my_rsv->rsv_end += size; -- cgit v1.2.1 From 2823b5535efad71e950ef50c2ce5f9e4dbaedc17 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 6 Dec 2006 20:41:28 -0800 Subject: [PATCH] ext3 balloc: use io_error label ext3_new_blocks has a nice io_error label for setting -EIO, so goto that in the one place that doesn't already use it. Signed-off-by: Mingming Cao Signed-off-by: Hugh Dickins Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/balloc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'fs/ext3') diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 03d39b6fd305..5a2c198762f0 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -1515,10 +1515,8 @@ retry_alloc: if (group_no >= ngroups) group_no = 0; gdp = ext3_get_group_desc(sb, group_no, &gdp_bh); - if (!gdp) { - *errp = -EIO; - goto out; - } + if (!gdp) + goto io_error; free_blocks = le16_to_cpu(gdp->bg_free_blocks_count); /* * skip this group if the number of -- cgit v1.2.1 From 7d1c520bb57e4b5e94ec937c13553dccf473341b Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 6 Dec 2006 20:41:30 -0800 Subject: [PATCH] ext3 balloc: fix _with_rsv freeze Port fix to the off-by-one in find_next_usable_block's memscan from ext2 to ext3; but it didn't cause a serious problem for ext3 because the additional ext3_test_allocatable check rescued it from the error. Signed-off-by: Mingming Cao Signed-off-by: Hugh Dickins Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/balloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/ext3') diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 5a2c198762f0..22161740ba29 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -730,7 +730,7 @@ find_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh, here = 0; p = ((char *)bh->b_data) + (here >> 3); - r = memscan(p, 0, (maxblocks - here + 7) >> 3); + r = memscan(p, 0, ((maxblocks + 7) >> 3) - (here >> 3)); next = (r - ((char *)bh->b_data)) << 3; if (next < maxblocks && next >= start && ext3_test_allocatable(next, bh)) -- cgit v1.2.1 From fe21a69389165b9641a8d0b89e00a71c4e5f5d59 Mon Sep 17 00:00:00 2001 From: "Josef \"Jeff\" Sipek" Date: Fri, 8 Dec 2006 02:36:38 -0800 Subject: [PATCH] ext3: change uses of f_{dentry, vfsmnt} to use f_path Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the ext3 filesystem. Signed-off-by: Josef "Jeff" Sipek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/dir.c | 8 ++++---- fs/ext3/file.c | 2 +- fs/ext3/ioctl.c | 2 +- fs/ext3/namei.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'fs/ext3') diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index 5a9313ecd4ef..665adee99b31 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c @@ -103,7 +103,7 @@ static int ext3_readdir(struct file * filp, struct ext3_dir_entry_2 *de; struct super_block *sb; int err; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; int ret = 0; sb = inode->i_sb; @@ -122,7 +122,7 @@ static int ext3_readdir(struct file * filp, * We don't set the inode dirty flag since it's not * critical that it get flushed back to the disk. */ - EXT3_I(filp->f_dentry->d_inode)->i_flags &= ~EXT3_INDEX_FL; + EXT3_I(filp->f_path.dentry->d_inode)->i_flags &= ~EXT3_INDEX_FL; } #endif stored = 0; @@ -402,7 +402,7 @@ static int call_filldir(struct file * filp, void * dirent, { struct dir_private_info *info = filp->private_data; loff_t curr_pos; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct super_block * sb; int error; @@ -432,7 +432,7 @@ static int ext3_dx_readdir(struct file * filp, void * dirent, filldir_t filldir) { struct dir_private_info *info = filp->private_data; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; struct fname *fname; int ret; diff --git a/fs/ext3/file.c b/fs/ext3/file.c index e96c388047e0..881f6365c41a 100644 --- a/fs/ext3/file.c +++ b/fs/ext3/file.c @@ -52,7 +52,7 @@ ext3_file_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { struct file *file = iocb->ki_filp; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; ssize_t ret; int err; diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c index 12daa6869572..9b8090d94e6c 100644 --- a/fs/ext3/ioctl.c +++ b/fs/ext3/ioctl.c @@ -257,7 +257,7 @@ flags_err: #ifdef CONFIG_COMPAT long ext3_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int ret; /* These are just misnamed, they actually get/put from/to user an int */ diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 60d2f9dbdb00..4df39c4315e1 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -602,7 +602,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash, start_minor_hash)); - dir = dir_file->f_dentry->d_inode; + dir = dir_file->f_path.dentry->d_inode; if (!(EXT3_I(dir)->i_flags & EXT3_INDEX_FL)) { hinfo.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version; hinfo.seed = EXT3_SB(dir->i_sb)->s_hash_seed; @@ -613,7 +613,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, } hinfo.hash = start_hash; hinfo.minor_hash = 0; - frame = dx_probe(NULL, dir_file->f_dentry->d_inode, &hinfo, frames, &err); + frame = dx_probe(NULL, dir_file->f_path.dentry->d_inode, &hinfo, frames, &err); if (!frame) return err; -- cgit v1.2.1 From f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 8 Dec 2006 02:37:49 -0800 Subject: [PATCH] LOG2: Implement a general integer log2 facility in the kernel This facility provides three entry points: ilog2() Log base 2 of unsigned long ilog2_u32() Log base 2 of u32 ilog2_u64() Log base 2 of u64 These facilities can either be used inside functions on dynamic data: int do_something(long q) { ...; y = ilog2(x) ...; } Or can be used to statically initialise global variables with constant values: unsigned n = ilog2(27); When performing static initialisation, the compiler will report "error: initializer element is not constant" if asked to take a log of zero or of something not reducible to a constant. They treat negative numbers as unsigned. When not dealing with a constant, they fall back to using fls() which permits them to use arch-specific log calculation instructions - such as BSR on x86/x86_64 or SCAN on FRV - if available. [akpm@osdl.org: MMC fix] Signed-off-by: David Howells Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Herbert Xu Cc: David Howells Cc: Wojtek Kaniewski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/super.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'fs/ext3') diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 580b8a6ca979..b34886734a44 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -1347,8 +1347,6 @@ static void ext3_orphan_cleanup (struct super_block * sb, sb->s_flags = s_flags; /* Restore MS_RDONLY status */ } -#define log2(n) ffz(~(n)) - /* * Maximal file size. There is a direct, and {,double-,triple-}indirect * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks. @@ -1597,8 +1595,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) sbi->s_desc_per_block = blocksize / sizeof(struct ext3_group_desc); sbi->s_sbh = bh; sbi->s_mount_state = le16_to_cpu(es->s_state); - sbi->s_addr_per_block_bits = log2(EXT3_ADDR_PER_BLOCK(sb)); - sbi->s_desc_per_block_bits = log2(EXT3_DESC_PER_BLOCK(sb)); + sbi->s_addr_per_block_bits = ilog2(EXT3_ADDR_PER_BLOCK(sb)); + sbi->s_desc_per_block_bits = ilog2(EXT3_DESC_PER_BLOCK(sb)); for (i=0; i < 4; i++) sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); sbi->s_def_hash_version = es->s_def_hash_version; -- cgit v1.2.1