dquot: cleanup dquot drop routine
[safe/jmp/linux-2.6] / fs / reiserfs / super.c
index bf43460..34f7cd0 100644 (file)
@@ -11,7 +11,6 @@
  * NO WARRANTY
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/time.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/reiserfs_acl.h>
 #include <linux/reiserfs_xattr.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/buffer_head.h>
+#include <linux/exportfs.h>
+#include <linux/quotaops.h>
 #include <linux/vfs.h>
-#include <linux/namespace.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
-#include <linux/quotaops.h>
+#include <linux/crc32.h>
+#include <linux/smp_lock.h>
 
 struct file_system_type reiserfs_fs_type;
 
@@ -60,22 +60,19 @@ static int is_any_reiserfs_magic_string(struct reiserfs_super_block *rs)
 }
 
 static int reiserfs_remount(struct super_block *s, int *flags, char *data);
-static int reiserfs_statfs(struct super_block *s, struct kstatfs *buf);
+static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf);
 
 static int reiserfs_sync_fs(struct super_block *s, int wait)
 {
-       if (!(s->s_flags & MS_RDONLY)) {
-               struct reiserfs_transaction_handle th;
-               reiserfs_write_lock(s);
-               if (!journal_begin(&th, s, 1))
-                       if (!journal_end_sync(&th, s, 1))
-                               reiserfs_flush_old_commits(s);
-               s->s_dirt = 0;  /* Even if it's not true.
-                                * We'll loop forever in sync_supers otherwise */
-               reiserfs_write_unlock(s);
-       } else {
-               s->s_dirt = 0;
-       }
+       struct reiserfs_transaction_handle th;
+
+       reiserfs_write_lock(s);
+       if (!journal_begin(&th, s, 1))
+               if (!journal_end_sync(&th, s, 1))
+                       reiserfs_flush_old_commits(s);
+       s->s_dirt = 0;  /* Even if it's not true.
+                        * We'll loop forever in sync_supers otherwise */
+       reiserfs_write_unlock(s);
        return 0;
 }
 
@@ -84,7 +81,7 @@ static void reiserfs_write_super(struct super_block *s)
        reiserfs_sync_fs(s, 1);
 }
 
-static void reiserfs_write_super_lockfs(struct super_block *s)
+static int reiserfs_freeze(struct super_block *s)
 {
        struct reiserfs_transaction_handle th;
        reiserfs_write_lock(s);
@@ -102,11 +99,13 @@ static void reiserfs_write_super_lockfs(struct super_block *s)
        }
        s->s_dirt = 0;
        reiserfs_write_unlock(s);
+       return 0;
 }
 
-static void reiserfs_unlockfs(struct super_block *s)
+static int reiserfs_unfreeze(struct super_block *s)
 {
        reiserfs_allow_writes(s);
+       return 0;
 }
 
 extern const struct in_core_key MAX_IN_CORE_KEY;
