1 /*
2 * linux/fs/ext2/file.c
3 *
4 * Copyright (C) 1992, 1993, 1994, 1995
5 * Remy Card (card@masi.ibp.fr)
6 * Laboratoire MASI - Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 *
9 * from
10 *
11 * linux/fs/minix/file.c
12 *
13 * Copyright (C) 1991, 1992 Linus Torvalds
14 *
15 * ext2 fs regular file handling primitives
16 */
17
18 #include <asm/segment.h>
19 #include <asm/system.h>
20
21 #include <linux/errno.h>
22 #include <linux/fs.h>
23 #include <linux/ext2_fs.h>
24 #include <linux/fcntl.h>
25 #include <linux/sched.h>
26 #include <linux/stat.h>
27 #include <linux/locks.h>
28 #include <linux/mm.h>
29 #include <linux/pagemap.h>
30
31 #define NBUF 32
32
33 #define MIN(a,b) (((a)<(b))?(a):(b))
34 #define MAX(a,b) (((a)>(b))?(a):(b))
35
36 #include <linux/fs.h>
37 #include <linux/ext2_fs.h>
38
39 static int ext2_file_write (struct inode *, struct file *, const char *, int);
40 static void ext2_release_file (struct inode *, struct file *);
41
42 /*
43 * We have mostly NULL's here: the current defaults are ok for
44 * the ext2 filesystem.
45 */
46 static struct file_operations ext2_file_operations = {
47 NULL, /* lseek - default */
48 generic_file_read, /* read */
49 ext2_file_write, /* write */
50 NULL, /* readdir - bad */
51 NULL, /* select - default */
52 ext2_ioctl, /* ioctl */
53 generic_mmap, /* mmap */
54 NULL, /* no special open is needed */
55 ext2_release_file, /* release */
56 ext2_sync_file, /* fsync */
57 NULL, /* fasync */
58 NULL, /* check_media_change */
59 NULL /* revalidate */
60 };
61
62 struct inode_operations ext2_file_inode_operations = {
63 &ext2_file_operations,/* default file operations */
64 NULL, /* create */
65 NULL, /* lookup */
66 NULL, /* link */
67 NULL, /* unlink */
68 NULL, /* symlink */
69 NULL, /* mkdir */
70 NULL, /* rmdir */
71 NULL, /* mknod */
72 NULL, /* rename */
73 NULL, /* readlink */
74 NULL, /* follow_link */
75 generic_readpage, /* readpage */
76 NULL, /* writepage */
77 ext2_bmap, /* bmap */
78 ext2_truncate, /* truncate */
79 ext2_permission, /* permission */
80 NULL /* smap */
81 };
82
83 static int ext2_file_write (struct inode * inode, struct file * filp,
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
84 const char * buf, int count)
85 {
86 const loff_t two_gb = 2147483647;
87 loff_t pos;
88 off_t pos2;
89 long block;
90 int offset;
91 int written, c;
92 struct buffer_head * bh, *bufferlist[NBUF];
93 struct super_block * sb;
94 int err;
95 int i,buffercount,write_error;
96
97 write_error = buffercount = 0;
98 if (!inode) {
99 printk("ext2_file_write: inode = NULL\n");
100 return -EINVAL;
101 }
102 sb = inode->i_sb;
103 if (sb->s_flags & MS_RDONLY)
104 /*
105 * This fs has been automatically remounted ro because of errors
106 */
107 return -ENOSPC;
108
109 if (!S_ISREG(inode->i_mode)) {
110 ext2_warning (sb, "ext2_file_write", "mode = %07o",
111 inode->i_mode);
112 return -EINVAL;
113 }
114 if (filp->f_flags & O_APPEND)
115 pos = inode->i_size;
116 else
117 pos = filp->f_pos;
118 pos2 = (off_t) pos;
119 /*
120 * If a file has been opened in synchronous mode, we have to ensure
121 * that meta-data will also be written synchronously. Thus, we
122 * set the i_osync field. This field is tested by the allocation
123 * routines.
124 */
125 if (filp->f_flags & O_SYNC)
126 inode->u.ext2_i.i_osync++;
127 block = pos2 >> EXT2_BLOCK_SIZE_BITS(sb);
128 offset = pos2 & (sb->s_blocksize - 1);
129 c = sb->s_blocksize - offset;
130 written = 0;
131 while (count > 0) {
132 if (pos > two_gb) {
133 if (!written)
134 written = -EFBIG;
135 break;
136 }
137 bh = ext2_getblk (inode, block, 1, &err);
138 if (!bh) {
139 if (!written)
140 written = err;
141 break;
142 }
143 count -= c;
144 if (count < 0)
145 c += count;
146 if (c != sb->s_blocksize && !buffer_uptodate(bh)) {
147 ll_rw_block (READ, 1, &bh);
148 wait_on_buffer (bh);
149 if (!buffer_uptodate(bh)) {
150 brelse (bh);
151 if (!written)
152 written = -EIO;
153 break;
154 }
155 }
156 memcpy_fromfs (bh->b_data + offset, buf, c);
157 update_vm_cache(inode, pos, bh->b_data + offset, c);
158 pos2 += c;
159 pos += c;
160 written += c;
161 buf += c;
162 mark_buffer_uptodate(bh, 1);
163 mark_buffer_dirty(bh, 0);
164 if (filp->f_flags & O_SYNC)
165 bufferlist[buffercount++] = bh;
166 else
167 brelse(bh);
168 if (buffercount == NBUF){
169 ll_rw_block(WRITE, buffercount, bufferlist);
170 for(i=0; i<buffercount; i++){
171 wait_on_buffer(bufferlist[i]);
172 if (!buffer_uptodate(bufferlist[i]))
173 write_error=1;
174 brelse(bufferlist[i]);
175 }
176 buffercount=0;
177 }
178 if(write_error)
179 break;
180 block++;
181 offset = 0;
182 c = sb->s_blocksize;
183 }
184 if ( buffercount ){
185 ll_rw_block(WRITE, buffercount, bufferlist);
186 for(i=0; i<buffercount; i++){
187 wait_on_buffer(bufferlist[i]);
188 if (!buffer_uptodate(bufferlist[i]))
189 write_error=1;
190 brelse(bufferlist[i]);
191 }
192 }
193 if (pos > inode->i_size)
194 inode->i_size = pos;
195 if (filp->f_flags & O_SYNC)
196 inode->u.ext2_i.i_osync--;
197 inode->i_ctime = inode->i_mtime = CURRENT_TIME;
198 filp->f_pos = pos;
199 inode->i_dirt = 1;
200 return written;
201 }
202
203 /*
204 * Called when a inode is released. Note that this is different
205 * from ext2_open: open gets called at every open, but release
206 * gets called only when /all/ the files are closed.
207 */
208 static void ext2_release_file (struct inode * inode, struct file * filp)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
209 {
210 if (filp->f_mode & 2)
211 ext2_discard_prealloc (inode);
212 }