fs: introduce f_op->mmap_capabilities for nommu mmap support
authorChristoph Hellwig <hch@lst.de>
Wed, 14 Jan 2015 09:42:32 +0000 (10:42 +0100)
committerJens Axboe <axboe@fb.com>
Tue, 20 Jan 2015 21:02:58 +0000 (14:02 -0700)
Since "BDI: Provide backing device capability information [try #3]" the
backing_dev_info structure also provides flags for the kind of mmap
operation available in a nommu environment, which is entirely unrelated
to it's original purpose.

Introduce a new nommu-only file operation to provide this information to
the nommu mmap code instead.  Splitting this from the backing_dev_info
structure allows to remove lots of backing_dev_info instance that aren't
otherwise needed, and entirely gets rid of the concept of providing a
backing_dev_info for a character device.  It also removes the need for
the mtd_inodefs filesystem.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Tejun Heo <tj@kernel.org>
Acked-by: Brian Norris <computersforpeace@gmail.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
32 files changed:
Documentation/nommu-mmap.txt
block/blk-core.c
drivers/char/mem.c
drivers/mtd/mtdchar.c
drivers/mtd/mtdconcat.c
drivers/mtd/mtdcore.c
drivers/mtd/mtdpart.c
drivers/staging/lustre/lustre/llite/llite_lib.c
fs/9p/v9fs.c
fs/afs/volume.c
fs/aio.c
fs/btrfs/disk-io.c
fs/char_dev.c
fs/cifs/connect.c
fs/coda/inode.c
fs/configfs/configfs_internal.h
fs/configfs/inode.c
fs/configfs/mount.c
fs/ecryptfs/main.c
fs/exofs/super.c
fs/ncpfs/inode.c
fs/ramfs/file-nommu.c
fs/ramfs/inode.c
fs/romfs/mmap-nommu.c
fs/ubifs/super.c
include/linux/backing-dev.h
include/linux/cdev.h
include/linux/fs.h
include/linux/mtd/mtd.h
mm/backing-dev.c
mm/nommu.c
security/security.c

index 8e1ddec2c78a2b9b9f4e73c745b9ae28e4b963b3..ae57b9ea0d4169258b48b0531976b1a4a30eabae 100644 (file)
@@ -43,12 +43,12 @@ and it's also much more restricted in the latter case:
            even if this was created by another process.
 
          - If possible, the file mapping will be directly on the backing device
-           if the backing device has the BDI_CAP_MAP_DIRECT capability and
+           if the backing device has the NOMMU_MAP_DIRECT capability and
            appropriate mapping protection capabilities. Ramfs, romfs, cramfs
            and mtd might all permit this.
 
         - If the backing device device can't or won't permit direct sharing,
-           but does have the BDI_CAP_MAP_COPY capability, then a copy of the
+           but does have the NOMMU_MAP_COPY capability, then a copy of the
            appropriate bit of the file will be read into a contiguous bit of
            memory and any extraneous space beyond the EOF will be cleared
 
