STATIC int linvfs_file_mmap( struct file *filp, struct vm_area_struct *vma) { struct inode *ip = filp->f_dentry->d_inode; vnode_t *vp = LINVFS_GET_VP(ip); vattr_t va = { .va_mask = XFS_AT_UPDATIME }; int error; if (vp->v_vfsp->vfs_flag & VFS_DMI) { xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp); error = -XFS_SEND_MMAP(mp, vma, 0); if (error) return error; } vma->vm_ops = &linvfs_file_vm_ops; VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error); if (!error) vn_revalidate(vp); /* update Linux inode flags */ return 0; }
STATIC int linvfs_setattr( struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; unsigned int ia_valid = attr->ia_valid; vnode_t *vp = LINVFS_GET_VP(inode); vattr_t vattr; int flags = 0; int error; memset(&vattr, 0, sizeof(vattr_t)); if (ia_valid & ATTR_UID) { vattr.va_mask |= XFS_AT_UID; vattr.va_uid = attr->ia_uid; } if (ia_valid & ATTR_GID) { vattr.va_mask |= XFS_AT_GID; vattr.va_gid = attr->ia_gid; } if (ia_valid & ATTR_SIZE) { vattr.va_mask |= XFS_AT_SIZE; vattr.va_size = attr->ia_size; } if (ia_valid & ATTR_ATIME) { vattr.va_mask |= XFS_AT_ATIME; vattr.va_atime = attr->ia_atime; inode->i_atime = attr->ia_atime; } if (ia_valid & ATTR_MTIME) { vattr.va_mask |= XFS_AT_MTIME; vattr.va_mtime = attr->ia_mtime; } if (ia_valid & ATTR_CTIME) { vattr.va_mask |= XFS_AT_CTIME; vattr.va_ctime = attr->ia_ctime; } if (ia_valid & ATTR_MODE) { vattr.va_mask |= XFS_AT_MODE; vattr.va_mode = attr->ia_mode; if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) inode->i_mode &= ~S_ISGID; } if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) flags |= ATTR_UTIME; #ifdef ATTR_NO_BLOCK if ((ia_valid & ATTR_NO_BLOCK)) flags |= ATTR_NONBLOCK; #endif VOP_SETATTR(vp, &vattr, flags, NULL, error); if (error) return -error; vn_revalidate(vp); return error; }
STATIC int linvfs_revalidate( struct dentry *dentry) { vnode_t *vp = LINVFS_GET_VP(dentry->d_inode); if (unlikely(vp->v_flag & VMODIFIED)) return vn_revalidate(vp); return 0; }
/* Brute force approach for now - copy data into linux inode * from the results of a getattr. This gets called out of things * like stat. */ int linvfs_revalidate_core( struct inode *inode, int flags) { vnode_t *vp = LINVFS_GET_VP(inode); /* vn_revalidate returns (-) error so this is ok */ return vn_revalidate(vp, flags); }
STATIC int xfs_vn_setattr( struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; unsigned int ia_valid = attr->ia_valid; bhv_vattr_t vattr = { 0 }; int flags = 0; int error; if (ia_valid & ATTR_UID) { vattr.va_mask |= XFS_AT_UID; vattr.va_uid = attr->ia_uid; } if (ia_valid & ATTR_GID) { vattr.va_mask |= XFS_AT_GID; vattr.va_gid = attr->ia_gid; } if (ia_valid & ATTR_SIZE) { vattr.va_mask |= XFS_AT_SIZE; vattr.va_size = attr->ia_size; } if (ia_valid & ATTR_ATIME) { vattr.va_mask |= XFS_AT_ATIME; vattr.va_atime = attr->ia_atime; inode->i_atime = attr->ia_atime; } if (ia_valid & ATTR_MTIME) { vattr.va_mask |= XFS_AT_MTIME; vattr.va_mtime = attr->ia_mtime; } if (ia_valid & ATTR_CTIME) { vattr.va_mask |= XFS_AT_CTIME; vattr.va_ctime = attr->ia_ctime; } if (ia_valid & ATTR_MODE) { vattr.va_mask |= XFS_AT_MODE; vattr.va_mode = attr->ia_mode; if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) inode->i_mode &= ~S_ISGID; } if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) flags |= ATTR_UTIME; #ifdef ATTR_NO_BLOCK if ((ia_valid & ATTR_NO_BLOCK)) flags |= ATTR_NONBLOCK; #endif error = xfs_setattr(XFS_I(inode), &vattr, flags, NULL); if (likely(!error)) vn_revalidate(vn_from_inode(inode)); return -error; }
STATIC int linvfs_getattr( struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { struct inode *inode = dentry->d_inode; vnode_t *vp = LINVFS_GET_VP(inode); int error = 0; if (unlikely(vp->v_flag & VMODIFIED)) error = vn_revalidate(vp); if (!error) generic_fillattr(inode, stat); return 0; }
STATIC int xfs_ioc_xattr( vnode_t *vp, xfs_inode_t *ip, struct file *filp, unsigned int cmd, unsigned long arg) { struct fsxattr fa; vattr_t va; int error; int attr_flags; unsigned int flags; switch (cmd) { case XFS_IOC_FSGETXATTR: { va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_NEXTENTS; VOP_GETATTR(vp, &va, 0, NULL, error); if (error) return -error; fa.fsx_xflags = va.va_xflags; fa.fsx_extsize = va.va_extsize; fa.fsx_nextents = va.va_nextents; if (copy_to_user((struct fsxattr *)arg, &fa, sizeof(fa))) return -XFS_ERROR(EFAULT); return 0; } case XFS_IOC_FSSETXATTR: { if (copy_from_user(&fa, (struct fsxattr *)arg, sizeof(fa))) return -XFS_ERROR(EFAULT); attr_flags = 0; if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) attr_flags |= ATTR_NONBLOCK; va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE; va.va_xflags = fa.fsx_xflags; va.va_extsize = fa.fsx_extsize; VOP_SETATTR(vp, &va, attr_flags, NULL, error); if (!error) vn_revalidate(vp); /* update Linux inode flags */ return -error; } case XFS_IOC_FSGETXATTRA: { va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_ANEXTENTS; VOP_GETATTR(vp, &va, 0, NULL, error); if (error) return -error; fa.fsx_xflags = va.va_xflags; fa.fsx_extsize = va.va_extsize; fa.fsx_nextents = va.va_anextents; if (copy_to_user((struct fsxattr *)arg, &fa, sizeof(fa))) return -XFS_ERROR(EFAULT); return 0; } case XFS_IOC_GETXFLAGS: { flags = xfs_di2lxflags(ip->i_d.di_flags); if (copy_to_user((unsigned int *)arg, &flags, sizeof(flags))) return -XFS_ERROR(EFAULT); return 0; } case XFS_IOC_SETXFLAGS: { if (copy_from_user(&flags, (unsigned int *)arg, sizeof(flags))) return -XFS_ERROR(EFAULT); if (flags & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \ LINUX_XFLAG_NOATIME | LINUX_XFLAG_NODUMP | \ LINUX_XFLAG_SYNC)) return -XFS_ERROR(EOPNOTSUPP); attr_flags = 0; if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) attr_flags |= ATTR_NONBLOCK; va.va_mask = XFS_AT_XFLAGS; va.va_xflags = xfs_merge_ioc_xflags(flags, xfs_dic2xflags(&ip->i_d, ARCH_NOCONVERT)); VOP_SETATTR(vp, &va, attr_flags, NULL, error); if (!error) vn_revalidate(vp); /* update Linux inode flags */ return -error; } case XFS_IOC_GETVERSION: { flags = LINVFS_GET_IP(vp)->i_generation; if (copy_to_user((unsigned int *)arg, &flags, sizeof(flags))) return -XFS_ERROR(EFAULT); return 0; } default: return -ENOTTY; } }
STATIC int linvfs_setattr( struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; unsigned int ia_valid = attr->ia_valid; vnode_t *vp = LINVFS_GET_VP(inode); vattr_t vattr; int flags = 0; int error; memset(&vattr, 0, sizeof(vattr_t)); if (ia_valid & ATTR_UID) { vattr.va_mask |= XFS_AT_UID; vattr.va_uid = attr->ia_uid; } if (ia_valid & ATTR_GID) { vattr.va_mask |= XFS_AT_GID; vattr.va_gid = attr->ia_gid; } if (ia_valid & ATTR_SIZE) { vattr.va_mask |= XFS_AT_SIZE; vattr.va_size = attr->ia_size; } if (ia_valid & ATTR_ATIME) { vattr.va_mask |= XFS_AT_ATIME; vattr.va_atime.tv_sec = attr->ia_atime; vattr.va_atime.tv_nsec = 0; } if (ia_valid & ATTR_MTIME) { vattr.va_mask |= XFS_AT_MTIME; vattr.va_mtime.tv_sec = attr->ia_mtime; vattr.va_mtime.tv_nsec = 0; } if (ia_valid & ATTR_CTIME) { vattr.va_mask |= XFS_AT_CTIME; vattr.va_ctime.tv_sec = attr->ia_ctime; vattr.va_ctime.tv_nsec = 0; } if (ia_valid & ATTR_MODE) { vattr.va_mask |= XFS_AT_MODE; vattr.va_mode = attr->ia_mode; if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) inode->i_mode &= ~S_ISGID; } if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) flags = ATTR_UTIME; VOP_SETATTR(vp, &vattr, flags, NULL, error); if (error) return(-error); /* Positive error up from XFS */ if (ia_valid & ATTR_SIZE) { error = vmtruncate(inode, attr->ia_size); } if (!error) { vn_revalidate(vp); } return error; }