annotate src/lib/file-set-size.c @ 23007:36e01285b5b8

lib: buffer - Improve header comment for buffer_insert() and buffer_delete().
author Stephan Bosch <stephan.bosch@dovecot.fi>
date Mon, 18 Mar 2019 00:52:37 +0100
parents cb108f786fb4
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
22713
cb108f786fb4 Updated copyright notices to include the year 2018.
Stephan Bosch <stephan.bosch@dovecot.fi>
parents: 21390
diff changeset
1 /* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
221
ed0d5b17c7a4 Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
2
6623
dde1980eccae We need to include config.h before checking HAVE_* macros.
Timo Sirainen <tss@iki.fi>
parents: 6622
diff changeset
3 #ifdef HAVE_CONFIG_H
dde1980eccae We need to include config.h before checking HAVE_* macros.
Timo Sirainen <tss@iki.fi>
parents: 6622
diff changeset
4 # include "config.h"
dde1980eccae We need to include config.h before checking HAVE_* macros.
Timo Sirainen <tss@iki.fi>
parents: 6622
diff changeset
5 #endif
dde1980eccae We need to include config.h before checking HAVE_* macros.
Timo Sirainen <tss@iki.fi>
parents: 6622
diff changeset
6
6622
d6cc55e018fe Solaris compile fix.
Timo Sirainen <tss@iki.fi>
parents: 6585
diff changeset
7 #ifdef HAVE_POSIX_FALLOCATE
d6cc55e018fe Solaris compile fix.
Timo Sirainen <tss@iki.fi>
parents: 6585
diff changeset
8 # define _XOPEN_SOURCE 600 /* Required by glibc, breaks Solaris 9 */
d6cc55e018fe Solaris compile fix.
Timo Sirainen <tss@iki.fi>
parents: 6585
diff changeset
9 #endif
12319
22c81f884032 Added file_preallocate() to preallocate space to a file without changing its size.
Timo Sirainen <tss@iki.fi>
parents: 11309
diff changeset
10 #define _GNU_SOURCE /* for fallocate() */
221
ed0d5b17c7a4 Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
11 #include "lib.h"
222
cf4d065f2f85 lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents: 221
diff changeset
12 #include "file-set-size.h"
221
ed0d5b17c7a4 Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
13
ed0d5b17c7a4 Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
14 #include <unistd.h>
5456
3660736f8163 Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents: 1741
diff changeset
15 #include <fcntl.h>
3660736f8163 Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents: 1741
diff changeset
16 #include <sys/stat.h>
17353
3d7b9a927656 lib: a couple of trivial sparse cleanups
Phil Carmody <phil@dovecot.fi>
parents: 17130
diff changeset
17 #if defined(HAVE_LINUX_FALLOC_H) && !defined(FALLOC_FL_KEEP_SIZE)
3d7b9a927656 lib: a couple of trivial sparse cleanups
Phil Carmody <phil@dovecot.fi>
parents: 17130
diff changeset
18 /* Legacy Linux does not have the FALLOC_FL_* flags under fcntl.h */
12319
22c81f884032 Added file_preallocate() to preallocate space to a file without changing its size.
Timo Sirainen <tss@iki.fi>
parents: 11309
diff changeset
19 # include <linux/falloc.h>
22c81f884032 Added file_preallocate() to preallocate space to a file without changing its size.
Timo Sirainen <tss@iki.fi>
parents: 11309
diff changeset
20 #endif
221
ed0d5b17c7a4 Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
21
ed0d5b17c7a4 Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
22 int file_set_size(int fd, off_t size)
ed0d5b17c7a4 Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
23 {
6585
a9dfe05dfadd If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents: 6569
diff changeset
24 #ifdef HAVE_POSIX_FALLOCATE
a9dfe05dfadd If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents: 6569
diff changeset
25 static bool posix_fallocate_supported = TRUE;
a9dfe05dfadd If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents: 6569
diff changeset
26 #endif
11309
88d7a36c7fa5 Use IO_BLOCK_SIZE macro to specify how large read/write syscalls to use.
Timo Sirainen <tss@iki.fi>
parents: 10582
diff changeset
27 char block[IO_BLOCK_SIZE];
5456
3660736f8163 Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents: 1741
diff changeset
28 off_t offset;
3660736f8163 Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents: 1741
diff changeset
29 ssize_t ret;
3660736f8163 Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents: 1741
diff changeset
30 struct stat st;
221
ed0d5b17c7a4 Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
31
ed0d5b17c7a4 Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
32 i_assert(size >= 0);
ed0d5b17c7a4 Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
33
6569
b7d8695d864d If file_set_size() fails for any other reason than "not enough disk
Timo Sirainen <tss@iki.fi>
parents: 6429
diff changeset
34 if (fstat(fd, &st) < 0) {
b7d8695d864d If file_set_size() fails for any other reason than "not enough disk
Timo Sirainen <tss@iki.fi>
parents: 6429
diff changeset
35 i_error("fstat() failed: %m");
221
ed0d5b17c7a4 Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
36 return -1;
6569
b7d8695d864d If file_set_size() fails for any other reason than "not enough disk
Timo Sirainen <tss@iki.fi>
parents: 6429
diff changeset
37 }
221
ed0d5b17c7a4 Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
38
6569
b7d8695d864d If file_set_size() fails for any other reason than "not enough disk
Timo Sirainen <tss@iki.fi>
parents: 6429
diff changeset
39 if (size < st.st_size) {
b7d8695d864d If file_set_size() fails for any other reason than "not enough disk
Timo Sirainen <tss@iki.fi>
parents: 6429
diff changeset
40 if (ftruncate(fd, size) < 0) {
b7d8695d864d If file_set_size() fails for any other reason than "not enough disk
Timo Sirainen <tss@iki.fi>
parents: 6429
diff changeset
41 i_error("ftruncate() failed: %m");
b7d8695d864d If file_set_size() fails for any other reason than "not enough disk
Timo Sirainen <tss@iki.fi>
parents: 6429
diff changeset
42 return -1;
b7d8695d864d If file_set_size() fails for any other reason than "not enough disk
Timo Sirainen <tss@iki.fi>
parents: 6429
diff changeset
43 }
b7d8695d864d If file_set_size() fails for any other reason than "not enough disk
Timo Sirainen <tss@iki.fi>
parents: 6429
diff changeset
44 return 0;
b7d8695d864d If file_set_size() fails for any other reason than "not enough disk
Timo Sirainen <tss@iki.fi>
parents: 6429
diff changeset
45 }
5456
3660736f8163 Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents: 1741
diff changeset
46 if (size == st.st_size)
252
14bad0a48eb4 file_set_size() was buggy when it was supposed to shrink file
Timo Sirainen <tss@iki.fi>
parents: 222
diff changeset
47 return 0;
222
cf4d065f2f85 lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents: 221
diff changeset
48
5456
3660736f8163 Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents: 1741
diff changeset
49 #ifdef HAVE_POSIX_FALLOCATE
6585
a9dfe05dfadd If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents: 6569
diff changeset
50 if (posix_fallocate_supported) {
9695
cff3cb25a3e9 Handle posix_fallocate() failures correctly. Check also for AIX's "not supported" failure.
Timo Sirainen <tss@iki.fi>
parents: 8590
diff changeset
51 int err;
cff3cb25a3e9 Handle posix_fallocate() failures correctly. Check also for AIX's "not supported" failure.
Timo Sirainen <tss@iki.fi>
parents: 8590
diff changeset
52
cff3cb25a3e9 Handle posix_fallocate() failures correctly. Check also for AIX's "not supported" failure.
Timo Sirainen <tss@iki.fi>
parents: 8590
diff changeset
53 err = posix_fallocate(fd, st.st_size, size - st.st_size);
cff3cb25a3e9 Handle posix_fallocate() failures correctly. Check also for AIX's "not supported" failure.
Timo Sirainen <tss@iki.fi>
parents: 8590
diff changeset
54 if (err == 0)
6585
a9dfe05dfadd If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents: 6569
diff changeset
55 return 0;
a9dfe05dfadd If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents: 6569
diff changeset
56
9695
cff3cb25a3e9 Handle posix_fallocate() failures correctly. Check also for AIX's "not supported" failure.
Timo Sirainen <tss@iki.fi>
parents: 8590
diff changeset
57 if (err != EINVAL /* Solaris */ &&
cff3cb25a3e9 Handle posix_fallocate() failures correctly. Check also for AIX's "not supported" failure.
Timo Sirainen <tss@iki.fi>
parents: 8590
diff changeset
58 err != EOPNOTSUPP /* AOX */) {
cff3cb25a3e9 Handle posix_fallocate() failures correctly. Check also for AIX's "not supported" failure.
Timo Sirainen <tss@iki.fi>
parents: 8590
diff changeset
59 if (!ENOSPACE(err))
6585
a9dfe05dfadd If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents: 6569
diff changeset
60 i_error("posix_fallocate() failed: %m");
a9dfe05dfadd If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents: 6569
diff changeset
61 return -1;
a9dfe05dfadd If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents: 6569
diff changeset
62 }
8207
2442529e4cec AIX: Silently ignore posix_fallocate() failures.
Timo Sirainen <tss@iki.fi>
parents: 7086
diff changeset
63 /* Not supported by kernel, fallback to writing. */
6585
a9dfe05dfadd If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents: 6569
diff changeset
64 posix_fallocate_supported = FALSE;
6569
b7d8695d864d If file_set_size() fails for any other reason than "not enough disk
Timo Sirainen <tss@iki.fi>
parents: 6429
diff changeset
65 }
6585
a9dfe05dfadd If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents: 6569
diff changeset
66 #endif
221
ed0d5b17c7a4 Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
67 /* start growing the file */
5456
3660736f8163 Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents: 1741
diff changeset
68 offset = st.st_size;
3660736f8163 Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents: 1741
diff changeset
69 memset(block, 0, I_MIN((ssize_t)sizeof(block), size - offset));
221
ed0d5b17c7a4 Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
70
5456
3660736f8163 Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents: 1741
diff changeset
71 while (offset < size) {
3660736f8163 Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents: 1741
diff changeset
72 ret = pwrite(fd, block,
3660736f8163 Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents: 1741
diff changeset
73 I_MIN((ssize_t)sizeof(block), size - offset),
3660736f8163 Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents: 1741
diff changeset
74 offset);
6569
b7d8695d864d If file_set_size() fails for any other reason than "not enough disk
Timo Sirainen <tss@iki.fi>
parents: 6429
diff changeset
75 if (ret < 0) {
b7d8695d864d If file_set_size() fails for any other reason than "not enough disk
Timo Sirainen <tss@iki.fi>
parents: 6429
diff changeset
76 if (!ENOSPACE(errno))
b7d8695d864d If file_set_size() fails for any other reason than "not enough disk
Timo Sirainen <tss@iki.fi>
parents: 6429
diff changeset
77 i_error("pwrite() failed: %m");
221
ed0d5b17c7a4 Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
78 return -1;
6569
b7d8695d864d If file_set_size() fails for any other reason than "not enough disk
Timo Sirainen <tss@iki.fi>
parents: 6429
diff changeset
79 }
9818
865ad92d0eb3 file_set_size() was broken with OSes that didn't support posix_fallocate().
Timo Sirainen <tss@iki.fi>
parents: 9695
diff changeset
80 offset += ret;
221
ed0d5b17c7a4 Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
81 }
5456
3660736f8163 Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents: 1741
diff changeset
82 return 0;
221
ed0d5b17c7a4 Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
83 }
12319
22c81f884032 Added file_preallocate() to preallocate space to a file without changing its size.
Timo Sirainen <tss@iki.fi>
parents: 11309
diff changeset
84
22c81f884032 Added file_preallocate() to preallocate space to a file without changing its size.
Timo Sirainen <tss@iki.fi>
parents: 11309
diff changeset
85 int file_preallocate(int fd ATTR_UNUSED, off_t size ATTR_UNUSED)
22c81f884032 Added file_preallocate() to preallocate space to a file without changing its size.
Timo Sirainen <tss@iki.fi>
parents: 11309
diff changeset
86 {
22c81f884032 Added file_preallocate() to preallocate space to a file without changing its size.
Timo Sirainen <tss@iki.fi>
parents: 11309
diff changeset
87 #if defined(HAVE_FALLOCATE) && defined(FALLOC_FL_KEEP_SIZE)
22c81f884032 Added file_preallocate() to preallocate space to a file without changing its size.
Timo Sirainen <tss@iki.fi>
parents: 11309
diff changeset
88 /* Linux */
22c81f884032 Added file_preallocate() to preallocate space to a file without changing its size.
Timo Sirainen <tss@iki.fi>
parents: 11309
diff changeset
89 if (fallocate(fd, FALLOC_FL_KEEP_SIZE, 0, size) < 0)
22c81f884032 Added file_preallocate() to preallocate space to a file without changing its size.
Timo Sirainen <tss@iki.fi>
parents: 11309
diff changeset
90 return errno == ENOSYS ? 0 : -1;
22c81f884032 Added file_preallocate() to preallocate space to a file without changing its size.
Timo Sirainen <tss@iki.fi>
parents: 11309
diff changeset
91 return 1;
12342
f6e45e83796b file_preallocate(): Added support for OS X.
Timo Sirainen <tss@iki.fi>
parents: 12319
diff changeset
92 #elif defined (F_PREALLOCATE)
f6e45e83796b file_preallocate(): Added support for OS X.
Timo Sirainen <tss@iki.fi>
parents: 12319
diff changeset
93 /* OSX */
f6e45e83796b file_preallocate(): Added support for OS X.
Timo Sirainen <tss@iki.fi>
parents: 12319
diff changeset
94 fstore_t fs;
f6e45e83796b file_preallocate(): Added support for OS X.
Timo Sirainen <tss@iki.fi>
parents: 12319
diff changeset
95
21389
59437f8764c6 global: Replaced all instances of memset(p, 0, sizeof(*p)) with the new i_zero() macro.
Stephan Bosch <stephan.bosch@dovecot.fi>
parents: 19552
diff changeset
96 i_zero(&fs);
12342
f6e45e83796b file_preallocate(): Added support for OS X.
Timo Sirainen <tss@iki.fi>
parents: 12319
diff changeset
97 fs.fst_flags = F_ALLOCATECONTIG;
f6e45e83796b file_preallocate(): Added support for OS X.
Timo Sirainen <tss@iki.fi>
parents: 12319
diff changeset
98 fs.fst_posmode = F_PEOFPOSMODE;
f6e45e83796b file_preallocate(): Added support for OS X.
Timo Sirainen <tss@iki.fi>
parents: 12319
diff changeset
99 fs.fst_offset = 0;
f6e45e83796b file_preallocate(): Added support for OS X.
Timo Sirainen <tss@iki.fi>
parents: 12319
diff changeset
100 fs.fst_length = size;
f6e45e83796b file_preallocate(): Added support for OS X.
Timo Sirainen <tss@iki.fi>
parents: 12319
diff changeset
101 fs.fst_bytesalloc = 0;
12343
aaca506ea33b file_preallocate(): Don't ignore ENOSPC with OSX either, caller will check it.
Timo Sirainen <tss@iki.fi>
parents: 12342
diff changeset
102 if (fcntl(fd, F_PREALLOCATE, &fs) < 0)
12342
f6e45e83796b file_preallocate(): Added support for OS X.
Timo Sirainen <tss@iki.fi>
parents: 12319
diff changeset
103 return -1;
14780
4b0095f19181 file_preallocate() returned wrong value on success with OSX.
Timo Sirainen <tss@iki.fi>
parents: 14133
diff changeset
104 return fs.fst_bytesalloc > 0 ? 1 : 0;
12319
22c81f884032 Added file_preallocate() to preallocate space to a file without changing its size.
Timo Sirainen <tss@iki.fi>
parents: 11309
diff changeset
105 #else
22c81f884032 Added file_preallocate() to preallocate space to a file without changing its size.
Timo Sirainen <tss@iki.fi>
parents: 11309
diff changeset
106 return 0;
22c81f884032 Added file_preallocate() to preallocate space to a file without changing its size.
Timo Sirainen <tss@iki.fi>
parents: 11309
diff changeset
107 #endif
22c81f884032 Added file_preallocate() to preallocate space to a file without changing its size.
Timo Sirainen <tss@iki.fi>
parents: 11309
diff changeset
108 }