. service tells you which device it couldn't stat
[minix3.git] / servers / mfs / mount.c
blob604af3ce904b8476e60b1d24ea9f9d47eac2e895
3 #include "fs.h"
4 #include <fcntl.h>
5 #include <string.h>
6 #include <minix/com.h>
7 #include <sys/stat.h>
8 #include "buf.h"
9 #include "inode.h"
10 #include "super.h"
11 #include "drivers.h"
12 #include <minix/vfsif.h>
18 /*===========================================================================*
19 * fs_readsuper *
20 *===========================================================================*/
21 PUBLIC int fs_readsuper()
23 /* This function reads the superblock of the partition, gets the root inode
24 * and sends back the details of them. Note, that the FS process does not
25 * know the index of the vmnt object which refers to it, whenever the pathname
26 * lookup leaves a partition an ELEAVEMOUNT error is transferred back
27 * so that the VFS knows that it has to find the vnode on which this FS
28 * process' partition is mounted on.
30 struct super_block *xp, *sp;
31 struct inode *root_ip;
32 int r = OK;
34 fs_dev = fs_m_in.REQ_DEV;
36 /* Map the driver endpoint for this major */
37 driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e = fs_m_in.REQ_DRIVER_E;
38 boottime = fs_m_in.REQ_BOOTTIME;
39 vfs_slink_storage = fs_m_in.REQ_SLINK_STORAGE;
41 sp = &super_block[0];
43 /* Fill in the super block. */
44 sp->s_dev = fs_dev; /* read_super() needs to know which dev */
45 r = read_super(sp);
47 /* Is it recognized as a Minix filesystem? */
48 if (r != OK) {
49 sp->s_dev = NO_DEV;
50 return(r);
53 /* Get the root inode of the mounted file system. */
54 root_ip = NIL_INODE; /* if 'r' not OK, make sure this is defined */
55 if (r == OK) {
56 if ( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NIL_INODE)
57 r = err_code;
60 if (root_ip != NIL_INODE && root_ip->i_mode == 0) {
61 put_inode(root_ip);
62 r = EINVAL;
65 if (r != OK) return r;
66 sp->s_rd_only = fs_m_in.REQ_READONLY;
67 sp->s_is_root = fs_m_in.REQ_ISROOT;
69 /* Root inode properties */
70 fs_m_out.RES_INODE_NR = root_ip->i_num;
71 fs_m_out.RES_MODE = root_ip->i_mode;
72 fs_m_out.RES_FILE_SIZE = root_ip->i_size;
74 /* Partition properties */
75 fs_m_out.RES_MAXSIZE = sp->s_max_size;
76 fs_m_out.RES_BLOCKSIZE = sp->s_block_size;
78 return r;
82 /*===========================================================================*
83 * fs_mountpoint *
84 *===========================================================================*/
85 PUBLIC int fs_mountpoint()
87 /* This function looks up the mount point, it checks the condition whether
88 * the partition can be mounted on the inode or not. If ok, it gets the
89 * mountpoint inode's details and stores the mounted vmnt's index (in the
90 * vmnt table) so that it can be transferred back when the pathname lookup
91 * encounters a mountpoint.
93 register struct inode *rip;
94 int r = OK;
95 mode_t bits;
97 /* Get inode */
98 caller_uid = fs_m_in.REQ_UID;
99 caller_gid = fs_m_in.REQ_GID;
101 /* Temporarily open the file. */
102 if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
103 printf("MFS(%d) get_inode by fs_mountpoint() failed\n", SELF_E);
104 return(EINVAL);
107 /* It may not be busy. */
108 if (rip->i_count > 1) r = EBUSY;
110 /* It may not be special. */
111 bits = rip->i_mode & I_TYPE;
112 if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL) r = ENOTDIR;
114 if ((rip->i_mode & I_TYPE) != I_DIRECTORY) r = ENOTDIR;
116 if (r != OK) {
117 put_inode(rip);
118 return r;
121 rip->i_mount = I_MOUNT;
122 rip->i_vmnt_ind = fs_m_in.REQ_VMNT_IND;
124 fs_m_out.m_source = rip->i_dev;/* Filled with the FS endp by the system */
125 fs_m_out.RES_INODE_NR = rip->i_num;
126 fs_m_out.RES_FILE_SIZE = rip->i_size;
127 fs_m_out.RES_MODE = rip->i_mode;
129 return r;
133 /*===========================================================================*
134 * fs_unmount *
135 *===========================================================================*/
136 PUBLIC int fs_unmount()
138 /* Unmount a file system by device number. */
139 struct super_block *sp, *sp1;
140 int count;
141 register struct inode *rip;
143 /* !!!!!!!!!!!!! REMOVE THIS LATER !!!!!!!!!!!!!!!!!!!!!!! */
144 /* Find the super block. */
145 sp = NIL_SUPER;
146 for (sp1 = &super_block[0]; sp1 < &super_block[NR_SUPERS]; sp1++) {
147 if (sp1->s_dev == fs_dev) {
148 sp = sp1;
149 break;
152 if (sp == NIL_SUPER) {
153 return(EINVAL);
155 /* !!!!!!!!!!!!! REMOVE THIS LATER !!!!!!!!!!!!!!!!!!!!!!! */
157 /* See if the mounted device is busy. Only 1 inode using it should be
158 * open -- the root inode -- and that inode only 1 time.
160 count = 0;
161 for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++) {
162 if (rip->i_count > 0 && rip->i_dev == fs_dev) {
163 /*printf("FSunmount DEV: %d inode: %d count: %d iaddr: %d\n",
164 rip->i_dev, rip->i_num, rip->i_count, rip);*/
165 count += rip->i_count;
169 if (count > 1) {
170 printf("MFS(%d) unmount: filesystem is busy %d\n", SELF_E, count);
171 return(EBUSY); /* can't umount a busy file system */
174 /* Put the root inode */
175 rip = get_inode(fs_dev, ROOT_INODE);
176 put_inode(rip);
177 put_inode(rip);
179 /* Sync the disk, and invalidate cache. */
180 (void) fs_sync(); /* force any cached blocks out of memory */
181 /*invalidate(fs_dev);*/ /* invalidate cache entries for this dev */
183 /* Finish off the unmount. */
184 sp->s_dev = NO_DEV;
187 return OK;