[BACK]Return to xfs_grio.c CVS log [TXT][DIR] Up to [Development] / xfs-linux-nodel

File: [Development] / xfs-linux-nodel / Attic / xfs_grio.c (download)

Revision 1.83, Fri Jun 9 06:40:03 2000 UTC (17 years, 4 months ago) by ananth
Branch: MAIN
Changes since 1.82: +184 -108 lines

Merge of 2.3.99pre2-xfs:slinx:63026a originally by cattelan on 05/30/00
  Masive type update 
  all daddr_t -> xfs_daddr_t
  caddr_t -> xfs_caddr_t
  off_t   -> xfs_off_t
  ino_t   -> xfs_ino_t
  off64_t -> xfs_off_t 
  Removed need for file xfs_to_linux.h and lunux_to_xfs.h

Merge of 2.3.99pre2-xfs:slinx:63295a originally by nathans on 06/03/00
  remove all references to stuff from ksa.h and psa.h.

Merge of 2.3.99pre2-xfs:slinx:63306a originally by dxm on 06/04/00
  RT/GRIO checkin

/*
 * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
 * 
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it would be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * 
 * Further, this software is distributed without any warranty that it is
 * free of the rightful claim of any third person regarding infringement
 * or the like.  Any license provided herein, whether implied or
 * otherwise, applies only to this software file.  Patent licenses, if
 * any, provided herein do not apply to combinations of this program with
 * other software, or any other product whatsoever.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write the Free Software Foundation, Inc., 59
 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
 * 
 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
 * Mountain View, CA  94043, or:
 * 
 * http://www.sgi.com 
 * 
 * For further information regarding this notice, see: 
 * 
 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
 */
#ident "$Header: /oss/CVS/cvs/xfs-linux-nodel/Attic/xfs_grio.c,v 1.83 2000/06/09 06:40:03 ananth Exp $"

#include <xfs_os_defs.h>

#include <sys/types.h>
#include <sys/param.h>
#include <sys/debug.h>
#include "xfs_buf.h"
#include <linux/xfs_sema.h>
#if 0 /* XXX PORT */
#include <sys/lock.h>
#endif
#ifdef SIM
#define _KERNEL 1
#endif
#include <sys/uuid.h>
#include <xfs_grio.h>
#ifdef SIM
#undef _KERNEL
#endif
#include <sys/kmem.h>
#include <sys/vnode.h>
#include <xfs_grio.h>
#include <xfs_macros.h>
#include <xfs_types.h>
#include <xfs_log.h>
#include <xfs_inum.h>
#include <xfs_trans.h>
#include <xfs_sb.h>
#include <xfs_dir.h>
#include <xfs_dir2.h>
#include <xfs_mount.h>
#include <xfs_alloc_btree.h>
#include <xfs_bmap_btree.h>
#include <xfs_ialloc_btree.h>
#include <xfs_btree.h>
#include <xfs_attr_sf.h>
#include <xfs_dir_sf.h>
#include <xfs_dir2_sf.h>
#include <xfs_dinode.h>
#include <xfs_inode.h>
#include <xfs_itable.h>
#include <xfs_error.h>
#include <asm/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/file.h>

#ifdef SIM
#include "sim.h"
#include <stdio.h>
#endif

#define IRELE(ip)		VN_RELE(XFS_ITOV(ip))

extern xfs_inode_t 			*xfs_get_inode ( dev_t, xfs_ino_t);
extern void grioinit(void);

/*
 * xfs_get_file_extents()
 *	This routine creates the cononical forms of all the extents
 *	for the given file and returns them to the user.
 *
 *  RETURNS:
 *	0 on success
 *	non zero on failure
 */
