vserver 1.9.3
[linux-2.6.git] / fs / xfs / linux-2.6 / xfs_file.c
1 /*
2  * Copyright (c) 2000-2004 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 #include <linux/smp_lock.h>
57
58 static struct vm_operations_struct linvfs_file_vm_ops;
59
60
61 STATIC inline ssize_t
62 __linvfs_read(
63         struct kiocb            *iocb,
64         char                    __user *buf,
65         int                     ioflags,
66         size_t                  count,
67         loff_t                  pos)
68 {
69         struct iovec            iov = {buf, count};
70         struct file             *file = iocb->ki_filp;
71         vnode_t                 *vp = LINVFS_GET_VP(file->f_dentry->d_inode);
72         ssize_t                 rval;
73
74         BUG_ON(iocb->ki_pos != pos);
75
76         if (unlikely(file->f_flags & O_DIRECT))
77                 ioflags |= IO_ISDIRECT;
78         VOP_READ(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval);
79         return rval;
80 }
81
82
83 STATIC ssize_t
84 linvfs_read(
85         struct kiocb            *iocb,
86         char                    __user *buf,
87         size_t                  count,
88         loff_t                  pos)
89 {
90         return __linvfs_read(iocb, buf, 0, count, pos);
91 }
92
93 STATIC ssize_t
94 linvfs_read_invis(
95         struct kiocb            *iocb,
96         char                    __user *buf,
97         size_t                  count,
98         loff_t                  pos)
99 {
100         return __linvfs_read(iocb, buf, IO_INVIS, count, pos);
101 }
102
103
104 STATIC inline ssize_t
105 __linvfs_write(
106         struct kiocb    *iocb,
107         const char      __user *buf,
108         int             ioflags,
109         size_t          count,
110         loff_t          pos)
111 {
112         struct iovec    iov = {(void __user *)buf, count};
113         struct file     *file = iocb->ki_filp;
114         struct inode    *inode = file->f_mapping->host;
115         vnode_t         *vp = LINVFS_GET_VP(inode);
116         ssize_t         rval;
117
118         BUG_ON(iocb->ki_pos != pos);
119         if (unlikely(file->f_flags & O_DIRECT))
120                 ioflags |= IO_ISDIRECT;
121
122         VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval);
123         return rval;
124 }
125
126
127 STATIC ssize_t
128 linvfs_write(
129         struct kiocb            *iocb,
130         const char              __user *buf,
131         size_t                  count,
132         loff_t                  pos)
133 {
134         return __linvfs_write(iocb, buf, 0, count, pos);
135 }
136
137 STATIC ssize_t
138 linvfs_write_invis(
139         struct kiocb            *iocb,
140         const char              __user *buf,
141         size_t                  count,
142         loff_t                  pos)
143 {
144         return __linvfs_write(iocb, buf, IO_INVIS, count, pos);
145 }
146
147
148 STATIC inline ssize_t
149 __linvfs_readv(
150         struct file             *file,
151         const struct iovec      *iov,
152         int                     ioflags,
153         unsigned long           nr_segs,
154         loff_t                  *ppos)
155 {
156         struct inode    *inode = file->f_mapping->host;
157         vnode_t         *vp = LINVFS_GET_VP(inode);
158         struct          kiocb kiocb;
159         ssize_t         rval;
160
161         init_sync_kiocb(&kiocb, file);
162         kiocb.ki_pos = *ppos;
163
164         if (unlikely(file->f_flags & O_DIRECT))
165                 ioflags |= IO_ISDIRECT;
166         VOP_READ(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval);
167
168         *ppos = kiocb.ki_pos;
169         return rval;
170 }
171
172 STATIC ssize_t
173 linvfs_readv(
174         struct file             *file,
175         const struct iovec      *iov,
176         unsigned long           nr_segs,
177         loff_t                  *ppos)
178 {
179         return __linvfs_readv(file, iov, 0, nr_segs, ppos);
180 }
181
182 STATIC ssize_t
183 linvfs_readv_invis(
184         struct file             *file,
185         const struct iovec      *iov,
186         unsigned long           nr_segs,
187         loff_t                  *ppos)
188 {
189         return __linvfs_readv(file, iov, IO_INVIS, nr_segs, ppos);
190 }
191
192
193 STATIC inline ssize_t
194 __linvfs_writev(
195         struct file             *file,
196         const struct iovec      *iov,
197         int                     ioflags,
198         unsigned long           nr_segs,
199         loff_t                  *ppos)
200 {
201         struct inode    *inode = file->f_mapping->host;
202         vnode_t         *vp = LINVFS_GET_VP(inode);
203         struct          kiocb kiocb;
204         ssize_t         rval;
205
206         init_sync_kiocb(&kiocb, file);
207         kiocb.ki_pos = *ppos;
208         if (unlikely(file->f_flags & O_DIRECT))
209                 ioflags |= IO_ISDIRECT;
210
211         VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval);
212
213         *ppos = kiocb.ki_pos;
214         return rval;
215 }
216
217
218 STATIC ssize_t
219 linvfs_writev(
220         struct file             *file,
221         const struct iovec      *iov,
222         unsigned long           nr_segs,
223         loff_t                  *ppos)
224 {
225         return __linvfs_writev(file, iov, 0, nr_segs, ppos);
226 }
227
228 STATIC ssize_t
229 linvfs_writev_invis(
230         struct file             *file,
231         const struct iovec      *iov,
232         unsigned long           nr_segs,
233         loff_t                  *ppos)
234 {
235         return __linvfs_writev(file, iov, IO_INVIS, nr_segs, ppos);
236 }
237
238 STATIC ssize_t
239 linvfs_sendfile(
240         struct file             *filp,
241         loff_t                  *ppos,
242         size_t                  count,
243         read_actor_t            actor,
244         void                    *target)
245 {
246         vnode_t                 *vp = LINVFS_GET_VP(filp->f_dentry->d_inode);
247         ssize_t                 rval;
248
249         VOP_SENDFILE(vp, filp, ppos, 0, count, actor, target, NULL, rval);
250         return rval;
251 }
252
253
254 STATIC int
255 linvfs_open(
256         struct inode    *inode,
257         struct file     *filp)
258 {
259         vnode_t         *vp = LINVFS_GET_VP(inode);
260         int             error;
261
262         if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
263                 return -EFBIG;
264
265         ASSERT(vp);
266         VOP_OPEN(vp, NULL, error);
267         return -error;
268 }
269
270
271 STATIC int
272 linvfs_release(
273         struct inode    *inode,
274         struct file     *filp)
275 {
276         vnode_t         *vp = LINVFS_GET_VP(inode);
277         int             error = 0;
278
279         if (vp)
280                 VOP_RELEASE(vp, error);
281         return -error;
282 }
283
284
285 STATIC int
286 linvfs_fsync(
287         struct file     *filp,
288         struct dentry   *dentry,
289         int             datasync)
290 {
291         struct inode    *inode = dentry->d_inode;
292         vnode_t         *vp = LINVFS_GET_VP(inode);
293         int             error;
294         int             flags = FSYNC_WAIT;
295
296         if (datasync)
297                 flags |= FSYNC_DATA;
298
299         ASSERT(vp);
300         VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error);
301         return -error;
302 }
303
304 /*
305  * linvfs_readdir maps to VOP_READDIR().
306  * We need to build a uio, cred, ...
307  */
308
309 #define nextdp(dp)      ((struct xfs_dirent *)((char *)(dp) + (dp)->d_reclen))
310
311 STATIC int
312 linvfs_readdir(
313         struct file     *filp,
314         void            *dirent,
315         filldir_t       filldir)
316 {
317         int             error = 0;
318         vnode_t         *vp;
319         uio_t           uio;
320         iovec_t         iov;
321         int             eof = 0;
322         caddr_t         read_buf;
323         int             namelen, size = 0;
324         size_t          rlen = PAGE_CACHE_SIZE;
325         xfs_off_t       start_offset, curr_offset;
326         xfs_dirent_t    *dbp = NULL;
327
328         vp = LINVFS_GET_VP(filp->f_dentry->d_inode);
329         ASSERT(vp);
330
331         /* Try fairly hard to get memory */
332         do {
333                 if ((read_buf = (caddr_t)kmalloc(rlen, GFP_KERNEL)))
334                         break;
335                 rlen >>= 1;
336         } while (rlen >= 1024);
337
338         if (read_buf == NULL)
339                 return -ENOMEM;
340
341         uio.uio_iov = &iov;
342         uio.uio_segflg = UIO_SYSSPACE;
343         curr_offset = filp->f_pos;
344         if (filp->f_pos != 0x7fffffff)
345                 uio.uio_offset = filp->f_pos;
346         else
347                 uio.uio_offset = 0xffffffff;
348
349         while (!eof) {
350                 uio.uio_resid = iov.iov_len = rlen;
351                 iov.iov_base = read_buf;
352                 uio.uio_iovcnt = 1;
353
354                 start_offset = uio.uio_offset;
355
356                 VOP_READDIR(vp, &uio, NULL, &eof, error);
357                 if ((uio.uio_offset == start_offset) || error) {
358                         size = 0;
359                         break;
360                 }
361
362                 size = rlen - uio.uio_resid;
363                 dbp = (xfs_dirent_t *)read_buf;
364                 while (size > 0) {
365                         namelen = strlen(dbp->d_name);
366
367                         if (filldir(dirent, dbp->d_name, namelen,
368                                         (loff_t) curr_offset & 0x7fffffff,
369                                         (ino_t) dbp->d_ino,
370                                         DT_UNKNOWN)) {
371                                 goto done;
372                         }
373                         size -= dbp->d_reclen;
374                         curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */;
375                         dbp = nextdp(dbp);
376                 }
377         }
378 done:
379         if (!error) {
380                 if (size == 0)
381                         filp->f_pos = uio.uio_offset & 0x7fffffff;
382                 else if (dbp)
383                         filp->f_pos = curr_offset;
384         }
385
386         kfree(read_buf);
387         return -error;
388 }
389
390
391 STATIC int
392 linvfs_file_mmap(
393         struct file     *filp,
394         struct vm_area_struct *vma)
395 {
396         struct inode    *ip = filp->f_dentry->d_inode;
397         vnode_t         *vp = LINVFS_GET_VP(ip);
398         vattr_t         va = { .va_mask = XFS_AT_UPDATIME };
399         int             error;
400
401         if ((vp->v_type == VREG) && (vp->v_vfsp->vfs_flag & VFS_DMI)) {
402                 xfs_mount_t     *mp = XFS_VFSTOM(vp->v_vfsp);
403
404                 error = -XFS_SEND_MMAP(mp, vma, 0);
405                 if (error)
406                         return error;
407         }
408
409         vma->vm_ops = &linvfs_file_vm_ops;
410
411         VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error);
412         if (!error)
413                 vn_revalidate(vp);      /* update Linux inode flags */
414         return 0;
415 }
416
417
418 STATIC int
419 linvfs_ioctl(
420         struct inode    *inode,
421         struct file     *filp,
422         unsigned int    cmd,
423         unsigned long   arg)
424 {
425         int             error;
426         vnode_t         *vp = LINVFS_GET_VP(inode);
427
428         unlock_kernel();
429         VOP_IOCTL(vp, inode, filp, 0, cmd, (void __user *)arg, error);
430         VMODIFY(vp);
431         lock_kernel();
432
433         /* NOTE:  some of the ioctl's return positive #'s as a
434          *        byte count indicating success, such as
435          *        readlink_by_handle.  So we don't "sign flip"
436          *        like most other routines.  This means true
437          *        errors need to be returned as a negative value.
438          */
439         return error;
440 }
441
442 STATIC int
443 linvfs_ioctl_invis(
444         struct inode    *inode,
445         struct file     *filp,
446         unsigned int    cmd,
447         unsigned long   arg)
448 {
449         int             error;
450         vnode_t         *vp = LINVFS_GET_VP(inode);
451
452         unlock_kernel();
453         ASSERT(vp);
454         VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error);
455         VMODIFY(vp);
456         lock_kernel();
457
458         /* NOTE:  some of the ioctl's return positive #'s as a
459          *        byte count indicating success, such as
460          *        readlink_by_handle.  So we don't "sign flip"
461          *        like most other routines.  This means true
462          *        errors need to be returned as a negative value.
463          */
464         return error;
465 }
466
467 #ifdef HAVE_VMOP_MPROTECT
468 STATIC int
469 linvfs_mprotect(
470         struct vm_area_struct *vma,
471         unsigned int    newflags)
472 {
473         vnode_t         *vp = LINVFS_GET_VP(vma->vm_file->f_dentry->d_inode);
474         int             error = 0;
475
476         if ((vp->v_type == VREG) && (vp->v_vfsp->vfs_flag & VFS_DMI)) {
477                 if ((vma->vm_flags & VM_MAYSHARE) &&
478                     (newflags & VM_WRITE) && !(vma->vm_flags & VM_WRITE)) {
479                         xfs_mount_t     *mp = XFS_VFSTOM(vp->v_vfsp);
480
481                         error = XFS_SEND_MMAP(mp, vma, VM_WRITE);
482                     }
483         }
484         return error;
485 }
486 #endif /* HAVE_VMOP_MPROTECT */
487
488
489 struct file_operations linvfs_file_operations = {
490         .llseek         = generic_file_llseek,
491         .read           = do_sync_read,
492         .write          = do_sync_write,
493         .readv          = linvfs_readv,
494         .writev         = linvfs_writev,
495         .aio_read       = linvfs_read,
496         .aio_write      = linvfs_write,
497         .sendfile       = linvfs_sendfile,
498         .ioctl          = linvfs_ioctl,
499         .mmap           = linvfs_file_mmap,
500         .open           = linvfs_open,
501         .release        = linvfs_release,
502         .fsync          = linvfs_fsync,
503 };
504
505 struct file_operations linvfs_invis_file_operations = {
506         .llseek         = generic_file_llseek,
507         .read           = do_sync_read,
508         .write          = do_sync_write,
509         .readv          = linvfs_readv_invis,
510         .writev         = linvfs_writev_invis,
511         .aio_read       = linvfs_read_invis,
512         .aio_write      = linvfs_write_invis,
513         .sendfile       = linvfs_sendfile,
514         .ioctl          = linvfs_ioctl_invis,
515         .mmap           = linvfs_file_mmap,
516         .open           = linvfs_open,
517         .release        = linvfs_release,
518         .fsync          = linvfs_fsync,
519 };
520
521
522 struct file_operations linvfs_dir_operations = {
523         .read           = generic_read_dir,
524         .readdir        = linvfs_readdir,
525         .ioctl          = linvfs_ioctl,
526         .fsync          = linvfs_fsync,
527 };
528
529 static struct vm_operations_struct linvfs_file_vm_ops = {
530         .nopage         = filemap_nopage,
531 #ifdef HAVE_VMOP_MPROTECT
532         .mprotect       = linvfs_mprotect,
533 #endif
534 };