summaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_ioctl.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c242
1 files changed, 133 insertions, 109 deletions
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index 5917808abbd6..ffec630e7db7 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -47,6 +47,7 @@
#include "xfs_utils.h"
#include "xfs_dfrag.h"
#include "xfs_fsops.h"
+#include "xfs_vnodeops.h"
#include <linux/capability.h>
#include <linux/dcache.h>
@@ -137,7 +138,8 @@ xfs_find_handle(
vp = vn_from_inode(inode);
/* now we can grab the fsid */
- memcpy(&handle.ha_fsid, vp->v_vfsp->vfs_altfsid, sizeof(xfs_fsid_t));
+ memcpy(&handle.ha_fsid, XFS_I(inode)->i_mount->m_fixedfsid,
+ sizeof(xfs_fsid_t));
hsize = sizeof(xfs_fsid_t);
if (cmd != XFS_IOC_PATH_TO_FSHANDLE) {
@@ -349,19 +351,44 @@ xfs_open_by_handle(
return new_fd;
}
+/*
+ * This is a copy from fs/namei.c:vfs_readlink(), except for removing it's
+ * unused first argument.
+ */
+STATIC int
+do_readlink(
+ char __user *buffer,
+ int buflen,
+ const char *link)
+{
+ int len;
+
+ len = PTR_ERR(link);
+ if (IS_ERR(link))
+ goto out;
+
+ len = strlen(link);
+ if (len > (unsigned) buflen)
+ len = buflen;
+ if (copy_to_user(buffer, link, len))
+ len = -EFAULT;
+ out:
+ return len;
+}
+
+
STATIC int
xfs_readlink_by_handle(
xfs_mount_t *mp,
void __user *arg,
struct inode *parinode)
{
- int error;
- struct iovec aiov;
- struct uio auio;
struct inode *inode;
xfs_fsop_handlereq_t hreq;
bhv_vnode_t *vp;
__u32 olen;
+ void *link;
+ int error;
if (!capable(CAP_SYS_ADMIN))
return -XFS_ERROR(EPERM);
@@ -374,29 +401,31 @@ xfs_readlink_by_handle(
/* Restrict this handle operation to symlinks only. */
if (!S_ISLNK(inode->i_mode)) {
- VN_RELE(vp);
- return -XFS_ERROR(EINVAL);
+ error = -XFS_ERROR(EINVAL);
+ goto out_iput;
}
if (copy_from_user(&olen, hreq.ohandlen, sizeof(__u32))) {
- VN_RELE(vp);
- return -XFS_ERROR(EFAULT);
+ error = -XFS_ERROR(EFAULT);
+ goto out_iput;
}
- aiov.iov_len = olen;
- aiov.iov_base = hreq.ohandle;
- auio.uio_iov = (struct kvec *)&aiov;
- auio.uio_iovcnt = 1;
- auio.uio_offset = 0;
- auio.uio_segflg = UIO_USERSPACE;
- auio.uio_resid = olen;
+ link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
+ if (!link)
+ goto out_iput;
- error = bhv_vop_readlink(vp, &auio, IO_INVIS, NULL);
- VN_RELE(vp);
+ error = -xfs_readlink(XFS_I(inode), link);
if (error)
- return -error;
+ goto out_kfree;
+ error = do_readlink(hreq.ohandle, olen, link);
+ if (error)
+ goto out_kfree;
- return (olen - auio.uio_resid);
+ out_kfree:
+ kfree(link);
+ out_iput:
+ iput(inode);
+ return error;
}
STATIC int
@@ -409,7 +438,6 @@ xfs_fssetdm_by_handle(
struct fsdmidata fsd;
xfs_fsop_setdm_handlereq_t dmhreq;
struct inode *inode;
- bhv_desc_t *bdp;
bhv_vnode_t *vp;
if (!capable(CAP_MKNOD))
@@ -431,8 +459,8 @@ xfs_fssetdm_by_handle(
return -XFS_ERROR(EFAULT);
}
- bdp = bhv_base_unlocked(VN_BHV_HEAD(vp));
- error = xfs_set_dmattrs(bdp, fsd.fsd_dmevmask, fsd.fsd_dmstate, NULL);
+ error = xfs_set_dmattrs(xfs_vtoi(vp),
+ fsd.fsd_dmevmask, fsd.fsd_dmstate);
VN_RELE(vp);
if (error)
@@ -470,8 +498,8 @@ xfs_attrlist_by_handle(
goto out_vn_rele;
cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
- error = bhv_vop_attr_list(vp, kbuf, al_hreq.buflen, al_hreq.flags,
- cursor, NULL);
+ error = xfs_attr_list(XFS_I(inode), kbuf, al_hreq.buflen,
+ al_hreq.flags, cursor);
if (error)
goto out_kfree;
@@ -488,7 +516,7 @@ xfs_attrlist_by_handle(
STATIC int
xfs_attrmulti_attr_get(
- bhv_vnode_t *vp,
+ struct inode *inode,
char *name,
char __user *ubuf,
__uint32_t *len,
@@ -503,7 +531,7 @@ xfs_attrmulti_attr_get(
if (!kbuf)
return ENOMEM;
- error = bhv_vop_attr_get(vp, name, kbuf, len, flags, NULL);
+ error = xfs_attr_get(XFS_I(inode), name, kbuf, len, flags, NULL);
if (error)
goto out_kfree;
@@ -517,7 +545,7 @@ xfs_attrmulti_attr_get(
STATIC int
xfs_attrmulti_attr_set(
- bhv_vnode_t *vp,
+ struct inode *inode,
char *name,
const char __user *ubuf,
__uint32_t len,
@@ -526,9 +554,9 @@ xfs_attrmulti_attr_set(
char *kbuf;
int error = EFAULT;
- if (IS_RDONLY(&vp->v_inode))
+ if (IS_RDONLY(inode))
return -EROFS;
- if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode))
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
return EPERM;
if (len > XATTR_SIZE_MAX)
return EINVAL;
@@ -540,7 +568,7 @@ xfs_attrmulti_attr_set(
if (copy_from_user(kbuf, ubuf, len))
goto out_kfree;
- error = bhv_vop_attr_set(vp, name, kbuf, len, flags, NULL);
+ error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags);
out_kfree:
kfree(kbuf);
@@ -549,15 +577,15 @@ xfs_attrmulti_attr_set(
STATIC int
xfs_attrmulti_attr_remove(
- bhv_vnode_t *vp,
+ struct inode *inode,
char *name,
__uint32_t flags)
{
- if (IS_RDONLY(&vp->v_inode))
+ if (IS_RDONLY(inode))
return -EROFS;
- if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode))
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
return EPERM;
- return bhv_vop_attr_remove(vp, name, flags, NULL);
+ return xfs_attr_remove(XFS_I(inode), name, flags);
}
STATIC int
@@ -613,17 +641,17 @@ xfs_attrmulti_by_handle(
switch (ops[i].am_opcode) {
case ATTR_OP_GET:
- ops[i].am_error = xfs_attrmulti_attr_get(vp,
+ ops[i].am_error = xfs_attrmulti_attr_get(inode,
attr_name, ops[i].am_attrvalue,
&ops[i].am_length, ops[i].am_flags);
break;
case ATTR_OP_SET:
- ops[i].am_error = xfs_attrmulti_attr_set(vp,
+ ops[i].am_error = xfs_attrmulti_attr_set(inode,
attr_name, ops[i].am_attrvalue,
ops[i].am_length, ops[i].am_flags);
break;
case ATTR_OP_REMOVE:
- ops[i].am_error = xfs_attrmulti_attr_remove(vp,
+ ops[i].am_error = xfs_attrmulti_attr_remove(inode,
attr_name, ops[i].am_flags);
break;
default:
@@ -649,7 +677,7 @@ xfs_attrmulti_by_handle(
STATIC int
xfs_ioc_space(
- bhv_desc_t *bdp,
+ struct xfs_inode *ip,
struct inode *inode,
struct file *filp,
int flags,
@@ -681,37 +709,37 @@ xfs_ioc_xattr(
void __user *arg);
STATIC int
+xfs_ioc_fsgetxattr(
+ xfs_inode_t *ip,
+ int attr,
+ void __user *arg);
+
+STATIC int
xfs_ioc_getbmap(
- bhv_desc_t *bdp,
+ struct xfs_inode *ip,
int flags,
unsigned int cmd,
void __user *arg);
STATIC int
xfs_ioc_getbmapx(
- bhv_desc_t *bdp,
+ struct xfs_inode *ip,
void __user *arg);
int
xfs_ioctl(
- bhv_desc_t *bdp,
- struct inode *inode,
+ xfs_inode_t *ip,
struct file *filp,
int ioflags,
unsigned int cmd,
void __user *arg)
{
+ struct inode *inode = filp->f_path.dentry->d_inode;
+ bhv_vnode_t *vp = vn_from_inode(inode);
+ xfs_mount_t *mp = ip->i_mount;
int error;
- bhv_vnode_t *vp;
- xfs_inode_t *ip;
- xfs_mount_t *mp;
- vp = vn_from_inode(inode);
-
- vn_trace_entry(vp, "xfs_ioctl", (inst_t *)__return_address);
-
- ip = XFS_BHVTOI(bdp);
- mp = ip->i_mount;
+ vn_trace_entry(XFS_I(inode), "xfs_ioctl", (inst_t *)__return_address);
switch (cmd) {
@@ -731,7 +759,7 @@ xfs_ioctl(
!capable(CAP_SYS_ADMIN))
return -EPERM;
- return xfs_ioc_space(bdp, inode, filp, ioflags, cmd, arg);
+ return xfs_ioc_space(ip, inode, filp, ioflags, cmd, arg);
case XFS_IOC_DIOINFO: {
struct dioattr da;
@@ -761,11 +789,13 @@ xfs_ioctl(
case XFS_IOC_GETVERSION:
return put_user(inode->i_generation, (int __user *)arg);
+ case XFS_IOC_FSGETXATTR:
+ return xfs_ioc_fsgetxattr(ip, 0, arg);
+ case XFS_IOC_FSGETXATTRA:
+ return xfs_ioc_fsgetxattr(ip, 1, arg);
case XFS_IOC_GETXFLAGS:
case XFS_IOC_SETXFLAGS:
- case XFS_IOC_FSGETXATTR:
case XFS_IOC_FSSETXATTR:
- case XFS_IOC_FSGETXATTRA:
return xfs_ioc_xattr(vp, ip, filp, cmd, arg);
case XFS_IOC_FSSETDM: {
@@ -774,17 +804,17 @@ xfs_ioctl(
if (copy_from_user(&dmi, arg, sizeof(dmi)))
return -XFS_ERROR(EFAULT);
- error = xfs_set_dmattrs(bdp, dmi.fsd_dmevmask, dmi.fsd_dmstate,
- NULL);
+ error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask,
+ dmi.fsd_dmstate);
return -error;
}
case XFS_IOC_GETBMAP:
case XFS_IOC_GETBMAPA:
- return xfs_ioc_getbmap(bdp, ioflags, cmd, arg);
+ return xfs_ioc_getbmap(ip, ioflags, cmd, arg);
case XFS_IOC_GETBMAPX:
- return xfs_ioc_getbmapx(bdp, arg);
+ return xfs_ioc_getbmapx(ip, arg);
case XFS_IOC_FD_TO_HANDLE:
case XFS_IOC_PATH_TO_HANDLE:
@@ -944,7 +974,7 @@ xfs_ioctl(
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- error = xfs_errortag_clearall(mp);
+ error = xfs_errortag_clearall(mp, 1);
return -error;
default:
@@ -954,7 +984,7 @@ xfs_ioctl(
STATIC int
xfs_ioc_space(
- bhv_desc_t *bdp,
+ struct xfs_inode *ip,
struct inode *inode,
struct file *filp,
int ioflags,
@@ -982,7 +1012,7 @@ xfs_ioc_space(
if (ioflags & IO_INVIS)
attr_flags |= ATTR_DMI;
- error = xfs_change_file_space(bdp, cmd, &bf, filp->f_pos,
+ error = xfs_change_file_space(ip, cmd, &bf, filp->f_pos,
NULL, attr_flags);
return -error;
}
@@ -1140,6 +1170,42 @@ xfs_di2lxflags(
}
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;
+}
+
+STATIC int
xfs_ioc_xattr(
bhv_vnode_t *vp,
xfs_inode_t *ip,
@@ -1158,27 +1224,6 @@ xfs_ioc_xattr(
return -ENOMEM;
switch (cmd) {
- case XFS_IOC_FSGETXATTR: {
- vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
- XFS_AT_NEXTENTS | XFS_AT_PROJID;
- error = bhv_vop_getattr(vp, vattr, 0, NULL);
- 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;
@@ -1194,34 +1239,13 @@ xfs_ioc_xattr(
vattr->va_extsize = fa.fsx_extsize;
vattr->va_projid = fa.fsx_projid;
- error = bhv_vop_setattr(vp, vattr, attr_flags, NULL);
+ error = xfs_setattr(ip, vattr, attr_flags, NULL);
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;
- error = bhv_vop_getattr(vp, vattr, 0, NULL);
- 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)))
@@ -1250,7 +1274,7 @@ xfs_ioc_xattr(
vattr->va_xflags = xfs_merge_ioc_xflags(flags,
xfs_ip2xflags(ip));
- error = bhv_vop_setattr(vp, vattr, attr_flags, NULL);
+ error = xfs_setattr(ip, vattr, attr_flags, NULL);
if (likely(!error))
__vn_revalidate(vp, vattr); /* update flags */
error = -error;
@@ -1268,7 +1292,7 @@ xfs_ioc_xattr(
STATIC int
xfs_ioc_getbmap(
- bhv_desc_t *bdp,
+ struct xfs_inode *ip,
int ioflags,
unsigned int cmd,
void __user *arg)
@@ -1287,7 +1311,7 @@ xfs_ioc_getbmap(
if (ioflags & IO_INVIS)
iflags |= BMV_IF_NO_DMAPI_READ;
- error = xfs_getbmap(bdp, &bm, (struct getbmap __user *)arg+1, iflags);
+ error = xfs_getbmap(ip, &bm, (struct getbmap __user *)arg+1, iflags);
if (error)
return -error;
@@ -1298,7 +1322,7 @@ xfs_ioc_getbmap(
STATIC int
xfs_ioc_getbmapx(
- bhv_desc_t *bdp,
+ struct xfs_inode *ip,
void __user *arg)
{
struct getbmapx bmx;
@@ -1325,7 +1349,7 @@ xfs_ioc_getbmapx(
iflags |= BMV_IF_EXTENDED;
- error = xfs_getbmap(bdp, &bm, (struct getbmapx __user *)arg+1, iflags);
+ error = xfs_getbmap(ip, &bm, (struct getbmapx __user *)arg+1, iflags);
if (error)
return -error;