Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 11 Dec 2009 23:31:13 +0000 (15:31 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 11 Dec 2009 23:31:13 +0000 (15:31 -0800)
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs-2.6: (21 commits)
  ext3: PTR_ERR return of wrong pointer in setup_new_group_blocks()
  ext3: Fix data / filesystem corruption when write fails to copy data
  ext4: Support for 64-bit quota format
  ext3: Support for vfsv1 quota format
  quota: Implement quota format with 64-bit space and inode limits
  quota: Move definition of QFMT_OCFS2 to linux/quota.h
  ext2: fix comment in ext2_find_entry about return values
  ext3: Unify log messages in ext3
  ext2: clear uptodate flag on super block I/O error
  ext2: Unify log messages in ext2
  ext3: make "norecovery" an alias for "noload"
  ext3: Don't update the superblock in ext3_statfs()
  ext3: journal all modifications in ext3_xattr_set_handle
  ext2: Explicitly assign values to on-disk enum of filetypes
  quota: Fix WARN_ON in lookup_one_len
  const: struct quota_format_ops
  ubifs: remove manual O_SYNC handling
  afs: remove manual O_SYNC handling
  kill wait_on_page_writeback_range
  vfs: Implement proper O_SYNC semantics
  ...

50 files changed:
Documentation/filesystems/ext3.txt
Documentation/filesystems/vfs.txt
arch/alpha/include/asm/fcntl.h
arch/blackfin/include/asm/fcntl.h
arch/mips/include/asm/fcntl.h
arch/mips/kernel/kspd.c
arch/mips/loongson/common/mem.c
arch/mips/mm/cache.c
arch/parisc/include/asm/fcntl.h
arch/sparc/include/asm/fcntl.h
arch/x86/mm/pat.c
drivers/char/mem.c
drivers/usb/gadget/file_storage.c
fs/afs/write.c
fs/btrfs/file.c
fs/cifs/dir.c
fs/cifs/file.c
fs/ext2/dir.c
fs/ext2/ext2.h
fs/ext2/inode.c
fs/ext2/super.c
fs/ext2/xip.c
fs/ext3/inode.c
fs/ext3/resize.c
fs/ext3/super.c
fs/ext3/xattr.c
fs/ext4/super.c
fs/isofs/compress.c
fs/isofs/rock.c
fs/jbd2/commit.c
fs/namei.c
fs/nfs/file.c
fs/nfs/write.c
fs/ocfs2/file.c
fs/ocfs2/quota.h
fs/ocfs2/quota_local.c
fs/quota/Kconfig
fs/quota/dquot.c
fs/quota/quota_v1.c
fs/quota/quota_v2.c
fs/quota/quotaio_v2.h
fs/sync.c
fs/xfs/linux-2.6/xfs_lrw.c
include/asm-generic/fcntl.h
include/linux/ext2_fs.h
include/linux/ext3_fs.h
include/linux/fs.h
include/linux/quota.h
mm/filemap.c
sound/core/rawmidi.c

index 05d5cf1..867c5b5 100644 (file)
@@ -32,8 +32,8 @@ journal_dev=devnum    When the external journal device's major/minor numbers
                        identified through its new major/minor numbers encoded
                        in devnum.
 
-noload                 Don't load the journal on mounting. Note that this forces
-                       mount of inconsistent filesystem, which can lead to
+norecovery             Don't load the journal on mounting. Note that this forces
+noload                 mount of inconsistent filesystem, which can lead to
                        various problems.
 
 data=journal           All data are committed into the journal prior to being
index 623f094..3de2f32 100644 (file)
@@ -472,7 +472,7 @@ __sync_single_inode) to check if ->writepages has been successful in
 writing out the whole address_space.
 
 The Writeback tag is used by filemap*wait* and sync_page* functions,
-via wait_on_page_writeback_range, to wait for all writeback to
+via filemap_fdatawait_range, to wait for all writeback to
 complete.  While waiting ->sync_page (if defined) will be called on
 each page that is found to require writeback.
 
index 25da001..21b1117 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef _ALPHA_FCNTL_H
 #define _ALPHA_FCNTL_H
 
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
 #define O_CREAT                 01000  /* not fcntl */
 #define O_TRUNC                 02000  /* not fcntl */
 #define O_EXCL          04000  /* not fcntl */
 
 #define O_NONBLOCK      00004
 #define O_APPEND        00010
-#define O_SYNC         040000
+#define O_DSYNC                040000  /* used to be O_SYNC, see below */
 #define O_DIRECTORY    0100000 /* must be a directory */
 #define O_NOFOLLOW     0200000 /* don't follow links */
 #define O_LARGEFILE    0400000 /* will be set by the kernel on every open */
 #define O_DIRECT       02000000 /* direct disk access - should check with OSF/1 */
 #define O_NOATIME      04000000
 #define O_CLOEXEC      010000000 /* set close_on_exec */
+/*
+ * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
+ * the O_SYNC flag.  We continue to use the existing numerical value
+ * for O_DSYNC semantics now, but using the correct symbolic name for it.
+ * This new value is used to request true Posix O_SYNC semantics.  It is
+ * defined in this strange way to make sure applications compiled against
+ * new headers get at least O_DSYNC semantics on older kernels.
+ *
+ * This has the nice side-effect that we can simply test for O_DSYNC
+ * wherever we do not care if O_DSYNC or O_SYNC is used.
+ *
+ * Note: __O_SYNC must never be used directly.
+ */
+#define __O_SYNC       020000000
+#define O_SYNC         (__O_SYNC|O_DSYNC)
 
 #define F_GETLK                7
 #define F_SETLK                8
index 8727b2b..251c911 100644 (file)
@@ -7,8 +7,6 @@
 #ifndef _BFIN_FCNTL_H
 #define _BFIN_FCNTL_H
 
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
 #define O_DIRECTORY     040000 /* must be a directory */
 #define O_NOFOLLOW     0100000 /* don't follow links */
 #define O_DIRECT       0200000 /* direct disk access hint - currently ignored */
index 2a52333..7c6681a 100644 (file)
@@ -10,7 +10,7 @@
 
 
 #define O_APPEND       0x0008
-#define O_SYNC         0x0010
+#define O_DSYNC                0x0010  /* used to be O_SYNC, see below */
 #define O_NONBLOCK     0x0080
 #define O_CREAT         0x0100 /* not fcntl */
 #define O_TRUNC                0x0200  /* not fcntl */
 #define O_NOCTTY       0x0800  /* not fcntl */
 #define FASYNC         0x1000  /* fcntl, for BSD compatibility */
 #define O_LARGEFILE    0x2000  /* allow large file opens */
+/*
+ * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
+ * the O_SYNC flag.  We continue to use the existing numerical value
+ * for O_DSYNC semantics now, but using the correct symbolic name for it.
+ * This new value is used to request true Posix O_SYNC semantics.  It is
+ * defined in this strange way to make sure applications compiled against
+ * new headers get at least O_DSYNC semantics on older kernels.
+ *
+ * This has the nice side-effect that we can simply test for O_DSYNC
+ * wherever we do not care if O_DSYNC or O_SYNC is used.
+ *
+ * Note: __O_SYNC must never be used directly.
+ */
+#define __O_SYNC       0x4000
+#define O_SYNC         (__O_SYNC|O_DSYNC)
 #define O_DIRECT       0x8000  /* direct disk access hint */
 
 #define F_GETLK                14
index ad4e017..80e2ba6 100644 (file)
@@ -82,6 +82,7 @@ static int sp_stopping;
 #define MTSP_O_SHLOCK          0x0010
 #define MTSP_O_EXLOCK          0x0020
 #define MTSP_O_ASYNC           0x0040
+/* XXX: check which of these is actually O_SYNC vs O_DSYNC */
 #define MTSP_O_FSYNC           O_SYNC
 #define MTSP_O_NOFOLLOW                0x0100
 #define MTSP_O_SYNC            0x0080
index 7c92f79..e94ef15 100644 (file)
@@ -26,7 +26,7 @@ void __init prom_init_memory(void)
 /* override of arch/mips/mm/cache.c: __uncached_access */
 int __uncached_access(struct file *file, unsigned long addr)
 {
-       if (file->f_flags & O_SYNC)
+       if (file->f_flags & O_DSYNC)
                return 1;
 
        return addr >= __pa(high_memory) ||
index 694d51f..102b2df 100644 (file)
@@ -194,7 +194,7 @@ void __devinit cpu_cache_init(void)
 
 int __weak __uncached_access(struct file *file, unsigned long addr)
 {
-       if (file->f_flags & O_SYNC)
+       if (file->f_flags & O_DSYNC)
                return 1;
 
        return addr >= __pa(high_memory);
index 1e1c824..f357fc6 100644 (file)
@@ -1,14 +1,13 @@
 #ifndef _PARISC_FCNTL_H
 #define _PARISC_FCNTL_H
 
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
 #define O_APPEND       000000010
 #define O_BLKSEEK      000000100 /* HPUX only */
 #define O_CREAT                000000400 /* not fcntl */
 #define O_EXCL         000002000 /* not fcntl */
 #define O_LARGEFILE    000004000
-#define O_SYNC         000100000
+#define __O_SYNC       000100000
+#define O_SYNC         (__O_SYNC|O_DSYNC)
 #define O_NONBLOCK     000200004 /* HPUX has separate NDELAY & NONBLOCK */
 #define O_NOCTTY       000400000 /* not fcntl */
 #define O_DSYNC                001000000 /* HPUX only */
index d4d9c9d..3b9cfb3 100644 (file)
@@ -1,14 +1,12 @@
 #ifndef _SPARC_FCNTL_H
 #define _SPARC_FCNTL_H
 
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
 #define O_APPEND       0x0008
 #define FASYNC         0x0040  /* fcntl, for BSD compatibility */
 #define O_CREAT                0x0200  /* not fcntl */
 #define O_TRUNC                0x0400  /* not fcntl */
 #define O_EXCL         0x0800  /* not fcntl */
-#define O_SYNC         0x2000
+#define O_DSYNC                0x2000  /* used to be O_SYNC, see below */
 #define O_NONBLOCK     0x4000
 #if defined(__sparc__) && defined(__arch64__)
 #define O_NDELAY       0x0004
 #define O_DIRECT        0x100000 /* direct disk access hint */
 #define O_NOATIME      0x200000
 #define O_CLOEXEC      0x400000
+/*
+ * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
+ * the O_SYNC flag.  We continue to use the existing numerical value
+ * for O_DSYNC semantics now, but using the correct symbolic name for it.
+ * This new value is used to request true Posix O_SYNC semantics.  It is
+ * defined in this strange way to make sure applications compiled against
+ * new headers get at least O_DSYNC semantics on older kernels.
+ *
+ * This has the nice side-effect that we can simply test for O_DSYNC
+ * wherever we do not care if O_DSYNC or O_SYNC is used.
+ *
+ * Note: __O_SYNC must never be used directly.
+ */
+#define __O_SYNC       0x800000
+#define O_SYNC         (__O_SYNC|O_DSYNC)
 
 #define F_GETOWN       5       /*  for sockets. */
 #define F_SETOWN       6       /*  for sockets. */
index 66b55d6..ae9648e 100644 (file)
@@ -704,9 +704,8 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
        if (!range_is_allowed(pfn, size))
                return 0;
 
-       if (file->f_flags & O_SYNC) {
+       if (file->f_flags & O_DSYNC)
                flags = _PAGE_CACHE_UC_MINUS;
-       }
 
 #ifdef CONFIG_X86_32
        /*
index 30eff80..fba76fb 100644 (file)
@@ -43,7 +43,7 @@ static inline int uncached_access(struct file *file, unsigned long addr)
 {
 #if defined(CONFIG_IA64)
        /*
-        * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases.
+        * On ia64, we ignore O_DSYNC because we cannot tolerate memory attribute aliases.
         */
        return !(efi_mem_attributes(addr) & EFI_MEMORY_WB);
 #elif defined(CONFIG_MIPS)
@@ -56,9 +56,9 @@ static inline int uncached_access(struct file *file, unsigned long addr)
 #else
        /*
         * Accessing memory above the top the kernel knows about or through a file pointer
-        * that was marked O_SYNC will be done non-cached.
+        * that was marked O_DSYNC will be done non-cached.
         */
-       if (file->f_flags & O_SYNC)
+       if (file->f_flags & O_DSYNC)
                return 1;
        return addr >= __pa(high_memory);
 #endif
index fca3407..29dfb02 100644 (file)
@@ -1274,7 +1274,7 @@ static int do_write(struct fsg_dev *fsg)
                }
                if (fsg->cmnd[1] & 0x08) {      // FUA
                        spin_lock(&curlun->filp->f_lock);
-                       curlun->filp->f_flags |= O_SYNC;
+                       curlun->filp->f_flags |= O_DSYNC;
                        spin_unlock(&curlun->filp->f_lock);
                }
        }
index c63a3c8..5e15a21 100644 (file)
@@ -671,7 +671,6 @@ ssize_t afs_file_write(struct kiocb *iocb, const struct iovec *iov,
        struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
        ssize_t result;
        size_t count = iov_length(iov, nr_segs);
-       int ret;
 
        _enter("{%x.%u},{%zu},%lu,",
               vnode->fid.vid, vnode->fid.vnode, count, nr_segs);
@@ -691,13 +690,6 @@ ssize_t afs_file_write(struct kiocb *iocb, const struct iovec *iov,
                return result;
        }
 
-       /* return error values for O_SYNC and IS_SYNC() */
-       if (IS_SYNC(&vnode->vfs_inode) || iocb->ki_filp->f_flags & O_SYNC) {
-               ret = afs_fsync(iocb->ki_filp, dentry, 1);
-               if (ret < 0)
-                       result = ret;
-       }
-
        _leave(" = %zd", result);
        return result;
 }
index 06550af..77f7593 100644 (file)
@@ -909,7 +909,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
        unsigned long last_index;
        int will_write;
 
