4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * (C) Copyright (c) 2020, DataDirect Networks Inc, all rights reserved.
8 * All rights reserved. This program and the accompanying materials
9 * are made available under the terms of the GNU Lesser General Public License
10 * LGPL version 2.1 or (at your discretion) any later version.
11 * LGPL version 2.1 accompanies this distribution, and is available at
12 * http://www.gnu.org/licenses/lgpl-2.1.html
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
22 * lustre/utils/liblustreapi_lseek.c
24 * lustreapi library for lseek-related functionality
26 * Author: Mikhail Pershin <mpershin@whamcloud.com>
33 #include <sys/types.h>
36 #ifndef FALLOC_FL_PUNCH_HOLE
37 #include <linux/falloc.h> /* for RHEL7.3 glibc-headers and earlier */
39 #include <sys/syscall.h>
40 #include <sys/ioctl.h>
43 #include <lustre/lustreapi.h>
44 #include "lustreapi_internal.h"
47 * Check if file has a hole
49 * \param fd file descriptor
51 * \retval boolean, true if file has a hole, false otherwise
53 bool llapi_file_is_sparse(int fd)
55 off_t file_end, hole_off;
57 file_end = lseek(fd, 0, SEEK_END);
58 hole_off = lseek(fd, 0, SEEK_HOLE);
60 /* Errors are ignored and file is just reported as non-sparse */
61 return file_end > 0 && hole_off >= 0 && hole_off < file_end;
65 * Get the first data segment in given extent.
67 * \param src_fd source file descriptor
68 * \param offset offset to start from
69 * \param length length of data segment found
71 * \retval next data offset and length on \p length on success.
72 * \retval -errno on failure.
74 off_t llapi_data_seek(int src_fd, off_t offset, size_t *length)
76 off_t data_off, hole_off;
81 llapi_error(LLAPI_MSG_ERROR, rc, "wrong offset: %jd",
86 data_off = lseek(src_fd, offset, SEEK_DATA);
90 llapi_error(LLAPI_MSG_ERROR, rc,
91 "failed SEEK_DATA from %jd",
95 hole_off = lseek(src_fd, 0, SEEK_END);
96 if (data_off > hole_off) /* out of file range */
98 /* no more data in src file, return end of file and zero size
99 * so caller will know there must be hole up to that offset
105 hole_off = lseek(src_fd, data_off, SEEK_HOLE);
108 llapi_error(LLAPI_MSG_ERROR, rc,
109 "failed SEEK_HOLE from %jd", data_off);
112 *length = hole_off - data_off;
117 * Punch hole in a file.
119 * \param fd file descriptor
120 * \param start offset to start from
121 * \param length hole length
123 * \retval 0 on success.
124 * \retval -errno on failure to punch hole
126 int llapi_hole_punch(int fd, off_t start, size_t length)
130 rc = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,