aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMatthew Ahrens <[email protected]>2021-05-06 11:24:56 -0700
committerGitHub <[email protected]>2021-05-06 11:24:56 -0700
commit610cb4fb8c6e8c354d3796e98932e79d45d057a4 (patch)
treef39d049113bb64cd09000fc6cfe9ccc38c7609b0 /lib
parentb1e44cdcea09db50c887c2b301e1af1fae1b5aa0 (diff)
undocumented libzfs API changes broke "zfs list"
While OpenZFS does permit breaking changes to the libzfs API, we should avoid these changes when reasonably possible, and take steps to mitigate the impact to consumers when changes are necessary. Commit e4288a8397bb1f made a libzfs API change that is especially difficult for consumers because there is no change to the function signatures, only to their behavior. Therefore, consumers can't notice that there was a change at compile time. Also, the API change was incompletely and incorrectly documented. The commit message mentions `zfs_get_prop()` [sic], but all callers of `get_numeric_property()` are impacted: `zfs_prop_get()`, `zfs_prop_get_numeric()`, and `zfs_prop_get_int()`. `zfs_prop_get_int()` always calls `get_numeric_property(src=NULL)`, so it assumes that the filesystem is not mounted. This means that e.g. `zfs_prop_get_int(ZFS_PROP_MOUNTED)` always returns 0. The documentation says that to preserve the previous behavior, callers should initialize `*src=ZPROP_SRC_NONE`, and some callers were changed to do that. However, the existing behavior is actually preserved by initializing `*src=ZPROP_SRC_ALL`, not `NONE`. The code comment above `zfs_prop_get()` says, "src: ... NULL will be treated as ZPROP_SRC_ALL.". However, the code actually treats NULL as ZPROP_SRC_NONE. i.e. `zfs_prop_get(src=NULL)` assumes that the filesystem is not mounted. There are several existing calls which use `src=NULL` which are impacted by the API change, most noticeably those used by `zfs list`, which now assumes that filesystems are not mounted. For example, `zfs list -o name,mounted` previously indicated whether a filesystem was mounted or not, but now it always (incorrectly) indicates that the filesystem is not mounted (`MOUNTED: no`). Similarly, properties that are set at mount time are ignored. E.g. `zfs list -o name,atime` may display an incorrect value if it was set at mount time. To address these problems, this commit reverts commit e4288a8397bb1f: "zfs get: don't lookup mount options when using "-s local"" Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Matthew Ahrens <[email protected]> Closes #11999
Diffstat (limited to 'lib')
-rw-r--r--lib/libzfs/libzfs_dataset.c19
-rw-r--r--lib/libzfs/libzfs_diff.c2
-rw-r--r--lib/libzfs/libzfs_mount.c4
-rw-r--r--lib/libzfs/libzfs_sendrecv.c2
4 files changed, 11 insertions, 16 deletions
diff --git a/lib/libzfs/libzfs_dataset.c b/lib/libzfs/libzfs_dataset.c
index dd2572b01..823fcb284 100644
--- a/lib/libzfs/libzfs_dataset.c
+++ b/lib/libzfs/libzfs_dataset.c
@@ -2180,8 +2180,7 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
* its presence.
*/
if (!zhp->zfs_mntcheck &&
- (mntopt_on != NULL || prop == ZFS_PROP_MOUNTED) &&
- (src && (*src & ZPROP_SRC_TEMPORARY))) {
+ (mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) {
libzfs_handle_t *hdl = zhp->zfs_hdl;
struct mnttab entry;
@@ -2596,16 +2595,9 @@ zcp_check(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t intval,
}
/*
- * Retrieve a property from the given object.
- *
- * Arguments:
- * src : On call, this must contain the bitmap of ZPROP_SRC_* types to
- * query. Properties whose values come from a different source
- * may not be returned. NULL will be treated as ZPROP_SRC_ALL. On
- * return, if not NULL, this variable will contain the source for
- * the queried property.
- * literal : If specified, then numbers are left as exact values. Otherwise,
- * they are converted to a human-readable form.
+ * Retrieve a property from the given object. If 'literal' is specified, then
+ * numbers are left as exact values. Otherwise, numbers are converted to a
+ * human-readable form.
*
* Returns 0 on success, or -1 on error.
*/
@@ -2628,6 +2620,9 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
if (received && zfs_prop_readonly(prop))
return (-1);
+ if (src)
+ *src = ZPROP_SRC_NONE;
+
switch (prop) {
case ZFS_PROP_CREATION:
/*
diff --git a/lib/libzfs/libzfs_diff.c b/lib/libzfs/libzfs_diff.c
index 1eda8bad1..12e079b0e 100644
--- a/lib/libzfs/libzfs_diff.c
+++ b/lib/libzfs/libzfs_diff.c
@@ -575,7 +575,7 @@ get_snapshot_names(differ_info_t *di, const char *fromsnap,
* tosnap is a clone of a fromsnap descendant.
*/
char origin[ZFS_MAX_DATASET_NAME_LEN];
- zprop_source_t src = ZPROP_SRC_NONE;
+ zprop_source_t src;
zfs_handle_t *zhp;
di->ds = zfs_alloc(di->zhp->zfs_hdl, tdslen + 1);
diff --git a/lib/libzfs/libzfs_mount.c b/lib/libzfs/libzfs_mount.c
index 37958a342..3df42e2dc 100644
--- a/lib/libzfs/libzfs_mount.c
+++ b/lib/libzfs/libzfs_mount.c
@@ -266,7 +266,7 @@ zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen,
zprop_source_t *source, int flags)
{
char sourceloc[MAXNAMELEN];
- zprop_source_t sourcetype = ZPROP_SRC_NONE;
+ zprop_source_t sourcetype;
if (!zfs_prop_valid_for_type(ZFS_PROP_MOUNTPOINT, zhp->zfs_type,
B_FALSE))
@@ -765,7 +765,7 @@ zfs_share_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto)
char shareopts[ZFS_MAXPROPLEN];
char sourcestr[ZFS_MAXPROPLEN];
zfs_share_proto_t *curr_proto;
- zprop_source_t sourcetype = ZPROP_SRC_NONE;
+ zprop_source_t sourcetype;
int err = 0;
if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL, 0))
diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c
index 8c55d6044..511895d18 100644
--- a/lib/libzfs/libzfs_sendrecv.c
+++ b/lib/libzfs/libzfs_sendrecv.c
@@ -2662,7 +2662,7 @@ static zfs_handle_t *
recv_open_grand_origin(zfs_handle_t *zhp)
{
char origin[ZFS_MAX_DATASET_NAME_LEN];
- zprop_source_t src = ZPROP_SRC_NONE;
+ zprop_source_t src;
zfs_handle_t *ozhp = zfs_handle_dup(zhp);
while (ozhp != NULL) {