Skip to content

Commit d50f471

Browse files
committed
Stable API extensions
This introduces a new ZFS_IOC_LIBZFS_CORE ioctl and replaces the ioctl calls in all but 1 function in libzfs_core.so and adds many more. It is intended to be as stable kernel/userland interface that allows basic userland functionality to continue working when an older userland is used with newer kernel modules or vice versa by mistake. At this time, it is a subset of the legacy functionality, but enough API functions have been implemented that mismatched kernel/userland code will not break the Gentoo's boot process (excluding zfs share and ZED, which are excluded at this time) and ClusterHQ's flocker. This sufficiently addresses the long standing /dev/zfs API instability that it opens the possibility of stabilization of the ZFS packaging in Gentoo on amd64 and other architectures, which makes this an improvement in more ways than one. To ease the transition to the new ABI, we include a shim library that implements the new C library extensions using the old kernel ABI. The --with-libzfs_core=default|all|legacy|stable configure switch determines which is used and presently, the default is an alias for legacy that can be changed in a future release. --with-libzfs_core=all will install both, with libzfs_core.so.1 using the new ABI while a libzfs_core-legacy.so.0 that can be loaded with LD_PRELOAD will be installed containing the old one. Signed-off-by: Richard Yao <ryao@gentoo.org>
1 parent 0195da3 commit d50f471

File tree

94 files changed

+11021
-1221
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+11021
-1221
lines changed

cmd/mount_zfs/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ mount_zfs_LDADD = \
1919
$(top_builddir)/lib/libuutil/libuutil.la \
2020
$(top_builddir)/lib/libzpool/libzpool.la \
2121
$(top_builddir)/lib/libzfs/libzfs.la \
22-
$(top_builddir)/lib/libzfs_core/libzfs_core.la
22+
$(top_builddir)/lib/libzfs_core-$(LIBZFS_CORE_VARIANT)/libzfs_core-$(LIBZFS_CORE_VARIANT).la

cmd/zdb/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ zdb_LDADD = \
1717
$(top_builddir)/lib/libuutil/libuutil.la \
1818
$(top_builddir)/lib/libzpool/libzpool.la \
1919
$(top_builddir)/lib/libzfs/libzfs.la \
20-
$(top_builddir)/lib/libzfs_core/libzfs_core.la
20+
$(top_builddir)/lib/libzfs_core-$(LIBZFS_CORE_VARIANT)/libzfs_core-$(LIBZFS_CORE_VARIANT).la

cmd/zed/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ zed_LDADD = \
3030
$(top_builddir)/lib/libspl/libspl.la \
3131
$(top_builddir)/lib/libzpool/libzpool.la \
3232
$(top_builddir)/lib/libzfs/libzfs.la \
33-
$(top_builddir)/lib/libzfs_core/libzfs_core.la
33+
$(top_builddir)/lib/libzfs_core-$(LIBZFS_CORE_VARIANT)/libzfs_core-$(LIBZFS_CORE_VARIANT).la
3434

3535
zedconfdir = $(sysconfdir)/zfs/zed.d
3636

cmd/zfs/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ zfs_LDADD = \
1717
$(top_builddir)/lib/libuutil/libuutil.la \
1818
$(top_builddir)/lib/libzpool/libzpool.la \
1919
$(top_builddir)/lib/libzfs/libzfs.la \
20-
$(top_builddir)/lib/libzfs_core/libzfs_core.la
20+
$(top_builddir)/lib/libzfs_core-$(LIBZFS_CORE_VARIANT)/libzfs_core-$(LIBZFS_CORE_VARIANT).la
2121

2222
zfs_LDFLAGS = -pthread

cmd/zfs/zfs_iter.c

