|
|
1.1 root 1: /*
2: * linux/fs/ext/inode.c
3: *
1.1.1.2 root 4: * Copyright (C) 1992 Remy Card ([email protected])
1.1 root 5: *
6: * from
7: *
8: * linux/fs/minix/inode.c
9: *
1.1.1.2 root 10: * Copyright (C) 1991, 1992 Linus Torvalds
1.1 root 11: */
12:
13: #include <linux/sched.h>
14: #include <linux/ext_fs.h>
15: #include <linux/kernel.h>
16: #include <linux/mm.h>
1.1.1.2 root 17: #include <linux/string.h>
18: #include <linux/stat.h>
19:
1.1 root 20: #include <asm/system.h>
21: #include <asm/segment.h>
22:
23: int sync_dev(int dev);
24:
1.1.1.3 ! root 25: static inline void wait_on_buffer(struct buffer_head * bh)
! 26: {
! 27: cli();
! 28: while (bh->b_lock)
! 29: sleep_on(&bh->b_wait);
! 30: sti();
! 31: }
! 32:
1.1 root 33: void ext_put_inode(struct inode *inode)
34: {
35: inode->i_size = 0;
36: ext_truncate(inode);
37: ext_free_inode(inode);
38: }
39:
40: void ext_put_super(struct super_block *sb)
41: {
42:
43: lock_super(sb);
44: sb->s_dev = 0;
1.1.1.3 ! root 45: if (sb->u.ext_sb.s_firstfreeinodeblock)
! 46: brelse (sb->u.ext_sb.s_firstfreeinodeblock);
! 47: if (sb->u.ext_sb.s_firstfreeblock)
! 48: brelse (sb->u.ext_sb.s_firstfreeblock);
1.1 root 49: free_super(sb);
50: return;
51: }
52:
53: static struct super_operations ext_sops = {
54: ext_read_inode,
55: ext_write_inode,
56: ext_put_inode,
57: ext_put_super,
58: ext_write_super,
59: ext_statfs
60: };
61:
62: struct super_block *ext_read_super(struct super_block *s,void *data)
63: {
64: struct buffer_head *bh;
65: struct ext_super_block *es;
1.1.1.2 root 66: int dev = s->s_dev,block;
1.1 root 67:
68: lock_super(s);
1.1.1.2 root 69: if (!(bh = bread(dev, 1, BLOCK_SIZE))) {
1.1 root 70: s->s_dev=0;
71: free_super(s);
72: printk("bread failed\n");
73: return NULL;
74: }
75: es = (struct ext_super_block *) bh->b_data;
1.1.1.2 root 76: s->s_blocksize = 1024;
77: s->u.ext_sb.s_ninodes = es->s_ninodes;
78: s->u.ext_sb.s_nzones = es->s_nzones;
79: s->u.ext_sb.s_firstdatazone = es->s_firstdatazone;
80: s->u.ext_sb.s_log_zone_size = es->s_log_zone_size;
81: s->u.ext_sb.s_max_size = es->s_max_size;
1.1 root 82: s->s_magic = es->s_magic;
1.1.1.3 ! root 83: s->u.ext_sb.s_firstfreeblocknumber = es->s_firstfreeblock;
! 84: s->u.ext_sb.s_freeblockscount = es->s_freeblockscount;
! 85: s->u.ext_sb.s_firstfreeinodenumber = es->s_firstfreeinode;
! 86: s->u.ext_sb.s_freeinodescount = es->s_freeinodescount;
1.1 root 87: brelse(bh);
88: if (s->s_magic != EXT_SUPER_MAGIC) {
89: s->s_dev = 0;
90: free_super(s);
91: printk("magic match failed\n");
92: return NULL;
93: }
1.1.1.3 ! root 94: if (!s->u.ext_sb.s_firstfreeblocknumber)
! 95: s->u.ext_sb.s_firstfreeblock = NULL;
1.1 root 96: else
1.1.1.3 ! root 97: if (!(s->u.ext_sb.s_firstfreeblock = bread(dev,
! 98: s->u.ext_sb.s_firstfreeblocknumber, BLOCK_SIZE))) {
1.1 root 99: printk ("ext_read_super: unable to read first free block\n");
100: s->s_dev = 0;
101: free_super(s);
102: return NULL;
103: }
1.1.1.3 ! root 104: if (!s->u.ext_sb.s_firstfreeinodenumber)
! 105: s->u.ext_sb.s_firstfreeinodeblock = NULL;
1.1 root 106: else {
1.1.1.3 ! root 107: block = 2 + (s->u.ext_sb.s_firstfreeinodenumber - 1) / EXT_INODES_PER_BLOCK;
! 108: if (!(s->u.ext_sb.s_firstfreeinodeblock = bread(dev, block, BLOCK_SIZE))) {
1.1 root 109: printk ("ext_read_super: unable to read first free inode block\n");
1.1.1.3 ! root 110: brelse(s->u.ext_sb.s_firstfreeblock);
1.1 root 111: s->s_dev = 0;
112: free_super (s);
113: return NULL;
114: }
115: }
116: free_super(s);
117: /* set up enough so that it can read an inode */
118: s->s_dev = dev;
119: s->s_op = &ext_sops;
120: if (!(s->s_mounted = iget(dev,EXT_ROOT_INO))) {
121: s->s_dev=0;
122: printk("get root inode failed\n");
123: return NULL;
124: }
125: return s;
126: }
127:
128: void ext_write_super (struct super_block *sb)
129: {
130: struct buffer_head * bh;
131: struct ext_super_block * es;
132:
1.1.1.2 root 133: if (!(bh = bread(sb->s_dev, 1, BLOCK_SIZE))) {
1.1 root 134: printk ("ext_write_super: bread failed\n");
135: return;
136: }
137: es = (struct ext_super_block *) bh->b_data;
1.1.1.3 ! root 138: es->s_firstfreeblock = sb->u.ext_sb.s_firstfreeblocknumber;
! 139: es->s_freeblockscount = sb->u.ext_sb.s_freeblockscount;
! 140: es->s_firstfreeinode = sb->u.ext_sb.s_firstfreeinodenumber;
! 141: es->s_freeinodescount = sb->u.ext_sb.s_freeinodescount;
1.1 root 142: bh->b_dirt = 1;
143: brelse (bh);
144: sb->s_dirt = 0;
145: }
146:
147: void ext_statfs (struct super_block *sb, struct statfs *buf)
148: {
149: long tmp;
150:
151: put_fs_long(EXT_SUPER_MAGIC, &buf->f_type);
152: put_fs_long(1024, &buf->f_bsize);
1.1.1.3 ! root 153: put_fs_long(sb->u.ext_sb.s_nzones << sb->u.ext_sb.s_log_zone_size,
! 154: &buf->f_blocks);
1.1 root 155: tmp = ext_count_free_blocks(sb);
156: put_fs_long(tmp, &buf->f_bfree);
157: put_fs_long(tmp, &buf->f_bavail);
1.1.1.2 root 158: put_fs_long(sb->u.ext_sb.s_ninodes, &buf->f_files);
1.1 root 159: put_fs_long(ext_count_free_inodes(sb), &buf->f_ffree);
160: /* Don't know what value to put in buf->f_fsid */
161: }
162:
1.1.1.3 ! root 163: #define inode_bmap(inode,nr) ((inode)->u.ext_i.i_data[(nr)])
! 164:
! 165: static int block_bmap(struct buffer_head * bh, int nr)
! 166: {
! 167: int tmp;
! 168:
! 169: if (!bh)
! 170: return 0;
! 171: tmp = ((unsigned long *) bh->b_data)[nr];
! 172: brelse(bh);
! 173: return tmp;
! 174: }
! 175:
! 176: int ext_bmap(struct inode * inode,int block)
1.1 root 177: {
178: int i;
179:
180: if (block<0) {
1.1.1.3 ! root 181: printk("ext_bmap: block<0");
1.1 root 182: return 0;
183: }
184: if (block >= 9+256+256*256+256*256*256) {
1.1.1.3 ! root 185: printk("ext_bmap: block>big");
1.1 root 186: return 0;
187: }
1.1.1.3 ! root 188: if (block<9)
! 189: return inode_bmap(inode,block);
1.1 root 190: block -= 9;
191: if (block<256) {
1.1.1.3 ! root 192: i = inode_bmap(inode,9);
! 193: if (!i)
1.1 root 194: return 0;
1.1.1.3 ! root 195: return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block);
1.1 root 196: }
197: block -= 256;
198: if (block<256*256) {
1.1.1.3 ! root 199: i = inode_bmap(inode,10);
1.1 root 200: if (!i)
201: return 0;
1.1.1.3 ! root 202: i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>8);
! 203: if (!i)
1.1 root 204: return 0;
1.1.1.3 ! root 205: return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255);
1.1 root 206: }
1.1.1.3 ! root 207: block -= 256*256;
! 208: i = inode_bmap(inode,11);
1.1.1.2 root 209: if (!i)
210: return 0;
1.1.1.3 ! root 211: i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>16);
1.1.1.2 root 212: if (!i)
213: return 0;
1.1.1.3 ! root 214: i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),(block>>8) & 255);
! 215: if (!i)
1.1.1.2 root 216: return 0;
1.1.1.3 ! root 217: return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255);
! 218: }
! 219:
! 220: static struct buffer_head * inode_getblk(struct inode * inode, int nr, int create)
! 221: {
! 222: int tmp;
! 223: unsigned long * p;
! 224: struct buffer_head * result;
! 225:
! 226: p = inode->u.ext_i.i_data + nr;
! 227: repeat:
! 228: tmp = *p;
! 229: if (tmp) {
! 230: result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
! 231: if (tmp == *p)
! 232: return result;
! 233: brelse(result);
! 234: goto repeat;
! 235: }
! 236: if (!create)
! 237: return NULL;
! 238: tmp = ext_new_block(inode->i_dev);
! 239: if (!tmp)
! 240: return NULL;
! 241: result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
! 242: if (*p) {
! 243: ext_free_block(inode->i_dev,tmp);
! 244: brelse(result);
! 245: goto repeat;
! 246: }
! 247: *p = tmp;
! 248: inode->i_ctime = CURRENT_TIME;
! 249: inode->i_dirt = 1;
! 250: return result;
! 251: }
! 252:
! 253: static struct buffer_head * block_getblk(struct buffer_head * bh, int nr, int create)
! 254: {
! 255: int tmp;
! 256: unsigned long * p;
! 257: struct buffer_head * result;
! 258:
! 259: if (!bh)
! 260: return NULL;
! 261: if (!bh->b_uptodate) {
! 262: ll_rw_block(READ,bh);
! 263: wait_on_buffer(bh);
! 264: if (!bh->b_uptodate) {
! 265: brelse(bh);
! 266: return NULL;
1.1.1.2 root 267: }
1.1.1.3 ! root 268: }
! 269: p = nr + (unsigned long *) bh->b_data;
! 270: repeat:
! 271: tmp = *p;
! 272: if (tmp) {
! 273: result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
! 274: if (tmp == *p) {
! 275: brelse(bh);
! 276: return result;
! 277: }
! 278: brelse(result);
! 279: goto repeat;
! 280: }
! 281: if (!create) {
! 282: brelse(bh);
! 283: return NULL;
! 284: }
! 285: tmp = ext_new_block(bh->b_dev);
! 286: if (!tmp) {
! 287: brelse(bh);
! 288: return NULL;
! 289: }
! 290: result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
! 291: if (*p) {
! 292: ext_free_block(bh->b_dev,tmp);
! 293: brelse(result);
! 294: goto repeat;
! 295: }
! 296: *p = tmp;
! 297: bh->b_dirt = 1;
! 298: brelse(bh);
! 299: return result;
1.1 root 300: }
301:
1.1.1.3 ! root 302: struct buffer_head * ext_getblk(struct inode * inode, int block, int create)
1.1 root 303: {
1.1.1.3 ! root 304: struct buffer_head * bh;
! 305:
! 306: if (block<0) {
! 307: printk("ext_getblk: block<0\n");
! 308: return NULL;
! 309: }
! 310: if (block >= 9+256+256*256+256*256*256) {
! 311: printk("ext_getblk: block>big\n");
! 312: return NULL;
! 313: }
! 314: if (block<9)
! 315: return inode_getblk(inode,block,create);
! 316: block -= 9;
! 317: if (block<256) {
! 318: bh = inode_getblk(inode,9,create);
! 319: return block_getblk(bh,block,create);
! 320: }
! 321: block -= 256;
! 322: if (block<256*256) {
! 323: bh = inode_getblk(inode,10,create);
! 324: bh = block_getblk(bh,block>>8,create);
! 325: return block_getblk(bh,block & 255,create);
! 326: }
! 327: block -= 256*256;
! 328: bh = inode_getblk(inode,11,create);
! 329: bh = block_getblk(bh,block>>16,create);
! 330: bh = block_getblk(bh,(block>>8) & 255,create);
! 331: return block_getblk(bh,block & 255,create);
1.1 root 332: }
333:
1.1.1.3 ! root 334: struct buffer_head * ext_bread(struct inode * inode, int block, int create)
1.1 root 335: {
1.1.1.3 ! root 336: struct buffer_head * bh;
! 337:
! 338: bh = ext_getblk(inode,block,create);
! 339: if (!bh || bh->b_uptodate)
! 340: return bh;
! 341: ll_rw_block(READ,bh);
! 342: wait_on_buffer(bh);
! 343: if (bh->b_uptodate)
! 344: return bh;
! 345: brelse(bh);
! 346: return NULL;
1.1 root 347: }
348:
349: void ext_read_inode(struct inode * inode)
350: {
351: struct buffer_head * bh;
352: struct ext_inode * raw_inode;
353: int block;
354:
355: block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK;
1.1.1.2 root 356: if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
1.1 root 357: panic("unable to read i-node block");
358: raw_inode = ((struct ext_inode *) bh->b_data) +
359: (inode->i_ino-1)%EXT_INODES_PER_BLOCK;
360: inode->i_mode = raw_inode->i_mode;
361: inode->i_uid = raw_inode->i_uid;
362: inode->i_gid = raw_inode->i_gid;
363: inode->i_nlink = raw_inode->i_nlinks;
364: inode->i_size = raw_inode->i_size;
365: inode->i_mtime = inode->i_atime = inode->i_ctime = raw_inode->i_time;
1.1.1.3 ! root 366: inode->i_blocks = inode->i_blksize = 0;
1.1 root 367: if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
368: inode->i_rdev = raw_inode->i_zone[0];
369: else for (block = 0; block < 12; block++)
1.1.1.3 ! root 370: inode->u.ext_i.i_data[block] = raw_inode->i_zone[block];
1.1 root 371: brelse(bh);
372: inode->i_op = NULL;
373: if (S_ISREG(inode->i_mode))
374: inode->i_op = &ext_file_inode_operations;
375: else if (S_ISDIR(inode->i_mode))
376: inode->i_op = &ext_dir_inode_operations;
377: else if (S_ISLNK(inode->i_mode))
378: inode->i_op = &ext_symlink_inode_operations;
379: else if (S_ISCHR(inode->i_mode))
380: inode->i_op = &ext_chrdev_inode_operations;
381: else if (S_ISBLK(inode->i_mode))
382: inode->i_op = &ext_blkdev_inode_operations;
383: else if (S_ISFIFO(inode->i_mode)) {
384: inode->i_op = &ext_fifo_inode_operations;
385: inode->i_pipe = 1;
1.1.1.3 ! root 386: PIPE_BASE(*inode) = NULL;
1.1 root 387: PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
1.1.1.3 ! root 388: PIPE_READ_WAIT(*inode) = PIPE_WRITE_WAIT(*inode) = NULL;
1.1 root 389: PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
390: }
391: }
392:
393: void ext_write_inode(struct inode * inode)
394: {
395: struct buffer_head * bh;
396: struct ext_inode * raw_inode;
397: int block;
398:
399: block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK;
1.1.1.2 root 400: if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
1.1 root 401: panic("unable to read i-node block");
402: raw_inode = ((struct ext_inode *)bh->b_data) +
403: (inode->i_ino-1)%EXT_INODES_PER_BLOCK;
404: raw_inode->i_mode = inode->i_mode;
405: raw_inode->i_uid = inode->i_uid;
406: raw_inode->i_gid = inode->i_gid;
407: raw_inode->i_nlinks = inode->i_nlink;
408: raw_inode->i_size = inode->i_size;
409: raw_inode->i_time = inode->i_mtime;
410: if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
411: raw_inode->i_zone[0] = inode->i_rdev;
412: else for (block = 0; block < 12; block++)
1.1.1.3 ! root 413: raw_inode->i_zone[block] = inode->u.ext_i.i_data[block];
1.1 root 414: bh->b_dirt=1;
415: inode->i_dirt=0;
416: brelse(bh);
417: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.