Commit ac69e092 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

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  ext2/3/4: delete unneeded includes of module.h
  ext{3,4}: Fix potential race when setversion ioctl updates inode
  udf: Mark LVID buffer as uptodate before marking it dirty
  ext3: Don't warn from writepage when readonly inode is spotted after error
  jbd: Remove j_barrier mutex
  reiserfs: Force inode evictions before umount to avoid crash
  reiserfs: Fix quota mount option parsing
  udf: Treat symlink component of type 2 as /
  udf: Fix deadlock when converting file from in-ICB one to normal one
  udf: Cleanup calling convention of inode_getblk()
  ext2: Fix error handling on inode bitmap corruption
  ext3: Fix error handling on inode bitmap corruption
  ext3: replace ll_rw_block with other functions
  ext3: NULL dereference in ext3_evict_inode()
  jbd: clear revoked flag on buffers before a new transaction started
  ext3: call ext3_mark_recovery_complete() when recovery is really needed
parents 9e203936 302bf2f3
...@@ -573,8 +573,11 @@ struct inode *ext2_new_inode(struct inode *dir, umode_t mode, ...@@ -573,8 +573,11 @@ struct inode *ext2_new_inode(struct inode *dir, umode_t mode,
inode->i_generation = sbi->s_next_generation++; inode->i_generation = sbi->s_next_generation++;
spin_unlock(&sbi->s_next_gen_lock); spin_unlock(&sbi->s_next_gen_lock);
if (insert_inode_locked(inode) < 0) { if (insert_inode_locked(inode) < 0) {
err = -EINVAL; ext2_error(sb, "ext2_new_inode",
goto fail_drop; "inode number already in use - inode=%lu",
(unsigned long) ino);
err = -EIO;
goto fail;
} }
dquot_initialize(inode); dquot_initialize(inode);
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include <linux/highuid.h> #include <linux/highuid.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/quotaops.h> #include <linux/quotaops.h>
#include <linux/module.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/mpage.h> #include <linux/mpage.h>
...@@ -36,10 +35,6 @@ ...@@ -36,10 +35,6 @@
#include "acl.h" #include "acl.h"
#include "xip.h" #include "xip.h"
MODULE_AUTHOR("Remy Card and others");
MODULE_DESCRIPTION("Second Extended Filesystem");
MODULE_LICENSE("GPL");
static int __ext2_write_inode(struct inode *inode, int do_sync); static int __ext2_write_inode(struct inode *inode, int do_sync);
/* /*
......
...@@ -1520,5 +1520,8 @@ static void __exit exit_ext2_fs(void) ...@@ -1520,5 +1520,8 @@ static void __exit exit_ext2_fs(void)
exit_ext2_xattr(); exit_ext2_xattr();
} }
MODULE_AUTHOR("Remy Card and others");
MODULE_DESCRIPTION("Second Extended Filesystem");
MODULE_LICENSE("GPL");
module_init(init_ext2_fs) module_init(init_ext2_fs)
module_exit(exit_ext2_fs) module_exit(exit_ext2_fs)
...@@ -54,7 +54,6 @@ ...@@ -54,7 +54,6 @@
*/ */
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mbcache.h> #include <linux/mbcache.h>
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
* Handler for storing security labels as extended attributes. * Handler for storing security labels as extended attributes.
*/ */
#include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/fs.h> #include <linux/fs.h>
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
* Copyright (C) 2003 by Andreas Gruenbacher, <a.gruenbacher@computer.org> * Copyright (C) 2003 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
*/ */
#include <linux/module.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/fs.h> #include <linux/fs.h>
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h>
#include <linux/string.h> #include <linux/string.h>
#include "ext2.h" #include "ext2.h"
#include "xattr.h" #include "xattr.h"
......
...@@ -525,8 +525,12 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, ...@@ -525,8 +525,12 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir,
if (IS_DIRSYNC(inode)) if (IS_DIRSYNC(inode))
handle->h_sync = 1; handle->h_sync = 1;
if (insert_inode_locked(inode) < 0) { if (insert_inode_locked(inode) < 0) {
err = -EINVAL; /*
goto fail_drop; * Likely a bitmap corruption causing inode to be allocated
* twice.
*/
err = -EIO;
goto fail;
} }
spin_lock(&sbi->s_next_gen_lock); spin_lock(&sbi->s_next_gen_lock);
inode->i_generation = sbi->s_next_generation++; inode->i_generation = sbi->s_next_generation++;
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
* Assorted race fixes, rewrite of ext3_get_block() by Al Viro, 2000 * Assorted race fixes, rewrite of ext3_get_block() by Al Viro, 2000
*/ */
#include <linux/module.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/ext3_jbd.h> #include <linux/ext3_jbd.h>
...@@ -223,8 +222,12 @@ void ext3_evict_inode (struct inode *inode) ...@@ -223,8 +222,12 @@ void ext3_evict_inode (struct inode *inode)
* *
* Note that directories do not have this problem because they don't * Note that directories do not have this problem because they don't
* use page cache. * use page cache.
*
* The s_journal check handles the case when ext3_get_journal() fails
* and puts the journal inode.
*/ */
if (inode->i_nlink && ext3_should_journal_data(inode) && if (inode->i_nlink && ext3_should_journal_data(inode) &&
EXT3_SB(inode->i_sb)->s_journal &&
(S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode))) { (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode))) {
tid_t commit_tid = atomic_read(&ei->i_datasync_tid); tid_t commit_tid = atomic_read(&ei->i_datasync_tid);
journal_t *journal = EXT3_SB(inode->i_sb)->s_journal; journal_t *journal = EXT3_SB(inode->i_sb)->s_journal;
...@@ -1132,9 +1135,11 @@ struct buffer_head *ext3_bread(handle_t *handle, struct inode *inode, ...@@ -1132,9 +1135,11 @@ struct buffer_head *ext3_bread(handle_t *handle, struct inode *inode,
bh = ext3_getblk(handle, inode, block, create, err); bh = ext3_getblk(handle, inode, block, create, err);
if (!bh) if (!bh)
return bh; return bh;
if (buffer_uptodate(bh)) if (bh_uptodate_or_lock(bh))
return bh; return bh;
ll_rw_block(READ | REQ_META | REQ_PRIO, 1, &bh); get_bh(bh);
bh->b_end_io = end_buffer_read_sync;
submit_bh(READ | REQ_META | REQ_PRIO, bh);
wait_on_buffer(bh); wait_on_buffer(bh);
if (buffer_uptodate(bh)) if (buffer_uptodate(bh))
return bh; return bh;
...@@ -1617,7 +1622,13 @@ static int ext3_ordered_writepage(struct page *page, ...@@ -1617,7 +1622,13 @@ static int ext3_ordered_writepage(struct page *page,
int err; int err;
J_ASSERT(PageLocked(page)); J_ASSERT(PageLocked(page));
WARN_ON_ONCE(IS_RDONLY(inode)); /*
* We don't want to warn for emergency remount. The condition is
* ordered to avoid dereferencing inode->i_sb in non-error case to
* avoid slow-downs.
*/
WARN_ON_ONCE(IS_RDONLY(inode) &&
!(EXT3_SB(inode->i_sb)->s_mount_state & EXT3_ERROR_FS));
/* /*
* We give up here if we're reentered, because it might be for a * We give up here if we're reentered, because it might be for a
...@@ -1692,7 +1703,13 @@ static int ext3_writeback_writepage(struct page *page, ...@@ -1692,7 +1703,13 @@ static int ext3_writeback_writepage(struct page *page,
int err; int err;
J_ASSERT(PageLocked(page)); J_ASSERT(PageLocked(page));
WARN_ON_ONCE(IS_RDONLY(inode)); /*
* We don't want to warn for emergency remount. The condition is
* ordered to avoid dereferencing inode->i_sb in non-error case to
* avoid slow-downs.
*/
WARN_ON_ONCE(IS_RDONLY(inode) &&
!(EXT3_SB(inode->i_sb)->s_mount_state & EXT3_ERROR_FS));
if (ext3_journal_current_handle()) if (ext3_journal_current_handle())
goto out_fail; goto out_fail;
...@@ -1735,7 +1752,13 @@ static int ext3_journalled_writepage(struct page *page, ...@@ -1735,7 +1752,13 @@ static int ext3_journalled_writepage(struct page *page,
int err; int err;
J_ASSERT(PageLocked(page)); J_ASSERT(PageLocked(page));
WARN_ON_ONCE(IS_RDONLY(inode)); /*
* We don't want to warn for emergency remount. The condition is
* ordered to avoid dereferencing inode->i_sb in non-error case to
* avoid slow-downs.
*/
WARN_ON_ONCE(IS_RDONLY(inode) &&
!(EXT3_SB(inode->i_sb)->s_mount_state & EXT3_ERROR_FS));
if (ext3_journal_current_handle()) if (ext3_journal_current_handle())
goto no_write; goto no_write;
...@@ -2064,12 +2087,10 @@ static int ext3_block_truncate_page(struct inode *inode, loff_t from) ...@@ -2064,12 +2087,10 @@ static int ext3_block_truncate_page(struct inode *inode, loff_t from)
if (PageUptodate(page)) if (PageUptodate(page))
set_buffer_uptodate(bh); set_buffer_uptodate(bh);
if (!buffer_uptodate(bh)) { if (!bh_uptodate_or_lock(bh)) {
err = -EIO; err = bh_submit_read(bh);
ll_rw_block(READ, 1, &bh);
wait_on_buffer(bh);
/* Uhhuh. Read error. Complain and punt. */ /* Uhhuh. Read error. Complain and punt. */
if (!buffer_uptodate(bh)) if (err)
goto unlock; goto unlock;
} }
......
...@@ -134,10 +134,11 @@ long ext3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -134,10 +134,11 @@ long ext3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
goto setversion_out; goto setversion_out;
} }
mutex_lock(&inode->i_mutex);
handle = ext3_journal_start(inode, 1); handle = ext3_journal_start(inode, 1);
if (IS_ERR(handle)) { if (IS_ERR(handle)) {
err = PTR_ERR(handle); err = PTR_ERR(handle);
goto setversion_out; goto unlock_out;
} }
err = ext3_reserve_inode_write(handle, inode, &iloc); err = ext3_reserve_inode_write(handle, inode, &iloc);
if (err == 0) { if (err == 0) {
...@@ -146,6 +147,9 @@ long ext3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -146,6 +147,9 @@ long ext3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
err = ext3_mark_iloc_dirty(handle, inode, &iloc); err = ext3_mark_iloc_dirty(handle, inode, &iloc);
} }
ext3_journal_stop(handle); ext3_journal_stop(handle);
unlock_out:
mutex_unlock(&inode->i_mutex);
setversion_out: setversion_out:
mnt_drop_write_file(filp); mnt_drop_write_file(filp);
return err; return err;
......
...@@ -921,9 +921,12 @@ static struct buffer_head *ext3_find_entry(struct inode *dir, ...@@ -921,9 +921,12 @@ static struct buffer_head *ext3_find_entry(struct inode *dir,
num++; num++;
bh = ext3_getblk(NULL, dir, b++, 0, &err); bh = ext3_getblk(NULL, dir, b++, 0, &err);
bh_use[ra_max] = bh; bh_use[ra_max] = bh;
if (bh) if (bh && !bh_uptodate_or_lock(bh)) {
ll_rw_block(READ | REQ_META | REQ_PRIO, get_bh(bh);
1, &bh); bh->b_end_io = end_buffer_read_sync;
submit_bh(READ | REQ_META | REQ_PRIO,
bh);
}
} }
} }
if ((bh = bh_use[ra_ptr++]) == NULL) if ((bh = bh_use[ra_ptr++]) == NULL)
......
...@@ -2059,9 +2059,10 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) ...@@ -2059,9 +2059,10 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
EXT3_SB(sb)->s_mount_state |= EXT3_ORPHAN_FS; EXT3_SB(sb)->s_mount_state |= EXT3_ORPHAN_FS;
ext3_orphan_cleanup(sb, es); ext3_orphan_cleanup(sb, es);
EXT3_SB(sb)->s_mount_state &= ~EXT3_ORPHAN_FS; EXT3_SB(sb)->s_mount_state &= ~EXT3_ORPHAN_FS;
if (needs_recovery) if (needs_recovery) {
ext3_msg(sb, KERN_INFO, "recovery complete");
ext3_mark_recovery_complete(sb, es); ext3_mark_recovery_complete(sb, es);
ext3_msg(sb, KERN_INFO, "recovery complete");
}
ext3_msg(sb, KERN_INFO, "mounted filesystem with %s data mode", ext3_msg(sb, KERN_INFO, "mounted filesystem with %s data mode",
test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA ? "journal": test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA ? "journal":
test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered": test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
...@@ -2229,12 +2230,12 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb, ...@@ -2229,12 +2230,12 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
goto out_bdev; goto out_bdev;
} }
journal->j_private = sb; journal->j_private = sb;
ll_rw_block(READ, 1, &journal->j_sb_buffer); if (!bh_uptodate_or_lock(journal->j_sb_buffer)) {
wait_on_buffer(journal->j_sb_buffer); if (bh_submit_read(journal->j_sb_buffer)) {
if (!buffer_uptodate(journal->j_sb_buffer)) {
ext3_msg(sb, KERN_ERR, "I/O error on journal device"); ext3_msg(sb, KERN_ERR, "I/O error on journal device");
goto out_journal; goto out_journal;
} }
}
if (be32_to_cpu(journal->j_superblock->s_nr_users) != 1) { if (be32_to_cpu(journal->j_superblock->s_nr_users) != 1) {
ext3_msg(sb, KERN_ERR, ext3_msg(sb, KERN_ERR,
"error: external journal has more than one " "error: external journal has more than one "
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
* Handler for storing security labels as extended attributes. * Handler for storing security labels as extended attributes.
*/ */
#include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/fs.h> #include <linux/fs.h>
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
* Copyright (C) 2003 by Andreas Gruenbacher, <a.gruenbacher@computer.org> * Copyright (C) 2003 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
*/ */
#include <linux/module.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/fs.h> #include <linux/fs.h>
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
* Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org> * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
*/ */
#include <linux/module.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/ext3_jbd.h> #include <linux/ext3_jbd.h>
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/quotaops.h> #include <linux/quotaops.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/module.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
* - smart tree reduction * - smart tree reduction
*/ */
#include <linux/module.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/jbd2.h> #include <linux/jbd2.h>
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
* (sct@redhat.com), 1993, 1998 * (sct@redhat.com), 1993, 1998
*/ */
#include <linux/module.h>
#include "ext4_jbd2.h" #include "ext4_jbd2.h"
#include "truncate.h" #include "truncate.h"
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
* Assorted race fixes, rewrite of ext4_get_block() by Al Viro, 2000 * Assorted race fixes, rewrite of ext4_get_block() by Al Viro, 2000
*/ */
#include <linux/module.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/jbd2.h> #include <linux/jbd2.h>
......
...@@ -158,10 +158,11 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -158,10 +158,11 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
goto setversion_out; goto setversion_out;
} }
mutex_lock(&inode->i_mutex);
handle = ext4_journal_start(inode, 1); handle = ext4_journal_start(inode, 1);
if (IS_ERR(handle)) { if (IS_ERR(handle)) {
err = PTR_ERR(handle); err = PTR_ERR(handle);
goto setversion_out; goto unlock_out;
} }
err = ext4_reserve_inode_write(handle, inode, &iloc); err = ext4_reserve_inode_write(handle, inode, &iloc);
if (err == 0) { if (err == 0) {
...@@ -170,6 +171,9 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -170,6 +171,9 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
err = ext4_mark_iloc_dirty(handle, inode, &iloc); err = ext4_mark_iloc_dirty(handle, inode, &iloc);
} }
ext4_journal_stop(handle); ext4_journal_stop(handle);
unlock_out:
mutex_unlock(&inode->i_mutex);
setversion_out: setversion_out:
mnt_drop_write_file(filp); mnt_drop_write_file(filp);
return err; return err;
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
* *
*/ */
#include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "ext4_jbd2.h" #include "ext4_jbd2.h"
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
* Written by Theodore Ts'o, 2010. * Written by Theodore Ts'o, 2010.
*/ */
#include <linux/module.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/jbd2.h> #include <linux/jbd2.h>
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
* Handler for storing security labels as extended attributes. * Handler for storing security labels as extended attributes.
*/ */
#include <linux/module.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/security.h> #include <linux/security.h>
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
* Copyright (C) 2003 by Andreas Gruenbacher, <a.gruenbacher@computer.org> * Copyright (C) 2003 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
*/ */
#include <linux/module.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/fs.h> #include <linux/fs.h>
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
* Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org> * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
*/ */
#include <linux/module.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/fs.h> #include <linux/fs.h>
#include "ext4_jbd2.h" #include "ext4_jbd2.h"
......
...@@ -391,6 +391,12 @@ void journal_commit_transaction(journal_t *journal) ...@@ -391,6 +391,12 @@ void journal_commit_transaction(journal_t *journal)
jbd_debug (3, "JBD: commit phase 1\n"); jbd_debug (3, "JBD: commit phase 1\n");
/*
* Clear revoked flag to reflect there is no revoked buffers
* in the next transaction which is going to be started.
*/
journal_clear_buffer_revoked_flags(journal);
/* /*
* Switch to a new revoke table. * Switch to a new revoke table.
*/ */
......
...@@ -721,7 +721,6 @@ static journal_t * journal_init_common (void) ...@@ -721,7 +721,6 @@ static journal_t * journal_init_common (void)
init_waitqueue_head(&journal->j_wait_checkpoint); init_waitqueue_head(&journal->j_wait_checkpoint);
init_waitqueue_head(&journal->j_wait_commit); init_waitqueue_head(&journal->j_wait_commit);
init_waitqueue_head(&journal->j_wait_updates); init_waitqueue_head(&journal->j_wait_updates);
mutex_init(&journal->j_barrier);
mutex_init(&journal->j_checkpoint_mutex); mutex_init(&journal->j_checkpoint_mutex);
spin_lock_init(&journal->j_revoke_lock); spin_lock_init(&journal->j_revoke_lock);
spin_lock_init(&journal->j_list_lock); spin_lock_init(&journal->j_list_lock);
......
...@@ -47,6 +47,10 @@ ...@@ -47,6 +47,10 @@
* overwriting the new data. We don't even need to clear the revoke * overwriting the new data. We don't even need to clear the revoke
* bit here. * bit here.
* *
* We cache revoke status of a buffer in the current transaction in b_states
* bits. As the name says, revokevalid flag indicates that the cached revoke
* status of a buffer is valid and we can rely on the cached status.
*
* Revoke information on buffers is a tri-state value: * Revoke information on buffers is a tri-state value:
* *
* RevokeValid clear: no cached revoke status, need to look it up * RevokeValid clear: no cached revoke status, need to look it up
...@@ -479,6 +483,36 @@ int journal_cancel_revoke(handle_t *handle, struct journal_head *jh) ...@@ -479,6 +483,36 @@ int journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
return did_revoke; return did_revoke;
} }
/*
* journal_clear_revoked_flags clears revoked flag of buffers in
* revoke table to reflect there is no revoked buffer in the next
* transaction which is going to be started.
*/
void journal_clear_buffer_revoked_flags(journal_t *journal)
{
struct jbd_revoke_table_s *revoke = journal->j_revoke;
int i = 0;
for (i = 0; i < revoke->hash_size; i++) {
struct list_head *hash_list;
struct list_head *list_entry;
hash_list = &revoke->hash_table[i];
list_for_each(list_entry, hash_list) {
struct jbd_revoke_record_s *record;
struct buffer_head *bh;
record = (struct jbd_revoke_record_s *)list_entry;
bh = __find_get_block(journal->j_fs_dev,
record->blocknr,
journal->j_blocksize);
if (bh) {
clear_buffer_revoked(bh);
__brelse(bh);
}
}
}
}
/* journal_switch_revoke table select j_revoke for next transaction /* journal_switch_revoke table select j_revoke for next transaction
* we do not want to suspend any processing until all revokes are * we do not want to suspend any processing until all revokes are
* written -bzzz * written -bzzz
......
...@@ -426,17 +426,34 @@ int journal_restart(handle_t *handle, int nblocks) ...@@ -426,17 +426,34 @@ int journal_restart(handle_t *handle, int nblocks)
* void journal_lock_updates () - establish a transaction barrier. * void journal_lock_updates () - establish a transaction barrier.
* @journal: Journal to establish a barrier on. * @journal: Journal to establish a barrier on.
* *
* This locks out any further updates from being started, and blocks * This locks out any further updates from being started, and blocks until all
* until all existing updates have completed, returning only once the * existing updates have completed, returning only once the journal is in a
* journal is in a quiescent state with no updates running. * quiescent state with no updates running.
* *
* The journal lock should not be held on entry. * We do not use simple mutex for synchronization as there are syscalls which
* want to return with filesystem locked and that trips up lockdep. Also
* hibernate needs to lock filesystem but locked mutex then blocks hibernation.
* Since locking filesystem is rare operation, we use simple counter and
* waitqueue for locking.
*/ */
void journal_lock_updates(journal_t *journal) void journal_lock_updates(journal_t *journal)
{ {
DEFINE_WAIT(wait); DEFINE_WAIT(wait);
wait:
/* Wait for previous locked operation to finish */
wait_event(journal->j_wait_transaction_locked,
journal->j_barrier_count == 0);
spin_lock(&journal->j_state_lock); spin_lock(&journal->j_state_lock);
/*
* Check reliably under the lock whether we are the ones winning the race
* and locking the journal
*/
if (journal->j_barrier_count > 0) {
spin_unlock(&journal->j_state_lock);
goto wait;
}
++journal->j_barrier_count; ++journal->j_barrier_count;
/* Wait until there are no running updates */ /* Wait until there are no running updates */
...@@ -460,14 +477,6 @@ void journal_lock_updates(journal_t *journal) ...@@ -460,14 +477,6 @@ void journal_lock_updates(journal_t *journal)
spin_lock(&journal->j_state_lock); spin_lock(&journal->j_state_lock);
} }
spin_unlock(&journal->j_state_lock); spin_unlock(&journal->j_state_lock);
/*
* We have now established a barrier against other normal updates, but
* we also need to barrier against other journal_lock_updates() calls
* to make sure that we serialise special journal-locked operations
* too.
*/
mutex_lock(&journal->j_barrier);
} }
/** /**
...@@ -475,14 +484,11 @@ void journal_lock_updates(journal_t *journal) ...@@ -475,14 +484,11 @@ void journal_lock_updates(journal_t *journal)
* @journal: Journal to release the barrier on. * @journal: Journal to release the barrier on.
* *
* Release a transaction barrier obtained with journal_lock_updates(). * Release a transaction barrier obtained with journal_lock_updates().
*
* Should be called without the journal lock held.
*/ */
void journal_unlock_updates (journal_t *journal) void journal_unlock_updates (journal_t *journal)
{ {
J_ASSERT(journal->j_barrier_count != 0); J_ASSERT(journal->j_barrier_count != 0);
mutex_unlock(&journal->j_barrier);
spin_lock(&journal->j_state_lock); spin_lock(&journal->j_state_lock);
--journal->j_barrier_count; --journal->j_barrier_count;
spin_unlock(&journal->j_state_lock); spin_unlock(&journal->j_state_lock);
......
...@@ -455,17 +455,21 @@ int remove_save_link(struct inode *inode, int truncate) ...@@ -455,17 +455,21 @@ int remove_save_link(struct inode *inode, int truncate)
static void reiserfs_kill_sb(struct super_block *s) static void reiserfs_kill_sb(struct super_block *s)
{ {
if (REISERFS_SB(s)) { if (REISERFS_SB(s)) {
if (REISERFS_SB(s)->xattr_root) { /*
d_invalidate(REISERFS_SB(s)->xattr_root); * Force any pending inode evictions to occur now. Any
* inodes to be removed that have extended attributes
* associated with them need to clean them up before
* we can release the extended attribute root dentries.
* shrink_dcache_for_umount will BUG if we don't release
* those before it's called so ->put_super is too late.
*/
shrink_dcache_sb(s);
dput(REISERFS_SB(s)->xattr_root); dput(REISERFS_SB(s)->xattr_root);
REISERFS_SB(s)->xattr_root = NULL; REISERFS_SB(s)->xattr_root = NULL;
}
if (REISERFS_SB(s)->priv_root) {
d_invalidate(REISERFS_SB(s)->priv_root);
dput(REISERFS_SB(s)->priv_root); dput(REISERFS_SB(s)->priv_root);
REISERFS_SB(s)->priv_root = NULL; REISERFS_SB(s)->priv_root = NULL;
} }
}
kill_block_super(s); kill_block_super(s);
} }
...@@ -1249,6 +1253,7 @@ static void handle_quota_files(struct super_block *s, char **qf_names, ...@@ -1249,6 +1253,7 @@ static void handle_quota_files(struct super_block *s, char **qf_names,
kfree(REISERFS_SB(s)->s_qf_names[i]); kfree(REISERFS_SB(s)->s_qf_names[i]);
REISERFS_SB(s)->s_qf_names[i] = qf_names[i]; REISERFS_SB(s)->s_qf_names[i] = qf_names[i];
} }
if (*qfmt)
REISERFS_SB(s)->s_jquota_fmt = *qfmt; REISERFS_SB(s)->s_jquota_fmt = *qfmt;
} }
#endif #endif
......
...@@ -125,7 +125,6 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, ...@@ -125,7 +125,6 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
err = udf_expand_file_adinicb(inode); err = udf_expand_file_adinicb(inode);
if (err) { if (err) {
udf_debug("udf_expand_adinicb: err=%d\n", err); udf_debug("udf_expand_adinicb: err=%d\n", err);
up_write(&iinfo->i_data_sem);
return err; return err;
} }
} else { } else {
...@@ -133,8 +132,9 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, ...@@ -133,8 +132,9 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
iinfo->i_lenAlloc = pos + count; iinfo->i_lenAlloc = pos + count;
else else
iinfo->i_lenAlloc = inode->i_size; iinfo->i_lenAlloc = inode->i_size;
up_write(&iinfo->i_data_sem);
} }
} } else
up_write(&iinfo->i_data_sem); up_write(&iinfo->i_data_sem);
retval = generic_file_aio_write(iocb, iov, nr_segs, ppos); retval = generic_file_aio_write(iocb, iov, nr_segs, ppos);
......
...@@ -53,8 +53,7 @@ static int udf_update_inode(struct inode *, int); ...@@ -53,8 +53,7 @@ static int udf_update_inode(struct inode *, int);
static void udf_fill_inode(struct inode *, struct buffer_head *); static void udf_fill_inode(struct inode *, struct buffer_head *);
static int udf_sync_inode(struct inode *inode); static int udf_sync_inode(struct inode *inode);
static int udf_alloc_i_data(struct inode *inode, size_t size); static int udf_alloc_i_data(struct inode *inode, size_t size);
static struct buffer_head *inode_getblk(struct inode *, sector_t, int *, static sector_t inode_getblk(struct inode *, sector_t, int *, int *);
sector_t *, int *);
static int8_t udf_insert_aext(struct inode *, struct extent_position, static int8_t udf_insert_aext(struct inode *, struct extent_position,
struct kernel_lb_addr, uint32_t); struct kernel_lb_addr, uint32_t);
static void udf_split_extents(struct inode *, int *, int, int, static void udf_split_extents(struct inode *, int *, int, int,
...@@ -151,6 +150,12 @@ const struct address_space_operations udf_aops = { ...@@ -151,6 +150,12 @@ const struct address_space_operations udf_aops = {
.bmap = udf_bmap, .bmap = udf_bmap,
}; };
/*
* Expand file stored in ICB to a normal one-block-file
*
* This function requires i_data_sem for writing and releases it.
* This function requires i_mutex held
*/
int udf_expand_file_adinicb(struct inode *inode) int udf_expand_file_adinicb(struct inode *inode)
{ {
struct page *page; struct page *page;
...@@ -169,9 +174,15 @@ int udf_expand_file_adinicb(struct inode *inode) ...@@ -169,9 +174,15 @@ int udf_expand_file_adinicb(struct inode *inode)
iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
/* from now on we have normal address_space methods */ /* from now on we have normal address_space methods */
inode->i_data.a_ops = &udf_aops; inode->i_data.a_ops = &udf_aops;
up_write(&iinfo->i_data_sem);
mark_inode_dirty(inode); mark_inode_dirty(inode);
return 0; return 0;
} }
/*
* Release i_data_sem so that we can lock a page - page lock ranks
* above i_data_sem. i_mutex still protects us against file changes.
*/
up_write(&iinfo->i_data_sem);
page = find_or_create_page(inode->i_mapping, 0, GFP_NOFS); page = find_or_create_page(inode->i_mapping, 0, GFP_NOFS);
if (!page) if (!page)
...@@ -187,6 +198,7 @@ int udf_expand_file_adinicb(struct inode *inode) ...@@ -187,6 +198,7 @@ int udf_expand_file_adinicb(struct inode *inode)
SetPageUptodate(page); SetPageUptodate(page);
kunmap(page); kunmap(page);
} }
down_write(&iinfo->i_data_sem);
memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0x00, memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0x00,
iinfo->i_lenAlloc); iinfo->i_lenAlloc);
iinfo->i_lenAlloc = 0; iinfo->i_lenAlloc = 0;
...@@ -196,17 +208,20 @@ int udf_expand_file_adinicb(struct inode *inode) ...@@ -196,17 +208,20 @@ int udf_expand_file_adinicb(struct inode *inode)
iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
/* from now on we have normal address_space methods */ /* from now on we have normal address_space methods */
inode->i_data.a_ops = &udf_aops; inode->i_data.a_ops = &udf_aops;
up_write(&iinfo->i_data_sem);
err = inode->i_data.a_ops->writepage(page, &udf_wbc); err = inode->i_data.a_ops->writepage(page, &udf_wbc);
if (err) { if (err) {
/* Restore everything back so that we don't lose data... */ /* Restore everything back so that we don't lose data... */
lock_page(page); lock_page(page);
kaddr = kmap(page); kaddr = kmap(page);
down_write(&iinfo->i_data_sem);
memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr, memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr,
inode->i_size); inode->i_size);
kunmap(page); kunmap(page);
unlock_page(page); unlock_page(page);
iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
inode->i_data.a_ops = &udf_adinicb_aops; inode->i_data.a_ops = &udf_adinicb_aops;
up_write(&iinfo->i_data_sem);
} }
page_cache_release(page); page_cache_release(page);
mark_inode_dirty(inode); mark_inode_dirty(inode);
...@@ -310,7 +325,6 @@ static int udf_get_block(struct inode *inode, sector_t block, ...@@ -310,7 +325,6 @@ static int udf_get_block(struct inode *inode, sector_t block,
struct buffer_head *bh_result, int create) struct buffer_head *bh_result, int create)
{ {
int err, new; int err, new;
struct buffer_head *bh;
sector_t phys = 0; sector_t phys = 0;
struct udf_inode_info *iinfo; struct udf_inode_info *iinfo;
...@@ -323,7 +337,6 @@ static int udf_get_block(struct inode *inode, sector_t block, ...@@ -323,7 +337,6 @@ static int udf_get_block(struct inode *inode, sector_t block,
err = -EIO; err = -EIO;
new = 0; new = 0;
bh = NULL;
iinfo = UDF_I(inode); iinfo = UDF_I(inode);
down_write(&iinfo->i_data_sem); down_write(&iinfo->i_data_sem);
...@@ -332,13 +345,10 @@ static int udf_get_block(struct inode *inode, sector_t block, ...@@ -332,13 +345,10 @@ static int udf_get_block(struct inode *inode, sector_t block,
iinfo->i_next_alloc_goal++; iinfo->i_next_alloc_goal++;
} }
err = 0;
bh = inode_getblk(inode, block, &err, &phys, &new); phys = inode_getblk(inode, block, &err, &new);
BUG_ON(bh); if (!phys)
if (err)
goto abort; goto abort;
BUG_ON(!phys);
if (new) if (new)
set_buffer_new(bh_result); set_buffer_new(bh_result);
...@@ -547,11 +557,10 @@ static int udf_extend_file(struct inode *inode, loff_t newsize) ...@@ -547,11 +557,10 @@ static int udf_extend_file(struct inode *inode, loff_t newsize)
return err; return err;
} }
static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, static sector_t inode_getblk(struct inode *inode, sector_t block,
int *err, sector_t *phys, int *new) int *err, int *new)
{ {
static sector_t last_block; static sector_t last_block;
struct buffer_head *result = NULL;
struct kernel_long_ad laarr[EXTENT_MERGE_SIZE]; struct kernel_long_ad laarr[EXTENT_MERGE_SIZE];
struct extent_position prev_epos, cur_epos, next_epos; struct extent_position prev_epos, cur_epos, next_epos;
int count = 0, startnum = 0, endnum = 0; int count = 0, startnum = 0, endnum = 0;
...@@ -566,6 +575,8 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, ...@@ -566,6 +575,8 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block,
int goal = 0, pgoal = iinfo->i_location.logicalBlockNum; int goal = 0, pgoal = iinfo->i_location.logicalBlockNum;
int lastblock = 0; int lastblock = 0;
*err = 0;
*new = 0;
prev_epos.offset = udf_file_entry_alloc_offset(inode); prev_epos.offset = udf_file_entry_alloc_offset(inode);
prev_epos.block = iinfo->i_location; prev_epos.block = iinfo->i_location;
prev_epos.bh = NULL; prev_epos.bh = NULL;
...@@ -635,8 +646,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, ...@@ -635,8 +646,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block,
brelse(cur_epos.bh); brelse(cur_epos.bh);
brelse(next_epos.bh); brelse(next_epos.bh);
newblock = udf_get_lb_pblock(inode->i_sb, &eloc, offset); newblock = udf_get_lb_pblock(inode->i_sb, &eloc, offset);
*phys = newblock; return newblock;
return NULL;
} }
last_block = block; last_block = block;
...@@ -664,7 +674,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, ...@@ -664,7 +674,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block,
brelse(cur_epos.bh); brelse(cur_epos.bh);
brelse(next_epos.bh); brelse(next_epos.bh);
*err = ret; *err = ret;
return NULL; return 0;
} }
c = 0; c = 0;
offset = 0; offset = 0;
...@@ -729,7 +739,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, ...@@ -729,7 +739,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block,
if (!newblocknum) { if (!newblocknum) {
brelse(prev_epos.bh); brelse(prev_epos.bh);
*err = -ENOSPC; *err = -ENOSPC;
return NULL; return 0;
} }
iinfo->i_lenExtents += inode->i_sb->s_blocksize; iinfo->i_lenExtents += inode->i_sb->s_blocksize;
} }
...@@ -761,10 +771,10 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, ...@@ -761,10 +771,10 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block,
newblock = udf_get_pblock(inode->i_sb, newblocknum, newblock = udf_get_pblock(inode->i_sb, newblocknum,
iinfo->i_location.partitionReferenceNum, 0); iinfo->i_location.partitionReferenceNum, 0);
if (!newblock) if (!newblock) {
return NULL; *err = -EIO;
*phys = newblock; return 0;
*err = 0; }
*new = 1; *new = 1;
iinfo->i_next_alloc_block = block; iinfo->i_next_alloc_block = block;
iinfo->i_next_alloc_goal = newblocknum; iinfo->i_next_alloc_goal = newblocknum;
...@@ -775,7 +785,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, ...@@ -775,7 +785,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block,
else else
mark_inode_dirty(inode); mark_inode_dirty(inode);
return result; return newblock;
} }
static void udf_split_extents(struct inode *inode, int *c, int offset, static void udf_split_extents(struct inode *inode, int *c, int offset,
...@@ -1111,10 +1121,9 @@ int udf_setsize(struct inode *inode, loff_t newsize) ...@@ -1111,10 +1121,9 @@ int udf_setsize(struct inode *inode, loff_t newsize)
if (bsize < if (bsize <
(udf_file_entry_alloc_offset(inode) + newsize)) { (udf_file_entry_alloc_offset(inode) + newsize)) {
err = udf_expand_file_adinicb(inode); err = udf_expand_file_adinicb(inode);
if (err) { if (err)
up_write(&iinfo->i_data_sem);
return err; return err;
} down_write(&iinfo->i_data_sem);
} else } else
iinfo->i_lenAlloc = newsize; iinfo->i_lenAlloc = newsize;
} }
......
...@@ -1798,6 +1798,12 @@ static void udf_close_lvid(struct super_block *sb) ...@@ -1798,6 +1798,12 @@ static void udf_close_lvid(struct super_block *sb)
le16_to_cpu(lvid->descTag.descCRCLength))); le16_to_cpu(lvid->descTag.descCRCLength)));
lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
/*
* We set buffer uptodate unconditionally here to avoid spurious
* warnings from mark_buffer_dirty() when previous EIO has marked
* the buffer as !uptodate
*/
set_buffer_uptodate(bh);
mark_buffer_dirty(bh); mark_buffer_dirty(bh);
sbi->s_lvid_dirty = 0; sbi->s_lvid_dirty = 0;
mutex_unlock(&sbi->s_alloc_mutex); mutex_unlock(&sbi->s_alloc_mutex);
......
...@@ -41,10 +41,16 @@ static void udf_pc_to_char(struct super_block *sb, unsigned char *from, ...@@ -41,10 +41,16 @@ static void udf_pc_to_char(struct super_block *sb, unsigned char *from,
pc = (struct pathComponent *)(from + elen); pc = (struct pathComponent *)(from + elen);
switch (pc->componentType) { switch (pc->componentType) {
case 1: case 1:
if (pc->lengthComponentIdent == 0) { /*
* Symlink points to some place which should be agreed
* upon between originator and receiver of the media. Ignore.
*/
if (pc->lengthComponentIdent > 0)
break;
/* Fall through */
case 2:
p = to; p = to;
*p++ = '/'; *p++ = '/';
}
break; break;
case 3: case 3:
memcpy(p, "../", 3); memcpy(p, "../", 3);
......
...@@ -497,7 +497,6 @@ struct transaction_s ...@@ -497,7 +497,6 @@ struct transaction_s
* @j_format_version: Version of the superblock format * @j_format_version: Version of the superblock format
* @j_state_lock: Protect the various scalars in the journal * @j_state_lock: Protect the various scalars in the journal
* @j_barrier_count: Number of processes waiting to create a barrier lock * @j_barrier_count: Number of processes waiting to create a barrier lock
* @j_barrier: The barrier lock itself
* @j_running_transaction: The current running transaction.. * @j_running_transaction: The current running transaction..
* @j_committing_transaction: the transaction we are pushing to disk * @j_committing_transaction: the transaction we are pushing to disk
* @j_checkpoint_transactions: a linked circular list of all transactions * @j_checkpoint_transactions: a linked circular list of all transactions
...@@ -580,9 +579,6 @@ struct journal_s ...@@ -580,9 +579,6 @@ struct journal_s
*/ */
int j_barrier_count; int j_barrier_count;
/* The barrier lock itself */
struct mutex j_barrier;
/* /*
* Transactions: The current running transaction... * Transactions: The current running transaction...
* [j_state_lock] [caller holding open handle] * [j_state_lock] [caller holding open handle]
...@@ -913,6 +909,7 @@ extern int journal_set_revoke(journal_t *, unsigned int, tid_t); ...@@ -913,6 +909,7 @@ extern int journal_set_revoke(journal_t *, unsigned int, tid_t);
extern int journal_test_revoke(journal_t *, unsigned int, tid_t); extern int journal_test_revoke(journal_t *, unsigned int, tid_t);
extern void journal_clear_revoke(journal_t *); extern void journal_clear_revoke(journal_t *);
extern void journal_switch_revoke_table(journal_t *journal); extern void journal_switch_revoke_table(journal_t *journal);
extern void journal_clear_buffer_revoked_flags(journal_t *journal);
/* /*
* The log thread user interface: * The log thread user interface:
......
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