Lines changed: 64 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -68,82 +68,37 @@ typedef struct callback_data {
6868

6969
uu_avl_pool_t *avl_pool;
7070

71-
/*
72-
* Include snaps if they were requested or if this a zfs list where types
73-
* were not specified and the "listsnapshots" property is set on this pool.
74-
*/
75-
static boolean_t
76-
zfs_include_snapshots(zfs_handle_t *zhp, callback_data_t *cb)
77-
{
78-
zpool_handle_t *zph;
79-
80-
if ((cb->cb_flags & ZFS_ITER_PROP_LISTSNAPS) == 0)
81-
return (cb->cb_types & ZFS_TYPE_SNAPSHOT);
82-
83-
zph = zfs_get_pool_handle(zhp);
84-
return (zpool_get_prop_int(zph, ZPOOL_PROP_LISTSNAPS, NULL));
85-
}
86-
87-
/*
88-
* Called for each dataset. If the object is of an appropriate type,
89-
* add it to the avl tree and recurse over any children as necessary.
90-
*/
71+
/* Called for each dataset. */
9172
static int
9273
zfs_callback(zfs_handle_t *zhp, void *data)
9374
{
9475
callback_data_t *cb = data;
9576
boolean_t dontclose = B_FALSE;
96-
boolean_t include_snaps = zfs_include_snapshots(zhp, cb);
97-
boolean_t include_bmarks = (cb->cb_types & ZFS_TYPE_BOOKMARK);
98-
99-
if ((zfs_get_type(zhp) & cb->cb_types) ||
100-
((zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT) && include_snaps)) {
101-
uu_avl_index_t idx;
102-
zfs_node_t *node = safe_malloc(sizeof (zfs_node_t));
103-
104-
node->zn_handle = zhp;
105-
uu_avl_node_init(node, &node->zn_avlnode, avl_pool);
106-
if (uu_avl_find(cb->cb_avl, node, cb->cb_sortcol,
107-
&idx) == NULL) {
108-
if (cb->cb_proplist) {
109-
if ((*cb->cb_proplist) &&
110-
!(*cb->cb_proplist)->pl_all)
111-
zfs_prune_proplist(zhp,
112-
cb->cb_props_table);
113-
114-
if (zfs_expand_proplist(zhp, cb->cb_proplist,
115-
(cb->cb_flags & ZFS_ITER_RECVD_PROPS),
116-
(cb->cb_flags & ZFS_ITER_LITERAL_PROPS))
117-
!= 0) {
118-
free(node);
119-
return (-1);
120-
}
77+
uu_avl_index_t idx;
78+
zfs_node_t *node = safe_malloc(sizeof (zfs_node_t));
79+
80+
node->zn_handle = zhp;
81+
uu_avl_node_init(node, &node->zn_avlnode, avl_pool);
82+
if (uu_avl_find(cb->cb_avl, node, cb->cb_sortcol,
83+
&idx) == NULL) {
84+
if (cb->cb_proplist) {
85+
if ((*cb->cb_proplist) &&
86+
!(*cb->cb_proplist)->pl_all)
87+
zfs_prune_proplist(zhp,
88+
cb->cb_props_table);
89+
90+
if (zfs_expand_proplist(zhp, cb->cb_proplist,
91+
(cb->cb_flags & ZFS_ITER_RECVD_PROPS),
92+
(cb->cb_flags & ZFS_ITER_LITERAL_PROPS))
93+
!= 0) {
94+
free(node);
95+
return (-1);
12196
}
122-
uu_avl_insert(cb->cb_avl, node, idx);
123-
dontclose = B_TRUE;
124-
} else {
125-
free(node);
12697
}
127-
}
128-
129-
/*
130-
* Recurse if necessary.
131-
*/
132-
if (cb->cb_flags & ZFS_ITER_RECURSE &&
133-
((cb->cb_flags & ZFS_ITER_DEPTH_LIMIT) == 0 ||
134-
cb->cb_depth < cb->cb_depth_limit)) {
135-
cb->cb_depth++;
136-
if (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM)
137-
(void) zfs_iter_filesystems(zhp, zfs_callback, data);
138-
if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
139-
ZFS_TYPE_BOOKMARK)) == 0) && include_snaps)
140-
(void) zfs_iter_snapshots(zhp,
141-
(cb->cb_flags & ZFS_ITER_SIMPLE) != 0, zfs_callback,
142-
data);
143-
if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
144-
ZFS_TYPE_BOOKMARK)) == 0) && include_bmarks)
145-
(void) zfs_iter_bookmarks(zhp, zfs_callback, data);
146-
cb->cb_depth--;
98+
uu_avl_insert(cb->cb_avl, node, idx);
99+
dontclose = B_TRUE;
100+
} else {
101+
free(node);
147102
}
148103

