diff options
Diffstat (limited to 'fs/block_dev.c')
| -rw-r--r-- | fs/block_dev.c | 117 |
1 files changed, 35 insertions, 82 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 0d435c794d76..2a305c1a2d88 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 19 | #include <linux/blkpg.h> | 19 | #include <linux/blkpg.h> |
| 20 | #include <linux/magic.h> | 20 | #include <linux/magic.h> |
| 21 | #include <linux/dax.h> | ||
| 21 | #include <linux/buffer_head.h> | 22 | #include <linux/buffer_head.h> |
| 22 | #include <linux/swap.h> | 23 | #include <linux/swap.h> |
| 23 | #include <linux/pagevec.h> | 24 | #include <linux/pagevec.h> |
| @@ -716,50 +717,18 @@ int bdev_write_page(struct block_device *bdev, sector_t sector, | |||
| 716 | } | 717 | } |
| 717 | EXPORT_SYMBOL_GPL(bdev_write_page); | 718 | EXPORT_SYMBOL_GPL(bdev_write_page); |
| 718 | 719 | ||
| 719 | /** | 720 | int bdev_dax_pgoff(struct block_device *bdev, sector_t sector, size_t size, |
| 720 | * bdev_direct_access() - Get the address for directly-accessibly memory | 721 | pgoff_t *pgoff) |
| 721 | * @bdev: The device containing the memory | ||
| 722 | * @dax: control and output parameters for ->direct_access | ||
| 723 | * | ||
| 724 | * If a block device is made up of directly addressable memory, this function | ||
| 725 | * will tell the caller the PFN and the address of the memory. The address | ||
| 726 | * may be directly dereferenced within the kernel without the need to call | ||
| 727 | * ioremap(), kmap() or similar. The PFN is suitable for inserting into | ||
| 728 | * page tables. | ||
| 729 | * | ||
| 730 | * Return: negative errno if an error occurs, otherwise the number of bytes | ||
| 731 | * accessible at this address. | ||
| 732 | */ | ||
| 733 | long bdev_direct_access(struct block_device *bdev, struct blk_dax_ctl *dax) | ||
| 734 | { | 722 | { |
| 735 | sector_t sector = dax->sector; | 723 | phys_addr_t phys_off = (get_start_sect(bdev) + sector) * 512; |
| 736 | long avail, size = dax->size; | ||
| 737 | const struct block_device_operations *ops = bdev->bd_disk->fops; | ||
| 738 | 724 | ||
| 739 | /* | 725 | if (pgoff) |
| 740 | * The device driver is allowed to sleep, in order to make the | 726 | *pgoff = PHYS_PFN(phys_off); |
| 741 | * memory directly accessible. | 727 | if (phys_off % PAGE_SIZE || size % PAGE_SIZE) |
| 742 | */ | ||
| 743 | might_sleep(); | ||
| 744 | |||
| 745 | if (size < 0) | ||
| 746 | return size; | ||
| 747 | if (!blk_queue_dax(bdev_get_queue(bdev)) || !ops->direct_access) | ||
| 748 | return -EOPNOTSUPP; | ||
| 749 | if ((sector + DIV_ROUND_UP(size, 512)) > | ||
| 750 | part_nr_sects_read(bdev->bd_part)) | ||
| 751 | return -ERANGE; | ||
| 752 | sector += get_start_sect(bdev); | ||
| 753 | if (sector % (PAGE_SIZE / 512)) | ||
| 754 | return -EINVAL; | 728 | return -EINVAL; |
| 755 | avail = ops->direct_access(bdev, sector, &dax->addr, &dax->pfn, size); | 729 | return 0; |
| 756 | if (!avail) | ||
| 757 | return -ERANGE; | ||
| 758 | if (avail > 0 && avail & ~PAGE_MASK) | ||
| 759 | return -ENXIO; | ||
| 760 | return min(avail, size); | ||
| 761 | } | 730 | } |
| 762 | EXPORT_SYMBOL_GPL(bdev_direct_access); | 731 | EXPORT_SYMBOL(bdev_dax_pgoff); |
| 763 | 732 | ||
| 764 | /** | 733 | /** |
| 765 | * bdev_dax_supported() - Check if the device supports dax for filesystem | 734 | * bdev_dax_supported() - Check if the device supports dax for filesystem |
| @@ -773,62 +742,46 @@ EXPORT_SYMBOL_GPL(bdev_direct_access); | |||
| 773 | */ | 742 | */ |
| 774 | int bdev_dax_supported(struct super_block *sb, int blocksize) | 743 | int bdev_dax_supported(struct super_block *sb, int blocksize) |
| 775 | { | 744 | { |
| 776 | struct blk_dax_ctl dax = { | 745 | struct block_device *bdev = sb->s_bdev; |
| 777 | .sector = 0, | 746 | struct dax_device *dax_dev; |
| 778 | .size = PAGE_SIZE, | 747 | pgoff_t pgoff; |
| 779 | }; | 748 | int err, id; |
| 780 | int err; | 749 | void *kaddr; |
| 750 | pfn_t pfn; | ||
| 751 | long len; | ||
| 781 | 752 | ||
| 782 | if (blocksize != PAGE_SIZE) { | 753 | if (blocksize != PAGE_SIZE) { |
| 783 | vfs_msg(sb, KERN_ERR, "error: unsupported blocksize for dax"); | 754 | vfs_msg(sb, KERN_ERR, "error: unsupported blocksize for dax"); |
| 784 | return -EINVAL; | 755 | return -EINVAL; |
| 785 | } | 756 | } |
| 786 | 757 | ||
| 787 | err = bdev_direct_access(sb->s_bdev, &dax); | 758 | err = bdev_dax_pgoff(bdev, 0, PAGE_SIZE, &pgoff); |
| 788 | if (err < 0) { | 759 | if (err) { |
| 789 | switch (err) { | 760 | vfs_msg(sb, KERN_ERR, "error: unaligned partition for dax"); |
| 790 | case -EOPNOTSUPP: | ||
| 791 | vfs_msg(sb, KERN_ERR, | ||
| 792 | "error: device does not support dax"); | ||
| 793 | break; | ||
| 794 | case -EINVAL: | ||
| 795 | vfs_msg(sb, KERN_ERR, | ||
| 796 | "error: unaligned partition for dax"); | ||
| 797 | break; | ||
| 798 | default: | ||
| 799 | vfs_msg(sb, KERN_ERR, | ||
| 800 | "error: dax access failed (%d)", err); | ||
| 801 | } | ||
| 802 | return err; | 761 | return err; |
| 803 | } | 762 | } |
| 804 | 763 | ||
| 805 | return 0; | 764 | dax_dev = dax_get_by_host(bdev->bd_disk->disk_name); |
| 806 | } | 765 | if (!dax_dev) { |
| 807 | EXPORT_SYMBOL_GPL(bdev_dax_supported); | 766 | vfs_msg(sb, KERN_ERR, "error: device does not support dax"); |
| 808 | 767 | return -EOPNOTSUPP; | |
| 809 | /** | 768 | } |
| 810 | * bdev_dax_capable() - Return if the raw device is capable for dax | ||
| 811 | * @bdev: The device for raw block device access | ||
| 812 | */ | ||
| 813 | bool bdev_dax_capable(struct block_device *bdev) | ||
| 814 | { | ||
| 815 | struct blk_dax_ctl dax = { | ||
| 816 | .size = PAGE_SIZE, | ||
| 817 | }; | ||
| 818 | 769 | ||
| 819 | if (!IS_ENABLED(CONFIG_FS_DAX)) | 770 | id = dax_read_lock(); |
| 820 | return false; | 771 | len = dax_direct_access(dax_dev, pgoff, 1, &kaddr, &pfn); |
| 772 | dax_read_unlock(id); | ||
| 821 | 773 | ||
| 822 | dax.sector = 0; | 774 | put_dax(dax_dev); |
| 823 | if (bdev_direct_access(bdev, &dax) < 0) | ||
| 824 | return false; | ||
| 825 | 775 | ||
| 826 | dax.sector = bdev->bd_part->nr_sects - (PAGE_SIZE / 512); | 776 | if (len < 1) { |
| 827 | if (bdev_direct_access(bdev, &dax) < 0) | 777 | vfs_msg(sb, KERN_ERR, |
| 828 | return false; | 778 | "error: dax access failed (%ld)", len); |
| 779 | return len < 0 ? len : -EIO; | ||
| 780 | } | ||
| 829 | 781 | ||
| 830 | return true; | 782 | return 0; |
| 831 | } | 783 | } |
| 784 | EXPORT_SYMBOL_GPL(bdev_dax_supported); | ||
| 832 | 785 | ||
| 833 | /* | 786 | /* |
| 834 | * pseudo-fs | 787 | * pseudo-fs |
