Skip to content

Commit 7bf7eac

Browse files
committed
dax: Arrange for dax_supported check to span multiple devices
Pankaj reports that starting with commit ad428cd "dax: Check the end of the block-device capacity with dax_direct_access()" device-mapper no longer allows dax operation. This results from the stricter checks in __bdev_dax_supported() that validate that the start and end of a block-device map to the same 'pagemap' instance. Teach the dax-core and device-mapper to validate the 'pagemap' on a per-target basis. This is accomplished by refactoring the bdev_dax_supported() internals into generic_fsdax_supported() which takes a sector range to validate. Consequently generic_fsdax_supported() is suitable to be used in a device-mapper ->iterate_devices() callback. A new ->dax_supported() operation is added to allow composite devices to split and route upper-level bdev_dax_supported() requests. Fixes: ad428cd ("dax: Check the end of the block-device...") Cc: <[email protected]> Cc: Ira Weiny <[email protected]> Cc: Dave Jiang <[email protected]> Cc: Keith Busch <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Vishal Verma <[email protected]> Cc: Heiko Carstens <[email protected]> Cc: Martin Schwidefsky <[email protected]> Reviewed-by: Jan Kara <[email protected]> Reported-by: Pankaj Gupta <[email protected]> Reviewed-by: Pankaj Gupta <[email protected]> Tested-by: Pankaj Gupta <[email protected]> Tested-by: Vaibhav Jain <[email protected]> Reviewed-by: Mike Snitzer <[email protected]> Signed-off-by: Dan Williams <[email protected]>
1 parent c01dafa commit 7bf7eac

File tree

7 files changed

+117
-37
lines changed

7 files changed

+117
-37
lines changed

drivers/dax/super.c

Lines changed: 57 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -73,22 +73,12 @@ struct dax_device *fs_dax_get_by_bdev(struct block_device *bdev)
7373
EXPORT_SYMBOL_GPL(fs_dax_get_by_bdev);
7474
#endif
7575

76-
/**
77-
* __bdev_dax_supported() - Check if the device supports dax for filesystem
78-
* @bdev: block device to check
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)
76+
bool __generic_fsdax_supported(struct dax_device *dax_dev,
77+
struct block_device *bdev, int blocksize, sector_t start,
78+
sector_t sectors)
8779
{
88-
struct dax_device *dax_dev;
8980
bool dax_enabled = false;
9081
pgoff_t pgoff, pgoff_end;
91-
struct request_queue *q;
9282
char buf[BDEVNAME_SIZE];
9383
void *kaddr, *end_kaddr;
9484
pfn_t pfn, end_pfn;
@@ -102,42 +92,26 @@ bool __bdev_dax_supported(struct block_device *bdev, int blocksize)
10292
return false;
10393
}
10494

105-
q = bdev_get_queue(bdev);
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);
95+
err = bdev_dax_pgoff(bdev, start, PAGE_SIZE, &pgoff);
11396
if (err) {
11497
pr_debug("%s: error: unaligned partition for dax\n",
11598
bdevname(bdev, buf));
11699
return false;
117100
}
118101

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;
120103
err = bdev_dax_pgoff(bdev, last_page, PAGE_SIZE, &pgoff_end);
121104
if (err) {
122105
pr_debug("%s: error: unaligned partition for dax\n",
123106
bdevname(bdev, buf));
124107
return false;
125108
}
126109

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-
134110
id = dax_read_lock();
135111
len = dax_direct_access(dax_dev, pgoff, 1, &kaddr, &pfn);
136112
len2 = dax_direct_access(dax_dev, pgoff_end, 1, &end_kaddr, &end_pfn);
137113
dax_read_unlock(id);
138114

139-
put_dax(dax_dev);
140-
141115
if (len < 1 || len2 < 1) {
142116
pr_debug("%s: error: dax access failed (%ld)\n",
143117
bdevname(bdev, buf), len < 1 ? len : len2);
@@ -178,6 +152,49 @@ bool __bdev_dax_supported(struct block_device *bdev, int blocksize)
178152
}
179153
return true;
180154
}
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+
}
181198
EXPORT_SYMBOL_GPL(__bdev_dax_supported);
182199
#endif
183200

@@ -303,6 +320,15 @@ long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages,
303320
}
304321
EXPORT_SYMBOL_GPL(dax_direct_access);
305322

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+
306332
size_t dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr,
307333
size_t bytes, struct iov_iter *i)
308334
{

drivers/md/dm-table.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -880,13 +880,17 @@ void dm_table_set_type(struct dm_table *t, enum dm_queue_mode type)
880880
}
881881
EXPORT_SYMBOL_GPL(dm_table_set_type);
882882

883+
/* validate the dax capability of the target device span */
883884
static int device_supports_dax(struct dm_target *ti, struct dm_dev *dev,
884-
sector_t start, sector_t len, void *data)
885+
sector_t start, sector_t len, void *data)
885886
{
886-
return bdev_dax_supported(dev->bdev, PAGE_SIZE);
887+
int blocksize = *(int *) data;
888+
889+
return generic_fsdax_supported(dev->dax_dev, dev->bdev, blocksize,
890+
start, len);
887891
}
888892

