Exemple #1
0
/*
 * NAME:	iTruncate(tid, ip, newsize)
 *
 * FUNCTION:    truncate up/down a regular file to specified size, or 
 *		truncate down directory or symbolic link to zero length 
 *		(length is ignored and assumed to be zero if the object
 * 		is a directory or symbolic link). 
 *		if length is > 0, the file must be open (i.e.bound to a 
 *		VM segment). 
 *		return 0 if type is not one of these.
 *
 * PARAMETER:	ip	- inode to truncate
 *		newsize	- new size of the file
 *
 * RETURN:
 *			
 * SERIALIZATION: the IWRITE_LOCK is held on entry/exit.
 */
int32 iTruncate(
	int32	tid, 
	inode_t	*ip, 
	int64	newsize)
{
	int32	rc;
	int64	nbytes;
	int64	pfirst, bfirst;
/*
printf("iTruncate: ip:0x%08x eof:0x%08x:0x%08x\n", ip, newsize); 
*/
	if ((ip->i_mode & IFMT) != IFREG)
		return EINVAL;

	/* if truncating to a non-zero newsize, make sure
	 * file is bound to its cache control object.
	 */
	if (newsize != 0 && ip->i_cacheid == NULL)
	{
		if (rc = iBindCache(ip))
	 		return rc;
	}

	/*
	 * if the newsize is not an integral number of pages,
	 * the file between newsize and next page boundary will 
	 * be cleared.
	 * if truncating into a file hole, it will cause
	 * a full block to be allocated for the logical block.
	 */

	/*
	 * if the file was commited with zero link count before
	 * (temporary file), its persistent resources were already
	 * freed at that time: just truncate/free working resources;
	 */
	if (ip->i_cflag & COMMIT_NOLINK)
	{
		rc = xtTruncate(0, ip, newsize, COMMIT_WMAP);
		return rc;
	}

	/*
	 * delete pages and set new size.
	 */
	rc = xtTruncate(tid, ip, newsize, COMMIT_TRUNCATE|COMMIT_PWMAP);

	imark(ip, ICHG|IUPD);

	return rc;
}
Exemple #2
0
/*
 * NAME:        jfs_defragfs()
 *
 * FUNCTION:    relocate specified extent for defragfs()
 *              optionally commiting the operation.
 */
