xref: /haiku/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/KernelRequestHandler.cpp (revision b671e9bbdbd10268a042b4f4cc4317ccd03d105e)
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 NOTIFY_IO_REQUEST_REQUEST:
110 			return _HandleRequest((NotifyIORequestRequest*)request);
111 	}
112 PRINT(("KernelRequestHandler::HandleRequest(): unexpected request: %lu\n",
113 request->GetType()));
114 	return B_BAD_DATA;
115 }
116 
117 // #pragma mark -
118 // #pragma mark ----- notifications -----
119 
120 // _HandleRequest
121 status_t
122 KernelRequestHandler::_HandleRequest(NotifyListenerRequest* request)
123 {
124 	// check and execute the request
125 	status_t result = B_OK;
126 	if (fVolume && request->device != fVolume->GetID())
127 		result = B_BAD_VALUE;
128 
129 	// get the names
130 	// name
131 	char* name = (char*)request->name.GetData();
132 	int32 nameLen = request->name.GetSize();
133 	if (name && (nameLen <= 0))
134 		name = NULL;
135 	else if (name)
136 		name[nameLen - 1] = '\0';	// NULL-terminate to be safe
137 
138 	// old name
139 	char* oldName = (char*)request->oldName.GetData();
140 	int32 oldNameLen = request->oldName.GetSize();
141 	if (oldName && (oldNameLen <= 0))
142 		oldName = NULL;
143 	else if (oldName)
144 		oldName[oldNameLen - 1] = '\0';	// NULL-terminate to be safe
145 
146 	// check the names
147 	if (result == B_OK) {
148 		switch (request->operation) {
149 			case B_ENTRY_MOVED:
150 				if (!oldName) {
151 					ERROR(("NotifyListenerRequest: NULL oldName for "
152 						"B_ENTRY_MOVED\n"));
153 					result = B_BAD_VALUE;
154 					break;
155 				}
156 				// fall through...
157 			case B_ENTRY_CREATED:
158 			case B_ENTRY_REMOVED:
159 			case B_ATTR_CHANGED:
160 				if (!name) {
161 					ERROR(("NotifyListenerRequest: NULL name for opcode: %ld\n",
162 						request->operation));
163 					result = B_BAD_VALUE;
164 				}
165 				break;
166 			case B_STAT_CHANGED:
167 				break;
168 		}
169 	}
170 
171 	// execute the request
172 	if (result == B_OK) {
173 		switch (request->operation) {
174 			case B_ENTRY_CREATED:
175 				PRINT(("notify_entry_created(%ld, %lld, \"%s\", %lld)\n",
176 					request->device, request->directory, name, request->node));
177 				result = notify_entry_created(request->device,
178 					request->directory, name, request->node);
179 				break;
180 
181 			case B_ENTRY_REMOVED:
182 				PRINT(("notify_entry_removed(%ld, %lld, \"%s\", %lld)\n",
183 					request->device, request->directory, name, request->node));
184 				result = notify_entry_removed(request->device,
185 					request->directory, name, request->node);
186 				break;
187 
188 			case B_ENTRY_MOVED:
189 				PRINT(("notify_entry_moved(%ld, %lld, \"%s\", %lld, \"%s\", "
190 					"%lld)\n", request->device, request->oldDirectory, oldName,
191 					request->directory, name, request->node));
192 				result = notify_entry_moved(request->device,
193 					request->oldDirectory, oldName, request->directory, name,
194 					request->node);
195 				break;
196 
197 			case B_STAT_CHANGED:
198 				PRINT(("notify_stat_changed(%ld, %lld, 0x%lx)\n",
199 					request->device, request->node, request->details));
200 				result = notify_stat_changed(request->device, request->node,
201 					request->details);
202 				break;
203 
204 			case B_ATTR_CHANGED:
205 				PRINT(("notify_attribute_changed(%ld, %lld, \"%s\", 0x%lx)\n",
206 					request->device, request->node, name,
207 					(int32)request->details));
208 				result = notify_attribute_changed(request->device,
209 					request->node, name, (int32)request->details);
210 				break;
211 
212 			default:
213 				ERROR(("NotifyQueryRequest: unsupported operation: %ld\n",
214 					request->operation));
215 				result = B_BAD_VALUE;
216 				break;
217 		}
218 	}
219 
220 	// prepare the reply
221 	RequestAllocator allocator(fPort->GetPort());
222 	NotifyListenerReply* reply;
223 	status_t error = AllocateRequest(allocator, &reply);
224 	if (error != B_OK)
225 		return error;
226 
227 	reply->error = result;
228 
229 	// send the reply
230 	return fPort->SendRequest(&allocator);
231 }
232 
233 // _HandleRequest
234 status_t
235 KernelRequestHandler::_HandleRequest(NotifySelectEventRequest* request)
236 {
237 	// check and execute the request
238 	status_t result = B_OK;
239 	if (fFileSystem->KnowsSelectSyncEntry(request->sync)) {
240 		if (request->unspecifiedEvent) {
241 			// old style add-ons can't provide an event argument; we shoot
242 			// all events
243 			notify_select_event(request->sync, B_SELECT_READ);
244 			notify_select_event(request->sync, B_SELECT_WRITE);
245 			notify_select_event(request->sync, B_SELECT_ERROR);
246 		} else {
247 			PRINT(("notify_select_event(%p, %d)\n", request->sync,
248 				(int)request->event));
249 			notify_select_event(request->sync, request->event);
250 		}
251 	} else
252 		result = B_BAD_VALUE;
253 
254 	// prepare the reply
255 	RequestAllocator allocator(fPort->GetPort());
256 	NotifySelectEventReply* reply;
257 	status_t error = AllocateRequest(allocator, &reply);
258 	if (error != B_OK)
259 		return error;
260 
261 	reply->error = result;
262 
263 	// send the reply
264 	return fPort->SendRequest(&allocator);
265 }
266 
267 // _HandleRequest
268 status_t
269 KernelRequestHandler::_HandleRequest(NotifyQueryRequest* request)
270 {
271 	// check and execute the request
272 	status_t result = B_OK;
273 	if (fVolume && request->device != fVolume->GetID())
274 		result = B_BAD_VALUE;
275 
276 	// check the name
277 	char* name = (char*)request->name.GetData();
278 	int32 nameLen = request->name.GetSize();
279 	if (!name || nameLen <= 0) {
280 		ERROR(("NotifyQueryRequest: NULL name!\n"));
281 		result = B_BAD_VALUE;
282 	} else
283 		name[nameLen - 1] = '\0';	// NULL-terminate to be safe
284 
285 	// execute the request
286 	if (result == B_OK) {
287 		switch (request->operation) {
288 			case B_ENTRY_CREATED:
289 				PRINT(("notify_query_entry_created(%ld, %ld, %ld, %lld,"
290 					" \"%s\", %lld)\n", request->port, request->token,
291 					request->device, request->directory, name, request->node));
292 				result = notify_query_entry_created(request->port,
293 					request->token, request->device, request->directory, name,
294 					request->node);
295 				break;
296 
297 			case B_ENTRY_REMOVED:
298 				PRINT(("notify_query_entry_removed(%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_removed(request->port,
302 					request->token, request->device, request->directory, name,
303 					request->node);
304 				break;
305 
306 			case B_ENTRY_MOVED:
307 			default:
308 				ERROR(("NotifyQueryRequest: unsupported operation: %ld\n",
309 					request->operation));
310 				result = B_BAD_VALUE;
311 				break;
312 		}
313 	}
314 
315 	// prepare the reply
316 	RequestAllocator allocator(fPort->GetPort());
317 	NotifyQueryReply* reply;
318 	status_t error = AllocateRequest(allocator, &reply);
319 	if (error != B_OK)
320 		return error;
321 
322 	reply->error = result;
323 
324 	// send the reply
325 	return fPort->SendRequest(&allocator);
326 }
327 
328 // #pragma mark -
329 // #pragma mark ----- vnodes -----
330 
331 // _HandleRequest
332 status_t
333 KernelRequestHandler::_HandleRequest(GetVNodeRequest* request)
334 {
335 	// check and execute the request
336 	Volume* volume = NULL;
337 	status_t result = _GetVolume(request->nsid, &volume);
338 	VolumePutter _(volume);
339 	void* node;
340 	if (result == B_OK)
341 		result = volume->GetVNode(request->vnid, &node);
342 	// prepare the reply
343 	RequestAllocator allocator(fPort->GetPort());
344 	GetVNodeReply* reply;
345 	status_t error = AllocateRequest(allocator, &reply);
346 	if (error != B_OK)
347 		return error;
348 	reply->error = result;
349 	reply->node = node;
350 	// send the reply
351 	return fPort->SendRequest(&allocator);
352 }
353 
354 // _HandleRequest
355 status_t
356 KernelRequestHandler::_HandleRequest(PutVNodeRequest* request)
357 {
358 	// check and execute the request
359 	Volume* volume = NULL;
360 	status_t result = _GetVolume(request->nsid, &volume);
361 	VolumePutter _(volume);
362 	if (result == B_OK)
363 		result = volume->PutVNode(request->vnid);
364 	// prepare the reply
365 	RequestAllocator allocator(fPort->GetPort());
366 	PutVNodeReply* reply;
367 	status_t error = AllocateRequest(allocator, &reply);
368 	if (error != B_OK)
369 		return error;
370 	reply->error = result;
371 	// send the reply
372 	return fPort->SendRequest(&allocator);
373 }
374 
375 
376 // _HandleRequest
377 status_t
378 KernelRequestHandler::_HandleRequest(AcquireVNodeRequest* request)
379 {
380 	// check and execute the request
381 	Volume* volume = NULL;
382 	status_t result = _GetVolume(request->nsid, &volume);
383 	VolumePutter _(volume);
384 	if (result == B_OK)
385 		result = volume->AcquireVNode(request->vnid);
386 
387 	// prepare the reply
388 	RequestAllocator allocator(fPort->GetPort());
389 	AcquireVNodeReply* reply;
390 	status_t error = AllocateRequest(allocator, &reply);
391 	if (error != B_OK)
392 		return error;
393 	reply->error = result;
394 
395 	// send the reply
396 	return fPort->SendRequest(&allocator);
397 }
398 
399 
400 // _HandleRequest
401 status_t
402 KernelRequestHandler::_HandleRequest(NewVNodeRequest* request)
403 {
404 	// check and execute the request
405 	Volume* volume = NULL;
406 	status_t result = _GetVolume(request->nsid, &volume);
407 	VolumePutter _(volume);
408 	if (result == B_OK) {
409 		result = volume->NewVNode(request->vnid, request->node,
410 			request->capabilities);
411 	}
412 
413 	// prepare the reply
414 	RequestAllocator allocator(fPort->GetPort());
415 	NewVNodeReply* reply;
416 	status_t error = AllocateRequest(allocator, &reply);
417 	if (error != B_OK)
418 		return error;
419 	reply->error = result;
420 
421 	// send the reply
422 	return fPort->SendRequest(&allocator);
423 }
424 
425 // _HandleRequest
426 status_t
427 KernelRequestHandler::_HandleRequest(PublishVNodeRequest* request)
428 {
429 	// check and execute the request
430 	Volume* volume = NULL;
431 	status_t result = _GetVolume(request->nsid, &volume);
432 	VolumePutter _(volume);
433 	if (result == B_OK) {
434 		result = volume->PublishVNode(request->vnid, request->node,
435 			request->type, request->flags, request->capabilities);
436 	}
437 
438 	// prepare the reply
439 	RequestAllocator allocator(fPort->GetPort());
440 	PublishVNodeReply* reply;
441 	status_t error = AllocateRequest(allocator, &reply);
442 	if (error != B_OK)
443 		return error;
444 
445 	reply->error = result;
446 
447 	// send the reply
448 	return fPort->SendRequest(&allocator);
449 }
450 
451 // _HandleRequest
452 status_t
453 KernelRequestHandler::_HandleRequest(RemoveVNodeRequest* request)
454 {
455 	// check and execute the request
456 	Volume* volume = NULL;
457 	status_t result = _GetVolume(request->nsid, &volume);
458 	VolumePutter _(volume);
459 	if (result == B_OK)
460 		result = volume->RemoveVNode(request->vnid);
461 	// prepare the reply
462 	RequestAllocator allocator(fPort->GetPort());
463 	RemoveVNodeReply* reply;
464 	status_t error = AllocateRequest(allocator, &reply);
465 	if (error != B_OK)
466 		return error;
467 	reply->error = result;
468 	// send the reply
469 	return fPort->SendRequest(&allocator);
470 }
471 
472 // _HandleRequest
473 status_t
474 KernelRequestHandler::_HandleRequest(UnremoveVNodeRequest* request)
475 {
476 	// check and execute the request
477 	Volume* volume = NULL;
478 	status_t result = _GetVolume(request->nsid, &volume);
479 	VolumePutter _(volume);
480 	if (result == B_OK)
481 		result = volume->UnremoveVNode(request->vnid);
482 	// prepare the reply
483 	RequestAllocator allocator(fPort->GetPort());
484 	UnremoveVNodeReply* reply;
485 	status_t error = AllocateRequest(allocator, &reply);
486 	if (error != B_OK)
487 		return error;
488 	reply->error = result;
489 	// send the reply
490 	return fPort->SendRequest(&allocator);
491 }
492 
493 // _HandleRequest
494 status_t
495 KernelRequestHandler::_HandleRequest(GetVNodeRemovedRequest* request)
496 {
497 	// check and execute the request
498 	Volume* volume = NULL;
499 	status_t result = _GetVolume(request->nsid, &volume);
500 	VolumePutter _(volume);
501 	bool removed = false;
502 	if (result == B_OK)
503 		result = volume->GetVNodeRemoved(request->vnid, &removed);
504 
505 	// prepare the reply
506 	RequestAllocator allocator(fPort->GetPort());
507 	GetVNodeRemovedReply* reply;
508 	status_t error = AllocateRequest(allocator, &reply);
509 	if (error != B_OK)
510 		return error;
511 
512 	reply->error = result;
513 	reply->removed = removed;
514 
515 	// send the reply
516 	return fPort->SendRequest(&allocator);
517 }
518 
519 
520 // _HandleRequest
521 status_t
522 KernelRequestHandler::_HandleRequest(FileCacheCreateRequest* request)
523 {
524 	// check and execute the request
525 	Volume* volume = NULL;
526 	status_t result = _GetVolume(request->nsid, &volume);
527 	VolumePutter _(volume);
528 
529 	if (result == B_OK)
530 		result = volume->CreateFileCache(request->vnid, request->size);
531 
532 	// prepare the reply
533 	RequestAllocator allocator(fPort->GetPort());
534 	FileCacheCreateReply* reply;
535 	status_t error = AllocateRequest(allocator, &reply);
536 	if (error != B_OK)
537 		return error;
538 	reply->error = result;
539 
540 	// send the reply
541 	return fPort->SendRequest(&allocator);
542 }
543 
544 
545 // _HandleRequest
546 status_t
547 KernelRequestHandler::_HandleRequest(FileCacheDeleteRequest* request)
548 {
549 	// check and execute the request
550 	Volume* volume = NULL;
551 	status_t result = _GetVolume(request->nsid, &volume);
552 	VolumePutter _(volume);
553 
554 	if (result == B_OK)
555 		result = volume->DeleteFileCache(request->vnid);
556 
557 	// prepare the reply
558 	RequestAllocator allocator(fPort->GetPort());
559 	FileCacheDeleteReply* reply;
560 	status_t error = AllocateRequest(allocator, &reply);
561 	if (error != B_OK)
562 		return error;
563 	reply->error = result;
564 
565 	// send the reply
566 	return fPort->SendRequest(&allocator);
567 }
568 
569 
570 // _HandleRequest
571 status_t
572 KernelRequestHandler::_HandleRequest(FileCacheSetEnabledRequest* request)
573 {
574 	// check and execute the request
575 	Volume* volume = NULL;
576 	status_t result = _GetVolume(request->nsid, &volume);
577 	VolumePutter _(volume);
578 
579 	if (result == B_OK)
580 		result = volume->SetFileCacheEnabled(request->vnid, request->enabled);
581 
582 	// prepare the reply
583 	RequestAllocator allocator(fPort->GetPort());
584 	FileCacheSetEnabledReply* reply;
585 	status_t error = AllocateRequest(allocator, &reply);
586 	if (error != B_OK)
587 		return error;
588 	reply->error = result;
589 
590 	// send the reply
591 	return fPort->SendRequest(&allocator);
592 }
593 
594 
595 // _HandleRequest
596 status_t
597 KernelRequestHandler::_HandleRequest(FileCacheSetSizeRequest* request)
598 {
599 	// check and execute the request
600 	Volume* volume = NULL;
601 	status_t result = _GetVolume(request->nsid, &volume);
602 	VolumePutter _(volume);
603 
604 	if (result == B_OK)
605 		result = volume->SetFileCacheSize(request->vnid, request->size);
606 
607 	// prepare the reply
608 	RequestAllocator allocator(fPort->GetPort());
609 	FileCacheSetSizeReply* reply;
610 	status_t error = AllocateRequest(allocator, &reply);
611 	if (error != B_OK)
612 		return error;
613 	reply->error = result;
614 
615 	// send the reply
616 	return fPort->SendRequest(&allocator);
617 }
618 
619 
620 // _HandleRequest
621 status_t
622 KernelRequestHandler::_HandleRequest(FileCacheSyncRequest* request)
623 {
624 	// check and execute the request
625 	Volume* volume = NULL;
626 	status_t result = _GetVolume(request->nsid, &volume);
627 	VolumePutter _(volume);
628 
629 	if (result == B_OK)
630 		result = volume->SyncFileCache(request->vnid);
631 
632 	// prepare the reply
633 	RequestAllocator allocator(fPort->GetPort());
634 	FileCacheSyncReply* reply;
635 	status_t error = AllocateRequest(allocator, &reply);
636 	if (error != B_OK)
637 		return error;
638 	reply->error = result;
639 
640 	// send the reply
641 	return fPort->SendRequest(&allocator);
642 }
643 
644 
645 // _HandleRequest
646 status_t
647 KernelRequestHandler::_HandleRequest(FileCacheReadRequest* request)
648 {
649 	// check the request
650 	Volume* volume = NULL;
651 	status_t result = _GetVolume(request->nsid, &volume);
652 	VolumePutter _(volume);
653 
654 	size_t size = request->size;
655 
656 	// allocate the reply
657 	RequestAllocator allocator(fPort->GetPort());
658 	FileCacheReadReply* reply;
659 	status_t error = AllocateRequest(allocator, &reply);
660 	if (error != B_OK)
661 		RETURN_ERROR(error);
662 
663 	void* buffer;
664 	if (result == B_OK) {
665 		result = allocator.AllocateAddress(reply->buffer, size, 1, &buffer,
666 			true);
667 	}
668 
669 	// execute the request
670 	if (result == B_OK) {
671 		result = volume->ReadFileCache(request->vnid, request->cookie,
672 			request->pos, buffer, &size);
673 	}
674 
675 	// prepare the reply
676 	reply->error = result;
677 	reply->bytesRead = size;
678 
679 	// send the reply
680 	if (reply->error == B_OK && reply->bytesRead > 0) {
681 		SingleReplyRequestHandler handler(RECEIPT_ACK_REPLY);
682 		return fPort->SendRequest(&allocator, &handler);
683 	}
684 
685 	return fPort->SendRequest(&allocator);
686 }
687 
688 
689 // _HandleRequest
690 status_t
691 KernelRequestHandler::_HandleRequest(FileCacheWriteRequest* request)
692 {
693 	// check and execute the request
694 	Volume* volume = NULL;
695 	status_t result = _GetVolume(request->nsid, &volume);
696 	VolumePutter _(volume);
697 
698 	size_t size = 0;
699 	if (result == B_OK) {
700 		size = request->buffer.GetSize();
701 		result = volume->WriteFileCache(request->vnid, request->cookie,
702 			request->pos, request->buffer.GetData(), &size);
703 	}
704 
705 	// prepare the reply
706 	RequestAllocator allocator(fPort->GetPort());
707 	FileCacheWriteReply* reply;
708 	status_t error = AllocateRequest(allocator, &reply);
709 	if (error != B_OK)
710 		return error;
711 	reply->error = result;
712 	reply->bytesWritten = size;
713 
714 	// send the reply
715 	return fPort->SendRequest(&allocator);
716 }
717 
718 
719 // _HandleRequest
720 status_t
721 KernelRequestHandler::_HandleRequest(DoIterativeFDIORequest* request)
722 {
723 	// check and execute the request
724 	Volume* volume = NULL;
725 	status_t result = _GetVolume(request->nsid, &volume);
726 	VolumePutter _(volume);
727 
728 	uint32 vecCount = request->vecCount;
729 	if (result == B_OK && vecCount > DoIterativeFDIORequest::MAX_VECS)
730 		result = B_BAD_VALUE;
731 
732 	if (result == B_OK) {
733 		result = volume->DoIterativeFDIO(request->fd, request->request,
734 			request->cookie, request->vecs, vecCount);
735 	}
736 
737 	// prepare the reply
738 	RequestAllocator allocator(fPort->GetPort());
739 	DoIterativeFDIOReply* reply;
740 	status_t error = AllocateRequest(allocator, &reply);
741 	if (error != B_OK)
742 		return error;
743 	reply->error = result;
744 
745 	// send the reply
746 	return fPort->SendRequest(&allocator);
747 }
748 
749 
750 // _HandleRequest
751 status_t
752 KernelRequestHandler::_HandleRequest(NotifyIORequestRequest* request)
753 {
754 	// check and execute the request
755 	Volume* volume = NULL;
756 	status_t result = _GetVolume(request->nsid, &volume);
757 	VolumePutter _(volume);
758 
759 	if (result == B_OK)
760 		result = volume->NotifyIORequest(request->request, request->status);
761 
762 	// prepare the reply
763 	RequestAllocator allocator(fPort->GetPort());
764 	NotifyIORequestReply* reply;
765 	status_t error = AllocateRequest(allocator, &reply);
766 	if (error != B_OK)
767 		return error;
768 	reply->error = result;
769 
770 	// send the reply
771 	return fPort->SendRequest(&allocator);
772 }
773 
774 
775 // _GetVolume
776 status_t
777 KernelRequestHandler::_GetVolume(dev_t id, Volume** volume)
778 {
779 	if (fVolume) {
780 		if (fVolume->GetID() != id) {
781 			*volume = NULL;
782 			return B_BAD_VALUE;
783 		}
784 		fVolume->AddReference();
785 		*volume = fVolume;
786 		return B_OK;
787 	}
788 	*volume = fFileSystem->GetVolume(id);
789 	return (*volume ? B_OK : B_BAD_VALUE);
790 }
791 
792