Whamcloud - gitweb
LU-12616 obclass: fix MDS start/stop race
[fs/lustre-release.git] / lustre / utils / liblustreapi_param.c
1 /*
2  * LGPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * All rights reserved. This program and the accompanying materials
7  * are made available under the terms of the GNU Lesser General Public License
8  * (LGPL) version 2.1 or (at your discretion) any later version.
9  * (LGPL) version 2.1 accompanies this distribution, and is available at
10  * http://www.gnu.org/licenses/lgpl-2.1.html
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * LGPL HEADER END
18  */
19 /*
20  * lustre/utils/liblustreapi_param.c
21  *
22  * This code handles user interaction with the configuration interface
23  * to the Lustre file system to fine tune it.
24  *
25  * Copyright (c) 2016, Intel Corporation.
26  */
27 #include <errno.h>
28 #include <stdint.h>
29
30 #include <libcfs/util/param.h>
31 #include <linux/lustre/lustre_user.h>
32 #include <lustre/lustreapi.h>
33 #include "lustreapi_internal.h"
34
35 /**
36  * return the parameter's path for a specific device type or mountpoint
37  *
38  * \param param         the results returned to the caller
39  * \param obd_type      Lustre OBD device type
40  *
41  * \param filter        filter combined with the type agrument allow the
42  * \param type          caller to limit the scope of the search for the
43  *                      parameter's path. Typical options are search by
44  *                      Lustre filesystem name or by the path to a file
45  *                      or directory in the filesystem.
46  *
47  * \param param_name    parameter name to fetch
48  *
49  * Using filter and the type argument we can limit the scope of the
50  * search to either the parameter belonging to a specific lustre filesystem
51  * (if it exists) or using a given file or directory path located on a
52  * mounted Lustre filesystem. The last case it can do is a special search
53  * based on exactly what the user passed instead of scanning file paths
54  * or specific file systems.
55  *
56  * If "obd_type" matches a Lustre device then the first matching device
57  * (as with "lctl dl", constrained by \param filter and \param type)
58  * will be used to provide the return value, otherwise the first such
59  * device found will be used.
60  *
61  * Return 0 for success, with the results stored in \param param.
62  * Return -ve value for error.
63  */
64 int
65 get_lustre_param_path(const char *obd_type, const char *filter,
66                       enum param_filter type, const char *param_name,
67                       glob_t *param)
68 {
69         char pattern[PATH_MAX];
70         int rc = 0;
71
72         if (filter == NULL && type != FILTER_BY_NONE)
73                 return -EINVAL;
74
75         switch (type) {
76         case FILTER_BY_PATH:
77                 rc = llapi_search_fsname(filter, pattern);
78                 if (rc) {
79                         llapi_error(LLAPI_MSG_ERROR, rc,
80                                     "'%s' is not on a Lustre filesystem",
81                                     filter);
82                         return rc;
83                 }
84                 if (strlen(pattern) + 3 > sizeof(pattern))
85                         return -E2BIG;
86                 strncat(pattern, "-*", sizeof(pattern) - 1);
87                 break;
88         case FILTER_BY_FS_NAME:
89                 rc = snprintf(pattern, sizeof(pattern) - 1, "%s-*", filter);
90                 if (rc < 0)
91                         return rc;
92                 else if (rc >= sizeof(pattern))
93                         return -EINVAL;
94                 rc = 0;
95                 break;
96         case FILTER_BY_EXACT:
97                 if (strlen(filter) + 1 > sizeof(pattern))
98                         return -E2BIG;
99                 strncpy(pattern, filter, sizeof(pattern));
100                 break;
101         case FILTER_BY_NONE:
102         default:
103                 break;
104         }
105
106         if (type == FILTER_BY_NONE) {
107                 if (cfs_get_param_paths(param, "%s", param_name) != 0)
108                         rc = -errno;
109         } else if (param_name != NULL) {
110                 if (cfs_get_param_paths(param, "%s/%s/%s",
111                                        obd_type, pattern, param_name) != 0)
112                         rc = -errno;
113         } else {
114                 if (cfs_get_param_paths(param, "%s/%s",
115                                        obd_type, pattern) != 0)
116                         rc = -errno;
117         }
118
119         return rc;
120 }
121
122 /**
123  * return a parameter of a single line value for a specific device type
124  * or mountpoint
125  *
126  * \param obd_type      Lustre OBD device type
127  *
128  * \param filter        filter combined with the type agruments allow the
129  * \param type          caller to limit the scope of the search for the
130  *                      parameter's path. Typical options are search by
131  *                      Lustre filesystem name or by the path to a file
132  *                      or directory in the filesystem.
133  *
134  * \param param_name    parameter name to fetch
135  * \param value         return buffer for parameter value string
136  * \param val_len       size of buffer for return value
137  *
138  * Using filter and the type argument we can limit the scope of the
139  * search to either the parameter belonging to a specific lustre filesystem
140  * (if it exists) or using a given file or directory path located on a
141  * mounted Lustre filesystem. The last case it can do is a special search
142  * based on exactly what the user passed instead of scanning file paths
143  * or specific file systems.
144  *
145  * If "obd_type" matches a Lustre device then the first matching device
146  * (as with "lctl dl", constrained by \param filter and \param type)
147  * will be used to provide the return value, otherwise the first such
148  * device found will be used.
149  *
150  * Return 0 for success, with a NUL-terminated string in \param value.
151  * Return negative errno value for error.
152  */
153 int
154 get_lustre_param_value(const char *obd_type, const char *filter,
155                        enum param_filter type, const char *param_name,
156                        char *value, size_t val_len)
157 {
158         glob_t param;
159         FILE *fp;
160         int rc;
161
162         rc = get_lustre_param_path(obd_type, filter, type, param_name, &param);
163         if (rc != 0)
164                 return -ENOENT;
165
166         fp = fopen(param.gl_pathv[0], "r");
167         if (fp == NULL) {
168                 rc = -errno;
169                 llapi_error(LLAPI_MSG_ERROR, rc, "error: opening '%s'",
170                             param.gl_pathv[0]);
171                 goto err;
172         }
173
174         if (fgets(value, val_len, fp) == NULL) {
175                 if (!feof(fp))
176                         rc = -ferror(fp);
177         }
178         fclose(fp);
179 err:
180         cfs_free_param_data(&param);
181
182         return rc;
183 }