@@ -146,7 +145,7 @@ static int finish_unfinished(struct super_block *s)
 {
        INITIALIZE_PATH(path);
        struct cpu_key max_cpu_key, obj_key;
-       struct reiserfs_key save_link_key;
+       struct reiserfs_key save_link_key, last_inode_key;
        int retval = 0;
        struct item_head *ih;
        struct buffer_head *bh;
@@ -167,6 +166,8 @@ static int finish_unfinished(struct super_block *s)
        set_cpu_key_k_offset(&max_cpu_key, ~0U);
        max_cpu_key.key_length = 3;
 
+       memset(&last_inode_key, 0, sizeof(last_inode_key));
+
 #ifdef CONFIG_QUOTA
        /* Needed for iput() to work correctly and not trash data */
        if (s->s_flags & MS_ACTIVE) {
@@ -180,9 +181,9 @@ static int finish_unfinished(struct super_block *s)
                if (REISERFS_SB(s)->s_qf_names[i]) {
                        int ret = reiserfs_quota_on_mount(s, i);
                        if (ret < 0)
-                               reiserfs_warning(s,
-                                                "reiserfs: cannot turn on journalled quota: error %d",
-                                                ret);
+                               reiserfs_warning(s, "reiserfs-2500",
+                                                "cannot turn on journaled "
+                                                "quota: error %d", ret);
                }
        }
 #endif
@@ -192,17 +193,16 @@ static int finish_unfinished(struct super_block *s)
        while (!retval) {
                retval = search_item(s, &max_cpu_key, &path);
                if (retval != ITEM_NOT_FOUND) {
-                       reiserfs_warning(s,
-                                        "vs-2140: finish_unfinished: search_by_key returned %d",
-                                        retval);
+                       reiserfs_error(s, "vs-2140",
+                                      "search_by_key returned %d", retval);
                        break;
                }
 
                bh = get_last_bh(&path);
                item_pos = get_item_pos(&path);
                if (item_pos != B_NR_ITEMS(bh)) {
-                       reiserfs_warning(s,
-                                        "vs-2060: finish_unfinished: wrong position found");
+                       reiserfs_warning(s, "vs-2060",
+                                        "wrong position found");
                        break;
                }
                item_pos--;
@@ -232,8 +232,7 @@ static int finish_unfinished(struct super_block *s)
                if (!inode) {
                        /* the unlink almost completed, it just did not manage to remove
                           "save" link and release objectid */
-                       reiserfs_warning(s,
-                                        "vs-2180: finish_unfinished: iget failed for %K",
+                       reiserfs_warning(s, "vs-2180", "iget failed for %K",
                                         &obj_key);
                        retval = remove_save_link_only(s, &save_link_key, 1);
                        continue;
@@ -241,21 +240,22 @@ static int finish_unfinished(struct super_block *s)
 
                if (!truncate && inode->i_nlink) {
                        /* file is not unlinked */
-                       reiserfs_warning(s,
-                                        "vs-2185: finish_unfinished: file %K is not unlinked",
+                       reiserfs_warning(s, "vs-2185",
+                                        "file %K is not unlinked",
                                         &obj_key);
                        retval = remove_save_link_only(s, &save_link_key, 0);
                        continue;
                }
-               DQUOT_INIT(inode);
+               vfs_dq_init(inode);
 
                if (truncate && S_ISDIR(inode->i_mode)) {
                        /* We got a truncate request for a dir which is impossible.
                           The only imaginable way is to execute unfinished truncate request
                           then boot into old kernel, remove the file and create dir with
                           the same key. */
-                       reiserfs_warning(s,
-                                        "green-2101: impossible truncate on a directory %k. Please report",
+                       reiserfs_warning(s, "green-2101",
+                                        "impossible truncate on a "
+                                        "directory %k. Please report",
                                         INODE_PKEY(inode));
                        retval = remove_save_link_only(s, &save_link_key, 0);
                        truncate = 0;
@@ -279,8 +279,19 @@ static int finish_unfinished(struct super_block *s)
                        REISERFS_I(inode)->i_flags |= i_link_saved_unlink_mask;
                        /* not completed unlink (rmdir) found */
                        reiserfs_info(s, "Removing %k..", INODE_PKEY(inode));
-                       /* removal gets completed in iput */
-                       retval = 0;
+                       if (memcmp(&last_inode_key, INODE_PKEY(inode),
+                                       sizeof(last_inode_key))){
+                               last_inode_key = *INODE_PKEY(inode);
+                               /* removal gets completed in iput */
+                               retval = 0;
+                       } else {
+                               reiserfs_warning(s, "super-2189", "Dead loop "
+                                                "in finish_unfinished "
+                                                "detected, just remove "
+                                                "save link\n");
+                               retval = remove_save_link_only(s,
+                                                       &save_link_key, 0);
+                       }
                }
 
                iput(inode);
@@ -293,7 +304,7 @@ static int finish_unfinished(struct super_block *s)
        /* Turn quotas off */
        for (i = 0; i < MAXQUOTAS; i++) {
                if (sb_dqopt(s)->files[i])
-                       vfs_quota_off_mount(s, i);
+                       vfs_quota_off(s, i, 0);
        }
        if (ms_active_set)
                /* Restore the flag back */
@@ -308,7 +319,7 @@ static int finish_unfinished(struct super_block *s)
 
 /* to protect file being unlinked from getting lost we "safe" link files
    being unlinked. This link will be deleted in the same transaction with last
-   item of file. mounting the filesytem we scan all these links and remove
+   item of file. mounting the filesystem we scan all these links and remove
    files which almost got lost */
 void add_save_link(struct reiserfs_transaction_handle *th,
                   struct inode *inode, int truncate)
@@ -347,8 +358,9 @@ void add_save_link(struct reiserfs_transaction_handle *th,
        } else {
                /* truncate */
                if (S_ISDIR(inode->i_mode))
-                       reiserfs_warning(inode->i_sb,
-                                        "green-2102: Adding a truncate savelink for a directory %k! Please report",
+                       reiserfs_warning(inode->i_sb, "green-2102",
+                                        "Adding a truncate savelink for "
+                                        "a directory %k! Please report",
                                         INODE_PKEY(inode));
                set_cpu_key_k_offset(&key, 1);
                set_cpu_key_k_type(&key, TYPE_INDIRECT);
@@ -363,9 +375,9 @@ void add_save_link(struct reiserfs_transaction_handle *th,
        retval = search_item(inode->i_sb, &key, &path);
        if (retval != ITEM_NOT_FOUND) {
                if (retval != -ENOSPC)
-                       reiserfs_warning(inode->i_sb, "vs-2100: add_save_link:"
-                                        "search_by_key (%K) returned %d", &key,
-                                        retval);
+                       reiserfs_error(inode->i_sb, "vs-2100",
+                                      "search_by_key (%K) returned %d", &key,
+                                      retval);
                pathrelse(&path);
                return;
        }
@@ -378,9 +390,8 @@ void add_save_link(struct reiserfs_transaction_handle *th,
            reiserfs_insert_item(th, &path, &key, &ih, NULL, (char *)&link);
        if (retval) {
                if (retval != -ENOSPC)
-                       reiserfs_warning(inode->i_sb,
-                                        "vs-2120: add_save_link: insert_item returned %d",
-                                        retval);
+                       reiserfs_error(inode->i_sb, "vs-2120",
+                                      "insert_item returned %d", retval);
        } else {
                if (truncate)
                        REISERFS_I(inode)->i_flags |=
@@ -431,21 +442,33 @@ int remove_save_link(struct inode *inode, int truncate)
        return journal_end(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT);
 }
 
+static void reiserfs_kill_sb(struct super_block *s)
+{
+       if (REISERFS_SB(s)) {
+               if (REISERFS_SB(s)->xattr_root) {
+                       d_invalidate(REISERFS_SB(s)->xattr_root);
+                       dput(REISERFS_SB(s)->xattr_root);
+                       REISERFS_SB(s)->xattr_root = NULL;
+               }
+               if (REISERFS_SB(s)->priv_root) {
+                       d_invalidate(REISERFS_SB(s)->priv_root);
+                       dput(REISERFS_SB(s)->priv_root);
+                       REISERFS_SB(s)->priv_root = NULL;
+               }
+       }
+
+       kill_block_super(s);
+}
+
 static void reiserfs_put_super(struct super_block *s)
 {
-       int i;
        struct reiserfs_transaction_handle th;
        th.t_trans_id = 0;
 
-       if (REISERFS_SB(s)->xattr_root) {
-               d_invalidate(REISERFS_SB(s)->xattr_root);
-               dput(REISERFS_SB(s)->xattr_root);
-       }
+       reiserfs_write_lock(s);
 
-       if (REISERFS_SB(s)->priv_root) {
-               d_invalidate(REISERFS_SB(s)->priv_root);
-               dput(REISERFS_SB(s)->priv_root);
-       }
+       if (s->s_dirt)
+               reiserfs_write_super(s);
 
        /* change file system state to current state if it was mounted with read-write permissions */
        if (!(s->s_flags & MS_RDONLY)) {
@@ -463,36 +486,32 @@ static void reiserfs_put_super(struct super_block *s)
         */
        journal_release(&th, s);
 
-       for (i = 0; i < SB_BMAP_NR(s); i++)
-               brelse(SB_AP_BITMAP(s)[i].bh);
-
-       vfree(SB_AP_BITMAP(s));
+       reiserfs_free_bitmap_cache(s);
 
        brelse(SB_BUFFER_WITH_SB(s));
 
        print_statistics(s);
 
        if (REISERFS_SB(s)->reserved_blocks != 0) {
-               reiserfs_warning(s,
-                                "green-2005: reiserfs_put_super: reserved blocks left %d",
+               reiserfs_warning(s, "green-2005", "reserved blocks left %d",
                                 REISERFS_SB(s)->reserved_blocks);
        }
 
        reiserfs_proc_info_done(s);
 
+       reiserfs_write_unlock(s);
+       mutex_destroy(&REISERFS_SB(s)->lock);
        kfree(s->s_fs_info);
        s->s_fs_info = NULL;
-
-       return;
 }
 
-static kmem_cache_t *reiserfs_inode_cachep;
+static struct kmem_cache *reiserfs_inode_cachep;
 
 static struct inode *reiserfs_alloc_inode(struct super_block *sb)
 {
        struct reiserfs_inode_info *ei;
        ei = (struct reiserfs_inode_info *)
-           kmem_cache_alloc(reiserfs_inode_cachep, SLAB_KERNEL);
+           kmem_cache_alloc(reiserfs_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        return &ei->vfs_inode;
@@ -503,17 +522,12 @@ static void reiserfs_destroy_inode(struct inode *inode)
        kmem_cache_free(reiserfs_inode_cachep, REISERFS_I(inode));
 }
 
-static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void *foo)
 {
        struct reiserfs_inode_info *ei = (struct reiserfs_inode_info *)foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
-               INIT_LIST_HEAD(&ei->i_prealloc_list);
-               inode_init_once(&ei->vfs_inode);
-               ei->i_acl_access = NULL;
-               ei->i_acl_default = NULL;
-       }
+       INIT_LIST_HEAD(&ei->i_prealloc_list);
+       inode_init_once(&ei->vfs_inode);
 }
 
 static int init_inodecache(void)
@@ -521,8 +535,9 @@ static int init_inodecache(void)
        reiserfs_inode_cachep = kmem_cache_create("reiser_inode_cache",
                                                  sizeof(struct
                                                         reiserfs_inode_info),
-                                                 0, SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
-                                                 init_once, NULL);
+                                                 0, (SLAB_RECLAIM_ACCOUNT|
+                                                       SLAB_MEM_SPREAD),
+                                                 init_once);
        if (reiserfs_inode_cachep == NULL)
                return -ENOMEM;
        return 0;
@@ -530,9 +545,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(reiserfs_inode_cachep))
-               reiserfs_warning(NULL,
-                                "reiserfs_inode_cache: not all structures were freed");
+       kmem_cache_destroy(reiserfs_inode_cachep);
 }
 
 /* we don't mark inodes dirty, we just log them */
@@ -541,40 +554,33 @@ static void reiserfs_dirty_inode(struct inode *inode)
        struct reiserfs_transaction_handle th;
 
        int err = 0;
+       int lock_depth;
+
        if (inode->i_sb->s_flags & MS_RDONLY) {
-               reiserfs_warning(inode->i_sb,
-                                "clm-6006: writing inode %lu on readonly FS",
+               reiserfs_warning(inode->i_sb, "clm-6006",
+                                "writing inode %lu on readonly FS",
                                 inode->i_ino);
                return;
        }
-       reiserfs_write_lock(inode->i_sb);
+       lock_depth = reiserfs_write_lock_once(inode->i_sb);
 
        /* this is really only used for atime updates, so they don't have
         ** to be included in O_SYNC or fsync
         */
        err = journal_begin(&th, inode->i_sb, 1);
-       if (err) {
-               reiserfs_write_unlock(inode->i_sb);
-               return;
-       }
+       if (err)
+               goto out;
+
        reiserfs_update_sd(&th, inode);
        journal_end(&th, inode->i_sb, 1);
-       reiserfs_write_unlock(inode->i_sb);
+
+out:
+       reiserfs_write_unlock_once(inode->i_sb, lock_depth);
 }
 
 static void reiserfs_clear_inode(struct inode *inode)
 {
-       struct posix_acl *acl;
-
-       acl = REISERFS_I(inode)->i_acl_access;
-       if (acl && !IS_ERR(acl))
-               posix_acl_release(acl);
-       REISERFS_I(inode)->i_acl_access = NULL;
-
-       acl = REISERFS_I(inode)->i_acl_default;
-       if (acl && !IS_ERR(acl))
-               posix_acl_release(acl);
-       REISERFS_I(inode)->i_acl_default = NULL;
+       dquot_drop(inode);
 }
 
 #ifdef CONFIG_QUOTA
@@ -584,20 +590,21 @@ static ssize_t reiserfs_quota_read(struct super_block *, int, char *, size_t,
                                   loff_t);
 #endif
 
-static struct super_operations reiserfs_sops = {
+static const struct super_operations reiserfs_sops = {
        .alloc_inode = reiserfs_alloc_inode,
        .destroy_inode = reiserfs_destroy_inode,
        .write_inode = reiserfs_write_inode,
        .dirty_inode = reiserfs_dirty_inode,
-       .delete_inode = reiserfs_delete_inode,
        .clear_inode = reiserfs_clear_inode,
+       .delete_inode = reiserfs_delete_inode,
        .put_super = reiserfs_put_super,
        .write_super = reiserfs_write_super,
        .sync_fs = reiserfs_sync_fs,
-       .write_super_lockfs = reiserfs_write_super_lockfs,
-       .unlockfs = reiserfs_unlockfs,
+       .freeze_fs = reiserfs_freeze,
+       .unfreeze_fs = reiserfs_unfreeze,
        .statfs = reiserfs_statfs,
        .remount_fs = reiserfs_remount,
+       .show_options = generic_show_options,
 #ifdef CONFIG_QUOTA
        .quota_read = reiserfs_quota_read,
        .quota_write = reiserfs_quota_write,
@@ -607,31 +614,25 @@ static struct super_operations reiserfs_sops = {
 #ifdef CONFIG_QUOTA
 #define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group")
 
-static int reiserfs_dquot_initialize(struct inode *, int);
-static int reiserfs_dquot_drop(struct inode *);
 static int reiserfs_write_dquot(struct dquot *);
 static int reiserfs_acquire_dquot(struct dquot *);
 static int reiserfs_release_dquot(struct dquot *);
 static int reiserfs_mark_dquot_dirty(struct dquot *);
 static int reiserfs_write_info(struct super_block *, int);
-static int reiserfs_quota_on(struct super_block *, int, int, char *);
-
-static struct dquot_operations reiserfs_quota_operations = {
-       .initialize = reiserfs_dquot_initialize,
-       .drop = reiserfs_dquot_drop,
-       .alloc_space = dquot_alloc_space,
-       .alloc_inode = dquot_alloc_inode,
-       .free_space = dquot_free_space,
-       .free_inode = dquot_free_inode,
-       .transfer = dquot_transfer,
+static int reiserfs_quota_on(struct super_block *, int, int, char *, int);
+
+static const struct dquot_operations reiserfs_quota_operations = {
+       .initialize = dquot_initialize,
        .write_dquot = reiserfs_write_dquot,
        .acquire_dquot = reiserfs_acquire_dquot,
        .release_dquot = reiserfs_release_dquot,
        .mark_dirty = reiserfs_mark_dquot_dirty,
        .write_info = reiserfs_write_info,
+       .alloc_dquot    = dquot_alloc,
+       .destroy_dquot  = dquot_destroy,
 };
 
-static struct quotactl_ops reiserfs_qctl_operations = {
+static const struct quotactl_ops reiserfs_qctl_operations = {
        .quota_on = reiserfs_quota_on,
        .quota_off = vfs_quota_off,
        .quota_sync = vfs_quota_sync,
@@ -642,11 +643,11 @@ static struct quotactl_ops reiserfs_qctl_operations = {
 };
 #endif
 
-static struct export_operations reiserfs_export_ops = {
+static const struct export_operations reiserfs_export_ops = {
        .encode_fh = reiserfs_encode_fh,
-       .decode_fh = reiserfs_decode_fh,
+       .fh_to_dentry = reiserfs_fh_to_dentry,
+       .fh_to_parent = reiserfs_fh_to_parent,
        .get_parent = reiserfs_get_parent,
-       .get_dentry = reiserfs_get_dentry,
 };
 
 /* this struct is used in reiserfs_getopt () for containing the value for those
@@ -684,14 +685,14 @@ static const arg_desc_t logging_mode[] = {
         (1 << REISERFS_DATA_ORDERED | 1 << REISERFS_DATA_WRITEBACK)},
        {"writeback", 1 << REISERFS_DATA_WRITEBACK,
         (1 << REISERFS_DATA_ORDERED | 1 << REISERFS_DATA_LOG)},
-       {NULL, 0}
+       {.value = NULL}
 };
 
 /* possible values for -o barrier= */
 static const arg_desc_t barrier_mode[] = {
        {"none", 1 << REISERFS_BARRIER_NONE, 1 << REISERFS_BARRIER_FLUSH},
        {"flush", 1 << REISERFS_BARRIER_FLUSH, 1 << REISERFS_BARRIER_NONE},
-       {NULL, 0}
+       {.value = NULL}
 };
 
 /* possible values for "-o block-allocator=" and bits which are to be set in
@@ -725,12 +726,6 @@ static const arg_desc_t error_actions[] = {
        {NULL, 0, 0},
 };
 
-int reiserfs_default_io_size = 128 * 1024;     /* Default recommended I/O size is 128k.
-                                                  There might be broken applications that are
-                                                  confused by this. Use nolargeio mount option
-                                                  to get usual i/o size = PAGE_SIZE.
-                                                */
-
 /* proceed only one option from a list *cur - string containing of mount options
    opts - array of options which are accepted
    opt_arg - if option is found and requires an argument and if it is specifed
@@ -741,7 +736,7 @@ static int reiserfs_getopt(struct super_block *s, char **cur, opt_desc_t * opts,
                           char **opt_arg, unsigned long *bit_flags)
 {
        char *p;
-       /* foo=bar, 
+       /* foo=bar,
           ^   ^  ^
           |   |  +-- option_end
           |   +-- arg_start
@@ -776,13 +771,15 @@ static int reiserfs_getopt(struct super_block *s, char **cur, opt_desc_t * opts,
                        if (bit_flags) {
                                if (opt->clrmask ==
                                    (1 << REISERFS_UNSUPPORTED_OPT))
-                                       reiserfs_warning(s, "%s not supported.",
+                                       reiserfs_warning(s, "super-6500",
+                                                        "%s not supported.\n",
                                                         p);
                                else
                                        *bit_flags &= ~opt->clrmask;
                                if (opt->setmask ==
                                    (1 << REISERFS_UNSUPPORTED_OPT))
-                                       reiserfs_warning(s, "%s not supported.",
+                                       reiserfs_warning(s, "super-6501",
+                                                        "%s not supported.\n",
                                                         p);
                                else
                                        *bit_flags |= opt->setmask;
@@ -791,7 +788,8 @@ static int reiserfs_getopt(struct super_block *s, char **cur, opt_desc_t * opts,
                }
        }
        if (!opt->option_name) {
-               reiserfs_warning(s, "unknown mount option \"%s\"", p);
+               reiserfs_warning(s, "super-6502",
+                                "unknown mount option \"%s\"", p);
                return -1;
        }
 
@@ -799,8 +797,9 @@ static int reiserfs_getopt(struct super_block *s, char **cur, opt_desc_t * opts,
        switch (*p) {
        case '=':
                if (!opt->arg_required) {
-                       reiserfs_warning(s,
-                                        "the option \"%s\" does not require an argument",
+                       reiserfs_warning(s, "super-6503",
+                                        "the option \"%s\" does not "
+                                        "require an argument\n",
                                         opt->option_name);
                        return -1;
                }
@@ -808,14 +807,15 @@ static int reiserfs_getopt(struct super_block *s, char **cur, opt_desc_t * opts,
 
        case 0:
                if (opt->arg_required) {
-                       reiserfs_warning(s,
-                                        "the option \"%s\" requires an argument",
-                                        opt->option_name);
+                       reiserfs_warning(s, "super-6504",
+                                        "the option \"%s\" requires an "
+                                        "argument\n", opt->option_name);
                        return -1;
                }
                break;
        default:
-               reiserfs_warning(s, "head of option \"%s\" is only correct",
+               reiserfs_warning(s, "super-6505",
+                                "head of option \"%s\" is only correct\n",
                                 opt->option_name);
                return -1;
        }
@@ -827,7 +827,8 @@ static int reiserfs_getopt(struct super_block *s, char **cur, opt_desc_t * opts,
            && !(opt->arg_required & (1 << REISERFS_OPT_ALLOWEMPTY))
            && !strlen(p)) {
                /* this catches "option=," if not allowed */
-               reiserfs_warning(s, "empty argument for \"%s\"",
+               reiserfs_warning(s, "super-6506",
+                                "empty argument for \"%s\"\n",
                                 opt->option_name);
                return -1;
        }
@@ -849,7 +850,8 @@ static int reiserfs_getopt(struct super_block *s, char **cur, opt_desc_t * opts,
                }
        }
 
-       reiserfs_warning(s, "bad value \"%s\" for option \"%s\"", p,
+       reiserfs_warning(s, "super-6506",
+                        "bad value \"%s\" for option \"%s\"\n", p,
                         opt->option_name);
        return -1;
 }
@@ -862,7 +864,9 @@ static int reiserfs_parse_options(struct super_block *s, char *options,     /* strin
                                     mount options were selected. */
                                  unsigned long *blocks,        /* strtol-ed from NNN of resize=NNN */
                                  char **jdev_name,
-                                 unsigned int *commit_max_age)
+                                 unsigned int *commit_max_age,
+                                 char **qf_names,
+                                 unsigned int *qfmt)
 {
        int c;
        char *arg = NULL;
@@ -875,6 +879,7 @@ static int reiserfs_parse_options(struct super_block *s, char *options,     /* strin
                {"conv",.setmask = 1 << REISERFS_CONVERT},
                {"attrs",.setmask = 1 << REISERFS_ATTRS},
                {"noattrs",.clrmask = 1 << REISERFS_ATTRS},
+               {"expose_privroot", .setmask = 1 << REISERFS_EXPOSE_PRIVROOT},
 #ifdef CONFIG_REISERFS_FS_XATTR
                {"user_xattr",.setmask = 1 << REISERFS_XATTRS_USER},
                {"nouser_xattr",.clrmask = 1 << REISERFS_XATTRS_USER},
@@ -889,7 +894,7 @@ static int reiserfs_parse_options(struct super_block *s, char *options,     /* strin
                {"acl",.setmask = 1 << REISERFS_UNSUPPORTED_OPT},
                {"noacl",.clrmask = 1 << REISERFS_UNSUPPORTED_OPT},
 #endif
-               {"nolog",},     /* This is unsupported */
+               {.option_name = "nolog"},
                {"replayonly",.setmask = 1 << REPLAYONLY},
                {"block-allocator",.arg_required = 'a',.values = balloc},
                {"data",.arg_required = 'd',.values = logging_mode},
@@ -907,7 +912,7 @@ static int reiserfs_parse_options(struct super_block *s, char *options,     /* strin
                {"grpjquota",.arg_required =
                 'g' | (1 << REISERFS_OPT_ALLOWEMPTY),.values = NULL},
                {"jqfmt",.arg_required = 'f',.values = NULL},
-               {NULL,}
+               {.option_name = NULL}
        };
 
        *blocks = 0;
@@ -937,9 +942,9 @@ static int reiserfs_parse_options(struct super_block *s, char *options,     /* strin
                                *blocks = simple_strtoul(arg, &p, 0);
                                if (*p != '\0') {
                                        /* NNN does not look like a number */
-                                       reiserfs_warning(s,
-                                                        "reiserfs_parse_options: bad value %s",
-                                                        arg);
+                                       reiserfs_warning(s, "super-6507",
+                                                        "bad value %s for "
+                                                        "-oresize\n", arg);
                                        return 0;
                                }
                        }
@@ -950,8 +955,8 @@ static int reiserfs_parse_options(struct super_block *s, char *options,     /* strin
                        unsigned long val = simple_strtoul(arg, &p, 0);
                        /* commit=NNN (time in seconds) */
                        if (*p != '\0' || val >= (unsigned int)-1) {
-                               reiserfs_warning(s,
-                                                "reiserfs_parse_options: bad value %s",
+                               reiserfs_warning(s, "super-6508",
+                                                "bad value %s for -ocommit\n",
                                                 arg);
                                return 0;
                        }
@@ -959,27 +964,18 @@ static int reiserfs_parse_options(struct super_block *s, char *options,   /* strin
                }
 
                if (c == 'w') {
-                       char *p = NULL;
-                       int val = simple_strtoul(arg, &p, 0);
-
-                       if (*p != '\0') {
-                               reiserfs_warning(s,
-                                                "reiserfs_parse_options: non-numeric value %s for nolargeio option",
-                                                arg);
-                               return 0;
-                       }
-                       if (val)
-                               reiserfs_default_io_size = PAGE_SIZE;
-                       else
-                               reiserfs_default_io_size = 128 * 1024;
+                       reiserfs_warning(s, "super-6509", "nolargeio option "
+                                        "is no longer supported");
+                       return 0;
                }
 
                if (c == 'j') {
                        if (arg && *arg && jdev_name) {
                                if (*jdev_name) {       //Hm, already assigned?
-                                       reiserfs_warning(s,
-                                                        "reiserfs_parse_options: journal device was already  specified to be %s",
-                                                        *jdev_name);
+                                       reiserfs_warning(s, "super-6510",
+                                                        "journal device was "
+                                                        "already specified to "
+                                                        "be %s", *jdev_name);
                                        return 0;
                                }
                                *jdev_name = arg;
@@ -989,72 +985,89 @@ static int reiserfs_parse_options(struct super_block *s, char *options,   /* strin
                if (c == 'u' || c == 'g') {
                        int qtype = c == 'u' ? USRQUOTA : GRPQUOTA;
 
-                       if (sb_any_quota_enabled(s)) {
-                               reiserfs_warning(s,
-                                                "reiserfs_parse_options: cannot change journalled quota options when quota turned on.");
+                       if (sb_any_quota_loaded(s) &&
+                           (!*arg != !REISERFS_SB(s)->s_qf_names[qtype])) {
+                               reiserfs_warning(s, "super-6511",
+                                                "cannot change journaled "
+                                                "quota options when quota "
+                                                "turned on.");
                                return 0;
                        }
                        if (*arg) {     /* Some filename specified? */
                                if (REISERFS_SB(s)->s_qf_names[qtype]
                                    && strcmp(REISERFS_SB(s)->s_qf_names[qtype],
                                              arg)) {
-                                       reiserfs_warning(s,
-                                                        "reiserfs_parse_options: %s quota file already specified.",
+                                       reiserfs_warning(s, "super-6512",
+                                                        "%s quota file "
+                                                        "already specified.",
                                                         QTYPE2NAME(qtype));
                                        return 0;
                                }
                                if (strchr(arg, '/')) {
-                                       reiserfs_warning(s,
-                                                        "reiserfs_parse_options: quotafile must be on filesystem root.");
+                                       reiserfs_warning(s, "super-6513",
+                                                        "quotafile must be "
+                                                        "on filesystem root.");
                                        return 0;
                                }
-                               REISERFS_SB(s)->s_qf_names[qtype] =
+                               qf_names[qtype] =
                                    kmalloc(strlen(arg) + 1, GFP_KERNEL);
-                               if (!REISERFS_SB(s)->s_qf_names[qtype]) {
-                                       reiserfs_warning(s,
-                                                        "reiserfs_parse_options: not enough memory for storing quotafile name.");
+                               if (!qf_names[qtype]) {
+                                       reiserfs_warning(s, "reiserfs-2502",
+                                                        "not enough memory "
+                                                        "for storing "
+                                                        "quotafile name.");
                                        return 0;
                                }
-                               strcpy(REISERFS_SB(s)->s_qf_names[qtype], arg);
+                               strcpy(qf_names[qtype], arg);
                                *mount_options |= 1 << REISERFS_QUOTA;
                        } else {
-                               kfree(REISERFS_SB(s)->s_qf_names[qtype]);
-                               REISERFS_SB(s)->s_qf_names[qtype] = NULL;
+                               if (qf_names[qtype] !=
+                                   REISERFS_SB(s)->s_qf_names[qtype])
+                                       kfree(qf_names[qtype]);
+                               qf_names[qtype] = NULL;
                        }
                }
                if (c == 'f') {
                        if (!strcmp(arg, "vfsold"))
-                               REISERFS_SB(s)->s_jquota_fmt = QFMT_VFS_OLD;
+                               *qfmt = QFMT_VFS_OLD;
                        else if (!strcmp(arg, "vfsv0"))
-                               REISERFS_SB(s)->s_jquota_fmt = QFMT_VFS_V0;
+                               *qfmt = QFMT_VFS_V0;
                        else {
-                               reiserfs_warning(s,
-                                                "reiserfs_parse_options: unknown quota format specified.");
+                               reiserfs_warning(s, "super-6514",
+                                                "unknown quota format "
+                                                "specified.");
+                               return 0;
+                       }
+                       if (sb_any_quota_loaded(s) &&
+                           *qfmt != REISERFS_SB(s)->s_jquota_fmt) {
+                               reiserfs_warning(s, "super-6515",
+                                                "cannot change journaled "
+                                                "quota options when quota "
+                                                "turned on.");
                                return 0;
                        }
                }
 #else
                if (c == 'u' || c == 'g' || c == 'f') {
-                       reiserfs_warning(s,
-                                        "reiserfs_parse_options: journalled quota options not supported.");
+                       reiserfs_warning(s, "reiserfs-2503", "journaled "
+                                        "quota options not supported.");
                        return 0;
                }
 #endif
        }
 
 #ifdef CONFIG_QUOTA
-       if (!REISERFS_SB(s)->s_jquota_fmt
-           && (REISERFS_SB(s)->s_qf_names[USRQUOTA]
-               || REISERFS_SB(s)->s_qf_names[GRPQUOTA])) {
-               reiserfs_warning(s,
-                                "reiserfs_parse_options: journalled quota format not specified.");
+       if (!REISERFS_SB(s)->s_jquota_fmt && !*qfmt
+           && (qf_names[USRQUOTA] || qf_names[GRPQUOTA])) {
+               reiserfs_warning(s, "super-6515",
+                                "journaled quota format not specified.");
                return 0;
        }
        /* This checking is not precise wrt the quota type but for our purposes it is sufficient */
        if (!(*mount_options & (1 << REISERFS_QUOTA))
-           && sb_any_quota_enabled(s)) {
-               reiserfs_warning(s,
-                                "reiserfs_parse_options: quota options must be present when quota is turned on.");
+           && sb_any_quota_loaded(s)) {
+               reiserfs_warning(s, "super-6516", "quota options must "
+                                "be present when quota is turned on.");
                return 0;
        }
 #endif
@@ -1114,19 +1127,35 @@ static void handle_attrs(struct super_block *s)
 
        if (reiserfs_attrs(s)) {
                if (old_format_only(s)) {
-                       reiserfs_warning(s,
-                                        "reiserfs: cannot support attributes on 3.5.x disk format");
+                       reiserfs_warning(s, "super-6517", "cannot support "
+                                        "attributes on 3.5.x disk format");
                        REISERFS_SB(s)->s_mount_opt &= ~(1 << REISERFS_ATTRS);
                        return;
                }
                if (!(le32_to_cpu(rs->s_flags) & reiserfs_attrs_cleared)) {
-                       reiserfs_warning(s,
-                                        "reiserfs: cannot support attributes until flag is set in super-block");
+                       reiserfs_warning(s, "super-6518", "cannot support "
+                                        "attributes until flag is set in "
+                                        "super-block");
                        REISERFS_SB(s)->s_mount_opt &= ~(1 << REISERFS_ATTRS);
                }
        }
 }
 
+#ifdef CONFIG_QUOTA
+static void handle_quota_files(struct super_block *s, char **qf_names,
+                              unsigned int *qfmt)
+{
+       int i;
+
+       for (i = 0; i < MAXQUOTAS; i++) {
+               if (qf_names[i] != REISERFS_SB(s)->s_qf_names[i])
+                       kfree(REISERFS_SB(s)->s_qf_names[i]);
+               REISERFS_SB(s)->s_qf_names[i] = qf_names[i];
+       }
+       REISERFS_SB(s)->s_jquota_fmt = *qfmt;
+}
+#endif
+
 static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
 {
        struct reiserfs_super_block *rs;
@@ -1136,23 +1165,36 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        unsigned long safe_mask = 0;
        unsigned int commit_max_age = (unsigned int)-1;
        struct reiserfs_journal *journal = SB_JOURNAL(s);
+       char *new_opts = kstrdup(arg, GFP_KERNEL);
        int err;
+       char *qf_names[MAXQUOTAS];
+       unsigned int qfmt = 0;
 #ifdef CONFIG_QUOTA
        int i;
 #endif
 
+       reiserfs_write_lock(s);
+
+#ifdef CONFIG_QUOTA
+       memcpy(qf_names, REISERFS_SB(s)->s_qf_names, sizeof(qf_names));
+#endif
+
        rs = SB_DISK_SUPER_BLOCK(s);
 
        if (!reiserfs_parse_options
-           (s, arg, &mount_options, &blocks, NULL, &commit_max_age)) {
+           (s, arg, &mount_options, &blocks, NULL, &commit_max_age,
+           qf_names, &qfmt)) {
 #ifdef CONFIG_QUOTA
-               for (i = 0; i < MAXQUOTAS; i++) {
-                       kfree(REISERFS_SB(s)->s_qf_names[i]);
-                       REISERFS_SB(s)->s_qf_names[i] = NULL;
-               }
+               for (i = 0; i < MAXQUOTAS; i++)
+                       if (qf_names[i] != REISERFS_SB(s)->s_qf_names[i])
+                               kfree(qf_names[i]);
 #endif
-               return -EINVAL;
+               err = -EINVAL;
+               goto out_err;
        }
+#ifdef CONFIG_QUOTA
+       handle_quota_files(s, qf_names, &qfmt);
+#endif
 
        handle_attrs(s);
 
@@ -1189,9 +1231,9 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        }
 
        if (blocks) {
-               int rc = reiserfs_resize(s, blocks);
-               if (rc != 0)
-                       return rc;
+               err = reiserfs_resize(s, blocks);
+               if (err != 0)
+                       goto out_err;
        }
 
        if (*mount_flags & MS_RDONLY) {
@@ -1199,16 +1241,16 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
                /* remount read-only */
                if (s->s_flags & MS_RDONLY)
                        /* it is read-only already */
-                       return 0;
+                       goto out_ok;
                /* try to remount file system with read-only permissions */
                if (sb_umount_state(rs) == REISERFS_VALID_FS
                    || REISERFS_SB(s)->s_mount_state != REISERFS_VALID_FS) {
-                       return 0;
+                       goto out_ok;
                }
 
                err = journal_begin(&th, s, 10);
                if (err)
-                       return err;
+                       goto out_err;
 
                /* Mounting a rw partition read-only. */
                reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
@@ -1218,11 +1260,13 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
                /* remount read-write */
                if (!(s->s_flags & MS_RDONLY)) {
                        reiserfs_xattr_init(s, *mount_flags);
-                       return 0;       /* We are read-write already */
+                       goto out_ok;    /* We are read-write already */
                }
 
-               if (reiserfs_is_journal_aborted(journal))
-                       return journal->j_errno;
+               if (reiserfs_is_journal_aborted(journal)) {
+                       err = journal->j_errno;
+                       goto out_err;
+               }
 
                handle_data_mode(s, mount_options);
                handle_barrier_mode(s, mount_options);
@@ -1230,13 +1274,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
                s->s_flags &= ~MS_RDONLY;       /* now it is safe to call journal_begin */
                err = journal_begin(&th, s, 10);
                if (err)
-                       return err;
+                       goto out_err;
 
                /* Mount a partition which is read-only, read-write */
                reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
                REISERFS_SB(s)->s_mount_state = sb_umount_state(rs);
                s->s_flags &= ~MS_RDONLY;
                set_sb_umount_state(rs, REISERFS_ERROR_FS);
+               if (!old_format_only(s))
+                       set_sb_mnt_count(rs, sb_mnt_count(rs) + 1);
                /* mark_buffer_dirty (SB_BUFFER_WITH_SB (s), 1); */
                journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s));
                REISERFS_SB(s)->s_mount_state = REISERFS_VALID_FS;
@@ -1245,7 +1291,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        SB_JOURNAL(s)->j_must_wait = 1;
        err = journal_end(&th, s, 10);
        if (err)
-               return err;
+               goto out_err;
        s->s_dirt = 0;
 
        if (!(*mount_flags & MS_RDONLY)) {
@@ -1253,119 +1299,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
                reiserfs_xattr_init(s, *mount_flags);
        }
 
+out_ok:
+       replace_mount_options(s, new_opts);
+       reiserfs_write_unlock(s);
        return 0;
-}
-
-/* load_bitmap_info_data - Sets up the reiserfs_bitmap_info structure from disk.
- * @sb - superblock for this filesystem
- * @bi - the bitmap info to be loaded. Requires that bi->bh is valid.
- *
- * This routine counts how many free bits there are, finding the first zero
- * as a side effect. Could also be implemented as a loop of test_bit() calls, or
- * a loop of find_first_zero_bit() calls. This implementation is similar to
- * find_first_zero_bit(), but doesn't return after it finds the first bit.
- * Should only be called on fs mount, but should be fairly efficient anyways.
- *
- * bi->first_zero_hint is considered unset if it == 0, since the bitmap itself
- * will * invariably occupt block 0 represented in the bitmap. The only
- * exception to this is when free_count also == 0, since there will be no
- * free blocks at all.
- */
-
-static void load_bitmap_info_data(struct super_block *sb,
-                                 struct reiserfs_bitmap_info *bi)
-{
-       unsigned long *cur = (unsigned long *)bi->bh->b_data;
-
-       while ((char *)cur < (bi->bh->b_data + sb->s_blocksize)) {
-
-               /* No need to scan if all 0's or all 1's.
-                * Since we're only counting 0's, we can simply ignore all 1's */
-               if (*cur == 0) {
-                       if (bi->first_zero_hint == 0) {
-                               bi->first_zero_hint =
-                                   ((char *)cur - bi->bh->b_data) << 3;
-                       }
-                       bi->free_count += sizeof(unsigned long) * 8;
-               } else if (*cur != ~0L) {
-                       int b;
-                       for (b = 0; b < sizeof(unsigned long) * 8; b++) {
-                               if (!reiserfs_test_le_bit(b, cur)) {
-                                       bi->free_count++;
-                                       if (bi->first_zero_hint == 0)
-                                               bi->first_zero_hint =
-                                                   (((char *)cur -
-                                                     bi->bh->b_data) << 3) + b;
-                               }
-                       }
-               }
-               cur++;
-       }
-
-#ifdef CONFIG_REISERFS_CHECK
-// This outputs a lot of unneded info on big FSes
-//    reiserfs_warning ("bitmap loaded from block %d: %d free blocks",
-//                    bi->bh->b_blocknr, bi->free_count);
-#endif
-}
-
-static int read_bitmaps(struct super_block *s)
-{
-       int i, bmap_nr;
-
-       SB_AP_BITMAP(s) =
-           vmalloc(sizeof(struct reiserfs_bitmap_info) * SB_BMAP_NR(s));
-       if (SB_AP_BITMAP(s) == 0)
-               return 1;
-       memset(SB_AP_BITMAP(s), 0,
-              sizeof(struct reiserfs_bitmap_info) * SB_BMAP_NR(s));
-       for (i = 0, bmap_nr =
-            REISERFS_DISK_OFFSET_IN_BYTES / s->s_blocksize + 1;
-            i < SB_BMAP_NR(s); i++, bmap_nr = s->s_blocksize * 8 * i) {
-               SB_AP_BITMAP(s)[i].bh = sb_getblk(s, bmap_nr);
-               if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh))
-                       ll_rw_block(READ, 1, &SB_AP_BITMAP(s)[i].bh);
-       }
-       for (i = 0; i < SB_BMAP_NR(s); i++) {
-               wait_on_buffer(SB_AP_BITMAP(s)[i].bh);
-               if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) {
-                       reiserfs_warning(s, "sh-2029: reiserfs read_bitmaps: "
-                                        "bitmap block (#%lu) reading failed",
-                                        SB_AP_BITMAP(s)[i].bh->b_blocknr);
-                       for (i = 0; i < SB_BMAP_NR(s); i++)
-                               brelse(SB_AP_BITMAP(s)[i].bh);
-                       vfree(SB_AP_BITMAP(s));
-                       SB_AP_BITMAP(s) = NULL;
-                       return 1;
-               }
-               load_bitmap_info_data(s, SB_AP_BITMAP(s) + i);
-       }
-       return 0;
-}
-
-static int read_old_bitmaps(struct super_block *s)
-{
-       int i;
-       struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(s);
-       int bmp1 = (REISERFS_OLD_DISK_OFFSET_IN_BYTES / s->s_blocksize) + 1;    /* first of bitmap blocks */
-
-       /* read true bitmap */
-       SB_AP_BITMAP(s) =
-           vmalloc(sizeof(struct reiserfs_buffer_info *) * sb_bmap_nr(rs));
-       if (SB_AP_BITMAP(s) == 0)
-               return 1;
 
-       memset(SB_AP_BITMAP(s), 0,
-              sizeof(struct reiserfs_buffer_info *) * sb_bmap_nr(rs));
-
-       for (i = 0; i < sb_bmap_nr(rs); i++) {
-               SB_AP_BITMAP(s)[i].bh = sb_bread(s, bmp1 + i);
-               if (!SB_AP_BITMAP(s)[i].bh)
-                       return 1;
-               load_bitmap_info_data(s, SB_AP_BITMAP(s) + i);
-       }
-
-       return 0;
+out_err:
+       kfree(new_opts);
+       reiserfs_write_unlock(s);
+       return err;
 }
 
 static int read_super_block(struct super_block *s, int offset)
@@ -1376,7 +1318,7 @@ static int read_super_block(struct super_block *s, int offset)
 
        bh = sb_bread(s, offset / s->s_blocksize);
        if (!bh) {
-               reiserfs_warning(s, "sh-2006: read_super_block: "
+               reiserfs_warning(s, "sh-2006",
                                 "bread failed (dev %s, block %lu, size %lu)",
                                 reiserfs_bdevname(s), offset / s->s_blocksize,
                                 s->s_blocksize);
@@ -1390,15 +1332,15 @@ static int read_super_block(struct super_block *s, int offset)
        }
        //
        // ok, reiserfs signature (old or new) found in at the given offset
-       //    
+       //
        fs_blocksize = sb_blocksize(rs);
        brelse(bh);
        sb_set_blocksize(s, fs_blocksize);
 
        bh = sb_bread(s, offset / s->s_blocksize);
        if (!bh) {
-               reiserfs_warning(s, "sh-2007: read_super_block: "
-                                "bread failed (dev %s, block %lu, size %lu)\n",
+               reiserfs_warning(s, "sh-2007",
+                                "bread failed (dev %s, block %lu, size %lu)",
                                 reiserfs_bdevname(s), offset / s->s_blocksize,
                                 s->s_blocksize);
                return 1;
@@ -1406,8 +1348,8 @@ static int read_super_block(struct super_block *s, int offset)
 
        rs = (struct reiserfs_super_block *)bh->b_data;
        if (sb_blocksize(rs) != s->s_blocksize) {
-               reiserfs_warning(s, "sh-2011: read_super_block: "
-                                "can't find a reiserfs filesystem on (dev %s, block %Lu, size %lu)\n",
+               reiserfs_warning(s, "sh-2011", "can't find a reiserfs "
+                                "filesystem on (dev %s, block %Lu, size %lu)",
                                 reiserfs_bdevname(s),
                                 (unsigned long long)bh->b_blocknr,
                                 s->s_blocksize);
@@ -1417,9 +1359,10 @@ static int read_super_block(struct super_block *s, int offset)
 
        if (rs->s_v1.s_root_block == cpu_to_le32(-1)) {
                brelse(bh);
-               reiserfs_warning(s,
-                                "Unfinished reiserfsck --rebuild-tree run detected. Please run\n"
-                                "reiserfsck --rebuild-tree and wait for a completion. If that fails\n"
+               reiserfs_warning(s, "super-6519", "Unfinished reiserfsck "
+                                "--rebuild-tree run detected. Please run\n"
+                                "reiserfsck --rebuild-tree and wait for a "
+                                "completion. If that fails\n"
                                 "get newer reiserfsprogs package");
                return 1;
        }
@@ -1431,18 +1374,15 @@ static int read_super_block(struct super_block *s, int offset)
                /* magic is of non-standard journal filesystem, look at s_version to
                   find which format is in use */
                if (sb_version(rs) == REISERFS_VERSION_2)
-                       reiserfs_warning(s,
-                                        "read_super_block: found reiserfs format \"3.6\""
-                                        " with non-standard journal");
+                       reiserfs_info(s, "found reiserfs format \"3.6\""
+                                     " with non-standard journal\n");
                else if (sb_version(rs) == REISERFS_VERSION_1)
-                       reiserfs_warning(s,
-                                        "read_super_block: found reiserfs format \"3.5\""
-                                        " with non-standard journal");
+                       reiserfs_info(s, "found reiserfs format \"3.5\""
+                                     " with non-standard journal\n");
                else {
-                       reiserfs_warning(s,
-                                        "sh-2012: read_super_block: found unknown "
-                                        "format \"%u\" of reiserfs with non-standard magic",
-                                        sb_version(rs));
+                       reiserfs_warning(s, "sh-2012", "found unknown "
+                                        "format \"%u\" of reiserfs with "
+                                        "non-standard magic", sb_version(rs));
                        return 1;
                }
        } else
@@ -1469,29 +1409,16 @@ static int read_super_block(struct super_block *s, int offset)
 /* after journal replay, reread all bitmap and super blocks */
 static int reread_meta_blocks(struct super_block *s)
 {
-       int i;
        ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s)));
+       reiserfs_write_unlock(s);
        wait_on_buffer(SB_BUFFER_WITH_SB(s));
+       reiserfs_write_lock(s);
        if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) {
-               reiserfs_warning(s,
-                                "reread_meta_blocks, error reading the super");
+               reiserfs_warning(s, "reiserfs-2504", "error reading the super");
                return 1;
        }
 
-       for (i = 0; i < SB_BMAP_NR(s); i++) {
-               ll_rw_block(READ, 1, &(SB_AP_BITMAP(s)[i].bh));
-               wait_on_buffer(SB_AP_BITMAP(s)[i].bh);
-               if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) {
-                       reiserfs_warning(s,
-                                        "reread_meta_blocks, error reading bitmap block number %d at %llu",
-                                        i,
-                                        (unsigned long long)SB_AP_BITMAP(s)[i].
-                                        bh->b_blocknr);
-                       return 1;
-               }
-       }
        return 0;
-
 }
 
 /////////////////////////////////////////////////////
@@ -1530,8 +1457,8 @@ static __u32 find_hash_out(struct super_block *s)
                        if (reiserfs_rupasov_hash(s)) {
                                hash = YURA_HASH;
                        }
-                       reiserfs_warning(s, "FS seems to be empty, autodetect "
-                                        "is using the default hash");
+                       reiserfs_info(s, "FS seems to be empty, autodetect "
+                                        "is using the default hash\n");
                        break;
                }
                r5hash = GET_HASH_VALUE(r5_hash(de.de_name, de.de_namelen));
@@ -1551,10 +1478,10 @@ static __u32 find_hash_out(struct super_block *s)
                        && (yurahash ==
                            GET_HASH_VALUE(deh_offset
                                           (&(de.de_deh[de.de_entry_num])))))) {
-                       reiserfs_warning(s,
-                                        "Unable to automatically detect hash function. "
-                                        "Please mount with -o hash={tea,rupasov,r5}",
-                                        reiserfs_bdevname(s));
+                       reiserfs_warning(s, "reiserfs-2506", "Unable to "
+                                        "automatically detect hash function. "
+                                        "Please mount with -o "
+                                        "hash={tea,rupasov,r5}");
                        hash = UNSET_HASH;
                        break;
                }
@@ -1568,7 +1495,8 @@ static __u32 find_hash_out(struct super_block *s)
                         (deh_offset(&(de.de_deh[de.de_entry_num]))) == r5hash)
                        hash = R5_HASH;
                else {
-                       reiserfs_warning(s, "Unrecognised hash function");
+                       reiserfs_warning(s, "reiserfs-2506",
+                                        "Unrecognised hash function");
                        hash = UNSET_HASH;
                }
        } while (0);
@@ -1592,21 +1520,24 @@ static int what_hash(struct super_block *s)
                code = find_hash_out(s);
 
        if (code != UNSET_HASH && reiserfs_hash_detect(s)) {
-               /* detection has found the hash, and we must check against the 
-                ** mount options 
+               /* detection has found the hash, and we must check against the
+                ** mount options
                 */
                if (reiserfs_rupasov_hash(s) && code != YURA_HASH) {
-                       reiserfs_warning(s, "Error, %s hash detected, "
+                       reiserfs_warning(s, "reiserfs-2507",
+                                        "Error, %s hash detected, "
                                         "unable to force rupasov hash",
                                         reiserfs_hashname(code));
                        code = UNSET_HASH;
                } else if (reiserfs_tea_hash(s) && code != TEA_HASH) {
-                       reiserfs_warning(s, "Error, %s hash detected, "
+                       reiserfs_warning(s, "reiserfs-2508",
+                                        "Error, %s hash detected, "
                                         "unable to force tea hash",
                                         reiserfs_hashname(code));
                        code = UNSET_HASH;
                } else if (reiserfs_r5_hash(s) && code != R5_HASH) {
-                       reiserfs_warning(s, "Error, %s hash detected, "
+                       reiserfs_warning(s, "reiserfs-2509",
+                                        "Error, %s hash detected, "
                                         "unable to force r5 hash",
                                         reiserfs_hashname(code));
                        code = UNSET_HASH;
@@ -1622,7 +1553,7 @@ static int what_hash(struct super_block *s)
                }
        }
 
-       /* if we are mounted RW, and we have a new valid hash code, update 
+       /* if we are mounted RW, and we have a new valid hash code, update
         ** the super
         */
        if (code != UNSET_HASH &&
@@ -1665,14 +1596,13 @@ static int function2code(hashf_t func)
        return 0;
 }
 
-#define SWARN(silent, s, ...)                  \
+#define SWARN(silent, s, id, ...)                      \
        if (!(silent))                          \
-               reiserfs_warning (s, __VA_ARGS__)
+               reiserfs_warning(s, id, __VA_ARGS__)
 
 static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
 {
        struct inode *root_inode;
-       int j;
        struct reiserfs_transaction_handle th;
        int old_format = 0;
        unsigned long blocks;
@@ -1683,14 +1613,17 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        char *jdev_name;
        struct reiserfs_sb_info *sbi;
        int errval = -EINVAL;
+       char *qf_names[MAXQUOTAS] = {};
+       unsigned int qfmt = 0;
+
+       save_mount_options(s, data);
 
-       sbi = kmalloc(sizeof(struct reiserfs_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct reiserfs_sb_info), GFP_KERNEL);
        if (!sbi) {
                errval = -ENOMEM;
-               goto error;
+               goto error_alloc;
        }
        s->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(struct reiserfs_sb_info));
        /* Set default values for options: non-aggressive tails, RO on errors */
        REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_SMALLTAIL);
        REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_ERROR_RO);
@@ -1699,22 +1632,35 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        REISERFS_SB(s)->s_alloc_options.preallocmin = 0;
        /* Preallocate by 16 blocks (17-1) at once */
        REISERFS_SB(s)->s_alloc_options.preallocsize = 17;
-       /* Initialize the rwsem for xattr dir */
-       init_rwsem(&REISERFS_SB(s)->xattr_dir_sem);
-
        /* setup default block allocator options */
        reiserfs_init_alloc_options(s);
 
+       mutex_init(&REISERFS_SB(s)->lock);
+       REISERFS_SB(s)->lock_depth = -1;
+
+       /*
+        * This function is called with the bkl, which also was the old
+        * locking used here.
+        * do_journal_begin() will soon check if we hold the lock (ie: was the
+        * bkl). This is likely because do_journal_begin() has several another
+        * callers because at this time, it doesn't seem to be necessary to
+        * protect against anything.
+        * Anyway, let's be conservative and lock for now.
+        */
+       reiserfs_write_lock(s);
+
        jdev_name = NULL;
        if (reiserfs_parse_options
            (s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name,
-            &commit_max_age) == 0) {
+            &commit_max_age, qf_names, &qfmt) == 0) {
                goto error;
        }
+#ifdef CONFIG_QUOTA
+       handle_quota_files(s, qf_names, &qfmt);
+#endif
 
        if (blocks) {
-               SWARN(silent, s, "jmacd-7: reiserfs_fill_super: resize option "
-                     "for remount only");
+               SWARN(silent, s, "jmacd-7", "resize option for remount only");
                goto error;
        }
 
@@ -1723,8 +1669,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
                old_format = 1;
        /* try new format (64-th 1k block), which can contain reiserfs super block */
        else if (read_super_block(s, REISERFS_DISK_OFFSET_IN_BYTES)) {
-               SWARN(silent, s,
-                     "sh-2021: reiserfs_fill_super: can not find reiserfs on %s",
+               SWARN(silent, s, "sh-2021", "can not find reiserfs on %s",
                      reiserfs_bdevname(s));
                goto error;
        }
@@ -1736,27 +1681,26 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        if (s->s_bdev && s->s_bdev->bd_inode
            && i_size_read(s->s_bdev->bd_inode) <
            sb_block_count(rs) * sb_blocksize(rs)) {
-               SWARN(silent, s,
-                     "Filesystem on %s cannot be mounted because it is bigger than the device",
-                     reiserfs_bdevname(s));
-               SWARN(silent, s,
-                     "You may need to run fsck or increase size of your LVM partition");
-               SWARN(silent, s,
-                     "Or may be you forgot to reboot after fdisk when it told you to");
+               SWARN(silent, s, "", "Filesystem cannot be "
+                     "mounted because it is bigger than the device");
+               SWARN(silent, s, "", "You may need to run fsck "
+                     "or increase size of your LVM partition");
+               SWARN(silent, s, "", "Or may be you forgot to "
+                     "reboot after fdisk when it told you to");
                goto error;
        }
 
        sbi->s_mount_state = SB_REISERFS_STATE(s);
        sbi->s_mount_state = REISERFS_VALID_FS;
 
-       if (old_format ? read_old_bitmaps(s) : read_bitmaps(s)) {
-               SWARN(silent, s,
-                     "jmacd-8: reiserfs_fill_super: unable to read bitmap");
+       if ((errval = reiserfs_init_bitmap_cache(s))) {
+               SWARN(silent, s, "jmacd-8", "unable to read bitmap");
                goto error;
        }
+       errval = -EINVAL;
 #ifdef CONFIG_REISERFS_CHECK
-       SWARN(silent, s, "CONFIG_REISERFS_CHECK is set ON");
-       SWARN(silent, s, "- it is slow mode for debugging.");
+       SWARN(silent, s, "", "CONFIG_REISERFS_CHECK is set ON");
+       SWARN(silent, s, "", "- it is slow mode for debugging.");
 #endif
 
        /* make data=ordered the default */
@@ -1777,8 +1721,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        }
        // set_device_ro(s->s_dev, 1) ;
        if (journal_init(s, jdev_name, old_format, commit_max_age)) {
-               SWARN(silent, s,
-                     "sh-2022: reiserfs_fill_super: unable to initialize journal space");
+               SWARN(silent, s, "sh-2022",
+                     "unable to initialize journal space");
                goto error;
        } else {
                jinit_done = 1; /* once this is set, journal_release must be called
@@ -1786,8 +1730,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
                                 */
        }
        if (reread_meta_blocks(s)) {
-               SWARN(silent, s,
-                     "jmacd-9: reiserfs_fill_super: unable to reread meta blocks after journal init");
+               SWARN(silent, s, "jmacd-9",
+                     "unable to reread meta blocks after journal init");
                goto error;
        }
 
@@ -1795,8 +1739,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
                goto error;
 
        if (bdev_read_only(s->s_bdev) && !(s->s_flags & MS_RDONLY)) {
-               SWARN(silent, s,
-                     "clm-7000: Detected readonly device, marking FS readonly");
+               SWARN(silent, s, "clm-7000",
+                     "Detected readonly device, marking FS readonly");
                s->s_flags |= MS_RDONLY;
        }
        args.objectid = REISERFS_ROOT_OBJECTID;
@@ -1805,8 +1749,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
            iget5_locked(s, REISERFS_ROOT_OBJECTID, reiserfs_find_actor,
                         reiserfs_init_locked_inode, (void *)(&args));
        if (!root_inode) {
-               SWARN(silent, s,
-                     "jmacd-10: reiserfs_fill_super: get root inode failed");
+               SWARN(silent, s, "jmacd-10", "get root inode failed");
                goto error;
        }
 
@@ -1831,6 +1774,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        if (is_reiserfs_3_5(rs)
            || (is_reiserfs_jr(rs) && SB_VERSION(s) == REISERFS_VERSION_1))
                set_bit(REISERFS_3_5, &(sbi->s_properties));
+       else if (old_format)
+               set_bit(REISERFS_OLD_FORMAT, &(sbi->s_properties));
        else
                set_bit(REISERFS_3_6, &(sbi->s_properties));
 
@@ -1847,6 +1792,21 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
                set_sb_umount_state(rs, REISERFS_ERROR_FS);
                set_sb_fs_state(rs, 0);
 
+               /* Clear out s_bmap_nr if it would wrap. We can handle this
+                * case, but older revisions can't. This will cause the
+                * file system to fail mount on those older implementations,
+                * avoiding corruption. -jeffm */
+               if (bmap_would_wrap(reiserfs_bmap_count(s)) &&
+                   sb_bmap_nr(rs) != 0) {
+                       reiserfs_warning(s, "super-2030", "This file system "
+                                       "claims to use %u bitmap blocks in "
+                                       "its super block, but requires %u. "
+                                       "Clearing to zero.", sb_bmap_nr(rs),
+                                       reiserfs_bmap_count(s));
+
+                       set_sb_bmap_nr(rs, 0);
+               }
+
                if (old_format_only(s)) {
                        /* filesystem of format 3.5 either with standard or non-standard
                           journal */
@@ -1871,7 +1831,9 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
                        } else if (!silent) {
                                reiserfs_info(s, "using 3.5.x disk format\n");
                        }
-               }
+               } else
+                       set_sb_mnt_count(rs, sb_mnt_count(rs) + 1);
+
 
                journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s));
                errval = journal_end(&th, s, 1);
@@ -1881,7 +1843,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
                        goto error;
                }
 
-               if ((errval = reiserfs_xattr_init(s, s->s_flags))) {
+               if ((errval = reiserfs_lookup_privroot(s)) ||
+                   (errval = reiserfs_xattr_init(s, s->s_flags))) {
                        dput(s->s_root);
                        s->s_root = NULL;
                        goto error;
@@ -1894,7 +1857,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
                        reiserfs_info(s, "using 3.5.x disk format\n");
                }
 
-               if ((errval = reiserfs_xattr_init(s, s->s_flags))) {
+               if ((errval = reiserfs_lookup_privroot(s)) ||
+                   (errval = reiserfs_xattr_init(s, s->s_flags))) {
                        dput(s->s_root);
                        s->s_root = NULL;
                        goto error;
@@ -1910,25 +1874,25 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        init_waitqueue_head(&(sbi->s_wait));
        spin_lock_init(&sbi->bitmap_lock);
 
+       reiserfs_write_unlock(s);
+
        return (0);
 
-      error:
+error:
+       reiserfs_write_unlock(s);
+error_alloc:
        if (jinit_done) {       /* kill the commit thread, free journal ram */
                journal_release_error(NULL, s);
        }
-       if (SB_DISK_SUPER_BLOCK(s)) {
-               for (j = 0; j < SB_BMAP_NR(s); j++) {
-                       if (SB_AP_BITMAP(s))
-                               brelse(SB_AP_BITMAP(s)[j].bh);
-               }
-               vfree(SB_AP_BITMAP(s));
-       }
+
+       reiserfs_free_bitmap_cache(s);
        if (SB_BUFFER_WITH_SB(s))
                brelse(SB_BUFFER_WITH_SB(s));
 #ifdef CONFIG_QUOTA
-       for (j = 0; j < MAXQUOTAS; j++) {
-               kfree(sbi->s_qf_names[j]);
-               sbi->s_qf_names[j] = NULL;
+       {
+               int j;
+               for (j = 0; j < MAXQUOTAS; j++)
+                       kfree(qf_names[j]);
        }
 #endif
        kfree(sbi);
@@ -1937,67 +1901,25 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        return errval;
 }
 
-static int reiserfs_statfs(struct super_block *s, struct kstatfs *buf)
+static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-       struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(s);
+       struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(dentry->d_sb);
 
        buf->f_namelen = (REISERFS_MAX_NAME(s->s_blocksize));
        buf->f_bfree = sb_free_blocks(rs);
        buf->f_bavail = buf->f_bfree;
        buf->f_blocks = sb_block_count(rs) - sb_bmap_nr(rs) - 1;
-       buf->f_bsize = s->s_blocksize;
+       buf->f_bsize = dentry->d_sb->s_blocksize;
        /* changed to accommodate gcc folks. */
        buf->f_type = REISERFS_SUPER_MAGIC;
+       buf->f_fsid.val[0] = (u32)crc32_le(0, rs->s_uuid, sizeof(rs->s_uuid)/2);
+       buf->f_fsid.val[1] = (u32)crc32_le(0, rs->s_uuid + sizeof(rs->s_uuid)/2,
+                               sizeof(rs->s_uuid)/2);
+
        return 0;
 }
 
 #ifdef CONFIG_QUOTA
-static int reiserfs_dquot_initialize(struct inode *inode, int type)
-{
-       struct reiserfs_transaction_handle th;
-       int ret, err;
-
-       /* We may create quota structure so we need to reserve enough blocks */
-       reiserfs_write_lock(inode->i_sb);
-       ret =
-           journal_begin(&th, inode->i_sb,
-                         2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb));
-       if (ret)
-               goto out;
-       ret = dquot_initialize(inode, type);
-       err =
-           journal_end(&th, inode->i_sb,
-                       2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb));
-       if (!ret && err)
-               ret = err;
-      out:
-       reiserfs_write_unlock(inode->i_sb);
-       return ret;
-}
-
-static int reiserfs_dquot_drop(struct inode *inode)
-{
-       struct reiserfs_transaction_handle th;
-       int ret, err;
-
-       /* We may delete quota structure so we need to reserve enough blocks */
-       reiserfs_write_lock(inode->i_sb);
-       ret =
-           journal_begin(&th, inode->i_sb,
-                         2 * REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb));
-       if (ret)
-               goto out;
-       ret = dquot_drop(inode);
-       err =
-           journal_end(&th, inode->i_sb,
-                       2 * REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb));
-       if (!ret && err)
-               ret = err;
-      out:
-       reiserfs_write_unlock(inode->i_sb);
-       return ret;
-}
-
 static int reiserfs_write_dquot(struct dquot *dquot)
 {
        struct reiserfs_transaction_handle th;
@@ -2051,8 +1973,11 @@ static int reiserfs_release_dquot(struct dquot *dquot)
        ret =
            journal_begin(&th, dquot->dq_sb,
                          REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
-       if (ret)
+       if (ret) {
+               /* Release dquot anyway to avoid endless cycle in dqput() */
+               dquot_release(dquot);
                goto out;
+       }
        ret = dquot_release(dquot);
        err =
            journal_end(&th, dquot->dq_sb,
@@ -2066,7 +1991,7 @@ static int reiserfs_release_dquot(struct dquot *dquot)
 
 static int reiserfs_mark_dquot_dirty(struct dquot *dquot)
 {
-       /* Are we journalling quotas? */
+       /* Are we journaling quotas? */
        if (REISERFS_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] ||
            REISERFS_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) {
                dquot_mark_dquot_dirty(dquot);
@@ -2107,41 +2032,65 @@ static int reiserfs_quota_on_mount(struct super_block *sb, int type)
  * Standard function to be called on quota_on
  */
 static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
-                            char *path)
+                            char *name, int remount)
 {
        int err;
-       struct nameidata nd;
+       struct path path;
+       struct inode *inode;
+       struct reiserfs_transaction_handle th;
 
        if (!(REISERFS_SB(sb)->s_mount_opt & (1 << REISERFS_QUOTA)))
                return -EINVAL;
-       err = path_lookup(path, LOOKUP_FOLLOW, &nd);
+       /* No more checks needed? Path and format_id are bogus anyway... */
+       if (remount)
+               return vfs_quota_on(sb, type, format_id, name, 1);
+       err = kern_path(name, LOOKUP_FOLLOW, &path);
        if (err)
                return err;
        /* Quotafile not on the same filesystem? */
-       if (nd.mnt->mnt_sb != sb) {
-               path_release(&nd);
-               return -EXDEV;
+       if (path.mnt->mnt_sb != sb) {
+               err = -EXDEV;
+               goto out;
        }
+       inode = path.dentry->d_inode;
        /* We must not pack tails for quota files on reiserfs for quota IO to work */
-       if (!REISERFS_I(nd.dentry->d_inode)->i_flags & i_nopack_mask) {
-               reiserfs_warning(sb,
-                                "reiserfs: Quota file must have tail packing disabled.");
-               path_release(&nd);
-               return -EINVAL;
+       if (!(REISERFS_I(inode)->i_flags & i_nopack_mask)) {
+               err = reiserfs_unpack(inode, NULL);
+               if (err) {
+                       reiserfs_warning(sb, "super-6520",
+                               "Unpacking tail of quota file failed"
+                               " (%d). Cannot turn on quotas.", err);
+                       err = -EINVAL;
+                       goto out;
+               }
+               mark_inode_dirty(inode);
+       }
+       /* Journaling quota? */
+       if (REISERFS_SB(sb)->s_qf_names[type]) {
+               /* Quotafile not of fs root? */
+               if (path.dentry->d_parent != sb->s_root)
+                       reiserfs_warning(sb, "super-6521",
+                                "Quota file not on filesystem root. "
+                                "Journalled quota will not work.");
        }
-       /* Not journalling quota? No more tests needed... */
-       if (!REISERFS_SB(sb)->s_qf_names[USRQUOTA] &&
-           !REISERFS_SB(sb)->s_qf_names[GRPQUOTA]) {
-               path_release(&nd);
-               return vfs_quota_on(sb, type, format_id, path);
+
+       /*
+        * When we journal data on quota file, we have to flush journal to see
+        * all updates to the file when we bypass pagecache...
+        */
+       if (reiserfs_file_data_log(inode)) {
+               /* Just start temporary transaction and finish it */
+               err = journal_begin(&th, sb, 1);
+               if (err)
+                       goto out;
+               err = journal_end_sync(&th, sb, 1);
+               if (err)
+                       goto out;
        }
-       /* Quotafile not of fs root? */
-       if (nd.dentry->d_parent->d_inode != sb->s_root->d_inode)
-               reiserfs_warning(sb,
-                                "reiserfs: Quota file not on filesystem root. "
-                                "Journalled quota will not work.");
-       path_release(&nd);
-       return vfs_quota_on(sb, type, format_id, path);
+       err = vfs_quota_on_path(sb, type, format_id, &path);
+out:
+       path_put(&path);
+       return err;
 }
 
 /* Read data from quotafile - avoid pagecache and such because we cannot afford
@@ -2203,7 +2152,13 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
        size_t towrite = len;
        struct buffer_head tmp_bh, *bh;
 
-       mutex_lock(&inode->i_mutex);
+       if (!current->journal_info) {
+               printk(KERN_WARNING "reiserfs: Quota write (off=%Lu, len=%Lu)"
+                       " cancelled because transaction is not started.\n",
+                       (unsigned long long)off, (unsigned long long)len);
+               return -EIO;
+       }
+       mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
        while (towrite > 0) {
                tocopy = sb->s_blocksize - offset < towrite ?
                    sb->s_blocksize - offset : towrite;
@@ -2234,9 +2189,11 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
                data += tocopy;
                blk++;
        }
-      out:
-       if (len == towrite)
+out:
+       if (len == towrite) {
+               mutex_unlock(&inode->i_mutex);
                return err;
+       }
        if (inode->i_size < off + len - towrite)
                i_size_write(inode, off + len - towrite);
        inode->i_version++;
@@ -2248,11 +2205,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
 
 #endif
 
-static struct super_block *get_super_block(struct file_system_type *fs_type,
-                                          int flags, const char *dev_name,
-                                          void *data)
+static int get_super_block(struct file_system_type *fs_type,
+                          int flags, const char *dev_name,
+                          void *data, struct vfsmount *mnt)
 {
-       return get_sb_bdev(fs_type, flags, dev_name, data, reiserfs_fill_super);
+       return get_sb_bdev(fs_type, flags, dev_name, data, reiserfs_fill_super,
+                          mnt);
 }
 
 static int __init init_reiserfs_fs(void)
@@ -2263,12 +2221,7 @@ static int __init init_reiserfs_fs(void)
                return ret;
        }
 
-       if ((ret = reiserfs_xattr_register_handlers()))
-               goto failed_reiserfs_xattr_register_handlers;
-
        reiserfs_proc_info_global_init();
-       reiserfs_proc_register_global("version",
-                                     reiserfs_global_version_in_proc);
 
        ret = register_filesystem(&reiserfs_fs_type);
 
@@ -2276,10 +2229,6 @@ static int __init init_reiserfs_fs(void)
                return 0;
        }
 
-       reiserfs_xattr_unregister_handlers();
-
-      failed_reiserfs_xattr_register_handlers:
-       reiserfs_proc_unregister_global("version");
        reiserfs_proc_info_global_done();
        destroy_inodecache();
 
@@ -2288,8 +2237,6 @@ static int __init init_reiserfs_fs(void)
 
 static void __exit exit_reiserfs_fs(void)
 {
-       reiserfs_xattr_unregister_handlers();
-       reiserfs_proc_unregister_global("version");
        reiserfs_proc_info_global_done();
        unregister_filesystem(&reiserfs_fs_type);
        destroy_inodecache();
@@ -2299,7 +2246,7 @@ struct file_system_type reiserfs_fs_type = {
        .owner = THIS_MODULE,
        .name = "reiserfs",
        .get_sb = get_super_block,
-       .kill_sb = kill_block_super,
+       .kill_sb = reiserfs_kill_sb,
        .fs_flags = FS_REQUIRES_DEV,
 };