149104
if (!dontclose)
@@ -378,6 +333,9 @@ zfs_for_each(int argc, char **argv, int flags, zfs_type_t types,
378333
int ret = 0;
379334
zfs_node_t *node;
380335
uu_avl_walk_t *walk;
336+
zfs_type_t argtype;
337+
zfs_type_t opentype;
338+
boolean_t limit_specified = !!(flags & ZFS_ITER_DEPTH_LIMIT);
381339

382340
avl_pool = uu_avl_pool_create("zfs_pool", sizeof (zfs_node_t),
383341
offsetof(zfs_node_t, zn_avlnode), zfs_sort, UU_DEFAULT);
@@ -386,6 +344,10 @@ zfs_for_each(int argc, char **argv, int flags, zfs_type_t types,
386344
nomem();
387345

388346
cb.cb_sortcol = sortcol;
347+
/*
348+
* XXX: We are phasing out the legacy recursive interface in
349+
* favor of the new stable list API.
350+
*/
389351
cb.cb_flags = flags;
390352
cb.cb_proplist = proplist;
391353
cb.cb_types = types;
@@ -431,39 +393,52 @@ zfs_for_each(int argc, char **argv, int flags, zfs_type_t types,
431393
if ((cb.cb_avl = uu_avl_create(avl_pool, NULL, UU_DEFAULT)) == NULL)
432394
nomem();
433395

396+
/*
397+
* zfs_iter_generic() lets the kernel worry about default types.
398+
*/
399+
argtype = types * !!(flags & ZFS_ITER_TYPES_SPECIFIED);
400+
opentype = argtype;
401+
if ((flags & ZFS_ITER_RECURSE) != 0 || limit_specified)
402+
opentype |= ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME;
434403
if (argc == 0) {
435404
/*
436405
* If given no arguments, iterate over all datasets.
437406
*/
438-
cb.cb_flags |= ZFS_ITER_RECURSE;
439-
ret = zfs_iter_root(g_zfs, zfs_callback, &cb);
407+
ret = zfs_iter_generic(g_zfs, NULL, argtype, 0,
408+
(limit_specified) ? limit : -1, limit_specified,
409+
zfs_callback, &cb);
440410
} else {
441411
int i;
442412
zfs_handle_t *zhp;
443-
zfs_type_t argtype;
444-
445-
/*
446-
* If we're recursive, then we always allow filesystems as
447-
* arguments. If we also are interested in snapshots, then we
448-
* can take volumes as well.
449-
*/
450-
argtype = types;
451-
if (flags & ZFS_ITER_RECURSE) {
452-
argtype |= ZFS_TYPE_FILESYSTEM;
453-
if (types & ZFS_TYPE_SNAPSHOT)
454-
argtype |= ZFS_TYPE_VOLUME;
455-
}
456413

457414
for (i = 0; i < argc; i++) {
415+
/*
416+
* Special case for bookmarks
417+
*/
418+
if (argv[i][0] != '/' &&
419+
strncmp(argv[i], "./", strlen("./")) != 0 &&
420+
strchr(argv[i], '#') != NULL) {
421+
ret = zfs_iter_generic(g_zfs, argv[i], argtype,
422+
0, 0, B_FALSE, zfs_callback, &cb);
423+
continue;
424+
}
425+
458426
if (flags & ZFS_ITER_ARGS_CAN_BE_PATHS) {
459427
zhp = zfs_path_to_zhandle(g_zfs, argv[i],
460-
argtype);
428+
opentype);
461429
} else {
462-
zhp = zfs_open(g_zfs, argv[i], argtype);
430+
zhp = zfs_open(g_zfs, argv[i],
431+
opentype);
463432
}
464-
if (zhp != NULL)
465-
ret |= zfs_callback(zhp, &cb);
466-
else
433+
if (zhp != NULL) {
434+
ret |= zfs_iter_generic(zfs_get_handle(zhp),
435+
zfs_get_name(zhp), argtype, 0,
436+
(limit_specified) ? limit : (flags &
437+
ZFS_ITER_RECURSE) ? -1 : 0,
438+
!(flags & ZFS_ITER_RECURSE), zfs_callback,
439+
&cb);
440+
zfs_close(zhp);
441+
} else
467442
ret = 1;
468443
}
469444
}

cmd/zfs/zfs_iter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ typedef struct zfs_sort_column {
4747
#define ZFS_ITER_RECVD_PROPS (1 << 4)
4848
#define ZFS_ITER_LITERAL_PROPS (1 << 5)
4949
#define ZFS_ITER_SIMPLE (1 << 6)
50+
#define ZFS_ITER_TYPES_SPECIFIED (1 << 7)
5051

5152
int zfs_for_each(int, char **, int options, zfs_type_t,
5253
zfs_sort_column_t *, zprop_list_t **, int, zfs_iter_f, void *);

0 commit comments

Comments
 (0)