xref: /haiku/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/KernelRequestHandler.cpp (revision 23f179da55b1bd1ba84fbf3d3c56947e2c8d0aca)
1 /*
2  * Copyright 2001-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include "Compatibility.h"
7 #include "Debug.h"
8 #include "FileSystem.h"
9 #include "KernelRequestHandler.h"
10 #include "RequestPort.h"
11 #include "Requests.h"
12 #include "SingleReplyRequestHandler.h"
13 #include "Volume.h"
14 
15 #include <NodeMonitor.h>
16 
17 #include <AutoDeleter.h>
18 
19 
20 // VolumePutter
21 class VolumePutter {
22 public:
23 	VolumePutter(Volume* volume) : fVolume(volume) {}
24 	~VolumePutter()
25 	{
26 		if (fVolume)
27 			fVolume->RemoveReference();
28 	}
29 
30 private:
31 	Volume	*fVolume;
32 };
33 
34 // constructor
35 KernelRequestHandler::KernelRequestHandler(Volume* volume, uint32 expectedReply)
36 	: RequestHandler(),
37 	  fFileSystem(volume->GetFileSystem()),
38 	  fVolume(volume),
39 	  fExpectedReply(expectedReply)
40 {
41 }
42 
43 // constructor
44 KernelRequestHandler::KernelRequestHandler(FileSystem* fileSystem,
45 	uint32 expectedReply)
46 	: RequestHandler(),
47 	  fFileSystem(fileSystem),
48 	  fVolume(NULL),
49 	  fExpectedReply(expectedReply)
50 {
51 }
52 
53 // destructor
54 KernelRequestHandler::~KernelRequestHandler()
55 {
56 }
57 
58 // HandleRequest
59 status_t
60 KernelRequestHandler::HandleRequest(Request* request)
61 {
62 	if (request->GetType() == fExpectedReply) {
63 		fDone = true;
64 		return B_OK;
65 	}
66 	switch (request->GetType()) {
67 		// notifications
68 		case NOTIFY_LISTENER_REQUEST:
69 			return _HandleRequest((NotifyListenerRequest*)request);
70 		case NOTIFY_SELECT_EVENT_REQUEST:
71 			return _HandleRequest((NotifySelectEventRequest*)request);
72 		case NOTIFY_QUERY_REQUEST:
73 			return _HandleRequest((NotifyQueryRequest*)request);
74 		// vnodes
75 		case GET_VNODE_REQUEST:
76 			return _HandleRequest((GetVNodeRequest*)request);
77 		case PUT_VNODE_REQUEST:
78 			return _HandleRequest((PutVNodeRequest*)request);
79 		case ACQUIRE_VNODE_REQUEST:
80 			return _HandleRequest((AcquireVNodeRequest*)request);
81 		case NEW_VNODE_REQUEST:
82 			return _HandleRequest((NewVNodeRequest*)request);
83 		case PUBLISH_VNODE_REQUEST:
84 			return _HandleRequest((PublishVNodeRequest*)request);
85 		case REMOVE_VNODE_REQUEST:
86 			return _HandleRequest((RemoveVNodeRequest*)request);
87 		case UNREMOVE_VNODE_REQUEST:
88 			return _HandleRequest((UnremoveVNodeRequest*)request);
89 		case GET_VNODE_REMOVED_REQUEST:
90 			return _HandleRequest((GetVNodeRemovedRequest*)request);
91 		// file cache
92 		case FILE_CACHE_CREATE_REQUEST:
93 			return _HandleRequest((FileCacheCreateRequest*)request);
94 		case FILE_CACHE_DELETE_REQUEST:
95 			return _HandleRequest((FileCacheDeleteRequest*)request);
96 		case FILE_CACHE_SET_ENABLED_REQUEST:
97 			return _HandleRequest((FileCacheSetEnabledRequest*)request);
98 		case FILE_CACHE_SET_SIZE_REQUEST:
99 			return _HandleRequest((FileCacheSetSizeRequest*)request);
100 		case FILE_CACHE_SYNC_REQUEST:
101 			return _HandleRequest((FileCacheSyncRequest*)request);
102 		case FILE_CACHE_READ_REQUEST:
103 			return _HandleRequest((FileCacheReadRequest*)request);
104 		case FILE_CACHE_WRITE_REQUEST:
105 			return _HandleRequest((FileCacheWriteRequest*)request);
106 		// I/O
107 		case DO_ITERATIVE_FD_IO_REQUEST:
108 			return _HandleRequest((DoIterativeFDIORequest*)request);
109 		case READ_FROM_IO_REQUEST_REQUEST:
110 			return _HandleRequest((ReadFromIORequestRequest*)request);
111 		case WRITE_TO_IO_REQUEST_REQUEST:
112 			return _HandleRequest((WriteToIORequestRequest*)request);
113 		case NOTIFY_IO_REQUEST_REQUEST:
114 			return _HandleRequest((NotifyIORequestRequest*)request);
115 		// node monitoring
116 		case ADD_NODE_LISTENER_REQUEST:
117 			return _HandleRequest((AddNodeListenerRequest*)request);
118 		case REMOVE_NODE_LISTENER_REQUEST:
119 			return _HandleRequest((RemoveNodeListenerRequest*)request);
120 	}
121 PRINT(("KernelRequestHandler::HandleRequest(): unexpected request: %lu\n",
122 request->GetType()));
123 	return B_BAD_DATA;
124 }
125 
126 // #pragma mark -
127 // #pragma mark ----- notifications -----
128 
129 // _HandleRequest
130 status_t
131 KernelRequestHandler::_HandleRequest(NotifyListenerRequest* request)
132 {
133 	// check and execute the request
134 	status_t result = B_OK;
135 	if (fVolume && request->device != fVolume->GetID())
136 		result = B_BAD_VALUE;
137 
138 	// get the names
139 	// name
140 	char* name = (char*)request->name.GetData();
141 	int32 nameLen = request->name.GetSize();
142 	if (name && (nameLen <= 0))
143 		name = NULL;
144 	else if (name)
145 		name[nameLen - 1] = '\0';	// NULL-terminate to be safe
146 
147 	// old name
148 	char* oldName = (char*)request->oldName.GetData();
149 	int32 oldNameLen = request->oldName.GetSize();
150 	if (oldName && (oldNameLen <= 0))
151 		oldName = NULL;
152 	else if (oldName)
153 		oldName[oldNameLen - 1] = '\0';	// NULL-terminate to be safe
154 
155 	// check the names
156 	if (result == B_OK) {
157 		switch (request->operation) {
158 			case B_ENTRY_MOVED:
159 				if (!oldName) {
160 					ERROR(("NotifyListenerRequest: NULL oldName for "
161 						"B_ENTRY_MOVED\n"));
162 					result = B_BAD_VALUE;
163 					break;
164 				}
165 				// fall through...
166 			case B_ENTRY_CREATED:
167 			case B_ENTRY_REMOVED:
168 			case B_ATTR_CHANGED:
169 				if (!name) {
170 					ERROR(("NotifyListenerRequest: NULL name for opcode: %ld\n",
171 						request->operation));
172 					result = B_BAD_VALUE;
173 				}
174 				break;
175 			case B_STAT_CHANGED:
176 				break;
177 		}
178 	}
179 
180 	// execute the request
181 	if (result == B_OK) {
182 		switch (request->operation) {
183 			case B_ENTRY_CREATED:
184 				PRINT(("notify_entry_created(%ld, %lld, \"%s\", %lld)\n",
185 					request->device, request->directory, name, request->node));
186 				result = notify_entry_created(request->device,
187 					request->directory, name, request->node);
188 				break;
189 
190 			case B_ENTRY_REMOVED:
191 				PRINT(("notify_entry_removed(%ld, %lld, \"%s\", %lld)\n",
192 					request->device, request->directory, name, request->node));
193 				result = notify_entry_removed(request->device,
194 					request->directory, name, request->node);
195 				break;
196 
197 			case B_ENTRY_MOVED:
198 				PRINT(("notify_entry_moved(%ld, %lld, \"%s\", %lld, \"%s\", "
199 					"%lld)\n", request->device, request->oldDirectory, oldName,
200 					request->directory, name, request->node));
201 				result = notify_entry_moved(request->device,
202 					request->oldDirectory, oldName, request->directory, name,
203 					request->node);
204 				break;
205 
206 			case B_STAT_CHANGED:
207 				PRINT(("notify_stat_changed(%ld, %lld, 0x%lx)\n",
208 					request->device, request->node, request->details));
209 				result = notify_stat_changed(request->device, request->node,
210 					request->details);
211 				break;
212 
213 			case B_ATTR_CHANGED:
214 				PRINT(("notify_attribute_changed(%ld, %lld, \"%s\", 0x%lx)\n",
215 					request->device, request->node, name,
216 					(int32)request->details));
217 				result = notify_attribute_changed(request->device,
218 					request->node, name, (int32)request->details);
219 				break;
220 
221 			default:
222 				ERROR(("NotifyQueryRequest: unsupported operation: %ld\n",
223 					request->operation));
224 				result = B_BAD_VALUE;
225 				break;
226 		}
227 	}
228 
229 	// prepare the reply
230 	RequestAllocator allocator(fPort->GetPort());
231 	NotifyListenerReply* reply;
232 	status_t error = AllocateRequest(allocator, &reply);
233 	if (error != B_OK)
234 		return error;
235 
236 	reply->error = result;
237 
238 	// send the reply
239 	return fPort->SendRequest(&allocator);
240 }
241 
242 // _HandleRequest
243 status_t
244 KernelRequestHandler::_HandleRequest(NotifySelectEventRequest* request)
245 {
246 	// check and execute the request
247 	status_t result = B_OK;
248 	if (fFileSystem->KnowsSelectSyncEntry(request->sync)) {
249 		if (request->unspecifiedEvent) {
250 			// old style add-ons can't provide an event argument; we shoot
251 			// all events
252 			notify_select_event(request->sync, B_SELECT_READ);
253 			notify_select_event(request->sync, B_SELECT_WRITE);
254 			notify_select_event(request->sync, B_SELECT_ERROR);
255 		} else {
256 			PRINT(("notify_select_event(%p, %d)\n", request->sync,
257 				(int)request->event));
258 			notify_select_event(request->sync, request->event);
259 		}
260 	} else
261 		result = B_BAD_VALUE;
262 
263 	// prepare the reply
264 	RequestAllocator allocator(fPort->GetPort());
265 	NotifySelectEventReply* reply;
266 	status_t error = AllocateRequest(allocator, &reply);
267 	if (error != B_OK)
268 		return error;
269 
270 	reply->error = result;
271 
272 	// send the reply
273 	return fPort->SendRequest(&allocator);
274 }
275 
276 // _HandleRequest
277 status_t
278 KernelRequestHandler::_HandleRequest(NotifyQueryRequest* request)
279 {
280 	// check and execute the request
281 	status_t result = B_OK;
282 	if (fVolume && request->device != fVolume->GetID())
283 		result = B_BAD_VALUE;
284 
285 	// check the name
286 	char* name = (char*)request->name.GetData();
287 	int32 nameLen = request->name.GetSize();
288 	if (!name || nameLen <= 0) {
289 		ERROR(("NotifyQueryRequest: NULL name!\n"));
290 		result = B_BAD_VALUE;
291 	} else
292 		name[nameLen - 1] = '\0';	// NULL-terminate to be safe
293 
294 	// execute the request
295 	if (result == B_OK) {
296 		switch (request->operation) {
297 			case B_ENTRY_CREATED:
298 				PRINT(("notify_query_entry_created(%ld, %ld, %ld, %lld,"
299 					" \"%s\", %lld)\n", request->port, request->token,
300 					request->device, request->directory, name, request->node));
301 				result = notify_query_entry_created(request->port,
302 					request->token, request->device, request->directory, name,
303 					request->node);
304 				break;
305 
306 			case B_ENTRY_REMOVED:
307 				PRINT(("notify_query_entry_removed(%ld, %ld, %ld, %lld,"
308 					" \"%s\", %lld)\n", request->port, request->token,
309 					request->device, request->directory, name, request->node));
310 				result = notify_query_entry_removed(request->port,
311 					request->token, request->device, request->directory, name,
312 					request->node);
313 				break;
314 
315 			case B_ENTRY_MOVED:
316 			default:
317 				ERROR(("NotifyQueryRequest: unsupported operation: %ld\n",
318 					request->operation));
319 				result = B_BAD_VALUE;
320 				break;
321 		}
322 	}
323 
324 	// prepare the reply
325 	RequestAllocator allocator(fPort->GetPort());
326 	NotifyQueryReply* reply;
327 	status_t error = AllocateRequest(allocator, &reply);
328 	if (error != B_OK)
329 		return error;
330 
331 	reply->error = result;
332 
333 	// send the reply
334 	return fPort->SendRequest(&allocator);
335 }
336 
337 // #pragma mark -
338 // #pragma mark ----- vnodes -----
339 
340 // _HandleRequest
341 status_t
342 KernelRequestHandler::_HandleRequest(GetVNodeRequest* request)
343 {
344 	// check and execute the request
345 	Volume* volume = NULL;
346 	status_t result = _GetVolume(request->nsid, &volume);
347 	VolumePutter _(volume);
348 	void* node;
349 	if (result == B_OK)
350 		result = volume->GetVNode(request->vnid, &node);
351 	// prepare the reply
352 	RequestAllocator allocator(fPort->GetPort());
353 	GetVNodeReply* reply;
354 	status_t error = AllocateRequest(allocator, &reply);
355 	if (error != B_OK)
356 		return error;
357 	reply->error = result;
358 	reply->node = node;
359 	// send the reply
360 	return fPort->SendRequest(&allocator);
361 }
362 
363 // _HandleRequest
364 status_t
365 KernelRequestHandler::_HandleRequest(PutVNodeRequest* request)
366 {
367 	// check and execute the request
368 	Volume* volume = NULL;
369 	status_t result = _GetVolume(request->nsid, &volume);
370 	VolumePutter _(volume);
371 	if (result == B_OK)
372 		result = volume->PutVNode(request->vnid);
373 	// prepare the reply
374 	RequestAllocator allocator(fPort->GetPort());
375 	PutVNodeReply* reply;
376 	status_t error = AllocateRequest(allocator, &reply);
377 	if (error != B_OK)
378 		return error;
379 	reply->error = result;
380 	// send the reply
381 	return fPort->SendRequest(&allocator);
382 }
383 
384 
385 // _HandleRequest
386 status_t
387 KernelRequestHandler::_HandleRequest(AcquireVNodeRequest* request)
388 {
389 	// check and execute the request
390 	Volume* volume = NULL;
391 	status_t result = _GetVolume(request->nsid, &volume);
392 	VolumePutter _(volume);
393 	if (result == B_OK)
394 		result = volume->AcquireVNode(request->vnid);
395 
396 	// prepare the reply
397 	RequestAllocator allocator(fPort->GetPort());
398 	AcquireVNodeReply* reply;
399 	status_t error = AllocateRequest(allocator, &reply);
400 	if (error != B_OK)
401 		return error;
402 	reply->error = result;
403 
404 	// send the reply
405 	return fPort->SendRequest(&allocator);
406 }
407 
408 
409 // _HandleRequest
410 status_t
411 KernelRequestHandler::_HandleRequest(NewVNodeRequest* request)
412 {
413 	// check and execute the request
414 	Volume* volume = NULL;
415 	status_t result = _GetVolume(request->nsid, &volume);
416 	VolumePutter _(volume);
417 	if (result == B_OK) {
418 		result = volume->NewVNode(request->vnid, request->node,
419 			request->capabilities);
420 	}
421 
422 	// prepare the reply
423 	RequestAllocator allocator(fPort->GetPort());
424 	NewVNodeReply* reply;
425 	status_t error = AllocateRequest(allocator, &reply);
426 	if (error != B_OK)
427 		return error;
428 	reply->error = result;
429 
430 	// send the reply
431 	return fPort->SendRequest(&allocator);
432 }
433 
434 // _HandleRequest
435 status_t
436 KernelRequestHandler::_HandleRequest(PublishVNodeRequest* request)
437 {
438 	// check and execute the request
439 	Volume* volume = NULL;
440 	status_t result = _GetVolume(request->nsid, &volume);
441 	VolumePutter _(volume);
442 	if (result == B_OK) {
443 		result = volume->PublishVNode(request->vnid, request->node,
444 			request->type, request->flags, request->capabilities);
445 	}
446 
447 	// prepare the reply
448 	RequestAllocator allocator(fPort->GetPort());
449 	PublishVNodeReply* reply;
450 	status_t error = AllocateRequest(allocator, &reply);
451 	if (error != B_OK)
452 		return error;
453 
454 	reply->error = result;
455 
456 	// send the reply
457 	return fPort->SendRequest(&allocator);
458 }
459 
460 // _HandleRequest
461 status_t
462 KernelRequestHandler::_HandleRequest(RemoveVNodeRequest* request)
463 {
464 	// check and execute the request
465 	Volume* volume = NULL;
466 	status_t result = _GetVolume(request->nsid, &volume);
467 	VolumePutter _(volume);
468 	if (result == B_OK)
469 		result = volume->RemoveVNode(request->vnid);
470 	// prepare the reply
471 	RequestAllocator allocator(fPort->GetPort());
472 	RemoveVNodeReply* reply;
473 	status_t error = AllocateRequest(allocator, &reply);
474 	if (error != B_OK)
475 		return error;
476 	reply->error = result;
477 	// send the reply
478 	return fPort->SendRequest(&allocator);
479 }
480 
481 // _HandleRequest
482 status_t
483 KernelRequestHandler::_HandleRequest(UnremoveVNodeRequest* request)
484 {
485 	// check and execute the request
486 	Volume* volume = NULL;
487 	status_t result = _GetVolume(request->nsid, &volume);
488 	VolumePutter _(volume);
489 	if (result == B_OK)
490 		result = volume->UnremoveVNode(request->vnid);
491 	// prepare the reply
492 	RequestAllocator allocator(fPort->GetPort());
493 	UnremoveVNodeReply* reply;
494 	status_t error = AllocateRequest(allocator, &reply);
495 	if (error != B_OK)
496 		return error;
497 	reply->error = result;
498 	// send the reply
499 	return fPort->SendRequest(&allocator);
500 }
501 
502 // _HandleRequest
503 status_t
504 KernelRequestHandler::_HandleRequest(GetVNodeRemovedRequest* request)
505 {
506 	// check and execute the request
507 	Volume* volume = NULL;
508 	status_t result = _GetVolume(request->nsid, &volume);
509 	VolumePutter _(volume);
510 	bool removed = false;
511 	if (result == B_OK)
512 		result = volume->GetVNodeRemoved(request->vnid, &removed);
513 
514 	// prepare the reply
515 	RequestAllocator allocator(fPort->GetPort());
516 	GetVNodeRemovedReply* reply;
517 	status_t error = AllocateRequest(allocator, &reply);
518 	if (error != B_OK)
519 		return error;
520 
521 	reply->error = result;
522 	reply->removed = removed;
523 
524 	// send the reply
525 	return fPort->SendRequest(&allocator);
526 }
527 
528 
529 // _HandleRequest
530 status_t
531 KernelRequestHandler::_HandleRequest(FileCacheCreateRequest* request)
532 {
533 	// check and execute the request
534 	Volume* volume = NULL;
535 	status_t result = _GetVolume(request->nsid, &volume);
536 	VolumePutter _(volume);
537 
538 	if (result == B_OK)
539 		result = volume->CreateFileCache(request->vnid, request->size);
540 
541 	// prepare the reply
542 	RequestAllocator allocator(fPort->GetPort());
543 	FileCacheCreateReply* reply;
544 	status_t error = AllocateRequest(allocator, &reply);
545 	if (error != B_OK)
546 		return error;
547 	reply->error = result;
548 
549 	// send the reply
550 	return fPort->SendRequest(&allocator);
551 }
552 
553 
554 // _HandleRequest
555 status_t
556 KernelRequestHandler::_HandleRequest(FileCacheDeleteRequest* request)
557 {
558 	// check and execute the request
559 	Volume* volume = NULL;
560 	status_t result = _GetVolume(request->nsid, &volume);
561 	VolumePutter _(volume);
562 
563 	if (result == B_OK)
564 		result = volume->DeleteFileCache(request->vnid);
565 
566 	// prepare the reply
567 	RequestAllocator allocator(fPort->GetPort());
568 	FileCacheDeleteReply* reply;
569 	status_t error = AllocateRequest(allocator, &reply);
570 	if (error != B_OK)
571 		return error;
572 	reply->error = result;
573 
574 	// send the reply
575 	return fPort->SendRequest(&allocator);
576 }
577 
578 
579 // _HandleRequest
580 status_t
581 KernelRequestHandler::_HandleRequest(FileCacheSetEnabledRequest* request)
582 {
583 	// check and execute the request
584 	Volume* volume = NULL;
585 	status_t result = _GetVolume(request->nsid, &volume);
586 	VolumePutter _(volume);
587 
588 	if (result == B_OK)
589 		result = volume->SetFileCacheEnabled(request->vnid, request->enabled);
590 
591 	// prepare the reply
592 	RequestAllocator allocator(fPort->GetPort());
593 	FileCacheSetEnabledReply* reply;
594 	status_t error = AllocateRequest(allocator, &reply);
595 	if (error != B_OK)
596 		return error;
597 	reply->error = result;
598 
599 	// send the reply
600 	return fPort->SendRequest(&allocator);
601 }
602 
603 
604 // _HandleRequest
605 status_t
606 KernelRequestHandler::_HandleRequest(FileCacheSetSizeRequest* request)
607 {
608 	// check and execute the request
609 	Volume* volume = NULL;
610 	status_t result = _GetVolume(request->nsid, &volume);
611 	VolumePutter _(volume);
612 
613 	if (result == B_OK)
614 		result = volume->SetFileCacheSize(request->vnid, request->size);
615 
616 	// prepare the reply
617 	RequestAllocator allocator(fPort->GetPort());
618 	FileCacheSetSizeReply* reply;
619 	status_t error = AllocateRequest(allocator, &reply);
620 	if (error != B_OK)
621 		return error;
622 	reply->error = result;
623 
624 	// send the reply
625 	return fPort->SendRequest(&allocator);
626 }
627 
628 
629 // _HandleRequest
630 status_t
631 KernelRequestHandler::_HandleRequest(FileCacheSyncRequest* request)
632 {
633 	// check and execute the request
634 	Volume* volume = NULL;
635 	status_t result = _GetVolume(request->nsid, &volume);
636 	VolumePutter _(volume);
637 
638 	if (result == B_OK)
639 		result = volume->SyncFileCache(request->vnid);
640 
641 	// prepare the reply
642 	RequestAllocator allocator(fPort->GetPort());
643 	FileCacheSyncReply* reply;
644 	status_t error = AllocateRequest(allocator, &reply);
645 	if (error != B_OK)
646 		return error;
647 	reply->error = result;
648 
649 	// send the reply
650 	return fPort->SendRequest(&allocator);
651 }
652 
653 
654 // _HandleRequest
655 status_t
656 KernelRequestHandler::_HandleRequest(FileCacheReadRequest* request)
657 {
658 	// check the request
659 	Volume* volume = NULL;
660 	status_t result = _GetVolume(request->nsid, &volume);
661 	VolumePutter _(volume);
662 
663 	size_t size = request->size;
664 
665 	// allocate the reply
666 	RequestAllocator allocator(fPort->GetPort());
667 	FileCacheReadReply* reply;
668 	status_t error = AllocateRequest(allocator, &reply);
669 	if (error != B_OK)
670 		RETURN_ERROR(error);
671 
672 	void* buffer;
673 	if (result == B_OK) {
674 		result = allocator.AllocateAddress(reply->buffer, size, 1, &buffer,
675 			true);
676 	}
677 
678 	// execute the request
679 	if (result == B_OK) {
680 		result = volume->ReadFileCache(request->vnid, request->cookie,
681 			request->pos, buffer, &size);
682 	}
683 
684 	// prepare the reply
685 	reply->error = result;
686 	reply->bytesRead = size;
687 
688 	// send the reply
689 	if (reply->error == B_OK && reply->bytesRead > 0) {
690 		SingleReplyRequestHandler handler(RECEIPT_ACK_REPLY);
691 		return fPort->SendRequest(&allocator, &handler);
692 	}
693 
694 	return fPort->SendRequest(&allocator);
695 }
696 
697 
698 // _HandleRequest
699 status_t
700 KernelRequestHandler::_HandleRequest(FileCacheWriteRequest* request)
701 {
702 	// check and execute the request
703 	Volume* volume = NULL;
704 	status_t result = _GetVolume(request->nsid, &volume);
705 	VolumePutter _(volume);
706 
707 	size_t size = 0;
708 	if (result == B_OK) {
709 		size = request->buffer.GetSize();
710 		result = volume->WriteFileCache(request->vnid, request->cookie,
711 			request->pos, request->buffer.GetData(), &size);
712 	}
713 
714 	// prepare the reply
715 	RequestAllocator allocator(fPort->GetPort());
716 	FileCacheWriteReply* reply;
717 	status_t error = AllocateRequest(allocator, &reply);
718 	if (error != B_OK)
719 		return error;
720 	reply->error = result;
721 	reply->bytesWritten = size;
722 
723 	// send the reply
724 	return fPort->SendRequest(&allocator);
725 }
726 
727 
728 // _HandleRequest
729 status_t
730 KernelRequestHandler::_HandleRequest(DoIterativeFDIORequest* request)
731 {
732 	// check and execute the request
733 	Volume* volume = NULL;
734 	status_t result = _GetVolume(request->nsid, &volume);
735 	VolumePutter _(volume);
736 
737 	uint32 vecCount = request->vecCount;
738 	if (result == B_OK && vecCount > DoIterativeFDIORequest::MAX_VECS)
739 		result = B_BAD_VALUE;
740 
741 	if (result == B_OK) {
742 		result = volume->DoIterativeFDIO(request->fd, request->request,
743 			request->cookie, request->vecs, vecCount);
744 	}
745 
746 	// prepare the reply
747 	RequestAllocator allocator(fPort->GetPort());
748 	DoIterativeFDIOReply* reply;
749 	status_t error = AllocateRequest(allocator, &reply);
750 	if (error != B_OK)
751 		return error;
752 	reply->error = result;
753 
754 	// send the reply
755 	return fPort->SendRequest(&allocator);
756 }
757 
758 
759 status_t
760 KernelRequestHandler::_HandleRequest(ReadFromIORequestRequest* request)
761 {
762 	// check the request
763 	Volume* volume = NULL;
764 	status_t result = _GetVolume(request->nsid, &volume);
765 	VolumePutter _(volume);
766 
767 	size_t size = request->size;
768 
769 	// allocate the reply
770 	RequestAllocator allocator(fPort->GetPort());
771 	ReadFromIORequestReply* reply;
772 	status_t error = AllocateRequest(allocator, &reply);
773 	if (error != B_OK)
774 		RETURN_ERROR(error);
775 
776 	void* buffer;
777 	if (result == B_OK) {
778 		result = allocator.AllocateAddress(reply->buffer, size, 1, &buffer,
779 			true);
780 	}
781 
782 	// execute the request
783 	if (result == B_OK)
784 		result = volume->ReadFromIORequest(request->request, buffer, size);
785 
786 	// prepare the reply
787 	reply->error = result;
788 
789 	// send the reply
790 	if (reply->error == B_OK && size > 0) {
791 		SingleReplyRequestHandler handler(RECEIPT_ACK_REPLY);
792 		return fPort->SendRequest(&allocator, &handler);
793 	}
794 
795 	return fPort->SendRequest(&allocator);
796 }
797 
798 
799 status_t
800 KernelRequestHandler::_HandleRequest(WriteToIORequestRequest* request)
801 {
802 	// check and execute the request
803 	Volume* volume = NULL;
804 	status_t result = _GetVolume(request->nsid, &volume);
805 	VolumePutter _(volume);
806 
807 	if (result == B_OK) {
808 		result = volume->WriteToIORequest(request->request,
809 			request->buffer.GetData(), request->buffer.GetSize());
810 	}
811 
812 	// prepare the reply
813 	RequestAllocator allocator(fPort->GetPort());
814 	WriteToIORequestReply* reply;
815 	status_t error = AllocateRequest(allocator, &reply);
816 	if (error != B_OK)
817 		return error;
818 	reply->error = result;
819 
820 	// send the reply
821 	return fPort->SendRequest(&allocator);
822 }
823 
824 
825 // _HandleRequest
826 status_t
827 KernelRequestHandler::_HandleRequest(NotifyIORequestRequest* request)
828 {
829 	// check and execute the request
830 	Volume* volume = NULL;
831 	status_t result = _GetVolume(request->nsid, &volume);
832 	VolumePutter _(volume);
833 
834 	if (result == B_OK)
835 		result = volume->NotifyIORequest(request->request, request->status);
836 
837 	// prepare the reply
838 	RequestAllocator allocator(fPort->GetPort());
839 	NotifyIORequestReply* reply;
840 	status_t error = AllocateRequest(allocator, &reply);
841 	if (error != B_OK)
842 		return error;
843 	reply->error = result;
844 
845 	// send the reply
846 	return fPort->SendRequest(&allocator);
847 }
848 
849 
850 status_t
851 KernelRequestHandler::_HandleRequest(AddNodeListenerRequest* request)
852 {
853 	// check and execute the request
854 	status_t result = fFileSystem->AddNodeListener(request->device,
855 		request->node, request->flags, request->listener);
856 
857 	// prepare the reply
858 	RequestAllocator allocator(fPort->GetPort());
859 	AddNodeListenerReply* reply;
860 	status_t error = AllocateRequest(allocator, &reply);
861 	if (error != B_OK)
862 		return error;
863 
864 	reply->error = result;
865 
866 	// send the reply
867 	return fPort->SendRequest(&allocator);
868 }
869 
870 
871 status_t
872 KernelRequestHandler::_HandleRequest(RemoveNodeListenerRequest* request)
873 {
874 	// check and execute the request
875 	status_t result = fFileSystem->RemoveNodeListener(request->device,
876 		request->node, request->listener);
877 
878 	// prepare the reply
879 	RequestAllocator allocator(fPort->GetPort());
880 	RemoveNodeListenerReply* reply;
881 	status_t error = AllocateRequest(allocator, &reply);
882 	if (error != B_OK)
883 		return error;
884 
885 	reply->error = result;
886 
887 	// send the reply
888 	return fPort->SendRequest(&allocator);
889 }
890 
891 
892 // _GetVolume
893 status_t
894 KernelRequestHandler::_GetVolume(dev_t id, Volume** volume)
895 {
896 	if (fVolume) {
897 		if (fVolume->GetID() != id) {
898 			*volume = NULL;
899 			return B_BAD_VALUE;
900 		}
901 		fVolume->AddReference();
902 		*volume = fVolume;
903 		return B_OK;
904 	}
905 	*volume = fFileSystem->GetVolume(id);
906 	return (*volume ? B_OK : B_BAD_VALUE);
907 }
908 
909