Limit maximum ashift value to 12
[zfs.git] / lib / libzfs / libzfs_dataset.c
index 378bbc7..7401513 100644 (file)
@@ -21,6 +21,8 @@
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
  */
 
 #include <ctype.h>
@@ -94,6 +96,7 @@ zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
        namecheck_err_t why;
        char what;
 
+       (void) zfs_prop_get_table();
        if (dataset_namecheck(path, &why, &what) != 0) {
                if (hdl != NULL) {
                        switch (why) {
@@ -1313,6 +1316,25 @@ zfs_setprop_error(libzfs_handle_t *hdl, zfs_prop_t prop, int err,
        }
 }
 
+static boolean_t
+zfs_is_namespace_prop(zfs_prop_t prop)
+{
+       switch (prop) {
+
+       case ZFS_PROP_ATIME:
+       case ZFS_PROP_DEVICES:
+       case ZFS_PROP_EXEC:
+       case ZFS_PROP_SETUID:
+       case ZFS_PROP_READONLY:
+       case ZFS_PROP_XATTR:
+       case ZFS_PROP_NBMAND:
+               return (B_TRUE);
+
+       default:
+               return (B_FALSE);
+       }
+}
+
 /*
  * Given a property name and value, set the property for the given dataset.
  */
@@ -1408,12 +1430,22 @@ zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
                if (do_prefix)
                        ret = changelist_postfix(cl);
 
-               /*
-                * Refresh the statistics so the new property value
-                * is reflected.
-                */
-               if (ret == 0)
+               if (ret == 0) {
+                       /*
+                        * Refresh the statistics so the new property
+                        * value is reflected.
+                        */
                        (void) get_stats(zhp);
+
+                       /*
+                        * Remount the filesystem to propagate the change
+                        * if one of the options handled by the generic
+                        * Linux namespace layer has been modified.
+                        */
+                       if (zfs_is_namespace_prop(prop) &&
+                           zfs_is_mounted(zhp, NULL))
+                               ret = zfs_mount(zhp, MNTOPT_REMOUNT, 0);
+               }
        }
 
 error:
@@ -1530,7 +1562,7 @@ error:
  * True DSL properties are stored in an nvlist.  The following two functions
  * extract them appropriately.
  */
-static uint64_t
+uint64_t
 getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
 {
        nvlist_t *nv;
@@ -1996,6 +2028,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
                }
                break;
 
+       case ZFS_PROP_REFRATIO:
        case ZFS_PROP_COMPRESSRATIO:
                if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
                        return (-1);
@@ -4282,6 +4315,193 @@ zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag,
        return (0);
 }
 