@@ -220,7 +220,7 @@ directly (can't be copied).
 
 The file->f_op->mmap() operation will be called to actually inaugurate the
 mapping. It can be rejected at that point. Returning the ENOSYS error will
-cause the mapping to be copied instead if BDI_CAP_MAP_COPY is specified.
+cause the mapping to be copied instead if NOMMU_MAP_COPY is specified.
 
 The vm_ops->close() routine will be invoked when the last mapping on a chardev
 is removed. An existing mapping will be shared, partially or not, if possible
@@ -232,7 +232,7 @@ want to handle it, despite the fact it's got an operation. For instance, it
 might try directing the call to a secondary driver which turns out not to
 implement it. Such is the case for the framebuffer driver which attempts to
 direct the call to the device-specific driver. Under such circumstances, the
-mapping request will be rejected if BDI_CAP_MAP_COPY is not specified, and a
+mapping request will be rejected if NOMMU_MAP_COPY is not specified, and a
 copy mapped otherwise.
 
 IMPORTANT NOTE:
index 3ad405571dcc5105a52da4284477a187db936f64..928aac29bccdadcbc8c2ece20e2228d10d31d987 100644 (file)
@@ -607,7 +607,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
        q->backing_dev_info.ra_pages =
                        (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
        q->backing_dev_info.state = 0;
-       q->backing_dev_info.capabilities = BDI_CAP_MAP_COPY;
+       q->backing_dev_info.capabilities = 0;
        q->backing_dev_info.name = "block";
        q->node = node_id;
 
index 4c58333b42570d233ccfaa83dac3c67f69e73b49..9a6b63783a94dd19a4f49133fd94265fad98c19c 100644 (file)
@@ -287,13 +287,24 @@ static unsigned long get_unmapped_area_mem(struct file *file,
        return pgoff << PAGE_SHIFT;
 }
 
+/* permit direct mmap, for read, write or exec */
+static unsigned memory_mmap_capabilities(struct file *file)
+{
+       return NOMMU_MAP_DIRECT |
+               NOMMU_MAP_READ | NOMMU_MAP_WRITE | NOMMU_MAP_EXEC;
+}
+
+static unsigned zero_mmap_capabilities(struct file *file)
+{
+       return NOMMU_MAP_COPY;
+}
+
 /* can't do an in-place private mapping if there's no MMU */
 static inline int private_mapping_ok(struct vm_area_struct *vma)
 {
        return vma->vm_flags & VM_MAYSHARE;
 }
 #else
-#define get_unmapped_area_mem  NULL
 
 static inline int private_mapping_ok(struct vm_area_struct *vma)
 {
@@ -721,7 +732,10 @@ static const struct file_operations mem_fops = {
        .write          = write_mem,
        .mmap           = mmap_mem,
        .open           = open_mem,
+#ifndef CONFIG_MMU
        .get_unmapped_area = get_unmapped_area_mem,
+       .mmap_capabilities = memory_mmap_capabilities,
+#endif
 };
 
 #ifdef CONFIG_DEVKMEM
@@ -731,7 +745,10 @@ static const struct file_operations kmem_fops = {
        .write          = write_kmem,
        .mmap           = mmap_kmem,
        .open           = open_kmem,
+#ifndef CONFIG_MMU
        .get_unmapped_area = get_unmapped_area_mem,
+       .mmap_capabilities = memory_mmap_capabilities,
+#endif
 };
 #endif
 
@@ -760,16 +777,9 @@ static const struct file_operations zero_fops = {
        .read_iter      = read_iter_zero,
        .aio_write      = aio_write_zero,
        .mmap           = mmap_zero,
-};
-
-/*
- * capabilities for /dev/zero
- * - permits private mappings, "copies" are taken of the source of zeros
- * - no writeback happens
- */
-static struct backing_dev_info zero_bdi = {
-       .name           = "char/mem",
-       .capabilities   = BDI_CAP_MAP_COPY | BDI_CAP_NO_ACCT_AND_WRITEBACK,
+#ifndef CONFIG_MMU
+       .mmap_capabilities = zero_mmap_capabilities,
+#endif
 };
 
 static const struct file_operations full_fops = {
@@ -783,22 +793,22 @@ static const struct memdev {
        const char *name;
        umode_t mode;
        const struct file_operations *fops;
-       struct backing_dev_info *dev_info;
+       fmode_t fmode;
 } devlist[] = {
-        [1] = { "mem", 0, &mem_fops, &directly_mappable_cdev_bdi },
+        [1] = { "mem", 0, &mem_fops, FMODE_UNSIGNED_OFFSET },
 #ifdef CONFIG_DEVKMEM
-        [2] = { "kmem", 0, &kmem_fops, &directly_mappable_cdev_bdi },
+        [2] = { "kmem", 0, &kmem_fops, FMODE_UNSIGNED_OFFSET },
 #endif
-        [3] = { "null", 0666, &null_fops, NULL },
+        [3] = { "null", 0666, &null_fops, 0 },
 #ifdef CONFIG_DEVPORT
-        [4] = { "port", 0, &port_fops, NULL },
+        [4] = { "port", 0, &port_fops, 0 },
 #endif
-        [5] = { "zero", 0666, &zero_fops, &zero_bdi },
-        [7] = { "full", 0666, &full_fops, NULL },
-        [8] = { "random", 0666, &random_fops, NULL },
-        [9] = { "urandom", 0666, &urandom_fops, NULL },
+        [5] = { "zero", 0666, &zero_fops, 0 },
+        [7] = { "full", 0666, &full_fops, 0 },
+        [8] = { "random", 0666, &random_fops, 0 },
+        [9] = { "urandom", 0666, &urandom_fops, 0 },
 #ifdef CONFIG_PRINTK
-       [11] = { "kmsg", 0644, &kmsg_fops, NULL },
+       [11] = { "kmsg", 0644, &kmsg_fops, 0 },
 #endif
 };
 
@@ -816,12 +826,7 @@ static int memory_open(struct inode *inode, struct file *filp)
                return -ENXIO;
 
        filp->f_op = dev->fops;
-       if (dev->dev_info)
-               filp->f_mapping->backing_dev_info = dev->dev_info;
-
-       /* Is /dev/mem or /dev/kmem ? */
-       if (dev->dev_info == &directly_mappable_cdev_bdi)
-               filp->f_mode |= FMODE_UNSIGNED_OFFSET;
+       filp->f_mode |= dev->fmode;
 
        if (dev->fops->open)
                return dev->fops->open(inode, filp);
@@ -846,11 +851,6 @@ static struct class *mem_class;
 static int __init chr_dev_init(void)
 {
        int minor;
-       int err;
-
-       err = bdi_init(&zero_bdi);
-       if (err)
-               return err;
 
        if (register_chrdev(MEM_MAJOR, "mem", &memory_fops))
                printk("unable to get major %d for memory devs\n", MEM_MAJOR);
index 53563955931b4e2bb20acd576fadb3cfde8a4085..55fa27ecf4e15203f83808c87fc5cea8f18661b4 100644 (file)
@@ -49,7 +49,6 @@ static DEFINE_MUTEX(mtd_mutex);
  */
 struct mtd_file_info {
        struct mtd_info *mtd;
-       struct inode *ino;
        enum mtd_file_modes mode;
 };
 
@@ -59,10 +58,6 @@ static loff_t mtdchar_lseek(struct file *file, loff_t offset, int orig)
        return fixed_size_llseek(file, offset, orig, mfi->mtd->size);
 }
 
-static int count;
-static struct vfsmount *mnt;
-static struct file_system_type mtd_inodefs_type;
-
 static int mtdchar_open(struct inode *inode, struct file *file)
 {
        int minor = iminor(inode);
@@ -70,7 +65,6 @@ static int mtdchar_open(struct inode *inode, struct file *file)
        int ret = 0;
        struct mtd_info *mtd;
        struct mtd_file_info *mfi;
-       struct inode *mtd_ino;
 
        pr_debug("MTD_open\n");
 
@@ -78,10 +72,6 @@ static int mtdchar_open(struct inode *inode, struct file *file)
        if ((file->f_mode & FMODE_WRITE) && (minor & 1))
                return -EACCES;
 
-       ret = simple_pin_fs(&mtd_inodefs_type, &mnt, &count);
-       if (ret)
-               return ret;
-
        mutex_lock(&mtd_mutex);
        mtd = get_mtd_device(NULL, devnum);
 
@@ -95,43 +85,26 @@ static int mtdchar_open(struct inode *inode, struct file *file)
                goto out1;
        }
 
-       mtd_ino = iget_locked(mnt->mnt_sb, devnum);
-       if (!mtd_ino) {
-               ret = -ENOMEM;
-               goto out1;
-       }
-       if (mtd_ino->i_state & I_NEW) {
-               mtd_ino->i_private = mtd;
-               mtd_ino->i_mode = S_IFCHR;
-               mtd_ino->i_data.backing_dev_info = mtd->backing_dev_info;
-               unlock_new_inode(mtd_ino);
-       }
-       file->f_mapping = mtd_ino->i_mapping;
-
        /* You can't open it RW if it's not a writeable device */
        if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) {
                ret = -EACCES;
-               goto out2;
+               goto out1;
        }
 
        mfi = kzalloc(sizeof(*mfi), GFP_KERNEL);
        if (!mfi) {
                ret = -ENOMEM;
-               goto out2;
+               goto out1;
        }
-       mfi->ino = mtd_ino;
        mfi->mtd = mtd;
        file->private_data = mfi;
        mutex_unlock(&mtd_mutex);
        return 0;
 
-out2:
-       iput(mtd_ino);
 out1:
        put_mtd_device(mtd);
 out:
        mutex_unlock(&mtd_mutex);
-       simple_release_fs(&mnt, &count);
        return ret;
 } /* mtdchar_open */
 
@@ -148,12 +121,9 @@ static int mtdchar_close(struct inode *inode, struct file *file)
        if ((file->f_mode & FMODE_WRITE))
                mtd_sync(mtd);
 
-       iput(mfi->ino);
-
        put_mtd_device(mtd);
        file->private_data = NULL;
        kfree(mfi);
-       simple_release_fs(&mnt, &count);
 
        return 0;
 } /* mtdchar_close */
@@ -1117,6 +1087,13 @@ static unsigned long mtdchar_get_unmapped_area(struct file *file,
        ret = mtd_get_unmapped_area(mtd, len, offset, flags);
        return ret == -EOPNOTSUPP ? -ENODEV : ret;
 }
+
+static unsigned mtdchar_mmap_capabilities(struct file *file)
+{
+       struct mtd_file_info *mfi = file->private_data;
+
+       return mtd_mmap_capabilities(mfi->mtd);
+}
 #endif
 
 /*
@@ -1160,27 +1137,10 @@ static const struct file_operations mtd_fops = {
        .mmap           = mtdchar_mmap,
 #ifndef CONFIG_MMU
        .get_unmapped_area = mtdchar_get_unmapped_area,
+       .mmap_capabilities = mtdchar_mmap_capabilities,
 #endif
 };
 
-static const struct super_operations mtd_ops = {
-       .drop_inode = generic_delete_inode,
-       .statfs = simple_statfs,
-};
-
-static struct dentry *mtd_inodefs_mount(struct file_system_type *fs_type,
-                               int flags, const char *dev_name, void *data)
-{
-       return mount_pseudo(fs_type, "mtd_inode:", &mtd_ops, NULL, MTD_INODE_FS_MAGIC);
-}
-
-static struct file_system_type mtd_inodefs_type = {
-       .name = "mtd_inodefs",
-       .mount = mtd_inodefs_mount,
-       .kill_sb = kill_anon_super,
-};
-MODULE_ALIAS_FS("mtd_inodefs");
-
 int __init init_mtdchar(void)
 {
        int ret;
@@ -1193,23 +1153,11 @@ int __init init_mtdchar(void)
                return ret;
        }
 
-       ret = register_filesystem(&mtd_inodefs_type);
-       if (ret) {
-               pr_err("Can't register mtd_inodefs filesystem, error %d\n",
-                      ret);
-               goto err_unregister_chdev;
-       }
-
-       return ret;
-
-err_unregister_chdev:
-       __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
        return ret;
 }
 
 void __exit cleanup_mtdchar(void)
 {
-       unregister_filesystem(&mtd_inodefs_type);
        __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
 }
 
index b9000563b9f4311d63ffdfe66ba5166eb158b482..eacc3aac732789085b1bbfc86531c6fa5b0dbe17 100644 (file)
@@ -732,8 +732,6 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[],       /* subdevices to c
 
        concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks;
 
-       concat->mtd.backing_dev_info = subdev[0]->backing_dev_info;
-
        concat->subdev[0] = subdev[0];
 
        for (i = 1; i < num_devs; i++) {
@@ -761,14 +759,6 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[],      /* subdevices to c
                                    subdev[i]->flags & MTD_WRITEABLE;
                }
 
-               /* only permit direct mapping if the BDIs are all the same
-                * - copy-mapping is still permitted
-                */
-               if (concat->mtd.backing_dev_info !=
-                   subdev[i]->backing_dev_info)
-                       concat->mtd.backing_dev_info =
-                               &default_backing_dev_info;
-
                concat->mtd.size += subdev[i]->size;
                concat->mtd.ecc_stats.badblocks +=
                        subdev[i]->ecc_stats.badblocks;
index 4c611871d7e6b40aee79bdc90b2fbfc39506c45c..ff38a1df22f71dc84209550c1c6fdf3ce776e02d 100644 (file)
 
 #include "mtdcore.h"
 
-/*
- * backing device capabilities for non-mappable devices (such as NAND flash)
- * - permits private mappings, copies are taken of the data
- */
-static struct backing_dev_info mtd_bdi_unmappable = {
-       .capabilities   = BDI_CAP_MAP_COPY,
-};
-
-/*
- * backing device capabilities for R/O mappable devices (such as ROM)
- * - permits private mappings, copies are taken of the data
- * - permits non-writable shared mappings
- */
-static struct backing_dev_info mtd_bdi_ro_mappable = {
-       .capabilities   = (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT |
-                          BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP),
-};
-
-/*
- * backing device capabilities for writable mappable devices (such as RAM)
- * - permits private mappings, copies are taken of the data
- * - permits non-writable shared mappings
- */
-static struct backing_dev_info mtd_bdi_rw_mappable = {
-       .capabilities   = (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT |
-                          BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP |
-                          BDI_CAP_WRITE_MAP),
+static struct backing_dev_info mtd_bdi = {
 };
 
 static int mtd_cls_suspend(struct device *dev, pm_message_t state);
@@ -365,6 +339,22 @@ static struct device_type mtd_devtype = {
        .release        = mtd_release,
 };
 
+#ifndef CONFIG_MMU
+unsigned mtd_mmap_capabilities(struct mtd_info *mtd)
+{
+       switch (mtd->type) {
+       case MTD_RAM:
+               return NOMMU_MAP_COPY | NOMMU_MAP_DIRECT | NOMMU_MAP_EXEC |
+                       NOMMU_MAP_READ | NOMMU_MAP_WRITE;
+       case MTD_ROM:
+               return NOMMU_MAP_COPY | NOMMU_MAP_DIRECT | NOMMU_MAP_EXEC |
+                       NOMMU_MAP_READ;
+       default:
+               return NOMMU_MAP_COPY;
+       }
+}
+#endif
+
 /**
  *     add_mtd_device - register an MTD device
  *     @mtd: pointer to new MTD device info structure
@@ -380,19 +370,7 @@ int add_mtd_device(struct mtd_info *mtd)
        struct mtd_notifier *not;
        int i, error;
 
-       if (!mtd->backing_dev_info) {
-               switch (mtd->type) {
-               case MTD_RAM:
-                       mtd->backing_dev_info = &mtd_bdi_rw_mappable;
-                       break;
-               case MTD_ROM:
-                       mtd->backing_dev_info = &mtd_bdi_ro_mappable;
-                       break;
-               default:
-                       mtd->backing_dev_info = &mtd_bdi_unmappable;
-                       break;
-               }
-       }
+       mtd->backing_dev_info = &mtd_bdi;
 
        BUG_ON(mtd->writesize == 0);
        mutex_lock(&mtd_table_mutex);
@@ -1237,17 +1215,9 @@ static int __init init_mtd(void)
        if (ret)
                goto err_reg;
 
-       ret = mtd_bdi_init(&mtd_bdi_unmappable, "mtd-unmap");
-       if (ret)
-               goto err_bdi1;
-
-       ret = mtd_bdi_init(&mtd_bdi_ro_mappable, "mtd-romap");
-       if (ret)
-               goto err_bdi2;
-
-       ret = mtd_bdi_init(&mtd_bdi_rw_mappable, "mtd-rwmap");
+       ret = mtd_bdi_init(&mtd_bdi, "mtd");
        if (ret)
-               goto err_bdi3;
+               goto err_bdi;
 
        proc_mtd = proc_create("mtd", 0, NULL, &mtd_proc_ops);
 
@@ -1260,11 +1230,7 @@ static int __init init_mtd(void)
 out_procfs:
        if (proc_mtd)
                remove_proc_entry("mtd", NULL);
-err_bdi3:
-       bdi_destroy(&mtd_bdi_ro_mappable);
-err_bdi2:
-       bdi_destroy(&mtd_bdi_unmappable);
-err_bdi1:
+err_bdi:
        class_unregister(&mtd_class);
 err_reg:
        pr_err("Error registering mtd class or bdi: %d\n", ret);
@@ -1277,9 +1243,7 @@ static void __exit cleanup_mtd(void)
        if (proc_mtd)
                remove_proc_entry("mtd", NULL);
        class_unregister(&mtd_class);
-       bdi_destroy(&mtd_bdi_unmappable);
-       bdi_destroy(&mtd_bdi_ro_mappable);
-       bdi_destroy(&mtd_bdi_rw_mappable);
+       bdi_destroy(&mtd_bdi);
 }
 
 module_init(init_mtd);
index a3e3a7d074d5c7b246aed2bebdd2ed25feba16f9..e779de315ade505f1a508edefc541f7a4223af97 100644 (file)
@@ -378,7 +378,6 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
 
        slave->mtd.name = name;
        slave->mtd.owner = master->owner;
-       slave->mtd.backing_dev_info = master->backing_dev_info;
 
        /* NOTE:  we don't arrange MTDs as a tree; it'd be error-prone
         * to have the same data be in two different partitions.
index a3367bfb1456a39c9c678bc7877e1e93f4531783..d5b149c5542d2e004330e21052c0c6e289cf2b3c 100644 (file)
@@ -987,7 +987,7 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt)
        if (err)
                goto out_free;
        lsi->lsi_flags |= LSI_BDI_INITIALIZED;
-       lsi->lsi_bdi.capabilities = BDI_CAP_MAP_COPY;
+       lsi->lsi_bdi.capabilities = 0;
        err = ll_bdi_register(&lsi->lsi_bdi);
        if (err)
                goto out_free;
index 6894b085f0ee0fed7a58fd7f6c0b3d110154e18d..620d93489539837b5a00b6ad723e22f68dcd329b 100644 (file)
@@ -335,7 +335,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
        }
        init_rwsem(&v9ses->rename_sem);
 
-       rc = bdi_setup_and_register(&v9ses->bdi, "9p", BDI_CAP_MAP_COPY);
+       rc = bdi_setup_and_register(&v9ses->bdi, "9p");
        if (rc) {
                kfree(v9ses->aname);
                kfree(v9ses->uname);
index 2b607257820c8ed7b383e486f3a7870052974ae4..d142a2449e65a9962437ce38918b0b47d9124e58 100644 (file)
@@ -106,7 +106,7 @@ struct afs_volume *afs_volume_lookup(struct afs_mount_params *params)
        volume->cell            = params->cell;
        volume->vid             = vlocation->vldb.vid[params->type];
 
-       ret = bdi_setup_and_register(&volume->bdi, "afs", BDI_CAP_MAP_COPY);
+       ret = bdi_setup_and_register(&volume->bdi, "afs");
        if (ret)
                goto error_bdi;
 
index 1b7893ecc29654f6d20cf420b24ee20dddbf9038..6f13d3fab07f1a0fc003af156b3df658571e10ff 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -165,15 +165,6 @@ static struct vfsmount *aio_mnt;
 static const struct file_operations aio_ring_fops;
 static const struct address_space_operations aio_ctx_aops;
 
-/* Backing dev info for aio fs.
- * -no dirty page accounting or writeback happens
- */
-static struct backing_dev_info aio_fs_backing_dev_info = {
-       .name           = "aiofs",
-       .state          = 0,
-       .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK | BDI_CAP_MAP_COPY,
-};
-
 static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages)
 {
        struct qstr this = QSTR_INIT("[aio]", 5);
@@ -185,7 +176,7 @@ static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages)
 
        inode->i_mapping->a_ops = &aio_ctx_aops;
        inode->i_mapping->private_data = ctx;
-       inode->i_mapping->backing_dev_info = &aio_fs_backing_dev_info;
+       inode->i_mapping->backing_dev_info = &noop_backing_dev_info;
        inode->i_size = PAGE_SIZE * nr_pages;
 
        path.dentry = d_alloc_pseudo(aio_mnt->mnt_sb, &this);
@@ -230,9 +221,6 @@ static int __init aio_setup(void)
        if (IS_ERR(aio_mnt))
                panic("Failed to create aio fs mount.");
 
-       if (bdi_init(&aio_fs_backing_dev_info))
-               panic("Failed to init aio fs backing dev info.");
-
        kiocb_cachep = KMEM_CACHE(kiocb, SLAB_HWCACHE_ALIGN|SLAB_PANIC);
        kioctx_cachep = KMEM_CACHE(kioctx,SLAB_HWCACHE_ALIGN|SLAB_PANIC);
 
index 8c63419a7f70de04d2e5fd1a51a3a0e334513918..afc4092989cd4f936a5c18668680c34362cb3f72 100644 (file)
@@ -1715,8 +1715,7 @@ static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi)
 {
        int err;
 
-       bdi->capabilities = BDI_CAP_MAP_COPY;
-       err = bdi_setup_and_register(bdi, "btrfs", BDI_CAP_MAP_COPY);
+       err = bdi_setup_and_register(bdi, "btrfs");
        if (err)
                return err;
 
index 67b2007f10fe65986a05d3af07e3b2b99ded7c61..ea06a3d0364cc218d5dad4885023d1829f28f214 100644 (file)
 
 #include "internal.h"
 
-/*
- * capabilities for /dev/mem, /dev/kmem and similar directly mappable character
- * devices
- * - permits shared-mmap for read, write and/or exec
- * - does not permit private mmap in NOMMU mode (can't do COW)
- * - no readahead or I/O queue unplugging required
- */
-struct backing_dev_info directly_mappable_cdev_bdi = {
-       .name = "char",
-       .capabilities   = (
-#ifdef CONFIG_MMU
-               /* permit private copies of the data to be taken */
-               BDI_CAP_MAP_COPY |
-#endif
-               /* permit direct mmap, for read, write or exec */
-               BDI_CAP_MAP_DIRECT |
-               BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP |
-               /* no writeback happens */
-               BDI_CAP_NO_ACCT_AND_WRITEBACK),
-};
-
 static struct kobj_map *cdev_map;
 
 static DEFINE_MUTEX(chrdevs_lock);
@@ -575,8 +554,6 @@ static struct kobject *base_probe(dev_t dev, int *part, void *data)
 void __init chrdev_init(void)
 {
        cdev_map = kobj_map_init(base_probe, &chrdevs_lock);
-       if (bdi_init(&directly_mappable_cdev_bdi))
-               panic("Failed to init directly mappable cdev bdi");
 }
 
 
@@ -590,4 +567,3 @@ EXPORT_SYMBOL(cdev_del);
 EXPORT_SYMBOL(cdev_add);
 EXPORT_SYMBOL(__register_chrdev);
 EXPORT_SYMBOL(__unregister_chrdev);
-EXPORT_SYMBOL(directly_mappable_cdev_bdi);
index 2a772da16b839fe124d12db9256b74d95f37c97a..d3aa999ab78520fcd4819f99548247e231df591b 100644 (file)
@@ -3446,7 +3446,7 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
        int referral_walks_count = 0;
 #endif
 
-       rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);
+       rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs");
        if (rc)
                return rc;
 
