Example #1
0
int32 jfs_strfromUCS(
char *      target,
UniChar *   source,
int32       len,
int32       source_len)
{
    int32   rc;
    int32   newlen;
    char    *pinned_string;

    pinned_string = (char *)allocpool(string_pool, 0);
    if (pinned_string == 0)
        return -1;

    rc = KernStrFromUcs(0,
                        pinned_string,
                        source,
                        MIN(JFS_PATH_MAX+1, len),
                        source_len);

    jEVENT((rc != 0), ("KernStrFromUcs returned %d\n", rc));

    if (! rc)
    {
        newlen = strlen(pinned_string);
        rc = KernCopyOut(target, pinned_string, newlen+1);
    }

    freepool(string_pool, (caddr_t *)pinned_string);

    if (rc)
        return -1;
    else
        return newlen;
}
Example #2
0
int32 jfs_strtoUCS(
UniChar *   target,
char *      source,
int32       len)
{
    int32   rc;
    int32   source_len;
    int32   newlen;

    source_len = strlen(source);
    rc = KernStrToUcs(0, target, source, len+1, source_len);
    if (rc)
    {
        jEVENT(1, ("KernStrToUcs return %d\n", rc));
        return -1;
    }
    else
//      return UniStrlen(target);   /* Nobody uses this anyway */
        return 0;
}
Example #3
0
/*
 * NAME:	jfs_mkdir(dvp, name, mode, crp)
 *
 * FUNCTION:	create a child directory in the parent directory <dvp>
 *		with name = <name> and mode = <mode>
 *
 * PARAMETER:	dvp 	- parent directory vnode
 *		name	- name of child directory
 *		mode	- create mode (rwxrwxrwx).
 *		crp	- credential
 *
 * RETURN:	Errors from subroutines
 *
 * note:
 * EACCESS: user needs search+write permission on the parent directory
 */
jfs_mkdir(
	struct vnode	*dvp,
	UniChar		*name,
	mode_t		mode,
#ifdef _JFS_OS2
        EAOP		*pEABuf,
#endif	/* _JFS_OS2 */
	struct ucred	*crp)
{
	int32 	rc = 0, rc1 = 0;
	int32	tid;		/* transaction id */
	struct vfs	*vfsp = dvp->v_vfsp;
	inode_t	*dip = VP2IP(dvp); /* parent directory inode */
	struct dasd_usage	*du;				// F226941
	inode_t *ip = NULL;	/* child directory inode */
	ino_t	ino;
	component_t dname;	/* child directory name */
	btstack_t	btstack;
	inode_t	*iplist[2];
	int64	orig_nblocks;					// F226941
#ifdef _JFS_LAZYCOMMIT
	tblock_t *tblk;						// D230860
#endif
#ifdef _JFS_OS2
	FEALIST		*pfealist = NULL;
#endif	/* _JFS_OS2 */

NOISE(1,("jfs_mkdir: dip:0x%08x name:%s\n", dip, name));

	/*
	 * the named file exists for "." or ".."
	 */
	if (name[0] == '.')
	{
		if ((name[1] == '.' && name[2] == '\0') ||
		    name[1] == '\0')
			return EEXIST;
	}

#ifdef _JFS_OS2
	/* validate the EAOP buffer, FEALIST size storage location and the
	 * entire FEALIST storage area.  Once all the storage has been
	 * validated, the entire FEALIST is validated for format and the size is
	 * computed and compared against the limit.
	 */
	if (pEABuf)
	{
		if (rc = jfs_ValidateUserFEAList(pEABuf, &pfealist,
				&pEABuf->oError))
		{
			/* something failed -- bail out */
			return rc;
		}
	}
#endif	/* _JFS_OS2 */

	if (dip->i_nlink == 0)
	{
		rc = ENOENT;
		goto out1;
	}

	/* link count overflow on parent directory ? */
	if (dip->i_nlink >= LINK_MAX)
	{
		rc = EMLINK;
		goto out1;
	}

	/*
	 * search parent directory for entry/freespace
	 * (dtSearch() returns parent directory page pinned)
	 */
	dname.name = name;
	dname.namlen = UniStrlen(name);
	if (dname.namlen > JFS_NAME_MAX-1)
	{
		rc = ERROR_FILENAME_EXCED_RANGE;
		goto out1;
	}

// BEGIN D233382
#ifdef _JFS_LAZYCOMMIT
	if (isReadOnly(dip))
	{
		rc = EROFS;
		goto out1;
	}

	/*
	 * Either iAlloc() or txBegin() may block.  Deadlock can occur if we
	 * block there while holding dtree page, so we allocate the inode &
	 * begin the transaction before we search the directory.
	 */
	if (rc = iAlloc(vfsp, dip, IFDIR|mode|IDIRECTORY, &ip, crp))
		goto out1;

