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

📄 namei.c

📁 jfs-2.4-1.1.7.tar.gz jfs 2.4-1.1.7 源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *   Copyright (C) International Business Machines Corp., 2000-2003 *   Portions Copyright (C) Christoph Hellwig, 2001-2002 * *   This program is free software;  you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or  *   (at your option) any later version. *  *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY;  without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See *   the GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program;  if not, write to the Free Software  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <linux/fs.h>#include "jfs_incore.h"#include "jfs_superblock.h"#include "jfs_inode.h"#include "jfs_dinode.h"#include "jfs_dmap.h"#include "jfs_unicode.h"#include "jfs_metapage.h"#include "jfs_xattr.h"#include "jfs_debug.h"extern struct inode_operations jfs_file_inode_operations;extern struct inode_operations jfs_symlink_inode_operations;extern struct inode_operations jfs_special_inode_operations;extern struct file_operations jfs_file_operations;extern struct address_space_operations jfs_aops;extern int jfs_fsync(struct file *, struct dentry *, int);extern void jfs_truncate_nolock(struct inode *, loff_t);/* * forward references */struct inode_operations jfs_dir_inode_operations;struct file_operations jfs_dir_operations;static s64 commitZeroLink(tid_t, struct inode *);/* * NAME:	jfs_create(dip, dentry, mode) * * FUNCTION:	create a regular file in the parent directory <dip> *		with name = <from dentry> and mode = <mode> * * PARAMETER:	dip 	- parent directory vnode *		dentry	- dentry of new file *		mode	- create mode (rwxrwxrwx). * * RETURN:	Errors from subroutines * */static int jfs_create(struct inode *dip, struct dentry *dentry, int mode){	int rc = 0;	tid_t tid;		/* transaction id */	struct inode *ip = NULL;	/* child directory inode */	ino_t ino;	struct component_name dname;	/* child directory name */	struct btstack btstack;	struct inode *iplist[2];	struct tblock *tblk;	jfs_info("jfs_create: dip:0x%p name:%s", dip, dentry->d_name.name);	/*	 * 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;	/*	 * 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.	 */	ip = ialloc(dip, mode);	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);	if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {		jfs_err("jfs_create: dtSearch returned %d", rc);		goto out3;	}	tblk = tid_to_tblock(tid);	tblk->xflag |= COMMIT_CREATE;	tblk->ip = ip;	iplist[0] = dip;	iplist[1] = ip;	/*	 * initialize the child XAD tree root in-line in inode	 */	xtInitRoot(tid, ip);	/*	 * create entry in parent directory for child directory	 * (dtInsert() releases parent directory page)	 */	ino = ip->i_ino;	if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {		jfs_err("jfs_create: dtInsert returned %d", rc);		if (rc == -EIO)			txAbort(tid, 1);	/* Marks Filesystem dirty */		else			txAbort(tid, 0);	/* Filesystem full */		goto out3;	}	ip->i_op = &jfs_file_inode_operations;	ip->i_fop = &jfs_file_operations;	ip->i_mapping->a_ops = &jfs_aops;	insert_inode_hash(ip);	mark_inode_dirty(ip);	dip->i_ctime = dip->i_mtime = CURRENT_TIME;	mark_inode_dirty(dip);	rc = txCommit(tid, 2, &iplist[0], 0);      out3:	txEnd(tid);	up(&JFS_IP(dip)->commit_sem);	up(&JFS_IP(ip)->commit_sem);	if (rc) {		ip->i_nlink = 0;		iput(ip);	} else		d_instantiate(dentry, ip);      out2:	free_UCSname(&dname);      out1:	jfs_info("jfs_create: rc:%d", rc);	return rc;}/* * NAME:	jfs_mkdir(dip, dentry, mode) * * FUNCTION:	create a child directory in the parent directory <dip> *		with name = <from dentry> and mode = <mode> * * PARAMETER:	dip 	- parent directory vnode *		dentry	- dentry of child directory *		mode	- create mode (rwxrwxrwx). * * RETURN:	Errors from subroutines * * note: * EACCESS: user needs search+write permission on the parent directory */static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode){	int rc = 0;	tid_t tid;		/* transaction id */	struct inode *ip = NULL;	/* child directory inode */	ino_t ino;	struct component_name dname;	/* child directory name */	struct btstack btstack;	struct inode *iplist[2];	struct tblock *tblk;	jfs_info("jfs_mkdir: dip:0x%p name:%s", dip, dentry->d_name.name);	/* link count overflow on parent directory ? */	if (dip->i_nlink == JFS_LINK_MAX) {		rc = -EMLINK;		goto out1;	}	/*	 * 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;	/*	 * 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.	 */	ip = ialloc(dip, S_IFDIR | mode);	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);	if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {		jfs_err("jfs_mkdir: dtSearch returned %d", rc);		goto out3;	}	tblk = tid_to_tblock(tid);	tblk->xflag |= COMMIT_CREATE;	tblk->ip = ip;	iplist[0] = dip;	iplist[1] = ip;	/*	 * initialize the child directory in-line in inode	 */	dtInitRoot(tid, ip, dip->i_ino);	/*	 * create entry in parent directory for child directory	 * (dtInsert() releases parent directory page)	 */	ino = ip->i_ino;	if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {		jfs_err("jfs_mkdir: dtInsert returned %d", rc);		if (rc == -EIO)			txAbort(tid, 1);	/* Marks Filesystem dirty */		else			txAbort(tid, 0);	/* Filesystem full */		goto out3;	}	ip->i_nlink = 2;	/* for '.' */	ip->i_op = &jfs_dir_inode_operations;	ip->i_fop = &jfs_dir_operations;	ip->i_mapping->a_ops = &jfs_aops;	ip->i_mapping->gfp_mask = GFP_NOFS;	insert_inode_hash(ip);	mark_inode_dirty(ip);	/* update parent directory inode */	dip->i_nlink++;		/* for '..' from child directory */	dip->i_ctime = dip->i_mtime = CURRENT_TIME;	mark_inode_dirty(dip);	rc = txCommit(tid, 2, &iplist[0], 0);      out3:	txEnd(tid);	up(&JFS_IP(dip)->commit_sem);	up(&JFS_IP(ip)->commit_sem);	if (rc) {		ip->i_nlink = 0;		iput(ip);	} else		d_instantiate(dentry, ip);      out2:	free_UCSname(&dname);      out1:	jfs_info("jfs_mkdir: rc:%d", rc);	return rc;}/* * NAME:	jfs_rmdir(dip, dentry) * * FUNCTION:	remove a link to child directory * * PARAMETER:	dip 	- parent inode *		dentry	- child directory dentry * * RETURN:	-EINVAL	- if name is . or .. *		-EINVAL  - if . or .. exist but are invalid. *		errors from subroutines * * note: * if other threads have the directory open when the last link  * is removed, the "." and ".." entries, if present, are removed before  * rmdir() returns and no new entries may be created in the directory,  * but the directory is not removed until the last reference to  * the directory is released (cf.unlink() of regular file). */static int jfs_rmdir(struct inode *dip, struct dentry *dentry){	int rc;	tid_t tid;		/* transaction id */	struct inode *ip = dentry->d_inode;	ino_t ino;	struct component_name dname;	struct inode *iplist[2];	struct tblock *tblk;	jfs_info("jfs_rmdir: dip:0x%p name:%s", dip, dentry->d_name.name);	/* directory must be empty to be removed */	if (!dtEmpty(ip)) {		rc = -ENOTEMPTY;		goto out;	}	if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dip->i_sb)->nls_tab))) {		goto out;	}	tid = txBegin(dip->i_sb, 0);	down(&JFS_IP(dip)->commit_sem);	down(&JFS_IP(ip)->commit_sem);	iplist[0] = dip;	iplist[1] = ip;	tblk = tid_to_tblock(tid);	tblk->xflag |= COMMIT_DELETE;	tblk->ip = ip;	/*	 * delete the entry of target directory from parent directory	 */	ino = ip->i_ino;	if ((rc = dtDelete(tid, dip, &dname, &ino, JFS_REMOVE))) {		jfs_err("jfs_rmdir: dtDelete returned %d", rc);		if (rc == -EIO)			txAbort(tid, 1);		txEnd(tid);		up(&JFS_IP(dip)->commit_sem);		up(&JFS_IP(ip)->commit_sem);		goto out2;	}	/* update parent directory's link count corresponding	 * to ".." entry of the target directory deleted	 */	dip->i_nlink--;	dip->i_ctime = dip->i_mtime = CURRENT_TIME;	mark_inode_dirty(dip);	/*	 * OS/2 could have created EA and/or ACL	 */	/* free EA from both persistent and working map */	if (JFS_IP(ip)->ea.flag & DXD_EXTENT) {		/* free EA pages */		txEA(tid, ip, &JFS_IP(ip)->ea, NULL);	}	JFS_IP(ip)->ea.flag = 0;	/* free ACL from both persistent and working map */	if (JFS_IP(ip)->acl.flag & DXD_EXTENT) {		/* free ACL pages */		txEA(tid, ip, &JFS_IP(ip)->acl, NULL);	}	JFS_IP(ip)->acl.flag = 0;	/* mark the target directory as deleted */	ip->i_nlink = 0;	mark_inode_dirty(ip);	rc = txCommit(tid, 2, &iplist[0], 0);	txEnd(tid);	up(&JFS_IP(dip)->commit_sem);	up(&JFS_IP(ip)->commit_sem);	/*	 * 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);	}      out2:	free_UCSname(&dname);      out:	jfs_info("jfs_rmdir: rc:%d", rc);	return rc;}/* * NAME:	jfs_unlink(dip, dentry) * * FUNCTION:	remove a link to object <vp> named by <name>  *		from parent directory <dvp> * * PARAMETER:	dip 	- inode of parent directory *		dentry 	- dentry of object to be removed * * RETURN:	errors from subroutines * * note: * temporary file: if one or more processes have the file open * when the last link is removed, the link will be removed before * unlink() returns, but the removal of the file contents will be * postponed until all references to the files are closed. * * JFS does NOT support unlink() on directories. * */static int jfs_unlink(struct inode *dip, struct dentry *dentry){	int rc;	tid_t tid;		/* transaction id */	struct inode *ip = dentry->d_inode;	ino_t ino;	struct component_name dname;	/* object name */	struct inode *iplist[2];	struct tblock *tblk;	s64 new_size = 0;	int commit_flag;	jfs_info("jfs_unlink: dip:0x%p name:%s", dip, dentry->d_name.name);	if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dip->i_sb)->nls_tab)))		goto out;	IWRITE_LOCK(ip);	tid = txBegin(dip->i_sb, 0);	down(&JFS_IP(dip)->commit_sem);	down(&JFS_IP(ip)->commit_sem);	iplist[0] = dip;	iplist[1] = ip;	/*	 * delete the entry of target file from parent directory	 */	ino = ip->i_ino;	if ((rc = dtDelete(tid, dip, &dname, &ino, JFS_REMOVE))) {		jfs_err("jfs_unlink: dtDelete returned %d", rc);		if (rc == -EIO)			txAbort(tid, 1);	/* Marks FS Dirty */		txEnd(tid);		up(&JFS_IP(dip)->commit_sem);		up(&JFS_IP(ip)->commit_sem);		IWRITE_UNLOCK(ip);		goto out1;	}	ASSERT(ip->i_nlink);	ip->i_ctime = dip->i_ctime = dip->i_mtime = CURRENT_TIME;	mark_inode_dirty(dip);	/* update target's inode */	ip->i_nlink--;	mark_inode_dirty(ip);	/*

⌨️ 快捷键说明

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