⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 namei.c

📁 jfs-2.4-1.1.7.tar.gz jfs 2.4-1.1.7 源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	 *      commit zero link count object	 */	if (ip->i_nlink == 0) {		assert(!test_cflag(COMMIT_Nolink, ip));		/* free block resources */		if ((new_size = commitZeroLink(tid, ip)) < 0) {			txAbort(tid, 1);	/* Marks FS Dirty */			txEnd(tid);			up(&JFS_IP(dip)->commit_sem);			up(&JFS_IP(ip)->commit_sem);			IWRITE_UNLOCK(ip);			rc = new_size;			goto out1;		}		tblk = tid_to_tblock(tid);		tblk->xflag |= COMMIT_DELETE;		tblk->ip = ip;	}	/*	 * Incomplete truncate of file data can	 * result in timing problems unless we synchronously commit the	 * transaction.	 */	if (new_size)		commit_flag = COMMIT_SYNC;	else		commit_flag = 0;	/*	 * If xtTruncate was incomplete, commit synchronously to avoid	 * timing complications	 */	rc = txCommit(tid, 2, &iplist[0], commit_flag);	txEnd(tid);	up(&JFS_IP(dip)->commit_sem);	up(&JFS_IP(ip)->commit_sem);	while (new_size && (rc == 0)) {		tid = txBegin(dip->i_sb, 0);		down(&JFS_IP(ip)->commit_sem);		new_size = xtTruncate_pmap(tid, ip, new_size);		if (new_size < 0) {			txAbort(tid, 1);	/* Marks FS Dirty */			rc = new_size;		} else			rc = txCommit(tid, 2, &iplist[0], COMMIT_SYNC);		txEnd(tid);		up(&JFS_IP(ip)->commit_sem);	}	if (ip->i_nlink == 0)		set_cflag(COMMIT_Nolink, ip);	IWRITE_UNLOCK(ip);	/*	 * Truncating the directory index table is not guaranteed.  It	 * may need to be done iteratively	 */	if (test_cflag(COMMIT_Stale, dip)) {		if (dip->i_size > 1)			jfs_truncate_nolock(dip, 0);		clear_cflag(COMMIT_Stale, dip);	}      out1:	free_UCSname(&dname);      out:	jfs_info("jfs_unlink: rc:%d", rc);	return rc;}/* * NAME:	commitZeroLink() * * FUNCTION:    for non-directory, called by jfs_remove(), *		truncate a regular file, directory or symbolic *		link to zero length. return 0 if type is not  *		one of these. * *		if the file is currently associated with a VM segment *		only permanent disk and inode map resources are freed, *		and neither the inode nor indirect blocks are modified *		so that the resources can be later freed in the work *		map by ctrunc1. *		if there is no VM segment on entry, the resources are *		freed in both work and permanent map. *		(? for temporary file - memory object is cached even  *		after no reference: *		reference count > 0 -   ) * * PARAMETERS:	cd	- pointer to commit data structure. *			  current inode is the one to truncate. * * RETURN:	Errors from subroutines */static s64 commitZeroLink(tid_t tid, struct inode *ip){	int filetype;	struct tblock *tblk;	jfs_info("commitZeroLink: tid = %d, ip = 0x%p", tid, ip);	filetype = ip->i_mode & S_IFMT;	switch (filetype) {	case S_IFREG:		break;	case S_IFLNK:		/* fast symbolic link */		if (ip->i_size < IDATASIZE) {			ip->i_size = 0;			return 0;		}		break;	default:		assert(filetype != S_IFDIR);		return 0;	}	set_cflag(COMMIT_Freewmap, ip);	/* mark transaction of block map update type */	tblk = tid_to_tblock(tid);	tblk->xflag |= COMMIT_PMAP;	/*	 * free EA	 */	if (JFS_IP(ip)->ea.flag & DXD_EXTENT)		/* acquire maplock on EA to be freed from block map */		txEA(tid, ip, &JFS_IP(ip)->ea, NULL);	/*	 * free ACL	 */	if (JFS_IP(ip)->acl.flag & DXD_EXTENT)		/* acquire maplock on EA to be freed from block map */		txEA(tid, ip, &JFS_IP(ip)->acl, NULL);	/*	 * free xtree/data (truncate to zero length):	 * free xtree/data pages from cache if COMMIT_PWMAP, 	 * free xtree/data blocks from persistent block map, and	 * free xtree/data blocks from working block map if COMMIT_PWMAP;	 */	if (ip->i_size)		return xtTruncate_pmap(tid, ip, 0);	return 0;}/* * NAME:	freeZeroLink() * * FUNCTION:    for non-directory, called by iClose(), *		free resources of a file from cache and WORKING map  *		for a file previously committed with zero link count *		while associated with a pager object, * * PARAMETER:	ip	- pointer to inode of file. * * RETURN:	0 -ok */int freeZeroLink(struct inode *ip){	int rc = 0;	int type;	jfs_info("freeZeroLink: ip = 0x%p", ip);	/* return if not reg or symbolic link or if size is	 * already ok.	 */	type = ip->i_mode & S_IFMT;	switch (type) {	case S_IFREG:		break;	case S_IFLNK:		/* if its contained in inode nothing to do */		if (ip->i_size < IDATASIZE)			return 0;		break;	default:		return 0;	}	/*	 * free EA	 */	if (JFS_IP(ip)->ea.flag & DXD_EXTENT) {		s64 xaddr = addressDXD(&JFS_IP(ip)->ea);		int xlen = lengthDXD(&JFS_IP(ip)->ea);		struct maplock maplock;	/* maplock for COMMIT_WMAP */		struct pxd_lock *pxdlock;	/* maplock for COMMIT_WMAP */		/* free EA pages from cache */		invalidate_dxd_metapages(ip, JFS_IP(ip)->ea);		/* free EA extent from working block map */		maplock.index = 1;		pxdlock = (struct pxd_lock *) & maplock;		pxdlock->flag = mlckFREEPXD;		PXDaddress(&pxdlock->pxd, xaddr);		PXDlength(&pxdlock->pxd, xlen);		txFreeMap(ip, pxdlock, 0, COMMIT_WMAP);	}	/*	 * free ACL	 */	if (JFS_IP(ip)->acl.flag & DXD_EXTENT) {		s64 xaddr = addressDXD(&JFS_IP(ip)->acl);		int xlen = lengthDXD(&JFS_IP(ip)->acl);		struct maplock maplock;	/* maplock for COMMIT_WMAP */		struct pxd_lock *pxdlock;	/* maplock for COMMIT_WMAP */		invalidate_dxd_metapages(ip, JFS_IP(ip)->acl);		/* free ACL extent from working block map */		maplock.index = 1;		pxdlock = (struct pxd_lock *) & maplock;		pxdlock->flag = mlckFREEPXD;		PXDaddress(&pxdlock->pxd, xaddr);		PXDlength(&pxdlock->pxd, xlen);		txFreeMap(ip, pxdlock, 0, COMMIT_WMAP);	}	/*	 * free xtree/data (truncate to zero length):	 * free xtree/data pages from cache, and	 * free xtree/data blocks from working block map;	 */	if (ip->i_size)		rc = xtTruncate(0, ip, 0, COMMIT_WMAP);	return rc;}/* * NAME:	jfs_link(vp, dvp, name, crp) * * FUNCTION:	create a link to <vp> by the name = <name> *		in the parent directory <dvp> * * PARAMETER:	vp 	- target object *		dvp	- parent directory of new link *		name	- name of new link to target object *		crp	- credential * * RETURN:	Errors from subroutines * * note: * JFS does NOT support link() on directories (to prevent circular * path in the directory hierarchy); * EPERM: the target object is a directory, and either the caller * does not have appropriate privileges or the implementation prohibits * using link() on directories [XPG4.2]. * * JFS does NOT support links between file systems: * EXDEV: target object and new link are on different file systems and * implementation does not support links between file systems [XPG4.2]. */static int jfs_link(struct dentry *old_dentry,	     struct inode *dir, struct dentry *dentry){	int rc;	tid_t tid;	struct inode *ip = old_dentry->d_inode;	ino_t ino;	struct component_name dname;	struct btstack btstack;	struct inode *iplist[2];	jfs_info("jfs_link: %s %s", old_dentry->d_name.name,		 dentry->d_name.name);	/* JFS does NOT support link() on directories */	if (S_ISDIR(ip->i_mode))		return -EPERM;	tid = txBegin(ip->i_sb, 0);	down(&JFS_IP(dir)->commit_sem);	down(&JFS_IP(ip)->commit_sem);	if (ip->i_nlink == JFS_LINK_MAX) {		rc = -EMLINK;		goto out;	}	if (ip->i_nlink == 0) {		rc = -ENOENT;		goto out;	}	/*	 * scan parent directory for entry/freespace	 */	if ((rc = get_UCSname(&dname, dentry, JFS_SBI(ip->i_sb)->nls_tab)))		goto out;	if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE)))		goto free_dname;	/*	 * create entry for new link in parent directory	 */	ino = ip->i_ino;	if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack)))		goto free_dname;	/* update object inode */	ip->i_nlink++;		/* for new link */	ip->i_ctime = CURRENT_TIME;	mark_inode_dirty(dir);	atomic_inc(&ip->i_count);	iplist[0] = ip;	iplist[1] = dir;	rc = txCommit(tid, 2, &iplist[0], 0);	if (!rc)		d_instantiate(dentry, ip);      free_dname:	free_UCSname(&dname);      out:	txEnd(tid);	up(&JFS_IP(dir)->commit_sem);	up(&JFS_IP(ip)->commit_sem);	jfs_info("jfs_link: rc:%d", rc);	return rc;}/* * NAME:	jfs_symlink(dip, dentry, name) * * FUNCTION:	creates a symbolic link to <symlink> by name <name> *		        in directory <dip> * * PARAMETER:	dip	    - parent directory vnode *		        dentry 	- dentry of symbolic link *		        name    - the path name of the existing object  *			              that will be the source of the link * * RETURN:	errors from subroutines * * note: * ENAMETOOLONG: pathname resolution of a symbolic link produced * an intermediate result whose length exceeds PATH_MAX [XPG4.2]*/static int jfs_symlink(struct inode *dip, struct dentry *dentry,		const char *name){	int rc;	tid_t tid;	ino_t ino = 0;	struct component_name dname;	int ssize;		/* source pathname size */	struct btstack btstack;	struct inode *ip = dentry->d_inode;	unchar *i_fastsymlink;	s64 xlen = 0;	int bmask = 0, xsize;	s64 extent = 0, xaddr;	struct metapage *mp;	struct super_block *sb;	struct tblock *tblk;	struct inode *iplist[2];	jfs_info("jfs_symlink: dip:0x%p name:%s", dip, name);	ssize = strlen(name) + 1;	/*	 * search parent directory for entry/freespace	 * (dtSearch() returns parent directory page pinned)	 */	if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dip->i_sb)->nls_tab)))		goto out1;	/*	 * allocate on-disk/in-memory inode for symbolic link:	 * (iAlloc() returns new, locked inode)	 */	ip = ialloc(dip, S_IFLNK | 0777);	if (ip == NULL) {		rc = -ENOSPC;		goto out2;	}	tid = txBegin(dip->i_sb, 0);	down(&JFS_IP(dip)->commit_sem);	down(&JFS_IP(ip)->commit_sem);	tblk = tid_to_tblock(tid);	tblk->xflag |= COMMIT_CREATE;	tblk->ip = ip;	/* fix symlink access permission	 * (dir_create() ANDs in the u.u_cmask, 	 * but symlinks really need to be 777 access)	 */	ip->i_mode |= 0777;	/*	 * write symbolic link target path name	 */	xtInitRoot(tid, ip);	/*	 * write source path name inline in on-disk inode (fast symbolic link)	 */	if (ssize <= IDATASIZE) {		ip->i_op = &jfs_symlink_inode_operations;		i_fastsymlink = JFS_IP(ip)->i_inline;		memcpy(i_fastsymlink, name, ssize);		ip->i_size = ssize - 1;		/*		 * if symlink is > 128 bytes, we don't have the space to		 * store inline extended attributes		 */		if (ssize > sizeof (JFS_IP(ip)->i_inline))			JFS_IP(ip)->mode2 &= ~INLINEEA;		jfs_info("jfs_symlink: fast symlink added  ssize:%d name:%s ",			 ssize, name);	}	/*	 * write source path name in a single extent	 */	else {		jfs_info("jfs_symlink: allocate extent ip:0x%p", ip);		ip->i_op = &page_symlink_inode_operations;		ip->i_mapping->a_ops = &jfs_aops;		/*		 * even though the data of symlink object (source 		 * path name) is treated as non-journaled user data,		 * it is read/written thru buffer cache for performance.		 */		sb = ip->i_sb;		bmask = JFS_SBI(sb)->bsize - 1;		xsize = (ssize + bmask) & ~bmask;		xaddr = 0;		xlen = xsize >> JFS_SBI(sb)->l2bsize;		if ((rc = xtInsert(tid, ip, 0, 0, xlen, &xaddr, 0))) {			txAbort(tid, 0);			rc = -ENOSPC;			goto out3;		}		extent = xaddr;		ip->i_size = ssize - 1;		while (ssize) {			/* This is kind of silly since PATH_MAX == 4K */			int copy_size = min(ssize, PSIZE);			mp = get_metapage(ip, xaddr, PSIZE, 1);			if (mp == NULL) {				dbFree(ip, extent, xlen);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -