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