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

📄 namei.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	nls_name.hash = full_name_hash(nls_name.name, nls_name.len);	/*	 * Note: No need for dent->d_lock lock as i_mutex is held on the	 * parent inode.	 */	/* Does a dentry matching the nls_name exist already? */	real_dent = d_lookup(dent->d_parent, &nls_name);	/* If not, create it now. */	if (!real_dent) {		real_dent = d_alloc(dent->d_parent, &nls_name);		kfree(nls_name.name);		if (!real_dent) {			err = -ENOMEM;			goto err_out;		}		new_dent = d_splice_alias(dent_inode, real_dent);		if (new_dent)			dput(real_dent);		else			new_dent = real_dent;		ntfs_debug("Done.  (Created new dentry.)");		return new_dent;	}	kfree(nls_name.name);	/* Matching dentry exists, check if it is negative. */	if (real_dent->d_inode) {		if (unlikely(real_dent->d_inode != dent_inode)) {			/* This can happen because bad inodes are unhashed. */			BUG_ON(!is_bad_inode(dent_inode));			BUG_ON(!is_bad_inode(real_dent->d_inode));		}		/*		 * Already have the inode and the dentry attached, decrement		 * the reference count to balance the ntfs_iget() we did		 * earlier on.  We found the dentry using d_lookup() so it		 * cannot be disconnected and thus we do not need to worry		 * about any NFS/disconnectedness issues here.		 */		iput(dent_inode);		ntfs_debug("Done.  (Already had inode and dentry.)");		return real_dent;	}	/*	 * Negative dentry: instantiate it unless the inode is a directory and	 * has a 'disconnected' dentry (i.e. IS_ROOT and DCACHE_DISCONNECTED),	 * in which case d_move() that in place of the found dentry.	 */	if (!S_ISDIR(dent_inode->i_mode)) {		/* Not a directory; everything is easy. */		d_instantiate(real_dent, dent_inode);		ntfs_debug("Done.  (Already had negative file dentry.)");		return real_dent;	}	spin_lock(&dcache_lock);	if (list_empty(&dent_inode->i_dentry)) {		/*		 * Directory without a 'disconnected' dentry; we need to do		 * d_instantiate() by hand because it takes dcache_lock which		 * we already hold.		 */		list_add(&real_dent->d_alias, &dent_inode->i_dentry);		real_dent->d_inode = dent_inode;		spin_unlock(&dcache_lock);		security_d_instantiate(real_dent, dent_inode);		ntfs_debug("Done.  (Already had negative directory dentry.)");		return real_dent;	}	/*	 * Directory with a 'disconnected' dentry; get a reference to the	 * 'disconnected' dentry.	 */	new_dent = list_entry(dent_inode->i_dentry.next, struct dentry,			d_alias);	dget_locked(new_dent);	spin_unlock(&dcache_lock);	/* Do security vodoo. */	security_d_instantiate(real_dent, dent_inode);	/* Move new_dent in place of real_dent. */	d_move(new_dent, real_dent);	/* Balance the ntfs_iget() we did above. */	iput(dent_inode);	/* Throw away real_dent. */	dput(real_dent);	/* Use new_dent as the actual dentry. */	ntfs_debug("Done.  (Already had negative, disconnected directory "			"dentry.)");	return new_dent;eio_err_out:	ntfs_error(vol->sb, "Illegal file name attribute. Run chkdsk.");	err = -EIO;err_out:	if (ctx)		ntfs_attr_put_search_ctx(ctx);	if (m)		unmap_mft_record(ni);	iput(dent_inode);	ntfs_error(vol->sb, "Failed, returning error code %i.", err);	return ERR_PTR(err);   }}/** * Inode operations for directories. */const struct inode_operations ntfs_dir_inode_ops = {	.lookup	= ntfs_lookup,	/* VFS: Lookup directory. */};/** * ntfs_get_parent - find the dentry of the parent of a given directory dentry * @child_dent:		dentry of the directory whose parent directory to find * * Find the dentry for the parent directory of the directory specified by the * dentry @child_dent.  This function is called from * fs/exportfs/expfs.c::find_exported_dentry() which in turn is called from the * default ->decode_fh() which is export_decode_fh() in the same file. * * The code is based on the ext3 ->get_parent() implementation found in * fs/ext3/namei.c::ext3_get_parent(). * * Note: ntfs_get_parent() is called with @child_dent->d_inode->i_mutex down. * * Return the dentry of the parent directory on success or the error code on * error (IS_ERR() is true). */static struct dentry *ntfs_get_parent(struct dentry *child_dent){	struct inode *vi = child_dent->d_inode;	ntfs_inode *ni = NTFS_I(vi);	MFT_RECORD *mrec;	ntfs_attr_search_ctx *ctx;	ATTR_RECORD *attr;	FILE_NAME_ATTR *fn;	struct inode *parent_vi;	struct dentry *parent_dent;	unsigned long parent_ino;	int err;	ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);	/* Get the mft record of the inode belonging to the child dentry. */	mrec = map_mft_record(ni);	if (IS_ERR(mrec))		return (struct dentry *)mrec;	/* Find the first file name attribute in the mft record. */	ctx = ntfs_attr_get_search_ctx(ni, mrec);	if (unlikely(!ctx)) {		unmap_mft_record(ni);		return ERR_PTR(-ENOMEM);	}try_next:	err = ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, CASE_SENSITIVE, 0, NULL,			0, ctx);	if (unlikely(err)) {		ntfs_attr_put_search_ctx(ctx);		unmap_mft_record(ni);		if (err == -ENOENT)			ntfs_error(vi->i_sb, "Inode 0x%lx does not have a "					"file name attribute.  Run chkdsk.",					vi->i_ino);		return ERR_PTR(err);	}	attr = ctx->attr;	if (unlikely(attr->non_resident))		goto try_next;	fn = (FILE_NAME_ATTR *)((u8 *)attr +			le16_to_cpu(attr->data.resident.value_offset));	if (unlikely((u8 *)fn + le32_to_cpu(attr->data.resident.value_length) >			(u8*)attr + le32_to_cpu(attr->length)))		goto try_next;	/* Get the inode number of the parent directory. */	parent_ino = MREF_LE(fn->parent_directory);	/* Release the search context and the mft record of the child. */	ntfs_attr_put_search_ctx(ctx);	unmap_mft_record(ni);	/* Get the inode of the parent directory. */	parent_vi = ntfs_iget(vi->i_sb, parent_ino);	if (IS_ERR(parent_vi) || unlikely(is_bad_inode(parent_vi))) {		if (!IS_ERR(parent_vi))			iput(parent_vi);		ntfs_error(vi->i_sb, "Failed to get parent directory inode "				"0x%lx of child inode 0x%lx.", parent_ino,				vi->i_ino);		return ERR_PTR(-EACCES);	}	/* Finally get a dentry for the parent directory and return it. */	parent_dent = d_alloc_anon(parent_vi);	if (unlikely(!parent_dent)) {		iput(parent_vi);		return ERR_PTR(-ENOMEM);	}	ntfs_debug("Done for inode 0x%lx.", vi->i_ino);	return parent_dent;}static struct inode *ntfs_nfs_get_inode(struct super_block *sb,		u64 ino, u32 generation){	struct inode *inode;	inode = ntfs_iget(sb, ino);	if (!IS_ERR(inode)) {		if (is_bad_inode(inode) || inode->i_generation != generation) {			iput(inode);			inode = ERR_PTR(-ESTALE);		}	}	return inode;}static struct dentry *ntfs_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,				    ntfs_nfs_get_inode);}static struct dentry *ntfs_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,				    ntfs_nfs_get_inode);}/** * Export operations allowing NFS exporting of mounted NTFS partitions. * * We use the default ->encode_fh() for now.  Note that they * use 32 bits to store the inode number which is an unsigned long so on 64-bit * architectures is usually 64 bits so it would all fail horribly on huge * volumes.  I guess we need to define our own encode and decode fh functions * that store 64-bit inode numbers at some point but for now we will ignore the * problem... * * We also use the default ->get_name() helper (used by ->decode_fh() via * fs/exportfs/expfs.c::find_exported_dentry()) as that is completely fs * independent. * * The default ->get_parent() just returns -EACCES so we have to provide our * own and the default ->get_dentry() is incompatible with NTFS due to not * allowing the inode number 0 which is used in NTFS for the system file $MFT * and due to using iget() whereas NTFS needs ntfs_iget(). */const struct export_operations ntfs_export_ops = {	.get_parent	= ntfs_get_parent,	/* Find the parent of a given						   directory. */	.fh_to_dentry	= ntfs_fh_to_dentry,	.fh_to_parent	= ntfs_fh_to_parent,};

⌨️ 快捷键说明

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