mm: thp: set the accessed flag for old pages on access fault
[pandora-kernel.git] / drivers / mtd / mtdpart.c
index 630be3e..198da0a 100644 (file)
@@ -73,9 +73,9 @@ static int part_read(struct mtd_info *mtd, loff_t from, size_t len,
        res = part->master->read(part->master, from + part->offset,
                                   len, retlen, buf);
        if (unlikely(res)) {
-               if (res == -EUCLEAN)
+               if (mtd_is_bitflip(res))
                        mtd->ecc_stats.corrected += part->master->ecc_stats.corrected - stats.corrected;
-               if (res == -EBADMSG)
+               if (mtd_is_eccerr(res))
                        mtd->ecc_stats.failed += part->master->ecc_stats.failed - stats.failed;
        }
        return res;
@@ -130,7 +130,7 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from,
        if (ops->oobbuf) {
                size_t len, pages;
 
-               if (ops->mode == MTD_OOB_AUTO)
+               if (ops->mode == MTD_OPS_AUTO_OOB)
                        len = mtd->oobavail;
                else
                        len = mtd->oobsize;
@@ -142,9 +142,9 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from,
 
        res = part->master->read_oob(part->master, from + part->offset, ops);
        if (unlikely(res)) {
-               if (res == -EUCLEAN)
+               if (mtd_is_bitflip(res))
                        mtd->ecc_stats.corrected++;
-               if (res == -EBADMSG)
+               if (mtd_is_eccerr(res))
                        mtd->ecc_stats.failed++;
        }
        return res;
@@ -479,6 +479,19 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
                               (unsigned long long)cur_offset, (unsigned long long)slave->offset);
                }
        }
+       if (slave->offset == MTDPART_OFS_RETAIN) {
+               slave->offset = cur_offset;
+               if (master->size - slave->offset >= slave->mtd.size) {
+                       slave->mtd.size = master->size - slave->offset
+                                                       - slave->mtd.size;
+               } else {
+                       printk(KERN_ERR "mtd partition \"%s\" doesn't have enough space: %#llx < %#llx, disabled\n",
+                               part->name, master->size - slave->offset,
+                               slave->mtd.size);
+                       /* register to preserve ordering */
+                       goto out_register;
+               }
+       }
        if (slave->mtd.size == MTDPART_SIZ_FULL)
                slave->mtd.size = master->size - slave->offset;
 
@@ -693,6 +706,8 @@ static struct mtd_part_parser *get_partition_parser(const char *name)
        return ret;
 }
 
+#define put_partition_parser(p) do { module_put((p)->owner); } while (0)
+
 int register_mtd_parser(struct mtd_part_parser *p)
 {
        spin_lock(&part_parser_lock);
@@ -712,28 +727,62 @@ int deregister_mtd_parser(struct mtd_part_parser *p)
 }
 EXPORT_SYMBOL_GPL(deregister_mtd_parser);
 
+/*
+ * Do not forget to update 'parse_mtd_partitions()' kerneldoc comment if you
+ * are changing this array!
+ */
+static const char *default_mtd_part_types[] = {
+       "cmdlinepart",
+       "ofpart",
+       NULL
+};
+
+/**
+ * parse_mtd_partitions - parse MTD partitions
+ * @master: the master partition (describes whole MTD device)
+ * @types: names of partition parsers to try or %NULL
+ * @pparts: array of partitions found is returned here
+ * @data: MTD partition parser-specific data
+ *
+ * This function tries to find partition on MTD device @master. It uses MTD
+ * partition parsers, specified in @types. However, if @types is %NULL, then
+ * the default list of parsers is used. The default list contains only the
+ * "cmdlinepart" and "ofpart" parsers ATM.
+ * Note: If there are more then one parser in @types, the kernel only takes the
+ * partitions parsed out by the first parser.
+ *
+ * This function may return:
+ * o a negative error code in case of failure
+ * o zero if no partitions were found
+ * o a positive number of found partitions, in which case on exit @pparts will
+ *   point to an array containing this number of &struct mtd_info objects.
+ */
 int parse_mtd_partitions(struct mtd_info *master, const char **types,
-                        struct mtd_partition **pparts, unsigned long origin)
+                        struct mtd_partition **pparts,
+                        struct mtd_part_parser_data *data)
 {
        struct mtd_part_parser *parser;
        int ret = 0;
 
+       if (!types)
+               types = default_mtd_part_types;
+
        for ( ; ret <= 0 && *types; types++) {
                parser = get_partition_parser(*types);
                if (!parser && !request_module("%s", *types))
                                parser = get_partition_parser(*types);
                if (!parser)
                        continue;
-               ret = (*parser->parse_fn)(master, pparts, origin);
+               ret = (*parser->parse_fn)(master, pparts, data);
+               put_partition_parser(parser);
                if (ret > 0) {
                        printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
                               ret, parser->name, master->name);
+                       break;
                }
-               put_partition_parser(parser);
        }
        return ret;
 }
-EXPORT_SYMBOL_GPL(parse_mtd_partitions);
 
 int mtd_is_partition(struct mtd_info *mtd)
 {