diff options
author | David Woodhouse <dwmw2@infradead.org> | 2006-10-01 18:55:53 +0200 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2006-10-01 18:55:53 +0200 |
commit | 8a84fc15ae5cafcc366dd85cf8e1ab2040679abc (patch) | |
tree | 5d8dce194c9667fa92e9ec9f545cec867a9a1e0d /fs/ext3 | |
parent | [MTD ONENAND] Check OneNAND lock scheme & all block unlock command support (diff) | |
parent | Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/agpgart (diff) | |
download | linux-8a84fc15ae5cafcc366dd85cf8e1ab2040679abc.tar.xz linux-8a84fc15ae5cafcc366dd85cf8e1ab2040679abc.zip |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Manually resolve conflict in include/mtd/Kbuild
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'fs/ext3')
-rw-r--r-- | fs/ext3/acl.c | 6 | ||||
-rw-r--r-- | fs/ext3/balloc.c | 350 | ||||
-rw-r--r-- | fs/ext3/bitmap.c | 2 | ||||
-rw-r--r-- | fs/ext3/dir.c | 22 | ||||
-rw-r--r-- | fs/ext3/file.c | 12 | ||||
-rw-r--r-- | fs/ext3/fsync.c | 6 | ||||
-rw-r--r-- | fs/ext3/hash.c | 8 | ||||
-rw-r--r-- | fs/ext3/ialloc.c | 55 | ||||
-rw-r--r-- | fs/ext3/inode.c | 82 | ||||
-rw-r--r-- | fs/ext3/ioctl.c | 55 | ||||
-rw-r--r-- | fs/ext3/namei.c | 75 | ||||
-rw-r--r-- | fs/ext3/resize.c | 42 | ||||
-rw-r--r-- | fs/ext3/super.c | 110 | ||||
-rw-r--r-- | fs/ext3/xattr.c | 16 |
14 files changed, 561 insertions, 280 deletions
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c index 0d21d558b87a..1e5038d9a01b 100644 --- a/fs/ext3/acl.c +++ b/fs/ext3/acl.c @@ -90,8 +90,8 @@ ext3_acl_to_disk(const struct posix_acl *acl, size_t *size) size_t n; *size = ext3_acl_size(acl->a_count); - ext_acl = (ext3_acl_header *)kmalloc(sizeof(ext3_acl_header) + - acl->a_count * sizeof(ext3_acl_entry), GFP_KERNEL); + ext_acl = kmalloc(sizeof(ext3_acl_header) + acl->a_count * + sizeof(ext3_acl_entry), GFP_KERNEL); if (!ext_acl) return ERR_PTR(-ENOMEM); ext_acl->a_version = cpu_to_le32(EXT3_ACL_VERSION); @@ -258,7 +258,7 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type, default: return -EINVAL; } - if (acl) { + if (acl) { value = ext3_acl_to_disk(acl, &size); if (IS_ERR(value)) return (int)PTR_ERR(value); diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 063d994bda0b..b41a7d7e20f0 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -38,6 +38,13 @@ #define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1) +/** + * ext3_get_group_desc() -- load group descriptor from disk + * @sb: super block + * @block_group: given block group + * @bh: pointer to the buffer head to store the block + * group descriptor + */ struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb, unsigned int block_group, struct buffer_head ** bh) @@ -73,8 +80,12 @@ struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb, return desc + offset; } -/* - * Read the bitmap for a given block_group, reading into the specified +/** + * read_block_bitmap() + * @sb: super block + * @block_group: given block group + * + * Read the bitmap for a given block_group, reading into the specified * slot in the superblock's bitmap cache. * * Return buffer_head on success or NULL in case of failure. @@ -103,15 +114,22 @@ error_out: * Operations include: * dump, find, add, remove, is_empty, find_next_reservable_window, etc. * - * We use sorted double linked list for the per-filesystem reservation - * window list. (like in vm_region). + * We use a red-black tree to represent per-filesystem reservation + * windows. + * + */ + +/** + * __rsv_window_dump() -- Dump the filesystem block allocation reservation map + * @rb_root: root of per-filesystem reservation rb tree + * @verbose: verbose mode + * @fn: function which wishes to dump the reservation map * - * Initially, we keep those small operations in the abstract functions, - * so later if we need a better searching tree than double linked-list, - * we could easily switch to that without changing too much - * code. + * If verbose is turned on, it will print the whole block reservation + * windows(start, end). Otherwise, it will only print out the "bad" windows, + * those windows that overlap with their immediate neighbors. */ -#if 0 +#if 1 static void __rsv_window_dump(struct rb_root *root, int verbose, const char *fn) { @@ -129,7 +147,7 @@ restart: rsv = list_entry(n, struct ext3_reserve_window_node, rsv_node); if (verbose) printk("reservation window 0x%p " - "start: %d, end: %d\n", + "start: %lu, end: %lu\n", rsv, rsv->rsv_start, rsv->rsv_end); if (rsv->rsv_start && rsv->rsv_start >= rsv->rsv_end) { printk("Bad reservation %p (start >= end)\n", @@ -161,6 +179,22 @@ restart: #define rsv_window_dump(root, verbose) do {} while (0) #endif +/** + * goal_in_my_reservation() + * @rsv: inode's reservation window + * @grp_goal: given goal block relative to the allocation block group + * @group: the current allocation block group + * @sb: filesystem super block + * + * Test if the given goal block (group relative) is within the file's + * own block reservation window range. + * + * If the reservation window is outside the goal allocation group, return 0; + * grp_goal (given goal block) could be -1, which means no specific + * goal block. In this case, always return 1. + * If the goal block is within the reservation window, return 1; + * otherwise, return 0; + */ static int goal_in_my_reservation(struct ext3_reserve_window *rsv, ext3_grpblk_t grp_goal, unsigned int group, struct super_block * sb) @@ -168,7 +202,7 @@ goal_in_my_reservation(struct ext3_reserve_window *rsv, ext3_grpblk_t grp_goal, ext3_fsblk_t group_first_block, group_last_block; group_first_block = ext3_group_first_block_no(sb, group); - group_last_block = group_first_block + EXT3_BLOCKS_PER_GROUP(sb) - 1; + group_last_block = group_first_block + (EXT3_BLOCKS_PER_GROUP(sb) - 1); if ((rsv->_rsv_start > group_last_block) || (rsv->_rsv_end < group_first_block)) @@ -179,7 +213,11 @@ goal_in_my_reservation(struct ext3_reserve_window *rsv, ext3_grpblk_t grp_goal, return 1; } -/* +/** + * search_reserve_window() + * @rb_root: root of reservation tree + * @goal: target allocation block + * * Find the reserved window which includes the goal, or the previous one * if the goal is not in any window. * Returns NULL if there are no windows or if all windows start after the goal. @@ -216,6 +254,13 @@ search_reserve_window(struct rb_root *root, ext3_fsblk_t goal) return rsv; } +/** + * ext3_rsv_window_add() -- Insert a window to the block reservation rb tree. + * @sb: super block + * @rsv: reservation window to add + * + * Must be called with rsv_lock hold. + */ void ext3_rsv_window_add(struct super_block *sb, struct ext3_reserve_window_node *rsv) { @@ -236,14 +281,25 @@ void ext3_rsv_window_add(struct super_block *sb, p = &(*p)->rb_left; else if (start > this->rsv_end) p = &(*p)->rb_right; - else + else { + rsv_window_dump(root, 1); BUG(); + } } rb_link_node(node, parent, p); rb_insert_color(node, root); } +/** + * ext3_rsv_window_remove() -- unlink a window from the reservation rb tree + * @sb: super block + * @rsv: reservation window to remove + * + * Mark the block reservation window as not allocated, and unlink it + * from the filesystem reservation window rb tree. Must be called with + * rsv_lock hold. + */ static void rsv_window_remove(struct super_block *sb, struct ext3_reserve_window_node *rsv) { @@ -253,11 +309,39 @@ static void rsv_window_remove(struct super_block *sb, rb_erase(&rsv->rsv_node, &EXT3_SB(sb)->s_rsv_window_root); } +/* + * rsv_is_empty() -- Check if the reservation window is allocated. + * @rsv: given reservation window to check + * + * returns 1 if the end block is EXT3_RESERVE_WINDOW_NOT_ALLOCATED. + */ static inline int rsv_is_empty(struct ext3_reserve_window *rsv) { /* a valid reservation end block could not be 0 */ - return (rsv->_rsv_end == EXT3_RESERVE_WINDOW_NOT_ALLOCATED); + return rsv->_rsv_end == EXT3_RESERVE_WINDOW_NOT_ALLOCATED; } + +/** + * ext3_init_block_alloc_info() + * @inode: file inode structure + * + * Allocate and initialize the reservation window structure, and + * link the window to the ext3 inode structure at last + * + * The reservation window structure is only dynamically allocated + * and linked to ext3 inode the first time the open file + * needs a new block. So, before every ext3_new_block(s) call, for + * regular files, we should check whether the reservation window + * structure exists or not. In the latter case, this function is called. + * Fail to do so will result in block reservation being turned off for that + * open file. + * + * This function is called from ext3_get_blocks_handle(), also called + * when setting the reservation window size through ioctl before the file + * is open for write (needs block allocation). + * + * Needs truncate_mutex protection prior to call this function. + */ void ext3_init_block_alloc_info(struct inode *inode) { struct ext3_inode_info *ei = EXT3_I(inode); @@ -271,7 +355,7 @@ void ext3_init_block_alloc_info(struct inode *inode) rsv->rsv_start = EXT3_RESERVE_WINDOW_NOT_ALLOCATED; rsv->rsv_end = EXT3_RESERVE_WINDOW_NOT_ALLOCATED; - /* + /* * if filesystem is mounted with NORESERVATION, the goal * reservation window size is set to zero to indicate * block reservation is off @@ -287,6 +371,19 @@ void ext3_init_block_alloc_info(struct inode *inode) ei->i_block_alloc_info = block_i; } +/** + * ext3_discard_reservation() + * @inode: inode + * + * Discard(free) block reservation window on last file close, or truncate + * or at last iput(). + * + * It is being called in three cases: + * ext3_release_file(): last writer close the file + * ext3_clear_inode(): last iput(), when nobody link to this file. + * ext3_truncate(): when the block indirect map is about to change. + * + */ void ext3_discard_reservation(struct inode *inode) { struct ext3_inode_info *ei = EXT3_I(inode); @@ -306,7 +403,14 @@ void ext3_discard_reservation(struct inode *inode) } } -/* Free given blocks, update quota and i_blocks field */ +/** + * ext3_free_blocks_sb() -- Free given blocks and update quota + * @handle: handle to this transaction + * @sb: super block + * @block: start physcial block to free + * @count: number of blocks to free + * @pdquot_freed_blocks: pointer to quota + */ void ext3_free_blocks_sb(handle_t *handle, struct super_block *sb, ext3_fsblk_t block, unsigned long count, unsigned long *pdquot_freed_blocks) @@ -419,8 +523,8 @@ do_more: } /* @@@ This prevents newly-allocated data from being * freed and then reallocated within the same - * transaction. - * + * transaction. + * * Ideally we would want to allow that to happen, but to * do so requires making journal_forget() capable of * revoking the queued write of a data block, which @@ -433,7 +537,7 @@ do_more: * safe not to set the allocation bit in the committed * bitmap, because we know that there is no outstanding * activity on the buffer any more and so it is safe to - * reallocate it. + * reallocate it. */ BUFFER_TRACE(bitmap_bh, "set in b_committed_data"); J_ASSERT_BH(bitmap_bh, @@ -490,7 +594,13 @@ error_return: return; } -/* Free given blocks, update quota and i_blocks field */ +/** + * ext3_free_blocks() -- Free given blocks and update quota + * @handle: handle for this transaction + * @inode: inode + * @block: start physical block to free + * @count: number of blocks to count + */ void ext3_free_blocks(handle_t *handle, struct inode *inode, ext3_fsblk_t block, unsigned long count) { @@ -508,7 +618,11 @@ void ext3_free_blocks(handle_t *handle, struct inode *inode, return; } -/* +/** + * ext3_test_allocatable() + * @nr: given allocation block group + * @bh: bufferhead contains the bitmap of the given block group + * * For ext3 allocations, we must not reuse any blocks which are * allocated in the bitmap buffer's "last committed data" copy. This * prevents deletes from freeing up the page for reuse until we have @@ -518,7 +632,7 @@ void ext3_free_blocks(handle_t *handle, struct inode *inode, * data would allow the old block to be overwritten before the * transaction committed (because we force data to disk before commit). * This would lead to corruption if we crashed between overwriting the - * data and committing the delete. + * data and committing the delete. * * @@@ We may want to make this allocation behaviour conditional on * data-writes at some point, and disable it for metadata allocations or @@ -541,6 +655,16 @@ static int ext3_test_allocatable(ext3_grpblk_t nr, struct buffer_head *bh) return ret; } +/** + * bitmap_search_next_usable_block() + * @start: the starting block (group relative) of the search + * @bh: bufferhead contains the block group bitmap + * @maxblocks: the ending block (group relative) of the reservation + * + * The bitmap search --- search forward alternately through the actual + * bitmap on disk and the last-committed copy in journal, until we find a + * bit free in both bitmaps. + */ static ext3_grpblk_t bitmap_search_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh, ext3_grpblk_t maxblocks) @@ -548,11 +672,6 @@ bitmap_search_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh, ext3_grpblk_t next; struct journal_head *jh = bh2jh(bh); - /* - * The bitmap search --- search forward alternately through the actual - * bitmap and the last-committed copy until we find a bit free in - * both - */ while (start < maxblocks) { next = ext3_find_next_zero_bit(bh->b_data, maxblocks, start); if (next >= maxblocks) @@ -562,14 +681,20 @@ bitmap_search_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh, jbd_lock_bh_state(bh); if (jh->b_committed_data) start = ext3_find_next_zero_bit(jh->b_committed_data, - maxblocks, next); + maxblocks, next); jbd_unlock_bh_state(bh); } return -1; } -/* - * Find an allocatable block in a bitmap. We honour both the bitmap and +/** + * find_next_usable_block() + * @start: the starting block (group relative) to find next + * allocatable block in bitmap. + * @bh: bufferhead contains the block group bitmap + * @maxblocks: the ending block (group relative) for the search + * + * Find an allocatable block in a bitmap. We honor both the bitmap and * its last-committed copy (if that exists), and perform the "most * appropriate allocation" algorithm of looking for a free block near * the initial goal; then for a free byte somewhere in the bitmap; then @@ -584,7 +709,7 @@ find_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh, if (start > 0) { /* - * The goal was occupied; search forward for a free + * The goal was occupied; search forward for a free * block within the next XX blocks. * * end_goal is more or less random, but it has to be @@ -620,7 +745,11 @@ find_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh, return here; } -/* +/** + * claim_block() + * @block: the free block (group relative) to allocate + * @bh: the bufferhead containts the block group bitmap + * * We think we can allocate this block in this bitmap. Try to set the bit. * If that succeeds then check that nobody has allocated and then freed the * block since we saw that is was not marked in b_committed_data. If it _was_ @@ -646,7 +775,26 @@ claim_block(spinlock_t *lock, ext3_grpblk_t block, struct buffer_head *bh) return ret; } -/* +/** + * ext3_try_to_allocate() + * @sb: superblock + * @handle: handle to this transaction + * @group: given allocation block group + * @bitmap_bh: bufferhead holds the block bitmap + * @grp_goal: given target block within the group + * @count: target number of blocks to allocate + * @my_rsv: reservation window + * + * Attempt to allocate blocks within a give range. Set the range of allocation + * first, then find the first free bit(s) from the bitmap (within the range), + * and at last, allocate the blocks by claiming the found free bit as allocated. + * + * To set the range of this allocation: + * if there is a reservation window, only try to allocate block(s) from the + * file's own reservation window; + * Otherwise, the allocation range starts from the give goal block, ends at + * the block group's last block. + * * If we failed to allocate the desired block then we may end up crossing to a * new bitmap. In that case we must release write access to the old one via * ext3_journal_release_buffer(), else we'll run out of credits. @@ -703,7 +851,8 @@ repeat: } start = grp_goal; - if (!claim_block(sb_bgl_lock(EXT3_SB(sb), group), grp_goal, bitmap_bh)) { + if (!claim_block(sb_bgl_lock(EXT3_SB(sb), group), + grp_goal, bitmap_bh)) { /* * The block was allocated by another thread, or it was * allocated and then freed by another thread @@ -718,7 +867,8 @@ repeat: grp_goal++; while (num < *count && grp_goal < end && ext3_test_allocatable(grp_goal, bitmap_bh) - && claim_block(sb_bgl_lock(EXT3_SB(sb), group), grp_goal, bitmap_bh)) { + && claim_block(sb_bgl_lock(EXT3_SB(sb), group), + grp_goal, bitmap_bh)) { num++; grp_goal++; } @@ -730,12 +880,12 @@ fail_access: } /** - * find_next_reservable_window(): + * find_next_reservable_window(): * find a reservable space within the given range. * It does not allocate the reservation window for now: * alloc_new_reservation() will do the work later. * - * @search_head: the head of the searching list; + * @search_head: the head of the searching list; * This is not necessarily the list head of the whole filesystem * * We have both head and start_block to assist the search @@ -743,12 +893,12 @@ fail_access: * but we will shift to the place where start_block is, * then start from there, when looking for a reservable space. * - * @size: the target new reservation window size + * @size: the target new reservation window size * - * @group_first_block: the first block we consider to start + * @group_first_block: the first block we consider to start * the real search from * - * @last_block: + * @last_block: * the maximum block number that our goal reservable space * could start from. This is normally the last block in this * group. The search will end when we found the start of next @@ -756,10 +906,10 @@ fail_access: * This could handle the cross boundary reservation window * request. * - * basically we search from the given range, rather than the whole - * reservation double linked list, (start_block, last_block) - * to find a free region that is of my size and has not - * been reserved. + * basically we search from the given range, rather than the whole + * reservation double linked list, (start_block, last_block) + * to find a free region that is of my size and has not + * been reserved. * */ static int find_next_reservable_window( @@ -812,7 +962,7 @@ static int find_next_reservable_window( /* * Found a reserveable space big enough. We could * have a reservation across the group boundary here - */ + */ break; } } @@ -848,7 +998,7 @@ static int find_next_reservable_window( } /** - * alloc_new_reservation()--allocate a new reservation window + * alloc_new_reservation()--allocate a new reservation window * * To make a new reservation, we search part of the filesystem * reservation list (the list that inside the group). We try to @@ -897,7 +1047,7 @@ static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv, spinlock_t *rsv_lock = &EXT3_SB(sb)->s_rsv_window_lock; group_first_block = ext3_group_first_block_no(sb, group); - group_end_block = group_first_block + EXT3_BLOCKS_PER_GROUP(sb) - 1; + group_end_block = group_first_block + (EXT3_BLOCKS_PER_GROUP(sb) - 1); if (grp_goal < 0) start_block = group_first_block; @@ -929,9 +1079,10 @@ static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv, if ((my_rsv->rsv_alloc_hit > (my_rsv->rsv_end - my_rsv->rsv_start + 1) / 2)) { /* - * if we previously allocation hit ration is greater than half - * we double the size of reservation window next time - * otherwise keep the same + * if the previously allocation hit ratio is + * greater than 1/2, then we double the size of + * the reservation window the next time, + * otherwise we keep the same size window */ size = size * 2; if (size > EXT3_MAX_RESERVE_BLOCKS) @@ -1010,6 +1161,23 @@ retry: goto retry; } +/** + * try_to_extend_reservation() + * @my_rsv: given reservation window + * @sb: super block + * @size: the delta to extend + * + * Attempt to expand the reservation window large enough to have + * required number of free blocks + * + * Since ext3_try_to_allocate() will always allocate blocks within + * the reservation window range, if the window size is too small, + * multiple blocks allocation has to stop at the end of the reservation + * window. To make this more efficient, given the total number of + * blocks needed and the current size of the window, we try to + * expand the reservation window size if necessary on a best-effort + * basis before ext3_new_blocks() tries to allocate blocks, + */ static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv, struct super_block *sb, int size) { @@ -1035,7 +1203,17 @@ static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv, spin_unlock(rsv_lock); } -/* +/** + * ext3_try_to_allocate_with_rsv() + * @sb: superblock + * @handle: handle to this transaction + * @group: given allocation block group + * @bitmap_bh: bufferhead holds the block bitmap + * @grp_goal: given target block within the group + * @count: target number of blocks to allocate + * @my_rsv: reservation window + * @errp: pointer to store the error code + * * This is the main function used to allocate a new block and its reservation * window. * @@ -1051,9 +1229,7 @@ static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv, * reservation), and there are lots of free blocks, but they are all * being reserved. * - * We use a sorted double linked list for the per-filesystem reservation list. - * The insert, remove and find a free space(non-reserved) operations for the - * sorted double linked list should be fast. + * We use a red-black tree for the per-filesystem reservation list. * */ static ext3_grpblk_t @@ -1063,7 +1239,7 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, struct ext3_reserve_window_node * my_rsv, unsigned long *count, int *errp) { - ext3_fsblk_t group_first_block; + ext3_fsblk_t group_first_block, group_last_block; ext3_grpblk_t ret = 0; int fatal; unsigned long num = *count; @@ -1100,6 +1276,7 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, * first block is the block number of the first block in this group */ group_first_block = ext3_group_first_block_no(sb, group); + group_last_block = group_first_block + (EXT3_BLOCKS_PER_GROUP(sb) - 1); /* * Basically we will allocate a new block from inode's reservation @@ -1118,7 +1295,8 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, */ while (1) { if (rsv_is_empty(&my_rsv->rsv_window) || (ret < 0) || - !goal_in_my_reservation(&my_rsv->rsv_window, grp_goal, group, sb)) { + !goal_in_my_reservation(&my_rsv->rsv_window, + grp_goal, group, sb)) { if (my_rsv->rsv_goal_size < *count) my_rsv->rsv_goal_size = *count; ret = alloc_new_reservation(my_rsv, grp_goal, sb, @@ -1126,17 +1304,21 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, if (ret < 0) break; /* failed */ - if (!goal_in_my_reservation(&my_rsv->rsv_window, grp_goal, group, sb)) + 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) + } 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); - if ((my_rsv->rsv_start >= group_first_block + EXT3_BLOCKS_PER_GROUP(sb)) - || (my_rsv->rsv_end < group_first_block)) + if ((my_rsv->rsv_start > group_last_block) || + (my_rsv->rsv_end < group_first_block)) { + rsv_window_dump(&EXT3_SB(sb)->s_rsv_window_root, 1); BUG(); - ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, grp_goal, - &num, &my_rsv->rsv_window); + } + ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, + grp_goal, &num, &my_rsv->rsv_window); if (ret >= 0) { my_rsv->rsv_alloc_hit += num; *count = num; @@ -1161,6 +1343,12 @@ out: return ret; } +/** + * ext3_has_free_blocks() + * @sbi: in-core super block structure. + * + * Check if filesystem has at least 1 free block available for allocation. + */ static int ext3_has_free_blocks(struct ext3_sb_info *sbi) { ext3_fsblk_t free_blocks, root_blocks; @@ -1175,11 +1363,17 @@ static int ext3_has_free_blocks(struct ext3_sb_info *sbi) return 1; } -/* +/** + * ext3_should_retry_alloc() + * @sb: super block + * @retries number of attemps has been made + * * ext3_should_retry_alloc() is called when ENOSPC is returned, and if * it is profitable to retry the operation, this function will wait * for the current or commiting transaction to complete, and then * return TRUE. + * + * if the total number of retries exceed three times, return FALSE. */ int ext3_should_retry_alloc(struct super_block *sb, int *retries) { @@ -1191,13 +1385,19 @@ int ext3_should_retry_alloc(struct super_block *sb, int *retries) return journal_force_commit_nested(EXT3_SB(sb)->s_journal); } -/* - * ext3_new_block uses a goal block to assist allocation. If the goal is - * free, or there is a free block within 32 blocks of the goal, that block - * is allocated. Otherwise a forward search is made for a free block; within - * each block group the search first looks for an entire free byte in the block - * bitmap, and then for any free bit if that fails. - * This function also updates quota and i_blocks field. +/** + * ext3_new_blocks() -- core block(s) allocation function + * @handle: handle to this transaction + * @inode: file inode + * @goal: given target block(filesystem wide) + * @count: target number of blocks to allocate + * @errp: error code + * + * ext3_new_blocks uses a goal block to assist allocation. It tries to + * allocate block(s) from the block group contains the goal block first. If that + * fails, it will try to allocate block(s) from other block groups without + * any specific goal block. + * */ ext3_fsblk_t ext3_new_blocks(handle_t *handle, struct inode *inode, ext3_fsblk_t goal, unsigned long *count, int *errp) @@ -1303,7 +1503,7 @@ retry_alloc: smp_rmb(); /* - * Now search the rest of the groups. We assume that + * Now search the rest of the groups. We assume that * i and gdp correctly point to the last group visited. */ for (bgi = 0; bgi < ngroups; bgi++) { @@ -1428,7 +1628,7 @@ allocated: spin_lock(sb_bgl_lock(sbi, group_no)); gdp->bg_free_blocks_count = - cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - num); + cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)-num); spin_unlock(sb_bgl_lock(sbi, group_no)); percpu_counter_mod(&sbi->s_freeblocks_counter, -num); @@ -1471,6 +1671,12 @@ ext3_fsblk_t ext3_new_block(handle_t *handle, struct inode *inode, return ext3_new_blocks(handle, inode, goal, &count, errp); } +/** + * ext3_count_free_blocks() -- count filesystem free blocks + * @sb: superblock + * + * Adds up the number of free blocks from each block group. + */ ext3_fsblk_t ext3_count_free_blocks(struct super_block *sb) { ext3_fsblk_t desc_count; diff --git a/fs/ext3/bitmap.c b/fs/ext3/bitmap.c index ce4f82b9e528..b9176eed98d1 100644 --- a/fs/ext3/bitmap.c +++ b/fs/ext3/bitmap.c @@ -20,7 +20,7 @@ unsigned long ext3_count_free (struct buffer_head * map, unsigned int numchars) unsigned int i; unsigned long sum = 0; - if (!map) + if (!map) return (0); for (i = 0; i < numchars; i++) sum += nibblemap[map->b_data[i] & 0xf] + diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index fbb0d4ed07d4..d0b54f30b914 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c @@ -44,6 +44,9 @@ const struct file_operations ext3_dir_operations = { .read = generic_read_dir, .readdir = ext3_readdir, /* we take BKL. needed?*/ .ioctl = ext3_ioctl, /* BKL held */ +#ifdef CONFIG_COMPAT + .compat_ioctl = ext3_compat_ioctl, +#endif .fsync = ext3_sync_file, /* BKL held */ #ifdef CONFIG_EXT3_INDEX .release = ext3_release_dir, @@ -59,7 +62,7 @@ static unsigned char get_dtype(struct super_block *sb, int filetype) return (ext3_filetype_table[filetype]); } - + int ext3_check_dir_entry (const char * function, struct inode * dir, struct ext3_dir_entry_2 * de, @@ -67,7 +70,7 @@ int ext3_check_dir_entry (const char * function, struct inode * dir, unsigned long offset) { const char * error_msg = NULL; - const int rlen = le16_to_cpu(de->rec_len); + const int rlen = le16_to_cpu(de->rec_len); if (rlen < EXT3_DIR_REC_LEN(1)) error_msg = "rec_len is smaller than minimal"; @@ -162,7 +165,7 @@ revalidate: * to make sure. */ if (filp->f_version != inode->i_version) { for (i = 0; i < sb->s_blocksize && i < offset; ) { - de = (struct ext3_dir_entry_2 *) + de = (struct ext3_dir_entry_2 *) (bh->b_data + i); /* It's too expensive to do a full * dirent test each time round this @@ -181,7 +184,7 @@ revalidate: filp->f_version = inode->i_version; } - while (!error && filp->f_pos < inode->i_size + while (!error && filp->f_pos < inode->i_size && offset < sb->s_blocksize) { de = (struct ext3_dir_entry_2 *) (bh->b_data + offset); if (!ext3_check_dir_entry ("ext3_readdir", inode, de, @@ -229,7 +232,7 @@ out: /* * These functions convert from the major/minor hash to an f_pos * value. - * + * * Currently we only use major hash numer. This is unfortunate, but * on 32-bit machines, the same VFS interface is used for lseek and * llseek, so if we use the 64 bit offset, then the 32-bit versions of @@ -250,7 +253,7 @@ out: struct fname { __u32 hash; __u32 minor_hash; - struct rb_node rb_hash; + struct rb_node rb_hash; struct fname *next; __u32 inode; __u8 name_len; @@ -343,10 +346,9 @@ int ext3_htree_store_dirent(struct file *dir_file, __u32 hash, /* Create and allocate the fname structure */ len = sizeof(struct fname) + dirent->name_len + 1; - new_fn = kmalloc(len, GFP_KERNEL); + new_fn = kzalloc(len, GFP_KERNEL); if (!new_fn) return -ENOMEM; - memset(new_fn, 0, len); new_fn->hash = hash; new_fn->minor_hash = minor_hash; new_fn->inode = le32_to_cpu(dirent->inode); @@ -410,7 +412,7 @@ static int call_filldir(struct file * filp, void * dirent, curr_pos = hash2pos(fname->hash, fname->minor_hash); while (fname) { error = filldir(dirent, fname->name, - fname->name_len, curr_pos, + fname->name_len, curr_pos, fname->inode, get_dtype(sb, fname->file_type)); if (error) { @@ -465,7 +467,7 @@ static int ext3_dx_readdir(struct file * filp, /* * Fill the rbtree if we have no more entries, * or the inode has changed since we last read in the - * cached entries. + * cached entries. */ if ((!info->curr_node) || (filp->f_version != inode->i_version)) { diff --git a/fs/ext3/file.c b/fs/ext3/file.c index 1efefb630ea9..e96c388047e0 100644 --- a/fs/ext3/file.c +++ b/fs/ext3/file.c @@ -48,14 +48,15 @@ static int ext3_release_file (struct inode * inode, struct file * filp) } static ssize_t -ext3_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos) +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; ssize_t ret; int err; - ret = generic_file_aio_write(iocb, buf, count, pos); + ret = generic_file_aio_write(iocb, iov, nr_segs, pos); /* * Skip flushing if there was an error, or if nothing was written. @@ -100,7 +101,7 @@ ext3_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t force_commit: err = ext3_force_commit(inode->i_sb); - if (err) + if (err) return err; return ret; } @@ -111,9 +112,10 @@ const struct file_operations ext3_file_operations = { .write = do_sync_write, .aio_read = generic_file_aio_read, .aio_write = ext3_file_write, - .readv = generic_file_readv, - .writev = generic_file_writev, .ioctl = ext3_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = ext3_compat_ioctl, +#endif .mmap = generic_file_mmap, .open = generic_file_open, .release = ext3_release_file, diff --git a/fs/ext3/fsync.c b/fs/ext3/fsync.c index 49382a208e05..dd1fd3c0fc05 100644 --- a/fs/ext3/fsync.c +++ b/fs/ext3/fsync.c @@ -8,14 +8,14 @@ * Universite Pierre et Marie Curie (Paris VI) * from * linux/fs/minix/truncate.c Copyright (C) 1991, 1992 Linus Torvalds - * + * * ext3fs fsync primitive * * Big-endian to little-endian byte-swapping/bitmaps by * David S. Miller (davem@caip.rutgers.edu), 1995 - * + * * Removed unnecessary code duplication for little endian machines - * and excessive __inline__s. + * and excessive __inline__s. * Andi Kleen, 1997 * * Major simplications and cleanup - we only need to do the metadata, because diff --git a/fs/ext3/hash.c b/fs/ext3/hash.c index 5a2d1235ead0..deeb27b5ba83 100644 --- a/fs/ext3/hash.c +++ b/fs/ext3/hash.c @@ -4,7 +4,7 @@ * Copyright (C) 2002 by Theodore Ts'o * * This file is released under the GPL v2. - * + * * This file may be redistributed under the terms of the GNU Public * License. */ @@ -80,11 +80,11 @@ static void str2hashbuf(const char *msg, int len, __u32 *buf, int num) * Returns the hash of a filename. If len is 0 and name is NULL, then * this function can be used to test whether or not a hash version is * supported. - * + * * The seed is an 4 longword (32 bits) "secret" which can be used to * uniquify a hash. If the seed is all zero's, then some default seed * may be used. - * + * * A particular hash version specifies whether or not the seed is * represented, and whether or not the returned hash is 32 bits or 64 * bits. 32 bit hashes will return 0 for the minor hash. @@ -95,7 +95,7 @@ int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo) __u32 minor_hash = 0; const char *p; int i; - __u32 in[8], buf[4]; + __u32 in[8], buf[4]; /* Initialize the default seed for the hash checksum functions */ buf[0] = 0x67452301; diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 36546ed36a14..e45dbd651736 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c @@ -202,7 +202,7 @@ error_return: static int find_group_dir(struct super_block *sb, struct inode *parent) { int ngroups = EXT3_SB(sb)->s_groups_count; - int freei, avefreei; + unsigned int freei, avefreei; struct ext3_group_desc *desc, *best_desc = NULL; struct buffer_head *bh; int group, best_group = -1; @@ -216,7 +216,7 @@ static int find_group_dir(struct super_block *sb, struct inode *parent) continue; if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei) continue; - if (!best_desc || + if (!best_desc || (le16_to_cpu(desc->bg_free_blocks_count) > le16_to_cpu(best_desc->bg_free_blocks_count))) { best_group = group; @@ -226,30 +226,30 @@ static int find_group_dir(struct super_block *sb, struct inode *parent) return best_group; } -/* - * Orlov's allocator for directories. - * +/* + * Orlov's allocator for directories. + * * We always try to spread first-level directories. * - * If there are blockgroups with both free inodes and free blocks counts - * not worse than average we return one with smallest directory count. - * Otherwise we simply return a random group. - * - * For the rest rules look so: - * - * It's OK to put directory into a group unless - * it has too many directories already (max_dirs) or - * it has too few free inodes left (min_inodes) or - * it has too few free blocks left (min_blocks) or - * it's already running too large debt (max_debt). - * Parent's group is prefered, if it doesn't satisfy these - * conditions we search cyclically through the rest. If none - * of the groups look good we just look for a group with more - * free inodes than average (starting at parent's group). - * - * Debt is incremented each time we allocate a directory and decremented - * when we allocate an inode, within 0--255. - */ + * If there are blockgroups with both free inodes and free blocks counts + * not worse than average we return one with smallest directory count. + * Otherwise we simply return a random group. + * + * For the rest rules look so: + * + * It's OK to put directory into a group unless + * it has too many directories already (max_dirs) or + * it has too few free inodes left (min_inodes) or + * it has too few free blocks left (min_blocks) or + * it's already running too large debt (max_debt). + * Parent's group is prefered, if it doesn't satisfy these + * conditions we search cyclically through the rest. If none + * of the groups look good we just look for a group with more + * free inodes than average (starting at parent's group). + * + * Debt is incremented each time we allocate a directory and decremented + * when we allocate an inode, within 0--255. + */ #define INODE_COST 64 #define BLOCK_COST 256 @@ -261,10 +261,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent) struct ext3_super_block *es = sbi->s_es; int ngroups = sbi->s_groups_count; int inodes_per_group = EXT3_INODES_PER_GROUP(sb); - int freei, avefreei; + unsigned int freei, avefreei; ext3_fsblk_t freeb, avefreeb; ext3_fsblk_t blocks_per_dir; - int ndirs; + unsigned int ndirs; int max_debt, max_dirs, min_inodes; ext3_grpblk_t min_blocks; int group = -1, i; @@ -454,7 +454,7 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode) group = find_group_dir(sb, dir); else group = find_group_orlov(sb, dir); - } else + } else group = find_group_other(sb, dir); err = -ENOSPC; @@ -559,7 +559,6 @@ got: inode->i_ino = ino; /* This is the optimal IO size (for stat), not the fs block size */ - inode->i_blksize = PAGE_SIZE; inode->i_blocks = 0; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 84be02e93652..03ba5bcab186 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -13,11 +13,11 @@ * Copyright (C) 1991, 1992 Linus Torvalds * * Goal-directed block allocation by Stephen Tweedie - * (sct@redhat.com), 1993, 1998 + * (sct@redhat.com), 1993, 1998 * Big-endian to little-endian byte-swapping/bitmaps by * David S. Miller (davem@caip.rutgers.edu), 1995 * 64-bit file support on 64-bit platforms by Jakub Jelinek - * (jj@sunsite.ms.mff.cuni.cz) + * (jj@sunsite.ms.mff.cuni.cz) * * Assorted race fixes, rewrite of ext3_get_block() by Al Viro, 2000 */ @@ -36,6 +36,7 @@ #include <linux/writeback.h> #include <linux/mpage.h> #include <linux/uio.h> +#include <linux/bio.h> #include "xattr.h" #include "acl.h" @@ -55,7 +56,7 @@ static int ext3_inode_is_fast_symlink(struct inode *inode) /* * The ext3 forget function must perform a revoke if we are freeing data * which has been journaled. Metadata (eg. indirect blocks) must be - * revoked in all cases. + * revoked in all cases. * * "bh" may be NULL: a metadata block may have been freed from memory * but there may still be a record of it in the journal, and that record @@ -105,7 +106,7 @@ int ext3_forget(handle_t *handle, int is_metadata, struct inode *inode, * Work out how many blocks we need to proceed with the next chunk of a * truncate transaction. */ -static unsigned long blocks_for_truncate(struct inode *inode) +static unsigned long blocks_for_truncate(struct inode *inode) { unsigned long needed; @@ -122,13 +123,13 @@ static unsigned long blocks_for_truncate(struct inode *inode) /* But we need to bound the transaction so we don't overflow the * journal. */ - if (needed > EXT3_MAX_TRANS_DATA) + if (needed > EXT3_MAX_TRANS_DATA) needed = EXT3_MAX_TRANS_DATA; return EXT3_DATA_TRANS_BLOCKS(inode->i_sb) + needed; } -/* +/* * Truncate transactions can be complex and absolutely huge. So we need to * be able to restart the transaction at a conventient checkpoint to make * sure we don't overflow the journal. @@ -136,9 +137,9 @@ static unsigned long blocks_for_truncate(struct inode *inode) * start_transaction gets us a new handle for a truncate transaction, * and extend_transaction tries to extend the existing one a bit. If * extend fails, we need to propagate the failure up and restart the - * transaction in the top-level truncate loop. --sct + * transaction in the top-level truncate loop. --sct */ -static handle_t *start_transaction(struct inode *inode) +static handle_t *start_transaction(struct inode *inode) { handle_t *result; @@ -215,12 +216,12 @@ void ext3_delete_inode (struct inode * inode) ext3_orphan_del(handle, inode); EXT3_I(inode)->i_dtime = get_seconds(); - /* + /* * One subtle ordering requirement: if anything has gone wrong * (transaction abort, IO errors, whatever), then we can still * do these next steps (the fs will already have been marked as * having errors), but we can't free the inode if the mark_dirty - * fails. + * fails. */ if (ext3_mark_inode_dirty(handle, inode)) /* If that failed, just do the required in-core inode clear. */ @@ -398,7 +399,7 @@ no_block: * + if there is a block to the left of our position - allocate near it. * + if pointer will live in indirect block - allocate near that block. * + if pointer will live in inode - allocate in the same - * cylinder group. + * cylinder group. * * In the latter case we colour the starting block by the callers PID to * prevent it from clashing with concurrent allocations for a different inode @@ -470,7 +471,7 @@ static ext3_fsblk_t ext3_find_goal(struct inode *inode, long block, * ext3_blks_to_allocate: Look up the block map and count the number * of direct blocks need to be allocated for the given branch. * - * @branch: chain of indirect blocks + * @branch: chain of indirect blocks * @k: number of blocks need for indirect blocks * @blks: number of data blocks to be mapped. * @blocks_to_boundary: the offset in the indirect block @@ -744,7 +745,7 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode, jbd_debug(5, "splicing indirect only\n"); BUFFER_TRACE(where->bh, "call ext3_journal_dirty_metadata"); err = ext3_journal_dirty_metadata(handle, where->bh); - if (err) + if (err) goto err_out; } else { /* @@ -1073,7 +1074,7 @@ struct buffer_head *ext3_bread(handle_t *handle, struct inode *inode, return bh; if (buffer_uptodate(bh)) return bh; - ll_rw_block(READ, 1, &bh); + ll_rw_block(READ_META, 1, &bh); wait_on_buffer(bh); if (buffer_uptodate(bh)) return bh; @@ -1098,7 +1099,7 @@ static int walk_page_buffers( handle_t *handle, for ( bh = head, block_start = 0; ret == 0 && (bh != head || !block_start); - block_start = block_end, bh = next) + block_start = block_end, bh = next) { next = bh->b_this_page; block_end = block_start + blocksize; @@ -1137,7 +1138,7 @@ static int walk_page_buffers( handle_t *handle, * So what we do is to rely on the fact that journal_stop/journal_start * will _not_ run commit under these circumstances because handle->h_ref * is elevated. We'll still have enough credits for the tiny quotafile - * write. + * write. */ static int do_journal_get_write_access(handle_t *handle, struct buffer_head *bh) @@ -1282,7 +1283,7 @@ static int ext3_journalled_commit_write(struct file *file, if (inode->i_size > EXT3_I(inode)->i_disksize) { EXT3_I(inode)->i_disksize = inode->i_size; ret2 = ext3_mark_inode_dirty(handle, inode); - if (!ret) + if (!ret) ret = ret2; } ret2 = ext3_journal_stop(handle); @@ -1291,7 +1292,7 @@ static int ext3_journalled_commit_write(struct file *file, return ret; } -/* +/* * bmap() is special. It gets used by applications such as lilo and by * the swapper to find the on-disk block of a specific piece of data. * @@ -1300,10 +1301,10 @@ static int ext3_journalled_commit_write(struct file *file, * filesystem and enables swap, then they may get a nasty shock when the * data getting swapped to that swapfile suddenly gets overwritten by * the original zero's written out previously to the journal and - * awaiting writeback in the kernel's buffer cache. + * awaiting writeback in the kernel's buffer cache. * * So, if we see any bmap calls here on a modified, data-journaled file, - * take extra steps to flush any blocks which might be in the cache. + * take extra steps to flush any blocks which might be in the cache. */ static sector_t ext3_bmap(struct address_space *mapping, sector_t block) { @@ -1312,16 +1313,16 @@ static sector_t ext3_bmap(struct address_space *mapping, sector_t block) int err; if (EXT3_I(inode)->i_state & EXT3_STATE_JDATA) { - /* + /* * This is a REALLY heavyweight approach, but the use of * bmap on dirty files is expected to be extremely rare: * only if we run lilo or swapon on a freshly made file - * do we expect this to happen. + * do we expect this to happen. * * (bmap requires CAP_SYS_RAWIO so this does not * represent an unprivileged user DOS attack --- we'd be * in trouble if mortal users could trigger this path at - * will.) + * will.) * * NB. EXT3_STATE_JDATA is not set on files other than * regular files. If somebody wants to bmap a directory @@ -1457,7 +1458,7 @@ static int ext3_ordered_writepage(struct page *page, */ /* - * And attach them to the current transaction. But only if + * And attach them to the current transaction. But only if * block_write_full_page() succeeded. Otherwise they are unmapped, * and generally junk. */ @@ -1644,7 +1645,7 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb, } } - ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, + ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, offset, nr_segs, ext3_get_block, NULL); @@ -2025,7 +2026,7 @@ static void ext3_free_data(handle_t *handle, struct inode *inode, __le32 *first, __le32 *last) { ext3_fsblk_t block_to_free = 0; /* Starting block # of a run */ - unsigned long count = 0; /* Number of blocks in the run */ + unsigned long count = 0; /* Number of blocks in the run */ __le32 *block_to_free_p = NULL; /* Pointer into inode/ind corresponding to block_to_free */ @@ -2054,7 +2055,7 @@ static void ext3_free_data(handle_t *handle, struct inode *inode, } else if (nr == block_to_free + count) { count++; } else { - ext3_clear_blocks(handle, inode, this_bh, + ext3_clear_blocks(handle, inode, this_bh, block_to_free, count, block_to_free_p, p); block_to_free = nr; @@ -2115,7 +2116,7 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode, */ if (!bh) { ext3_error(inode->i_sb, "ext3_free_branches", - "Read failure, inode=%ld, block="E3FSBLK, + "Read failure, inode=%lu, block="E3FSBLK, inode->i_ino, nr); continue; } @@ -2184,7 +2185,7 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode, *p = 0; BUFFER_TRACE(parent_bh, "call ext3_journal_dirty_metadata"); - ext3_journal_dirty_metadata(handle, + ext3_journal_dirty_metadata(handle, parent_bh); } } @@ -2540,7 +2541,7 @@ make_io: */ get_bh(bh); bh->b_end_io = end_buffer_read_sync; - submit_bh(READ, bh); + submit_bh(READ_META, bh); wait_on_buffer(bh); if (!buffer_uptodate(bh)) { ext3_error(inode->i_sb, "ext3_get_inode_loc", @@ -2632,9 +2633,6 @@ void ext3_read_inode(struct inode * inode) * recovery code: that's fine, we're about to complete * the process of deleting those. */ } - inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size - * (for stat), not the fs block - * size */ inode->i_blocks = le32_to_cpu(raw_inode->i_blocks); ei->i_flags = le32_to_cpu(raw_inode->i_flags); #ifdef EXT3_FRAGMENTS @@ -2704,7 +2702,7 @@ void ext3_read_inode(struct inode * inode) if (raw_inode->i_block[0]) init_special_inode(inode, inode->i_mode, old_decode_dev(le32_to_cpu(raw_inode->i_block[0]))); - else + else init_special_inode(inode, inode->i_mode, new_decode_dev(le32_to_cpu(raw_inode->i_block[1]))); } @@ -2724,8 +2722,8 @@ bad_inode: * * The caller must have write access to iloc->bh. */ -static int ext3_do_update_inode(handle_t *handle, - struct inode *inode, +static int ext3_do_update_inode(handle_t *handle, + struct inode *inode, struct ext3_iloc *iloc) { struct ext3_inode *raw_inode = ext3_raw_inode(iloc); @@ -2900,7 +2898,7 @@ int ext3_write_inode(struct inode *inode, int wait) * commit will leave the blocks being flushed in an unused state on * disk. (On recovery, the inode will get truncated and the blocks will * be freed, so we have a strong guarantee that no future commit will - * leave these blocks visible to the user.) + * leave these blocks visible to the user.) * * Called with inode->sem down. */ @@ -3043,13 +3041,13 @@ int ext3_mark_iloc_dirty(handle_t *handle, return err; } -/* +/* * On success, We end up with an outstanding reference count against - * iloc->bh. This _must_ be cleaned up later. + * iloc->bh. This _must_ be cleaned up later. */ int -ext3_reserve_inode_write(handle_t *handle, struct inode *inode, +ext3_reserve_inode_write(handle_t *handle, struct inode *inode, struct ext3_iloc *iloc) { int err = 0; @@ -3139,7 +3137,7 @@ out: } #if 0 -/* +/* * Bind an inode's backing buffer_head into this transaction, to prevent * it from being flushed to disk early. Unlike * ext3_reserve_inode_write, this leaves behind no bh reference and @@ -3157,7 +3155,7 @@ static int ext3_pin_inode(handle_t *handle, struct inode *inode) BUFFER_TRACE(iloc.bh, "get_write_access"); err = journal_get_write_access(handle, iloc.bh); if (!err) - err = ext3_journal_dirty_metadata(handle, + err = ext3_journal_dirty_metadata(handle, iloc.bh); brelse(iloc.bh); } diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c index 3a6b012d120c..12daa6869572 100644 --- a/fs/ext3/ioctl.c +++ b/fs/ext3/ioctl.c @@ -13,9 +13,10 @@ #include <linux/ext3_fs.h> #include <linux/ext3_jbd.h> #include <linux/time.h> +#include <linux/compat.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> - int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg) { @@ -252,3 +253,55 @@ flags_err: return -ENOTTY; } } + +#ifdef CONFIG_COMPAT +long ext3_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct inode *inode = file->f_dentry->d_inode; + int ret; + + /* These are just misnamed, they actually get/put from/to user an int */ + switch (cmd) { + case EXT3_IOC32_GETFLAGS: + cmd = EXT3_IOC_GETFLAGS; + break; + case EXT3_IOC32_SETFLAGS: + cmd = EXT3_IOC_SETFLAGS; + break; + case EXT3_IOC32_GETVERSION: + cmd = EXT3_IOC_GETVERSION; + break; + case EXT3_IOC32_SETVERSION: + cmd = EXT3_IOC_SETVERSION; + break; + case EXT3_IOC32_GROUP_EXTEND: + cmd = EXT3_IOC_GROUP_EXTEND; + break; + case EXT3_IOC32_GETVERSION_OLD: + cmd = EXT3_IOC_GETVERSION_OLD; + break; + case EXT3_IOC32_SETVERSION_OLD: + cmd = EXT3_IOC_SETVERSION_OLD; + break; +#ifdef CONFIG_JBD_DEBUG + case EXT3_IOC32_WAIT_FOR_READONLY: + cmd = EXT3_IOC_WAIT_FOR_READONLY; + break; +#endif + case EXT3_IOC32_GETRSVSZ: + cmd = EXT3_IOC_GETRSVSZ; + break; + case EXT3_IOC32_SETRSVSZ: + cmd = EXT3_IOC_SETRSVSZ; + break; + case EXT3_IOC_GROUP_ADD: + break; + default: + return -ENOIOCTLCMD; + } + lock_kernel(); + ret = ext3_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg)); + unlock_kernel(); + return ret; +} +#endif diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 2aa7101b27cd..906731a20f1a 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -15,13 +15,13 @@ * Big-endian to little-endian byte-swapping/bitmaps by * David S. Miller (davem@caip.rutgers.edu), 1995 * Directory entry file type support and forward compatibility hooks - * for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998 + * for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998 * Hash Tree Directory indexing (c) - * Daniel Phillips, 2001 + * Daniel Phillips, 2001 * Hash Tree Directory indexing porting - * Christopher Li, 2002 + * Christopher Li, 2002 * Hash Tree Directory indexing cleanup - * Theodore Ts'o, 2002 + * Theodore Ts'o, 2002 */ #include <linux/fs.h> @@ -35,6 +35,7 @@ #include <linux/string.h> #include <linux/quotaops.h> #include <linux/buffer_head.h> +#include <linux/bio.h> #include <linux/smp_lock.h> #include "namei.h" @@ -76,7 +77,7 @@ static struct buffer_head *ext3_append(handle_t *handle, #ifdef DX_DEBUG #define dxtrace(command) command #else -#define dxtrace(command) +#define dxtrace(command) #endif struct fake_dirent @@ -169,7 +170,7 @@ static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size); static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block); static int ext3_htree_next_block(struct inode *dir, __u32 hash, struct dx_frame *frame, - struct dx_frame *frames, + struct dx_frame *frames, __u32 *start_hash); static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, struct ext3_dir_entry_2 **res_dir, int *err); @@ -250,7 +251,7 @@ static void dx_show_index (char * label, struct dx_entry *entries) } struct stats -{ +{ unsigned names; unsigned space; unsigned bcount; @@ -278,7 +279,7 @@ static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext3_dir_ent ((char *) de - base)); } space += EXT3_DIR_REC_LEN(de->name_len); - names++; + names++; } de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); } @@ -464,7 +465,7 @@ static void dx_release (struct dx_frame *frames) */ static int ext3_htree_next_block(struct inode *dir, __u32 hash, struct dx_frame *frame, - struct dx_frame *frames, + struct dx_frame *frames, __u32 *start_hash) { struct dx_frame *p; @@ -632,7 +633,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, } count += ret; hashval = ~0; - ret = ext3_htree_next_block(dir, HASH_NB_ALWAYS, + ret = ext3_htree_next_block(dir, HASH_NB_ALWAYS, frame, frames, &hashval); *next_hash = hashval; if (ret < 0) { @@ -649,7 +650,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, break; } dx_release(frames); - dxtrace(printk("Fill tree: returned %d entries, next hash: %x\n", + dxtrace(printk("Fill tree: returned %d entries, next hash: %x\n", count, *next_hash)); return count; errout: @@ -870,7 +871,7 @@ restart: bh = ext3_getblk(NULL, dir, b++, 0, &err); bh_use[ra_max] = bh; if (bh) - ll_rw_block(READ, 1, &bh); + ll_rw_block(READ_META, 1, &bh); } } if ((bh = bh_use[ra_ptr++]) == NULL) @@ -1050,7 +1051,7 @@ struct dentry *ext3_get_parent(struct dentry *child) parent = ERR_PTR(-ENOMEM); } return parent; -} +} #define S_SHIFT 12 static unsigned char ext3_type_by_mode[S_IFMT >> S_SHIFT] = { @@ -1198,7 +1199,7 @@ errout: * add_dirent_to_buf will attempt search the directory block for * space. It will return -ENOSPC if no space is available, and -EIO * and -EEXIST if directory entry already exists. - * + * * NOTE! bh is NOT released in the case where ENOSPC is returned. In * all other cases bh is released. */ @@ -1572,7 +1573,7 @@ cleanup: * ext3_delete_entry deletes a directory entry by merging it with the * previous entry */ -static int ext3_delete_entry (handle_t *handle, +static int ext3_delete_entry (handle_t *handle, struct inode * dir, struct ext3_dir_entry_2 * de_del, struct buffer_head * bh) @@ -1615,12 +1616,12 @@ static int ext3_delete_entry (handle_t *handle, */ static inline void ext3_inc_count(handle_t *handle, struct inode *inode) { - inode->i_nlink++; + inc_nlink(inode); } static inline void ext3_dec_count(handle_t *handle, struct inode *inode) { - inode->i_nlink--; + drop_nlink(inode); } static int ext3_add_nondir(handle_t *handle, @@ -1643,12 +1644,12 @@ static int ext3_add_nondir(handle_t *handle, * is so far negative - it has no inode. * * If the create succeeds, we fill in the inode information - * with d_instantiate(). + * with d_instantiate(). */ static int ext3_create (struct inode * dir, struct dentry * dentry, int mode, struct nameidata *nd) { - handle_t *handle; + handle_t *handle; struct inode * inode; int err, retries = 0; @@ -1688,7 +1689,7 @@ static int ext3_mknod (struct inode * dir, struct dentry *dentry, retry: handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + - EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + + EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb)); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -1742,7 +1743,7 @@ retry: inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; dir_block = ext3_bread (handle, inode, 0, 1, &err); if (!dir_block) { - inode->i_nlink--; /* is this nlink == 0? */ + drop_nlink(inode); /* is this nlink == 0? */ ext3_mark_inode_dirty(handle, inode); iput (inode); goto out_stop; @@ -1774,7 +1775,7 @@ retry: iput (inode); goto out_stop; } - dir->i_nlink++; + inc_nlink(dir); ext3_update_dx_flag(dir); ext3_mark_inode_dirty(handle, dir); d_instantiate(dentry, inode); @@ -1813,10 +1814,10 @@ static int empty_dir (struct inode * inode) de1 = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); if (le32_to_cpu(de->inode) != inode->i_ino || - !le32_to_cpu(de1->inode) || + !le32_to_cpu(de1->inode) || strcmp (".", de->name) || strcmp ("..", de1->name)) { - ext3_warning (inode->i_sb, "empty_dir", + ext3_warning (inode->i_sb, "empty_dir", "bad directory (dir #%lu) - no `.' or `..'", inode->i_ino); brelse (bh); @@ -1883,7 +1884,7 @@ int ext3_orphan_add(handle_t *handle, struct inode *inode) * being truncated, or files being unlinked. */ /* @@@ FIXME: Observation from aviro: - * I think I can trigger J_ASSERT in ext3_orphan_add(). We block + * I think I can trigger J_ASSERT in ext3_orphan_add(). We block * here (on lock_super()), so race with ext3_link() which might bump * ->i_nlink. For, say it, character device. Not a regular file, * not a directory, not a symlink and ->i_nlink > 0. @@ -1919,8 +1920,8 @@ int ext3_orphan_add(handle_t *handle, struct inode *inode) if (!err) list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan); - jbd_debug(4, "superblock will point to %ld\n", inode->i_ino); - jbd_debug(4, "orphan inode %ld will point to %d\n", + jbd_debug(4, "superblock will point to %lu\n", inode->i_ino); + jbd_debug(4, "orphan inode %lu will point to %d\n", inode->i_ino, NEXT_ORPHAN(inode)); out_unlock: unlock_super(sb); @@ -2044,7 +2045,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry) "empty directory has nlink!=2 (%d)", inode->i_nlink); inode->i_version++; - inode->i_nlink = 0; + clear_nlink(inode); /* There's no need to set i_disksize: the fact that i_nlink is * zero will ensure that the right thing happens during any * recovery. */ @@ -2052,7 +2053,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry) ext3_orphan_add(handle, inode); inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; ext3_mark_inode_dirty(handle, inode); - dir->i_nlink--; + drop_nlink(dir); ext3_update_dx_flag(dir); ext3_mark_inode_dirty(handle, dir); @@ -2103,7 +2104,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry) dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; ext3_update_dx_flag(dir); ext3_mark_inode_dirty(handle, dir); - inode->i_nlink--; + drop_nlink(inode); if (!inode->i_nlink) ext3_orphan_add(handle, inode); inode->i_ctime = dir->i_ctime; @@ -2129,7 +2130,7 @@ static int ext3_symlink (struct inode * dir, retry: handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + - EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 + + EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 + 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb)); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -2227,7 +2228,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry, DQUOT_INIT(new_dentry->d_inode); handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS(old_dir->i_sb) + - EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2); + EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -2325,7 +2326,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry, } if (new_inode) { - new_inode->i_nlink--; + drop_nlink(new_inode); new_inode->i_ctime = CURRENT_TIME_SEC; } old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC; @@ -2336,11 +2337,11 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry, PARENT_INO(dir_bh->b_data) = cpu_to_le32(new_dir->i_ino); BUFFER_TRACE(dir_bh, "call ext3_journal_dirty_metadata"); ext3_journal_dirty_metadata(handle, dir_bh); - old_dir->i_nlink--; + drop_nlink(old_dir); if (new_inode) { - new_inode->i_nlink--; + drop_nlink(new_inode); } else { - new_dir->i_nlink++; + inc_nlink(new_dir); ext3_update_dx_flag(new_dir); ext3_mark_inode_dirty(handle, new_dir); } @@ -2393,4 +2394,4 @@ struct inode_operations ext3_special_inode_operations = { .removexattr = generic_removexattr, #endif .permission = ext3_permission, -}; +}; diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index 5e1337fd878a..b73cba12f79c 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c @@ -336,7 +336,7 @@ static int verify_reserved_gdb(struct super_block *sb, unsigned five = 5; unsigned seven = 7; unsigned grp; - __u32 *p = (__u32 *)primary->b_data; + __le32 *p = (__le32 *)primary->b_data; int gdbackups = 0; while ((grp = ext3_list_backups(sb, &three, &five, &seven)) < end) { @@ -380,7 +380,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, struct buffer_head *dind; int gdbackups; struct ext3_iloc iloc; - __u32 *data; + __le32 *data; int err; if (test_opt(sb, DEBUG)) @@ -417,7 +417,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, goto exit_bh; } - data = (__u32 *)dind->b_data; + data = (__le32 *)dind->b_data; if (le32_to_cpu(data[gdb_num % EXT3_ADDR_PER_BLOCK(sb)]) != gdblock) { ext3_warning(sb, __FUNCTION__, "new group %u GDT block "E3FSBLK" not reserved", @@ -439,8 +439,8 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, if ((err = ext3_reserve_inode_write(handle, inode, &iloc))) goto exit_dindj; - n_group_desc = (struct buffer_head **)kmalloc((gdb_num + 1) * - sizeof(struct buffer_head *), GFP_KERNEL); + n_group_desc = kmalloc((gdb_num + 1) * sizeof(struct buffer_head *), + GFP_KERNEL); if (!n_group_desc) { err = -ENOMEM; ext3_warning (sb, __FUNCTION__, @@ -519,7 +519,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode, struct buffer_head *dind; struct ext3_iloc iloc; ext3_fsblk_t blk; - __u32 *data, *end; + __le32 *data, *end; int gdbackups = 0; int res, i; int err; @@ -536,8 +536,8 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode, } blk = EXT3_SB(sb)->s_sbh->b_blocknr + 1 + EXT3_SB(sb)->s_gdb_count; - data = (__u32 *)dind->b_data + EXT3_SB(sb)->s_gdb_count; - end = (__u32 *)dind->b_data + EXT3_ADDR_PER_BLOCK(sb); + data = (__le32 *)dind->b_data + EXT3_SB(sb)->s_gdb_count; + end = (__le32 *)dind->b_data + EXT3_ADDR_PER_BLOCK(sb); /* Get each reserved primary GDT block and verify it holds backups */ for (res = 0; res < reserved_gdb; res++, blk++) { @@ -545,7 +545,8 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode, ext3_warning(sb, __FUNCTION__, "reserved block "E3FSBLK " not at offset %ld", - blk, (long)(data - (__u32 *)dind->b_data)); + blk, + (long)(data - (__le32 *)dind->b_data)); err = -EINVAL; goto exit_bh; } @@ -560,7 +561,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode, goto exit_bh; } if (++data >= end) - data = (__u32 *)dind->b_data; + data = (__le32 *)dind->b_data; } for (i = 0; i < reserved_gdb; i++) { @@ -584,7 +585,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode, blk = input->group * EXT3_BLOCKS_PER_GROUP(sb); for (i = 0; i < reserved_gdb; i++) { int err2; - data = (__u32 *)primary[i]->b_data; + data = (__le32 *)primary[i]->b_data; /* printk("reserving backup %lu[%u] = %lu\n", primary[i]->b_blocknr, gdbackups, blk + primary[i]->b_blocknr); */ @@ -689,7 +690,7 @@ exit_err: "can't update backup for group %d (err %d), " "forcing fsck on next reboot", group, err); sbi->s_mount_state &= ~EXT3_VALID_FS; - sbi->s_es->s_state &= ~cpu_to_le16(EXT3_VALID_FS); + sbi->s_es->s_state &= cpu_to_le16(~EXT3_VALID_FS); mark_buffer_dirty(sbi->s_sbh); } } @@ -730,6 +731,18 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input) return -EPERM; } + if (le32_to_cpu(es->s_blocks_count) + input->blocks_count < + le32_to_cpu(es->s_blocks_count)) { + ext3_warning(sb, __FUNCTION__, "blocks_count overflow\n"); + return -EINVAL; + } + + if (le32_to_cpu(es->s_inodes_count) + EXT3_INODES_PER_GROUP(sb) < + le32_to_cpu(es->s_inodes_count)) { + ext3_warning(sb, __FUNCTION__, "inodes_count overflow\n"); + return -EINVAL; + } + if (reserved_gdb || gdb_off == 0) { if (!EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_RESIZE_INODE)){ @@ -958,6 +971,11 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es, add = EXT3_BLOCKS_PER_GROUP(sb) - last; + if (o_blocks_count + add < o_blocks_count) { + ext3_warning(sb, __FUNCTION__, "blocks_count overflow"); + return -EINVAL; + } + if (o_blocks_count + add > n_blocks_count) add = n_blocks_count - o_blocks_count; diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 3559086eee5f..8bfd56ef18ca 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -45,7 +45,7 @@ static int ext3_load_journal(struct super_block *, struct ext3_super_block *, unsigned long journal_devnum); static int ext3_create_journal(struct super_block *, struct ext3_super_block *, - int); + unsigned int); static void ext3_commit_super (struct super_block * sb, struct ext3_super_block * es, int sync); @@ -62,13 +62,13 @@ static void ext3_unlockfs(struct super_block *sb); static void ext3_write_super (struct super_block * sb); static void ext3_write_super_lockfs(struct super_block *sb); -/* +/* * Wrappers for journal_start/end. * * The only special thing we need to do here is to make sure that all * journal_end calls result in the superblock being marked dirty, so * that sync() will call the filesystem's write_super callback if - * appropriate. + * appropriate. */ handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks) { @@ -90,11 +90,11 @@ handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks) return journal_start(journal, nblocks); } -/* +/* * The only special thing we need to do here is to make sure that all * journal_stop calls result in the superblock being marked dirty, so * that sync() will call the filesystem's write_super callback if - * appropriate. + * appropriate. */ int __ext3_journal_stop(const char *where, handle_t *handle) { @@ -159,20 +159,21 @@ static void ext3_handle_error(struct super_block *sb) if (sb->s_flags & MS_RDONLY) return; - if (test_opt (sb, ERRORS_RO)) { - printk (KERN_CRIT "Remounting filesystem read-only\n"); - sb->s_flags |= MS_RDONLY; - } else { + if (!test_opt (sb, ERRORS_CONT)) { journal_t *journal = EXT3_SB(sb)->s_journal; EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT; if (journal) journal_abort(journal, -EIO); } + if (test_opt (sb, ERRORS_RO)) { + printk (KERN_CRIT "Remounting filesystem read-only\n"); + sb->s_flags |= MS_RDONLY; + } + ext3_commit_super(sb, es, 1); if (test_opt(sb, ERRORS_PANIC)) panic("EXT3-fs (device %s): panic forced after error\n", sb->s_id); - ext3_commit_super(sb, es, 1); } void ext3_error (struct super_block * sb, const char * function, @@ -369,16 +370,16 @@ static void dump_orphan_list(struct super_block *sb, struct ext3_sb_info *sbi) { struct list_head *l; - printk(KERN_ERR "sb orphan head is %d\n", + printk(KERN_ERR "sb orphan head is %d\n", le32_to_cpu(sbi->s_es->s_last_orphan)); printk(KERN_ERR "sb_info orphan list:\n"); list_for_each(l, &sbi->s_orphan) { struct inode *inode = orphan_list_entry(l); printk(KERN_ERR " " - "inode %s:%ld at %p: mode %o, nlink %d, next %d\n", + "inode %s:%lu at %p: mode %o, nlink %d, next %d\n", inode->i_sb->s_id, inode->i_ino, inode, - inode->i_mode, inode->i_nlink, + inode->i_mode, inode->i_nlink, NEXT_ORPHAN(inode)); } } @@ -475,7 +476,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) inode_init_once(&ei->vfs_inode); } } - + static int init_inodecache(void) { ext3_inode_cachep = kmem_cache_create("ext3_inode_cache", @@ -490,8 +491,7 @@ static int init_inodecache(void) static void destroy_inodecache(void) { - if (kmem_cache_destroy(ext3_inode_cachep)) - printk(KERN_INFO "ext3_inode_cache: not all structures were freed\n"); + kmem_cache_destroy(ext3_inode_cachep); } static void ext3_clear_inode(struct inode *inode) @@ -733,8 +733,8 @@ static match_table_t tokens = { static ext3_fsblk_t get_sb_block(void **data) { - ext3_fsblk_t sb_block; - char *options = (char *) *data; + ext3_fsblk_t sb_block; + char *options = (char *) *data; if (!options || strncmp(options, "sb=", 3) != 0) return 1; /* Default location */ @@ -753,7 +753,7 @@ static ext3_fsblk_t get_sb_block(void **data) } static int parse_options (char *options, struct super_block *sb, - unsigned long *inum, unsigned long *journal_devnum, + unsigned int *inum, unsigned long *journal_devnum, ext3_fsblk_t *n_blocks_count, int is_remount) { struct ext3_sb_info *sbi = EXT3_SB(sb); @@ -1174,7 +1174,8 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es, static int ext3_check_descriptors (struct super_block * sb) { struct ext3_sb_info *sbi = EXT3_SB(sb); - ext3_fsblk_t block = le32_to_cpu(sbi->s_es->s_first_data_block); + ext3_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block); + ext3_fsblk_t last_block; struct ext3_group_desc * gdp = NULL; int desc_block = 0; int i; @@ -1183,12 +1184,17 @@ static int ext3_check_descriptors (struct super_block * sb) for (i = 0; i < sbi->s_groups_count; i++) { + if (i == sbi->s_groups_count - 1) + last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1; + else + last_block = first_block + + (EXT3_BLOCKS_PER_GROUP(sb) - 1); + if ((i % EXT3_DESC_PER_BLOCK(sb)) == 0) gdp = (struct ext3_group_desc *) sbi->s_group_desc[desc_block++]->b_data; - if (le32_to_cpu(gdp->bg_block_bitmap) < block || - le32_to_cpu(gdp->bg_block_bitmap) >= - block + EXT3_BLOCKS_PER_GROUP(sb)) + if (le32_to_cpu(gdp->bg_block_bitmap) < first_block || + le32_to_cpu(gdp->bg_block_bitmap) > last_block) { ext3_error (sb, "ext3_check_descriptors", "Block bitmap for group %d" @@ -1197,9 +1203,8 @@ static int ext3_check_descriptors (struct super_block * sb) le32_to_cpu(gdp->bg_block_bitmap)); return 0; } - if (le32_to_cpu(gdp->bg_inode_bitmap) < block || - le32_to_cpu(gdp->bg_inode_bitmap) >= - block + EXT3_BLOCKS_PER_GROUP(sb)) + if (le32_to_cpu(gdp->bg_inode_bitmap) < first_block || + le32_to_cpu(gdp->bg_inode_bitmap) > last_block) { ext3_error (sb, "ext3_check_descriptors", "Inode bitmap for group %d" @@ -1208,9 +1213,9 @@ static int ext3_check_descriptors (struct super_block * sb) le32_to_cpu(gdp->bg_inode_bitmap)); return 0; } - if (le32_to_cpu(gdp->bg_inode_table) < block || - le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >= - block + EXT3_BLOCKS_PER_GROUP(sb)) + if (le32_to_cpu(gdp->bg_inode_table) < first_block || + le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group > + last_block) { ext3_error (sb, "ext3_check_descriptors", "Inode table for group %d" @@ -1219,7 +1224,7 @@ static int ext3_check_descriptors (struct super_block * sb) le32_to_cpu(gdp->bg_inode_table)); return 0; } - block += EXT3_BLOCKS_PER_GROUP(sb); + first_block += EXT3_BLOCKS_PER_GROUP(sb); gdp++; } @@ -1301,17 +1306,17 @@ static void ext3_orphan_cleanup (struct super_block * sb, DQUOT_INIT(inode); if (inode->i_nlink) { printk(KERN_DEBUG - "%s: truncating inode %ld to %Ld bytes\n", + "%s: truncating inode %lu to %Ld bytes\n", __FUNCTION__, inode->i_ino, inode->i_size); - jbd_debug(2, "truncating inode %ld to %Ld bytes\n", + jbd_debug(2, "truncating inode %lu to %Ld bytes\n", inode->i_ino, inode->i_size); ext3_truncate(inode); nr_truncates++; } else { printk(KERN_DEBUG - "%s: deleting unreferenced inode %ld\n", + "%s: deleting unreferenced inode %lu\n", __FUNCTION__, inode->i_ino); - jbd_debug(2, "deleting unreferenced inode %ld\n", + jbd_debug(2, "deleting unreferenced inode %lu\n", inode->i_ino); nr_orphans++; } @@ -1390,7 +1395,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) ext3_fsblk_t sb_block = get_sb_block(&data); ext3_fsblk_t logic_sb_block; unsigned long offset = 0; - unsigned long journal_inum = 0; + unsigned int journal_inum = 0; unsigned long journal_devnum = 0; unsigned long def_mount_opts; struct inode *root; @@ -1401,11 +1406,10 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) int needs_recovery; __le32 features; - sbi = kmalloc(sizeof(*sbi), GFP_KERNEL); + sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) return -ENOMEM; sb->s_fs_info = sbi; - memset(sbi, 0, sizeof(*sbi)); sbi->s_mount_opt = 0; sbi->s_resuid = EXT3_DEF_RESUID; sbi->s_resgid = EXT3_DEF_RESGID; @@ -1483,7 +1487,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) (EXT3_HAS_COMPAT_FEATURE(sb, ~0U) || EXT3_HAS_RO_COMPAT_FEATURE(sb, ~0U) || EXT3_HAS_INCOMPAT_FEATURE(sb, ~0U))) - printk(KERN_WARNING + printk(KERN_WARNING "EXT3-fs warning: feature flags set on rev 0 fs, " "running e2fsck is recommended\n"); /* @@ -1509,7 +1513,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) if (blocksize < EXT3_MIN_BLOCK_SIZE || blocksize > EXT3_MAX_BLOCK_SIZE) { - printk(KERN_ERR + printk(KERN_ERR "EXT3-fs: Unsupported filesystem blocksize %d on %s.\n", blocksize, sb->s_id); goto failed_mount; @@ -1533,14 +1537,14 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) offset = (sb_block * EXT3_MIN_BLOCK_SIZE) % blocksize; bh = sb_bread(sb, logic_sb_block); if (!bh) { - printk(KERN_ERR + printk(KERN_ERR "EXT3-fs: Can't read superblock on 2nd try.\n"); goto failed_mount; } es = (struct ext3_super_block *)(((char *)bh->b_data) + offset); sbi->s_es = es; if (es->s_magic != cpu_to_le16(EXT3_SUPER_MAGIC)) { - printk (KERN_ERR + printk (KERN_ERR "EXT3-fs: Magic mismatch, very weird !\n"); goto failed_mount; } @@ -1622,10 +1626,9 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) if (EXT3_BLOCKS_PER_GROUP(sb) == 0) goto cantfind_ext3; - sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) - - le32_to_cpu(es->s_first_data_block) + - EXT3_BLOCKS_PER_GROUP(sb) - 1) / - EXT3_BLOCKS_PER_GROUP(sb); + sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) - + le32_to_cpu(es->s_first_data_block) - 1) + / EXT3_BLOCKS_PER_GROUP(sb)) + 1; db_count = (sbi->s_groups_count + EXT3_DESC_PER_BLOCK(sb) - 1) / EXT3_DESC_PER_BLOCK(sb); sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *), @@ -1820,7 +1823,7 @@ out_fail: /* * Setup any per-fs journal parameters now. We'll do this both on * initial mount, once the journal has been initialised but before we've - * done any recovery; and again on any subsequent remount. + * done any recovery; and again on any subsequent remount. */ static void ext3_init_journal_params(struct super_block *sb, journal_t *journal) { @@ -1840,7 +1843,8 @@ static void ext3_init_journal_params(struct super_block *sb, journal_t *journal) spin_unlock(&journal->j_state_lock); } -static journal_t *ext3_get_journal(struct super_block *sb, int journal_inum) +static journal_t *ext3_get_journal(struct super_block *sb, + unsigned int journal_inum) { struct inode *journal_inode; journal_t *journal; @@ -1975,7 +1979,7 @@ static int ext3_load_journal(struct super_block *sb, unsigned long journal_devnum) { journal_t *journal; - int journal_inum = le32_to_cpu(es->s_journal_inum); + unsigned int journal_inum = le32_to_cpu(es->s_journal_inum); dev_t journal_dev; int err = 0; int really_read_only; @@ -2061,7 +2065,7 @@ static int ext3_load_journal(struct super_block *sb, static int ext3_create_journal(struct super_block * sb, struct ext3_super_block * es, - int journal_inum) + unsigned int journal_inum) { journal_t *journal; @@ -2074,7 +2078,7 @@ static int ext3_create_journal(struct super_block * sb, if (!(journal = ext3_get_journal(sb, journal_inum))) return -EINVAL; - printk(KERN_INFO "EXT3-fs: creating new journal on inode %d\n", + printk(KERN_INFO "EXT3-fs: creating new journal on inode %u\n", journal_inum); if (journal_create(journal)) { @@ -2342,10 +2346,8 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) */ ext3_clear_journal_err(sb, es); sbi->s_mount_state = le16_to_cpu(es->s_state); - if ((ret = ext3_group_extend(sb, es, n_blocks_count))) { - err = ret; + if ((err = ext3_group_extend(sb, es, n_blocks_count))) goto restore_opts; - } if (!ext3_setup_super (sb, es, 0)) sb->s_flags &= ~MS_RDONLY; } @@ -2734,7 +2736,7 @@ static int __init init_ext3_fs(void) out: destroy_inodecache(); out1: - exit_ext3_xattr(); + exit_ext3_xattr(); return err; } diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index a44a0562203a..f86f2482f01d 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c @@ -75,7 +75,7 @@ #ifdef EXT3_XATTR_DEBUG # define ea_idebug(inode, f...) do { \ - printk(KERN_DEBUG "inode %s:%ld: ", \ + printk(KERN_DEBUG "inode %s:%lu: ", \ inode->i_sb->s_id, inode->i_ino); \ printk(f); \ printk("\n"); \ @@ -233,7 +233,7 @@ ext3_xattr_block_get(struct inode *inode, int name_index, const char *name, atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount)); if (ext3_xattr_check_block(bh)) { bad_block: ext3_error(inode->i_sb, __FUNCTION__, - "inode %ld: bad block "E3FSBLK, inode->i_ino, + "inode %lu: bad block "E3FSBLK, inode->i_ino, EXT3_I(inode)->i_file_acl); error = -EIO; goto cleanup; @@ -375,7 +375,7 @@ ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size) atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount)); if (ext3_xattr_check_block(bh)) { ext3_error(inode->i_sb, __FUNCTION__, - "inode %ld: bad block "E3FSBLK, inode->i_ino, + "inode %lu: bad block "E3FSBLK, inode->i_ino, EXT3_I(inode)->i_file_acl); error = -EIO; goto cleanup; @@ -647,7 +647,7 @@ ext3_xattr_block_find(struct inode *inode, struct ext3_xattr_info *i, le32_to_cpu(BHDR(bs->bh)->h_refcount)); if (ext3_xattr_check_block(bs->bh)) { ext3_error(sb, __FUNCTION__, - "inode %ld: bad block "E3FSBLK, inode->i_ino, + "inode %lu: bad block "E3FSBLK, inode->i_ino, EXT3_I(inode)->i_file_acl); error = -EIO; goto cleanup; @@ -848,7 +848,7 @@ cleanup_dquot: bad_block: ext3_error(inode->i_sb, __FUNCTION__, - "inode %ld: bad block "E3FSBLK, inode->i_ino, + "inode %lu: bad block "E3FSBLK, inode->i_ino, EXT3_I(inode)->i_file_acl); goto cleanup; @@ -1077,14 +1077,14 @@ ext3_xattr_delete_inode(handle_t *handle, struct inode *inode) bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl); if (!bh) { ext3_error(inode->i_sb, __FUNCTION__, - "inode %ld: block "E3FSBLK" read error", inode->i_ino, + "inode %lu: block "E3FSBLK" read error", inode->i_ino, EXT3_I(inode)->i_file_acl); goto cleanup; } if (BHDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || BHDR(bh)->h_blocks != cpu_to_le32(1)) { ext3_error(inode->i_sb, __FUNCTION__, - "inode %ld: bad block "E3FSBLK, inode->i_ino, + "inode %lu: bad block "E3FSBLK, inode->i_ino, EXT3_I(inode)->i_file_acl); goto cleanup; } @@ -1211,7 +1211,7 @@ again: bh = sb_bread(inode->i_sb, ce->e_block); if (!bh) { ext3_error(inode->i_sb, __FUNCTION__, - "inode %ld: block %lu read error", + "inode %lu: block %lu read error", inode->i_ino, (unsigned long) ce->e_block); } else if (le32_to_cpu(BHDR(bh)->h_refcount) >= EXT3_XATTR_REFCOUNT_MAX) { |