Commit 7d2f280e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs-2.6

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs-2.6: (24 commits)
  quota: Fix possible oops in __dquot_initialize()
  ext3: Update kernel-doc comments
  jbd/2: fixed typos
  ext2: fixed typo.
  ext3: Fix debug messages in ext3_group_extend()
  jbd: Convert atomic_inc() to get_bh()
  ext3: Remove misplaced BUFFER_TRACE() in ext3_truncate()
  jbd: Fix debug message in do_get_write_access()
  jbd: Check return value of __getblk()
  ext3: Use DIV_ROUND_UP() on group desc block counting
  ext3: Return proper error code on ext3_fill_super()
  ext3: Remove unnecessary casts on bh->b_data
  ext3: Cleanup ext3_setup_super()
  quota: Fix issuing of warnings from dquot_transfer
  quota: fix dquot_disable vs dquot_transfer race v2
  jbd: Convert bitops to buffer fns
  ext3/jbd: Avoid WARN() messages when failing to write the superblock
  jbd: Use offset_in_page() instead of manual calculation
  jbd: Remove unnecessary goto statement
  jbd: Use printk_ratelimited() in journal_alloc_journal_head()
  ...
parents e3e1288e 4408ea41
...@@ -646,10 +646,9 @@ find_next_usable_block(int start, struct buffer_head *bh, int maxblocks) ...@@ -646,10 +646,9 @@ find_next_usable_block(int start, struct buffer_head *bh, int maxblocks)
return here; return here;
} }
/* /**
* ext2_try_to_allocate() * ext2_try_to_allocate()
* @sb: superblock * @sb: superblock
* @handle: handle to this transaction
* @group: given allocation block group * @group: given allocation block group
* @bitmap_bh: bufferhead holds the block bitmap * @bitmap_bh: bufferhead holds the block bitmap
* @grp_goal: given target block within the group * @grp_goal: given target block within the group
......
...@@ -792,9 +792,9 @@ find_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh, ...@@ -792,9 +792,9 @@ find_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh,
if (here < 0) if (here < 0)
here = 0; here = 0;
p = ((char *)bh->b_data) + (here >> 3); p = bh->b_data + (here >> 3);
r = memscan(p, 0, ((maxblocks + 7) >> 3) - (here >> 3)); r = memscan(p, 0, ((maxblocks + 7) >> 3) - (here >> 3));
next = (r - ((char *)bh->b_data)) << 3; next = (r - bh->b_data) << 3;
if (next < maxblocks && next >= start && ext3_test_allocatable(next, bh)) if (next < maxblocks && next >= start && ext3_test_allocatable(next, bh))
return next; return next;
...@@ -810,8 +810,9 @@ find_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh, ...@@ -810,8 +810,9 @@ find_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh,
/** /**
* claim_block() * claim_block()
* @lock: the spin lock for this block group
* @block: the free block (group relative) to allocate * @block: the free block (group relative) to allocate
* @bh: the bufferhead containts the block group bitmap * @bh: the buffer_head contains the block group bitmap
* *
* We think we can allocate this block in this bitmap. Try to set the bit. * 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 * If that succeeds then check that nobody has allocated and then freed the
...@@ -956,9 +957,11 @@ ext3_try_to_allocate(struct super_block *sb, handle_t *handle, int group, ...@@ -956,9 +957,11 @@ ext3_try_to_allocate(struct super_block *sb, handle_t *handle, int group,
* but we will shift to the place where start_block is, * but we will shift to the place where start_block is,
* then start from there, when looking for a reservable space. * then start from there, when looking for a reservable space.
* *
* @size: the target new reservation window size * @my_rsv: the reservation window
* *
* @group_first_block: the first block we consider to start * @sb: the super block
*
* @start_block: the first block we consider to start
* the real search from * the real search from
* *
* @last_block: * @last_block:
...@@ -1084,7 +1087,7 @@ static int find_next_reservable_window( ...@@ -1084,7 +1087,7 @@ static int find_next_reservable_window(
* *
* failed: we failed to find a reservation window in this group * failed: we failed to find a reservation window in this group
* *
* @rsv: the reservation * @my_rsv: the reservation window
* *
* @grp_goal: The goal (group-relative). It is where the search for a * @grp_goal: The goal (group-relative). It is where the search for a
* free reservable space should start from. * free reservable space should start from.
...@@ -1273,8 +1276,8 @@ static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv, ...@@ -1273,8 +1276,8 @@ static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv,
* @group: given allocation block group * @group: given allocation block group
* @bitmap_bh: bufferhead holds the block bitmap * @bitmap_bh: bufferhead holds the block bitmap
* @grp_goal: given target block within the group * @grp_goal: given target block within the group
* @count: target number of blocks to allocate
* @my_rsv: reservation window * @my_rsv: reservation window
* @count: target number of blocks to allocate
* @errp: pointer to store the error code * @errp: pointer to store the error code
* *
* This is the main function used to allocate a new block and its reservation * This is the main function used to allocate a new block and its reservation
......
...@@ -570,9 +570,14 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode) ...@@ -570,9 +570,14 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)
ei->i_state_flags = 0; ei->i_state_flags = 0;
ext3_set_inode_state(inode, EXT3_STATE_NEW); ext3_set_inode_state(inode, EXT3_STATE_NEW);
/* See comment in ext3_iget for explanation */
if (ino >= EXT3_FIRST_INO(sb) + 1 &&
EXT3_INODE_SIZE(sb) > EXT3_GOOD_OLD_INODE_SIZE) {
ei->i_extra_isize = ei->i_extra_isize =
(EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) ? sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE;
sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE : 0; } else {
ei->i_extra_isize = 0;
}
ret = inode; ret = inode;
dquot_initialize(inode); dquot_initialize(inode);
......
...@@ -498,7 +498,7 @@ static ext3_fsblk_t ext3_find_goal(struct inode *inode, long block, ...@@ -498,7 +498,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 * ext3_blks_to_allocate - Look up the block map and count the number
* of direct blocks need to be allocated for the given branch. * of direct blocks need to be allocated for the given branch.
* *
* @branch: chain of indirect blocks * @branch: chain of indirect blocks
...@@ -536,14 +536,18 @@ static int ext3_blks_to_allocate(Indirect *branch, int k, unsigned long blks, ...@@ -536,14 +536,18 @@ static int ext3_blks_to_allocate(Indirect *branch, int k, unsigned long blks,
} }
/** /**
* ext3_alloc_blocks: multiple allocate blocks needed for a branch * ext3_alloc_blocks - multiple allocate blocks needed for a branch
* @handle: handle for this transaction
* @inode: owner
* @goal: preferred place for allocation
* @indirect_blks: the number of blocks need to allocate for indirect * @indirect_blks: the number of blocks need to allocate for indirect
* blocks * blocks
* * @blks: number of blocks need to allocated for direct blocks
* @new_blocks: on return it will store the new block numbers for * @new_blocks: on return it will store the new block numbers for
* the indirect blocks(if needed) and the first direct block, * the indirect blocks(if needed) and the first direct block,
* @blks: on return it will store the total number of allocated * @err: here we store the error value
* direct blocks *
* return the number of direct blocks allocated
*/ */
static int ext3_alloc_blocks(handle_t *handle, struct inode *inode, static int ext3_alloc_blocks(handle_t *handle, struct inode *inode,
ext3_fsblk_t goal, int indirect_blks, int blks, ext3_fsblk_t goal, int indirect_blks, int blks,
...@@ -598,9 +602,11 @@ static int ext3_alloc_blocks(handle_t *handle, struct inode *inode, ...@@ -598,9 +602,11 @@ static int ext3_alloc_blocks(handle_t *handle, struct inode *inode,
/** /**
* ext3_alloc_branch - allocate and set up a chain of blocks. * ext3_alloc_branch - allocate and set up a chain of blocks.
* @handle: handle for this transaction
* @inode: owner * @inode: owner
* @indirect_blks: number of allocated indirect blocks * @indirect_blks: number of allocated indirect blocks
* @blks: number of allocated direct blocks * @blks: number of allocated direct blocks
* @goal: preferred place for allocation
* @offsets: offsets (in the blocks) to store the pointers to next. * @offsets: offsets (in the blocks) to store the pointers to next.
* @branch: place to store the chain in. * @branch: place to store the chain in.
* *
...@@ -700,10 +706,9 @@ static int ext3_alloc_branch(handle_t *handle, struct inode *inode, ...@@ -700,10 +706,9 @@ static int ext3_alloc_branch(handle_t *handle, struct inode *inode,
/** /**
* ext3_splice_branch - splice the allocated branch onto inode. * ext3_splice_branch - splice the allocated branch onto inode.
* @handle: handle for this transaction
* @inode: owner * @inode: owner
* @block: (logical) number of block we are adding * @block: (logical) number of block we are adding
* @chain: chain of indirect blocks (with a missing link - see
* ext3_alloc_branch)
* @where: location of missing link * @where: location of missing link
* @num: number of indirect blocks we are adding * @num: number of indirect blocks we are adding
* @blks: number of direct blocks we are adding * @blks: number of direct blocks we are adding
...@@ -2530,7 +2535,6 @@ void ext3_truncate(struct inode *inode) ...@@ -2530,7 +2535,6 @@ void ext3_truncate(struct inode *inode)
*/ */
} else { } else {
/* Shared branch grows from an indirect block */ /* Shared branch grows from an indirect block */
BUFFER_TRACE(partial->bh, "get_write_access");
ext3_free_branches(handle, inode, partial->bh, ext3_free_branches(handle, inode, partial->bh,
partial->p, partial->p,
partial->p+1, (chain+n-1) - partial); partial->p+1, (chain+n-1) - partial);
......
...@@ -977,7 +977,8 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es, ...@@ -977,7 +977,8 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
o_blocks_count = le32_to_cpu(es->s_blocks_count); o_blocks_count = le32_to_cpu(es->s_blocks_count);
if (test_opt(sb, DEBUG)) if (test_opt(sb, DEBUG))
printk(KERN_DEBUG "EXT3-fs: extending last group from "E3FSBLK" uto "E3FSBLK" blocks\n", printk(KERN_DEBUG "EXT3-fs: extending last group from "E3FSBLK
" upto "E3FSBLK" blocks\n",
o_blocks_count, n_blocks_count); o_blocks_count, n_blocks_count);
if (n_blocks_count == 0 || n_blocks_count == o_blocks_count) if (n_blocks_count == 0 || n_blocks_count == o_blocks_count)
...@@ -985,7 +986,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es, ...@@ -985,7 +986,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
if (n_blocks_count > (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) { if (n_blocks_count > (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
printk(KERN_ERR "EXT3-fs: filesystem on %s:" printk(KERN_ERR "EXT3-fs: filesystem on %s:"
" too large to resize to %lu blocks safely\n", " too large to resize to "E3FSBLK" blocks safely\n",
sb->s_id, n_blocks_count); sb->s_id, n_blocks_count);
if (sizeof(sector_t) < 8) if (sizeof(sector_t) < 8)
ext3_warning(sb, __func__, ext3_warning(sb, __func__,
...@@ -1065,11 +1066,11 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es, ...@@ -1065,11 +1066,11 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
es->s_blocks_count = cpu_to_le32(o_blocks_count + add); es->s_blocks_count = cpu_to_le32(o_blocks_count + add);
ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
mutex_unlock(&EXT3_SB(sb)->s_resize_lock); mutex_unlock(&EXT3_SB(sb)->s_resize_lock);
ext3_debug("freeing blocks %lu through "E3FSBLK"\n", o_blocks_count, ext3_debug("freeing blocks "E3FSBLK" through "E3FSBLK"\n",
o_blocks_count + add); o_blocks_count, o_blocks_count + add);
ext3_free_blocks_sb(handle, sb, o_blocks_count, add, &freed_blocks); ext3_free_blocks_sb(handle, sb, o_blocks_count, add, &freed_blocks);
ext3_debug("freed blocks "E3FSBLK" through "E3FSBLK"\n", o_blocks_count, ext3_debug("freed blocks "E3FSBLK" through "E3FSBLK"\n",
o_blocks_count + add); o_blocks_count, o_blocks_count + add);
if ((err = ext3_journal_stop(handle))) if ((err = ext3_journal_stop(handle)))
goto exit_put; goto exit_put;
if (test_opt(sb, DEBUG)) if (test_opt(sb, DEBUG))
......
...@@ -1301,9 +1301,9 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es, ...@@ -1301,9 +1301,9 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es,
ext3_msg(sb, KERN_WARNING, ext3_msg(sb, KERN_WARNING,
"warning: mounting fs with errors, " "warning: mounting fs with errors, "
"running e2fsck is recommended"); "running e2fsck is recommended");
else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 && else if ((__s16) le16_to_cpu(es->s_max_mnt_count) > 0 &&
le16_to_cpu(es->s_mnt_count) >= le16_to_cpu(es->s_mnt_count) >=
(unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count)) le16_to_cpu(es->s_max_mnt_count))
ext3_msg(sb, KERN_WARNING, ext3_msg(sb, KERN_WARNING,
"warning: maximal mount count reached, " "warning: maximal mount count reached, "
"running e2fsck is recommended"); "running e2fsck is recommended");
...@@ -1320,7 +1320,7 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es, ...@@ -1320,7 +1320,7 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es,
valid forever! :) */ valid forever! :) */
es->s_state &= cpu_to_le16(~EXT3_VALID_FS); es->s_state &= cpu_to_le16(~EXT3_VALID_FS);
#endif #endif
if (!(__s16) le16_to_cpu(es->s_max_mnt_count)) if (!le16_to_cpu(es->s_max_mnt_count))
es->s_max_mnt_count = cpu_to_le16(EXT3_DFL_MAX_MNT_COUNT); es->s_max_mnt_count = cpu_to_le16(EXT3_DFL_MAX_MNT_COUNT);
le16_add_cpu(&es->s_mnt_count, 1); le16_add_cpu(&es->s_mnt_count, 1);
es->s_mtime = cpu_to_le32(get_seconds()); es->s_mtime = cpu_to_le32(get_seconds());
...@@ -1647,7 +1647,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) ...@@ -1647,7 +1647,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
* Note: s_es must be initialized as soon as possible because * Note: s_es must be initialized as soon as possible because
* some ext3 macro-instructions depend on its value * some ext3 macro-instructions depend on its value
*/ */
es = (struct ext3_super_block *) (((char *)bh->b_data) + offset); es = (struct ext3_super_block *) (bh->b_data + offset);
sbi->s_es = es; sbi->s_es = es;
sb->s_magic = le16_to_cpu(es->s_magic); sb->s_magic = le16_to_cpu(es->s_magic);
if (sb->s_magic != EXT3_SUPER_MAGIC) if (sb->s_magic != EXT3_SUPER_MAGIC)
...@@ -1758,7 +1758,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) ...@@ -1758,7 +1758,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
"error: can't read superblock on 2nd try"); "error: can't read superblock on 2nd try");
goto failed_mount; goto failed_mount;
} }
es = (struct ext3_super_block *)(((char *)bh->b_data) + offset); es = (struct ext3_super_block *)(bh->b_data + offset);
sbi->s_es = es; sbi->s_es = es;
if (es->s_magic != cpu_to_le16(EXT3_SUPER_MAGIC)) { if (es->s_magic != cpu_to_le16(EXT3_SUPER_MAGIC)) {
ext3_msg(sb, KERN_ERR, ext3_msg(sb, KERN_ERR,
...@@ -1857,13 +1857,13 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) ...@@ -1857,13 +1857,13 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) - sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) -
le32_to_cpu(es->s_first_data_block) - 1) le32_to_cpu(es->s_first_data_block) - 1)
/ EXT3_BLOCKS_PER_GROUP(sb)) + 1; / EXT3_BLOCKS_PER_GROUP(sb)) + 1;
db_count = (sbi->s_groups_count + EXT3_DESC_PER_BLOCK(sb) - 1) / db_count = DIV_ROUND_UP(sbi->s_groups_count, EXT3_DESC_PER_BLOCK(sb));
EXT3_DESC_PER_BLOCK(sb);
sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *), sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *),
GFP_KERNEL); GFP_KERNEL);
if (sbi->s_group_desc == NULL) { if (sbi->s_group_desc == NULL) {
ext3_msg(sb, KERN_ERR, ext3_msg(sb, KERN_ERR,
"error: not enough memory"); "error: not enough memory");
ret = -ENOMEM;
goto failed_mount; goto failed_mount;
} }
...@@ -1951,6 +1951,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) ...@@ -1951,6 +1951,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
} }
if (err) { if (err) {
ext3_msg(sb, KERN_ERR, "error: insufficient memory"); ext3_msg(sb, KERN_ERR, "error: insufficient memory");
ret = err;
goto failed_mount3; goto failed_mount3;
} }
...@@ -2159,7 +2160,7 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb, ...@@ -2159,7 +2160,7 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
goto out_bdev; goto out_bdev;
} }
es = (struct ext3_super_block *) (((char *)bh->b_data) + offset); es = (struct ext3_super_block *) (bh->b_data + offset);
if ((le16_to_cpu(es->s_magic) != EXT3_SUPER_MAGIC) || if ((le16_to_cpu(es->s_magic) != EXT3_SUPER_MAGIC) ||
!(le32_to_cpu(es->s_feature_incompat) & !(le32_to_cpu(es->s_feature_incompat) &
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) { EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
...@@ -2352,6 +2353,21 @@ static int ext3_commit_super(struct super_block *sb, ...@@ -2352,6 +2353,21 @@ static int ext3_commit_super(struct super_block *sb,
if (!sbh) if (!sbh)
return error; return error;
if (buffer_write_io_error(sbh)) {
/*
* Oh, dear. A previous attempt to write the
* superblock failed. This could happen because the
* USB device was yanked out. Or it could happen to
* be a transient write error and maybe the block will
* be remapped. Nothing we can do but to retry the
* write and hope for the best.
*/
ext3_msg(sb, KERN_ERR, "previous I/O error to "
"superblock detected");
clear_buffer_write_io_error(sbh);
set_buffer_uptodate(sbh);
}
/* /*
* If the file system is mounted read-only, don't update the * If the file system is mounted read-only, don't update the
* superblock write time. This avoids updating the superblock * superblock write time. This avoids updating the superblock
...@@ -2368,8 +2384,15 @@ static int ext3_commit_super(struct super_block *sb, ...@@ -2368,8 +2384,15 @@ static int ext3_commit_super(struct super_block *sb,
es->s_free_inodes_count = cpu_to_le32(ext3_count_free_inodes(sb)); es->s_free_inodes_count = cpu_to_le32(ext3_count_free_inodes(sb));
BUFFER_TRACE(sbh, "marking dirty"); BUFFER_TRACE(sbh, "marking dirty");
mark_buffer_dirty(sbh); mark_buffer_dirty(sbh);
if (sync) if (sync) {
error = sync_dirty_buffer(sbh); error = sync_dirty_buffer(sbh);
if (buffer_write_io_error(sbh)) {
ext3_msg(sb, KERN_ERR, "I/O error while writing "
"superblock");
clear_buffer_write_io_error(sbh);
set_buffer_uptodate(sbh);
}
}
return error; return error;
} }
......
...@@ -221,7 +221,7 @@ static int __wait_cp_io(journal_t *journal, transaction_t *transaction) ...@@ -221,7 +221,7 @@ static int __wait_cp_io(journal_t *journal, transaction_t *transaction)
goto restart; goto restart;
} }
if (buffer_locked(bh)) { if (buffer_locked(bh)) {
atomic_inc(&bh->b_count); get_bh(bh);
spin_unlock(&journal->j_list_lock); spin_unlock(&journal->j_list_lock);
jbd_unlock_bh_state(bh); jbd_unlock_bh_state(bh);
wait_on_buffer(bh); wait_on_buffer(bh);
...@@ -283,7 +283,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, ...@@ -283,7 +283,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
int ret = 0; int ret = 0;
if (buffer_locked(bh)) { if (buffer_locked(bh)) {
atomic_inc(&bh->b_count); get_bh(bh);
spin_unlock(&journal->j_list_lock); spin_unlock(&journal->j_list_lock);
jbd_unlock_bh_state(bh); jbd_unlock_bh_state(bh);
wait_on_buffer(bh); wait_on_buffer(bh);
......
...@@ -587,13 +587,13 @@ void journal_commit_transaction(journal_t *journal) ...@@ -587,13 +587,13 @@ void journal_commit_transaction(journal_t *journal)
/* Bump b_count to prevent truncate from stumbling over /* Bump b_count to prevent truncate from stumbling over
the shadowed buffer! @@@ This can go if we ever get the shadowed buffer! @@@ This can go if we ever get
rid of the BJ_IO/BJ_Shadow pairing of buffers. */ rid of the BJ_IO/BJ_Shadow pairing of buffers. */
atomic_inc(&jh2bh(jh)->b_count); get_bh(jh2bh(jh));
/* Make a temporary IO buffer with which to write it out /* Make a temporary IO buffer with which to write it out
(this will requeue both the metadata buffer and the (this will requeue both the metadata buffer and the
temporary IO buffer). new_bh goes on BJ_IO*/ temporary IO buffer). new_bh goes on BJ_IO*/
set_bit(BH_JWrite, &jh2bh(jh)->b_state); set_buffer_jwrite(jh2bh(jh));
/* /*
* akpm: journal_write_metadata_buffer() sets * akpm: journal_write_metadata_buffer() sets
* new_bh->b_transaction to commit_transaction. * new_bh->b_transaction to commit_transaction.
...@@ -603,7 +603,7 @@ void journal_commit_transaction(journal_t *journal) ...@@ -603,7 +603,7 @@ void journal_commit_transaction(journal_t *journal)
JBUFFER_TRACE(jh, "ph3: write metadata"); JBUFFER_TRACE(jh, "ph3: write metadata");
flags = journal_write_metadata_buffer(commit_transaction, flags = journal_write_metadata_buffer(commit_transaction,
jh, &new_jh, blocknr); jh, &new_jh, blocknr);
set_bit(BH_JWrite, &jh2bh(new_jh)->b_state); set_buffer_jwrite(jh2bh(new_jh));
wbuf[bufs++] = jh2bh(new_jh); wbuf[bufs++] = jh2bh(new_jh);
/* Record the new block's tag in the current descriptor /* Record the new block's tag in the current descriptor
...@@ -713,7 +713,7 @@ void journal_commit_transaction(journal_t *journal) ...@@ -713,7 +713,7 @@ void journal_commit_transaction(journal_t *journal)
shadowed buffer */ shadowed buffer */
jh = commit_transaction->t_shadow_list->b_tprev; jh = commit_transaction->t_shadow_list->b_tprev;
bh = jh2bh(jh); bh = jh2bh(jh);
clear_bit(BH_JWrite, &bh->b_state); clear_buffer_jwrite(bh);
J_ASSERT_BH(bh, buffer_jbddirty(bh)); J_ASSERT_BH(bh, buffer_jbddirty(bh));
/* The metadata is now released for reuse, but we need /* The metadata is now released for reuse, but we need
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/poison.h> #include <linux/poison.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/ratelimit.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/page.h> #include <asm/page.h>
...@@ -84,6 +85,7 @@ EXPORT_SYMBOL(journal_force_commit); ...@@ -84,6 +85,7 @@ EXPORT_SYMBOL(journal_force_commit);
static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *); static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
static void __journal_abort_soft (journal_t *journal, int errno); static void __journal_abort_soft (journal_t *journal, int errno);
static const char *journal_dev_name(journal_t *journal, char *buffer);
/* /*
* Helper function used to manage commit timeouts * Helper function used to manage commit timeouts
...@@ -439,7 +441,7 @@ int __log_start_commit(journal_t *journal, tid_t target) ...@@ -439,7 +441,7 @@ int __log_start_commit(journal_t *journal, tid_t target)
*/ */
if (!tid_geq(journal->j_commit_request, target)) { if (!tid_geq(journal->j_commit_request, target)) {
/* /*
* We want a new commit: OK, mark the request and wakup the * We want a new commit: OK, mark the request and wakeup the
* commit thread. We do _not_ do the commit ourselves. * commit thread. We do _not_ do the commit ourselves.
*/ */
...@@ -950,6 +952,8 @@ int journal_create(journal_t *journal) ...@@ -950,6 +952,8 @@ int journal_create(journal_t *journal)
if (err) if (err)
return err; return err;
bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
if (unlikely(!bh))
return -ENOMEM;
lock_buffer(bh); lock_buffer(bh);
memset (bh->b_data, 0, journal->j_blocksize); memset (bh->b_data, 0, journal->j_blocksize);
BUFFER_TRACE(bh, "marking dirty"); BUFFER_TRACE(bh, "marking dirty");
...@@ -1010,6 +1014,23 @@ void journal_update_superblock(journal_t *journal, int wait) ...@@ -1010,6 +1014,23 @@ void journal_update_superblock(journal_t *journal, int wait)
goto out; goto out;
} }
if (buffer_write_io_error(bh)) {
char b[BDEVNAME_SIZE];
/*
* Oh, dear. A previous attempt to write the journal
* superblock failed. This could happen because the
* USB device was yanked out. Or it could happen to
* be a transient write error and maybe the block will
* be remapped. Nothing we can do but to retry the
* write and hope for the best.
*/
printk(KERN_ERR "JBD: previous I/O error detected "
"for journal superblock update for %s.\n",
journal_dev_name(journal, b));
clear_buffer_write_io_error(bh);
set_buffer_uptodate(bh);
}
spin_lock(&journal->j_state_lock); spin_lock(&journal->j_state_lock);
jbd_debug(1,"JBD: updating superblock (start %u, seq %d, errno %d)\n", jbd_debug(1,"JBD: updating superblock (start %u, seq %d, errno %d)\n",
journal->j_tail, journal->j_tail_sequence, journal->j_errno); journal->j_tail, journal->j_tail_sequence, journal->j_errno);
...@@ -1021,9 +1042,17 @@ void journal_update_superblock(journal_t *journal, int wait) ...@@ -1021,9 +1042,17 @@ void journal_update_superblock(journal_t *journal, int wait)
BUFFER_TRACE(bh, "marking dirty"); BUFFER_TRACE(bh, "marking dirty");
mark_buffer_dirty(bh); mark_buffer_dirty(bh);
if (wait) if (wait) {
sync_dirty_buffer(bh); sync_dirty_buffer(bh);
else if (buffer_write_io_error(bh)) {
char b[BDEVNAME_SIZE];
printk(KERN_ERR "JBD: I/O error detected "
"when updating journal superblock for %s.\n",
journal_dev_name(journal, b));
clear_buffer_write_io_error(bh);
set_buffer_uptodate(bh);
}
} else
write_dirty_buffer(bh, WRITE); write_dirty_buffer(bh, WRITE);
out: out:
...@@ -1719,7 +1748,6 @@ static void journal_destroy_journal_head_cache(void) ...@@ -1719,7 +1748,6 @@ static void journal_destroy_journal_head_cache(void)
static struct journal_head *journal_alloc_journal_head(void) static struct journal_head *journal_alloc_journal_head(void)
{ {
struct journal_head *ret; struct journal_head *ret;
static unsigned long last_warning;
#ifdef CONFIG_JBD_DEBUG #ifdef CONFIG_JBD_DEBUG
atomic_inc(&nr_journal_heads); atomic_inc(&nr_journal_heads);
...@@ -1727,11 +1755,9 @@ static struct journal_head *journal_alloc_journal_head(void) ...@@ -1727,11 +1755,9 @@ static struct journal_head *journal_alloc_journal_head(void)
ret = kmem_cache_alloc(journal_head_cache, GFP_NOFS); ret = kmem_cache_alloc(journal_head_cache, GFP_NOFS);
if (ret == NULL) { if (ret == NULL) {
jbd_debug(1, "out of memory for journal_head\n"); jbd_debug(1, "out of memory for journal_head\n");
if (time_after(jiffies, last_warning + 5*HZ)) { printk_ratelimited(KERN_NOTICE "ENOMEM in %s, retrying.\n",
printk(KERN_NOTICE "ENOMEM in %s, retrying.\n",
__func__); __func__);
last_warning = jiffies;
}
while (ret == NULL) { while (ret == NULL) {
yield(); yield();
ret = kmem_cache_alloc(journal_head_cache, GFP_NOFS); ret = kmem_cache_alloc(journal_head_cache, GFP_NOFS);
......
...@@ -296,10 +296,10 @@ int journal_skip_recovery(journal_t *journal) ...@@ -296,10 +296,10 @@ int journal_skip_recovery(journal_t *journal)
#ifdef CONFIG_JBD_DEBUG #ifdef CONFIG_JBD_DEBUG
int dropped = info.end_transaction - int dropped = info.end_transaction -
be32_to_cpu(journal->j_superblock->s_sequence); be32_to_cpu(journal->j_superblock->s_sequence);
#endif
jbd_debug(1, jbd_debug(1,
"JBD: ignoring %d transaction%s from the journal.\n", "JBD: ignoring %d transaction%s from the journal.\n",
dropped, (dropped == 1) ? "" : "s"); dropped, (dropped == 1) ? "" : "s");
#endif
journal->j_transaction_sequence = ++info.end_transaction; journal->j_transaction_sequence = ++info.end_transaction;
} }
......
...@@ -293,9 +293,7 @@ handle_t *journal_start(journal_t *journal, int nblocks) ...@@ -293,9 +293,7 @@ handle_t *journal_start(journal_t *journal, int nblocks)
jbd_free_handle(handle); jbd_free_handle(handle);
current->journal_info = NULL; current->journal_info = NULL;
handle = ERR_PTR(err); handle = ERR_PTR(err);
goto out;
} }
out:
return handle; return handle;
} }
...@@ -528,7 +526,7 @@ do_get_write_access(handle_t *handle, struct journal_head *jh, ...@@ -528,7 +526,7 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
transaction = handle->h_transaction; transaction = handle->h_transaction;
journal = transaction->t_journal; journal = transaction->t_journal;
jbd_debug(5, "buffer_head %p, force_copy %d\n", jh, force_copy); jbd_debug(5, "journal_head %p, force_copy %d\n", jh, force_copy);
JBUFFER_TRACE(jh, "entry"); JBUFFER_TRACE(jh, "entry");
repeat: repeat:
...@@ -713,7 +711,7 @@ do_get_write_access(handle_t *handle, struct journal_head *jh, ...@@ -713,7 +711,7 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
J_EXPECT_JH(jh, buffer_uptodate(jh2bh(jh)), J_EXPECT_JH(jh, buffer_uptodate(jh2bh(jh)),
"Possible IO failure.\n"); "Possible IO failure.\n");
page = jh2bh(jh)->b_page; page = jh2bh(jh)->b_page;
offset = ((unsigned long) jh2bh(jh)->b_data) & ~PAGE_MASK; offset = offset_in_page(jh2bh(jh)->b_data);
source = kmap_atomic(page, KM_USER0); source = kmap_atomic(page, KM_USER0);
memcpy(jh->b_frozen_data, source+offset, jh2bh(jh)->b_size); memcpy(jh->b_frozen_data, source+offset, jh2bh(jh)->b_size);
kunmap_atomic(source, KM_USER0); kunmap_atomic(source, KM_USER0);
......
...@@ -478,7 +478,7 @@ int __jbd2_log_start_commit(journal_t *journal, tid_t target) ...@@ -478,7 +478,7 @@ int __jbd2_log_start_commit(journal_t *journal, tid_t target)
*/ */
if (!tid_geq(journal->j_commit_request, target)) { if (!tid_geq(journal->j_commit_request, target)) {
/* /*
* We want a new commit: OK, mark the request and wakup the * We want a new commit: OK, mark the request and wakeup the
* commit thread. We do _not_ do the commit ourselves. * commit thread. We do _not_ do the commit ourselves.
*/ */
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
config QUOTA config QUOTA
bool "Quota support" bool "Quota support"
select QUOTACTL
help help
If you say Y here, you will be able to set per user limits for disk If you say Y here, you will be able to set per user limits for disk
usage (also called disk quotas). Currently, it works for the usage (also called disk quotas). Currently, it works for the
...@@ -65,8 +66,7 @@ config QFMT_V2 ...@@ -65,8 +66,7 @@ config QFMT_V2
config QUOTACTL config QUOTACTL
bool bool
depends on XFS_QUOTA || QUOTA default n
default y
config QUOTACTL_COMPAT config QUOTACTL_COMPAT
bool bool
......
...@@ -1386,6 +1386,9 @@ static void __dquot_initialize(struct inode *inode, int type) ...@@ -1386,6 +1386,9 @@ static void __dquot_initialize(struct inode *inode, int type)
/* Avoid races with quotaoff() */ /* Avoid races with quotaoff() */
if (!sb_has_quota_active(sb, cnt)) if (!sb_has_quota_active(sb, cnt))
continue; continue;
/* We could race with quotaon or dqget() could have failed */
if (!got[cnt])
continue;
if (!inode->i_dquot[cnt]) { if (!inode->i_dquot[cnt]) {
inode->i_dquot[cnt] = got[cnt]; inode->i_dquot[cnt] = got[cnt];
got[cnt] = NULL; got[cnt] = NULL;
...@@ -1736,6 +1739,7 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) ...@@ -1736,6 +1739,7 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
qsize_t rsv_space = 0; qsize_t rsv_space = 0;
struct dquot *transfer_from[MAXQUOTAS] = {}; struct dquot *transfer_from[MAXQUOTAS] = {};
int cnt, ret = 0; int cnt, ret = 0;
char is_valid[MAXQUOTAS] = {};
char warntype_to[MAXQUOTAS]; char warntype_to[MAXQUOTAS];
char warntype_from_inodes[MAXQUOTAS], warntype_from_space[MAXQUOTAS]; char warntype_from_inodes[MAXQUOTAS], warntype_from_space[MAXQUOTAS];
...@@ -1757,8 +1761,15 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) ...@@ -1757,8 +1761,15 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
space = cur_space + rsv_space; space = cur_space + rsv_space;
/* Build the transfer_from list and check the limits */ /* Build the transfer_from list and check the limits */
for (cnt = 0; cnt < MAXQUOTAS; cnt++) { for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
/*
* Skip changes for same uid or gid or for turned off quota-type.
*/
if (!transfer_to[cnt]) if (!transfer_to[cnt])
continue; continue;
/* Avoid races with quotaoff() */
if (!sb_has_quota_active(inode->i_sb, cnt))
continue;
is_valid[cnt] = 1;
transfer_from[cnt] = inode->i_dquot[cnt]; transfer_from[cnt] = inode->i_dquot[cnt];
ret = check_idq(transfer_to[cnt], 1, warntype_to + cnt); ret = check_idq(transfer_to[cnt], 1, warntype_to + cnt);
if (ret) if (ret)
...@@ -1772,12 +1783,8 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) ...@@ -1772,12 +1783,8 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
* Finally perform the needed transfer from transfer_from to transfer_to * Finally perform the needed transfer from transfer_from to transfer_to
*/ */
for (cnt = 0; cnt < MAXQUOTAS; cnt++) { for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
/* if (!is_valid[cnt])
* Skip changes for same uid or gid or for turned off quota-type.
*/
if (!transfer_to[cnt])
continue; continue;
/* Due to IO error we might not have transfer_from[] structure */ /* Due to IO error we might not have transfer_from[] structure */
if (transfer_from[cnt]) { if (transfer_from[cnt]) {
warntype_from_inodes[cnt] = warntype_from_inodes[cnt] =
...@@ -1801,18 +1808,19 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) ...@@ -1801,18 +1808,19 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
mark_all_dquot_dirty(transfer_from); mark_all_dquot_dirty(transfer_from);
mark_all_dquot_dirty(transfer_to); mark_all_dquot_dirty(transfer_to);
/* Pass back references to put */
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
transfer_to[cnt] = transfer_from[cnt];
warn:
flush_warnings(transfer_to, warntype_to); flush_warnings(transfer_to, warntype_to);
flush_warnings(transfer_from, warntype_from_inodes); flush_warnings(transfer_from, warntype_from_inodes);
flush_warnings(transfer_from, warntype_from_space); flush_warnings(transfer_from, warntype_from_space);
return ret; /* Pass back references to put */
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
if (is_valid[cnt])
transfer_to[cnt] = transfer_from[cnt];
return 0;
over_quota: over_quota:
spin_unlock(&dq_data_lock); spin_unlock(&dq_data_lock);
up_write(&sb_dqopt(inode->i_sb)->dqptr_sem); up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
goto warn; flush_warnings(transfer_to, warntype_to);
return ret;
} }
EXPORT_SYMBOL(__dquot_transfer); EXPORT_SYMBOL(__dquot_transfer);
......
...@@ -22,6 +22,7 @@ config XFS_FS ...@@ -22,6 +22,7 @@ config XFS_FS
config XFS_QUOTA config XFS_QUOTA
bool "XFS Quota support" bool "XFS Quota support"
depends on XFS_FS depends on XFS_FS
select QUOTACTL
help help
If you say Y here, you will be able to set limits for disk usage on If you say Y here, you will be able to set limits for disk usage on
a per user and/or a per group basis under XFS. XFS considers quota a per user and/or a per group basis under XFS. XFS considers quota
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment