blob: 89b1a74213573306a6a8eb9da9aa0045f6333c82 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Nathan Scott7b718762005-11-02 14:58:39 +11002 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
Nathan Scott7b718762005-11-02 14:58:39 +11005 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 * published by the Free Software Foundation.
8 *
Nathan Scott7b718762005-11-02 14:58:39 +11009 * 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.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 *
Nathan Scott7b718762005-11-02 14:58:39 +110014 * 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
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include "xfs.h"
Nathan Scotta844f452005-11-02 14:38:42 +110019#include "xfs_bit.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include "xfs_log.h"
Nathan Scotta844f452005-11-02 14:38:42 +110021#include "xfs_inum.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include "xfs_sb.h"
Nathan Scotta844f452005-11-02 14:38:42 +110023#include "xfs_ag.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include "xfs_dir.h"
25#include "xfs_dir2.h"
26#include "xfs_trans.h"
27#include "xfs_dmapi.h"
28#include "xfs_mount.h"
29#include "xfs_bmap_btree.h"
30#include "xfs_alloc_btree.h"
31#include "xfs_ialloc_btree.h"
32#include "xfs_alloc.h"
33#include "xfs_btree.h"
34#include "xfs_attr_sf.h"
35#include "xfs_dir_sf.h"
36#include "xfs_dir2_sf.h"
37#include "xfs_dinode.h"
38#include "xfs_inode.h"
39#include "xfs_error.h"
40#include "xfs_rw.h"
41#include "xfs_ioctl32.h"
42
43#include <linux/dcache.h>
44#include <linux/smp_lock.h>
45
Nathan Scott3562fd42006-03-14 14:00:35 +110046static struct vm_operations_struct xfs_file_vm_ops;
Dean Roehrich6fac0cb2005-06-21 14:07:45 +100047#ifdef CONFIG_XFS_DMAPI
Nathan Scott3562fd42006-03-14 14:00:35 +110048static struct vm_operations_struct xfs_dmapi_file_vm_ops;
Dean Roehrich6fac0cb2005-06-21 14:07:45 +100049#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51STATIC inline ssize_t
Nathan Scott3562fd42006-03-14 14:00:35 +110052__xfs_file_read(
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 struct kiocb *iocb,
54 char __user *buf,
55 int ioflags,
56 size_t count,
57 loff_t pos)
58{
59 struct iovec iov = {buf, count};
60 struct file *file = iocb->ki_filp;
Nathan Scott67fcaa72006-06-09 17:00:52 +100061 bhv_vnode_t *vp = vn_from_inode(file->f_dentry->d_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
63 BUG_ON(iocb->ki_pos != pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 if (unlikely(file->f_flags & O_DIRECT))
65 ioflags |= IO_ISDIRECT;
Nathan Scott67fcaa72006-06-09 17:00:52 +100066 return bhv_vop_read(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067}
68
Linus Torvalds1da177e2005-04-16 15:20:36 -070069STATIC ssize_t
Nathan Scott3562fd42006-03-14 14:00:35 +110070xfs_file_aio_read(
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 struct kiocb *iocb,
72 char __user *buf,
73 size_t count,
74 loff_t pos)
75{
Nathan Scott3562fd42006-03-14 14:00:35 +110076 return __xfs_file_read(iocb, buf, IO_ISAIO, count, pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -070077}
78
79STATIC ssize_t
Nathan Scott3562fd42006-03-14 14:00:35 +110080xfs_file_aio_read_invis(
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 struct kiocb *iocb,
82 char __user *buf,
83 size_t count,
84 loff_t pos)
85{
Nathan Scott3562fd42006-03-14 14:00:35 +110086 return __xfs_file_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -070087}
88
Linus Torvalds1da177e2005-04-16 15:20:36 -070089STATIC inline ssize_t
Nathan Scott3562fd42006-03-14 14:00:35 +110090__xfs_file_write(
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 struct kiocb *iocb,
92 const char __user *buf,
93 int ioflags,
94 size_t count,
95 loff_t pos)
96{
97 struct iovec iov = {(void __user *)buf, count};
98 struct file *file = iocb->ki_filp;
99 struct inode *inode = file->f_mapping->host;
Nathan Scott67fcaa72006-06-09 17:00:52 +1000100 bhv_vnode_t *vp = vn_from_inode(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
102 BUG_ON(iocb->ki_pos != pos);
103 if (unlikely(file->f_flags & O_DIRECT))
104 ioflags |= IO_ISDIRECT;
Nathan Scott67fcaa72006-06-09 17:00:52 +1000105 return bhv_vop_write(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106}
107
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108STATIC ssize_t
Nathan Scott3562fd42006-03-14 14:00:35 +1100109xfs_file_aio_write(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 struct kiocb *iocb,
111 const char __user *buf,
112 size_t count,
113 loff_t pos)
114{
Nathan Scott3562fd42006-03-14 14:00:35 +1100115 return __xfs_file_write(iocb, buf, IO_ISAIO, count, pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116}
117
118STATIC ssize_t
Nathan Scott3562fd42006-03-14 14:00:35 +1100119xfs_file_aio_write_invis(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 struct kiocb *iocb,
121 const char __user *buf,
122 size_t count,
123 loff_t pos)
124{
Nathan Scott3562fd42006-03-14 14:00:35 +1100125 return __xfs_file_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126}
127
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128STATIC inline ssize_t
Nathan Scott3562fd42006-03-14 14:00:35 +1100129__xfs_file_readv(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 struct file *file,
131 const struct iovec *iov,
132 int ioflags,
133 unsigned long nr_segs,
134 loff_t *ppos)
135{
136 struct inode *inode = file->f_mapping->host;
Nathan Scott67fcaa72006-06-09 17:00:52 +1000137 bhv_vnode_t *vp = vn_from_inode(inode);
Nathan Scott524fbf52006-03-14 14:07:53 +1100138 struct kiocb kiocb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 ssize_t rval;
140
Nathan Scott524fbf52006-03-14 14:07:53 +1100141 init_sync_kiocb(&kiocb, file);
142 kiocb.ki_pos = *ppos;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143
144 if (unlikely(file->f_flags & O_DIRECT))
145 ioflags |= IO_ISDIRECT;
Nathan Scott67fcaa72006-06-09 17:00:52 +1000146 rval = bhv_vop_read(vp, &kiocb, iov, nr_segs,
147 &kiocb.ki_pos, ioflags, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148
Nathan Scott524fbf52006-03-14 14:07:53 +1100149 *ppos = kiocb.ki_pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 return rval;
151}
152
153STATIC ssize_t
Nathan Scott3562fd42006-03-14 14:00:35 +1100154xfs_file_readv(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 struct file *file,
156 const struct iovec *iov,
157 unsigned long nr_segs,
158 loff_t *ppos)
159{
Nathan Scott3562fd42006-03-14 14:00:35 +1100160 return __xfs_file_readv(file, iov, 0, nr_segs, ppos);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161}
162
163STATIC ssize_t
Nathan Scott3562fd42006-03-14 14:00:35 +1100164xfs_file_readv_invis(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 struct file *file,
166 const struct iovec *iov,
167 unsigned long nr_segs,
168 loff_t *ppos)
169{
Nathan Scott3562fd42006-03-14 14:00:35 +1100170 return __xfs_file_readv(file, iov, IO_INVIS, nr_segs, ppos);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171}
172
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173STATIC inline ssize_t
Nathan Scott3562fd42006-03-14 14:00:35 +1100174__xfs_file_writev(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 struct file *file,
176 const struct iovec *iov,
177 int ioflags,
178 unsigned long nr_segs,
179 loff_t *ppos)
180{
181 struct inode *inode = file->f_mapping->host;
Nathan Scott67fcaa72006-06-09 17:00:52 +1000182 bhv_vnode_t *vp = vn_from_inode(inode);
Nathan Scott524fbf52006-03-14 14:07:53 +1100183 struct kiocb kiocb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 ssize_t rval;
185
Nathan Scott524fbf52006-03-14 14:07:53 +1100186 init_sync_kiocb(&kiocb, file);
187 kiocb.ki_pos = *ppos;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 if (unlikely(file->f_flags & O_DIRECT))
189 ioflags |= IO_ISDIRECT;
190
Nathan Scott67fcaa72006-06-09 17:00:52 +1000191 rval = bhv_vop_write(vp, &kiocb, iov, nr_segs,
192 &kiocb.ki_pos, ioflags, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
Nathan Scott524fbf52006-03-14 14:07:53 +1100194 *ppos = kiocb.ki_pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 return rval;
196}
197
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198STATIC ssize_t
Nathan Scott3562fd42006-03-14 14:00:35 +1100199xfs_file_writev(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 struct file *file,
201 const struct iovec *iov,
202 unsigned long nr_segs,
203 loff_t *ppos)
204{
Nathan Scott3562fd42006-03-14 14:00:35 +1100205 return __xfs_file_writev(file, iov, 0, nr_segs, ppos);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206}
207
208STATIC ssize_t
Nathan Scott3562fd42006-03-14 14:00:35 +1100209xfs_file_writev_invis(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 struct file *file,
211 const struct iovec *iov,
212 unsigned long nr_segs,
213 loff_t *ppos)
214{
Nathan Scott3562fd42006-03-14 14:00:35 +1100215 return __xfs_file_writev(file, iov, IO_INVIS, nr_segs, ppos);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216}
217
218STATIC ssize_t
Nathan Scott3562fd42006-03-14 14:00:35 +1100219xfs_file_sendfile(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 struct file *filp,
Nathan Scott1b895842006-03-31 13:08:59 +1000221 loff_t *pos,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 size_t count,
223 read_actor_t actor,
224 void *target)
225{
Nathan Scott67fcaa72006-06-09 17:00:52 +1000226 return bhv_vop_sendfile(vn_from_inode(filp->f_dentry->d_inode),
227 filp, pos, 0, count, actor, target, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228}
229
Nathan Scott1b895842006-03-31 13:08:59 +1000230STATIC ssize_t
231xfs_file_sendfile_invis(
232 struct file *filp,
233 loff_t *pos,
234 size_t count,
235 read_actor_t actor,
236 void *target)
237{
Nathan Scott67fcaa72006-06-09 17:00:52 +1000238 return bhv_vop_sendfile(vn_from_inode(filp->f_dentry->d_inode),
239 filp, pos, IO_INVIS, count, actor, target, NULL);
Nathan Scott1b895842006-03-31 13:08:59 +1000240}
241
242STATIC ssize_t
243xfs_file_splice_read(
244 struct file *infilp,
Jens Axboecbb7e572006-04-11 14:57:50 +0200245 loff_t *ppos,
Ingo Molnar3a326a22006-04-10 15:18:35 +0200246 struct pipe_inode_info *pipe,
Nathan Scott1b895842006-03-31 13:08:59 +1000247 size_t len,
248 unsigned int flags)
249{
Nathan Scott67fcaa72006-06-09 17:00:52 +1000250 return bhv_vop_splice_read(vn_from_inode(infilp->f_dentry->d_inode),
251 infilp, ppos, pipe, len, flags, 0, NULL);
Nathan Scott1b895842006-03-31 13:08:59 +1000252}
253
254STATIC ssize_t
255xfs_file_splice_read_invis(
256 struct file *infilp,
Jens Axboecbb7e572006-04-11 14:57:50 +0200257 loff_t *ppos,
Ingo Molnar3a326a22006-04-10 15:18:35 +0200258 struct pipe_inode_info *pipe,
Nathan Scott1b895842006-03-31 13:08:59 +1000259 size_t len,
260 unsigned int flags)
261{
Nathan Scott67fcaa72006-06-09 17:00:52 +1000262 return bhv_vop_splice_read(vn_from_inode(infilp->f_dentry->d_inode),
263 infilp, ppos, pipe, len, flags, IO_INVIS,
264 NULL);
Nathan Scott1b895842006-03-31 13:08:59 +1000265}
266
267STATIC ssize_t
268xfs_file_splice_write(
Ingo Molnar3a326a22006-04-10 15:18:35 +0200269 struct pipe_inode_info *pipe,
Nathan Scott1b895842006-03-31 13:08:59 +1000270 struct file *outfilp,
Jens Axboecbb7e572006-04-11 14:57:50 +0200271 loff_t *ppos,
Nathan Scott1b895842006-03-31 13:08:59 +1000272 size_t len,
273 unsigned int flags)
274{
Nathan Scott67fcaa72006-06-09 17:00:52 +1000275 return bhv_vop_splice_write(vn_from_inode(outfilp->f_dentry->d_inode),
276 pipe, outfilp, ppos, len, flags, 0, NULL);
Nathan Scott1b895842006-03-31 13:08:59 +1000277}
278
279STATIC ssize_t
280xfs_file_splice_write_invis(
Ingo Molnar3a326a22006-04-10 15:18:35 +0200281 struct pipe_inode_info *pipe,
Nathan Scott1b895842006-03-31 13:08:59 +1000282 struct file *outfilp,
Jens Axboecbb7e572006-04-11 14:57:50 +0200283 loff_t *ppos,
Nathan Scott1b895842006-03-31 13:08:59 +1000284 size_t len,
285 unsigned int flags)
286{
Nathan Scott67fcaa72006-06-09 17:00:52 +1000287 return bhv_vop_splice_write(vn_from_inode(outfilp->f_dentry->d_inode),
288 pipe, outfilp, ppos, len, flags, IO_INVIS,
289 NULL);
Nathan Scott1b895842006-03-31 13:08:59 +1000290}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
292STATIC int
Nathan Scott3562fd42006-03-14 14:00:35 +1100293xfs_file_open(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 struct inode *inode,
295 struct file *filp)
296{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
298 return -EFBIG;
Nathan Scott67fcaa72006-06-09 17:00:52 +1000299 return -bhv_vop_open(vn_from_inode(inode), NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300}
301
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302STATIC int
Nathan Scott7d4fb402006-06-09 15:27:16 +1000303xfs_file_close(
304 struct file *filp)
305{
Nathan Scott67fcaa72006-06-09 17:00:52 +1000306 return -bhv_vop_close(vn_from_inode(filp->f_dentry->d_inode), 0,
307 file_count(filp) > 1 ? L_FALSE : L_TRUE, NULL);
Nathan Scott7d4fb402006-06-09 15:27:16 +1000308}
309
310STATIC int
Nathan Scott3562fd42006-03-14 14:00:35 +1100311xfs_file_release(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 struct inode *inode,
313 struct file *filp)
314{
Nathan Scott67fcaa72006-06-09 17:00:52 +1000315 bhv_vnode_t *vp = vn_from_inode(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316
317 if (vp)
Nathan Scott67fcaa72006-06-09 17:00:52 +1000318 return -bhv_vop_release(vp);
319 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320}
321
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322STATIC int
Nathan Scott3562fd42006-03-14 14:00:35 +1100323xfs_file_fsync(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 struct file *filp,
325 struct dentry *dentry,
326 int datasync)
327{
Nathan Scott67fcaa72006-06-09 17:00:52 +1000328 bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 int flags = FSYNC_WAIT;
330
331 if (datasync)
332 flags |= FSYNC_DATA;
Nathan Scott7d4fb402006-06-09 15:27:16 +1000333 if (VN_TRUNC(vp))
334 VUNTRUNCATE(vp);
Nathan Scott67fcaa72006-06-09 17:00:52 +1000335 return -bhv_vop_fsync(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336}
337
Dean Roehrichbb3f7242005-09-02 15:43:05 +1000338#ifdef CONFIG_XFS_DMAPI
Dean Roehrichbb3f7242005-09-02 15:43:05 +1000339STATIC struct page *
Nathan Scott3562fd42006-03-14 14:00:35 +1100340xfs_vm_nopage(
Dean Roehrichbb3f7242005-09-02 15:43:05 +1000341 struct vm_area_struct *area,
342 unsigned long address,
343 int *type)
344{
345 struct inode *inode = area->vm_file->f_dentry->d_inode;
Nathan Scott67fcaa72006-06-09 17:00:52 +1000346 bhv_vnode_t *vp = vn_from_inode(inode);
Dean Roehrichbb3f7242005-09-02 15:43:05 +1000347
348 ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI);
Nathan Scottfbc14622006-06-09 14:52:13 +1000349 if (XFS_SEND_MMAP(XFS_VFSTOM(vp->v_vfsp), area, 0))
Dean Roehrichbb3f7242005-09-02 15:43:05 +1000350 return NULL;
Dean Roehrichbb3f7242005-09-02 15:43:05 +1000351 return filemap_nopage(area, address, type);
352}
Dean Roehrichbb3f7242005-09-02 15:43:05 +1000353#endif /* CONFIG_XFS_DMAPI */
354
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355STATIC int
Nathan Scott3562fd42006-03-14 14:00:35 +1100356xfs_file_readdir(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 struct file *filp,
358 void *dirent,
359 filldir_t filldir)
360{
361 int error = 0;
Nathan Scott67fcaa72006-06-09 17:00:52 +1000362 bhv_vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 uio_t uio;
364 iovec_t iov;
365 int eof = 0;
366 caddr_t read_buf;
367 int namelen, size = 0;
368 size_t rlen = PAGE_CACHE_SIZE;
369 xfs_off_t start_offset, curr_offset;
370 xfs_dirent_t *dbp = NULL;
371
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 /* Try fairly hard to get memory */
373 do {
374 if ((read_buf = (caddr_t)kmalloc(rlen, GFP_KERNEL)))
375 break;
376 rlen >>= 1;
377 } while (rlen >= 1024);
378
379 if (read_buf == NULL)
380 return -ENOMEM;
381
382 uio.uio_iov = &iov;
383 uio.uio_segflg = UIO_SYSSPACE;
384 curr_offset = filp->f_pos;
385 if (filp->f_pos != 0x7fffffff)
386 uio.uio_offset = filp->f_pos;
387 else
388 uio.uio_offset = 0xffffffff;
389
390 while (!eof) {
391 uio.uio_resid = iov.iov_len = rlen;
392 iov.iov_base = read_buf;
393 uio.uio_iovcnt = 1;
394
395 start_offset = uio.uio_offset;
396
Nathan Scott67fcaa72006-06-09 17:00:52 +1000397 error = bhv_vop_readdir(vp, &uio, NULL, &eof);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 if ((uio.uio_offset == start_offset) || error) {
399 size = 0;
400 break;
401 }
402
403 size = rlen - uio.uio_resid;
404 dbp = (xfs_dirent_t *)read_buf;
405 while (size > 0) {
406 namelen = strlen(dbp->d_name);
407
408 if (filldir(dirent, dbp->d_name, namelen,
409 (loff_t) curr_offset & 0x7fffffff,
410 (ino_t) dbp->d_ino,
411 DT_UNKNOWN)) {
412 goto done;
413 }
414 size -= dbp->d_reclen;
415 curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */;
Nathan Scott1b895842006-03-31 13:08:59 +1000416 dbp = (xfs_dirent_t *)((char *)dbp + dbp->d_reclen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 }
418 }
419done:
420 if (!error) {
421 if (size == 0)
422 filp->f_pos = uio.uio_offset & 0x7fffffff;
423 else if (dbp)
424 filp->f_pos = curr_offset;
425 }
426
427 kfree(read_buf);
428 return -error;
429}
430
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431STATIC int
Nathan Scott3562fd42006-03-14 14:00:35 +1100432xfs_file_mmap(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 struct file *filp,
434 struct vm_area_struct *vma)
435{
Nathan Scott3562fd42006-03-14 14:00:35 +1100436 vma->vm_ops = &xfs_file_vm_ops;
Dean Roehrich6fac0cb2005-06-21 14:07:45 +1000437
Dean Roehrich6fac0cb2005-06-21 14:07:45 +1000438#ifdef CONFIG_XFS_DMAPI
Nathan Scottfbc14622006-06-09 14:52:13 +1000439 if (vn_from_inode(filp->f_dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI)
Nathan Scott3562fd42006-03-14 14:00:35 +1100440 vma->vm_ops = &xfs_dmapi_file_vm_ops;
Dean Roehrichbb3f7242005-09-02 15:43:05 +1000441#endif /* CONFIG_XFS_DMAPI */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442
Nathan Scottfbc14622006-06-09 14:52:13 +1000443 file_accessed(filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 return 0;
445}
446
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447STATIC long
Nathan Scott3562fd42006-03-14 14:00:35 +1100448xfs_file_ioctl(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 struct file *filp,
450 unsigned int cmd,
Nathan Scott67fcaa72006-06-09 17:00:52 +1000451 unsigned long p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452{
453 int error;
Nathan Scott1f6553f2006-03-14 13:30:48 +1100454 struct inode *inode = filp->f_dentry->d_inode;
Nathan Scott67fcaa72006-06-09 17:00:52 +1000455 bhv_vnode_t *vp = vn_from_inode(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456
Nathan Scott67fcaa72006-06-09 17:00:52 +1000457 error = bhv_vop_ioctl(vp, inode, filp, 0, cmd, (void __user *)p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 VMODIFY(vp);
459
460 /* NOTE: some of the ioctl's return positive #'s as a
461 * byte count indicating success, such as
462 * readlink_by_handle. So we don't "sign flip"
463 * like most other routines. This means true
464 * errors need to be returned as a negative value.
465 */
466 return error;
467}
468
469STATIC long
Nathan Scott3562fd42006-03-14 14:00:35 +1100470xfs_file_ioctl_invis(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 struct file *filp,
472 unsigned int cmd,
Nathan Scott67fcaa72006-06-09 17:00:52 +1000473 unsigned long p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474{
Nathan Scott1b895842006-03-31 13:08:59 +1000475 int error;
Nathan Scott67fcaa72006-06-09 17:00:52 +1000476 struct inode *inode = filp->f_dentry->d_inode;
477 bhv_vnode_t *vp = vn_from_inode(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
Nathan Scott67fcaa72006-06-09 17:00:52 +1000479 error = bhv_vop_ioctl(vp, inode, filp, IO_INVIS, cmd, (void __user *)p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 VMODIFY(vp);
481
482 /* NOTE: some of the ioctl's return positive #'s as a
483 * byte count indicating success, such as
484 * readlink_by_handle. So we don't "sign flip"
485 * like most other routines. This means true
486 * errors need to be returned as a negative value.
487 */
488 return error;
489}
490
Dean Roehrichbb3f7242005-09-02 15:43:05 +1000491#ifdef CONFIG_XFS_DMAPI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492#ifdef HAVE_VMOP_MPROTECT
493STATIC int
Nathan Scott3562fd42006-03-14 14:00:35 +1100494xfs_vm_mprotect(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 struct vm_area_struct *vma,
496 unsigned int newflags)
497{
Nathan Scott67fcaa72006-06-09 17:00:52 +1000498 bhv_vnode_t *vp = vn_from_inode(vma->vm_file->f_dentry->d_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 int error = 0;
500
501 if (vp->v_vfsp->vfs_flag & VFS_DMI) {
502 if ((vma->vm_flags & VM_MAYSHARE) &&
503 (newflags & VM_WRITE) && !(vma->vm_flags & VM_WRITE)) {
504 xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
505
506 error = XFS_SEND_MMAP(mp, vma, VM_WRITE);
507 }
508 }
509 return error;
510}
511#endif /* HAVE_VMOP_MPROTECT */
Dean Roehrichbb3f7242005-09-02 15:43:05 +1000512#endif /* CONFIG_XFS_DMAPI */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513
514#ifdef HAVE_FOP_OPEN_EXEC
515/* If the user is attempting to execute a file that is offline then
516 * we have to trigger a DMAPI READ event before the file is marked as busy
517 * otherwise the invisible I/O will not be able to write to the file to bring
518 * it back online.
519 */
520STATIC int
Nathan Scott3562fd42006-03-14 14:00:35 +1100521xfs_file_open_exec(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 struct inode *inode)
523{
Nathan Scott67fcaa72006-06-09 17:00:52 +1000524 bhv_vnode_t *vp = vn_from_inode(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
526 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 xfs_inode_t *ip;
528
529 if (vp->v_vfsp->vfs_flag & VFS_DMI) {
Christoph Hellwig75e17b32006-01-11 20:58:44 +1100530 ip = xfs_vtoi(vp);
531 if (!ip) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 error = -EINVAL;
533 goto open_exec_out;
534 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ)) {
536 error = -XFS_SEND_DATA(mp, DM_EVENT_READ, vp,
537 0, 0, 0, NULL);
538 }
539 }
540open_exec_out:
541 return error;
542}
543#endif /* HAVE_FOP_OPEN_EXEC */
544
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800545const struct file_operations xfs_file_operations = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 .llseek = generic_file_llseek,
547 .read = do_sync_read,
Dean Roehrichbb3f7242005-09-02 15:43:05 +1000548 .write = do_sync_write,
Nathan Scott3562fd42006-03-14 14:00:35 +1100549 .readv = xfs_file_readv,
550 .writev = xfs_file_writev,
551 .aio_read = xfs_file_aio_read,
552 .aio_write = xfs_file_aio_write,
553 .sendfile = xfs_file_sendfile,
Nathan Scott1b895842006-03-31 13:08:59 +1000554 .splice_read = xfs_file_splice_read,
555 .splice_write = xfs_file_splice_write,
Nathan Scott3562fd42006-03-14 14:00:35 +1100556 .unlocked_ioctl = xfs_file_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557#ifdef CONFIG_COMPAT
Nathan Scott3562fd42006-03-14 14:00:35 +1100558 .compat_ioctl = xfs_file_compat_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559#endif
Nathan Scott3562fd42006-03-14 14:00:35 +1100560 .mmap = xfs_file_mmap,
561 .open = xfs_file_open,
Nathan Scott7d4fb402006-06-09 15:27:16 +1000562 .flush = xfs_file_close,
Nathan Scott3562fd42006-03-14 14:00:35 +1100563 .release = xfs_file_release,
564 .fsync = xfs_file_fsync,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565#ifdef HAVE_FOP_OPEN_EXEC
Nathan Scott3562fd42006-03-14 14:00:35 +1100566 .open_exec = xfs_file_open_exec,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567#endif
568};
569
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800570const struct file_operations xfs_invis_file_operations = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 .llseek = generic_file_llseek,
572 .read = do_sync_read,
Dean Roehrichbb3f7242005-09-02 15:43:05 +1000573 .write = do_sync_write,
Nathan Scott3562fd42006-03-14 14:00:35 +1100574 .readv = xfs_file_readv_invis,
575 .writev = xfs_file_writev_invis,
576 .aio_read = xfs_file_aio_read_invis,
577 .aio_write = xfs_file_aio_write_invis,
Nathan Scott1b895842006-03-31 13:08:59 +1000578 .sendfile = xfs_file_sendfile_invis,
579 .splice_read = xfs_file_splice_read_invis,
580 .splice_write = xfs_file_splice_write_invis,
Nathan Scott3562fd42006-03-14 14:00:35 +1100581 .unlocked_ioctl = xfs_file_ioctl_invis,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582#ifdef CONFIG_COMPAT
Nathan Scott3562fd42006-03-14 14:00:35 +1100583 .compat_ioctl = xfs_file_compat_invis_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584#endif
Nathan Scott3562fd42006-03-14 14:00:35 +1100585 .mmap = xfs_file_mmap,
586 .open = xfs_file_open,
Nathan Scott7d4fb402006-06-09 15:27:16 +1000587 .flush = xfs_file_close,
Nathan Scott3562fd42006-03-14 14:00:35 +1100588 .release = xfs_file_release,
589 .fsync = xfs_file_fsync,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590};
591
592
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800593const struct file_operations xfs_dir_file_operations = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 .read = generic_read_dir,
Nathan Scott3562fd42006-03-14 14:00:35 +1100595 .readdir = xfs_file_readdir,
596 .unlocked_ioctl = xfs_file_ioctl,
Nathan Scottd3870392005-05-06 06:44:46 -0700597#ifdef CONFIG_COMPAT
Nathan Scott3562fd42006-03-14 14:00:35 +1100598 .compat_ioctl = xfs_file_compat_ioctl,
Nathan Scottd3870392005-05-06 06:44:46 -0700599#endif
Nathan Scott3562fd42006-03-14 14:00:35 +1100600 .fsync = xfs_file_fsync,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601};
602
Nathan Scott3562fd42006-03-14 14:00:35 +1100603static struct vm_operations_struct xfs_file_vm_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 .nopage = filemap_nopage,
605 .populate = filemap_populate,
Dean Roehrich6fac0cb2005-06-21 14:07:45 +1000606};
607
608#ifdef CONFIG_XFS_DMAPI
Nathan Scott3562fd42006-03-14 14:00:35 +1100609static struct vm_operations_struct xfs_dmapi_file_vm_ops = {
610 .nopage = xfs_vm_nopage,
Dean Roehrich6fac0cb2005-06-21 14:07:45 +1000611 .populate = filemap_populate,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612#ifdef HAVE_VMOP_MPROTECT
Nathan Scott3562fd42006-03-14 14:00:35 +1100613 .mprotect = xfs_vm_mprotect,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614#endif
615};
Dean Roehrich6fac0cb2005-06-21 14:07:45 +1000616#endif /* CONFIG_XFS_DMAPI */