|
|
1.1 root 1: /*
1.1.1.2 root 2: * linux/fs/super.c
3: *
4: * (C) 1991 Linus Torvalds
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>
12: #include <linux/kernel.h>
1.1.1.2 root 13: #include <asm/system.h>
14:
15: #include <errno.h>
16: #include <sys/stat.h>
17:
18: int sync_dev(int dev);
19: void wait_for_keypress(void);
1.1 root 20:
21: /* set_bit uses setb, as gas doesn't recognize setc */
22: #define set_bit(bitnr,addr) ({ \
23: register int __res __asm__("ax"); \
24: __asm__("bt %2,%3;setb %%al":"=a" (__res):"a" (0),"r" (bitnr),"m" (*(addr))); \
25: __res; })
26:
27: struct super_block super_block[NR_SUPER];
1.1.1.2 root 28: /* this is initialized in init/main.c */
29: int ROOT_DEV = 0;
1.1 root 30:
1.1.1.2 root 31: static void lock_super(struct super_block * sb)
1.1 root 32: {
1.1.1.2 root 33: cli();
34: while (sb->s_lock)
35: sleep_on(&(sb->s_wait));
36: sb->s_lock = 1;
37: sti();
38: }
39:
40: static void free_super(struct super_block * sb)
41: {
42: cli();
43: sb->s_lock = 0;
44: wake_up(&(sb->s_wait));
45: sti();
46: }
47:
48: static void wait_on_super(struct super_block * sb)
49: {
50: cli();
51: while (sb->s_lock)
52: sleep_on(&(sb->s_wait));
53: sti();
54: }
55:
56: struct super_block * get_super(int dev)
57: {
58: struct super_block * s;
59:
60: if (!dev)
61: return NULL;
62: s = 0+super_block;
63: while (s < NR_SUPER+super_block)
64: if (s->s_dev == dev) {
65: wait_on_super(s);
66: if (s->s_dev == dev)
67: return s;
68: s = 0+super_block;
69: } else
70: s++;
71: return NULL;
72: }
73:
74: void put_super(int dev)
75: {
76: struct super_block * sb;
1.1.1.3 ! root 77: struct m_inode * inode;
1.1.1.2 root 78: int i;
79:
80: if (dev == ROOT_DEV) {
81: printk("root diskette changed: prepare for armageddon\n\r");
82: return;
83: }
84: if (!(sb = get_super(dev)))
85: return;
86: if (sb->s_imount) {
87: printk("Mounted disk changed - tssk, tssk\n\r");
88: return;
89: }
90: lock_super(sb);
91: sb->s_dev = 0;
92: for(i=0;i<I_MAP_SLOTS;i++)
93: brelse(sb->s_imap[i]);
94: for(i=0;i<Z_MAP_SLOTS;i++)
95: brelse(sb->s_zmap[i]);
96: free_super(sb);
97: return;
98: }
99:
100: static struct super_block * read_super(int dev)
101: {
102: struct super_block * s;
1.1 root 103: struct buffer_head * bh;
104: int i,block;
105:
1.1.1.2 root 106: if (!dev)
1.1 root 107: return NULL;
1.1.1.2 root 108: check_disk_change(dev);
109: if (s = get_super(dev))
110: return s;
111: for (s = 0+super_block ;; s++) {
112: if (s >= NR_SUPER+super_block)
113: return NULL;
114: if (!s->s_dev)
115: break;
116: }
117: s->s_dev = dev;
118: s->s_isup = NULL;
119: s->s_imount = NULL;
120: s->s_time = 0;
121: s->s_rd_only = 0;
122: s->s_dirt = 0;
123: lock_super(s);
124: if (!(bh = bread(dev,1))) {
125: s->s_dev=0;
126: free_super(s);
1.1 root 127: return NULL;
1.1.1.2 root 128: }
129: *((struct d_super_block *) s) =
130: *((struct d_super_block *) bh->b_data);
1.1 root 131: brelse(bh);
1.1.1.2 root 132: if (s->s_magic != SUPER_MAGIC) {
133: s->s_dev = 0;
134: free_super(s);
1.1 root 135: return NULL;
136: }
137: for (i=0;i<I_MAP_SLOTS;i++)
1.1.1.2 root 138: s->s_imap[i] = NULL;
1.1 root 139: for (i=0;i<Z_MAP_SLOTS;i++)
1.1.1.2 root 140: s->s_zmap[i] = NULL;
1.1 root 141: block=2;
1.1.1.2 root 142: for (i=0 ; i < s->s_imap_blocks ; i++)
143: if (s->s_imap[i]=bread(dev,block))
1.1 root 144: block++;
145: else
146: break;
1.1.1.2 root 147: for (i=0 ; i < s->s_zmap_blocks ; i++)
148: if (s->s_zmap[i]=bread(dev,block))
1.1 root 149: block++;
150: else
151: break;
1.1.1.2 root 152: if (block != 2+s->s_imap_blocks+s->s_zmap_blocks) {
1.1 root 153: for(i=0;i<I_MAP_SLOTS;i++)
1.1.1.2 root 154: brelse(s->s_imap[i]);
1.1 root 155: for(i=0;i<Z_MAP_SLOTS;i++)
1.1.1.2 root 156: brelse(s->s_zmap[i]);
157: s->s_dev=0;
158: free_super(s);
1.1 root 159: return NULL;
160: }
1.1.1.2 root 161: s->s_imap[0]->b_data[0] |= 1;
162: s->s_zmap[0]->b_data[0] |= 1;
163: free_super(s);
164: return s;
165: }
166:
167: int sys_umount(char * dev_name)
168: {
169: struct m_inode * inode;
170: struct super_block * sb;
171: int dev;
172:
173: if (!(inode=namei(dev_name)))
174: return -ENOENT;
175: dev = inode->i_zone[0];
176: if (!S_ISBLK(inode->i_mode)) {
177: iput(inode);
178: return -ENOTBLK;
179: }
180: iput(inode);
181: if (dev==ROOT_DEV)
182: return -EBUSY;
183: if (!(sb=get_super(dev)) || !(sb->s_imount))
184: return -ENOENT;
185: if (!sb->s_imount->i_mount)
186: printk("Mounted inode has i_mount=0\n");
1.1.1.3 ! root 187: for (inode=inode_table+0 ; inode<inode_table+NR_INODE ; inode++)
1.1.1.2 root 188: if (inode->i_dev==dev && inode->i_count)
1.1.1.3 ! root 189: return -EBUSY;
1.1.1.2 root 190: sb->s_imount->i_mount=0;
191: iput(sb->s_imount);
192: sb->s_imount = NULL;
193: iput(sb->s_isup);
194: sb->s_isup = NULL;
195: put_super(dev);
196: sync_dev(dev);
197: return 0;
198: }
199:
200: int sys_mount(char * dev_name, char * dir_name, int rw_flag)
201: {
202: struct m_inode * dev_i, * dir_i;
203: struct super_block * sb;
204: int dev;
205:
206: if (!(dev_i=namei(dev_name)))
207: return -ENOENT;
208: dev = dev_i->i_zone[0];
209: if (!S_ISBLK(dev_i->i_mode)) {
210: iput(dev_i);
211: return -EPERM;
212: }
213: iput(dev_i);
214: if (!(dir_i=namei(dir_name)))
215: return -ENOENT;
216: if (dir_i->i_count != 1 || dir_i->i_num == ROOT_INO) {
217: iput(dir_i);
218: return -EBUSY;
219: }
220: if (!S_ISDIR(dir_i->i_mode)) {
221: iput(dir_i);
222: return -EPERM;
223: }
224: if (!(sb=read_super(dev))) {
225: iput(dir_i);
226: return -EBUSY;
227: }
228: if (sb->s_imount) {
229: iput(dir_i);
230: return -EBUSY;
231: }
232: if (dir_i->i_mount) {
233: iput(dir_i);
234: return -EPERM;
235: }
236: sb->s_imount=dir_i;
237: dir_i->i_mount=1;
238: dir_i->i_dirt=1; /* NOTE! we don't iput(dir_i) */
239: return 0; /* we do that in umount */
1.1 root 240: }
241:
242: void mount_root(void)
243: {
244: int i,free;
245: struct super_block * p;
246: struct m_inode * mi;
247:
248: if (32 != sizeof (struct d_inode))
249: panic("bad i-node size");
250: for(i=0;i<NR_FILE;i++)
251: file_table[i].f_count=0;
1.1.1.2 root 252: if (MAJOR(ROOT_DEV) == 2) {
253: printk("Insert root floppy and press ENTER");
254: wait_for_keypress();
255: }
256: for(p = &super_block[0] ; p < &super_block[NR_SUPER] ; p++) {
1.1 root 257: p->s_dev = 0;
1.1.1.2 root 258: p->s_lock = 0;
259: p->s_wait = NULL;
260: }
261: if (!(p=read_super(ROOT_DEV)))
1.1 root 262: panic("Unable to mount root");
1.1.1.2 root 263: if (!(mi=iget(ROOT_DEV,ROOT_INO)))
1.1 root 264: panic("Unable to read root i-node");
265: mi->i_count += 3 ; /* NOTE! it is logically used 4 times, not 1 */
266: p->s_isup = p->s_imount = mi;
267: current->pwd = mi;
268: current->root = mi;
269: free=0;
270: i=p->s_nzones;
271: while (-- i >= 0)
272: if (!set_bit(i&8191,p->s_zmap[i>>13]->b_data))
273: free++;
274: printk("%d/%d free blocks\n\r",free,p->s_nzones);
275: free=0;
276: i=p->s_ninodes+1;
277: while (-- i >= 0)
278: if (!set_bit(i&8191,p->s_imap[i>>13]->b_data))
279: free++;
280: printk("%d/%d free inodes\n\r",free,p->s_ninodes);
281: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.