This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / fs / ext3 / super.c
index 4bbb5a0..1aa5b04 100644 (file)
@@ -493,10 +493,9 @@ static void destroy_inodecache(void)
                printk(KERN_INFO "ext3_inode_cache: not all structures were freed\n");
 }
 
-#ifdef CONFIG_EXT3_FS_POSIX_ACL
-
 static void ext3_clear_inode(struct inode *inode)
 {
+#ifdef CONFIG_EXT3_FS_POSIX_ACL
        if (EXT3_I(inode)->i_acl &&
            EXT3_I(inode)->i_acl != EXT3_ACL_NOT_CACHED) {
                posix_acl_release(EXT3_I(inode)->i_acl);
@@ -507,11 +506,10 @@ static void ext3_clear_inode(struct inode *inode)
                posix_acl_release(EXT3_I(inode)->i_default_acl);
                EXT3_I(inode)->i_default_acl = EXT3_ACL_NOT_CACHED;
        }
-}
-
-#else
-# define ext3_clear_inode NULL
 #endif
+       if (!is_bad_inode(inode))
+               ext3_discard_reservation(inode);
+}
 
 #ifdef CONFIG_QUOTA
 
@@ -521,6 +519,8 @@ static void ext3_clear_inode(struct inode *inode)
 static int ext3_dquot_initialize(struct inode *inode, int type);
 static int ext3_dquot_drop(struct inode *inode);
 static int ext3_write_dquot(struct dquot *dquot);
+static int ext3_acquire_dquot(struct dquot *dquot);
+static int ext3_release_dquot(struct dquot *dquot);
 static int ext3_mark_dquot_dirty(struct dquot *dquot);
 static int ext3_write_info(struct super_block *sb, int type);
 static int ext3_quota_on(struct super_block *sb, int type, int format_id, char *path);
@@ -536,6 +536,8 @@ static struct dquot_operations ext3_quota_operations = {
        .free_inode     = dquot_free_inode,
        .transfer       = dquot_transfer,
        .write_dquot    = ext3_write_dquot,
+       .acquire_dquot  = ext3_acquire_dquot,
+       .release_dquot  = ext3_release_dquot,
        .mark_dirty     = ext3_mark_dquot_dirty,
        .write_info     = ext3_write_info
 };