index b945410bfcd58d7b5469bf120c38e54c6b250fa2..82ec68b59208282f49ece9fb06e0fdb5135c3749 100644 (file)
@@ -183,7 +183,7 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
                goto unlock_out;
        }
 
-       error = bdi_setup_and_register(&vc->bdi, "coda", BDI_CAP_MAP_COPY);
+       error = bdi_setup_and_register(&vc->bdi, "coda");
        if (error)
                goto unlock_out;
 
index bd4a3c167091346b951cc5b86c1911f7372c920d..a315677e44d34d8501b1b03629da0201283f5b1f 100644 (file)
@@ -70,8 +70,6 @@ extern int configfs_is_root(struct config_item *item);
 
 extern struct inode * configfs_new_inode(umode_t mode, struct configfs_dirent *, struct super_block *);
 extern int configfs_create(struct dentry *, umode_t mode, int (*init)(struct inode *));
-extern int configfs_inode_init(void);
-extern void configfs_inode_exit(void);
 
 extern int configfs_create_file(struct config_item *, const struct configfs_attribute *);
 extern int configfs_make_dirent(struct configfs_dirent *,
index 5946ad98053fa0f2133f5baf51aa9951005513a8..0ad6b4d6de00125b0222c81a33de720271fc504b 100644 (file)
@@ -50,12 +50,6 @@ static const struct address_space_operations configfs_aops = {
        .write_end      = simple_write_end,
 };
 
-static struct backing_dev_info configfs_backing_dev_info = {
-       .name           = "configfs",
-       .ra_pages       = 0,    /* No readahead */
-       .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK,
-};
-
 static const struct inode_operations configfs_inode_operations ={
        .setattr        = configfs_setattr,
 };
@@ -137,7 +131,7 @@ struct inode *configfs_new_inode(umode_t mode, struct configfs_dirent *sd,
        if (inode) {
                inode->i_ino = get_next_ino();
                inode->i_mapping->a_ops = &configfs_aops;
-               inode->i_mapping->backing_dev_info = &configfs_backing_dev_info;
+               inode->i_mapping->backing_dev_info = &noop_backing_dev_info;
                inode->i_op = &configfs_inode_operations;
 
                if (sd->s_iattr) {
@@ -283,13 +277,3 @@ void configfs_hash_and_remove(struct dentry * dir, const char * name)
        }
        mutex_unlock(&dir->d_inode->i_mutex);
 }
-
-int __init configfs_inode_init(void)
-{
-       return bdi_init(&configfs_backing_dev_info);
-}
-
-void configfs_inode_exit(void)
-{
-       bdi_destroy(&configfs_backing_dev_info);
-}
index f6c285833390164ba358d8d9e6fd20e10838a56e..da94e41bdbf685b02b567e95e3c0f37db33c2795 100644 (file)
@@ -145,19 +145,13 @@ static int __init configfs_init(void)
        if (!config_kobj)
                goto out2;
 
-       err = configfs_inode_init();
-       if (err)
-               goto out3;
-
        err = register_filesystem(&configfs_fs_type);
        if (err)
-               goto out4;
+               goto out3;
 
        return 0;
-out4:
-       pr_err("Unable to register filesystem!\n");
-       configfs_inode_exit();
 out3:
+       pr_err("Unable to register filesystem!\n");
        kobject_put(config_kobj);
 out2:
        kmem_cache_destroy(configfs_dir_cachep);
@@ -172,7 +166,6 @@ static void __exit configfs_exit(void)
        kobject_put(config_kobj);
        kmem_cache_destroy(configfs_dir_cachep);
        configfs_dir_cachep = NULL;
-       configfs_inode_exit();
 }
 
 MODULE_AUTHOR("Oracle");
index d9eb84bda5591a36c68c6519faf591daf7a05efa..1895d60f4122c21d0e2ee267066c6308473ba642 100644 (file)
@@ -520,7 +520,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
                goto out;
        }
 
