This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / fs / xfs / linux / xfs_file.c
1 /*
2  * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it would be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.  Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc., 59
21  * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22  *
23  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24  * Mountain View, CA  94043, or:
25  *
26  * http://www.sgi.com
27  *
28  * For further information regarding this notice, see:
29  *
30  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31  */
32
33 #include "xfs.h"
34 #include "xfs_inum.h"
35 #include "xfs_log.h"
36 #include "xfs_sb.h"
37 #include "xfs_dir.h"
38 #include "xfs_dir2.h"
39 #include "xfs_trans.h"
40 #include "xfs_dmapi.h"
41 #include "xfs_mount.h"
42 #include "xfs_bmap_btree.h"
43 #include "xfs_alloc_btree.h"
44 #include "xfs_ialloc_btree.h"
45 #include "xfs_alloc.h"
46 #include "xfs_btree.h"
47 #include "xfs_attr_sf.h"
48 #include "xfs_dir_sf.h"
49 #include "xfs_dir2_sf.h"
50 #include "xfs_dinode.h"
51 #include "xfs_inode.h"
52 #include "xfs_error.h"
53 #include "xfs_rw.h"
54
55 #include <linux/dcache.h>
56
57 static struct vm_operations_struct linvfs_file_vm_ops;
58
59
60 STATIC inline ssize_t
61 __linvfs_read(
62         struct kiocb            *iocb,
63         char __user             *buf,
64         int                     ioflags,
65         size_t                  count,
66         loff_t                  pos)
67 {
68         struct iovec            iov = {buf, count};
69         struct file             *file = iocb->ki_filp;
70         vnode_t                 *vp = LINVFS_GET_VP(file->f_dentry->d_inode);
71         ssize_t                 rval;
72
73         BUG_ON(iocb->ki_pos != pos);
74
75         if (unlikely(file->f_flags & O_DIRECT))
76                 ioflags |= IO_ISDIRECT;
77         VOP_READ(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval);
78         return rval;
79 }
80
81
82 STATIC ssize_t
83 linvfs_read(
84         struct kiocb            *iocb,
85         char __user             *buf,
86         size_t                  count,
87         loff_t                  pos)
88 {
89         return __linvfs_read(iocb, buf, 0, count, pos);
90 }
91
92 STATIC ssize_t
93 linvfs_read_invis(
94         struct kiocb            *iocb,
95         char __user             *buf,
96         size_t                  count,
97         loff_t                  pos)
98 {
99         return __linvfs_read(iocb, buf, IO_INVIS, count, pos);
100 }
101
102
103 STATIC inline ssize_t
104 __linvfs_write(
105         struct kiocb    *iocb,
106         const char      *buf,
107         int             ioflags,
108         size_t          count,
109         loff_t          pos)
110 {
111         struct iovec    iov = {(void *)buf, count};
112         struct file     *file = iocb->ki_filp;
113         struct inode    *inode = file->f_mapping->host;
114         vnode_t         *vp = LINVFS_GET_VP(inode);
115         ssize_t         rval;
116
117         BUG_ON(iocb->ki_pos != pos);
118         if (unlikely(file->f_flags & O_DIRECT)) {
119                 ioflags |= IO_ISDIRECT;
120                 VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos,
121                                 ioflags, NULL, rval);
122         } else {
123                 down(&inode->i_sem);
124                 VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos,
125                                 ioflags, NULL, rval);
126                 up(&inode->i_sem);
127         }
128
129         return rval;
130 }
131
132
133 STATIC ssize_t
134 linvfs_write(
135         struct kiocb            *iocb,
136         const char __user       *buf,
137         size_t                  count,
138         loff_t                  pos)
139 {
140         return __linvfs_write(iocb, buf, 0, count, pos);
141 }
142
143 STATIC ssize_t
144 linvfs_write_invis(
145         struct kiocb            *iocb,
146         const char __user       *buf,
147         size_t                  count,
148         loff_t                  pos)
149 {
150         return __linvfs_write(iocb, buf, IO_INVIS, count, pos);
151 }
152
153
154 STATIC inline ssize_t
155 __linvfs_readv(
156         struct file             *file,
157         const struct iovec      *iov,
158         int                     ioflags,
159         unsigned long           nr_segs,
160         loff_t                  *ppos)
161 {
162         struct inode    *inode = file->f_mapping->host;
163         vnode_t         *vp = LINVFS_GET_VP(inode);
164         struct          kiocb kiocb;
165         ssize_t         rval;
166
167         init_sync_kiocb(&kiocb, file);
168         kiocb.ki_pos = *ppos;
169
170         if (unlikely(file->f_flags & O_DIRECT))
171                 ioflags |= IO_ISDIRECT;
172         VOP_READ(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval);
173         if (rval == -EIOCBQUEUED)
174                 rval = wait_on_sync_kiocb(&kiocb);
175
176         *ppos = kiocb.ki_pos;
177         return rval;
178 }
179
180 STATIC ssize_t
181 linvfs_readv(
182         struct file             *file,
183         const struct iovec      *iov,
184         unsigned long           nr_segs,
185         loff_t                  *ppos)
186 {
187         return __linvfs_readv(file, iov, 0, nr_segs, ppos);
188 }
189
190 STATIC ssize_t
191 linvfs_readv_invis(
192         struct file             *file,
193         const struct iovec      *iov,
194         unsigned long           nr_segs,
195         loff_t                  *ppos)
196 {
197         return __linvfs_readv(file, iov, IO_INVIS, nr_segs, ppos);
198 }
199
200
201 STATIC inline ssize_t
202 __linvfs_writev(
203         struct file             *file,
204         const struct iovec      *iov,
205         int                     ioflags,
206         unsigned long           nr_segs,
207         loff_t                  *ppos)
208 {
209         struct inode    *inode = file->f_mapping->host;
210         vnode_t         *vp = LINVFS_GET_VP(inode);
211         struct          kiocb kiocb;
212         ssize_t         rval;
213
214         init_sync_kiocb(&kiocb, file);
215         kiocb.ki_pos = *ppos;
216         if (unlikely(file->f_flags & O_DIRECT)) {
217                 ioflags |= IO_ISDIRECT;
218                 VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos,
219                                 ioflags, NULL, rval);
220         } else {
221                 down(&inode->i_sem);
222                 VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos,
223                                 ioflags, NULL, rval);
224                 up(&inode->i_sem);
225         }
226
227         if (rval == -EIOCBQUEUED)
228                 rval = wait_on_sync_kiocb(&kiocb);
229
230         *ppos = kiocb.ki_pos;
231         return rval;
232 }
233
234
235 STATIC ssize_t
236 linvfs_writev(
237         struct file             *file,
238         const struct iovec      *iov,
239         unsigned long           nr_segs,
240         loff_t                  *ppos)
241 {
242         return __linvfs_writev(file, iov, 0, nr_segs, ppos);
243 }
244
245 STATIC ssize_t
246 linvfs_writev_invis(
247         struct file             *file,
248         const struct iovec      *iov,
249         unsigned long           nr_segs,
250         loff_t                  *ppos)
251 {
252         return __linvfs_writev(file, iov, IO_INVIS, nr_segs, ppos);
253 }
254
255 STATIC ssize_t
256 linvfs_sendfile(
257         struct file             *filp,
258         loff_t                  *ppos,
259         size_t                  count,
260         read_actor_t            actor,
261         void                    *target)
262 {
263         vnode_t                 *vp = LINVFS_GET_VP(filp->f_dentry->d_inode);
264         int                     error;
265
266         VOP_SENDFILE(vp, filp, ppos, 0, count, actor, target, NULL, error);
267         return error;
268 }
269
270
271 STATIC int
272 linvfs_open(
273         struct inode    *inode,
274         struct file     *filp)
275 {
276         vnode_t         *vp = LINVFS_GET_VP(inode);
277         int             error;
278
279         if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
280                 return -EFBIG;
281
282         ASSERT(vp);
283         VOP_OPEN(vp, NULL, error);
284         return -error;
285 }
286
287
288 STATIC int
289 linvfs_release(
290         struct inode    *inode,
291         struct file     *filp)
292 {
293         vnode_t         *vp = LINVFS_GET_VP(inode);
294         int             error = 0;
295
296         if (vp)
297                 VOP_RELEASE(vp, error);
298         return -error;
299 }
300
301
302 STATIC int
303 linvfs_fsync(
304         struct file     *filp,
305         struct dentry   *dentry,
306         int             datasync)
307 {
308         struct inode    *inode = dentry->d_inode;
309         vnode_t         *vp = LINVFS_GET_VP(inode);
310         int             error;
311         int             flags = FSYNC_WAIT;
312
313         if (datasync)
314                 flags |= FSYNC_DATA;
315
316         ASSERT(vp);
317         VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error);
318         return -error;
319 }
320
321 /*
322  * linvfs_readdir maps to VOP_READDIR().
323  * We need to build a uio, cred, ...
324  */
325
326 #define nextdp(dp)      ((struct xfs_dirent *)((char *)(dp) + (dp)->d_reclen))
327
328 STATIC int
329 linvfs_readdir(
330         struct file     *filp,
331         void            *dirent,
332         filldir_t       filldir)
333 {
334         int             error = 0;
335         vnode_t         *vp;
336         uio_t           uio;
337         iovec_t         iov;
338         int             eof = 0;
339         caddr_t         read_buf;
340         int             namelen, size = 0;
341         size_t          rlen = PAGE_CACHE_SIZE;
342         xfs_off_t       start_offset, curr_offset;
343         xfs_dirent_t    *dbp = NULL;
344
345         vp = LINVFS_GET_VP(filp->f_dentry->d_inode);
346         ASSERT(vp);
347
348         /* Try fairly hard to get memory */
349         do {
350                 if ((read_buf = (caddr_t)kmalloc(rlen, GFP_KERNEL)))
351                         break;
352                 rlen >>= 1;
353         } while (rlen >= 1024);
354
355         if (read_buf == NULL)
356                 return -ENOMEM;
357
358         uio.uio_iov = &iov;
359         uio.uio_segflg = UIO_SYSSPACE;
360         curr_offset = filp->f_pos;
361         if (filp->f_pos != 0x7fffffff)
362                 uio.uio_offset = filp->f_pos;
363         else
364                 uio.uio_offset = 0xffffffff;
365
366         while (!eof) {
367                 uio.uio_resid = iov.iov_len = rlen;
368                 iov.iov_base = read_buf;
369                 uio.uio_iovcnt = 1;
370
371                 start_offset = uio.uio_offset;
372
373                 VOP_READDIR(vp, &uio, NULL, &eof, error);
374                 if ((uio.uio_offset == start_offset) || error) {
375                         size = 0;
376                         break;
377                 }
378
379                 size = rlen - uio.uio_resid;
380                 dbp = (xfs_dirent_t *)read_buf;
381                 while (size > 0) {
382                         namelen = strlen(dbp->d_name);
383
384                         if (filldir(dirent, dbp->d_name, namelen,
385                                         (loff_t) curr_offset & 0x7fffffff,
386                                         (ino_t) dbp->d_ino,
387                                         DT_UNKNOWN)) {
388                                 goto done;
389                         }
390                         size -= dbp->d_reclen;
391                         curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */;
392                         dbp = nextdp(dbp);
393                 }
394         }
395 done:
396         if (!error) {
397                 if (size == 0)
398                         filp->f_pos = uio.uio_offset & 0x7fffffff;
399                 else if (dbp)
400                         filp->f_pos = curr_offset;
401         }
402
403         kfree(read_buf);
404         return -error;
405 }
406
407
408 STATIC int
409 linvfs_file_mmap(
410         struct file     *filp,
411         struct vm_area_struct *vma)
412 {
413         struct inode    *ip = filp->f_dentry->d_inode;
414         vnode_t         *vp = LINVFS_GET_VP(ip);
415         vattr_t         va = { .va_mask = XFS_AT_UPDATIME };
416         int             error;
417
418         if ((vp->v_type == VREG) && (vp->v_vfsp->vfs_flag & VFS_DMI)) {
419                 xfs_mount_t     *mp = XFS_VFSTOM(vp->v_vfsp);
420
421                 error = -XFS_SEND_MMAP(mp, vma, 0);
422                 if (error)
423                         return error;
424         }
425
426         vma->vm_ops = &linvfs_file_vm_ops;
427
428         VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error);
429         return 0;
430 }
431
432
433 STATIC int
434 linvfs_ioctl(
435         struct inode    *inode,
436         struct file     *filp,
437         unsigned int    cmd,
438         unsigned long   arg)
439 {
440         int             error;
441         vnode_t         *vp = LINVFS_GET_VP(inode);
442
443         ASSERT(vp);
444         VOP_IOCTL(vp, inode, filp, 0, cmd, arg, error);
445         VMODIFY(vp);
446
447         /* NOTE:  some of the ioctl's return positive #'s as a
448          *        byte count indicating success, such as
449          *        readlink_by_handle.  So we don't "sign flip"
450          *        like most other routines.  This means true
451          *        errors need to be returned as a negative value.
452          */
453         return error;
454 }
455
456 STATIC int
457 linvfs_ioctl_invis(
458         struct inode    *inode,
459         struct file     *filp,
460         unsigned int    cmd,
461         unsigned long   arg)
462 {
463         int             error;
464         vnode_t         *vp = LINVFS_GET_VP(inode);
465
466         ASSERT(vp);
467         VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, arg, error);
468         VMODIFY(vp);
469
470         /* NOTE:  some of the ioctl's return positive #'s as a
471          *        byte count indicating success, such as
472          *        readlink_by_handle.  So we don't "sign flip"
473          *        like most other routines.  This means true
474          *        errors need to be returned as a negative value.
475          */
476         return error;
477 }
478
479 #ifdef HAVE_VMOP_MPROTECT
480 STATIC int
481 linvfs_mprotect(
482         struct vm_area_struct *vma,
483         unsigned int    newflags)
484 {
485         vnode_t         *vp = LINVFS_GET_VP(vma->vm_file->f_dentry->d_inode);
486         int             error = 0;
487
488         if ((vp->v_type == VREG) && (vp->v_vfsp->vfs_flag & VFS_DMI)) {
489                 if ((vma->vm_flags & VM_MAYSHARE) &&
490                     (newflags & VM_WRITE) && !(vma->vm_flags & VM_WRITE)) {
491                         xfs_mount_t     *mp = XFS_VFSTOM(vp->v_vfsp);
492
493                         error = XFS_SEND_MMAP(mp, vma, VM_WRITE);
494                     }
495         }
496         return error;
497 }
498 #endif /* HAVE_VMOP_MPROTECT */
499
500
501 struct file_operations linvfs_file_operations = {
502         .llseek         = generic_file_llseek,
503         .read           = do_sync_read,
504         .write          = do_sync_write,
505         .readv          = linvfs_readv,
506         .writev         = linvfs_writev,
507         .aio_read       = linvfs_read,
508         .aio_write      = linvfs_write,
509         .sendfile       = linvfs_sendfile,
510         .ioctl          = linvfs_ioctl,
511         .mmap           = linvfs_file_mmap,
512         .open           = linvfs_open,
513         .release        = linvfs_release,
514         .fsync          = linvfs_fsync,
515 };
516
517 struct file_operations linvfs_invis_file_operations = {
518         .llseek         = generic_file_llseek,
519         .read           = do_sync_read,
520         .write          = do_sync_write,
521         .readv          = linvfs_readv_invis,
522         .writev         = linvfs_writev_invis,
523         .aio_read       = linvfs_read_invis,
524         .aio_write      = linvfs_write_invis,
525         .sendfile       = linvfs_sendfile,
526         .ioctl          = linvfs_ioctl_invis,
527         .mmap           = linvfs_file_mmap,
528         .open           = linvfs_open,
529         .release        = linvfs_release,
530         .fsync          = linvfs_fsync,
531 };
532
533
534 struct file_operations linvfs_dir_operations = {
535         .read           = generic_read_dir,
536         .readdir        = linvfs_readdir,
537         .ioctl          = linvfs_ioctl,
538         .fsync          = linvfs_fsync,
539 };
540
541 static struct vm_operations_struct linvfs_file_vm_ops = {
542         .nopage         = filemap_nopage,
543 #ifdef HAVE_VMOP_MPROTECT
544         .mprotect       = linvfs_mprotect,
545 #endif
546 };