]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/ubifs/super.c
Merge branch 'linux-next' of git://git.infradead.org/ubifs-2.6
[linux-2.6-omap-h63xx.git] / fs / ubifs / super.c
index 9a9220333b3be51399e4fe2c28cb9a60840842fb..8780efbf40ac64fbf901fd448998361823c38be3 100644 (file)
@@ -401,6 +401,16 @@ static int ubifs_show_options(struct seq_file *s, struct vfsmount *mnt)
        else if (c->mount_opts.unmount_mode == 1)
                seq_printf(s, ",norm_unmount");
 
+       if (c->mount_opts.bulk_read == 2)
+               seq_printf(s, ",bulk_read");
+       else if (c->mount_opts.bulk_read == 1)
+               seq_printf(s, ",no_bulk_read");
+
+       if (c->mount_opts.chk_data_crc == 2)
+               seq_printf(s, ",chk_data_crc");
+       else if (c->mount_opts.chk_data_crc == 1)
+               seq_printf(s, ",no_chk_data_crc");
+
        return 0;
 }
 
@@ -408,13 +418,26 @@ static int ubifs_sync_fs(struct super_block *sb, int wait)
 {
        struct ubifs_info *c = sb->s_fs_info;
        int i, ret = 0, err;
+       long long bud_bytes;
 
-       if (c->jheads)
+       if (c->jheads) {
                for (i = 0; i < c->jhead_cnt; i++) {
                        err = ubifs_wbuf_sync(&c->jheads[i].wbuf);
                        if (err && !ret)
                                ret = err;
                }
+
+               /* Commit the journal unless it has too little data */
+               spin_lock(&c->buds_lock);
+               bud_bytes = c->bud_bytes;
+               spin_unlock(&c->buds_lock);
+               if (bud_bytes > c->leb_size) {
+                       err = ubifs_run_commit(c);
+                       if (err)
+                               return err;
+               }
+       }
+
        /*
         * We ought to call sync for c->ubi but it does not have one. If it had
         * it would in turn call mtd->sync, however mtd operations are
@@ -538,6 +561,18 @@ static int init_constants_early(struct ubifs_info *c)
         * calculations when reporting free space.
         */
        c->leb_overhead = c->leb_size % UBIFS_MAX_DATA_NODE_SZ;
+       /* Buffer size for bulk-reads */
+       c->bulk_read_buf_size = UBIFS_MAX_BULK_READ * UBIFS_MAX_DATA_NODE_SZ;
+       if (c->bulk_read_buf_size > c->leb_size)
+               c->bulk_read_buf_size = c->leb_size;
+       if (c->bulk_read_buf_size > 128 * 1024) {
+               /* Check if we can kmalloc more than 128KiB */
+               void *try = kmalloc(c->bulk_read_buf_size, GFP_KERNEL);
+
+               kfree(try);
+               if (!try)
+                       c->bulk_read_buf_size = 128 * 1024;
+       }
        return 0;
 }
 
@@ -840,17 +875,29 @@ static int check_volume_empty(struct ubifs_info *c)
  *
  * Opt_fast_unmount: do not run a journal commit before un-mounting
  * Opt_norm_unmount: run a journal commit before un-mounting
+ * Opt_bulk_read: enable bulk-reads
+ * Opt_no_bulk_read: disable bulk-reads
+ * Opt_chk_data_crc: check CRCs when reading data nodes
+ * Opt_no_chk_data_crc: do not check CRCs when reading data nodes
  * Opt_err: just end of array marker
  */
 enum {
        Opt_fast_unmount,
        Opt_norm_unmount,
+       Opt_bulk_read,
+       Opt_no_bulk_read,
+       Opt_chk_data_crc,
+       Opt_no_chk_data_crc,
        Opt_err,
 };
 
 static const match_table_t tokens = {
        {Opt_fast_unmount, "fast_unmount"},
        {Opt_norm_unmount, "norm_unmount"},
+       {Opt_bulk_read, "bulk_read"},
+       {Opt_no_bulk_read, "no_bulk_read"},
+       {Opt_chk_data_crc, "chk_data_crc"},
+       {Opt_no_chk_data_crc, "no_chk_data_crc"},
        {Opt_err, NULL},
 };
 
@@ -888,6 +935,22 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options,
                        c->mount_opts.unmount_mode = 1;
                        c->fast_unmount = 0;
                        break;
+               case Opt_bulk_read:
+                       c->mount_opts.bulk_read = 2;
+                       c->bulk_read = 1;
+                       break;
+               case Opt_no_bulk_read:
+                       c->mount_opts.bulk_read = 1;
+                       c->bulk_read = 0;
+                       break;
+               case Opt_chk_data_crc:
+                       c->mount_opts.chk_data_crc = 2;
+                       c->no_chk_data_crc = 0;
+                       break;
+               case Opt_no_chk_data_crc:
+                       c->mount_opts.chk_data_crc = 1;
+                       c->no_chk_data_crc = 1;
+                       break;
                default:
                        ubifs_err("unrecognized mount option \"%s\" "
                                  "or missing value", p);
@@ -996,6 +1059,8 @@ static int mount_ubifs(struct ubifs_info *c)
                        goto out_free;
        }
 
+       c->always_chk_crc = 1;
+
        err = ubifs_read_superblock(c);
        if (err)
                goto out_free;
