Esempio n. 1
0
STATIC int
xfs_ioc_setxflags(
	xfs_inode_t		*ip,
	struct file		*filp,
	void			__user *arg)
{
	struct fsxattr		fa;
	unsigned int		flags;
	unsigned int		mask;
	int error;

	if (copy_from_user(&flags, arg, sizeof(flags)))
		return -EFAULT;

	if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
		      FS_NOATIME_FL | FS_NODUMP_FL | \
		      FS_SYNC_FL))
		return -EOPNOTSUPP;

	mask = FSX_XFLAGS;
	if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
		mask |= FSX_NONBLOCK;
	fa.fsx_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip));

	error = mnt_want_write_file(filp);
	if (error)
		return error;
	error = xfs_ioctl_setattr(ip, &fa, mask);
	mnt_drop_write_file(filp);
	return -error;
}
Esempio n. 2
0
STATIC int
xfs_ioc_fsgetxattr(
	xfs_inode_t		*ip,
	int			attr,
	void			__user *arg)
{
	struct fsxattr		fa;

	xfs_ilock(ip, XFS_ILOCK_SHARED);
	fa.fsx_xflags = xfs_ip2xflags(ip);
	fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
	fa.fsx_projid = ip->i_d.di_projid;

	if (attr) {
		if (ip->i_afp) {
			if (ip->i_afp->if_flags & XFS_IFEXTENTS)
				fa.fsx_nextents = ip->i_afp->if_bytes /
							sizeof(xfs_bmbt_rec_t);
			else
				fa.fsx_nextents = ip->i_d.di_anextents;
		} else
			fa.fsx_nextents = 0;
	} else {
		if (ip->i_df.if_flags & XFS_IFEXTENTS)
			fa.fsx_nextents = ip->i_df.if_bytes /
						sizeof(xfs_bmbt_rec_t);
		else
			fa.fsx_nextents = ip->i_d.di_nextents;
	}
	xfs_iunlock(ip, XFS_ILOCK_SHARED);

	if (copy_to_user(arg, &fa, sizeof(fa)))
		return -EFAULT;
	return 0;
}
Esempio n. 3
0
STATIC void
xfs_diflags_to_linux(
	struct xfs_inode	*ip)
{
	struct inode		*inode = VFS_I(ip);
	unsigned int		xflags = xfs_ip2xflags(ip);

	if (xflags & FS_XFLAG_IMMUTABLE)
		inode->i_flags |= S_IMMUTABLE;
	else
		inode->i_flags &= ~S_IMMUTABLE;
	if (xflags & FS_XFLAG_APPEND)
		inode->i_flags |= S_APPEND;
	else
		inode->i_flags &= ~S_APPEND;
	if (xflags & FS_XFLAG_SYNC)
		inode->i_flags |= S_SYNC;
	else
		inode->i_flags &= ~S_SYNC;
	if (xflags & FS_XFLAG_NOATIME)
		inode->i_flags |= S_NOATIME;
	else
		inode->i_flags &= ~S_NOATIME;
	if (xflags & FS_XFLAG_DAX)
		inode->i_flags |= S_DAX;
	else
		inode->i_flags &= ~S_DAX;

}
Esempio n. 4
0
/*
 * Revalidate the Linux inode from the XFS inode.
 * Note: i_size _not_ updated; we must hold the inode
 * semaphore when doing that - callers responsibility.
 */
int
vn_revalidate(
    bhv_vnode_t        *vp)
{
    struct inode        *inode = vn_to_inode(vp);
    struct xfs_inode    *ip = XFS_I(inode);
    struct xfs_mount    *mp = ip->i_mount;
    unsigned long        xflags;

    xfs_itrace_entry(ip);

    if (XFS_FORCED_SHUTDOWN(mp))
        return -EIO;

    xfs_ilock(ip, XFS_ILOCK_SHARED);
    inode->i_mode        = ip->i_d.di_mode;
    inode->i_uid        = ip->i_d.di_uid;
    inode->i_gid        = ip->i_d.di_gid;
    inode->i_mtime.tv_sec = ip->i_d.di_mtime.t_sec;
    inode->i_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec;
    inode->i_ctime.tv_sec = ip->i_d.di_ctime.t_sec;
    inode->i_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec;

    xflags = xfs_ip2xflags(ip);
    if (xflags & XFS_XFLAG_IMMUTABLE)
        inode->i_flags |= S_IMMUTABLE;
    else
        inode->i_flags &= ~S_IMMUTABLE;
    if (xflags & XFS_XFLAG_APPEND)
        inode->i_flags |= S_APPEND;
    else
        inode->i_flags &= ~S_APPEND;
    if (xflags & XFS_XFLAG_SYNC)
        inode->i_flags |= S_SYNC;
    else
        inode->i_flags &= ~S_SYNC;
    if (xflags & XFS_XFLAG_NOATIME)
        inode->i_flags |= S_NOATIME;
    else
        inode->i_flags &= ~S_NOATIME;
    xfs_iunlock(ip, XFS_ILOCK_SHARED);

    xfs_iflags_clear(ip, XFS_IMODIFIED);
    return 0;
}
Esempio n. 5
0
/*
 * Return stat information for one inode.
 * Return 0 if ok, else errno.
 */
