xref: /haiku/src/add-ons/kernel/file_systems/layers/log_overlay/log_overlay.cpp (revision 21258e2674226d6aa732321b6f8494841895af5f)
1 /*
2  * Copyright 2010, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Michael Lotz <mmlr@mlotz.ch>
7  */
8 
9 #include <new>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 
14 #include <errno.h>
15 #include <dirent.h>
16 
17 #include <fs_info.h>
18 #include <fs_interface.h>
19 
20 #include <debug.h>
21 #include <KernelExport.h>
22 
23 #include <io_requests.h>
24 
25 static const char *kLogFilePrefix = "/var/log/log_overlay";
26 
27 
28 #define DO_LOG(format, args...) \
29 	{ \
30 		char _printBuffer[256]; \
31 		int _printSize = snprintf(_printBuffer, sizeof(_printBuffer), \
32 			"%" B_PRId64 " %" B_PRId32 " %p: " format, system_time(), \
33 			find_thread(NULL), \
34 			((fs_vnode *)vnode->private_node)->private_node, args); \
35 		if ((unsigned int)_printSize > sizeof(_printBuffer)) { \
36 			_printBuffer[sizeof(_printBuffer) - 1] = '\n'; \
37 			_printSize = sizeof(_printBuffer); \
38 		} \
39 		write((int)(addr_t)volume->private_volume, _printBuffer, _printSize); \
40 	}
41 
42 #define OVERLAY_CALL(op, params...) \
43 	status_t result = B_UNSUPPORTED; \
44 	fs_vnode *superVnode = (fs_vnode *)vnode->private_node; \
45 	if (superVnode->ops->op != NULL) \
46 		result = superVnode->ops->op(volume->super_volume, superVnode, params);
47 
48 
49 static status_t
50 overlay_put_vnode(fs_volume *volume, fs_vnode *vnode, bool reenter)
51 {
52 	DO_LOG("put_vnode reenter: %s\n", reenter ? "yes" : "no");
53 
54 	status_t result = B_UNSUPPORTED;
55 	fs_vnode *superVnode = (fs_vnode *)vnode->private_node;
56 	if (superVnode->ops->put_vnode != NULL) {
57 		result = superVnode->ops->put_vnode(volume->super_volume, superVnode,
58 			reenter);
59 	}
60 
61 	DO_LOG("put_vnode result: %#" B_PRIx32 "\n", result);
62 	delete (fs_vnode *)vnode->private_node;
63 	return result;
64 }
65 
66 
67 static status_t
68 overlay_remove_vnode(fs_volume *volume, fs_vnode *vnode, bool reenter)
69 {
70 	DO_LOG("remove_vnode reenter: %s\n", reenter ? "yes" : "no");
71 
72 	status_t result = B_UNSUPPORTED;
73 	fs_vnode *superVnode = (fs_vnode *)vnode->private_node;
74 	if (superVnode->ops->remove_vnode != NULL) {
75 		result = superVnode->ops->remove_vnode(volume->super_volume, superVnode,
76 			reenter);
77 	}
78 
79 	DO_LOG("remove_vnode result: %#" B_PRIx32 "\n", result);
80 	delete (fs_vnode *)vnode->private_node;
81 	return result;
82 }
83 
84 
85 static status_t
86 overlay_get_super_vnode(fs_volume *volume, fs_vnode *vnode,
87 	fs_volume *superVolume, fs_vnode *_superVnode)
88 {
89 	if (volume == superVolume) {
90 		*_superVnode = *vnode;
91 		return B_OK;
92 	}
93 
94 	fs_vnode *superVnode = (fs_vnode *)vnode->private_node;
95 	if (superVnode->ops->get_super_vnode != NULL) {
96 		return superVnode->ops->get_super_vnode(volume->super_volume,
97 			superVnode, superVolume, _superVnode);
98 	}
99 
100 	*_superVnode = *superVnode;
101 	return B_OK;
102 }
103 
104 
105 static status_t
106 overlay_lookup(fs_volume *volume, fs_vnode *vnode, const char *name, ino_t *id)
107 {
108 	DO_LOG("lookup name: \"%s\"\n", name);
109 	OVERLAY_CALL(lookup, name, id)
110 	DO_LOG("lookup result: %#" B_PRIx32 "; id: %" B_PRIdINO "\n", result, *id);
111 	return result;
112 }
113 
114 
115 static status_t
116 overlay_get_vnode_name(fs_volume *volume, fs_vnode *vnode, char *buffer,
117 	size_t bufferSize)
118 {
119 	DO_LOG("get_vnode_name buffer: %p; buffer_size: %" B_PRIuSIZE "\n", buffer,
120 		bufferSize);
121 	OVERLAY_CALL(get_vnode_name, buffer, bufferSize)
122 	DO_LOG("get_vnode_name result: %#" B_PRIx32 "; buffer: \"%s\"\n", result,
123 		result == B_OK ? buffer : "unsafe");
124 	return result;
125 }
126 
127 
128 static bool
129 overlay_can_page(fs_volume *volume, fs_vnode *vnode, void *cookie)
130 {
131 	DO_LOG("can_page cookie: %p\n", cookie);
132 	bool result = false;
133 	fs_vnode *superVnode = (fs_vnode *)vnode->private_node;
134 	if (superVnode->ops->can_page != NULL) {
135 		result = superVnode->ops->can_page(volume->super_volume, superVnode,
136 			cookie);
137 	}
138 
139 	DO_LOG("can_page result: %s\n", result ? "yes" : "no");
140 	return result;
141 }
142 
143 
144 static status_t
145 overlay_read_pages(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos,
146 	const iovec *vecs, size_t count, size_t *numBytes)
147 {
148 	DO_LOG("read_pages cookie: %p; pos: %" B_PRIdOFF "; vecs: %p; count: %"
149 		B_PRIuSIZE "; num_bytes: %" B_PRIuSIZE "\n", cookie, pos, vecs, count,
150 		*numBytes);
151 	OVERLAY_CALL(read_pages, cookie, pos, vecs, count, numBytes)
152 	DO_LOG("read_pages result: %#" B_PRIx32 "; num_bytes: %" B_PRIuSIZE "\n",
153 		result, *numBytes);
154 	return result;
155 }
156 
157 
158 static status_t
159 overlay_write_pages(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos,
160 	const iovec *vecs, size_t count, size_t *numBytes)
161 {
162 	DO_LOG("write_pages cookie: %p; pos: %" B_PRIdOFF "; vecs: %p; count: %"
163 		B_PRIuSIZE "; num_bytes: %" B_PRIuSIZE "\n", cookie, pos, vecs, count,
164 		*numBytes);
165 	OVERLAY_CALL(write_pages, cookie, pos, vecs, count, numBytes)
166 	DO_LOG("write_pages result: %#" B_PRIx32 "; num_bytes: %" B_PRIuSIZE "\n",
167 		result, *numBytes);
168 	return result;
169 }
170 
171 
172 static status_t
173 overlay_io(fs_volume *volume, fs_vnode *vnode, void *cookie,
174 	io_request *request)
175 {
176 	DO_LOG("io cookie: %p; request: %p (write: %s; offset: %" B_PRIdOFF
177 		"; length: %" B_PRIdOFF ")\n", cookie, request,
178 		io_request_is_write(request) ? "yes" : "no", io_request_offset(request),
179 		io_request_length(request));
180 	OVERLAY_CALL(io, cookie, request)
181 	DO_LOG("io result: %#" B_PRIx32 "\n", result);
182 	return result;
183 }
184 
185 
186 static status_t
187 overlay_cancel_io(fs_volume *volume, fs_vnode *vnode, void *cookie,
188 	io_request *request)
189 {
190 	DO_LOG("cancel_io cookie: %p; request: %p\n", cookie, request);
191 	OVERLAY_CALL(cancel_io, cookie, request)
192 	DO_LOG("cancel_io result: %#" B_PRIx32 "\n", result);
193 	return result;
194 }
195 
196 
197 static status_t
198 overlay_get_file_map(fs_volume *volume, fs_vnode *vnode, off_t offset,
199 	size_t size, struct file_io_vec *vecs, size_t *count)
200 {
201 	DO_LOG("get_file_map offset: %" B_PRIdOFF "; size: %" B_PRIuSIZE
202 		"; vecs: %p; count: %" B_PRIuSIZE "\n", offset, size, vecs, *count);
203 	OVERLAY_CALL(get_file_map, offset, size, vecs, count)
204 	DO_LOG("get_file_map result: %#" B_PRIx32 "; count: %" B_PRIuSIZE "\n",
205 		result, *count);
206 	return result;
207 }
208 
209 
210 static status_t
211 overlay_ioctl(fs_volume *volume, fs_vnode *vnode, void *cookie, uint32 op,
212 	void *buffer, size_t length)
213 {
214 	DO_LOG("ioctl cookie: %p; op: %" B_PRIu32 "; buffer: %p; size: %" B_PRIuSIZE
215 		"\n", cookie, op, buffer, length);
216 	OVERLAY_CALL(ioctl, cookie, op, buffer, length)
217 	DO_LOG("ioctl result: %#" B_PRIx32 "\n", result);
218 	return result;
219 }
220 
221 
222 static status_t
223 overlay_set_flags(fs_volume *volume, fs_vnode *vnode, void *cookie,
224 	int flags)
225 {
226 	DO_LOG("set_flags cookie: %p; flags: %#x\n", cookie, flags);
227 	OVERLAY_CALL(set_flags, cookie, flags)
228 	DO_LOG("set_flags result: %#" B_PRIx32 "\n", result);
229 	return result;
230 }
231 
232 
233 static status_t
234 overlay_select(fs_volume *volume, fs_vnode *vnode, void *cookie, uint8 event,
235 	selectsync *sync)
236 {
237 	DO_LOG("select cookie: %p; event: %" B_PRIu8 "; selectsync: %p\n", cookie,
238 		event, sync);
239 	OVERLAY_CALL(select, cookie, event, sync)
240 	DO_LOG("select result: %#" B_PRIx32 "\n", result);
241 	return result;
242 }
243 
244 
245 static status_t
246 overlay_deselect(fs_volume *volume, fs_vnode *vnode, void *cookie, uint8 event,
247 	selectsync *sync)
248 {
249 	DO_LOG("deselect cookie: %p; event: %" B_PRIu8 "; selectsync: %p\n", cookie,
250 		event, sync);
251 	OVERLAY_CALL(deselect, cookie, event, sync)
252 	DO_LOG("deselect result: %#" B_PRIx32 "\n", result);
253 	return result;
254 }
255 
256 
257 static status_t
258 overlay_fsync(fs_volume *volume, fs_vnode *vnode)
259 {
260 	DO_LOG("%s\n", "fsync");
261 
262 	status_t result = B_UNSUPPORTED;
263 	fs_vnode *superVnode = (fs_vnode *)vnode->private_node;
264 	if (superVnode->ops->fsync != NULL)
265 		result = superVnode->ops->fsync(volume->super_volume, superVnode);
266 
267 	DO_LOG("fsync result: %#" B_PRIx32 "\n", result);
268 	return result;
269 }
270 
271 
272 static status_t
273 overlay_read_symlink(fs_volume *volume, fs_vnode *vnode, char *buffer,
274 	size_t *bufferSize)
275 {
276 	DO_LOG("read_symlink buffer: %p; buffer_size: %" B_PRIuSIZE "\n", buffer,
277 		*bufferSize);
278 	OVERLAY_CALL(read_symlink, buffer, bufferSize)
279 	DO_LOG("read_symlink result: %#" B_PRIx32 "; buffer_size: %" B_PRIuSIZE
280 		"; \"%.*s\"\n", result, *bufferSize,
281 		result == B_OK ? (int)*bufferSize : 6,
282 		result == B_OK ? buffer : "unsafe");
283 	return result;
284 }
285 
286 
287 static status_t
288 overlay_create_symlink(fs_volume *volume, fs_vnode *vnode, const char *name,
289 	const char *path, int mode)
290 {
291 	DO_LOG("create_symlink name: \"%s\"; path: \"%s\"; mode: %#x\n", name, path,
292 		mode);
293 	OVERLAY_CALL(create_symlink, name, path, mode)
294 	DO_LOG("create_symlink result: %#" B_PRIx32 "\n", result);
295 	return result;
296 }
297 
298 
299 static status_t
300 overlay_link(fs_volume *volume, fs_vnode *vnode, const char *name,
301 	fs_vnode *target)
302 {
303 	DO_LOG("link name: \"%s\"; target: %p\n", name,
304 		((fs_vnode *)target->private_node)->private_node);
305 	OVERLAY_CALL(link, name, (fs_vnode *)target->private_node)
306 	DO_LOG("link result: %#" B_PRIx32 "\n", result);
307 	return result;
308 }
309 
310 
311 static status_t
312 overlay_unlink(fs_volume *volume, fs_vnode *vnode, const char *name)
313 {
314 	DO_LOG("unlink name: \"%s\"\n", name);
315 	OVERLAY_CALL(unlink, name)
316 	DO_LOG("unlink result: %#" B_PRIx32 "\n", result);
317 	return result;
318 }
319 
320 
321 static status_t
322 overlay_rename(fs_volume *volume, fs_vnode *vnode,
323 	const char *fromName, fs_vnode *toDir, const char *toName)
324 {
325 	DO_LOG("rename from_name: \"%s\"; to_dir: %p; to_name: \"%s\"\n",
326 		fromName, ((fs_vnode *)toDir->private_node)->private_node, toName);
327 	OVERLAY_CALL(rename, fromName, (fs_vnode *)toDir->private_node, toName)
328 	DO_LOG("rename result: %#" B_PRIx32 "\n", result);
329 	return result;
330 }
331 
332 
333 static status_t
334 overlay_access(fs_volume *volume, fs_vnode *vnode, int mode)
335 {
336 	DO_LOG("access mode: %#x\n", mode);
337 	OVERLAY_CALL(access, mode)
338 	DO_LOG("access result: %#" B_PRIx32 "\n", result);
339 	return result;
340 }
341 
342 
343 static status_t
344 overlay_read_stat(fs_volume *volume, fs_vnode *vnode, struct stat *stat)
345 {
346 	DO_LOG("read_stat stat: %p\n", stat);
347 	OVERLAY_CALL(read_stat, stat)
348 	if (result == B_OK) {
349 		DO_LOG("read_stat result: %#" B_PRIx32 "; stat(dev: %" B_PRIdDEV
350 			"; ino: %" B_PRIdINO "; mode: %#x; uid: %u; gid %u; size: %"
351 			B_PRIdOFF ")\n", result, stat->st_dev, stat->st_ino, stat->st_mode,
352 			stat->st_uid, stat->st_gid, stat->st_size);
353 	} else
354 		DO_LOG("read_stat result: %#" B_PRIx32 "\n", result);
355 	return result;
356 }
357 
358 
359 static status_t
360 overlay_write_stat(fs_volume *volume, fs_vnode *vnode, const struct stat *stat,
361 	uint32 statMask)
362 {
363 	DO_LOG("write_stat stat: %p; mask: %" B_PRIu32 "\n", stat, statMask);
364 	OVERLAY_CALL(write_stat, stat, statMask)
365 	DO_LOG("write_stat result: %#" B_PRIx32 "\n", result);
366 	return result;
367 }
368 
369 
370 static status_t
371 overlay_create(fs_volume *volume, fs_vnode *vnode, const char *name,
372 	int openMode, int perms, void **cookie, ino_t *newVnodeID)
373 {
374 	DO_LOG("create name: \"%s\"; open_mode: %#x; perms: %#x\n", name, openMode,
375 		perms);
376 	OVERLAY_CALL(create, name, openMode, perms, cookie, newVnodeID)
377 	DO_LOG("create result: %#" B_PRIx32 "; cookie: %p; new_vnode_id: %"
378 		B_PRIdINO "\n", result, *cookie, *newVnodeID);
379 	return result;
380 }
381 
382 
383 static status_t
384 overlay_open(fs_volume *volume, fs_vnode *vnode, int openMode, void **cookie)
385 {
386 	DO_LOG("open open_mode: %#x\n", openMode);
387 	OVERLAY_CALL(open, openMode, cookie)
388 	DO_LOG("open result: %#" B_PRIx32 "; cookie: %p\n", result, *cookie);
389 	return result;
390 }
391 
392 
393 static status_t
394 overlay_close(fs_volume *volume, fs_vnode *vnode, void *cookie)
395 {
396 	DO_LOG("close cookie %p\n", cookie);
397 	OVERLAY_CALL(close, cookie)
398 	DO_LOG("close result: %#" B_PRIx32 "\n", result);
399 	return result;
400 }
401 
402 
403 static status_t
404 overlay_free_cookie(fs_volume *volume, fs_vnode *vnode, void *cookie)
405 {
406 	DO_LOG("free_cookie cookie %p\n", cookie);
407 	OVERLAY_CALL(free_cookie, cookie)
408 	DO_LOG("free_cookie result: %#" B_PRIx32 "\n", result);
409 	return result;
410 }
411 
412 
413 static status_t
414 overlay_read(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos,
415 	void *buffer, size_t *length)
416 {
417 	DO_LOG("read cookie: %p; pos: %" B_PRIdOFF "; buffer: %p; length: %"
418 		B_PRIuSIZE "\n", cookie, pos, buffer, *length);
419 	OVERLAY_CALL(read, cookie, pos, buffer, length)
420 	DO_LOG("read result: %#" B_PRIx32 "; length: %" B_PRIuSIZE "\n", result,
421 		*length);
422 	return result;
423 }
424 
425 
426 static status_t
427 overlay_write(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos,
428 	const void *buffer, size_t *length)
429 {
430 	DO_LOG("write cookie: %p; pos: %" B_PRIdOFF "; buffer: %p; length: %"
431 		B_PRIuSIZE "\n", cookie, pos, buffer, *length);
432 	OVERLAY_CALL(write, cookie, pos, buffer, length)
433 	DO_LOG("write result: %#" B_PRIx32 "; length: %" B_PRIuSIZE "\n", result,
434 		*length);
435 	return result;
436 }
437 
438 
439 static status_t
440 overlay_create_dir(fs_volume *volume, fs_vnode *vnode, const char *name,
441 	int perms)
442 {
443 	DO_LOG("create_dir name: \"%s\"; perms: %#x\n", name, perms);
444 	OVERLAY_CALL(create_dir, name, perms)
445 	DO_LOG("create_dir result: %#" B_PRIx32 "\n", result);
446 	return result;
447 }
448 
449 
450 static status_t
451 overlay_remove_dir(fs_volume *volume, fs_vnode *vnode, const char *name)
452 {
453 	DO_LOG("remove_dir name: \"%s\"\n", name);
454 	OVERLAY_CALL(remove_dir, name)
455 	DO_LOG("remove_dir result: %#" B_PRIx32 "\n", result);
456 	return result;
457 }
458 
459 
460 static status_t
461 overlay_open_dir(fs_volume *volume, fs_vnode *vnode, void **cookie)
462 {
463 	DO_LOG("%s\n", "open_dir");
464 	OVERLAY_CALL(open_dir, cookie)
465 	DO_LOG("open_dir result: %#" B_PRIx32 "; cookie: %p\n", result, *cookie);
466 	return result;
467 }
468 
469 
470 static status_t
471 overlay_close_dir(fs_volume *volume, fs_vnode *vnode, void *cookie)
472 {
473 	DO_LOG("close_dir cookie: %p\n", cookie);
474 	OVERLAY_CALL(close_dir, cookie)
475 	DO_LOG("close_dir result: %#" B_PRIx32 "\n", result);
476 	return result;
477 }
478 
479 
480 static status_t
481 overlay_free_dir_cookie(fs_volume *volume, fs_vnode *vnode, void *cookie)
482 {
483 	DO_LOG("free_dir_cookie cookie: %p\n", cookie);
484 	OVERLAY_CALL(free_dir_cookie, cookie)
485 	DO_LOG("free_dir_cookie result: %#" B_PRIx32 "\n", result);
486 	return result;
487 }
488 
489 
490 static status_t
491 overlay_read_dir(fs_volume *volume, fs_vnode *vnode, void *cookie,
492 	struct dirent *buffer, size_t bufferSize, uint32 *num)
493 {
494 	DO_LOG("read_dir cookie: %p; buffer: %p; buffer_size: %" B_PRIuSIZE "\n",
495 		cookie, buffer, bufferSize);
496 	OVERLAY_CALL(read_dir, cookie, buffer, bufferSize, num);
497 	DO_LOG("read_dir result: %#" B_PRIx32 "; num: %" B_PRIu32 "\n", result,
498 		*num);
499 	return result;
500 }
501 
502 
503 static status_t
504 overlay_rewind_dir(fs_volume *volume, fs_vnode *vnode, void *cookie)
505 {
506 	DO_LOG("rewind_dir cookie: %p\n", cookie);
507 	OVERLAY_CALL(rewind_dir, cookie)
508 	DO_LOG("rewind_dir result: %#" B_PRIx32 "\n", result);
509 	return result;
510 }
511 
512 
513 static status_t
514 overlay_open_attr_dir(fs_volume *volume, fs_vnode *vnode, void **cookie)
515 {
516 	DO_LOG("%s\n", "open_attr_dir");
517 	OVERLAY_CALL(open_attr_dir, cookie)
518 	DO_LOG("open_attr_dir result: %#" B_PRIx32 "; cookie: %p\n", result,
519 		*cookie);
520 	return result;
521 }
522 
523 
524 static status_t
525 overlay_close_attr_dir(fs_volume *volume, fs_vnode *vnode, void *cookie)
526 {
527 	DO_LOG("close_attr_dir cookie: %p\n", cookie);
528 	OVERLAY_CALL(close_attr_dir, cookie)
529 	DO_LOG("close_attr_dir result: %#" B_PRIx32 "\n", result);
530 	return result;
531 }
532 
533 
534 static status_t
535 overlay_free_attr_dir_cookie(fs_volume *volume, fs_vnode *vnode, void *cookie)
536 {
537 	DO_LOG("free_attr_dir_cookie cookie: %p\n", cookie);
538 	OVERLAY_CALL(free_attr_dir_cookie, cookie)
539 	DO_LOG("free_attr_dir_cookie result: %#" B_PRIx32 "\n", result);
540 	return result;
541 }
542 
543 
544 static status_t
545 overlay_read_attr_dir(fs_volume *volume, fs_vnode *vnode, void *cookie,
546 	struct dirent *buffer, size_t bufferSize, uint32 *num)
547 {
548 	DO_LOG("read_attr_dir cookie: %p; buffer: %p; buffer_size: %" B_PRIuSIZE
549 		"\n", cookie, buffer, bufferSize);
550 	OVERLAY_CALL(read_attr_dir, cookie, buffer, bufferSize, num);
551 	DO_LOG("read_attr_dir result: %#" B_PRIx32 "; num: %" B_PRIu32 "\n", result,
552 		*num);
553 	return result;
554 }
555 
556 
557 static status_t
558 overlay_rewind_attr_dir(fs_volume *volume, fs_vnode *vnode, void *cookie)
559 {
560 	DO_LOG("rewind_attr_dir cookie: %p\n", cookie);
561 	OVERLAY_CALL(rewind_attr_dir, cookie)
562 	DO_LOG("rewind_attr_dir result: %#" B_PRIx32 "\n", result);
563 	return result;
564 }
565 
566 
567 static status_t
568 overlay_create_attr(fs_volume *volume, fs_vnode *vnode, const char *name,
569 	uint32 type, int openMode, void **cookie)
570 {
571 	DO_LOG("create_attr name: \"%s\"; type: %#" B_PRIx32 "; open_mode: %#x\n",
572 		name, type, openMode);
573 	OVERLAY_CALL(create_attr, name, type, openMode, cookie)
574 	DO_LOG("create_attr result: %#" B_PRIx32 "; cookie: %p\n", result, *cookie);
575 	return result;
576 }
577 
578 
579 static status_t
580 overlay_open_attr(fs_volume *volume, fs_vnode *vnode, const char *name,
581 	int openMode, void **cookie)
582 {
583 	DO_LOG("open_attr name: \"%s\"; open_mode: %#x\n", name, openMode);
584 	OVERLAY_CALL(open_attr, name, openMode, cookie)
585 	DO_LOG("open_attr result: %#" B_PRIx32 "; cookie: %p\n", result, *cookie);
586 	return result;
587 }
588 
589 
590 static status_t
591 overlay_close_attr(fs_volume *volume, fs_vnode *vnode, void *cookie)
592 {
593 	DO_LOG("close_attr cookie: %p\n", cookie);
594 	OVERLAY_CALL(close_attr, cookie)
595 	DO_LOG("close_attr result: %#" B_PRIx32 "\n", result);
596 	return result;
597 }
598 
599 
600 static status_t
601 overlay_free_attr_cookie(fs_volume *volume, fs_vnode *vnode, void *cookie)
602 {
603 	DO_LOG("free_attr_cookie cookie: %p\n", cookie);
604 	OVERLAY_CALL(free_attr_cookie, cookie)
605 	DO_LOG("free_attr_cookie result: %#" B_PRIx32 "\n", result);
606 	return result;
607 }
608 
609 
610 static status_t
611 overlay_read_attr(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos,
612 	void *buffer, size_t *length)
613 {
614 	DO_LOG("read_attr cookie: %p; pos: %" B_PRIdOFF "; buffer: %p; length: %"
615 		B_PRIuSIZE "\n", cookie, pos, buffer, *length);
616 	OVERLAY_CALL(read_attr, cookie, pos, buffer, length)
617 	DO_LOG("read_attr result: %#" B_PRIx32 "; length: %" B_PRIuSIZE "\n",
618 		result, *length);
619 	return result;
620 }
621 
622 
623 static status_t
624 overlay_write_attr(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos,
625 	const void *buffer, size_t *length)
626 {
627 	DO_LOG("write_attr cookie: %p; pos: %" B_PRIdOFF "; buffer: %p; length: %"
628 		B_PRIuSIZE "\n", cookie, pos, buffer, *length);
629 	OVERLAY_CALL(write_attr, cookie, pos, buffer, length)
630 	DO_LOG("write_attr result: %#" B_PRIx32 "; length: %" B_PRIuSIZE "\n",
631 		result, *length);
632 	return result;
633 }
634 
635 
636 static status_t
637 overlay_read_attr_stat(fs_volume *volume, fs_vnode *vnode, void *cookie,
638 	struct stat *stat)
639 {
640 	DO_LOG("read_attr_stat cookie: %p; stat: %p\n", cookie, stat);
641 	OVERLAY_CALL(read_attr_stat, cookie, stat)
642 	if (result == B_OK) {
643 		DO_LOG("read_attr_stat result: %#" B_PRIx32 "; stat(dev: %" B_PRIdDEV
644 			"; ino: %" B_PRIdINO "; mode: %#x; uid: %u; gid %u; size: %"
645 			B_PRIdOFF "; type: %#" B_PRIx32 ")\n", result,
646 			stat->st_dev, stat->st_ino, stat->st_mode, stat->st_uid,
647 			stat->st_gid, stat->st_size, stat->st_type);
648 	} else
649 		DO_LOG("read_attr_stat result: %#" B_PRIx32 "\n", result);
650 	return result;
651 }
652 
653 
654 static status_t
655 overlay_write_attr_stat(fs_volume *volume, fs_vnode *vnode, void *cookie,
656 	const struct stat *stat, int statMask)
657 {
658 	DO_LOG("write_attr_stat cookie: %p; stat: %p; mask: %#x\n", cookie, stat,
659 		statMask);
660 	OVERLAY_CALL(write_attr_stat, cookie, stat, statMask)
661 	DO_LOG("write_attr_stat result: %#" B_PRIx32 "\n", result);
662 	return result;
663 }
664 
665 
666 static status_t
667 overlay_rename_attr(fs_volume *volume, fs_vnode *vnode,
668 	const char *fromName, fs_vnode *toVnode, const char *toName)
669 {
670 	DO_LOG("rename_attr from_name: \"%s\"; to_vnode: %p; to_name: \"%s\"\n",
671 		fromName, ((fs_vnode *)toVnode->private_node)->private_node, toName);
672 	OVERLAY_CALL(rename_attr, fromName, (fs_vnode *)toVnode->private_node,
673 		toName)
674 	DO_LOG("rename_attr result: %#" B_PRIx32 "\n", result);
675 	return result;
676 }
677 
678 
679 static status_t
680 overlay_remove_attr(fs_volume *volume, fs_vnode *vnode, const char *name)
681 {
682 	DO_LOG("remove_attr name: \"%s\"\n", name);
683 	OVERLAY_CALL(remove_attr, name)
684 	DO_LOG("remove_attr result: %#" B_PRIx32 "\n", result);
685 	return result;
686 }
687 
688 
689 static status_t
690 overlay_create_special_node(fs_volume *volume, fs_vnode *vnode,
691 	const char *name, fs_vnode *subVnode, mode_t mode, uint32 flags,
692 	fs_vnode *_superVnode, ino_t *nodeID)
693 {
694 	DO_LOG("create_special_node name: \"%s\"; sub_vnode: %p; mode: %#x;"
695 		" flags: %" B_PRIu32 "\n", name, subVnode->private_node, mode, flags);
696 	OVERLAY_CALL(create_special_node, name, (fs_vnode *)subVnode->private_node,
697 		mode, flags, _superVnode, nodeID)
698 	DO_LOG("create_special_node result: %#" B_PRIx32 "; super_vnode: %p;"
699 		" node_id: %" B_PRIdINO "\n", result, _superVnode->private_node,
700 		*nodeID);
701 	return result;
702 }
703 
704 
705 static fs_vnode_ops sOverlayVnodeOps = {
706 	&overlay_lookup,
707 	&overlay_get_vnode_name,
708 
709 	&overlay_put_vnode,
710 	&overlay_remove_vnode,
711 
712 	&overlay_can_page,
713 	&overlay_read_pages,
714 	&overlay_write_pages,
715 
716 	&overlay_io,
717 	&overlay_cancel_io,
718 
719 	&overlay_get_file_map,
720 
721 	/* common */
722 	&overlay_ioctl,
723 	&overlay_set_flags,
724 	&overlay_select,
725 	&overlay_deselect,
726 	&overlay_fsync,
727 
728 	&overlay_read_symlink,
729 	&overlay_create_symlink,
730 	&overlay_link,
731 	&overlay_unlink,
732 	&overlay_rename,
733 
734 	&overlay_access,
735 	&overlay_read_stat,
736 	&overlay_write_stat,
737 	NULL,	// fs_preallocate
738 
739 	/* file */
740 	&overlay_create,
741 	&overlay_open,
742 	&overlay_close,
743 	&overlay_free_cookie,
744 	&overlay_read,
745 	&overlay_write,
746 
747 	/* directory */
748 	&overlay_create_dir,
749 	&overlay_remove_dir,
750 	&overlay_open_dir,
751 	&overlay_close_dir,
752 	&overlay_free_dir_cookie,
753 	&overlay_read_dir,
754 	&overlay_rewind_dir,
755 
756 	/* attribute directory operations */
757 	&overlay_open_attr_dir,
758 	&overlay_close_attr_dir,
759 	&overlay_free_attr_dir_cookie,
760 	&overlay_read_attr_dir,
761 	&overlay_rewind_attr_dir,
762 
763 	/* attribute operations */
764 	&overlay_create_attr,
765 	&overlay_open_attr,
766 	&overlay_close_attr,
767 	&overlay_free_attr_cookie,
768 	&overlay_read_attr,
769 	&overlay_write_attr,
770 
771 	&overlay_read_attr_stat,
772 	&overlay_write_attr_stat,
773 	&overlay_rename_attr,
774 	&overlay_remove_attr,
775 
776 	/* support for node and FS layers */
777 	&overlay_create_special_node,
778 	&overlay_get_super_vnode
779 };
780 
781 
782 //	#pragma mark - volume ops
783 
784 
785 #define DO_VOLUME_LOG(format, args...) \
786 	{ \
787 		char _printBuffer[256]; \
788 		int _printSize = snprintf(_printBuffer, sizeof(_printBuffer), \
789 			"%" B_PRId64 " %" B_PRId32 " %p: " format, system_time(), \
790 			find_thread(NULL), volume->super_volume, args); \
791 		if ((unsigned int)_printSize > sizeof(_printBuffer)) { \
792 			_printBuffer[sizeof(_printBuffer) - 1] = '\n'; \
793 			_printSize = sizeof(_printBuffer); \
794 		} \
795 		write((int)(addr_t)volume->private_volume, _printBuffer, _printSize); \
796 	}
797 
798 #define OVERLAY_VOLUME_CALL(op, params...) \
799 	status_t result = B_UNSUPPORTED; \
800 	if (volume->super_volume->ops->op != NULL) \
801 		result = volume->super_volume->ops->op(volume->super_volume, params);
802 
803 
804 static status_t
805 overlay_unmount(fs_volume *volume)
806 {
807 	if (volume->super_volume != NULL
808 		&& volume->super_volume->ops != NULL
809 		&& volume->super_volume->ops->unmount != NULL)
810 		volume->super_volume->ops->unmount(volume->super_volume);
811 
812 	close((int)(addr_t)volume->private_volume);
813 	return B_OK;
814 }
815 
816 
817 static status_t
818 overlay_read_fs_info(fs_volume *volume, struct fs_info *info)
819 {
820 	DO_VOLUME_LOG("%s\n", "read_fs_info");
821 	OVERLAY_VOLUME_CALL(read_fs_info, info)
822 	DO_VOLUME_LOG("read_fs_info result: %#" B_PRIx32 "; info(dev: %" B_PRIdDEV
823 		"; root: %" B_PRIdINO "; flags: %#" B_PRIx32 "; block_size: %" B_PRIdOFF
824 		"; io_size: %" B_PRIdOFF "; total_blocks: %" B_PRIdOFF
825 		"; free_blocks: %" B_PRIdOFF "; total_nodes: %" B_PRIdOFF
826 		"; free_nodes: %" B_PRIdOFF "; device_name: \"%s\"; volume_name: \"%s\""
827 		"; fsh_name: \"%s\")\n", result, info->dev, info->root, info->flags,
828 		info->block_size, info->io_size, info->total_blocks, info->free_blocks,
829 		info->total_nodes, info->free_nodes, info->device_name,
830 		info->volume_name, info->fsh_name);
831 	return result;
832 }
833 
834 
835 static status_t
836 overlay_write_fs_info(fs_volume *volume, const struct fs_info *info,
837 	uint32 mask)
838 {
839 	DO_VOLUME_LOG("write_fs_info info: %p; mask: %#" B_PRIx32 "\n", info, mask);
840 	OVERLAY_VOLUME_CALL(write_fs_info, info, mask)
841 	DO_VOLUME_LOG("write_fs_info result: %#" B_PRIx32 "\n", result);
842 	return result;
843 }
844 
845 
846 static status_t
847 overlay_sync(fs_volume *volume)
848 {
849 	DO_VOLUME_LOG("%s\n", "sync");
850 	status_t result = B_UNSUPPORTED;
851 	if (volume->super_volume->ops->sync != NULL)
852 		result = volume->super_volume->ops->sync(volume->super_volume);
853 	DO_VOLUME_LOG("sync result: %#" B_PRIx32 "\n", result);
854 	return result;
855 }
856 
857 
858 static status_t
859 overlay_get_vnode(fs_volume *volume, ino_t id, fs_vnode *vnode, int *type,
860 	uint32 *flags, bool reenter)
861 {
862 	DO_VOLUME_LOG("get_vnode id: %" B_PRIdINO "; vnode: %p; type*: %p;"
863 		" flags*: %p; reenter: %s\n", id, vnode, type, flags,
864 		reenter ? "yes" : "no");
865 
866 	if (volume->super_volume->ops->get_vnode == NULL) {
867 		DO_VOLUME_LOG("get_vnode %s\n", "not supported");
868 		return B_UNSUPPORTED;
869 	}
870 
871 	fs_vnode *superVnode = new(std::nothrow) fs_vnode;
872 	if (superVnode == NULL) {
873 		DO_VOLUME_LOG("get_vnode %s\n", "no memory");
874 		return B_NO_MEMORY;
875 	}
876 
877 	status_t result = volume->super_volume->ops->get_vnode(volume->super_volume,
878 		id, superVnode, type, flags, reenter);
879 	if (result != B_OK) {
880 		DO_VOLUME_LOG("get_vnode result: %#" B_PRIx32 "\n", result);
881 		delete superVnode;
882 		return result;
883 	}
884 
885 	vnode->private_node = superVnode;
886 	vnode->ops = &sOverlayVnodeOps;
887 
888 	DO_VOLUME_LOG("get_vnode result: %#" B_PRIx32 "; super_vnode: %p\n", result,
889 		superVnode->private_node);
890 	return B_OK;
891 }
892 
893 
894 static status_t
895 overlay_open_index_dir(fs_volume *volume, void **cookie)
896 {
897 	DO_VOLUME_LOG("%s\n", "open_index_dir");
898 	OVERLAY_VOLUME_CALL(open_index_dir, cookie)
899 	DO_VOLUME_LOG("open_index_dir result: %#" B_PRIx32 "; cookie: %p\n", result,
900 		*cookie);
901 	return result;
902 }
903 
904 
905 static status_t
906 overlay_close_index_dir(fs_volume *volume, void *cookie)
907 {
908 	DO_VOLUME_LOG("close_index_dir cookie: %p\n", cookie);
909 	OVERLAY_VOLUME_CALL(close_index_dir, cookie)
910 	DO_VOLUME_LOG("close_index_dir result: %#" B_PRIx32 "\n", result);
911 	return result;
912 }
913 
914 
915 static status_t
916 overlay_free_index_dir_cookie(fs_volume *volume, void *cookie)
917 {
918 	DO_VOLUME_LOG("free_index_dir_cookie cookie: %p\n", cookie);
919 	OVERLAY_VOLUME_CALL(free_index_dir_cookie, cookie)
920 	DO_VOLUME_LOG("free_index_dir_cookie result: %#" B_PRIx32 "\n", result);
921 	return result;
922 }
923 
924 
925 static status_t
926 overlay_read_index_dir(fs_volume *volume, void *cookie, struct dirent *buffer,
927 	size_t bufferSize, uint32 *num)
928 {
929 	DO_VOLUME_LOG("read_index_dir cookie: %p; buffer: %p; buffer_size: %"
930 		B_PRIuSIZE "\n", cookie, buffer, bufferSize);
931 	OVERLAY_VOLUME_CALL(read_index_dir, cookie, buffer, bufferSize, num)
932 	DO_VOLUME_LOG("read_index_dir result: %#" B_PRIx32 "; num: %" B_PRIu32 "\n",
933 		result, *num);
934 	return result;
935 }
936 
937 
938 static status_t
939 overlay_rewind_index_dir(fs_volume *volume, void *cookie)
940 {
941 	DO_VOLUME_LOG("rewind_index_dir cookie: %p\n", cookie);
942 	OVERLAY_VOLUME_CALL(rewind_index_dir, cookie)
943 	DO_VOLUME_LOG("rewind_index_dir result: %#" B_PRIx32 "\n", result);
944 	return result;
945 }
946 
947 
948 static status_t
949 overlay_create_index(fs_volume *volume, const char *name, uint32 type,
950 	uint32 flags)
951 {
952 	DO_VOLUME_LOG("create_index name: \"%s\"; type: %#" B_PRIx32
953 		"; flags: %#" B_PRIx32 "\n", name, type, flags);
954 	OVERLAY_VOLUME_CALL(create_index, name, type, flags)
955 	DO_VOLUME_LOG("create_index result: %#" B_PRIx32 "\n", result);
956 	return result;
957 }
958 
959 
960 static status_t
961 overlay_remove_index(fs_volume *volume, const char *name)
962 {
963 	DO_VOLUME_LOG("remove_index name: \"%s\"\n", name);
964 	OVERLAY_VOLUME_CALL(remove_index, name)
965 	DO_VOLUME_LOG("remove_index result: %#" B_PRIx32 "\n", result);
966 	return result;
967 }
968 
969 
970 static status_t
971 overlay_read_index_stat(fs_volume *volume, const char *name, struct stat *stat)
972 {
973 	DO_VOLUME_LOG("read_index_stat name: \"%s\"; stat: %p\n", name, stat);
974 	OVERLAY_VOLUME_CALL(read_index_stat, name, stat)
975 	if (result == B_OK) {
976 		DO_VOLUME_LOG("read_index_stat result: %#" B_PRIx32 "; stat(dev: %"
977 			B_PRIdDEV "; ino: %" B_PRIdINO "; mode: %#x; uid: %u; gid %u;"
978 			" size: %" B_PRIdOFF "; type: %#" B_PRIx32 ")\n", result,
979 			stat->st_dev, stat->st_ino, stat->st_mode, stat->st_uid,
980 			stat->st_gid, stat->st_size, stat->st_type);
981 	} else
982 		DO_VOLUME_LOG("read_index_stat result: %#" B_PRIx32 "\n", result);
983 	return result;
984 }
985 
986 
987 static status_t
988 overlay_open_query(fs_volume *volume, const char *query, uint32 flags,
989 	port_id port, uint32 token, void **cookie)
990 {
991 	DO_VOLUME_LOG("open_query query: \"%s\"; flags: %#" B_PRIx32 "; port: %"
992 		B_PRId32 "; token: %" B_PRIu32 "\n", query, flags, port, token);
993 	OVERLAY_VOLUME_CALL(open_query, query, flags, port, token, cookie)
994 	DO_VOLUME_LOG("open_query result: %#" B_PRIx32 "; cookie: %p\n", result,
995 		*cookie);
996 	return result;
997 }
998 
999 
1000 static status_t
1001 overlay_close_query(fs_volume *volume, void *cookie)
1002 {
1003 	DO_VOLUME_LOG("close_query cookie: %p\n", cookie);
1004 	OVERLAY_VOLUME_CALL(close_query, cookie)
1005 	DO_VOLUME_LOG("close_query result: %#" B_PRIx32 "\n", result);
1006 	return result;
1007 }
1008 
1009 
1010 static status_t
1011 overlay_free_query_cookie(fs_volume *volume, void *cookie)
1012 {
1013 	DO_VOLUME_LOG("free_query_cookie cookie: %p\n", cookie);
1014 	OVERLAY_VOLUME_CALL(free_query_cookie, cookie)
1015 	DO_VOLUME_LOG("free_query_cookie result: %#" B_PRIx32 "\n", result);
1016 	return result;
1017 }
1018 
1019 
1020 static status_t
1021 overlay_read_query(fs_volume *volume, void *cookie, struct dirent *buffer,
1022 	size_t bufferSize, uint32 *num)
1023 {
1024 	DO_VOLUME_LOG("read_query cookie: %p; buffer: %p; buffer_size: %"
1025 		B_PRIuSIZE "\n", cookie, buffer, bufferSize);
1026 	OVERLAY_VOLUME_CALL(read_query, cookie, buffer, bufferSize, num)
1027 	DO_VOLUME_LOG("read_query result: %#" B_PRIx32 "; num: %" B_PRIu32 "\n",
1028 		result, *num);
1029 	return result;
1030 }
1031 
1032 
1033 static status_t
1034 overlay_rewind_query(fs_volume *volume, void *cookie)
1035 {
1036 	DO_VOLUME_LOG("rewind_query cookie: %p\n", cookie);
1037 	OVERLAY_VOLUME_CALL(rewind_query, cookie)
1038 	DO_VOLUME_LOG("rewind_query result: %#" B_PRIx32 "\n", result);
1039 	return result;
1040 }
1041 
1042 
1043 static status_t
1044 overlay_all_layers_mounted(fs_volume *volume)
1045 {
1046 	return B_OK;
1047 }
1048 
1049 
1050 static status_t
1051 overlay_create_sub_vnode(fs_volume *volume, ino_t id, fs_vnode *vnode)
1052 {
1053 	fs_vnode *superVnode = new(std::nothrow) fs_vnode;
1054 	if (superVnode == NULL)
1055 		return B_NO_MEMORY;
1056 
1057 	*superVnode = *vnode;
1058 	vnode->private_node = superVnode;
1059 	vnode->ops = &sOverlayVnodeOps;
1060 	return B_OK;
1061 }
1062 
1063 
1064 static status_t
1065 overlay_delete_sub_vnode(fs_volume *volume, fs_vnode *vnode)
1066 {
1067 	delete (fs_vnode *)vnode->private_node;
1068 	return B_OK;
1069 }
1070 
1071 
1072 static fs_volume_ops sOverlayVolumeOps = {
1073 	&overlay_unmount,
1074 
1075 	&overlay_read_fs_info,
1076 	&overlay_write_fs_info,
1077 	&overlay_sync,
1078 
1079 	&overlay_get_vnode,
1080 	&overlay_open_index_dir,
1081 	&overlay_close_index_dir,
1082 	&overlay_free_index_dir_cookie,
1083 	&overlay_read_index_dir,
1084 	&overlay_rewind_index_dir,
1085 
1086 	&overlay_create_index,
1087 	&overlay_remove_index,
1088 	&overlay_read_index_stat,
1089 
1090 	&overlay_open_query,
1091 	&overlay_close_query,
1092 	&overlay_free_query_cookie,
1093 	&overlay_read_query,
1094 	&overlay_rewind_query,
1095 
1096 	&overlay_all_layers_mounted,
1097 	&overlay_create_sub_vnode,
1098 	&overlay_delete_sub_vnode
1099 };
1100 
1101 
1102 //	#pragma mark - filesystem module
1103 
1104 
1105 static status_t
1106 overlay_mount(fs_volume *volume, const char *device, uint32 flags,
1107 	const char *args, ino_t *rootID)
1108 {
1109 	char filename[256];
1110 	snprintf(filename, sizeof(filename), "%s%s", kLogFilePrefix, device);
1111 	filename[sizeof(filename) - 1] = 0;
1112 
1113 	int filenameLength = strlen(filename);
1114 	for (int i = strlen(kLogFilePrefix); i < filenameLength; i++) {
1115 		if (filename[i] == '/')
1116 			filename[i] = '_';
1117 	}
1118 
1119 	int fd = creat(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1120 	if (fd < 0)
1121 		return errno;
1122 
1123 	volume->private_volume = (void *)(addr_t)fd;
1124 	volume->ops = &sOverlayVolumeOps;
1125 	return B_OK;
1126 }
1127 
1128 
1129 static status_t
1130 overlay_std_ops(int32 op, ...)
1131 {
1132 	switch (op) {
1133 		case B_MODULE_INIT:
1134 		case B_MODULE_UNINIT:
1135 			return B_OK;
1136 		default:
1137 			return B_ERROR;
1138 	}
1139 }
1140 
1141 
1142 static file_system_module_info sOverlayFileSystem = {
1143 	{
1144 		"file_systems/log_overlay" B_CURRENT_FS_API_VERSION,
1145 		0,
1146 		overlay_std_ops,
1147 	},
1148 
1149 	"log_overlay",						// short_name
1150 	"Logging Overlay File System",		// pretty_name
1151 	0,									// DDM flags
1152 
1153 	// scanning
1154 	NULL, // identify_partition
1155 	NULL, // scan_partition
1156 	NULL, // free_identify_partition_cookie
1157 	NULL, // free_partition_content_cookie
1158 
1159 	// general operations
1160 	&overlay_mount,
1161 
1162 	// capability querying
1163 	NULL, // get_supported_operations
1164 
1165 	NULL, // validate_resize
1166 	NULL, // validate_move
1167 	NULL, // validate_set_content_name
1168 	NULL, // validate_set_content_parameters
1169 	NULL, // validate_initialize
1170 
1171 	// shadow partition modification
1172 	NULL, // shadow_changed
1173 
1174 	// writing
1175 	NULL, // defragment
1176 	NULL, // repair
1177 	NULL, // resize
1178 	NULL, // move
1179 	NULL, // set_content_name
1180 	NULL, // set_content_parameters
1181 	NULL // initialize
1182 };
1183 
1184 module_info *modules[] = {
1185 	(module_info *)&sOverlayFileSystem,
1186 	NULL,
1187 };
1188