Import 2.1.15
[davej-history.git] / fs / ext2 / file.c
blob12f1b24fa785e96d8e4727bd0cdca192f005a7fe
1 /*
2 * linux/fs/ext2/file.c
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)
9 * from
11 * linux/fs/minix/file.c
13 * Copyright (C) 1991, 1992 Linus Torvalds
15 * ext2 fs regular file handling primitives
18 #include <asm/uaccess.h>
19 #include <asm/system.h>
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>
31 #define NBUF 32
33 #define MIN(a,b) (((a)<(b))?(a):(b))
34 #define MAX(a,b) (((a)>(b))?(a):(b))
36 #include <linux/fs.h>
37 #include <linux/ext2_fs.h>
39 static long longext2_file_lseek(struct inode *,struct file *,long long,int);
40 static longext2_file_write(struct inode *,struct file *,const char*,unsigned long);
41 static voidext2_release_file(struct inode *,struct file *);
44 * We have mostly NULL's here: the current defaults are ok for
45 * the ext2 filesystem.
47 static struct file_operations ext2_file_operations = {
48 ext2_file_lseek,/* lseek */
49 generic_file_read,/* read */
50 ext2_file_write,/* write */
51 NULL,/* readdir - bad */
52 NULL,/* select - default */
53 ext2_ioctl,/* ioctl */
54 generic_file_mmap,/* mmap */
55 NULL,/* no special open is needed */
56 ext2_release_file,/* release */
57 ext2_sync_file,/* fsync */
58 NULL,/* fasync */
59 NULL,/* check_media_change */
60 NULL /* revalidate */
63 struct inode_operations ext2_file_inode_operations = {
64 &ext2_file_operations,/* default file operations */
65 NULL,/* create */
66 NULL,/* lookup */
67 NULL,/* link */
68 NULL,/* unlink */
69 NULL,/* symlink */
70 NULL,/* mkdir */
71 NULL,/* rmdir */
72 NULL,/* mknod */
73 NULL,/* rename */
74 NULL,/* readlink */
75 NULL,/* follow_link */
76 generic_readpage,/* readpage */
77 NULL,/* writepage */
78 ext2_bmap,/* bmap */
79 ext2_truncate,/* truncate */
80 ext2_permission,/* permission */
81 NULL /* smap */
85 * Make sure the offset never goes beyond the 32-bit mark..
87 static long longext2_file_lseek(struct inode *inode,
88 struct file *file,
89 long long offset,
90 int origin)
92 long long retval;
94 switch(origin) {
95 case2:
96 offset += inode->i_size;
97 break;
98 case1:
99 offset += file->f_pos;
101 retval = -EINVAL;
102 /* make sure the offset fits in 32 bits */
103 if(((unsigned long long) offset >>32) ==0) {
104 if(offset != file->f_pos) {
105 file->f_pos = offset;
106 file->f_reada =0;
107 file->f_version = ++event;
109 retval = offset;
111 return retval;
114 staticinlinevoidremove_suid(struct inode *inode)
116 unsigned int mode;
118 /* set S_IGID if S_IXGRP is set, and always set S_ISUID */
119 mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID;
121 /* was any of the uid bits set? */
122 mode &= inode->i_mode;
123 if(mode && !suser()) {
124 inode->i_mode &= ~mode;
125 inode->i_dirt =1;
129 static longext2_file_write(struct inode * inode,struct file * filp,
130 const char* buf,unsigned long count)
132 __u32 pos;
133 long block;
134 int offset;
135 int written, c;
136 struct buffer_head * bh, *bufferlist[NBUF];
137 struct super_block * sb;
138 int err;
139 int i,buffercount,write_error;
141 /* POSIX: mtime/ctime may not change for 0 count */
142 if(!count)
143 return0;
144 write_error = buffercount =0;
145 if(!inode) {
146 printk("ext2_file_write: inode = NULL\n");
147 return-EINVAL;
149 sb = inode->i_sb;
150 if(sb->s_flags & MS_RDONLY)
152 * This fs has been automatically remounted ro because of errors
154 return-ENOSPC;
156 if(!S_ISREG(inode->i_mode)) {
157 ext2_warning(sb,"ext2_file_write","mode = %07o",
158 inode->i_mode);
159 return-EINVAL;
161 remove_suid(inode);
163 if(filp->f_flags & O_APPEND)
164 pos = inode->i_size;
165 else
166 pos = filp->f_pos;
167 /* Check for overflow.. */
168 if(pos > (__u32) (pos + count)) {
169 count = ~pos;/* == 0xFFFFFFFF - pos */
170 if(!count)
171 return-EFBIG;
175 * If a file has been opened in synchronous mode, we have to ensure
176 * that meta-data will also be written synchronously. Thus, we
177 * set the i_osync field. This field is tested by the allocation
178 * routines.
180 if(filp->f_flags & O_SYNC)
181 inode->u.ext2_i.i_osync++;
182 block = pos >>EXT2_BLOCK_SIZE_BITS(sb);
183 offset = pos & (sb->s_blocksize -1);
184 c = sb->s_blocksize - offset;
185 written =0;
187 bh =ext2_getblk(inode, block,1, &err);
188 if(!bh) {
189 if(!written)
190 written = err;
191 break;
193 if(c > count)
194 c = count;
195 if(c != sb->s_blocksize && !buffer_uptodate(bh)) {
196 ll_rw_block(READ,1, &bh);
197 wait_on_buffer(bh);
198 if(!buffer_uptodate(bh)) {
199 brelse(bh);
200 if(!written)
201 written = -EIO;
202 break;
205 c -=copy_from_user(bh->b_data + offset, buf, c);
206 if(!c) {
207 brelse(bh);
208 if(!written)
209 written = -EFAULT;
210 break;
212 update_vm_cache(inode, pos, bh->b_data + offset, c);
213 pos += c;
214 written += c;
215 buf += c;
216 count -= c;
217 mark_buffer_uptodate(bh,1);
218 mark_buffer_dirty(bh,0);
219 if(filp->f_flags & O_SYNC)
220 bufferlist[buffercount++] = bh;
221 else
222 brelse(bh);
223 if(buffercount == NBUF){
224 ll_rw_block(WRITE, buffercount, bufferlist);
225 for(i=0; i<buffercount; i++){
226 wait_on_buffer(bufferlist[i]);
227 if(!buffer_uptodate(bufferlist[i]))
228 write_error=1;
229 brelse(bufferlist[i]);
231 buffercount=0;
233 if(write_error)
234 break;
235 block++;
236 offset =0;
237 c = sb->s_blocksize;
238 }while(count);
239 if( buffercount ){
240 ll_rw_block(WRITE, buffercount, bufferlist);
241 for(i=0; i<buffercount; i++){
242 wait_on_buffer(bufferlist[i]);
243 if(!buffer_uptodate(bufferlist[i]))
244 write_error=1;
245 brelse(bufferlist[i]);
248 if(pos > inode->i_size)
249 inode->i_size = pos;
250 if(filp->f_flags & O_SYNC)
251 inode->u.ext2_i.i_osync--;
252 inode->i_ctime = inode->i_mtime = CURRENT_TIME;
253 filp->f_pos = pos;
254 inode->i_dirt =1;
255 return written;
259 * Called when an inode is released. Note that this is different
260 * from ext2_open: open gets called at every open, but release
261 * gets called only when /all/ the files are closed.
263 static voidext2_release_file(struct inode * inode,struct file * filp)
265 if(filp->f_mode &2)
266 ext2_discard_prealloc(inode);
close