@@ -557,7 +559,6 @@ static struct super_operations ext3_sops = {
        .read_inode     = ext3_read_inode,
        .write_inode    = ext3_write_inode,
        .dirty_inode    = ext3_dirty_inode,
-       .put_inode      = ext3_put_inode,
        .delete_inode   = ext3_delete_inode,
        .put_super      = ext3_put_super,
        .write_super    = ext3_write_super,
@@ -578,12 +579,13 @@ enum {
        Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
        Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
        Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov,
-       Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_noload,
+       Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
+       Opt_reservation, Opt_noreservation, Opt_noload,
        Opt_commit, Opt_journal_update, Opt_journal_inum,
        Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
        Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
        Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0,
-       Opt_ignore, Opt_err,
+       Opt_tagxid, Opt_ignore, Opt_err, Opt_resize,
 };
 
 static match_table_t tokens = {
@@ -610,6 +612,8 @@ static match_table_t tokens = {
        {Opt_nouser_xattr, "nouser_xattr"},
        {Opt_acl, "acl"},
        {Opt_noacl, "noacl"},
+       {Opt_reservation, "reservation"},
+       {Opt_noreservation, "noreservation"},
        {Opt_noload, "noload"},
        {Opt_commit, "commit=%u"},
        {Opt_journal_update, "journal=update"},
@@ -624,11 +628,14 @@ static match_table_t tokens = {
        {Opt_grpjquota, "grpjquota=%s"},
        {Opt_jqfmt_vfsold, "jqfmt=vfsold"},
        {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
+       {Opt_tagxid, "tagxid"},
        {Opt_ignore, "grpquota"},
        {Opt_ignore, "noquota"},
        {Opt_ignore, "quota"},
        {Opt_ignore, "usrquota"},
-       {Opt_err, NULL}
+       {Opt_err, NULL},
+       {Opt_resize, "resize"}
+               
 };
 
 static unsigned long get_sb_block(void **data)
@@ -652,7 +659,7 @@ static unsigned long get_sb_block(void **data)
 }
 
 static int parse_options (char * options, struct super_block *sb,
-                         unsigned long * inum, int is_remount)
+                         unsigned long * inum, unsigned long *n_blocks_count, int is_remount)
 {
        struct ext3_sb_info *sbi = EXT3_SB(sb);
        char * p;
@@ -717,6 +724,11 @@ static int parse_options (char * options, struct super_block *sb,
                case Opt_nouid32:
                        set_opt (sbi->s_mount_opt, NO_UID32);
                        break;
+#ifndef CONFIG_INOXID_NONE
+               case Opt_tagxid:
+                       set_opt (sbi->s_mount_opt, TAG_XID);
+                       break;
+#endif
                case Opt_check:
 #ifdef CONFIG_EXT3_CHECK
                        set_opt (sbi->s_mount_opt, CHECK);
@@ -763,6 +775,12 @@ static int parse_options (char * options, struct super_block *sb,
                        printk("EXT3 (no)acl options not supported\n");
                        break;
 #endif
+               case Opt_reservation:
+                       set_opt(sbi->s_mount_opt, RESERVATION);
+                       break;
+               case Opt_noreservation:
+                       clear_opt(sbi->s_mount_opt, RESERVATION);
+                       break;
                case Opt_journal_update:
                        /* @@@ FIXME */
                        /* Eventually we will want to be able to create
@@ -895,6 +913,15 @@ clear_qf_name:
                        break;
                case Opt_ignore:
                        break;
+               case Opt_resize:
+                       if (!n_blocks_count) {
+                               printk("EXT3-fs: resize option only available "
+                                       "for remount\n");
+                               return 0;
+                       }
+                       match_int(&args[0], &option);
+                       *n_blocks_count = option;
+                       break;
                default:
                        printk (KERN_ERR
                                "EXT3-fs: Unrecognized mount option \"%s\" "
@@ -1284,9 +1311,13 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
        sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
 
-       if (!parse_options ((char *) data, sb, &journal_inum, 0))
+       set_opt(sbi->s_mount_opt, RESERVATION);
+
+       if (!parse_options ((char *) data, sb, &journal_inum, NULL, 0))
                goto failed_mount;
 
+       if (EXT3_SB(sb)->s_mount_opt & EXT3_MOUNT_TAG_XID)
+               sb->s_flags |= MS_TAGXID;
        sb->s_flags |= MS_ONE_SECOND;
        sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
                ((sbi->s_mount_opt & EXT3_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
@@ -1458,6 +1489,14 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        sbi->s_gdb_count = db_count;
        get_random_bytes(&sbi->s_next_generation, sizeof(u32));
        spin_lock_init(&sbi->s_next_gen_lock);
+       /* per fileystem reservation list head & lock */
+       spin_lock_init(&sbi->s_rsv_window_lock);
+       INIT_LIST_HEAD(&sbi->s_rsv_window_head.rsv_list);
+       sbi->s_rsv_window_head.rsv_start = 0;
+       sbi->s_rsv_window_head.rsv_end = 0;
+       sbi->s_rsv_window_head.rsv_alloc_hit = 0;
+       atomic_set(&sbi->s_rsv_window_head.rsv_goal_size, 0);
+
        /*
         * set up enough so that it can read an inode
         */
@@ -2004,11 +2043,12 @@ int ext3_remount (struct super_block * sb, int * flags, char * data)
        struct ext3_super_block * es;
        struct ext3_sb_info *sbi = EXT3_SB(sb);
        unsigned long tmp;
+       unsigned long n_blocks_count = 0;
 
        /*
         * Allow the "check" option to be passed as a remount option.
         */
-       if (!parse_options(data, sb, &tmp, 1))
+       if (!parse_options(data, sb, &tmp, &n_blocks_count, 1))
                return -EINVAL;
 
        if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
@@ -2021,7 +2061,8 @@ int ext3_remount (struct super_block * sb, int * flags, char * data)
 
        ext3_init_journal_params(sbi, sbi->s_journal);
 
-       if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) {
+       if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY) ||
+               n_blocks_count > le32_to_cpu(es->s_blocks_count)) {
                if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
                        return -EROFS;
 
@@ -2060,6 +2101,8 @@ int ext3_remount (struct super_block * sb, int * flags, char * data)
                         */
                        ext3_clear_journal_err(sb, es);
                        sbi->s_mount_state = le16_to_cpu(es->s_state);
+                       if ((ret = ext3_group_extend(sb, es, n_blocks_count)))
+                               return ret;
                        if (!ext3_setup_super (sb, es, 0))
                                sb->s_flags &= ~MS_RDONLY;
                }
@@ -2181,6 +2224,38 @@ static int ext3_write_dquot(struct dquot *dquot)
        return ret;
 }
 
+static int ext3_acquire_dquot(struct dquot *dquot)
+{
+       int ret, err;
+       handle_t *handle;
+
+       handle = ext3_journal_start(dquot_to_inode(dquot),
+                                       EXT3_QUOTA_INIT_BLOCKS);
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       ret = dquot_acquire(dquot);
+       err = ext3_journal_stop(handle);
+       if (!ret)
+               ret = err;
+       return ret;
+}
+
+static int ext3_release_dquot(struct dquot *dquot)
+{
+       int ret, err;
+       handle_t *handle;
+
+       handle = ext3_journal_start(dquot_to_inode(dquot),
+                                       EXT3_QUOTA_INIT_BLOCKS);
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       ret = dquot_release(dquot);
+       err = ext3_journal_stop(handle);
+       if (!ret)
+               ret = err;
+       return ret;
+}
+
 static int ext3_mark_dquot_dirty(struct dquot *dquot)
 {
        /* Are we journalling quotas? */