int32 jfs_defragfs(
	char	*pData,		/* pointer to buffer containing plist */ 
	uint32	lenData,	/* length of buffer */
	uint16	*pbufsize)	/* pointer of buffer length */ 
{
	int32	rc = 0;
	defragfs_t	pList, *p = &pList;
	uint32	xtype;
	int64	offset, xoff, oxaddr, nxaddr;
	int32	xlen;
	inode_t	*ipmnt, *ipimap, *ipbmap;
	inode_t	*ip = NULL;
	xad_t	oxad;
	pxd_t	opxd;
        mode_t	imode;
        int32	tid;
        inode_t	*iplist[1];
	struct vfs *vfsp;

	if (rc = KernCopyIn(&pList, pData, lenData))
		return rc;

	/* get the 'mount' inode */
        for (vfsp = vfs_anchor; vfsp != NULL; vfsp = vfsp->vfs_next)
		if (vfsp->vfs_vpfsi->vpi_drive == pList.dev)
			break;
	if (vfsp == NULL)
		return EINVAL;

	xtype = pList.flag;

	/* sync at start of defragfs ? */
	if (xtype & DEFRAGFS_SYNC)
	{
jEVENT(0,("jfs_defragfs: DEFRAGFS_SYNC\n"));

		if ((vfsp->vfs_flag & VFS_READONLY) ||
		    (vfsp->vfs_flag & VFS_ACCEPT))
			return 0;

		ipimap = (inode_t *)vfsp->vfs_data;
		ipmnt = ipimap->i_ipmnt;
		ipbmap = ipmnt->i_ipbmap;

		/* sync the file system */
		iSyncFS(vfsp);

		/* write dirty pages of imap */
		diSync(ipimap);

		/* write dirty pages of bmap */
		dbSync(ipbmap);

		return 0;
	}
	else if (!(xtype & DEFRAGFS_RELOCATE))
		return EINVAL;

	if (vfsp->vfs_flag & VFS_READONLY)
		return EROFS;

	if (vfsp->vfs_flag & VFS_ACCEPT)
		return EINVAL;

	/* get the relocation parameter */
        xoff = pList.xoff;
        oxaddr = pList.old_xaddr;
        nxaddr = pList.new_xaddr;
        xlen = pList.xlen;

jEVENT(0,("jfs_defragfs: i:%d xtype:0x%08x xoff:%lld xlen:%d xaddr:%lld:%lld\n",
	pList.ino, xtype, xoff, xlen, oxaddr, nxaddr));

	/* get the object inode if it exist */
	ICACHE_LOCK();
	rc = iget(vfsp, pList.ino, &ip, 0);
	ICACHE_UNLOCK();
	if(rc)
        {
jEVENT(0,("jfs_defragfs: stale target object.\n"));
		rc = ESTALE;  /* stale object ENOENT */
		goto out1;
        }

	IWRITE_LOCK(ip);
	
	/* validate inode */
	if (ip->i_nlink == 0  
	|| ip->i_gen != pList.gen
	|| ip->i_fileset != pList.fileset
	|| ip->i_inostamp != pList.inostamp)
	{
jEVENT(0,("jfs_defragfs: stale target object.\n"));
		rc = ESTALE;  /* stale object ENOENT */
		goto out1;
	}
	
	/* validate object type: regular file or directory */
	imode = ip->i_mode & IFMT;
	switch(imode)
	{
	case IFREG:
	case IFDIR:
		break;
	default:
		rc = ESTALE;	/* invalid object type ENOENT */
		goto out1;
	}

	/*
	 * try to allocate new destination extent
	 */
	if (rc = dbAllocExact(ip, nxaddr, xlen))
        {
jEVENT(0,("jfs_defragfs: stale destination extent.\n"));
		rc = ENOSPC;
		goto out1;
        }

	iBindCache(ip);

	/*
	 *	regular file: 
         */
	if (imode == IFREG)
	{
		/*
		 * automatic commit before and after each relocation 
		 * may be skipped after more experience;
		 */
		/*
		 * commit any update before relocation
		 */
		if (ip->i_flag & IUPD)
		{
			ip->i_flag |= IFSYNC;

			txBegin(ip->i_ipmnt, &tid, 0);
			iplist[0] = ip;
			rc = txCommit(tid, 1, &iplist[0], 0);
			if (rc)
				goto out2;
			txEnd(tid);
		}

		/*
		 *	relocate either xtpage or data extent
		 */
		txBegin(ip->i_ipmnt, &tid, 0);

		/* source extent xad */
		XADoffset(&oxad, xoff);
		XADaddress(&oxad, oxaddr);
		XADlength(&oxad, xlen);

		rc = xtRelocate(tid, ip, &oxad, nxaddr, xtype);
		if (rc)
			goto out2;

		iplist[0] = ip;
		rc = txCommit(tid, 1, &iplist[0], 0);
		if (rc)
			goto out2;

		txEnd(tid);
		goto out1;
	}
	/*
	 *	directory:
	 */
	else  /* IFDIR */
	{
		/*
		 *	relocate dtpage
		 */
		txBegin(ip->i_ipmnt, &tid, 0);

		/* source extent pxd */
		PXDaddress(&opxd, oxaddr);
		PXDlength(&opxd, xlen);
	
		rc = dtRelocate(tid, ip, xoff, &opxd, nxaddr); 
		if (rc)
			goto out2;

		iplist[0] = ip;
		rc = txCommit(tid, 1, &iplist[0], 0);
		if (rc)
			goto out2;

		txEnd(tid);
		goto out1;
	}

out2:
	dbFree(ip, nxaddr, xlen) ;

out1:
	if (ip)
	{
		IWRITE_UNLOCK(ip);

		ICACHE_LOCK();
		iput(ip, NULL);
		ICACHE_UNLOCK();
	}

jEVENT(0,("jfs_defragfs: rc=%d\n", rc));
	return (rc);
}
Exemple #3
0
/*
 * NAME:	iOpen()
 *
 * FUNCTION:	common function that opens a file.
 *		called by jfs_open() and jfs_create().
 *
 * PARAMETER:	ip	- inode to open
 *		flag	- open flags from the file pointer.
 *		ext	- external data used by the device driver.
 *		crp	- credential
 *
 * RETURN:	EBUSY	- if truncating a mapped file
 *		errors from subroutines		
 *
 * note: at most a single commit may occur in jfs_open() and jfs_create()
 * as FEXEC and FTRUNC are mutually exclusive.
 */
