xref: /haiku/src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp (revision 4365774b6889e9467e4fd8719c5c89ca56240d28)
1 /*
2  * Copyright 2001-2017, Axel Dörfler, axeld@pinc-software.de.
3  * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
4  * All rights reserved. Distributed under the terms of the MIT License.
5  */
6 
7 
8 #include "system_dependencies.h"
9 #include "Directory.h"
10 #include "Inode.h"
11 #include "Volume.h"
12 
13 
14 #define XFS_IO_SIZE	65536
15 
16 struct identify_cookie
17 {
18 	/*	super_block_struct super_block;
19 	*	No structure yet implemented.
20 	*/
21 	int cookie;
22 };
23 
24 
25 //!	xfs_io() callback hook
26 static status_t
27 iterative_io_get_vecs_hook(void *cookie, io_request *request, off_t offset,
28 	size_t size, struct file_io_vec *vecs, size_t *_count)
29 {
30 	return B_NOT_SUPPORTED;
31 }
32 
33 
34 //!	xfs_io() callback hook
35 static status_t
36 iterative_io_finished_hook(void *cookie, io_request *request, status_t status,
37 	bool partialTransfer, size_t bytesTransferred)
38 {
39 	return B_NOT_SUPPORTED;
40 }
41 
42 
43 //	#pragma mark - Scanning
44 
45 
46 static float
47 xfs_identify_partition(int fd, partition_data *partition, void **_cookie)
48 {
49 	return B_NOT_SUPPORTED;
50 }
51 
52 
53 static status_t
54 xfs_scan_partition(int fd, partition_data *partition, void *_cookie)
55 {
56 	return B_NOT_SUPPORTED;
57 }
58 
59 
60 static void
61 xfs_free_identify_partition_cookie(partition_data *partition, void *_cookie)
62 {
63 	dprintf("Unsupported in XFS currently.\n");
64 	return;
65 }
66 
67 
68 //	#pragma mark -
69 
70 
71 static status_t
72 xfs_mount(fs_volume *_volume, const char *device, uint32 flags,
73 	const char *args, ino_t *_rootID)
74 {
75 	TRACE("xfs_mount(): Trying to mount\n");
76 
77 	Volume *volume = new (std::nothrow) Volume(_volume);
78 	if (volume == NULL)
79 		return B_NO_MEMORY;
80 
81 	_volume->private_volume = volume;
82 	_volume->ops = &gxfsVolumeOps;
83 
84 	status_t status = volume->Mount(device, flags);
85 	if (status != B_OK) {
86 		ERROR("Failed mounting the volume. Error: %s\n", strerror(status));
87 		delete volume;
88 		_volume->private_volume = NULL;
89 		return status;
90 	}
91 
92 	*_rootID = volume->Root();
93 	return B_OK;
94 }
95 
96 
97 static status_t
98 xfs_unmount(fs_volume *_volume)
99 {
100 	Volume* volume = (Volume*) _volume->private_volume;
101 
102 	status_t status = volume->Unmount();
103 	delete volume;
104 	TRACE("xfs_unmount(): Deleted volume");
105 	return status;
106 }
107 
108 
109 static status_t
110 xfs_read_fs_info(fs_volume *_volume, struct fs_info *info)
111 {
112 	TRACE("XFS_READ_FS_INFO:\n");
113 	Volume* volume = (Volume*)_volume->private_volume;
114 
115 	info->flags = B_FS_IS_READONLY
116 					| B_FS_HAS_ATTR | B_FS_IS_PERSISTENT;
117 
118 	info->io_size = XFS_IO_SIZE;
119 	info->block_size = volume->SuperBlock().BlockSize();
120 	info->total_blocks = volume->SuperBlock().TotalBlocks();
121 	info->free_blocks = volume->SuperBlock().FreeBlocks();
122 
123 	strlcpy(info->volume_name, volume->Name(), sizeof(info->volume_name));
124 	strlcpy(info->fsh_name, "xfs", sizeof(info->fsh_name));
125 
126 	return B_OK;
127 }
128 
129 
130 //	#pragma mark -
131 
132 
133 static status_t
134 xfs_get_vnode(fs_volume *_volume, ino_t id, fs_vnode *_node, int *_type,
135 	uint32 *_flags, bool reenter)
136 {
137 	TRACE("XFS_GET_VNODE:\n");
138 	Volume* volume = (Volume*)_volume->private_volume;
139 
140 	Inode* inode = new(std::nothrow) Inode(volume, id);
141 	if (inode == NULL)
142 		return B_NO_MEMORY;
143 
144 	status_t status = inode->Init();
145 	if (status != B_OK) {
146 		delete inode;
147 		ERROR("get_vnode: InitCheck() failed. Error: %s\n", strerror(status));
148 		return B_NO_INIT;
149 	}
150 
151 	_node->private_node = inode;
152 	_node->ops = &gxfsVnodeOps;
153 	*_type = inode->Mode();
154 	*_flags = 0;
155 	TRACE("(%ld)\n", inode->ID());
156 	return B_OK;
157 }
158 
159 
160 static status_t
161 xfs_put_vnode(fs_volume *_volume, fs_vnode *_node, bool reenter)
162 {
163 	TRACE("XFS_PUT_VNODE:\n");
164 	delete (Inode*)_node->private_node;
165 	return B_OK;
166 }
167 
168 
169 static bool
170 xfs_can_page(fs_volume *_volume, fs_vnode *_node, void *_cookie)
171 {
172 	return B_NOT_SUPPORTED;
173 }
174 
175 
176 static status_t
177 xfs_read_pages(fs_volume *_volume, fs_vnode *_node, void *_cookie,
178 	off_t pos, const iovec *vecs, size_t count, size_t *_numBytes)
179 {
180 	return B_NOT_SUPPORTED;
181 }
182 
183 
184 static status_t
185 xfs_io(fs_volume *_volume, fs_vnode *_node, void *_cookie,
186 	io_request *request)
187 {
188 	return B_NOT_SUPPORTED;
189 }
190 
191 
192 static status_t
193 xfs_get_file_map(fs_volume *_volume, fs_vnode *_node, off_t offset,
194 	size_t size, struct file_io_vec *vecs, size_t *_count)
195 {
196 	return B_NOT_SUPPORTED;
197 }
198 
199 
200 //	#pragma mark -
201 
202 
203 static status_t
204 xfs_lookup(fs_volume *_volume, fs_vnode *_directory, const char *name,
205 	ino_t *_vnodeID)
206 {
207 	TRACE("XFS_LOOKUP: %p (%s)\n", name, name);
208 	Volume* volume = (Volume*)_volume->private_volume;
209 	Inode* directory = (Inode*)_directory->private_node;
210 
211 	if (!directory->IsDirectory())
212 		return B_NOT_A_DIRECTORY;
213 
214 	status_t status = directory->CheckPermissions(X_OK);
215 	if (status < B_OK)
216 		return status;
217 
218 	DirectoryIterator* iterator =
219 		new(std::nothrow) DirectoryIterator(directory);
220 	if (iterator == NULL)
221 		return B_NO_MEMORY;
222 
223 	status = iterator->Init();
224 	if (status != B_OK) {
225 		delete iterator;
226 		return status;
227 	}
228 
229 	status = iterator->Lookup(name, strlen(name), (xfs_ino_t*)_vnodeID);
230 	if (status != B_OK) {
231 		delete iterator;
232 		return status;
233 	}
234 
235 	TRACE("XFS_LOOKUP: ID: (%ld)\n", *_vnodeID);
236 	status = get_vnode(volume->FSVolume(), *_vnodeID, NULL);
237 	TRACE("get_vnode status: (%d)\n", status);
238 	return status;
239 }
240 
241 
242 static status_t
243 xfs_ioctl(fs_volume *_volume, fs_vnode *_node, void *_cookie, uint32 cmd,
244 	void *buffer, size_t bufferLength)
245 {
246 	return B_NOT_SUPPORTED;
247 }
248 
249 
250 static status_t
251 xfs_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat)
252 {
253 	Inode* inode = (Inode*)_node->private_node;
254 	TRACE("XFS_READ_STAT: id: (%ld)\n", inode->ID());
255 	stat->st_dev = inode->GetVolume()->ID();
256 	stat->st_ino = inode->ID();
257 	stat->st_nlink = 1;
258 	stat->st_blksize = XFS_IO_SIZE;
259 
260 	stat->st_uid = inode->UserId();
261 	stat->st_gid = inode->GroupId();
262 	stat->st_mode = inode->Mode();
263 	stat->st_type = 0;	// TODO
264 
265 	stat->st_size = inode->Size();
266 	stat->st_blocks = inode->BlockCount();
267 
268 	inode->GetAccessTime(stat->st_atim);
269 	inode->GetModificationTime(stat->st_mtim);
270 	inode->GetChangeTime(stat->st_ctim);
271 
272 	/* TODO: Can we obtain the Creation Time in v4 system? */
273 	inode->GetChangeTime(stat->st_crtim);
274 
275 	return B_OK;
276 
277 }
278 
279 
280 static status_t
281 xfs_open(fs_volume * /*_volume*/, fs_vnode *_node, int openMode,
282 	void **_cookie)
283 {
284 	return B_NOT_SUPPORTED;
285 }
286 
287 
288 static status_t
289 xfs_read(fs_volume *_volume, fs_vnode *_node, void *_cookie, off_t pos,
290 	void *buffer, size_t *_length)
291 {
292 	return B_NOT_SUPPORTED;
293 }
294 
295 
296 static status_t
297 xfs_close(fs_volume *_volume, fs_vnode *_node, void *_cookie)
298 {
299 	return B_NOT_SUPPORTED;
300 }
301 
302 
303 static status_t
304 xfs_free_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie)
305 {
306 	return B_NOT_SUPPORTED;
307 }
308 
309 
310 static status_t
311 xfs_access(fs_volume *_volume, fs_vnode *_node, int accessMode)
312 {
313 	Inode* inode = (Inode*)_node->private_node;
314 	return inode->CheckPermissions(accessMode);
315 }
316 
317 
318 static status_t
319 xfs_read_link(fs_volume *_volume, fs_vnode *_node, char *buffer,
320 	size_t *_bufferSize)
321 {
322 	return B_NOT_SUPPORTED;
323 }
324 
325 
326 status_t
327 xfs_unlink(fs_volume *_volume, fs_vnode *_directory, const char *name)
328 {
329 	return B_NOT_SUPPORTED;
330 }
331 
332 
333 //	#pragma mark - Directory functions
334 
335 
336 static status_t
337 xfs_create_dir(fs_volume *_volume, fs_vnode *_directory, const char *name,
338 	int mode)
339 {
340 	return B_NOT_SUPPORTED;
341 }
342 
343 
344 static status_t
345 xfs_remove_dir(fs_volume *_volume, fs_vnode *_directory, const char *name)
346 {
347 	return B_NOT_SUPPORTED;
348 }
349 
350 
351 static status_t
352 xfs_open_dir(fs_volume * /*_volume*/, fs_vnode *_node, void **_cookie)
353 {
354 	Inode* inode = (Inode*)_node->private_node;
355 	TRACE("XFS_OPEN_DIR: (%ld)\n", inode->ID());
356 
357 	status_t status = inode->CheckPermissions(R_OK);
358 	if (status < B_OK)
359 		return status;
360 
361 	if (!inode->IsDirectory())
362 		return B_NOT_A_DIRECTORY;
363 
364 	DirectoryIterator* iterator = new(std::nothrow) DirectoryIterator(inode);
365 	if (iterator == NULL) {
366 		delete iterator;
367 		return B_NO_MEMORY;
368 	}
369 	status = iterator->Init();
370 	*_cookie = iterator;
371 	return status;
372 }
373 
374 
375 static status_t
376 xfs_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
377 	struct dirent *buffer, size_t bufferSize, uint32 *_num)
378 {
379 	TRACE("XFS_READ_DIR\n");
380 	DirectoryIterator* iterator = (DirectoryIterator*)_cookie;
381 	Volume* volume = (Volume*)_volume->private_volume;
382 
383 	uint32 maxCount = *_num;
384 	uint32 count = 0;
385 
386 	while (count < maxCount && (bufferSize > sizeof(struct dirent))) {
387 		size_t length = bufferSize - sizeof(struct dirent) + 1;
388 		xfs_ino_t ino;
389 
390 		status_t status = iterator->GetNext(buffer->d_name, &length, &ino);
391 		if (status == B_ENTRY_NOT_FOUND)
392 			break;
393 		if (status == B_BUFFER_OVERFLOW) {
394 			if (count == 0)
395 				return status;
396 			break;
397 		}
398 		if (status != B_OK)
399 			return status;
400 
401 		buffer->d_dev = volume->ID();
402 		buffer->d_ino = ino;
403 		buffer->d_reclen = sizeof(struct dirent) + length;
404 		bufferSize -= buffer->d_reclen;
405 		buffer = (struct dirent*)((uint8*)buffer + buffer->d_reclen);
406 		count++;
407 	}
408 
409 	*_num = count;
410 	TRACE("Count: (%d)\n", count);
411 	return B_OK;
412 }
413 
414 
415 static status_t
416 xfs_rewind_dir(fs_volume * /*_volume*/, fs_vnode * /*node*/, void *_cookie)
417 {
418 	return B_NOT_SUPPORTED;
419 }
420 
421 
422 static status_t
423 xfs_close_dir(fs_volume * /*_volume*/, fs_vnode * /*node*/,
424 	void * /*_cookie*/)
425 {
426 	return B_NOT_SUPPORTED;
427 }
428 
429 
430 static status_t
431 xfs_free_dir_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie)
432 {
433 	return B_NOT_SUPPORTED;
434 }
435 
436 
437 static status_t
438 xfs_open_attr_dir(fs_volume *_volume, fs_vnode *_node, void **_cookie)
439 {
440 	return B_NOT_SUPPORTED;
441 }
442 
443 
444 static status_t
445 xfs_close_attr_dir(fs_volume *_volume, fs_vnode *_node, void *cookie)
446 {
447 	return B_NOT_SUPPORTED;
448 }
449 
450 
451 static status_t
452 xfs_free_attr_dir_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie)
453 {
454 	return B_NOT_SUPPORTED;
455 }
456 
457 
458 static status_t
459 xfs_read_attr_dir(fs_volume *_volume, fs_vnode *_node,
460 	void *_cookie, struct dirent *dirent, size_t bufferSize, uint32 *_num)
461 {
462 	return B_NOT_SUPPORTED;
463 }
464 
465 
466 static status_t
467 xfs_rewind_attr_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie)
468 {
469 	return B_NOT_SUPPORTED;
470 }
471 
472 
473 /* attribute operations */
474 static status_t
475 xfs_create_attr(fs_volume *_volume, fs_vnode *_node,
476 	const char *name, uint32 type, int openMode, void **_cookie)
477 {
478 	return B_NOT_SUPPORTED;
479 }
480 
481 
482 static status_t
483 xfs_open_attr(fs_volume *_volume, fs_vnode *_node, const char *name,
484 	int openMode, void **_cookie)
485 {
486 	return B_NOT_SUPPORTED;
487 }
488 
489 
490 static status_t
491 xfs_close_attr(fs_volume *_volume, fs_vnode *_node,
492 	void *cookie)
493 {
494 	return B_NOT_SUPPORTED;
495 }
496 
497 
498 static status_t
499 xfs_free_attr_cookie(fs_volume *_volume, fs_vnode *_node, void *cookie)
500 {
501 	return B_NOT_SUPPORTED;
502 }
503 
504 
505 static status_t
506 xfs_read_attr(fs_volume *_volume, fs_vnode *_node, void *_cookie,
507 	off_t pos, void *buffer, size_t *_length)
508 {
509 	return B_NOT_SUPPORTED;
510 }
511 
512 
513 static status_t
514 xfs_write_attr(fs_volume *_volume, fs_vnode *_node, void *cookie,
515 	off_t pos, const void *buffer, size_t *length)
516 {
517 	return B_NOT_SUPPORTED;
518 }
519 
520 
521 static status_t
522 xfs_read_attr_stat(fs_volume *_volume, fs_vnode *_node,
523 	void *_cookie, struct stat *stat)
524 {
525 	return B_NOT_SUPPORTED;
526 }
527 
528 
529 static status_t
530 xfs_write_attr_stat(fs_volume *_volume, fs_vnode *_node,
531 	void *cookie, const struct stat *stat, int statMask)
532 {
533 	return B_NOT_SUPPORTED;
534 }
535 
536 
537 static status_t
538 xfs_rename_attr(fs_volume *_volume, fs_vnode *fromVnode,
539 	const char *fromName, fs_vnode *toVnode, const char *toName)
540 {
541 	return B_NOT_SUPPORTED;
542 }
543 
544 
545 static status_t
546 xfs_remove_attr(fs_volume *_volume, fs_vnode *vnode,
547 	const char *name)
548 {
549 	return B_NOT_SUPPORTED;
550 }
551 
552 
553 static uint32
554 xfs_get_supported_operations(partition_data *partition, uint32 mask)
555 {
556 	return B_NOT_SUPPORTED;
557 }
558 
559 
560 static status_t
561 xfs_initialize(int fd, partition_id partitionID, const char *name,
562 	const char *parameterString, off_t partitionSize, disk_job_id job)
563 {
564 	return B_NOT_SUPPORTED;
565 }
566 
567 
568 static status_t
569 xfs_uninitialize(int fd, partition_id partitionID, off_t partitionSize,
570 	uint32 blockSize, disk_job_id job)
571 {
572 	return B_NOT_SUPPORTED;
573 }
574 
575 
576 //	#pragma mark -
577 
578 
579 static status_t
580 xfs_std_ops(int32 op, ...)
581 {
582 	switch (op)
583 	{
584 	case B_MODULE_INIT:
585 #ifdef XFS_DEBUGGER_COMMANDS
586 		// Perform nothing at the moment
587 		// add_debugger_commands();
588 #endif
589 		return B_OK;
590 	case B_MODULE_UNINIT:
591 #ifdef XFS_DEBUGGER_COMMANDS
592 		// Perform nothing at the moment
593 		// remove_debugger_commands();
594 #endif
595 		return B_OK;
596 
597 	default:
598 		return B_ERROR;
599 	}
600 }
601 
602 
603 fs_volume_ops gxfsVolumeOps = {
604 	&xfs_unmount,
605 	&xfs_read_fs_info,
606 	NULL,				// write_fs_info()
607 	NULL,				// fs_sync,
608 	&xfs_get_vnode,
609 };
610 
611 
612 fs_vnode_ops gxfsVnodeOps = {
613 	/* vnode operations */
614 	&xfs_lookup,
615 	NULL,				// xfs_get_vnode_name- optional, and we can't do better
616 						// than the fallback implementation, so leave as NULL.
617 	&xfs_put_vnode,
618 	NULL, 				// xfs_remove_vnode,
619 
620 	/* VM file access */
621 	&xfs_can_page,
622 	&xfs_read_pages,
623 	NULL,				// xfs_write_pages,
624 
625 	&xfs_io,			// io()
626 	NULL,				// cancel_io()
627 
628 	&xfs_get_file_map,
629 
630 	&xfs_ioctl,
631 	NULL,
632 	NULL,				// fs_select
633 	NULL,				// fs_deselect
634 	NULL,				// fs_fsync,
635 
636 	&xfs_read_link,
637 	NULL,				// fs_create_symlink,
638 
639 	NULL,				// fs_link,
640 	&xfs_unlink,
641 	NULL,				// fs_rename,
642 
643 	&xfs_access,
644 	&xfs_read_stat,
645 	NULL,				// fs_write_stat,
646 	NULL,				// fs_preallocate
647 
648 	/* file operations */
649 	NULL,				// fs_create,
650 	&xfs_open,
651 	&xfs_close,
652 	&xfs_free_cookie,
653 	&xfs_read,
654 	NULL,				// fs_write,
655 
656 	/* directory operations */
657 	&xfs_create_dir,
658 	&xfs_remove_dir,
659 	&xfs_open_dir,
660 	&xfs_close_dir,
661 	&xfs_free_dir_cookie,
662 	&xfs_read_dir,
663 	&xfs_rewind_dir,
664 
665 	/* attribute directory operations */
666 	&xfs_open_attr_dir,
667 	&xfs_close_attr_dir,
668 	&xfs_free_attr_dir_cookie,
669 	&xfs_read_attr_dir,
670 	&xfs_rewind_attr_dir,
671 
672 	/* attribute operations */
673 	&xfs_create_attr,
674 	&xfs_open_attr,
675 	&xfs_close_attr,
676 	&xfs_free_attr_cookie,
677 	&xfs_read_attr,
678 	&xfs_write_attr,
679 	&xfs_read_attr_stat,
680 	&xfs_write_attr_stat,
681 	&xfs_rename_attr,
682 	&xfs_remove_attr,
683 };
684 
685 
686 static
687 file_system_module_info sxfsFileSystem = {
688 	{
689 		"file_systems/xfs" B_CURRENT_FS_API_VERSION,
690 		0,
691 		xfs_std_ops,
692 	},
693 
694 	"xfs",				// short_name
695 	"XFS File System",	// pretty_name
696 
697 	// DDM flags
698 	0 |B_DISK_SYSTEM_SUPPORTS_INITIALIZING |B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME
699 	//	| B_DISK_SYSTEM_SUPPORTS_WRITING
700 	,
701 
702 	// scanning
703 	xfs_identify_partition,
704 	xfs_scan_partition,
705 	xfs_free_identify_partition_cookie,
706 	NULL,				// free_partition_content_cookie()
707 
708 	&xfs_mount,
709 
710 	/* capability querying operations */
711 	&xfs_get_supported_operations,
712 
713 	NULL,				// validate_resize
714 	NULL,				// validate_move
715 	NULL,				// validate_set_content_name
716 	NULL,				// validate_set_content_parameters
717 	NULL,				// validate_initialize,
718 
719 	/* shadow partition modification */
720 	NULL,				// shadow_changed
721 
722 	/* writing */
723 	NULL,				// defragment
724 	NULL,				// repair
725 	NULL,				// resize
726 	NULL,				// move
727 	NULL,				// set_content_name
728 	NULL,				// set_content_parameters
729 	xfs_initialize,
730 	xfs_uninitialize};
731 
732 module_info *modules[] = {
733 	(module_info *)&sxfsFileSystem,
734 	NULL,
735 };
736