1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2014 Red Hat
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
16 #include <sys/types.h>
20 // from include/linux/falloc.h:
21 #ifndef FALLOC_FL_PUNCH_HOLE
22 # define FALLOC_FL_PUNCH_HOLE 0x2
33 #if defined(DARWIN) || defined(__FreeBSD__)
34 #include <sys/mount.h>
38 #include "include/compat.h"
42 FS *FS::create(uint64_t f_type)
54 FS *FS::create_by_fd(int fd)
58 return create(st.f_type);
63 int FS::set_alloc_hint(int fd, uint64_t hint)
68 #ifdef HAVE_NAME_TO_HANDLE_AT
69 int FS::get_handle(int fd, std::string *h)
71 char buf[sizeof(struct file_handle) + MAX_HANDLE_SZ];
72 struct file_handle *fh = (struct file_handle *)buf;
75 fh->handle_bytes = MAX_HANDLE_SZ;
76 int r = name_to_handle_at(fd, "", fh, &mount_id, AT_EMPTY_PATH);
80 *h = std::string(buf, fh->handle_bytes + sizeof(struct file_handle));
84 int FS::open_handle(int mount_fd, const std::string& h, int flags)
86 if (h.length() < sizeof(struct file_handle)) {
89 struct file_handle *fh = (struct file_handle *)h.data();
90 if (fh->handle_bytes > h.length()) {
93 int fd = open_by_handle_at(mount_fd, fh, flags);
99 #else // HAVE_NAME_TO_HANDLE_AT
101 int FS::get_handle(int fd, std::string *h)
106 int FS::open_handle(int mount_fd, const std::string& h, int flags)
111 #endif // HAVE_NAME_TO_HANDLE_AT
113 int FS::copy_file_range(int to_fd, uint64_t to_offset,
115 uint64_t from_offset, uint64_t from_len)
117 assert(0 == "write me");
120 int FS::zero(int fd, uint64_t offset, uint64_t length)
126 From the fallocate(2) man page:
128 Specifying the FALLOC_FL_PUNCH_HOLE flag (available since Linux 2.6.38)
129 in mode deallocates space (i.e., creates a hole) in the byte range
130 starting at offset and continuing for len bytes. Within the specified
131 range, partial filesystem blocks are zeroed, and whole filesystem
132 blocks are removed from the file. After a successful call, subsequent
133 reads from this range will return zeroes.
135 The FALLOC_FL_PUNCH_HOLE flag must be ORed with FALLOC_FL_KEEP_SIZE in
136 mode; in other words, even when punching off the end of the file, the
137 file size (as reported by stat(2)) does not change.
139 Not all filesystems support FALLOC_FL_PUNCH_HOLE; if a filesystem
140 doesn't support the operation, an error is returned. The operation is
141 supported on at least the following filesystems:
143 * XFS (since Linux 2.6.38)
145 * ext4 (since Linux 3.0)
147 * Btrfs (since Linux 3.7)
149 * tmpfs (since Linux 3.5)
151 So: we only do this is PUNCH_HOLE *and* KEEP_SIZE are defined.
154 #if !defined(DARWIN) && !defined(__FreeBSD__)
155 # ifdef CEPH_HAVE_FALLOCATE
156 # ifdef FALLOC_FL_KEEP_SIZE
157 // first try fallocate
158 r = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, offset, length);
162 if (r != -EOPNOTSUPP) {
163 goto out; // a real error
165 // if that failed (-EOPNOTSUPP), fall back to writing zeros.
171 // fall back to writing zeros
173 bl.append_zero(length);
174 r = ::lseek64(fd, offset, SEEK_SET);