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 Original line 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.
           even if this was created by another process.


         - If possible, the file mapping will be directly on the backing device
         - 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
           appropriate mapping protection capabilities. Ramfs, romfs, cramfs
           and mtd might all permit this.
           and mtd might all permit this.


	 - If the backing device device can't or won't permit direct sharing,
	 - 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
           appropriate bit of the file will be read into a contiguous bit of
           memory and any extraneous space beyond the EOF will be cleared
           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
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
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
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
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
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
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
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.
copy mapped otherwise.


IMPORTANT NOTE:
IMPORTANT NOTE:
+1 −1
Original line number Original line 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 =
	q->backing_dev_info.ra_pages =
			(VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
			(VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
	q->backing_dev_info.state = 0;
	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->backing_dev_info.name = "block";
	q->node = node_id;
	q->node = node_id;


+32 −32
Original line number Original line Diff line number Diff line
@@ -287,13 +287,24 @@ static unsigned long get_unmapped_area_mem(struct file *file,
	return pgoff << PAGE_SHIFT;
	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 */
/* can't do an in-place private mapping if there's no MMU */
static inline int private_mapping_ok(struct vm_area_struct *vma)
static inline int private_mapping_ok(struct vm_area_struct *vma)
{
{
	return vma->vm_flags & VM_MAYSHARE;
	return vma->vm_flags & VM_MAYSHARE;
}
}
#else
#else
#define get_unmapped_area_mem	NULL


static inline int private_mapping_ok(struct vm_area_struct *vma)
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,
	.write		= write_mem,
	.mmap		= mmap_mem,
	.mmap		= mmap_mem,
	.open		= open_mem,
	.open		= open_mem,
#ifndef CONFIG_MMU
	.get_unmapped_area = get_unmapped_area_mem,
	.get_unmapped_area = get_unmapped_area_mem,
	.mmap_capabilities = memory_mmap_capabilities,
#endif
};
};


#ifdef CONFIG_DEVKMEM
#ifdef CONFIG_DEVKMEM
@@ -731,7 +745,10 @@ static const struct file_operations kmem_fops = {
	.write		= write_kmem,
	.write		= write_kmem,
	.mmap		= mmap_kmem,
	.mmap		= mmap_kmem,
	.open		= open_kmem,
	.open		= open_kmem,
#ifndef CONFIG_MMU
	.get_unmapped_area = get_unmapped_area_mem,
	.get_unmapped_area = get_unmapped_area_mem,
	.mmap_capabilities = memory_mmap_capabilities,
#endif
};
};
#endif
#endif


@@ -760,16 +777,9 @@ static const struct file_operations zero_fops = {
	.read_iter	= read_iter_zero,
	.read_iter	= read_iter_zero,
	.aio_write	= aio_write_zero,
	.aio_write	= aio_write_zero,
	.mmap		= mmap_zero,
	.mmap		= mmap_zero,
};
#ifndef CONFIG_MMU

	.mmap_capabilities = zero_mmap_capabilities,
/*
#endif
 * 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,
};
};


static const struct file_operations full_fops = {
static const struct file_operations full_fops = {
@@ -783,22 +793,22 @@ static const struct memdev {
	const char *name;
	const char *name;
	umode_t mode;
	umode_t mode;
	const struct file_operations *fops;
	const struct file_operations *fops;
	struct backing_dev_info *dev_info;
	fmode_t fmode;
} devlist[] = {
} devlist[] = {
	 [1] = { "mem", 0, &mem_fops, &directly_mappable_cdev_bdi },
	 [1] = { "mem", 0, &mem_fops, FMODE_UNSIGNED_OFFSET },
#ifdef CONFIG_DEVKMEM
#ifdef CONFIG_DEVKMEM
	 [2] = { "kmem", 0, &kmem_fops, &directly_mappable_cdev_bdi },
	 [2] = { "kmem", 0, &kmem_fops, FMODE_UNSIGNED_OFFSET },
#endif
#endif
	 [3] = { "null", 0666, &null_fops, NULL },
	 [3] = { "null", 0666, &null_fops, 0 },
#ifdef CONFIG_DEVPORT
#ifdef CONFIG_DEVPORT
	 [4] = { "port", 0, &port_fops, NULL },
	 [4] = { "port", 0, &port_fops, 0 },
#endif
#endif
	 [5] = { "zero", 0666, &zero_fops, &zero_bdi },
	 [5] = { "zero", 0666, &zero_fops, 0 },
	 [7] = { "full", 0666, &full_fops, NULL },
	 [7] = { "full", 0666, &full_fops, 0 },
	 [8] = { "random", 0666, &random_fops, NULL },
	 [8] = { "random", 0666, &random_fops, 0 },
	 [9] = { "urandom", 0666, &urandom_fops, NULL },
	 [9] = { "urandom", 0666, &urandom_fops, 0 },
#ifdef CONFIG_PRINTK
#ifdef CONFIG_PRINTK
	[11] = { "kmsg", 0644, &kmsg_fops, NULL },
	[11] = { "kmsg", 0644, &kmsg_fops, 0 },
#endif
#endif
};
};


@@ -816,12 +826,7 @@ static int memory_open(struct inode *inode, struct file *filp)
		return -ENXIO;
		return -ENXIO;


	filp->f_op = dev->fops;
	filp->f_op = dev->fops;
	if (dev->dev_info)
	filp->f_mode |= dev->fmode;
		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;


	if (dev->fops->open)
	if (dev->fops->open)
		return dev->fops->open(inode, filp);
		return dev->fops->open(inode, filp);
@@ -846,11 +851,6 @@ static struct class *mem_class;
static int __init chr_dev_init(void)
static int __init chr_dev_init(void)
{
{
	int minor;
	int minor;
	int err;

	err = bdi_init(&zero_bdi);
	if (err)
		return err;


	if (register_chrdev(MEM_MAJOR, "mem", &memory_fops))
	if (register_chrdev(MEM_MAJOR, "mem", &memory_fops))
		printk("unable to get major %d for memory devs\n", MEM_MAJOR);
		printk("unable to get major %d for memory devs\n", MEM_MAJOR);
+1 −3
Original line number Original line Diff line number Diff line
@@ -104,11 +104,9 @@ static int raw_release(struct inode *inode, struct file *filp)


	mutex_lock(&raw_mutex);
	mutex_lock(&raw_mutex);
	bdev = raw_devices[minor].binding;
	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  */
		/* Here  inode->i_mapping == bdev->bd_inode->i_mapping  */
		inode->i_mapping = &inode->i_data;
		inode->i_mapping = &inode->i_data;
		inode->i_mapping->backing_dev_info = &default_backing_dev_info;
	}
	mutex_unlock(&raw_mutex);
	mutex_unlock(&raw_mutex);


	blkdev_put(bdev, filp->f_mode | FMODE_EXCL);
	blkdev_put(bdev, filp->f_mode | FMODE_EXCL);
