Mercurial > dovecot > original-hg > dovecot-1.2
annotate src/lib/file-set-size.c @ 9272:de52dfd93516 HEAD
Handle posix_fallocate() failures correctly. Check also for AIX's "not supported" failure.
Based on patch by Ralf Becker.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 30 Jul 2009 14:07:13 -0400 |
parents | b9faf4db2a9f |
children | aaa1b2c25c14 |
rev | line source |
---|---|
8590
b9faf4db2a9f
Updated copyright notices to include year 2009.
Timo Sirainen <tss@iki.fi>
parents:
8228
diff
changeset
|
1 /* Copyright (c) 2002-2009 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 | |
221
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
10 #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
|
11 #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
|
12 |
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
13 #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
|
14 #include <fcntl.h> |
3660736f8163
Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents:
1741
diff
changeset
|
15 #include <sys/stat.h> |
221
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
16 |
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
17 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
|
18 { |
6585
a9dfe05dfadd
If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents:
6569
diff
changeset
|
19 #ifdef HAVE_POSIX_FALLOCATE |
a9dfe05dfadd
If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents:
6569
diff
changeset
|
20 static bool posix_fallocate_supported = TRUE; |
a9dfe05dfadd
If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents:
6569
diff
changeset
|
21 #endif |
5456
3660736f8163
Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents:
1741
diff
changeset
|
22 char block[4096]; |
3660736f8163
Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents:
1741
diff
changeset
|
23 off_t offset; |
3660736f8163
Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents:
1741
diff
changeset
|
24 ssize_t ret; |
3660736f8163
Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents:
1741
diff
changeset
|
25 struct stat st; |
221
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
26 |
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
27 i_assert(size >= 0); |
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
28 |
6569
b7d8695d864d
If file_set_size() fails for any other reason than "not enough disk
Timo Sirainen <tss@iki.fi>
parents:
6429
diff
changeset
|
29 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
|
30 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
|
31 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
|
32 } |
221
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 (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
|
35 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
|
36 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
|
37 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
|
38 } |
b7d8695d864d
If file_set_size() fails for any other reason than "not enough disk
Timo Sirainen <tss@iki.fi>
parents:
6429
diff
changeset
|
39 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
|
40 } |
5456
3660736f8163
Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents:
1741
diff
changeset
|
41 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
|
42 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
|
43 |
5456
3660736f8163
Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents:
1741
diff
changeset
|
44 #ifdef HAVE_POSIX_FALLOCATE |
6585
a9dfe05dfadd
If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents:
6569
diff
changeset
|
45 if (posix_fallocate_supported) { |
9272
de52dfd93516
Handle posix_fallocate() failures correctly. Check also for AIX's "not supported" failure.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
46 int err; |
de52dfd93516
Handle posix_fallocate() failures correctly. Check also for AIX's "not supported" failure.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
47 |
de52dfd93516
Handle posix_fallocate() failures correctly. Check also for AIX's "not supported" failure.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
48 err = posix_fallocate(fd, st.st_size, size - st.st_size); |
de52dfd93516
Handle posix_fallocate() failures correctly. Check also for AIX's "not supported" failure.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
49 if (err == 0) |
6585
a9dfe05dfadd
If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents:
6569
diff
changeset
|
50 return 0; |
a9dfe05dfadd
If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents:
6569
diff
changeset
|
51 |
9272
de52dfd93516
Handle posix_fallocate() failures correctly. Check also for AIX's "not supported" failure.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
52 if (err != EINVAL /* Solaris */ && |
de52dfd93516
Handle posix_fallocate() failures correctly. Check also for AIX's "not supported" failure.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
53 err != EOPNOTSUPP /* AOX */) { |
de52dfd93516
Handle posix_fallocate() failures correctly. Check also for AIX's "not supported" failure.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
54 if (!ENOSPACE(err)) |
6585
a9dfe05dfadd
If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents:
6569
diff
changeset
|
55 i_error("posix_fallocate() failed: %m"); |
a9dfe05dfadd
If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents:
6569
diff
changeset
|
56 return -1; |
a9dfe05dfadd
If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents:
6569
diff
changeset
|
57 } |
8207
2442529e4cec
AIX: Silently ignore posix_fallocate() failures.
Timo Sirainen <tss@iki.fi>
parents:
7086
diff
changeset
|
58 /* 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
|
59 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
|
60 } |
6585
a9dfe05dfadd
If posix_fallocate() returns EINVAL, fallback to writing.
Timo Sirainen <tss@iki.fi>
parents:
6569
diff
changeset
|
61 #endif |
221
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
62 /* 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
|
63 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
|
64 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
|
65 |
5456
3660736f8163
Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents:
1741
diff
changeset
|
66 while (offset < size) { |
3660736f8163
Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents:
1741
diff
changeset
|
67 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
|
68 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
|
69 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
|
70 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
|
71 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
|
72 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
|
73 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
|
74 } |
5456
3660736f8163
Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents:
1741
diff
changeset
|
75 offset += size; |
221
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
76 } |
5456
3660736f8163
Use posix_fallocate() if possible. Also did minor optimizations to the
Timo Sirainen <tss@iki.fi>
parents:
1741
diff
changeset
|
77 return 0; |
221
ed0d5b17c7a4
Added extra functions for easier printing of error messages. Moved
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
78 } |