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
|
#include "fs.h"
#include "inode.h"
#include "super.h"
#include <minix/vfsif.h>
#include <minix/bdev.h>
/*===========================================================================*
* fs_mount *
*===========================================================================*/
int fs_mount(dev_t dev, unsigned int flags, struct fsdriver_node *root_node,
unsigned int *res_flags)
{
/* This function reads the superblock of the partition, gets the root inode
* and sends back the details of them.
*/
struct inode *root_ip;
int r, readonly;
fs_dev = dev;
readonly = (flags & REQ_RDONLY) ? 1 : 0;
/* Open the device the file system lives on. */
if (bdev_open(fs_dev, readonly ? BDEV_R_BIT : (BDEV_R_BIT|BDEV_W_BIT) ) !=
OK) {
return(EINVAL);
}
/* Fill in the super block. */
superblock.s_dev = fs_dev; /* read_super() needs to know which dev */
r = read_super(&superblock);
/* Is it recognized as a Minix filesystem? */
if (r != OK) {
superblock.s_dev = NO_DEV;
bdev_close(fs_dev);
return(r);
}
/* clean check: if rw and not clean, switch to readonly */
if(!(superblock.s_flags & MFSFLAG_CLEAN) && !readonly) {
if(bdev_close(fs_dev) != OK)
panic("couldn't bdev_close after found unclean FS");
readonly = 1;
if (bdev_open(fs_dev, BDEV_R_BIT) != OK) {
panic("couldn't bdev_open after found unclean FS");
return(EINVAL);
}
printf("MFS: WARNING: FS 0x%llx unclean, mounting readonly\n", fs_dev);
}
lmfs_set_blocksize(superblock.s_block_size);
/* Compute the current number of used zones, and report it to libminixfs.
* Note that libminixfs really wants numbers of *blocks*, but this MFS
* implementation dropped support for differing zone/block sizes a while ago.
*/
used_zones = superblock.s_zones - count_free_bits(&superblock, ZMAP);
lmfs_set_blockusage(superblock.s_zones, used_zones);
/* Get the root inode of the mounted file system. */
if( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NULL) {
printf("MFS: couldn't get root inode\n");
superblock.s_dev = NO_DEV;
bdev_close(fs_dev);
return(EINVAL);
}
if(root_ip->i_mode == 0) {
printf("%s:%d zero mode for root inode?\n", __FILE__, __LINE__);
put_inode(root_ip);
superblock.s_dev = NO_DEV;
bdev_close(fs_dev);
return(EINVAL);
}
superblock.s_rd_only = readonly;
/* Root inode properties */
root_node->fn_ino_nr = root_ip->i_num;
root_node->fn_mode = root_ip->i_mode;
root_node->fn_size = root_ip->i_size;
root_node->fn_uid = root_ip->i_uid;
root_node->fn_gid = root_ip->i_gid;
root_node->fn_dev = NO_DEV;
*res_flags = RES_NOFLAGS;
/* Mark it dirty */
if(!superblock.s_rd_only) {
superblock.s_flags &= ~MFSFLAG_CLEAN;
if(write_super(&superblock) != OK)
panic("mounting: couldn't write dirty superblock");
}
return(r);
}
/*===========================================================================*
* fs_mountpt *
*===========================================================================*/
int fs_mountpt(ino_t ino_nr)
{
/* This function looks up the mount point, it checks the condition whether
* the partition can be mounted on the inode or not.
*/
register struct inode *rip;
int r = OK;
mode_t bits;
/* Temporarily open the file. */
if( (rip = get_inode(fs_dev, ino_nr)) == NULL)
return(EINVAL);
if(rip->i_mountpoint) r = EBUSY;
/* It may not be special. */
bits = rip->i_mode & I_TYPE;
if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL) r = ENOTDIR;
put_inode(rip);
if(r == OK) rip->i_mountpoint = TRUE;
return(r);
}
/*===========================================================================*
* fs_unmount *
*===========================================================================*/
void fs_unmount(void)
{
/* Unmount a file system. */
int count;
struct inode *rip, *root_ip;
/* See if the mounted device is busy. Only 1 inode using it should be
* open --the root inode-- and that inode only 1 time. This is an integrity
* check only: VFS expects the unmount to succeed either way.
*/
count = 0;
for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++)
if (rip->i_count > 0 && rip->i_dev == fs_dev) count += rip->i_count;
if (count != 1)
printf("MFS: file system has %d in-use inodes!\n", count);
if ((root_ip = find_inode(fs_dev, ROOT_INODE)) == NULL)
panic("MFS: couldn't find root inode\n");
put_inode(root_ip);
/* force any cached blocks out of memory */
fs_sync();
/* Mark it clean if we're allowed to write _and_ it was clean originally. */
if (!superblock.s_rd_only) {
superblock.s_flags |= MFSFLAG_CLEAN;
write_super(&superblock);
}
/* Close the device the file system lives on. */
bdev_close(fs_dev);
/* Throw out blocks out of the VM cache, to prevent corruption later. */
lmfs_invalidate(fs_dev);
/* Finish off the unmount. */
superblock.s_dev = NO_DEV;
}
|