int
xfs_bulkstat_one_int(
	struct xfs_mount	*mp,		/* mount point for filesystem */
	xfs_ino_t		ino,		/* inode to get data for */
	void __user		*buffer,	/* buffer to place output in */
	int			ubsize,		/* size of buffer */
	bulkstat_one_fmt_pf	formatter,	/* formatter, copy to user */
	int			*ubused,	/* bytes used by me */
	int			*stat)		/* BULKSTAT_RV_... */
{
	struct xfs_icdinode	*dic;		/* dinode core info pointer */
	struct xfs_inode	*ip;		/* incore inode pointer */
	struct xfs_bstat	*buf;		/* return buffer */
	int			error = 0;	/* error value */

	*stat = BULKSTAT_RV_NOTHING;

	if (!buffer || xfs_internal_inum(mp, ino))
		return -EINVAL;

	buf = kmem_alloc(sizeof(*buf), KM_SLEEP | KM_MAYFAIL);
	if (!buf)
		return -ENOMEM;

	error = xfs_iget(mp, NULL, ino,
			 (XFS_IGET_DONTCACHE | XFS_IGET_UNTRUSTED),
			 XFS_ILOCK_SHARED, &ip);
	if (error)
		goto out_free;

	ASSERT(ip != NULL);
	ASSERT(ip->i_imap.im_blkno != 0);

	dic = &ip->i_d;

	/* xfs_iget returns the following without needing
	 * further change.
	 */
	buf->bs_nlink = dic->di_nlink;
	buf->bs_projid_lo = dic->di_projid_lo;
	buf->bs_projid_hi = dic->di_projid_hi;
	buf->bs_ino = ino;
	buf->bs_mode = dic->di_mode;
	buf->bs_uid = dic->di_uid;
	buf->bs_gid = dic->di_gid;
	buf->bs_size = dic->di_size;
	buf->bs_atime.tv_sec = dic->di_atime.t_sec;
	buf->bs_atime.tv_nsec = dic->di_atime.t_nsec;
	buf->bs_mtime.tv_sec = dic->di_mtime.t_sec;
	buf->bs_mtime.tv_nsec = dic->di_mtime.t_nsec;
	buf->bs_ctime.tv_sec = dic->di_ctime.t_sec;
	buf->bs_ctime.tv_nsec = dic->di_ctime.t_nsec;
	buf->bs_xflags = xfs_ip2xflags(ip);
	buf->bs_extsize = dic->di_extsize << mp->m_sb.sb_blocklog;
	buf->bs_extents = dic->di_nextents;
	buf->bs_gen = dic->di_gen;
	memset(buf->bs_pad, 0, sizeof(buf->bs_pad));
	buf->bs_dmevmask = dic->di_dmevmask;
	buf->bs_dmstate = dic->di_dmstate;
	buf->bs_aextents = dic->di_anextents;
	buf->bs_forkoff = XFS_IFORK_BOFF(ip);

	switch (dic->di_format) {
	case XFS_DINODE_FMT_DEV:
		buf->bs_rdev = ip->i_df.if_u2.if_rdev;
		buf->bs_blksize = BLKDEV_IOSIZE;
		buf->bs_blocks = 0;
		break;
	case XFS_DINODE_FMT_LOCAL:
	case XFS_DINODE_FMT_UUID:
		buf->bs_rdev = 0;
		buf->bs_blksize = mp->m_sb.sb_blocksize;
		buf->bs_blocks = 0;
		break;
	case XFS_DINODE_FMT_EXTENTS:
	case XFS_DINODE_FMT_BTREE:
		buf->bs_rdev = 0;
		buf->bs_blksize = mp->m_sb.sb_blocksize;
		buf->bs_blocks = dic->di_nblocks + ip->i_delayed_blks;
		break;
	}
	xfs_iunlock(ip, XFS_ILOCK_SHARED);
	IRELE(ip);

	error = formatter(buffer, ubsize, ubused, buf);
	if (!error)
		*stat = BULKSTAT_RV_DIDONE;

 out_free:
	kmem_free(buf);
	return error;
}
Esempio n. 6
0
STATIC int
xfs_ioc_xattr(
	vnode_t			*vp,
	xfs_inode_t		*ip,
	struct file		*filp,
	unsigned int		cmd,
	void			__user *arg)
{
	struct fsxattr		fa;
	struct vattr		*vattr;
	int			error = 0;
	int			attr_flags;
	unsigned int		flags;

	vattr = kmalloc(sizeof(*vattr), GFP_KERNEL);
	if (unlikely(!vattr))
		return -ENOMEM;

	switch (cmd) {
	case XFS_IOC_FSGETXATTR: {
		vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
				 XFS_AT_NEXTENTS | XFS_AT_PROJID;
		VOP_GETATTR(vp, vattr, 0, NULL, error);
		if (unlikely(error)) {
			error = -error;
			break;
		}

		fa.fsx_xflags	= vattr->va_xflags;
		fa.fsx_extsize	= vattr->va_extsize;
		fa.fsx_nextents = vattr->va_nextents;
		fa.fsx_projid	= vattr->va_projid;

		if (copy_to_user(arg, &fa, sizeof(fa))) {
			error = -EFAULT;
			break;
		}
		break;
	}

	case XFS_IOC_FSSETXATTR: {
		if (copy_from_user(&fa, arg, sizeof(fa))) {
			error = -EFAULT;
			break;
		}

		attr_flags = 0;
		if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
			attr_flags |= ATTR_NONBLOCK;

		vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID;
		vattr->va_xflags  = fa.fsx_xflags;
		vattr->va_extsize = fa.fsx_extsize;
		vattr->va_projid  = fa.fsx_projid;

		VOP_SETATTR(vp, vattr, attr_flags, NULL, error);
		if (likely(!error))
			__vn_revalidate(vp, vattr);	/* update flags */
		error = -error;
		break;
	}

	case XFS_IOC_FSGETXATTRA: {
		vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
				 XFS_AT_ANEXTENTS | XFS_AT_PROJID;
		VOP_GETATTR(vp, vattr, 0, NULL, error);
		if (unlikely(error)) {
			error = -error;
			break;
		}

		fa.fsx_xflags	= vattr->va_xflags;
		fa.fsx_extsize	= vattr->va_extsize;
		fa.fsx_nextents = vattr->va_anextents;
		fa.fsx_projid	= vattr->va_projid;

		if (copy_to_user(arg, &fa, sizeof(fa))) {
			error = -EFAULT;
			break;
		}
		break;
	}

	case XFS_IOC_GETXFLAGS: {
		flags = xfs_di2lxflags(ip->i_d.di_flags);
		if (copy_to_user(arg, &flags, sizeof(flags)))
			error = -EFAULT;
		break;
	}

	case XFS_IOC_SETXFLAGS: {
		if (copy_from_user(&flags, arg, sizeof(flags))) {
			error = -EFAULT;
			break;
		}

		if (flags & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \
			      LINUX_XFLAG_NOATIME | LINUX_XFLAG_NODUMP | \
			      LINUX_XFLAG_SYNC)) {
			error = -EOPNOTSUPP;
			break;
		}

		attr_flags = 0;
		if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
			attr_flags |= ATTR_NONBLOCK;

		vattr->va_mask = XFS_AT_XFLAGS;
		vattr->va_xflags = xfs_merge_ioc_xflags(flags,
							xfs_ip2xflags(ip));

		VOP_SETATTR(vp, vattr, attr_flags, NULL, error);
		if (likely(!error))
			__vn_revalidate(vp, vattr);	/* update flags */
		error = -error;
		break;
	}

	case XFS_IOC_GETVERSION: {
		flags = vn_to_inode(vp)->i_generation;
		if (copy_to_user(arg, &flags, sizeof(flags)))
			error = -EFAULT;
		break;
	}

	default:
		error = -ENOTTY;
		break;
	}

	kfree(vattr);
	return error;
}