X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=lib%2Flibzfs%2Flibzfs_dataset.c;h=661f9b5f97eca7d6a468188c4061f36efcb07527;hb=c6327b63e6d3a11bb333829a8341d572e2fa7d9f;hp=74015139a3b2da8bf4d35ba28a90f37f9a8a85e1;hpb=0b7936d5c2337bc976ac831c1c38de563844c36b;p=zfs.git diff --git a/lib/libzfs/libzfs_dataset.c b/lib/libzfs/libzfs_dataset.c index 7401513..661f9b5 100644 --- a/lib/libzfs/libzfs_dataset.c +++ b/lib/libzfs/libzfs_dataset.c @@ -413,6 +413,9 @@ make_dataset_handle_common(zfs_handle_t *zhp, zfs_cmd_t *zc) zhp->zfs_head_type = ZFS_TYPE_VOLUME; else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) zhp->zfs_head_type = ZFS_TYPE_FILESYSTEM; + else if (zhp->zfs_dmustats.dds_type == DMU_OST_OTHER) + return (-1); /* zpios' and other testing datasets are + of this type, ignore if encountered */ else abort(); @@ -2249,15 +2252,19 @@ out: * convert the propname into parameters needed by kernel * Eg: userquota@ahrens -> ZFS_PROP_USERQUOTA, "", 126829 * Eg: userused@matt@domain -> ZFS_PROP_USERUSED, "S-1-123-456", 789 + * Eg: groupquota@staff -> ZFS_PROP_GROUPQUOTA, "", 1234 + * Eg: groupused@staff -> ZFS_PROP_GROUPUSED, "", 1234 */ static int userquota_propname_decode(const char *propname, boolean_t zoned, zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp) { zfs_userquota_prop_t type; - char *cp, *end; - char *numericsid = NULL; + char *cp; boolean_t isuser; + boolean_t isgroup; + struct passwd *pw; + struct group *gr; domain[0] = '\0'; @@ -2271,18 +2278,29 @@ userquota_propname_decode(const char *propname, boolean_t zoned, return (EINVAL); *typep = type; - isuser = (type == ZFS_PROP_USERQUOTA || - type == ZFS_PROP_USERUSED); + isuser = (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_USERUSED); + isgroup = (type == ZFS_PROP_GROUPQUOTA || type == ZFS_PROP_GROUPUSED); cp = strchr(propname, '@') + 1; - if (strchr(cp, '@')) { + if (isuser && (pw = getpwnam(cp)) != NULL) { + if (zoned && getzoneid() == GLOBAL_ZONEID) + return (ENOENT); + *ridp = pw->pw_uid; + } else if (isgroup && (gr = getgrnam(cp)) != NULL) { + if (zoned && getzoneid() == GLOBAL_ZONEID) + return (ENOENT); + *ridp = gr->gr_gid; + } else if (strchr(cp, '@')) { #ifdef HAVE_IDMAP /* * It's a SID name (eg "user@domain") that needs to be * turned into S-1-domainID-RID. */ directory_error_t e; + char *numericsid = NULL; + char *end; + if (zoned && getzoneid() == GLOBAL_ZONEID) return (ENOENT); if (isuser) { @@ -2299,14 +2317,6 @@ userquota_propname_decode(const char *propname, boolean_t zoned, if (numericsid == NULL) return (ENOENT); cp = numericsid; - /* will be further decoded below */ -#else - return (ENOSYS); -#endif /* HAVE_IDMAP */ - } - - if (strncmp(cp, "S-1-", 4) == 0) { - /* It's a numeric SID (eg "S-1-234-567-89") */ (void) strlcpy(domain, cp, domainlen); cp = strrchr(domain, '-'); *cp = '\0'; @@ -2314,39 +2324,22 @@ userquota_propname_decode(const char *propname, boolean_t zoned, errno = 0; *ridp = strtoull(cp, &end, 10); - if (numericsid) { - free(numericsid); - numericsid = NULL; - } + free(numericsid); + if (errno != 0 || *end != '\0') return (EINVAL); - } else if (!isdigit(*cp)) { - /* - * It's a user/group name (eg "user") that needs to be - * turned into a uid/gid - */ - if (zoned && getzoneid() == GLOBAL_ZONEID) - return (ENOENT); - if (isuser) { - struct passwd *pw; - pw = getpwnam(cp); - if (pw == NULL) - return (ENOENT); - *ridp = pw->pw_uid; - } else { - struct group *gr; - gr = getgrnam(cp); - if (gr == NULL) - return (ENOENT); - *ridp = gr->gr_gid; - } +#else + return (ENOSYS); +#endif /* HAVE_IDMAP */ } else { #ifdef HAVE_IDMAP /* It's a user/group ID (eg "12345"). */ - uid_t id = strtoul(cp, &end, 10); + uid_t id; idmap_rid_t rid; char *mapdomain; + char *end; + id = strtoul(cp, &end, 10); if (*end != '\0') return (EINVAL); if (id > MAXUID) { @@ -2364,7 +2357,6 @@ userquota_propname_decode(const char *propname, boolean_t zoned, #endif /* HAVE_IDMAP */ } - ASSERT3P(numericsid, ==, NULL); return (0); } @@ -3928,10 +3920,29 @@ int zvol_remove_link(libzfs_handle_t *hdl, const char *dataset) { zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 }; + int timeout = 3000; /* in milliseconds */ + int error = 0; + int i; (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); - if (ioctl(hdl->libzfs_fd, ZFS_IOC_REMOVE_MINOR, &zc) != 0) { + /* + * Due to concurrent updates by udev the device may be reported as + * busy. In this case don't immediately fail. Instead briefly delay + * and retry the ioctl() which is now likely to succeed. If unable + * remove the link after timeout milliseconds return the failure. + */ + for (i = 0; i < timeout; i++) { + error = ioctl(hdl->libzfs_fd, ZFS_IOC_REMOVE_MINOR, &zc); + if (error && errno == EBUSY) { + usleep(1000); + continue; + } else { + break; + } + } + + if (error) { switch (errno) { case ENXIO: /*