XRootD
XrdSysFallocate.cc
Go to the documentation of this file.
1 //----------------------------------------------------------------------------------
2 // 1. The Original Code is Mozilla code.
3 // The Initial Developer of the Original Code is Mozilla Foundation.
4 // Portions created by the Initial Developer are Copyright (C) 2010 the Initial Developer. All Rights Reserved.
5 // Contributor(s): Taras Glek <tglek@mozilla.com>
6 // 2. Created from the OSX-specific code from Mozilla's mozilla::fallocation() function.
7 // Adaptation (C) 2015,2016 R.J.V. Bertin for KDE, project.
8 //
9 // Original license allows modification / redistribution under LGPL 2.1 or higher.
10 //----------------------------------------------------------------------------------
11 // XRootD is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU Lesser General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // XRootD is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public License
22 // along with XRootD. If not, see <http://www.gnu.org/licenses/>.
23 //----------------------------------------------------------------------------------
24 
25 // Implementation of posix_allocate for OSX.
26 
27 #ifdef __APPLE__
28 
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 
34 // From Linux `man posix_fallocate`:
35 // DESCRIPTION
36 // The function posix_fallocate() ensures that disk space is allocated for
37 // the file referred to by the descriptor fd for the bytes in the range
38 // starting at offset and continuing for len bytes. After a successful
39 // call to posix_fallocate(), subsequent writes to bytes in the specified
40 // range are guaranteed not to fail because of lack of disk space.
41 //
42 // If the size of the file is less than offset+len, then the file is
43 // increased to this size; otherwise the file size is left unchanged.
44 
45 // From OS X man fcntl:
46 // F_PREALLOCATE Preallocate file storage space. Note: upon success, the space
47 // that is allocated can be the same size or larger than the space
48 // requested.
49 // The F_PREALLOCATE command operates on the following structure:
50 // typedef struct fstore {
51 // u_int32_t fst_flags; /* IN: flags word */
52 // int fst_posmode; /* IN: indicates offset field */
53 // off_t fst_offset; /* IN: start of the region */
54 // off_t fst_length; /* IN: size of the region */
55 // off_t fst_bytesalloc; /* OUT: number of bytes allocated */
56 // } fstore_t;
57 // The flags (fst_flags) for the F_PREALLOCATE command are as follows:
58 // F_ALLOCATECONTIG Allocate contiguous space.
59 // F_ALLOCATEALL Allocate all requested space or no space at all.
60 // The position modes (fst_posmode) for the F_PREALLOCATE command indicate how to use
61 // the offset field. The modes are as follows:
62 // F_PEOFPOSMODE Allocate from the physical end of file.
63 // F_VOLPOSMODE Allocate from the volume offset.
64 
65 // From OS X man ftruncate:
66 // DESCRIPTION
67 // ftruncate() and truncate() cause the file named by path, or referenced by fildes, to
68 // be truncated (or extended) to length bytes in size. If the file size exceeds length,
69 // any extra data is discarded. If the file size is smaller than length, the file
70 // extended and filled with zeros to the indicated length. The ftruncate() form requires
71 // the file to be open for writing.
72 // Note: ftruncate() and truncate() do not modify the current file offset for any open
73 // file descriptions associated with the file.
74 
75 
76 int posix_fallocate(int fd, off_t offset, off_t len)
77 {
78  off_t c_test;
79  int ret;
80  if (!__builtin_saddll_overflow(offset, len, &c_test)) {
81  fstore_t store = {F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, offset + len};
82  // Try to get a continous chunk of disk space
83  ret = fcntl(fd, F_PREALLOCATE, &store);
84  if (ret < 0) {
85  // OK, perhaps we are too fragmented, allocate non-continuous
86  store.fst_flags = F_ALLOCATEALL;
87  ret = fcntl(fd, F_PREALLOCATE, &store);
88  if (ret < 0) {
89  return ret;
90  }
91  }
92  ret = ftruncate(fd, offset + len);
93  } else {
94  // offset+len would overflow.
95  ret = -1;
96  }
97  return ret;
98 }
99 
100 #endif
int ftruncate(int fildes, off_t offset)
int fcntl(int fd, int cmd,...)