mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
fuse: add support for striped backing
Add the FUSE_BACKING_MAP_CYCLIC flag for FUSE_NOTIFY_BACKING_MAP notifications to enable creating striped maps. This is just a set of regular extents that repeats after the end of the last extent using a striping pattern (i.e. on the target backings the stripes have a contiguous footprint). Two additional limits apply compared to non-cyclic extent map population: - the size of the extents (chunk size) must be equal - the extents must start from zero offset and follow each other without gaps. Originally-by: John Groves <john@groves.net> Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
e8bc74b6ed
commit
dfc68b6c99
|
|
@ -103,12 +103,18 @@ static int fuse_ext_map_iomap_begin(struct inode *inode, loff_t offset, loff_t l
|
|||
{
|
||||
struct fuse_backing *fb = fuse_inode_backing(get_fuse_inode(inode));
|
||||
struct fuse_iext *fie;
|
||||
u64 ncycle = 0, seq_off = 0, addr, tmp;
|
||||
loff_t ext_len;
|
||||
|
||||
if (!fb || fb->type != FUSE_BACKING_EXTMAP)
|
||||
return fuse_EIO("missing or wrong type backing");
|
||||
|
||||
fie = fuse_find_extent(&fb->extents, offset);
|
||||
if (fb->cycle_length) {
|
||||
ncycle = div64_u64(offset, fb->cycle_length);
|
||||
seq_off = ncycle * fb->cycle_length;
|
||||
}
|
||||
|
||||
fie = fuse_find_extent(&fb->extents, offset - seq_off);
|
||||
if (!fie)
|
||||
return fuse_EIO("missing mapping");
|
||||
|
||||
|
|
@ -121,9 +127,15 @@ static int fuse_ext_map_iomap_begin(struct inode *inode, loff_t offset, loff_t l
|
|||
}
|
||||
|
||||
ext_len = fie->end - fie->start;
|
||||
addr = fie->backing_offset;
|
||||
if (check_mul_overflow(ncycle, ext_len, &tmp) || check_add_overflow(addr, tmp, &addr))
|
||||
return fuse_EIO("extent address overflow");
|
||||
|
||||
iomap->offset = fie->start;
|
||||
iomap->addr = fie->backing_offset;
|
||||
if (check_add_overflow(addr, ext_len, &tmp))
|
||||
return fuse_EIO("extent end overflow");
|
||||
|
||||
iomap->offset = fie->start + seq_off;
|
||||
iomap->addr = addr;
|
||||
iomap->length = ext_len;
|
||||
iomap->dax_dev = fie->backing->dax_dev;
|
||||
iomap->type = IOMAP_MAPPED;
|
||||
|
|
@ -259,6 +271,7 @@ int fuse_ext_map_populate(struct fuse_conn *fc, struct fuse_notify_backing_map_o
|
|||
struct fuse_backing *fb;
|
||||
unsigned int i;
|
||||
int err;
|
||||
u64 chunk_size = 0;
|
||||
|
||||
if (!arg->num_extents)
|
||||
return fuse_EIO("no extents");
|
||||
|
|
@ -276,7 +289,18 @@ int fuse_ext_map_populate(struct fuse_conn *fc, struct fuse_notify_backing_map_o
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arg->flags & FUSE_BACKING_MAP_CYCLIC) {
|
||||
chunk_size = ext[0].length;
|
||||
err = -EINVAL;
|
||||
if (check_mul_overflow(chunk_size, arg->num_extents, &fb->cycle_length))
|
||||
goto err_put;
|
||||
}
|
||||
|
||||
for (i = 0; i < arg->num_extents; i++) {
|
||||
err = -EINVAL;
|
||||
if (chunk_size && (ext[i].offset != chunk_size * i || ext[i].length != chunk_size))
|
||||
goto err_put;
|
||||
|
||||
err = fuse_add_extent(fc, &fb->extents, &ext[i]);
|
||||
if (err)
|
||||
goto err_put;
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ struct fuse_backing {
|
|||
};
|
||||
struct {
|
||||
struct rb_root extents;
|
||||
u64 cycle_length;
|
||||
};
|
||||
};
|
||||
u64 backing_id;
|
||||
|
|
|
|||
|
|
@ -461,7 +461,7 @@ static int fuse_notify_map(struct fuse_conn *fc, unsigned int size,
|
|||
if (outarg.reserved[0] != 0 || outarg.reserved[1] != 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (outarg.flags & ~FUSE_BACKING_MAP_CREATE)
|
||||
if (outarg.flags & ~(FUSE_BACKING_MAP_CREATE | FUSE_BACKING_MAP_CYCLIC))
|
||||
return -EINVAL;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_FUSE_PASSTHROUGH))
|
||||
|
|
|
|||
|
|
@ -255,7 +255,8 @@
|
|||
* - add FUSE_DEV_IOC_BACKING_CREATE, struct fuse_backing_create_in
|
||||
* - add FUSE_NOTIFY_BACKING_REMOVE, struct fuse_notify_backing_remove_out
|
||||
* - add backing_id_64 to fuse_open_out
|
||||
* - add FUSE_NOTIFY_BACKING_MAP, fuse_notify_backing_map_out, fuse_extent, FUSE_BACKING_MAP_CREATE
|
||||
* - add FUSE_NOTIFY_BACKING_MAP, fuse_notify_backing_map_out, fuse_extent
|
||||
* - add FUSE_BACKING_MAP_CREATE, FUSE_BACKING_MAP_CYCLIC
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_FUSE_H
|
||||
|
|
@ -1219,8 +1220,10 @@ struct fuse_notify_backing_remove_out {
|
|||
* notify_map flags
|
||||
*
|
||||
* FUSE_BACKING_MAP_CREATE: create backing with the supplied ID
|
||||
* FUSE_BACKING_MAP_CYCLIC: map repeats after last extent
|
||||
*/
|
||||
#define FUSE_BACKING_MAP_CREATE (1 << 0)
|
||||
#define FUSE_BACKING_MAP_CYCLIC (1 << 1)
|
||||
|
||||
struct fuse_notify_backing_map_out {
|
||||
uint64_t backing_id;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user