[source navigation] [diff markup] [identifier search] [freetext search] [file search]

Oldlinux Cross Reference
Linux/fs/super.c

Version: [1.0] [0.99.11] [0.99] [0.98] [0.97] [0.96a] [0.95] [0.12] [0.11] [0.01]
Architecture: [i386]

  1 /*
  2  *  linux/fs/super.c
  3  *
  4  *  (C) 1991  Linus Torvalds
  5  */
  6 
  7 /*
  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>
 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);
 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];
 28 /* this is initialized in init/main.c */
 29 int ROOT_DEV = 0;
 30 
 31 static void lock_super(struct super_block * sb)
 32 {
 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;
 77         struct m_inode * inode;
 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;
103         struct buffer_head * bh;
104         int i,block;
105 
106         if (!dev)
107                 return NULL;
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);
127                 return NULL;
128         }
129         *((struct d_super_block *) s) =
130                 *((struct d_super_block *) bh->b_data);
131         brelse(bh);
132         if (s->s_magic != SUPER_MAGIC) {
133                 s->s_dev = 0;
134                 free_super(s);
135                 return NULL;
136         }
137         for (i=0;i<I_MAP_SLOTS;i++)
138                 s->s_imap[i] = NULL;
139         for (i=0;i<Z_MAP_SLOTS;i++)
140                 s->s_zmap[i] = NULL;
141         block=2;
142         for (i=0 ; i < s->s_imap_blocks ; i++)
143                 if (s->s_imap[i]=bread(dev,block))
144                         block++;
145                 else
146                         break;
147         for (i=0 ; i < s->s_zmap_blocks ; i++)
148                 if (s->s_zmap[i]=bread(dev,block))
149                         block++;
150                 else
151                         break;
152         if (block != 2+s->s_imap_blocks+s->s_zmap_blocks) {
153                 for(i=0;i<I_MAP_SLOTS;i++)
154                         brelse(s->s_imap[i]);
155                 for(i=0;i<Z_MAP_SLOTS;i++)
156                         brelse(s->s_zmap[i]);
157                 s->s_dev=0;
158                 free_super(s);
159                 return NULL;
160         }
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");
187         for (inode=inode_table+0 ; inode<inode_table+NR_INODE ; inode++)
188                 if (inode->i_dev==dev && inode->i_count)
189                                 return -EBUSY;
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 */
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;
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++) {
257                 p->s_dev = 0;
258                 p->s_lock = 0;
259                 p->s_wait = NULL;
260         }
261         if (!(p=read_super(ROOT_DEV)))
262                 panic("Unable to mount root");
263         if (!(mi=iget(ROOT_DEV,ROOT_INO)))
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 }
282 

[source navigation] [diff markup] [identifier search] [freetext search] [file search]

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.