[patch 08/11] Hook up compat XFS_IOC_ATTRLIST_BY_HANDLE ioctl handler
Christoph Hellwig
hch at infradead.org
Wed Nov 19 09:13:48 CST 2008
On Tue, Nov 18, 2008 at 10:44:09PM -0600, sandeen at sandeen.net wrote:
> +/*
> + * Convert userspace handle data into inode.
> + *
> + * We use the fact that all the fsop_handlereq ioctl calls have a data
> + * structure argument whose first component is always a xfs_fsop_handlereq_t,
> + * so we can pass that sub structure into this handy, shared routine.
> + *
> + * If no error, caller must always iput the returned inode.
> + */
> +STATIC int
> +xfs_vget_fsop_handlereq_compat(
> + xfs_mount_t *mp,
> + struct inode *parinode, /* parent inode pointer */
> + compat_xfs_fsop_handlereq_t *hreq,
> + struct inode **inode)
> +{
> + void __user *hanp;
> + size_t hlen;
> + xfs_fid_t *xfid;
> + xfs_handle_t *handlep;
> + xfs_handle_t handle;
> + xfs_inode_t *ip;
> + xfs_ino_t ino;
> + __u32 igen;
> + int error;
> +
> + /*
> + * Only allow handle opens under a directory.
> + */
> + if (!S_ISDIR(parinode->i_mode))
> + return XFS_ERROR(ENOTDIR);
> +
> + hanp = compat_ptr(hreq->ihandle);
> + hlen = hreq->ihandlen;
> + handlep = &handle;
> +
> + if (hlen < sizeof(handlep->ha_fsid) || hlen > sizeof(*handlep))
> + return XFS_ERROR(EINVAL);
> + if (copy_from_user(handlep, hanp, hlen))
> + return XFS_ERROR(EFAULT);
> + if (hlen < sizeof(*handlep))
> + memset(((char *)handlep) + hlen, 0, sizeof(*handlep) - hlen);
> + if (hlen > sizeof(handlep->ha_fsid)) {
> + if (handlep->ha_fid.fid_len !=
> + (hlen - sizeof(handlep->ha_fsid) -
> + sizeof(handlep->ha_fid.fid_len)) ||
> + handlep->ha_fid.fid_pad)
> + return XFS_ERROR(EINVAL);
> + }
> +
> + /*
> + * Crack the handle, obtain the inode # & generation #
> + */
> + xfid = (struct xfs_fid *)&handlep->ha_fid;
> + if (xfid->fid_len == sizeof(*xfid) - sizeof(xfid->fid_len)) {
> + ino = xfid->fid_ino;
> + igen = xfid->fid_gen;
> + } else {
> + return XFS_ERROR(EINVAL);
> + }
> +
> + /*
> + * Get the XFS inode, building a Linux inode to go with it.
> + */
> + error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0);
> + if (error)
> + return error;
> + if (ip == NULL)
> + return XFS_ERROR(EIO);
> + if (ip->i_d.di_gen != igen) {
> + xfs_iput_new(ip, XFS_ILOCK_SHARED);
> + return XFS_ERROR(ENOENT);
> + }
> +
> + xfs_iunlock(ip, XFS_ILOCK_SHARED);
> +
> + *inode = VFS_I(ip);
> + return 0;
Not really a big fan of duplicating this, at least the second half could
be factored out into a common helper for native and compat handle ops,
dmapi and nfs exporting. But I think this is fine for now, I have some
bigger plans for this area anyway.
So ACK for this patch.
More information about the xfs
mailing list