889-
static bool dm_table_supports_dax(struct dm_table *t)
893+
bool dm_table_supports_dax(struct dm_table *t, int blocksize)
890894
{
891895
struct dm_target *ti;
892896
unsigned i;
@@ -899,7 +903,8 @@ static bool dm_table_supports_dax(struct dm_table *t)
899903
return false;
900904

901905
if (!ti->type->iterate_devices ||
902-
!ti->type->iterate_devices(ti, device_supports_dax, NULL))
906+
!ti->type->iterate_devices(ti, device_supports_dax,
907+
&blocksize))
903908
return false;
904909
}
905910

@@ -979,7 +984,7 @@ static int dm_table_determine_type(struct dm_table *t)
979984
verify_bio_based:
980985
/* We must use this table as bio-based */
981986
t->type = DM_TYPE_BIO_BASED;
982-
if (dm_table_supports_dax(t) ||
987+
if (dm_table_supports_dax(t, PAGE_SIZE) ||
983988
(list_empty(devices) && live_md_type == DM_TYPE_DAX_BIO_BASED)) {
984989
t->type = DM_TYPE_DAX_BIO_BASED;
985990
} else {
@@ -1905,7 +1910,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
19051910
}
19061911
blk_queue_write_cache(q, wc, fua);
19071912

1908-
if (dm_table_supports_dax(t))
1913+
if (dm_table_supports_dax(t, PAGE_SIZE))
19091914
blk_queue_flag_set(QUEUE_FLAG_DAX, q);
19101915
else
19111916
blk_queue_flag_clear(QUEUE_FLAG_DAX, q);

drivers/md/dm.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,25 @@ static long dm_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff,
11071107
return ret;
11081108
}
11091109

