This source file includes following definitions.
- get_fs_type
- __wait_on_super
- sync_supers
- get_super
- put_super
- read_super
- get_unnamed_dev
- put_unnamed_dev
- do_umount
- sys_umount
- do_mount
- do_remount_sb
- do_remount
- sys_mount
- mount_root
1
2
3
4
5
6
7
8
9
10 #include <linux/config.h>
11 #include <linux/sched.h>
12 #include <linux/kernel.h>
13 #include <linux/stat.h>
14 #include <linux/errno.h>
15 #include <linux/string.h>
16 #include <linux/locks.h>
17
18 #include <asm/system.h>
19 #include <asm/segment.h>
20
21
22
23
24
25
26
27 extern struct file_system_type file_systems[];
28 extern struct file_operations * blkdev_fops[];
29
30 extern void wait_for_keypress(void);
31 extern void fcntl_init_locks(void);
32
33 extern int root_mountflags;
34
35 struct super_block super_blocks[NR_SUPER];
36
37 static int do_remount_sb(struct super_block *sb, int flags);
38
39
40 dev_t ROOT_DEV = 0;
41
42 struct file_system_type *get_fs_type(char *name)
43 {
44 int a;
45
46 if (!name)
47 return &file_systems[0];
48 for(a = 0 ; file_systems[a].read_super ; a++)
49 if (!strcmp(name,file_systems[a].name))
50 return(&file_systems[a]);
51 return NULL;
52 }
53
54 void __wait_on_super(struct super_block * sb)
55 {
56 struct wait_queue wait = { current, NULL };
57
58 add_wait_queue(&sb->s_wait, &wait);
59 repeat:
60 current->state = TASK_UNINTERRUPTIBLE;
61 if (sb->s_lock) {
62 schedule();
63 goto repeat;
64 }
65 remove_wait_queue(&sb->s_wait, &wait);
66 current->state = TASK_RUNNING;
67 }
68
69 void sync_supers(dev_t dev)
70 {
71 struct super_block * sb;
72
73 for (sb = super_blocks + 0 ; sb < super_blocks + NR_SUPER ; sb++) {
74 if (!sb->s_dev)
75 continue;
76 if (dev && sb->s_dev != dev)
77 continue;
78 wait_on_super(sb);
79 if (!sb->s_dev || !sb->s_dirt)
80 continue;
81 if (dev && (dev != sb->s_dev))
82 continue;
83 if (sb->s_op && sb->s_op->write_super)
84 sb->s_op->write_super(sb);
85 }
86 }
87
88 static struct super_block * get_super(dev_t dev)
89 {
90 struct super_block * s;
91
92 if (!dev)
93 return NULL;
94 s = 0+super_blocks;
95 while (s < NR_SUPER+super_blocks)
96 if (s->s_dev == dev) {
97 wait_on_super(s);
98 if (s->s_dev == dev)
99 return s;
100 s = 0+super_blocks;
101 } else
102 s++;
103 return NULL;
104 }
105
106 void put_super(dev_t dev)
107 {
108 struct super_block * sb;
109
110 if (dev == ROOT_DEV) {
111 printk("VFS: Root device %d/%d: prepare for armageddon\n",
112 MAJOR(dev), MINOR(dev));
113 return;
114 }
115 if (!(sb = get_super(dev)))
116 return;
117 if (sb->s_covered) {
118 printk("VFS: Mounted device %d/%d - tssk, tssk\n",
119 MAJOR(dev), MINOR(dev));
120 return;
121 }
122 if (sb->s_op && sb->s_op->put_super)
123 sb->s_op->put_super(sb);
124 }
125
126 static struct super_block * read_super(dev_t dev,char *name,int flags,
127 void *data, int silent)
128 {
129 struct super_block * s;
130 struct file_system_type *type;
131
132 if (!dev)
133 return NULL;
134 check_disk_change(dev);
135 s = get_super(dev);
136 if (s)
137 return s;
138 if (!(type = get_fs_type(name))) {
139 printk("VFS: on device %d/%d: get_fs_type(%s) failed\n",
140 MAJOR(dev), MINOR(dev), name);
141 return NULL;
142 }
143 for (s = 0+super_blocks ;; s++) {
144 if (s >= NR_SUPER+super_blocks)
145 return NULL;
146 if (!s->s_dev)
147 break;
148 }
149 s->s_dev = dev;
150 s->s_flags = flags;
151 if (!type->read_super(s,data, silent)) {
152 s->s_dev = 0;
153 return NULL;
154 }
155 s->s_dev = dev;
156 s->s_covered = NULL;
157 s->s_rd_only = 0;
158 s->s_dirt = 0;
159 return s;
160 }
161
162
163
164
165
166
167 static char unnamed_dev_in_use[256];
168
169 static dev_t get_unnamed_dev(void)
170 {
171 static int first_use = 0;
172 int i;
173
174 if (first_use == 0) {
175 first_use = 1;
176 memset(unnamed_dev_in_use, 0, sizeof(unnamed_dev_in_use));
177 unnamed_dev_in_use[0] = 1;
178 }
179 for (i = 0; i < 256; i++) {
180 if (!unnamed_dev_in_use[i]) {
181 unnamed_dev_in_use[i] = 1;
182 return (UNNAMED_MAJOR << 8) | i;
183 }
184 }
185 return 0;
186 }
187
188 static void put_unnamed_dev(dev_t dev)
189 {
190 if (!dev)
191 return;
192 if (!unnamed_dev_in_use[dev]) {
193 printk("VFS: put_unnamed_dev: freeing unused device %d/%d\n",
194 MAJOR(dev), MINOR(dev));
195 return;
196 }
197 unnamed_dev_in_use[dev] = 0;
198 }
199
200 static int do_umount(dev_t dev)
201 {
202 struct super_block * sb;
203 int retval;
204
205 if (dev==ROOT_DEV) {
206
207
208 if (!(sb=get_super(dev)))
209 return -ENOENT;
210 if (!(sb->s_flags & MS_RDONLY)) {
211 retval = do_remount_sb(sb, MS_RDONLY);
212 if (retval)
213 return retval;
214 }
215 return 0;
216 }
217 if (!(sb=get_super(dev)) || !(sb->s_covered))
218 return -ENOENT;
219 if (!sb->s_covered->i_mount)
220 printk("VFS: umount(%d/%d): mounted inode has i_mount=0\n",
221 MAJOR(dev), MINOR(dev));
222 if (!fs_may_umount(dev, sb->s_mounted))
223 return -EBUSY;
224 sb->s_covered->i_mount=0;
225 iput(sb->s_covered);
226 sb->s_covered = NULL;
227 iput(sb->s_mounted);
228 sb->s_mounted = NULL;
229 if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
230 sb->s_op->write_super(sb);
231 put_super(dev);
232 return 0;
233 }
234
235
236
237
238
239
240
241
242
243
244
245
246 extern "C" int sys_umount(char * name)
247 {
248 struct inode * inode;
249 dev_t dev;
250 int retval;
251 struct inode dummy_inode;
252 struct file_operations * fops;
253
254 if (!suser())
255 return -EPERM;
256 retval = namei(name,&inode);
257 if (retval)
258 return retval;
259 if (S_ISBLK(inode->i_mode)) {
260 dev = inode->i_rdev;
261 if (IS_NODEV(inode)) {
262 iput(inode);
263 return -EACCES;
264 }
265 } else if (S_ISDIR(inode->i_mode)) {
266 if (!inode || !inode->i_sb || inode != inode->i_sb->s_mounted) {
267 iput(inode);
268 return -EINVAL;
269 }
270 dev = inode->i_sb->s_dev;
271 iput(inode);
272 memset(&dummy_inode, 0, sizeof(dummy_inode));
273 dummy_inode.i_rdev = dev;
274 inode = &dummy_inode;
275 } else {
276 iput(inode);
277 return -EINVAL;
278 }
279 if (MAJOR(dev) >= MAX_BLKDEV) {
280 iput(inode);
281 return -ENXIO;
282 }
283 if (!(retval = do_umount(dev)) && dev != ROOT_DEV) {
284 fops = blkdev_fops[MAJOR(dev)];
285 if (fops && fops->release)
286 fops->release(inode,NULL);
287 if (MAJOR(dev) == UNNAMED_MAJOR)
288 put_unnamed_dev(dev);
289 }
290 if (inode != &dummy_inode)
291 iput(inode);
292 if (retval)
293 return retval;
294 fsync_dev(dev);
295 return 0;
296 }
297
298
299
300
301
302
303
304
305
306
307 static int do_mount(dev_t dev, const char * dir, char * type, int flags, void * data)
308 {
309 struct inode * dir_i;
310 struct super_block * sb;
311 int error;
312
313 error = namei(dir,&dir_i);
314 if (error)
315 return error;
316 if (dir_i->i_count != 1 || dir_i->i_mount) {
317 iput(dir_i);
318 return -EBUSY;
319 }
320 if (!S_ISDIR(dir_i->i_mode)) {
321 iput(dir_i);
322 return -EPERM;
323 }
324 if (!fs_may_mount(dev)) {
325 iput(dir_i);
326 return -EBUSY;
327 }
328 sb = read_super(dev,type,flags,data,0);
329 if (!sb || sb->s_covered) {
330 iput(dir_i);
331 return -EBUSY;
332 }
333 sb->s_covered = dir_i;
334 dir_i->i_mount = 1;
335 return 0;
336 }
337
338
339
340
341
342
343
344
345 static int do_remount_sb(struct super_block *sb, int flags)
346 {
347 int retval;
348
349
350 if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY))
351 if (!fs_may_remount_ro(sb->s_dev))
352 return -EBUSY;
353 if (sb->s_op && sb->s_op->remount_fs) {
354 retval = sb->s_op->remount_fs(sb, &flags);
355 if (retval)
356 return retval;
357 }
358 sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) |
359 (flags & MS_RMT_MASK);
360 return 0;
361 }
362
363 static int do_remount(const char *dir,int flags)
364 {
365 struct inode *dir_i;
366 int retval;
367
368 retval = namei(dir,&dir_i);
369 if (retval)
370 return retval;
371 if (dir_i != dir_i->i_sb->s_mounted) {
372 iput(dir_i);
373 return -EINVAL;
374 }
375 retval = do_remount_sb(dir_i->i_sb, flags);
376 iput(dir_i);
377 return retval;
378 }
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393 extern "C" int sys_mount(char * dev_name, char * dir_name, char * type,
394 unsigned long new_flags, void * data)
395 {
396 struct file_system_type * fstype;
397 struct inode * inode;
398 struct file_operations * fops;
399 dev_t dev;
400 int retval;
401 char tmp[100], * t;
402 int i;
403 unsigned long flags = 0;
404 unsigned long page = 0;
405
406 if (!suser())
407 return -EPERM;
408 if ((new_flags & (MS_MGC_MSK | MS_REMOUNT)) == (MS_MGC_VAL | MS_REMOUNT)) {
409 return do_remount(dir_name,new_flags & ~MS_MGC_MSK & ~MS_REMOUNT);
410 }
411 if (type) {
412 for (i = 0 ; i < 100 ; i++) {
413 if (TASK_SIZE <= (unsigned long) type)
414 return -EFAULT;
415 if (!(tmp[i] = get_fs_byte(type++)))
416 break;
417 }
418 t = tmp;
419 } else
420 t = NULL;
421 if (!(fstype = get_fs_type(t)))
422 return -ENODEV;
423 t = fstype->name;
424 if (fstype->requires_dev) {
425 retval = namei(dev_name,&inode);
426 if (retval)
427 return retval;
428 if (!S_ISBLK(inode->i_mode)) {
429 iput(inode);
430 return -ENOTBLK;
431 }
432 if (IS_NODEV(inode)) {
433 iput(inode);
434 return -EACCES;
435 }
436 dev = inode->i_rdev;
437 if (MAJOR(dev) >= MAX_BLKDEV) {
438 iput(inode);
439 return -ENXIO;
440 }
441 } else {
442 if (!(dev = get_unnamed_dev()))
443 return -EMFILE;
444 inode = NULL;
445 }
446 fops = blkdev_fops[MAJOR(dev)];
447 if (fops && fops->open) {
448 retval = fops->open(inode,NULL);
449 if (retval) {
450 iput(inode);
451 return retval;
452 }
453 }
454 if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL) {
455 flags = new_flags & ~MS_MGC_MSK;
456 if (data) {
457 if ((unsigned long) data >= TASK_SIZE) {
458 iput(inode);
459 return -EFAULT;
460 }
461 page = get_free_page(GFP_KERNEL);
462 i = TASK_SIZE - (unsigned long) data;
463 if (i < 0 || i > 4095)
464 i = 4095;
465 memcpy_fromfs((void *) page,data,i);
466 }
467 }
468 retval = do_mount(dev,dir_name,t,flags,(void *) page);
469 free_page(page);
470 if (retval && fops && fops->release)
471 fops->release(inode,NULL);
472 iput(inode);
473 return retval;
474 }
475
476 void mount_root(void)
477 {
478 struct file_system_type * fs_type;
479 struct super_block * sb;
480 struct inode * inode;
481
482 memset(super_blocks, 0, sizeof(super_blocks));
483 fcntl_init_locks();
484 if (MAJOR(ROOT_DEV) == 2) {
485 printk("VFS: Insert root floppy and press ENTER");
486 wait_for_keypress();
487 }
488 for (fs_type = file_systems; fs_type->read_super; fs_type++) {
489 if (!fs_type->requires_dev)
490 continue;
491 sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1);
492 if (sb) {
493 inode = sb->s_mounted;
494 inode->i_count += 3 ;
495 sb->s_covered = inode;
496 sb->s_flags = root_mountflags;
497 current->pwd = inode;
498 current->root = inode;
499 printk ("VFS: Mounted root (%s filesystem)%s.\n",
500 fs_type->name,
501 (sb->s_flags & MS_RDONLY) ? " readonly" : "");
502 return;
503 }
504 }
505 panic("VFS: Unable to mount root");
506 }