-       will_write = ((file->f_flags & O_SYNC) || IS_SYNC(inode) ||
+       will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) ||
                      (file->f_flags & O_DIRECT));
 
        nrptrs = min((count + PAGE_CACHE_SIZE - 1) / PAGE_CACHE_SIZE,
@@ -1076,7 +1076,7 @@ out_nolock:
                if (err)
                        num_written = err;
 
-               if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
+               if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) {
                        trans = btrfs_start_transaction(root, 1);
                        ret = btrfs_log_dentry_safe(trans, root,
                                                    file->f_dentry);
index 1f42f77..6ccf726 100644 (file)
@@ -214,7 +214,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
                posix_flags |= SMB_O_EXCL;
        if (oflags & O_TRUNC)
                posix_flags |= SMB_O_TRUNC;
-       if (oflags & O_SYNC)
+       /* be safe and imply O_SYNC for O_DSYNC */
+       if (oflags & O_DSYNC)
                posix_flags |= SMB_O_SYNC;
        if (oflags & O_DIRECTORY)
                posix_flags |= SMB_O_DIRECTORY;
index 429337e..057e1da 100644 (file)
@@ -76,8 +76,10 @@ static inline fmode_t cifs_posix_convert_flags(unsigned int flags)
           reopening a file.  They had their effect on the original open */
        if (flags & O_APPEND)
                posix_flags |= (fmode_t)O_APPEND;
-       if (flags & O_SYNC)
-               posix_flags |= (fmode_t)O_SYNC;
+       if (flags & O_DSYNC)
+               posix_flags |= (fmode_t)O_DSYNC;
+       if (flags & __O_SYNC)
+               posix_flags |= (fmode_t)__O_SYNC;
        if (flags & O_DIRECTORY)
                posix_flags |= (fmode_t)O_DIRECTORY;
        if (flags & O_NOFOLLOW)
index 6cde970..fc2bd05 100644 (file)
@@ -353,8 +353,8 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
  *     ext2_find_entry()
  *
  * finds an entry in the specified directory with the wanted name. It
- * returns the page in which the entry was found, and the entry itself
- * (as a parameter - res_dir). Page is returned mapped and unlocked.
+ * returns the page in which the entry was found (as a parameter - res_page),
+ * and the entry itself. Page is returned mapped and unlocked.
  * Entry is guaranteed to be valid.
  */
 struct ext2_dir_entry_2 *ext2_find_entry (struct inode * dir,
index 9a8a8e2..da318b0 100644 (file)
@@ -142,7 +142,7 @@ struct dentry *ext2_get_parent(struct dentry *child);
 /* super.c */
 extern void ext2_error (struct super_block *, const char *, const char *, ...)
        __attribute__ ((format (printf, 3, 4)));
-extern void ext2_warning (struct super_block *, const char *, const char *, ...)
+extern void ext2_msg(struct super_block *, const char *, const char *, ...)
        __attribute__ ((format (printf, 3, 4)));
 extern void ext2_update_dynamic_rev (struct super_block *sb);
 extern void ext2_write_super (struct super_block *);
index ade6340..71b032c 100644 (file)
@@ -137,7 +137,8 @@ static int ext2_block_to_path(struct inode *inode,
        int final = 0;
 
        if (i_block < 0) {
-               ext2_warning (inode->i_sb, "ext2_block_to_path", "block < 0");
+               ext2_msg(inode->i_sb, KERN_WARNING,
+                       "warning: %s: block < 0", __func__);
        } else if (i_block < direct_blocks) {
                offsets[n++] = i_block;
                final = direct_blocks;
@@ -157,7 +158,8 @@ static int ext2_block_to_path(struct inode *inode,
                offsets[n++] = i_block & (ptrs - 1);
                final = ptrs;
        } else {
-               ext2_warning (inode->i_sb, "ext2_block_to_path", "block > big");
+               ext2_msg(inode->i_sb, KERN_WARNING,
+                       "warning: %s: block is too big", __func__);
        }
        if (boundary)
                *boundary = final - 1 - (i_block & (ptrs - 1));
index 1a9ffee..1388802 100644 (file)
@@ -58,27 +58,27 @@ void ext2_error (struct super_block * sb, const char * function,
        }
 
        va_start(args, fmt);
-       printk(KERN_CRIT "EXT2-fs error (device %s): %s: ",sb->s_id, function);
+       printk(KERN_CRIT "EXT2-fs (%s): error: %s: ", sb->s_id, function);
        vprintk(fmt, args);
        printk("\n");
        va_end(args);
 
        if (test_opt(sb, ERRORS_PANIC))
-               panic("EXT2-fs panic from previous error\n");
+               panic("EXT2-fs: panic from previous error\n");
        if (test_opt(sb, ERRORS_RO)) {
-               printk("Remounting filesystem read-only\n");
+               ext2_msg(sb, KERN_CRIT,
+                            "error: remounting filesystem read-only");
                sb->s_flags |= MS_RDONLY;
        }
 }
 
-void ext2_warning (struct super_block * sb, const char * function,
-                  const char * fmt, ...)
+void ext2_msg(struct super_block *sb, const char *prefix,
+               const char *fmt, ...)
 {
        va_list args;
 
        va_start(args, fmt);
-       printk(KERN_WARNING "EXT2-fs warning (device %s): %s: ",
-              sb->s_id, function);
+       printk("%sEXT2-fs (%s): ", prefix, sb->s_id);
        vprintk(fmt, args);
        printk("\n");
        va_end(args);
@@ -91,9 +91,9 @@ void ext2_update_dynamic_rev(struct super_block *sb)
        if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV)
                return;
 
-       ext2_warning(sb, __func__,
-                    "updating to rev %d because of new feature flag, "
-                    "running e2fsck is recommended",
+       ext2_msg(sb, KERN_WARNING,
+                    "warning: updating to rev %d because of "
+                    "new feature flag, running e2fsck is recommended",
                     EXT2_DYNAMIC_REV);
 
        es->s_first_ino = cpu_to_le32(EXT2_GOOD_OLD_FIRST_INO);
@@ -419,10 +419,10 @@ static const match_table_t tokens = {
        {Opt_err, NULL}
 };
 
-static int parse_options (char * options,
-                         struct ext2_sb_info *sbi)
+static int parse_options(char *options, struct super_block *sb)
 {
-       char * p;
+       char *p;
+       struct ext2_sb_info *sbi = EXT2_SB(sb);
        substring_t args[MAX_OPT_ARGS];
        int option;
 
@@ -505,7 +505,8 @@ static int parse_options (char * options,
 #else
                case Opt_user_xattr:
                case Opt_nouser_xattr:
-                       printk("EXT2 (no)user_xattr options not supported\n");
+                       ext2_msg(sb, KERN_INFO, "(no)user_xattr options"
+                               "not supported");
                        break;
 #endif
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
@@ -518,14 +519,15 @@ static int parse_options (char * options,
 #else
                case Opt_acl:
                case Opt_noacl:
-                       printk("EXT2 (no)acl options not supported\n");
+                       ext2_msg(sb, KERN_INFO,
+                               "(no)acl options not supported");
                        break;
 #endif
                case Opt_xip:
 #ifdef CONFIG_EXT2_FS_XIP
                        set_opt (sbi->s_mount_opt, XIP);
 #else
-                       printk("EXT2 xip option not supported\n");
+                       ext2_msg(sb, KERN_INFO, "xip option not supported");
 #endif
                        break;
 
@@ -542,19 +544,18 @@ static int parse_options (char * options,
                case Opt_quota:
                case Opt_usrquota:
                case Opt_grpquota:
-                       printk(KERN_ERR
-                               "EXT2-fs: quota operations not supported.\n");
-
+                       ext2_msg(sb, KERN_INFO,
+                               "quota operations not supported");
                        break;
 #endif
 
                case Opt_reservation:
                        set_opt(sbi->s_mount_opt, RESERVATION);
-                       printk("reservations ON\n");
+                       ext2_msg(sb, KERN_INFO, "reservations ON");
                        break;
                case Opt_noreservation:
                        clear_opt(sbi->s_mount_opt, RESERVATION);
-                       printk("reservations OFF\n");
+                       ext2_msg(sb, KERN_INFO, "reservations OFF");
                        break;
                case Opt_ignore:
                        break;
@@ -573,34 +574,40 @@ static int ext2_setup_super (struct super_block * sb,
        struct ext2_sb_info *sbi = EXT2_SB(sb);
 
        if (le32_to_cpu(es->s_rev_level) > EXT2_MAX_SUPP_REV) {
-               printk ("EXT2-fs warning: revision level too high, "
-                       "forcing read-only mode\n");
+               ext2_msg(sb, KERN_ERR,
+                       "error: revision level too high, "
+                       "forcing read-only mode");
                res = MS_RDONLY;
        }
        if (read_only)
                return res;
        if (!(sbi->s_mount_state & EXT2_VALID_FS))
-               printk ("EXT2-fs warning: mounting unchecked fs, "
-                       "running e2fsck is recommended\n");
+               ext2_msg(sb, KERN_WARNING,
+                       "warning: mounting unchecked fs, "
+                       "running e2fsck is recommended");
        else if ((sbi->s_mount_state & EXT2_ERROR_FS))
-               printk ("EXT2-fs warning: mounting fs with errors, "
-                       "running e2fsck is recommended\n");
+               ext2_msg(sb, KERN_WARNING,
+                       "warning: mounting fs with errors, "
+                       "running e2fsck is recommended");
        else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 &&
                 le16_to_cpu(es->s_mnt_count) >=
                 (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count))
-               printk ("EXT2-fs warning: maximal mount count reached, "
-                       "running e2fsck is recommended\n");
+               ext2_msg(sb, KERN_WARNING,
+                       "warning: maximal mount count reached, "
+                       "running e2fsck is recommended");
        else if (le32_to_cpu(es->s_checkinterval) &&
-               (le32_to_cpu(es->s_lastcheck) + le32_to_cpu(es->s_checkinterval) <= get_seconds()))
-               printk ("EXT2-fs warning: checktime reached, "
-                       "running e2fsck is recommended\n");
+               (le32_to_cpu(es->s_lastcheck) +
+                       le32_to_cpu(es->s_checkinterval) <= get_seconds()))
+               ext2_msg(sb, KERN_WARNING,
+                       "warning: checktime reached, "
+                       "running e2fsck is recommended");
        if (!le16_to_cpu(es->s_max_mnt_count))
                es->s_max_mnt_count = cpu_to_le16(EXT2_DFL_MAX_MNT_COUNT);
        le16_add_cpu(&es->s_mnt_count, 1);
        ext2_write_super(sb);
        if (test_opt (sb, DEBUG))
-               printk ("[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, "
-                       "bpg=%lu, ipg=%lu, mo=%04lx]\n",
+               ext2_msg(sb, KERN_INFO, "%s, %s, bs=%lu, fs=%lu, gc=%lu, "
+                       "bpg=%lu, ipg=%lu, mo=%04lx]",
                        EXT2FS_VERSION, EXT2FS_DATE, sb->s_blocksize,
                        sbi->s_frag_size,
                        sbi->s_groups_count,
@@ -767,7 +774,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
         */
        blocksize = sb_min_blocksize(sb, BLOCK_SIZE);
        if (!blocksize) {
-               printk ("EXT2-fs: unable to set blocksize\n");
+               ext2_msg(sb, KERN_ERR, "error: unable to set blocksize");
                goto failed_sbi;
        }
 
@@ -783,7 +790,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
        }
 
        if (!(bh = sb_bread(sb, logic_sb_block))) {
-               printk ("EXT2-fs: unable to read superblock\n");
+               ext2_msg(sb, KERN_ERR, "error: unable to read superblock");
                goto failed_sbi;
        }
        /*
@@ -826,7 +833,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
        
        set_opt(sbi->s_mount_opt, RESERVATION);
 
-       if (!parse_options ((char *) data, sbi))
+       if (!parse_options((char *) data, sb))
                goto failed_mount;
 
        sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
@@ -840,8 +847,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
            (EXT2_HAS_COMPAT_FEATURE(sb, ~0U) ||
             EXT2_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
             EXT2_HAS_INCOMPAT_FEATURE(sb, ~0U)))
-               printk("EXT2-fs warning: feature flags set on rev 0 fs, "
-                      "running e2fsck is recommended\n");
+               ext2_msg(sb, KERN_WARNING,
+                       "warning: feature flags set on rev 0 fs, "
+                       "running e2fsck is recommended");
        /*
         * Check feature flags regardless of the revision level, since we
         * previously didn't change the revision level when setting the flags,
@@ -849,16 +857,16 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
         */
        features = EXT2_HAS_INCOMPAT_FEATURE(sb, ~EXT2_FEATURE_INCOMPAT_SUPP);
        if (features) {
-               printk("EXT2-fs: %s: couldn't mount because of "
-                      "unsupported optional features (%x).\n",
-                      sb->s_id, le32_to_cpu(features));
+               ext2_msg(sb, KERN_ERR,  "error: couldn't mount because of "
+                      "unsupported optional features (%x)",
+                       le32_to_cpu(features));
                goto failed_mount;
        }
        if (!(sb->s_flags & MS_RDONLY) &&
            (features = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP))){
-               printk("EXT2-fs: %s: couldn't mount RDWR because of "
-                      "unsupported optional features (%x).\n",
-                      sb->s_id, le32_to_cpu(features));
+               ext2_msg(sb, KERN_ERR, "error: couldn't mount RDWR because of "
+                      "unsupported optional features (%x)",
+                      le32_to_cpu(features));
                goto failed_mount;
        }
 
@@ -866,7 +874,8 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
 
        if (ext2_use_xip(sb) && blocksize != PAGE_SIZE) {
                if (!silent)
-                       printk("XIP: Unsupported blocksize\n");
+                       ext2_msg(sb, KERN_ERR,
+                               "error: unsupported blocksize for xip");
                goto failed_mount;
        }
 
@@ -875,7 +884,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
                brelse(bh);
 
                if (!sb_set_blocksize(sb, blocksize)) {
-                       printk(KERN_ERR "EXT2-fs: blocksize too small for device.\n");
+                       ext2_msg(sb, KERN_ERR, "error: blocksize is too small");
                        goto failed_sbi;
                }
 
@@ -883,14 +892,14 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
                offset = (sb_block*BLOCK_SIZE) % blocksize;
                bh = sb_bread(sb, logic_sb_block);
                if(!bh) {
-                       printk("EXT2-fs: Couldn't read superblock on "
-                              "2nd try.\n");
+                       ext2_msg(sb, KERN_ERR, "error: couldn't read"
+                               "superblock on 2nd try");
                        goto failed_sbi;
                }
                es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);
                sbi->s_es = es;
                if (es->s_magic != cpu_to_le16(EXT2_SUPER_MAGIC)) {
-                       printk ("EXT2-fs: Magic mismatch, very weird !\n");
+                       ext2_msg(sb, KERN_ERR, "error: magic mismatch");
                        goto failed_mount;
                }
        }
@@ -906,7 +915,8 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
                if ((sbi->s_inode_size < EXT2_GOOD_OLD_INODE_SIZE) ||
                    !is_power_of_2(sbi->s_inode_size) ||
                    (sbi->s_inode_size > blocksize)) {
-                       printk ("EXT2-fs: unsupported inode size: %d\n",
+                       ext2_msg(sb, KERN_ERR,
+                               "error: unsupported inode size: %d",
                                sbi->s_inode_size);
                        goto failed_mount;
                }
@@ -943,29 +953,33 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
 
        if (sb->s_blocksize != bh->b_size) {
                if (!silent)
-                       printk ("VFS: Unsupported blocksize on dev "
-                               "%s.\n", sb->s_id);
+                       ext2_msg(sb, KERN_ERR, "error: unsupported blocksize");
                goto failed_mount;
        }
 
        if (sb->s_blocksize != sbi->s_frag_size) {
-               printk ("EXT2-fs: fragsize %lu != blocksize %lu (not supported yet)\n",
+               ext2_msg(sb, KERN_ERR,
+                       "error: fragsize %lu != blocksize %lu"
+                       "(not supported yet)",
                        sbi->s_frag_size, sb->s_blocksize);
                goto failed_mount;
        }
 
        if (sbi->s_blocks_per_group > sb->s_blocksize * 8) {
-               printk ("EXT2-fs: #blocks per group too big: %lu\n",
+               ext2_msg(sb, KERN_ERR,
+                       "error: #blocks per group too big: %lu",
                        sbi->s_blocks_per_group);
                goto failed_mount;
        }
        if (sbi->s_frags_per_group > sb->s_blocksize * 8) {
-               printk ("EXT2-fs: #fragments per group too big: %lu\n",
+               ext2_msg(sb, KERN_ERR,
+                       "error: #fragments per group too big: %lu",
                        sbi->s_frags_per_group);
                goto failed_mount;
        }
        if (sbi->s_inodes_per_group > sb->s_blocksize * 8) {
-               printk ("EXT2-fs: #inodes per group too big: %lu\n",
+               ext2_msg(sb, KERN_ERR,
+                       "error: #inodes per group too big: %lu",
                        sbi->s_inodes_per_group);
                goto failed_mount;
        }
@@ -979,13 +993,13 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
                   EXT2_DESC_PER_BLOCK(sb);
        sbi->s_group_desc = kmalloc (db_count * sizeof (struct buffer_head *), GFP_KERNEL);
        if (sbi->s_group_desc == NULL) {
-               printk ("EXT2-fs: not enough memory\n");
+               ext2_msg(sb, KERN_ERR, "error: not enough memory");
                goto failed_mount;
        }
        bgl_lock_init(sbi->s_blockgroup_lock);
        sbi->s_debts = kcalloc(sbi->s_groups_count, sizeof(*sbi->s_debts), GFP_KERNEL);
        if (!sbi->s_debts) {
-               printk ("EXT2-fs: not enough memory\n");
+               ext2_msg(sb, KERN_ERR, "error: not enough memory");
                goto failed_mount_group_desc;
        }
        for (i = 0; i < db_count; i++) {
@@ -994,12 +1008,13 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
                if (!sbi->s_group_desc[i]) {
                        for (j = 0; j < i; j++)
                                brelse (sbi->s_group_desc[j]);
-                       printk ("EXT2-fs: unable to read group descriptors\n");
+                       ext2_msg(sb, KERN_ERR,
+                               "error: unable to read group descriptors");
                        goto failed_mount_group_desc;
                }
        }
        if (!ext2_check_descriptors (sb)) {
-               printk ("EXT2-fs: group descriptors corrupted!\n");
+               ext2_msg(sb, KERN_ERR, "group descriptors corrupted");
                goto failed_mount2;
        }
        sbi->s_gdb_count = db_count;
@@ -1032,7 +1047,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
                                ext2_count_dirs(sb));
        }
        if (err) {
-               printk(KERN_ERR "EXT2-fs: insufficient memory\n");
+               ext2_msg(sb, KERN_ERR, "error: insufficient memory");
                goto failed_mount3;
        }
        /*
@@ -1048,27 +1063,28 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
        }
        if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
                iput(root);
-               printk(KERN_ERR "EXT2-fs: corrupt root inode, run e2fsck\n");
+               ext2_msg(sb, KERN_ERR, "error: corrupt root inode, run e2fsck");
                goto failed_mount3;
        }
 
        sb->s_root = d_alloc_root(root);
        if (!sb->s_root) {
                iput(root);
-               printk(KERN_ERR "EXT2-fs: get root inode failed\n");
+               ext2_msg(sb, KERN_ERR, "error: get root inode failed");
                ret = -ENOMEM;
                goto failed_mount3;
        }
        if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL))
-               ext2_warning(sb, __func__,
-                       "mounting ext3 filesystem as ext2");
+               ext2_msg(sb, KERN_WARNING,
+                       "warning: mounting ext3 filesystem as ext2");
        ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY);
        return 0;
 
 cantfind_ext2:
        if (!silent)
-               printk("VFS: Can't find an ext2 filesystem on dev %s.\n",
-                      sb->s_id);
+               ext2_msg(sb, KERN_ERR,
+                       "error: can't find an ext2 filesystem on dev %s.",
+                       sb->s_id);
        goto failed_mount;
 failed_mount3:
        percpu_counter_destroy(&sbi->s_freeblocks_counter);
@@ -1121,8 +1137,24 @@ static void ext2_sync_super(struct super_block *sb, struct ext2_super_block *es)
 static int ext2_sync_fs(struct super_block *sb, int wait)
 {
        struct ext2_super_block *es = EXT2_SB(sb)->s_es;
+       struct buffer_head *sbh = EXT2_SB(sb)->s_sbh;
 
        lock_kernel();
+       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.
+                */
+               ext2_msg(sb, KERN_ERR,
+                      "previous I/O error to superblock detected\n");
+               clear_buffer_write_io_error(sbh);
+               set_buffer_uptodate(sbh);
+       }
+
        if (es->s_state & cpu_to_le16(EXT2_VALID_FS)) {
                ext2_debug("setting valid to 0\n");
                es->s_state &= cpu_to_le16(~EXT2_VALID_FS);
@@ -1170,7 +1202,7 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
        /*
         * Allow the "check" option to be passed as a remount option.
         */
-       if (!parse_options (data, sbi)) {
+       if (!parse_options(data, sb)) {
                err = -EINVAL;
                goto restore_opts;
        }
@@ -1182,7 +1214,8 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
                                    EXT2_MOUNT_XIP if not */
 
        if ((ext2_use_xip(sb)) && (sb->s_blocksize != PAGE_SIZE)) {
-               printk("XIP: Unsupported blocksize\n");
+               ext2_msg(sb, KERN_WARNING,
+                       "warning: unsupported blocksize for xip");
                err = -EINVAL;
                goto restore_opts;
        }
@@ -1191,8 +1224,8 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
        if (((sbi->s_mount_opt & EXT2_MOUNT_XIP) !=
            (old_mount_opt & EXT2_MOUNT_XIP)) &&
            invalidate_inodes(sb)) {
-               ext2_warning(sb, __func__, "refusing change of xip flag "
-                            "with busy inodes while remounting");
+               ext2_msg(sb, KERN_WARNING, "warning: refusing change of "
+                        "xip flag with busy inodes while remounting");
                sbi->s_mount_opt &= ~EXT2_MOUNT_XIP;
                sbi->s_mount_opt |= old_mount_opt & EXT2_MOUNT_XIP;
        }
@@ -1216,9 +1249,10 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
                __le32 ret = EXT2_HAS_RO_COMPAT_FEATURE(sb,
                                               ~EXT2_FEATURE_RO_COMPAT_SUPP);
                if (ret) {
-                       printk("EXT2-fs: %s: couldn't remount RDWR because of "
-                              "unsupported optional features (%x).\n",
-                              sb->s_id, le32_to_cpu(ret));
+                       ext2_msg(sb, KERN_WARNING,
+                               "warning: couldn't remount RDWR because of "
+                               "unsupported optional features (%x).",
+                               le32_to_cpu(ret));
                        err = -EROFS;
                        goto restore_opts;
                }
index c18fbf3..322a56b 100644 (file)
@@ -69,8 +69,9 @@ void ext2_xip_verify_sb(struct super_block *sb)
        if ((sbi->s_mount_opt & EXT2_MOUNT_XIP) &&
            !sb->s_bdev->bd_disk->fops->direct_access) {
                sbi->s_mount_opt &= (~EXT2_MOUNT_XIP);
-               ext2_warning(sb, __func__,
-                            "ignoring xip option - not supported by bdev");
+               ext2_msg(sb, KERN_WARNING,
+                            "warning: ignoring xip option - "
+                            "not supported by bdev");
        }
 }
 
index 2db9577..ad14227 100644 (file)
@@ -1151,6 +1151,16 @@ static int do_journal_get_write_access(handle_t *handle,
        return ext3_journal_get_write_access(handle, bh);
 }
 
+/*
+ * Truncate blocks that were not used by write. We have to truncate the
+ * pagecache as well so that corresponding buffers get properly unmapped.
+ */
+static void ext3_truncate_failed_write(struct inode *inode)
+{
+       truncate_inode_pages(inode->i_mapping, inode->i_size);
+       ext3_truncate(inode);
+}
+
 static int ext3_write_begin(struct file *file, struct address_space *mapping,
                                loff_t pos, unsigned len, unsigned flags,
                                struct page **pagep, void **fsdata)
@@ -1209,7 +1219,7 @@ write_begin_failed:
                unlock_page(page);
                page_cache_release(page);
                if (pos + len > inode->i_size)
-                       ext3_truncate(inode);
+                       ext3_truncate_failed_write(inode);
        }
        if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
                goto retry;
@@ -1304,7 +1314,7 @@ static int ext3_ordered_write_end(struct file *file,
        page_cache_release(page);
 
        if (pos + len > inode->i_size)
-               ext3_truncate(inode);
+               ext3_truncate_failed_write(inode);
        return ret ? ret : copied;
 }
 
@@ -1330,7 +1340,7 @@ static int ext3_writeback_write_end(struct file *file,
        page_cache_release(page);
 
        if (pos + len > inode->i_size)
-               ext3_truncate(inode);
+               ext3_truncate_failed_write(inode);
        return ret ? ret : copied;
 }
 
@@ -1383,7 +1393,7 @@ static int ext3_journalled_write_end(struct file *file,
        page_cache_release(page);
 
        if (pos + len > inode->i_size)
-               ext3_truncate(inode);
+               ext3_truncate_failed_write(inode);
        return ret ? ret : copied;
 }
 
index 8359e7b..5f83b61 100644 (file)
@@ -266,7 +266,7 @@ static int setup_new_group_blocks(struct super_block *sb,
                        goto exit_bh;
 
                if (IS_ERR(gdb = bclean(handle, sb, block))) {
-                       err = PTR_ERR(bh);
+                       err = PTR_ERR(gdb);
                        goto exit_bh;
                }
                ext3_journal_dirty_metadata(handle, gdb);
index 427496c..7ad1e8c 100644 (file)
@@ -135,12 +135,24 @@ void ext3_journal_abort_handle(const char *caller, const char *err_fn,
        if (is_handle_aborted(handle))
                return;
 
-       printk(KERN_ERR "%s: aborting transaction: %s in %s\n",
-              caller, errstr, err_fn);
+       printk(KERN_ERR "EXT3-fs: %s: aborting transaction: %s in %s\n",
+               caller, errstr, err_fn);
 
        journal_abort_handle(handle);
 }
 
+void ext3_msg(struct super_block *sb, const char *prefix,
+               const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       printk("%sEXT3-fs (%s): ", prefix, sb->s_id);
+       vprintk(fmt, args);
+       printk("\n");
+       va_end(args);
+}
+
 /* Deal with the reporting of failure conditions on a filesystem such as
  * inconsistencies detected or read IO failures.
  *
@@ -174,12 +186,13 @@ static void ext3_handle_error(struct super_block *sb)
                        journal_abort(journal, -EIO);
        }
        if (test_opt (sb, ERRORS_RO)) {
-               printk (KERN_CRIT "Remounting filesystem read-only\n");
+               ext3_msg(sb, KERN_CRIT,
+                       "error: remounting filesystem read-only");
                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",
+               panic("EXT3-fs (%s): panic forced after error\n",
                        sb->s_id);
 }
 
@@ -247,8 +260,7 @@ void __ext3_std_error (struct super_block * sb, const char * function,
                return;
 
        errstr = ext3_decode_error(sb, errno, nbuf);
-       printk (KERN_CRIT "EXT3-fs error (device %s) in %s: %s\n",
-               sb->s_id, function, errstr);
+       ext3_msg(sb, KERN_CRIT, "error in %s: %s", function, errstr);
 
        ext3_handle_error(sb);
 }
@@ -268,21 +280,20 @@ void ext3_abort (struct super_block * sb, const char * function,
 {
        va_list args;
 
-       printk (KERN_CRIT "ext3_abort called.\n");
-
        va_start(args, fmt);
-       printk(KERN_CRIT "EXT3-fs error (device %s): %s: ",sb->s_id, function);
+       printk(KERN_CRIT "EXT3-fs (%s): error: %s: ", sb->s_id, function);
        vprintk(fmt, args);
        printk("\n");
        va_end(args);
 
        if (test_opt(sb, ERRORS_PANIC))
-               panic("EXT3-fs panic from previous error\n");
+               panic("EXT3-fs: panic from previous error\n");
 
        if (sb->s_flags & MS_RDONLY)
                return;
 
-       printk(KERN_CRIT "Remounting filesystem read-only\n");
+       ext3_msg(sb, KERN_CRIT,
+               "error: remounting filesystem read-only");
        EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
        sb->s_flags |= MS_RDONLY;
        EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT;
@@ -296,7 +307,7 @@ void ext3_warning (struct super_block * sb, const char * function,
        va_list args;
 
        va_start(args, fmt);
-       printk(KERN_WARNING "EXT3-fs warning (device %s): %s: ",
+       printk(KERN_WARNING "EXT3-fs (%s): warning: %s: ",
               sb->s_id, function);
        vprintk(fmt, args);
        printk("\n");
@@ -310,10 +321,10 @@ void ext3_update_dynamic_rev(struct super_block *sb)
        if (le32_to_cpu(es->s_rev_level) > EXT3_GOOD_OLD_REV)
                return;
 
-       ext3_warning(sb, __func__,
-                    "updating to rev %d because of new feature flag, "
-                    "running e2fsck is recommended",
-                    EXT3_DYNAMIC_REV);
+       ext3_msg(sb, KERN_WARNING,
+               "warning: updating to rev %d because of "
+               "new feature flag, running e2fsck is recommended",
+               EXT3_DYNAMIC_REV);
 
        es->s_first_ino = cpu_to_le32(EXT3_GOOD_OLD_FIRST_INO);
        es->s_inode_size = cpu_to_le16(EXT3_GOOD_OLD_INODE_SIZE);
@@ -331,7 +342,7 @@ void ext3_update_dynamic_rev(struct super_block *sb)
 /*
  * Open the external journal device
  */
-static struct block_device *ext3_blkdev_get(dev_t dev)
+static struct block_device *ext3_blkdev_get(dev_t dev, struct super_block *sb)
 {
        struct block_device *bdev;
        char b[BDEVNAME_SIZE];
@@ -342,8 +353,9 @@ static struct block_device *ext3_blkdev_get(dev_t dev)
        return bdev;
 
 fail:
-       printk(KERN_ERR "EXT3: failed to open journal device %s: %ld\n",
-                       __bdevname(dev, b), PTR_ERR(bdev));
+       ext3_msg(sb, "error: failed to open journal device %s: %ld",
+               __bdevname(dev, b), PTR_ERR(bdev));
+
        return NULL;
 }
 
@@ -378,13 +390,13 @@ 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",
+       ext3_msg(sb, KERN_ERR, "error: sb orphan head is %d",
               le32_to_cpu(sbi->s_es->s_last_orphan));
 
-       printk(KERN_ERR "sb_info orphan list:\n");
+       ext3_msg(sb, KERN_ERR, "sb_info orphan list:");
        list_for_each(l, &sbi->s_orphan) {
                struct inode *inode = orphan_list_entry(l);
-               printk(KERN_ERR "  "
+               ext3_msg(sb, KERN_ERR, "  "
                       "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,
@@ -527,9 +539,22 @@ static inline void ext3_show_quota_options(struct seq_file *seq, struct super_bl
 #if defined(CONFIG_QUOTA)
        struct ext3_sb_info *sbi = EXT3_SB(sb);
 
-       if (sbi->s_jquota_fmt)
-               seq_printf(seq, ",jqfmt=%s",
-               (sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold": "vfsv0");
+       if (sbi->s_jquota_fmt) {
+               char *fmtname = "";
+
+               switch (sbi->s_jquota_fmt) {
+               case QFMT_VFS_OLD:
+                       fmtname = "vfsold";
+                       break;
+               case QFMT_VFS_V0:
+                       fmtname = "vfsv0";
+                       break;
+               case QFMT_VFS_V1:
+                       fmtname = "vfsv1";
+                       break;
+               }
+               seq_printf(seq, ",jqfmt=%s", fmtname);
+       }
 
        if (sbi->s_qf_names[USRQUOTA])
                seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]);
@@ -636,6 +661,9 @@ static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
        if (test_opt(sb, DATA_ERR_ABORT))
                seq_puts(seq, ",data_err=abort");
 
+       if (test_opt(sb, NOLOAD))
+               seq_puts(seq, ",norecovery");
+
        ext3_show_quota_options(seq, sb);
 
        return 0;
@@ -787,9 +815,9 @@ enum {
        Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
        Opt_data_err_abort, Opt_data_err_ignore,
        Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
-       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
-       Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
-       Opt_grpquota
+       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
+       Opt_noquota, Opt_ignore, Opt_barrier, Opt_err, Opt_resize,
+       Opt_usrquota, Opt_grpquota
 };
 
 static const match_table_t tokens = {
@@ -818,6 +846,7 @@ static const match_table_t tokens = {
        {Opt_reservation, "reservation"},
        {Opt_noreservation, "noreservation"},
        {Opt_noload, "noload"},
+       {Opt_noload, "norecovery"},
        {Opt_nobh, "nobh"},
        {Opt_bh, "bh"},
        {Opt_commit, "commit=%u"},
@@ -836,6 +865,7 @@ static const match_table_t tokens = {
        {Opt_grpjquota, "grpjquota=%s"},
        {Opt_jqfmt_vfsold, "jqfmt=vfsold"},
        {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
+       {Opt_jqfmt_vfsv1, "jqfmt=vfsv1"},
        {Opt_grpquota, "grpquota"},
        {Opt_noquota, "noquota"},
        {Opt_quota, "quota"},
@@ -845,7 +875,7 @@ static const match_table_t tokens = {
        {Opt_err, NULL},
 };
 
-static ext3_fsblk_t get_sb_block(void **data)
+static ext3_fsblk_t get_sb_block(void **data, struct super_block *sb)
 {
        ext3_fsblk_t    sb_block;
        char            *options = (char *) *data;
@@ -856,7 +886,7 @@ static ext3_fsblk_t get_sb_block(void **data)
        /*todo: use simple_strtoll with >32bit ext3 */
        sb_block = simple_strtoul(options, &options, 0);
        if (*options && *options != ',') {
-               printk("EXT3-fs: Invalid sb specification: %s\n",
+               ext3_msg(sb, "error: invalid sb specification: %s",
                       (char *) *data);
                return 1;
        }
@@ -956,7 +986,8 @@ static int parse_options (char *options, struct super_block *sb,
 #else
                case Opt_user_xattr:
                case Opt_nouser_xattr:
-                       printk("EXT3 (no)user_xattr options not supported\n");
+                       ext3_msg(sb, KERN_INFO,
+                               "(no)user_xattr options not supported");
                        break;
 #endif
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
@@ -969,7 +1000,8 @@ static int parse_options (char *options, struct super_block *sb,
 #else
                case Opt_acl:
                case Opt_noacl:
-                       printk("EXT3 (no)acl options not supported\n");
+                       ext3_msg(sb, KERN_INFO,
+                               "(no)acl options not supported");
                        break;
 #endif
                case Opt_reservation:
@@ -985,16 +1017,16 @@ static int parse_options (char *options, struct super_block *sb,
                           user to specify an existing inode to be the
                           journal file. */
                        if (is_remount) {
-                               printk(KERN_ERR "EXT3-fs: cannot specify "
-                                      "journal on remount\n");
+                               ext3_msg(sb, KERN_ERR, "error: cannot specify "
+                                       "journal on remount");
                                return 0;
                        }
                        set_opt (sbi->s_mount_opt, UPDATE_JOURNAL);
                        break;
                case Opt_journal_inum:
                        if (is_remount) {
-                               printk(KERN_ERR "EXT3-fs: cannot specify "
-                                      "journal on remount\n");
+                               ext3_msg(sb, KERN_ERR, "error: cannot specify "
+                                      "journal on remount");
                                return 0;
                        }
                        if (match_int(&args[0], &option))
@@ -1003,8 +1035,8 @@ static int parse_options (char *options, struct super_block *sb,
                        break;
                case Opt_journal_dev:
                        if (is_remount) {
-                               printk(KERN_ERR "EXT3-fs: cannot specify "
-                                      "journal on remount\n");
+                               ext3_msg(sb, KERN_ERR, "error: cannot specify "
+                                      "journal on remount");
                                return 0;
                        }
                        if (match_int(&args[0], &option))
@@ -1036,12 +1068,11 @@ static int parse_options (char *options, struct super_block *sb,
                                if ((sbi->s_mount_opt & EXT3_MOUNT_DATA_FLAGS)
                                                == data_opt)
                                        break;
-                               printk(KERN_ERR
-                                       "EXT3-fs (device %s): Cannot change "
+                               ext3_msg(sb, KERN_ERR,
+                                       "error: cannot change "
                                        "data mode on remount. The filesystem "
                                        "is mounted in data=%s mode and you "
-                                       "try to remount it in data=%s mode.\n",
-                                       sb->s_id,
+                                       "try to remount it in data=%s mode.",
                                        data_mode_string(sbi->s_mount_opt &
                                                        EXT3_MOUNT_DATA_FLAGS),
                                        data_mode_string(data_opt));
@@ -1066,31 +1097,31 @@ static int parse_options (char *options, struct super_block *sb,
 set_qf_name:
                        if (sb_any_quota_loaded(sb) &&
                            !sbi->s_qf_names[qtype]) {
-                               printk(KERN_ERR
-                                       "EXT3-fs: Cannot change journaled "
-                                       "quota options when quota turned on.\n");
+                               ext3_msg(sb, KERN_ERR,
+                                       "error: cannot change journaled "
+                                       "quota options when quota turned on.");
                                return 0;
                        }
                        qname = match_strdup(&args[0]);
                        if (!qname) {
-                               printk(KERN_ERR
-                                       "EXT3-fs: not enough memory for "
-                                       "storing quotafile name.\n");
+                               ext3_msg(sb, KERN_ERR,
+                                       "error: not enough memory for "
+                                       "storing quotafile name.");
                                return 0;
                        }
                        if (sbi->s_qf_names[qtype] &&
                            strcmp(sbi->s_qf_names[qtype], qname)) {
-                               printk(KERN_ERR
-                                       "EXT3-fs: %s quota file already "
-                                       "specified.\n", QTYPE2NAME(qtype));
+                               ext3_msg(sb, KERN_ERR,
+                                       "error: %s quota file already "
+                                       "specified.", QTYPE2NAME(qtype));
                                kfree(qname);
                                return 0;
                        }
                        sbi->s_qf_names[qtype] = qname;
                        if (strchr(sbi->s_qf_names[qtype], '/')) {
-                               printk(KERN_ERR
-                                       "EXT3-fs: quotafile must be on "
-                                       "filesystem root.\n");
+                               ext3_msg(sb, KERN_ERR,
+                                       "error: quotafile must be on "
+                                       "filesystem root.");
                                kfree(sbi->s_qf_names[qtype]);
                                sbi->s_qf_names[qtype] = NULL;
                                return 0;
@@ -1105,9 +1136,9 @@ set_qf_name:
 clear_qf_name:
                        if (sb_any_quota_loaded(sb) &&
                            sbi->s_qf_names[qtype]) {
-                               printk(KERN_ERR "EXT3-fs: Cannot change "
+                               ext3_msg(sb, KERN_ERR, "error: cannot change "
                                        "journaled quota options when "
-                                       "quota turned on.\n");
+                                       "quota turned on.");
                                return 0;
                        }
                        /*
@@ -1121,12 +1152,15 @@ clear_qf_name:
                        goto set_qf_format;
                case Opt_jqfmt_vfsv0:
                        qfmt = QFMT_VFS_V0;
+                       goto set_qf_format;
+               case Opt_jqfmt_vfsv1:
+                       qfmt = QFMT_VFS_V1;
 set_qf_format:
                        if (sb_any_quota_loaded(sb) &&
                            sbi->s_jquota_fmt != qfmt) {
-                               printk(KERN_ERR "EXT3-fs: Cannot change "
+                               ext3_msg(sb, KERN_ERR, "error: cannot change "
                                        "journaled quota options when "
-                                       "quota turned on.\n");
+                                       "quota turned on.");
                                return 0;
                        }
                        sbi->s_jquota_fmt = qfmt;
@@ -1142,8 +1176,8 @@ set_qf_format:
                        break;
                case Opt_noquota:
                        if (sb_any_quota_loaded(sb)) {
-                               printk(KERN_ERR "EXT3-fs: Cannot change quota "
-                                       "options when quota turned on.\n");
+                               ext3_msg(sb, KERN_ERR, "error: cannot change "
+                                       "quota options when quota turned on.");
                                return 0;
                        }
                        clear_opt(sbi->s_mount_opt, QUOTA);
@@ -1154,8 +1188,8 @@ set_qf_format:
                case Opt_quota:
                case Opt_usrquota:
                case Opt_grpquota:
-                       printk(KERN_ERR
-                               "EXT3-fs: quota options not supported.\n");
+                       ext3_msg(sb, KERN_ERR,
+                               "error: quota options not supported.");
                        break;
                case Opt_usrjquota:
                case Opt_grpjquota:
@@ -1163,9 +1197,10 @@ set_qf_format:
                case Opt_offgrpjquota:
                case Opt_jqfmt_vfsold:
                case Opt_jqfmt_vfsv0:
-                       printk(KERN_ERR
-                               "EXT3-fs: journaled quota options not "
-                               "supported.\n");
+               case Opt_jqfmt_vfsv1:
+                       ext3_msg(sb, KERN_ERR,
+                               "error: journaled quota options not "
+                               "supported.");
                        break;
                case Opt_noquota:
                        break;
@@ -1185,8 +1220,9 @@ set_qf_format:
                        break;
                case Opt_resize:
                        if (!is_remount) {
-                               printk("EXT3-fs: resize option only available "
-                                       "for remount\n");
+                               ext3_msg(sb, KERN_ERR,
+                                       "error: resize option only available "
+                                       "for remount");
                                return 0;
                        }
                        if (match_int(&args[0], &option) != 0)
@@ -1200,9 +1236,9 @@ set_qf_format:
                        clear_opt(sbi->s_mount_opt, NOBH);
                        break;
                default:
-                       printk (KERN_ERR
-                               "EXT3-fs: Unrecognized mount option \"%s\" "
-                               "or missing value\n", p);
+                       ext3_msg(sb, KERN_ERR,
+                               "error: unrecognized mount option \"%s\" "
+                               "or missing value", p);
                        return 0;
                }
        }
@@ -1220,21 +1256,21 @@ set_qf_format:
                                (sbi->s_mount_opt & EXT3_MOUNT_GRPQUOTA)) ||
                    (sbi->s_qf_names[GRPQUOTA] &&
                                (sbi->s_mount_opt & EXT3_MOUNT_USRQUOTA))) {
-                       printk(KERN_ERR "EXT3-fs: old and new quota "
-                                       "format mixing.\n");
+                       ext3_msg(sb, KERN_ERR, "error: old and new quota "
+                                       "format mixing.");
                        return 0;
                }
 
                if (!sbi->s_jquota_fmt) {
-                       printk(KERN_ERR "EXT3-fs: journaled quota format "
-                                       "not specified.\n");
+                       ext3_msg(sb, KERN_ERR, "error: journaled quota format "
+                                       "not specified.");
                        return 0;
                }
        } else {
                if (sbi->s_jquota_fmt) {
-                       printk(KERN_ERR "EXT3-fs: journaled quota format "
+                       ext3_msg(sb, KERN_ERR, "error: journaled quota format "
                                        "specified with no journaling "
-                                       "enabled.\n");
+                                       "enabled.");
                        return 0;
                }
        }
@@ -1249,31 +1285,33 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es,
        int res = 0;
 
        if (le32_to_cpu(es->s_rev_level) > EXT3_MAX_SUPP_REV) {
-               printk (KERN_ERR "EXT3-fs warning: revision level too high, "
-                       "forcing read-only mode\n");
+               ext3_msg(sb, KERN_ERR,
+                       "error: revision level too high, "
+                       "forcing read-only mode");
                res = MS_RDONLY;
        }
        if (read_only)
                return res;
        if (!(sbi->s_mount_state & EXT3_VALID_FS))
-               printk (KERN_WARNING "EXT3-fs warning: mounting unchecked fs, "
-                       "running e2fsck is recommended\n");
+               ext3_msg(sb, KERN_WARNING,
+                       "warning: mounting unchecked fs, "
+                       "running e2fsck is recommended");
        else if ((sbi->s_mount_state & EXT3_ERROR_FS))
-               printk (KERN_WARNING
-                       "EXT3-fs warning: mounting fs with errors, "
-                       "running e2fsck is recommended\n");
+               ext3_msg(sb, KERN_WARNING,
+                       "warning: mounting fs with errors, "
+                       "running e2fsck is recommended");
        else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 &&
                 le16_to_cpu(es->s_mnt_count) >=
                 (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count))
-               printk (KERN_WARNING
-                       "EXT3-fs warning: maximal mount count reached, "
-                       "running e2fsck is recommended\n");
+               ext3_msg(sb, KERN_WARNING,
+                       "warning: maximal mount count reached, "
+                       "running e2fsck is recommended");
        else if (le32_to_cpu(es->s_checkinterval) &&
                (le32_to_cpu(es->s_lastcheck) +
                        le32_to_cpu(es->s_checkinterval) <= get_seconds()))
-               printk (KERN_WARNING
-                       "EXT3-fs warning: checktime reached, "
-                       "running e2fsck is recommended\n");
+               ext3_msg(sb, KERN_WARNING,
+                       "warning: checktime reached, "
+                       "running e2fsck is recommended");
 #if 0
                /* @@@ We _will_ want to clear the valid bit if we find
                    inconsistencies, to force a fsck at reboot.  But for
@@ -1290,22 +1328,20 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es,
 
        ext3_commit_super(sb, es, 1);
        if (test_opt(sb, DEBUG))
-               printk(KERN_INFO "[EXT3 FS bs=%lu, gc=%lu, "
-                               "bpg=%lu, ipg=%lu, mo=%04lx]\n",
+               ext3_msg(sb, KERN_INFO, "[bs=%lu, gc=%lu, "
+                               "bpg=%lu, ipg=%lu, mo=%04lx]",
                        sb->s_blocksize,
                        sbi->s_groups_count,
                        EXT3_BLOCKS_PER_GROUP(sb),
                        EXT3_INODES_PER_GROUP(sb),
                        sbi->s_mount_opt);
 
-       printk(KERN_INFO "EXT3 FS on %s, ", sb->s_id);
        if (EXT3_SB(sb)->s_journal->j_inode == NULL) {
                char b[BDEVNAME_SIZE];
-
-               printk("external journal on %s\n",
+               ext3_msg(sb, KERN_INFO, "using external journal on %s",
                        bdevname(EXT3_SB(sb)->s_journal->j_dev, b));
        } else {
-               printk("internal journal\n");
+               ext3_msg(sb, KERN_INFO, "using internal journal");
        }
        return res;
 }
@@ -1399,8 +1435,8 @@ static void ext3_orphan_cleanup (struct super_block * sb,
        }
 
        if (bdev_read_only(sb->s_bdev)) {
-               printk(KERN_ERR "EXT3-fs: write access "
-                       "unavailable, skipping orphan cleanup.\n");
+               ext3_msg(sb, KERN_ERR, "error: write access "
+                       "unavailable, skipping orphan cleanup.");
                return;
        }
 
@@ -1414,8 +1450,7 @@ static void ext3_orphan_cleanup (struct super_block * sb,
        }
 
        if (s_flags & MS_RDONLY) {
-               printk(KERN_INFO "EXT3-fs: %s: orphan cleanup on readonly fs\n",
-                      sb->s_id);
+               ext3_msg(sb, KERN_INFO, "orphan cleanup on readonly fs");
                sb->s_flags &= ~MS_RDONLY;
        }
 #ifdef CONFIG_QUOTA
@@ -1426,9 +1461,9 @@ static void ext3_orphan_cleanup (struct super_block * sb,
                if (EXT3_SB(sb)->s_qf_names[i]) {
                        int ret = ext3_quota_on_mount(sb, i);
                        if (ret < 0)
-                               printk(KERN_ERR
-                                       "EXT3-fs: Cannot turn on journaled "
-                                       "quota: error %d\n", ret);
+                               ext3_msg(sb, KERN_ERR,
+                                       "error: cannot turn on journaled "
+                                       "quota: %d", ret);
                }
        }
 #endif
@@ -1466,11 +1501,11 @@ static void ext3_orphan_cleanup (struct super_block * sb,
 #define PLURAL(x) (x), ((x)==1) ? "" : "s"
 
        if (nr_orphans)
-               printk(KERN_INFO "EXT3-fs: %s: %d orphan inode%s deleted\n",
-                      sb->s_id, PLURAL(nr_orphans));
+               ext3_msg(sb, KERN_INFO, "%d orphan inode%s deleted",
+                      PLURAL(nr_orphans));
        if (nr_truncates)
-               printk(KERN_INFO "EXT3-fs: %s: %d truncate%s cleaned up\n",
-                      sb->s_id, PLURAL(nr_truncates));
+               ext3_msg(sb, KERN_INFO, "%d truncate%s cleaned up",
+                      PLURAL(nr_truncates));
 #ifdef CONFIG_QUOTA
        /* Turn quotas off */
        for (i = 0; i < MAXQUOTAS; i++) {
@@ -1554,7 +1589,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        struct ext3_super_block *es = NULL;
        struct ext3_sb_info *sbi;
        ext3_fsblk_t block;
-       ext3_fsblk_t sb_block = get_sb_block(&data);
+       ext3_fsblk_t sb_block = get_sb_block(&data, sb);
        ext3_fsblk_t logic_sb_block;
        unsigned long offset = 0;
        unsigned int journal_inum = 0;
@@ -1590,7 +1625,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 
        blocksize = sb_min_blocksize(sb, EXT3_MIN_BLOCK_SIZE);
        if (!blocksize) {
-               printk(KERN_ERR "EXT3-fs: unable to set blocksize\n");
+               ext3_msg(sb, KERN_ERR, "error: unable to set blocksize");
                goto out_fail;
        }
 
@@ -1606,7 +1641,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        }
 
        if (!(bh = sb_bread(sb, logic_sb_block))) {
-               printk (KERN_ERR "EXT3-fs: unable to read superblock\n");
+               ext3_msg(sb, KERN_ERR, "error: unable to read superblock");
                goto out_fail;
        }
        /*
@@ -1665,9 +1700,9 @@ 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
-                      "EXT3-fs warning: feature flags set on rev 0 fs, "
-                      "running e2fsck is recommended\n");
+               ext3_msg(sb, KERN_WARNING,
+                       "warning: feature flags set on rev 0 fs, "
+                       "running e2fsck is recommended");
        /*
         * Check feature flags regardless of the revision level, since we
         * previously didn't change the revision level when setting the flags,
@@ -1675,25 +1710,25 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
         */
        features = EXT3_HAS_INCOMPAT_FEATURE(sb, ~EXT3_FEATURE_INCOMPAT_SUPP);
        if (features) {
-               printk(KERN_ERR "EXT3-fs: %s: couldn't mount because of "
-                      "unsupported optional features (%x).\n",
-                      sb->s_id, le32_to_cpu(features));
+               ext3_msg(sb, KERN_ERR,
+                       "error: couldn't mount because of unsupported "
+                       "optional features (%x)", le32_to_cpu(features));
                goto failed_mount;
        }
        features = EXT3_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP);
        if (!(sb->s_flags & MS_RDONLY) && features) {
-               printk(KERN_ERR "EXT3-fs: %s: couldn't mount RDWR because of "
-                      "unsupported optional features (%x).\n",
-                      sb->s_id, le32_to_cpu(features));
+               ext3_msg(sb, KERN_ERR,
+                       "error: couldn't mount RDWR because of unsupported "
+                       "optional features (%x)", le32_to_cpu(features));
                goto failed_mount;
        }
        blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
 
        if (blocksize < EXT3_MIN_BLOCK_SIZE ||
            blocksize > EXT3_MAX_BLOCK_SIZE) {
-               printk(KERN_ERR
-                      "EXT3-fs: Unsupported filesystem blocksize %d on %s.\n",
-                      blocksize, sb->s_id);
+               ext3_msg(sb, KERN_ERR,
+                       "error: couldn't mount because of unsupported "
+                       "filesystem blocksize %d", blocksize);
                goto failed_mount;
        }
 
@@ -1704,30 +1739,31 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                 * than the hardware sectorsize for the machine.
                 */
                if (blocksize < hblock) {
-                       printk(KERN_ERR "EXT3-fs: blocksize %d too small for "
-                              "device blocksize %d.\n", blocksize, hblock);
+                       ext3_msg(sb, KERN_ERR,
+                               "error: fsblocksize %d too small for "
+                               "hardware sectorsize %d", blocksize, hblock);
                        goto failed_mount;
                }
 
                brelse (bh);
                if (!sb_set_blocksize(sb, blocksize)) {
-                       printk(KERN_ERR "EXT3-fs: bad blocksize %d.\n",
-                               blocksize);
+                       ext3_msg(sb, KERN_ERR,
+                               "error: bad blocksize %d", blocksize);
                        goto out_fail;
                }
                logic_sb_block = (sb_block * EXT3_MIN_BLOCK_SIZE) / blocksize;
                offset = (sb_block * EXT3_MIN_BLOCK_SIZE) % blocksize;
                bh = sb_bread(sb, logic_sb_block);
                if (!bh) {
-                       printk(KERN_ERR
-                              "EXT3-fs: Can't read superblock on 2nd try.\n");
+                       ext3_msg(sb, KERN_ERR,
+                              "error: can't read superblock on 2nd try");
                        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
-                               "EXT3-fs: Magic mismatch, very weird !\n");
+                       ext3_msg(sb, KERN_ERR,
+                               "error: magic mismatch");
                        goto failed_mount;
                }
        }
@@ -1743,8 +1779,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                if ((sbi->s_inode_size < EXT3_GOOD_OLD_INODE_SIZE) ||
                    (!is_power_of_2(sbi->s_inode_size)) ||
                    (sbi->s_inode_size > blocksize)) {
-                       printk (KERN_ERR
-                               "EXT3-fs: unsupported inode size: %d\n",
+                       ext3_msg(sb, KERN_ERR,
+                               "error: unsupported inode size: %d",
                                sbi->s_inode_size);
                        goto failed_mount;
                }
@@ -1752,8 +1788,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        sbi->s_frag_size = EXT3_MIN_FRAG_SIZE <<
                                   le32_to_cpu(es->s_log_frag_size);
        if (blocksize != sbi->s_frag_size) {
-               printk(KERN_ERR
-                      "EXT3-fs: fragsize %lu != blocksize %u (unsupported)\n",
+               ext3_msg(sb, KERN_ERR,
+                      "error: fragsize %lu != blocksize %u (unsupported)",
                       sbi->s_frag_size, blocksize);
                goto failed_mount;
        }
@@ -1789,31 +1825,31 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        }
 
        if (sbi->s_blocks_per_group > blocksize * 8) {
-               printk (KERN_ERR
-                       "EXT3-fs: #blocks per group too big: %lu\n",
+               ext3_msg(sb, KERN_ERR,
+                       "#blocks per group too big: %lu",
                        sbi->s_blocks_per_group);
                goto failed_mount;
        }
        if (sbi->s_frags_per_group > blocksize * 8) {
-               printk (KERN_ERR
-                       "EXT3-fs: #fragments per group too big: %lu\n",
+               ext3_msg(sb, KERN_ERR,
+                       "error: #fragments per group too big: %lu",
                        sbi->s_frags_per_group);
                goto failed_mount;
        }
        if (sbi->s_inodes_per_group > blocksize * 8) {
-               printk (KERN_ERR
-                       "EXT3-fs: #inodes per group too big: %lu\n",
+               ext3_msg(sb, KERN_ERR,
+                       "error: #inodes per group too big: %lu",
                        sbi->s_inodes_per_group);
                goto failed_mount;
        }
 
        if (le32_to_cpu(es->s_blocks_count) >
                    (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
-               printk(KERN_ERR "EXT3-fs: filesystem on %s:"
-                       " too large to mount safely\n", sb->s_id);
+               ext3_msg(sb, KERN_ERR,
+                       "error: filesystem is too large to mount safely");
                if (sizeof(sector_t) < 8)
-                       printk(KERN_WARNING "EXT3-fs: CONFIG_LBDAF not "
-                                       "enabled\n");
+                       ext3_msg(sb, KERN_ERR,
+                               "error: CONFIG_LBDAF not enabled");
                goto failed_mount;
        }
 
@@ -1827,7 +1863,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *),
                                    GFP_KERNEL);
        if (sbi->s_group_desc == NULL) {
-               printk (KERN_ERR "EXT3-fs: not enough memory\n");
+               ext3_msg(sb, KERN_ERR,
+                       "error: not enough memory");
                goto failed_mount;
        }
 
@@ -1837,14 +1874,15 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                block = descriptor_loc(sb, logic_sb_block, i);
                sbi->s_group_desc[i] = sb_bread(sb, block);
                if (!sbi->s_group_desc[i]) {
-                       printk (KERN_ERR "EXT3-fs: "
-                               "can't read group descriptor %d\n", i);
+                       ext3_msg(sb, KERN_ERR,
+                               "error: can't read group descriptor %d", i);
                        db_count = i;
                        goto failed_mount2;
                }
        }
        if (!ext3_check_descriptors (sb)) {
-               printk(KERN_ERR "EXT3-fs: group descriptors corrupted!\n");
+               ext3_msg(sb, KERN_ERR,
+                       "error: group descriptors corrupted");
                goto failed_mount2;
        }
        sbi->s_gdb_count = db_count;
@@ -1862,7 +1900,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                                ext3_count_dirs(sb));
        }
        if (err) {
-               printk(KERN_ERR "EXT3-fs: insufficient memory\n");
+               ext3_msg(sb, KERN_ERR, "error: insufficient memory");
                goto failed_mount3;
        }
 
@@ -1910,9 +1948,9 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                        goto failed_mount3;
        } else {
                if (!silent)
-                       printk (KERN_ERR
-                               "ext3: No journal on filesystem on %s\n",
-                               sb->s_id);
+                       ext3_msg(sb, KERN_ERR,
+                               "error: no journal found. "
+                               "mounting ext3 over ext2?");
                goto failed_mount3;
        }
 
@@ -1934,8 +1972,9 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        case EXT3_MOUNT_WRITEBACK_DATA:
                if (!journal_check_available_features
                    (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)) {
-                       printk(KERN_ERR "EXT3-fs: Journal does not support "
-                              "requested data journaling mode\n");
+                       ext3_msg(sb, KERN_ERR,
+                               "error: journal does not support "
+                               "requested data journaling mode");
                        goto failed_mount4;
                }
        default:
@@ -1944,8 +1983,9 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 
        if (test_opt(sb, NOBH)) {
                if (!(test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)) {
-                       printk(KERN_WARNING "EXT3-fs: Ignoring nobh option - "
-                               "its supported only with writeback mode\n");
+                       ext3_msg(sb, KERN_WARNING,
+                               "warning: ignoring nobh option - "
+                               "it is supported only with writeback mode");
                        clear_opt(sbi->s_mount_opt, NOBH);
                }
        }
@@ -1956,18 +1996,18 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 
        root = ext3_iget(sb, EXT3_ROOT_INO);
        if (IS_ERR(root)) {
-               printk(KERN_ERR "EXT3-fs: get root inode failed\n");
+               ext3_msg(sb, KERN_ERR, "error: get root inode failed");
                ret = PTR_ERR(root);
                goto failed_mount4;
        }
        if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
                iput(root);
-               printk(KERN_ERR "EXT3-fs: corrupt root inode, run e2fsck\n");
+               ext3_msg(sb, KERN_ERR, "error: corrupt root inode, run e2fsck");
                goto failed_mount4;
        }
        sb->s_root = d_alloc_root(root);
        if (!sb->s_root) {
-               printk(KERN_ERR "EXT3-fs: get root dentry failed\n");
+               ext3_msg(sb, KERN_ERR, "error: get root dentry failed");
                iput(root);
                ret = -ENOMEM;
                goto failed_mount4;
@@ -1986,9 +2026,9 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        ext3_orphan_cleanup(sb, es);
        EXT3_SB(sb)->s_mount_state &= ~EXT3_ORPHAN_FS;
        if (needs_recovery)
-               printk (KERN_INFO "EXT3-fs: recovery complete.\n");
+               ext3_msg(sb, KERN_INFO, "recovery complete");
        ext3_mark_recovery_complete(sb, es);
-       printk (KERN_INFO "EXT3-fs: mounted filesystem with %s data mode.\n",
+       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_ORDERED_DATA ? "ordered":
                "writeback");
@@ -1998,7 +2038,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 
 cantfind_ext3:
        if (!silent)
-               printk(KERN_ERR "VFS: Can't find ext3 filesystem on dev %s.\n",
+               ext3_msg(sb, KERN_INFO,
+                       "error: can't find ext3 filesystem on dev %s.",
                       sb->s_id);
        goto failed_mount;
 
@@ -2066,27 +2107,27 @@ static journal_t *ext3_get_journal(struct super_block *sb,
 
        journal_inode = ext3_iget(sb, journal_inum);
        if (IS_ERR(journal_inode)) {
-               printk(KERN_ERR "EXT3-fs: no journal found.\n");
+               ext3_msg(sb, KERN_ERR, "error: no journal found");
                return NULL;
        }
        if (!journal_inode->i_nlink) {
                make_bad_inode(journal_inode);
                iput(journal_inode);
-               printk(KERN_ERR "EXT3-fs: journal inode is deleted.\n");
+               ext3_msg(sb, KERN_ERR, "error: journal inode is deleted");
                return NULL;
        }
 
        jbd_debug(2, "Journal inode found at %p: %Ld bytes\n",
                  journal_inode, journal_inode->i_size);
        if (!S_ISREG(journal_inode->i_mode)) {
-               printk(KERN_ERR "EXT3-fs: invalid journal inode.\n");
+               ext3_msg(sb, KERN_ERR, "error: invalid journal inode");
                iput(journal_inode);
                return NULL;
        }
 
        journal = journal_init_inode(journal_inode);
        if (!journal) {
-               printk(KERN_ERR "EXT3-fs: Could not load journal inode\n");
+               ext3_msg(sb, KERN_ERR, "error: could not load journal inode");
                iput(journal_inode);
                return NULL;
        }
@@ -2108,13 +2149,13 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
        struct ext3_super_block * es;
        struct block_device *bdev;
 
-       bdev = ext3_blkdev_get(j_dev);
+       bdev = ext3_blkdev_get(j_dev, sb);
        if (bdev == NULL)
                return NULL;
 
        if (bd_claim(bdev, sb)) {
-               printk(KERN_ERR
-                       "EXT3: failed to claim external journal device.\n");
+               ext3_msg(sb, KERN_ERR,
+                       "error: failed to claim external journal device");
                blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
                return NULL;
        }
@@ -2122,8 +2163,8 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
        blocksize = sb->s_blocksize;
        hblock = bdev_logical_block_size(bdev);
        if (blocksize < hblock) {
-               printk(KERN_ERR
-                       "EXT3-fs: blocksize too small for journal device.\n");
+               ext3_msg(sb, KERN_ERR,
+                       "error: blocksize too small for journal device");
                goto out_bdev;
        }
 
@@ -2131,8 +2172,8 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
        offset = EXT3_MIN_BLOCK_SIZE % blocksize;
        set_blocksize(bdev, blocksize);
        if (!(bh = __bread(bdev, sb_block, blocksize))) {
-               printk(KERN_ERR "EXT3-fs: couldn't read superblock of "
-                      "external journal\n");
+               ext3_msg(sb, KERN_ERR, "error: couldn't read superblock of "
+                       "external journal");
                goto out_bdev;
        }
 
@@ -2140,14 +2181,14 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
        if ((le16_to_cpu(es->s_magic) != EXT3_SUPER_MAGIC) ||
            !(le32_to_cpu(es->s_feature_incompat) &
              EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
-               printk(KERN_ERR "EXT3-fs: external journal has "
-                                       "bad superblock\n");
+               ext3_msg(sb, KERN_ERR, "error: external journal has "
+                       "bad superblock");
                brelse(bh);
                goto out_bdev;
        }
 
        if (memcmp(EXT3_SB(sb)->s_es->s_journal_uuid, es->s_uuid, 16)) {
-               printk(KERN_ERR "EXT3-fs: journal UUID does not match\n");
+               ext3_msg(sb, KERN_ERR, "error: journal UUID does not match");
                brelse(bh);
                goto out_bdev;
        }
@@ -2159,19 +2200,21 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
        journal = journal_init_dev(bdev, sb->s_bdev,
                                        start, len, blocksize);
        if (!journal) {
-               printk(KERN_ERR "EXT3-fs: failed to create device journal\n");
+               ext3_msg(sb, KERN_ERR,
+                       "error: failed to create device journal");
                goto out_bdev;
        }
        journal->j_private = sb;
        ll_rw_block(READ, 1, &journal->j_sb_buffer);
        wait_on_buffer(journal->j_sb_buffer);
        if (!buffer_uptodate(journal->j_sb_buffer)) {
-               printk(KERN_ERR "EXT3-fs: I/O error on journal device\n");
+               ext3_msg(sb, KERN_ERR, "I/O error on journal device");
                goto out_journal;
        }
        if (be32_to_cpu(journal->j_superblock->s_nr_users) != 1) {
-               printk(KERN_ERR "EXT3-fs: External journal has more than one "
-                                       "user (unsupported) - %d\n",
+               ext3_msg(sb, KERN_ERR,
+                       "error: external journal has more than one "
+                       "user (unsupported) - %d",
                        be32_to_cpu(journal->j_superblock->s_nr_users));
                goto out_journal;
        }
@@ -2197,8 +2240,8 @@ static int ext3_load_journal(struct super_block *sb,
 
        if (journal_devnum &&
            journal_devnum != le32_to_cpu(es->s_journal_dev)) {
-               printk(KERN_INFO "EXT3-fs: external journal device major/minor "
-                       "numbers have changed\n");
+               ext3_msg(sb, KERN_INFO, "external journal device major/minor "
+                       "numbers have changed");
                journal_dev = new_decode_dev(journal_devnum);
        } else
                journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev));
@@ -2213,21 +2256,21 @@ static int ext3_load_journal(struct super_block *sb,
 
        if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER)) {
                if (sb->s_flags & MS_RDONLY) {
-                       printk(KERN_INFO "EXT3-fs: INFO: recovery "
-                                       "required on readonly filesystem.\n");
+                       ext3_msg(sb, KERN_INFO,
+                               "recovery required on readonly filesystem");
                        if (really_read_only) {
-                               printk(KERN_ERR "EXT3-fs: write access "
-                                       "unavailable, cannot proceed.\n");
+                               ext3_msg(sb, KERN_ERR, "error: write access "
+                                       "unavailable, cannot proceed");
                                return -EROFS;
                        }
-                       printk (KERN_INFO "EXT3-fs: write access will "
-                                       "be enabled during recovery.\n");
+                       ext3_msg(sb, KERN_INFO,
+                               "write access will be enabled during recovery");
                }
        }
 
        if (journal_inum && journal_dev) {
-               printk(KERN_ERR "EXT3-fs: filesystem has both journal "
-                      "and inode journals!\n");
+               ext3_msg(sb, KERN_ERR, "error: filesystem has both journal "
+                      "and inode journals");
                return -EINVAL;
        }
 
@@ -2242,7 +2285,7 @@ static int ext3_load_journal(struct super_block *sb,
        if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) {
                err = journal_update_format(journal);
                if (err)  {
-                       printk(KERN_ERR "EXT3-fs: error updating journal.\n");
+                       ext3_msg(sb, KERN_ERR, "error updating journal");
                        journal_destroy(journal);
                        return err;
                }
@@ -2254,7 +2297,7 @@ static int ext3_load_journal(struct super_block *sb,
                err = journal_load(journal);
 
        if (err) {
-               printk(KERN_ERR "EXT3-fs: error loading journal.\n");
+               ext3_msg(sb, KERN_ERR, "error loading journal");
                journal_destroy(journal);
                return err;
        }
@@ -2273,16 +2316,17 @@ static int ext3_load_journal(struct super_block *sb,
        return 0;
 }
 
-static int ext3_create_journal(struct super_block * sb,
-                              struct ext3_super_block * es,
+static int ext3_create_journal(struct super_block *sb,
+                              struct ext3_super_block *es,
                               unsigned int journal_inum)
 {
        journal_t *journal;
        int err;
 
        if (sb->s_flags & MS_RDONLY) {
-               printk(KERN_ERR "EXT3-fs: readonly filesystem when trying to "
-                               "create journal.\n");
+               ext3_msg(sb, KERN_ERR,
+                       "error: readonly filesystem when trying to "
+                       "create journal");
                return -EROFS;
        }
 
@@ -2290,12 +2334,12 @@ static int ext3_create_journal(struct super_block * sb,
        if (!journal)
                return -EINVAL;
 
-       printk(KERN_INFO "EXT3-fs: creating new journal on inode %u\n",
+       ext3_msg(sb, KERN_INFO, "creating new journal on inode %u",
               journal_inum);
 
        err = journal_create(journal);
        if (err) {
-               printk(KERN_ERR "EXT3-fs: error creating journal.\n");
+               ext3_msg(sb, KERN_ERR, "error creating journal");
                journal_destroy(journal);
                return -EIO;
        }
@@ -2376,8 +2420,8 @@ out:
  * has recorded an error from a previous lifetime, move that error to the
  * main filesystem now.
  */
-static void ext3_clear_journal_err(struct super_block * sb,
-                                  struct ext3_super_block * es)
+static void ext3_clear_journal_err(struct super_block *sb,
+                                  struct ext3_super_block *es)
 {
        journal_t *journal;
        int j_errno;
@@ -2568,10 +2612,10 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
                        __le32 ret;
                        if ((ret = EXT3_HAS_RO_COMPAT_FEATURE(sb,
                                        ~EXT3_FEATURE_RO_COMPAT_SUPP))) {
-                               printk(KERN_WARNING "EXT3-fs: %s: couldn't "
-                                      "remount RDWR because of unsupported "
-                                      "optional features (%x).\n",
-                                      sb->s_id, le32_to_cpu(ret));
+                               ext3_msg(sb, KERN_WARNING,
+                                       "warning: couldn't remount RDWR "
+                                       "because of unsupported optional "
+                                       "features (%x)", le32_to_cpu(ret));
                                err = -EROFS;
                                goto restore_opts;
                        }
@@ -2582,11 +2626,10 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
                         * require a full umount/remount for now.
                         */
                        if (es->s_last_orphan) {
-                               printk(KERN_WARNING "EXT3-fs: %s: couldn't "
+                               ext3_msg(sb, KERN_WARNING, "warning: couldn't "
                                       "remount RDWR because of unprocessed "
                                       "orphan inode list.  Please "
-                                      "umount/remount instead.\n",
-                                      sb->s_id);
+                                      "umount/remount instead.");
                                err = -EINVAL;
                                goto restore_opts;
                        }
@@ -2686,13 +2729,11 @@ static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf)
        buf->f_bsize = sb->s_blocksize;
        buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last;
        buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter);
-       es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
        buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
        if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
                buf->f_bavail = 0;
        buf->f_files = le32_to_cpu(es->s_inodes_count);
        buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter);
-       es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
        buf->f_namelen = EXT3_NAME_LEN;
        fsid = le64_to_cpup((void *)es->s_uuid) ^
               le64_to_cpup((void *)es->s_uuid + sizeof(u64));
@@ -2837,9 +2878,9 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id,
        if (EXT3_SB(sb)->s_qf_names[type]) {
                /* Quotafile not of fs root? */
                if (path.dentry->d_parent != sb->s_root)
-                       printk(KERN_WARNING
-                               "EXT3-fs: Quota file not on filesystem root. "
-                               "Journaled quota will not work.\n");
+                       ext3_msg(sb, KERN_WARNING,
+                               "warning: Quota file not on filesystem root. "
+                               "Journaled quota will not work.");
        }
 
        /*
@@ -2921,8 +2962,9 @@ static ssize_t ext3_quota_write(struct super_block *sb, int type,
        handle_t *handle = journal_current_handle();
 
        if (!handle) {
-               printk(KERN_WARNING "EXT3-fs: Quota write (off=%Lu, len=%Lu)"
-                       " cancelled because transaction is not started.\n",
+               ext3_msg(sb, KERN_WARNING,
+                       "warning: quota write (off=%llu, len=%llu)"
+                       " cancelled because transaction is not started.",
                        (unsigned long long)off, (unsigned long long)len);
                return -EIO;
        }
index 545e37c..387d92d 100644 (file)
@@ -960,6 +960,10 @@ ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
        if (error)
                goto cleanup;
 
+       error = ext3_journal_get_write_access(handle, is.iloc.bh);
+       if (error)
+               goto cleanup;
+
        if (EXT3_I(inode)->i_state & EXT3_STATE_NEW) {
                struct ext3_inode *raw_inode = ext3_raw_inode(&is.iloc);
                memset(raw_inode, 0, EXT3_SB(inode->i_sb)->s_inode_size);
@@ -985,9 +989,6 @@ ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
                if (flags & XATTR_CREATE)
                        goto cleanup;
        }
-       error = ext3_journal_get_write_access(handle, is.iloc.bh);
-       if (error)
-               goto cleanup;
        if (!value) {
                if (!is.s.not_found)
                        error = ext3_xattr_ibody_set(handle, inode, &i, &is);
index 8b58a14..768c111 100644 (file)
@@ -769,9 +769,22 @@ static inline void ext4_show_quota_options(struct seq_file *seq,
 #if defined(CONFIG_QUOTA)
        struct ext4_sb_info *sbi = EXT4_SB(sb);
 
-       if (sbi->s_jquota_fmt)
-               seq_printf(seq, ",jqfmt=%s",
-               (sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold" : "vfsv0");
+       if (sbi->s_jquota_fmt) {
+               char *fmtname = "";
+
+               switch (sbi->s_jquota_fmt) {
+               case QFMT_VFS_OLD:
+                       fmtname = "vfsold";
+                       break;
+               case QFMT_VFS_V0:
+                       fmtname = "vfsv0";
+                       break;
+               case QFMT_VFS_V1:
+                       fmtname = "vfsv1";
+                       break;
+               }
+               seq_printf(seq, ",jqfmt=%s", fmtname);
+       }
 
        if (sbi->s_qf_names[USRQUOTA])
                seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]);
@@ -1084,9 +1097,9 @@ enum {
        Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
        Opt_data_err_abort, Opt_data_err_ignore,
        Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
-       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
-       Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, Opt_resize,
-       Opt_usrquota, Opt_grpquota, Opt_i_version,
+       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
+       Opt_noquota, Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err,
+       Opt_resize, Opt_usrquota, Opt_grpquota, Opt_i_version,
        Opt_stripe, Opt_delalloc, Opt_nodelalloc,
        Opt_block_validity, Opt_noblock_validity,
        Opt_inode_readahead_blks, Opt_journal_ioprio,
@@ -1137,6 +1150,7 @@ static const match_table_t tokens = {
        {Opt_grpjquota, "grpjquota=%s"},
        {Opt_jqfmt_vfsold, "jqfmt=vfsold"},
        {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
+       {Opt_jqfmt_vfsv1, "jqfmt=vfsv1"},
        {Opt_grpquota, "grpquota"},
        {Opt_noquota, "noquota"},
        {Opt_quota, "quota"},
@@ -1439,6 +1453,9 @@ clear_qf_name:
                        goto set_qf_format;
                case Opt_jqfmt_vfsv0:
                        qfmt = QFMT_VFS_V0;
+                       goto set_qf_format;
+               case Opt_jqfmt_vfsv1:
+                       qfmt = QFMT_VFS_V1;
 set_qf_format:
                        if (sb_any_quota_loaded(sb) &&
                            sbi->s_jquota_fmt != qfmt) {
@@ -1481,6 +1498,7 @@ set_qf_format:
                case Opt_offgrpjquota:
                case Opt_jqfmt_vfsold:
                case Opt_jqfmt_vfsv0:
+               case Opt_jqfmt_vfsv1:
                        ext4_msg(sb, KERN_ERR,
                                "journaled quota options not supported");
                        break;
index defb932..0b3fa79 100644 (file)
@@ -36,286 +36,323 @@ static void *zisofs_zlib_workspace;
 static DEFINE_MUTEX(zisofs_zlib_lock);
 
 /*
- * When decompressing, we typically obtain more than one page
- * per reference.  We inject the additional pages into the page
- * cache as a form of readahead.
+ * Read data of @inode from @block_start to @block_end and uncompress
+ * to one zisofs block. Store the data in the @pages array with @pcount
+ * entries. Start storing at offset @poffset of the first page.
  */
-static int zisofs_readpage(struct file *file, struct page *page)
+static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,
+                                     loff_t block_end, int pcount,
+                                     struct page **pages, unsigned poffset,
+                                     int *errp)
 {
-       struct inode *inode = file->f_path.dentry->d_inode;
-       struct address_space *mapping = inode->i_mapping;
-       unsigned int maxpage, xpage, fpage, blockindex;
-       unsigned long offset;
-       unsigned long blockptr, blockendptr, cstart, cend, csize;
-       struct buffer_head *bh, *ptrbh[2];
-       unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
-       unsigned int bufshift = ISOFS_BUFFER_BITS(inode);
-       unsigned long bufmask  = bufsize - 1;
-       int err = -EIO;
-       int i;
-       unsigned int header_size = ISOFS_I(inode)->i_format_parm[0];
        unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1];
-       /* unsigned long zisofs_block_size = 1UL << zisofs_block_shift; */
-       unsigned int zisofs_block_page_shift = zisofs_block_shift-PAGE_CACHE_SHIFT;
-       unsigned long zisofs_block_pages = 1UL << zisofs_block_page_shift;
-       unsigned long zisofs_block_page_mask = zisofs_block_pages-1;
-       struct page *pages[zisofs_block_pages];
-       unsigned long index = page->index;
-       int indexblocks;
-
-       /* We have already been given one page, this is the one
-          we must do. */
-       xpage = index & zisofs_block_page_mask;
-       pages[xpage] = page;
-       /* The remaining pages need to be allocated and inserted */
-       offset = index & ~zisofs_block_page_mask;
-       blockindex = offset >> zisofs_block_page_shift;
-       maxpage = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-
-       /*
-        * If this page is wholly outside i_size we just return zero;
-        * do_generic_file_read() will handle this for us
-        */
-       if (page->index >= maxpage) {
-               SetPageUptodate(page);
-               unlock_page(page);
+       unsigned int bufsize = ISOFS_BUFFER_SIZE(inode);
+       unsigned int bufshift = ISOFS_BUFFER_BITS(inode);
+       unsigned int bufmask = bufsize - 1;
+       int i, block_size = block_end - block_start;
+       z_stream stream = { .total_out = 0,
+                           .avail_in = 0,
+                           .avail_out = 0, };
+       int zerr;
+       int needblocks = (block_size + (block_start & bufmask) + bufmask)
+                               >> bufshift;
+       int haveblocks;
+       blkcnt_t blocknum;
+       struct buffer_head *bhs[needblocks + 1];
+       int curbh, curpage;
+
+       if (block_size > deflateBound(1UL << zisofs_block_shift)) {
+               *errp = -EIO;
                return 0;
        }
-
-       maxpage = min(zisofs_block_pages, maxpage-offset);
-
-       for ( i = 0 ; i < maxpage ; i++, offset++ ) {
-               if ( i != xpage ) {
-                       pages[i] = grab_cache_page_nowait(mapping, offset);
-               }
-               page = pages[i];
-               if ( page ) {
-                       ClearPageError(page);
-                       kmap(page);
+       /* Empty block? */
+       if (block_size == 0) {
+               for ( i = 0 ; i < pcount ; i++ ) {
+                       if (!pages[i])
+                               continue;
+                       memset(page_address(pages[i]), 0, PAGE_CACHE_SIZE);
+                       flush_dcache_page(pages[i]);
+                       SetPageUptodate(pages[i]);
                }
+               return ((loff_t)pcount) << PAGE_CACHE_SHIFT;
        }
 
-       /* This is the last page filled, plus one; used in case of abort. */
-       fpage = 0;
+       /* Because zlib is not thread-safe, do all the I/O at the top. */
+       blocknum = block_start >> bufshift;
+       memset(bhs, 0, (needblocks + 1) * sizeof(struct buffer_head *));
+       haveblocks = isofs_get_blocks(inode, blocknum, bhs, needblocks);
+       ll_rw_block(READ, haveblocks, bhs);
 
-       /* Find the pointer to this specific chunk */
-       /* Note: we're not using isonum_731() here because the data is known aligned */
-       /* Note: header_size is in 32-bit words (4 bytes) */
-       blockptr = (header_size + blockindex) << 2;
-       blockendptr = blockptr + 4;
+       curbh = 0;
+       curpage = 0;
+       /*
+        * First block is special since it may be fractional.  We also wait for
+        * it before grabbing the zlib mutex; odds are that the subsequent
+        * blocks are going to come in in short order so we don't hold the zlib
+        * mutex longer than necessary.
+        */
 
-       indexblocks = ((blockptr^blockendptr) >> bufshift) ? 2 : 1;
-       ptrbh[0] = ptrbh[1] = NULL;
+       if (!bhs[0])
+               goto b_eio;
 
-       if ( isofs_get_blocks(inode, blockptr >> bufshift, ptrbh, indexblocks) != indexblocks ) {
-               if ( ptrbh[0] ) brelse(ptrbh[0]);
-               printk(KERN_DEBUG "zisofs: Null buffer on reading block table, inode = %lu, block = %lu\n",
-                      inode->i_ino, blockptr >> bufshift);
-               goto eio;
-       }
-       ll_rw_block(READ, indexblocks, ptrbh);
-
-       bh = ptrbh[0];
-       if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
-               printk(KERN_DEBUG "zisofs: Failed to read block table, inode = %lu, block = %lu\n",
-                      inode->i_ino, blockptr >> bufshift);
-               if ( ptrbh[1] )
-                       brelse(ptrbh[1]);
-               goto eio;
-       }
-       cstart = le32_to_cpu(*(__le32 *)(bh->b_data + (blockptr & bufmask)));
-
-       if ( indexblocks == 2 ) {
-               /* We just crossed a block boundary.  Switch to the next block */
-               brelse(bh);
-               bh = ptrbh[1];
-               if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
-                       printk(KERN_DEBUG "zisofs: Failed to read block table, inode = %lu, block = %lu\n",
-                              inode->i_ino, blockendptr >> bufshift);
-                       goto eio;
-               }
+       wait_on_buffer(bhs[0]);
+       if (!buffer_uptodate(bhs[0])) {
+               *errp = -EIO;
+               goto b_eio;
        }
-       cend = le32_to_cpu(*(__le32 *)(bh->b_data + (blockendptr & bufmask)));
-       brelse(bh);
 
-       if (cstart > cend)
-               goto eio;
+       stream.workspace = zisofs_zlib_workspace;
+       mutex_lock(&zisofs_zlib_lock);
                
-       csize = cend-cstart;
-
-       if (csize > deflateBound(1UL << zisofs_block_shift))
-               goto eio;
-
-       /* Now page[] contains an array of pages, any of which can be NULL,
-          and the locks on which we hold.  We should now read the data and
-          release the pages.  If the pages are NULL the decompressed data
-          for that particular page should be discarded. */
-       
-       if ( csize == 0 ) {
-               /* This data block is empty. */
-
-               for ( fpage = 0 ; fpage < maxpage ; fpage++ ) {
-                       if ( (page = pages[fpage]) != NULL ) {
-                               memset(page_address(page), 0, PAGE_CACHE_SIZE);
-                               
-                               flush_dcache_page(page);
-                               SetPageUptodate(page);
-                               kunmap(page);
-                               unlock_page(page);
-                               if ( fpage == xpage )
-                                       err = 0; /* The critical page */
-                               else
-                                       page_cache_release(page);
+       zerr = zlib_inflateInit(&stream);
+       if (zerr != Z_OK) {
+               if (zerr == Z_MEM_ERROR)
+                       *errp = -ENOMEM;
+               else
+                       *errp = -EIO;
+               printk(KERN_DEBUG "zisofs: zisofs_inflateInit returned %d\n",
+                              zerr);
+               goto z_eio;
+       }
+
+       while (curpage < pcount && curbh < haveblocks &&
+              zerr != Z_STREAM_END) {
+               if (!stream.avail_out) {
+                       if (pages[curpage]) {
+                               stream.next_out = page_address(pages[curpage])
+                                               + poffset;
+                               stream.avail_out = PAGE_CACHE_SIZE - poffset;
+                               poffset = 0;
+                       } else {
+                               stream.next_out = (void *)&zisofs_sink_page;
+                               stream.avail_out = PAGE_CACHE_SIZE;
                        }
                }
-       } else {
-               /* This data block is compressed. */
-               z_stream stream;
-               int bail = 0, left_out = -1;
-               int zerr;
-               int needblocks = (csize + (cstart & bufmask) + bufmask) >> bufshift;
-               int haveblocks;
-               struct buffer_head *bhs[needblocks+1];
-               struct buffer_head **bhptr;
-
-               /* Because zlib is not thread-safe, do all the I/O at the top. */
-
-               blockptr = cstart >> bufshift;
-               memset(bhs, 0, (needblocks+1)*sizeof(struct buffer_head *));
-               haveblocks = isofs_get_blocks(inode, blockptr, bhs, needblocks);
-               ll_rw_block(READ, haveblocks, bhs);
-
-               bhptr = &bhs[0];
-               bh = *bhptr++;
-
-               /* First block is special since it may be fractional.
-                  We also wait for it before grabbing the zlib
-                  mutex; odds are that the subsequent blocks are
-                  going to come in in short order so we don't hold
-                  the zlib mutex longer than necessary. */
-
-               if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
-                       printk(KERN_DEBUG "zisofs: Hit null buffer, fpage = %d, xpage = %d, csize = %ld\n",
-                              fpage, xpage, csize);
-                       goto b_eio;
-               }
-               stream.next_in  = bh->b_data + (cstart & bufmask);
-               stream.avail_in = min(bufsize-(cstart & bufmask), csize);
-               csize -= stream.avail_in;
-
-               stream.workspace = zisofs_zlib_workspace;
-               mutex_lock(&zisofs_zlib_lock);
-               
-               zerr = zlib_inflateInit(&stream);
-               if ( zerr != Z_OK ) {
-                       if ( err && zerr == Z_MEM_ERROR )
-                               err = -ENOMEM;
-                       printk(KERN_DEBUG "zisofs: zisofs_inflateInit returned %d\n",
-                              zerr);
-                       goto z_eio;
+               if (!stream.avail_in) {
+                       wait_on_buffer(bhs[curbh]);
+                       if (!buffer_uptodate(bhs[curbh])) {
+                               *errp = -EIO;
+                               break;
+                       }
+                       stream.next_in  = bhs[curbh]->b_data +
+                                               (block_start & bufmask);
+                       stream.avail_in = min_t(unsigned, bufsize -
+                                               (block_start & bufmask),
+                                               block_size);
+                       block_size -= stream.avail_in;
+                       block_start = 0;
                }
 
-               while ( !bail && fpage < maxpage ) {
-                       page = pages[fpage];
-                       if ( page )
-                               stream.next_out = page_address(page);
-                       else
-                               stream.next_out = (void *)&zisofs_sink_page;
-                       stream.avail_out = PAGE_CACHE_SIZE;
-
-                       while ( stream.avail_out ) {
-                               int ao, ai;
-                               if ( stream.avail_in == 0 && left_out ) {
-                                       if ( !csize ) {
-                                               printk(KERN_WARNING "zisofs: ZF read beyond end of input\n");
-                                               bail = 1;
-                                               break;
-                                       } else {
-                                               bh = *bhptr++;
-                                               if ( !bh ||
-                                                    (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
-                                                       /* Reached an EIO */
-                                                       printk(KERN_DEBUG "zisofs: Hit null buffer, fpage = %d, xpage = %d, csize = %ld\n",
-                                                              fpage, xpage, csize);
-                                                              
-                                                       bail = 1;
-                                                       break;
-                                               }
-                                               stream.next_in = bh->b_data;
-                                               stream.avail_in = min(csize,bufsize);
-                                               csize -= stream.avail_in;
-                                       }
-                               }
-                               ao = stream.avail_out;  ai = stream.avail_in;
-                               zerr = zlib_inflate(&stream, Z_SYNC_FLUSH);
-                               left_out = stream.avail_out;
-                               if ( zerr == Z_BUF_ERROR && stream.avail_in == 0 )
-                                       continue;
-                               if ( zerr != Z_OK ) {
-                                       /* EOF, error, or trying to read beyond end of input */
-                                       if ( err && zerr == Z_MEM_ERROR )
-                                               err = -ENOMEM;
-                                       if ( zerr != Z_STREAM_END )
-                                               printk(KERN_DEBUG "zisofs: zisofs_inflate returned %d, inode = %lu, index = %lu, fpage = %d, xpage = %d, avail_in = %d, avail_out = %d, ai = %d, ao = %d\n",
-                                                      zerr, inode->i_ino, index,
-                                                      fpage, xpage,
-                                                      stream.avail_in, stream.avail_out,
-                                                      ai, ao);
-                                       bail = 1;
-                                       break;
+               while (stream.avail_out && stream.avail_in) {
+                       zerr = zlib_inflate(&stream, Z_SYNC_FLUSH);
+                       if (zerr == Z_BUF_ERROR && stream.avail_in == 0)
+                               break;
+                       if (zerr == Z_STREAM_END)
+                               break;
+                       if (zerr != Z_OK) {
+                               /* EOF, error, or trying to read beyond end of input */
+                               if (zerr == Z_MEM_ERROR)
+                                       *errp = -ENOMEM;
+                               else {
+                                       printk(KERN_DEBUG
+                                              "zisofs: zisofs_inflate returned"
+                                              " %d, inode = %lu,"
+                                              " page idx = %d, bh idx = %d,"
+                                              " avail_in = %d,"
+                                              " avail_out = %d\n",
+                                              zerr, inode->i_ino, curpage,
+                                              curbh, stream.avail_in,
+                                              stream.avail_out);
+                                       *errp = -EIO;
                                }
+                               goto inflate_out;
                        }
+               }
 
-                       if ( stream.avail_out && zerr == Z_STREAM_END ) {
-                               /* Fractional page written before EOF.  This may
-                                  be the last page in the file. */
-                               memset(stream.next_out, 0, stream.avail_out);
-                               stream.avail_out = 0;
+               if (!stream.avail_out) {
+                       /* This page completed */
+                       if (pages[curpage]) {
+                               flush_dcache_page(pages[curpage]);
+                               SetPageUptodate(pages[curpage]);
                        }
+                       curpage++;
+               }
+               if (!stream.avail_in)
+                       curbh++;
+       }
+inflate_out:
+       zlib_inflateEnd(&stream);
 
-                       if ( !stream.avail_out ) {
-                               /* This page completed */
-                               if ( page ) {
-                                       flush_dcache_page(page);
-                                       SetPageUptodate(page);
-                                       kunmap(page);
-                                       unlock_page(page);
-                                       if ( fpage == xpage )
-                                               err = 0; /* The critical page */
-                                       else
-                                               page_cache_release(page);
-                               }
-                               fpage++;
-                       }
+z_eio:
+       mutex_unlock(&zisofs_zlib_lock);
+
+b_eio:
+       for (i = 0; i < haveblocks; i++)
+               brelse(bhs[i]);
+       return stream.total_out;
+}
+
+/*
+ * Uncompress data so that pages[full_page] is fully uptodate and possibly
+ * fills in other pages if we have data for them.
+ */
+static int zisofs_fill_pages(struct inode *inode, int full_page, int pcount,
+                            struct page **pages)
+{
+       loff_t start_off, end_off;
+       loff_t block_start, block_end;
+       unsigned int header_size = ISOFS_I(inode)->i_format_parm[0];
+       unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1];
+       unsigned int blockptr;
+       loff_t poffset = 0;
+       blkcnt_t cstart_block, cend_block;
+       struct buffer_head *bh;
+       unsigned int blkbits = ISOFS_BUFFER_BITS(inode);
+       unsigned int blksize = 1 << blkbits;
+       int err;
+       loff_t ret;
+
+       BUG_ON(!pages[full_page]);
+
+       /*
+        * We want to read at least 'full_page' page. Because we have to
+        * uncompress the whole compression block anyway, fill the surrounding
+        * pages with the data we have anyway...
+        */
+       start_off = page_offset(pages[full_page]);
+       end_off = min_t(loff_t, start_off + PAGE_CACHE_SIZE, inode->i_size);
+
+       cstart_block = start_off >> zisofs_block_shift;
+       cend_block = (end_off + (1 << zisofs_block_shift) - 1)
+                       >> zisofs_block_shift;
+
+       WARN_ON(start_off - (full_page << PAGE_CACHE_SHIFT) !=
+               ((cstart_block << zisofs_block_shift) & PAGE_CACHE_MASK));
+
+       /* Find the pointer to this specific chunk */
+       /* Note: we're not using isonum_731() here because the data is known aligned */
+       /* Note: header_size is in 32-bit words (4 bytes) */
+       blockptr = (header_size + cstart_block) << 2;
+       bh = isofs_bread(inode, blockptr >> blkbits);
+       if (!bh)
+               return -EIO;
+       block_start = le32_to_cpu(*(__le32 *)
+                               (bh->b_data + (blockptr & (blksize - 1))));
+
+       while (cstart_block < cend_block && pcount > 0) {
+               /* Load end of the compressed block in the file */
+               blockptr += 4;
+               /* Traversed to next block? */
+               if (!(blockptr & (blksize - 1))) {
+                       brelse(bh);
+
+                       bh = isofs_bread(inode, blockptr >> blkbits);
+                       if (!bh)
+                               return -EIO;
+               }
+               block_end = le32_to_cpu(*(__le32 *)
+                               (bh->b_data + (blockptr & (blksize - 1))));
+               if (block_start > block_end) {
+                       brelse(bh);
+                       return -EIO;
+               }
+               err = 0;
+               ret = zisofs_uncompress_block(inode, block_start, block_end,
+                                             pcount, pages, poffset, &err);
+               poffset += ret;
+               pages += poffset >> PAGE_CACHE_SHIFT;
+               pcount -= poffset >> PAGE_CACHE_SHIFT;
+               full_page -= poffset >> PAGE_CACHE_SHIFT;
+               poffset &= ~PAGE_CACHE_MASK;
+
+               if (err) {
+                       brelse(bh);
+                       /*
+                        * Did we finish reading the page we really wanted
+                        * to read?
+                        */
+                       if (full_page < 0)
+                               return 0;
+                       return err;
                }
-               zlib_inflateEnd(&stream);
 
-       z_eio:
-               mutex_unlock(&zisofs_zlib_lock);
+               block_start = block_end;
+               cstart_block++;
+       }
+
+       if (poffset && *pages) {
+               memset(page_address(*pages) + poffset, 0,
+                      PAGE_CACHE_SIZE - poffset);
+               flush_dcache_page(*pages);
+               SetPageUptodate(*pages);
+       }
+       return 0;
+}
 
-       b_eio:
-               for ( i = 0 ; i < haveblocks ; i++ ) {
-                       if ( bhs[i] )
-                               brelse(bhs[i]);
+/*
+ * When decompressing, we typically obtain more than one page
+ * per reference.  We inject the additional pages into the page
+ * cache as a form of readahead.
+ */
+static int zisofs_readpage(struct file *file, struct page *page)
+{
+       struct inode *inode = file->f_path.dentry->d_inode;
+       struct address_space *mapping = inode->i_mapping;
+       int err;
+       int i, pcount, full_page;
+       unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1];
+       unsigned int zisofs_pages_per_cblock =
+               PAGE_CACHE_SHIFT <= zisofs_block_shift ?
+               (1 << (zisofs_block_shift - PAGE_CACHE_SHIFT)) : 0;
+       struct page *pages[max_t(unsigned, zisofs_pages_per_cblock, 1)];
+       pgoff_t index = page->index, end_index;
+
+       end_index = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+       /*
+        * If this page is wholly outside i_size we just return zero;
+        * do_generic_file_read() will handle this for us
+        */
+       if (index >= end_index) {
+               SetPageUptodate(page);
+               unlock_page(page);
+               return 0;
+       }
+
+       if (PAGE_CACHE_SHIFT <= zisofs_block_shift) {
+               /* We have already been given one page, this is the one
+                  we must do. */
+               full_page = index & (zisofs_pages_per_cblock - 1);
+               pcount = min_t(int, zisofs_pages_per_cblock,
+                       end_index - (index & ~(zisofs_pages_per_cblock - 1)));
+               index -= full_page;
+       } else {
+               full_page = 0;
+               pcount = 1;
+       }
+       pages[full_page] = page;
+
+       for (i = 0; i < pcount; i++, index++) {
+               if (i != full_page)
+                       pages[i] = grab_cache_page_nowait(mapping, index);
+               if (pages[i]) {
+                       ClearPageError(pages[i]);
+                       kmap(pages[i]);
                }
        }
 
-eio:
+       err = zisofs_fill_pages(inode, full_page, pcount, pages);
 
        /* Release any residual pages, do not SetPageUptodate */
-       while ( fpage < maxpage ) {
-               page = pages[fpage];
-               if ( page ) {
-                       flush_dcache_page(page);
-                       if ( fpage == xpage )
-                               SetPageError(page);
-                       kunmap(page);
-                       unlock_page(page);
-                       if ( fpage != xpage )
-                               page_cache_release(page);
+       for (i = 0; i < pcount; i++) {
+               if (pages[i]) {
+                       flush_dcache_page(pages[i]);
+                       if (i == full_page && err)
+                               SetPageError(pages[i]);
+                       kunmap(pages[i]);
+                       unlock_page(pages[i]);
+                       if (i != full_page)
+                               page_cache_release(pages[i]);
                }
-               fpage++;
        }                       
 
        /* At this point, err contains 0 or -EIO depending on the "critical" page */
index c2fb2dd..96a685c 100644 (file)
@@ -518,8 +518,7 @@ repeat:
                        if (algo == SIG('p', 'z')) {
                                int block_shift =
                                        isonum_711(&rr->u.ZF.parms[1]);
-                               if (block_shift < PAGE_CACHE_SHIFT
-                                               || block_shift > 17) {
+                               if (block_shift > 17) {
                                        printk(KERN_WARNING "isofs: "
                                                "Can't handle ZF block "
                                                "size of 2^%d\n",
index 8896c1d..6a10238 100644 (file)
@@ -286,7 +286,7 @@ static int journal_finish_inode_data_buffers(journal_t *journal,
                if (err) {
                        /*
                         * Because AS_EIO is cleared by
-                        * wait_on_page_writeback_range(), set it again so
+                        * filemap_fdatawait_range(), set it again so
                         * that user process can get -EIO from fsync().
                         */
                        set_bit(AS_EIO,
index d3c190c..87f97ba 100644 (file)
@@ -1656,6 +1656,15 @@ struct file *do_filp_open(int dfd, const char *pathname,
        int will_write;
        int flag = open_to_namei_flags(open_flag);
 
+       /*
+        * O_SYNC is implemented as __O_SYNC|O_DSYNC.  As many places only
+        * check for O_DSYNC if the need any syncing at all we enforce it's
+        * always set instead of having to deal with possibly weird behaviour
+        * for malicious applications setting only __O_SYNC.
+        */
+       if (open_flag & __O_SYNC)
+               open_flag |= O_DSYNC;
+
        if (!acc_mode)
                acc_mode = MAY_OPEN | ACC_MODE(flag);
 
index f5fdd39..6b89132 100644 (file)
@@ -581,7 +581,7 @@ static int nfs_need_sync_write(struct file *filp, struct inode *inode)
 {
        struct nfs_open_context *ctx;
 
-       if (IS_SYNC(inode) || (filp->f_flags & O_SYNC))
+       if (IS_SYNC(inode) || (filp->f_flags & O_DSYNC))
                return 1;
        ctx = nfs_file_open_context(filp);
        if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags))
@@ -622,7 +622,7 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
 
        nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count);
        result = generic_file_aio_write(iocb, iov, nr_segs, pos);
-       /* Return error values for O_SYNC and IS_SYNC() */
+       /* Return error values for O_DSYNC and IS_SYNC() */
        if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) {
                int err = nfs_do_fsync(nfs_file_open_context(iocb->ki_filp), inode);
                if (err < 0)
index c84b5cc..b1ce2ea 100644 (file)
@@ -774,7 +774,7 @@ int nfs_updatepage(struct file *file, struct page *page,
         */
        if (nfs_write_pageuptodate(page, inode) &&
                        inode->i_flock == NULL &&
-                       !(file->f_flags & O_SYNC)) {
+                       !(file->f_flags & O_DSYNC)) {
                count = max(count + offset, nfs_page_length(page));
                offset = 0;
        }
index de059f4..3d30a1c 100644 (file)
@@ -2006,7 +2006,7 @@ out_dio:
        /* buffered aio wouldn't have proper lock coverage today */
        BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT));
 
-       if ((file->f_flags & O_SYNC && !direct_io) || IS_SYNC(inode)) {
+       if ((file->f_flags & O_DSYNC && !direct_io) || IS_SYNC(inode)) {
                ret = filemap_fdatawrite_range(file->f_mapping, pos,
                                               pos + count - 1);
                if (ret < 0)
index e5df9d1..123bc52 100644 (file)
 
 #include "ocfs2.h"
 
-/* Common stuff */
-/* id number of quota format */
-#define QFMT_OCFS2 3
-
 /*
  * In-memory structures
  */
index 1a2c50a..21f9e71 100644 (file)
@@ -1325,7 +1325,7 @@ out:
        return status;
 }
 
-static struct quota_format_ops ocfs2_format_ops = {
+static const struct quota_format_ops ocfs2_format_ops = {
        .check_quota_file       = ocfs2_local_check_quota_file,
        .read_file_info         = ocfs2_local_read_info,
        .write_file_info        = ocfs2_global_write_info,
index 353e78a..efc02eb 100644 (file)
@@ -46,12 +46,14 @@ config QFMT_V1
          format say Y here.
 
 config QFMT_V2
-       tristate "Quota format v2 support"
+       tristate "Quota format vfsv0 and vfsv1 support"
        depends on QUOTA
        select QUOTA_TREE
        help
-         This quota format allows using quotas with 32-bit UIDs/GIDs. If you
-         need this functionality say Y here.
+         This config option enables kernel support for vfsv0 and vfsv1 quota
+         formats. Both these formats support 32-bit UIDs/GIDs and vfsv1 format
+         also supports 64-bit inode and block quota limits. If you need this
+         functionality say Y here.
 
 config QUOTACTL
        bool
index eb5a755..cd6bb9a 100644 (file)
@@ -2164,7 +2164,9 @@ int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
        struct dentry *dentry;
        int error;
 
+       mutex_lock(&sb->s_root->d_inode->i_mutex);
        dentry = lookup_one_len(qf_name, sb->s_root, strlen(qf_name));
+       mutex_unlock(&sb->s_root->d_inode->i_mutex);
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
 
index 0edcf42..2ae757e 100644 (file)
@@ -204,7 +204,7 @@ out:
        return ret;
 }
 
-static struct quota_format_ops v1_format_ops = {
+static const struct quota_format_ops v1_format_ops = {
        .check_quota_file       = v1_check_quota_file,
        .read_file_info         = v1_read_file_info,
        .write_file_info        = v1_write_file_info,
index a5475fb..3dfc23e 100644 (file)
@@ -23,14 +23,23 @@ MODULE_LICENSE("GPL");
 
 #define __QUOTA_V2_PARANOIA
 
-static void v2_mem2diskdqb(void *dp, struct dquot *dquot);
-static void v2_disk2memdqb(struct dquot *dquot, void *dp);
-static int v2_is_id(void *dp, struct dquot *dquot);
-
-static struct qtree_fmt_operations v2_qtree_ops = {
-       .mem2disk_dqblk = v2_mem2diskdqb,
-       .disk2mem_dqblk = v2_disk2memdqb,
-       .is_id = v2_is_id,
+static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot);
+static void v2r0_disk2memdqb(struct dquot *dquot, void *dp);
+static int v2r0_is_id(void *dp, struct dquot *dquot);
+static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot);
+static void v2r1_disk2memdqb(struct dquot *dquot, void *dp);
+static int v2r1_is_id(void *dp, struct dquot *dquot);
+
+static struct qtree_fmt_operations v2r0_qtree_ops = {
+       .mem2disk_dqblk = v2r0_mem2diskdqb,
+       .disk2mem_dqblk = v2r0_disk2memdqb,
+       .is_id = v2r0_is_id,
+};
+
+static struct qtree_fmt_operations v2r1_qtree_ops = {
+       .mem2disk_dqblk = v2r1_mem2diskdqb,
+       .disk2mem_dqblk = v2r1_disk2memdqb,
+       .is_id = v2r1_is_id,
 };
 
 #define QUOTABLOCK_BITS 10
@@ -46,23 +55,33 @@ static inline qsize_t v2_qbtos(qsize_t blocks)
        return blocks << QUOTABLOCK_BITS;
 }
 
+static int v2_read_header(struct super_block *sb, int type,
+                         struct v2_disk_dqheader *dqhead)
+{
+       ssize_t size;
+
+       size = sb->s_op->quota_read(sb, type, (char *)dqhead,
+                                   sizeof(struct v2_disk_dqheader), 0);
+       if (size != sizeof(struct v2_disk_dqheader)) {
+               printk(KERN_WARNING "quota_v2: Failed header read:"
+                      " expected=%zd got=%zd\n",
+                       sizeof(struct v2_disk_dqheader), size);
+               return 0;
+       }
+       return 1;
+}
+
 /* Check whether given file is really vfsv0 quotafile */
 static int v2_check_quota_file(struct super_block *sb, int type)
 {
        struct v2_disk_dqheader dqhead;
-       ssize_t size;
        static const uint quota_magics[] = V2_INITQMAGICS;
        static const uint quota_versions[] = V2_INITQVERSIONS;
  
-       size = sb->s_op->quota_read(sb, type, (char *)&dqhead,
-                                   sizeof(struct v2_disk_dqheader), 0);
-       if (size != sizeof(struct v2_disk_dqheader)) {
-               printk("quota_v2: failed read expected=%zd got=%zd\n",
-                       sizeof(struct v2_disk_dqheader), size);
+       if (!v2_read_header(sb, type, &dqhead))
                return 0;
-       }
        if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
-           le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
+           le32_to_cpu(dqhead.dqh_version) > quota_versions[type])
                return 0;
        return 1;
 }
@@ -71,14 +90,20 @@ static int v2_check_quota_file(struct super_block *sb, int type)
 static int v2_read_file_info(struct super_block *sb, int type)
 {
        struct v2_disk_dqinfo dinfo;
+       struct v2_disk_dqheader dqhead;
        struct mem_dqinfo *info = sb_dqinfo(sb, type);
        struct qtree_mem_dqinfo *qinfo;
        ssize_t size;
+       unsigned int version;
+
+       if (!v2_read_header(sb, type, &dqhead))
+               return 0;
+       version = le32_to_cpu(dqhead.dqh_version);
 
        size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
               sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
        if (size != sizeof(struct v2_disk_dqinfo)) {
-               printk(KERN_WARNING "Can't read info structure on device %s.\n",
+               printk(KERN_WARNING "quota_v2: Can't read info structure on device %s.\n",
                        sb->s_id);
                return -1;
        }
@@ -89,9 +114,15 @@ static int v2_read_file_info(struct super_block *sb, int type)
                return -1;
        }
        qinfo = info->dqi_priv;
-       /* limits are stored as unsigned 32-bit data */
-       info->dqi_maxblimit = 0xffffffff;
-       info->dqi_maxilimit = 0xffffffff;
+       if (version == 0) {
+               /* limits are stored as unsigned 32-bit data */
+               info->dqi_maxblimit = 0xffffffff;
+               info->dqi_maxilimit = 0xffffffff;
+       } else {
+               /* used space is stored as unsigned 64-bit value */
+               info->dqi_maxblimit = 0xffffffffffffffff;       /* 2^64-1 */
+               info->dqi_maxilimit = 0xffffffffffffffff;
+       }
        info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
        info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
        info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);
@@ -103,8 +134,13 @@ static int v2_read_file_info(struct super_block *sb, int type)
        qinfo->dqi_blocksize_bits = V2_DQBLKSIZE_BITS;
        qinfo->dqi_usable_bs = 1 << V2_DQBLKSIZE_BITS;
        qinfo->dqi_qtree_depth = qtree_depth(qinfo);
-       qinfo->dqi_entry_size = sizeof(struct v2_disk_dqblk);
-       qinfo->dqi_ops = &v2_qtree_ops;
+       if (version == 0) {
+               qinfo->dqi_entry_size = sizeof(struct v2r0_disk_dqblk);
+               qinfo->dqi_ops = &v2r0_qtree_ops;
+       } else {
+               qinfo->dqi_entry_size = sizeof(struct v2r1_disk_dqblk);
+               qinfo->dqi_ops = &v2r1_qtree_ops;
+       }
        return 0;
 }
 
@@ -135,9 +171,9 @@ static int v2_write_file_info(struct super_block *sb, int type)
        return 0;
 }
 
-static void v2_disk2memdqb(struct dquot *dquot, void *dp)
+static void v2r0_disk2memdqb(struct dquot *dquot, void *dp)
 {
-       struct v2_disk_dqblk *d = dp, empty;
+       struct v2r0_disk_dqblk *d = dp, empty;
        struct mem_dqblk *m = &dquot->dq_dqb;
 
        m->dqb_ihardlimit = le32_to_cpu(d->dqb_ihardlimit);
@@ -149,15 +185,15 @@ static void v2_disk2memdqb(struct dquot *dquot, void *dp)
        m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
        m->dqb_btime = le64_to_cpu(d->dqb_btime);
        /* We need to escape back all-zero structure */
-       memset(&empty, 0, sizeof(struct v2_disk_dqblk));
+       memset(&empty, 0, sizeof(struct v2r0_disk_dqblk));
        empty.dqb_itime = cpu_to_le64(1);
-       if (!memcmp(&empty, dp, sizeof(struct v2_disk_dqblk)))
+       if (!memcmp(&empty, dp, sizeof(struct v2r0_disk_dqblk)))
                m->dqb_itime = 0;
 }
 
-static void v2_mem2diskdqb(void *dp, struct dquot *dquot)
+static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot)
 {
-       struct v2_disk_dqblk *d = dp;
+       struct v2r0_disk_dqblk *d = dp;
        struct mem_dqblk *m = &dquot->dq_dqb;
        struct qtree_mem_dqinfo *info =
                        sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
@@ -175,9 +211,60 @@ static void v2_mem2diskdqb(void *dp, struct dquot *dquot)
                d->dqb_itime = cpu_to_le64(1);
 }
 
-static int v2_is_id(void *dp, struct dquot *dquot)
+static int v2r0_is_id(void *dp, struct dquot *dquot)
+{
+       struct v2r0_disk_dqblk *d = dp;
+       struct qtree_mem_dqinfo *info =
+                       sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
+
+       if (qtree_entry_unused(info, dp))
+               return 0;
+       return le32_to_cpu(d->dqb_id) == dquot->dq_id;
+}
+
+static void v2r1_disk2memdqb(struct dquot *dquot, void *dp)
+{
+       struct v2r1_disk_dqblk *d = dp, empty;
+       struct mem_dqblk *m = &dquot->dq_dqb;
+
+       m->dqb_ihardlimit = le64_to_cpu(d->dqb_ihardlimit);
+       m->dqb_isoftlimit = le64_to_cpu(d->dqb_isoftlimit);
+       m->dqb_curinodes = le64_to_cpu(d->dqb_curinodes);
+       m->dqb_itime = le64_to_cpu(d->dqb_itime);
+       m->dqb_bhardlimit = v2_qbtos(le64_to_cpu(d->dqb_bhardlimit));
+       m->dqb_bsoftlimit = v2_qbtos(le64_to_cpu(d->dqb_bsoftlimit));
+       m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
+       m->dqb_btime = le64_to_cpu(d->dqb_btime);
+       /* We need to escape back all-zero structure */
+       memset(&empty, 0, sizeof(struct v2r1_disk_dqblk));
+       empty.dqb_itime = cpu_to_le64(1);
+       if (!memcmp(&empty, dp, sizeof(struct v2r1_disk_dqblk)))
+               m->dqb_itime = 0;
+}
+
+static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot)
+{
+       struct v2r1_disk_dqblk *d = dp;
+       struct mem_dqblk *m = &dquot->dq_dqb;
+       struct qtree_mem_dqinfo *info =
+                       sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
+
+       d->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit);
+       d->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit);
+       d->dqb_curinodes = cpu_to_le64(m->dqb_curinodes);
+       d->dqb_itime = cpu_to_le64(m->dqb_itime);
+       d->dqb_bhardlimit = cpu_to_le64(v2_stoqb(m->dqb_bhardlimit));
+       d->dqb_bsoftlimit = cpu_to_le64(v2_stoqb(m->dqb_bsoftlimit));
+       d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
+       d->dqb_btime = cpu_to_le64(m->dqb_btime);
+       d->dqb_id = cpu_to_le32(dquot->dq_id);
+       if (qtree_entry_unused(info, dp))
+               d->dqb_itime = cpu_to_le64(1);
+}
+
+static int v2r1_is_id(void *dp, struct dquot *dquot)
 {
-       struct v2_disk_dqblk *d = dp;
+       struct v2r1_disk_dqblk *d = dp;
        struct qtree_mem_dqinfo *info =
                        sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
 
@@ -207,7 +294,7 @@ static int v2_free_file_info(struct super_block *sb, int type)
        return 0;
 }
 
-static struct quota_format_ops v2_format_ops = {
+static const struct quota_format_ops v2_format_ops = {
        .check_quota_file       = v2_check_quota_file,
        .read_file_info         = v2_read_file_info,
        .write_file_info        = v2_write_file_info,
@@ -217,20 +304,32 @@ static struct quota_format_ops v2_format_ops = {
        .release_dqblk          = v2_release_dquot,
 };
 
-static struct quota_format_type v2_quota_format = {
+static struct quota_format_type v2r0_quota_format = {
        .qf_fmt_id      = QFMT_VFS_V0,
        .qf_ops         = &v2_format_ops,
        .qf_owner       = THIS_MODULE
 };
 
+static struct quota_format_type v2r1_quota_format = {
+       .qf_fmt_id      = QFMT_VFS_V1,
+       .qf_ops         = &v2_format_ops,
+       .qf_owner       = THIS_MODULE
+};
+
 static int __init init_v2_quota_format(void)
 {
-       return register_quota_format(&v2_quota_format);
+       int ret;
+
+       ret = register_quota_format(&v2r0_quota_format);
+       if (ret)
+               return ret;
+       return register_quota_format(&v2r1_quota_format);
 }
 
 static void __exit exit_v2_quota_format(void)
 {
-       unregister_quota_format(&v2_quota_format);
+       unregister_quota_format(&v2r0_quota_format);
+       unregister_quota_format(&v2r1_quota_format);
 }
 
 module_init(init_v2_quota_format);
index 530fe58..f1966b4 100644 (file)
@@ -17,8 +17,8 @@
 }
 
 #define V2_INITQVERSIONS {\
-       0,              /* USRQUOTA */\
-       0               /* GRPQUOTA */\
+       1,              /* USRQUOTA */\
+       1               /* GRPQUOTA */\
 }
 
 /* First generic header */
@@ -32,7 +32,7 @@ struct v2_disk_dqheader {
  * (as it appears on disk) - the file is a radix tree whose leaves point
  * to blocks of these structures.
  */
-struct v2_disk_dqblk {
+struct v2r0_disk_dqblk {
        __le32 dqb_id;          /* id this quota applies to */
        __le32 dqb_ihardlimit;  /* absolute limit on allocated inodes */
        __le32 dqb_isoftlimit;  /* preferred inode limit */
@@ -44,6 +44,19 @@ struct v2_disk_dqblk {
        __le64 dqb_itime;       /* time limit for excessive inode use */
 };
 
+struct v2r1_disk_dqblk {
+       __le32 dqb_id;          /* id this quota applies to */
+       __le32 dqb_pad;
+       __le64 dqb_ihardlimit;  /* absolute limit on allocated inodes */
+       __le64 dqb_isoftlimit;  /* preferred inode limit */
+       __le64 dqb_curinodes;   /* current # allocated inodes */
+       __le64 dqb_bhardlimit;  /* absolute limit on disk space (in QUOTABLOCK_SIZE) */
+       __le64 dqb_bsoftlimit;  /* preferred limit on disk space (in QUOTABLOCK_SIZE) */
+       __le64 dqb_curspace;    /* current space occupied (in bytes) */
+       __le64 dqb_btime;       /* time limit for excessive disk use */
+       __le64 dqb_itime;       /* time limit for excessive inode use */
+};
+
 /* Header with type and version specific information */
 struct v2_disk_dqinfo {
        __le32 dqi_bgrace;      /* Time before block soft limit becomes hard limit */
index d104591..36752a6 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -295,10 +295,11 @@ SYSCALL_DEFINE1(fdatasync, unsigned int, fd)
  */
 int generic_write_sync(struct file *file, loff_t pos, loff_t count)
 {
-       if (!(file->f_flags & O_SYNC) && !IS_SYNC(file->f_mapping->host))
+       if (!(file->f_flags & O_DSYNC) && !IS_SYNC(file->f_mapping->host))
                return 0;
        return vfs_fsync_range(file, file->f_path.dentry, pos,
-                              pos + count - 1, 1);
+                              pos + count - 1,
+                              (file->f_flags & __O_SYNC) ? 0 : 1);
 }
 EXPORT_SYMBOL(generic_write_sync);
 
@@ -452,9 +453,7 @@ int do_sync_mapping_range(struct address_space *mapping, loff_t offset,
 
        ret = 0;
        if (flags & SYNC_FILE_RANGE_WAIT_BEFORE) {
-               ret = wait_on_page_writeback_range(mapping,
-                                       offset >> PAGE_CACHE_SHIFT,
-                                       endbyte >> PAGE_CACHE_SHIFT);
+               ret = filemap_fdatawait_range(mapping, offset, endbyte);
                if (ret < 0)
                        goto out;
        }
@@ -467,9 +466,7 @@ int do_sync_mapping_range(struct address_space *mapping, loff_t offset,
        }
 
        if (flags & SYNC_FILE_RANGE_WAIT_AFTER) {
-               ret = wait_on_page_writeback_range(mapping,
-                                       offset >> PAGE_CACHE_SHIFT,
-                                       endbyte >> PAGE_CACHE_SHIFT);
+               ret = filemap_fdatawait_range(mapping, offset, endbyte);
        }
 out:
        return ret;
index 78dbfcd..1bf47f2 100644 (file)
@@ -806,7 +806,7 @@ write_retry:
        XFS_STATS_ADD(xs_write_bytes, ret);
 
        /* Handle various SYNC-type writes */
-       if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
+       if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) {
                loff_t end = pos + ret - 1;
                int error2;
 
index 495dc8a..681ddf3 100644 (file)
@@ -3,8 +3,6 @@
 
 #include <linux/types.h>
 
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
 #define O_ACCMODE      00000003
 #define O_RDONLY       00000000
 #define O_WRONLY       00000001
@@ -27,8 +25,8 @@
 #ifndef O_NONBLOCK
 #define O_NONBLOCK     00004000
 #endif
-#ifndef O_SYNC
-#define O_SYNC         00010000
+#ifndef O_DSYNC
+#define O_DSYNC                00010000        /* used to be O_SYNC, see below */
 #endif
 #ifndef FASYNC
 #define FASYNC         00020000        /* fcntl, for BSD compatibility */
 #ifndef O_CLOEXEC
 #define O_CLOEXEC      02000000        /* set close_on_exec */
 #endif
+
+/*
+ * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
+ * the O_SYNC flag.  We continue to use the existing numerical value
+ * for O_DSYNC semantics now, but using the correct symbolic name for it.
+ * This new value is used to request true Posix O_SYNC semantics.  It is
+ * defined in this strange way to make sure applications compiled against
+ * new headers get at least O_DSYNC semantics on older kernels.
+ *
+ * This has the nice side-effect that we can simply test for O_DSYNC
+ * wherever we do not care if O_DSYNC or O_SYNC is used.
+ *
+ * Note: __O_SYNC must never be used directly.
+ */
+#ifndef O_SYNC
+#define __O_SYNC       04000000
+#define O_SYNC         (__O_SYNC|O_DSYNC)
+#endif
+
 #ifndef O_NDELAY
 #define O_NDELAY       O_NONBLOCK
 #endif
index 121720d..2dfa707 100644 (file)
@@ -565,14 +565,14 @@ struct ext2_dir_entry_2 {
  * other bits are reserved for now.
  */
 enum {
-       EXT2_FT_UNKNOWN,
-       EXT2_FT_REG_FILE,
-       EXT2_FT_DIR,
-       EXT2_FT_CHRDEV,
-       EXT2_FT_BLKDEV,
-       EXT2_FT_FIFO,
-       EXT2_FT_SOCK,
-       EXT2_FT_SYMLINK,
+       EXT2_FT_UNKNOWN         = 0,
+       EXT2_FT_REG_FILE        = 1,
+       EXT2_FT_DIR             = 2,
+       EXT2_FT_CHRDEV          = 3,
+       EXT2_FT_BLKDEV          = 4,
+       EXT2_FT_FIFO            = 5,
+       EXT2_FT_SOCK            = 6,
+       EXT2_FT_SYMLINK         = 7,
        EXT2_FT_MAX
 };
 
index 7499b36..6b04903 100644 (file)
@@ -918,6 +918,8 @@ extern void ext3_abort (struct super_block *, const char *, const char *, ...)
        __attribute__ ((format (printf, 3, 4)));
 extern void ext3_warning (struct super_block *, const char *, const char *, ...)
        __attribute__ ((format (printf, 3, 4)));
+extern void ext3_msg(struct super_block *, const char *, const char *, ...)
+       __attribute__ ((format (printf, 3, 4)));
 extern void ext3_update_dynamic_rev (struct super_block *sb);
 
 #define ext3_std_error(sb, errno)                              \
index 891f7d6..a057f48 100644 (file)
@@ -2091,8 +2091,6 @@ extern int filemap_fdatawait_range(struct address_space *, loff_t lstart,
 extern int filemap_write_and_wait(struct address_space *mapping);
 extern int filemap_write_and_wait_range(struct address_space *mapping,
                                        loff_t lstart, loff_t lend);
-extern int wait_on_page_writeback_range(struct address_space *mapping,
-                               pgoff_t start, pgoff_t end);
 extern int __filemap_fdatawrite_range(struct address_space *mapping,
                                loff_t start, loff_t end, int sync_mode);
 extern int filemap_fdatawrite_range(struct address_space *mapping,
index ce9a9b2..e70e621 100644 (file)
@@ -73,6 +73,8 @@
 /* Quota format type IDs */
 #define        QFMT_VFS_OLD 1
 #define        QFMT_VFS_V0 2
+#define QFMT_OCFS2 3
+#define        QFMT_VFS_V1 4
 
 /* Size of block in which space limits are passed through the quota
  * interface */
@@ -334,7 +336,7 @@ struct quotactl_ops {
 
 struct quota_format_type {
        int qf_fmt_id;  /* Quota format id */
-       struct quota_format_ops *qf_ops;        /* Operations of format */
+       const struct quota_format_ops *qf_ops;  /* Operations of format */
        struct module *qf_owner;                /* Module implementing quota format */
        struct quota_format_type *qf_next;
 };
@@ -394,7 +396,7 @@ struct quota_info {
        struct rw_semaphore dqptr_sem;          /* serialize ops using quota_info struct, pointers from inode to dquots */
        struct inode *files[MAXQUOTAS];         /* inodes of quotafiles */
        struct mem_dqinfo info[MAXQUOTAS];      /* Information for each quota type */
-       struct quota_format_ops *ops[MAXQUOTAS];        /* Operations for each type */
+       const struct quota_format_ops *ops[MAXQUOTAS];  /* Operations for each type */
 };
 
 int register_quota_format(struct quota_format_type *fmt);
index c3d3506..8b4d88f 100644 (file)
@@ -260,27 +260,27 @@ int filemap_flush(struct address_space *mapping)
 EXPORT_SYMBOL(filemap_flush);
 
 /**
- * wait_on_page_writeback_range - wait for writeback to complete
- * @mapping:   target address_space
- * @start:     beginning page index
- * @end:       ending page index
+ * filemap_fdatawait_range - wait for writeback to complete
+ * @mapping:           address space structure to wait for
+ * @start_byte:                offset in bytes where the range starts
+ * @end_byte:          offset in bytes where the range ends (inclusive)
  *
- * Wait for writeback to complete against pages indexed by start->end
- * inclusive
+ * Walk the list of under-writeback pages of the given address space
+ * in the given range and wait for all of them.
  */
-int wait_on_page_writeback_range(struct address_space *mapping,
-                               pgoff_t start, pgoff_t end)
+int filemap_fdatawait_range(struct address_space *mapping, loff_t start_byte,
+                           loff_t end_byte)
 {
+       pgoff_t index = start_byte >> PAGE_CACHE_SHIFT;
+       pgoff_t end = end_byte >> PAGE_CACHE_SHIFT;
        struct pagevec pvec;
        int nr_pages;
        int ret = 0;
-       pgoff_t index;
 
-       if (end < start)
+       if (end_byte < start_byte)
                return 0;
 
        pagevec_init(&pvec, 0);
-       index = start;
        while ((index <= end) &&
                        (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
                        PAGECACHE_TAG_WRITEBACK,
@@ -310,25 +310,6 @@ int wait_on_page_writeback_range(struct address_space *mapping,
 
        return ret;
 }
-
-/**
- * filemap_fdatawait_range - wait for all under-writeback pages to complete in a given range
- * @mapping: address space structure to wait for
- * @start:     offset in bytes where the range starts
- * @end:       offset in bytes where the range ends (inclusive)
- *
- * Walk the list of under-writeback pages of the given address space
- * in the given range and wait for all of them.
- *
- * This is just a simple wrapper so that callers don't have to convert offsets
- * to page indexes themselves
- */
-int filemap_fdatawait_range(struct address_space *mapping, loff_t start,
-                           loff_t end)
-{
-       return wait_on_page_writeback_range(mapping, start >> PAGE_CACHE_SHIFT,
-                                           end >> PAGE_CACHE_SHIFT);
-}
 EXPORT_SYMBOL(filemap_fdatawait_range);
 
 /**
@@ -345,8 +326,7 @@ int filemap_fdatawait(struct address_space *mapping)
        if (i_size == 0)
                return 0;
 
-       return wait_on_page_writeback_range(mapping, 0,
-                               (i_size - 1) >> PAGE_CACHE_SHIFT);
+       return filemap_fdatawait_range(mapping, 0, i_size - 1);
 }
 EXPORT_SYMBOL(filemap_fdatawait);
 
@@ -393,9 +373,8 @@ int filemap_write_and_wait_range(struct address_space *mapping,
                                                 WB_SYNC_ALL);
                /* See comment of filemap_write_and_wait() */
                if (err != -EIO) {
-                       int err2 = wait_on_page_writeback_range(mapping,
-                                               lstart >> PAGE_CACHE_SHIFT,
-                                               lend >> PAGE_CACHE_SHIFT);
+                       int err2 = filemap_fdatawait_range(mapping,
+                                               lstart, lend);
                        if (!err)
                                err = err2;
                }
index 2f76612..0f5a194 100644 (file)
@@ -1257,7 +1257,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,
                        break;
                count -= count1;
        }
-       if (file->f_flags & O_SYNC) {
+       if (file->f_flags & O_DSYNC) {
                spin_lock_irq(&runtime->lock);
                while (runtime->avail != runtime->buffer_size) {
                        wait_queue_t wait;