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

📄 namei.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	struct inode *iplist[4];	struct tblock *tblk;	s64 new_size = 0;	int commit_flag;	jfs_info("jfs_rename: %s %s", old_dentry->d_name.name,		 new_dentry->d_name.name);	old_ip = old_dentry->d_inode;	new_ip = new_dentry->d_inode;	if ((rc = get_UCSname(&old_dname, old_dentry)))		goto out1;	if ((rc = get_UCSname(&new_dname, new_dentry)))		goto out2;	/*	 * Make sure source inode number is what we think it is	 */	rc = dtSearch(old_dir, &old_dname, &ino, &btstack, JFS_LOOKUP);	if (rc || (ino != old_ip->i_ino)) {		rc = -ENOENT;		goto out3;	}	/*	 * Make sure dest inode number (if any) is what we think it is	 */	rc = dtSearch(new_dir, &new_dname, &ino, &btstack, JFS_LOOKUP);	if (rc == 0) {		if ((new_ip == 0) || (ino != new_ip->i_ino)) {			rc = -ESTALE;			goto out3;		}	} else if (rc != -ENOENT)		goto out3;	else if (new_ip) {		/* no entry exists, but one was expected */		rc = -ESTALE;		goto out3;	}	if (S_ISDIR(old_ip->i_mode)) {		if (new_ip) {			if (!dtEmpty(new_ip)) {				rc = -ENOTEMPTY;				goto out3;			}		} else if ((new_dir != old_dir) &&			   (new_dir->i_nlink == JFS_LINK_MAX)) {			rc = -EMLINK;			goto out3;		}	} else if (new_ip) {		IWRITE_LOCK(new_ip, RDWRLOCK_NORMAL);		/* Init inode for quota operations. */		DQUOT_INIT(new_ip);	}	/*	 * The real work starts here	 */	tid = txBegin(new_dir->i_sb, 0);	/*	 * How do we know the locking is safe from deadlocks?	 * The vfs does the hard part for us.  Any time we are taking nested	 * commit_mutexes, the vfs already has i_mutex held on the parent.	 * Here, the vfs has already taken i_mutex on both old_dir and new_dir.	 */	mutex_lock_nested(&JFS_IP(new_dir)->commit_mutex, COMMIT_MUTEX_PARENT);	mutex_lock_nested(&JFS_IP(old_ip)->commit_mutex, COMMIT_MUTEX_CHILD);	if (old_dir != new_dir)		mutex_lock_nested(&JFS_IP(old_dir)->commit_mutex,				  COMMIT_MUTEX_SECOND_PARENT);	if (new_ip) {		mutex_lock_nested(&JFS_IP(new_ip)->commit_mutex,				  COMMIT_MUTEX_VICTIM);		/*		 * Change existing directory entry to new inode number		 */		ino = new_ip->i_ino;		rc = dtModify(tid, new_dir, &new_dname, &ino,			      old_ip->i_ino, JFS_RENAME);		if (rc)			goto out4;		drop_nlink(new_ip);		if (S_ISDIR(new_ip->i_mode)) {			drop_nlink(new_ip);			if (new_ip->i_nlink) {				mutex_unlock(&JFS_IP(new_ip)->commit_mutex);				if (old_dir != new_dir)					mutex_unlock(&JFS_IP(old_dir)->commit_mutex);				mutex_unlock(&JFS_IP(old_ip)->commit_mutex);				mutex_unlock(&JFS_IP(new_dir)->commit_mutex);				if (!S_ISDIR(old_ip->i_mode) && new_ip)					IWRITE_UNLOCK(new_ip);				jfs_error(new_ip->i_sb,					  "jfs_rename: new_ip->i_nlink != 0");				return -EIO;			}			tblk = tid_to_tblock(tid);			tblk->xflag |= COMMIT_DELETE;			tblk->u.ip = new_ip;		} else if (new_ip->i_nlink == 0) {			assert(!test_cflag(COMMIT_Nolink, new_ip));			/* free block resources */			if ((new_size = commitZeroLink(tid, new_ip)) < 0) {				txAbort(tid, 1);	/* Marks FS Dirty */				rc = new_size;				goto out4;			}			tblk = tid_to_tblock(tid);			tblk->xflag |= COMMIT_DELETE;			tblk->u.ip = new_ip;		} else {			new_ip->i_ctime = CURRENT_TIME;			mark_inode_dirty(new_ip);		}	} else {		/*		 * Add new directory entry		 */		rc = dtSearch(new_dir, &new_dname, &ino, &btstack,			      JFS_CREATE);		if (rc) {			jfs_err("jfs_rename didn't expect dtSearch to fail "				"w/rc = %d", rc);			goto out4;		}		ino = old_ip->i_ino;		rc = dtInsert(tid, new_dir, &new_dname, &ino, &btstack);		if (rc) {			if (rc == -EIO)				jfs_err("jfs_rename: dtInsert returned -EIO");			goto out4;		}		if (S_ISDIR(old_ip->i_mode))			inc_nlink(new_dir);	}	/*	 * Remove old directory entry	 */	ino = old_ip->i_ino;	rc = dtDelete(tid, old_dir, &old_dname, &ino, JFS_REMOVE);	if (rc) {		jfs_err("jfs_rename did not expect dtDelete to return rc = %d",			rc);		txAbort(tid, 1);	/* Marks Filesystem dirty */		goto out4;	}	if (S_ISDIR(old_ip->i_mode)) {		drop_nlink(old_dir);		if (old_dir != new_dir) {			/*			 * Change inode number of parent for moved directory			 */			JFS_IP(old_ip)->i_dtroot.header.idotdot =				cpu_to_le32(new_dir->i_ino);			/* Linelock header of dtree */			tlck = txLock(tid, old_ip,				    (struct metapage *) &JFS_IP(old_ip)->bxflag,				      tlckDTREE | tlckBTROOT | tlckRELINK);			dtlck = (struct dt_lock *) & tlck->lock;			ASSERT(dtlck->index == 0);			lv = & dtlck->lv[0];			lv->offset = 0;			lv->length = 1;			dtlck->index++;		}	}	/*	 * Update ctime on changed/moved inodes & mark dirty	 */	old_ip->i_ctime = CURRENT_TIME;	mark_inode_dirty(old_ip);	new_dir->i_ctime = new_dir->i_mtime = current_fs_time(new_dir->i_sb);	mark_inode_dirty(new_dir);	/* Build list of inodes modified by this transaction */	ipcount = 0;	iplist[ipcount++] = old_ip;	if (new_ip)		iplist[ipcount++] = new_ip;	iplist[ipcount++] = old_dir;	if (old_dir != new_dir) {		iplist[ipcount++] = new_dir;		old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;		mark_inode_dirty(old_dir);	}	/*	 * 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;	rc = txCommit(tid, ipcount, iplist, commit_flag);      out4:	txEnd(tid);	if (new_ip)		mutex_unlock(&JFS_IP(new_ip)->commit_mutex);	if (old_dir != new_dir)		mutex_unlock(&JFS_IP(old_dir)->commit_mutex);	mutex_unlock(&JFS_IP(old_ip)->commit_mutex);	mutex_unlock(&JFS_IP(new_dir)->commit_mutex);	while (new_size && (rc == 0)) {		tid = txBegin(new_ip->i_sb, 0);		mutex_lock(&JFS_IP(new_ip)->commit_mutex);		new_size = xtTruncate_pmap(tid, new_ip, new_size);		if (new_size < 0) {			txAbort(tid, 1);			rc = new_size;		} else			rc = txCommit(tid, 1, &new_ip, COMMIT_SYNC);		txEnd(tid);		mutex_unlock(&JFS_IP(new_ip)->commit_mutex);	}	if (new_ip && (new_ip->i_nlink == 0))		set_cflag(COMMIT_Nolink, new_ip);      out3:	free_UCSname(&new_dname);      out2:	free_UCSname(&old_dname);      out1:	if (new_ip && !S_ISDIR(new_ip->i_mode))		IWRITE_UNLOCK(new_ip);	/*	 * Truncating the directory index table is not guaranteed.  It	 * may need to be done iteratively	 */	if (test_cflag(COMMIT_Stale, old_dir)) {		if (old_dir->i_size > 1)			jfs_truncate_nolock(old_dir, 0);		clear_cflag(COMMIT_Stale, old_dir);	}	jfs_info("jfs_rename: returning %d", rc);	return rc;}/* * NAME:	jfs_mknod * * FUNCTION:	Create a special file (device) */static int jfs_mknod(struct inode *dir, struct dentry *dentry,		int mode, dev_t rdev){	struct jfs_inode_info *jfs_ip;	struct btstack btstack;	struct component_name dname;	ino_t ino;	struct inode *ip;	struct inode *iplist[2];	int rc;	tid_t tid;	struct tblock *tblk;	if (!new_valid_dev(rdev))		return -EINVAL;	jfs_info("jfs_mknod: %s", dentry->d_name.name);	if ((rc = get_UCSname(&dname, dentry)))		goto out;	ip = ialloc(dir, mode);	if (IS_ERR(ip)) {		rc = PTR_ERR(ip);		goto out1;	}	jfs_ip = JFS_IP(ip);	tid = txBegin(dir->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);	rc = jfs_init_acl(tid, ip, dir);	if (rc)		goto out3;	rc = jfs_init_security(tid, ip, dir);	if (rc) {		txAbort(tid, 0);		goto out3;	}	if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE))) {		txAbort(tid, 0);		goto out3;	}	tblk = tid_to_tblock(tid);	tblk->xflag |= COMMIT_CREATE;	tblk->ino = ip->i_ino;	tblk->u.ixpxd = JFS_IP(ip)->ixpxd;	ino = ip->i_ino;	if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack))) {		txAbort(tid, 0);		goto out3;	}	ip->i_op = &jfs_file_inode_operations;	jfs_ip->dev = new_encode_dev(rdev);	init_special_inode(ip, ip->i_mode, rdev);	insert_inode_hash(ip);	mark_inode_dirty(ip);	dir->i_ctime = dir->i_mtime = CURRENT_TIME;	mark_inode_dirty(dir);	iplist[0] = dir;	iplist[1] = ip;	rc = txCommit(tid, 2, iplist, 0);      out3:	txEnd(tid);	mutex_unlock(&JFS_IP(ip)->commit_mutex);	mutex_unlock(&JFS_IP(dir)->commit_mutex);	if (rc) {		free_ea_wmap(ip);		ip->i_nlink = 0;		iput(ip);	} else		d_instantiate(dentry, ip);      out1:	free_UCSname(&dname);      out:	jfs_info("jfs_mknod: returning %d", rc);	return rc;}static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struct nameidata *nd){	struct btstack btstack;	ino_t inum;	struct inode *ip;	struct component_name key;	const char *name = dentry->d_name.name;	int len = dentry->d_name.len;	int rc;	jfs_info("jfs_lookup: name = %s", name);	if (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2)		dentry->d_op = &jfs_ci_dentry_operations;	if ((name[0] == '.') && (len == 1))		inum = dip->i_ino;	else if (strcmp(name, "..") == 0)		inum = PARENT(dip);	else {		if ((rc = get_UCSname(&key, dentry)))			return ERR_PTR(rc);		rc = dtSearch(dip, &key, &inum, &btstack, JFS_LOOKUP);		free_UCSname(&key);		if (rc == -ENOENT) {			d_add(dentry, NULL);			return ERR_PTR(0);		} else if (rc) {			jfs_err("jfs_lookup: dtSearch returned %d", rc);			return ERR_PTR(rc);		}	}	ip = iget(dip->i_sb, inum);	if (ip == NULL || is_bad_inode(ip)) {		jfs_err("jfs_lookup: iget failed on inum %d", (uint) inum);		if (ip)			iput(ip);		return ERR_PTR(-EACCES);	}	dentry = d_splice_alias(ip, dentry);	if (dentry && (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2))		dentry->d_op = &jfs_ci_dentry_operations;	return dentry;}static struct inode *jfs_nfs_get_inode(struct super_block *sb,		u64 ino, u32 generation){	struct inode *inode;	if (ino == 0)		return ERR_PTR(-ESTALE);	inode = iget(sb, ino);	if (inode == NULL)		return ERR_PTR(-ENOMEM);	if (is_bad_inode(inode) ||	    (generation && inode->i_generation != generation)) {		iput(inode);		return ERR_PTR(-ESTALE);	}	return inode;}struct dentry *jfs_fh_to_dentry(struct super_block *sb, struct fid *fid,		int fh_len, int fh_type){	return generic_fh_to_dentry(sb, fid, fh_len, fh_type,				    jfs_nfs_get_inode);}struct dentry *jfs_fh_to_parent(struct super_block *sb, struct fid *fid,		int fh_len, int fh_type){	return generic_fh_to_parent(sb, fid, fh_len, fh_type,				    jfs_nfs_get_inode);}struct dentry *jfs_get_parent(struct dentry *dentry){	struct super_block *sb = dentry->d_inode->i_sb;	struct dentry *parent = ERR_PTR(-ENOENT);	struct inode *inode;	unsigned long parent_ino;	parent_ino =		le32_to_cpu(JFS_IP(dentry->d_inode)->i_dtroot.header.idotdot);	inode = iget(sb, parent_ino);	if (inode) {		if (is_bad_inode(inode)) {			iput(inode);			parent = ERR_PTR(-EACCES);		} else {			parent = d_alloc_anon(inode);			if (!parent) {				parent = ERR_PTR(-ENOMEM);				iput(inode);			}		}	}	return parent;}const struct inode_operations jfs_dir_inode_operations = {	.create		= jfs_create,	.lookup		= jfs_lookup,	.link		= jfs_link,	.unlink		= jfs_unlink,	.symlink	= jfs_symlink,	.mkdir		= jfs_mkdir,	.rmdir		= jfs_rmdir,	.mknod		= jfs_mknod,	.rename		= jfs_rename,	.setxattr	= jfs_setxattr,	.getxattr	= jfs_getxattr,	.listxattr	= jfs_listxattr,	.removexattr	= jfs_removexattr,#ifdef CONFIG_JFS_POSIX_ACL	.setattr	= jfs_setattr,	.permission	= jfs_permission,#endif};const struct file_operations jfs_dir_operations = {	.read		= generic_read_dir,	.readdir	= jfs_readdir,	.fsync		= jfs_fsync,	.ioctl		= jfs_ioctl,};static int jfs_ci_hash(struct dentry *dir, struct qstr *this){	unsigned long hash;	int i;	hash = init_name_hash();	for (i=0; i < this->len; i++)		hash = partial_name_hash(tolower(this->name[i]), hash);	this->hash = end_name_hash(hash);	return 0;}static int jfs_ci_compare(struct dentry *dir, struct qstr *a, struct qstr *b){	int i, result = 1;	if (a->len != b->len)		goto out;	for (i=0; i < a->len; i++) {		if (tolower(a->name[i]) != tolower(b->name[i]))			goto out;	}	result = 0;	/*	 * We want creates to preserve case.  A negative dentry, a, that	 * has a different case than b may cause a new entry to be created	 * with the wrong case.  Since we can't tell if a comes from a negative	 * dentry, we blindly replace it with b.  This should be harmless if	 * a is not a negative dentry.	 */	memcpy((unsigned char *)a->name, b->name, a->len);out:	return result;}struct dentry_operations jfs_ci_dentry_operations ={	.d_hash = jfs_ci_hash,	.d_compare = jfs_ci_compare,};

⌨️ 快捷键说明

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