2 * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
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.
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.
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.
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.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
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"
54 #include <linux/iobuf.h>
56 #include <linux/dcache.h>
57 #include <linux/smp_lock.h>
58 #include <linux/mman.h> /* for PROT_WRITE */
60 static struct vm_operations_struct linvfs_file_vm_ops;
70 struct inode *inode = file->f_dentry->d_inode;
71 vnode_t *vp = LINVFS_GET_VP(inode);
74 if (unlikely(file->f_flags & O_DIRECT)) {
75 ioflags |= IO_ISDIRECT;
76 down_read(&inode->i_alloc_sem);
77 VOP_READ(vp, file, buf, size, offset, ioflags, NULL, rval);
78 up_read(&inode->i_alloc_sem);
80 VOP_READ(vp, file, buf, size, offset, ioflags, NULL, rval);
93 return __linvfs_read(file, buf, 0, size, offset);
103 return __linvfs_read(file, buf, IO_INVIS, size, offset);
107 STATIC inline ssize_t
115 struct inode *inode = file->f_dentry->d_inode;
116 vnode_t *vp = LINVFS_GET_VP(inode);
118 ssize_t rval; /* Use negative errors in this f'n */
120 if ((ssize_t) count < 0)
123 if (!access_ok(VERIFY_READ, buf, count))
130 rval = file->f_error;
136 /* We allow multiple direct writers in, there is no
137 * potential call to vmtruncate in that path.
139 if (unlikely(file->f_flags & O_DIRECT)) {
140 ioflags |= IO_ISDIRECT;
141 down_read(&inode->i_alloc_sem);
142 VOP_WRITE(vp, file, buf, count, &pos, ioflags, NULL, rval);
144 up_read(&inode->i_alloc_sem);
147 VOP_WRITE(vp, file, buf, count, &pos, ioflags, NULL, rval);
155 STATIC inline ssize_t
162 return __linvfs_write(file, buf, 0, count, ppos);
165 STATIC inline ssize_t
172 return __linvfs_write(file, buf, IO_INVIS, count, ppos);
180 vnode_t *vp = LINVFS_GET_VP(inode);
183 if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
187 VOP_OPEN(vp, NULL, error);
197 vnode_t *vp = LINVFS_GET_VP(inode);
201 VOP_RELEASE(vp, error);
209 struct dentry *dentry,
212 struct inode *inode = dentry->d_inode;
213 vnode_t *vp = LINVFS_GET_VP(inode);
215 int flags = FSYNC_WAIT;
217 error = fsync_inode_data_buffers(inode);
225 VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error);
230 * linvfs_readdir maps to VOP_READDIR().
231 * We need to build a uio, cred, ...
234 #define nextdp(dp) ((struct xfs_dirent *)((char *)(dp) + (dp)->d_reclen))
248 int namelen, size = 0;
249 size_t rlen = PAGE_CACHE_SIZE;
250 xfs_off_t start_offset, curr_offset;
251 xfs_dirent_t *dbp = NULL;
253 vp = LINVFS_GET_VP(filp->f_dentry->d_inode);
256 /* Try fairly hard to get memory */
258 if ((read_buf = (caddr_t)kmalloc(rlen, GFP_KERNEL)))
261 } while (rlen >= 1024);
263 if (read_buf == NULL)
267 uio.uio_segflg = UIO_SYSSPACE;
268 curr_offset = filp->f_pos;
269 if (filp->f_pos != 0x7fffffff)
270 uio.uio_offset = filp->f_pos;
272 uio.uio_offset = 0xffffffff;
275 uio.uio_resid = iov.iov_len = rlen;
276 iov.iov_base = read_buf;
279 start_offset = uio.uio_offset;
281 VOP_READDIR(vp, &uio, NULL, &eof, error);
282 if ((uio.uio_offset == start_offset) || error) {
287 size = rlen - uio.uio_resid;
288 dbp = (xfs_dirent_t *)read_buf;
290 namelen = strlen(dbp->d_name);
292 if (filldir(dirent, dbp->d_name, namelen,
293 (loff_t) curr_offset & 0x7fffffff,
298 size -= dbp->d_reclen;
299 curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */;
306 filp->f_pos = uio.uio_offset & 0x7fffffff;
308 filp->f_pos = curr_offset;
318 struct vm_area_struct *vma)
320 struct inode *ip = filp->f_dentry->d_inode;
321 vnode_t *vp = LINVFS_GET_VP(ip);
322 vattr_t va = { .va_mask = XFS_AT_UPDATIME };
325 if (vp->v_vfsp->vfs_flag & VFS_DMI) {
326 xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
328 error = -XFS_SEND_MMAP(mp, vma, 0);
333 vma->vm_ops = &linvfs_file_vm_ops;
335 VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error);
337 vn_revalidate(vp); /* update Linux inode flags */
350 vnode_t *vp = LINVFS_GET_VP(inode);
353 VOP_IOCTL(vp, inode, filp, 0, cmd, arg, error);
357 /* NOTE: some of the ioctl's return positive #'s as a
358 * byte count indicating success, such as
359 * readlink_by_handle. So we don't "sign flip"
360 * like most other routines. This means true
361 * errors need to be returned as a negative value.
374 vnode_t *vp = LINVFS_GET_VP(inode);
377 VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, arg, error);
381 /* NOTE: some of the ioctl's return positive #'s as a
382 * byte count indicating success, such as
383 * readlink_by_handle. So we don't "sign flip"
384 * like most other routines. This means true
385 * errors need to be returned as a negative value.
390 #ifdef HAVE_VMOP_MPROTECT
393 struct vm_area_struct *vma,
394 unsigned int newflags)
396 vnode_t *vp = LINVFS_GET_VP(vma->vm_file->f_dentry->d_inode);
399 if (vp->v_vfsp->vfs_flag & VFS_DMI) {
400 if ((vma->vm_flags & VM_MAYSHARE) &&
401 (newflags & PROT_WRITE) && !(vma->vm_flags & PROT_WRITE)) {
402 xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
404 error = XFS_SEND_MMAP(mp, vma, VM_WRITE);
409 #endif /* HAVE_VMOP_MPROTECT */
412 struct file_operations linvfs_file_operations = {
413 .llseek = generic_file_llseek,
415 .write = linvfs_write,
416 .ioctl = linvfs_ioctl,
417 .mmap = linvfs_file_mmap,
419 .release = linvfs_release,
420 .fsync = linvfs_fsync,
423 struct file_operations linvfs_invis_file_operations = {
424 .llseek = generic_file_llseek,
425 .read = linvfs_read_invis,
426 .write = linvfs_write_invis,
427 .ioctl = linvfs_ioctl_invis,
428 .mmap = linvfs_file_mmap,
430 .release = linvfs_release,
431 .fsync = linvfs_fsync,
435 struct file_operations linvfs_dir_operations = {
436 .read = generic_read_dir,
437 .readdir = linvfs_readdir,
438 .ioctl = linvfs_ioctl,
439 .fsync = linvfs_fsync,
442 static struct vm_operations_struct linvfs_file_vm_ops = {
443 .nopage = filemap_nopage,
444 #ifdef HAVE_VMOP_MPROTECT
445 .mprotect = linvfs_mprotect,