1110+
static bool dm_dax_supported(struct dax_device *dax_dev, struct block_device *bdev,
1111+
int blocksize, sector_t start, sector_t len)
1112+
{
1113+
struct mapped_device *md = dax_get_private(dax_dev);
1114+
struct dm_table *map;
1115+
int srcu_idx;
1116+
bool ret;
1117+
1118+
map = dm_get_live_table(md, &srcu_idx);
1119+
if (!map)
1120+
return false;
1121+
1122+
ret = dm_table_supports_dax(map, blocksize);
1123+
1124+
dm_put_live_table(md, srcu_idx);
1125+
1126+
return ret;
1127+
}
1128+
11101129
static size_t dm_dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff,
11111130
void *addr, size_t bytes, struct iov_iter *i)
11121131
{
@@ -3192,6 +3211,7 @@ static const struct block_device_operations dm_blk_dops = {
31923211

31933212
static const struct dax_operations dm_dax_ops = {
31943213
.direct_access = dm_dax_direct_access,
3214+
.dax_supported = dm_dax_supported,
31953215
.copy_from_iter = dm_dax_copy_from_iter,
31963216
.copy_to_iter = dm_dax_copy_to_iter,
31973217
};

drivers/md/dm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ bool dm_table_bio_based(struct dm_table *t);
7272
bool dm_table_request_based(struct dm_table *t);
7373
void dm_table_free_md_mempools(struct dm_table *t);
7474
struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t);
75+
bool dm_table_supports_dax(struct dm_table *t, int blocksize);
7576

7677
void dm_lock_md_type(struct mapped_device *md);
7778
void dm_unlock_md_type(struct mapped_device *md);

drivers/nvdimm/pmem.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ static size_t pmem_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff,
295295

296296
static const struct dax_operations pmem_dax_ops = {
297297
.direct_access = pmem_dax_direct_access,
298+
.dax_supported = generic_fsdax_supported,
298299
.copy_from_iter = pmem_copy_from_iter,
299300
.copy_to_iter = pmem_copy_to_iter,
300301
};

drivers/s390/block/dcssblk.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ static size_t dcssblk_dax_copy_to_iter(struct dax_device *dax_dev,
5959

6060
static const struct dax_operations dcssblk_dax_ops = {
6161
.direct_access = dcssblk_dax_direct_access,
62+
.dax_supported = generic_fsdax_supported,
6263
.copy_from_iter = dcssblk_dax_copy_from_iter,
6364
.copy_to_iter = dcssblk_dax_copy_to_iter,
6465
};

include/linux/dax.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ struct dax_operations {
1919
*/
2020
long (*direct_access)(struct dax_device *, pgoff_t, long,
2121
void **, pfn_t *);
22+
/*
23+
* Validate whether this device is usable as an fsdax backing
24+
* device.
25+
*/
26+
bool (*dax_supported)(struct dax_device *, struct block_device *, int,
27+
sector_t, sector_t);
2228
/* copy_from_iter: required operation for fs-dax direct-i/o */
2329
size_t (*copy_from_iter)(struct dax_device *, pgoff_t, void *, size_t,
2430
struct iov_iter *);
@@ -75,6 +81,17 @@ static inline bool bdev_dax_supported(struct block_device *bdev, int blocksize)
7581
return __bdev_dax_supported(bdev, blocksize);
7682
}
7783

84+
bool __generic_fsdax_supported(struct dax_device *dax_dev,
85+
struct block_device *bdev, int blocksize, sector_t start,
86+
sector_t sectors);
87+
static inline bool generic_fsdax_supported(struct dax_device *dax_dev,
88+
struct block_device *bdev, int blocksize, sector_t start,
89+
sector_t sectors)
90+
{
91+
return __generic_fsdax_supported(dax_dev, bdev, blocksize, start,
92+
sectors);
93+
}
94+
7895
static inline struct dax_device *fs_dax_get_by_host(const char *host)
7996
{
8097
return dax_get_by_host(host);
@@ -99,6 +116,13 @@ static inline bool bdev_dax_supported(struct block_device *bdev,
99116
return false;
100117
}
101118

119+
static inline bool generic_fsdax_supported(struct dax_device *dax_dev,
120+
struct block_device *bdev, int blocksize, sector_t start,
121+
sector_t sectors)
122+
{
123+
return false;
124+
}
125+
102126
static inline struct dax_device *fs_dax_get_by_host(const char *host)
103127
{
104128
return NULL;
@@ -142,6 +166,8 @@ bool dax_alive(struct dax_device *dax_dev);
142166
void *dax_get_private(struct dax_device *dax_dev);
143167
long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages,
144168
void **kaddr, pfn_t *pfn);
169+
bool dax_supported(struct dax_device *dax_dev, struct block_device *bdev,
170+
int blocksize, sector_t start, sector_t len);
145171
size_t dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr,
146172
size_t bytes, struct iov_iter *i);
147173
size_t dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr,

0 commit comments

Comments
 (0)