-       rc = bdi_setup_and_register(&sbi->bdi, "ecryptfs", BDI_CAP_MAP_COPY);
+       rc = bdi_setup_and_register(&sbi->bdi, "ecryptfs");
        if (rc)
                goto out1;
 
index 95965503afcbe5d0ce8abbd3792e8be50e0a9123..fcc2e565f540c3d126997c181ee7c03340b075f3 100644 (file)
@@ -836,7 +836,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
                goto free_sbi;
        }
 
-       ret = bdi_setup_and_register(&sbi->bdi, "exofs", BDI_CAP_MAP_COPY);
+       ret = bdi_setup_and_register(&sbi->bdi, "exofs");
        if (ret) {
                EXOFS_DBGMSG("Failed to bdi_setup_and_register\n");
                dput(sb->s_root);
index e31e589369a49a930f45be2124114c7252c83723..a699a3fc62c07ac248b1988b3ed3228fc938ec0b 100644 (file)
@@ -560,7 +560,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
        server = NCP_SBP(sb);
        memset(server, 0, sizeof(*server));
 
-       error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY);
+       error = bdi_setup_and_register(&server->bdi, "ncpfs");
        if (error)
                goto out_fput;
 
index bbafbde3471a65b0f0f509b0ba5ccc48dd1d2718..f6ab41b39612bd4cd04bd49921095443e54150e3 100644 (file)
@@ -34,7 +34,14 @@ static unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
                                                   unsigned long flags);
 static int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma);
 
