Mercurial > dovecot > original-hg > dovecot-1.2
annotate src/lib/nfs-workarounds.c @ 5970:a290b84d144a HEAD
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 12 Jul 2007 23:54:13 +0300 |
parents | 885ed4d5c51d |
children | 6a64e64fa3a3 |
rev | line source |
---|---|
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
1 /* Copyright (c) 2006-2007 Timo Sirainen */ |
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 |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
37 #ifdef __linux__ |
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 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
40 |
4225
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
41 static int |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
42 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
|
43 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
|
44 { |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
45 const char *dir = NULL; |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
46 struct stat st; |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
47 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
|
48 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
|
49 |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
50 t_push(); |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
51 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
|
52 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
|
53 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
|
54 break; |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
55 |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
56 /* ESTALE: Some operating systems may fail with this if they |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
57 can't internally revalidating the NFS handle. It may also |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
58 happen if the parent directory has been deleted. If the |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
59 directory still exists, try reopening the file. */ |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
60 if (dir == NULL) { |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
61 dir = strrchr(path, '/'); |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
62 if (dir == NULL) |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
63 break; |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
64 dir = t_strdup_until(path, dir); |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
65 } |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
66 if (stat(dir, &st) < 0) { |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
67 /* maybe it's gone or something else bad happened to |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
68 it. in any case we can't open the file, so fail |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
69 with the original ESTALE error and let our caller |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
70 handle it. */ |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
71 errno = ESTALE; |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
72 break; |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
73 } |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
74 |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
75 /* directory still exists, try reopening */ |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
76 } |
cd3d26cf124a
Renamed safe-open.* to nfs-workarounds.*, safe_open() to nfs_safe_open() and
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
77 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
|
78 return ret; |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
79 } |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
80 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
81 struct nfs_safe_open_context { |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
82 int flags; |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
83 int fd; |
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 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
86 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
|
87 { |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
88 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
|
89 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
90 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
|
91 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
|
92 } |
4225
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 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
|
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 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
|
97 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
98 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
|
99 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
100 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
|
101 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
|
102 return -1; |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
103 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
104 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
|
105 } |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
106 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
107 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
|
108 { |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
109 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
|
110 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
111 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
|
112 } |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
113 |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
114 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
|
115 { |
abdef9d86a94
Added nfs_safe_stat() to transparently work around ESTALE with stat().
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4071
diff
changeset
|
116 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
|
117 } |
5968 | 118 |
119 static int nfs_safe_lstat_callback(const char *path, void *context) | |
120 { | |
121 struct stat *buf = context; | |
122 | |
123 return lstat(path, buf); | |
124 } | |
125 | |
126 int nfs_safe_lstat(const char *path, struct stat *buf) | |
127 { | |
128 return nfs_safe_do(path, nfs_safe_lstat_callback, buf); | |
129 } | |
5970
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
130 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
131 static void nfs_flush_fchown_uid(const char *path, int fd) |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
132 { |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
133 struct stat st; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
134 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
135 if (fstat(fd, &st) < 0) { |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
136 if (errno == ESTALE) { |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
137 /* 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
|
138 return; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
139 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
140 i_error("nfs_flush_fchown_uid: fstat(%s) failed: %m", path); |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
141 return; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
142 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
143 if (fchown(fd, st.st_uid, (gid_t)-1) < 0) { |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
144 if (errno == ESTALE || errno == EACCES || errno == EPERM) { |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
145 /* attr cache is flushed */ |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
146 return; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
147 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
148 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
149 i_error("nfs_flush_fchown_uid: fchown(%s) failed: %m", path); |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
150 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
151 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
152 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
153 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
|
154 { |
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 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
157 if (stat(path, &st) < 0) { |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
158 if (errno == ESTALE) { |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
159 /* ESTALE causes the OS to flush the attr cache */ |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
160 return; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
161 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
162 if (errno != ENOENT) { |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
163 i_error("nfs_flush_chown_uid: stat(%s) failed: %m", |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
164 path); |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
165 return; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
166 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
167 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
168 /* flush a negative cache entry. use effective UID to chown. |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
169 it probably doesn't really matter what UID is used, because |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
170 as long as we're not root we don't have permission to really |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
171 change it anyway */ |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
172 st.st_uid = geteuid(); |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
173 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
174 if (chown(path, st.st_uid, (gid_t)-1) < 0) { |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
175 if (errno == ESTALE || errno == EACCES || |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
176 errno == EPERM || errno == ENOENT) { |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
177 /* attr cache is flushed */ |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
178 return; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
179 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
180 i_error("nfs_flush_chown_uid: chown(%s) failed: %m", path); |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
181 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
182 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
183 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
184 #ifdef READ_CACHE_FLUSH_FCNTL |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
185 static void nfs_flush_fcntl(const char *path, int fd, int old_lock_type) |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
186 { |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
187 struct flock fl; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
188 int ret; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
189 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
190 /* 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
|
191 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
|
192 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
|
193 only when read/write locking succeeded. */ |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
194 fl.l_type = old_lock_type != F_UNLCK ? old_lock_type : F_RDLCK; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
195 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
|
196 fl.l_start = 0; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
197 fl.l_len = 0; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
198 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
199 alarm(60); |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
200 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
|
201 alarm(0); |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
202 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
203 if (ret < 0) { |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
204 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
|
205 return; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
206 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
207 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
208 if (old_lock_type == F_UNLCK) { |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
209 fl.l_type = F_UNLCK; |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
210 (void)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
|
211 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
212 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
213 #endif |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
214 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
215 void nfs_flush_attr_cache(const char *path) |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
216 { |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
217 nfs_flush_chown_uid(path); |
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 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
220 void nfs_flush_attr_cache_fd(const char *path, int fd) |
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 nfs_flush_fchown_uid(path, fd); |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
223 } |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
224 |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
225 void nfs_flush_read_cache(const char *path, int fd, |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
226 int lock_type __attr_unused__, |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
227 bool just_locked __attr_unused__) |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
228 { |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
229 #ifdef READ_CACHE_FLUSH_FCNTL |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
230 if (!just_locked) |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
231 nfs_flush_fcntl(path, fd, lock_type); |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
232 #else |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
233 /* FreeBSD, Solaris */ |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
234 nfs_flush_fchown_uid(path, fd); |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
235 #endif |
a290b84d144a
Added nfs_flush_attr_cache() and nfs_flush_read_cache().
Timo Sirainen <tss@iki.fi>
parents:
5968
diff
changeset
|
236 } |