annotate src/lib/nfs-workarounds.c @ 6858:78922561e9ea HEAD

Don't try to rmdir() the file to flush its file handle with FreeBSD. Although it appeared to work in my test program, looks like it doesn't really work after all..
author Timo Sirainen <tss@iki.fi>
date Mon, 26 Nov 2007 12:09:05 +0200
parents 41911abe6fa7
children 95caa2ab300c
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 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
326 }
256725979152 nfs_flush_attr_cache() doesn't take flush_dir paramter anymore. Instead the
Timo Sirainen <tss@iki.fi>
parents: 6816
diff changeset
327
6829
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
328 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
329 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
330 {
6829
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
331 #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
332 /* 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
333 #else
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
334 /* 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
335 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
336 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
337 #endif
5970
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
338 }
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
339
6829
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
340 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
341 {
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
342 #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
343 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
344 #else
6829
dbab5e592577 NFS cache flushing APIs changed and backend implements it a bit differently.
Timo Sirainen <tss@iki.fi>
parents: 6825
diff changeset
345 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
346 #endif
a290b84d144a Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents: 5968
diff changeset
347 }