1 /* Created (MFS based):
2 * February 2010 (Evgeniy Ivanov)
13 #include <minix/vfsif.h>
14 #include <minix/bdev.h>
17 /*===========================================================================*
19 *===========================================================================*/
22 /* This function reads the superblock of the partition, gets the root inode
23 * and sends back the details of them. Note, that the FS process does not
24 * know the index of the vmnt object which refers to it, whenever the pathname
25 * lookup leaves a partition an ELEAVEMOUNT error is transferred back
26 * so that the VFS knows that it has to find the vnode on which this FS
27 * process' partition is mounted on.
29 struct inode
*root_ip
;
30 cp_grant_id_t label_gid
;
36 fs_dev
= fs_m_in
.REQ_DEV
;
37 label_gid
= fs_m_in
.REQ_GRANT
;
38 label_len
= fs_m_in
.REQ_PATH_LEN
;
39 readonly
= (fs_m_in
.REQ_FLAGS
& REQ_RDONLY
) ? 1 : 0;
40 isroot
= (fs_m_in
.REQ_FLAGS
& REQ_ISROOT
) ? 1 : 0;
42 if (label_len
> sizeof(fs_dev_label
))
45 r
= sys_safecopyfrom(fs_m_in
.m_source
, label_gid
, 0,
46 (vir_bytes
)fs_dev_label
, label_len
);
48 printf("%s:%d fs_readsuper: safecopyfrom failed: %d\n",
49 __FILE__
, __LINE__
, r
);
53 /* Map the driver label for this major. */
54 bdev_driver(fs_dev
, fs_dev_label
);
56 /* Open the device the file system lives on. */
57 if (bdev_open(fs_dev
, readonly
? R_BIT
: (R_BIT
|W_BIT
)) != OK
) {
61 /* Fill in the super block. */
62 STATICINIT(superblock
, 1);
64 panic("Can't allocate memory for superblock.");
65 superblock
->s_dev
= fs_dev
; /* read_super() needs to know which dev */
66 r
= read_super(superblock
);
68 /* Is it recognized as a Minix filesystem? */
70 superblock
->s_dev
= NO_DEV
;
75 if (superblock
->s_rev_level
!= EXT2_GOOD_OLD_REV
) {
76 struct super_block
*sp
= superblock
; /* just shorter name */
77 mask
= ~SUPPORTED_INCOMPAT_FEATURES
;
78 if (HAS_INCOMPAT_FEATURE(sp
, mask
)) {
79 if (HAS_INCOMPAT_FEATURE(sp
, INCOMPAT_COMPRESSION
& mask
))
80 printf("ext2: fs compression is not supported by server\n");
81 if (HAS_INCOMPAT_FEATURE(sp
, INCOMPAT_FILETYPE
& mask
))
82 printf("ext2: fs in dir filetype is not supported by server\n");
83 if (HAS_INCOMPAT_FEATURE(sp
, INCOMPAT_RECOVER
& mask
))
84 printf("ext2: fs recovery is not supported by server\n");
85 if (HAS_INCOMPAT_FEATURE(sp
, INCOMPAT_JOURNAL_DEV
& mask
))
86 printf("ext2: fs journal dev is not supported by server\n");
87 if (HAS_INCOMPAT_FEATURE(sp
, INCOMPAT_META_BG
& mask
))
88 printf("ext2: fs meta bg is not supported by server\n");
91 mask
= ~SUPPORTED_RO_COMPAT_FEATURES
;
92 if (HAS_RO_COMPAT_FEATURE(sp
, mask
)) {
93 if (HAS_RO_COMPAT_FEATURE(sp
, RO_COMPAT_SPARSE_SUPER
& mask
)) {
94 printf("ext2: sparse super is not supported by server, \
95 remount read-only\n");
97 if (HAS_RO_COMPAT_FEATURE(sp
, RO_COMPAT_LARGE_FILE
& mask
)) {
98 printf("ext2: large files are not supported by server, \
99 remount read-only\n");
101 if (HAS_RO_COMPAT_FEATURE(sp
, RO_COMPAT_BTREE_DIR
& mask
)) {
102 printf("ext2: dir's btree is not supported by server, \
103 remount read-only\n");
109 if (superblock
->s_state
== EXT2_ERROR_FS
) {
110 printf("ext2: filesystem wasn't cleanly unmounted last time\n");
111 superblock
->s_dev
= NO_DEV
;
117 lmfs_set_blocksize(superblock
->s_block_size
, major(fs_dev
));
119 /* Get the root inode of the mounted file system. */
120 if ( (root_ip
= get_inode(fs_dev
, ROOT_INODE
)) == NULL
) {
121 printf("ext2: couldn't get root inode\n");
122 superblock
->s_dev
= NO_DEV
;
127 if (root_ip
!= NULL
&& root_ip
->i_mode
== 0) {
128 printf("%s:%d zero mode for root inode?\n", __FILE__
, __LINE__
);
130 superblock
->s_dev
= NO_DEV
;
135 if (root_ip
!= NULL
&& (root_ip
->i_mode
& I_TYPE
) != I_DIRECTORY
) {
136 printf("%s:%d root inode has wrong type, it's not a DIR\n",
139 superblock
->s_dev
= NO_DEV
;
144 superblock
->s_rd_only
= readonly
;
145 superblock
->s_is_root
= isroot
;
148 superblock
->s_state
= EXT2_ERROR_FS
;
149 superblock
->s_mnt_count
++;
150 superblock
->s_mtime
= clock_time();
151 write_super(superblock
); /* Commit info, we just set above */
154 /* Root inode properties */
155 fs_m_out
.RES_INODE_NR
= root_ip
->i_num
;
156 fs_m_out
.RES_MODE
= root_ip
->i_mode
;
157 fs_m_out
.RES_FILE_SIZE_LO
= root_ip
->i_size
;
158 fs_m_out
.RES_UID
= root_ip
->i_uid
;
159 fs_m_out
.RES_GID
= root_ip
->i_gid
;
161 fs_m_out
.RES_CONREQS
= 1; /* We can handle only 1 request at a time */
167 /*===========================================================================*
169 *===========================================================================*/
172 /* This function looks up the mount point, it checks the condition whether
173 * the partition can be mounted on the inode or not.
175 register struct inode
*rip
;
179 /* Temporarily open the file. */
180 if( (rip
= get_inode(fs_dev
, fs_m_in
.REQ_INODE_NR
)) == NULL
)
184 if(rip
->i_mountpoint
) r
= EBUSY
;
186 /* It may not be special. */
187 bits
= rip
->i_mode
& I_TYPE
;
188 if (bits
== I_BLOCK_SPECIAL
|| bits
== I_CHAR_SPECIAL
) r
= ENOTDIR
;
192 if(r
== OK
) rip
->i_mountpoint
= TRUE
;
198 /*===========================================================================*
200 *===========================================================================*/
203 /* Unmount a file system by device number. */
205 struct inode
*rip
, *root_ip
;
207 if(superblock
->s_dev
!= fs_dev
) return(EINVAL
);
209 /* See if the mounted device is busy. Only 1 inode using it should be
210 * open --the root inode-- and that inode only 1 time. */
212 for (rip
= &inode
[0]; rip
< &inode
[NR_INODES
]; rip
++)
213 if (rip
->i_count
> 0 && rip
->i_dev
== fs_dev
) count
+= rip
->i_count
;
215 if ((root_ip
= find_inode(fs_dev
, ROOT_INODE
)) == NULL
) {
216 printf("ext2: couldn't find root inode. Unmount failed.\n");
217 panic("ext2: couldn't find root inode");
221 /* Sync fs data before checking count. In some cases VFS can force unmounting
222 * and it will damage unsynced FS. We don't sync before checking root_ip since
223 * if it is missing then something strange happened with FS, so it's better
224 * to not use possibly corrupted data for syncing.
226 if (!superblock
->s_rd_only
) {
227 /* force any cached blocks out of memory */
231 if (count
> 1) return(EBUSY
); /* can't umount a busy file system */
235 if (!superblock
->s_rd_only
) {
236 superblock
->s_wtime
= clock_time();
237 superblock
->s_state
= EXT2_VALID_FS
;
238 write_super(superblock
); /* Commit info, we just set above */
241 /* Close the device the file system lives on. */
244 /* Finish off the unmount. */
245 superblock
->s_dev
= NO_DEV
;