diff options
author | Dan Williams <dan.j.williams@intel.com> | 2015-11-30 13:20:29 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2016-01-09 09:30:49 -0500 |
commit | 5a023cdba50c5f5f2bc351783b3131699deb3937 (patch) | |
tree | bae047e7bf8fb28e48563b33afc2881c226f4e31 /block | |
parent | 4ebb16ca9a06a54cdb2e7f2ce1e506fa4d432445 (diff) |
block: enable dax for raw block devices
If an application wants exclusive access to all of the persistent memory
provided by an NVDIMM namespace it can use this raw-block-dax facility
to forgo establishing a filesystem. This capability is targeted
primarily to hypervisors wanting to provision persistent memory for
guests. It can be disabled / enabled dynamically via the new BLKDAXSET
ioctl.
Cc: Jeff Moyer <jmoyer@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
Reported-by: kbuild test robot <fengguang.wu@intel.com>
Reviewed-by: Jan Kara <jack@suse.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/ioctl.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/block/ioctl.c b/block/ioctl.c index 0918aed2d847..7a964d842913 100644 --- a/block/ioctl.c +++ b/block/ioctl.c | |||
@@ -406,6 +406,62 @@ static inline int is_unrecognized_ioctl(int ret) | |||
406 | ret == -ENOIOCTLCMD; | 406 | ret == -ENOIOCTLCMD; |
407 | } | 407 | } |
408 | 408 | ||
409 | #ifdef CONFIG_FS_DAX | ||
410 | bool blkdev_dax_capable(struct block_device *bdev) | ||
411 | { | ||
412 | struct gendisk *disk = bdev->bd_disk; | ||
413 | |||
414 | if (!disk->fops->direct_access) | ||
415 | return false; | ||
416 | |||
417 | /* | ||
418 | * If the partition is not aligned on a page boundary, we can't | ||
419 | * do dax I/O to it. | ||
420 | */ | ||
421 | if ((bdev->bd_part->start_sect % (PAGE_SIZE / 512)) | ||
422 | || (bdev->bd_part->nr_sects % (PAGE_SIZE / 512))) | ||
423 | return false; | ||
424 | |||
425 | return true; | ||
426 | } | ||
427 | |||
428 | static int blkdev_daxset(struct block_device *bdev, unsigned long argp) | ||
429 | { | ||
430 | unsigned long arg; | ||
431 | int rc = 0; | ||
432 | |||
433 | if (!capable(CAP_SYS_ADMIN)) | ||
434 | return -EACCES; | ||
435 | |||
436 | if (get_user(arg, (int __user *)(argp))) | ||
437 | return -EFAULT; | ||
438 | arg = !!arg; | ||
439 | if (arg == !!(bdev->bd_inode->i_flags & S_DAX)) | ||
440 | return 0; | ||
441 | |||
442 | if (arg) | ||
443 | arg = S_DAX; | ||
444 | |||
445 | if (arg && !blkdev_dax_capable(bdev)) | ||
446 | return -ENOTTY; | ||
447 | |||
448 | mutex_lock(&bdev->bd_inode->i_mutex); | ||
449 | if (bdev->bd_map_count == 0) | ||
450 | inode_set_flags(bdev->bd_inode, arg, S_DAX); | ||
451 | else | ||
452 | rc = -EBUSY; | ||
453 | mutex_unlock(&bdev->bd_inode->i_mutex); | ||
454 | return rc; | ||
455 | } | ||
456 | #else | ||
457 | static int blkdev_daxset(struct block_device *bdev, int arg) | ||
458 | { | ||
459 | if (arg) | ||
460 | return -ENOTTY; | ||
461 | return 0; | ||
462 | } | ||
463 | #endif | ||
464 | |||
409 | static int blkdev_flushbuf(struct block_device *bdev, fmode_t mode, | 465 | static int blkdev_flushbuf(struct block_device *bdev, fmode_t mode, |
410 | unsigned cmd, unsigned long arg) | 466 | unsigned cmd, unsigned long arg) |
411 | { | 467 | { |
@@ -568,6 +624,11 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, | |||
568 | case BLKTRACESETUP: | 624 | case BLKTRACESETUP: |
569 | case BLKTRACETEARDOWN: | 625 | case BLKTRACETEARDOWN: |
570 | return blk_trace_ioctl(bdev, cmd, argp); | 626 | return blk_trace_ioctl(bdev, cmd, argp); |
627 | case BLKDAXSET: | ||
628 | return blkdev_daxset(bdev, arg); | ||
629 | case BLKDAXGET: | ||
630 | return put_int(arg, !!(bdev->bd_inode->i_flags & S_DAX)); | ||
631 | break; | ||
571 | case IOC_PR_REGISTER: | 632 | case IOC_PR_REGISTER: |
572 | return blkdev_pr_register(bdev, argp); | 633 | return blkdev_pr_register(bdev, argp); |
573 | case IOC_PR_RESERVE: | 634 | case IOC_PR_RESERVE: |