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