Skip to content

Commit 3d236a7

Browse files
fuporovvStackFedorUporovVstack
authored andcommitted
vdev/geom: Add vdev chr/blk devices access support
Add to ZFS ability to open char/block devices, which does not have the geom provider. The functionality is implemented under vdev_file, which now able to open char and block devices from devfs additionally to regular files. The geom provider detection decision is made under platform-dependent zfs_dev_is_whole_disk() function. The two new *strategy* functions are added to vdev_file platform-dependent API to call devfs device strategy routine directly. Also, the zfs_file_attr_t structure is modified to able to get logical and physical devfs device block sizes. The user logic for devfs devices is the same as for zpool creation/importing for regular files. Mean, zpool could be created based on devfs devices and later could be imported by using '-s' option or using '-d' option with /dev directory argument. In case of zpool import without arguments, zpool on devfs will not be seen. For devices, which have both devfs device and geom provider (case nvme: ndaX/nvdX + nvmeXnsY), pool could be created on geom and later imported as devfs using vdev_file importing rules and vise versa. Signed-off-by: Fedor Uporov <[email protected]>
1 parent ab9bb19 commit 3d236a7

File tree

7 files changed

+508
-38
lines changed

7 files changed

+508
-38
lines changed

cmd/zpool/zpool_vdev.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -353,15 +353,32 @@ make_leaf_vdev(nvlist_t *props, const char *arg, boolean_t is_primary)
353353
/*
354354
* Determine whether this is a device or a file.
355355
*/
356+
#if defined(__FreeBSD__)
357+
if (wholedisk) {
358+
/* Devices with geom provider only */
359+
type = VDEV_TYPE_DISK;
360+
} else if (S_ISREG(statbuf.st_mode) ||
361+
S_ISCHR(statbuf.st_mode) || S_ISBLK(statbuf.st_mode)) {
362+
/*
363+
* Regular and devfs files, excluding have geom
364+
* providers. The decision, is it geom provider,
365+
* is made by zfs_dev_is_whole_disk() function.
366+
*/
367+
type = VDEV_TYPE_FILE;
368+
}
369+
#else
356370
if (wholedisk || S_ISBLK(statbuf.st_mode)) {
357371
type = VDEV_TYPE_DISK;
358372
} else if (S_ISREG(statbuf.st_mode)) {
359373
type = VDEV_TYPE_FILE;
360-
} else {
361-
fprintf(stderr, gettext("cannot use '%s': must "
362-
"be a block device or regular file\n"), path);
363-
return (NULL);
364374
}
375+
#endif
376+
}
377+
378+
if (type == NULL) {
379+
fprintf(stderr, gettext("cannot use '%s': must "
380+
"be a block device or regular file\n"), path);
381+
return (NULL);
365382
}
366383

367384
/*

include/sys/zfs_file.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@ typedef struct file zfs_file_t;
3737
#endif
3838

3939
typedef struct zfs_file_attr {
40-
uint64_t zfa_size; /* file size */
41-
mode_t zfa_mode; /* file type */
40+
uint64_t zfa_size; /* file size */
41+
mode_t zfa_mode; /* file type */
42+
uint32_t zfa_logical_block_size; /* file logical bs */
43+
uint32_t zfa_physical_block_size; /* file physical bs */
4244
} zfs_file_attr_t;
4345

4446
int zfs_file_open(const char *path, int flags, int mode, zfs_file_t **fp);
@@ -51,6 +53,9 @@ int zfs_file_read(zfs_file_t *fp, void *buf, size_t len, ssize_t *resid);
5153
int zfs_file_pread(zfs_file_t *fp, void *buf, size_t len, loff_t off,
5254
ssize_t *resid);
5355

56+
void zfs_file_io_strategy(zfs_file_t *fp, void *arg);
57+
void zfs_file_io_strategy_done(zfs_file_t *fp, void *arg);
58+
5459
int zfs_file_seek(zfs_file_t *fp, loff_t *offp, int whence);
5560
int zfs_file_getattr(zfs_file_t *fp, zfs_file_attr_t *zfattr);
5661
int zfs_file_fsync(zfs_file_t *fp, int flags);

lib/libzpool/kernel.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,6 +1324,36 @@ zfs_file_seek(zfs_file_t *fp, loff_t *offp, int whence)
13241324
return (0);
13251325
}
13261326

1327+
/*
1328+
* The file IO strategy routine.
1329+
*
1330+
* fp - pointer to file (regular, blk or chr)
1331+
* arg - data to transfer from/to file, typically ZFS zio
1332+
*
1333+
* Used only on FreeBSD kernel side for now.
1334+
*/
1335+
void
1336+
zfs_file_io_strategy(zfs_file_t *fp, void *arg)
1337+
{
1338+
(void) fp;
1339+
(void) arg;
1340+
}
1341+
1342+
/*
1343+
* The file IO strategy completion routine.
1344+
*
1345+
* fp - pointer to file (regular, blk or chr)
1346+
* arg - data to transfer from/to file, typically ZFS zio
1347+
*
1348+
* Used only on FreeBSD kernel side for now.
1349+
*/
1350+
void
1351+
zfs_file_io_strategy_done(zfs_file_t *fp, void *arg)
1352+
{
1353+
(void) fp;
1354+
(void) arg;
1355+
}
1356+
13271357
/*
13281358
* Get file attributes
13291359
*
@@ -1344,6 +1374,8 @@ zfs_file_getattr(zfs_file_t *fp, zfs_file_attr_t *zfattr)
13441374

13451375
zfattr->zfa_size = st.st_size;
13461376
zfattr->zfa_mode = st.st_mode;
1377+
zfattr->zfa_logical_block_size = 0;
1378+
zfattr->zfa_physical_block_size = 0;
13471379

13481380
return (0);
13491381
}

lib/libzutil/os/freebsd/zutil_device_path_os.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,23 @@ zfs_get_underlying_path(const char *dev_name)
7979
boolean_t
8080
zfs_dev_is_whole_disk(const char *dev_name)
8181
{
82+
boolean_t wholedisk = B_FALSE;
83+
char *name;
8284
int fd;
8385

8486
fd = g_open(dev_name, 0);
85-
if (fd >= 0) {
86-
g_close(fd);
87-
return (B_TRUE);
87+
if (fd < 0) {
88+
return (B_FALSE);
8889
}
89-
return (B_FALSE);
90+
91+
name = g_providername(fd);
92+
if (name != NULL) {
93+
wholedisk = B_TRUE;
94+
}
95+
96+
g_close(fd);
97+
98+
return (wholedisk);
9099
}
91100

92101
/*

0 commit comments

Comments
 (0)