Annotation of linux/fs/super.c, revision 1.1.1.11

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.