int
xfs_get_file_extents(
	sysarg_t sysarg_file_id,
	sysarg_t sysarg_extents_addr,
	sysarg_t sysarg_count)
{
	int			i, recsize, num_extents = 0;
	int			error = 0;
	dev_t			fs_dev;
	xfs_ino_t		ino;
	xfs_inode_t 		*ip;
	xfs_bmbt_rec_t 		*ep;
	xfs_bmbt_irec_t 	thisrec;
	grio_bmbt_irec_t	*grec;
	grio_file_id_t		fileid;
	xfs_caddr_t			extents, count;

	if (copy_from_user(&fileid, SYSARG_TO_PTR(sysarg_file_id), sizeof(grio_file_id_t))) {
		error = -XFS_ERROR(EFAULT);
		return( error );
	}

	fs_dev 		= fileid.fs_dev;
	ino		= fileid.ino;

	/*
	 * Get sysarg arguements
	 */
	extents		= (xfs_caddr_t)SYSARG_TO_PTR(sysarg_extents_addr);
	count		= (xfs_caddr_t)SYSARG_TO_PTR(sysarg_count);

	/*
 	 * Get the inode
	 */
	if (!(ip = xfs_get_inode( fs_dev, ino ))) {
		error = -XFS_ERROR(ENOENT);
		if (copy_to_user((xfs_caddr_t)count, &num_extents, 
				sizeof( num_extents))) {

			error = -XFS_ERROR(EFAULT);
		}
		return( error );
	}

	/*
	 * Get the number of extents in the file.
	 */
	num_extents = ip->i_d.di_nextents;

	if (num_extents) {

		/*
		 * Copy the extents if they exist.
		 */
		ASSERT(num_extents <  XFS_MAX_INCORE_EXTENTS);

		/*
		 * Read in the file extents from disk if necessary.
		 */
		if (!(ip->i_df.if_flags & XFS_IFEXTENTS)) {
			error = xfs_iread_extents(NULL, ip, XFS_DATA_FORK);
			if (error) {
				goto out;
			}
		}

		recsize = sizeof(grio_bmbt_irec_t) * num_extents;
		grec = kmem_alloc(recsize, KM_SLEEP );

		ep = ip->i_df.if_u1.if_extents;

		ASSERT( ep );

		for (i = 0; i < num_extents; i++, ep++) {
			/*
 			 * copy extent numbers;
 			 */
			xfs_bmbt_get_all(ep, &thisrec);
			grec[i].br_startoff 	= thisrec.br_startoff;
			grec[i].br_startblock 	= thisrec.br_startblock;
			grec[i].br_blockcount 	= thisrec.br_blockcount;
		}

		if (copy_to_user((xfs_caddr_t)extents, grec, recsize )) {
			error = -XFS_ERROR(EFAULT);
		}
		kmem_free(grec, recsize);
	}

	/* 
	 * copy out to user space along with count.
 	 */
	if (copy_to_user((xfs_caddr_t)count,  &num_extents, sizeof( num_extents))) {
		error = -XFS_ERROR(EFAULT);
	}

 out:
	xfs_iunlock( ip, XFS_ILOCK_SHARED );
	IRELE( ip );
	return( error );
}

/*
 * xfs_get_file_rt()
 *	This routine determines if the given file has real time
 *	extents. If so a 1 is written to the user memory pointed at
 *	by rt, if not a 0 is written.
 *
 *
 * RETURNS:
 *	0 on success
 *	non zero on failure
 */
int
xfs_get_file_rt( 
	sysarg_t sysarg_file_id,
	sysarg_t sysarg_rt)
{
	int 		inodert = 0, error = 0;
	dev_t		fs_dev;
	xfs_ino_t	ino;
	xfs_inode_t 	*ip;
	xfs_caddr_t		rt;
	grio_file_id_t	fileid;


	if ( copy_from_user(&fileid, SYSARG_TO_PTR(sysarg_file_id), sizeof(grio_file_id_t))) {
		error = -XFS_ERROR(EFAULT);
		return( error );
	}

	rt		= (xfs_caddr_t)SYSARG_TO_PTR(sysarg_rt);
	fs_dev 		= fileid.fs_dev;
	ino		= fileid.ino;

	/*
 	 * Get the inode.
	 */
	if (!(ip = xfs_get_inode( fs_dev, ino ))) {
		return -XFS_ERROR( ENOENT );
	}

	/*
	 * Check if the inode is marked as real time.
	 */
	if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) {
		inodert = 1;
	}

	/*
 	 * Copy the results to user space.
 	 */
	if (copy_to_user((xfs_caddr_t)rt, &inodert, sizeof(int)) ) {
		error = -XFS_ERROR(EFAULT);
	}

	xfs_iunlock( ip, XFS_ILOCK_SHARED );
	IRELE( ip );
	return( error );

}


/*
 * xfs_get_block_size()
 *	This routine determines the block size of the given
 *	file system copies it to the user memory pointed at by fs_size.
 *
 * RETURNS:
 *	0 on success
 *	non zero on failure
 */
int
xfs_get_block_size(
	sysarg_t sysarg_fs_dev, 
	sysarg_t sysarg_fs_size)
{
	int 		error = 0;
	dev_t		fs_dev;
	xfs_caddr_t		fs_size;
	struct vfs	*vfsp;
	extern int	xfs_fstype;

	fs_dev 		= (dev_t)sysarg_fs_dev;
	fs_size		= (xfs_caddr_t)SYSARG_TO_PTR(sysarg_fs_size);

	if ( vfsp = vfs_devsearch( fs_dev, xfs_fstype ) ) {
		if (copy_to_user((xfs_caddr_t)fs_size, &(vfsp->vfs_bsize), 
				sizeof(u_int)) ) {

			error = -XFS_ERROR(EFAULT);
		}
	} else {
		error = -XFS_ERROR( EIO );
	}
	return( error );
}



