]> mj.ucw.cz Git - moe.git/blob - ucw/fb-param.c
Merge branch 'layout'
[moe.git] / ucw / fb-param.c
1 /*
2  *      UCW Library -- FastIO on files with run-time parametrization
3  *
4  *      (c) 2007 Pavel Charvat <pchar@ucw.cz>
5  *      (c) 2007 Martin Mares <mj@ucw.cz>
6  *
7  *      This software may be freely distributed and used according to the terms
8  *      of the GNU Lesser General Public License.
9  */
10
11 #include "ucw/lib.h"
12 #include "ucw/conf.h"
13 #include "ucw/lfs.h"
14 #include "ucw/fastbuf.h"
15
16 #include <fcntl.h>
17 #include <stdio.h>
18
19 struct fb_params fbpar_def = {
20   .buffer_size = 65536,
21   .read_ahead = 1,
22   .write_back = 1,
23 };
24
25 static char *
26 fbpar_cf_commit(struct fb_params *p UNUSED)
27 {
28   if (p->type == FB_DIRECT)
29     {
30 #ifndef CONFIG_UCW_THREADS
31       return "Direct I/O is supported only with CONFIG_UCW_THREADS";
32 #endif
33 #ifdef CONFIG_DARWIN
34       return "Direct I/O is not supported on darwin";
35 #endif
36 #ifndef CONFIG_DIRECT_IO
37       return "Direct I/O disabled by configure switch -CONFIG_DIRECT_IO";
38 #endif
39 #ifndef CONFIG_UCW_FB_DIRECT
40       return "Direct I/O disabled by configure switch -CONFIG_UCW_FB_DIRECT";
41 #endif
42     }
43   return NULL;
44 }
45
46 struct cf_section fbpar_cf = {
47 # define F(x) PTR_TO(struct fb_params, x)
48   CF_TYPE(struct fb_params),
49   CF_COMMIT(fbpar_cf_commit),
50   CF_ITEMS {
51     CF_LOOKUP("Type", (int *)F(type), ((const char * const []){"std", "direct", "mmap", NULL})),
52     CF_UNS("BufSize", F(buffer_size)),
53     CF_UNS("KeepBackBuf", F(keep_back_buf)),
54     CF_UNS("ReadAhead", F(read_ahead)),
55     CF_UNS("WriteBack", F(write_back)),
56     CF_END
57   }
58 # undef F
59 };
60
61 static struct cf_section fbpar_global_cf = {
62   CF_ITEMS {
63     CF_SECTION("Defaults", &fbpar_def, &fbpar_cf),
64     CF_END
65   }
66 };
67
68 static void CONSTRUCTOR
69 fbpar_global_init(void)
70 {
71   cf_declare_section("FBParam", &fbpar_global_cf, 0);
72 }
73
74 static struct fastbuf *
75 bopen_fd_internal(int fd, struct fb_params *params, uns mode, const char *name)
76 {
77   char buf[32];
78   if (!name)
79     {
80       sprintf(buf, "fd%d", fd);
81       name = buf;
82     }
83   struct fastbuf *fb;
84   switch (params->type)
85     {
86 #ifdef CONFIG_UCW_FB_DIRECT
87       case FB_DIRECT:
88         fb = fbdir_open_fd_internal(fd, name, params->asio,
89             params->buffer_size ? : fbpar_def.buffer_size,
90             params->read_ahead ? : fbpar_def.read_ahead,
91             params->write_back ? : fbpar_def.write_back);
92         if (!~mode && !fbdir_cheat && ((int)(mode = fcntl(fd, F_GETFL)) < 0 || fcntl(fd, F_SETFL, mode | O_DIRECT)) < 0)
93           msg(L_WARN, "Cannot set O_DIRECT on fd %d: %m", fd);
94         return fb;
95 #endif
96       case FB_STD:
97         fb = bfdopen_internal(fd, name,
98             params->buffer_size ? : fbpar_def.buffer_size);
99         if (params->keep_back_buf)
100           bconfig(fb, BCONFIG_KEEP_BACK_BUF, 1);
101         return fb;
102       case FB_MMAP:
103         if (!~mode && (int)(mode = fcntl(fd, F_GETFL)) < 0)
104           die("Cannot get flags of fd %d: %m", fd);
105         return bfmmopen_internal(fd, name, mode);
106       default:
107         ASSERT(0);
108     }
109 }
110
111 static struct fastbuf *
112 bopen_file_internal(const char *name, int mode, struct fb_params *params, int try)
113 {
114   if (!params)
115     params = &fbpar_def;
116 #ifdef CONFIG_UCW_FB_DIRECT
117   if (params->type == FB_DIRECT && !fbdir_cheat)
118     mode |= O_DIRECT;
119 #endif
120   if (params->type == FB_MMAP && (mode & O_ACCMODE) == O_WRONLY)
121     mode = (mode & ~O_ACCMODE) | O_RDWR;
122   int fd = ucw_open(name, mode, 0666);
123   if (fd < 0)
124     if (try)
125       return NULL;
126     else
127       die("Unable to %s file %s: %m", (mode & O_CREAT) ? "create" : "open", name);
128   struct fastbuf *fb = bopen_fd_internal(fd, params, mode, name);
129   ASSERT(fb);
130   if (mode & O_APPEND)
131     bseek(fb, 0, SEEK_END);
132   return fb;
133 }
134
135 struct fastbuf *
136 bopen_file(const char *name, int mode, struct fb_params *params)
137 {
138   return bopen_file_internal(name, mode, params, 0);
139 }
140
141 struct fastbuf *
142 bopen_file_try(const char *name, int mode, struct fb_params *params)
143 {
144   return bopen_file_internal(name, mode, params, 1);
145 }
146
147 struct fastbuf *
148 bopen_fd_name(int fd, struct fb_params *params, const char *name)
149 {
150   return bopen_fd_internal(fd, params ? : &fbpar_def, ~0U, name);
151 }
152
153 /* Function for use by individual file back-ends */
154
155 void
156 bclose_file_helper(struct fastbuf *f, int fd, int is_temp_file)
157 {
158   switch (is_temp_file)
159     {
160     case 1:
161       if (unlink(f->name) < 0)
162         msg(L_ERROR, "unlink(%s): %m", f->name);
163     case 0:
164       if (close(fd))
165         die("close(%s): %m", f->name);
166     }
167 }
168
169 /* Compatibility wrappers */
170
171 struct fastbuf *
172 bopen_try(const char *name, uns mode, uns buflen)
173 {
174   return bopen_file_try(name, mode, &(struct fb_params){ .type = FB_STD, .buffer_size = buflen });
175 }
176
177 struct fastbuf *
178 bopen(const char *name, uns mode, uns buflen)
179 {
180   return bopen_file(name, mode, &(struct fb_params){ .type = FB_STD, .buffer_size = buflen });
181 }
182
183 struct fastbuf *
184 bfdopen(int fd, uns buflen)
185 {
186   return bopen_fd(fd, &(struct fb_params){ .type = FB_STD, .buffer_size = buflen });
187 }
188
189 struct fastbuf *
190 bfdopen_shared(int fd, uns buflen)
191 {
192   struct fastbuf *f = bfdopen(fd, buflen);
193   bconfig(f, BCONFIG_IS_TEMP_FILE, 2);
194   return f;
195 }