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);
196 /* If error, save errno value */
197 rc = rc ? -errno : 0;
203 * detach PCC cache of a file via FID.
205 * \param mntpath Fullpath to the client mount point.
206 * \param fid FID of the file.
207 * \param option Detach option.
209 * \return 0 on success, an error code otherwise.
211 int llapi_pcc_detach_fid(const char *mntpath, const struct lu_fid *fid,
216 struct lu_pcc_detach_fid detach;
218 rc = get_root_path(WANT_FD, NULL, &fd, (char *)mntpath, -1, NULL, NULL);
220 llapi_error(LLAPI_MSG_ERROR, rc, "cannot get root path: %s",
226 * PCC prefetching algorithm scans Lustre OPEN/CLOSE changelogs
227 * to determine the candidate files needing to prefetch into
228 * PCC. To avoid generattion of unnecessary open/close changelogs,
229 * we implement a new dir ioctl LL_IOC_PCC_DETACH_BY_FID to detach
232 detach.pccd_fid = *fid;
233 detach.pccd_opt = option;
235 /* fd is cached internally, no need to close */
236 rc = ioctl(fd, LL_IOC_PCC_DETACH_BY_FID, &detach);
237 rc = rc ? -errno : 0;
243 * detach PCC cache of a file via FID.
245 * \param mntpath Fullpath to the client mount point.
246 * \param fidstr FID string of the file.
247 * \param option Detach option.
249 * \return 0 on success, an error code otherwise.
251 int llapi_pcc_detach_fid_str(const char *mntpath, const char *fidstr,
256 const char *fidstr_orig = fidstr;
258 while (*fidstr == '[')
260 rc = sscanf(fidstr, SFID, RFID(&fid));
261 if (rc != 3 || !fid_is_sane(&fid)) {
262 llapi_err_noerrno(LLAPI_MSG_ERROR,
263 "bad FID format '%s', should be [seq:oid:ver]"
264 " (e.g. "DFID")\n", fidstr_orig,
265 (unsigned long long)FID_SEQ_NORMAL, 2, 0);
269 rc = llapi_pcc_detach_fid(mntpath, &fid, option);
275 * detach PCC cache of a file.
277 * \param path Fullpath to the file to operate on.
278 * \param option Detach option.
280 * \return 0 on success, an error code otherwise.
282 int llapi_pcc_detach_file(const char *path, __u32 option)
287 fd = open(path, O_RDWR | O_NONBLOCK);
290 llapi_error(LLAPI_MSG_ERROR, rc, "cannot open '%s'",
295 rc = llapi_pcc_detach_fd(fd, option);
301 * Return the current PCC state related to a file.
303 * \param fd File handle.
304 * \param state PCC state info.
306 * \return 0 on success, an error code otherwise.
308 int llapi_pcc_state_get_fd(int fd, struct lu_pcc_state *state)
312 rc = ioctl(fd, LL_IOC_PCC_STATE, state);
313 /* If error, save errno value */
314 rc = rc ? -errno : 0;
320 * Return the current PCC state related to file pointed by a path.
322 * see llapi_pcc_state_get_fd() for args use and return
324 int llapi_pcc_state_get(const char *path, struct lu_pcc_state *state)
329 fd = open(path, O_RDONLY | O_NONBLOCK);
333 rc = llapi_pcc_state_get_fd(fd, state);
340 * Add/delete a PCC backend on a client.
342 int llapi_pccdev_set(const char *mntpath, const char *cmd)
344 char buf[sizeof(struct obd_uuid)];
350 rc = llapi_getname(mntpath, buf, sizeof(buf));
352 llapi_error(LLAPI_MSG_ERROR, rc,
353 "cannot get name for '%s'", mntpath);
357 rc = cfs_get_param_paths(&path, "llite/%s/pcc", buf);
361 fd = open(path.gl_pathv[0], O_WRONLY);
364 llapi_error(LLAPI_MSG_ERROR, rc, "error opening %s",
369 count = write(fd, cmd, strlen(cmd));
373 llapi_error(LLAPI_MSG_ERROR, rc,
374 "error: setting llite.%s.pcc='%s'",
376 } else if (count < strlen(cmd)) { /* Truncate case */
378 llapi_error(LLAPI_MSG_ERROR, rc,
379 "setting llite.%s.pcc='%s': wrote only %zd",
384 cfs_free_param_data(&path);
389 * List all PCC backend devices on a client.
391 int llapi_pccdev_get(const char *mntpath)
393 long page_size = sysconf(_SC_PAGESIZE);
394 char pathbuf[sizeof(struct obd_uuid)];
400 rc = llapi_getname(mntpath, pathbuf, sizeof(pathbuf));
402 llapi_error(LLAPI_MSG_ERROR, rc,
403 "cannot get name for '%s'", mntpath);
407 rc = cfs_get_param_paths(&path, "llite/%s/pcc", pathbuf);
411 /* Read the contents of file to stdout */
412 fd = open(path.gl_pathv[0], O_RDONLY);
415 llapi_error(LLAPI_MSG_ERROR, rc,
416 "error: pccdev_get: opening '%s'",
421 buf = calloc(1, page_size);
424 llapi_error(LLAPI_MSG_ERROR, rc,
425 "error: pccdev_get: allocating '%s' buffer",
431 ssize_t count = read(fd, buf, page_size);
438 llapi_error(LLAPI_MSG_ERROR, rc,
439 "error: pccdev_get: reading failed");
444 if (fwrite(buf, 1, count, stdout) != count) {
446 llapi_error(LLAPI_MSG_ERROR, rc,
447 "error: get_param: write to stdout");
455 cfs_free_param_data(&path);