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

📄 namei.c

📁 jfs-2.4-1.1.7.tar.gz jfs 2.4-1.1.7 源码
💻 C
📖 第 1 页 / 共 3 页
字号:
				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;		}		ip->i_blocks = LBLK2PBLK(sb, xlen);	}	/*	 * 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)			dbFree(ip, extent, xlen);		txAbort(tid, 0);		/* discard new inode */		goto out3;	}	insert_inode_hash(ip);	mark_inode_dirty(ip);	/*	 * commit update of parent directory and link object	 */	iplist[0] = dip;	iplist[1] = ip;	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_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;	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,			      JFS_SBI(old_dir->i_sb)->nls_tab)))		goto out1;	if ((rc = get_UCSname(&new_dname, new_dentry,			      JFS_SBI(old_dir->i_sb)->nls_tab)))		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);	/*	 * The real work starts here	 */	tid = txBegin(new_dir->i_sb, 0);	down(&JFS_IP(new_dir)->commit_sem);	down(&JFS_IP(old_ip)->commit_sem);	if (old_dir != new_dir)		down(&JFS_IP(old_dir)->commit_sem);	if (new_ip) {		down(&JFS_IP(new_ip)->commit_sem);		/*		 * 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;		new_ip->i_nlink--;		if (S_ISDIR(new_ip->i_mode)) {			new_ip->i_nlink--;			if (new_ip->i_nlink) {				up(&JFS_IP(new_dir)->commit_sem);				up(&JFS_IP(old_ip)->commit_sem);				if (old_dir != new_dir)					up(&JFS_IP(old_dir)->commit_sem);				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->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->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) {			jfs_err("jfs_rename: dtInsert failed w/rc = %d",				rc);			goto out4;		}		if (S_ISDIR(old_ip->i_mode))			new_dir->i_nlink++;	}	/*	 * 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)) {		old_dir->i_nlink--;		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_TIME;	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);	up(&JFS_IP(new_dir)->commit_sem);	up(&JFS_IP(old_ip)->commit_sem);	if (old_dir != new_dir)		up(&JFS_IP(old_dir)->commit_sem);	if (new_ip)		up(&JFS_IP(new_ip)->commit_sem);	while (new_size && (rc == 0)) {		tid = txBegin(new_ip->i_sb, 0);		down(&JFS_IP(new_ip)->commit_sem);		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);		up(&JFS_IP(new_ip)->commit_sem);	}	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, int rdev){	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;	jfs_info("jfs_mknod: %s", dentry->d_name.name);	if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dir->i_sb)->nls_tab)))		goto out;	ip = ialloc(dir, mode);	if (ip == NULL) {		rc = -ENOSPC;		goto out1;	}	tid = txBegin(dir->i_sb, 0);	down(&JFS_IP(dir)->commit_sem);	down(&JFS_IP(ip)->commit_sem);	if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE)))		goto out3;	tblk = tid_to_tblock(tid);	tblk->xflag |= COMMIT_CREATE;	tblk->ip = ip;	ino = ip->i_ino;	if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack)))		goto out3;	ip->i_op = &jfs_special_inode_operations;	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);	up(&JFS_IP(ip)->commit_sem);	up(&JFS_IP(dir)->commit_sem);	if (rc) {		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 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 ((name[0] == '.') && (len == 1))		inum = dip->i_ino;	else if (strcmp(name, "..") == 0)		inum = PARENT(dip);	else {		if ((rc =		     get_UCSname(&key, dentry, JFS_SBI(dip->i_sb)->nls_tab)))			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) {		jfs_err("jfs_lookup: iget failed on inum %d", (uint) inum);		return ERR_PTR(-EACCES);	}	if (is_bad_inode(ip)) {		jfs_err("jfs_lookup: iget returned bad inode, inum = %d",			(uint) inum);		iput(ip);		return ERR_PTR(-EACCES);	}	d_add(dentry, ip);	return ERR_PTR(0);}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,#ifdef JFS_XATTR	.setxattr	= jfs_setxattr,	.getxattr	= jfs_getxattr,	.listxattr	= jfs_listxattr,	.removexattr	= jfs_removexattr,#endif};struct file_operations jfs_dir_operations = {	.read		= generic_read_dir,	.readdir	= jfs_readdir,	.fsync		= jfs_fsync,};

⌨️ 快捷键说明

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