|
|
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:
33: static int ext_file_read(struct inode *, struct file *, char *, int);
34: static int ext_file_write(struct inode *, struct file *, char *, int);
35:
36: /*
37: * We have mostly NULL's here: the current defaults are ok for
38: * the ext filesystem.
39: */
40: static struct file_operations ext_file_operations = {
41: NULL, /* lseek - default */
42: ext_file_read, /* read */
43: ext_file_write, /* write */
44: NULL, /* readdir - bad */
45: NULL, /* select - default */
46: NULL, /* ioctl - default */
47: NULL, /* no special open is needed */
48: NULL /* release */
49: };
50:
51: struct inode_operations ext_file_inode_operations = {
52: &ext_file_operations, /* default file operations */
53: NULL, /* create */
54: NULL, /* lookup */
55: NULL, /* link */
56: NULL, /* unlink */
57: NULL, /* symlink */
58: NULL, /* mkdir */
59: NULL, /* rmdir */
60: NULL, /* mknod */
61: NULL, /* rename */
62: NULL, /* readlink */
63: NULL, /* follow_link */
64: ext_bmap, /* bmap */
65: ext_truncate /* truncate */
66: };
67:
68: static inline void wait_on_buffer(struct buffer_head * bh)
69: {
70: cli();
71: while (bh->b_lock)
72: sleep_on(&bh->b_wait);
73: sti();
74: }
75:
76: static int ext_file_read(struct inode * inode, struct file * filp, char * buf, int count)
77: {
78: int read,left,chars,nr;
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;
107: if (nr = ext_bmap(inode,block++)) {
1.1.1.2 ! root 108: *bhb = getblk(inode->i_dev, nr, BLOCK_SIZE);
1.1 root 109: if (!(*bhb)->b_uptodate)
110: ll_rw_block(READ,*bhb);
111: } else
112: *bhb = NULL;
113:
114: if (++bhb == &buflist[NBUF])
115: bhb = buflist;
116:
117: if (bhb != bhe)
118: continue;
119: }
120: if (*bhe) {
121: wait_on_buffer(*bhe);
122: if (!(*bhe)->b_uptodate) {
123: do {
124: brelse(*bhe);
125: if (++bhe == &buflist[NBUF])
126: bhe = buflist;
127: } while (bhe != bhb);
128: break;
129: }
130: }
131:
132: if (left < BLOCK_SIZE - offset)
133: chars = left;
134: else
135: chars = BLOCK_SIZE - offset;
136: filp->f_pos += chars;
137: left -= chars;
138: read += chars;
139: if (*bhe) {
140: memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
141: brelse(*bhe);
142: buf += chars;
143: } else {
144: while (chars-->0)
145: put_fs_byte(0,buf++);
146: }
147: offset = 0;
148: if (++bhe == &buflist[NBUF])
149: bhe = buflist;
150: } while (left > 0);
151: if (!read)
152: return -EIO;
1.1.1.2 ! root 153: if (!IS_RDONLY(inode)) {
! 154: inode->i_atime = CURRENT_TIME;
! 155: inode->i_dirt = 1;
! 156: }
1.1 root 157: return read;
158: }
159:
160: static int ext_file_write(struct inode * inode, struct file * filp, char * buf, int count)
161: {
162: off_t pos;
163: int written,block,c;
164: struct buffer_head * bh;
165: char * p;
166:
167: if (!inode) {
168: printk("ext_file_write: inode = NULL\n");
169: return -EINVAL;
170: }
171: if (!S_ISREG(inode->i_mode)) {
172: printk("ext_file_write: mode = %07o\n",inode->i_mode);
173: return -EINVAL;
174: }
175: /*
176: * ok, append may not work when many processes are writing at the same time
177: * but so what. That way leads to madness anyway.
178: */
179: if (filp->f_flags & O_APPEND)
180: pos = inode->i_size;
181: else
182: pos = filp->f_pos;
183: written = 0;
184: while (written<count) {
185: if (!(block = ext_create_block(inode,pos/BLOCK_SIZE))) {
186: if (!written)
187: written = -ENOSPC;
188: break;
189: }
190: c = BLOCK_SIZE - (pos % BLOCK_SIZE);
191: if (c > count-written)
192: c = count-written;
193: if (c == BLOCK_SIZE)
1.1.1.2 ! root 194: bh = getblk(inode->i_dev, block, BLOCK_SIZE);
1.1 root 195: else
1.1.1.2 ! root 196: bh = bread(inode->i_dev, block, BLOCK_SIZE);
1.1 root 197: if (!bh) {
198: if (!written)
199: written = -EIO;
200: break;
201: }
202: p = (pos % BLOCK_SIZE) + bh->b_data;
203: pos += c;
204: if (pos > inode->i_size) {
205: inode->i_size = pos;
206: inode->i_dirt = 1;
207: }
208: written += c;
209: memcpy_fromfs(p,buf,c);
210: buf += c;
211: bh->b_uptodate = 1;
212: bh->b_dirt = 1;
213: brelse(bh);
214: }
215: inode->i_mtime = CURRENT_TIME;
216: inode->i_ctime = CURRENT_TIME;
217: filp->f_pos = pos;
218: inode->i_dirt = 1;
219: return written;
220: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.