struct dentry *dentry,
int datasync)
{
- bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
int flags = FSYNC_WAIT;
if (datasync)
flags |= FSYNC_DATA;
- if (VN_TRUNC(vp))
- VUNTRUNCATE(vp);
+ xfs_iflags_clear(XFS_I(dentry->d_inode), XFS_ITRUNCATED);
return -xfs_fsync(XFS_I(dentry->d_inode), flags,
(xfs_off_t)0, (xfs_off_t)-1);
}
}
#endif /* CONFIG_XFS_DMAPI */
+/*
+ * Unfortunately we can't just use the clean and simple readdir implementation
+ * below, because nfs might call back into ->lookup from the filldir callback
+ * and that will deadlock the low-level btree code.
+ *
+ * Hopefully we'll find a better workaround that allows to use the optimal
+ * version at least for local readdirs for 2.6.25.
+ */
+#if 0
STATIC int
xfs_file_readdir(
struct file *filp,
return -error;
return 0;
}
+#else
+
+struct hack_dirent {
+ u64 ino;
+ loff_t offset;
+ int namlen;
+ unsigned int d_type;
+ char name[];
+};
+
+struct hack_callback {
+ char *dirent;
+ size_t len;
+ size_t used;
+};
+
+STATIC int
+xfs_hack_filldir(
+ void *__buf,
+ const char *name,
+ int namlen,
+ loff_t offset,
+ u64 ino,
+ unsigned int d_type)
+{
+ struct hack_callback *buf = __buf;
+ struct hack_dirent *de = (struct hack_dirent *)(buf->dirent + buf->used);
+ unsigned int reclen;
+
+ reclen = ALIGN(sizeof(struct hack_dirent) + namlen, sizeof(u64));
+ if (buf->used + reclen > buf->len)
+ return -EINVAL;
+
+ de->namlen = namlen;
+ de->offset = offset;
+ de->ino = ino;
+ de->d_type = d_type;
+ memcpy(de->name, name, namlen);
+ buf->used += reclen;
+ return 0;
+}
+
+STATIC int
+xfs_file_readdir(
+ struct file *filp,
+ void *dirent,
+ filldir_t filldir)
+{
+ struct inode *inode = filp->f_path.dentry->d_inode;
+ xfs_inode_t *ip = XFS_I(inode);
+ struct hack_callback buf;
+ struct hack_dirent *de;
+ int error;
+ loff_t size;
+ int eof = 0;
+ xfs_off_t start_offset, curr_offset, offset;
+
+ /*
+ * Try fairly hard to get memory
+ */
+ buf.len = PAGE_CACHE_SIZE;
+ do {
+ buf.dirent = kmalloc(buf.len, GFP_KERNEL);
+ if (buf.dirent)
+ break;
+ buf.len >>= 1;
+ } while (buf.len >= 1024);
+
+ if (!buf.dirent)
+ return -ENOMEM;
+
+ curr_offset = filp->f_pos;
+ if (curr_offset == 0x7fffffff)
+ offset = 0xffffffff;
+ else
+ offset = filp->f_pos;
+
+ while (!eof) {
+ unsigned int reclen;
+
+ start_offset = offset;
+
+ buf.used = 0;
+ error = -xfs_readdir(ip, &buf, buf.len, &offset,
+ xfs_hack_filldir);
+ if (error || offset == start_offset) {
+ size = 0;
+ break;
+ }
+
+ size = buf.used;
+ de = (struct hack_dirent *)buf.dirent;
+ while (size > 0) {
+ curr_offset = de->offset /* & 0x7fffffff */;
+ if (filldir(dirent, de->name, de->namlen,
+ curr_offset & 0x7fffffff,
+ de->ino, de->d_type)) {
+ goto done;
+ }
+
+ reclen = ALIGN(sizeof(struct hack_dirent) + de->namlen,
+ sizeof(u64));
+ size -= reclen;
+ de = (struct hack_dirent *)((char *)de + reclen);
+ }
+ }
+
+ done:
+ if (!error) {
+ if (size == 0)
+ filp->f_pos = offset & 0x7fffffff;
+ else if (de)
+ filp->f_pos = curr_offset;
+ }
+
+ kfree(buf.dirent);
+ return error;
+}
+#endif
STATIC int
xfs_file_mmap(
vma->vm_flags |= VM_CAN_NONLINEAR;
#ifdef CONFIG_XFS_DMAPI
- if (vn_from_inode(filp->f_path.dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI)
+ if (XFS_M(filp->f_path.dentry->d_inode->i_sb)->m_flags & XFS_MOUNT_DMAPI)
vma->vm_ops = &xfs_dmapi_file_vm_ops;
#endif /* CONFIG_XFS_DMAPI */
{
int error;
struct inode *inode = filp->f_path.dentry->d_inode;
- bhv_vnode_t *vp = vn_from_inode(inode);
error = xfs_ioctl(XFS_I(inode), filp, 0, cmd, (void __user *)p);
- VMODIFY(vp);
+ xfs_iflags_set(XFS_I(inode), XFS_IMODIFIED);
/* NOTE: some of the ioctl's return positive #'s as a
* byte count indicating success, such as
{
int error;
struct inode *inode = filp->f_path.dentry->d_inode;
- bhv_vnode_t *vp = vn_from_inode(inode);
error = xfs_ioctl(XFS_I(inode), filp, IO_INVIS, cmd, (void __user *)p);
- VMODIFY(vp);
+ xfs_iflags_set(XFS_I(inode), XFS_IMODIFIED);
/* NOTE: some of the ioctl's return positive #'s as a
* byte count indicating success, such as
struct vm_area_struct *vma,
unsigned int newflags)
{
- bhv_vnode_t *vp = vn_from_inode(vma->vm_file->f_path.dentry->d_inode);
+ struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
+ struct xfs_mount *mp = XFS_M(inode->i_sb);
int error = 0;
- if (vp->v_vfsp->vfs_flag & VFS_DMI) {
+ if (mp->m_flags & XFS_MOUNT_DMAPI) {
if ((vma->vm_flags & VM_MAYSHARE) &&
- (newflags & VM_WRITE) && !(vma->vm_flags & VM_WRITE)) {
- xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
-
+ (newflags & VM_WRITE) && !(vma->vm_flags & VM_WRITE))
error = XFS_SEND_MMAP(mp, vma, VM_WRITE);
- }
}
return error;
}
xfs_file_open_exec(
struct inode *inode)
{
- bhv_vnode_t *vp = vn_from_inode(inode);
+ struct xfs_mount *mp = XFS_M(inode->i_sb);
- if (unlikely(vp->v_vfsp->vfs_flag & VFS_DMI)) {
- xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
- xfs_inode_t *ip = xfs_vtoi(vp);
+ if (unlikely(mp->m_flags & XFS_MOUNT_DMAPI)) {
+ if (DM_EVENT_ENABLED(XFS_I(inode), DM_EVENT_READ)) {
+ bhv_vnode_t *vp = vn_from_inode(inode);
- if (!ip)
- return -EINVAL;
- if (DM_EVENT_ENABLED(ip, DM_EVENT_READ))
- return -XFS_SEND_DATA(mp, DM_EVENT_READ, vp,
- 0, 0, 0, NULL);
+ return -XFS_SEND_DATA(mp, DM_EVENT_READ,
+ vp, 0, 0, 0, NULL);
+ }
}
+
return 0;
}
#endif /* HAVE_FOP_OPEN_EXEC */