Mercurial > dovecot > core-2.2
annotate src/lib/nfs-workarounds.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) 2006-2018 Dovecot authors, see the included COPYING file */ |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
2 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
3 /* |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
4 These tests were done with various Linux 2.6 kernels, FreeBSD 6.2 and |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
5 Solaris 8 and 10. |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
6 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
7 Attribute cache is usually flushed with chown()ing or fchown()ing the file. |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
8 The safest way would be to use uid=-1 gid=-1, but this doesn't work with |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
9 Linux (it does with FreeBSD 6.2 and Solaris). So we'll first get the |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
10 file's owner and use it. As long as we're not root the file's owner can't |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
11 change accidentally. If would be possible to also use chmod()/fchmod(), but |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
12 that's riskier since it could actually cause an unwanted change. |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
13 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
14 Write cache can be flushed with fdatasync(). It's all we need, but other |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
15 tested alternatives are: fcntl locking (Linux 2.6, Solaris), |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
16 fchown() (Solaris) and dup()+close() (Linux 2.6, Solaris). |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
17 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
18 Read cache flushing is more problematic. There's no universal way to do it. |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
19 The working methods are: |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
20 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
21 Linux 2.6: fcntl(), O_DIRECT |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
22 Solaris: fchown(), fcntl(), dup()+close() |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
23 FreeBSD 6.2: fchown() |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
24 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
25 fchown() can be easily used for Solaris and FreeBSD, but Linux requires |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
26 playing with locks. O_DIRECT requires CONFIG_NFS_DIRECTIO to be enabled, so |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
27 we can't always use it. |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
28 */ |
4071
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
29 |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
30 #include "lib.h" |
10502
13be6ac759ee
Added t_get_current_dir() and use it instead of getcwd().
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
31 #include "abspath.h" |
4071
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
32 #include "nfs-workarounds.h" |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
33 |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
34 #include <fcntl.h> |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
35 #include <unistd.h> |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
36 #include <sys/stat.h> |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
37 |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
38 #if defined (__linux__) || defined(__sun) |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
39 # define READ_CACHE_FLUSH_FCNTL |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
40 #endif |
6820
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
41 #if defined(__FreeBSD__) || defined(__sun) |
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
42 # define ATTRCACHE_FLUSH_CHOWN_UID_1 |
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
43 #endif |
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
44 |
6857 | 45 static void nfs_flush_file_handle_cache_parent_dir(const char *path); |
46 | |
4225
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
47 static int |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
48 nfs_safe_do(const char *path, int (*callback)(const char *path, void *context), |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
49 void *context) |
4071
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
50 { |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
51 unsigned int i; |
4225
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
52 int ret; |
4071
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
53 |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
54 for (i = 1;; i++) { |
4225
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
55 ret = callback(path, context); |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
56 if (ret == 0 || errno != ESTALE || i == NFS_ESTALE_RETRY_COUNT) |
4071
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
57 break; |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
58 |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
59 /* ESTALE: Some operating systems may fail with this if they |
6857 | 60 can't internally revalidate the NFS file handle. Flush the |
61 file handle and try again */ | |
62 nfs_flush_file_handle_cache(path); | |
4071
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
63 } |
4225
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
64 return ret; |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
65 } |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
66 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
67 struct nfs_safe_open_context { |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
68 int flags; |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
69 int fd; |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
70 }; |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
71 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
72 static int nfs_safe_open_callback(const char *path, void *context) |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
73 { |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
74 struct nfs_safe_open_context *ctx = context; |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
75 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
76 ctx->fd = open(path, ctx->flags); |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
77 return ctx->fd == -1 ? -1 : 0; |
4071
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
78 } |
4225
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
79 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
80 int nfs_safe_open(const char *path, int flags) |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
81 { |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
82 struct nfs_safe_open_context ctx; |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
83 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
84 i_assert((flags & O_CREAT) == 0); |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
85 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
86 ctx.flags = flags; |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
87 if (nfs_safe_do(path, nfs_safe_open_callback, &ctx) < 0) |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
88 return -1; |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
89 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
90 return ctx.fd; |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
91 } |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
92 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
93 static int nfs_safe_stat_callback(const char *path, void *context) |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
94 { |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
95 struct stat *buf = context; |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
96 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
97 return stat(path, buf); |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
98 } |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
99 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
100 int nfs_safe_stat(const char *path, struct stat *buf) |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
101 { |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
102 return nfs_safe_do(path, nfs_safe_stat_callback, buf); |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
103 } |
5968 | 104 |
105 static int nfs_safe_lstat_callback(const char *path, void *context) | |
106 { | |
107 struct stat *buf = context; | |
108 | |
109 return lstat(path, buf); | |
110 } | |
111 | |
112 int nfs_safe_lstat(const char *path, struct stat *buf) | |
113 { | |
114 return nfs_safe_do(path, nfs_safe_lstat_callback, buf); | |
115 } | |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
116 |
6813
575235932194
nfs_safe_link(): Support linking files without original link count=1. Use it
Timo Sirainen <tss@iki.fi>
parents:
6811
diff
changeset
|
117 int nfs_safe_link(const char *oldpath, const char *newpath, bool links1) |
6811 | 118 { |
119 struct stat st; | |
6813
575235932194
nfs_safe_link(): Support linking files without original link count=1. Use it
Timo Sirainen <tss@iki.fi>
parents:
6811
diff
changeset
|
120 nlink_t orig_link_count = 1; |
6811 | 121 |
6813
575235932194
nfs_safe_link(): Support linking files without original link count=1. Use it
Timo Sirainen <tss@iki.fi>
parents:
6811
diff
changeset
|
122 if (!links1) { |
575235932194
nfs_safe_link(): Support linking files without original link count=1. Use it
Timo Sirainen <tss@iki.fi>
parents:
6811
diff
changeset
|
123 if (stat(oldpath, &st) < 0) |
575235932194
nfs_safe_link(): Support linking files without original link count=1. Use it
Timo Sirainen <tss@iki.fi>
parents:
6811
diff
changeset
|
124 return -1; |
575235932194
nfs_safe_link(): Support linking files without original link count=1. Use it
Timo Sirainen <tss@iki.fi>
parents:
6811
diff
changeset
|
125 orig_link_count = st.st_nlink; |
6811 | 126 } |
6813
575235932194
nfs_safe_link(): Support linking files without original link count=1. Use it
Timo Sirainen <tss@iki.fi>
parents:
6811
diff
changeset
|
127 |
6811 | 128 if (link(oldpath, newpath) == 0) { |
129 #ifndef __FreeBSD__ | |
130 return 0; | |
131 #endif | |
132 /* FreeBSD at least up to v6.2 converts EEXIST errors to | |
133 success. */ | |
134 } else if (errno != EEXIST) | |
135 return -1; | |
136 | |
137 /* We don't know if it succeeded or failed. stat() to make sure. */ | |
138 if (stat(oldpath, &st) < 0) | |
139 return -1; | |
6813
575235932194
nfs_safe_link(): Support linking files without original link count=1. Use it
Timo Sirainen <tss@iki.fi>
parents:
6811
diff
changeset
|
140 if (st.st_nlink == orig_link_count) { |
6811 | 141 errno = EEXIST; |
142 return -1; | |
143 } | |
144 return 0; | |
145 } | |
146 | |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
147 static void nfs_flush_chown_uid(const char *path) |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
148 { |
6820
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
149 uid_t uid; |
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
150 |
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
151 #ifdef ATTRCACHE_FLUSH_CHOWN_UID_1 |
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
152 uid = (uid_t)-1; |
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
153 #else |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
154 struct stat st; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
155 |
6820
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
156 if (stat(path, &st) == 0) |
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
157 uid = st.st_uid; |
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
158 else { |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
159 if (errno == ESTALE) { |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
160 /* ESTALE causes the OS to flush the attr cache */ |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
161 return; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
162 } |
6857 | 163 if (likely(errno == ENOENT)) { |
164 nfs_flush_file_handle_cache_parent_dir(path); | |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
165 return; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
166 } |
6857 | 167 i_error("nfs_flush_chown_uid: stat(%s) failed: %m", path); |
168 return; | |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
169 } |
6820
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
170 #endif |
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
171 if (chown(path, uid, (gid_t)-1) < 0) { |
6857 | 172 if (errno == ESTALE || errno == EPERM || errno == ENOENT) { |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
173 /* attr cache is flushed */ |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
174 return; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
175 } |
6857 | 176 if (likely(errno == ENOENT)) { |
177 nfs_flush_file_handle_cache_parent_dir(path); | |
178 return; | |
179 } | |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
180 i_error("nfs_flush_chown_uid: chown(%s) failed: %m", path); |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
181 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
182 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
183 |
6857 | 184 #ifdef __FreeBSD__ |
185 static bool nfs_flush_fchown_uid(const char *path, int fd) | |
186 { | |
187 uid_t uid; | |
188 #ifndef ATTRCACHE_FLUSH_CHOWN_UID_1 | |
189 struct stat st; | |
190 | |
191 if (fstat(fd, &st) < 0) { | |
192 if (likely(errno == ESTALE)) | |
193 return FALSE; | |
194 i_error("nfs_flush_attr_cache_fchown: fstat(%s) failed: %m", | |
195 path); | |
196 return TRUE; | |
197 } | |
198 uid = st.st_uid; | |
7860
85f457b9b3ad
FreeBSD NFS workarounds: We called fchown() with random UID. It shouldn't
Timo Sirainen <tss@iki.fi>
parents:
7226
diff
changeset
|
199 #else |
85f457b9b3ad
FreeBSD NFS workarounds: We called fchown() with random UID. It shouldn't
Timo Sirainen <tss@iki.fi>
parents:
7226
diff
changeset
|
200 uid = (uid_t)-1; |
6857 | 201 #endif |
202 if (fchown(fd, uid, (gid_t)-1) < 0) { | |
203 if (errno == ESTALE) | |
204 return FALSE; | |
205 if (likely(errno == EACCES || errno == EPERM)) { | |
206 /* attr cache is flushed */ | |
207 return TRUE; | |
208 } | |
209 | |
210 i_error("nfs_flush_attr_cache_fd_locked: fchown(%s) failed: %m", | |
211 path); | |
212 } | |
213 return TRUE; | |
214 } | |
215 #endif | |
216 | |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
217 #ifdef READ_CACHE_FLUSH_FCNTL |
8476
9bcc2dd5f17f
Linux/Solaris NFS: if there are no locks, try flushing data cache by flushing attr cache.
Timo Sirainen <tss@iki.fi>
parents:
7860
diff
changeset
|
218 static bool nfs_flush_fcntl(const char *path, int fd) |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
219 { |
8476
9bcc2dd5f17f
Linux/Solaris NFS: if there are no locks, try flushing data cache by flushing attr cache.
Timo Sirainen <tss@iki.fi>
parents:
7860
diff
changeset
|
220 static bool locks_disabled = FALSE; |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
221 struct flock fl; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
222 int ret; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
223 |
8476
9bcc2dd5f17f
Linux/Solaris NFS: if there are no locks, try flushing data cache by flushing attr cache.
Timo Sirainen <tss@iki.fi>
parents:
7860
diff
changeset
|
224 if (locks_disabled) |
9bcc2dd5f17f
Linux/Solaris NFS: if there are no locks, try flushing data cache by flushing attr cache.
Timo Sirainen <tss@iki.fi>
parents:
7860
diff
changeset
|
225 return FALSE; |
9bcc2dd5f17f
Linux/Solaris NFS: if there are no locks, try flushing data cache by flushing attr cache.
Timo Sirainen <tss@iki.fi>
parents:
7860
diff
changeset
|
226 |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
227 /* If the file was already locked, we'll just get the same lock |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
228 again. It should succeed just fine. If was was unlocked, we'll |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
229 have to get a lock and then unlock it. Linux 2.6 flushes read cache |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
230 only when read/write locking succeeded. */ |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
231 fl.l_type = F_RDLCK; |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
232 fl.l_whence = SEEK_SET; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
233 fl.l_start = 0; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
234 fl.l_len = 0; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
235 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
236 alarm(60); |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
237 ret = fcntl(fd, F_SETLKW, &fl); |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
238 alarm(0); |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
239 |
6825
85385079b044
Use likely() and unlikely() macros to make commonly checked error handling
Timo Sirainen <tss@iki.fi>
parents:
6820
diff
changeset
|
240 if (unlikely(ret < 0)) { |
8476
9bcc2dd5f17f
Linux/Solaris NFS: if there are no locks, try flushing data cache by flushing attr cache.
Timo Sirainen <tss@iki.fi>
parents:
7860
diff
changeset
|
241 if (errno == ENOLCK) { |
9bcc2dd5f17f
Linux/Solaris NFS: if there are no locks, try flushing data cache by flushing attr cache.
Timo Sirainen <tss@iki.fi>
parents:
7860
diff
changeset
|
242 locks_disabled = TRUE; |
9bcc2dd5f17f
Linux/Solaris NFS: if there are no locks, try flushing data cache by flushing attr cache.
Timo Sirainen <tss@iki.fi>
parents:
7860
diff
changeset
|
243 return FALSE; |
9bcc2dd5f17f
Linux/Solaris NFS: if there are no locks, try flushing data cache by flushing attr cache.
Timo Sirainen <tss@iki.fi>
parents:
7860
diff
changeset
|
244 } |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
245 i_error("nfs_flush_fcntl: fcntl(%s, F_RDLCK) failed: %m", path); |
8476
9bcc2dd5f17f
Linux/Solaris NFS: if there are no locks, try flushing data cache by flushing attr cache.
Timo Sirainen <tss@iki.fi>
parents:
7860
diff
changeset
|
246 return FALSE; |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
247 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
248 |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
249 fl.l_type = F_UNLCK; |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
250 (void)fcntl(fd, F_SETLKW, &fl); |
8476
9bcc2dd5f17f
Linux/Solaris NFS: if there are no locks, try flushing data cache by flushing attr cache.
Timo Sirainen <tss@iki.fi>
parents:
7860
diff
changeset
|
251 return TRUE; |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
252 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
253 #endif |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
254 |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
255 void nfs_flush_attr_cache_unlocked(const char *path) |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
256 { |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
257 int fd; |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
258 |
6857 | 259 /* Try to flush the attribute cache the nice way first. */ |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
260 fd = open(path, O_RDONLY); |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
261 if (fd != -1) |
14691
3945a3646c67
Changed i_close_fd() API to set the fd to -1 after closing.
Timo Sirainen <tss@iki.fi>
parents:
14687
diff
changeset
|
262 i_close_fd(&fd); |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
263 else if (errno == ESTALE) { |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
264 /* this already flushed the cache */ |
6857 | 265 } else { |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
266 /* most likely ENOENT, which means a negative cache hit. |
6857 | 267 flush the file handles for its parent directory. */ |
268 nfs_flush_file_handle_cache_parent_dir(path); | |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
269 } |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
270 } |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
271 |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
272 void nfs_flush_attr_cache_maybe_locked(const char *path) |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
273 { |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
274 nfs_flush_chown_uid(path); |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
275 } |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
276 |
14682
d0d7b810646b
Make sure we check all the functions' return values. Minor API changes to simplify this.
Timo Sirainen <tss@iki.fi>
parents:
14133
diff
changeset
|
277 void nfs_flush_attr_cache_fd_locked(const char *path ATTR_UNUSED, |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
278 int fd ATTR_UNUSED) |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
279 { |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
280 #ifdef __FreeBSD__ |
6857 | 281 /* FreeBSD doesn't flush attribute cache with fcntl(), so we have |
282 to do it ourself. */ | |
14682
d0d7b810646b
Make sure we check all the functions' return values. Minor API changes to simplify this.
Timo Sirainen <tss@iki.fi>
parents:
14133
diff
changeset
|
283 (void)nfs_flush_fchown_uid(path, fd); |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
284 #else |
6857 | 285 /* Linux and Solaris are fine. */ |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
286 #endif |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
287 } |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
288 |
7156
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
289 static bool |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
290 nfs_flush_file_handle_cache_dir(const char *path, bool try_parent ATTR_UNUSED) |
6819
256725979152
nfs_flush_attr_cache() doesn't take flush_dir paramter anymore. Instead the
Timo Sirainen <tss@iki.fi>
parents:
6816
diff
changeset
|
291 { |
6857 | 292 #ifdef __linux__ |
293 /* chown()ing parent is the safest way to handle this */ | |
294 nfs_flush_chown_uid(path); | |
295 #else | |
296 /* rmdir() is the only choice with FreeBSD and Solaris */ | |
6825
85385079b044
Use likely() and unlikely() macros to make commonly checked error handling
Timo Sirainen <tss@iki.fi>
parents:
6820
diff
changeset
|
297 if (unlikely(rmdir(path) == 0)) { |
6857 | 298 if (mkdir(path, 0700) == 0) { |
299 i_warning("nfs_flush_file_handle_cache_dir: " | |
300 "rmdir(%s) unexpectedly " | |
6819
256725979152
nfs_flush_attr_cache() doesn't take flush_dir paramter anymore. Instead the
Timo Sirainen <tss@iki.fi>
parents:
6816
diff
changeset
|
301 "removed the dir. recreated.", path); |
256725979152
nfs_flush_attr_cache() doesn't take flush_dir paramter anymore. Instead the
Timo Sirainen <tss@iki.fi>
parents:
6816
diff
changeset
|
302 } else { |
6857 | 303 i_warning("nfs_flush_file_handle_cache_dir: " |
304 "rmdir(%s) unexpectedly " | |
305 "removed the dir. mkdir() failed: %m", path); | |
6819
256725979152
nfs_flush_attr_cache() doesn't take flush_dir paramter anymore. Instead the
Timo Sirainen <tss@iki.fi>
parents:
6816
diff
changeset
|
306 } |
6892
95caa2ab300c
Ignore EEXIST errors for rmdir().
Timo Sirainen <tss@iki.fi>
parents:
6858
diff
changeset
|
307 } else if (errno == ESTALE || errno == ENOTDIR || |
7155
dd64c0e649aa
nfs_flush_file_handle_cache_dir: If rmdir() fails with EACCES, the cache is
Timo Sirainen <tss@iki.fi>
parents:
7086
diff
changeset
|
308 errno == ENOTEMPTY || errno == EEXIST || errno == EACCES) { |
6819
256725979152
nfs_flush_attr_cache() doesn't take flush_dir paramter anymore. Instead the
Timo Sirainen <tss@iki.fi>
parents:
6816
diff
changeset
|
309 /* expected failures */ |
6857 | 310 } else if (errno == ENOENT) { |
311 return FALSE; | |
7156
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
312 } else if (errno == EINVAL && try_parent) { |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
313 /* Solaris gives this if we're trying to rmdir() the current |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
314 directory. Work around this by temporarily changing the |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
315 current directory to the parent directory. */ |
10502
13be6ac759ee
Added t_get_current_dir() and use it instead of getcwd().
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
316 const char *cur_path, *p; |
7156
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
317 int cur_dir_fd; |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
318 bool ret; |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
319 |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
320 cur_dir_fd = open(".", O_RDONLY); |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
321 if (cur_dir_fd == -1) { |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
322 i_error("open(.) failed for: %m"); |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
323 return TRUE; |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
324 } |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
325 |
10502
13be6ac759ee
Added t_get_current_dir() and use it instead of getcwd().
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
326 if (t_get_current_dir(&cur_path) < 0) { |
7156
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
327 i_error("nfs_flush_file_handle_cache_dir: " |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
328 "getcwd() failed"); |
14691
3945a3646c67
Changed i_close_fd() API to set the fd to -1 after closing.
Timo Sirainen <tss@iki.fi>
parents:
14687
diff
changeset
|
329 i_close_fd(&cur_dir_fd); |
7156
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
330 return TRUE; |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
331 } |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
332 p = strrchr(cur_path, '/'); |
10502
13be6ac759ee
Added t_get_current_dir() and use it instead of getcwd().
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
333 if (p == NULL) |
13be6ac759ee
Added t_get_current_dir() and use it instead of getcwd().
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
334 cur_path = "/"; |
13be6ac759ee
Added t_get_current_dir() and use it instead of getcwd().
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
335 else |
13be6ac759ee
Added t_get_current_dir() and use it instead of getcwd().
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
336 cur_path = t_strdup_until(cur_path, p); |
7156
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
337 if (chdir(cur_path) < 0) { |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
338 i_error("nfs_flush_file_handle_cache_dir: " |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
339 "chdir() failed"); |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
340 } |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
341 ret = nfs_flush_file_handle_cache_dir(path, FALSE); |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
342 if (fchdir(cur_dir_fd) < 0) |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
343 i_error("fchdir() failed: %m"); |
14691
3945a3646c67
Changed i_close_fd() API to set the fd to -1 after closing.
Timo Sirainen <tss@iki.fi>
parents:
14687
diff
changeset
|
344 i_close_fd(&cur_dir_fd); |
7156
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
345 return ret; |
6819
256725979152
nfs_flush_attr_cache() doesn't take flush_dir paramter anymore. Instead the
Timo Sirainen <tss@iki.fi>
parents:
6816
diff
changeset
|
346 } else { |
6857 | 347 i_error("nfs_flush_file_handle_cache_dir: " |
348 "rmdir(%s) failed: %m", path); | |
6819
256725979152
nfs_flush_attr_cache() doesn't take flush_dir paramter anymore. Instead the
Timo Sirainen <tss@iki.fi>
parents:
6816
diff
changeset
|
349 } |
6857 | 350 #endif |
351 return TRUE; | |
352 } | |
353 | |
354 static void nfs_flush_file_handle_cache_parent_dir(const char *path) | |
355 { | |
356 const char *p; | |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
357 |
6857 | 358 p = strrchr(path, '/'); |
10502
13be6ac759ee
Added t_get_current_dir() and use it instead of getcwd().
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
359 T_BEGIN { |
13be6ac759ee
Added t_get_current_dir() and use it instead of getcwd().
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
360 if (p == NULL) |
14682
d0d7b810646b
Make sure we check all the functions' return values. Minor API changes to simplify this.
Timo Sirainen <tss@iki.fi>
parents:
14133
diff
changeset
|
361 (void)nfs_flush_file_handle_cache_dir(".", TRUE); |
10502
13be6ac759ee
Added t_get_current_dir() and use it instead of getcwd().
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
362 else |
14682
d0d7b810646b
Make sure we check all the functions' return values. Minor API changes to simplify this.
Timo Sirainen <tss@iki.fi>
parents:
14133
diff
changeset
|
363 (void)nfs_flush_file_handle_cache_dir(t_strdup_until(path, p), |
d0d7b810646b
Make sure we check all the functions' return values. Minor API changes to simplify this.
Timo Sirainen <tss@iki.fi>
parents:
14133
diff
changeset
|
364 TRUE); |
7226
e6693a0ec8e1
Renamed T_FRAME_BEGIN/END to T_BEGIN/END. Removed T_FRAME() macro and
Timo Sirainen <tss@iki.fi>
parents:
7156
diff
changeset
|
365 } T_END; |
6857 | 366 } |
367 | |
368 void nfs_flush_file_handle_cache(const char *path) | |
369 { | |
370 nfs_flush_file_handle_cache_parent_dir(path); | |
6819
256725979152
nfs_flush_attr_cache() doesn't take flush_dir paramter anymore. Instead the
Timo Sirainen <tss@iki.fi>
parents:
6816
diff
changeset
|
371 } |
256725979152
nfs_flush_attr_cache() doesn't take flush_dir paramter anymore. Instead the
Timo Sirainen <tss@iki.fi>
parents:
6816
diff
changeset
|
372 |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
373 void nfs_flush_read_cache_locked(const char *path ATTR_UNUSED, |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
374 int fd ATTR_UNUSED) |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
375 { |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
376 #ifdef READ_CACHE_FLUSH_FCNTL |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
377 /* already flushed when fcntl() was called */ |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
378 #else |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
379 /* we can only hope that underlying filesystem uses micro/nanosecond |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
380 resolution so that attribute cache flushing notices mtime changes */ |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
381 nfs_flush_attr_cache_fd_locked(path, fd); |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
382 #endif |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
383 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
384 |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
385 void nfs_flush_read_cache_unlocked(const char *path, int fd) |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
386 { |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
387 #ifdef READ_CACHE_FLUSH_FCNTL |
8476
9bcc2dd5f17f
Linux/Solaris NFS: if there are no locks, try flushing data cache by flushing attr cache.
Timo Sirainen <tss@iki.fi>
parents:
7860
diff
changeset
|
388 if (!nfs_flush_fcntl(path, fd)) |
9bcc2dd5f17f
Linux/Solaris NFS: if there are no locks, try flushing data cache by flushing attr cache.
Timo Sirainen <tss@iki.fi>
parents:
7860
diff
changeset
|
389 nfs_flush_attr_cache_fd_locked(path, fd); |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
390 #else |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
391 nfs_flush_read_cache_locked(path, fd); |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
392 #endif |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
393 } |