1 /* Created (MFS based):
2 * February 2010 (Evgeniy Ivanov)
10 #include <minix/vfsif.h>
11 #include <minix/bdev.h>
14 /*===========================================================================*
16 *===========================================================================*/
17 int fs_mount(dev_t dev
, unsigned int flags
, struct fsdriver_node
*root_node
,
18 unsigned int *res_flags
)
20 /* This function reads the superblock of the partition, gets the root inode
21 * and sends back the details of them.
23 struct inode
*root_ip
;
28 readonly
= (flags
& REQ_RDONLY
) ? 1 : 0;
30 /* Open the device the file system lives on. */
31 if (bdev_open(fs_dev
, readonly
? BDEV_R_BIT
: (BDEV_R_BIT
|BDEV_W_BIT
)) !=
36 /* Fill in the super block. */
37 if(!(superblock
= malloc(sizeof(*superblock
))))
38 panic("Can't allocate memory for superblock.");
40 superblock
->s_dev
= fs_dev
; /* read_super() needs to know which dev */
41 r
= read_super(superblock
);
43 /* Is it recognized as a Minix filesystem? */
45 superblock
->s_dev
= NO_DEV
;
50 if (superblock
->s_rev_level
!= EXT2_GOOD_OLD_REV
) {
51 struct super_block
*sp
= superblock
; /* just shorter name */
52 mask
= ~SUPPORTED_INCOMPAT_FEATURES
;
53 if (HAS_INCOMPAT_FEATURE(sp
, mask
)) {
54 if (HAS_INCOMPAT_FEATURE(sp
, INCOMPAT_COMPRESSION
& mask
))
55 printf("ext2: fs compression is not supported by server\n");
56 if (HAS_INCOMPAT_FEATURE(sp
, INCOMPAT_FILETYPE
& mask
))
57 printf("ext2: fs in dir filetype is not supported by server\n");
58 if (HAS_INCOMPAT_FEATURE(sp
, INCOMPAT_RECOVER
& mask
))
59 printf("ext2: fs recovery is not supported by server\n");
60 if (HAS_INCOMPAT_FEATURE(sp
, INCOMPAT_JOURNAL_DEV
& mask
))
61 printf("ext2: fs journal dev is not supported by server\n");
62 if (HAS_INCOMPAT_FEATURE(sp
, INCOMPAT_META_BG
& mask
))
63 printf("ext2: fs meta bg is not supported by server\n");
66 mask
= ~SUPPORTED_RO_COMPAT_FEATURES
;
67 if (HAS_RO_COMPAT_FEATURE(sp
, mask
)) {
68 if (HAS_RO_COMPAT_FEATURE(sp
, RO_COMPAT_SPARSE_SUPER
& mask
)) {
69 printf("ext2: sparse super is not supported by server, \
70 remount read-only\n");
72 if (HAS_RO_COMPAT_FEATURE(sp
, RO_COMPAT_LARGE_FILE
& mask
)) {
73 printf("ext2: large files are not supported by server, \
74 remount read-only\n");
76 if (HAS_RO_COMPAT_FEATURE(sp
, RO_COMPAT_BTREE_DIR
& mask
)) {
77 printf("ext2: dir's btree is not supported by server, \
78 remount read-only\n");
84 if (superblock
->s_state
== EXT2_ERROR_FS
) {
85 printf("ext2: filesystem wasn't cleanly unmounted last time\n");
86 superblock
->s_dev
= NO_DEV
;
91 lmfs_set_blocksize(superblock
->s_block_size
);
92 lmfs_set_blockusage(superblock
->s_blocks_count
,
93 superblock
->s_blocks_count
- superblock
->s_free_blocks_count
);
95 /* Get the root inode of the mounted file system. */
96 if ( (root_ip
= get_inode(fs_dev
, ROOT_INODE
)) == NULL
) {
97 printf("ext2: couldn't get root inode\n");
98 superblock
->s_dev
= NO_DEV
;
103 if (root_ip
!= NULL
&& root_ip
->i_mode
== 0) {
104 printf("%s:%d zero mode for root inode?\n", __FILE__
, __LINE__
);
106 superblock
->s_dev
= NO_DEV
;
111 if (root_ip
!= NULL
&& (root_ip
->i_mode
& I_TYPE
) != I_DIRECTORY
) {
112 printf("%s:%d root inode has wrong type, it's not a DIR\n",
115 superblock
->s_dev
= NO_DEV
;
120 superblock
->s_rd_only
= readonly
;
123 superblock
->s_state
= EXT2_ERROR_FS
;
124 superblock
->s_mnt_count
++;
125 superblock
->s_mtime
= clock_time(NULL
);
126 write_super(superblock
); /* Commit info, we just set above */
129 /* Root inode properties */
130 root_node
->fn_ino_nr
= root_ip
->i_num
;
131 root_node
->fn_mode
= root_ip
->i_mode
;
132 root_node
->fn_size
= root_ip
->i_size
;
133 root_node
->fn_uid
= root_ip
->i_uid
;
134 root_node
->fn_gid
= root_ip
->i_gid
;
135 root_node
->fn_dev
= NO_DEV
;
137 *res_flags
= RES_NOFLAGS
;
143 /*===========================================================================*
145 *===========================================================================*/
146 int fs_mountpt(ino_t ino_nr
)
148 /* This function looks up the mount point, it checks the condition whether
149 * the partition can be mounted on the inode or not.
151 register struct inode
*rip
;
155 /* Temporarily open the file. */
156 if( (rip
= get_inode(fs_dev
, ino_nr
)) == NULL
)
159 if(rip
->i_mountpoint
) r
= EBUSY
;
161 /* It may not be special. */
162 bits
= rip
->i_mode
& I_TYPE
;
163 if (bits
== I_BLOCK_SPECIAL
|| bits
== I_CHAR_SPECIAL
) r
= ENOTDIR
;
167 if(r
== OK
) rip
->i_mountpoint
= TRUE
;
173 /*===========================================================================*
175 *===========================================================================*/
176 void fs_unmount(void)
178 /* Unmount a file system by device number. */
180 struct inode
*rip
, *root_ip
;
182 /* See if the mounted device is busy. Only 1 inode using it should be
183 * open --the root inode-- and that inode only 1 time. This is an integrity
184 * check only: VFS expects the unmount to succeed either way.
187 for (rip
= &inode
[0]; rip
< &inode
[NR_INODES
]; rip
++)
188 if (rip
->i_count
> 0 && rip
->i_dev
== fs_dev
) count
+= rip
->i_count
;
190 printf("ext2: file system has %d in-use inodes!\n", count
);
192 if ((root_ip
= find_inode(fs_dev
, ROOT_INODE
)) == NULL
)
193 panic("ext2: couldn't find root inode");
195 /* Sync fs data before checking count. In some cases VFS can force unmounting
196 * and it will damage unsynced FS. We don't sync before checking root_ip since
197 * if it is missing then something strange happened with FS, so it's better
198 * to not use possibly corrupted data for syncing.
200 if (!superblock
->s_rd_only
) {
201 /* force any cached blocks out of memory */
207 if (!superblock
->s_rd_only
) {
208 superblock
->s_wtime
= clock_time(NULL
);
209 superblock
->s_state
= EXT2_VALID_FS
;
210 write_super(superblock
); /* Commit info, we just set above */
213 /* Close the device the file system lives on. */
216 /* Throw all blocks out of the VM cache, to prevent corruption later. */
217 lmfs_invalidate(fs_dev
);
219 /* Finish off the unmount. */
220 superblock
->s_dev
= NO_DEV
;