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

📄 namei.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	}	/*	 * 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);	mutex_unlock(&JFS_IP(ip)->commit_mutex);	mutex_unlock(&JFS_IP(dip)->commit_mutex);	while (new_size && (rc == 0)) {		tid = txBegin(dip->i_sb, 0);		mutex_lock(&JFS_IP(ip)->commit_mutex);		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);		mutex_unlock(&JFS_IP(ip)->commit_mutex);	}	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:	jfs_free_zero_link() * * 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. */void jfs_free_zero_link(struct inode *ip){	int type;	jfs_info("jfs_free_zero_link: 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;		break;	default:		return;	}	/*	 * 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, NULL, 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, NULL, 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)		xtTruncate(0, ip, 0, COMMIT_WMAP);}/* * 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);	if (ip->i_nlink == JFS_LINK_MAX)		return -EMLINK;	if (ip->i_nlink == 0)		return -ENOENT;	tid = txBegin(ip->i_sb, 0);	mutex_lock_nested(&JFS_IP(dir)->commit_mutex, COMMIT_MUTEX_PARENT);	mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);	/*	 * scan parent directory for entry/freespace	 */	if ((rc = get_UCSname(&dname, dentry)))		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 */	inc_nlink(ip);		/* for new link */	ip->i_ctime = CURRENT_TIME;	dir->i_ctime = dir->i_mtime = 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) {		ip->i_nlink--; /* never instantiated */		iput(ip);	} else		d_instantiate(dentry, ip);      free_dname:	free_UCSname(&dname);      out:	txEnd(tid);	mutex_unlock(&JFS_IP(ip)->commit_mutex);	mutex_unlock(&JFS_IP(dir)->commit_mutex);	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)))		goto out1;	/*	 * allocate on-disk/in-memory inode for symbolic link:	 * (iAlloc() returns new, locked inode)	 */	ip = ialloc(dip, S_IFLNK | 0777);	if (IS_ERR(ip)) {		rc = PTR_ERR(ip);		goto out2;	}	tid = txBegin(dip->i_sb, 0);	mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);	mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);	rc = jfs_init_security(tid, ip, dip);	if (rc)		goto out3;	tblk = tid_to_tblock(tid);	tblk->xflag |= COMMIT_CREATE;	tblk->ino = ip->i_ino;	tblk->u.ixpxd = JFS_IP(ip)->ixpxd;	/* 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);			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) {				xtTruncate(tid, ip, 0, COMMIT_PWMAP);				rc = -EIO;				txAbort(tid, 0);				goto out3;			}			memcpy(mp->data, name, copy_size);			flush_metapage(mp);			ssize -= copy_size;			name += copy_size;			xaddr += JFS_SBI(sb)->nbperpage;		}	}	/*	 * create entry for symbolic link in parent directory	 */	rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE);	if (rc == 0) {		ino = ip->i_ino;		rc = dtInsert(tid, dip, &dname, &ino, &btstack);	}	if (rc) {		if (xlen)			xtTruncate(tid, ip, 0, COMMIT_PWMAP);		txAbort(tid, 0);		/* discard new inode */		goto out3;	}	insert_inode_hash(ip);	mark_inode_dirty(ip);	dip->i_ctime = dip->i_mtime = CURRENT_TIME;	mark_inode_dirty(dip);	/*	 * commit update of parent directory and link object	 */	iplist[0] = dip;	iplist[1] = ip;	rc = txCommit(tid, 2, &iplist[0], 0);      out3:	txEnd(tid);	mutex_unlock(&JFS_IP(ip)->commit_mutex);	mutex_unlock(&JFS_IP(dip)->commit_mutex);	if (rc) {		free_ea_wmap(ip);		ip->i_nlink = 0;		iput(ip);	} else		d_instantiate(dentry, ip);      out2:	free_UCSname(&dname);      out1:	jfs_info("jfs_symlink: rc:%d", rc);	return rc;}/* * NAME:	jfs_rename * * FUNCTION:	rename a file or directory */static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,	       struct inode *new_dir, struct dentry *new_dentry){	struct btstack btstack;	ino_t ino;	struct component_name new_dname;	struct inode *new_ip;	struct component_name old_dname;	struct inode *old_ip;	int rc;	tid_t tid;	struct tlock *tlck;	struct dt_lock *dtlck;	struct lv *lv;	int ipcount;

⌨️ 快捷键说明

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