annotate src/lib/nfs-workarounds.c @ 6857:41911abe6fa7 HEAD

NFS cache flushing updates.
author Timo Sirainen <tss@iki.fi>
date Sun, 25 Nov 2007 15:47:36 +0200
parents dbab5e592577
children 78922561e9ea
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
6429
65c69a53a7be Replaced my Copyright notices. The year range always ends with 2007 now.
Timo Sirainen <tss@iki.fi>
parents: 6411
diff changeset
1 /* Copyright (c) 2006-2007 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
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
44 static void nfs_flush_file_handle_cache_parent_dir(const char *path);
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
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 t_push();
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
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
60 can't internally revalidate the NFS file handle. Flush the
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
61 file handle and try again */
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
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 }
cd3d26cf124a Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
64 t_pop();
4225
abdef9d86a94 Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents: 4071
diff changeset
65 return ret;
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
abdef9d86a94 Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents: 4071
diff changeset
68 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
69 int flags;
abdef9d86a94 Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents: 4071
diff changeset
70 int fd;
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
abdef9d86a94 Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents: 4071
diff changeset
73 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
74 {
abdef9d86a94 Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents: 4071
diff changeset
75 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
76
abdef9d86a94 Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents: 4071
diff changeset
77 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
78 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
79 }
4225
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 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
82 {
abdef9d86a94 Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents: 4071
diff changeset
83 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
84
abdef9d86a94 Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents: 4071
diff changeset
85 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
86
abdef9d86a94 Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents: 4071
diff changeset
87 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
88 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
89 return -1;
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 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
92 }
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 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
95 {
abdef9d86a94 Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents: 4071
diff changeset
96 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
97
abdef9d86a94 Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents: 4071
diff changeset
98 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
99 }
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 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
102 {
abdef9d86a94 Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents: 4071
diff changeset
103 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
104 }
5968
885ed4d5c51d Added nfs_safe_lstat()
Timo Sirainen <tss@iki.fi>
parents: 4225
diff changeset
105
885ed4d5c51d Added nfs_safe_lstat()
Timo Sirainen <tss@iki.fi>
parents: 4225
diff changeset
106 static int nfs_safe_lstat_callback(const char *path, void *context)
885ed4d5c51d Added nfs_safe_lstat()
Timo Sirainen <tss@iki.fi>
parents: 4225
diff changeset
107 {
885ed4d5c51d Added nfs_safe_lstat()
Timo Sirainen <tss@iki.fi>
parents: 4225
diff changeset
108 struct stat *buf = context;
885ed4d5c51d Added nfs_safe_lstat()
Timo Sirainen <tss@iki.fi>
parents: 4225
diff changeset
109
885ed4d5c51d Added nfs_safe_lstat()
Timo Sirainen <tss@iki.fi>
parents: 4225
diff changeset
110 return lstat(path, buf);
885ed4d5c51d Added nfs_safe_lstat()
Timo Sirainen <tss@iki.fi>
parents: 4225
diff changeset
111 }
885ed4d5c51d Added nfs_safe_lstat()
Timo Sirainen <tss@iki.fi>
parents: 4225
diff changeset
112
885ed4d5c51d Added nfs_safe_lstat()
Timo Sirainen <tss@iki.fi>
parents: 4225
diff changeset
113 int nfs_safe_lstat(const char *path, struct stat *buf)
885ed4d5c51d Added nfs_safe_lstat()
Timo Sirainen <tss@iki.fi>
parents: 4225
diff changeset
114 {
885ed4d5c51d Added nfs_safe_lstat()
Timo Sirainen <tss@iki.fi>
parents: 4225
diff changeset
115 return nfs_safe_do(path, nfs_safe_lstat_callback, buf);
885ed4d5c51d Added nfs_safe_lstat()
Timo Sirainen <tss@iki.fi>
parents: 4225
diff changeset
116 }
5970
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
117
6813
575235932194 nfs_safe_link(): Support linking files without original link count=1. Use it
Timo Sirainen <tss@iki.fi>
parents: 6811
diff changeset
118 int nfs_safe_link(const char *oldpath, const char *newpath, bool links1)
6811
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
119 {
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
120 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
121 nlink_t orig_link_count = 1;
6811
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
122
6813
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 (!links1) {
575235932194 nfs_safe_link(): Support linking files without original link count=1. Use it
Timo Sirainen <tss@iki.fi>
parents: 6811
diff changeset
124 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
125 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
126 orig_link_count = st.st_nlink;
6811
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
127 }
6813
575235932194 nfs_safe_link(): Support linking files without original link count=1. Use it
Timo Sirainen <tss@iki.fi>
parents: 6811
diff changeset
128
6811
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
129 if (link(oldpath, newpath) == 0) {
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
130 #ifndef __FreeBSD__
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
131 return 0;
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
132 #endif
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
133 /* FreeBSD at least up to v6.2 converts EEXIST errors to
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
134 success. */
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
135 } else if (errno != EEXIST)
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
136 return -1;
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
137
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
138 /* We don't know if it succeeded or failed. stat() to make sure. */
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
139 if (stat(oldpath, &st) < 0)
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
140 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
141 if (st.st_nlink == orig_link_count) {
6811
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
142 errno = EEXIST;
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
143 return -1;
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
144 }
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
145 return 0;
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
146 }
9bc620b934f4 Added nfs_safe_link().
Timo Sirainen <tss@iki.fi>
parents: 6797
diff changeset
147
5970
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
148 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
149 {
6820
6dfb3969baae FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents: 6819
diff changeset
150 uid_t uid;
6dfb3969baae FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents: 6819
diff changeset
151
6dfb3969baae FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents: 6819
diff changeset
152 #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
153 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
154 #else
5970
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
155 struct stat st;
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
156
6820
6dfb3969baae FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents: 6819
diff changeset
157 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
158 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
159 else {
5970
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
160 if (errno == ESTALE) {
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
161 /* 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
162 return;
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
163 }
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
164 if (likely(errno == ENOENT)) {
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
165 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
166 return;
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
167 }
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
168 i_error("nfs_flush_chown_uid: stat(%s) failed: %m", path);
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
169 return;
5970
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
170 }
6820
6dfb3969baae FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents: 6819
diff changeset
171 #endif
6dfb3969baae FreeBSD and Solaris supports flushing attribute cache with chown(uid=-1,
Timo Sirainen <tss@iki.fi>
parents: 6819
diff changeset
172 if (chown(path, uid, (gid_t)-1) < 0) {
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
173 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
174 /* attr cache is flushed */
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
175 return;
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
176 }
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
177 if (likely(errno == ENOENT)) {
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
178 nfs_flush_file_handle_cache_parent_dir(path);
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
179 return;
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
180 }
5970
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
181 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
182 }
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
183 }
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
184
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
185 #ifdef __FreeBSD__
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
186 static bool nfs_flush_fchown_uid(const char *path, int fd)
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
187 {
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
188 uid_t uid;
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
189 #ifndef ATTRCACHE_FLUSH_CHOWN_UID_1
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
190 struct stat st;
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
191
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
192 if (fstat(fd, &st) < 0) {
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
193 if (likely(errno == ESTALE))
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
194 return FALSE;
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
195 i_error("nfs_flush_attr_cache_fchown: fstat(%s) failed: %m",
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
196 path);
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
197 return TRUE;
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
198 }
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
199 uid = st.st_uid;
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
200 #endif
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
201 if (fchown(fd, uid, (gid_t)-1) < 0) {
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
202 if (errno == ESTALE)
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
203 return FALSE;
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
204 if (likely(errno == EACCES || errno == EPERM)) {
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
205 /* attr cache is flushed */
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
206 return TRUE;
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
207 }
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
208
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
209 i_error("nfs_flush_attr_cache_fd_locked: fchown(%s) failed: %m",
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
210 path);
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
211 }
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
212 return TRUE;
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
213 }
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
214 #endif
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
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
6829
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
217 static void 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 {
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
219 struct flock fl;
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
220 int ret;
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
221
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
222 /* 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
223 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
224 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
225 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
226 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
227 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
228 fl.l_start = 0;
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
229 fl.l_len = 0;
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
230
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
231 alarm(60);
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
232 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
233 alarm(0);
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
234
6825
85385079b044 Use likely() and unlikely() macros to make commonly checked error handling
Timo Sirainen <tss@iki.fi>
parents: 6820
diff changeset
235 if (unlikely(ret < 0)) {
5970
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
236 i_error("nfs_flush_fcntl: fcntl(%s, F_RDLCK) failed: %m", path);
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
237 return;
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
238 }
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
239
6829
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
240 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
241 (void)fcntl(fd, F_SETLKW, &fl);
5970
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
242 }
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
243 #endif
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
244
6829
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
245 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
246 {
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
247 int fd;
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
248
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
249 /* 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
250 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
251 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
252 (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
253 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
254 /* this already flushed the cache */
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
255 } else {
6829
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
256 /* most likely ENOENT, which means a negative cache hit.
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
257 flush the file handles for its parent directory. */
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
258 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
259 }
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
260 }
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
261
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
262 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
263 {
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
264 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
265 }
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
266
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
267 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
268 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
269 {
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
270 #ifdef __FreeBSD__
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
271 /* FreeBSD doesn't flush attribute cache with fcntl(), so we have
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
272 to do it ourself. */
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
273 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
274 #else
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
275 /* 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
276 return TRUE;
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
277 #endif
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
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
280 static bool nfs_flush_file_handle_cache_dir(const char *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
281 {
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
282 #ifdef __linux__
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
283 /* chown()ing parent is the safest way to handle this */
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
284 nfs_flush_chown_uid(path);
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
285 #else
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
286 /* 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
287 if (unlikely(rmdir(path) == 0)) {
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
288 if (mkdir(path, 0700) == 0) {
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
289 i_warning("nfs_flush_file_handle_cache_dir: "
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
290 "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
291 "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
292 } else {
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
293 i_warning("nfs_flush_file_handle_cache_dir: "
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
294 "rmdir(%s) unexpectedly "
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
295 "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
296 }
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
297 } else if (errno == ESTALE || errno == ENOTDIR || errno == ENOTEMPTY) {
6819
256725979152 nfs_flush_attr_cache() doesn't take flush_dir paramter anymore. Instead the
Timo Sirainen <tss@iki.fi>
parents: 6816
diff changeset
298 /* expected failures */
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
299 } else if (errno == ENOENT) {
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
300 return FALSE;
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 } else {
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
302 i_error("nfs_flush_file_handle_cache_dir: "
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
303 "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
304 }
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
305 #endif
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
306 return TRUE;
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
307 }
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
308
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
309 static void nfs_flush_file_handle_cache_parent_dir(const char *path)
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
310 {
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
311 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
312
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
313 p = strrchr(path, '/');
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
314 if (p == NULL)
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
315 nfs_flush_file_handle_cache_dir(".");
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
316 else {
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
317 t_push();
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
318 nfs_flush_file_handle_cache_dir(t_strdup_until(path, p));
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
319 t_pop();
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
320 }
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
321 }
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
322
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
323 void nfs_flush_file_handle_cache(const char *path)
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
324 {
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
325 #ifdef __FreeBSD__
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
326 /* Try to handle this more safely by rmdir()ing the file itself */
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
327 if (nfs_flush_file_handle_cache_dir(path))
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
328 return;
6819
256725979152 nfs_flush_attr_cache() doesn't take flush_dir paramter anymore. Instead the
Timo Sirainen <tss@iki.fi>
parents: 6816
diff changeset
329 #endif
6857
41911abe6fa7 NFS cache flushing updates.
Timo Sirainen <tss@iki.fi>
parents: 6829
diff changeset
330 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
331 }
256725979152 nfs_flush_attr_cache() doesn't take flush_dir paramter anymore. Instead the
Timo Sirainen <tss@iki.fi>
parents: 6816
diff changeset
332
6829
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
333 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
334 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
335 {
6829
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
336 #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
337 /* 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
338 #else
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
339 /* 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
340 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
341 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
342 #endif
5970
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
343 }
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
344
6829
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
345 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
346 {
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
347 #ifdef READ_CACHE_FLUSH_FCNTL
6829
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
348 nfs_flush_fcntl(path, fd);
5970
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
349 #else
6829
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
350 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
351 #endif
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
352 }