Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6bec0035 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-3.20/bdi' of git://git.kernel.dk/linux-block

Pull backing device changes from Jens Axboe:
 "This contains a cleanup of how the backing device is handled, in
  preparation for a rework of the life time rules.  In this part, the
  most important change is to split the unrelated nommu mmap flags from
  it, but also removing a backing_dev_info pointer from the
  address_space (and inode), and a cleanup of other various minor bits.

  Christoph did all the work here, I just fixed an oops with pages that
  have a swap backing.  Arnd fixed a missing export, and Oleg killed the
  lustre backing_dev_info from staging.  Last patch was from Al,
  unexporting parts that are now no longer needed outside"

* 'for-3.20/bdi' of git://git.kernel.dk/linux-block:
  Make super_blocks and sb_lock static
  mtd: export new mtd_mmap_capabilities
  fs: make inode_to_bdi() handle NULL inode
  staging/lustre/llite: get rid of backing_dev_info
  fs: remove default_backing_dev_info
  fs: don't reassign dirty inodes to default_backing_dev_info
  nfs: don't call bdi_unregister
  ceph: remove call to bdi_unregister
  fs: remove mapping->backing_dev_info
  fs: export inode_to_bdi and use it in favor of mapping->backing_dev_info
  nilfs2: set up s_bdi like the generic mount_bdev code
  block_dev: get bdev inode bdi directly from the block device
  block_dev: only write bdev inode on close
  fs: introduce f_op->mmap_capabilities for nommu mmap support
  fs: kill BDI_CAP_SWAP_BACKED
  fs: deduplicate noop_backing_dev_info
parents 5d8e7fb6 15d0f5ea
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -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:
+1 −1
Original line number Diff line number Diff line
@@ -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;

+32 −32
Original line number Diff line number Diff line
@@ -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);
+1 −3
Original line number Diff line number Diff line
@@ -104,11 +104,9 @@ static int raw_release(struct inode *inode, struct file *filp)

	mutex_lock(&raw_mutex);
	bdev = raw_devices[minor].binding;
	if (--raw_devices[minor].inuse == 0) {
	if (--raw_devices[minor].inuse == 0)
		/* Here  inode->i_mapping == bdev->bd_inode->i_mapping  */
		inode->i_mapping = &inode->i_data;
		inode->i_mapping->backing_dev_info = &default_backing_dev_info;
	}
	mutex_unlock(&raw_mutex);

	blkdev_put(bdev, filp->f_mode | FMODE_EXCL);
+10 −62
Original line number Diff line number Diff line
@@ -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");
}

Loading