+10 −62
Original line number Original line Diff line number Diff line
@@ -49,7 +49,6 @@ static DEFINE_MUTEX(mtd_mutex);
 */
 */
struct mtd_file_info {
struct mtd_file_info {
	struct mtd_info *mtd;
	struct mtd_info *mtd;
	struct inode *ino;
	enum mtd_file_modes mode;
	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);
	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)
static int mtdchar_open(struct inode *inode, struct file *file)
{
{
	int minor = iminor(inode);
	int minor = iminor(inode);
@@ -70,7 +65,6 @@ static int mtdchar_open(struct inode *inode, struct file *file)
	int ret = 0;
	int ret = 0;
	struct mtd_info *mtd;
	struct mtd_info *mtd;
	struct mtd_file_info *mfi;
	struct mtd_file_info *mfi;
	struct inode *mtd_ino;


	pr_debug("MTD_open\n");
	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))
	if ((file->f_mode & FMODE_WRITE) && (minor & 1))
		return -EACCES;
		return -EACCES;


	ret = simple_pin_fs(&mtd_inodefs_type, &mnt, &count);
	if (ret)
		return ret;

	mutex_lock(&mtd_mutex);
	mutex_lock(&mtd_mutex);
	mtd = get_mtd_device(NULL, devnum);
	mtd = get_mtd_device(NULL, devnum);


@@ -95,43 +85,26 @@ static int mtdchar_open(struct inode *inode, struct file *file)
		goto out1;
		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 */
	/* You can't open it RW if it's not a writeable device */
	if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) {
	if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) {
		ret = -EACCES;
		ret = -EACCES;
		goto out2;
		goto out1;
	}
	}


	mfi = kzalloc(sizeof(*mfi), GFP_KERNEL);
	mfi = kzalloc(sizeof(*mfi), GFP_KERNEL);
	if (!mfi) {
	if (!mfi) {
		ret = -ENOMEM;
		ret = -ENOMEM;
		goto out2;
		goto out1;
	}
	}
	mfi->ino = mtd_ino;
	mfi->mtd = mtd;
	mfi->mtd = mtd;
	file->private_data = mfi;
	file->private_data = mfi;
	mutex_unlock(&mtd_mutex);
	mutex_unlock(&mtd_mutex);
	return 0;
	return 0;


out2:
	iput(mtd_ino);
out1:
out1:
	put_mtd_device(mtd);
	put_mtd_device(mtd);
out:
out:
	mutex_unlock(&mtd_mutex);
	mutex_unlock(&mtd_mutex);
	simple_release_fs(&mnt, &count);
	return ret;
	return ret;
} /* mtdchar_open */
} /* mtdchar_open */


@@ -148,12 +121,9 @@ static int mtdchar_close(struct inode *inode, struct file *file)
	if ((file->f_mode & FMODE_WRITE))
	if ((file->f_mode & FMODE_WRITE))
		mtd_sync(mtd);
		mtd_sync(mtd);


	iput(mfi->ino);

	put_mtd_device(mtd);
	put_mtd_device(mtd);
	file->private_data = NULL;
	file->private_data = NULL;
	kfree(mfi);
	kfree(mfi);
	simple_release_fs(&mnt, &count);


	return 0;
	return 0;
} /* mtdchar_close */
} /* 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);
	ret = mtd_get_unmapped_area(mtd, len, offset, flags);
	return ret == -EOPNOTSUPP ? -ENODEV : ret;
	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
#endif


/*
/*
@@ -1160,27 +1137,10 @@ static const struct file_operations mtd_fops = {
	.mmap		= mtdchar_mmap,
	.mmap		= mtdchar_mmap,
#ifndef CONFIG_MMU
#ifndef CONFIG_MMU
	.get_unmapped_area = mtdchar_get_unmapped_area,
	.get_unmapped_area = mtdchar_get_unmapped_area,
	.mmap_capabilities = mtdchar_mmap_capabilities,
#endif
#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 __init init_mtdchar(void)
{
{
	int ret;
	int ret;
@@ -1193,23 +1153,11 @@ int __init init_mtdchar(void)
		return ret;
		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;
	return ret;
}
}


void __exit cleanup_mtdchar(void)
void __exit cleanup_mtdchar(void)
{
{
	unregister_filesystem(&mtd_inodefs_type);
	__unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
	__unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
}
}


Loading