xref: /haiku/src/add-ons/kernel/file_systems/bindfs/kernel_interface.cpp (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
1 /*
2  * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <new>
8 
9 #include <fs_info.h>
10 #include <fs_interface.h>
11 #include <KernelExport.h>
12 
13 #include <vfs.h>
14 
15 #include <AutoDeleter.h>
16 
17 #include "DebugSupport.h"
18 #include "kernel_interface.h"
19 #include "Node.h"
20 #include "Utils.h"
21 #include "Volume.h"
22 
23 
24 /*!	\brief Binds an arbitrary folder to a given path (which must be that of a
25 	folder, too). All requests to the mounted path will be passed to the
26 	corresponding node of the bound (source) filesystem.
27 
28 	TODO: node monitoring!
29 
30 	TODO: path filter, such that /dev can be bind-mounted with only a subset
31 		  of entries
32 */
33 
34 
35 // #pragma mark - helper macros
36 
37 
38 #define FETCH_SOURCE_VOLUME_AND_NODE(volume, nodeID)				\
39 	fs_volume* sourceVolume = volume->SourceFSVolume();				\
40 	if (sourceVolume == NULL)										\
41 		RETURN_ERROR(B_ERROR);										\
42 	vnode* sourceVnode;												\
43 	status_t error = vfs_get_vnode(volume->SourceFSVolume()->id,	\
44 		nodeID, true, &sourceVnode);								\
45 	if (error != B_OK)												\
46 		RETURN_ERROR(error);										\
47 	VnodePutter putter(sourceVnode);								\
48 	fs_vnode* sourceNode = vfs_fsnode_for_vnode(sourceVnode);		\
49 	if (sourceNode == NULL)											\
50 		RETURN_ERROR(B_ERROR);
51 
52 
53 // #pragma mark - Volume
54 
55 
56 static status_t
57 bindfs_mount(fs_volume* fsVolume, const char* device, uint32 flags,
58 	const char* parameters, ino_t* _rootID)
59 {
60 	FUNCTION("fsVolume: %p, device: \"%s\", flags: %#lx, parameters: \"%s\"\n",
61 		fsVolume, device, flags, parameters);
62 
63 	// create a Volume object
64 	Volume* volume = new(std::nothrow) Volume(fsVolume);
65 	if (volume == NULL)
66 		RETURN_ERROR(B_NO_MEMORY);
67 	ObjectDeleter<Volume> volumeDeleter(volume);
68 
69 	status_t error = volume->Mount(parameters);
70 	if (error != B_OK)
71 		return error;
72 
73 	// set return values
74 	*_rootID = volume->RootNode()->ID();
75 	fsVolume->private_volume = volumeDeleter.Detach();
76 	fsVolume->ops = &gBindFSVolumeOps;
77 
78 	return B_OK;
79 }
80 
81 
82 static status_t
83 bindfs_unmount(fs_volume* fsVolume)
84 {
85 	Volume* volume = (Volume*)fsVolume->private_volume;
86 
87 	FUNCTION("volume: %p\n", volume);
88 
89 	volume->Unmount();
90 	delete volume;
91 
92 	return B_OK;
93 }
94 
95 
96 static status_t
97 bindfs_read_fs_info(fs_volume* fsVolume, struct fs_info* info)
98 {
99 	Volume* volume = (Volume*)fsVolume->private_volume;
100 
101 	FUNCTION("volume: %p, info: %p\n", volume, info);
102 
103 	fs_volume* sourceVolume = volume->SourceFSVolume();
104 
105 	if (sourceVolume->ops->read_fs_info != NULL) {
106 		status_t error = sourceVolume->ops->read_fs_info(sourceVolume, info);
107 		if (error != B_OK)
108 			RETURN_ERROR(error);
109 	} else {
110 		info->block_size = 512;
111 		info->io_size = 64 * 1024;
112 	}
113 
114 	info->dev = volume->ID();
115 	info->root = volume->RootNode()->ID();
116 	info->total_blocks = info->free_blocks = 0;
117 	info->total_nodes = info->free_nodes = 0;
118 
119 	strlcpy(info->volume_name, volume->Name(), sizeof(info->volume_name));
120 
121 	return B_OK;
122 }
123 
124 
125 // #pragma mark - VNodes
126 
127 
128 static status_t
129 bindfs_lookup(fs_volume* fsVolume, fs_vnode* fsDir, const char* entryName,
130 	ino_t* _vnid)
131 {
132 	Volume* volume = (Volume*)fsVolume->private_volume;
133 	Node* node = (Node*)fsDir->private_node;
134 
135 	FUNCTION("volume: %p, dir: %p (%lld), entry: \"%s\"\n", volume, node,
136 		node->ID(), entryName);
137 
138 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
139 
140 	error = sourceNode->ops->lookup(sourceVolume, sourceNode, entryName, _vnid);
141 	if (error != B_OK)
142 		RETURN_ERROR(error);
143 
144 	return get_vnode(fsVolume, *_vnid, NULL);
145 }
146 
147 
148 static status_t
149 bindfs_get_vnode(fs_volume* fsVolume, ino_t vnid, fs_vnode* fsNode,
150 	int* _type, uint32* _flags, bool reenter)
151 {
152 	Volume* volume = (Volume*)fsVolume->private_volume;
153 
154 	FUNCTION("volume: %p, vnid: %lld\n", volume, vnid);
155 
156 	FETCH_SOURCE_VOLUME_AND_NODE(volume, vnid);
157 
158 	struct stat st;
159 	error = sourceNode->ops->read_stat(sourceVolume, sourceNode, &st);
160 
161 	Node* node = new(std::nothrow) Node(vnid, st.st_mode);
162 	if (node == NULL)
163 		RETURN_ERROR(B_NO_MEMORY);
164 
165 	fsNode->private_node = node;
166 	fsNode->ops = const_cast<fs_vnode_ops*>(volume->VnodeOps());
167 	*_type = node->Mode() & S_IFMT;
168 	*_flags = 0;
169 
170 	return B_OK;
171 }
172 
173 
174 static status_t
175 bindfs_get_vnode_name(fs_volume* fsVolume, fs_vnode* fsNode, char* buffer,
176 	size_t bufferSize)
177 {
178 	Volume* volume = (Volume*)fsVolume->private_volume;
179 	Node* node = (Node*)fsNode->private_node;
180 
181 	FUNCTION("volume: %p, node: %p\n", volume, node);
182 
183 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
184 
185 	return sourceNode->ops->get_vnode_name(sourceVolume, sourceNode, buffer,
186 		bufferSize);
187 }
188 
189 static status_t
190 bindfs_put_vnode(fs_volume* fsVolume, fs_vnode* fsNode, bool reenter)
191 {
192 	Volume* volume = (Volume*)fsVolume->private_volume;
193 	Node* node = (Node*)fsNode->private_node;
194 
195 	FUNCTION("volume: %p, node: %p\n", volume, node);
196 
197 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
198 
199 	delete node;
200 
201 	return B_OK;
202 }
203 
204 
205 static status_t
206 bindfs_remove_vnode(fs_volume* fsVolume, fs_vnode* fsNode, bool reenter)
207 {
208 	Volume* volume = (Volume*)fsVolume->private_volume;
209 	Node* node = (Node*)fsNode->private_node;
210 
211 	FUNCTION("volume: %p, node: %p\n", volume, node);
212 
213 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
214 
215 	delete node;
216 
217 	return sourceNode->ops->remove_vnode(sourceVolume, sourceNode, reenter);
218 }
219 
220 
221 // #pragma mark - VM access
222 
223 
224 static bool
225 bindfs_can_page(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie)
226 {
227 	Volume* volume = (Volume*)fsVolume->private_volume;
228 	Node* node = (Node*)fsNode->private_node;
229 
230 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume,
231 		node, node->ID(), cookie);
232 
233 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
234 
235 	return sourceNode->ops->can_page(sourceVolume, sourceNode, cookie);
236 }
237 
238 
239 static status_t
240 bindfs_read_pages(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
241 	off_t pos, const iovec* vecs, size_t count, size_t* _numBytes)
242 {
243 	Volume* volume = (Volume*)fsVolume->private_volume;
244 	Node* node = (Node*)fsNode->private_node;
245 
246 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p, pos: %lld, vecs: %p, "
247 			"count: %ld\n",
248 		volume, node, node->ID(), cookie, pos, vecs, count);
249 
250 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
251 
252 	return sourceNode->ops->read_pages(sourceVolume, sourceNode, cookie, pos,
253 		vecs, count, _numBytes);
254 }
255 
256 
257 static status_t
258 bindfs_write_pages(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
259 	off_t pos, const iovec* vecs, size_t count, size_t* _numBytes)
260 {
261 	Volume* volume = (Volume*)fsVolume->private_volume;
262 	Node* node = (Node*)fsNode->private_node;
263 
264 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p, pos: %lld, vecs: %p, "
265 			"count: %ld\n",
266 		volume, node, node->ID(), cookie, pos, vecs, count);
267 
268 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
269 
270 	return sourceNode->ops->write_pages(sourceVolume, sourceNode, cookie, pos,
271 		vecs, count, _numBytes);
272 }
273 
274 
275 // #pragma mark - Request I/O
276 
277 
278 static status_t
279 bindfs_io(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
280 	io_request* request)
281 {
282 	Volume* volume = (Volume*)fsVolume->private_volume;
283 	Node* node = (Node*)fsNode->private_node;
284 
285 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p, request: %p\n", volume,
286 		node, node->ID(), cookie, request);
287 
288 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
289 
290 	return sourceNode->ops->io(sourceVolume, sourceNode, cookie, request);
291 }
292 
293 
294 static status_t
295 bindfs_cancel_io(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
296 	io_request* request)
297 {
298 	Volume* volume = (Volume*)fsVolume->private_volume;
299 	Node* node = (Node*)fsNode->private_node;
300 
301 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p, request: %p\n", volume,
302 		node, node->ID(), cookie, request);
303 
304 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
305 
306 	return sourceNode->ops->cancel_io(sourceVolume, sourceNode, cookie,
307 		request);
308 }
309 
310 
311 // #pragma mark - File Map
312 
313 
314 static status_t
315 bindfs_get_file_map(fs_volume* fsVolume, fs_vnode* fsNode, off_t offset,
316 	size_t size, struct file_io_vec* vecs, size_t* _count)
317 {
318 	Volume* volume = (Volume*)fsVolume->private_volume;
319 	Node* node = (Node*)fsNode->private_node;
320 
321 	FUNCTION("volume: %p, node: %p (%lld), offset: %lld, size: %ld, vecs: %p\n",
322 		volume, node, node->ID(), offset, size, vecs);
323 
324 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
325 
326 	return sourceNode->ops->get_file_map(sourceVolume, sourceNode, offset, size,
327 		vecs, _count);
328 }
329 
330 
331 // #pragma mark - Special
332 
333 
334 static status_t
335 bindfs_ioctl(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, uint32 op,
336 	void* buffer, size_t length)
337 {
338 	Volume* volume = (Volume*)fsVolume->private_volume;
339 	Node* node = (Node*)fsNode->private_node;
340 
341 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p, op: %lx, buffer: %p, "
342 			"length: %ld\n",
343 		volume, node, node->ID(), cookie, op, buffer, length);
344 
345 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
346 
347 	return sourceNode->ops->ioctl(sourceVolume, sourceNode, cookie, op, buffer,
348 		length);
349 }
350 
351 
352 static status_t
353 bindfs_set_flags(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, int flags)
354 {
355 	Volume* volume = (Volume*)fsVolume->private_volume;
356 	Node* node = (Node*)fsNode->private_node;
357 
358 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p, flags: %x\n",
359 		volume, node, node->ID(), cookie, flags);
360 
361 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
362 
363 	return sourceNode->ops->set_flags(sourceVolume, sourceNode, cookie, flags);
364 }
365 
366 
367 static status_t
368 bindfs_select(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie, uint8 event,
369 	selectsync* sync)
370 {
371 	Volume* volume = (Volume*)fsVolume->private_volume;
372 	Node* node = (Node*)fsNode->private_node;
373 
374 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p, event: %x, sync: %p\n",
375 		volume, node, node->ID(), cookie, event, sync);
376 
377 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
378 
379 	return sourceNode->ops->select(sourceVolume, sourceNode, cookie, event,
380 		sync);
381 }
382 
383 
384 static status_t
385 bindfs_deselect(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
386 	uint8 event, selectsync* sync)
387 {
388 	Volume* volume = (Volume*)fsVolume->private_volume;
389 	Node* node = (Node*)fsNode->private_node;
390 
391 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p, event: %x, sync: %p\n",
392 		volume, node, node->ID(), cookie, event, sync);
393 
394 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
395 
396 	return sourceNode->ops->deselect(sourceVolume, sourceNode, cookie, event,
397 		sync);
398 }
399 
400 
401 static status_t
402 bindfs_fsync(fs_volume* fsVolume, fs_vnode* fsNode)
403 {
404 	Volume* volume = (Volume*)fsVolume->private_volume;
405 	Node* node = (Node*)fsNode->private_node;
406 
407 	FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID());
408 
409 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
410 
411 	return sourceNode->ops->fsync(sourceVolume, sourceNode);
412 }
413 
414 
415 // #pragma mark - Nodes
416 
417 
418 static status_t
419 bindfs_read_symlink(fs_volume* fsVolume, fs_vnode* fsNode, char* buffer,
420 	size_t* _bufferSize)
421 {
422 	Volume* volume = (Volume*)fsVolume->private_volume;
423 	Node* node = (Node*)fsNode->private_node;
424 
425 	FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID());
426 
427 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
428 
429 	return sourceNode->ops->read_symlink(sourceVolume, sourceNode, buffer,
430 		_bufferSize);
431 }
432 
433 
434 static status_t
435 bindfs_create_symlink(fs_volume* fsVolume, fs_vnode* fsNode, const char* name,
436 	const char* path, int mode)
437 {
438 	Volume* volume = (Volume*)fsVolume->private_volume;
439 	Node* node = (Node*)fsNode->private_node;
440 
441 	FUNCTION("volume: %p, node: %p (%lld), name: %s, path: %s, mode: %x\n",
442 		volume, node, node->ID(), name, path, mode);
443 
444 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
445 
446 	return sourceNode->ops->create_symlink(sourceVolume, sourceNode, name, path,
447 		mode);
448 }
449 
450 
451 static status_t
452 bindfs_link(fs_volume* fsVolume, fs_vnode* fsNode, const char* name,
453 	fs_vnode* toNode)
454 {
455 	Volume* volume = (Volume*)fsVolume->private_volume;
456 	Node* node = (Node*)fsNode->private_node;
457 
458 	FUNCTION("volume: %p, node: %p (%lld), name: %s, tonode: %p\n",
459 		volume, node, node->ID(), name, toNode);
460 
461 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
462 
463 	return sourceNode->ops->link(sourceVolume, sourceNode, name, toNode);
464 }
465 
466 
467 static status_t
468 bindfs_unlink(fs_volume* fsVolume, fs_vnode* fsNode, const char* name)
469 {
470 	Volume* volume = (Volume*)fsVolume->private_volume;
471 	Node* node = (Node*)fsNode->private_node;
472 
473 	FUNCTION("volume: %p, node: %p (%lld), name: %s\n",
474 		volume, node, node->ID(), name);
475 
476 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
477 
478 	return sourceNode->ops->unlink(sourceVolume, sourceNode, name);
479 }
480 
481 
482 static status_t
483 bindfs_rename(fs_volume* fsVolume, fs_vnode* fsNode, const char* fromName,
484 	fs_vnode* toDir, const char* toName)
485 {
486 	Volume* volume = (Volume*)fsVolume->private_volume;
487 	Node* node = (Node*)fsNode->private_node;
488 
489 	FUNCTION("volume: %p, node: %p (%lld), from: %s, toDir: %p, to: %s\n",
490 		volume, node, node->ID(), fromName, toDir, toName);
491 
492 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
493 
494 	return sourceNode->ops->rename(sourceVolume, sourceNode, fromName, toDir,
495 		toName);
496 }
497 
498 
499 static status_t
500 bindfs_access(fs_volume* fsVolume, fs_vnode* fsNode, int mode)
501 {
502 	Volume* volume = (Volume*)fsVolume->private_volume;
503 	Node* node = (Node*)fsNode->private_node;
504 
505 	FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID());
506 
507 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
508 
509 	return sourceNode->ops->access(sourceVolume, sourceNode, mode);
510 }
511 
512 
513 static status_t
514 bindfs_read_stat(fs_volume* fsVolume, fs_vnode* fsNode, struct stat* st)
515 {
516 	Volume* volume = (Volume*)fsVolume->private_volume;
517 	Node* node = (Node*)fsNode->private_node;
518 
519 	FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID());
520 
521 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
522 
523 	error = sourceNode->ops->read_stat(sourceVolume, sourceNode, st);
524 	if (error != B_OK)
525 		RETURN_ERROR(error);
526 
527 	st->st_dev = volume->ID();
528 
529 	return B_OK;
530 }
531 
532 
533 static status_t
534 bindfs_write_stat(fs_volume* fsVolume, fs_vnode* fsNode,
535 	const struct stat* _st, uint32 statMask)
536 {
537 	Volume* volume = (Volume*)fsVolume->private_volume;
538 	Node* node = (Node*)fsNode->private_node;
539 
540 	FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID());
541 
542 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
543 
544 	struct stat st;
545 	memcpy(&st, _st, sizeof(st));
546 	st.st_dev = sourceVolume->id;
547 
548 	return sourceNode->ops->write_stat(sourceVolume, sourceNode, &st, statMask);
549 }
550 
551 
552 static status_t
553 bindfs_preallocate(fs_volume* fsVolume, fs_vnode* fsNode, off_t pos,
554 	off_t length)
555 {
556 	Volume* volume = (Volume*)fsVolume->private_volume;
557 	Node* node = (Node*)fsNode->private_node;
558 
559 	FUNCTION("volume: %p, node: %p (%lld), pos: %lld, length: %lld\n",
560 		volume, node, node->ID(), pos, length);
561 
562 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
563 
564 	return sourceNode->ops->preallocate(sourceVolume, sourceNode, pos, length);
565 }
566 
567 
568 // #pragma mark - Files
569 
570 
571 static status_t
572 bindfs_create(fs_volume* fsVolume, fs_vnode* fsNode, const char* name,
573 	int openMode, int perms, void** _cookie, ino_t* _newVnodeID)
574 {
575 	Volume* volume = (Volume*)fsVolume->private_volume;
576 	Node* node = (Node*)fsNode->private_node;
577 
578 	FUNCTION("volume: %p, node: %p (%lld), name: %s, openMode %#x, perms: %x\n",
579 		volume, node, node->ID(), name, openMode, perms);
580 
581 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
582 
583 	return sourceNode->ops->create(sourceVolume, sourceNode, name, openMode,
584 		perms, _cookie, _newVnodeID);
585 }
586 
587 
588 static status_t
589 bindfs_open(fs_volume* fsVolume, fs_vnode* fsNode, int openMode,
590 	void** _cookie)
591 {
592 	Volume* volume = (Volume*)fsVolume->private_volume;
593 	Node* node = (Node*)fsNode->private_node;
594 
595 	FUNCTION("volume: %p, node: %p (%lld), openMode %#x\n", volume, node,
596 		node->ID(), openMode);
597 
598 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
599 
600 	return sourceNode->ops->open(sourceVolume, sourceNode, openMode, _cookie);
601 }
602 
603 
604 static status_t
605 bindfs_close(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie)
606 {
607 	Volume* volume = (Volume*)fsVolume->private_volume;
608 	Node* node = (Node*)fsNode->private_node;
609 
610 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
611 		node->ID(), cookie);
612 
613 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
614 
615 	return sourceNode->ops->close(sourceVolume, sourceNode, cookie);
616 }
617 
618 
619 static status_t
620 bindfs_free_cookie(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie)
621 {
622 	Volume* volume = (Volume*)fsVolume->private_volume;
623 	Node* node = (Node*)fsNode->private_node;
624 
625 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
626 		node->ID(), cookie);
627 
628 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
629 
630 	return sourceNode->ops->free_cookie(sourceVolume, sourceNode, cookie);
631 }
632 
633 
634 static status_t
635 bindfs_read(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
636 	off_t offset, void* buffer, size_t* bufferSize)
637 {
638 	Volume* volume = (Volume*)fsVolume->private_volume;
639 	Node* node = (Node*)fsNode->private_node;
640 
641 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p, offset: %lld, "
642 		"buffer: %p, size: %lu\n", volume, node, node->ID(), cookie, offset,
643 		buffer, *bufferSize);
644 
645 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
646 
647 	return sourceNode->ops->read(sourceVolume, sourceNode, cookie, offset,
648 		buffer, bufferSize);
649 }
650 
651 
652 static status_t
653 bindfs_write(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
654 	off_t offset, const void* buffer, size_t* bufferSize)
655 {
656 	Volume* volume = (Volume*)fsVolume->private_volume;
657 	Node* node = (Node*)fsNode->private_node;
658 
659 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p, offset: %lld, "
660 		"buffer: %p, size: %lu\n", volume, node, node->ID(), cookie, offset,
661 		buffer, *bufferSize);
662 
663 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
664 
665 	return sourceNode->ops->write(sourceVolume, sourceNode, cookie, offset,
666 		buffer, bufferSize);
667 }
668 
669 
670 // #pragma mark - Directories
671 
672 
673 static status_t
674 bindfs_create_dir(fs_volume* fsVolume, fs_vnode* fsNode, const char* name,
675 	int perms)
676 {
677 	Volume* volume = (Volume*)fsVolume->private_volume;
678 	Node* node = (Node*)fsNode->private_node;
679 
680 	FUNCTION("volume: %p, node: %p (%lld), name: %s, perms: %x\n", volume, node,
681 		node->ID(), name, perms);
682 
683 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
684 
685 	return sourceNode->ops->create_dir(sourceVolume, sourceNode, name, perms);
686 }
687 
688 
689 static status_t
690 bindfs_remove_dir(fs_volume* fsVolume, fs_vnode* fsNode, const char* name)
691 {
692 	Volume* volume = (Volume*)fsVolume->private_volume;
693 	Node* node = (Node*)fsNode->private_node;
694 
695 	FUNCTION("volume: %p, node: %p (%lld), name: %s\n", volume, node,
696 		node->ID(), name);
697 
698 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
699 
700 	return sourceNode->ops->remove_dir(sourceVolume, sourceNode, name);
701 }
702 
703 
704 static status_t
705 bindfs_open_dir(fs_volume* fsVolume, fs_vnode* fsNode, void** _cookie)
706 {
707 	Volume* volume = (Volume*)fsVolume->private_volume;
708 	Node* node = (Node*)fsNode->private_node;
709 
710 	FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID());
711 
712 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
713 
714 	return sourceNode->ops->open_dir(sourceVolume, sourceNode, _cookie);
715 }
716 
717 
718 static status_t
719 bindfs_close_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie)
720 {
721 	Volume* volume = (Volume*)fsVolume->private_volume;
722 	Node* node = (Node*)fsNode->private_node;
723 
724 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
725 		node->ID(), cookie);
726 
727 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
728 
729 	return sourceNode->ops->close_dir(sourceVolume, sourceNode, cookie);
730 }
731 
732 
733 static status_t
734 bindfs_free_dir_cookie(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie)
735 {
736 	Volume* volume = (Volume*)fsVolume->private_volume;
737 	Node* node = (Node*)fsNode->private_node;
738 
739 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
740 		node->ID(), cookie);
741 
742 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
743 
744 	return sourceNode->ops->free_dir_cookie(sourceVolume, sourceNode, cookie);
745 }
746 
747 
748 static status_t
749 bindfs_read_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
750 	struct dirent* buffer, size_t bufferSize, uint32* _count)
751 {
752 	Volume* volume = (Volume*)fsVolume->private_volume;
753 	Node* node = (Node*)fsNode->private_node;
754 
755 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
756 		node->ID(), cookie);
757 
758 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
759 
760 	return sourceNode->ops->read_dir(sourceVolume, sourceNode, cookie, buffer,
761 		bufferSize, _count);
762 }
763 
764 
765 static status_t
766 bindfs_rewind_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie)
767 {
768 	Volume* volume = (Volume*)fsVolume->private_volume;
769 	Node* node = (Node*)fsNode->private_node;
770 
771 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
772 		node->ID(), cookie);
773 
774 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
775 
776 	return sourceNode->ops->rewind_dir(sourceVolume, sourceNode, cookie);
777 }
778 
779 
780 // #pragma mark - Attribute Directories
781 
782 
783 status_t
784 bindfs_open_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void** _cookie)
785 {
786 	Volume* volume = (Volume*)fsVolume->private_volume;
787 	Node* node = (Node*)fsNode->private_node;
788 
789 	FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID());
790 
791 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
792 
793 	return sourceNode->ops->open_attr_dir(sourceVolume, sourceNode, _cookie);
794 }
795 
796 
797 status_t
798 bindfs_close_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie)
799 {
800 	Volume* volume = (Volume*)fsVolume->private_volume;
801 	Node* node = (Node*)fsNode->private_node;
802 
803 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
804 		node->ID(), cookie);
805 
806 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
807 
808 	return sourceNode->ops->close_attr_dir(sourceVolume, sourceNode, cookie);
809 }
810 
811 
812 status_t
813 bindfs_free_attr_dir_cookie(fs_volume* fsVolume, fs_vnode* fsNode,
814 	void* cookie)
815 {
816 	Volume* volume = (Volume*)fsVolume->private_volume;
817 	Node* node = (Node*)fsNode->private_node;
818 
819 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
820 		node->ID(), cookie);
821 
822 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
823 
824 	return sourceNode->ops->free_attr_dir_cookie(sourceVolume, sourceNode,
825 		cookie);
826 }
827 
828 
829 status_t
830 bindfs_read_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
831 	struct dirent* buffer, size_t bufferSize, uint32* _count)
832 {
833 	Volume* volume = (Volume*)fsVolume->private_volume;
834 	Node* node = (Node*)fsNode->private_node;
835 
836 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
837 		node->ID(), cookie);
838 
839 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
840 
841 	return sourceNode->ops->read_attr_dir(sourceVolume, sourceNode, cookie,
842 		buffer, bufferSize, _count);
843 }
844 
845 
846 status_t
847 bindfs_rewind_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie)
848 {
849 	Volume* volume = (Volume*)fsVolume->private_volume;
850 	Node* node = (Node*)fsNode->private_node;
851 
852 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
853 		node->ID(), cookie);
854 
855 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
856 
857 	return sourceNode->ops->rewind_attr_dir(sourceVolume, sourceNode, cookie);
858 }
859 
860 
861 // #pragma mark - Attribute Operations
862 
863 
864 status_t
865 bindfs_create_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* name,
866 	uint32 type, int openMode, void** _cookie)
867 {
868 	Volume* volume = (Volume*)fsVolume->private_volume;
869 	Node* node = (Node*)fsNode->private_node;
870 
871 	FUNCTION("volume: %p, node: %p (%lld), name: \"%s\", type: %lx, "
872 			"openMode %#x\n",
873 		volume, node, node->ID(), name, type, openMode);
874 
875 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
876 
877 	return sourceNode->ops->create_attr(sourceVolume, sourceNode, name, type,
878 		openMode, _cookie);
879 }
880 
881 
882 status_t
883 bindfs_open_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* name,
884 	int openMode, void** _cookie)
885 {
886 	Volume* volume = (Volume*)fsVolume->private_volume;
887 	Node* node = (Node*)fsNode->private_node;
888 
889 	FUNCTION("volume: %p, node: %p (%lld), name: \"%s\", openMode %#x\n",
890 		volume, node, node->ID(), name, openMode);
891 
892 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
893 
894 	return sourceNode->ops->open_attr(sourceVolume, sourceNode, name, openMode,
895 		_cookie);
896 }
897 
898 
899 status_t
900 bindfs_close_attr(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie)
901 {
902 	Volume* volume = (Volume*)fsVolume->private_volume;
903 	Node* node = (Node*)fsNode->private_node;
904 
905 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
906 		node->ID(), cookie);
907 
908 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
909 
910 	return sourceNode->ops->close_attr(sourceVolume, sourceNode, cookie);
911 }
912 
913 
914 status_t
915 bindfs_free_attr_cookie(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie)
916 {
917 	Volume* volume = (Volume*)fsVolume->private_volume;
918 	Node* node = (Node*)fsNode->private_node;
919 
920 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
921 		node->ID(), cookie);
922 
923 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
924 
925 	return sourceNode->ops->free_attr_cookie(sourceVolume, sourceNode, cookie);
926 }
927 
928 
929 status_t
930 bindfs_read_attr(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
931 	off_t offset, void* buffer, size_t* bufferSize)
932 {
933 	Volume* volume = (Volume*)fsVolume->private_volume;
934 	Node* node = (Node*)fsNode->private_node;
935 
936 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
937 		node->ID(), cookie);
938 
939 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
940 
941 	return sourceNode->ops->read_attr(sourceVolume, sourceNode, cookie, offset,
942 		buffer, bufferSize);
943 }
944 
945 
946 status_t
947 bindfs_write_attr(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
948 	off_t offset, const void* buffer, size_t* bufferSize)
949 {
950 	Volume* volume = (Volume*)fsVolume->private_volume;
951 	Node* node = (Node*)fsNode->private_node;
952 
953 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
954 		node->ID(), cookie);
955 
956 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
957 
958 	return sourceNode->ops->write_attr(sourceVolume, sourceNode, cookie, offset,
959 		buffer, bufferSize);
960 }
961 
962 
963 status_t
964 bindfs_read_attr_stat(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
965 	struct stat* st)
966 {
967 	Volume* volume = (Volume*)fsVolume->private_volume;
968 	Node* node = (Node*)fsNode->private_node;
969 
970 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
971 		node->ID(), cookie);
972 
973 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
974 
975 	error
976 		= sourceNode->ops->read_attr_stat(sourceVolume, sourceNode, cookie, st);
977 	if (error != B_OK)
978 		RETURN_ERROR(error);
979 
980 	st->st_dev = volume->ID();
981 
982 	return B_OK;
983 }
984 
985 
986 status_t
987 bindfs_write_attr_stat(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
988 	const struct stat* _st, int statMask)
989 {
990 	Volume* volume = (Volume*)fsVolume->private_volume;
991 	Node* node = (Node*)fsNode->private_node;
992 
993 	FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
994 		node->ID(), cookie);
995 
996 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
997 
998 	struct stat st;
999 	memcpy(&st, _st, sizeof(st));
1000 	st.st_dev = sourceVolume->id;
1001 
1002 	return sourceNode->ops->write_attr_stat(sourceVolume, sourceNode, cookie,
1003 		&st, statMask);
1004 }
1005 
1006 
1007 static status_t
1008 bindfs_rename_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* fromName,
1009 	fs_vnode* toDir, const char* toName)
1010 {
1011 	Volume* volume = (Volume*)fsVolume->private_volume;
1012 	Node* node = (Node*)fsNode->private_node;
1013 
1014 	FUNCTION("volume: %p, node: %p (%lld), from: %s, toDir: %p, to: %s\n",
1015 		volume, node, node->ID(), fromName, toDir, toName);
1016 
1017 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
1018 
1019 	return sourceNode->ops->rename_attr(sourceVolume, sourceNode, fromName,
1020 		toDir, toName);
1021 }
1022 
1023 
1024 static status_t
1025 bindfs_remove_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* name)
1026 {
1027 	Volume* volume = (Volume*)fsVolume->private_volume;
1028 	Node* node = (Node*)fsNode->private_node;
1029 
1030 	FUNCTION("volume: %p, node: %p (%lld), name: %s\n", volume, node,
1031 		node->ID(), name);
1032 
1033 	FETCH_SOURCE_VOLUME_AND_NODE(volume, node->ID());
1034 
1035 	return sourceNode->ops->remove_attr(sourceVolume, sourceNode, name);
1036 }
1037 
1038 
1039 // #pragma mark - Module Interface
1040 
1041 
1042 static status_t
1043 bindfs_std_ops(int32 op, ...)
1044 {
1045 	switch (op) {
1046 		case B_MODULE_INIT:
1047 		{
1048 			init_debugging();
1049 			PRINT("bindfs_std_ops(): B_MODULE_INIT\n");
1050 
1051 			return B_OK;
1052 		}
1053 
1054 		case B_MODULE_UNINIT:
1055 		{
1056 			PRINT("bind_std_ops(): B_MODULE_UNINIT\n");
1057 			exit_debugging();
1058 			return B_OK;
1059 		}
1060 
1061 		default:
1062 			return B_ERROR;
1063 	}
1064 }
1065 
1066 
1067 static file_system_module_info sBindFSModuleInfo = {
1068 	{
1069 		"file_systems/bindfs" B_CURRENT_FS_API_VERSION,
1070 		0,
1071 		bindfs_std_ops,
1072 	},
1073 
1074 	"bindfs",				// short_name
1075 	"Bind File System",		// pretty_name
1076 	0,						// DDM flags
1077 
1078 
1079 	// scanning
1080 	NULL,	// identify_partition,
1081 	NULL,	// scan_partition,
1082 	NULL,	// free_identify_partition_cookie,
1083 	NULL,	// free_partition_content_cookie()
1084 
1085 	&bindfs_mount
1086 };
1087 
1088 
1089 fs_volume_ops gBindFSVolumeOps = {
1090 	&bindfs_unmount,
1091 	&bindfs_read_fs_info,
1092 	NULL,	// write_fs_info,
1093 	NULL,	// sync,
1094 
1095 	&bindfs_get_vnode
1096 
1097 	// TODO: index operations
1098 	// TODO: query operations
1099 	// TODO: FS layer operations
1100 };
1101 
1102 
1103 fs_vnode_ops gBindFSVnodeOps = {
1104 	// vnode operations
1105 	&bindfs_lookup,
1106 	&bindfs_get_vnode_name,
1107 	&bindfs_put_vnode,
1108 	&bindfs_remove_vnode,
1109 
1110 	// VM file access
1111 	&bindfs_can_page,
1112 	&bindfs_read_pages,
1113 	&bindfs_write_pages,
1114 
1115 	&bindfs_io,
1116 	&bindfs_cancel_io,
1117 
1118 	&bindfs_get_file_map,
1119 
1120 	&bindfs_ioctl,
1121 	&bindfs_set_flags,
1122 	&bindfs_select,
1123 	&bindfs_deselect,
1124 	&bindfs_fsync,
1125 
1126 	&bindfs_read_symlink,
1127 	&bindfs_create_symlink,
1128 
1129 	&bindfs_link,
1130 	&bindfs_unlink,
1131 	&bindfs_rename,
1132 
1133 	&bindfs_access,
1134 	&bindfs_read_stat,
1135 	&bindfs_write_stat,
1136 	&bindfs_preallocate,
1137 
1138 	// file operations
1139 	&bindfs_create,
1140 	&bindfs_open,
1141 	&bindfs_close,
1142 	&bindfs_free_cookie,
1143 	&bindfs_read,
1144 	&bindfs_write,
1145 
1146 	// directory operations
1147 	&bindfs_create_dir,
1148 	&bindfs_remove_dir,
1149 	&bindfs_open_dir,
1150 	&bindfs_close_dir,
1151 	&bindfs_free_dir_cookie,
1152 	&bindfs_read_dir,
1153 	&bindfs_rewind_dir,
1154 
1155 	// attribute directory operations
1156 	&bindfs_open_attr_dir,
1157 	&bindfs_close_attr_dir,
1158 	&bindfs_free_attr_dir_cookie,
1159 	&bindfs_read_attr_dir,
1160 	&bindfs_rewind_attr_dir,
1161 
1162 	// attribute operations
1163 	&bindfs_create_attr,
1164 	&bindfs_open_attr,
1165 	&bindfs_close_attr,
1166 	&bindfs_free_attr_cookie,
1167 	&bindfs_read_attr,
1168 	&bindfs_write_attr,
1169 
1170 	&bindfs_read_attr_stat,
1171 	&bindfs_write_attr_stat,
1172 	&bindfs_rename_attr,
1173 	&bindfs_remove_attr,
1174 
1175 	// TODO: FS layer operations
1176 };
1177 
1178 
1179 module_info *modules[] = {
1180 	(module_info *)&sBindFSModuleInfo,
1181 	NULL,
1182 };
1183