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