xref: /haiku/src/add-ons/kernel/file_systems/xfs/Volume.cpp (revision 830f67ef991407f287dbc1238aa5f5906d90c991)
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 "Volume.h"
9 
10 #include "Inode.h"
11 
12 
13 Volume::Volume(fs_volume *volume)
14 	: fFSVolume(volume)
15 {
16 	fFlags = 0;
17 	mutex_init(&fLock, "xfs volume");
18 	TRACE("Volume::Volume() : Initialising volume");
19 }
20 
21 
22 Volume::~Volume()
23 {
24 	mutex_destroy(&fLock);
25 	TRACE("Volume::Destructor : Removing Volume");
26 }
27 
28 
29 bool
30 Volume::IsValidSuperBlock() const
31 {
32 	return fSuperBlock.IsValid();
33 }
34 
35 
36 status_t
37 Volume::Identify(int fd, XfsSuperBlock *superBlock)
38 {
39 
40 	TRACE("Volume::Identify() : Identifying Volume in progress");
41 
42 	if (read_pos(fd, 0, superBlock, sizeof(XfsSuperBlock))
43 		!= sizeof(XfsSuperBlock))
44 			return B_IO_ERROR;
45 
46 	superBlock->SwapEndian();
47 
48 	if (!superBlock->IsValid()) {
49 		ERROR("Volume::Identify(): Invalid Superblock!\n");
50 		return B_BAD_VALUE;
51 	}
52 	return B_OK;
53 }
54 
55 
56 status_t
57 Volume::Mount(const char *deviceName, uint32 flags)
58 {
59 	TRACE("Volume::Mount() : Mounting in progress");
60 
61 	flags |= B_MOUNT_READ_ONLY;
62 
63 	if ((flags & B_MOUNT_READ_ONLY) != 0) {
64 		TRACE("Volume::Mount(): Read only\n");
65 	} else {
66 		TRACE("Volume::Mount(): Read write\n");
67 	}
68 
69 	DeviceOpener opener(deviceName, (flags & B_MOUNT_READ_ONLY) != 0
70 										? O_RDONLY
71 										: O_RDWR);
72 	fDevice = opener.Device();
73 	if (fDevice < B_OK) {
74 		ERROR("Volume::Mount(): couldn't open device\n");
75 		return fDevice;
76 	}
77 
78 	if (opener.IsReadOnly())
79 		fFlags |= VOLUME_READ_ONLY;
80 
81 	// read the superblock
82 	status_t status = Identify(fDevice, &fSuperBlock);
83 	if (status != B_OK) {
84 		ERROR("Volume::Mount(): Invalid super block!\n");
85 		return B_BAD_VALUE;
86 	}
87 
88 	TRACE("Volume::Mount(): Valid SuperBlock.\n");
89 
90 	// check if the device size is large enough to hold the file system
91 	off_t diskSize;
92 	if (opener.GetSize(&diskSize) != B_OK) {
93 		ERROR("Volume:Mount() Unable to get diskSize");
94 		return B_ERROR;
95 	}
96 
97 	opener.Keep();
98 
99 	//publish the root inode
100 	Inode* rootInode = new(std::nothrow) Inode(this, Root());
101 	if (rootInode == NULL)
102 		return B_NO_MEMORY;
103 
104 	status = rootInode->Init();
105 	if (status != B_OK)
106 		return status;
107 
108 	status = publish_vnode(FSVolume(), Root(),
109 		(void*)rootInode, &gxfsVnodeOps, rootInode->Mode(), 0);
110 	if (status != B_OK)
111 		return B_BAD_VALUE;
112 
113 	return B_OK;
114 }
115 
116 
117 status_t
118 Volume::Unmount()
119 {
120 	TRACE("Volume::Unmount(): Unmounting");
121 
122 	TRACE("Volume::Unmount(): Closing device");
123 	close(fDevice);
124 
125 	return B_OK;
126 }
127