source: src/linux/xscale/linux-2.6.24/fs/xfs/linux-2.6/xfs_file.c @ 8887

Last change on this file since 8887 was 8887, checked in by BrainSlayer, 5 years ago

2.6.24 xscale kernel port (i have never seen so much useless api changes)

File size: 13.0 KB
Line 
1/*
2 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18#include "xfs.h"
19#include "xfs_bit.h"
20#include "xfs_log.h"
21#include "xfs_inum.h"
22#include "xfs_sb.h"
23#include "xfs_ag.h"
24#include "xfs_dir2.h"
25#include "xfs_trans.h"
26#include "xfs_dmapi.h"
27#include "xfs_mount.h"
28#include "xfs_bmap_btree.h"
29#include "xfs_alloc_btree.h"
30#include "xfs_ialloc_btree.h"
31#include "xfs_alloc.h"
32#include "xfs_btree.h"
33#include "xfs_attr_sf.h"
34#include "xfs_dir2_sf.h"
35#include "xfs_dinode.h"
36#include "xfs_inode.h"
37#include "xfs_error.h"
38#include "xfs_rw.h"
39#include "xfs_ioctl32.h"
40#include "xfs_vnodeops.h"
41
42#include <linux/dcache.h>
43#include <linux/smp_lock.h>
44
45static struct vm_operations_struct xfs_file_vm_ops;
46#ifdef CONFIG_XFS_DMAPI
47static struct vm_operations_struct xfs_dmapi_file_vm_ops;
48#endif
49
50STATIC_INLINE ssize_t
51__xfs_file_read(
52        struct kiocb            *iocb,
53        const struct iovec      *iov,
54        unsigned long           nr_segs,
55        int                     ioflags,
56        loff_t                  pos)
57{
58        struct file             *file = iocb->ki_filp;
59
60        BUG_ON(iocb->ki_pos != pos);
61        if (unlikely(file->f_flags & O_DIRECT))
62                ioflags |= IO_ISDIRECT;
63        return xfs_read(XFS_I(file->f_path.dentry->d_inode), iocb, iov,
64                                nr_segs, &iocb->ki_pos, ioflags);
65}
66
67STATIC ssize_t
68xfs_file_aio_read(
69        struct kiocb            *iocb,
70        const struct iovec      *iov,
71        unsigned long           nr_segs,
72        loff_t                  pos)
73{
74        return __xfs_file_read(iocb, iov, nr_segs, IO_ISAIO, pos);
75}
76
77STATIC ssize_t
78xfs_file_aio_read_invis(
79        struct kiocb            *iocb,
80        const struct iovec      *iov,
81        unsigned long           nr_segs,
82        loff_t                  pos)
83{
84        return __xfs_file_read(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos);
85}
86
87STATIC_INLINE ssize_t
88__xfs_file_write(
89        struct kiocb            *iocb,
90        const struct iovec      *iov,
91        unsigned long           nr_segs,
92        int                     ioflags,
93        loff_t                  pos)
94{
95        struct file     *file = iocb->ki_filp;
96
97        BUG_ON(iocb->ki_pos != pos);
98        if (unlikely(file->f_flags & O_DIRECT))
99                ioflags |= IO_ISDIRECT;
100        return xfs_write(XFS_I(file->f_mapping->host), iocb, iov, nr_segs,
101                                &iocb->ki_pos, ioflags);
102}
103
104STATIC ssize_t
105xfs_file_aio_write(
106        struct kiocb            *iocb,
107        const struct iovec      *iov,
108        unsigned long           nr_segs,
109        loff_t                  pos)
110{
111        return __xfs_file_write(iocb, iov, nr_segs, IO_ISAIO, pos);
112}
113
114STATIC ssize_t
115xfs_file_aio_write_invis(
116        struct kiocb            *iocb,
117        const struct iovec      *iov,
118        unsigned long           nr_segs,
119        loff_t                  pos)
120{
121        return __xfs_file_write(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos);
122}
123
124STATIC ssize_t
125xfs_file_splice_read(
126        struct file             *infilp,
127        loff_t                  *ppos,
128        struct pipe_inode_info  *pipe,
129        size_t                  len,
130        unsigned int            flags)
131{
132        return xfs_splice_read(XFS_I(infilp->f_path.dentry->d_inode),
133                                   infilp, ppos, pipe, len, flags, 0);
134}
135
136STATIC ssize_t
137xfs_file_splice_read_invis(
138        struct file             *infilp,
139        loff_t                  *ppos,
140        struct pipe_inode_info  *pipe,
141        size_t                  len,
142        unsigned int            flags)
143{
144        return xfs_splice_read(XFS_I(infilp->f_path.dentry->d_inode),
145                                   infilp, ppos, pipe, len, flags, IO_INVIS);
146}
147
148STATIC ssize_t
149xfs_file_splice_write(
150        struct pipe_inode_info  *pipe,
151        struct file             *outfilp,
152        loff_t                  *ppos,
153        size_t                  len,
154        unsigned int            flags)
155{
156        return xfs_splice_write(XFS_I(outfilp->f_path.dentry->d_inode),
157                                    pipe, outfilp, ppos, len, flags, 0);
158}
159
160STATIC ssize_t
161xfs_file_splice_write_invis(
162        struct pipe_inode_info  *pipe,
163        struct file             *outfilp,
164        loff_t                  *ppos,
165        size_t                  len,
166        unsigned int            flags)
167{
168        return xfs_splice_write(XFS_I(outfilp->f_path.dentry->d_inode),
169                                    pipe, outfilp, ppos, len, flags, IO_INVIS);
170}
171
172STATIC int
173xfs_file_open(
174        struct inode    *inode,
175        struct file     *filp)
176{
177        if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
178                return -EFBIG;
179        return -xfs_open(XFS_I(inode));
180}
181
182STATIC int
183xfs_file_release(
184        struct inode    *inode,
185        struct file     *filp)
186{
187        return -xfs_release(XFS_I(inode));
188}
189
190STATIC int
191xfs_file_fsync(
192        struct file     *filp,
193        struct dentry   *dentry,
194        int             datasync)
195{
196        int             flags = FSYNC_WAIT;
197
198        if (datasync)
199                flags |= FSYNC_DATA;
200        xfs_iflags_clear(XFS_I(dentry->d_inode), XFS_ITRUNCATED);
201        return -xfs_fsync(XFS_I(dentry->d_inode), flags,
202                        (xfs_off_t)0, (xfs_off_t)-1);
203}
204
205#ifdef CONFIG_XFS_DMAPI
206STATIC int
207xfs_vm_fault(
208        struct vm_area_struct   *vma,
209        struct vm_fault *vmf)
210{
211        struct inode    *inode = vma->vm_file->f_path.dentry->d_inode;
212        bhv_vnode_t     *vp = vn_from_inode(inode);
213
214        ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI);
215        if (XFS_SEND_MMAP(XFS_VFSTOM(vp->v_vfsp), vma, 0))
216                return VM_FAULT_SIGBUS;
217        return filemap_fault(vma, vmf);
218}
219#endif /* CONFIG_XFS_DMAPI */
220
221/*
222 * Unfortunately we can't just use the clean and simple readdir implementation
223 * below, because nfs might call back into ->lookup from the filldir callback
224 * and that will deadlock the low-level btree code.
225 *
226 * Hopefully we'll find a better workaround that allows to use the optimal
227 * version at least for local readdirs for 2.6.25.
228 */
229#if 0
230STATIC int
231xfs_file_readdir(
232        struct file     *filp,
233        void            *dirent,
234        filldir_t       filldir)
235{
236        struct inode    *inode = filp->f_path.dentry->d_inode;
237        xfs_inode_t     *ip = XFS_I(inode);
238        int             error;
239        size_t          bufsize;
240
241        /*
242         * The Linux API doesn't pass down the total size of the buffer
243         * we read into down to the filesystem.  With the filldir concept
244         * it's not needed for correct information, but the XFS dir2 leaf
245         * code wants an estimate of the buffer size to calculate it's
246         * readahead window and size the buffers used for mapping to
247         * physical blocks.
248         *
249         * Try to give it an estimate that's good enough, maybe at some
250         * point we can change the ->readdir prototype to include the
251         * buffer size.
252         */
253        bufsize = (size_t)min_t(loff_t, PAGE_SIZE, inode->i_size);
254
255        error = xfs_readdir(ip, dirent, bufsize,
256                                (xfs_off_t *)&filp->f_pos, filldir);
257        if (error)
258                return -error;
259        return 0;
260}
261#else
262
263struct hack_dirent {
264        u64             ino;
265        loff_t          offset;
266        int             namlen;
267        unsigned int    d_type;
268        char            name[];
269};
270
271struct hack_callback {
272        char            *dirent;
273        size_t          len;
274        size_t          used;
275};
276
277STATIC int
278xfs_hack_filldir(
279        void            *__buf,
280        const char      *name,
281        int             namlen,
282        loff_t          offset,
283        u64             ino,
284        unsigned int    d_type)
285{
286        struct hack_callback *buf = __buf;
287        struct hack_dirent *de = (struct hack_dirent *)(buf->dirent + buf->used);
288        unsigned int reclen;
289
290        reclen = ALIGN(sizeof(struct hack_dirent) + namlen, sizeof(u64));
291        if (buf->used + reclen > buf->len)
292                return -EINVAL;
293
294        de->namlen = namlen;
295        de->offset = offset;
296        de->ino = ino;
297        de->d_type = d_type;
298        memcpy(de->name, name, namlen);
299        buf->used += reclen;
300        return 0;
301}
302
303STATIC int
304xfs_file_readdir(
305        struct file     *filp,
306        void            *dirent,
307        filldir_t       filldir)
308{
309        struct inode    *inode = filp->f_path.dentry->d_inode;
310        xfs_inode_t     *ip = XFS_I(inode);
311        struct hack_callback buf;
312        struct hack_dirent *de;
313        int             error;
314        loff_t          size;
315        int             eof = 0;
316        xfs_off_t       start_offset, curr_offset, offset;
317
318        /*
319         * Try fairly hard to get memory
320         */
321        buf.len = PAGE_CACHE_SIZE;
322        do {
323                buf.dirent = kmalloc(buf.len, GFP_KERNEL);
324                if (buf.dirent)
325                        break;
326                buf.len >>= 1;
327        } while (buf.len >= 1024);
328
329        if (!buf.dirent)
330                return -ENOMEM;
331
332        curr_offset = filp->f_pos;
333        if (curr_offset == 0x7fffffff)
334                offset = 0xffffffff;
335        else
336                offset = filp->f_pos;
337
338        while (!eof) {
339                unsigned int reclen;
340
341                start_offset = offset;
342
343                buf.used = 0;
344                error = -xfs_readdir(ip, &buf, buf.len, &offset,
345                                     xfs_hack_filldir);
346                if (error || offset == start_offset) {
347                        size = 0;
348                        break;
349                }
350
351                size = buf.used;
352                de = (struct hack_dirent *)buf.dirent;
353                curr_offset = de->offset /* & 0x7fffffff */;
354                while (size > 0) {
355                        if (filldir(dirent, de->name, de->namlen,
356                                        curr_offset & 0x7fffffff,
357                                        de->ino, de->d_type)) {
358                                goto done;
359                        }
360
361                        reclen = ALIGN(sizeof(struct hack_dirent) + de->namlen,
362                                       sizeof(u64));
363                        size -= reclen;
364                        de = (struct hack_dirent *)((char *)de + reclen);
365                        curr_offset = de->offset /* & 0x7fffffff */;
366                }
367        }
368
369 done:
370        if (!error) {
371                if (size == 0)
372                        filp->f_pos = offset & 0x7fffffff;
373                else if (de)
374                        filp->f_pos = curr_offset;
375        }
376
377        kfree(buf.dirent);
378        return error;
379}
380#endif
381
382STATIC int
383xfs_file_mmap(
384        struct file     *filp,
385        struct vm_area_struct *vma)
386{
387        vma->vm_ops = &xfs_file_vm_ops;
388        vma->vm_flags |= VM_CAN_NONLINEAR;
389
390#ifdef CONFIG_XFS_DMAPI
391        if (XFS_M(filp->f_path.dentry->d_inode->i_sb)->m_flags & XFS_MOUNT_DMAPI)
392                vma->vm_ops = &xfs_dmapi_file_vm_ops;
393#endif /* CONFIG_XFS_DMAPI */
394
395        file_accessed(filp);
396        return 0;
397}
398
399STATIC long
400xfs_file_ioctl(
401        struct file     *filp,
402        unsigned int    cmd,
403        unsigned long   p)
404{
405        int             error;
406        struct inode    *inode = filp->f_path.dentry->d_inode;
407
408        error = xfs_ioctl(XFS_I(inode), filp, 0, cmd, (void __user *)p);
409        xfs_iflags_set(XFS_I(inode), XFS_IMODIFIED);
410
411        /* NOTE:  some of the ioctl's return positive #'s as a
412         *        byte count indicating success, such as
413         *        readlink_by_handle.  So we don't "sign flip"
414         *        like most other routines.  This means true
415         *        errors need to be returned as a negative value.
416         */
417        return error;
418}
419
420STATIC long
421xfs_file_ioctl_invis(
422        struct file     *filp,
423        unsigned int    cmd,
424        unsigned long   p)
425{
426        int             error;
427        struct inode    *inode = filp->f_path.dentry->d_inode;
428
429        error = xfs_ioctl(XFS_I(inode), filp, IO_INVIS, cmd, (void __user *)p);
430        xfs_iflags_set(XFS_I(inode), XFS_IMODIFIED);
431
432        /* NOTE:  some of the ioctl's return positive #'s as a
433         *        byte count indicating success, such as
434         *        readlink_by_handle.  So we don't "sign flip"
435         *        like most other routines.  This means true
436         *        errors need to be returned as a negative value.
437         */
438        return error;
439}
440
441#ifdef CONFIG_XFS_DMAPI
442#ifdef HAVE_VMOP_MPROTECT
443STATIC int
444xfs_vm_mprotect(
445        struct vm_area_struct *vma,
446        unsigned int    newflags)
447{
448        struct inode    *inode = vma->vm_file->f_path.dentry->d_inode;
449        struct xfs_mount *mp = XFS_M(inode->i_sb);
450        int             error = 0;
451
452        if (mp->m_flags & XFS_MOUNT_DMAPI) {
453                if ((vma->vm_flags & VM_MAYSHARE) &&
454                    (newflags & VM_WRITE) && !(vma->vm_flags & VM_WRITE))
455                        error = XFS_SEND_MMAP(mp, vma, VM_WRITE);
456        }
457        return error;
458}
459#endif /* HAVE_VMOP_MPROTECT */
460#endif /* CONFIG_XFS_DMAPI */
461
462#ifdef HAVE_FOP_OPEN_EXEC
463/* If the user is attempting to execute a file that is offline then
464 * we have to trigger a DMAPI READ event before the file is marked as busy
465 * otherwise the invisible I/O will not be able to write to the file to bring
466 * it back online.
467 */
468STATIC int
469xfs_file_open_exec(
470        struct inode    *inode)
471{
472        struct xfs_mount *mp = XFS_M(inode->i_sb);
473
474        if (unlikely(mp->m_flags & XFS_MOUNT_DMAPI)) {
475                if (DM_EVENT_ENABLED(XFS_I(inode), DM_EVENT_READ)) {
476                        bhv_vnode_t *vp = vn_from_inode(inode);
477
478                        return -XFS_SEND_DATA(mp, DM_EVENT_READ,
479                                                vp, 0, 0, 0, NULL);
480                }
481        }
482
483        return 0;
484}
485#endif /* HAVE_FOP_OPEN_EXEC */
486
487/*
488 * mmap()d file has taken write protection fault and is being made
489 * writable. We can set the page state up correctly for a writable
490 * page, which means we can do correct delalloc accounting (ENOSPC
491 * checking!) and unwritten extent mapping.
492 */
493STATIC int
494xfs_vm_page_mkwrite(
495        struct vm_area_struct   *vma,
496        struct page             *page)
497{
498        return block_page_mkwrite(vma, page, xfs_get_blocks);
499}
500
501const struct file_operations xfs_file_operations = {
502        .llseek         = generic_file_llseek,
503        .read           = do_sync_read,
504        .write          = do_sync_write,
505        .aio_read       = xfs_file_aio_read,
506        .aio_write      = xfs_file_aio_write,
507        .splice_read    = xfs_file_splice_read,
508        .splice_write   = xfs_file_splice_write,
509        .unlocked_ioctl = xfs_file_ioctl,
510#ifdef CONFIG_COMPAT
511        .compat_ioctl   = xfs_file_compat_ioctl,
512#endif
513        .mmap           = xfs_file_mmap,
514        .open           = xfs_file_open,
515        .release        = xfs_file_release,
516        .fsync          = xfs_file_fsync,
517#ifdef HAVE_FOP_OPEN_EXEC
518        .open_exec      = xfs_file_open_exec,
519#endif
520};
521
522const struct file_operations xfs_invis_file_operations = {
523        .llseek         = generic_file_llseek,
524        .read           = do_sync_read,
525        .write          = do_sync_write,
526        .aio_read       = xfs_file_aio_read_invis,
527        .aio_write      = xfs_file_aio_write_invis,
528        .splice_read    = xfs_file_splice_read_invis,
529        .splice_write   = xfs_file_splice_write_invis,
530        .unlocked_ioctl = xfs_file_ioctl_invis,
531#ifdef CONFIG_COMPAT
532        .compat_ioctl   = xfs_file_compat_invis_ioctl,
533#endif
534        .mmap           = xfs_file_mmap,
535        .open           = xfs_file_open,
536        .release        = xfs_file_release,
537        .fsync          = xfs_file_fsync,
538};
539
540
541const struct file_operations xfs_dir_file_operations = {
542        .read           = generic_read_dir,
543        .readdir        = xfs_file_readdir,
544        .unlocked_ioctl = xfs_file_ioctl,
545#ifdef CONFIG_COMPAT
546        .compat_ioctl   = xfs_file_compat_ioctl,
547#endif
548        .fsync          = xfs_file_fsync,
549};
550
551static struct vm_operations_struct xfs_file_vm_ops = {
552        .fault          = filemap_fault,
553        .page_mkwrite   = xfs_vm_page_mkwrite,
554};
555
556#ifdef CONFIG_XFS_DMAPI
557static struct vm_operations_struct xfs_dmapi_file_vm_ops = {
558        .fault          = xfs_vm_fault,
559        .page_mkwrite   = xfs_vm_page_mkwrite,
560#ifdef HAVE_VMOP_MPROTECT
561        .mprotect       = xfs_vm_mprotect,
562#endif
563};
564#endif /* CONFIG_XFS_DMAPI */
Note: See TracBrowser for help on using the repository browser.