int32 iOpen(
	inode_t *ip,		/* inode of file to open */
	int32	flag,		/* open(2) flags */
	int32	tflag,		/* trucation flag */
	FEALIST	*pfealist,	/* EAs if truncating */
	struct ucred *crp)	/* credential */
{
	int32	rc = 0;		
	struct gnode *gp;	/* gnode pointer from inode	*/
	int64	orig_nblocks;					// F226941
	int32	tid;

	/* bind the newly opened file to a cache control object */
	if ((ip->i_mode & IFMT) == IFREG && ip->i_cacheid == NULL)
	{
		if (rc = iBindCache(ip))
			return rc;
	}

	/* if open/create FTRUNC, truncate to zero length */
	if (tflag & OPEN_ACTION_REPLACE_IF_EXISTS)
	{
		if (isReadOnly(ip))
			return EROFS;

		orig_nblocks = ip->i_nblocks;			// F226941
// BEGIN D230860
		/*
		 * Cannot begin transaction until all inodes are locked
		 */
		if (ip->i_dasdlim &&
		    (ip->i_dasdlim->flag & DLIM_DIRS_LOCKED) == 0)
			dasd_write_lock(0, ip->i_dasdlim);
// END D230860
		txBegin(ip->i_ipmnt, &tid, 0);

		if (rc = iTruncate(tid, ip, 0))
		{
			txEnd(tid);
			return rc;
		}

		imark(ip, IACC|ICHG|IUPD|IFSYNC);		// D233382

#ifdef _JFS_OS2
		rc = jfs_InitializeFEAList(ip, tid, pfealist);

		/* If we successfully truncated the file, but failed adding the
		 * EA's, we are in a bad state.  Punt...
		 */
		if (rc)
		{
			txAbort(tid, 0);
			txEnd(tid);
			return rc;
		}
#endif	/* _JFS_OS2 */
		DLIM_UPDATE(tid, ip, ip->i_nblocks - orig_nblocks);  // F226941

		rc = DLIM_TXCOMMIT(tid, ip, 0);			// F226941
		txEnd(tid);
		if (rc)
			return rc;
	}

	/*
	 * update per open counters
	 */
	gp = IP2GP(ip);

#ifdef	_JFS_OS2

	/* keep count of opens by type
	 */
	switch (flag & (OPEN_ACCESS_READWRITE | OPEN_ACCESS_WRITEONLY))
	{
	    case (OPEN_ACCESS_READWRITE):
		gp->gn_wrcnt++;
		gp->gn_rdcnt++;
		break;

	    case (OPEN_ACCESS_WRITEONLY):
		gp->gn_wrcnt++;
		break;

	    default:
		gp->gn_rdcnt++;
	}

	/* set up sharing mode
	 */
	switch (flag & (OPEN_SHARE_DENYREAD))
	{
	    case(OPEN_SHARE_DENYWRITE):
		gp->gn_dwcnt++;
		break;

	    case(OPEN_SHARE_DENYREAD):
		gp->gn_drcnt++;
		break;

	    case(OPEN_SHARE_DENYREADWRITE):
		gp->gn_flags |= GNF_NSHARE;
		break;
	}
	if ((flag & OPEN_FLAGS_LARGEFILE) == 0)
		gp->gn_lgcnt++;

#endif	/* _JFS_OS2 */

	return rc;
}