diff options
Diffstat (limited to 'drivers/dax/super.c')
| -rw-r--r-- | drivers/dax/super.c | 88 | 
1 files changed, 57 insertions, 31 deletions
diff --git a/drivers/dax/super.c b/drivers/dax/super.c index bbd57ca0634a..3a7b0a0bf469 100644 --- a/drivers/dax/super.c +++ b/drivers/dax/super.c  | |||
| @@ -73,22 +73,12 @@ struct dax_device *fs_dax_get_by_bdev(struct block_device *bdev) | |||
| 73 | EXPORT_SYMBOL_GPL(fs_dax_get_by_bdev); | 73 | EXPORT_SYMBOL_GPL(fs_dax_get_by_bdev); | 
| 74 | #endif | 74 | #endif | 
| 75 | 75 | ||
| 76 | /** | 76 | bool __generic_fsdax_supported(struct dax_device *dax_dev, | 
| 77 | * __bdev_dax_supported() - Check if the device supports dax for filesystem | 77 | struct block_device *bdev, int blocksize, sector_t start, | 
| 78 | * @bdev: block device to check | 78 | sector_t sectors) | 
| 79 | * @blocksize: The block size of the device | ||
| 80 | * | ||
| 81 | * This is a library function for filesystems to check if the block device | ||
| 82 | * can be mounted with dax option. | ||
| 83 | * | ||
| 84 | * Return: true if supported, false if unsupported | ||
| 85 | */ | ||
| 86 | bool __bdev_dax_supported(struct block_device *bdev, int blocksize) | ||
| 87 | { | 79 | { | 
| 88 | struct dax_device *dax_dev; | ||
| 89 | bool dax_enabled = false; | 80 | bool dax_enabled = false; | 
| 90 | pgoff_t pgoff, pgoff_end; | 81 | pgoff_t pgoff, pgoff_end; | 
| 91 | struct request_queue *q; | ||
| 92 | char buf[BDEVNAME_SIZE]; | 82 | char buf[BDEVNAME_SIZE]; | 
| 93 | void *kaddr, *end_kaddr; | 83 | void *kaddr, *end_kaddr; | 
| 94 | pfn_t pfn, end_pfn; | 84 | pfn_t pfn, end_pfn; | 
| @@ -102,21 +92,14 @@ bool __bdev_dax_supported(struct block_device *bdev, int blocksize) | |||
| 102 | return false; | 92 | return false; | 
| 103 | } | 93 | } | 
| 104 | 94 | ||
| 105 | q = bdev_get_queue(bdev); | 95 | err = bdev_dax_pgoff(bdev, start, PAGE_SIZE, &pgoff); | 
| 106 | if (!q || !blk_queue_dax(q)) { | ||
| 107 | pr_debug("%s: error: request queue doesn't support dax\n", | ||
| 108 | bdevname(bdev, buf)); | ||
| 109 | return false; | ||
| 110 | } | ||
| 111 | |||
| 112 | err = bdev_dax_pgoff(bdev, 0, PAGE_SIZE, &pgoff); | ||
| 113 | if (err) { | 96 | if (err) { | 
| 114 | pr_debug("%s: error: unaligned partition for dax\n", | 97 | pr_debug("%s: error: unaligned partition for dax\n", | 
| 115 | bdevname(bdev, buf)); | 98 | bdevname(bdev, buf)); | 
| 116 | return false; | 99 | return false; | 
| 117 | } | 100 | } | 
| 118 | 101 | ||
| 119 | last_page = PFN_DOWN(i_size_read(bdev->bd_inode) - 1) * 8; | 102 | last_page = PFN_DOWN((start + sectors - 1) * 512) * PAGE_SIZE / 512; | 
| 120 | err = bdev_dax_pgoff(bdev, last_page, PAGE_SIZE, &pgoff_end); | 103 | err = bdev_dax_pgoff(bdev, last_page, PAGE_SIZE, &pgoff_end); | 
| 121 | if (err) { | 104 | if (err) { | 
| 122 | pr_debug("%s: error: unaligned partition for dax\n", | 105 | pr_debug("%s: error: unaligned partition for dax\n", | 
| @@ -124,20 +107,11 @@ bool __bdev_dax_supported(struct block_device *bdev, int blocksize) | |||
| 124 | return false; | 107 | return false; | 
| 125 | } | 108 | } | 
| 126 | 109 | ||
| 127 | dax_dev = dax_get_by_host(bdev->bd_disk->disk_name); | ||
| 128 | if (!dax_dev) { | ||
| 129 | pr_debug("%s: error: device does not support dax\n", | ||
| 130 | bdevname(bdev, buf)); | ||
| 131 | return false; | ||
| 132 | } | ||
| 133 | |||
| 134 | id = dax_read_lock(); | 110 | id = dax_read_lock(); | 
| 135 | len = dax_direct_access(dax_dev, pgoff, 1, &kaddr, &pfn); | 111 | len = dax_direct_access(dax_dev, pgoff, 1, &kaddr, &pfn); | 
| 136 | len2 = dax_direct_access(dax_dev, pgoff_end, 1, &end_kaddr, &end_pfn); | 112 | len2 = dax_direct_access(dax_dev, pgoff_end, 1, &end_kaddr, &end_pfn); | 
| 137 | dax_read_unlock(id); | 113 | dax_read_unlock(id); | 
| 138 | 114 | ||
| 139 | put_dax(dax_dev); | ||
| 140 | |||
| 141 | if (len < 1 || len2 < 1) { | 115 | if (len < 1 || len2 < 1) { | 
| 142 | pr_debug("%s: error: dax access failed (%ld)\n", | 116 | pr_debug("%s: error: dax access failed (%ld)\n", | 
| 143 | bdevname(bdev, buf), len < 1 ? len : len2); | 117 | bdevname(bdev, buf), len < 1 ? len : len2); | 
| @@ -178,6 +152,49 @@ bool __bdev_dax_supported(struct block_device *bdev, int blocksize) | |||
| 178 | } | 152 | } | 
| 179 | return true; | 153 | return true; | 
| 180 | } | 154 | } | 
| 155 | EXPORT_SYMBOL_GPL(__generic_fsdax_supported); | ||
| 156 | |||
| 157 | /** | ||
| 158 | * __bdev_dax_supported() - Check if the device supports dax for filesystem | ||
| 159 | * @bdev: block device to check | ||
| 160 | * @blocksize: The block size of the device | ||
| 161 | * | ||
| 162 | * This is a library function for filesystems to check if the block device | ||
| 163 | * can be mounted with dax option. | ||
| 164 | * | ||
| 165 | * Return: true if supported, false if unsupported | ||
| 166 | */ | ||
| 167 | bool __bdev_dax_supported(struct block_device *bdev, int blocksize) | ||
| 168 | { | ||
| 169 | struct dax_device *dax_dev; | ||
| 170 | struct request_queue *q; | ||
| 171 | char buf[BDEVNAME_SIZE]; | ||
| 172 | bool ret; | ||
| 173 | int id; | ||
| 174 | |||
| 175 | q = bdev_get_queue(bdev); | ||
| 176 | if (!q || !blk_queue_dax(q)) { | ||
| 177 | pr_debug("%s: error: request queue doesn't support dax\n", | ||
| 178 | bdevname(bdev, buf)); | ||
| 179 | return false; | ||
| 180 | } | ||
| 181 | |||
| 182 | dax_dev = dax_get_by_host(bdev->bd_disk->disk_name); | ||
| 183 | if (!dax_dev) { | ||
| 184 | pr_debug("%s: error: device does not support dax\n", | ||
| 185 | bdevname(bdev, buf)); | ||
| 186 | return false; | ||
| 187 | } | ||
| 188 | |||
| 189 | id = dax_read_lock(); | ||
| 190 | ret = dax_supported(dax_dev, bdev, blocksize, 0, | ||
| 191 | i_size_read(bdev->bd_inode) / 512); | ||
| 192 | dax_read_unlock(id); | ||
| 193 | |||
| 194 | put_dax(dax_dev); | ||
| 195 | |||
| 196 | return ret; | ||
| 197 | } | ||
| 181 | EXPORT_SYMBOL_GPL(__bdev_dax_supported); | 198 | EXPORT_SYMBOL_GPL(__bdev_dax_supported); | 
| 182 | #endif | 199 | #endif | 
| 183 | 200 | ||
| @@ -303,6 +320,15 @@ long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages, | |||
| 303 | } | 320 | } | 
| 304 | EXPORT_SYMBOL_GPL(dax_direct_access); | 321 | EXPORT_SYMBOL_GPL(dax_direct_access); | 
| 305 | 322 | ||
| 323 | bool dax_supported(struct dax_device *dax_dev, struct block_device *bdev, | ||
| 324 | int blocksize, sector_t start, sector_t len) | ||
| 325 | { | ||
| 326 | if (!dax_alive(dax_dev)) | ||
| 327 | return false; | ||
| 328 | |||
| 329 | return dax_dev->ops->dax_supported(dax_dev, bdev, blocksize, start, len); | ||
| 330 | } | ||
| 331 | |||
| 306 | size_t dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr, | 332 | size_t dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr, | 
| 307 | size_t bytes, struct iov_iter *i) | 333 | size_t bytes, struct iov_iter *i) | 
| 308 | { | 334 | { | 
