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

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: }

unix.superglobalmegacorp.com

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