	txBegin(dip->i_ipmnt, &tid, 0);

	if (rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))
	{
		ip->i_nlink = 0;
		ICACHE_LOCK();
		iput(ip, vfsp);
		ICACHE_UNLOCK();
		txEnd(tid);
		goto out1;
	}

	tblk = &TxBlock[tid];					// D230860
	tblk->xflag |= COMMIT_CREATE;				// D230860
	tblk->ip = ip;						// D230860

#else /* ! _JFS_LAZYCOMMIT */
// END D233382

	if (rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))
		goto out1;

	if (isReadOnly(dip))
	{
		rc = EROFS;

		/* release parent directory page */
		BT_PUTSEARCH(&btstack);
		goto out1;
	}

	/*
	 * allocate on-disk/in-memory inode for child directory:
	 * (iAlloc() returns new, locked inode)
	 */
	if (rc = iAlloc(vfsp, dip, IFDIR|mode|IDIRECTORY, &ip, crp))
	{
		/* release parent directory page */
		BT_PUTSEARCH(&btstack);

jEVENT(0,("jfs_mkdir: iAlloc error(%d)\n", rc));
		goto out1;
	}

	txBegin(dip->i_ipmnt, &tid, 0);
#endif /* _JFS_LAZYCOMMIT */

	du = ip->i_dasdlim = dip->i_dasdlim;			// F226941

	orig_nblocks = dip->i_nblocks;				// F226941

	iplist[0] = dip;
	iplist[1] = ip;
	
	/*
	 * initialize the child directory in-line in inode
	 */
	dtInitRoot(tid, ip, dip->i_number);

	/*
	 * create entry in parent directory for child directory
	 * (dtInsert() releases parent directory page)
	 */
	ino = ip->i_number;
	if (rc = dtInsert(tid, dip, &dname, &ino, &btstack))
	{	
		/* discard new directory inode */
		ip->i_nlink = 0;

		if (rc == EIO)
			txAbort(tid, 1);	/* Marks Filesystem dirty */
		else
			txAbort(tid, 0);	/* Filesystem full */
		txEnd(tid);
		goto out3;
	}

	/* update child directory inode */
// BEGIN F226941
	setDASDLIMIT(&ip->i_DASD, 0);
	setDASDUSED(&ip->i_DASD, 0);
// END F226941

	ip->i_nlink++;	/* for '.' */ 
	imark(ip, IACC|ICHG|IUPD|IFSYNC);	

	/* update parent directory inode */
	dip->i_nlink++; /* for '..' from child directory */
	imark(dip, ICHG|IUPD|IFSYNC);	

	/*
	 * insert entry for the new file to dnlc
	 */
	ncEnter(dip->i_ipimap, dip->i_number, &dname, ino, NULL);

#ifdef _JFS_OS2

	if ((rc1 == 0) && pfealist)				// F226941
		rc1 = jfs_InitializeFEAList(ip, tid, pfealist);

	if ((rc1 == 0) && (dip->i_acl.flag) && (dip->i_acl.size))
		rc1 = jfs_CopyACL(ip, dip, tid);

#endif	/* _JFS_OS2 */

// BEGIN FF226941
	DLIM_UPDATE(tid, dip, dip->i_nblocks + ip->i_nblocks - orig_nblocks);
	setDASDUSED(&ip->i_DASD, ip->i_nblocks);		// D233382
#ifndef _JFS_FASTDASD						// D233382
	/*
	 * If the transaction modified the ancestors of the inode, the
	 * parent will be in the dasd usage list.  Otherwise, transaction
	 * will only change new directory and parent.
	 */
	if (du && (du->flag & DLIM_LOGGED))
		rc = dasd_commit(tid, ip, 0);
	else
#endif /* _JFS_FASTDASD */					// D233382
// END FF226941

		rc = txCommit(tid, 2, &iplist[0], 0);
	txEnd(tid);

#ifdef _JFS_OS2

	/* If we successfully added the directory, but failed adding the EA or
	 * ACL, we must cleanup the created directory entry and return the
	 * error.
	 */
	if (rc1)
	{
// BEGIN D230860
		if ((du) && (du->first_locked))
		{
			/*
			 * txCommit unlocked one or more inodes.
			 * We need to unlock all the directories &
			 * relock them.
			 */
			dip->i_dasdlim = 0;
			DLIM_WRITE_UNLOCK_DETACH(ip, du);
			DLIM_WRITE_LOCK_ATTACH(ip, du);
			dip->i_dasdlim = du;
		}
// END D230860
		jfs_xrmdir(dip, ip, name);
		rc = rc1;
	}

