|
|
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.