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

📄 inode.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	if ((name->len == 1 && memcmp(name->name, ".", 1) == 0) ||	    (name->len == 2 && memcmp(name->name, "..", 2) == 0 &&	     dir == sb->s_root->d_inode)) {		igrab(dir);		return dir;	}	if (gfs2_glock_is_locked_by_me(dip->i_gl) == 0) {		error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);		if (error)			return ERR_PTR(error);		unlock = 1;	}	if (!is_root) {		error = permission(dir, MAY_EXEC, NULL);		if (error)			goto out;	}	inode = gfs2_dir_search(dir, name);	if (IS_ERR(inode))		error = PTR_ERR(inode);out:	if (unlock)		gfs2_glock_dq_uninit(&d_gh);	if (error == -ENOENT)		return NULL;	return inode ? inode : ERR_PTR(error);}static void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf){	const struct gfs2_inum_range *str = buf;	ir->ir_start = be64_to_cpu(str->ir_start);	ir->ir_length = be64_to_cpu(str->ir_length);}static void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf){	struct gfs2_inum_range *str = buf;	str->ir_start = cpu_to_be64(ir->ir_start);	str->ir_length = cpu_to_be64(ir->ir_length);}static int pick_formal_ino_1(struct gfs2_sbd *sdp, u64 *formal_ino){	struct gfs2_inode *ip = GFS2_I(sdp->sd_ir_inode);	struct buffer_head *bh;	struct gfs2_inum_range_host ir;	int error;	error = gfs2_trans_begin(sdp, RES_DINODE, 0);	if (error)		return error;	mutex_lock(&sdp->sd_inum_mutex);	error = gfs2_meta_inode_buffer(ip, &bh);	if (error) {		mutex_unlock(&sdp->sd_inum_mutex);		gfs2_trans_end(sdp);		return error;	}	gfs2_inum_range_in(&ir, bh->b_data + sizeof(struct gfs2_dinode));	if (ir.ir_length) {		*formal_ino = ir.ir_start++;		ir.ir_length--;		gfs2_trans_add_bh(ip->i_gl, bh, 1);		gfs2_inum_range_out(&ir,				    bh->b_data + sizeof(struct gfs2_dinode));		brelse(bh);		mutex_unlock(&sdp->sd_inum_mutex);		gfs2_trans_end(sdp);		return 0;	}	brelse(bh);	mutex_unlock(&sdp->sd_inum_mutex);	gfs2_trans_end(sdp);	return 1;}static int pick_formal_ino_2(struct gfs2_sbd *sdp, u64 *formal_ino){	struct gfs2_inode *ip = GFS2_I(sdp->sd_ir_inode);	struct gfs2_inode *m_ip = GFS2_I(sdp->sd_inum_inode);	struct gfs2_holder gh;	struct buffer_head *bh;	struct gfs2_inum_range_host ir;	int error;	error = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);	if (error)		return error;	error = gfs2_trans_begin(sdp, 2 * RES_DINODE, 0);	if (error)		goto out;	mutex_lock(&sdp->sd_inum_mutex);	error = gfs2_meta_inode_buffer(ip, &bh);	if (error)		goto out_end_trans;	gfs2_inum_range_in(&ir, bh->b_data + sizeof(struct gfs2_dinode));	if (!ir.ir_length) {		struct buffer_head *m_bh;		u64 x, y;		__be64 z;		error = gfs2_meta_inode_buffer(m_ip, &m_bh);		if (error)			goto out_brelse;		z = *(__be64 *)(m_bh->b_data + sizeof(struct gfs2_dinode));		x = y = be64_to_cpu(z);		ir.ir_start = x;		ir.ir_length = GFS2_INUM_QUANTUM;		x += GFS2_INUM_QUANTUM;		if (x < y)			gfs2_consist_inode(m_ip);		z = cpu_to_be64(x);		gfs2_trans_add_bh(m_ip->i_gl, m_bh, 1);		*(__be64 *)(m_bh->b_data + sizeof(struct gfs2_dinode)) = z;		brelse(m_bh);	}	*formal_ino = ir.ir_start++;	ir.ir_length--;	gfs2_trans_add_bh(ip->i_gl, bh, 1);	gfs2_inum_range_out(&ir, bh->b_data + sizeof(struct gfs2_dinode));out_brelse:	brelse(bh);out_end_trans:	mutex_unlock(&sdp->sd_inum_mutex);	gfs2_trans_end(sdp);out:	gfs2_glock_dq_uninit(&gh);	return error;}static int pick_formal_ino(struct gfs2_sbd *sdp, u64 *inum){	int error;	error = pick_formal_ino_1(sdp, inum);	if (error <= 0)		return error;	error = pick_formal_ino_2(sdp, inum);	return error;}/** * create_ok - OK to create a new on-disk inode here? * @dip:  Directory in which dinode is to be created * @name:  Name of new dinode * @mode: * * Returns: errno */static int create_ok(struct gfs2_inode *dip, const struct qstr *name,		     unsigned int mode){	int error;	error = permission(&dip->i_inode, MAY_WRITE | MAY_EXEC, NULL);	if (error)		return error;	/*  Don't create entries in an unlinked directory  */	if (!dip->i_inode.i_nlink)		return -EPERM;	error = gfs2_dir_check(&dip->i_inode, name, NULL);	switch (error) {	case -ENOENT:		error = 0;		break;	case 0:		return -EEXIST;	default:		return error;	}	if (dip->i_di.di_entries == (u32)-1)		return -EFBIG;	if (S_ISDIR(mode) && dip->i_inode.i_nlink == (u32)-1)		return -EMLINK;	return 0;}static void munge_mode_uid_gid(struct gfs2_inode *dip, unsigned int *mode,			       unsigned int *uid, unsigned int *gid){	if (GFS2_SB(&dip->i_inode)->sd_args.ar_suiddir &&	    (dip->i_inode.i_mode & S_ISUID) && dip->i_inode.i_uid) {		if (S_ISDIR(*mode))			*mode |= S_ISUID;		else if (dip->i_inode.i_uid != current->fsuid)			*mode &= ~07111;		*uid = dip->i_inode.i_uid;	} else		*uid = current->fsuid;	if (dip->i_inode.i_mode & S_ISGID) {		if (S_ISDIR(*mode))			*mode |= S_ISGID;		*gid = dip->i_inode.i_gid;	} else		*gid = current->fsgid;}static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation){	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);	int error;	gfs2_alloc_get(dip);	dip->i_alloc.al_requested = RES_DINODE;	error = gfs2_inplace_reserve(dip);	if (error)		goto out;	error = gfs2_trans_begin(sdp, RES_RG_BIT + RES_STATFS, 0);	if (error)		goto out_ipreserv;	*no_addr = gfs2_alloc_di(dip, generation);	gfs2_trans_end(sdp);out_ipreserv:	gfs2_inplace_release(dip);out:	gfs2_alloc_put(dip);	return error;}/** * init_dinode - Fill in a new dinode structure * @dip: the directory this inode is being created in * @gl: The glock covering the new inode * @inum: the inode number * @mode: the file permissions * @uid: * @gid: * */static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,			const struct gfs2_inum_host *inum, unsigned int mode,			unsigned int uid, unsigned int gid,			const u64 *generation, dev_t dev, struct buffer_head **bhp){	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);	struct gfs2_dinode *di;	struct buffer_head *dibh;	struct timespec tv = CURRENT_TIME;	dibh = gfs2_meta_new(gl, inum->no_addr);	gfs2_trans_add_bh(gl, dibh, 1);	gfs2_metatype_set(dibh, GFS2_METATYPE_DI, GFS2_FORMAT_DI);	gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));	di = (struct gfs2_dinode *)dibh->b_data;	di->di_num.no_formal_ino = cpu_to_be64(inum->no_formal_ino);	di->di_num.no_addr = cpu_to_be64(inum->no_addr);	di->di_mode = cpu_to_be32(mode);	di->di_uid = cpu_to_be32(uid);	di->di_gid = cpu_to_be32(gid);	di->di_nlink = 0;	di->di_size = 0;	di->di_blocks = cpu_to_be64(1);	di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(tv.tv_sec);	di->di_major = cpu_to_be32(MAJOR(dev));	di->di_minor = cpu_to_be32(MINOR(dev));	di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr);	di->di_generation = cpu_to_be64(*generation);	di->di_flags = 0;	if (S_ISREG(mode)) {		if ((dip->i_di.di_flags & GFS2_DIF_INHERIT_JDATA) ||		    gfs2_tune_get(sdp, gt_new_files_jdata))			di->di_flags |= cpu_to_be32(GFS2_DIF_JDATA);		if ((dip->i_di.di_flags & GFS2_DIF_INHERIT_DIRECTIO) ||		    gfs2_tune_get(sdp, gt_new_files_directio))			di->di_flags |= cpu_to_be32(GFS2_DIF_DIRECTIO);	} else if (S_ISDIR(mode)) {		di->di_flags |= cpu_to_be32(dip->i_di.di_flags &					    GFS2_DIF_INHERIT_DIRECTIO);		di->di_flags |= cpu_to_be32(dip->i_di.di_flags &					    GFS2_DIF_INHERIT_JDATA);	}	di->__pad1 = 0;	di->di_payload_format = cpu_to_be32(S_ISDIR(mode) ? GFS2_FORMAT_DE : 0);	di->di_height = 0;	di->__pad2 = 0;	di->__pad3 = 0;	di->di_depth = 0;	di->di_entries = 0;	memset(&di->__pad4, 0, sizeof(di->__pad4));	di->di_eattr = 0;	di->di_atime_nsec = cpu_to_be32(tv.tv_nsec);	di->di_mtime_nsec = cpu_to_be32(tv.tv_nsec);	di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec);	memset(&di->di_reserved, 0, sizeof(di->di_reserved));		set_buffer_uptodate(dibh);	*bhp = dibh;}static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,		       unsigned int mode, const struct gfs2_inum_host *inum,		       const u64 *generation, dev_t dev, struct buffer_head **bhp){	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);	unsigned int uid, gid;	int error;	munge_mode_uid_gid(dip, &mode, &uid, &gid);	gfs2_alloc_get(dip);	error = gfs2_quota_lock(dip, uid, gid);	if (error)		goto out;	error = gfs2_quota_check(dip, uid, gid);	if (error)		goto out_quota;	error = gfs2_trans_begin(sdp, RES_DINODE + RES_QUOTA, 0);	if (error)		goto out_quota;	init_dinode(dip, gl, inum, mode, uid, gid, generation, dev, bhp);	gfs2_quota_change(dip, +1, uid, gid);	gfs2_trans_end(sdp);out_quota:	gfs2_quota_unlock(dip);out:	gfs2_alloc_put(dip);	return error;}static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,		       struct gfs2_inode *ip){	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);	struct gfs2_alloc *al;	int alloc_required;	struct buffer_head *dibh;	int error;	al = gfs2_alloc_get(dip);	error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);	if (error)		goto fail;	error = alloc_required = gfs2_diradd_alloc_required(&dip->i_inode, name);	if (alloc_required < 0)		goto fail;	if (alloc_required) {		error = gfs2_quota_check(dip, dip->i_inode.i_uid, dip->i_inode.i_gid);		if (error)			goto fail_quota_locks;		al->al_requested = sdp->sd_max_dirres;		error = gfs2_inplace_reserve(dip);		if (error)			goto fail_quota_locks;		error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +					 al->al_rgd->rd_length +					 2 * RES_DINODE +					 RES_STATFS + RES_QUOTA, 0);		if (error)			goto fail_ipreserv;	} else {		error = gfs2_trans_begin(sdp, RES_LEAF + 2 * RES_DINODE, 0);		if (error)			goto fail_quota_locks;	}	error = gfs2_dir_add(&dip->i_inode, name, ip, IF2DT(ip->i_inode.i_mode));	if (error)		goto fail_end_trans;	error = gfs2_meta_inode_buffer(ip, &dibh);	if (error)		goto fail_end_trans;	ip->i_inode.i_nlink = 1;	gfs2_trans_add_bh(ip->i_gl, dibh, 1);	gfs2_dinode_out(ip, dibh->b_data);	brelse(dibh);	return 0;fail_end_trans:	gfs2_trans_end(sdp);fail_ipreserv:	if (dip->i_alloc.al_rgd)		gfs2_inplace_release(dip);fail_quota_locks:	gfs2_quota_unlock(dip);fail:	gfs2_alloc_put(dip);	return error;}static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip){	int err;	size_t len;	void *value;	char *name;	struct gfs2_ea_request er;	err = security_inode_init_security(&ip->i_inode, &dip->i_inode,					   &name, &value, &len);	if (err) {		if (err == -EOPNOTSUPP)			return 0;		return err;	}	memset(&er, 0, sizeof(struct gfs2_ea_request));	er.er_type = GFS2_EATYPE_SECURITY;	er.er_name = name;	er.er_data = value;	er.er_name_len = strlen(name);	er.er_data_len = len;	err = gfs2_ea_set_i(ip, &er);	kfree(value);	kfree(name);	return err;}/** * gfs2_createi - Create a new inode * @ghs: An array of two holders * @name: The name of the new file * @mode: the permissions on the new inode * * @ghs[0] is an initialized holder for the directory * @ghs[1] is the holder for the inode lock * * If the return value is not NULL, the glocks on both the directory and the new * file are held.  A transaction has been started and an inplace reservation * is held, as well. * * Returns: An inode

⌨️ 快捷键说明

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