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