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