Esempio n. 1
0
/*
 * NAME:	jfs_ftruncate(vp, flags, length, vinfo, crp)
 *
 * FUNCTION:	truncate regular file <vp> to the specified size <length>.
 *
 * PARAMETER:	vp 	_ file to be truncated.
 *		flags	- open flags
 *		length	- new length
 *		vinfo	- unused
 *		crp	- credential
 *
 * RETURN:	
 *
 * note: EINVAL: JFS does NOT support ftruncate() on file types
 * other than regular filei: the effect of ftruncate()/truncate()
 * on file types other than regular file is unspecified. [XPG4.2].
 * 
 * LFS validation ?: the file must be open for writing.
 */
jfs_ftruncate(
	struct vnode	*vp,		/* file */
	int32		flags,		/* open flags */
	offset_t	length,		/* new length */
	caddr_t		vinfo,		/* Gfs specific inofo */
	struct ucred	*crp)		/* credential structure */
{
	int64	orig_nblocks;					// F226941
	int32	rc = 0;
	int32	tid;
	inode_t	*ip = VP2IP(vp);
	extern int iwritelockx();
	extern int iwriteunlockx();

	if ((ip->i_mode & IFMT) != IFREG)
		return EINVAL;

	IWRITE_LOCK(ip);

	/*
	 * verify mandatory/enforcement-mode file section locking
	 */
/*
	if (ENF_LOCK(ip->i_mode))
	{
		struct eflock bf;

		bf.l_type = F_WRLCK;
		bf.l_whence = 0;
		bf.l_start = length;
		bf.l_len = 0;      
		bf.l_pid = U.U_procp->p_pid;
		bf.l_sysid = 0;
		bf.l_vfs = MNT_XJFS;

		if ((rc = common_reclock(IP2GP(ip),
				ip->i_size,
				length,
				&bf,
		      		((flags & (FNDELAY|FNONBLOCK)) ?
					INOFLCK : SLPFLCK|INOFLCK),
				0,
				0,
				iwritelockx,
				iwriteunlockx)) ||
		    bf.l_type != F_UNLCK)
		{
			rc = rc ? rc : EAGAIN;
			goto out;
		}
	}
*/

	/*
	 *	truncate down
	 */
	if (length < ip->i_size)
	{
// BEGIN D230860
		/*
		 * All inodes must be locked before beginning transaction
		 */
		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);

		orig_nblocks = ip->i_nblocks;			// F226941

		if (rc = iTruncate(tid, ip, (int64)length))
		{
			txEnd(tid);
			goto out;
		}
		ip->i_flag |= IFSYNC;

		DLIM_UPDATE(tid, ip , ip->i_nblocks - orig_nblocks);  // F226941

		rc = DLIM_TXCOMMIT(tid, ip, 0);			// F226941

		txEnd(tid);

		goto out;
	}
	/*
	 *	truncate up (extension)
	 */
	else if (length > ip->i_size)
	{
#ifndef _JFS_OS2
		/* check u_limit */
		if (length > U.U_limit)
		{
			rc = EFBIG;
			goto out;
		}
#endif /* _JFS_OS2 */

// BEGIN F226941
		orig_nblocks = ip->i_nblocks;			// D233382
#ifndef _JFS_FASTDASD						// D233382
		if (ip->i_dasdlim)
		{
			/*
			 * All inodes must be locked before begining
			 * transaction
			 */
			if ((ip->i_dasdlim->flag & DLIM_DIRS_LOCKED) == 0) // D230860
				dasd_write_lock(0, ip->i_dasdlim);  // D230860

			txBegin(ip->i_ipmnt, &tid, 1);
		}
		else
#endif /* _JFS_FASTDASD */					// D233382
		{
#ifdef _JFS_LAZYCOMMIT
			txBeginAnon(ip->i_ipmnt);		// D233382
#endif
			tid = 0;
		}
// END F226941

		if (rc = iExtend(tid, ip, (int64)length))
		{
#ifndef _JFS_FASTDASD						// D233382
			if (tid)				// F226941
				txEnd(tid);			// F226941
#endif								// D233382
			goto out;
		}

		ip->i_flag |= IFSYNC;

// BEGIN F226941
		DLIM_UPDATE(tid, ip, ip->i_nblocks - orig_nblocks);
#ifndef _JFS_FASTDASD						// D233382
		if (tid)
		{
			rc = DLIM_TXCOMMIT(tid, ip, 0);
			txEnd(tid);
		}
		else
#endif /* _JFS_FASTDASD */					// D233382
// END F226941
		/* if available tlocks are scarce and inode has anonymous
		 * tlocks, OR if we modified a metadata page that is on the
		 * synclist, commit inode.
	 	 */
        	if ((TlocksLow && ip->i_atlhead) ||
		    (ip->i_flag & ISYNCLIST))
		{
			txBegin(ip->i_ipmnt, &tid, COMMIT_FORCE);
			rc = txCommit(tid, 1, &ip, 0);		// F226941
			txEnd(tid);
		}
	}
	/*
	 *	no change in size
	 */
	else /* (length == ip->i_size) */
		/* mark the inode as changed and updated (ala BSD) */
		imark(ip, ICHG|IUPD);
out:
	DLIM_WRITE_UNLOCK(ip, ip->i_dasdlim);			// F226941

	return rc;
}
Esempio n. 2
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;
}