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.
186 * \return 0 on success, an error code otherwise.
188 int llapi_pcc_detach_fd(int fd)
192 rc = ioctl(fd, LL_IOC_PCC_DETACH);
197 * detach PCC cache of a file via FID.
199 * \param mntpath Fullpath to the client mount point.
200 * \param fid FID of the file.
202 * \return 0 on success, an error code otherwise.
204 int llapi_pcc_detach_fid(const char *mntpath, const struct lu_fid *fid)
208 struct lu_pcc_detach detach;
210 rc = get_root_path(WANT_FD, NULL, &fd, (char *)mntpath, -1);
212 llapi_error(LLAPI_MSG_ERROR, rc, "cannot get root path: %s",
218 * PCC prefetching algorithm scans Lustre OPEN/CLOSE changelogs
219 * to determine the candidate files needing to prefetch into
220 * PCC. To avoid generattion of unnecessary open/close changelogs,
221 * we implement a new dir ioctl LL_IOC_PCC_DETACH_BY_FID to detach
224 detach.pccd_fid = *fid;
225 rc = ioctl(fd, LL_IOC_PCC_DETACH_BY_FID, &detach);
231 * detach PCC cache of a file via FID.
233 * \param mntpath Fullpath to the client mount point.
234 * \param fid FID string of the file.
236 * \return 0 on success, an error code otherwise.
238 int llapi_pcc_detach_fid_str(const char *mntpath, const char *fidstr)
242 const char *fidstr_orig = fidstr;
244 while (*fidstr == '[')
246 rc = sscanf(fidstr, SFID, RFID(&fid));
247 if (rc != 3 || !fid_is_sane(&fid)) {
248 llapi_err_noerrno(LLAPI_MSG_ERROR,
249 "bad FID format '%s', should be [seq:oid:ver]"
250 " (e.g. "DFID")\n", fidstr_orig,
251 (unsigned long long)FID_SEQ_NORMAL, 2, 0);
255 rc = llapi_pcc_detach_fid(mntpath, &fid);
261 * detach PCC cache of a file.
263 * \param path Fullpath to the file to operate on.
265 * \return 0 on success, an error code otherwise.
267 int llapi_pcc_detach_file(const char *path)
272 fd = open(path, O_RDWR | O_NONBLOCK);
275 llapi_error(LLAPI_MSG_ERROR, rc, "cannot open '%s'",
280 rc = llapi_pcc_detach_fd(fd);
286 * Return the current PCC state related to a file.
288 * \param fd File handle.
289 * \param state PCC state info.
291 * \return 0 on success, an error code otherwise.
293 int llapi_pcc_state_get_fd(int fd, struct lu_pcc_state *state)
297 rc = ioctl(fd, LL_IOC_PCC_STATE, state);
298 /* If error, save errno value */
299 rc = rc ? -errno : 0;
305 * Return the current PCC state related to file pointed by a path.
307 * see llapi_pcc_state_get_fd() for args use and return
309 int llapi_pcc_state_get(const char *path, struct lu_pcc_state *state)
314 fd = open(path, O_RDONLY | O_NONBLOCK);
318 rc = llapi_pcc_state_get_fd(fd, state);
325 * Add/delete a PCC backend on a client.
327 int llapi_pccdev_set(const char *mntpath, const char *cmd)
329 char buf[sizeof(struct obd_uuid)];
335 rc = llapi_getname(mntpath, buf, sizeof(buf));
337 llapi_error(LLAPI_MSG_ERROR, rc,
338 "cannot get name for '%s'\n", mntpath);
342 rc = cfs_get_param_paths(&path, "llite/%s/pcc", buf);
346 fd = open(path.gl_pathv[0], O_WRONLY);
349 llapi_error(LLAPI_MSG_ERROR, rc, "error opening %s",
354 count = write(fd, cmd, strlen(cmd));
358 llapi_error(LLAPI_MSG_ERROR, rc,
359 "error: setting llite.%s.pcc=\"%s\"\n",
361 } else if (count < strlen(cmd)) { /* Truncate case */
363 llapi_error(LLAPI_MSG_ERROR, rc,
364 "setting llite.%s.pcc=\"%s\": wrote only %zd\n",
369 cfs_free_param_data(&path);
374 * List all PCC backend devices on a client.
376 int llapi_pccdev_get(const char *mntpath)
378 long page_size = sysconf(_SC_PAGESIZE);
379 char pathbuf[sizeof(struct obd_uuid)];
385 rc = llapi_getname(mntpath, pathbuf, sizeof(pathbuf));
387 llapi_error(LLAPI_MSG_ERROR, rc,
388 "cannot get name for '%s'\n", mntpath);
392 rc = cfs_get_param_paths(&path, "llite/%s/pcc", pathbuf);
396 /* Read the contents of file to stdout */
397 fd = open(path.gl_pathv[0], O_RDONLY);
400 llapi_error(LLAPI_MSG_ERROR, rc,
401 "error: pccdev_get: opening '%s'\n",
406 buf = calloc(1, page_size);
409 llapi_error(LLAPI_MSG_ERROR, rc,
410 "error: pccdev_get: allocating '%s' buffer\n",
416 ssize_t count = read(fd, buf, page_size);
423 llapi_error(LLAPI_MSG_ERROR, rc,
424 "error: pccdev_get: "
430 if (fwrite(buf, 1, count, stdout) != count) {
432 llapi_error(LLAPI_MSG_ERROR, rc,
433 "error: get_param: write to stdout\n");
441 cfs_free_param_data(&path);