+static unsigned ramfs_mmap_capabilities(struct file *file)
+{
+       return NOMMU_MAP_DIRECT | NOMMU_MAP_COPY | NOMMU_MAP_READ |
+               NOMMU_MAP_WRITE | NOMMU_MAP_EXEC;
+}
+
 const struct file_operations ramfs_file_operations = {
+       .mmap_capabilities      = ramfs_mmap_capabilities,
        .mmap                   = ramfs_nommu_mmap,
        .get_unmapped_area      = ramfs_nommu_get_unmapped_area,
        .read                   = new_sync_read,
index d365b1c4eb3cbe469965ba4a0e93d63a57124cc7..ad4d712002f4fda48897089f37c4c70d839c883d 100644 (file)
@@ -50,14 +50,6 @@ static const struct address_space_operations ramfs_aops = {
        .set_page_dirty = __set_page_dirty_no_writeback,
 };
 
-static struct backing_dev_info ramfs_backing_dev_info = {
-       .name           = "ramfs",
-       .ra_pages       = 0,    /* No readahead */
-       .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK |
-                         BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY |
-                         BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP,
-};
-
 struct inode *ramfs_get_inode(struct super_block *sb,
                                const struct inode *dir, umode_t mode, dev_t dev)
 {
@@ -67,7 +59,7 @@ struct inode *ramfs_get_inode(struct super_block *sb,
                inode->i_ino = get_next_ino();
                inode_init_owner(inode, dir, mode);
                inode->i_mapping->a_ops = &ramfs_aops;
-               inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
+               inode->i_mapping->backing_dev_info = &noop_backing_dev_info;
                mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER);
                mapping_set_unevictable(inode->i_mapping);
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
@@ -267,19 +259,9 @@ static struct file_system_type ramfs_fs_type = {
 int __init init_ramfs_fs(void)
 {
        static unsigned long once;
-       int err;
 
        if (test_and_set_bit(0, &once))
                return 0;
-
-       err = bdi_init(&ramfs_backing_dev_info);
-       if (err)
-               return err;
-
-       err = register_filesystem(&ramfs_fs_type);
-       if (err)
-               bdi_destroy(&ramfs_backing_dev_info);
-
-       return err;
+       return register_filesystem(&ramfs_fs_type);
 }
 fs_initcall(init_ramfs_fs);
index ea06c7554860d7ada89db9ba0a8838e17b40d3fc..7da9e2153953eb31399bf3909a9ef881328ddf90 100644 (file)
@@ -70,6 +70,15 @@ static int romfs_mmap(struct file *file, struct vm_area_struct *vma)
        return vma->vm_flags & (VM_SHARED | VM_MAYSHARE) ? 0 : -ENOSYS;
 }
 
+static unsigned romfs_mmap_capabilities(struct file *file)
+{
+       struct mtd_info *mtd = file_inode(file)->i_sb->s_mtd;
+
+       if (!mtd)
+               return NOMMU_MAP_COPY;
+       return mtd_mmap_capabilities(mtd);
+}
+
 const struct file_operations romfs_ro_fops = {
        .llseek                 = generic_file_llseek,
        .read                   = new_sync_read,
@@ -77,4 +86,5 @@ const struct file_operations romfs_ro_fops = {
        .splice_read            = generic_file_splice_read,
        .mmap                   = romfs_mmap,
        .get_unmapped_area      = romfs_get_unmapped_area,
+       .mmap_capabilities      = romfs_mmap_capabilities,
 };
index 106bf20629ce6d01128b75680936082bdc0be83a..ed93dc6ae245c43caf685f572c22cc13b22646af 100644 (file)
@@ -2017,7 +2017,7 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
         * Read-ahead will be disabled because @c->bdi.ra_pages is 0.
         */
        c->bdi.name = "ubifs",
-       c->bdi.capabilities = BDI_CAP_MAP_COPY;
+       c->bdi.capabilities = 0;
        err  = bdi_init(&c->bdi);
        if (err)
                goto out_close;
index e936cea856dc5ecaf8bc049253413da97184e40a..478f95d92d73be43967aeef9d8f3c859016bf972 100644 (file)
@@ -114,7 +114,7 @@ int bdi_register(struct backing_dev_info *bdi, struct device *parent,
                const char *fmt, ...);
 int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev);
 void bdi_unregister(struct backing_dev_info *bdi);
-int __must_check bdi_setup_and_register(struct backing_dev_info *, char *, unsigned int);
+int __must_check bdi_setup_and_register(struct backing_dev_info *, char *);
 void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages,
                        enum wb_reason reason);
 void bdi_start_background_writeback(struct backing_dev_info *bdi);
@@ -228,42 +228,17 @@ int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio);
  * BDI_CAP_NO_ACCT_DIRTY:  Dirty pages shouldn't contribute to accounting
  * BDI_CAP_NO_WRITEBACK:   Don't write pages back
  * BDI_CAP_NO_ACCT_WB:     Don't automatically account writeback pages
