LCOV - code coverage report
Current view: top level - drivers/mtd - mtdsuper.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 50 0.0 %
Date: 2014-02-18 Functions: 0 6 0.0 %
Branches: 0 32 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* MTD-based superblock management
       2                 :            :  *
       3                 :            :  * Copyright © 2001-2007 Red Hat, Inc. All Rights Reserved.
       4                 :            :  * Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org>
       5                 :            :  *
       6                 :            :  * Written by:  David Howells <dhowells@redhat.com>
       7                 :            :  *              David Woodhouse <dwmw2@infradead.org>
       8                 :            :  *
       9                 :            :  * This program is free software; you can redistribute it and/or
      10                 :            :  * modify it under the terms of the GNU General Public License
      11                 :            :  * as published by the Free Software Foundation; either version
      12                 :            :  * 2 of the License, or (at your option) any later version.
      13                 :            :  */
      14                 :            : 
      15                 :            : #include <linux/mtd/super.h>
      16                 :            : #include <linux/namei.h>
      17                 :            : #include <linux/export.h>
      18                 :            : #include <linux/ctype.h>
      19                 :            : #include <linux/slab.h>
      20                 :            : #include <linux/major.h>
      21                 :            : 
      22                 :            : /*
      23                 :            :  * compare superblocks to see if they're equivalent
      24                 :            :  * - they are if the underlying MTD device is the same
      25                 :            :  */
      26                 :          0 : static int get_sb_mtd_compare(struct super_block *sb, void *_mtd)
      27                 :            : {
      28                 :            :         struct mtd_info *mtd = _mtd;
      29                 :            : 
      30         [ #  # ]:          0 :         if (sb->s_mtd == mtd) {
      31                 :            :                 pr_debug("MTDSB: Match on device %d (\"%s\")\n",
      32                 :            :                       mtd->index, mtd->name);
      33                 :            :                 return 1;
      34                 :            :         }
      35                 :            : 
      36                 :            :         pr_debug("MTDSB: No match, device %d (\"%s\"), device %d (\"%s\")\n",
      37                 :            :               sb->s_mtd->index, sb->s_mtd->name, mtd->index, mtd->name);
      38                 :          0 :         return 0;
      39                 :            : }
      40                 :            : 
      41                 :            : /*
      42                 :            :  * mark the superblock by the MTD device it is using
      43                 :            :  * - set the device number to be the correct MTD block device for pesuperstence
      44                 :            :  *   of NFS exports
      45                 :            :  */
      46                 :          0 : static int get_sb_mtd_set(struct super_block *sb, void *_mtd)
      47                 :            : {
      48                 :            :         struct mtd_info *mtd = _mtd;
      49                 :            : 
      50                 :          0 :         sb->s_mtd = mtd;
      51                 :          0 :         sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, mtd->index);
      52                 :          0 :         sb->s_bdi = mtd->backing_dev_info;
      53                 :          0 :         return 0;
      54                 :            : }
      55                 :            : 
      56                 :            : /*
      57                 :            :  * get a superblock on an MTD-backed filesystem
      58                 :            :  */
      59                 :          0 : static struct dentry *mount_mtd_aux(struct file_system_type *fs_type, int flags,
      60                 :            :                           const char *dev_name, void *data,
      61                 :            :                           struct mtd_info *mtd,
      62                 :            :                           int (*fill_super)(struct super_block *, void *, int))
      63                 :            : {
      64                 :            :         struct super_block *sb;
      65                 :            :         int ret;
      66                 :            : 
      67                 :          0 :         sb = sget(fs_type, get_sb_mtd_compare, get_sb_mtd_set, flags, mtd);
      68         [ #  # ]:          0 :         if (IS_ERR(sb))
      69                 :            :                 goto out_error;
      70                 :            : 
      71         [ #  # ]:          0 :         if (sb->s_root)
      72                 :            :                 goto already_mounted;
      73                 :            : 
      74                 :            :         /* fresh new superblock */
      75                 :            :         pr_debug("MTDSB: New superblock for device %d (\"%s\")\n",
      76                 :            :               mtd->index, mtd->name);
      77                 :            : 
      78                 :          0 :         ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
      79         [ #  # ]:          0 :         if (ret < 0) {
      80                 :          0 :                 deactivate_locked_super(sb);
      81                 :            :                 return ERR_PTR(ret);
      82                 :            :         }
      83                 :            : 
      84                 :            :         /* go */
      85                 :          0 :         sb->s_flags |= MS_ACTIVE;
      86                 :          0 :         return dget(sb->s_root);
      87                 :            : 
      88                 :            :         /* new mountpoint for an already mounted superblock */
      89                 :            : already_mounted:
      90                 :            :         pr_debug("MTDSB: Device %d (\"%s\") is already mounted\n",
      91                 :            :               mtd->index, mtd->name);
      92                 :          0 :         put_mtd_device(mtd);
      93                 :          0 :         return dget(sb->s_root);
      94                 :            : 
      95                 :            : out_error:
      96                 :          0 :         put_mtd_device(mtd);
      97                 :            :         return ERR_CAST(sb);
      98                 :            : }
      99                 :            : 
     100                 :            : /*
     101                 :            :  * get a superblock on an MTD-backed filesystem by MTD device number
     102                 :            :  */
     103                 :          0 : static struct dentry *mount_mtd_nr(struct file_system_type *fs_type, int flags,
     104                 :            :                          const char *dev_name, void *data, int mtdnr,
     105                 :            :                          int (*fill_super)(struct super_block *, void *, int))
     106                 :            : {
     107                 :            :         struct mtd_info *mtd;
     108                 :            : 
     109                 :          0 :         mtd = get_mtd_device(NULL, mtdnr);
     110         [ #  # ]:          0 :         if (IS_ERR(mtd)) {
     111                 :            :                 pr_debug("MTDSB: Device #%u doesn't appear to exist\n", mtdnr);
     112                 :            :                 return ERR_CAST(mtd);
     113                 :            :         }
     114                 :            : 
     115                 :          0 :         return mount_mtd_aux(fs_type, flags, dev_name, data, mtd, fill_super);
     116                 :            : }
     117                 :            : 
     118                 :            : /*
     119                 :            :  * set up an MTD-based superblock
     120                 :            :  */
     121                 :          0 : struct dentry *mount_mtd(struct file_system_type *fs_type, int flags,
     122                 :            :                const char *dev_name, void *data,
     123                 :            :                int (*fill_super)(struct super_block *, void *, int))
     124                 :            : {
     125                 :            : #ifdef CONFIG_BLOCK
     126                 :            :         struct block_device *bdev;
     127                 :            :         int ret, major;
     128                 :            : #endif
     129                 :            :         int mtdnr;
     130                 :            : 
     131         [ #  # ]:          0 :         if (!dev_name)
     132                 :            :                 return ERR_PTR(-EINVAL);
     133                 :            : 
     134                 :            :         pr_debug("MTDSB: dev_name \"%s\"\n", dev_name);
     135                 :            : 
     136                 :            :         /* the preferred way of mounting in future; especially when
     137                 :            :          * CONFIG_BLOCK=n - we specify the underlying MTD device by number or
     138                 :            :          * by name, so that we don't require block device support to be present
     139                 :            :          * in the kernel. */
     140 [ #  # ][ #  # ]:          0 :         if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') {
                 [ #  # ]
     141         [ #  # ]:          0 :                 if (dev_name[3] == ':') {
     142                 :            :                         struct mtd_info *mtd;
     143                 :            : 
     144                 :            :                         /* mount by MTD device name */
     145                 :            :                         pr_debug("MTDSB: mtd:%%s, name \"%s\"\n",
     146                 :            :                               dev_name + 4);
     147                 :            : 
     148                 :          0 :                         mtd = get_mtd_device_nm(dev_name + 4);
     149         [ #  # ]:          0 :                         if (!IS_ERR(mtd))
     150                 :          0 :                                 return mount_mtd_aux(
     151                 :            :                                         fs_type, flags,
     152                 :            :                                         dev_name, data, mtd,
     153                 :            :                                         fill_super);
     154                 :            : 
     155                 :          0 :                         printk(KERN_NOTICE "MTD:"
     156                 :            :                                " MTD device with name \"%s\" not found.\n",
     157                 :            :                                dev_name + 4);
     158                 :            : 
     159         [ #  # ]:          0 :                 } else if (isdigit(dev_name[3])) {
     160                 :            :                         /* mount by MTD device number name */
     161                 :            :                         char *endptr;
     162                 :            : 
     163                 :          0 :                         mtdnr = simple_strtoul(dev_name + 3, &endptr, 0);
     164         [ #  # ]:          0 :                         if (!*endptr) {
     165                 :            :                                 /* It was a valid number */
     166                 :            :                                 pr_debug("MTDSB: mtd%%d, mtdnr %d\n",
     167                 :            :                                       mtdnr);
     168                 :          0 :                                 return mount_mtd_nr(fs_type, flags,
     169                 :            :                                                      dev_name, data,
     170                 :            :                                                      mtdnr, fill_super);
     171                 :            :                         }
     172                 :            :                 }
     173                 :            :         }
     174                 :            : 
     175                 :            : #ifdef CONFIG_BLOCK
     176                 :            :         /* try the old way - the hack where we allowed users to mount
     177                 :            :          * /dev/mtdblock$(n) but didn't actually _use_ the blockdev
     178                 :            :          */
     179                 :          0 :         bdev = lookup_bdev(dev_name);
     180         [ #  # ]:          0 :         if (IS_ERR(bdev)) {
     181                 :            :                 ret = PTR_ERR(bdev);
     182                 :            :                 pr_debug("MTDSB: lookup_bdev() returned %d\n", ret);
     183                 :            :                 return ERR_PTR(ret);
     184                 :            :         }
     185                 :            :         pr_debug("MTDSB: lookup_bdev() returned 0\n");
     186                 :            : 
     187                 :            :         ret = -EINVAL;
     188                 :            : 
     189                 :          0 :         major = MAJOR(bdev->bd_dev);
     190                 :          0 :         mtdnr = MINOR(bdev->bd_dev);
     191                 :          0 :         bdput(bdev);
     192                 :            : 
     193         [ #  # ]:          0 :         if (major != MTD_BLOCK_MAJOR)
     194                 :            :                 goto not_an_MTD_device;
     195                 :            : 
     196                 :          0 :         return mount_mtd_nr(fs_type, flags, dev_name, data, mtdnr, fill_super);
     197                 :            : 
     198                 :            : not_an_MTD_device:
     199                 :            : #endif /* CONFIG_BLOCK */
     200                 :            : 
     201         [ #  # ]:          0 :         if (!(flags & MS_SILENT))
     202                 :          0 :                 printk(KERN_NOTICE
     203                 :            :                        "MTD: Attempt to mount non-MTD device \"%s\"\n",
     204                 :            :                        dev_name);
     205                 :            :         return ERR_PTR(-EINVAL);
     206                 :            : }
     207                 :            : 
     208                 :            : EXPORT_SYMBOL_GPL(mount_mtd);
     209                 :            : 
     210                 :            : /*
     211                 :            :  * destroy an MTD-based superblock
     212                 :            :  */
     213                 :          0 : void kill_mtd_super(struct super_block *sb)
     214                 :            : {
     215                 :          0 :         generic_shutdown_super(sb);
     216                 :          0 :         put_mtd_device(sb->s_mtd);
     217                 :          0 :         sb->s_mtd = NULL;
     218                 :          0 : }
     219                 :            : 
     220                 :            : EXPORT_SYMBOL_GPL(kill_mtd_super);

Generated by: LCOV version 1.9