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 * This file is part of Lustre, http://www.lustre.org/
22 * lustre/utils/liblustreapi_mirror.c
24 * Copyright (c) 2017, Intel Corporation.
26 * Author: Jinshan Xiong <jinshan.xiong@intel.com>
33 #include <sys/ioctl.h>
40 #include <sys/types.h>
41 #include <sys/xattr.h>
43 #include <sys/param.h>
45 #include <libcfs/util/ioctl.h>
46 #include <lustre/lustreapi.h>
47 #include <linux/lustre/lustre_ioctl.h>
50 * Set the mirror id for the opening file pointed by @fd, once the mirror
51 * is set successfully, the policy to choose mirrors will be disabed and the
52 * following I/O from this file descriptor will be led to this dedicated
54 * If @id is zero, it will clear the mirror id setting.
56 * \param fd file descriptor, must be opened with O_DIRECT
59 * \retval 0 on success.
60 * \retval -errno on failure.
62 int llapi_mirror_set(int fd, unsigned int id)
67 rc = ioctl(fd, LL_IOC_FLR_SET_MIRROR, id);
76 /* in the current implementation, llite doesn't verify if the mirror
77 * id is valid, it has to be verified in an I/O context so the fstat()
78 * call is to verify that the mirror id is correct. */
79 rc = fstat(fd, &stbuf);
83 (void) ioctl(fd, LL_IOC_FLR_SET_MIRROR, 0);
90 * Clear mirror id setting.
92 * \See llapi_mirror_set() for details.
94 int llapi_mirror_clear(int fd)
96 return llapi_mirror_set(fd, 0);
100 * Read data from a specified mirror with @id. This function won't read
101 * partial read result; either file end is reached, or number of @count bytes
102 * is read, or an error will be returned.
104 * \param fd file descriptor, should be opened with O_DIRECT
105 * \param id mirror id to be read from
106 * \param buf read buffer
107 * \param count number of bytes to be read
108 * \param pos file postion where the read starts
110 * \result >= 0 Number of bytes has been read
111 * \result < 0 The last seen error
113 ssize_t llapi_mirror_read(int fd, unsigned int id, void *buf, size_t count,
120 page_size = sysconf(_SC_PAGESIZE);
126 rc = llapi_mirror_set(fd, id);
133 bytes_read = pread(fd, buf, count, pos);
134 if (!bytes_read) /* end of file */
137 if (bytes_read < 0) {
139 llapi_error(LLAPI_MSG_WARN, result,
140 "fail to pread %ld-%ld of mirror %u",
145 result += bytes_read;
150 if (bytes_read & (page_size - 1)) /* end of file */
154 (void) llapi_mirror_clear(fd);
159 ssize_t llapi_mirror_write(int fd, unsigned int id, const void *buf,
160 size_t count, off_t pos)
166 page_size = sysconf(_SC_PAGESIZE);
170 if (((unsigned long)buf & (page_size - 1)) || pos & (page_size - 1))
173 rc = llapi_mirror_set(fd, id);
178 ssize_t bytes_written;
180 if (pos & (page_size - 1)) {
185 bytes_written = pwrite(fd, buf, count, pos);
186 if (bytes_written < 0) {
188 llapi_error(LLAPI_MSG_WARN, result,
189 "fail to pwrite %ld-%ld of mirror %u",
194 result += bytes_written;
195 pos += bytes_written;
196 buf += bytes_written;
197 count -= bytes_written;
200 (void) llapi_mirror_clear(fd);
205 int llapi_mirror_truncate(int fd, unsigned int id, off_t length)
209 rc = llapi_mirror_set(fd, id);
213 rc = ftruncate(fd, length);
216 llapi_error(LLAPI_MSG_WARN, rc,
217 "fail to ftruncate mirror %u to %ld", id, length);
220 (void) llapi_mirror_clear(fd);
225 int llapi_mirror_punch(int fd, unsigned int id, off_t start, size_t length)
229 rc = llapi_mirror_set(fd, id);
233 rc = llapi_hole_punch(fd, start, length);
234 (void) llapi_mirror_clear(fd);
239 bool llapi_mirror_is_sparse(int fd, unsigned int id)
244 rc = llapi_mirror_set(fd, id);
248 sparse = llapi_file_is_sparse(fd);
249 (void) llapi_mirror_clear(fd);
255 * Seek data in a specified mirror with @id. This function looks for the
256 * first data segment from given offset and returns its offset and length
258 * \param fd file descriptor, should be opened with O_DIRECT
259 * \param id mirror id to be read from
260 * \param pos position for start data seek from
261 * \param size size of data segment found
263 * \result >= 0 Number of bytes has been read
264 * \result < 0 The last seen error
266 off_t llapi_mirror_data_seek(int fd, unsigned int id, off_t pos, size_t *size)
271 rc = llapi_mirror_set(fd, id);
275 data_off = llapi_data_seek(fd, pos, size);
276 (void) llapi_mirror_clear(fd);
282 * Copy data contents from source mirror @src to multiple destinations
283 * pointed by @dst. The destination array @dst will be altered to store
284 * successfully copied mirrors.
286 * \param fd file descriptor, should be opened with O_DIRECT
287 * \param src source mirror id, usually a valid mirror
288 * \param dst an array of destination mirror ids
289 * \param count number of elements in array @dst
291 * \result > 0 Number of mirrors successfully copied
292 * \result < 0 The last seen error
294 ssize_t llapi_mirror_copy_many(int fd, __u16 src, __u16 *dst, size_t count)
296 const size_t buflen = 4 * 1024 * 1024; /* 4M */
311 page_size = sysconf(_SC_PAGESIZE);
317 rc = posix_memalign(&buf, page_size, buflen);
318 if (rc) /* error code is returned directly */
321 sparse = llapi_mirror_is_sparse(fd, src);
325 /* for sparse src we have to be sure that dst has no
326 * data in src holes, so truncate it first
328 for (i = 0; i < nr; i++) {
329 rc = llapi_mirror_truncate(fd, dst[i], pos);
332 /* exclude the failed one */
347 size_t to_write, to_read;
349 if (sparse && pos >= data_end) {
352 data_off = llapi_mirror_data_seek(fd, src, pos,
355 /* Non-fatal, switch to full copy */
360 /* hole at the end of file, set pos to the
361 * data_off, so truncate block at the end
362 * will set final dst size.
368 data_end = data_off + data_size;
370 pos = data_off & ~(page_size - 1);
371 data_end = ((data_end - 1) | (page_size - 1)) + 1;
372 to_read = MIN(data_end - pos, buflen);
377 bytes_read = llapi_mirror_read(fd, src, buf, to_read, pos);
378 if (!bytes_read) { /* end of file */
380 } else if (bytes_read < 0) {
383 llapi_error(LLAPI_MSG_ERROR, result,
384 "error reading bytes %ld-%ld of mirror %u",
389 /* round up to page align to make direct IO happy.
390 * this implies the last segment to write. */
391 to_write = ((bytes_read - 1) | (page_size - 1)) + 1;
393 for (i = 0; i < nr; i++) {
396 written = llapi_mirror_write(fd, dst[i], buf,
401 /* this mirror is not written succesfully,
402 * get rid of it from the array */
407 assert(written == to_write);
410 eof = bytes_read < to_read;
416 for (i = 0; i < nr; i++) {
417 rc = llapi_mirror_truncate(fd, dst[i], pos);
421 /* exclude the failed one */
429 return nr > 0 ? nr : result;
433 * Copy data contents from source mirror @src to target mirror @dst.
435 * \param fd file descriptor, should be opened with O_DIRECT
436 * \param src source mirror id, usually a valid mirror
437 * \param dst mirror id of copy destination
438 * \param pos start file pos
439 * \param count number of bytes to be copied
441 * \result > 0 Number of mirrors successfully copied
442 * \result < 0 The last seen error
444 int llapi_mirror_copy(int fd, unsigned int src, unsigned int dst, off_t pos,
447 const size_t buflen = 4 * 1024 * 1024; /* 4M */
456 page_size = sysconf(_SC_PAGESIZE);
460 if (pos & (page_size - 1) || !dst)
463 if (count != OBD_OBJECT_EOF && count & (page_size - 1))
466 rc = posix_memalign(&buf, page_size, buflen);
467 if (rc) /* error code is returned directly */
470 while (result < count) {
471 ssize_t bytes_read, bytes_written;
472 size_t to_read, to_write;
474 to_read = MIN(buflen, count - result);
476 bytes_read = pread(fd, buf, to_read, pos);
478 bytes_read = llapi_mirror_read(fd, src, buf, to_read,
480 if (!bytes_read) { /* end of file */
482 } else if (bytes_read < 0) {
484 llapi_error(LLAPI_MSG_ERROR, result,
485 "error reading bytes %ld-%ld of mirror %u",
490 /* round up to page align to make direct IO happy.
491 * this implies the last segment to write. */
492 to_write = (bytes_read + page_size - 1) & ~(page_size - 1);
494 bytes_written = llapi_mirror_write(fd, dst, buf, to_write,
496 if (bytes_written < 0) {
497 result = bytes_written;
498 llapi_error(LLAPI_MSG_ERROR, result,
499 "error writing bytes %ld-%ld of mirror %u",
504 assert(bytes_written == to_write);
507 result += bytes_read;
509 if (bytes_read < to_read) /* short read occurred */
515 if (result > 0 && pos & (page_size - 1)) {
516 rc = llapi_mirror_truncate(fd, dst, pos);
518 llapi_error(LLAPI_MSG_ERROR, result,
519 "error truncating mirror %u to %ld",