1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
| | /*
* Copyright (C) 2012-2020 all contributors <cmogstored-public@yhbt.net>
* License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
*/
#include "cmogstored.h"
#include "digest.h"
bool mog_open_expire_retry(struct mog_svc *svc)
{
switch (errno) {
case ENFILE:
case EMFILE:
case ENOMEM:
if (mog_fdmap_expire(svc->idle_timeout) > 0)
return true;
}
return false;
}
static struct mog_fd *mog_file_init_common(int fd, struct mog_svc *svc)
{
struct mog_fd *mfd = mog_fd_init(fd, MOG_FD_TYPE_FILE);
struct mog_file *file;
file = &mfd->as.file;
memset(file, 0, sizeof(struct mog_file));
file->svc = svc;
file->ioq = mog_ioq_current;
return mfd;
}
/* path must be a free()-able pointer */
struct mog_fd *
mog_file_open_read(struct mog_svc *svc, char *path)
{
struct mog_fd *mfd;
int fd = mog_open_read(svc, path);
if (fd < 0 && mog_open_expire_retry(svc))
fd = mog_open_read(svc, path);
if (fd < 0) return NULL;
mfd = mog_file_init_common(fd, svc);
mfd->as.file.fsize = -1;
return mfd;
}
static int mkpath_open_put(struct mog_svc *svc, char *path, int flags)
{
int fd = mog_open_put(svc, path, flags);
if (fd < 0 && errno == ENOENT) {
/* directory does not exist, create it and retry open */
if (mog_mkpath_for(svc, path) == 0)
return mog_open_put(svc, path, flags);
syslog(LOG_ERR, "failed to create directory for path=%s (%m)",
path);
errno = ENOENT; /* restore open() errno */
}
return fd;
}
/* path must be a free()-able pointer */
struct mog_fd *
mog_file_open_put(struct mog_svc *svc, char *path, int flags)
{
int fd = mkpath_open_put(svc, path, flags);
if (fd < 0 && mog_open_expire_retry(svc))
fd = mkpath_open_put(svc, path, flags);
if (fd < 0) return NULL;
return mog_file_init_common(fd, svc);
}
void mog_file_close(struct mog_fd *mfd)
{
struct mog_file *mfile = &mfd->as.file;
struct mog_ioq *ioq;
assert(mfd->fd_type == MOG_FD_TYPE_FILE && "mog_fd is not a file");
/* all of these may already be NULL */
free(mfile->path);
free(mfile->tmppath);
mog_digest_destroy(&mfile->digest);
ioq = mfile->ioq;
mog_fd_put(mfd);
mog_ioq_next(ioq);
}
|