#endif	/* _JFS_OS2 */

out3:
	ip->i_dasdlim = 0;					// F226941
	IWRITE_UNLOCK(ip);

	ICACHE_LOCK();
	iput(ip, vfsp);
	ICACHE_UNLOCK();

out1:

#ifdef _JFS_OS2
		/*
		 * this buffer was allocated by
		 * jfs_ValidateUserFEAList() at twice the
		 * size of the given list to provide buffer
		 * space for eliminating duplicate names
		 */
	if (pfealist)
		jfs_EABufFree((char *)pfealist, (pfealist->cbList << 1));
#endif	/* _JFS_OS2 */

NOISE(1,("jfs_mkdir: rc:%d\n", rc));
	return rc;
}
Example #4
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);
}
Example #5
0
/*
 * NAME:	jfs_open(vp, flag, ext, vinfop, crp)
 *
 * FUNCTION:	open a file <vp> with open flag <flag>.
 *
 * PARAMETER:	vp	- vnode to open
 *		flag	- open flags from the file pointer.
 *		ext	- external data for device driver.
 *		vinfop	- pointer to the vinfo field for the open file
 *		crp	- credential
 *
 * RETURN:	ENOENT	- non-positive link count
 *		errors from subroutines
 *
 * note: silly story of open/type/mode flag ...
 * at user level, open flag (O_xxxx) is defined by fcntl.h,
 * file type and permission flags (S_xxxx defined by 
 * sys/mode.h included in sys/stat.h);
 * in LFS, open flag is converted to file flag (Fxxxx defined 
 * by fcntl.h) and to vnode type (Vxxxx defined by sys/vnode.h);
 * in PFS, file type and permission is defined by Ixxxx flag
 * (also defined by sys/mode.h) in addition to file flag and
 * vnode type;
 */
jfs_open(
	struct vnode	*vp,		/* object vnode */
	int32		flag,		/* open(2) flag	*/
	uint32		oflag,		/* file existence options */
	EAOP		*pcEABuf,
	struct ucred	*crp)		/* credential */
{
	int32	rc, rc1 = 0;	
	inode_t *ip = VP2IP(vp);	/* object inode */
	int32 	type;
#ifdef _JFS_OS2
	FEALIST	*pfealist = NULL;
	inode_t	*iplist[1];
#endif	/* _JFS_OS2 */

jEVENT(0,("jfs_open(ip:0x%08x, flag:0x%08x)\n", ip, flag));

	/* validate file type */
	type = ip->i_mode & IFMT;
	if (! (type == IFREG || type == IFDIR))
	{
jEVENT(0,("jfs_open(ip:0x%08x, flag:0x%08x ERROR(EINVAL)\n", ip, flag));
		return EINVAL;
	}

#ifdef _JFS_OS2
	/* validate the EAOP buffer, FEALIST size storage location and the
	 * entire FEALIST storage area.  Once all the storage has been
	 * validated, the entire FEALIST is validated for format and the size is
	 * computed and compared against the limit.
	 */
	if (pcEABuf && (oflag & OPEN_ACTION_REPLACE_IF_EXISTS))
	{
		if (rc = jfs_ValidateUserFEAList(pcEABuf,
				&pfealist, &pcEABuf->oError))
		{
			/* something failed -- bail out */
			return rc;
		}
	}
#endif	/* _JFS_OS2 */

	/* named file does not exist anymore ? */
	if (ip->i_nlink == 0)
	{
		rc = ENOENT;
		goto out;
	}

	/* validate open access permission */
	if (rc = iOpenAccess(ip, flag, crp))
		goto out;

#ifdef _JFS_OS2
	rc = iOpen(ip, flag, oflag, pfealist, crp);
#endif

out:
#ifdef _JFS_OS2
		/*
		 * this buffer was allocated by
		 * jfs_ValidateUserFEAList() at twice the
		 * size of the given list to provide buffer
		 * space for eliminating duplicate names
		 */
	if (pfealist)
		jfs_EABufFree((char *)pfealist, (pfealist->cbList << 1));
#endif	/* _JFS_OS2 */

	/* If opening a file readonly, and we aren't explicitly told that
	 * the access is random, perform readahead of first 32K
	 */
	if ((rc == 0) &&
	    ((flag & (OPEN_ACCESS_READWRITE | OPEN_ACCESS_WRITEONLY)) ==
	     OPEN_ACCESS_READONLY) &&
	    ((flag & OPEN_FLAGS_RANDOM) == 0))
	{
		if (ip->i_size > 0)
			cmKickStart(ip);
	}

jEVENT(0,("jfs_open(rc:%d)\n", rc));

	return rc;
}