@@ -1032,8 +1097,6 @@ static int mount_ubifs(struct ubifs_info *c)
 
                /* Create background thread */
                c->bgt = kthread_create(ubifs_bg_thread, c, c->bgt_name);
-               if (!c->bgt)
-                       c->bgt = ERR_PTR(-EINVAL);
                if (IS_ERR(c->bgt)) {
                        err = PTR_ERR(c->bgt);
                        c->bgt = NULL;
@@ -1139,24 +1202,28 @@ static int mount_ubifs(struct ubifs_info *c)
        if (err)
                goto out_infos;
 
+       c->always_chk_crc = 0;
+
        ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"",
                  c->vi.ubi_num, c->vi.vol_id, c->vi.name);
        if (mounted_read_only)
                ubifs_msg("mounted read-only");
        x = (long long)c->main_lebs * c->leb_size;
-       ubifs_msg("file system size: %lld bytes (%lld KiB, %lld MiB, %d LEBs)",
-                 x, x >> 10, x >> 20, c->main_lebs);
+       ubifs_msg("file system size:   %lld bytes (%lld KiB, %lld MiB, %d "
+                 "LEBs)", x, x >> 10, x >> 20, c->main_lebs);
        x = (long long)c->log_lebs * c->leb_size + c->max_bud_bytes;
-       ubifs_msg("journal size: %lld bytes (%lld KiB, %lld MiB, %d LEBs)",
-                 x, x >> 10, x >> 20, c->log_lebs + c->max_bud_cnt);
-       ubifs_msg("default compressor: %s", ubifs_compr_name(c->default_compr));
-       ubifs_msg("media format %d, latest format %d",
+       ubifs_msg("journal size:       %lld bytes (%lld KiB, %lld MiB, %d "
+                 "LEBs)", x, x >> 10, x >> 20, c->log_lebs + c->max_bud_cnt);
+       ubifs_msg("media format:       %d (latest is %d)",
                  c->fmt_version, UBIFS_FORMAT_VERSION);
+       ubifs_msg("default compressor: %s", ubifs_compr_name(c->default_compr));
+       ubifs_msg("reserved for root:  %llu bytes (%llu KiB)",
+               c->report_rp_size, c->report_rp_size >> 10);
 
        dbg_msg("compiled on:         " __DATE__ " at " __TIME__);
        dbg_msg("min. I/O unit size:  %d bytes", c->min_io_size);
        dbg_msg("LEB size:            %d bytes (%d KiB)",
-               c->leb_size, c->leb_size / 1024);
+               c->leb_size, c->leb_size >> 10);
        dbg_msg("data journal heads:  %d",
                c->jhead_cnt - NONDATA_JHEADS_CNT);
        dbg_msg("UUID:                %02X%02X%02X%02X-%02X%02X"
@@ -1282,6 +1349,7 @@ static int ubifs_remount_rw(struct ubifs_info *c)
 
        mutex_lock(&c->umount_mutex);
        c->remounting_rw = 1;
+       c->always_chk_crc = 1;
 
        /* Check for enough free space */
        if (ubifs_calc_available(c, c->min_idx_lebs) <= 0) {
@@ -1345,20 +1413,20 @@ static int ubifs_remount_rw(struct ubifs_info *c)
 
        /* Create background thread */
        c->bgt = kthread_create(ubifs_bg_thread, c, c->bgt_name);
-       if (!c->bgt)
-               c->bgt = ERR_PTR(-EINVAL);
        if (IS_ERR(c->bgt)) {
                err = PTR_ERR(c->bgt);
                c->bgt = NULL;
                ubifs_err("cannot spawn \"%s\", error %d",
                          c->bgt_name, err);
-               return err;
+               goto out;
        }
        wake_up_process(c->bgt);
 
        c->orph_buf = vmalloc(c->leb_size);
-       if (!c->orph_buf)
-               return -ENOMEM;
+       if (!c->orph_buf) {
+               err = -ENOMEM;
+               goto out;
+       }
 
        /* Check for enough log space */
        lnum = c->lhead_lnum + 1;
@@ -1385,6 +1453,7 @@ static int ubifs_remount_rw(struct ubifs_info *c)
        dbg_gen("re-mounted read-write");
        c->vfs_sb->s_flags &= ~MS_RDONLY;
        c->remounting_rw = 0;
+       c->always_chk_crc = 0;
        mutex_unlock(&c->umount_mutex);
        return 0;
 
@@ -1400,6 +1469,7 @@ out:
        c->ileb_buf = NULL;
        ubifs_lpt_free(c, 1);
        c->remounting_rw = 0;
+       c->always_chk_crc = 0;
        mutex_unlock(&c->umount_mutex);
        return err;
 }
@@ -1408,12 +1478,9 @@ out:
  * commit_on_unmount - commit the journal when un-mounting.
  * @c: UBIFS file-system description object
  *
- * This function is called during un-mounting and it commits the journal unless
- * the "fast unmount" mode is enabled. It also avoids committing the journal if
- * it contains too few data.
- *
- * Sometimes recovery requires the journal to be committed at least once, and
- * this function takes care about this.
+ * This function is called during un-mounting and re-mounting, and it commits
+ * the journal unless the "fast unmount" mode is enabled. It also avoids
+ * committing the journal if it contains too few data.
  */
 static void commit_on_unmount(struct ubifs_info *c)
 {