xref: /haiku/src/add-ons/kernel/file_systems/userlandfs/private/Requests.cpp (revision 1214ef1b2100f2b3299fc9d8d6142e46f70a4c3f)
1 // Requests.cpp
2 
3 #include <limits.h>
4 
5 #include "Debug.h"
6 #include "Requests.h"
7 
8 #define _ADD_ADDRESS(_address, _flags)				\
9 	if (*count >= MAX_REQUEST_ADDRESS_COUNT)		\
10 		return B_BAD_VALUE;							\
11 	infos[*count].address = &_address;				\
12 	infos[*count].flags = _flags;					\
13 	infos[(*count)++].max_size = LONG_MAX;	// TODO:...
14 
15 #define ADD_ADDRESS(address)	_ADD_ADDRESS(address, 0)
16 #define ADD_STRING(address)		_ADD_ADDRESS(address, ADDRESS_IS_STRING)
17 #define ADD_NON_NULL_ADDRESS(address)	_ADD_ADDRESS(address, ADDRESS_NOT_NULL)
18 #define ADD_NON_NULL_STRING(address)	\
19 	_ADD_ADDRESS(address, (ADDRESS_IS_STRING | ADDRESS_NOT_NULL))
20 
21 // FSConnectRequest
22 status_t
23 FSConnectRequest::GetAddressInfos(AddressInfo* infos, int32* count)
24 {
25 	ADD_NON_NULL_STRING(fsName);
26 	return B_OK;
27 }
28 
29 // FSConnectReply
30 status_t
31 FSConnectReply::GetAddressInfos(AddressInfo* infos, int32* count)
32 {
33 	ADD_NON_NULL_ADDRESS(portInfos);
34 	return B_OK;
35 }
36 
37 // MountVolumeRequest
38 status_t
39 MountVolumeRequest::GetAddressInfos(AddressInfo* infos, int32* count)
40 {
41 	ADD_NON_NULL_STRING(cwd);
42 	ADD_STRING(device);
43 	ADD_STRING(parameters);
44 	return B_OK;
45 }
46 
47 //// InitializeVolumeRequest
48 //status_t
49 //InitializeVolumeRequest::GetAddressInfos(AddressInfo* infos, int32* count)
50 //{
51 //	ADD_STRING(device);
52 //	ADD_STRING(parameters);
53 //	return B_OK;
54 //}
55 
56 // GetVNodeNameReply
57 status_t
58 GetVNodeNameReply::GetAddressInfos(AddressInfo* infos, int32* count)
59 {
60 	ADD_STRING(buffer);
61 	return B_OK;
62 }
63 
64 // CreateRequest
65 status_t
66 CreateRequest::GetAddressInfos(AddressInfo* infos, int32* count)
67 {
68 	ADD_NON_NULL_STRING(name);
69 	return B_OK;
70 }
71 
72 // ReadReply
73 status_t
74 ReadReply::GetAddressInfos(AddressInfo* infos, int32* count)
75 {
76 	ADD_ADDRESS(buffer);
77 	return B_OK;
78 }
79 
80 // WriteRequest
81 status_t
82 WriteRequest::GetAddressInfos(AddressInfo* infos, int32* count)
83 {
84 	ADD_ADDRESS(buffer);
85 	return B_OK;
86 }
87 
88 // IOCtlRequest
89 status_t
90 IOCtlRequest::GetAddressInfos(AddressInfo* infos, int32* count)
91 {
92 	ADD_ADDRESS(buffer);
93 	return B_OK;
94 }
95 
96 // IOCtlReply
97 status_t
98 IOCtlReply::GetAddressInfos(AddressInfo* infos, int32* count)
99 {
100 	ADD_ADDRESS(buffer);
101 	return B_OK;
102 }
103 
104 // LinkRequest
105 status_t
106 LinkRequest::GetAddressInfos(AddressInfo* infos, int32* count)
107 {
108 	ADD_NON_NULL_STRING(name);
109 	return B_OK;
110 }
111 
112 // UnlinkRequest
113 status_t
114 UnlinkRequest::GetAddressInfos(AddressInfo* infos, int32* count)
115 {
116 	ADD_NON_NULL_STRING(name);
117 	return B_OK;
118 }
119 
120 // CreateSymlinkRequest
121 status_t
122 CreateSymlinkRequest::GetAddressInfos(AddressInfo* infos, int32* count)
123 {
124 	ADD_NON_NULL_STRING(name);
125 	ADD_NON_NULL_STRING(target);
126 	return B_OK;
127 }
128 
129 // ReadSymlinkReply
130 status_t
131 ReadSymlinkReply::GetAddressInfos(AddressInfo* infos, int32* count)
132 {
133 	ADD_STRING(buffer);
134 	return B_OK;
135 }
136 
137 // RenameRequest
138 status_t
139 RenameRequest::GetAddressInfos(AddressInfo* infos, int32* count)
140 {
141 	ADD_NON_NULL_STRING(oldName);
142 	ADD_NON_NULL_STRING(newName);
143 	return B_OK;
144 }
145 
146 // CreateDirRequest
147 status_t
148 CreateDirRequest::GetAddressInfos(AddressInfo* infos, int32* count)
149 {
150 	ADD_NON_NULL_STRING(name);
151 	return B_OK;
152 }
153 
154 // RemoveDirRequest
155 status_t
156 RemoveDirRequest::GetAddressInfos(AddressInfo* infos, int32* count)
157 {
158 	ADD_NON_NULL_STRING(name);
159 	return B_OK;
160 }
161 
162 // ReadDirReply
163 status_t
164 ReadDirReply::GetAddressInfos(AddressInfo* infos, int32* count)
165 {
166 	ADD_ADDRESS(buffer);
167 	return B_OK;
168 }
169 
170 // LookupRequest
171 status_t
172 LookupRequest::GetAddressInfos(AddressInfo* infos, int32* count)
173 {
174 	ADD_NON_NULL_STRING(entryName);
175 	return B_OK;
176 }
177 
178 // ReadAttrDirReply
179 status_t
180 ReadAttrDirReply::GetAddressInfos(AddressInfo* infos, int32* count)
181 {
182 	ADD_ADDRESS(buffer);
183 	return B_OK;
184 }
185 
186 // CreateAttrRequest
187 status_t
188 CreateAttrRequest::GetAddressInfos(AddressInfo* infos, int32* count)
189 {
190 	ADD_NON_NULL_STRING(name);
191 	return B_OK;
192 }
193 
194 // OpenAttrRequest
195 status_t
196 OpenAttrRequest::GetAddressInfos(AddressInfo* infos, int32* count)
197 {
198 	ADD_NON_NULL_STRING(name);
199 	return B_OK;
200 }
201 
202 // ReadAttrReply
203 status_t
204 ReadAttrReply::GetAddressInfos(AddressInfo* infos, int32* count)
205 {
206 	ADD_ADDRESS(buffer);
207 	return B_OK;
208 }
209 
210 // WriteAttrRequest
211 status_t
212 WriteAttrRequest::GetAddressInfos(AddressInfo* infos, int32* count)
213 {
214 	ADD_ADDRESS(buffer);
215 	return B_OK;
216 }
217 
218 // RemoveAttrRequest
219 status_t
220 RemoveAttrRequest::GetAddressInfos(AddressInfo* infos, int32* count)
221 {
222 	ADD_NON_NULL_STRING(name);
223 	return B_OK;
224 }
225 
226 // RenameAttrRequest
227 status_t
228 RenameAttrRequest::GetAddressInfos(AddressInfo* infos, int32* count)
229 {
230 	ADD_NON_NULL_STRING(oldName);
231 	ADD_NON_NULL_STRING(newName);
232 	return B_OK;
233 }
234 
235 // ReadIndexDirReply
236 status_t
237 ReadIndexDirReply::GetAddressInfos(AddressInfo* infos, int32* count)
238 {
239 	ADD_ADDRESS(buffer);
240 	return B_OK;
241 }
242 
243 // CreateIndexRequest
244 status_t
245 CreateIndexRequest::GetAddressInfos(AddressInfo* infos, int32* count)
246 {
247 	ADD_NON_NULL_STRING(name);
248 	return B_OK;
249 }
250 
251 // RemoveIndexRequest
252 status_t
253 RemoveIndexRequest::GetAddressInfos(AddressInfo* infos, int32* count)
254 {
255 	ADD_NON_NULL_STRING(name);
256 	return B_OK;
257 }
258 
259 // ReadIndexStatRequest
260 status_t
261 ReadIndexStatRequest::GetAddressInfos(AddressInfo* infos, int32* count)
262 {
263 	ADD_NON_NULL_STRING(name);
264 	return B_OK;
265 }
266 
267 // OpenQueryRequest
268 status_t
269 OpenQueryRequest::GetAddressInfos(AddressInfo* infos, int32* count)
270 {
271 	ADD_NON_NULL_STRING(queryString);
272 	return B_OK;
273 }
274 
275 // ReadQueryReply
276 status_t
277 ReadQueryReply::GetAddressInfos(AddressInfo* infos, int32* count)
278 {
279 	ADD_ADDRESS(buffer);
280 	return B_OK;
281 }
282 
283 // NotifyListenerRequest
284 status_t
285 NotifyListenerRequest::GetAddressInfos(AddressInfo* infos, int32* count)
286 {
287 	ADD_STRING(oldName);
288 	ADD_STRING(name);
289 	return B_OK;
290 }
291 
292 // NotifyQueryRequest
293 status_t
294 NotifyQueryRequest::GetAddressInfos(AddressInfo* infos, int32* count)
295 {
296 	ADD_STRING(name);
297 	return B_OK;
298 }
299 
300 
301 // #pragma mark -
302 
303 // RequestAddressInfoGetter
304 struct RequestAddressInfoGetter {
305 	RequestAddressInfoGetter(AddressInfo* infos, int32* count)
306 		: fInfos(infos),
307 		  fCount(count)
308 	{
309 	}
310 
311 	template<typename R> status_t operator()(R* request)
312 	{
313 		return request->GetAddressInfos(fInfos, fCount);
314 	}
315 
316 private:
317 	AddressInfo*	fInfos;
318 	int32*			fCount;
319 };
320 
321 // get_request_address_infos
322 status_t
323 UserlandFSUtil::get_request_address_infos(Request* request, AddressInfo* infos,
324 	int32* count)
325 {
326 	if (!infos || !count)
327 		return B_BAD_VALUE;
328 	*count = 0;
329 	RequestAddressInfoGetter task(infos, count);
330 	return do_for_request(request, task);
331 }
332 
333 // RequestChecker
334 struct RequestChecker {
335 	template<typename R> status_t operator()(R* request)
336 	{
337 		return request->Check();
338 	}
339 };
340 
341 // check_request
342 status_t
343 UserlandFSUtil::check_request(Request* request)
344 {
345 	RequestChecker task;
346 	return do_for_request(request, task);
347 }
348 
349 
350 // is_error_reply
351 static inline
352 bool
353 is_error_reply(Request* request)
354 {
355 	return false;
356 }
357 
358 // is_error_reply
359 static inline
360 bool
361 is_error_reply(ReplyRequest* request)
362 {
363 	return (request->error != B_OK);
364 }
365 
366 // RequestRelocator
367 struct RequestRelocator {
368 	RequestRelocator(int32 requestBufferSize, area_id* areas, int32* count)
369 		: fRequestBufferSize(requestBufferSize),
370 		  fAreas(areas),
371 		  fAreaCount(count)
372 	{
373 		*fAreaCount = 0;
374 	}
375 
376 	~RequestRelocator()
377 	{
378 		if (!fSuccess) {
379 			for (int32 i = 0; i < *fAreaCount; i++)
380 				delete_area(fAreas[i]);
381 		}
382 	}
383 
384 	template<typename R> status_t operator()(R* request)
385 	{
386 		// check the request buffer size
387 		if (fRequestBufferSize < (int32)sizeof(R))
388 			RETURN_ERROR(B_BAD_DATA);
389 		// no need to relocate the addresses of a reply that indicates an error
390 		if (is_error_reply(request)) {
391 			fSuccess = true;
392 			return B_OK;
393 		}
394 		// get the address infos
395 		AddressInfo infos[MAX_REQUEST_ADDRESS_COUNT];
396 		int32 count = 0;
397 		status_t error = request->GetAddressInfos(infos, &count);
398 		if (error != B_OK)
399 			RETURN_ERROR(error);
400 		// check and relocate the addresses
401 		for (int32 i = 0; i < count; i++) {
402 			// check
403 			Address* address = infos[i].address;
404 			int32 size = address->GetSize();
405 			int32 offset = address->GetOffset();
406 //PRINT(("  relocating address: area: %ld, offset: %ld, size: %ld...\n",
407 //address->GetArea(), offset, size));
408 			if (offset < 0 || size < 0 || size > infos[i].max_size)
409 				RETURN_ERROR(B_BAD_DATA);
410 			if ((infos[i].flags & ADDRESS_NOT_NULL) && size == 0)
411 				RETURN_ERROR(B_BAD_DATA);
412 			// relocate
413 			area_id area = address->GetArea();
414 			if (area < 0) {
415 				// data in the buffer itself
416 				if (offset == 0 && size == 0) {
417 //PRINT(("    -> relocated address: NULL\n"));
418 					address->SetRelocatedAddress(NULL);
419 				} else {
420 					if (offset < (int32)sizeof(R)
421 						|| offset + size > fRequestBufferSize) {
422 						RETURN_ERROR(B_BAD_DATA);
423 					}
424 //PRINT(("    -> relocated address: %p\n", (uint8*)request + offset));
425 					address->SetRelocatedAddress((uint8*)request + offset);
426 				}
427 			} else {
428 				// clone the area
429 				void* data;
430 				area = clone_area("cloned request data", &data,
431 #ifdef _KERNEL_MODE
432 					B_ANY_KERNEL_ADDRESS,
433 #else
434 					B_ANY_ADDRESS,
435 #endif
436 					B_READ_AREA, area);
437 				if (area < 0)
438 					RETURN_ERROR(area);
439 				fAreas[(*fAreaCount)++] = area;
440 				// check offset and size
441 				area_info areaInfo;
442 				error = get_area_info(area, &areaInfo);
443 				if (error != B_OK)
444 					RETURN_ERROR(error);
445 				if (offset + size > (int32)areaInfo.size)
446 					RETURN_ERROR(B_BAD_DATA);
447 //PRINT(("    -> relocated address: %p\n", (uint8*)data + offset));
448 				address->SetRelocatedAddress((uint8*)data + offset);
449 			}
450 		}
451 		// finally let the request check its integrity
452 		error = request->Check();
453 		if (error != B_OK)
454 			RETURN_ERROR(error);
455 		fSuccess = true;
456 //PRINT(("RequestRelocator done: success\n"));
457 		return B_OK;
458 	}
459 
460 private:
461 	int32		fRequestBufferSize;
462 	area_id*	fAreas;
463 	int32*		fAreaCount;
464 	bool		fSuccess;
465 };
466 
467 // relocate_request
468 status_t
469 UserlandFSUtil::relocate_request(Request* request, int32 requestBufferSize,
470 	area_id* areas, int32* count)
471 {
472 	if (!request || !areas || !count)
473 		return B_BAD_VALUE;
474 	RequestRelocator task(requestBufferSize, areas, count);
475 	return do_for_request(request, task);
476 }
477 
478 // is_kernel_request
479 bool
480 UserlandFSUtil::is_kernel_request(uint32 type)
481 {
482 	switch (type) {
483 		// kernel -> userland requests
484 		// administrative
485 		case UFS_DISCONNECT_REQUEST:
486 		case FS_CONNECT_REQUEST:
487 			return true;
488 		case FS_CONNECT_REPLY:
489 			return false;
490 		// FS
491 		case MOUNT_VOLUME_REQUEST:
492 		case UNMOUNT_VOLUME_REQUEST:
493 //		case INITIALIZE_VOLUME_REQUEST:
494 		case SYNC_VOLUME_REQUEST:
495 		case READ_FS_INFO_REQUEST:
496 		case WRITE_FS_INFO_REQUEST:
497 			return true;
498 		case MOUNT_VOLUME_REPLY:
499 		case UNMOUNT_VOLUME_REPLY:
500 //		case INITIALIZE_VOLUME_REPLY:
501 		case SYNC_VOLUME_REPLY:
502 		case READ_FS_INFO_REPLY:
503 		case WRITE_FS_INFO_REPLY:
504 			return false;
505 		// vnodes
506 		case LOOKUP_REQUEST:
507 		case GET_VNODE_NAME_REQUEST:
508 		case READ_VNODE_REQUEST:
509 		case WRITE_VNODE_REQUEST:
510 		case FS_REMOVE_VNODE_REQUEST:
511 			return true;
512 		case LOOKUP_REPLY:
513 		case GET_VNODE_NAME_REPLY:
514 		case READ_VNODE_REPLY:
515 		case WRITE_VNODE_REPLY:
516 		case FS_REMOVE_VNODE_REPLY:
517 			return false;
518 		// nodes
519 		case IOCTL_REQUEST:
520 		case SET_FLAGS_REQUEST:
521 		case SELECT_REQUEST:
522 		case DESELECT_REQUEST:
523 		case FSYNC_REQUEST:
524 		case READ_SYMLINK_REQUEST:
525 		case CREATE_SYMLINK_REQUEST:
526 		case LINK_REQUEST:
527 		case UNLINK_REQUEST:
528 		case RENAME_REQUEST:
529 		case ACCESS_REQUEST:
530 		case READ_STAT_REQUEST:
531 		case WRITE_STAT_REQUEST:
532 			return true;
533 		case IOCTL_REPLY:
534 		case SET_FLAGS_REPLY:
535 		case SELECT_REPLY:
536 		case DESELECT_REPLY:
537 		case FSYNC_REPLY:
538 		case READ_SYMLINK_REPLY:
539 		case CREATE_SYMLINK_REPLY:
540 		case LINK_REPLY:
541 		case UNLINK_REPLY:
542 		case RENAME_REPLY:
543 		case ACCESS_REPLY:
544 		case READ_STAT_REPLY:
545 		case WRITE_STAT_REPLY:
546 			return false;
547 		// files
548 		case CREATE_REQUEST:
549 		case OPEN_REQUEST:
550 		case CLOSE_REQUEST:
551 		case FREE_COOKIE_REQUEST:
552 		case READ_REQUEST:
553 		case WRITE_REQUEST:
554 			return true;
555 		case CREATE_REPLY:
556 		case OPEN_REPLY:
557 		case CLOSE_REPLY:
558 		case FREE_COOKIE_REPLY:
559 		case READ_REPLY:
560 		case WRITE_REPLY:
561 			return false;
562 		// directories
563 		case CREATE_DIR_REQUEST:
564 		case REMOVE_DIR_REQUEST:
565 		case OPEN_DIR_REQUEST:
566 		case CLOSE_DIR_REQUEST:
567 		case FREE_DIR_COOKIE_REQUEST:
568 		case READ_DIR_REQUEST:
569 		case REWIND_DIR_REQUEST:
570 			return true;
571 		case CREATE_DIR_REPLY:
572 		case REMOVE_DIR_REPLY:
573 		case OPEN_DIR_REPLY:
574 		case CLOSE_DIR_REPLY:
575 		case FREE_DIR_COOKIE_REPLY:
576 		case READ_DIR_REPLY:
577 		case REWIND_DIR_REPLY:
578 			return false;
579 		// attribute directories
580 		case OPEN_ATTR_DIR_REQUEST:
581 		case CLOSE_ATTR_DIR_REQUEST:
582 		case FREE_ATTR_DIR_COOKIE_REQUEST:
583 		case READ_ATTR_DIR_REQUEST:
584 		case REWIND_ATTR_DIR_REQUEST:
585 			return true;
586 		case OPEN_ATTR_DIR_REPLY:
587 		case CLOSE_ATTR_DIR_REPLY:
588 		case FREE_ATTR_DIR_COOKIE_REPLY:
589 		case READ_ATTR_DIR_REPLY:
590 		case REWIND_ATTR_DIR_REPLY:
591 			return false;
592 		// attributes
593 		case CREATE_ATTR_REQUEST:
594 		case OPEN_ATTR_REQUEST:
595 		case CLOSE_ATTR_REQUEST:
596 		case FREE_ATTR_COOKIE_REQUEST:
597 		case READ_ATTR_REQUEST:
598 		case WRITE_ATTR_REQUEST:
599 		case READ_ATTR_STAT_REQUEST:
600 		case WRITE_ATTR_STAT_REQUEST:
601 		case RENAME_ATTR_REQUEST:
602 		case REMOVE_ATTR_REQUEST:
603 			return true;
604 		case CREATE_ATTR_REPLY:
605 		case OPEN_ATTR_REPLY:
606 		case CLOSE_ATTR_REPLY:
607 		case FREE_ATTR_COOKIE_REPLY:
608 		case READ_ATTR_REPLY:
609 		case WRITE_ATTR_REPLY:
610 		case READ_ATTR_STAT_REPLY:
611 		case WRITE_ATTR_STAT_REPLY:
612 		case RENAME_ATTR_REPLY:
613 		case REMOVE_ATTR_REPLY:
614 			return false;
615 		// indices
616 		case OPEN_INDEX_DIR_REQUEST:
617 		case CLOSE_INDEX_DIR_REQUEST:
618 		case FREE_INDEX_DIR_COOKIE_REQUEST:
619 		case READ_INDEX_DIR_REQUEST:
620 		case REWIND_INDEX_DIR_REQUEST:
621 		case CREATE_INDEX_REQUEST:
622 		case REMOVE_INDEX_REQUEST:
623 		case READ_INDEX_STAT_REQUEST:
624 			return true;
625 		case OPEN_INDEX_DIR_REPLY:
626 		case CLOSE_INDEX_DIR_REPLY:
627 		case FREE_INDEX_DIR_COOKIE_REPLY:
628 		case READ_INDEX_DIR_REPLY:
629 		case REWIND_INDEX_DIR_REPLY:
630 		case CREATE_INDEX_REPLY:
631 		case REMOVE_INDEX_REPLY:
632 		case READ_INDEX_STAT_REPLY:
633 			return false;
634 		// queries
635 		case OPEN_QUERY_REQUEST:
636 		case CLOSE_QUERY_REQUEST:
637 		case FREE_QUERY_COOKIE_REQUEST:
638 		case READ_QUERY_REQUEST:
639 		case REWIND_QUERY_REQUEST:
640 			return true;
641 		case OPEN_QUERY_REPLY:
642 		case CLOSE_QUERY_REPLY:
643 		case FREE_QUERY_COOKIE_REPLY:
644 		case READ_QUERY_REPLY:
645 		case REWIND_QUERY_REPLY:
646 			return false;
647 
648 		// userland -> kernel requests
649 		// notifications
650 		case NOTIFY_LISTENER_REQUEST:
651 		case NOTIFY_SELECT_EVENT_REQUEST:
652 		case NOTIFY_QUERY_REQUEST:
653 			return false;
654 		case NOTIFY_LISTENER_REPLY:
655 		case NOTIFY_SELECT_EVENT_REPLY:
656 		case NOTIFY_QUERY_REPLY:
657 			return true;
658 		// vnodes
659 		case GET_VNODE_REQUEST:
660 		case PUT_VNODE_REQUEST:
661 		case NEW_VNODE_REQUEST:
662 		case PUBLISH_VNODE_REQUEST:
663 		case REMOVE_VNODE_REQUEST:
664 		case UNREMOVE_VNODE_REQUEST:
665 		case GET_VNODE_REMOVED_REQUEST:
666 			return false;
667 		case GET_VNODE_REPLY:
668 		case PUT_VNODE_REPLY:
669 		case NEW_VNODE_REPLY:
670 		case PUBLISH_VNODE_REPLY:
671 		case REMOVE_VNODE_REPLY:
672 		case UNREMOVE_VNODE_REPLY:
673 		case GET_VNODE_REMOVED_REPLY:
674 			return true;
675 
676 		// general reply
677 		case RECEIPT_ACK_REPLY:
678 			return true;
679 		default:
680 			return false;
681 	}
682 }
683 
684 // is_userland_request
685 bool
686 UserlandFSUtil::is_userland_request(uint32 type)
687 {
688 	switch (type) {
689 		// kernel -> userland requests
690 		// administrative
691 		case UFS_DISCONNECT_REQUEST:
692 		case FS_CONNECT_REQUEST:
693 			return false;
694 		case FS_CONNECT_REPLY:
695 			return true;
696 		// FS
697 		case MOUNT_VOLUME_REQUEST:
698 		case UNMOUNT_VOLUME_REQUEST:
699 //		case INITIALIZE_VOLUME_REQUEST:
700 		case SYNC_VOLUME_REQUEST:
701 		case READ_FS_INFO_REQUEST:
702 		case WRITE_FS_INFO_REQUEST:
703 			return false;
704 		case MOUNT_VOLUME_REPLY:
705 		case UNMOUNT_VOLUME_REPLY:
706 //		case INITIALIZE_VOLUME_REPLY:
707 		case SYNC_VOLUME_REPLY:
708 		case READ_FS_INFO_REPLY:
709 		case WRITE_FS_INFO_REPLY:
710 			return true;
711 		// vnodes
712 		case LOOKUP_REQUEST:
713 		case GET_VNODE_NAME_REQUEST:
714 		case READ_VNODE_REQUEST:
715 		case WRITE_VNODE_REQUEST:
716 		case FS_REMOVE_VNODE_REQUEST:
717 			return false;
718 		case LOOKUP_REPLY:
719 		case GET_VNODE_NAME_REPLY:
720 		case READ_VNODE_REPLY:
721 		case WRITE_VNODE_REPLY:
722 		case FS_REMOVE_VNODE_REPLY:
723 			return true;
724 		// nodes
725 		case IOCTL_REQUEST:
726 		case SET_FLAGS_REQUEST:
727 		case SELECT_REQUEST:
728 		case DESELECT_REQUEST:
729 		case FSYNC_REQUEST:
730 		case READ_SYMLINK_REQUEST:
731 		case CREATE_SYMLINK_REQUEST:
732 		case LINK_REQUEST:
733 		case UNLINK_REQUEST:
734 		case RENAME_REQUEST:
735 		case ACCESS_REQUEST:
736 		case READ_STAT_REQUEST:
737 		case WRITE_STAT_REQUEST:
738 			return false;
739 		case IOCTL_REPLY:
740 		case SET_FLAGS_REPLY:
741 		case SELECT_REPLY:
742 		case DESELECT_REPLY:
743 		case FSYNC_REPLY:
744 		case READ_SYMLINK_REPLY:
745 		case CREATE_SYMLINK_REPLY:
746 		case LINK_REPLY:
747 		case UNLINK_REPLY:
748 		case RENAME_REPLY:
749 		case ACCESS_REPLY:
750 		case READ_STAT_REPLY:
751 		case WRITE_STAT_REPLY:
752 			return true;
753 		// files
754 		case CREATE_REQUEST:
755 		case OPEN_REQUEST:
756 		case CLOSE_REQUEST:
757 		case FREE_COOKIE_REQUEST:
758 		case READ_REQUEST:
759 		case WRITE_REQUEST:
760 			return false;
761 		case CREATE_REPLY:
762 		case OPEN_REPLY:
763 		case CLOSE_REPLY:
764 		case FREE_COOKIE_REPLY:
765 		case READ_REPLY:
766 		case WRITE_REPLY:
767 			return true;
768 		// directories
769 		case CREATE_DIR_REQUEST:
770 		case REMOVE_DIR_REQUEST:
771 		case OPEN_DIR_REQUEST:
772 		case CLOSE_DIR_REQUEST:
773 		case FREE_DIR_COOKIE_REQUEST:
774 		case READ_DIR_REQUEST:
775 		case REWIND_DIR_REQUEST:
776 			return false;
777 		case CREATE_DIR_REPLY:
778 		case REMOVE_DIR_REPLY:
779 		case OPEN_DIR_REPLY:
780 		case CLOSE_DIR_REPLY:
781 		case FREE_DIR_COOKIE_REPLY:
782 		case READ_DIR_REPLY:
783 		case REWIND_DIR_REPLY:
784 			return true;
785 		// attribute directories
786 		case OPEN_ATTR_DIR_REQUEST:
787 		case CLOSE_ATTR_DIR_REQUEST:
788 		case FREE_ATTR_DIR_COOKIE_REQUEST:
789 		case READ_ATTR_DIR_REQUEST:
790 		case REWIND_ATTR_DIR_REQUEST:
791 			return false;
792 		case OPEN_ATTR_DIR_REPLY:
793 		case CLOSE_ATTR_DIR_REPLY:
794 		case FREE_ATTR_DIR_COOKIE_REPLY:
795 		case READ_ATTR_DIR_REPLY:
796 		case REWIND_ATTR_DIR_REPLY:
797 			return true;
798 		// attributes
799 		case CREATE_ATTR_REQUEST:
800 		case OPEN_ATTR_REQUEST:
801 		case CLOSE_ATTR_REQUEST:
802 		case FREE_ATTR_COOKIE_REQUEST:
803 		case READ_ATTR_REQUEST:
804 		case WRITE_ATTR_REQUEST:
805 		case RENAME_ATTR_REQUEST:
806 		case READ_ATTR_STAT_REQUEST:
807 		case WRITE_ATTR_STAT_REQUEST:
808 		case REMOVE_ATTR_REQUEST:
809 			return false;
810 		case CREATE_ATTR_REPLY:
811 		case OPEN_ATTR_REPLY:
812 		case CLOSE_ATTR_REPLY:
813 		case FREE_ATTR_COOKIE_REPLY:
814 		case READ_ATTR_REPLY:
815 		case WRITE_ATTR_REPLY:
816 		case READ_ATTR_STAT_REPLY:
817 		case WRITE_ATTR_STAT_REPLY:
818 		case RENAME_ATTR_REPLY:
819 		case REMOVE_ATTR_REPLY:
820 			return true;
821 		// indices
822 		case OPEN_INDEX_DIR_REQUEST:
823 		case CLOSE_INDEX_DIR_REQUEST:
824 		case FREE_INDEX_DIR_COOKIE_REQUEST:
825 		case READ_INDEX_DIR_REQUEST:
826 		case REWIND_INDEX_DIR_REQUEST:
827 		case CREATE_INDEX_REQUEST:
828 		case REMOVE_INDEX_REQUEST:
829 		case READ_INDEX_STAT_REQUEST:
830 			return false;
831 		case OPEN_INDEX_DIR_REPLY:
832 		case CLOSE_INDEX_DIR_REPLY:
833 		case FREE_INDEX_DIR_COOKIE_REPLY:
834 		case READ_INDEX_DIR_REPLY:
835 		case REWIND_INDEX_DIR_REPLY:
836 		case CREATE_INDEX_REPLY:
837 		case REMOVE_INDEX_REPLY:
838 		case READ_INDEX_STAT_REPLY:
839 			return true;
840 		// queries
841 		case OPEN_QUERY_REQUEST:
842 		case CLOSE_QUERY_REQUEST:
843 		case FREE_QUERY_COOKIE_REQUEST:
844 		case READ_QUERY_REQUEST:
845 		case REWIND_QUERY_REQUEST:
846 			return false;
847 		case OPEN_QUERY_REPLY:
848 		case CLOSE_QUERY_REPLY:
849 		case FREE_QUERY_COOKIE_REPLY:
850 		case READ_QUERY_REPLY:
851 		case REWIND_QUERY_REPLY:
852 			return true;
853 
854 		// userland -> kernel requests
855 		// notifications
856 		case NOTIFY_LISTENER_REQUEST:
857 		case NOTIFY_SELECT_EVENT_REQUEST:
858 		case NOTIFY_QUERY_REQUEST:
859 			return true;
860 		case NOTIFY_LISTENER_REPLY:
861 		case NOTIFY_SELECT_EVENT_REPLY:
862 		case NOTIFY_QUERY_REPLY:
863 			return false;
864 		// vnodes
865 		case GET_VNODE_REQUEST:
866 		case PUT_VNODE_REQUEST:
867 		case NEW_VNODE_REQUEST:
868 		case PUBLISH_VNODE_REQUEST:
869 		case REMOVE_VNODE_REQUEST:
870 		case UNREMOVE_VNODE_REQUEST:
871 		case GET_VNODE_REMOVED_REQUEST:
872 			return true;
873 		case GET_VNODE_REPLY:
874 		case PUT_VNODE_REPLY:
875 		case NEW_VNODE_REPLY:
876 		case PUBLISH_VNODE_REPLY:
877 		case REMOVE_VNODE_REPLY:
878 		case UNREMOVE_VNODE_REPLY:
879 		case GET_VNODE_REMOVED_REPLY:
880 			return false;
881 
882 		// general reply
883 		case RECEIPT_ACK_REPLY:
884 			return true;
885 		default:
886 			return false;
887 	}
888 }
889