-
Notifications
You must be signed in to change notification settings - Fork 0
/
FileSystem.cpp
240 lines (186 loc) · 6.25 KB
/
FileSystem.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
#include "Global.h"
#include "FileSystem.h"
#include <iostream>
#include <cstring>
using namespace std;
/*============================== SuperBlock ==============================*/
SuperBlock::SuperBlock() {
}
SuperBlock::~SuperBlock() {
}
/*============================== SuperBlock ==============================*/
/*============================== FileSystem ==============================*/
FileSystem::FileSystem() {
this->m_SuperBlock = &globalSuperBlock;
this->m_BufferManager = &globalBufferManager;
this->m_DeviceManager = &globalDeviceManager;
if (!this->m_DeviceManager->IsExist()) {
this->Format();
}
else {
this->LoadSuperBlock();
}
}
FileSystem::~FileSystem() {
this->Update();
}
void FileSystem::FormatSuperBlock() {
this->m_SuperBlock->s_isize = inode_block_num;
this->m_SuperBlock->s_fsize = disk_block_num;
this->m_SuperBlock->s_nfree = nfree_init;
this->m_SuperBlock->s_free[0] = -1;
this->m_SuperBlock->s_ninode = ninode_init;
}
void FileSystem::LoadSuperBlock() {
m_DeviceManager->read(m_SuperBlock, sizeof(SuperBlock), superblock_offset); // 读取SuperBlock
}
void FileSystem::Update() {
/* 引用全局变量 */
InodeTable& inodeTable = globalINodeTable;
/* 将superblock写回 */
for (int i = 0; i < superblock_block_num; i++) {
Buf* bp = this->m_BufferManager->GetBlk(i); // 读盘块进入缓存
memcpy(bp->b_addr, (int*)this->m_SuperBlock + i * 128 , block_size); // 更新缓存
m_BufferManager->Bwrite(bp); // 写回
}
/* 将InodeTable写回磁盘 */
inodeTable.UpdateInodeTable();
/* 将所有延迟写的buffer写回磁盘 */
m_BufferManager->Bflush();
}
void FileSystem::Format() {
/* 将SuperBlock初始化并写入磁盘 */
this->FormatSuperBlock();
this->m_DeviceManager->Open();
this->m_DeviceManager->write(this->m_SuperBlock, sizeof(SuperBlock), superblock_offset);
/* 将根目录初始化并写入磁盘 */
DiskInode root;
root.d_mode |= Inode::IALLOC | Inode::IFDIR;
root.d_nlink = 1;
this->m_DeviceManager->write(&root, sizeof(root));
/* 初始化SuperBlock的s_inode,并写入磁盘inode区 */
DiskInode diskInode;
for (int i = 1; i < inode_num; i++) {
if (this->m_SuperBlock->s_ninode < s_inode_size) {
this->m_SuperBlock->s_inode[this->m_SuperBlock->s_ninode++] = i;
}
this->m_DeviceManager->write(&diskInode, sizeof(diskInode));
}
char block[block_size], buffer[block_size];
memset(block, 0, sizeof(block));
for (int i = 0; i < data_block_num; i++) {
if (this->m_SuperBlock->s_nfree >= s_free_size) {
memcpy(buffer, &this->m_SuperBlock->s_nfree, sizeof(this->m_SuperBlock->s_free) + sizeof(int));
this->m_DeviceManager->write(buffer, block_size);
this->m_SuperBlock->s_nfree = nfree_init;
}
else {
this->m_DeviceManager->write(block, block_size);
}
this->m_SuperBlock->s_free[this->m_SuperBlock->s_nfree++] = i + data_offset;
}
/* 更新写入superblock */
this->m_DeviceManager->write(this->m_SuperBlock, sizeof(SuperBlock), superblock_offset);
}
Inode* FileSystem::IAlloc() {
/* 引用全局变量 */
User& user = globalUser;
InodeTable& inodeTable = globalINodeTable;
int inumber; // 分配到的空闲外存Inode编号
/* 判断SuperBlock是否还有直接管理的空闲Inode */
if (this->m_SuperBlock->s_ninode <= 0) {
inumber = NOT_FOUND;
/* 遍历磁盘Inode区的磁盘块 */
for (int i = 0; i < this->m_SuperBlock->s_isize; i++) {
Buf* bp = this->m_BufferManager->Bread(inode_offset + i); // 将磁盘Inode读入缓存
int* addrp = (int*)bp->b_addr; // 取缓冲区的首地址
/* 盘里该磁盘中的所有外存Inode */
for (int j = 0; j < inode_num_per_block; j++) {
inumber++;
int mode = *(addrp + j * sizeof(DiskInode) / sizeof(int)); // 取缓冲区第j个DiskInode的mode
/* 判断是否被占用 */
if (mode) {
continue;
}
/* 判断未更新的磁盘Inode在内存Inode中 */
if (inodeTable.IsLoaded(inumber) == NOT_FOUND) {
/* 加入空闲索引表 */
this->m_SuperBlock->s_inode[this->m_SuperBlock->s_ninode++] = inumber;
/* 判断是否装满 */
if (this->m_SuperBlock->s_ninode >= s_inode_size) {
break;
}
}
}
this->m_BufferManager->Brelse(bp); // 释放缓存
/* 判断是否装满 */
if (this->m_SuperBlock->s_ninode >= s_inode_size) {
break;
}
}
/* 没有找到任何空闲Inode */
if (m_SuperBlock->s_ninode <= 0) {
user.u_error = User::myENOSPC;
return NULL;
}
}
inumber = this->m_SuperBlock->s_inode[--this->m_SuperBlock->s_ninode];
/* 分配空闲的内存Inode */
Inode* ip = inodeTable.IGet(inumber);
if (ip == NULL) {
cerr << "没用空闲的内存Inode" << endl;
return NULL;
}
ip->Clean();
return ip;
}
void FileSystem::IFree(const int& inumber) {
/* 判断直接管理的外存Inode */
if (this->m_SuperBlock->s_ninode >= s_inode_size) {
return; // 直接散落在磁盘Inode区
}
/* 加入到直接管理的外存Inode */
this->m_SuperBlock->s_inode[this->m_SuperBlock->s_ninode++] = inumber;
}
Buf* FileSystem::Alloc() {
/* 引用全局变量 */
User& user = globalUser;
int blkno = this->m_SuperBlock->s_free[--this->m_SuperBlock->s_nfree]; // 从索引表栈顶取空闲磁盘块号
/* 分配出错 */
if (blkno <= 0) {
m_SuperBlock->s_nfree = 0;
user.u_error = User::myENOSPC;
return NULL;
}
/* 判断是否栈空 */
if (this->m_SuperBlock->s_nfree <= 0) {
Buf* bp = this->m_BufferManager->Bread(blkno); // 将栈顶磁盘块读入缓存
int* addrp = (int*)bp->b_addr; // 取缓存首地址
/* 更新m_SpuerBlock */
this->m_SuperBlock->s_nfree = *addrp++; // 读入空闲盘块数
memcpy(this->m_SuperBlock->s_free, addrp, sizeof(this->m_SuperBlock->s_free)); // 读入空闲盘块号
this->m_BufferManager->Brelse(bp); // 释放缓存
}
/* 分配空闲盘块对应的缓存 */
Buf* bp = this->m_BufferManager->GetBlk(blkno);
if (bp) {
this->m_BufferManager->Bclear(bp); // 清理缓存
}
return bp;
}
void FileSystem::Free(const int& blkno) {
/* 判断直接管理的空闲盘块是否已满 */
if (this->m_SuperBlock->s_nfree >= s_free_size) {
/* 将当前空前盘块读入blkno */
Buf* bp = this->m_BufferManager->GetBlk(blkno); // 分配缓存
int* addrp = (int*)bp->b_addr; // 缓存开始位置
*addrp++ = this->m_SuperBlock->s_nfree; // 将盘块数写入缓存
memcpy(addrp, this->m_SuperBlock->s_free, sizeof(int) * s_free_size); // 将盘块号写入缓存
this->m_BufferManager->Bwrite(bp); // 写回磁盘
/* 更新superblock */
this->m_SuperBlock->s_nfree = 0;
}
/* blkno加入空闲盘块 */
this->m_SuperBlock->s_free[this->m_SuperBlock->s_nfree++] = blkno;
}
/*============================== FileSystem ==============================*/