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>
44 #include <libcfs/util/ioctl.h>
45 #include <lustre/lustreapi.h>
46 #include <linux/lustre/lustre_ioctl.h>
49 * Set the mirror id for the opening file pointed by @fd, once the mirror
50 * is set successfully, the policy to choose mirrors will be disabed and the
51 * following I/O from this file descriptor will be led to this dedicated
53 * If @id is zero, it will clear the mirror id setting.
55 * \param fd file descriptor, must be opened with O_DIRECT
58 * \retval 0 on success.
59 * \retval -errno on failure.
61 int llapi_mirror_set(int fd, unsigned int id)
66 rc = ioctl(fd, LL_IOC_FLR_SET_MIRROR, id);
75 /* in the current implementation, llite doesn't verify if the mirror
76 * id is valid, it has to be verified in an I/O context so the fstat()
77 * call is to verify that the mirror id is correct. */
78 rc = fstat(fd, &stbuf);
82 (void) ioctl(fd, LL_IOC_FLR_SET_MIRROR, 0);
89 * Clear mirror id setting.
91 * \See llapi_mirror_set() for details.
93 int llapi_mirror_clear(int fd)
95 return llapi_mirror_set(fd, 0);
99 * Read data from a specified mirror with @id. This function won't read
100 * partial read result; either file end is reached, or number of @count bytes
101 * is read, or an error will be returned.
103 * \param fd file descriptor, should be opened with O_DIRECT
104 * \param id mirror id to be read from
105 * \param buf read buffer
106 * \param count number of bytes to be read
107 * \param pos file postion where the read starts
109 * \result >= 0 Number of bytes has been read
110 * \result < 0 The last seen error
112 ssize_t llapi_mirror_read(int fd, unsigned int id, void *buf, size_t count,
115 size_t page_size = sysconf(_SC_PAGESIZE);
119 rc = llapi_mirror_set(fd, id);
126 bytes_read = pread(fd, buf, count, pos);
127 if (!bytes_read) /* end of file */
130 if (bytes_read < 0) {
135 result += bytes_read;
140 if (bytes_read & (page_size - 1)) /* end of file */
144 (void) llapi_mirror_clear(fd);
149 static ssize_t llapi_mirror_write(int fd, unsigned int id,
150 const void *buf, size_t count, off_t pos)
152 size_t page_size = sysconf(_SC_PAGESIZE);
156 if (((unsigned long)buf & (page_size - 1)) || pos & (page_size - 1))
159 rc = llapi_mirror_set(fd, id);
164 ssize_t bytes_written;
166 if (pos & (page_size - 1)) {
171 bytes_written = pwrite(fd, buf, count, pos);
172 if (bytes_written < 0) {
177 result += bytes_written;
178 pos += bytes_written;
179 buf += bytes_written;
180 count -= bytes_written;
183 (void) llapi_mirror_clear(fd);
188 static int llapi_mirror_truncate(int fd, unsigned int id, off_t length)
192 rc = llapi_mirror_set(fd, id);
196 rc = ftruncate(fd, length);
198 (void) llapi_mirror_clear(fd);
204 * Copy data contents from source mirror @src to multiple destinations
205 * pointed by @dst. The destination array @dst will be altered to store
206 * successfully copied mirrors.
208 * \param fd file descriptor, should be opened with O_DIRECT
209 * \param src source mirror id, usually a valid mirror
210 * \param dst an array of destination mirror ids
211 * \param count number of elements in array @dst
213 * \result > 0 Number of mirrors successfully copied
214 * \result < 0 The last seen error
216 ssize_t llapi_mirror_copy_many(int fd, unsigned int src, unsigned int *dst,
219 const size_t buflen = 4 * 1024 * 1024; /* 4M */
222 size_t page_size = sysconf(_SC_PAGESIZE);
232 rc = posix_memalign(&buf, page_size, buflen);
233 if (rc) /* error code is returned directly */
241 bytes_read = llapi_mirror_read(fd, src, buf, buflen, pos);
242 if (!bytes_read) { /* end of file */
244 } else if (bytes_read < 0) {
250 /* round up to page align to make direct IO happy.
251 * this implies the last segment to write. */
252 to_write = (bytes_read + page_size - 1) & ~(page_size - 1);
254 for (i = 0; i < nr; i++) {
257 written = llapi_mirror_write(fd, dst[i], buf,
262 /* this mirror is not written succesfully,
263 * get rid of it from the array */
269 assert(written == to_write);
273 eof = bytes_read < buflen;
279 for (i = 0; i < nr; i++) {
280 rc = llapi_mirror_truncate(fd, dst[i], pos);
284 /* exclude the failed one */
292 return nr > 0 ? nr : result;
295 int llapi_mirror_copy(int fd, unsigned int src, unsigned int dst)
299 rc = llapi_mirror_copy_many(fd, src, &dst, 1);
300 return rc > 0 ? 0 : rc;