Mercurial > dovecot > original-hg > dovecot-1.2
annotate src/lib/nfs-workarounds.c @ 8590:b9faf4db2a9f HEAD
Updated copyright notices to include year 2009.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 06 Jan 2009 09:25:38 -0500 |
parents | 9bcc2dd5f17f |
children | 00cd9aacd03c |
rev | line source |
---|---|
8590
b9faf4db2a9f
Updated copyright notices to include year 2009.
Timo Sirainen <tss@iki.fi>
parents:
8476
diff
changeset
|
1 /* Copyright (c) 2006-2009 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" |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
31 #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
|
32 |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
33 #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
|
34 #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
|
35 #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
|
36 |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
37 #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
|
38 # 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
|
39 #endif |
6820
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
40 #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
|
41 # 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
|
42 #endif |
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
43 |
6857 | 44 static void nfs_flush_file_handle_cache_parent_dir(const char *path); |
45 | |
4225
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
46 static int |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
47 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
|
48 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
|
49 { |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
50 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
|
51 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
|
52 |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
53 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
|
54 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
|
55 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
|
56 break; |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
57 |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
58 /* ESTALE: Some operating systems may fail with this if they |
6857 | 59 can't internally revalidate the NFS file handle. Flush the |
60 file handle and try again */ | |
61 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
|
62 } |
4225
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
63 return ret; |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
64 } |
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 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
|
67 int flags; |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
68 int fd; |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
69 }; |
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 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
|
72 { |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
73 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
|
74 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
75 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
|
76 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
|
77 } |
4225
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
78 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
79 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
|
80 { |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
81 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
|
82 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
83 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
|
84 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
85 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
|
86 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
|
87 return -1; |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
88 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
89 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
|
90 } |
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 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
|
93 { |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
94 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
|
95 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
96 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
|
97 } |
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 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
|
100 { |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
101 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
|
102 } |
5968 | 103 |
104 static int nfs_safe_lstat_callback(const char *path, void *context) | |
105 { | |
106 struct stat *buf = context; | |
107 | |
108 return lstat(path, buf); | |
109 } | |
110 | |
111 int nfs_safe_lstat(const char *path, struct stat *buf) | |
112 { | |
113 return nfs_safe_do(path, nfs_safe_lstat_callback, buf); | |
114 } | |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
115 |
6813
575235932194
nfs_safe_link(): Support linking files without original link count=1. Use it
Timo Sirainen <tss@iki.fi>
parents:
6811
diff
changeset
|
116 int nfs_safe_link(const char *oldpath, const char *newpath, bool links1) |
6811 | 117 { |
118 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
|
119 nlink_t orig_link_count = 1; |
6811 | 120 |
6813
575235932194
nfs_safe_link(): Support linking files without original link count=1. Use it
Timo Sirainen <tss@iki.fi>
parents:
6811
diff
changeset
|
121 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
|
122 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
|
123 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
|
124 orig_link_count = st.st_nlink; |
6811 | 125 } |
6813
575235932194
nfs_safe_link(): Support linking files without original link count=1. Use it
Timo Sirainen <tss@iki.fi>
parents:
6811
diff
changeset
|
126 |
6811 | 127 if (link(oldpath, newpath) == 0) { |
128 #ifndef __FreeBSD__ | |
129 return 0; | |
130 #endif | |
131 /* FreeBSD at least up to v6.2 converts EEXIST errors to | |
132 success. */ | |
133 } else if (errno != EEXIST) | |
134 return -1; | |
135 | |
136 /* We don't know if it succeeded or failed. stat() to make sure. */ | |
137 if (stat(oldpath, &st) < 0) | |
138 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
|
139 if (st.st_nlink == orig_link_count) { |
6811 | 140 errno = EEXIST; |
141 return -1; | |
142 } | |
143 return 0; | |
144 } | |
145 | |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
146 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
|
147 { |
6820
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
148 uid_t uid; |
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
149 |
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
150 #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
|
151 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
|
152 #else |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
153 struct stat st; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
154 |
6820
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
155 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
|
156 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
|
157 else { |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
158 if (errno == ESTALE) { |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
159 /* 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
|
160 return; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
161 } |
6857 | 162 if (likely(errno == ENOENT)) { |
163 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
|
164 return; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
165 } |
6857 | 166 i_error("nfs_flush_chown_uid: stat(%s) failed: %m", path); |
167 return; | |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
168 } |
6820
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
169 #endif |
6dfb3969baae
FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents:
6819
diff
changeset
|
170 if (chown(path, uid, (gid_t)-1) < 0) { |
6857 | 171 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
|
172 /* attr cache is flushed */ |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
173 return; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
174 } |
6857 | 175 if (likely(errno == ENOENT)) { |
176 nfs_flush_file_handle_cache_parent_dir(path); | |
177 return; | |
178 } | |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
179 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
|
180 } |
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 |
6857 | 183 #ifdef __FreeBSD__ |
184 static bool nfs_flush_fchown_uid(const char *path, int fd) | |
185 { | |
186 uid_t uid; | |
187 #ifndef ATTRCACHE_FLUSH_CHOWN_UID_1 | |
188 struct stat st; | |
189 | |
190 if (fstat(fd, &st) < 0) { | |
191 if (likely(errno == ESTALE)) | |
192 return FALSE; | |
193 i_error("nfs_flush_attr_cache_fchown: fstat(%s) failed: %m", | |
194 path); | |
195 return TRUE; | |
196 } | |
197 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
|
198 #else |
85f457b9b3ad
FreeBSD NFS workarounds: We called fchown() with random UID. It shouldn't
Timo Sirainen <tss@iki.fi>
parents:
7226
diff
changeset
|
199 uid = (uid_t)-1; |
6857 | 200 #endif |
201 if (fchown(fd, uid, (gid_t)-1) < 0) { | |
202 if (errno == ESTALE) | |
203 return FALSE; | |
204 if (likely(errno == EACCES || errno == EPERM)) { | |
205 /* attr cache is flushed */ | |
206 return TRUE; | |
207 } | |
208 | |
209 i_error("nfs_flush_attr_cache_fd_locked: fchown(%s) failed: %m", | |
210 path); | |
211 } | |
212 return TRUE; | |
213 } | |
214 #endif | |
215 | |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
216 #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
|
217 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
|
218 { |
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
|
219 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
|
220 struct flock fl; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
221 int ret; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
222 |
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
|
223 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
|
224 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
|
225 |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
226 /* 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
|
227 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
|
228 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
|
229 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
|
230 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
|
231 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
|
232 fl.l_start = 0; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
233 fl.l_len = 0; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
234 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
235 alarm(60); |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
236 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
|
237 alarm(0); |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
238 |
6825
85385079b044
Use likely() and unlikely() macros to make commonly checked error handling
Timo Sirainen <tss@iki.fi>
parents:
6820
diff
changeset
|
239 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
|
240 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
|
241 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
|
242 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
|
243 } |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
244 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
|
245 return FALSE; |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
246 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
247 |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
248 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
|
249 (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
|
250 return TRUE; |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
251 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
252 #endif |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
253 |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
254 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
|
255 { |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
256 int fd; |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
257 |
6857 | 258 /* 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
|
259 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
|
260 if (fd != -1) |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
261 (void)close(fd); |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
262 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
|
263 /* this already flushed the cache */ |
6857 | 264 } else { |
6829
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
265 /* most likely ENOENT, which means a negative cache hit. |
6857 | 266 flush the file handles for its parent directory. */ |
267 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
|
268 } |
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 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
|
272 { |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
273 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
|
274 } |
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 bool nfs_flush_attr_cache_fd_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
|
277 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
|
278 { |
dbab5e592577
NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents:
6825
diff
changeset
|
279 #ifdef __FreeBSD__ |
6857 | 280 /* FreeBSD doesn't flush attribute cache with fcntl(), so we have |
281 to do it ourself. */ | |
282 return 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
|
283 #else |
6857 | 284 /* 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
|
285 return TRUE; |
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. */ |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
316 char cur_path[PATH_MAX], *p; |
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 |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
326 if (getcwd(cur_path, sizeof(cur_path)) == NULL) { |
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"); |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
329 (void)close(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
|
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, '/'); |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
333 if (p != NULL) |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
334 *p = '\0'; |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
335 else { |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
336 p[0] = '/'; |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
337 p[1] = '\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 } |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
339 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
|
340 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
|
341 "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
|
342 } |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
343 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
|
344 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
|
345 i_error("fchdir() failed: %m"); |
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
346 (void)close(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
|
347 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
|
348 } else { |
6857 | 349 i_error("nfs_flush_file_handle_cache_dir: " |
350 "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
|
351 } |
6857 | 352 #endif |
353 return TRUE; | |
354 } | |
355 | |
356 static void nfs_flush_file_handle_cache_parent_dir(const char *path) | |
357 { | |
358 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
|
359 |
6857 | 360 p = strrchr(path, '/'); |
361 if (p == NULL) | |
7156
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
362 nfs_flush_file_handle_cache_dir(".", 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
|
363 else T_BEGIN { |
7156
5dda06c19eb1
Fixed nfs_flush_file_handle_cache() for Solaris when trying to flush the
Timo Sirainen <tss@iki.fi>
parents:
7155
diff
changeset
|
364 nfs_flush_file_handle_cache_dir(t_strdup_until(path, p), 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 } |