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

📄 namei.c

📁 ocfs1.2.7 源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* -*- mode: c; c-basic-offset: 8; -*- * vim: noexpandtab sw=8 ts=8 sts=0: * * namei.c * * Create and rename file, directory, symlinks * * Copyright (C) 2002, 2004 Oracle.  All rights reserved. * *  Portions of this code from linux/fs/ext3/dir.c * *  Copyright (C) 1992, 1993, 1994, 1995 *  Remy Card (card@masi.ibp.fr) *  Laboratoire MASI - Institut Blaise pascal *  Universite Pierre et Marie Curie (Paris VI) * *   from * *   linux/fs/minix/dir.c * *   Copyright (C) 1991, 1992 Linux Torvalds * * 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 021110-1307, USA. */#include <linux/fs.h>#include <linux/types.h>#include <linux/slab.h>#include <linux/highmem.h>#define MLOG_MASK_PREFIX ML_NAMEI#include <cluster/masklog.h>#include "ocfs2.h"#include "alloc.h"#include "dcache.h"#include "dir.h"#include "dlmglue.h"#include "extent_map.h"#include "file.h"#include "inode.h"#include "journal.h"#include "namei.h"#include "suballoc.h"#include "symlink.h"#include "sysfile.h"#include "uptodate.h"#include "vote.h"#include "buffer_head_io.h"#define NAMEI_RA_CHUNKS  2#define NAMEI_RA_BLOCKS  4#define NAMEI_RA_SIZE        (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)#define NAMEI_RA_INDEX(c,b)  (((c) * NAMEI_RA_BLOCKS) + (b))static int inline ocfs2_search_dirblock(struct buffer_head *bh,					struct inode *dir,					const char *name, int namelen,					unsigned long offset,					struct ocfs2_dir_entry **res_dir);static int ocfs2_delete_entry(struct ocfs2_journal_handle *handle,			      struct inode *dir,			      struct ocfs2_dir_entry *de_del,			      struct buffer_head *bh);static int __ocfs2_add_entry(struct ocfs2_journal_handle *handle,			     struct inode *dir,			     const char *name, int namelen,			     struct inode *inode, u64 blkno,			     struct buffer_head *parent_fe_bh,			     struct buffer_head *insert_bh);static int ocfs2_mknod_locked(struct ocfs2_super *osb,			      struct inode *dir,			      struct dentry *dentry, int mode,			      dev_t dev,			      struct buffer_head **new_fe_bh,			      struct buffer_head *parent_fe_bh,			      struct ocfs2_journal_handle *handle,			      struct inode **ret_inode,			      struct ocfs2_alloc_context *inode_ac);static int ocfs2_fill_new_dir(struct ocfs2_super *osb,			      struct ocfs2_journal_handle *handle,			      struct inode *parent,			      struct inode *inode,			      struct buffer_head *fe_bh,			      struct ocfs2_alloc_context *data_ac);static int ocfs2_double_lock(struct ocfs2_super *osb,			     struct ocfs2_journal_handle *handle,			     struct buffer_head **bh1,			     struct inode *inode1,			     struct buffer_head **bh2,			     struct inode *inode2);static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,				    struct ocfs2_journal_handle *handle,				    struct inode *inode,				    char *name,				    struct buffer_head **de_bh);static int ocfs2_orphan_add(struct ocfs2_super *osb,			    struct ocfs2_journal_handle *handle,			    struct inode *inode,			    struct ocfs2_dinode *fe,			    char *name,			    struct buffer_head *de_bh);static int ocfs2_create_symlink_data(struct ocfs2_super *osb,				     struct ocfs2_journal_handle *handle,				     struct inode *inode,				     const char *symname);static inline int ocfs2_add_entry(struct ocfs2_journal_handle *handle,				  struct dentry *dentry,				  struct inode *inode, u64 blkno,				  struct buffer_head *parent_fe_bh,				  struct buffer_head *insert_bh){	return __ocfs2_add_entry(handle, dentry->d_parent->d_inode,				 dentry->d_name.name, dentry->d_name.len,				 inode, blkno, parent_fe_bh, insert_bh);}/* An orphan dir name is an 8 byte value, printed as a hex string */#define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64)))static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry,				   struct nameidata *nd){	int status;	u64 blkno;	struct buffer_head *dirent_bh = NULL;	struct inode *inode = NULL;	struct dentry *ret;	struct ocfs2_dir_entry *dirent;	struct ocfs2_inode_info *oi;	mlog_entry("(0x%p, 0x%p, '%.*s')\n", dir, dentry,		   dentry->d_name.len, dentry->d_name.name);	if (dentry->d_name.len > OCFS2_MAX_FILENAME_LEN) {		ret = ERR_PTR(-ENAMETOOLONG);		goto bail;	}	mlog(0, "find name %.*s in directory %"MLFu64"\n", dentry->d_name.len,	     dentry->d_name.name, OCFS2_I(dir)->ip_blkno);	status = ocfs2_meta_lock(dir, NULL, NULL, 0);	if (status < 0) {		if (status != -ENOENT)			mlog_errno(status);		ret = ERR_PTR(status);		goto bail;	}	status = ocfs2_find_files_on_disk(dentry->d_name.name,					  dentry->d_name.len, &blkno,					  dir, &dirent_bh, &dirent);	if (status < 0)		goto bail_add;	inode = ocfs2_iget(OCFS2_SB(dir->i_sb), blkno);	if (IS_ERR(inode)) {		mlog(ML_ERROR, "Unable to create inode %"MLFu64"\n", blkno);		ret = ERR_PTR(-EACCES);		goto bail_unlock;	}	oi = OCFS2_I(inode);	/* Clear any orphaned state... If we were able to look up the	 * inode from a directory, it certainly can't be orphaned. We	 * might have the bad state from a node which intended to	 * orphan this inode but crashed before it could commit the	 * unlink. */	spin_lock(&oi->ip_lock);	oi->ip_flags &= ~OCFS2_INODE_MAYBE_ORPHANED;	oi->ip_orphaned_slot = OCFS2_INVALID_SLOT;	oi->ip_deleting_node = O2NM_INVALID_NODE_NUM;	spin_unlock(&oi->ip_lock);bail_add:	dentry->d_op = &ocfs2_dentry_ops;	ret = d_splice_alias(inode, dentry);bail_unlock:	/* Don't drop the cluster lock until *after* the d_add --	 * unlink on another node will message us to remove that	 * dentry under this lock so otherwise we can race this with	 * the vote thread and have a stale dentry. */	ocfs2_meta_unlock(dir, 0);bail:	if (dirent_bh)		brelse(dirent_bh);	mlog_exit_ptr(ret);	return ret;}static int ocfs2_fill_new_dir(struct ocfs2_super *osb,			      struct ocfs2_journal_handle *handle,			      struct inode *parent,			      struct inode *inode,			      struct buffer_head *fe_bh,			      struct ocfs2_alloc_context *data_ac){	int status;	struct buffer_head *new_bh = NULL;	struct ocfs2_dir_entry *de = NULL;	mlog_entry_void();	status = ocfs2_do_extend_dir(osb->sb, handle, inode, fe_bh,				     data_ac, NULL, &new_bh);	if (status < 0) {		mlog_errno(status);		goto bail;	}	ocfs2_set_new_buffer_uptodate(inode, new_bh);	status = ocfs2_journal_access(handle, inode, new_bh,				      OCFS2_JOURNAL_ACCESS_CREATE);	if (status < 0) {		mlog_errno(status);		goto bail;	}	memset(new_bh->b_data, 0, osb->sb->s_blocksize);	de = (struct ocfs2_dir_entry *) new_bh->b_data;	de->inode = cpu_to_le64(OCFS2_I(inode)->ip_blkno);	de->name_len = 1;	de->rec_len =		cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len));	strcpy(de->name, ".");	ocfs2_set_de_type(de, S_IFDIR);	de = (struct ocfs2_dir_entry *) ((char *)de + le16_to_cpu(de->rec_len));	de->inode = cpu_to_le64(OCFS2_I(parent)->ip_blkno);	de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize -				  OCFS2_DIR_REC_LEN(1));	de->name_len = 2;	strcpy(de->name, "..");	ocfs2_set_de_type(de, S_IFDIR);	status = ocfs2_journal_dirty(handle, new_bh);	if (status < 0) {		mlog_errno(status);		goto bail;	}	i_size_write(inode, inode->i_sb->s_blocksize);	inode->i_nlink = 2;	inode->i_blocks = ocfs2_align_bytes_to_sectors(inode->i_sb->s_blocksize);	status = ocfs2_mark_inode_dirty(handle, inode, fe_bh);	if (status < 0) {		mlog_errno(status);		goto bail;	}	status = 0;bail:	if (new_bh)		brelse(new_bh);	mlog_exit(status);	return status;}static int ocfs2_mknod(struct inode *dir,		       struct dentry *dentry,		       int mode,		       dev_t dev){	int status = 0;	struct buffer_head *parent_fe_bh = NULL;	struct ocfs2_journal_handle *handle = NULL;	struct ocfs2_super *osb;	struct ocfs2_dinode *dirfe;	struct buffer_head *new_fe_bh = NULL;	struct buffer_head *de_bh = NULL;	struct inode *inode = NULL;	struct ocfs2_alloc_context *inode_ac = NULL;	struct ocfs2_alloc_context *data_ac = NULL;	mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode,		   (unsigned long)dev, dentry->d_name.len,		   dentry->d_name.name);	/* get our super block */	osb = OCFS2_SB(dir->i_sb);	if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) {		mlog(ML_ERROR, "inode %"MLFu64" has i_nlink of %u\n",		     OCFS2_I(dir)->ip_blkno, dir->i_nlink);		status = -EMLINK;		goto leave;	}	handle = ocfs2_alloc_handle(osb);	if (handle == NULL) {		status = -ENOMEM;		mlog_errno(status);		goto leave;	}	status = ocfs2_meta_lock(dir, handle, &parent_fe_bh, 1);	if (status < 0) {		if (status != -ENOENT)			mlog_errno(status);		goto leave;	}	dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data;	if (!dirfe->i_links_count) {		/* can't make a file in a deleted directory. */		status = -ENOENT;		goto leave;	}	status = ocfs2_check_dir_for_entry(dir, dentry->d_name.name,					   dentry->d_name.len);	if (status)		goto leave;	/* get a spot inside the dir. */	status = ocfs2_prepare_dir_for_insert(osb, dir, parent_fe_bh,					      dentry->d_name.name,					      dentry->d_name.len, &de_bh);	if (status < 0) {		mlog_errno(status);		goto leave;	}	/* reserve an inode spot */	status = ocfs2_reserve_new_inode(osb, handle, &inode_ac);	if (status < 0) {		if (status != -ENOSPC)			mlog_errno(status);		goto leave;	}	/* are we making a directory? If so, reserve a cluster for his	 * 1st extent. */	if (S_ISDIR(mode)) {		status = ocfs2_reserve_clusters(osb, handle, 1, &data_ac);		if (status < 0) {			if (status != -ENOSPC)				mlog_errno(status);			goto leave;		}	}	handle = ocfs2_start_trans(osb, handle, OCFS2_MKNOD_CREDITS);	if (IS_ERR(handle)) {		status = PTR_ERR(handle);		handle = NULL;		mlog_errno(status);		goto leave;	}	/* do the real work now. */	status = ocfs2_mknod_locked(osb, dir, dentry, mode, dev,				    &new_fe_bh, parent_fe_bh, handle,				    &inode, inode_ac);	if (status < 0) {		mlog_errno(status);		goto leave;	}	if (S_ISDIR(mode)) {		status = ocfs2_fill_new_dir(osb, handle, dir, inode,					    new_fe_bh, data_ac);		if (status < 0) {			mlog_errno(status);			goto leave;		}		status = ocfs2_journal_access(handle, dir, parent_fe_bh,					      OCFS2_JOURNAL_ACCESS_WRITE);		if (status < 0) {			mlog_errno(status);			goto leave;		}		le16_add_cpu(&dirfe->i_links_count, 1);		status = ocfs2_journal_dirty(handle, parent_fe_bh);		if (status < 0) {			mlog_errno(status);			goto leave;		}		dir->i_nlink++;	}	status = ocfs2_add_entry(handle, dentry, inode,				 OCFS2_I(inode)->ip_blkno, parent_fe_bh,				 de_bh);	if (status < 0) {		mlog_errno(status);		goto leave;	}	insert_inode_hash(inode);	dentry->d_op = &ocfs2_dentry_ops;	d_instantiate(dentry, inode);	status = 0;leave:	if (handle)		ocfs2_commit_trans(handle);	if (status == -ENOSPC)		mlog(0, "Disk is full\n");	if (new_fe_bh)		brelse(new_fe_bh);	if (de_bh)		brelse(de_bh);	if (parent_fe_bh)		brelse(parent_fe_bh);	if ((status < 0) && inode)		iput(inode);	if (inode_ac)		ocfs2_free_alloc_context(inode_ac);	if (data_ac)		ocfs2_free_alloc_context(data_ac);	mlog_exit(status);	return status;}static int ocfs2_mknod_locked(struct ocfs2_super *osb,			      struct inode *dir,			      struct dentry *dentry, int mode,			      dev_t dev,			      struct buffer_head **new_fe_bh,			      struct buffer_head *parent_fe_bh,			      struct ocfs2_journal_handle *handle,			      struct inode **ret_inode,			      struct ocfs2_alloc_context *inode_ac){	int status = 0;	struct ocfs2_dinode *fe = NULL;	struct ocfs2_extent_list *fel;	u64 fe_blkno = 0;	u16 suballoc_bit;	struct inode *inode = NULL;	mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode,		   (unsigned long)dev, dentry->d_name.len,		   dentry->d_name.name);	*new_fe_bh = NULL;	*ret_inode = NULL;	status = ocfs2_claim_new_inode(osb, handle, inode_ac, &suballoc_bit,				       &fe_blkno);	if (status < 0) {		mlog_errno(status);		goto leave;	}	inode = new_inode(dir->i_sb);	if (IS_ERR(inode)) {		status = PTR_ERR(inode);		mlog(ML_ERROR, "new_inode failed!\n");		goto leave;	}	/* populate as many fields early on as possible - many of	 * these are used by the support functions here and in	 * callers. */	inode->i_ino = ino_from_blkno(osb->sb, fe_blkno);	OCFS2_I(inode)->ip_blkno = fe_blkno;	if (S_ISDIR(mode))		inode->i_nlink = 2;	else		inode->i_nlink = 1;	inode->i_mode = mode;	spin_lock(&osb->osb_lock);	inode->i_generation = osb->s_next_generation++;	spin_unlock(&osb->osb_lock);	*new_fe_bh = sb_getblk(osb->sb, fe_blkno);	if (!*new_fe_bh) {		status = -EIO;		mlog_errno(status);		goto leave;	}	ocfs2_set_new_buffer_uptodate(inode, *new_fe_bh);	status = ocfs2_journal_access(handle, inode, *new_fe_bh,				      OCFS2_JOURNAL_ACCESS_CREATE);	if (status < 0) {		mlog_errno(status);		goto leave;	}	fe = (struct ocfs2_dinode *) (*new_fe_bh)->b_data;	memset(fe, 0, osb->sb->s_blocksize);	fe->i_generation = cpu_to_le32(inode->i_generation);	fe->i_fs_generation = cpu_to_le32(osb->fs_generation);	fe->i_blkno = cpu_to_le64(fe_blkno);	fe->i_suballoc_bit = cpu_to_le16(suballoc_bit);	fe->i_suballoc_slot = cpu_to_le16(osb->slot_num);	fe->i_uid = cpu_to_le32(current->fsuid);	if (dir->i_mode & S_ISGID) {		fe->i_gid = cpu_to_le32(dir->i_gid);		if (S_ISDIR(mode))			mode |= S_ISGID;	} else		fe->i_gid = cpu_to_le32(current->fsgid);	fe->i_mode = cpu_to_le16(mode);	if (S_ISCHR(mode) || S_ISBLK(mode))		fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev));	fe->i_links_count = cpu_to_le16(inode->i_nlink);	fe->i_last_eb_blk = 0;	strcpy(fe->i_signature, OCFS2_INODE_SIGNATURE);	le32_add_cpu(&fe->i_flags, OCFS2_VALID_FL);	fe->i_atime = fe->i_ctime = fe->i_mtime =		cpu_to_le64(CURRENT_TIME.tv_sec);	fe->i_mtime_nsec = fe->i_ctime_nsec = fe->i_atime_nsec =		cpu_to_le32(CURRENT_TIME.tv_nsec);	fe->i_dtime = 0;	fel = &fe->id2.i_list;	fel->l_tree_depth = 0;	fel->l_next_free_rec = 0;	fel->l_count = cpu_to_le16(ocfs2_extent_recs_per_inode(osb->sb));	status = ocfs2_journal_dirty(handle, *new_fe_bh);	if (status < 0) {		mlog_errno(status);		goto leave;	}	if (ocfs2_populate_inode(inode, fe, 1) < 0) {		mlog(ML_ERROR, "populate inode failed! bh->b_blocknr=%llu, "		     "i_blkno=%"MLFu64", i_ino=%lu\n",		     (unsigned long long) (*new_fe_bh)->b_blocknr,		     fe->i_blkno, inode->i_ino);

⌨️ 快捷键说明

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