xref: /haiku/src/add-ons/kernel/file_systems/ufs2/Volume.cpp (revision e1c4049fed1047bdb957b0529e1921e97ef94770)
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 const char*
31 Volume::Name() const
32 {
33 	// The name may be empty, in that case, userspace will generate one.
34 	return fSuperBlock.fs_volname;
35 }
36 
37 
38 bool
39 Volume::IsValidSuperBlock()
40 {
41 	return fSuperBlock.IsValid();
42 }
43 
44 
45 Volume::Volume(fs_volume *volume)
46 	: fFSVolume(volume),
47 	fRootNode(NULL)
48 {
49 	fFlags = 0;
50 	mutex_init(&fLock, "ufs2 volume");
51 	TRACE("Volume::Volume() : Initialising volume\n");
52 }
53 
54 
55 Volume::~Volume()
56 {
57 	mutex_destroy(&fLock);
58 	TRACE("Volume::Destructor : Removing Volume\n");
59 }
60 
61 
62 status_t
63 Volume::Identify(int fd, ufs2_super_block *superBlock)
64 {
65 	if (read_pos(fd, SBLOCK_UFS2, superBlock,
66 		sizeof(ufs2_super_block)) != sizeof(ufs2_super_block))
67 		return B_IO_ERROR;
68 
69 
70 	if (!superBlock->IsValid()) {
71 		ERROR("Invalid superblock! Identify failed!!\n");
72 		return B_BAD_VALUE;
73 	}
74 
75 	return B_OK;
76 }
77 
78 
79 status_t
80 Volume::Mount(const char *deviceName, uint32 flags)
81 {
82 	TRACE("Mounting volume... Please wait.\n");
83 	flags |= B_MOUNT_READ_ONLY;
84 	if ((flags & B_MOUNT_READ_ONLY) != 0)
85 	{
86 		TRACE("Volume is read only\n");
87 	}
88 	else
89 	{
90 		TRACE("Volume is read write\n");
91 	}
92 
93 	DeviceOpener opener(deviceName, (flags & B_MOUNT_READ_ONLY) != 0
94 									? O_RDONLY:O_RDWR);
95 	fDevice = opener.Device();
96 	if (fDevice < B_OK) {
97 		ERROR("Could not open device\n");
98 		return fDevice;
99 	}
100 
101 	if (opener.IsReadOnly())
102 		fFlags |= VOLUME_READ_ONLY;
103 
104 	status_t status = Identify(fDevice, &fSuperBlock);
105 	if (status != B_OK) {
106 		ERROR("Invalid super block\n");
107 		return status;
108 	}
109 
110 	TRACE("Valid super block\n");
111 
112 	fRootNode = new(std::nothrow) Inode(this, UFS2_ROOT);
113 	status = publish_vnode(this->FSVolume(), UFS2_ROOT, (void*)fRootNode,
114 			&gufs2VnodeOps, fRootNode->Mode(), 0);
115 
116 	opener.Keep();
117 	return B_OK;
118 
119 }
120 
121 
122 status_t
123 Volume::Unmount()
124 {
125 	TRACE("Unmounting the volume");
126 
127 	TRACE("Closing device");
128 	close(fDevice);
129 
130 	return B_OK;
131 }
132