1153323Srodrigc/* 2159451Srodrigc * Copyright (c) 2000-2005 Silicon Graphics, Inc. 3159451Srodrigc * All Rights Reserved. 4153323Srodrigc * 5159451Srodrigc * This program is free software; you can redistribute it and/or 6159451Srodrigc * modify it under the terms of the GNU General Public License as 7153323Srodrigc * published by the Free Software Foundation. 8153323Srodrigc * 9159451Srodrigc * This program is distributed in the hope that it would be useful, 10159451Srodrigc * but WITHOUT ANY WARRANTY; without even the implied warranty of 11159451Srodrigc * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12159451Srodrigc * GNU General Public License for more details. 13153323Srodrigc * 14159451Srodrigc * You should have received a copy of the GNU General Public License 15159451Srodrigc * along with this program; if not, write the Free Software Foundation, 16159451Srodrigc * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17153323Srodrigc */ 18153323Srodrigc#include "xfs.h" 19153323Srodrigc#include "xfs_fs.h" 20159451Srodrigc#include "xfs_bit.h" 21159451Srodrigc#include "xfs_log.h" 22153323Srodrigc#include "xfs_inum.h" 23153323Srodrigc#include "xfs_trans.h" 24153323Srodrigc#include "xfs_sb.h" 25159451Srodrigc#include "xfs_ag.h" 26153323Srodrigc#include "xfs_dir.h" 27153323Srodrigc#include "xfs_dir2.h" 28153323Srodrigc#include "xfs_alloc.h" 29153323Srodrigc#include "xfs_dmapi.h" 30153323Srodrigc#include "xfs_mount.h" 31159451Srodrigc#include "xfs_bmap_btree.h" 32153323Srodrigc#include "xfs_alloc_btree.h" 33153323Srodrigc#include "xfs_ialloc_btree.h" 34159451Srodrigc#include "xfs_dir_sf.h" 35153323Srodrigc#include "xfs_attr_sf.h" 36153323Srodrigc#include "xfs_dir2_sf.h" 37153323Srodrigc#include "xfs_dinode.h" 38153323Srodrigc#include "xfs_inode.h" 39159451Srodrigc#include "xfs_btree.h" 40159451Srodrigc#include "xfs_ialloc.h" 41153323Srodrigc#include "xfs_rtalloc.h" 42159451Srodrigc#include "xfs_itable.h" 43153323Srodrigc#include "xfs_error.h" 44153323Srodrigc#include "xfs_rw.h" 45153323Srodrigc#include "xfs_acl.h" 46153323Srodrigc#include "xfs_cap.h" 47153323Srodrigc#include "xfs_mac.h" 48153323Srodrigc#include "xfs_attr.h" 49159451Srodrigc#include "xfs_bmap.h" 50153323Srodrigc#include "xfs_buf_item.h" 51153323Srodrigc#include "xfs_utils.h" 52153323Srodrigc#include "xfs_dfrag.h" 53153323Srodrigc#include "xfs_fsops.h" 54153323Srodrigc 55153323Srodrigc 56159451Srodrigc#include <sys/file.h> 57159451Srodrigc#if 1 58153323Srodrigc/* 59153323Srodrigc * ioctl commands that are used by Linux filesystems 60153323Srodrigc */ 61153323Srodrigc#define XFS_IOC_GETXFLAGS _IOR('f', 1, long) 62153323Srodrigc#define XFS_IOC_SETXFLAGS _IOW('f', 2, long) 63153323Srodrigc#define XFS_IOC_GETVERSION _IOR('v', 1, long) 64153323Srodrigc 65159451Srodrigc#undef copy_to_user 66159451Srodrigcstatic __inline__ int 67159451Srodrigccopy_to_user(void *dst, void *src, int len) { 68159451Srodrigc memcpy(dst,src,len); 69159451Srodrigc return 0; 70159451Srodrigc} 71159451Srodrigc#undef copy_from_user 72159451Srodrigcstatic __inline__ int 73159451Srodrigccopy_from_user(void *dst, void *src, int len) { 74159451Srodrigc memcpy(dst,src,len); 75159451Srodrigc return 0; 76159451Srodrigc} 77153323Srodrigc 78153323Srodrigc/* 79153323Srodrigc * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to 80153323Srodrigc * a file or fs handle. 81153323Srodrigc * 82153323Srodrigc * XFS_IOC_PATH_TO_FSHANDLE 83153323Srodrigc * returns fs handle for a mount point or path within that mount point 84153323Srodrigc * XFS_IOC_FD_TO_HANDLE 85153323Srodrigc * returns full handle for a FD opened in user space 86153323Srodrigc * XFS_IOC_PATH_TO_HANDLE 87153323Srodrigc * returns full handle for a path 88153323Srodrigc */ 89153323SrodrigcSTATIC int 90153323Srodrigcxfs_find_handle( 91153323Srodrigc unsigned int cmd, 92159451Srodrigc void __user *arg) 93153323Srodrigc{ 94159451Srodrigc#ifdef RMC 95153323Srodrigc int hsize; 96159451Srodrigc#endif 97153323Srodrigc xfs_handle_t handle; 98153323Srodrigc xfs_fsop_handlereq_t hreq; 99159451Srodrigc#ifdef RMC 100159451Srodrigc struct inode *inode; 101159451Srodrigc xfs_vnode_t *vp; 102159451Srodrigc#endif 103153323Srodrigc 104159451Srodrigc if (copy_from_user(&hreq, arg, sizeof(hreq))) 105159451Srodrigc return -XFS_ERROR(EFAULT); 106153323Srodrigc 107153323Srodrigc memset((char *)&handle, 0, sizeof(handle)); 108153323Srodrigc 109153323Srodrigc switch (cmd) { 110159451Srodrigc#if 0 111153323Srodrigc case XFS_IOC_PATH_TO_FSHANDLE: 112153323Srodrigc case XFS_IOC_PATH_TO_HANDLE: { 113153323Srodrigc struct nameidata nd; 114153323Srodrigc int error; 115153323Srodrigc 116159451Srodrigc NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, 117153323Srodrigc UIO_USERSPACE, hreq.path, td); 118153323Srodrigc error = namei(&nd); 119153323Srodrigc if (error) 120153323Srodrigc return error; 121153323Srodrigc NDFREE(&nd, NDF_ONLY_PNBUF); 122153323Srodrigc break; 123153323Srodrigc } 124153323Srodrigc 125153323Srodrigc case XFS_IOC_FD_TO_HANDLE: { 126153323Srodrigc struct file *file; 127159451Srodrigc int error; 128153323Srodrigc 129153323Srodrigc error = getvnode(td->td_proc->p_fd, hreq.fd, &file); 130153323Srodrigc if (error) 131153323Srodrigc return error; 132153323Srodrigc 133153323Srodrigc error = vget(vp, LK_EXCLUSIVE, td); 134153323Srodrigc if (error) { 135153323Srodrigc fdrop(file); 136153323Srodrigc return error; 137153323Srodrigc } 138153323Srodrigc fdrop(file); 139153323Srodrigc break; 140153323Srodrigc } 141159451Srodrigc#endif 142153323Srodrigc 143153323Srodrigc default: 144153323Srodrigc ASSERT(0); 145153323Srodrigc return XFS_ERROR(EINVAL); 146153323Srodrigc } 147153323Srodrigc 148159451Srodrigc#ifdef RMC 149153323Srodrigc if (inode->i_sb->s_magic != XFS_SB_MAGIC) { 150153323Srodrigc /* we're not in XFS anymore, Toto */ 151153323Srodrigc iput(inode); 152153323Srodrigc return XFS_ERROR(EINVAL); 153153323Srodrigc } 154153323Srodrigc 155159451Srodrigc switch (inode->i_mode & S_IFMT) { 156159451Srodrigc case S_IFREG: 157159451Srodrigc case S_IFDIR: 158159451Srodrigc case S_IFLNK: 159159451Srodrigc break; 160159451Srodrigc default: 161153323Srodrigc iput(inode); 162153323Srodrigc return XFS_ERROR(EBADF); 163153323Srodrigc } 164159451Srodrigc /* we need the vnode */ 165159451Srodrigc vp = vn_from_inode(inode); 166153323Srodrigc 167153323Srodrigc /* now we can grab the fsid */ 168153323Srodrigc memcpy(&handle.ha_fsid, vp->v_vfsp->vfs_altfsid, sizeof(xfs_fsid_t)); 169153323Srodrigc hsize = sizeof(xfs_fsid_t); 170153323Srodrigc 171153323Srodrigc if (cmd != XFS_IOC_PATH_TO_FSHANDLE) { 172153323Srodrigc xfs_inode_t *ip; 173153323Srodrigc int lock_mode; 174153323Srodrigc 175153323Srodrigc /* need to get access to the xfs_inode to read the generation */ 176159451Srodrigc ip = xfs_vtoi(vp); 177153323Srodrigc ASSERT(ip); 178153323Srodrigc lock_mode = xfs_ilock_map_shared(ip); 179153323Srodrigc 180153323Srodrigc /* fill in fid section of handle from inode */ 181153323Srodrigc handle.ha_fid.xfs_fid_len = sizeof(xfs_fid_t) - 182153323Srodrigc sizeof(handle.ha_fid.xfs_fid_len); 183153323Srodrigc handle.ha_fid.xfs_fid_pad = 0; 184153323Srodrigc handle.ha_fid.xfs_fid_gen = ip->i_d.di_gen; 185153323Srodrigc handle.ha_fid.xfs_fid_ino = ip->i_ino; 186153323Srodrigc 187153323Srodrigc xfs_iunlock_map_shared(ip, lock_mode); 188153323Srodrigc 189153323Srodrigc hsize = XFS_HSIZE(handle); 190153323Srodrigc } 191153323Srodrigc 192153323Srodrigc /* now copy our handle into the user buffer & write out the size */ 193159451Srodrigc if (copy_to_user(hreq.ohandle, &handle, hsize) || 194153323Srodrigc copy_to_user(hreq.ohandlen, &hsize, sizeof(__s32))) { 195153323Srodrigc iput(inode); 196159451Srodrigc return XFS_ERROR(EFAULT); 197153323Srodrigc } 198153323Srodrigc 199153323Srodrigc iput(inode); 200159451Srodrigc#endif 201153323Srodrigc return 0; 202153323Srodrigc} 203153323Srodrigc 204153323Srodrigc 205153323Srodrigc/* 206153323Srodrigc * Convert userspace handle data into vnode (and inode). 207153323Srodrigc * We [ab]use the fact that all the fsop_handlereq ioctl calls 208153323Srodrigc * have a data structure argument whose first component is always 209153323Srodrigc * a xfs_fsop_handlereq_t, so we can cast to and from this type. 210153323Srodrigc * This allows us to optimise the copy_from_user calls and gives 211153323Srodrigc * a handy, shared routine. 212153323Srodrigc * 213153323Srodrigc * If no error, caller must always VN_RELE the returned vp. 214153323Srodrigc */ 215153323SrodrigcSTATIC int 216153323Srodrigcxfs_vget_fsop_handlereq( 217153323Srodrigc xfs_mount_t *mp, 218153323Srodrigc struct inode *parinode, /* parent inode pointer */ 219153323Srodrigc xfs_fsop_handlereq_t *hreq, 220159451Srodrigc xfs_vnode_t **vp, 221153323Srodrigc struct inode **inode) 222153323Srodrigc{ 223159451Srodrigc#if 0 224159451Srodrigc void __user *hanp; 225153323Srodrigc size_t hlen; 226153323Srodrigc xfs_fid_t *xfid; 227153323Srodrigc xfs_handle_t *handlep; 228153323Srodrigc xfs_handle_t handle; 229153323Srodrigc xfs_inode_t *ip; 230153323Srodrigc struct inode *inodep; 231159451Srodrigc xfs_vnode_t *vpp; 232153323Srodrigc xfs_ino_t ino; 233153323Srodrigc __u32 igen; 234153323Srodrigc int error; 235153323Srodrigc 236153323Srodrigc /* 237153323Srodrigc * Only allow handle opens under a directory. 238153323Srodrigc */ 239153323Srodrigc if (!S_ISDIR(parinode->i_mode)) 240153323Srodrigc return XFS_ERROR(ENOTDIR); 241153323Srodrigc 242153323Srodrigc hanp = hreq->ihandle; 243153323Srodrigc hlen = hreq->ihandlen; 244153323Srodrigc handlep = &handle; 245153323Srodrigc 246153323Srodrigc if (hlen < sizeof(handlep->ha_fsid) || hlen > sizeof(*handlep)) 247153323Srodrigc return XFS_ERROR(EINVAL); 248153323Srodrigc if (copy_from_user(handlep, hanp, hlen)) 249153323Srodrigc return XFS_ERROR(EFAULT); 250153323Srodrigc if (hlen < sizeof(*handlep)) 251153323Srodrigc memset(((char *)handlep) + hlen, 0, sizeof(*handlep) - hlen); 252153323Srodrigc if (hlen > sizeof(handlep->ha_fsid)) { 253153323Srodrigc if (handlep->ha_fid.xfs_fid_len != 254153323Srodrigc (hlen - sizeof(handlep->ha_fsid) 255153323Srodrigc - sizeof(handlep->ha_fid.xfs_fid_len)) 256153323Srodrigc || handlep->ha_fid.xfs_fid_pad) 257153323Srodrigc return XFS_ERROR(EINVAL); 258153323Srodrigc } 259153323Srodrigc 260153323Srodrigc /* 261153323Srodrigc * Crack the handle, obtain the inode # & generation # 262153323Srodrigc */ 263153323Srodrigc xfid = (struct xfs_fid *)&handlep->ha_fid; 264153323Srodrigc if (xfid->xfs_fid_len == sizeof(*xfid) - sizeof(xfid->xfs_fid_len)) { 265153323Srodrigc ino = xfid->xfs_fid_ino; 266153323Srodrigc igen = xfid->xfs_fid_gen; 267153323Srodrigc } else { 268153323Srodrigc return XFS_ERROR(EINVAL); 269153323Srodrigc } 270153323Srodrigc 271153323Srodrigc /* 272153323Srodrigc * Get the XFS inode, building a vnode to go with it. 273153323Srodrigc */ 274159451Srodrigc error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0); 275153323Srodrigc if (error) 276153323Srodrigc return error; 277153323Srodrigc if (ip == NULL) 278153323Srodrigc return XFS_ERROR(EIO); 279153323Srodrigc if (ip->i_d.di_mode == 0 || ip->i_d.di_gen != igen) { 280153323Srodrigc xfs_iput_new(ip, XFS_ILOCK_SHARED); 281153323Srodrigc return XFS_ERROR(ENOENT); 282153323Srodrigc } 283153323Srodrigc 284153323Srodrigc vpp = XFS_ITOV(ip); 285159451Srodrigc inodep = vn_to_inode(vpp); 286153323Srodrigc xfs_iunlock(ip, XFS_ILOCK_SHARED); 287153323Srodrigc 288153323Srodrigc *vp = vpp; 289153323Srodrigc *inode = inodep; 290159451Srodrigc#endif 291153323Srodrigc return 0; 292153323Srodrigc} 293153323Srodrigc 294153323SrodrigcSTATIC int 295153323Srodrigcxfs_open_by_handle( 296153323Srodrigc xfs_mount_t *mp, 297159451Srodrigc void __user *arg, 298153323Srodrigc struct file *parfilp, 299153323Srodrigc struct inode *parinode) 300153323Srodrigc{ 301159451Srodrigc int new_fd = 0; 302159451Srodrigc#if 0 303153323Srodrigc int error; 304153323Srodrigc int permflag; 305153323Srodrigc struct file *filp; 306153323Srodrigc struct inode *inode; 307153323Srodrigc struct dentry *dentry; 308159451Srodrigc xfs_vnode_t *vp; 309153323Srodrigc xfs_fsop_handlereq_t hreq; 310153323Srodrigc 311159451Srodrigc if (!capable(CAP_SYS_ADMIN)) 312159451Srodrigc return -XFS_ERROR(EPERM); 313159451Srodrigc if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t))) 314159451Srodrigc return XFS_ERROR(EFAULT); 315159451Srodrigc 316159451Srodrigc error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &vp, &inode); 317153323Srodrigc if (error) 318159451Srodrigc return error; 319153323Srodrigc 320153323Srodrigc /* Restrict xfs_open_by_handle to directories & regular files. */ 321153323Srodrigc if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) { 322153323Srodrigc iput(inode); 323159451Srodrigc return XFS_ERROR(EINVAL); 324153323Srodrigc } 325153323Srodrigc 326153323Srodrigc#if BITS_PER_LONG != 32 327153323Srodrigc hreq.oflags |= O_LARGEFILE; 328153323Srodrigc#endif 329153323Srodrigc /* Put open permission in namei format. */ 330153323Srodrigc permflag = hreq.oflags; 331153323Srodrigc if ((permflag+1) & O_ACCMODE) 332153323Srodrigc permflag++; 333153323Srodrigc if (permflag & O_TRUNC) 334153323Srodrigc permflag |= 2; 335153323Srodrigc 336153323Srodrigc if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) && 337153323Srodrigc (permflag & FMODE_WRITE) && IS_APPEND(inode)) { 338153323Srodrigc iput(inode); 339159451Srodrigc return XFS_ERROR(EPERM); 340153323Srodrigc } 341153323Srodrigc 342153323Srodrigc if ((permflag & FMODE_WRITE) && IS_IMMUTABLE(inode)) { 343153323Srodrigc iput(inode); 344159451Srodrigc return XFS_ERROR(EACCES); 345153323Srodrigc } 346153323Srodrigc 347153323Srodrigc /* Can't write directories. */ 348153323Srodrigc if ( S_ISDIR(inode->i_mode) && (permflag & FMODE_WRITE)) { 349153323Srodrigc iput(inode); 350159451Srodrigc return XFS_ERROR(EISDIR); 351153323Srodrigc } 352153323Srodrigc 353153323Srodrigc if ((new_fd = get_unused_fd()) < 0) { 354153323Srodrigc iput(inode); 355153323Srodrigc return new_fd; 356153323Srodrigc } 357153323Srodrigc 358153323Srodrigc dentry = d_alloc_anon(inode); 359153323Srodrigc if (dentry == NULL) { 360153323Srodrigc iput(inode); 361153323Srodrigc put_unused_fd(new_fd); 362159451Srodrigc return XFS_ERROR(ENOMEM); 363153323Srodrigc } 364153323Srodrigc 365153323Srodrigc /* Ensure umount returns EBUSY on umounts while this file is open. */ 366153323Srodrigc mntget(parfilp->f_vfsmnt); 367153323Srodrigc 368153323Srodrigc /* Create file pointer. */ 369153323Srodrigc filp = dentry_open(dentry, parfilp->f_vfsmnt, hreq.oflags); 370153323Srodrigc if (IS_ERR(filp)) { 371153323Srodrigc put_unused_fd(new_fd); 372153323Srodrigc return -XFS_ERROR(-PTR_ERR(filp)); 373153323Srodrigc } 374153323Srodrigc if (inode->i_mode & S_IFREG) 375159451Srodrigc filp->f_op = &xfs_invis_file_operations; 376153323Srodrigc 377153323Srodrigc fd_install(new_fd, filp); 378159451Srodrigc#endif 379153323Srodrigc return new_fd; 380153323Srodrigc} 381153323Srodrigc 382153323SrodrigcSTATIC int 383153323Srodrigcxfs_readlink_by_handle( 384153323Srodrigc xfs_mount_t *mp, 385159451Srodrigc void __user *arg, 386153323Srodrigc struct file *parfilp, 387153323Srodrigc struct inode *parinode) 388153323Srodrigc{ 389153323Srodrigc int error; 390153323Srodrigc struct iovec aiov; 391153323Srodrigc struct uio auio; 392153323Srodrigc struct inode *inode; 393153323Srodrigc xfs_fsop_handlereq_t hreq; 394170124Skan xfs_vnode_t *vp = NULL; 395153323Srodrigc __u32 olen; 396153323Srodrigc 397159451Srodrigc if (!capable(CAP_SYS_ADMIN)) 398159451Srodrigc return -XFS_ERROR(EPERM); 399159451Srodrigc if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t))) 400159451Srodrigc return -XFS_ERROR(EFAULT); 401159451Srodrigc 402159451Srodrigc error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &vp, &inode); 403153323Srodrigc if (error) 404153323Srodrigc return -error; 405153323Srodrigc 406159451Srodrigc#if 0 407153323Srodrigc /* Restrict this handle operation to symlinks only. */ 408153323Srodrigc if (vp->v_type != VLNK) { 409153323Srodrigc VN_RELE(vp); 410153323Srodrigc return -XFS_ERROR(EINVAL); 411153323Srodrigc } 412159451Srodrigc#endif 413153323Srodrigc 414153323Srodrigc if (copy_from_user(&olen, hreq.ohandlen, sizeof(__u32))) { 415153323Srodrigc VN_RELE(vp); 416153323Srodrigc return -XFS_ERROR(EFAULT); 417153323Srodrigc } 418153323Srodrigc aiov.iov_len = olen; 419153323Srodrigc aiov.iov_base = hreq.ohandle; 420153323Srodrigc 421153323Srodrigc auio.uio_iov = &aiov; 422153323Srodrigc auio.uio_iovcnt = 1; 423153323Srodrigc auio.uio_offset = 0; 424153323Srodrigc auio.uio_segflg = UIO_USERSPACE; 425153323Srodrigc auio.uio_resid = olen; 426153323Srodrigc 427159451Srodrigc XVOP_READLINK(vp, &auio, IO_INVIS, NULL, error); 428153323Srodrigc 429153323Srodrigc VN_RELE(vp); 430153323Srodrigc return (olen - auio.uio_resid); 431153323Srodrigc} 432153323Srodrigc 433153323SrodrigcSTATIC int 434153323Srodrigcxfs_fssetdm_by_handle( 435153323Srodrigc xfs_mount_t *mp, 436159451Srodrigc void __user *arg, 437153323Srodrigc struct file *parfilp, 438153323Srodrigc struct inode *parinode) 439153323Srodrigc{ 440159451Srodrigc int error = 0; 441159451Srodrigc#if 0 442153323Srodrigc struct fsdmidata fsd; 443153323Srodrigc xfs_fsop_setdm_handlereq_t dmhreq; 444153323Srodrigc struct inode *inode; 445153323Srodrigc bhv_desc_t *bdp; 446159451Srodrigc xfs_vnode_t *vp; 447153323Srodrigc 448159451Srodrigc if (!capable(CAP_MKNOD)) 449159451Srodrigc return XFS_ERROR(EPERM); 450159451Srodrigc if (copy_from_user(&dmhreq, arg, sizeof(xfs_fsop_setdm_handlereq_t))) 451159451Srodrigc return XFS_ERROR(EFAULT); 452159451Srodrigc 453159451Srodrigc error = xfs_vget_fsop_handlereq(mp, parinode, &dmhreq.hreq, &vp, &inode); 454153323Srodrigc if (error) 455159451Srodrigc return error; 456153323Srodrigc 457153323Srodrigc if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { 458153323Srodrigc VN_RELE(vp); 459159451Srodrigc return XFS_ERROR(EPERM); 460153323Srodrigc } 461153323Srodrigc 462153323Srodrigc if (copy_from_user(&fsd, dmhreq.data, sizeof(fsd))) { 463153323Srodrigc VN_RELE(vp); 464159451Srodrigc return XFS_ERROR(EFAULT); 465153323Srodrigc } 466153323Srodrigc 467153323Srodrigc bdp = bhv_base_unlocked(VN_BHV_HEAD(vp)); 468153323Srodrigc error = xfs_set_dmattrs(bdp, fsd.fsd_dmevmask, fsd.fsd_dmstate, NULL); 469153323Srodrigc 470153323Srodrigc VN_RELE(vp); 471153323Srodrigc if (error) 472159451Srodrigc return error; 473159451Srodrigc#endif 474159451Srodrigc return error; 475153323Srodrigc} 476153323Srodrigc 477153323SrodrigcSTATIC int 478153323Srodrigcxfs_attrlist_by_handle( 479153323Srodrigc xfs_mount_t *mp, 480159451Srodrigc void __user *arg, 481153323Srodrigc struct file *parfilp, 482153323Srodrigc struct inode *parinode) 483153323Srodrigc{ 484159451Srodrigc int error = 0; 485159451Srodrigc#if 0 486153323Srodrigc attrlist_cursor_kern_t *cursor; 487153323Srodrigc xfs_fsop_attrlist_handlereq_t al_hreq; 488153323Srodrigc struct inode *inode; 489159451Srodrigc xfs_vnode_t *vp; 490159451Srodrigc char *kbuf; 491153323Srodrigc 492159451Srodrigc if (!capable(CAP_SYS_ADMIN)) 493159451Srodrigc return -XFS_ERROR(EPERM); 494159451Srodrigc if (copy_from_user(&al_hreq, arg, sizeof(xfs_fsop_attrlist_handlereq_t))) 495159451Srodrigc return -XFS_ERROR(EFAULT); 496159451Srodrigc if (al_hreq.buflen > XATTR_LIST_MAX) 497159451Srodrigc return -XFS_ERROR(EINVAL); 498159451Srodrigc 499159451Srodrigc error = xfs_vget_fsop_handlereq(mp, parinode, &al_hreq.hreq, 500159451Srodrigc &vp, &inode); 501153323Srodrigc if (error) 502159451Srodrigc goto out; 503153323Srodrigc 504159451Srodrigc kbuf = kmalloc(al_hreq.buflen, GFP_KERNEL); 505159451Srodrigc if (!kbuf) 506159451Srodrigc goto out_vn_rele; 507159451Srodrigc 508153323Srodrigc cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; 509159451Srodrigc XVOP_ATTR_LIST(vp, kbuf, al_hreq.buflen, al_hreq.flags, 510153323Srodrigc cursor, NULL, error); 511159451Srodrigc if (error) 512159451Srodrigc goto out_kfree; 513159451Srodrigc 514159451Srodrigc if (copy_to_user(al_hreq.buffer, kbuf, al_hreq.buflen)) 515159451Srodrigc error = -EFAULT; 516159451Srodrigc 517159451Srodrigc out_kfree: 518159451Srodrigc kfree(kbuf); 519159451Srodrigc out_vn_rele: 520153323Srodrigc VN_RELE(vp); 521159451Srodrigc out: 522159451Srodrigc#endif 523159451Srodrigc return error; 524159451Srodrigc} 525159451Srodrigc 526159451Srodrigc#if 0 527159451SrodrigcSTATIC int 528159451Srodrigcxfs_attrmulti_attr_get( 529159451Srodrigc xfs_vnode_t *vp, 530159451Srodrigc char *name, 531159451Srodrigc char __user *ubuf, 532159451Srodrigc __uint32_t *len, 533159451Srodrigc __uint32_t flags) 534159451Srodrigc{ 535159451Srodrigc int error = EFAULT; 536159451Srodrigc char *kbuf; 537159451Srodrigc 538159451Srodrigc if (*len > XATTR_SIZE_MAX) 539159451Srodrigc return EINVAL; 540159451Srodrigc kbuf = kmalloc(*len, GFP_KERNEL); 541159451Srodrigc if (!kbuf) 542159451Srodrigc return ENOMEM; 543159451Srodrigc 544159451Srodrigc XVOP_ATTR_GET(vp, name, kbuf, len, flags, NULL, error); 545153323Srodrigc if (error) 546159451Srodrigc goto out_kfree; 547159451Srodrigc 548159451Srodrigc if (copy_to_user(ubuf, kbuf, *len)) 549159451Srodrigc error = EFAULT; 550159451Srodrigc 551159451Srodrigc out_kfree: 552159451Srodrigc kfree(kbuf); 553159451Srodrigc return error; 554153323Srodrigc} 555159451Srodrigc#endif 556153323Srodrigc 557159451Srodrigc#if 0 558153323SrodrigcSTATIC int 559159451Srodrigcxfs_attrmulti_attr_set( 560159451Srodrigc xfs_vnode_t *vp, 561159451Srodrigc char *name, 562159451Srodrigc const char __user *ubuf, 563159451Srodrigc __uint32_t len, 564159451Srodrigc __uint32_t flags) 565159451Srodrigc{ 566159451Srodrigc int error = EFAULT; 567159451Srodrigc char *kbuf; 568159451Srodrigc 569159451Srodrigc if (IS_RDONLY(&vp->v_inode)) 570159451Srodrigc return -EROFS; 571159451Srodrigc if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode)) 572159451Srodrigc return EPERM; 573159451Srodrigc if (len > XATTR_SIZE_MAX) 574159451Srodrigc return EINVAL; 575159451Srodrigc 576159451Srodrigc kbuf = kmalloc(len, GFP_KERNEL); 577159451Srodrigc if (!kbuf) 578159451Srodrigc return ENOMEM; 579159451Srodrigc 580159451Srodrigc if (copy_from_user(kbuf, ubuf, len)) 581159451Srodrigc goto out_kfree; 582159451Srodrigc 583159451Srodrigc XVOP_ATTR_SET(vp, name, kbuf, len, flags, NULL, error); 584159451Srodrigc 585159451Srodrigc out_kfree: 586159451Srodrigc kfree(kbuf); 587159451Srodrigc return error; 588159451Srodrigc} 589159451Srodrigc#endif 590159451Srodrigc 591159451Srodrigc#if 0 592159451SrodrigcSTATIC int 593159451Srodrigcxfs_attrmulti_attr_remove( 594159451Srodrigc xfs_vnode_t *vp, 595159451Srodrigc char *name, 596159451Srodrigc __uint32_t flags) 597159451Srodrigc{ 598159451Srodrigc int error; 599159451Srodrigc 600159451Srodrigc if (IS_RDONLY(&vp->v_inode)) 601159451Srodrigc return -EROFS; 602159451Srodrigc if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode)) 603159451Srodrigc return EPERM; 604159451Srodrigc 605159451Srodrigc XVOP_ATTR_REMOVE(vp, name, flags, NULL, error); 606159451Srodrigc return error; 607159451Srodrigc} 608159451Srodrigc#endif 609159451Srodrigc 610159451SrodrigcSTATIC int 611153323Srodrigcxfs_attrmulti_by_handle( 612153323Srodrigc xfs_mount_t *mp, 613159451Srodrigc void __user *arg, 614153323Srodrigc struct file *parfilp, 615153323Srodrigc struct inode *parinode) 616153323Srodrigc{ 617159451Srodrigc int error = 0; 618159451Srodrigc#if 0 619153323Srodrigc xfs_attr_multiop_t *ops; 620153323Srodrigc xfs_fsop_attrmulti_handlereq_t am_hreq; 621153323Srodrigc struct inode *inode; 622159451Srodrigc xfs_vnode_t *vp; 623159451Srodrigc unsigned int i, size; 624159451Srodrigc char *attr_name; 625153323Srodrigc 626159451Srodrigc if (!capable(CAP_SYS_ADMIN)) 627159451Srodrigc return -XFS_ERROR(EPERM); 628159451Srodrigc if (copy_from_user(&am_hreq, arg, sizeof(xfs_fsop_attrmulti_handlereq_t))) 629159451Srodrigc return -XFS_ERROR(EFAULT); 630159451Srodrigc 631159451Srodrigc error = xfs_vget_fsop_handlereq(mp, parinode, &am_hreq.hreq, &vp, &inode); 632153323Srodrigc if (error) 633159451Srodrigc goto out; 634153323Srodrigc 635159451Srodrigc error = E2BIG; 636153323Srodrigc size = am_hreq.opcount * sizeof(attr_multiop_t); 637159451Srodrigc if (!size || size > 16 * PAGE_SIZE) 638159451Srodrigc goto out_vn_rele; 639153323Srodrigc 640159451Srodrigc error = ENOMEM; 641159451Srodrigc ops = kmalloc(size, GFP_KERNEL); 642159451Srodrigc if (!ops) 643159451Srodrigc goto out_vn_rele; 644153323Srodrigc 645159451Srodrigc error = EFAULT; 646159451Srodrigc if (copy_from_user(ops, am_hreq.ops, size)) 647159451Srodrigc goto out_kfree_ops; 648159451Srodrigc 649159451Srodrigc attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL); 650159451Srodrigc if (!attr_name) 651159451Srodrigc goto out_kfree_ops; 652159451Srodrigc 653159451Srodrigc 654159451Srodrigc error = 0; 655153323Srodrigc for (i = 0; i < am_hreq.opcount; i++) { 656159451Srodrigc ops[i].am_error = strncpy_from_user(attr_name, 657159451Srodrigc ops[i].am_attrname, MAXNAMELEN); 658159451Srodrigc if (ops[i].am_error == 0 || ops[i].am_error == MAXNAMELEN) 659159451Srodrigc error = -ERANGE; 660159451Srodrigc if (ops[i].am_error < 0) 661159451Srodrigc break; 662159451Srodrigc 663159451Srodrigc switch (ops[i].am_opcode) { 664153323Srodrigc case ATTR_OP_GET: 665159451Srodrigc ops[i].am_error = xfs_attrmulti_attr_get(vp, 666159451Srodrigc attr_name, ops[i].am_attrvalue, 667159451Srodrigc &ops[i].am_length, ops[i].am_flags); 668153323Srodrigc break; 669153323Srodrigc case ATTR_OP_SET: 670159451Srodrigc ops[i].am_error = xfs_attrmulti_attr_set(vp, 671159451Srodrigc attr_name, ops[i].am_attrvalue, 672159451Srodrigc ops[i].am_length, ops[i].am_flags); 673153323Srodrigc break; 674153323Srodrigc case ATTR_OP_REMOVE: 675159451Srodrigc ops[i].am_error = xfs_attrmulti_attr_remove(vp, 676159451Srodrigc attr_name, ops[i].am_flags); 677153323Srodrigc break; 678153323Srodrigc default: 679153323Srodrigc ops[i].am_error = EINVAL; 680153323Srodrigc } 681153323Srodrigc } 682153323Srodrigc 683153323Srodrigc if (copy_to_user(am_hreq.ops, ops, size)) 684159451Srodrigc error = XFS_ERROR(EFAULT); 685153323Srodrigc 686159451Srodrigc kfree(attr_name); 687159451Srodrigc out_kfree_ops: 688153323Srodrigc kfree(ops); 689159451Srodrigc out_vn_rele: 690153323Srodrigc VN_RELE(vp); 691159451Srodrigc out: 692159451Srodrigc#endif 693153323Srodrigc return error; 694153323Srodrigc} 695153323Srodrigc 696153323Srodrigc/* prototypes for a few of the stack-hungry cases that have 697153323Srodrigc * their own functions. Functions are defined after their use 698153323Srodrigc * so gcc doesn't get fancy and inline them with -03 */ 699153323Srodrigc 700153323SrodrigcSTATIC int 701153323Srodrigcxfs_ioc_space( 702153323Srodrigc bhv_desc_t *bdp, 703159451Srodrigc xfs_vnode_t *vp, 704153323Srodrigc struct file *filp, 705153323Srodrigc int flags, 706194944Srdivacky u_long cmd, 707159451Srodrigc void __user *arg); 708153323Srodrigc 709153323SrodrigcSTATIC int 710153323Srodrigcxfs_ioc_bulkstat( 711153323Srodrigc xfs_mount_t *mp, 712153323Srodrigc unsigned int cmd, 713159451Srodrigc void __user *arg); 714153323Srodrigc 715153323SrodrigcSTATIC int 716153323Srodrigcxfs_ioc_fsgeometry_v1( 717153323Srodrigc xfs_mount_t *mp, 718159451Srodrigc void __user *arg); 719153323Srodrigc 720153323SrodrigcSTATIC int 721153323Srodrigcxfs_ioc_fsgeometry( 722153323Srodrigc xfs_mount_t *mp, 723159451Srodrigc void __user *arg); 724153323Srodrigc 725153323SrodrigcSTATIC int 726153323Srodrigcxfs_ioc_xattr( 727159451Srodrigc xfs_vnode_t *vp, 728153323Srodrigc xfs_inode_t *ip, 729153323Srodrigc struct file *filp, 730153323Srodrigc unsigned int cmd, 731159451Srodrigc void __user *arg); 732153323Srodrigc 733153323SrodrigcSTATIC int 734153323Srodrigcxfs_ioc_getbmap( 735153323Srodrigc bhv_desc_t *bdp, 736153323Srodrigc struct file *filp, 737153323Srodrigc int flags, 738153323Srodrigc unsigned int cmd, 739159451Srodrigc void __user *arg); 740153323Srodrigc 741153323SrodrigcSTATIC int 742153323Srodrigcxfs_ioc_getbmapx( 743153323Srodrigc bhv_desc_t *bdp, 744159451Srodrigc void __user *arg); 745153323Srodrigc 746153323Srodrigcint 747153323Srodrigcxfs_ioctl( 748153323Srodrigc bhv_desc_t *bdp, 749153323Srodrigc struct inode *inode, 750153323Srodrigc struct file *filp, 751153323Srodrigc int ioflags, 752194944Srdivacky u_long cmd, 753159451Srodrigc void *arg) 754153323Srodrigc{ 755153323Srodrigc int error; 756159451Srodrigc xfs_vnode_t *vp; 757153323Srodrigc xfs_inode_t *ip; 758153323Srodrigc xfs_mount_t *mp; 759153323Srodrigc 760159451Srodrigc// vp = vn_from_inode(inode); 761159451Srodrigc vp = BHV_TO_VNODE(bdp); 762153323Srodrigc 763194974Srdivacky printf("xfs_ioctl: bdp %p flags 0x%x cmd 0x%lx basecmd 0x%lx arg %p\n", 764159451Srodrigc bdp, ioflags, cmd, 765159451Srodrigc IOCBASECMD(cmd), 766159451Srodrigc arg); 767159451Srodrigc 768159451Srodrigc 769153323Srodrigc vn_trace_entry(vp, "xfs_ioctl", (inst_t *)__return_address); 770153323Srodrigc 771153323Srodrigc ip = XFS_BHVTOI(bdp); 772153323Srodrigc mp = ip->i_mount; 773153323Srodrigc 774159451Srodrigc 775159451Srodrigc#if 0 776159451Srodrigc if ((cmd << 24 >> 24) == (XFS_IOC_GETBMAPX << 24 >> 24)) { 777159451Srodrigc cmd = XFS_IOC_GETBMAPX; 778159451Srodrigc } 779159451Srodrigc#endif 780159451Srodrigc 781159451Srodrigc 782159451Srodrigc 783153323Srodrigc switch (cmd) { 784153323Srodrigc 785153323Srodrigc case XFS_IOC_ALLOCSP: 786153323Srodrigc case XFS_IOC_FREESP: 787153323Srodrigc case XFS_IOC_RESVSP: 788153323Srodrigc case XFS_IOC_UNRESVSP: 789153323Srodrigc case XFS_IOC_ALLOCSP64: 790153323Srodrigc case XFS_IOC_FREESP64: 791153323Srodrigc case XFS_IOC_RESVSP64: 792153323Srodrigc case XFS_IOC_UNRESVSP64: 793153323Srodrigc /* 794153323Srodrigc * Only allow the sys admin to reserve space unless 795153323Srodrigc * unwritten extents are enabled. 796153323Srodrigc */ 797153323Srodrigc if (!XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb) && 798153323Srodrigc !capable(CAP_SYS_ADMIN)) 799153323Srodrigc return -EPERM; 800153323Srodrigc 801153323Srodrigc return xfs_ioc_space(bdp, vp, filp, ioflags, cmd, arg); 802153323Srodrigc 803153323Srodrigc case XFS_IOC_DIOINFO: { 804153323Srodrigc struct dioattr da; 805159451Srodrigc xfs_buftarg_t *target = 806159451Srodrigc (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ? 807159451Srodrigc mp->m_rtdev_targp : mp->m_ddev_targp; 808153323Srodrigc 809159451Srodrigc da.d_mem = da.d_miniosz = 1 << target->bt_sshift; 810159451Srodrigc da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1); 811153323Srodrigc 812159451Srodrigc if (copy_to_user(arg, &da, sizeof(da))) 813159451Srodrigc return XFS_ERROR(EFAULT); 814153323Srodrigc return 0; 815153323Srodrigc } 816153323Srodrigc 817153323Srodrigc case XFS_IOC_FSBULKSTAT_SINGLE: 818153323Srodrigc case XFS_IOC_FSBULKSTAT: 819153323Srodrigc case XFS_IOC_FSINUMBERS: 820153323Srodrigc return xfs_ioc_bulkstat(mp, cmd, arg); 821153323Srodrigc 822153323Srodrigc case XFS_IOC_FSGEOMETRY_V1: 823153323Srodrigc return xfs_ioc_fsgeometry_v1(mp, arg); 824153323Srodrigc 825153323Srodrigc case XFS_IOC_FSGEOMETRY: 826153323Srodrigc return xfs_ioc_fsgeometry(mp, arg); 827153323Srodrigc 828153323Srodrigc case XFS_IOC_GETVERSION: 829153323Srodrigc case XFS_IOC_GETXFLAGS: 830153323Srodrigc case XFS_IOC_SETXFLAGS: 831153323Srodrigc case XFS_IOC_FSGETXATTR: 832153323Srodrigc case XFS_IOC_FSSETXATTR: 833153323Srodrigc case XFS_IOC_FSGETXATTRA: 834153323Srodrigc return xfs_ioc_xattr(vp, ip, filp, cmd, arg); 835153323Srodrigc 836153323Srodrigc case XFS_IOC_FSSETDM: { 837153323Srodrigc struct fsdmidata dmi; 838153323Srodrigc 839159451Srodrigc if (copy_from_user(&dmi, arg, sizeof(dmi))) 840159451Srodrigc return XFS_ERROR(EFAULT); 841153323Srodrigc 842153323Srodrigc error = xfs_set_dmattrs(bdp, dmi.fsd_dmevmask, dmi.fsd_dmstate, 843153323Srodrigc NULL); 844159451Srodrigc return error; 845153323Srodrigc } 846153323Srodrigc 847153323Srodrigc case XFS_IOC_GETBMAP: 848153323Srodrigc case XFS_IOC_GETBMAPA: 849153323Srodrigc return xfs_ioc_getbmap(bdp, filp, ioflags, cmd, arg); 850153323Srodrigc 851153323Srodrigc case XFS_IOC_GETBMAPX: 852153323Srodrigc return xfs_ioc_getbmapx(bdp, arg); 853153323Srodrigc 854153323Srodrigc case XFS_IOC_FD_TO_HANDLE: 855153323Srodrigc case XFS_IOC_PATH_TO_HANDLE: 856153323Srodrigc case XFS_IOC_PATH_TO_FSHANDLE: 857153323Srodrigc return xfs_find_handle(cmd, arg); 858153323Srodrigc 859153323Srodrigc case XFS_IOC_OPEN_BY_HANDLE: 860153323Srodrigc return xfs_open_by_handle(mp, arg, filp, inode); 861153323Srodrigc 862153323Srodrigc case XFS_IOC_FSSETDM_BY_HANDLE: 863153323Srodrigc return xfs_fssetdm_by_handle(mp, arg, filp, inode); 864153323Srodrigc 865153323Srodrigc case XFS_IOC_READLINK_BY_HANDLE: 866153323Srodrigc return xfs_readlink_by_handle(mp, arg, filp, inode); 867153323Srodrigc 868153323Srodrigc case XFS_IOC_ATTRLIST_BY_HANDLE: 869153323Srodrigc return xfs_attrlist_by_handle(mp, arg, filp, inode); 870153323Srodrigc 871153323Srodrigc case XFS_IOC_ATTRMULTI_BY_HANDLE: 872153323Srodrigc return xfs_attrmulti_by_handle(mp, arg, filp, inode); 873153323Srodrigc 874153323Srodrigc case XFS_IOC_SWAPEXT: { 875159451Srodrigc error = xfs_swapext((struct xfs_swapext __user *)arg); 876159451Srodrigc return error; 877153323Srodrigc } 878153323Srodrigc 879153323Srodrigc case XFS_IOC_FSCOUNTS: { 880153323Srodrigc xfs_fsop_counts_t out; 881153323Srodrigc 882153323Srodrigc error = xfs_fs_counts(mp, &out); 883153323Srodrigc if (error) 884159451Srodrigc return error; 885153323Srodrigc 886159451Srodrigc if (copy_to_user(arg, &out, sizeof(out))) 887159451Srodrigc return XFS_ERROR(EFAULT); 888153323Srodrigc return 0; 889153323Srodrigc } 890153323Srodrigc 891153323Srodrigc case XFS_IOC_SET_RESBLKS: { 892153323Srodrigc xfs_fsop_resblks_t inout; 893153323Srodrigc __uint64_t in; 894153323Srodrigc 895153323Srodrigc if (!capable(CAP_SYS_ADMIN)) 896159451Srodrigc return EPERM; 897153323Srodrigc 898159451Srodrigc if (copy_from_user(&inout, arg, sizeof(inout))) 899159451Srodrigc return XFS_ERROR(EFAULT); 900153323Srodrigc 901153323Srodrigc /* input parameter is passed in resblks field of structure */ 902153323Srodrigc in = inout.resblks; 903153323Srodrigc error = xfs_reserve_blocks(mp, &in, &inout); 904153323Srodrigc if (error) 905159451Srodrigc return error; 906153323Srodrigc 907159451Srodrigc if (copy_to_user(arg, &inout, sizeof(inout))) 908159451Srodrigc return XFS_ERROR(EFAULT); 909153323Srodrigc return 0; 910153323Srodrigc } 911153323Srodrigc 912153323Srodrigc case XFS_IOC_GET_RESBLKS: { 913153323Srodrigc xfs_fsop_resblks_t out; 914153323Srodrigc 915153323Srodrigc if (!capable(CAP_SYS_ADMIN)) 916159451Srodrigc return EPERM; 917153323Srodrigc 918153323Srodrigc error = xfs_reserve_blocks(mp, NULL, &out); 919153323Srodrigc if (error) 920159451Srodrigc return error; 921153323Srodrigc 922159451Srodrigc if (copy_to_user(arg, &out, sizeof(out))) 923159451Srodrigc return XFS_ERROR(EFAULT); 924153323Srodrigc 925153323Srodrigc return 0; 926153323Srodrigc } 927153323Srodrigc 928153323Srodrigc case XFS_IOC_FSGROWFSDATA: { 929153323Srodrigc xfs_growfs_data_t in; 930153323Srodrigc 931153323Srodrigc if (!capable(CAP_SYS_ADMIN)) 932159451Srodrigc return EPERM; 933153323Srodrigc 934159451Srodrigc if (copy_from_user(&in, arg, sizeof(in))) 935159451Srodrigc return XFS_ERROR(EFAULT); 936153323Srodrigc 937153323Srodrigc error = xfs_growfs_data(mp, &in); 938159451Srodrigc return error; 939153323Srodrigc } 940153323Srodrigc 941153323Srodrigc case XFS_IOC_FSGROWFSLOG: { 942153323Srodrigc xfs_growfs_log_t in; 943153323Srodrigc 944153323Srodrigc if (!capable(CAP_SYS_ADMIN)) 945159451Srodrigc return EPERM; 946153323Srodrigc 947159451Srodrigc if (copy_from_user(&in, arg, sizeof(in))) 948159451Srodrigc return XFS_ERROR(EFAULT); 949153323Srodrigc 950153323Srodrigc error = xfs_growfs_log(mp, &in); 951159451Srodrigc return error; 952153323Srodrigc } 953153323Srodrigc 954153323Srodrigc case XFS_IOC_FSGROWFSRT: { 955153323Srodrigc xfs_growfs_rt_t in; 956153323Srodrigc 957153323Srodrigc if (!capable(CAP_SYS_ADMIN)) 958159451Srodrigc return EPERM; 959153323Srodrigc 960159451Srodrigc if (copy_from_user(&in, arg, sizeof(in))) 961159451Srodrigc return XFS_ERROR(EFAULT); 962153323Srodrigc 963153323Srodrigc error = xfs_growfs_rt(mp, &in); 964159451Srodrigc return error; 965153323Srodrigc } 966159451Srodrigc#if 0 967153323Srodrigc case XFS_IOC_FREEZE: 968153323Srodrigc if (!capable(CAP_SYS_ADMIN)) 969153323Srodrigc return -EPERM; 970153323Srodrigc xfs_fs_freeze(mp); 971153323Srodrigc return 0; 972153323Srodrigc 973153323Srodrigc case XFS_IOC_THAW: 974153323Srodrigc if (!capable(CAP_SYS_ADMIN)) 975153323Srodrigc return -EPERM; 976153323Srodrigc xfs_fs_thaw(mp); 977153323Srodrigc return 0; 978159451Srodrigc#endif 979153323Srodrigc 980153323Srodrigc case XFS_IOC_GOINGDOWN: { 981153323Srodrigc __uint32_t in; 982153323Srodrigc 983153323Srodrigc if (!capable(CAP_SYS_ADMIN)) 984159451Srodrigc return EPERM; 985153323Srodrigc 986159451Srodrigc if (copy_from_user(&in, arg, sizeof(__uint32_t))) 987159451Srodrigc return XFS_ERROR(EFAULT); 988153323Srodrigc 989153323Srodrigc error = xfs_fs_goingdown(mp, in); 990159451Srodrigc return error; 991153323Srodrigc } 992153323Srodrigc 993153323Srodrigc case XFS_IOC_ERROR_INJECTION: { 994153323Srodrigc xfs_error_injection_t in; 995153323Srodrigc 996159451Srodrigc if (!capable(CAP_SYS_ADMIN)) 997159451Srodrigc return EPERM; 998153323Srodrigc 999159451Srodrigc if (copy_from_user(&in, arg, sizeof(in))) 1000159451Srodrigc return XFS_ERROR(EFAULT); 1001159451Srodrigc 1002153323Srodrigc error = xfs_errortag_add(in.errtag, mp); 1003159451Srodrigc return error; 1004153323Srodrigc } 1005153323Srodrigc 1006153323Srodrigc case XFS_IOC_ERROR_CLEARALL: 1007159451Srodrigc if (!capable(CAP_SYS_ADMIN)) 1008159451Srodrigc return EPERM; 1009159451Srodrigc 1010153323Srodrigc error = xfs_errortag_clearall(mp); 1011159451Srodrigc return error; 1012153323Srodrigc 1013153323Srodrigc default: 1014159451Srodrigc return ENOTTY; 1015153323Srodrigc } 1016153323Srodrigc} 1017153323Srodrigc 1018153323SrodrigcSTATIC int 1019153323Srodrigcxfs_ioc_space( 1020153323Srodrigc bhv_desc_t *bdp, 1021159451Srodrigc xfs_vnode_t *vp, 1022153323Srodrigc struct file *filp, 1023153323Srodrigc int ioflags, 1024194944Srdivacky u_long cmd, 1025159451Srodrigc void __user *arg) 1026153323Srodrigc{ 1027153323Srodrigc xfs_flock64_t bf; 1028153323Srodrigc int attr_flags = 0; 1029153323Srodrigc int error; 1030153323Srodrigc 1031159451Srodrigc#if 0 1032153323Srodrigc if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND)) 1033153323Srodrigc return -XFS_ERROR(EPERM); 1034153323Srodrigc 1035159451Srodrigc if (!(filp->f_mode & FMODE_WRITE)) 1036153323Srodrigc return -XFS_ERROR(EBADF); 1037159451Srodrigc#endif 1038153323Srodrigc 1039159451Srodrigc if (!VN_ISREG(vp)) 1040153323Srodrigc return -XFS_ERROR(EINVAL); 1041153323Srodrigc 1042159451Srodrigc if (copy_from_user(&bf, arg, sizeof(bf))) 1043153323Srodrigc return -XFS_ERROR(EFAULT); 1044153323Srodrigc 1045159451Srodrigc#if 0 1046153323Srodrigc if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) 1047153323Srodrigc attr_flags |= ATTR_NONBLOCK; 1048159451Srodrigc#endif 1049153323Srodrigc if (ioflags & IO_INVIS) 1050153323Srodrigc attr_flags |= ATTR_DMI; 1051153323Srodrigc 1052159451Srodrigc error = xfs_change_file_space(bdp, cmd, 1053159451Srodrigc &bf, filp->f_offset, 1054159451Srodrigc NULL, attr_flags); 1055153323Srodrigc return -error; 1056153323Srodrigc} 1057153323Srodrigc 1058153323SrodrigcSTATIC int 1059153323Srodrigcxfs_ioc_bulkstat( 1060153323Srodrigc xfs_mount_t *mp, 1061153323Srodrigc unsigned int cmd, 1062159451Srodrigc void __user *arg) 1063153323Srodrigc{ 1064153323Srodrigc xfs_fsop_bulkreq_t bulkreq; 1065153323Srodrigc int count; /* # of records returned */ 1066153323Srodrigc xfs_ino_t inlast; /* last inode number */ 1067153323Srodrigc int done; 1068153323Srodrigc int error; 1069153323Srodrigc 1070153323Srodrigc /* done = 1 if there are more stats to get and if bulkstat */ 1071153323Srodrigc /* should be called again (unused here, but used in dmapi) */ 1072153323Srodrigc 1073159451Srodrigc#if 0 1074153323Srodrigc if (!capable(CAP_SYS_ADMIN)) 1075153323Srodrigc return -EPERM; 1076159451Srodrigc#endif 1077153323Srodrigc 1078153323Srodrigc if (XFS_FORCED_SHUTDOWN(mp)) 1079153323Srodrigc return -XFS_ERROR(EIO); 1080153323Srodrigc 1081159451Srodrigc if (copy_from_user(&bulkreq, arg, sizeof(xfs_fsop_bulkreq_t))) 1082153323Srodrigc return -XFS_ERROR(EFAULT); 1083153323Srodrigc 1084159451Srodrigc if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64))) 1085153323Srodrigc return -XFS_ERROR(EFAULT); 1086153323Srodrigc 1087153323Srodrigc if ((count = bulkreq.icount) <= 0) 1088153323Srodrigc return -XFS_ERROR(EINVAL); 1089153323Srodrigc 1090153323Srodrigc if (cmd == XFS_IOC_FSINUMBERS) 1091159451Srodrigc error = xfs_inumbers(mp, &inlast, &count, 1092153323Srodrigc bulkreq.ubuffer); 1093153323Srodrigc else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) 1094153323Srodrigc error = xfs_bulkstat_single(mp, &inlast, 1095153323Srodrigc bulkreq.ubuffer, &done); 1096153323Srodrigc else { /* XFS_IOC_FSBULKSTAT */ 1097153323Srodrigc if (count == 1 && inlast != 0) { 1098153323Srodrigc inlast++; 1099153323Srodrigc error = xfs_bulkstat_single(mp, &inlast, 1100153323Srodrigc bulkreq.ubuffer, &done); 1101153323Srodrigc } else { 1102159451Srodrigc error = xfs_bulkstat(mp, &inlast, &count, 1103153323Srodrigc (bulkstat_one_pf)xfs_bulkstat_one, NULL, 1104153323Srodrigc sizeof(xfs_bstat_t), bulkreq.ubuffer, 1105153323Srodrigc BULKSTAT_FG_QUICK, &done); 1106153323Srodrigc } 1107153323Srodrigc } 1108153323Srodrigc 1109153323Srodrigc if (error) 1110153323Srodrigc return -error; 1111153323Srodrigc 1112153323Srodrigc if (bulkreq.ocount != NULL) { 1113159451Srodrigc if (copy_to_user(bulkreq.lastip, &inlast, 1114153323Srodrigc sizeof(xfs_ino_t))) 1115153323Srodrigc return -XFS_ERROR(EFAULT); 1116153323Srodrigc 1117159451Srodrigc if (copy_to_user(bulkreq.ocount, &count, sizeof(count))) 1118153323Srodrigc return -XFS_ERROR(EFAULT); 1119153323Srodrigc } 1120153323Srodrigc 1121153323Srodrigc return 0; 1122153323Srodrigc} 1123153323Srodrigc 1124153323SrodrigcSTATIC int 1125153323Srodrigcxfs_ioc_fsgeometry_v1( 1126153323Srodrigc xfs_mount_t *mp, 1127159451Srodrigc void __user *arg) 1128153323Srodrigc{ 1129153323Srodrigc xfs_fsop_geom_v1_t fsgeo; 1130153323Srodrigc int error; 1131153323Srodrigc 1132153323Srodrigc error = xfs_fs_geometry(mp, (xfs_fsop_geom_t *)&fsgeo, 3); 1133153323Srodrigc if (error) 1134153323Srodrigc return -error; 1135153323Srodrigc 1136159451Srodrigc if (copy_to_user(arg, &fsgeo, sizeof(fsgeo))) 1137153323Srodrigc return -XFS_ERROR(EFAULT); 1138153323Srodrigc return 0; 1139153323Srodrigc} 1140153323Srodrigc 1141153323SrodrigcSTATIC int 1142153323Srodrigcxfs_ioc_fsgeometry( 1143153323Srodrigc xfs_mount_t *mp, 1144159451Srodrigc void __user *arg) 1145153323Srodrigc{ 1146153323Srodrigc xfs_fsop_geom_t fsgeo; 1147153323Srodrigc int error; 1148153323Srodrigc 1149153323Srodrigc error = xfs_fs_geometry(mp, &fsgeo, 4); 1150153323Srodrigc if (error) 1151159451Srodrigc goto error; 1152153323Srodrigc 1153159451Srodrigc printf ("xfs_ioc_fsgeometry: error? %d arg %p\n",error,arg); 1154159451Srodrigc 1155159451Srodrigc#if 0 1156159451Srodrigc if (copy_to_user(arg, &fsgeo, sizeof(fsgeo))) 1157159451Srodrigc return XFS_ERROR(EFAULT); 1158159451Srodrigc#endif 1159159451Srodrigc memcpy(arg, &fsgeo, sizeof(fsgeo)); 1160159451Srodrigc 1161159451Srodrigc printf ("xfs_ioc_fsgeometry: error? %d arg %p\n",error,arg); 1162159451Srodrigcerror: 1163159451Srodrigc return error; 1164153323Srodrigc} 1165153323Srodrigc 1166153323Srodrigc/* 1167153323Srodrigc * Linux extended inode flags interface. 1168153323Srodrigc */ 1169153323Srodrigc#define LINUX_XFLAG_SYNC 0x00000008 /* Synchronous updates */ 1170153323Srodrigc#define LINUX_XFLAG_IMMUTABLE 0x00000010 /* Immutable file */ 1171153323Srodrigc#define LINUX_XFLAG_APPEND 0x00000020 /* writes to file may only append */ 1172153323Srodrigc#define LINUX_XFLAG_NODUMP 0x00000040 /* do not dump file */ 1173153323Srodrigc#define LINUX_XFLAG_NOATIME 0x00000080 /* do not update atime */ 1174153323Srodrigc 1175153323SrodrigcSTATIC unsigned int 1176153323Srodrigcxfs_merge_ioc_xflags( 1177153323Srodrigc unsigned int flags, 1178153323Srodrigc unsigned int start) 1179153323Srodrigc{ 1180153323Srodrigc unsigned int xflags = start; 1181153323Srodrigc 1182153323Srodrigc if (flags & LINUX_XFLAG_IMMUTABLE) 1183153323Srodrigc xflags |= XFS_XFLAG_IMMUTABLE; 1184153323Srodrigc else 1185153323Srodrigc xflags &= ~XFS_XFLAG_IMMUTABLE; 1186153323Srodrigc if (flags & LINUX_XFLAG_APPEND) 1187153323Srodrigc xflags |= XFS_XFLAG_APPEND; 1188153323Srodrigc else 1189153323Srodrigc xflags &= ~XFS_XFLAG_APPEND; 1190153323Srodrigc if (flags & LINUX_XFLAG_SYNC) 1191153323Srodrigc xflags |= XFS_XFLAG_SYNC; 1192153323Srodrigc else 1193153323Srodrigc xflags &= ~XFS_XFLAG_SYNC; 1194153323Srodrigc if (flags & LINUX_XFLAG_NOATIME) 1195153323Srodrigc xflags |= XFS_XFLAG_NOATIME; 1196153323Srodrigc else 1197153323Srodrigc xflags &= ~XFS_XFLAG_NOATIME; 1198153323Srodrigc if (flags & LINUX_XFLAG_NODUMP) 1199153323Srodrigc xflags |= XFS_XFLAG_NODUMP; 1200153323Srodrigc else 1201153323Srodrigc xflags &= ~XFS_XFLAG_NODUMP; 1202153323Srodrigc 1203153323Srodrigc return xflags; 1204153323Srodrigc} 1205153323Srodrigc 1206159451SrodrigcSTATIC unsigned int 1207159451Srodrigcxfs_di2lxflags( 1208159451Srodrigc __uint16_t di_flags) 1209159451Srodrigc{ 1210159451Srodrigc unsigned int flags = 0; 1211159451Srodrigc 1212159451Srodrigc if (di_flags & XFS_DIFLAG_IMMUTABLE) 1213159451Srodrigc flags |= LINUX_XFLAG_IMMUTABLE; 1214159451Srodrigc if (di_flags & XFS_DIFLAG_APPEND) 1215159451Srodrigc flags |= LINUX_XFLAG_APPEND; 1216159451Srodrigc if (di_flags & XFS_DIFLAG_SYNC) 1217159451Srodrigc flags |= LINUX_XFLAG_SYNC; 1218159451Srodrigc if (di_flags & XFS_DIFLAG_NOATIME) 1219159451Srodrigc flags |= LINUX_XFLAG_NOATIME; 1220159451Srodrigc if (di_flags & XFS_DIFLAG_NODUMP) 1221159451Srodrigc flags |= LINUX_XFLAG_NODUMP; 1222159451Srodrigc return flags; 1223159451Srodrigc} 1224159451Srodrigc 1225153323SrodrigcSTATIC int 1226153323Srodrigcxfs_ioc_xattr( 1227159451Srodrigc xfs_vnode_t *vp, 1228153323Srodrigc xfs_inode_t *ip, 1229153323Srodrigc struct file *filp, 1230153323Srodrigc unsigned int cmd, 1231159451Srodrigc void __user *arg) 1232153323Srodrigc{ 1233153323Srodrigc struct fsxattr fa; 1234159451Srodrigc struct xfs_vattr *vattr; 1235153323Srodrigc int error; 1236153323Srodrigc int attr_flags; 1237153323Srodrigc unsigned int flags; 1238153323Srodrigc 1239159451Srodrigc error = 0; 1240159451Srodrigc attr_flags = 0; 1241159451Srodrigc 1242159451Srodrigc vattr = kmem_alloc(sizeof(struct xfs_vattr), KM_SLEEP); 1243159451Srodrigc if (unlikely(!vattr)) 1244159451Srodrigc return ENOMEM; 1245159451Srodrigc 1246153323Srodrigc switch (cmd) { 1247153323Srodrigc case XFS_IOC_FSGETXATTR: { 1248159451Srodrigc vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \ 1249159451Srodrigc XFS_AT_NEXTENTS | XFS_AT_PROJID; 1250159451Srodrigc XVOP_GETATTR(vp, vattr, 0, NULL, error); 1251159451Srodrigc if (unlikely(error)) { 1252159451Srodrigc break; 1253159451Srodrigc } 1254153323Srodrigc 1255159451Srodrigc fa.fsx_xflags = vattr->va_xflags; 1256159451Srodrigc fa.fsx_extsize = vattr->va_extsize; 1257159451Srodrigc fa.fsx_nextents = vattr->va_nextents; 1258159451Srodrigc fa.fsx_projid = vattr->va_projid; 1259153323Srodrigc 1260159451Srodrigc if (copy_to_user(arg, &fa, sizeof(fa))) { 1261159451Srodrigc error = EFAULT; 1262159451Srodrigc break; 1263159451Srodrigc } 1264159451Srodrigc break; 1265153323Srodrigc } 1266153323Srodrigc 1267153323Srodrigc case XFS_IOC_FSSETXATTR: { 1268159451Srodrigc if (copy_from_user(&fa, arg, sizeof(fa))) { 1269159451Srodrigc error = EFAULT; 1270159451Srodrigc break; 1271159451Srodrigc } 1272153323Srodrigc 1273153323Srodrigc attr_flags = 0; 1274159451Srodrigc#if 0 1275153323Srodrigc if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) 1276153323Srodrigc attr_flags |= ATTR_NONBLOCK; 1277159451Srodrigc#endif 1278153323Srodrigc 1279159451Srodrigc vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID; 1280159451Srodrigc vattr->va_xflags = fa.fsx_xflags; 1281159451Srodrigc vattr->va_extsize = fa.fsx_extsize; 1282159451Srodrigc vattr->va_projid = fa.fsx_projid; 1283153323Srodrigc 1284159451Srodrigc XVOP_SETATTR(vp, vattr, attr_flags, NULL, error); 1285159451Srodrigc#if 0 1286159451Srodrigc if (likely(!error)) 1287159451Srodrigc __vn_revalidate(vp, vattr); /* update flags */ 1288159451Srodrigc#endif 1289159451Srodrigc break; 1290153323Srodrigc } 1291153323Srodrigc 1292153323Srodrigc case XFS_IOC_FSGETXATTRA: { 1293159451Srodrigc vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \ 1294159451Srodrigc XFS_AT_ANEXTENTS | XFS_AT_PROJID; 1295159451Srodrigc XVOP_GETATTR(vp, vattr, 0, NULL, error); 1296159451Srodrigc if (unlikely(error)) { 1297159451Srodrigc break; 1298159451Srodrigc } 1299153323Srodrigc 1300159451Srodrigc fa.fsx_xflags = vattr->va_xflags; 1301159451Srodrigc fa.fsx_extsize = vattr->va_extsize; 1302159451Srodrigc fa.fsx_nextents = vattr->va_anextents; 1303159451Srodrigc fa.fsx_projid = vattr->va_projid; 1304153323Srodrigc 1305159451Srodrigc if (copy_to_user(arg, &fa, sizeof(fa))) { 1306159451Srodrigc error = EFAULT; 1307159451Srodrigc break; 1308159451Srodrigc } 1309159451Srodrigc break; 1310153323Srodrigc } 1311153323Srodrigc 1312153323Srodrigc case XFS_IOC_GETXFLAGS: { 1313159451Srodrigc flags = xfs_di2lxflags(ip->i_d.di_flags); 1314159451Srodrigc if (copy_to_user(arg, &flags, sizeof(flags))) 1315159451Srodrigc error = EFAULT; 1316159451Srodrigc break; 1317153323Srodrigc } 1318153323Srodrigc 1319153323Srodrigc case XFS_IOC_SETXFLAGS: { 1320159451Srodrigc if (copy_from_user(&flags, arg, sizeof(flags))) { 1321159451Srodrigc error = EFAULT; 1322159451Srodrigc break; 1323159451Srodrigc } 1324153323Srodrigc 1325153323Srodrigc if (flags & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \ 1326153323Srodrigc LINUX_XFLAG_NOATIME | LINUX_XFLAG_NODUMP | \ 1327159451Srodrigc LINUX_XFLAG_SYNC)) { 1328159451Srodrigc error = EOPNOTSUPP; 1329159451Srodrigc break; 1330159451Srodrigc } 1331153323Srodrigc 1332159451Srodrigc#if 0 1333153323Srodrigc attr_flags = 0; 1334153323Srodrigc if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) 1335153323Srodrigc attr_flags |= ATTR_NONBLOCK; 1336159451Srodrigc#endif 1337153323Srodrigc 1338159451Srodrigc vattr->va_mask = XFS_AT_XFLAGS; 1339159451Srodrigc vattr->va_xflags = xfs_merge_ioc_xflags(flags, 1340159451Srodrigc xfs_ip2xflags(ip)); 1341153323Srodrigc 1342159451Srodrigc XVOP_SETATTR(vp, vattr, attr_flags, NULL, error); 1343159451Srodrigc#if 0 1344159451Srodrigc if (likely(!error)) 1345159451Srodrigc __vn_revalidate(vp, vattr); /* update flags */ 1346159451Srodrigc#endif 1347159451Srodrigc break; 1348153323Srodrigc } 1349153323Srodrigc 1350159451Srodrigc#if 0 1351153323Srodrigc case XFS_IOC_GETVERSION: { 1352159451Srodrigc flags = vn_to_inode(vp)->i_generation; 1353159451Srodrigc if (copy_to_user(arg, &flags, sizeof(flags))) 1354159451Srodrigc error = EFAULT; 1355159451Srodrigc break; 1356153323Srodrigc } 1357159451Srodrigc#endif 1358153323Srodrigc 1359153323Srodrigc default: 1360159451Srodrigc error = ENOTTY; 1361159451Srodrigc break; 1362153323Srodrigc } 1363159451Srodrigc 1364159451Srodrigc kmem_free(vattr,sizeof(struct xfs_vattr)); 1365159451Srodrigc return error; 1366153323Srodrigc} 1367153323Srodrigc 1368153323SrodrigcSTATIC int 1369153323Srodrigcxfs_ioc_getbmap( 1370153323Srodrigc bhv_desc_t *bdp, 1371153323Srodrigc struct file *filp, 1372153323Srodrigc int ioflags, 1373153323Srodrigc unsigned int cmd, 1374159451Srodrigc void __user *arg) 1375153323Srodrigc{ 1376153323Srodrigc struct getbmap bm; 1377153323Srodrigc int iflags; 1378153323Srodrigc int error; 1379153323Srodrigc 1380159451Srodrigc if (copy_from_user(&bm, arg, sizeof(bm))) 1381153323Srodrigc return -XFS_ERROR(EFAULT); 1382153323Srodrigc 1383153323Srodrigc if (bm.bmv_count < 2) 1384153323Srodrigc return -XFS_ERROR(EINVAL); 1385153323Srodrigc 1386153323Srodrigc iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0); 1387153323Srodrigc if (ioflags & IO_INVIS) 1388153323Srodrigc iflags |= BMV_IF_NO_DMAPI_READ; 1389153323Srodrigc 1390159451Srodrigc error = xfs_getbmap(bdp, &bm, (struct getbmap __user *)arg+1, iflags); 1391153323Srodrigc if (error) 1392153323Srodrigc return -error; 1393153323Srodrigc 1394159451Srodrigc if (copy_to_user(arg, &bm, sizeof(bm))) 1395153323Srodrigc return -XFS_ERROR(EFAULT); 1396153323Srodrigc return 0; 1397153323Srodrigc} 1398153323Srodrigc 1399153323SrodrigcSTATIC int 1400153323Srodrigcxfs_ioc_getbmapx( 1401153323Srodrigc bhv_desc_t *bdp, 1402159451Srodrigc void __user *arg) 1403153323Srodrigc{ 1404153323Srodrigc struct getbmapx bmx; 1405153323Srodrigc struct getbmap bm; 1406153323Srodrigc int iflags; 1407153323Srodrigc int error; 1408153323Srodrigc 1409159451Srodrigc printf("%s:%d\n",__FILE__,__LINE__); 1410159451Srodrigc if (copy_from_user(&bmx, arg, sizeof(bmx))) 1411159451Srodrigc return XFS_ERROR(EFAULT); 1412153323Srodrigc 1413159451Srodrigc printf("%s:%d\n",__FILE__,__LINE__); 1414153323Srodrigc if (bmx.bmv_count < 2) 1415159451Srodrigc return XFS_ERROR(EINVAL); 1416153323Srodrigc 1417153323Srodrigc /* 1418153323Srodrigc * Map input getbmapx structure to a getbmap 1419153323Srodrigc * structure for xfs_getbmap. 1420153323Srodrigc */ 1421153323Srodrigc GETBMAP_CONVERT(bmx, bm); 1422153323Srodrigc 1423153323Srodrigc iflags = bmx.bmv_iflags; 1424153323Srodrigc 1425153323Srodrigc if (iflags & (~BMV_IF_VALID)) 1426159451Srodrigc return XFS_ERROR(EINVAL); 1427153323Srodrigc 1428153323Srodrigc iflags |= BMV_IF_EXTENDED; 1429153323Srodrigc 1430159451Srodrigc printf("%s:%d arg+1 %p arg %p\n",__FILE__,__LINE__,(struct getbmapx __user *)arg+1,arg); 1431159451Srodrigc error = xfs_getbmap(bdp, &bm, (struct getbmapx __user *)arg+1, iflags); 1432153323Srodrigc if (error) 1433159451Srodrigc return error; 1434153323Srodrigc 1435159451Srodrigc printf("%s:%d\n",__FILE__,__LINE__); 1436153323Srodrigc GETBMAP_CONVERT(bm, bmx); 1437153323Srodrigc 1438159451Srodrigc printf("%s:%d\n",__FILE__,__LINE__); 1439159451Srodrigc if (copy_to_user(arg, &bmx, sizeof(bmx))) 1440159451Srodrigc return XFS_ERROR(EFAULT); 1441153323Srodrigc 1442159451Srodrigc printf("%s:%d\n",__FILE__,__LINE__); 1443153323Srodrigc return 0; 1444153323Srodrigc} 1445153323Srodrigc 1446159451Srodrigc#else 1447153323Srodrigc 1448153323Srodrigcint 1449153323Srodrigcxfs_ioctl( 1450153323Srodrigc bhv_desc_t *bdp, 1451153323Srodrigc struct inode *inode, 1452153323Srodrigc struct file *filp, 1453153323Srodrigc int ioflags, 1454194944Srdivacky u_long cmd, 1455153323Srodrigc unsigned long arg) 1456153323Srodrigc{ 1457153323Srodrigc return EINVAL; 1458153323Srodrigc} 1459159451Srodrigc 1460159451Srodrigc#endif 1461