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

📄 inode.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 */struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,			   unsigned int mode, dev_t dev){	struct inode *inode = NULL;	struct gfs2_inode *dip = ghs->gh_gl->gl_object;	struct inode *dir = &dip->i_inode;	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);	struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 };	int error;	u64 generation;	struct buffer_head *bh=NULL;	if (!name->len || name->len > GFS2_FNAMESIZE)		return ERR_PTR(-ENAMETOOLONG);	gfs2_holder_reinit(LM_ST_EXCLUSIVE, 0, ghs);	error = gfs2_glock_nq(ghs);	if (error)		goto fail;	error = create_ok(dip, name, mode);	if (error)		goto fail_gunlock;	error = pick_formal_ino(sdp, &inum.no_formal_ino);	if (error)		goto fail_gunlock;	error = alloc_dinode(dip, &inum.no_addr, &generation);	if (error)		goto fail_gunlock;	error = gfs2_glock_nq_num(sdp, inum.no_addr, &gfs2_inode_glops,				  LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1);	if (error)		goto fail_gunlock;	error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation, dev, &bh);	if (error)		goto fail_gunlock2;	inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode),					inum.no_addr,					inum.no_formal_ino, 0);	if (IS_ERR(inode))		goto fail_gunlock2;	gfs2_inode_bh(GFS2_I(inode), bh);	error = gfs2_inode_refresh(GFS2_I(inode));	if (error)		goto fail_gunlock2;	error = gfs2_acl_create(dip, GFS2_I(inode));	if (error)		goto fail_gunlock2;	error = gfs2_security_init(dip, GFS2_I(inode));	if (error)		goto fail_gunlock2;	error = link_dinode(dip, name, GFS2_I(inode));	if (error)		goto fail_gunlock2;	if (!inode)		return ERR_PTR(-ENOMEM);	return inode;fail_gunlock2:	gfs2_glock_dq_uninit(ghs + 1);	if (inode)		iput(inode);fail_gunlock:	gfs2_glock_dq(ghs);fail:	return ERR_PTR(error);}/** * gfs2_rmdiri - Remove a directory * @dip: The parent directory of the directory to be removed * @name: The name of the directory to be removed * @ip: The GFS2 inode of the directory to be removed * * Assumes Glocks on dip and ip are held * * Returns: errno */int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,		struct gfs2_inode *ip){	struct qstr dotname;	int error;	if (ip->i_di.di_entries != 2) {		if (gfs2_consist_inode(ip))			gfs2_dinode_print(ip);		return -EIO;	}	error = gfs2_dir_del(dip, name);	if (error)		return error;	error = gfs2_change_nlink(dip, -1);	if (error)		return error;	gfs2_str2qstr(&dotname, ".");	error = gfs2_dir_del(ip, &dotname);	if (error)		return error;	gfs2_str2qstr(&dotname, "..");	error = gfs2_dir_del(ip, &dotname);	if (error)		return error;	/* It looks odd, but it really should be done twice */	error = gfs2_change_nlink(ip, -1);	if (error)		return error;	error = gfs2_change_nlink(ip, -1);	if (error)		return error;	return error;}/* * gfs2_unlink_ok - check to see that a inode is still in a directory * @dip: the directory * @name: the name of the file * @ip: the inode * * Assumes that the lock on (at least) @dip is held. * * Returns: 0 if the parent/child relationship is correct, errno if it isn't */int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,		   const struct gfs2_inode *ip){	int error;	if (IS_IMMUTABLE(&ip->i_inode) || IS_APPEND(&ip->i_inode))		return -EPERM;	if ((dip->i_inode.i_mode & S_ISVTX) &&	    dip->i_inode.i_uid != current->fsuid &&	    ip->i_inode.i_uid != current->fsuid && !capable(CAP_FOWNER))		return -EPERM;	if (IS_APPEND(&dip->i_inode))		return -EPERM;	error = permission(&dip->i_inode, MAY_WRITE | MAY_EXEC, NULL);	if (error)		return error;	error = gfs2_dir_check(&dip->i_inode, name, ip);	if (error)		return error;	return 0;}/* * gfs2_ok_to_move - check if it's ok to move a directory to another directory * @this: move this * @to: to here * * Follow @to back to the root and make sure we don't encounter @this * Assumes we already hold the rename lock. * * Returns: errno */int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to){	struct inode *dir = &to->i_inode;	struct super_block *sb = dir->i_sb;	struct inode *tmp;	struct qstr dotdot;	int error = 0;	gfs2_str2qstr(&dotdot, "..");	igrab(dir);	for (;;) {		if (dir == &this->i_inode) {			error = -EINVAL;			break;		}		if (dir == sb->s_root->d_inode) {			error = 0;			break;		}		tmp = gfs2_lookupi(dir, &dotdot, 1, NULL);		if (IS_ERR(tmp)) {			error = PTR_ERR(tmp);			break;		}		iput(dir);		dir = tmp;	}	iput(dir);	return error;}/** * gfs2_readlinki - return the contents of a symlink * @ip: the symlink's inode * @buf: a pointer to the buffer to be filled * @len: a pointer to the length of @buf * * If @buf is too small, a piece of memory is kmalloc()ed and needs * to be freed by the caller. * * Returns: errno */int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len){	struct gfs2_holder i_gh;	struct buffer_head *dibh;	unsigned int x;	int error;	gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &i_gh);	error = gfs2_glock_nq_atime(&i_gh);	if (error) {		gfs2_holder_uninit(&i_gh);		return error;	}	if (!ip->i_di.di_size) {		gfs2_consist_inode(ip);		error = -EIO;		goto out;	}	error = gfs2_meta_inode_buffer(ip, &dibh);	if (error)		goto out;	x = ip->i_di.di_size + 1;	if (x > *len) {		*buf = kmalloc(x, GFP_KERNEL);		if (!*buf) {			error = -ENOMEM;			goto out_brelse;		}	}	memcpy(*buf, dibh->b_data + sizeof(struct gfs2_dinode), x);	*len = x;out_brelse:	brelse(dibh);out:	gfs2_glock_dq_uninit(&i_gh);	return error;}/** * gfs2_glock_nq_atime - Acquire a hold on an inode's glock, and *       conditionally update the inode's atime * @gh: the holder to acquire * * Tests atime (access time) for gfs2_read, gfs2_readdir and gfs2_mmap * Update if the difference between the current time and the inode's current * atime is greater than an interval specified at mount. * * Returns: errno */int gfs2_glock_nq_atime(struct gfs2_holder *gh){	struct gfs2_glock *gl = gh->gh_gl;	struct gfs2_sbd *sdp = gl->gl_sbd;	struct gfs2_inode *ip = gl->gl_object;	s64 quantum = gfs2_tune_get(sdp, gt_atime_quantum);	unsigned int state;	int flags;	int error;	struct timespec tv = CURRENT_TIME;	if (gfs2_assert_warn(sdp, gh->gh_flags & GL_ATIME) ||	    gfs2_assert_warn(sdp, !(gh->gh_flags & GL_ASYNC)) ||	    gfs2_assert_warn(sdp, gl->gl_ops == &gfs2_inode_glops))		return -EINVAL;	state = gh->gh_state;	flags = gh->gh_flags;	error = gfs2_glock_nq(gh);	if (error)		return error;	if (test_bit(SDF_NOATIME, &sdp->sd_flags) ||	    (sdp->sd_vfs->s_flags & MS_RDONLY))		return 0;	if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {		gfs2_glock_dq(gh);		gfs2_holder_reinit(LM_ST_EXCLUSIVE, gh->gh_flags & ~LM_FLAG_ANY,				   gh);		error = gfs2_glock_nq(gh);		if (error)			return error;		/* Verify that atime hasn't been updated while we were		   trying to get exclusive lock. */		tv = CURRENT_TIME;		if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {			struct buffer_head *dibh;			struct gfs2_dinode *di;			error = gfs2_trans_begin(sdp, RES_DINODE, 0);			if (error == -EROFS)				return 0;			if (error)				goto fail;			error = gfs2_meta_inode_buffer(ip, &dibh);			if (error)				goto fail_end_trans;			ip->i_inode.i_atime = tv;			gfs2_trans_add_bh(ip->i_gl, dibh, 1);			di = (struct gfs2_dinode *)dibh->b_data;			di->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);			di->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec);			brelse(dibh);			gfs2_trans_end(sdp);		}		/* If someone else has asked for the glock,		   unlock and let them have it. Then reacquire		   in the original state. */		if (gfs2_glock_is_blocking(gl)) {			gfs2_glock_dq(gh);			gfs2_holder_reinit(state, flags, gh);			return gfs2_glock_nq(gh);		}	}	return 0;fail_end_trans:	gfs2_trans_end(sdp);fail:	gfs2_glock_dq(gh);	return error;}static int__gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr){	struct buffer_head *dibh;	int error;	error = gfs2_meta_inode_buffer(ip, &dibh);	if (!error) {		error = inode_setattr(&ip->i_inode, attr);		gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error);		gfs2_trans_add_bh(ip->i_gl, dibh, 1);		gfs2_dinode_out(ip, dibh->b_data);		brelse(dibh);	}	return error;}/** * gfs2_setattr_simple - * @ip: * @attr: * * Called with a reference on the vnode. * * Returns: errno */int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr){	int error;	if (current->journal_info)		return __gfs2_setattr_simple(ip, attr);	error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), RES_DINODE, 0);	if (error)		return error;	error = __gfs2_setattr_simple(ip, attr);	gfs2_trans_end(GFS2_SB(&ip->i_inode));	return error;}void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf){	const struct gfs2_dinode_host *di = &ip->i_di;	struct gfs2_dinode *str = buf;	str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC);	str->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI);	str->di_header.__pad0 = 0;	str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI);	str->di_header.__pad1 = 0;	str->di_num.no_addr = cpu_to_be64(ip->i_no_addr);	str->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino);	str->di_mode = cpu_to_be32(ip->i_inode.i_mode);	str->di_uid = cpu_to_be32(ip->i_inode.i_uid);	str->di_gid = cpu_to_be32(ip->i_inode.i_gid);	str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);	str->di_size = cpu_to_be64(di->di_size);	str->di_blocks = cpu_to_be64(di->di_blocks);	str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);	str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec);	str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec);	str->di_goal_meta = cpu_to_be64(di->di_goal_meta);	str->di_goal_data = cpu_to_be64(di->di_goal_data);	str->di_generation = cpu_to_be64(di->di_generation);	str->di_flags = cpu_to_be32(di->di_flags);	str->di_height = cpu_to_be16(di->di_height);	str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) &&					     !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ?					     GFS2_FORMAT_DE : 0);	str->di_depth = cpu_to_be16(di->di_depth);	str->di_entries = cpu_to_be32(di->di_entries);	str->di_eattr = cpu_to_be64(di->di_eattr);	str->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec);	str->di_mtime_nsec = cpu_to_be32(ip->i_inode.i_mtime.tv_nsec);	str->di_ctime_nsec = cpu_to_be32(ip->i_inode.i_ctime.tv_nsec);}void gfs2_dinode_print(const struct gfs2_inode *ip){	const struct gfs2_dinode_host *di = &ip->i_di;	printk(KERN_INFO "  no_formal_ino = %llu\n",	       (unsigned long long)ip->i_no_formal_ino);	printk(KERN_INFO "  no_addr = %llu\n",	       (unsigned long long)ip->i_no_addr);	printk(KERN_INFO "  di_size = %llu\n", (unsigned long long)di->di_size);	printk(KERN_INFO "  di_blocks = %llu\n",	       (unsigned long long)di->di_blocks);	printk(KERN_INFO "  di_goal_meta = %llu\n",	       (unsigned long long)di->di_goal_meta);	printk(KERN_INFO "  di_goal_data = %llu\n",	       (unsigned long long)di->di_goal_data);	printk(KERN_INFO "  di_flags = 0x%.8X\n", di->di_flags);	printk(KERN_INFO "  di_height = %u\n", di->di_height);	printk(KERN_INFO "  di_depth = %u\n", di->di_depth);	printk(KERN_INFO "  di_entries = %u\n", di->di_entries);	printk(KERN_INFO "  di_eattr = %llu\n",	       (unsigned long long)di->di_eattr);}

⌨️ 快捷键说明

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