Mercurial > dovecot > core-2.2
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 |
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 | 7 #ifdef HAVE_POSIX_FALLOCATE |
8 # define _XOPEN_SOURCE 600 /* Required by glibc, breaks Solaris 9 */ | |
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 } |