xref: /minix/minix/fs/mfs/mount.c (revision 433d6423)
1 #include "fs.h"
2 #include "inode.h"
3 #include "super.h"
4 #include <minix/vfsif.h>
5 #include <minix/bdev.h>
6 
7 static int cleanmount = 1;
8 
9 /*===========================================================================*
10  *				fs_readsuper				     *
11  *===========================================================================*/
12 int fs_readsuper()
13 {
14 /* This function reads the superblock of the partition, gets the root inode
15  * and sends back the details of them. Note, that the FS process does not
16  * know the index of the vmnt object which refers to it, whenever the pathname
17  * lookup leaves a partition an ELEAVEMOUNT error is transferred back
18  * so that the VFS knows that it has to find the vnode on which this FS
19  * process' partition is mounted on.
20  */
21   struct inode *root_ip;
22   cp_grant_id_t label_gid;
23   size_t label_len;
24   int r;
25   int readonly, isroot;
26 
27   fs_dev    = fs_m_in.m_vfs_fs_readsuper.device;
28   label_gid = fs_m_in.m_vfs_fs_readsuper.grant;
29   label_len = fs_m_in.m_vfs_fs_readsuper.path_len;
30   readonly  = (fs_m_in.m_vfs_fs_readsuper.flags & REQ_RDONLY) ? 1 : 0;
31   isroot    = (fs_m_in.m_vfs_fs_readsuper.flags & REQ_ISROOT) ? 1 : 0;
32 
33   if (label_len > sizeof(fs_dev_label))
34 	return(EINVAL);
35 
36   r = sys_safecopyfrom(fs_m_in.m_source, label_gid, (vir_bytes) 0,
37 		       (vir_bytes) fs_dev_label, label_len);
38   if (r != OK) {
39 	printf("MFS %s:%d safecopyfrom failed: %d\n", __FILE__, __LINE__, r);
40 	return(EINVAL);
41   }
42 
43   /* Map the driver label for this major. */
44   bdev_driver(fs_dev, fs_dev_label);
45 
46   /* Open the device the file system lives on. */
47   if (bdev_open(fs_dev, readonly ? BDEV_R_BIT : (BDEV_R_BIT|BDEV_W_BIT) ) !=
48 		OK) {
49         return(EINVAL);
50   }
51 
52   /* Fill in the super block. */
53   superblock.s_dev = fs_dev;	/* read_super() needs to know which dev */
54   r = read_super(&superblock);
55 
56   /* Is it recognized as a Minix filesystem? */
57   if (r != OK) {
58 	superblock.s_dev = NO_DEV;
59 	bdev_close(fs_dev);
60 	return(r);
61   }
62 
63   /* Remember whether we were mounted cleanly so we know what to
64    * do at unmount time
65    */
66   if(superblock.s_flags & MFSFLAG_CLEAN)
67 	cleanmount = 1;
68 
69   /* clean check: if rw and not clean, switch to readonly */
70   if(!(superblock.s_flags & MFSFLAG_CLEAN) && !readonly) {
71 	if(bdev_close(fs_dev) != OK)
72 		panic("couldn't bdev_close after found unclean FS");
73 	readonly = 1;
74 
75 	if (bdev_open(fs_dev, BDEV_R_BIT) != OK) {
76 		panic("couldn't bdev_open after found unclean FS");
77 		return(EINVAL);
78   	}
79 	printf("MFS: WARNING: FS 0x%llx unclean, mounting readonly\n", fs_dev);
80   }
81 
82   lmfs_set_blocksize(superblock.s_block_size, major(fs_dev));
83 
84   /* Get the root inode of the mounted file system. */
85   if( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NULL)  {
86 	printf("MFS: couldn't get root inode\n");
87 	superblock.s_dev = NO_DEV;
88 	bdev_close(fs_dev);
89 	return(EINVAL);
90   }
91 
92   if(root_ip->i_mode == 0) {
93 	printf("%s:%d zero mode for root inode?\n", __FILE__, __LINE__);
94 	put_inode(root_ip);
95 	superblock.s_dev = NO_DEV;
96 	bdev_close(fs_dev);
97 	return(EINVAL);
98   }
99 
100   superblock.s_rd_only = readonly;
101   superblock.s_is_root = isroot;
102 
103   /* Root inode properties */
104   fs_m_out.m_fs_vfs_readsuper.inode = root_ip->i_num;
105   fs_m_out.m_fs_vfs_readsuper.mode = root_ip->i_mode;
106   fs_m_out.m_fs_vfs_readsuper.file_size = root_ip->i_size;
107   fs_m_out.m_fs_vfs_readsuper.uid = root_ip->i_uid;
108   fs_m_out.m_fs_vfs_readsuper.gid = root_ip->i_gid;
109   fs_m_out.m_fs_vfs_readsuper.flags = RES_HASPEEK;
110 
111   /* Mark it dirty */
112   if(!superblock.s_rd_only) {
113 	  superblock.s_flags &= ~MFSFLAG_CLEAN;
114 	  if(write_super(&superblock) != OK)
115 		panic("mounting: couldn't write dirty superblock");
116   }
117 
118   return(r);
119 }
120 
121 
122 /*===========================================================================*
123  *				fs_mountpoint				     *
124  *===========================================================================*/
125 int fs_mountpoint()
126 {
127 /* This function looks up the mount point, it checks the condition whether
128  * the partition can be mounted on the inode or not.
129  */
130   register struct inode *rip;
131   int r = OK;
132   mode_t bits;
133 
134   /* Temporarily open the file. */
135   if( (rip = get_inode(fs_dev, fs_m_in.m_vfs_fs_mountpoint.inode)) == NULL)
136 	  return(EINVAL);
137 
138 
139   if(rip->i_mountpoint) r = EBUSY;
140 
141   /* It may not be special. */
142   bits = rip->i_mode & I_TYPE;
143   if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL) r = ENOTDIR;
144 
145   put_inode(rip);
146 
147   if(r == OK) rip->i_mountpoint = TRUE;
148 
149   return(r);
150 }
151 
152 
153 /*===========================================================================*
154  *				fs_unmount				     *
155  *===========================================================================*/
156 int fs_unmount()
157 {
158 /* Unmount a file system by device number. */
159   int count;
160   struct inode *rip, *root_ip;
161 
162   if(superblock.s_dev != fs_dev) return(EINVAL);
163 
164   /* See if the mounted device is busy.  Only 1 inode using it should be
165    * open --the root inode-- and that inode only 1 time. */
166   count = 0;
167   for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++)
168 	  if (rip->i_count > 0 && rip->i_dev == fs_dev) count += rip->i_count;
169 
170   if ((root_ip = find_inode(fs_dev, ROOT_INODE)) == NULL) {
171   	panic("MFS: couldn't find root inode\n");
172   	return(EINVAL);
173   }
174 
175   if (count > 1) return(EBUSY);	/* can't umount a busy file system */
176   put_inode(root_ip);
177 
178   /* force any cached blocks out of memory */
179   (void) fs_sync();
180 
181   /* Mark it clean if we're allowed to write _and_ it was clean originally. */
182   if(cleanmount && !superblock.s_rd_only) {
183 	superblock.s_flags |= MFSFLAG_CLEAN;
184 	write_super(&superblock);
185   }
186 
187   /* Close the device the file system lives on. */
188   bdev_close(fs_dev);
189 
190   /* Throw out blocks out of the VM cache, to prevent corruption later. */
191   lmfs_invalidate(fs_dev);
192 
193   /* Finish off the unmount. */
194   superblock.s_dev = NO_DEV;
195   unmountdone = TRUE;
196 
197   return(OK);
198 }
199 
200