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