Whamcloud - gitweb
LU-8900 snapshot: simulate readonly device
[fs/lustre-release.git] / lustre / utils / mount_utils_zfs.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License version 2 for more details.  A copy is
14  * included in the COPYING file that accompanied this code.
15
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2012, 2016, Intel Corporation.
24  * Use is subject to license terms.
25  */
26 /*
27  * Author: Brian Behlendorf <behlendorf1@llnl.gov>
28  */
29 #include "mount_utils.h"
30 #include <stddef.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <libzfs.h>
34
35 #define HOSTID_PATH "/etc/hostid"
36
37 /* Persistent mount data is stored in these user attributes */
38 #define LDD_PREFIX              "lustre:"
39 #define LDD_VERSION_PROP        LDD_PREFIX "version"
40 #define LDD_FLAGS_PROP          LDD_PREFIX "flags"
41 #define LDD_INDEX_PROP          LDD_PREFIX "index"
42 #define LDD_FSNAME_PROP         LDD_PREFIX "fsname"
43 #define LDD_SVNAME_PROP         LDD_PREFIX "svname"
44 #define LDD_UUID_PROP           LDD_PREFIX "uuid"
45 #define LDD_USERDATA_PROP       LDD_PREFIX "userdata"
46 #define LDD_MOUNTOPTS_PROP      LDD_PREFIX "mountopts"
47
48 /* This structure is used to help bridge the gap between the ZFS
49  * properties Lustre uses and their corresponding internal LDD fields.
50  * It is meant to be used internally by the mount utility only. */
51 struct zfs_ldd_prop_bridge {
52         /* Contains the publicly visible name for the property
53          * (i.e. what is shown when running "zfs get") */
54         char *zlpb_prop_name;
55         /* Contains the offset into the lustre_disk_data structure where
56          * the value of this property is or will be stored. (i.e. the
57          * property is read from and written to this offset within ldd) */
58         int   zlpb_ldd_offset;
59         /* Function pointer responsible for reading in the @prop
60          * property from @zhp and storing it in @ldd_field */
61         int (*zlpb_get_prop_fn)(zfs_handle_t *zhp, char *prop, void *ldd_field);
62         /* Function pointer responsible for writing the value of @ldd_field
63          * into the @prop dataset property in @zhp */
64         int (*zlpb_set_prop_fn)(zfs_handle_t *zhp, char *prop, void *ldd_field);
65 };
66
67 /* Forward declarations needed to initialize the ldd prop bridge list */
68 static int zfs_get_prop_int(zfs_handle_t *, char *, void *);
69 static int zfs_set_prop_int(zfs_handle_t *, char *, void *);
70 static int zfs_get_prop_str(zfs_handle_t *, char *, void *);
71 static int zfs_set_prop_str(zfs_handle_t *, char *, void *);
72
73 /* Helper for initializing the entries in the special_ldd_prop_params list.
74  *    - @name: stored directly in the zlpb_prop_name field
75  *             (e.g. lustre:fsname, lustre:version, etc.)
76  *    - @field: the field in the lustre_disk_data which directly maps to
77  *              the @name property. (e.g. ldd_fsname, ldd_config_ver, etc.)
78  *    - @type: The type of @field. Only "int" and "str" are supported.
79  */
80 #define ZLB_INIT(name, field, type)                     \
81 {                                                       \
82         name, offsetof(struct lustre_disk_data, field), \
83         zfs_get_prop_ ## type, zfs_set_prop_ ## type    \
84 }
85
86 /* These ldd properties are special because they all have their own
87  * individual fields in the lustre_disk_data structure, as opposed to
88  * being globbed into the ldd_params field. As such, these need special
89  * handling when reading/writing the ldd structure to/from persistent
90  * storage. */
91 struct zfs_ldd_prop_bridge special_ldd_prop_params[] = {
92         ZLB_INIT(LDD_VERSION_PROP,   ldd_config_ver, int),
93         ZLB_INIT(LDD_FLAGS_PROP,     ldd_flags,      int),
94         ZLB_INIT(LDD_INDEX_PROP,     ldd_svindex,    int),
95         ZLB_INIT(LDD_FSNAME_PROP,    ldd_fsname,     str),
96         ZLB_INIT(LDD_SVNAME_PROP,    ldd_svname,     str),
97         ZLB_INIT(LDD_UUID_PROP,      ldd_uuid,       str),
98         ZLB_INIT(LDD_USERDATA_PROP,  ldd_userdata,   str),
99         ZLB_INIT(LDD_MOUNTOPTS_PROP, ldd_mount_opts, str),
100         { NULL }
101 };
102
103 /* indicate if the ZFS OSD has been successfully setup */
104 static int osd_zfs_setup = 0;
105
106 static libzfs_handle_t *g_zfs;
107
108 void zfs_fini(void);
109
110 static int zfs_set_prop_int(zfs_handle_t *zhp, char *prop, void *val)
111 {
112         char str[64];
113         int ret;
114
115         (void) snprintf(str, sizeof (str), "%i", *(int *)val);
116         vprint("  %s=%s\n", prop, str);
117         ret = zfs_prop_set(zhp, prop, str);
118
119         return ret;
120 }
121
122 /*
123  * Write the zfs property string, note that properties with a NULL or
124  * zero-length value will not be written and 0 returned.
125  */
126 static int zfs_set_prop_str(zfs_handle_t *zhp, char *prop, void *val)
127 {
128         int ret = 0;
129
130         if (val && strlen(val) > 0) {
131                 vprint("  %s=%s\n", prop, (char *)val);
132                 ret = zfs_prop_set(zhp, prop, (char *)val);
133         }
134
135         return ret;
136 }
137
138 /*
139  * Map '<key>=<value> ...' pairs in the passed string to dataset properties
140  * of the form 'lustre:<key>=<value>'.  Malformed <key>=<value> pairs will
141  * be skipped.
142  */
143 static int zfs_set_prop_params(zfs_handle_t *zhp, char *params)
144 {
145         char *params_dup, *token, *key, *value;
146         char *save_token = NULL;
147         char prop_name[ZFS_MAXPROPLEN];
148         int ret = 0;
149
150         params_dup = strdup(params);
151         if (params_dup == NULL)
152                 return ENOMEM;
153
154         token = strtok_r(params_dup, " ", &save_token);
155         while (token) {
156                 key = strtok(token, "=");
157                 if (key == NULL)
158                         continue;
159
160                 value = strtok(NULL, "=");
161                 if (value == NULL)
162                         continue;
163
164                 sprintf(prop_name, "%s%s", LDD_PREFIX, key);
165                 vprint("  %s=%s\n", prop_name, value);
166
167                 ret = zfs_prop_set(zhp, prop_name, value);
168                 if (ret)
169                         break;
170
171                 token = strtok_r(NULL, " ", &save_token);
172         }
173
174         free(params_dup);
175
176         return ret;
177 }
178
179 static int zfs_check_hostid(struct mkfs_opts *mop)
180 {
181         FILE *f;
182         unsigned long hostid;
183         int rc;
184
185         if (strstr(mop->mo_ldd.ldd_params, PARAM_FAILNODE) == NULL)
186                 return 0;
187
188         f = fopen("/sys/module/spl/parameters/spl_hostid", "r");
189         if (f == NULL) {
190                 fatal();
191                 fprintf(stderr, "Failed to open spl_hostid: %s\n",
192                         strerror(errno));
193                 return errno;
194         }
195         rc = fscanf(f, "%li", &hostid);
196         fclose(f);
197         if (rc != 1) {
198                 fatal();
199                 fprintf(stderr, "Failed to read spl_hostid: %d\n", rc);
200                 return rc;
201         }
202
203         if (hostid != 0)
204                 return 0;
205
206         f = fopen(HOSTID_PATH, "r");
207         if (f == NULL)
208                 goto out;
209
210         rc = fread(&hostid, sizeof(uint32_t), 1, f);
211         fclose(f);
212
213         if (rc != 1) {
214                 fprintf(stderr, "Failed to read "HOSTID_PATH": %d\n",
215                        rc);
216                 hostid = 0;
217         }
218
219 out:
220         if (hostid == 0) {
221                 if (mop->mo_flags & MO_NOHOSTID_CHECK) {
222                         fprintf(stderr, "WARNING: spl_hostid not set. ZFS has "
223                                 "no zpool import protection\n");
224                 } else {
225                         fatal();
226                         fprintf(stderr, "spl_hostid not set. See %s(8)",
227                                 progname);
228                         return EINVAL;
229                 }
230         }
231
232         return 0;
233 }
234
235 static int osd_check_zfs_setup(void)
236 {
237         if (osd_zfs_setup == 0) {
238                 /* setup failed */
239                 fatal();
240                 fprintf(stderr, "Failed to initialize ZFS library. Are the ZFS "
241                         "packages and modules correctly installed?\n");
242         }
243         return osd_zfs_setup == 1;
244 }
245
246 /* Write the server config as properties associated with the dataset */
247 int zfs_write_ldd(struct mkfs_opts *mop)
248 {
249         struct lustre_disk_data *ldd = &mop->mo_ldd;
250         char *ds = mop->mo_device;
251         zfs_handle_t *zhp;
252         struct zfs_ldd_prop_bridge *bridge;
253         int i, ret = EINVAL;
254
255         if (osd_check_zfs_setup() == 0)
256                 goto out;
257
258         zhp = zfs_open(g_zfs, ds, ZFS_TYPE_FILESYSTEM);
259         if (zhp == NULL) {
260                 fprintf(stderr, "Failed to open zfs dataset %s\n", ds);
261                 goto out;
262         }
263
264         ret = zfs_check_hostid(mop);
265         if (ret != 0)
266                 goto out;
267
268         vprint("Writing %s properties\n", ds);
269
270         for (i = 0; special_ldd_prop_params[i].zlpb_prop_name != NULL; i++) {
271                 bridge = &special_ldd_prop_params[i];
272                 ret = bridge->zlpb_set_prop_fn(zhp, bridge->zlpb_prop_name,
273                                         (void *)ldd + bridge->zlpb_ldd_offset);
274                 if (ret)
275                         goto out_close;
276         }
277
278         ret = zfs_set_prop_params(zhp, ldd->ldd_params);
279
280 out_close:
281         zfs_close(zhp);
282 out:
283         return ret;
284 }
285
286 static int zfs_get_prop_int(zfs_handle_t *zhp, char *prop, void *val)
287 {
288         nvlist_t *propval;
289         char *propstr;
290         int ret;
291
292         ret = nvlist_lookup_nvlist(zfs_get_user_props(zhp), prop, &propval);
293         if (ret)
294                 return ret;
295
296         ret = nvlist_lookup_string(propval, ZPROP_VALUE, &propstr);
297         if (ret)
298                 return ret;
299
300         errno = 0;
301         *(__u32 *)val = strtoul(propstr, NULL, 10);
302         if (errno)
303                 return errno;
304
305         return ret;
306 }
307
308 static int zfs_get_prop_str(zfs_handle_t *zhp, char *prop, void *val)
309 {
310         nvlist_t *propval;
311         char *propstr;
312         int ret;
313
314         ret = nvlist_lookup_nvlist(zfs_get_user_props(zhp), prop, &propval);
315         if (ret)
316                 return ret;
317
318         ret = nvlist_lookup_string(propval, ZPROP_VALUE, &propstr);
319         if (ret)
320                 return ret;
321
322         (void) strcpy(val, propstr);
323
324         return ret;
325 }
326
327 static int zfs_is_special_ldd_prop_param(char *name)
328 {
329         int i;
330
331         for (i = 0; special_ldd_prop_params[i].zlpb_prop_name != NULL; i++)
332                 if (!strcmp(name, special_ldd_prop_params[i].zlpb_prop_name))
333                         return 1;
334
335         return 0;
336 }
337
338 static int zfs_get_prop_params(zfs_handle_t *zhp, char *param, int len)
339 {
340         nvlist_t *props;
341         nvpair_t *nvp;
342         char key[ZFS_MAXPROPLEN];
343         char *value;
344         int ret = 0;
345
346         props = zfs_get_user_props(zhp);
347         if (props == NULL)
348                 return ENOENT;
349
350         value = malloc(len);
351         if (value == NULL)
352                 return ENOMEM;
353
354         nvp = NULL;
355         while (nvp = nvlist_next_nvpair(props, nvp), nvp) {
356                 ret = zfs_get_prop_str(zhp, nvpair_name(nvp), value);
357                 if (ret)
358                         break;
359
360                 if (strncmp(nvpair_name(nvp), LDD_PREFIX, strlen(LDD_PREFIX)))
361                         continue;
362
363                 if (zfs_is_special_ldd_prop_param(nvpair_name(nvp)))
364                         continue;
365
366                 sprintf(key, "%s=",  nvpair_name(nvp) + strlen(LDD_PREFIX));
367
368                 ret = add_param(param, key, value);
369                 if (ret)
370                         break;
371         }
372
373         free(value);
374
375         return ret;
376 }
377
378 /*
379  * Read the server config as properties associated with the dataset.
380  * Missing entries as not treated error and are simply skipped.
381  */
382 int zfs_read_ldd(char *ds,  struct lustre_disk_data *ldd)
383 {
384         zfs_handle_t *zhp;
385         struct zfs_ldd_prop_bridge *bridge;
386         int i, ret = EINVAL;
387
388         if (osd_check_zfs_setup() == 0)
389                 return EINVAL;
390
391         zhp = zfs_open(g_zfs, ds, ZFS_TYPE_FILESYSTEM);
392         if (!zhp) {
393                 zhp = zfs_open(g_zfs, ds, ZFS_TYPE_SNAPSHOT);
394                 if (!zhp)
395                         goto out;
396         }
397
398         for (i = 0; special_ldd_prop_params[i].zlpb_prop_name != NULL; i++) {
399                 bridge = &special_ldd_prop_params[i];
400                 ret = bridge->zlpb_get_prop_fn(zhp, bridge->zlpb_prop_name,
401                                         (void *)ldd + bridge->zlpb_ldd_offset);
402                 if (ret && (ret != ENOENT))
403                         goto out_close;
404         }
405
406         ret = zfs_get_prop_params(zhp, ldd->ldd_params, 4096);
407         if (ret && (ret != ENOENT))
408                 goto out_close;
409
410         ldd->ldd_mount_type = LDD_MT_ZFS;
411         ret = 0;
412 out_close:
413         zfs_close(zhp);
414 out:
415         return ret;
416 }
417
418 int zfs_is_lustre(char *ds, unsigned *mount_type)
419 {
420         struct lustre_disk_data tmp_ldd;
421         int ret;
422
423         if (osd_zfs_setup == 0)
424                 return 0;
425
426         ret = zfs_read_ldd(ds, &tmp_ldd);
427         if ((ret == 0) && (tmp_ldd.ldd_config_ver > 0) &&
428             (strlen(tmp_ldd.ldd_svname) > 0)) {
429                 *mount_type = tmp_ldd.ldd_mount_type;
430                 return 1;
431         }
432
433         return 0;
434 }
435
436 static char *zfs_mkfs_opts(struct mkfs_opts *mop, char *str, int len)
437 {
438         memset(str, 0, len);
439
440         if (strlen(mop->mo_mkfsopts) != 0)
441                 snprintf(str, len, " -o %s", mop->mo_mkfsopts);
442
443         return str;
444 }
445
446 static int zfs_create_vdev(struct mkfs_opts *mop, char *vdev)
447 {
448         int ret = 0;
449
450         /* Silently ignore reserved vdev names */
451         if ((strncmp(vdev, "disk", 4) == 0) ||
452             (strncmp(vdev, "file", 4) == 0) ||
453             (strncmp(vdev, "mirror", 6) == 0) ||
454             (strncmp(vdev, "raidz", 5) == 0) ||
455             (strncmp(vdev, "spare", 5) == 0) ||
456             (strncmp(vdev, "log", 3) == 0) ||
457             (strncmp(vdev, "cache", 5) == 0))
458                 return ret;
459
460         /*
461          * Verify a file exists at the provided absolute path.  If it doesn't
462          * and mo_device_kb is set attempt to create a file vdev to be used.
463          * Relative paths will be passed directly to 'zpool create' which
464          * will check multiple multiple locations under /dev/.
465          */
466         if (vdev[0] == '/') {
467                 ret = access(vdev, F_OK);
468                 if (ret == 0)
469                         return ret;
470
471                 ret = errno;
472                 if (ret != ENOENT) {
473                         fatal();
474                         fprintf(stderr, "Unable to access required vdev "
475                                 "for pool %s (%d)\n", vdev, ret);
476                         return ret;
477                 }
478
479                 if (mop->mo_device_kb == 0) {
480                         fatal();
481                         fprintf(stderr, "Unable to create vdev due to "
482                                 "missing --device-size=#N(KB) parameter\n");
483                         return EINVAL;
484                 }
485
486                 ret = file_create(vdev, mop->mo_device_kb);
487                 if (ret) {
488                         fatal();
489                         fprintf(stderr, "Unable to create vdev %s (%d)\n",
490                                 vdev, ret);
491                         return ret;
492                 }
493         }
494
495         return ret;
496 }
497
498 int zfs_make_lustre(struct mkfs_opts *mop)
499 {
500         zfs_handle_t *zhp;
501         zpool_handle_t *php;
502         char *pool = NULL;
503         char *mkfs_cmd = NULL;
504         char *mkfs_tmp = NULL;
505         char *ds = mop->mo_device;
506         int pool_exists = 0, ret;
507
508         if (osd_check_zfs_setup() == 0)
509                 return EINVAL;
510
511         /* no automatic index with zfs backend */
512         if (mop->mo_ldd.ldd_flags & LDD_F_NEED_INDEX) {
513                 fatal();
514                 fprintf(stderr, "The target index must be specified with "
515                                 "--index\n");
516                 return EINVAL;
517         }
518
519         ret = zfs_check_hostid(mop);
520         if (ret != 0)
521                 goto out;
522
523         pool = strdup(ds);
524         if (pool == NULL)
525                 return ENOMEM;
526
527         mkfs_cmd = malloc(PATH_MAX);
528         if (mkfs_cmd == NULL) {
529                 ret = ENOMEM;
530                 goto out;
531         }
532
533         mkfs_tmp = malloc(PATH_MAX);
534         if (mkfs_tmp == NULL) {
535                 ret = ENOMEM;
536                 goto out;
537         }
538
539         /* Due to zfs_prepare_lustre() check the '/' must exist */
540         strchr(pool, '/')[0] = '\0';
541
542         /* If --reformat was given attempt to destroy the previous dataset */
543         if ((mop->mo_flags & MO_FORCEFORMAT) &&
544             ((zhp = zfs_open(g_zfs, ds, ZFS_TYPE_FILESYSTEM)) != NULL)) {
545
546                 ret = zfs_destroy(zhp, 0);
547                 if (ret) {
548                         zfs_close(zhp);
549                         fprintf(stderr, "Failed destroy zfs dataset %s (%d)\n",
550                                 ds, ret);
551                         goto out;
552                 }
553
554                 zfs_close(zhp);
555         }
556
557         /*
558          * Create the zpool if the vdevs have been specified and the pool
559          * does not already exists.  The pool creation itself will be done
560          * with the zpool command rather than the zpool_create() library call
561          * so the existing zpool error handling can be leveraged.
562          */
563         php = zpool_open(g_zfs, pool);
564         if (php) {
565                 pool_exists = 1;
566                 zpool_close(php);
567         }
568
569         if ((mop->mo_pool_vdevs != NULL) && (pool_exists == 0)) {
570
571                 memset(mkfs_cmd, 0, PATH_MAX);
572                 snprintf(mkfs_cmd, PATH_MAX,
573                         "zpool create -f -O canmount=off %s", pool);
574
575                 /* Append the vdev config and create file vdevs as required */
576                 while (*mop->mo_pool_vdevs != NULL) {
577                         strscat(mkfs_cmd, " ", PATH_MAX);
578                         strscat(mkfs_cmd, *mop->mo_pool_vdevs, PATH_MAX);
579
580                         ret = zfs_create_vdev(mop, *mop->mo_pool_vdevs);
581                         if (ret)
582                                 goto out;
583
584                         mop->mo_pool_vdevs++;
585                 }
586
587                 vprint("mkfs_cmd = %s\n", mkfs_cmd);
588                 ret = run_command(mkfs_cmd, PATH_MAX);
589                 if (ret) {
590                         fatal();
591                         fprintf(stderr, "Unable to create pool %s (%d)\n",
592                                 pool, ret);
593                         goto out;
594                 }
595         }
596
597         /*
598          * Create the ZFS filesystem with any required mkfs options:
599          * - canmount=off is set to prevent zfs automounting
600          * - xattr=sa is set to use system attribute based xattrs
601          */
602         memset(mkfs_cmd, 0, PATH_MAX);
603         snprintf(mkfs_cmd, PATH_MAX,
604                  "zfs create -o canmount=off -o xattr=sa%s %s",
605                  zfs_mkfs_opts(mop, mkfs_tmp, PATH_MAX), ds);
606
607         vprint("mkfs_cmd = %s\n", mkfs_cmd);
608         ret = run_command(mkfs_cmd, PATH_MAX);
609         if (ret) {
610                 fatal();
611                 fprintf(stderr, "Unable to create filesystem %s (%d)\n",
612                         ds, ret);
613                 goto out;
614         }
615
616 out:
617         if (pool != NULL)
618                 free(pool);
619
620         if (mkfs_cmd != NULL)
621                 free(mkfs_cmd);
622
623         if (mkfs_tmp != NULL)
624                 free(mkfs_tmp);
625
626         return ret;
627 }
628
629 int zfs_enable_quota(struct mkfs_opts *mop)
630 {
631         fprintf(stderr, "this option is not only valid for zfs\n");
632         return ENOSYS;
633 }
634
635 int zfs_prepare_lustre(struct mkfs_opts *mop,
636                        char *wanted_mountopts, size_t len)
637 {
638         if (osd_check_zfs_setup() == 0)
639                 return EINVAL;
640
641         if (zfs_name_valid(mop->mo_device, ZFS_TYPE_FILESYSTEM) == 0) {
642                 fatal();
643                 fprintf(stderr, "Invalid filesystem name %s\n", mop->mo_device);
644                 return EINVAL;
645         }
646
647         if (strchr(mop->mo_device, '/') == NULL) {
648                 fatal();
649                 fprintf(stderr, "Missing pool in filesystem name %s\n",
650                         mop->mo_device);
651                 return EINVAL;
652         }
653
654         return 0;
655 }
656
657 int zfs_tune_lustre(char *dev, struct mount_opts *mop)
658 {
659         if (osd_check_zfs_setup() == 0)
660                 return EINVAL;
661
662         return 0;
663 }
664
665 int zfs_label_lustre(struct mount_opts *mop)
666 {
667         zfs_handle_t *zhp;
668         int ret;
669
670         if (osd_check_zfs_setup() == 0)
671                 return EINVAL;
672
673         zhp = zfs_open(g_zfs, mop->mo_source, ZFS_TYPE_FILESYSTEM);
674         if (zhp == NULL)
675                 return EINVAL;
676
677         ret = zfs_set_prop_str(zhp, LDD_SVNAME_PROP, mop->mo_ldd.ldd_svname);
678         zfs_close(zhp);
679
680         return ret;
681 }
682
683 int zfs_init(void)
684 {
685         int ret = 0;
686
687         g_zfs = libzfs_init();
688         if (g_zfs == NULL) {
689                 /* Try to load zfs.ko and retry libzfs_init() */
690
691                 ret = system("/sbin/modprobe -q zfs");
692
693                 if (ret == 0) {
694                         g_zfs = libzfs_init();
695                         if (g_zfs == NULL)
696                                 ret = EINVAL;
697                 }
698         }
699
700         if (ret == 0)
701                 osd_zfs_setup = 1;
702
703         else
704                 fprintf(stderr, "Failed to initialize ZFS library: %d\n", ret);
705
706         return ret;
707 }
708
709 void zfs_fini(void)
710 {
711         if (g_zfs) {
712                 libzfs_fini(g_zfs);
713                 g_zfs = NULL;
714         }
715         osd_zfs_setup = 0;
716 }