1 789 ahrens /* 2 789 ahrens * CDDL HEADER START 3 789 ahrens * 4 789 ahrens * The contents of this file are subject to the terms of the 5 1544 eschrock * Common Development and Distribution License (the "License"). 6 1544 eschrock * You may not use this file except in compliance with the License. 7 789 ahrens * 8 789 ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 789 ahrens * or http://www.opensolaris.org/os/licensing. 10 789 ahrens * See the License for the specific language governing permissions 11 789 ahrens * and limitations under the License. 12 789 ahrens * 13 789 ahrens * When distributing Covered Code, include this CDDL HEADER in each 14 789 ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 789 ahrens * If applicable, add the following below this CDDL HEADER, with the 16 789 ahrens * fields enclosed by brackets "[]" replaced with your own identifying 17 789 ahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18 789 ahrens * 19 789 ahrens * CDDL HEADER END 20 789 ahrens */ 21 3126 ahl 22 789 ahrens /* 23 8536 David * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 789 ahrens * Use is subject to license terms. 25 789 ahrens */ 26 789 ahrens 27 789 ahrens /* 28 789 ahrens * Routines to manage ZFS mounts. We separate all the nasty routines that have 29 3126 ahl * to deal with the OS. The following functions are the main entry points -- 30 3126 ahl * they are used by mount and unmount and when changing a filesystem's 31 3126 ahl * mountpoint. 32 789 ahrens * 33 789 ahrens * zfs_is_mounted() 34 789 ahrens * zfs_mount() 35 789 ahrens * zfs_unmount() 36 789 ahrens * zfs_unmountall() 37 789 ahrens * 38 3126 ahl * This file also contains the functions used to manage sharing filesystems via 39 3126 ahl * NFS and iSCSI: 40 789 ahrens * 41 789 ahrens * zfs_is_shared() 42 789 ahrens * zfs_share() 43 789 ahrens * zfs_unshare() 44 3126 ahl * 45 3126 ahl * zfs_is_shared_nfs() 46 5331 amw * zfs_is_shared_smb() 47 5331 amw * zfs_is_shared_iscsi() 48 5331 amw * zfs_share_proto() 49 5331 amw * zfs_shareall(); 50 5331 amw * zfs_share_iscsi() 51 3126 ahl * zfs_unshare_nfs() 52 5331 amw * zfs_unshare_smb() 53 3126 ahl * zfs_unshareall_nfs() 54 5331 amw * zfs_unshareall_smb() 55 5331 amw * zfs_unshareall() 56 5331 amw * zfs_unshareall_bypath() 57 3126 ahl * zfs_unshare_iscsi() 58 2474 eschrock * 59 2474 eschrock * The following functions are available for pool consumers, and will 60 3126 ahl * mount/unmount and share/unshare all datasets within pool: 61 2474 eschrock * 62 3126 ahl * zpool_enable_datasets() 63 3126 ahl * zpool_disable_datasets() 64 789 ahrens */ 65 789 ahrens 66 789 ahrens #include <dirent.h> 67 3134 ahl #include <dlfcn.h> 68 789 ahrens #include <errno.h> 69 789 ahrens #include <libgen.h> 70 789 ahrens #include <libintl.h> 71 789 ahrens #include <stdio.h> 72 789 ahrens #include <stdlib.h> 73 789 ahrens #include <strings.h> 74 789 ahrens #include <unistd.h> 75 789 ahrens #include <zone.h> 76 789 ahrens #include <sys/mntent.h> 77 789 ahrens #include <sys/mount.h> 78 789 ahrens #include <sys/stat.h> 79 789 ahrens 80 789 ahrens #include <libzfs.h> 81 789 ahrens 82 789 ahrens #include "libzfs_impl.h" 83 4180 dougm 84 4180 dougm #include <libshare.h> 85 4180 dougm #include <sys/systeminfo.h> 86 4180 dougm #define MAXISALEN 257 /* based on sysinfo(2) man page */ 87 3134 ahl 88 5331 amw static int zfs_share_proto(zfs_handle_t *, zfs_share_proto_t *); 89 5331 amw zfs_share_type_t zfs_is_shared_proto(zfs_handle_t *, char **, 90 5331 amw zfs_share_proto_t); 91 5331 amw 92 3134 ahl static int (*iscsitgt_zfs_share)(const char *); 93 3134 ahl static int (*iscsitgt_zfs_unshare)(const char *); 94 3134 ahl static int (*iscsitgt_zfs_is_shared)(const char *); 95 4543 marks static int (*iscsitgt_svc_online)(); 96 5331 amw 97 5331 amw /* 98 5331 amw * The share protocols table must be in the same order as the zfs_share_prot_t 99 5331 amw * enum in libzfs_impl.h 100 5331 amw */ 101 5331 amw typedef struct { 102 5331 amw zfs_prop_t p_prop; 103 5331 amw char *p_name; 104 5331 amw int p_share_err; 105 5331 amw int p_unshare_err; 106 5331 amw } proto_table_t; 107 5331 amw 108 5331 amw proto_table_t proto_table[PROTO_END] = { 109 5331 amw {ZFS_PROP_SHARENFS, "nfs", EZFS_SHARENFSFAILED, EZFS_UNSHARENFSFAILED}, 110 5331 amw {ZFS_PROP_SHARESMB, "smb", EZFS_SHARESMBFAILED, EZFS_UNSHARESMBFAILED}, 111 5331 amw }; 112 5331 amw 113 5331 amw zfs_share_proto_t nfs_only[] = { 114 5331 amw PROTO_NFS, 115 5331 amw PROTO_END 116 5331 amw }; 117 5331 amw 118 5331 amw zfs_share_proto_t smb_only[] = { 119 5331 amw PROTO_SMB, 120 5331 amw PROTO_END 121 5331 amw }; 122 5331 amw zfs_share_proto_t share_all_proto[] = { 123 5331 amw PROTO_NFS, 124 5331 amw PROTO_SMB, 125 5331 amw PROTO_END 126 5331 amw }; 127 3134 ahl 128 3134 ahl #pragma init(zfs_iscsi_init) 129 3134 ahl static void 130 3134 ahl zfs_iscsi_init(void) 131 3134 ahl { 132 3134 ahl void *libiscsitgt; 133 3134 ahl 134 3134 ahl if ((libiscsitgt = dlopen("/lib/libiscsitgt.so.1", 135 3134 ahl RTLD_LAZY | RTLD_GLOBAL)) == NULL || 136 3134 ahl (iscsitgt_zfs_share = (int (*)(const char *))dlsym(libiscsitgt, 137 3134 ahl "iscsitgt_zfs_share")) == NULL || 138 3134 ahl (iscsitgt_zfs_unshare = (int (*)(const char *))dlsym(libiscsitgt, 139 3134 ahl "iscsitgt_zfs_unshare")) == NULL || 140 3134 ahl (iscsitgt_zfs_is_shared = (int (*)(const char *))dlsym(libiscsitgt, 141 4543 marks "iscsitgt_zfs_is_shared")) == NULL || 142 4543 marks (iscsitgt_svc_online = (int (*)(const char *))dlsym(libiscsitgt, 143 4543 marks "iscsitgt_svc_online")) == NULL) { 144 3134 ahl iscsitgt_zfs_share = NULL; 145 3134 ahl iscsitgt_zfs_unshare = NULL; 146 3134 ahl iscsitgt_zfs_is_shared = NULL; 147 4543 marks iscsitgt_svc_online = NULL; 148 3134 ahl } 149 3134 ahl } 150 789 ahrens 151 789 ahrens /* 152 5331 amw * Search the sharetab for the given mountpoint and protocol, returning 153 5331 amw * a zfs_share_type_t value. 154 789 ahrens */ 155 5331 amw static zfs_share_type_t 156 5331 amw is_shared(libzfs_handle_t *hdl, const char *mountpoint, zfs_share_proto_t proto) 157 789 ahrens { 158 789 ahrens char buf[MAXPATHLEN], *tab; 159 5331 amw char *ptr; 160 789 ahrens 161 2082 eschrock if (hdl->libzfs_sharetab == NULL) 162 5331 amw return (SHARED_NOT_SHARED); 163 789 ahrens 164 2082 eschrock (void) fseek(hdl->libzfs_sharetab, 0, SEEK_SET); 165 789 ahrens 166 2082 eschrock while (fgets(buf, sizeof (buf), hdl->libzfs_sharetab) != NULL) { 167 789 ahrens 168 789 ahrens /* the mountpoint is the first entry on each line */ 169 5331 amw if ((tab = strchr(buf, '\t')) == NULL) 170 5331 amw continue; 171 5331 amw 172 5331 amw *tab = '\0'; 173 5331 amw if (strcmp(buf, mountpoint) == 0) { 174 5331 amw /* 175 5331 amw * the protocol field is the third field 176 5331 amw * skip over second field 177 5331 amw */ 178 5331 amw ptr = ++tab; 179 5331 amw if ((tab = strchr(ptr, '\t')) == NULL) 180 5331 amw continue; 181 5331 amw ptr = ++tab; 182 5331 amw if ((tab = strchr(ptr, '\t')) == NULL) 183 5331 amw continue; 184 789 ahrens *tab = '\0'; 185 5331 amw if (strcmp(ptr, 186 5331 amw proto_table[proto].p_name) == 0) { 187 5331 amw switch (proto) { 188 5331 amw case PROTO_NFS: 189 5331 amw return (SHARED_NFS); 190 5331 amw case PROTO_SMB: 191 5331 amw return (SHARED_SMB); 192 5331 amw default: 193 5331 amw return (0); 194 5331 amw } 195 5331 amw } 196 789 ahrens } 197 789 ahrens } 198 789 ahrens 199 5331 amw return (SHARED_NOT_SHARED); 200 789 ahrens } 201 789 ahrens 202 789 ahrens /* 203 2082 eschrock * Returns true if the specified directory is empty. If we can't open the 204 2082 eschrock * directory at all, return true so that the mount can fail with a more 205 789 ahrens * informative error message. 206 789 ahrens */ 207 2082 eschrock static boolean_t 208 789 ahrens dir_is_empty(const char *dirname) 209 789 ahrens { 210 789 ahrens DIR *dirp; 211 789 ahrens struct dirent64 *dp; 212 789 ahrens 213 789 ahrens if ((dirp = opendir(dirname)) == NULL) 214 2082 eschrock return (B_TRUE); 215 789 ahrens 216 789 ahrens while ((dp = readdir64(dirp)) != NULL) { 217 789 ahrens 218 789 ahrens if (strcmp(dp->d_name, ".") == 0 || 219 789 ahrens strcmp(dp->d_name, "..") == 0) 220 789 ahrens continue; 221 789 ahrens 222 789 ahrens (void) closedir(dirp); 223 2082 eschrock return (B_FALSE); 224 789 ahrens } 225 789 ahrens 226 789 ahrens (void) closedir(dirp); 227 2082 eschrock return (B_TRUE); 228 789 ahrens } 229 789 ahrens 230 789 ahrens /* 231 789 ahrens * Checks to see if the mount is active. If the filesystem is mounted, we fill 232 789 ahrens * in 'where' with the current mountpoint, and return 1. Otherwise, we return 233 789 ahrens * 0. 234 789 ahrens */ 235 2082 eschrock boolean_t 236 3444 ek110237 is_mounted(libzfs_handle_t *zfs_hdl, const char *special, char **where) 237 789 ahrens { 238 8228 Eric struct mnttab entry; 239 789 ahrens 240 8228 Eric if (libzfs_mnttab_find(zfs_hdl, special, &entry) != 0) 241 2082 eschrock return (B_FALSE); 242 789 ahrens 243 789 ahrens if (where != NULL) 244 3444 ek110237 *where = zfs_strdup(zfs_hdl, entry.mnt_mountp); 245 789 ahrens 246 2082 eschrock return (B_TRUE); 247 3444 ek110237 } 248 3444 ek110237 249 3444 ek110237 boolean_t 250 3444 ek110237 zfs_is_mounted(zfs_handle_t *zhp, char **where) 251 3444 ek110237 { 252 3444 ek110237 return (is_mounted(zhp->zfs_hdl, zfs_get_name(zhp), where)); 253 789 ahrens } 254 789 ahrens 255 789 ahrens /* 256 2676 eschrock * Returns true if the given dataset is mountable, false otherwise. Returns the 257 2676 eschrock * mountpoint in 'buf'. 258 2676 eschrock */ 259 2676 eschrock static boolean_t 260 2676 eschrock zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen, 261 5094 lling zprop_source_t *source) 262 2676 eschrock { 263 2676 eschrock char sourceloc[ZFS_MAXNAMELEN]; 264 5094 lling zprop_source_t sourcetype; 265 2676 eschrock 266 2676 eschrock if (!zfs_prop_valid_for_type(ZFS_PROP_MOUNTPOINT, zhp->zfs_type)) 267 2676 eschrock return (B_FALSE); 268 2676 eschrock 269 2676 eschrock verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, buf, buflen, 270 2676 eschrock &sourcetype, sourceloc, sizeof (sourceloc), B_FALSE) == 0); 271 2676 eschrock 272 2676 eschrock if (strcmp(buf, ZFS_MOUNTPOINT_NONE) == 0 || 273 2676 eschrock strcmp(buf, ZFS_MOUNTPOINT_LEGACY) == 0) 274 2676 eschrock return (B_FALSE); 275 2676 eschrock 276 6168 hs24103 if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_OFF) 277 2676 eschrock return (B_FALSE); 278 2676 eschrock 279 2676 eschrock if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) && 280 2676 eschrock getzoneid() == GLOBAL_ZONEID) 281 2676 eschrock return (B_FALSE); 282 2676 eschrock 283 2676 eschrock if (source) 284 2676 eschrock *source = sourcetype; 285 2676 eschrock 286 2676 eschrock return (B_TRUE); 287 2676 eschrock } 288 2676 eschrock 289 2676 eschrock /* 290 789 ahrens * Mount the given filesystem. 291 789 ahrens */ 292 789 ahrens int 293 789 ahrens zfs_mount(zfs_handle_t *zhp, const char *options, int flags) 294 789 ahrens { 295 789 ahrens struct stat buf; 296 789 ahrens char mountpoint[ZFS_MAXPROPLEN]; 297 789 ahrens char mntopts[MNT_LINE_MAX]; 298 2082 eschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 299 789 ahrens 300 789 ahrens if (options == NULL) 301 789 ahrens mntopts[0] = '\0'; 302 789 ahrens else 303 789 ahrens (void) strlcpy(mntopts, options, sizeof (mntopts)); 304 789 ahrens 305 2676 eschrock if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL)) 306 2082 eschrock return (0); 307 789 ahrens 308 789 ahrens /* Create the directory if it doesn't already exist */ 309 789 ahrens if (lstat(mountpoint, &buf) != 0) { 310 789 ahrens if (mkdirp(mountpoint, 0755) != 0) { 311 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 312 2082 eschrock "failed to create mountpoint")); 313 3237 lling return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED, 314 2082 eschrock dgettext(TEXT_DOMAIN, "cannot mount '%s'"), 315 2082 eschrock mountpoint)); 316 789 ahrens } 317 789 ahrens } 318 789 ahrens 319 789 ahrens /* 320 789 ahrens * Determine if the mountpoint is empty. If so, refuse to perform the 321 789 ahrens * mount. We don't perform this check if MS_OVERLAY is specified, which 322 789 ahrens * would defeat the point. We also avoid this check if 'remount' is 323 789 ahrens * specified. 324 789 ahrens */ 325 789 ahrens if ((flags & MS_OVERLAY) == 0 && 326 789 ahrens strstr(mntopts, MNTOPT_REMOUNT) == NULL && 327 789 ahrens !dir_is_empty(mountpoint)) { 328 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 329 2082 eschrock "directory is not empty")); 330 3237 lling return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED, 331 2082 eschrock dgettext(TEXT_DOMAIN, "cannot mount '%s'"), mountpoint)); 332 789 ahrens } 333 789 ahrens 334 789 ahrens /* perform the mount */ 335 789 ahrens if (mount(zfs_get_name(zhp), mountpoint, MS_OPTIONSTR | flags, 336 789 ahrens MNTTYPE_ZFS, NULL, 0, mntopts, sizeof (mntopts)) != 0) { 337 789 ahrens /* 338 789 ahrens * Generic errors are nasty, but there are just way too many 339 789 ahrens * from mount(), and they're well-understood. We pick a few 340 789 ahrens * common ones to improve upon. 341 789 ahrens */ 342 4302 dougm if (errno == EBUSY) { 343 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 344 2082 eschrock "mountpoint or dataset is busy")); 345 4543 marks } else if (errno == EPERM) { 346 4543 marks zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 347 4543 marks "Insufficient privileges")); 348 4302 dougm } else { 349 2082 eschrock zfs_error_aux(hdl, strerror(errno)); 350 4302 dougm } 351 3237 lling return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED, 352 2082 eschrock dgettext(TEXT_DOMAIN, "cannot mount '%s'"), 353 2082 eschrock zhp->zfs_name)); 354 789 ahrens } 355 789 ahrens 356 8228 Eric /* add the mounted entry into our cache */ 357 8228 Eric libzfs_mnttab_add(hdl, zfs_get_name(zhp), mountpoint, 358 8228 Eric mntopts); 359 789 ahrens return (0); 360 789 ahrens } 361 789 ahrens 362 789 ahrens /* 363 2474 eschrock * Unmount a single filesystem. 364 2474 eschrock */ 365 2474 eschrock static int 366 2474 eschrock unmount_one(libzfs_handle_t *hdl, const char *mountpoint, int flags) 367 2474 eschrock { 368 2474 eschrock if (umount2(mountpoint, flags) != 0) { 369 2474 eschrock zfs_error_aux(hdl, strerror(errno)); 370 3237 lling return (zfs_error_fmt(hdl, EZFS_UMOUNTFAILED, 371 2474 eschrock dgettext(TEXT_DOMAIN, "cannot unmount '%s'"), 372 2474 eschrock mountpoint)); 373 2474 eschrock } 374 2474 eschrock 375 2474 eschrock return (0); 376 2474 eschrock } 377 2474 eschrock 378 2474 eschrock /* 379 789 ahrens * Unmount the given filesystem. 380 789 ahrens */ 381 789 ahrens int 382 789 ahrens zfs_unmount(zfs_handle_t *zhp, const char *mountpoint, int flags) 383 789 ahrens { 384 8228 Eric libzfs_handle_t *hdl = zhp->zfs_hdl; 385 8228 Eric struct mnttab entry; 386 4180 dougm char *mntpt = NULL; 387 789 ahrens 388 8228 Eric /* check to see if we need to unmount the filesystem */ 389 789 ahrens if (mountpoint != NULL || ((zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) && 390 8228 Eric libzfs_mnttab_find(hdl, zhp->zfs_name, &entry) == 0)) { 391 4180 dougm /* 392 4180 dougm * mountpoint may have come from a call to 393 4180 dougm * getmnt/getmntany if it isn't NULL. If it is NULL, 394 8228 Eric * we know it comes from libzfs_mnttab_find which can 395 8228 Eric * then get freed later. We strdup it to play it safe. 396 4180 dougm */ 397 789 ahrens if (mountpoint == NULL) 398 8228 Eric mntpt = zfs_strdup(hdl, entry.mnt_mountp); 399 4180 dougm else 400 8228 Eric mntpt = zfs_strdup(hdl, mountpoint); 401 789 ahrens 402 789 ahrens /* 403 2474 eschrock * Unshare and unmount the filesystem 404 789 ahrens */ 405 5331 amw if (zfs_unshare_proto(zhp, mntpt, share_all_proto) != 0) 406 4331 th199096 return (-1); 407 4331 th199096 408 8228 Eric if (unmount_one(hdl, mntpt, flags) != 0) { 409 4180 dougm free(mntpt); 410 5331 amw (void) zfs_shareall(zhp); 411 789 ahrens return (-1); 412 4180 dougm } 413 8228 Eric libzfs_mnttab_remove(hdl, zhp->zfs_name); 414 4180 dougm free(mntpt); 415 789 ahrens } 416 789 ahrens 417 789 ahrens return (0); 418 789 ahrens } 419 789 ahrens 420 789 ahrens /* 421 789 ahrens * Unmount this filesystem and any children inheriting the mountpoint property. 422 789 ahrens * To do this, just act like we're changing the mountpoint property, but don't 423 789 ahrens * remount the filesystems afterwards. 424 789 ahrens */ 425 789 ahrens int 426 789 ahrens zfs_unmountall(zfs_handle_t *zhp, int flags) 427 789 ahrens { 428 789 ahrens prop_changelist_t *clp; 429 789 ahrens int ret; 430 789 ahrens 431 7366 Tim clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT, 0, flags); 432 789 ahrens if (clp == NULL) 433 789 ahrens return (-1); 434 789 ahrens 435 789 ahrens ret = changelist_prefix(clp); 436 789 ahrens changelist_free(clp); 437 789 ahrens 438 789 ahrens return (ret); 439 789 ahrens } 440 789 ahrens 441 3126 ahl boolean_t 442 3126 ahl zfs_is_shared(zfs_handle_t *zhp) 443 3126 ahl { 444 5331 amw zfs_share_type_t rc = 0; 445 5331 amw zfs_share_proto_t *curr_proto; 446 5331 amw 447 3126 ahl if (ZFS_IS_VOLUME(zhp)) 448 3126 ahl return (zfs_is_shared_iscsi(zhp)); 449 3126 ahl 450 5331 amw for (curr_proto = share_all_proto; *curr_proto != PROTO_END; 451 5331 amw curr_proto++) 452 5331 amw rc |= zfs_is_shared_proto(zhp, NULL, *curr_proto); 453 5331 amw 454 5331 amw return (rc ? B_TRUE : B_FALSE); 455 3126 ahl } 456 3126 ahl 457 3126 ahl int 458 3126 ahl zfs_share(zfs_handle_t *zhp) 459 3126 ahl { 460 3126 ahl if (ZFS_IS_VOLUME(zhp)) 461 3126 ahl return (zfs_share_iscsi(zhp)); 462 3126 ahl 463 5331 amw return (zfs_share_proto(zhp, share_all_proto)); 464 3126 ahl } 465 3126 ahl 466 3126 ahl int 467 3126 ahl zfs_unshare(zfs_handle_t *zhp) 468 3126 ahl { 469 3126 ahl if (ZFS_IS_VOLUME(zhp)) 470 3126 ahl return (zfs_unshare_iscsi(zhp)); 471 3126 ahl 472 5331 amw return (zfs_unshareall(zhp)); 473 3126 ahl } 474 3126 ahl 475 789 ahrens /* 476 789 ahrens * Check to see if the filesystem is currently shared. 477 789 ahrens */ 478 5331 amw zfs_share_type_t 479 5331 amw zfs_is_shared_proto(zfs_handle_t *zhp, char **where, zfs_share_proto_t proto) 480 789 ahrens { 481 789 ahrens char *mountpoint; 482 5331 amw zfs_share_type_t rc; 483 789 ahrens 484 789 ahrens if (!zfs_is_mounted(zhp, &mountpoint)) 485 5331 amw return (SHARED_NOT_SHARED); 486 789 ahrens 487 5331 amw if (rc = is_shared(zhp->zfs_hdl, mountpoint, proto)) { 488 789 ahrens if (where != NULL) 489 789 ahrens *where = mountpoint; 490 789 ahrens else 491 789 ahrens free(mountpoint); 492 5331 amw return (rc); 493 789 ahrens } else { 494 789 ahrens free(mountpoint); 495 5331 amw return (SHARED_NOT_SHARED); 496 789 ahrens } 497 5331 amw } 498 5331 amw 499 5331 amw boolean_t 500 5331 amw zfs_is_shared_nfs(zfs_handle_t *zhp, char **where) 501 5331 amw { 502 5331 amw return (zfs_is_shared_proto(zhp, where, 503 5331 amw PROTO_NFS) != SHARED_NOT_SHARED); 504 5331 amw } 505 5331 amw 506 5331 amw boolean_t 507 5331 amw zfs_is_shared_smb(zfs_handle_t *zhp, char **where) 508 5331 amw { 509 5331 amw return (zfs_is_shared_proto(zhp, where, 510 5331 amw PROTO_SMB) != SHARED_NOT_SHARED); 511 789 ahrens } 512 789 ahrens 513 789 ahrens /* 514 4180 dougm * Make sure things will work if libshare isn't installed by using 515 4180 dougm * wrapper functions that check to see that the pointers to functions 516 4180 dougm * initialized in _zfs_init_libshare() are actually present. 517 4180 dougm */ 518 4180 dougm 519 4180 dougm static sa_handle_t (*_sa_init)(int); 520 4180 dougm static void (*_sa_fini)(sa_handle_t); 521 4180 dougm static sa_share_t (*_sa_find_share)(sa_handle_t, char *); 522 4180 dougm static int (*_sa_enable_share)(sa_share_t, char *); 523 4180 dougm static int (*_sa_disable_share)(sa_share_t, char *); 524 4180 dougm static char *(*_sa_errorstr)(int); 525 4180 dougm static int (*_sa_parse_legacy_options)(sa_group_t, char *, char *); 526 5951 dougm static boolean_t (*_sa_needs_refresh)(sa_handle_t *); 527 5951 dougm static libzfs_handle_t *(*_sa_get_zfs_handle)(sa_handle_t); 528 5951 dougm static int (*_sa_zfs_process_share)(sa_handle_t, sa_group_t, sa_share_t, 529 5951 dougm char *, char *, zprop_source_t, char *, char *, char *); 530 5951 dougm static void (*_sa_update_sharetab_ts)(sa_handle_t); 531 4180 dougm 532 4180 dougm /* 533 4180 dougm * _zfs_init_libshare() 534 4180 dougm * 535 4180 dougm * Find the libshare.so.1 entry points that we use here and save the 536 4180 dougm * values to be used later. This is triggered by the runtime loader. 537 4180 dougm * Make sure the correct ISA version is loaded. 538 4180 dougm */ 539 5951 dougm 540 4180 dougm #pragma init(_zfs_init_libshare) 541 4180 dougm static void 542 4180 dougm _zfs_init_libshare(void) 543 4180 dougm { 544 4180 dougm void *libshare; 545 4180 dougm char path[MAXPATHLEN]; 546 4180 dougm char isa[MAXISALEN]; 547 4180 dougm 548 4180 dougm #if defined(_LP64) 549 4180 dougm if (sysinfo(SI_ARCHITECTURE_64, isa, MAXISALEN) == -1) 550 4302 dougm isa[0] = '\0'; 551 4180 dougm #else 552 4180 dougm isa[0] = '\0'; 553 4180 dougm #endif 554 4180 dougm (void) snprintf(path, MAXPATHLEN, 555 4302 dougm "/usr/lib/%s/libshare.so.1", isa); 556 4180 dougm 557 4180 dougm if ((libshare = dlopen(path, RTLD_LAZY | RTLD_GLOBAL)) != NULL) { 558 4302 dougm _sa_init = (sa_handle_t (*)(int))dlsym(libshare, "sa_init"); 559 4302 dougm _sa_fini = (void (*)(sa_handle_t))dlsym(libshare, "sa_fini"); 560 4302 dougm _sa_find_share = (sa_share_t (*)(sa_handle_t, char *)) 561 4302 dougm dlsym(libshare, "sa_find_share"); 562 4302 dougm _sa_enable_share = (int (*)(sa_share_t, char *))dlsym(libshare, 563 4302 dougm "sa_enable_share"); 564 4302 dougm _sa_disable_share = (int (*)(sa_share_t, char *))dlsym(libshare, 565 4302 dougm "sa_disable_share"); 566 4302 dougm _sa_errorstr = (char *(*)(int))dlsym(libshare, "sa_errorstr"); 567 4302 dougm _sa_parse_legacy_options = (int (*)(sa_group_t, char *, char *)) 568 4302 dougm dlsym(libshare, "sa_parse_legacy_options"); 569 5951 dougm _sa_needs_refresh = (boolean_t (*)(sa_handle_t *)) 570 5951 dougm dlsym(libshare, "sa_needs_refresh"); 571 5951 dougm _sa_get_zfs_handle = (libzfs_handle_t *(*)(sa_handle_t)) 572 5951 dougm dlsym(libshare, "sa_get_zfs_handle"); 573 5951 dougm _sa_zfs_process_share = (int (*)(sa_handle_t, sa_group_t, 574 5951 dougm sa_share_t, char *, char *, zprop_source_t, char *, 575 5951 dougm char *, char *))dlsym(libshare, "sa_zfs_process_share"); 576 5951 dougm _sa_update_sharetab_ts = (void (*)(sa_handle_t)) 577 5951 dougm dlsym(libshare, "sa_update_sharetab_ts"); 578 4327 dougm if (_sa_init == NULL || _sa_fini == NULL || 579 4327 dougm _sa_find_share == NULL || _sa_enable_share == NULL || 580 4327 dougm _sa_disable_share == NULL || _sa_errorstr == NULL || 581 5951 dougm _sa_parse_legacy_options == NULL || 582 5951 dougm _sa_needs_refresh == NULL || _sa_get_zfs_handle == NULL || 583 5951 dougm _sa_zfs_process_share == NULL || 584 5951 dougm _sa_update_sharetab_ts == NULL) { 585 4327 dougm _sa_init = NULL; 586 4327 dougm _sa_fini = NULL; 587 4327 dougm _sa_disable_share = NULL; 588 4327 dougm _sa_enable_share = NULL; 589 4327 dougm _sa_errorstr = NULL; 590 4327 dougm _sa_parse_legacy_options = NULL; 591 4327 dougm (void) dlclose(libshare); 592 5951 dougm _sa_needs_refresh = NULL; 593 5951 dougm _sa_get_zfs_handle = NULL; 594 5951 dougm _sa_zfs_process_share = NULL; 595 5951 dougm _sa_update_sharetab_ts = NULL; 596 4327 dougm } 597 4180 dougm } 598 4180 dougm } 599 4180 dougm 600 4180 dougm /* 601 4180 dougm * zfs_init_libshare(zhandle, service) 602 4180 dougm * 603 4180 dougm * Initialize the libshare API if it hasn't already been initialized. 604 4180 dougm * In all cases it returns 0 if it succeeded and an error if not. The 605 4180 dougm * service value is which part(s) of the API to initialize and is a 606 4180 dougm * direct map to the libshare sa_init(service) interface. 607 4180 dougm */ 608 4180 dougm int 609 4180 dougm zfs_init_libshare(libzfs_handle_t *zhandle, int service) 610 4180 dougm { 611 4180 dougm int ret = SA_OK; 612 4180 dougm 613 4302 dougm if (_sa_init == NULL) 614 4302 dougm ret = SA_CONFIG_ERR; 615 5951 dougm 616 5951 dougm if (ret == SA_OK && zhandle->libzfs_shareflags & ZFSSHARE_MISS) { 617 5951 dougm /* 618 5951 dougm * We had a cache miss. Most likely it is a new ZFS 619 5951 dougm * dataset that was just created. We want to make sure 620 5951 dougm * so check timestamps to see if a different process 621 5951 dougm * has updated any of the configuration. If there was 622 5951 dougm * some non-ZFS change, we need to re-initialize the 623 5951 dougm * internal cache. 624 5951 dougm */ 625 5951 dougm zhandle->libzfs_shareflags &= ~ZFSSHARE_MISS; 626 5951 dougm if (_sa_needs_refresh != NULL && 627 5951 dougm _sa_needs_refresh(zhandle->libzfs_sharehdl)) { 628 5951 dougm zfs_uninit_libshare(zhandle); 629 5951 dougm zhandle->libzfs_sharehdl = _sa_init(service); 630 5951 dougm } 631 5951 dougm } 632 4302 dougm 633 4302 dougm if (ret == SA_OK && zhandle && zhandle->libzfs_sharehdl == NULL) 634 4302 dougm zhandle->libzfs_sharehdl = _sa_init(service); 635 4302 dougm 636 4302 dougm if (ret == SA_OK && zhandle->libzfs_sharehdl == NULL) 637 4302 dougm ret = SA_NO_MEMORY; 638 4302 dougm 639 4180 dougm return (ret); 640 4180 dougm } 641 4180 dougm 642 4180 dougm /* 643 4180 dougm * zfs_uninit_libshare(zhandle) 644 4180 dougm * 645 4180 dougm * Uninitialize the libshare API if it hasn't already been 646 4180 dougm * uninitialized. It is OK to call multiple times. 647 4180 dougm */ 648 4180 dougm void 649 4180 dougm zfs_uninit_libshare(libzfs_handle_t *zhandle) 650 4180 dougm { 651 4180 dougm if (zhandle != NULL && zhandle->libzfs_sharehdl != NULL) { 652 4302 dougm if (_sa_fini != NULL) 653 4302 dougm _sa_fini(zhandle->libzfs_sharehdl); 654 4302 dougm zhandle->libzfs_sharehdl = NULL; 655 4180 dougm } 656 4180 dougm } 657 4180 dougm 658 4180 dougm /* 659 4180 dougm * zfs_parse_options(options, proto) 660 4180 dougm * 661 4180 dougm * Call the legacy parse interface to get the protocol specific 662 4180 dougm * options using the NULL arg to indicate that this is a "parse" only. 663 4180 dougm */ 664 4180 dougm int 665 5331 amw zfs_parse_options(char *options, zfs_share_proto_t proto) 666 4180 dougm { 667 5367 ahrens if (_sa_parse_legacy_options != NULL) { 668 5367 ahrens return (_sa_parse_legacy_options(NULL, options, 669 5367 ahrens proto_table[proto].p_name)); 670 5367 ahrens } 671 5367 ahrens return (SA_CONFIG_ERR); 672 4180 dougm } 673 4180 dougm 674 4180 dougm /* 675 4180 dougm * zfs_sa_find_share(handle, path) 676 4180 dougm * 677 4180 dougm * wrapper around sa_find_share to find a share path in the 678 4180 dougm * configuration. 679 4180 dougm */ 680 4180 dougm static sa_share_t 681 4180 dougm zfs_sa_find_share(sa_handle_t handle, char *path) 682 4180 dougm { 683 4180 dougm if (_sa_find_share != NULL) 684 4302 dougm return (_sa_find_share(handle, path)); 685 4180 dougm return (NULL); 686 4180 dougm } 687 4180 dougm 688 4180 dougm /* 689 4180 dougm * zfs_sa_enable_share(share, proto) 690 4180 dougm * 691 4180 dougm * Wrapper for sa_enable_share which enables a share for a specified 692 4180 dougm * protocol. 693 4180 dougm */ 694 4180 dougm static int 695 4180 dougm zfs_sa_enable_share(sa_share_t share, char *proto) 696 4180 dougm { 697 4180 dougm if (_sa_enable_share != NULL) 698 4302 dougm return (_sa_enable_share(share, proto)); 699 4180 dougm return (SA_CONFIG_ERR); 700 4180 dougm } 701 4180 dougm 702 4180 dougm /* 703 4180 dougm * zfs_sa_disable_share(share, proto) 704 4180 dougm * 705 4180 dougm * Wrapper for sa_enable_share which disables a share for a specified 706 4180 dougm * protocol. 707 4180 dougm */ 708 4180 dougm static int 709 4180 dougm zfs_sa_disable_share(sa_share_t share, char *proto) 710 4180 dougm { 711 4180 dougm if (_sa_disable_share != NULL) 712 4302 dougm return (_sa_disable_share(share, proto)); 713 4180 dougm return (SA_CONFIG_ERR); 714 4180 dougm } 715 4180 dougm 716 4180 dougm /* 717 5331 amw * Share the given filesystem according to the options in the specified 718 5331 amw * protocol specific properties (sharenfs, sharesmb). We rely 719 4180 dougm * on "libshare" to the dirty work for us. 720 789 ahrens */ 721 5331 amw static int 722 5331 amw zfs_share_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto) 723 789 ahrens { 724 789 ahrens char mountpoint[ZFS_MAXPROPLEN]; 725 789 ahrens char shareopts[ZFS_MAXPROPLEN]; 726 5951 dougm char sourcestr[ZFS_MAXPROPLEN]; 727 2082 eschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 728 4180 dougm sa_share_t share; 729 5331 amw zfs_share_proto_t *curr_proto; 730 5951 dougm zprop_source_t sourcetype; 731 4180 dougm int ret; 732 789 ahrens 733 2676 eschrock if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL)) 734 789 ahrens return (0); 735 789 ahrens 736 4180 dougm if ((ret = zfs_init_libshare(hdl, SA_INIT_SHARE_API)) != SA_OK) { 737 4302 dougm (void) zfs_error_fmt(hdl, EZFS_SHARENFSFAILED, 738 4302 dougm dgettext(TEXT_DOMAIN, "cannot share '%s': %s"), 739 5951 dougm zfs_get_name(zhp), _sa_errorstr != NULL ? 740 5951 dougm _sa_errorstr(ret) : ""); 741 4302 dougm return (-1); 742 4180 dougm } 743 5331 amw 744 5331 amw for (curr_proto = proto; *curr_proto != PROTO_END; curr_proto++) { 745 5331 amw /* 746 5331 amw * Return success if there are no share options. 747 5331 amw */ 748 5331 amw if (zfs_prop_get(zhp, proto_table[*curr_proto].p_prop, 749 5951 dougm shareopts, sizeof (shareopts), &sourcetype, sourcestr, 750 5951 dougm ZFS_MAXPROPLEN, B_FALSE) != 0 || 751 5951 dougm strcmp(shareopts, "off") == 0) 752 5331 amw continue; 753 5331 amw 754 5331 amw /* 755 5331 amw * If the 'zoned' property is set, then zfs_is_mountable() 756 5331 amw * will have already bailed out if we are in the global zone. 757 5331 amw * But local zones cannot be NFS servers, so we ignore it for 758 5331 amw * local zones as well. 759 5331 amw */ 760 5331 amw if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) 761 5331 amw continue; 762 5331 amw 763 5331 amw share = zfs_sa_find_share(hdl->libzfs_sharehdl, mountpoint); 764 5951 dougm if (share == NULL) { 765 5951 dougm /* 766 5951 dougm * This may be a new file system that was just 767 5951 dougm * created so isn't in the internal cache 768 5951 dougm * (second time through). Rather than 769 5951 dougm * reloading the entire configuration, we can 770 5951 dougm * assume ZFS has done the checking and it is 771 5951 dougm * safe to add this to the internal 772 5951 dougm * configuration. 773 5951 dougm */ 774 5951 dougm if (_sa_zfs_process_share(hdl->libzfs_sharehdl, 775 5951 dougm NULL, NULL, mountpoint, 776 5951 dougm proto_table[*curr_proto].p_name, sourcetype, 777 5951 dougm shareopts, sourcestr, zhp->zfs_name) != SA_OK) { 778 5951 dougm (void) zfs_error_fmt(hdl, 779 5951 dougm proto_table[*curr_proto].p_share_err, 780 5951 dougm dgettext(TEXT_DOMAIN, "cannot share '%s'"), 781 5951 dougm zfs_get_name(zhp)); 782 5951 dougm return (-1); 783 5951 dougm } 784 5951 dougm hdl->libzfs_shareflags |= ZFSSHARE_MISS; 785 5951 dougm share = zfs_sa_find_share(hdl->libzfs_sharehdl, 786 5951 dougm mountpoint); 787 5951 dougm } 788 5331 amw if (share != NULL) { 789 5331 amw int err; 790 5331 amw err = zfs_sa_enable_share(share, 791 5331 amw proto_table[*curr_proto].p_name); 792 5331 amw if (err != SA_OK) { 793 5331 amw (void) zfs_error_fmt(hdl, 794 5331 amw proto_table[*curr_proto].p_share_err, 795 5331 amw dgettext(TEXT_DOMAIN, "cannot share '%s'"), 796 5331 amw zfs_get_name(zhp)); 797 5331 amw return (-1); 798 5331 amw } 799 5331 amw } else { 800 5331 amw (void) zfs_error_fmt(hdl, 801 5331 amw proto_table[*curr_proto].p_share_err, 802 4302 dougm dgettext(TEXT_DOMAIN, "cannot share '%s'"), 803 4302 dougm zfs_get_name(zhp)); 804 4302 dougm return (-1); 805 4302 dougm } 806 5331 amw 807 2474 eschrock } 808 5331 amw return (0); 809 5331 amw } 810 2474 eschrock 811 5331 amw 812 5331 amw int 813 5331 amw zfs_share_nfs(zfs_handle_t *zhp) 814 5331 amw { 815 5331 amw return (zfs_share_proto(zhp, nfs_only)); 816 5331 amw } 817 5331 amw 818 5331 amw int 819 5331 amw zfs_share_smb(zfs_handle_t *zhp) 820 5331 amw { 821 5331 amw return (zfs_share_proto(zhp, smb_only)); 822 5331 amw } 823 5331 amw 824 5331 amw int 825 5331 amw zfs_shareall(zfs_handle_t *zhp) 826 5331 amw { 827 5331 amw return (zfs_share_proto(zhp, share_all_proto)); 828 2474 eschrock } 829 2474 eschrock 830 2474 eschrock /* 831 2474 eschrock * Unshare a filesystem by mountpoint. 832 2474 eschrock */ 833 2474 eschrock static int 834 5331 amw unshare_one(libzfs_handle_t *hdl, const char *name, const char *mountpoint, 835 5331 amw zfs_share_proto_t proto) 836 2474 eschrock { 837 4180 dougm sa_share_t share; 838 4180 dougm int err; 839 4180 dougm char *mntpt; 840 2474 eschrock /* 841 4180 dougm * Mountpoint could get trashed if libshare calls getmntany 842 8228 Eric * which it does during API initialization, so strdup the 843 4180 dougm * value. 844 2474 eschrock */ 845 4180 dougm mntpt = zfs_strdup(hdl, mountpoint); 846 2474 eschrock 847 4180 dougm /* make sure libshare initialized */ 848 4180 dougm if ((err = zfs_init_libshare(hdl, SA_INIT_SHARE_API)) != SA_OK) { 849 4180 dougm free(mntpt); /* don't need the copy anymore */ 850 4180 dougm return (zfs_error_fmt(hdl, EZFS_SHARENFSFAILED, 851 4302 dougm dgettext(TEXT_DOMAIN, "cannot unshare '%s': %s"), 852 4302 dougm name, _sa_errorstr(err))); 853 789 ahrens } 854 789 ahrens 855 4180 dougm share = zfs_sa_find_share(hdl->libzfs_sharehdl, mntpt); 856 4180 dougm free(mntpt); /* don't need the copy anymore */ 857 789 ahrens 858 4180 dougm if (share != NULL) { 859 5331 amw err = zfs_sa_disable_share(share, proto_table[proto].p_name); 860 4180 dougm if (err != SA_OK) { 861 4302 dougm return (zfs_error_fmt(hdl, EZFS_UNSHARENFSFAILED, 862 4302 dougm dgettext(TEXT_DOMAIN, "cannot unshare '%s': %s"), 863 4302 dougm name, _sa_errorstr(err))); 864 4180 dougm } 865 4180 dougm } else { 866 4180 dougm return (zfs_error_fmt(hdl, EZFS_UNSHARENFSFAILED, 867 4302 dougm dgettext(TEXT_DOMAIN, "cannot unshare '%s': not found"), 868 4302 dougm name)); 869 4180 dougm } 870 789 ahrens return (0); 871 789 ahrens } 872 789 ahrens 873 789 ahrens /* 874 789 ahrens * Unshare the given filesystem. 875 789 ahrens */ 876 789 ahrens int 877 5331 amw zfs_unshare_proto(zfs_handle_t *zhp, const char *mountpoint, 878 5331 amw zfs_share_proto_t *proto) 879 789 ahrens { 880 8228 Eric libzfs_handle_t *hdl = zhp->zfs_hdl; 881 8228 Eric struct mnttab entry; 882 4180 dougm char *mntpt = NULL; 883 789 ahrens 884 789 ahrens /* check to see if need to unmount the filesystem */ 885 2082 eschrock rewind(zhp->zfs_hdl->libzfs_mnttab); 886 4302 dougm if (mountpoint != NULL) 887 8228 Eric mountpoint = mntpt = zfs_strdup(hdl, mountpoint); 888 4302 dougm 889 789 ahrens if (mountpoint != NULL || ((zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) && 890 8228 Eric libzfs_mnttab_find(hdl, zfs_get_name(zhp), &entry) == 0)) { 891 5331 amw zfs_share_proto_t *curr_proto; 892 789 ahrens 893 789 ahrens if (mountpoint == NULL) 894 5331 amw mntpt = zfs_strdup(zhp->zfs_hdl, entry.mnt_mountp); 895 789 ahrens 896 5331 amw for (curr_proto = proto; *curr_proto != PROTO_END; 897 5331 amw curr_proto++) { 898 5331 amw 899 8228 Eric if (is_shared(hdl, mntpt, *curr_proto) && 900 8228 Eric unshare_one(hdl, zhp->zfs_name, 901 5331 amw mntpt, *curr_proto) != 0) { 902 5331 amw if (mntpt != NULL) 903 5331 amw free(mntpt); 904 5331 amw return (-1); 905 5331 amw } 906 4180 dougm } 907 789 ahrens } 908 4180 dougm if (mntpt != NULL) 909 4302 dougm free(mntpt); 910 789 ahrens 911 789 ahrens return (0); 912 789 ahrens } 913 789 ahrens 914 5331 amw int 915 5331 amw zfs_unshare_nfs(zfs_handle_t *zhp, const char *mountpoint) 916 5331 amw { 917 5331 amw return (zfs_unshare_proto(zhp, mountpoint, nfs_only)); 918 5331 amw } 919 5331 amw 920 5331 amw int 921 5331 amw zfs_unshare_smb(zfs_handle_t *zhp, const char *mountpoint) 922 5331 amw { 923 5331 amw return (zfs_unshare_proto(zhp, mountpoint, smb_only)); 924 5331 amw } 925 5331 amw 926 789 ahrens /* 927 5331 amw * Same as zfs_unmountall(), but for NFS and SMB unshares. 928 789 ahrens */ 929 789 ahrens int 930 5331 amw zfs_unshareall_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto) 931 789 ahrens { 932 789 ahrens prop_changelist_t *clp; 933 789 ahrens int ret; 934 789 ahrens 935 7366 Tim clp = changelist_gather(zhp, ZFS_PROP_SHARENFS, 0, 0); 936 789 ahrens if (clp == NULL) 937 789 ahrens return (-1); 938 789 ahrens 939 5331 amw ret = changelist_unshare(clp, proto); 940 789 ahrens changelist_free(clp); 941 789 ahrens 942 789 ahrens return (ret); 943 5331 amw } 944 5331 amw 945 5331 amw int 946 5331 amw zfs_unshareall_nfs(zfs_handle_t *zhp) 947 5331 amw { 948 5331 amw return (zfs_unshareall_proto(zhp, nfs_only)); 949 5331 amw } 950 5331 amw 951 5331 amw int 952 5331 amw zfs_unshareall_smb(zfs_handle_t *zhp) 953 5331 amw { 954 5331 amw return (zfs_unshareall_proto(zhp, smb_only)); 955 5331 amw } 956 5331 amw 957 5331 amw int 958 5331 amw zfs_unshareall(zfs_handle_t *zhp) 959 5331 amw { 960 5331 amw return (zfs_unshareall_proto(zhp, share_all_proto)); 961 5331 amw } 962 5331 amw 963 5331 amw int 964 5331 amw zfs_unshareall_bypath(zfs_handle_t *zhp, const char *mountpoint) 965 5331 amw { 966 5331 amw return (zfs_unshare_proto(zhp, mountpoint, share_all_proto)); 967 789 ahrens } 968 789 ahrens 969 789 ahrens /* 970 789 ahrens * Remove the mountpoint associated with the current dataset, if necessary. 971 789 ahrens * We only remove the underlying directory if: 972 789 ahrens * 973 789 ahrens * - The mountpoint is not 'none' or 'legacy' 974 789 ahrens * - The mountpoint is non-empty 975 789 ahrens * - The mountpoint is the default or inherited 976 789 ahrens * - The 'zoned' property is set, or we're in a local zone 977 789 ahrens * 978 789 ahrens * Any other directories we leave alone. 979 789 ahrens */ 980 789 ahrens void 981 789 ahrens remove_mountpoint(zfs_handle_t *zhp) 982 789 ahrens { 983 789 ahrens char mountpoint[ZFS_MAXPROPLEN]; 984 5094 lling zprop_source_t source; 985 789 ahrens 986 2676 eschrock if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), 987 2676 eschrock &source)) 988 789 ahrens return; 989 789 ahrens 990 5094 lling if (source == ZPROP_SRC_DEFAULT || 991 5094 lling source == ZPROP_SRC_INHERITED) { 992 789 ahrens /* 993 789 ahrens * Try to remove the directory, silently ignoring any errors. 994 789 ahrens * The filesystem may have since been removed or moved around, 995 2676 eschrock * and this error isn't really useful to the administrator in 996 2676 eschrock * any way. 997 789 ahrens */ 998 789 ahrens (void) rmdir(mountpoint); 999 789 ahrens } 1000 789 ahrens } 1001 2474 eschrock 1002 3126 ahl boolean_t 1003 3126 ahl zfs_is_shared_iscsi(zfs_handle_t *zhp) 1004 3126 ahl { 1005 4543 marks 1006 4543 marks /* 1007 4543 marks * If iscsi deamon isn't running then we aren't shared 1008 4543 marks */ 1009 4543 marks if (iscsitgt_svc_online && iscsitgt_svc_online() == 1) 1010 5331 amw return (B_FALSE); 1011 4543 marks else 1012 4543 marks return (iscsitgt_zfs_is_shared != NULL && 1013 4543 marks iscsitgt_zfs_is_shared(zhp->zfs_name) != 0); 1014 3126 ahl } 1015 3126 ahl 1016 3126 ahl int 1017 3126 ahl zfs_share_iscsi(zfs_handle_t *zhp) 1018 3126 ahl { 1019 3126 ahl char shareopts[ZFS_MAXPROPLEN]; 1020 3126 ahl const char *dataset = zhp->zfs_name; 1021 3126 ahl libzfs_handle_t *hdl = zhp->zfs_hdl; 1022 3126 ahl 1023 3126 ahl /* 1024 3126 ahl * Return success if there are no share options. 1025 3126 ahl */ 1026 3126 ahl if (zfs_prop_get(zhp, ZFS_PROP_SHAREISCSI, shareopts, 1027 3126 ahl sizeof (shareopts), NULL, NULL, 0, B_FALSE) != 0 || 1028 3126 ahl strcmp(shareopts, "off") == 0) 1029 3126 ahl return (0); 1030 3126 ahl 1031 4543 marks if (iscsitgt_zfs_share == NULL || iscsitgt_zfs_share(dataset) != 0) { 1032 4543 marks int error = EZFS_SHAREISCSIFAILED; 1033 4543 marks 1034 4543 marks /* 1035 4543 marks * If service isn't availabele and EPERM was 1036 4543 marks * returned then use special error. 1037 4543 marks */ 1038 4543 marks if (iscsitgt_svc_online && errno == EPERM && 1039 4543 marks (iscsitgt_svc_online() != 0)) 1040 4543 marks error = EZFS_ISCSISVCUNAVAIL; 1041 4543 marks 1042 4543 marks return (zfs_error_fmt(hdl, error, 1043 3126 ahl dgettext(TEXT_DOMAIN, "cannot share '%s'"), dataset)); 1044 4543 marks } 1045 3126 ahl 1046 3126 ahl return (0); 1047 3126 ahl } 1048 3126 ahl 1049 3126 ahl int 1050 3126 ahl zfs_unshare_iscsi(zfs_handle_t *zhp) 1051 3126 ahl { 1052 3126 ahl const char *dataset = zfs_get_name(zhp); 1053 3126 ahl libzfs_handle_t *hdl = zhp->zfs_hdl; 1054 3126 ahl 1055 3126 ahl /* 1056 3380 gw25295 * Return if the volume is not shared 1057 3380 gw25295 */ 1058 5331 amw if (zfs_is_shared_iscsi(zhp) != SHARED_ISCSI) 1059 3380 gw25295 return (0); 1060 3380 gw25295 1061 3380 gw25295 /* 1062 3126 ahl * If this fails with ENODEV it indicates that zvol wasn't shared so 1063 3126 ahl * we should return success in that case. 1064 3126 ahl */ 1065 3134 ahl if (iscsitgt_zfs_unshare == NULL || 1066 4543 marks (iscsitgt_zfs_unshare(dataset) != 0 && errno != ENODEV)) { 1067 4543 marks if (errno == EPERM) 1068 4543 marks zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1069 4543 marks "Insufficient privileges to unshare iscsi")); 1070 3237 lling return (zfs_error_fmt(hdl, EZFS_UNSHAREISCSIFAILED, 1071 3126 ahl dgettext(TEXT_DOMAIN, "cannot unshare '%s'"), dataset)); 1072 4543 marks } 1073 3126 ahl 1074 3126 ahl return (0); 1075 3126 ahl } 1076 3126 ahl 1077 2474 eschrock typedef struct mount_cbdata { 1078 2474 eschrock zfs_handle_t **cb_datasets; 1079 2474 eschrock int cb_used; 1080 2474 eschrock int cb_alloc; 1081 2474 eschrock } mount_cbdata_t; 1082 2474 eschrock 1083 2474 eschrock static int 1084 2474 eschrock mount_cb(zfs_handle_t *zhp, void *data) 1085 2474 eschrock { 1086 2474 eschrock mount_cbdata_t *cbp = data; 1087 2474 eschrock 1088 3126 ahl if (!(zfs_get_type(zhp) & (ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME))) { 1089 2474 eschrock zfs_close(zhp); 1090 2474 eschrock return (0); 1091 2474 eschrock } 1092 2474 eschrock 1093 6168 hs24103 if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_NOAUTO) { 1094 6168 hs24103 zfs_close(zhp); 1095 6168 hs24103 return (0); 1096 6168 hs24103 } 1097 6168 hs24103 1098 2474 eschrock if (cbp->cb_alloc == cbp->cb_used) { 1099 2676 eschrock void *ptr; 1100 2474 eschrock 1101 2676 eschrock if ((ptr = zfs_realloc(zhp->zfs_hdl, 1102 2676 eschrock cbp->cb_datasets, cbp->cb_alloc * sizeof (void *), 1103 2676 eschrock cbp->cb_alloc * 2 * sizeof (void *))) == NULL) 1104 2474 eschrock return (-1); 1105 2676 eschrock cbp->cb_datasets = ptr; 1106 2474 eschrock 1107 2676 eschrock cbp->cb_alloc *= 2; 1108 2474 eschrock } 1109 2474 eschrock 1110 2474 eschrock cbp->cb_datasets[cbp->cb_used++] = zhp; 1111 3126 ahl 1112 6027 rm160521 return (zfs_iter_filesystems(zhp, mount_cb, cbp)); 1113 2474 eschrock } 1114 2474 eschrock 1115 2474 eschrock static int 1116 3126 ahl dataset_cmp(const void *a, const void *b) 1117 2474 eschrock { 1118 2474 eschrock zfs_handle_t **za = (zfs_handle_t **)a; 1119 2474 eschrock zfs_handle_t **zb = (zfs_handle_t **)b; 1120 2474 eschrock char mounta[MAXPATHLEN]; 1121 2474 eschrock char mountb[MAXPATHLEN]; 1122 3126 ahl boolean_t gota, gotb; 1123 2474 eschrock 1124 3126 ahl if ((gota = (zfs_get_type(*za) == ZFS_TYPE_FILESYSTEM)) != 0) 1125 3126 ahl verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta, 1126 3126 ahl sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0); 1127 3126 ahl if ((gotb = (zfs_get_type(*zb) == ZFS_TYPE_FILESYSTEM)) != 0) 1128 3126 ahl verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb, 1129 3126 ahl sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0); 1130 2474 eschrock 1131 3126 ahl if (gota && gotb) 1132 3126 ahl return (strcmp(mounta, mountb)); 1133 3126 ahl 1134 3126 ahl if (gota) 1135 3126 ahl return (-1); 1136 3126 ahl if (gotb) 1137 3126 ahl return (1); 1138 3126 ahl 1139 3126 ahl return (strcmp(zfs_get_name(a), zfs_get_name(b))); 1140 2474 eschrock } 1141 2474 eschrock 1142 3126 ahl /* 1143 3126 ahl * Mount and share all datasets within the given pool. This assumes that no 1144 3126 ahl * datasets within the pool are currently mounted. Because users can create 1145 3126 ahl * complicated nested hierarchies of mountpoints, we first gather all the 1146 3126 ahl * datasets and mountpoints within the pool, and sort them by mountpoint. Once 1147 3126 ahl * we have the list of all filesystems, we iterate over them in order and mount 1148 3126 ahl * and/or share each one. 1149 3126 ahl */ 1150 3126 ahl #pragma weak zpool_mount_datasets = zpool_enable_datasets 1151 2474 eschrock int 1152 3126 ahl zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags) 1153 2474 eschrock { 1154 2474 eschrock mount_cbdata_t cb = { 0 }; 1155 2474 eschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1156 2474 eschrock zfs_handle_t *zfsp; 1157 2474 eschrock int i, ret = -1; 1158 4180 dougm int *good; 1159 2474 eschrock 1160 2474 eschrock /* 1161 6027 rm160521 * Gather all non-snap datasets within the pool. 1162 2474 eschrock */ 1163 2474 eschrock if ((cb.cb_datasets = zfs_alloc(hdl, 4 * sizeof (void *))) == NULL) 1164 2474 eschrock return (-1); 1165 2474 eschrock cb.cb_alloc = 4; 1166 2474 eschrock 1167 5094 lling if ((zfsp = zfs_open(hdl, zhp->zpool_name, ZFS_TYPE_DATASET)) == NULL) 1168 2474 eschrock goto out; 1169 2474 eschrock 1170 2474 eschrock cb.cb_datasets[0] = zfsp; 1171 2474 eschrock cb.cb_used = 1; 1172 2474 eschrock 1173 6027 rm160521 if (zfs_iter_filesystems(zfsp, mount_cb, &cb) != 0) 1174 2474 eschrock goto out; 1175 2474 eschrock 1176 2474 eschrock /* 1177 2474 eschrock * Sort the datasets by mountpoint. 1178 2474 eschrock */ 1179 3126 ahl qsort(cb.cb_datasets, cb.cb_used, sizeof (void *), dataset_cmp); 1180 2474 eschrock 1181 2474 eschrock /* 1182 4180 dougm * And mount all the datasets, keeping track of which ones 1183 8536 David * succeeded or failed. 1184 2474 eschrock */ 1185 8536 David if ((good = zfs_alloc(zhp->zpool_hdl, 1186 8536 David cb.cb_used * sizeof (int))) == NULL) 1187 8536 David goto out; 1188 8536 David 1189 2474 eschrock ret = 0; 1190 2474 eschrock for (i = 0; i < cb.cb_used; i++) { 1191 4302 dougm if (zfs_mount(cb.cb_datasets[i], mntopts, flags) != 0) 1192 4180 dougm ret = -1; 1193 4302 dougm else 1194 4180 dougm good[i] = 1; 1195 4180 dougm } 1196 5951 dougm 1197 4180 dougm /* 1198 4180 dougm * Then share all the ones that need to be shared. This needs 1199 4180 dougm * to be a separate pass in order to avoid excessive reloading 1200 4180 dougm * of the configuration. Good should never be NULL since 1201 4180 dougm * zfs_alloc is supposed to exit if memory isn't available. 1202 4180 dougm */ 1203 4180 dougm for (i = 0; i < cb.cb_used; i++) { 1204 4180 dougm if (good[i] && zfs_share(cb.cb_datasets[i]) != 0) 1205 2474 eschrock ret = -1; 1206 2474 eschrock } 1207 4180 dougm 1208 4180 dougm free(good); 1209 2474 eschrock 1210 2474 eschrock out: 1211 2474 eschrock for (i = 0; i < cb.cb_used; i++) 1212 2474 eschrock zfs_close(cb.cb_datasets[i]); 1213 2474 eschrock free(cb.cb_datasets); 1214 2474 eschrock 1215 2474 eschrock return (ret); 1216 2474 eschrock } 1217 2474 eschrock 1218 10588 Eric /*ARGSUSED1*/ 1219 10588 Eric static int 1220 10588 Eric zvol_cb(zfs_handle_t *zhp, void *unused) 1221 10588 Eric { 1222 10588 Eric int error = 0; 1223 3126 ahl 1224 10588 Eric if (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) 1225 10588 Eric (void) zfs_iter_children(zhp, zvol_cb, NULL); 1226 10588 Eric if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME) 1227 10588 Eric error = zfs_unshare_iscsi(zhp); 1228 3126 ahl zfs_close(zhp); 1229 3126 ahl 1230 10588 Eric return (error); 1231 3126 ahl } 1232 3126 ahl 1233 2474 eschrock static int 1234 2474 eschrock mountpoint_compare(const void *a, const void *b) 1235 2474 eschrock { 1236 2474 eschrock const char *mounta = *((char **)a); 1237 2474 eschrock const char *mountb = *((char **)b); 1238 2474 eschrock 1239 2474 eschrock return (strcmp(mountb, mounta)); 1240 2474 eschrock } 1241 2474 eschrock 1242 10588 Eric /* alias for 2002/240 */ 1243 10588 Eric #pragma weak zpool_unmount_datasets = zpool_disable_datasets 1244 3126 ahl /* 1245 3126 ahl * Unshare and unmount all datasets within the given pool. We don't want to 1246 3126 ahl * rely on traversing the DSL to discover the filesystems within the pool, 1247 3126 ahl * because this may be expensive (if not all of them are mounted), and can fail 1248 3126 ahl * arbitrarily (on I/O error, for example). Instead, we walk /etc/mnttab and 1249 3126 ahl * gather all the filesystems that are currently mounted. 1250 3126 ahl */ 1251 2474 eschrock int 1252 3126 ahl zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force) 1253 2474 eschrock { 1254 2474 eschrock int used, alloc; 1255 2474 eschrock struct mnttab entry; 1256 2474 eschrock size_t namelen; 1257 2474 eschrock char **mountpoints = NULL; 1258 10588 Eric zfs_handle_t *zfp; 1259 2474 eschrock zfs_handle_t **datasets = NULL; 1260 2474 eschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 1261 2474 eschrock int i; 1262 2474 eschrock int ret = -1; 1263 2474 eschrock int flags = (force ? MS_FORCE : 0); 1264 3126 ahl 1265 3126 ahl /* 1266 3126 ahl * First unshare all zvols. 1267 3126 ahl */ 1268 10588 Eric zfp = zfs_open(zhp->zpool_hdl, zhp->zpool_name, 1269 10588 Eric ZFS_TYPE_FILESYSTEM); 1270 10588 Eric if (zfp != NULL) { 1271 10588 Eric (void) zfs_iter_children(zfp, zvol_cb, NULL); 1272 10588 Eric zfs_close(zfp); 1273 10588 Eric } 1274 2474 eschrock 1275 2474 eschrock namelen = strlen(zhp->zpool_name); 1276 2474 eschrock 1277 2474 eschrock rewind(hdl->libzfs_mnttab); 1278 2474 eschrock used = alloc = 0; 1279 2474 eschrock while (getmntent(hdl->libzfs_mnttab, &entry) == 0) { 1280 2474 eschrock /* 1281 2474 eschrock * Ignore non-ZFS entries. 1282 2474 eschrock */ 1283 2474 eschrock if (entry.mnt_fstype == NULL || 1284 2474 eschrock strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) 1285 2474 eschrock continue; 1286 2474 eschrock 1287 2474 eschrock /* 1288 2474 eschrock * Ignore filesystems not within this pool. 1289 2474 eschrock */ 1290 2474 eschrock if (entry.mnt_mountp == NULL || 1291 2474 eschrock strncmp(entry.mnt_special, zhp->zpool_name, namelen) != 0 || 1292 2474 eschrock (entry.mnt_special[namelen] != '/' && 1293 2474 eschrock entry.mnt_special[namelen] != '\0')) 1294 2474 eschrock continue; 1295 2474 eschrock 1296 2474 eschrock /* 1297 2474 eschrock * At this point we've found a filesystem within our pool. Add 1298 2474 eschrock * it to our growing list. 1299 2474 eschrock */ 1300 2474 eschrock if (used == alloc) { 1301 2474 eschrock if (alloc == 0) { 1302 2474 eschrock if ((mountpoints = zfs_alloc(hdl, 1303 2474 eschrock 8 * sizeof (void *))) == NULL) 1304 2474 eschrock goto out; 1305 2474 eschrock 1306 2474 eschrock if ((datasets = zfs_alloc(hdl, 1307 2474 eschrock 8 * sizeof (void *))) == NULL) 1308 2474 eschrock goto out; 1309 2474 eschrock 1310 2474 eschrock alloc = 8; 1311 2474 eschrock } else { 1312 2676 eschrock void *ptr; 1313 2474 eschrock 1314 2676 eschrock if ((ptr = zfs_realloc(hdl, mountpoints, 1315 2676 eschrock alloc * sizeof (void *), 1316 2474 eschrock alloc * 2 * sizeof (void *))) == NULL) 1317 2474 eschrock goto out; 1318 2676 eschrock mountpoints = ptr; 1319 2474 eschrock 1320 2676 eschrock if ((ptr = zfs_realloc(hdl, datasets, 1321 2676 eschrock alloc * sizeof (void *), 1322 2474 eschrock alloc * 2 * sizeof (void *))) == NULL) 1323 2474 eschrock goto out; 1324 2676 eschrock datasets = ptr; 1325 2474 eschrock 1326 2474 eschrock alloc *= 2; 1327 2474 eschrock } 1328 2474 eschrock } 1329 2474 eschrock 1330 2474 eschrock if ((mountpoints[used] = zfs_strdup(hdl, 1331 2474 eschrock entry.mnt_mountp)) == NULL) 1332 2474 eschrock goto out; 1333 2474 eschrock 1334 2474 eschrock /* 1335 2474 eschrock * This is allowed to fail, in case there is some I/O error. It 1336 2474 eschrock * is only used to determine if we need to remove the underlying 1337 2474 eschrock * mountpoint, so failure is not fatal. 1338 2474 eschrock */ 1339 2474 eschrock datasets[used] = make_dataset_handle(hdl, entry.mnt_special); 1340 2474 eschrock 1341 2474 eschrock used++; 1342 2474 eschrock } 1343 2474 eschrock 1344 2474 eschrock /* 1345 2474 eschrock * At this point, we have the entire list of filesystems, so sort it by 1346 2474 eschrock * mountpoint. 1347 2474 eschrock */ 1348 2474 eschrock qsort(mountpoints, used, sizeof (char *), mountpoint_compare); 1349 2474 eschrock 1350 2474 eschrock /* 1351 2474 eschrock * Walk through and first unshare everything. 1352 2474 eschrock */ 1353 2474 eschrock for (i = 0; i < used; i++) { 1354 5331 amw zfs_share_proto_t *curr_proto; 1355 5331 amw for (curr_proto = share_all_proto; *curr_proto != PROTO_END; 1356 5331 amw curr_proto++) { 1357 5331 amw if (is_shared(hdl, mountpoints[i], *curr_proto) && 1358 5331 amw unshare_one(hdl, mountpoints[i], 1359 5331 amw mountpoints[i], *curr_proto) != 0) 1360 5331 amw goto out; 1361 5331 amw } 1362 2474 eschrock } 1363 2474 eschrock 1364 2474 eschrock /* 1365 2474 eschrock * Now unmount everything, removing the underlying directories as 1366 2474 eschrock * appropriate. 1367 2474 eschrock */ 1368 2474 eschrock for (i = 0; i < used; i++) { 1369 2474 eschrock if (unmount_one(hdl, mountpoints[i], flags) != 0) 1370 2474 eschrock goto out; 1371 2676 eschrock } 1372 2474 eschrock 1373 2676 eschrock for (i = 0; i < used; i++) { 1374 2474 eschrock if (datasets[i]) 1375 2474 eschrock remove_mountpoint(datasets[i]); 1376 2474 eschrock } 1377 2474 eschrock 1378 2474 eschrock ret = 0; 1379 2474 eschrock out: 1380 2474 eschrock for (i = 0; i < used; i++) { 1381 2474 eschrock if (datasets[i]) 1382 2474 eschrock zfs_close(datasets[i]); 1383 2474 eschrock free(mountpoints[i]); 1384 2474 eschrock } 1385 2474 eschrock free(datasets); 1386 2474 eschrock free(mountpoints); 1387 2474 eschrock 1388 2474 eschrock return (ret); 1389 2474 eschrock } 1390