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