xref: /haiku/src/add-ons/kernel/file_systems/ufs2/Volume.cpp (revision 42f51416eb68b0a79f50fe185b6d0ecb064c62dc)
1 /*
2  * Copyright 2020 Suhel Mehta, mehtasuhel@gmail.com
3  * All rights reserved. Distributed under the terms of the MIT License.
4  */
5 #include "Volume.h"
6 
7 #include "DeviceOpener.h"
8 #include "Inode.h"
9 
10 
11 #define TRACE_UFS2
12 #ifdef TRACE_UFS2
13 #define TRACE(x...) dprintf("\33[34mufs2:\33[0m " x);
14 #else
15 #define TRACE(x...) ;
16 #endif
17 #define ERROR(x...) dprintf("\33[34mufs2:\33[0m " x)
18 
19 
20 bool
21 ufs2_super_block::IsValid()
22 {
23 	if (fs_magic != FS_UFS2_MAGIC)
24 		return false;
25 
26 	return true;
27 }
28 
29 
30 bool
31 Volume::IsValidSuperBlock()
32 {
33 	return fSuperBlock.IsValid();
34 }
35 
36 
37 Volume::Volume(fs_volume *volume)
38 	: fFSVolume(volume),
39 	fRootNode(NULL)
40 {
41 	fFlags = 0;
42 	mutex_init(&fLock, "ufs2 volume");
43 	TRACE("Volume::Volume() : Initialising volume\n");
44 }
45 
46 
47 Volume::~Volume()
48 {
49 	mutex_destroy(&fLock);
50 	TRACE("Volume::Destructor : Removing Volume\n");
51 }
52 
53 
54 status_t
55 Volume::Identify(int fd, ufs2_super_block *superBlock)
56 {
57 	if (read_pos(fd, SBLOCK_UFS2, superBlock,
58 		sizeof(ufs2_super_block)) != sizeof(ufs2_super_block))
59 		return B_IO_ERROR;
60 
61 
62 	if (!superBlock->IsValid()) {
63 		ERROR("Invalid superblock! Identify failed!!\n");
64 		return B_BAD_VALUE;
65 	}
66 
67 	return B_OK;
68 }
69 
70 
71 status_t
72 Volume::Mount(const char *deviceName, uint32 flags)
73 {
74 	TRACE("Mounting volume... Please wait.\n");
75 	flags |= B_MOUNT_READ_ONLY;
76 	if ((flags & B_MOUNT_READ_ONLY) != 0)
77 	{
78 		TRACE("Volume is read only\n");
79 	}
80 	else
81 	{
82 		TRACE("Volume is read write\n");
83 	}
84 
85 	DeviceOpener opener(deviceName, (flags & B_MOUNT_READ_ONLY) != 0
86 									? O_RDONLY:O_RDWR);
87 	fDevice = opener.Device();
88 	if (fDevice < B_OK) {
89 		ERROR("Could not open device\n");
90 		return fDevice;
91 	}
92 
93 	if (opener.IsReadOnly())
94 		fFlags |= VOLUME_READ_ONLY;
95 
96 	status_t status = Identify(fDevice, &fSuperBlock);
97 	if (status != B_OK) {
98 		ERROR("Invalid super block\n");
99 		return status;
100 	}
101 
102 	TRACE("Valid super block\n");
103 
104 	status = get_vnode(fFSVolume, UFS2_ROOT, (void**) &fRootNode);
105 	if (status != B_OK) {
106 		ERROR("could not create root node: get_vnode() failed! %d\n",status);
107 		return status;
108 	}
109 	fRootNode = new(std::nothrow) Inode(this, UFS2_ROOT);
110 	status = publish_vnode(fFSVolume, UFS2_ROOT, (void*)fRootNode,
111 			&gufs2VnodeOps, fRootNode->Mode(), 0);
112 	opener.Keep();
113 	return B_OK;
114 
115 }
116 
117 
118 status_t
119 Volume::Unmount()
120 {
121 	TRACE("Unmounting the volume");
122 
123 	TRACE("Closing device");
124 	close(fDevice);
125 
126 	return B_OK;
127 }
128