]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
ocfs2: Add dir_resv_level mount option
authorMark Fasheh <mfasheh@suse.com>
Tue, 6 Apr 2010 01:17:16 +0000 (18:17 -0700)
committerJoel Becker <joel.becker@oracle.com>
Thu, 6 May 2010 01:18:07 +0000 (18:18 -0700)
The default behavior for directory reservations stays the same, but we add a
mount option so people can tweak the size of directory reservations
according to their workloads.

Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Documentation/filesystems/ocfs2.txt
fs/ocfs2/dir.c
fs/ocfs2/ocfs2.h
fs/ocfs2/reservations.c
fs/ocfs2/reservations.h
fs/ocfs2/super.c

index 32339e584a9a136284baea04b5ac613e22ce43e0..1f7ae144f6d89bc351c8aa34076262bf366f4a4d 100644 (file)
@@ -83,3 +83,7 @@ noacl         (*)     Disables POSIX Access Control Lists support.
 resv_level=2   (*)     Set how agressive allocation reservations will be.
                        Valid values are between 0 (reservations off) to 8
                        (maximum space for reservations).
+dir_resv_level=        (*)     By default, directory reservations will scale with file
+                       reservations - users should rarely need to change this
+                       value. If allocation reservations are turned off, this
+                       option will have no effect.
index 8563f97c58aff7a68e83d4a8c7f788185b29e28b..6c9a28a2d3ae57a131e2d6b91ecf96f4f0db90ce 100644 (file)
@@ -2977,7 +2977,8 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
         * if we only get one now, that's enough to continue. The rest
         * will be claimed after the conversion to extents.
         */
-       data_ac->ac_resv = &oi->ip_la_data_resv;
+       if (ocfs2_dir_resv_allowed(osb))
+               data_ac->ac_resv = &oi->ip_la_data_resv;
        ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off, &len);
        if (ret) {
                mlog_errno(ret);
@@ -3348,7 +3349,8 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
                        goto bail;
                }
 
-               data_ac->ac_resv = &OCFS2_I(dir)->ip_la_data_resv;
+               if (ocfs2_dir_resv_allowed(osb))
+                       data_ac->ac_resv = &OCFS2_I(dir)->ip_la_data_resv;
 
                credits = ocfs2_calc_extend_credits(sb, el, 1);
        } else {
index 09d7aee3dabe40f1b1a983665a795b2bafe396ba..a388528f485cec90c79728028da928f592df4359 100644 (file)
@@ -356,6 +356,7 @@ struct ocfs2_super
        struct ocfs2_reservation_map    osb_la_resmap;
 
        unsigned int    osb_resv_level;
+       unsigned int    osb_dir_resv_level;
 
        /* Next three fields are for local node slot recovery during
         * mount. */
index 87fa35791f184700b01ef0f18a8bd0e1b7ed5917..6497bcc00fa524da1624b03ad39e13b9ecd884c9 100644 (file)
@@ -44,7 +44,11 @@ DEFINE_SPINLOCK(resv_lock);
 
 #define        OCFS2_MIN_RESV_WINDOW_BITS      8
 #define        OCFS2_MAX_RESV_WINDOW_BITS      1024
-#define        OCFS2_RESV_DIR_WINDOW_BITS      OCFS2_MIN_RESV_WINDOW_BITS
+
+int ocfs2_dir_resv_allowed(struct ocfs2_super *osb)
+{
+       return (osb->osb_resv_level && osb->osb_dir_resv_level);
+}
 
 static unsigned int ocfs2_resv_window_bits(struct ocfs2_reservation_map *resmap,
                                           struct ocfs2_alloc_reservation *resv)
@@ -56,8 +60,7 @@ static unsigned int ocfs2_resv_window_bits(struct ocfs2_reservation_map *resmap,
                /* 8, 16, 32, 64, 128, 256, 512, 1024 */
                bits = 4 << osb->osb_resv_level;
        } else {
-               /* For now, treat directories the same as files. */
-               bits = 4 << osb->osb_resv_level;
+               bits = 4 << osb->osb_dir_resv_level;
        }
        return bits;
 }
index 022aff601e15e14f3c04f625651814ea2644d360..25b0c0e31e912a817eb9f09ede9f0190ccc05302 100644 (file)
@@ -67,6 +67,8 @@ void ocfs2_resv_init_once(struct ocfs2_alloc_reservation *resv);
 void ocfs2_resv_set_type(struct ocfs2_alloc_reservation *resv,
                         unsigned int flags);
 
+int ocfs2_dir_resv_allowed(struct ocfs2_super *osb);
+
 /**
  * ocfs2_resv_discard() - truncate a reservation
  * @resmap:
index 5745682eb1c02b91b6fcbcd23d317efa0f945c6f..79d7d4cf45b141d49834626df08edce7db07be78 100644 (file)
@@ -96,6 +96,7 @@ struct mount_options
        signed short    slot;
        int             localalloc_opt;
        unsigned int    resv_level;
+       int             dir_resv_level;
        char            cluster_stack[OCFS2_STACK_LABEL_LEN + 1];
 };
 
@@ -178,6 +179,7 @@ enum {
        Opt_usrquota,
        Opt_grpquota,
        Opt_resv_level,
+       Opt_dir_resv_level,
        Opt_err,
 };
 
@@ -205,6 +207,7 @@ static const match_table_t tokens = {
        {Opt_usrquota, "usrquota"},
        {Opt_grpquota, "grpquota"},
        {Opt_resv_level, "resv_level=%u"},
+       {Opt_dir_resv_level, "dir_resv_level=%u"},
        {Opt_err, NULL}
 };
 
@@ -1034,6 +1037,11 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
 
        ocfs2_la_set_sizes(osb, parsed_options.localalloc_opt);
        osb->osb_resv_level = parsed_options.resv_level;
+       osb->osb_dir_resv_level = parsed_options.resv_level;
+       if (parsed_options.dir_resv_level == -1)
+               osb->osb_dir_resv_level = parsed_options.resv_level;
+       else
+               osb->osb_dir_resv_level = parsed_options.dir_resv_level;
 
        status = ocfs2_verify_userspace_stack(osb, &parsed_options);
        if (status)
@@ -1295,6 +1303,7 @@ static int ocfs2_parse_options(struct super_block *sb,
        mopt->localalloc_opt = -1;
        mopt->cluster_stack[0] = '\0';
        mopt->resv_level = OCFS2_DEFAULT_RESV_LEVEL;
+       mopt->dir_resv_level = -1;
 
        if (!options) {
                status = 1;
@@ -1449,6 +1458,17 @@ static int ocfs2_parse_options(struct super_block *sb,
                            option < OCFS2_MAX_RESV_LEVEL)
                                mopt->resv_level = option;
                        break;
+               case Opt_dir_resv_level:
+                       if (is_remount)
+                               break;
+                       if (match_int(&args[0], &option)) {
+                               status = 0;
+                               goto bail;
+                       }
+                       if (option >= OCFS2_MIN_RESV_LEVEL &&
+                           option < OCFS2_MAX_RESV_LEVEL)
+                               mopt->dir_resv_level = option;
+                       break;
                default:
                        mlog(ML_ERROR,
                             "Unrecognized mount option \"%s\" "
@@ -1533,6 +1553,9 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
        if (osb->osb_resv_level != OCFS2_DEFAULT_RESV_LEVEL)
                seq_printf(s, ",resv_level=%d", osb->osb_resv_level);
 
+       if (osb->osb_dir_resv_level != osb->osb_resv_level)
+               seq_printf(s, ",dir_resv_level=%d", osb->osb_resv_level);
+
        return 0;
 }