|
|
1.1 root 1: /*
1.1.1.2 root 2: * linux/fs/super.c
3: *
1.1.1.10! root 4: * Copyright (C) 1991, 1992 Linus Torvalds
1.1.1.2 root 5: */
6:
7: /*
1.1 root 8: * super.c contains code to handle the super-block tables.
9: */
10: #include <linux/config.h>
11: #include <linux/sched.h>
1.1.1.5 root 12: #include <linux/minix_fs.h>
1.1.1.9 root 13: #include <linux/ext_fs.h>
1.1.1.10! root 14: #include <linux/msdos_fs.h>
1.1 root 15: #include <linux/kernel.h>
1.1.1.8 root 16: #include <linux/stat.h>
1.1.1.10! root 17: #include <linux/errno.h>
! 18:
1.1.1.2 root 19: #include <asm/system.h>
1.1.1.7 root 20: #include <asm/segment.h>
1.1.1.2 root 21:
22: int sync_dev(int dev);
23: void wait_for_keypress(void);
1.1 root 24:
25: /* set_bit uses setb, as gas doesn't recognize setc */
26: #define set_bit(bitnr,addr) ({ \
27: register int __res __asm__("ax"); \
28: __asm__("bt %2,%3;setb %%al":"=a" (__res):"a" (0),"r" (bitnr),"m" (*(addr))); \
29: __res; })
30:
31: struct super_block super_block[NR_SUPER];
1.1.1.2 root 32: /* this is initialized in init/main.c */
33: int ROOT_DEV = 0;
1.1 root 34:
1.1.1.6 root 35: /* Move into include file later */
36:
37: static struct file_system_type file_systems[] = {
38: {minix_read_super,"minix"},
1.1.1.9 root 39: {ext_read_super,"ext"},
1.1.1.10! root 40: {msdos_read_super,"msdos"},
1.1.1.6 root 41: {NULL,NULL}
42: };
43:
44: /* end of include file */
45:
46: struct file_system_type *get_fs_type(char *name)
47: {
48: int a;
49:
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 lock_super(struct super_block * sb)
1.1 root 57: {
1.1.1.2 root 58: cli();
59: while (sb->s_lock)
60: sleep_on(&(sb->s_wait));
61: sb->s_lock = 1;
62: sti();
63: }
64:
1.1.1.6 root 65: void free_super(struct super_block * sb)
1.1.1.2 root 66: {
67: sb->s_lock = 0;
68: wake_up(&(sb->s_wait));
69: }
70:
1.1.1.6 root 71: void wait_on_super(struct super_block * sb)
1.1.1.2 root 72: {
73: cli();
74: while (sb->s_lock)
75: sleep_on(&(sb->s_wait));
76: sti();
77: }
78:
79: struct super_block * get_super(int dev)
80: {
81: struct super_block * s;
82:
83: if (!dev)
84: return NULL;
85: s = 0+super_block;
86: while (s < NR_SUPER+super_block)
87: if (s->s_dev == dev) {
88: wait_on_super(s);
89: if (s->s_dev == dev)
90: return s;
91: s = 0+super_block;
92: } else
93: s++;
94: return NULL;
95: }
96:
97: void put_super(int dev)
98: {
99: struct super_block * sb;
100:
101: if (dev == ROOT_DEV) {
102: printk("root diskette changed: prepare for armageddon\n\r");
103: return;
104: }
105: if (!(sb = get_super(dev)))
106: return;
1.1.1.5 root 107: if (sb->s_covered) {
1.1.1.2 root 108: printk("Mounted disk changed - tssk, tssk\n\r");
109: return;
110: }
1.1.1.6 root 111: if (sb->s_op && sb->s_op->put_super)
112: sb->s_op->put_super(sb);
1.1.1.2 root 113: }
114:
1.1.1.10! root 115: static struct super_block * read_super(int dev,char *name,int flags,void *data)
1.1.1.2 root 116: {
117: struct super_block * s;
1.1.1.6 root 118: struct file_system_type *type;
1.1 root 119:
1.1.1.2 root 120: if (!dev)
1.1 root 121: return NULL;
1.1.1.2 root 122: check_disk_change(dev);
123: if (s = get_super(dev))
124: return s;
1.1.1.6 root 125: if (!(type=get_fs_type(name))) {
126: printk("get fs type failed %s\n",name);
127: return NULL;
128: }
1.1.1.2 root 129: for (s = 0+super_block ;; s++) {
130: if (s >= NR_SUPER+super_block)
131: return NULL;
132: if (!s->s_dev)
133: break;
134: }
135: s->s_dev = dev;
1.1.1.10! root 136: s->s_flags = flags;
1.1.1.6 root 137: if (!type->read_super(s,data))
138: return(NULL);
139: s->s_dev = dev;
1.1.1.5 root 140: s->s_covered = NULL;
1.1.1.2 root 141: s->s_rd_only = 0;
142: s->s_dirt = 0;
1.1.1.6 root 143: return(s);
1.1.1.2 root 144: }
145:
1.1.1.10! root 146: static int do_umount(int dev)
1.1.1.2 root 147: {
148: struct super_block * sb;
1.1.1.10! root 149: struct inode * inode;
1.1.1.2 root 150:
151: if (dev==ROOT_DEV)
152: return -EBUSY;
1.1.1.5 root 153: if (!(sb=get_super(dev)) || !(sb->s_covered))
1.1.1.2 root 154: return -ENOENT;
1.1.1.5 root 155: if (!sb->s_covered->i_mount)
1.1.1.2 root 156: printk("Mounted inode has i_mount=0\n");
1.1.1.6 root 157: for (inode = inode_table+0 ; inode < inode_table+NR_INODE ; inode++)
1.1.1.2 root 158: if (inode->i_dev==dev && inode->i_count)
1.1.1.5 root 159: if (inode == sb->s_mounted && inode->i_count == 1)
160: continue;
161: else
1.1.1.3 root 162: return -EBUSY;
1.1.1.5 root 163: sb->s_covered->i_mount=0;
164: iput(sb->s_covered);
165: sb->s_covered = NULL;
166: iput(sb->s_mounted);
167: sb->s_mounted = NULL;
1.1.1.9 root 168: if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
169: sb->s_op->write_super (sb);
1.1.1.6 root 170: put_super(dev);
1.1.1.2 root 171: return 0;
172: }
173:
1.1.1.10! root 174: int sys_umount(char * dev_name)
1.1.1.2 root 175: {
1.1.1.10! root 176: struct inode * inode;
! 177: int dev,retval;
1.1.1.2 root 178:
1.1.1.7 root 179: if (!suser())
180: return -EPERM;
1.1.1.10! root 181: if (!(inode = namei(dev_name)))
1.1.1.2 root 182: return -ENOENT;
1.1.1.10! root 183: dev = inode->i_rdev;
! 184: if (!S_ISBLK(inode->i_mode)) {
! 185: iput(inode);
! 186: return -ENOTBLK;
1.1.1.2 root 187: }
1.1.1.10! root 188: retval = do_umount(dev);
! 189: if (!retval && MAJOR(dev) < MAX_BLKDEV &&
! 190: blkdev_fops[MAJOR(dev)]->release)
! 191: blkdev_fops[MAJOR(dev)]->release(inode,NULL);
! 192: iput(inode);
! 193: if (retval) return retval;
! 194: sync_dev(dev);
! 195: return 0;
! 196: }
! 197:
! 198: /*
! 199: * do_mount() does the actual mounting after sys_mount has done the ugly
! 200: * parameter parsing. When enough time has gone by, and everything uses the
! 201: * new mount() parameters, sys_mount() can then be cleaned up.
! 202: *
! 203: * We cannot mount a filesystem if it has active, used, or dirty inodes.
! 204: * We also have to flush all inode-data for this device, as the new mount
! 205: * might need new info.
! 206: */
! 207: static int do_mount(int dev, const char * dir, char * type, int flags, void * data)
! 208: {
! 209: struct inode * inode, * dir_i;
! 210: struct super_block * sb;
! 211:
! 212: if (!(dir_i = namei(dir)))
1.1.1.2 root 213: return -ENOENT;
1.1.1.10! root 214: if (dir_i->i_count != 1 || dir_i->i_mount) {
1.1.1.2 root 215: iput(dir_i);
216: return -EBUSY;
217: }
218: if (!S_ISDIR(dir_i->i_mode)) {
219: iput(dir_i);
220: return -EPERM;
221: }
1.1.1.10! root 222: for (inode = inode_table+0 ; inode < inode_table+NR_INODE ; inode++) {
! 223: if (inode->i_dev != dev)
! 224: continue;
! 225: if (inode->i_count || inode->i_dirt || inode->i_lock) {
! 226: iput(dir_i);
! 227: return -EBUSY;
! 228: }
! 229: inode->i_dev = 0;
! 230: }
! 231: sb = read_super(dev,type,flags,data);
! 232: if (!sb || sb->s_covered) {
1.1.1.2 root 233: iput(dir_i);
1.1.1.10! root 234: return -EBUSY;
! 235: }
! 236: sb->s_flags = flags;
! 237: sb->s_covered = dir_i;
! 238: dir_i->i_mount = 1;
! 239: return 0; /* we don't iput(dir_i) - see umount */
! 240: }
! 241:
! 242: /*
! 243: * Flags is a 16-bit value that allows up to 16 non-fs dependent flags to
! 244: * be given to the mount() call (ie: read-only, no-dev, no-suid etc).
! 245: *
! 246: * data is a (void *) that can point to any structure up to 4095 bytes, which
! 247: * can contain arbitrary fs-dependent information (or be NULL).
! 248: *
! 249: * NOTE! As old versions of mount() didn't use this setup, the flags has to have
! 250: * a special 16-bit magic number in the hight word: 0xC0ED. If this magic word
! 251: * isn't present, the flags and data info isn't used, as the syscall assumes we
! 252: * are talking to an older version that didn't understand them.
! 253: */
! 254: int sys_mount(char * dev_name, char * dir_name, char * type,
! 255: unsigned long new_flags, void *data)
! 256: {
! 257: struct inode * inode;
! 258: int dev;
! 259: int retval = 0;
! 260: char tmp[100],*t;
! 261: int i;
! 262: unsigned long flags = 0;
! 263: unsigned long page = 0;
! 264:
! 265: if (!suser())
1.1.1.6 root 266: return -EPERM;
1.1.1.10! root 267: if (!(inode = namei(dev_name)))
! 268: return -ENOENT;
! 269: dev = inode->i_rdev;
! 270: if (!S_ISBLK(inode->i_mode))
! 271: retval = -EPERM;
! 272: else if (IS_NODEV(inode))
! 273: retval = -EACCES;
! 274: if (!retval && blkdev_fops[MAJOR(dev)]->open)
! 275: retval = blkdev_fops[MAJOR(dev)]->open(inode,NULL);
! 276: if (retval) {
! 277: iput(inode);
! 278: return retval;
! 279: }
! 280: if ((new_flags & 0xffff0000) == 0xC0ED0000) {
! 281: flags = new_flags & 0xffff;
! 282: if (data && (unsigned long) data < TASK_SIZE)
! 283: page = get_free_page(GFP_KERNEL);
! 284: }
! 285: if (page) {
! 286: i = TASK_SIZE - (unsigned long) data;
! 287: if (i < 0 || i > 4095)
! 288: i = 4095;
! 289: memcpy_fromfs((void *) page,data,i);
1.1.1.2 root 290: }
1.1.1.7 root 291: if (type) {
1.1.1.10! root 292: for (i = 0 ; i < 100 ; i++)
! 293: if (!(tmp[i] = get_fs_byte(type++)))
! 294: break;
1.1.1.7 root 295: t = tmp;
296: } else
297: t = "minix";
1.1.1.10! root 298: retval = do_mount(dev,dir_name,t,flags,(void *) page);
! 299: free_page(page);
! 300: if (retval && blkdev_fops[MAJOR(dev)]->release)
! 301: blkdev_fops[MAJOR(dev)]->release(inode,NULL);
! 302: iput(inode);
! 303: return retval;
1.1 root 304: }
305:
306: void mount_root(void)
307: {
1.1.1.10! root 308: int i;
! 309: struct file_system_type * fs_type = file_systems;
1.1 root 310: struct super_block * p;
1.1.1.5 root 311: struct inode * mi;
1.1 root 312:
1.1.1.5 root 313: if (32 != sizeof (struct minix_inode))
1.1 root 314: panic("bad i-node size");
315: for(i=0;i<NR_FILE;i++)
316: file_table[i].f_count=0;
1.1.1.2 root 317: if (MAJOR(ROOT_DEV) == 2) {
318: printk("Insert root floppy and press ENTER");
319: wait_for_keypress();
320: }
321: for(p = &super_block[0] ; p < &super_block[NR_SUPER] ; p++) {
1.1 root 322: p->s_dev = 0;
1.1.1.10! root 323: p->s_blocksize = 0;
1.1.1.2 root 324: p->s_lock = 0;
325: p->s_wait = NULL;
1.1.1.10! root 326: p->s_mounted = p->s_covered = NULL;
! 327: }
! 328: while (fs_type->read_super && fs_type->name) {
! 329: p = read_super(ROOT_DEV,fs_type->name,0,NULL);
! 330: if (p) {
! 331: mi = p->s_mounted;
! 332: mi->i_count += 3 ; /* NOTE! it is logically used 4 times, not 1 */
! 333: p->s_covered = mi;
! 334: p->s_flags = 0;
! 335: current->pwd = mi;
! 336: current->root = mi;
! 337: return;
! 338: }
! 339: fs_type++;
1.1.1.2 root 340: }
1.1.1.10! root 341: panic("Unable to mount root");
1.1 root 342: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.