4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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
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.
20 * Copyright (c) 2017, DDN Storage Corporation.
23 * This file is part of Lustre, http://www.lustre.org/
27 * lustreapi library for Persistent Client Cache.
29 * Author: Li Xi <lixi@ddn.com>
30 * Author: Qian Yingjin <qian@ddn.com>
32 #include <sys/types.h>
35 #include <lustre/lustreapi.h>
36 #include <linux/lustre/lustre_user.h>
37 #include <linux/lustre/lustre_fid.h>
41 #include <sys/ioctl.h>
42 #include "lustreapi_internal.h"
45 * Fetch and attach a file to readwrite PCC.
48 static int llapi_readwrite_pcc_attach_fd(int fd, __u32 archive_id)
51 struct ll_ioc_lease *data;
53 rc = llapi_lease_acquire(fd, LL_LEASE_WRLCK);
55 llapi_error(LLAPI_MSG_ERROR, rc, "cannot get lease");
59 data = malloc(offsetof(typeof(*data), lil_ids[1]));
62 llapi_err_noerrno(LLAPI_MSG_ERROR,
63 "failed to allocate memory");
67 data->lil_mode = LL_LEASE_UNLCK;
68 data->lil_flags = LL_LEASE_PCC_ATTACH;
70 data->lil_ids[0] = archive_id;
71 rc = llapi_lease_set(fd, data);
73 if (rc == 0) /* lost lease lock */
75 llapi_error(LLAPI_MSG_ERROR, rc,
76 "cannot attach with ID: %u", archive_id);
85 static int llapi_readwrite_pcc_attach(const char *path, __u32 archive_id)
90 fd = open(path, O_RDWR | O_NONBLOCK);
93 llapi_error(LLAPI_MSG_ERROR, rc, "cannot open '%s'",
98 rc = llapi_readwrite_pcc_attach_fd(fd, archive_id);
104 int llapi_pcc_attach(const char *path, __u32 id, enum lu_pcc_type type)
109 case LU_PCC_READWRITE:
110 rc = llapi_readwrite_pcc_attach(path, id);
119 static int llapi_readwrite_pcc_attach_fid(const char *mntpath,
120 const struct lu_fid *fid,
126 fd = llapi_open_by_fid(mntpath, fid, O_RDWR | O_NONBLOCK);
129 llapi_error(LLAPI_MSG_ERROR, rc,
130 "llapi_open_by_fid for " DFID "failed",
135 rc = llapi_readwrite_pcc_attach_fd(fd, id);
141 int llapi_pcc_attach_fid(const char *mntpath, const struct lu_fid *fid,
142 __u32 id, enum lu_pcc_type type)
147 case LU_PCC_READWRITE:
148 rc = llapi_readwrite_pcc_attach_fid(mntpath, fid, id);
158 int llapi_pcc_attach_fid_str(const char *mntpath, const char *fidstr,
159 __u32 id, enum lu_pcc_type type)
163 const char *fidstr_orig = fidstr;
165 while (*fidstr == '[')
167 rc = sscanf(fidstr, SFID, RFID(&fid));
169 llapi_err_noerrno(LLAPI_MSG_ERROR,
170 "bad FID format '%s', should be [seq:oid:ver]"
171 " (e.g. "DFID")\n", fidstr_orig,
172 (unsigned long long)FID_SEQ_NORMAL, 2, 0);
176 rc = llapi_pcc_attach_fid(mntpath, &fid, id, type);
182 * detach PCC cache of a file by using fd.
184 * \param fd File handle.
185 * \param option Detach option
187 * \return 0 on success, an error code otherwise.
189 int llapi_pcc_detach_fd(int fd, __u32 option)
191 struct lu_pcc_detach detach;
194 detach.pccd_opt = option;
195 rc = ioctl(fd, LL_IOC_PCC_DETACH, &detach);
200 * detach PCC cache of a file via FID.
202 * \param mntpath Fullpath to the client mount point.
203 * \param fid FID of the file.
204 * \param option Detach option.
206 * \return 0 on success, an error code otherwise.
208 int llapi_pcc_detach_fid(const char *mntpath, const struct lu_fid *fid,
213 struct lu_pcc_detach_fid detach;
215 rc = get_root_path(WANT_FD, NULL, &fd, (char *)mntpath, -1);
217 llapi_error(LLAPI_MSG_ERROR, rc, "cannot get root path: %s",
223 * PCC prefetching algorithm scans Lustre OPEN/CLOSE changelogs
224 * to determine the candidate files needing to prefetch into
225 * PCC. To avoid generattion of unnecessary open/close changelogs,
226 * we implement a new dir ioctl LL_IOC_PCC_DETACH_BY_FID to detach
229 detach.pccd_fid = *fid;
230 detach.pccd_opt = option;
231 rc = ioctl(fd, LL_IOC_PCC_DETACH_BY_FID, &detach);
237 * detach PCC cache of a file via FID.
239 * \param mntpath Fullpath to the client mount point.
240 * \param fidstr FID string of the file.
241 * \param option Detach option.
243 * \return 0 on success, an error code otherwise.
245 int llapi_pcc_detach_fid_str(const char *mntpath, const char *fidstr,
250 const char *fidstr_orig = fidstr;
252 while (*fidstr == '[')
254 rc = sscanf(fidstr, SFID, RFID(&fid));
255 if (rc != 3 || !fid_is_sane(&fid)) {
256 llapi_err_noerrno(LLAPI_MSG_ERROR,
257 "bad FID format '%s', should be [seq:oid:ver]"
258 " (e.g. "DFID")\n", fidstr_orig,
259 (unsigned long long)FID_SEQ_NORMAL, 2, 0);
263 rc = llapi_pcc_detach_fid(mntpath, &fid, option);
269 * detach PCC cache of a file.
271 * \param path Fullpath to the file to operate on.
272 * \param option Detach option.
274 * \return 0 on success, an error code otherwise.
276 int llapi_pcc_detach_file(const char *path, __u32 option)
281 fd = open(path, O_RDWR | O_NONBLOCK);
284 llapi_error(LLAPI_MSG_ERROR, rc, "cannot open '%s'",
289 rc = llapi_pcc_detach_fd(fd, option);
295 * Return the current PCC state related to a file.
297 * \param fd File handle.
298 * \param state PCC state info.
300 * \return 0 on success, an error code otherwise.
302 int llapi_pcc_state_get_fd(int fd, struct lu_pcc_state *state)
306 rc = ioctl(fd, LL_IOC_PCC_STATE, state);
307 /* If error, save errno value */
308 rc = rc ? -errno : 0;
314 * Return the current PCC state related to file pointed by a path.
316 * see llapi_pcc_state_get_fd() for args use and return
318 int llapi_pcc_state_get(const char *path, struct lu_pcc_state *state)
323 fd = open(path, O_RDONLY | O_NONBLOCK);
327 rc = llapi_pcc_state_get_fd(fd, state);
334 * Add/delete a PCC backend on a client.
336 int llapi_pccdev_set(const char *mntpath, const char *cmd)
338 char buf[sizeof(struct obd_uuid)];
344 rc = llapi_getname(mntpath, buf, sizeof(buf));
346 llapi_error(LLAPI_MSG_ERROR, rc,
347 "cannot get name for '%s'\n", mntpath);
351 rc = cfs_get_param_paths(&path, "llite/%s/pcc", buf);
355 fd = open(path.gl_pathv[0], O_WRONLY);
358 llapi_error(LLAPI_MSG_ERROR, rc, "error opening %s",
363 count = write(fd, cmd, strlen(cmd));
367 llapi_error(LLAPI_MSG_ERROR, rc,
368 "error: setting llite.%s.pcc=\"%s\"\n",
370 } else if (count < strlen(cmd)) { /* Truncate case */
372 llapi_error(LLAPI_MSG_ERROR, rc,
373 "setting llite.%s.pcc=\"%s\": wrote only %zd\n",
378 cfs_free_param_data(&path);
383 * List all PCC backend devices on a client.
385 int llapi_pccdev_get(const char *mntpath)
387 long page_size = sysconf(_SC_PAGESIZE);
388 char pathbuf[sizeof(struct obd_uuid)];
394 rc = llapi_getname(mntpath, pathbuf, sizeof(pathbuf));
396 llapi_error(LLAPI_MSG_ERROR, rc,
397 "cannot get name for '%s'\n", mntpath);
401 rc = cfs_get_param_paths(&path, "llite/%s/pcc", pathbuf);
405 /* Read the contents of file to stdout */
406 fd = open(path.gl_pathv[0], O_RDONLY);
409 llapi_error(LLAPI_MSG_ERROR, rc,
410 "error: pccdev_get: opening '%s'\n",
415 buf = calloc(1, page_size);
418 llapi_error(LLAPI_MSG_ERROR, rc,
419 "error: pccdev_get: allocating '%s' buffer\n",
425 ssize_t count = read(fd, buf, page_size);
432 llapi_error(LLAPI_MSG_ERROR, rc,
433 "error: pccdev_get: "
439 if (fwrite(buf, 1, count, stdout) != count) {
441 llapi_error(LLAPI_MSG_ERROR, rc,
442 "error: get_param: write to stdout\n");
450 cfs_free_param_data(&path);