- *
- * These flags let !MMU mmap() govern direct device mapping vs immediate
- * copying more easily for MAP_PRIVATE, especially for ROM filesystems.
- *
- * BDI_CAP_MAP_COPY:       Copy can be mapped (MAP_PRIVATE)
- * BDI_CAP_MAP_DIRECT:     Can be mapped directly (MAP_SHARED)
- * BDI_CAP_READ_MAP:       Can be mapped for reading
- * BDI_CAP_WRITE_MAP:      Can be mapped for writing
- * BDI_CAP_EXEC_MAP:       Can be mapped for execution
- *
  * BDI_CAP_STRICTLIMIT:    Keep number of dirty pages below bdi threshold.
  */
 #define BDI_CAP_NO_ACCT_DIRTY  0x00000001
 #define BDI_CAP_NO_WRITEBACK   0x00000002
-#define BDI_CAP_MAP_COPY       0x00000004
-#define BDI_CAP_MAP_DIRECT     0x00000008
-#define BDI_CAP_READ_MAP       0x00000010
-#define BDI_CAP_WRITE_MAP      0x00000020
-#define BDI_CAP_EXEC_MAP       0x00000040
-#define BDI_CAP_NO_ACCT_WB     0x00000080
-#define BDI_CAP_STABLE_WRITES  0x00000200
-#define BDI_CAP_STRICTLIMIT    0x00000400
-
-#define BDI_CAP_VMFLAGS \
-       (BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP)
+#define BDI_CAP_NO_ACCT_WB     0x00000004
+#define BDI_CAP_STABLE_WRITES  0x00000008
+#define BDI_CAP_STRICTLIMIT    0x00000010
 
 #define BDI_CAP_NO_ACCT_AND_WRITEBACK \
        (BDI_CAP_NO_WRITEBACK | BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_ACCT_WB)
 
-#if defined(VM_MAYREAD) && \
-       (BDI_CAP_READ_MAP != VM_MAYREAD || \
-        BDI_CAP_WRITE_MAP != VM_MAYWRITE || \
-        BDI_CAP_EXEC_MAP != VM_MAYEXEC)
-#error please change backing_dev_info::capabilities flags
-#endif
-
 extern struct backing_dev_info default_backing_dev_info;
 extern struct backing_dev_info noop_backing_dev_info;
 
index fb4591977b039a80587fa79d899c2f86d632657b..f8763615a5f2dc87073cbaa49e64a9e6a1ebe5e4 100644 (file)
@@ -30,6 +30,4 @@ void cdev_del(struct cdev *);
 
 void cd_forget(struct inode *);
 
-extern struct backing_dev_info directly_mappable_cdev_bdi;
-
 #endif
index 42efe13077b6c1b8dd139c6cea7a241e5d6b320d..1dada399aa2310f427d25373b3a16d4559a1e189 100644 (file)
@@ -1502,6 +1502,26 @@ struct block_device_operations;
 #define HAVE_COMPAT_IOCTL 1
 #define HAVE_UNLOCKED_IOCTL 1
 