+int
+zfs_get_fsacl(zfs_handle_t *zhp, nvlist_t **nvl)
+{
+       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       libzfs_handle_t *hdl = zhp->zfs_hdl;
+       int nvsz = 2048;
+       void *nvbuf;
+       int err = 0;
+       char errbuf[ZFS_MAXNAMELEN+32];
+
+       assert(zhp->zfs_type == ZFS_TYPE_VOLUME ||
+           zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
+
+tryagain:
+
+       nvbuf = malloc(nvsz);
+       if (nvbuf == NULL) {
+               err = (zfs_error(hdl, EZFS_NOMEM, strerror(errno)));
+               goto out;
+       }
+
+       zc.zc_nvlist_dst_size = nvsz;
+       zc.zc_nvlist_dst = (uintptr_t)nvbuf;
+
+       (void) strlcpy(zc.zc_name, zhp->zfs_name, ZFS_MAXNAMELEN);
+
+       if (zfs_ioctl(hdl, ZFS_IOC_GET_FSACL, &zc) != 0) {
+               (void) snprintf(errbuf, sizeof (errbuf),
+                   dgettext(TEXT_DOMAIN, "cannot get permissions on '%s'"),
+                   zc.zc_name);
+               switch (errno) {
+               case ENOMEM:
+                       free(nvbuf);
+                       nvsz = zc.zc_nvlist_dst_size;
+                       goto tryagain;
+
+               case ENOTSUP:
+                       zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+                           "pool must be upgraded"));
+                       err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
+                       break;
+               case EINVAL:
+                       err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
+                       break;
+               case ENOENT:
+                       err = zfs_error(hdl, EZFS_NOENT, errbuf);
+                       break;
+               default:
+                       err = zfs_standard_error_fmt(hdl, errno, errbuf);
+                       break;
+               }
+       } else {
+               /* success */
+               int rc = nvlist_unpack(nvbuf, zc.zc_nvlist_dst_size, nvl, 0);
+               if (rc) {
+                       (void) snprintf(errbuf, sizeof (errbuf), dgettext(
+                           TEXT_DOMAIN, "cannot get permissions on '%s'"),
+                           zc.zc_name);
+                       err = zfs_standard_error_fmt(hdl, rc, errbuf);
+               }
+       }
+
+       free(nvbuf);
+out:
+       return (err);
+}
+
+int
+zfs_set_fsacl(zfs_handle_t *zhp, boolean_t un, nvlist_t *nvl)
+{
+       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       libzfs_handle_t *hdl = zhp->zfs_hdl;
+       char *nvbuf;
+       char errbuf[ZFS_MAXNAMELEN+32];
+       size_t nvsz;
+       int err;
+
+       assert(zhp->zfs_type == ZFS_TYPE_VOLUME ||
+           zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
+
+       err = nvlist_size(nvl, &nvsz, NV_ENCODE_NATIVE);
+       assert(err == 0);
+
+       nvbuf = malloc(nvsz);
+
+       err = nvlist_pack(nvl, &nvbuf, &nvsz, NV_ENCODE_NATIVE, 0);
+       assert(err == 0);
+
+       zc.zc_nvlist_src_size = nvsz;
+       zc.zc_nvlist_src = (uintptr_t)nvbuf;
+       zc.zc_perm_action = un;
+
+       (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
+
+       if (zfs_ioctl(hdl, ZFS_IOC_SET_FSACL, &zc) != 0) {
+               (void) snprintf(errbuf, sizeof (errbuf),
+                   dgettext(TEXT_DOMAIN, "cannot set permissions on '%s'"),
+                   zc.zc_name);
+               switch (errno) {
+               case ENOTSUP:
+                       zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+                           "pool must be upgraded"));
+                       err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
+                       break;
+               case EINVAL:
+                       err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
+                       break;
+               case ENOENT:
+                       err = zfs_error(hdl, EZFS_NOENT, errbuf);
+                       break;
+               default:
+                       err = zfs_standard_error_fmt(hdl, errno, errbuf);
+                       break;
+               }
+       }
+
+       free(nvbuf);
+
+       return (err);
+}
+
+int
+zfs_get_holds(zfs_handle_t *zhp, nvlist_t **nvl)
+{
+       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
+       libzfs_handle_t *hdl = zhp->zfs_hdl;
+       int nvsz = 2048;
+       void *nvbuf;
+       int err = 0;
+       char errbuf[ZFS_MAXNAMELEN+32];
+
+       assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
+
+tryagain:
+
+       nvbuf = malloc(nvsz);
+       if (nvbuf == NULL) {
+               err = (zfs_error(hdl, EZFS_NOMEM, strerror(errno)));
+               goto out;
+       }
+
+       zc.zc_nvlist_dst_size = nvsz;
+       zc.zc_nvlist_dst = (uintptr_t)nvbuf;
+
+       (void) strlcpy(zc.zc_name, zhp->zfs_name, ZFS_MAXNAMELEN);
+
+       if (zfs_ioctl(hdl, ZFS_IOC_GET_HOLDS, &zc) != 0) {
+               (void) snprintf(errbuf, sizeof (errbuf),
+                   dgettext(TEXT_DOMAIN, "cannot get holds for '%s'"),
+                   zc.zc_name);
+               switch (errno) {
+               case ENOMEM:
+                       free(nvbuf);
+                       nvsz = zc.zc_nvlist_dst_size;
+                       goto tryagain;
+
+               case ENOTSUP:
+                       zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+                           "pool must be upgraded"));
+                       err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
+                       break;
+               case EINVAL:
+                       err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
+                       break;
+               case ENOENT:
+                       err = zfs_error(hdl, EZFS_NOENT, errbuf);
+                       break;
+               default:
+                       err = zfs_standard_error_fmt(hdl, errno, errbuf);
+                       break;
+               }
+       } else {
+               /* success */
+               int rc = nvlist_unpack(nvbuf, zc.zc_nvlist_dst_size, nvl, 0);
+               if (rc) {
+                       (void) snprintf(errbuf, sizeof (errbuf),
+                           dgettext(TEXT_DOMAIN, "cannot get holds for '%s'"),
+                           zc.zc_name);
+                       err = zfs_standard_error_fmt(hdl, rc, errbuf);
+               }
+       }
+
+       free(nvbuf);
+out:
+       return (err);
+}
+
 uint64_t
 zvol_volsize_to_reservation(uint64_t volsize, nvlist_t *props)
 {