5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Portions Copyright 2011 Martin Matuska
25 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
26 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
27 * Copyright (c) 2012 by Delphix. All rights reserved.
28 */
29
30 /*
31 * ZFS ioctls.
32 *
33 * This file handles the ioctls to /dev/zfs, used for configuring ZFS storage
34 * pools and filesystems, e.g. with /sbin/zfs and /sbin/zpool.
35 *
36 * There are two ways that we handle ioctls: the legacy way where almost
37 * all of the logic is in the ioctl callback, and the new way where most
38 * of the marshalling is handled in the common entry point, zfsdev_ioctl().
39 *
40 * Non-legacy ioctls should be registered by calling
41 * zfs_ioctl_register() from zfs_ioctl_init(). The ioctl is invoked
42 * from userland by lzc_ioctl().
43 *
44 * The registration arguments are as follows:
45 *
3155 cbfunc = zfs_create_cb;
3156 break;
3157
3158 case DMU_OST_ZVOL:
3159 cbfunc = zvol_create_cb;
3160 break;
3161
3162 default:
3163 cbfunc = NULL;
3164 break;
3165 }
3166 if (strchr(fsname, '@') ||
3167 strchr(fsname, '%'))
3168 return (EINVAL);
3169
3170 zct.zct_props = nvprops;
3171
3172 if (cbfunc == NULL)
3173 return (EINVAL);
3174
3175 if (zfs_get_parent(name, parent, MAXNAMELEN) == 0 &&
3176 zfs_is_wormed(parent)) {
3177 return (EPERM);
3178 }
3179
3180 if (type == DMU_OST_ZVOL) {
3181 uint64_t volsize, volblocksize;
3182
3183 if (nvprops == NULL)
3184 return (EINVAL);
3185 if (nvlist_lookup_uint64(nvprops,
3186 zfs_prop_to_name(ZFS_PROP_VOLSIZE), &volsize) != 0)
3187 return (EINVAL);
3188
3189 if ((error = nvlist_lookup_uint64(nvprops,
3190 zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
3191 &volblocksize)) != 0 && error != ENOENT)
3192 return (EINVAL);
3193
3194 if (error != 0)
3195 volblocksize = zfs_prop_default_numeric(
4171 error = dsl_dataset_hold_obj(dp,
4172 ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &dsfrom);
4173 rw_exit(&dp->dp_config_rwlock);
4174 if (error) {
4175 dsl_dataset_rele(ds, FTAG);
4176 return (error);
4177 }
4178 error = dmu_objset_from_ds(dsfrom, &fromsnap);
4179 if (error) {
4180 dsl_dataset_rele(dsfrom, FTAG);
4181 dsl_dataset_rele(ds, FTAG);
4182 return (error);
4183 }
4184 }
4185 }
4186
4187 if (estimate) {
4188 error = dmu_send_estimate(tosnap, fromsnap,
4189 &zc->zc_objset_type);
4190 } else {
4191 file_t *fp = getf(zc->zc_cookie);
4192 if (fp == NULL) {
4193 dsl_dataset_rele(ds, FTAG);
4194 if (dsfrom)
4195 dsl_dataset_rele(dsfrom, FTAG);
4196 return (EBADF);
4197 }
4198
4199 off = fp->f_offset;
4200 error = dmu_send(tosnap, fromsnap,
4201 zc->zc_cookie, fp->f_vnode, &off);
4202
4203 if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
4204 fp->f_offset = off;
4205 releasef(zc->zc_cookie);
4206 }
4207 if (dsfrom)
4208 dsl_dataset_rele(dsfrom, FTAG);
4209 dsl_dataset_rele(ds, FTAG);
4210 return (error);
4211 }
4212
4213 /*
4214 * inputs:
4215 * zc_name name of snapshot on which to report progress
4216 * zc_cookie file descriptor of send stream
4217 *
4218 * outputs:
4219 * zc_cookie number of bytes written in send stream thus far
4220 */
4221 static int
4222 zfs_ioc_send_progress(zfs_cmd_t *zc)
5155 return (error);
5156
5157 error = nvlist_lookup_string(innvl, "fromsnap", &fromname);
5158 if (error == 0) {
5159 error = dmu_objset_hold(fromname, FTAG, &fromsnap);
5160 if (error) {
5161 dmu_objset_rele(tosnap, FTAG);
5162 return (error);
5163 }
5164 }
5165
5166 file_t *fp = getf(fd);
5167 if (fp == NULL) {
5168 dmu_objset_rele(tosnap, FTAG);
5169 if (fromsnap != NULL)
5170 dmu_objset_rele(fromsnap, FTAG);
5171 return (EBADF);
5172 }
5173
5174 off = fp->f_offset;
5175 error = dmu_send(tosnap, fromsnap, fd, fp->f_vnode, &off);
5176
5177 if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
5178 fp->f_offset = off;
5179 releasef(fd);
5180 if (fromsnap != NULL)
5181 dmu_objset_rele(fromsnap, FTAG);
5182 dmu_objset_rele(tosnap, FTAG);
5183 return (error);
5184 }
5185
5186 /*
5187 * Determine approximately how large a zfs send stream will be -- the number
5188 * of bytes that will be written to the fd supplied to zfs_ioc_send_new().
5189 *
5190 * innvl: {
5191 * (optional) "fromsnap" -> full snap name to send an incremental from
5192 * }
5193 *
5194 * outnvl: {
5195 * "space" -> bytes of space (uint64)
|
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Portions Copyright 2011 Martin Matuska
25 * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
26 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
27 * Copyright (c) 2012 by Delphix. All rights reserved.
28 */
29
30 /*
31 * ZFS ioctls.
32 *
33 * This file handles the ioctls to /dev/zfs, used for configuring ZFS storage
34 * pools and filesystems, e.g. with /sbin/zfs and /sbin/zpool.
35 *
36 * There are two ways that we handle ioctls: the legacy way where almost
37 * all of the logic is in the ioctl callback, and the new way where most
38 * of the marshalling is handled in the common entry point, zfsdev_ioctl().
39 *
40 * Non-legacy ioctls should be registered by calling
41 * zfs_ioctl_register() from zfs_ioctl_init(). The ioctl is invoked
42 * from userland by lzc_ioctl().
43 *
44 * The registration arguments are as follows:
45 *
3155 cbfunc = zfs_create_cb;
3156 break;
3157
3158 case DMU_OST_ZVOL:
3159 cbfunc = zvol_create_cb;
3160 break;
3161
3162 default:
3163 cbfunc = NULL;
3164 break;
3165 }
3166 if (strchr(fsname, '@') ||
3167 strchr(fsname, '%'))
3168 return (EINVAL);
3169
3170 zct.zct_props = nvprops;
3171
3172 if (cbfunc == NULL)
3173 return (EINVAL);
3174
3175 if (zfs_get_parent(fsname, parent, MAXNAMELEN) == 0 &&
3176 zfs_is_wormed(parent)) {
3177 return (EPERM);
3178 }
3179
3180 if (type == DMU_OST_ZVOL) {
3181 uint64_t volsize, volblocksize;
3182
3183 if (nvprops == NULL)
3184 return (EINVAL);
3185 if (nvlist_lookup_uint64(nvprops,
3186 zfs_prop_to_name(ZFS_PROP_VOLSIZE), &volsize) != 0)
3187 return (EINVAL);
3188
3189 if ((error = nvlist_lookup_uint64(nvprops,
3190 zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
3191 &volblocksize)) != 0 && error != ENOENT)
3192 return (EINVAL);
3193
3194 if (error != 0)
3195 volblocksize = zfs_prop_default_numeric(
4171 error = dsl_dataset_hold_obj(dp,
4172 ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &dsfrom);
4173 rw_exit(&dp->dp_config_rwlock);
4174 if (error) {
4175 dsl_dataset_rele(ds, FTAG);
4176 return (error);
4177 }
4178 error = dmu_objset_from_ds(dsfrom, &fromsnap);
4179 if (error) {
4180 dsl_dataset_rele(dsfrom, FTAG);
4181 dsl_dataset_rele(ds, FTAG);
4182 return (error);
4183 }
4184 }
4185 }
4186
4187 if (estimate) {
4188 error = dmu_send_estimate(tosnap, fromsnap,
4189 &zc->zc_objset_type);
4190 } else {
4191 offset_t off_starting;
4192 file_t *fp = getf(zc->zc_cookie);
4193 if (fp == NULL) {
4194 dsl_dataset_rele(ds, FTAG);
4195 if (dsfrom)
4196 dsl_dataset_rele(dsfrom, FTAG);
4197 return (EBADF);
4198 }
4199
4200 off = fp->f_offset;
4201 off_starting = off;
4202 error = dmu_send(tosnap, fromsnap, zc->zc_cookie, fp->f_vnode,
4203 &off, zc->zc_sendsize);
4204
4205 zc->zc_sendcounter = off - off_starting;
4206 if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
4207 fp->f_offset = off;
4208 releasef(zc->zc_cookie);
4209 }
4210 if (dsfrom)
4211 dsl_dataset_rele(dsfrom, FTAG);
4212 dsl_dataset_rele(ds, FTAG);
4213 return (error);
4214 }
4215
4216 /*
4217 * inputs:
4218 * zc_name name of snapshot on which to report progress
4219 * zc_cookie file descriptor of send stream
4220 *
4221 * outputs:
4222 * zc_cookie number of bytes written in send stream thus far
4223 */
4224 static int
4225 zfs_ioc_send_progress(zfs_cmd_t *zc)
5158 return (error);
5159
5160 error = nvlist_lookup_string(innvl, "fromsnap", &fromname);
5161 if (error == 0) {
5162 error = dmu_objset_hold(fromname, FTAG, &fromsnap);
5163 if (error) {
5164 dmu_objset_rele(tosnap, FTAG);
5165 return (error);
5166 }
5167 }
5168
5169 file_t *fp = getf(fd);
5170 if (fp == NULL) {
5171 dmu_objset_rele(tosnap, FTAG);
5172 if (fromsnap != NULL)
5173 dmu_objset_rele(fromsnap, FTAG);
5174 return (EBADF);
5175 }
5176
5177 off = fp->f_offset;
5178 error = dmu_send(tosnap, fromsnap, fd, fp->f_vnode, &off, B_FALSE);
5179
5180 if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
5181 fp->f_offset = off;
5182 releasef(fd);
5183 if (fromsnap != NULL)
5184 dmu_objset_rele(fromsnap, FTAG);
5185 dmu_objset_rele(tosnap, FTAG);
5186 return (error);
5187 }
5188
5189 /*
5190 * Determine approximately how large a zfs send stream will be -- the number
5191 * of bytes that will be written to the fd supplied to zfs_ioc_send_new().
5192 *
5193 * innvl: {
5194 * (optional) "fromsnap" -> full snap name to send an incremental from
5195 * }
5196 *
5197 * outnvl: {
5198 * "space" -> bytes of space (uint64)
|