+/*
+ * These flags let !MMU mmap() govern direct device mapping vs immediate
+ * copying more easily for MAP_PRIVATE, especially for ROM filesystems.
+ *
+ * NOMMU_MAP_COPY:     Copy can be mapped (MAP_PRIVATE)
+ * NOMMU_MAP_DIRECT:   Can be mapped directly (MAP_SHARED)
+ * NOMMU_MAP_READ:     Can be mapped for reading
+ * NOMMU_MAP_WRITE:    Can be mapped for writing
+ * NOMMU_MAP_EXEC:     Can be mapped for execution
+ */
+#define NOMMU_MAP_COPY         0x00000001
+#define NOMMU_MAP_DIRECT       0x00000008
+#define NOMMU_MAP_READ         VM_MAYREAD
+#define NOMMU_MAP_WRITE                VM_MAYWRITE
+#define NOMMU_MAP_EXEC         VM_MAYEXEC
+
+#define NOMMU_VMFLAGS \
+       (NOMMU_MAP_READ | NOMMU_MAP_WRITE | NOMMU_MAP_EXEC)
+
+
 struct iov_iter;
 
 struct file_operations {
@@ -1536,6 +1556,9 @@ struct file_operations {
        long (*fallocate)(struct file *file, int mode, loff_t offset,
                          loff_t len);
        void (*show_fdinfo)(struct seq_file *m, struct file *f);
+#ifndef CONFIG_MMU
+       unsigned (*mmap_capabilities)(struct file *);
+#endif
 };
 
 struct inode_operations {
index 031ff3a9a0bdff8a71a64538ba02568681e1ee12..3301c4c289d625987efb33e6471a70ce4987ff2e 100644 (file)
@@ -408,4 +408,6 @@ static inline int mtd_is_bitflip_or_eccerr(int err) {
        return mtd_is_bitflip(err) || mtd_is_eccerr(err);
 }
 
+unsigned mtd_mmap_capabilities(struct mtd_info *mtd);
+
 #endif /* __MTD_MTD_H__ */
index 0ae0df55000bb0cac674159a20ca90345ce0c44c..16c68958aedadb3ec6f312527505a8f323047bf0 100644 (file)
@@ -17,8 +17,6 @@ static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0);
 struct backing_dev_info default_backing_dev_info = {
        .name           = "default",
        .ra_pages       = VM_MAX_READAHEAD * 1024 / PAGE_CACHE_SIZE,
-       .state          = 0,
-       .capabilities   = BDI_CAP_MAP_COPY,
 };
 EXPORT_SYMBOL_GPL(default_backing_dev_info);
 
@@ -513,13 +511,12 @@ EXPORT_SYMBOL(bdi_destroy);
  * For use from filesystems to quickly init and register a bdi associated
  * with dirty writeback
  */
-int bdi_setup_and_register(struct backing_dev_info *bdi, char *name,
-                          unsigned int cap)
+int bdi_setup_and_register(struct backing_dev_info *bdi, char *name)
 {
        int err;
 
        bdi->name = name;
-       bdi->capabilities = cap;
+       bdi->capabilities = 0;
        err = bdi_init(bdi);
        if (err)
                return err;
index b51eadf6d9528fa69ea80ad6d1c994763656e8da..13af96f35a4b9cafffdb9a7d42effbb36aba0451 100644 (file)
@@ -946,9 +946,6 @@ static int validate_mmap_request(struct file *file,
                return -EOVERFLOW;
 
        if (file) {
-               /* validate file mapping requests */
-               struct address_space *mapping;
-
                /* files must support mmap */
                if (!file->f_op->mmap)
                        return -ENODEV;
@@ -957,28 +954,22 @@ static int validate_mmap_request(struct file *file,
                 * - we support chardevs that provide their own "memory"
                 * - we support files/blockdevs that are memory backed
                 */
-               mapping = file->f_mapping;
-               if (!mapping)
-                       mapping = file_inode(file)->i_mapping;
-
-               capabilities = 0;
-               if (mapping && mapping->backing_dev_info)
-                       capabilities = mapping->backing_dev_info->capabilities;
-
-               if (!capabilities) {
+               if (file->f_op->mmap_capabilities) {
+                       capabilities = file->f_op->mmap_capabilities(file);
+               } else {
                        /* no explicit capabilities set, so assume some
                         * defaults */
                        switch (file_inode(file)->i_mode & S_IFMT) {
                        case S_IFREG:
                        case S_IFBLK:
-                               capabilities = BDI_CAP_MAP_COPY;
+                               capabilities = NOMMU_MAP_COPY;
                                break;
 
                        case S_IFCHR:
                                capabilities =
-                                       BDI_CAP_MAP_DIRECT |
-                                       BDI_CAP_READ_MAP |
-                                       BDI_CAP_WRITE_MAP;
+                                       NOMMU_MAP_DIRECT |
+                                       NOMMU_MAP_READ |
+                                       NOMMU_MAP_WRITE;
                                break;
 
                        default:
@@ -989,9 +980,9 @@ static int validate_mmap_request(struct file *file,
                /* eliminate any capabilities that we can't support on this
                 * device */
                if (!file->f_op->get_unmapped_area)
-                       capabilities &= ~BDI_CAP_MAP_DIRECT;
+                       capabilities &= ~NOMMU_MAP_DIRECT;
                if (!file->f_op->read)
-                       capabilities &= ~BDI_CAP_MAP_COPY;
+                       capabilities &= ~NOMMU_MAP_COPY;
 
                /* The file shall have been opened with read permission. */
                if (!(file->f_mode & FMODE_READ))
@@ -1010,29 +1001,29 @@ static int validate_mmap_request(struct file *file,
                        if (locks_verify_locked(file))
                                return -EAGAIN;
 
-                       if (!(capabilities & BDI_CAP_MAP_DIRECT))
+                       if (!(capabilities & NOMMU_MAP_DIRECT))
                                return -ENODEV;
 
                        /* we mustn't privatise shared mappings */
-                       capabilities &= ~BDI_CAP_MAP_COPY;
+                       capabilities &= ~NOMMU_MAP_COPY;
                } else {
                        /* we're going to read the file into private memory we
                         * allocate */
-                       if (!(capabilities & BDI_CAP_MAP_COPY))
+                       if (!(capabilities & NOMMU_MAP_COPY))
                                return -ENODEV;
 
                        /* we don't permit a private writable mapping to be
                         * shared with the backing device */
                        if (prot & PROT_WRITE)
-                               capabilities &= ~BDI_CAP_MAP_DIRECT;
+                               capabilities &= ~NOMMU_MAP_DIRECT;
                }
 
-               if (capabilities & BDI_CAP_MAP_DIRECT) {
-                       if (((prot & PROT_READ)  && !(capabilities & BDI_CAP_READ_MAP))  ||
-                           ((prot & PROT_WRITE) && !(capabilities & BDI_CAP_WRITE_MAP)) ||
-                           ((prot & PROT_EXEC)  && !(capabilities & BDI_CAP_EXEC_MAP))
+               if (capabilities & NOMMU_MAP_DIRECT) {
+                       if (((prot & PROT_READ)  && !(capabilities & NOMMU_MAP_READ))  ||
+                           ((prot & PROT_WRITE) && !(capabilities & NOMMU_MAP_WRITE)) ||
+                           ((prot & PROT_EXEC)  && !(capabilities & NOMMU_MAP_EXEC))
                            ) {
-                               capabilities &= ~BDI_CAP_MAP_DIRECT;
+                               capabilities &= ~NOMMU_MAP_DIRECT;
                                if (flags & MAP_SHARED) {
                                        printk(KERN_WARNING
                                               "MAP_SHARED not completely supported on !MMU\n");
@@ -1049,21 +1040,21 @@ static int validate_mmap_request(struct file *file,
                } else if ((prot & PROT_READ) && !(prot & PROT_EXEC)) {
                        /* handle implication of PROT_EXEC by PROT_READ */
                        if (current->personality & READ_IMPLIES_EXEC) {
-                               if (capabilities & BDI_CAP_EXEC_MAP)
+                               if (capabilities & NOMMU_MAP_EXEC)
                                        prot |= PROT_EXEC;
                        }
                } else if ((prot & PROT_READ) &&
                         (prot & PROT_EXEC) &&
-                        !(capabilities & BDI_CAP_EXEC_MAP)
+                        !(capabilities & NOMMU_MAP_EXEC)
                         ) {
                        /* backing file is not executable, try to copy */
-                       capabilities &= ~BDI_CAP_MAP_DIRECT;
+                       capabilities &= ~NOMMU_MAP_DIRECT;
                }
        } else {
                /* anonymous mappings are always memory backed and can be
                 * privately mapped
                 */
-               capabilities = BDI_CAP_MAP_COPY;
+               capabilities = NOMMU_MAP_COPY;
 
                /* handle PROT_EXEC implication by PROT_READ */
                if ((prot & PROT_READ) &&
@@ -1095,7 +1086,7 @@ static unsigned long determine_vm_flags(struct file *file,
        vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags);
        /* vm_flags |= mm->def_flags; */
 
-       if (!(capabilities & BDI_CAP_MAP_DIRECT)) {
+       if (!(capabilities & NOMMU_MAP_DIRECT)) {
                /* attempt to share read-only copies of mapped file chunks */
                vm_flags |= VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
                if (file && !(prot & PROT_WRITE))
@@ -1104,7 +1095,7 @@ static unsigned long determine_vm_flags(struct file *file,
                /* overlay a shareable mapping on the backing device or inode
                 * if possible - used for chardevs, ramfs/tmpfs/shmfs and
                 * romfs/cramfs */
-               vm_flags |= VM_MAYSHARE | (capabilities & BDI_CAP_VMFLAGS);
+               vm_flags |= VM_MAYSHARE | (capabilities & NOMMU_VMFLAGS);
                if (flags & MAP_SHARED)
                        vm_flags |= VM_SHARED;
        }
@@ -1157,7 +1148,7 @@ static int do_mmap_private(struct vm_area_struct *vma,
         * shared mappings on devices or memory
         * - VM_MAYSHARE will be set if it may attempt to share
         */
-       if (capabilities & BDI_CAP_MAP_DIRECT) {
+       if (capabilities & NOMMU_MAP_DIRECT) {
                ret = vma->vm_file->f_op->mmap(vma->vm_file, vma);
                if (ret == 0) {
                        /* shouldn't return success if we're not sharing */
@@ -1346,7 +1337,7 @@ unsigned long do_mmap_pgoff(struct file *file,
                        if ((pregion->vm_pgoff != pgoff || rpglen != pglen) &&
                            !(pgoff >= pregion->vm_pgoff && pgend <= rpgend)) {
                                /* new mapping is not a subset of the region */
-                               if (!(capabilities & BDI_CAP_MAP_DIRECT))
+                               if (!(capabilities & NOMMU_MAP_DIRECT))
                                        goto sharing_violation;
                                continue;
                        }
@@ -1385,7 +1376,7 @@ unsigned long do_mmap_pgoff(struct file *file,
                 * - this is the hook for quasi-memory character devices to
                 *   tell us the location of a shared mapping
                 */
-               if (capabilities & BDI_CAP_MAP_DIRECT) {
+               if (capabilities & NOMMU_MAP_DIRECT) {
                        addr = file->f_op->get_unmapped_area(file, addr, len,
                                                             pgoff, flags);
                        if (IS_ERR_VALUE(addr)) {
@@ -1397,10 +1388,10 @@ unsigned long do_mmap_pgoff(struct file *file,
                                 * the mapping so we'll have to attempt to copy
                                 * it */
                                ret = -ENODEV;
-                               if (!(capabilities & BDI_CAP_MAP_COPY))
+                               if (!(capabilities & NOMMU_MAP_COPY))
                                        goto error_just_free;
 
-                               capabilities &= ~BDI_CAP_MAP_DIRECT;
+                               capabilities &= ~NOMMU_MAP_DIRECT;
                        } else {
                                vma->vm_start = region->vm_start = addr;
                                vma->vm_end = region->vm_end = addr + len;
@@ -1411,7 +1402,7 @@ unsigned long do_mmap_pgoff(struct file *file,
        vma->vm_region = region;
 
        /* set up the mapping
-        * - the region is filled in if BDI_CAP_MAP_DIRECT is still set
+        * - the region is filled in if NOMMU_MAP_DIRECT is still set
         */
        if (file && vma->vm_flags & VM_SHARED)
                ret = do_mmap_shared_file(vma);
index 18b35c63fc0c80cb3f0ce9dfc734f42c33efe98b..a0442b20f001b80f6cf567c8aad4e9a038e901d3 100644 (file)
@@ -726,16 +726,15 @@ static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
                return prot | PROT_EXEC;
        /*
         * ditto if it's not on noexec mount, except that on !MMU we need
-        * BDI_CAP_EXEC_MMAP (== VM_MAYEXEC) in this case
+        * NOMMU_MAP_EXEC (== VM_MAYEXEC) in this case
         */
        if (!(file->f_path.mnt->mnt_flags & MNT_NOEXEC)) {
 #ifndef CONFIG_MMU
-               unsigned long caps = 0;
-               struct address_space *mapping = file->f_mapping;
-               if (mapping && mapping->backing_dev_info)
-                       caps = mapping->backing_dev_info->capabilities;
-               if (!(caps & BDI_CAP_EXEC_MAP))
-                       return prot;
+               if (file->f_op->mmap_capabilities) {
+                       unsigned caps = file->f_op->mmap_capabilities(file);
+                       if (!(caps & NOMMU_MAP_EXEC))
+                               return prot;
+               }
 #endif
                return prot | PROT_EXEC;
        }