|
|
1.1 ! root 1: /* ! 2: * linux/fs/ext/file.c ! 3: * ! 4: * (C) 1992 Remy Card ([email protected]) ! 5: * ! 6: * from ! 7: * ! 8: * linux/fs/minix/file.c ! 9: * ! 10: * (C) 1991 Linus Torvalds ! 11: * ! 12: * ext regular file handling primitives ! 13: */ ! 14: ! 15: #include <errno.h> ! 16: ! 17: #include <sys/dirent.h> ! 18: ! 19: #include <asm/segment.h> ! 20: #include <asm/system.h> ! 21: ! 22: #include <linux/fcntl.h> ! 23: #include <linux/sched.h> ! 24: #include <linux/ext_fs.h> ! 25: #include <linux/kernel.h> ! 26: #include <linux/stat.h> ! 27: ! 28: #define NBUF 16 ! 29: ! 30: #define MIN(a,b) (((a)<(b))?(a):(b)) ! 31: #define MAX(a,b) (((a)>(b))?(a):(b)) ! 32: ! 33: #include <linux/fs.h> ! 34: #include <linux/ext_fs.h> ! 35: ! 36: static int ext_file_read(struct inode *, struct file *, char *, int); ! 37: static int ext_file_write(struct inode *, struct file *, char *, int); ! 38: ! 39: /* ! 40: * We have mostly NULL's here: the current defaults are ok for ! 41: * the ext filesystem. ! 42: */ ! 43: static struct file_operations ext_file_operations = { ! 44: NULL, /* lseek - default */ ! 45: ext_file_read, /* read */ ! 46: ext_file_write, /* write */ ! 47: NULL, /* readdir - bad */ ! 48: NULL, /* select - default */ ! 49: NULL, /* ioctl - default */ ! 50: NULL, /* no special open is needed */ ! 51: NULL /* release */ ! 52: }; ! 53: ! 54: struct inode_operations ext_file_inode_operations = { ! 55: &ext_file_operations, /* default file operations */ ! 56: NULL, /* create */ ! 57: NULL, /* lookup */ ! 58: NULL, /* link */ ! 59: NULL, /* unlink */ ! 60: NULL, /* symlink */ ! 61: NULL, /* mkdir */ ! 62: NULL, /* rmdir */ ! 63: NULL, /* mknod */ ! 64: NULL, /* rename */ ! 65: NULL, /* readlink */ ! 66: NULL, /* follow_link */ ! 67: ext_bmap, /* bmap */ ! 68: ext_truncate /* truncate */ ! 69: }; ! 70: ! 71: static inline void wait_on_buffer(struct buffer_head * bh) ! 72: { ! 73: cli(); ! 74: while (bh->b_lock) ! 75: sleep_on(&bh->b_wait); ! 76: sti(); ! 77: } ! 78: ! 79: static int ext_file_read(struct inode * inode, struct file * filp, char * buf, int count) ! 80: { ! 81: int read,left,chars,nr; ! 82: int block, blocks, offset; ! 83: struct buffer_head ** bhb, ** bhe; ! 84: struct buffer_head * buflist[NBUF]; ! 85: ! 86: if (!inode) { ! 87: printk("ext_file_read: inode = NULL\n"); ! 88: return -EINVAL; ! 89: } ! 90: if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) { ! 91: printk("ext_file_read: mode = %07o\n",inode->i_mode); ! 92: return -EINVAL; ! 93: } ! 94: if (filp->f_pos > inode->i_size) ! 95: left = 0; ! 96: else ! 97: left = inode->i_size - filp->f_pos; ! 98: if (left > count) ! 99: left = count; ! 100: if (left <= 0) ! 101: return 0; ! 102: read = 0; ! 103: block = filp->f_pos >> BLOCK_SIZE_BITS; ! 104: offset = filp->f_pos & (BLOCK_SIZE-1); ! 105: blocks = (left + offset + BLOCK_SIZE - 1) / BLOCK_SIZE; ! 106: bhb = bhe = buflist; ! 107: do { ! 108: if (blocks) { ! 109: --blocks; ! 110: if (nr = ext_bmap(inode,block++)) { ! 111: *bhb = getblk(inode->i_dev,nr); ! 112: if (!(*bhb)->b_uptodate) ! 113: ll_rw_block(READ,*bhb); ! 114: } else ! 115: *bhb = NULL; ! 116: ! 117: if (++bhb == &buflist[NBUF]) ! 118: bhb = buflist; ! 119: ! 120: if (bhb != bhe) ! 121: continue; ! 122: } ! 123: if (*bhe) { ! 124: wait_on_buffer(*bhe); ! 125: if (!(*bhe)->b_uptodate) { ! 126: do { ! 127: brelse(*bhe); ! 128: if (++bhe == &buflist[NBUF]) ! 129: bhe = buflist; ! 130: } while (bhe != bhb); ! 131: break; ! 132: } ! 133: } ! 134: ! 135: if (left < BLOCK_SIZE - offset) ! 136: chars = left; ! 137: else ! 138: chars = BLOCK_SIZE - offset; ! 139: filp->f_pos += chars; ! 140: left -= chars; ! 141: read += chars; ! 142: if (*bhe) { ! 143: memcpy_tofs(buf,offset+(*bhe)->b_data,chars); ! 144: brelse(*bhe); ! 145: buf += chars; ! 146: } else { ! 147: while (chars-->0) ! 148: put_fs_byte(0,buf++); ! 149: } ! 150: offset = 0; ! 151: if (++bhe == &buflist[NBUF]) ! 152: bhe = buflist; ! 153: } while (left > 0); ! 154: if (!read) ! 155: return -EIO; ! 156: inode->i_atime = CURRENT_TIME; ! 157: inode->i_dirt = 1; ! 158: return read; ! 159: } ! 160: ! 161: static int ext_file_write(struct inode * inode, struct file * filp, char * buf, int count) ! 162: { ! 163: off_t pos; ! 164: int written,block,c; ! 165: struct buffer_head * bh; ! 166: char * p; ! 167: ! 168: if (!inode) { ! 169: printk("ext_file_write: inode = NULL\n"); ! 170: return -EINVAL; ! 171: } ! 172: if (!S_ISREG(inode->i_mode)) { ! 173: printk("ext_file_write: mode = %07o\n",inode->i_mode); ! 174: return -EINVAL; ! 175: } ! 176: /* ! 177: * ok, append may not work when many processes are writing at the same time ! 178: * but so what. That way leads to madness anyway. ! 179: */ ! 180: if (filp->f_flags & O_APPEND) ! 181: pos = inode->i_size; ! 182: else ! 183: pos = filp->f_pos; ! 184: written = 0; ! 185: while (written<count) { ! 186: if (!(block = ext_create_block(inode,pos/BLOCK_SIZE))) { ! 187: if (!written) ! 188: written = -ENOSPC; ! 189: break; ! 190: } ! 191: c = BLOCK_SIZE - (pos % BLOCK_SIZE); ! 192: if (c > count-written) ! 193: c = count-written; ! 194: if (c == BLOCK_SIZE) ! 195: bh = getblk(inode->i_dev, block); ! 196: else ! 197: bh = bread(inode->i_dev,block); ! 198: if (!bh) { ! 199: if (!written) ! 200: written = -EIO; ! 201: break; ! 202: } ! 203: p = (pos % BLOCK_SIZE) + bh->b_data; ! 204: pos += c; ! 205: if (pos > inode->i_size) { ! 206: inode->i_size = pos; ! 207: inode->i_dirt = 1; ! 208: } ! 209: written += c; ! 210: memcpy_fromfs(p,buf,c); ! 211: buf += c; ! 212: bh->b_uptodate = 1; ! 213: bh->b_dirt = 1; ! 214: brelse(bh); ! 215: } ! 216: inode->i_mtime = CURRENT_TIME; ! 217: inode->i_ctime = CURRENT_TIME; ! 218: filp->f_pos = pos; ! 219: inode->i_dirt = 1; ! 220: return written; ! 221: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.