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