/*
 * xfs_grio_get_inumber
 *	Convert a users file descriptor to an inode number.
 *
 * RETURNS:
 *	64 bit inode number
 *
 * CAVEAT:
 *	this must be called from context of the user process
 */
xfs_ino_t 
xfs_grio_get_inumber( int fdes )
{
	xfs_ino_t   ino=-1;
        struct file *filp;
        
        filp = fget(fdes);
        if (filp) {
                struct dentry *dentry = filp->f_dentry;
                struct inode *inode = dentry->d_inode;
            
                ino=inode->i_ino;
                fput(filp);    
        }
        printk("xfs_grio_get_inumber fd %d -> ino %Ld\n",
                fdes, ino);
        
        return ino;

}


/*
 * xfs_grio_get_fs_dev
 *	Convert a users file descriptor to a file system device.
 *
 * RETURNS:
 *	the dev_t of the file system where the file resides
 *
 * CAVEAT:
 *	this must be called from the context of the user process
 */
dev_t 
xfs_grio_get_fs_dev( int fdes )
{
	dev_t		dev=0;
        struct file     *filp;

        filp = fget(fdes);
        if (filp) {
                struct dentry *dentry = filp->f_dentry;
                struct inode *inode = dentry->d_inode;
            
                dev=inode->i_dev;
                
                fput(filp);    
        }
        printk("xfs_grio_get_fs_dev fd %d -> dev 0x%x (%d)\n",
                fdes, dev, dev);
                
	return( dev );
}

/* stubbed out - real version is in grio module */
int grio_strategy(xfs_buf_t *bp) 
{
	return pagebuf_iorequest(bp);
}

/* make XFS GRIO syscall available thru /dev/grio ioctl */

int xfs_grio_ioctl (
	struct inode	*inode,
	struct file	*filp,
	unsigned int	cmd,
	unsigned long	arg)
{
        
        if (cmd!=XFS_GRIO_CMD) {
            printk("xfs_grio_ioctl command %d (expect %d)\n", 
                    cmd, XFS_GRIO_CMD);
            return -EINVAL;
        }
        
        /* XXX PORT do we need to check for FORCED_SHUTDOWN here? */

	switch (cmd) {

	case XFS_GRIO_CMD: {
		xfs_grio_ioctl_t   grioio;

		if (copy_from_user(&grioio, (xfs_grio_ioctl_t *)arg,
						sizeof(xfs_grio_ioctl_t)))
			return -XFS_ERROR(EFAULT);
                
                return grio_config(grioio.cmd,
                                        grioio.arg1, grioio.arg2,
                                        grioio.arg3, grioio.arg4);
	}

	default:
		return -EINVAL;
	}
}

static atomic_t xfs_grio_isopen = ATOMIC_INIT(0);

static int xfs_grio_open(struct inode *inode, struct file *file)
{
        MOD_INC_USE_COUNT;
        return 0;
}

static int xfs_grio_release(struct inode *inode, struct file *file)
{
        MOD_DEC_USE_COUNT;
        return 0;
}

static struct file_operations xfs_grio_fops = {
        ioctl:          xfs_grio_ioctl,
        open:           xfs_grio_open,
        release:        xfs_grio_release,
};

static struct miscdevice xfs_grio_dev=
{
        XFS_GRIO_MINOR,
        "xfs_grio",
        &xfs_grio_fops
};

void xfs_grio_init(void)
{
        printk("xfs_grio_init\n");
        printk("sizeof(grio_cmd_t)=%d\n", sizeof(grio_cmd_t));
    printk("%d %d %d %d %d\n", 
            offsetof(grio_cmd_t,gr_fp),
            offsetof(grio_cmd_t,other_end),
            offsetof(grio_cmd_t,memloc),
            offsetof(grio_cmd_t,cmd_info),
            offsetof(grio_cmd_t,gr_usecs_bw));
    printk("%d %d %d %d\n", 
            offsetof(struct end_info,gr_end_type),
            offsetof(struct end_info,gr_dev),
            offsetof(struct end_info,gr_ino),
            sizeof(struct end_info));
        grioinit();
        misc_register(&xfs_grio_dev);
}

void xfs_grio_uninit(void)
{
        printk("xfs_grio_uninit\n");
        misc_deregister(&xfs_grio_dev);
}