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

📄 eattr.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/** * gfs2_ea_get_i - * @ip: The GFS2 inode * @er: The request structure * * Returns: actual size of data on success, -errno on error */int gfs2_ea_get_i(struct gfs2_inode *ip, struct gfs2_ea_request *er){	struct gfs2_ea_location el;	int error;	if (!ip->i_di.di_eattr)		return -ENODATA;	error = gfs2_ea_find(ip, er, &el);	if (error)		return error;	if (!el.el_ea)		return -ENODATA;	if (er->er_data_len) {		if (GFS2_EA_DATA_LEN(el.el_ea) > er->er_data_len)			error =  -ERANGE;		else			error = gfs2_ea_get_copy(ip, &el, er->er_data);	}	if (!error)		error = GFS2_EA_DATA_LEN(el.el_ea);	brelse(el.el_bh);	return error;}/** * gfs2_ea_get - * @ip: The GFS2 inode * @er: The request structure * * Returns: actual size of data on success, -errno on error */int gfs2_ea_get(struct gfs2_inode *ip, struct gfs2_ea_request *er){	struct gfs2_holder i_gh;	int error;	if (!er->er_name_len ||	    er->er_name_len > GFS2_EA_MAX_NAME_LEN)		return -EINVAL;	if (!er->er_data || !er->er_data_len) {		er->er_data = NULL;		er->er_data_len = 0;	}	error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);	if (error)		return error;	error = gfs2_ea_ops[er->er_type]->eo_get(ip, er);	gfs2_glock_dq_uninit(&i_gh);	return error;}/** * ea_alloc_blk - allocates a new block for extended attributes. * @ip: A pointer to the inode that's getting extended attributes * @bhp: Pointer to pointer to a struct buffer_head * * Returns: errno */static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp){	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);	struct gfs2_ea_header *ea;	u64 block;	block = gfs2_alloc_meta(ip);	*bhp = gfs2_meta_new(ip->i_gl, block);	gfs2_trans_add_bh(ip->i_gl, *bhp, 1);	gfs2_metatype_set(*bhp, GFS2_METATYPE_EA, GFS2_FORMAT_EA);	gfs2_buffer_clear_tail(*bhp, sizeof(struct gfs2_meta_header));	ea = GFS2_EA_BH2FIRST(*bhp);	ea->ea_rec_len = cpu_to_be32(sdp->sd_jbsize);	ea->ea_type = GFS2_EATYPE_UNUSED;	ea->ea_flags = GFS2_EAFLAG_LAST;	ea->ea_num_ptrs = 0;	ip->i_di.di_blocks++;	gfs2_set_inode_blocks(&ip->i_inode);	return 0;}/** * ea_write - writes the request info to an ea, creating new blocks if *            necessary * @ip: inode that is being modified * @ea: the location of the new ea in a block * @er: the write request * * Note: does not update ea_rec_len or the GFS2_EAFLAG_LAST bin of ea_flags * * returns : errno */static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea,		    struct gfs2_ea_request *er){	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);	ea->ea_data_len = cpu_to_be32(er->er_data_len);	ea->ea_name_len = er->er_name_len;	ea->ea_type = er->er_type;	ea->__pad = 0;	memcpy(GFS2_EA2NAME(ea), er->er_name, er->er_name_len);	if (GFS2_EAREQ_SIZE_STUFFED(er) <= sdp->sd_jbsize) {		ea->ea_num_ptrs = 0;		memcpy(GFS2_EA2DATA(ea), er->er_data, er->er_data_len);	} else {		__be64 *dataptr = GFS2_EA2DATAPTRS(ea);		const char *data = er->er_data;		unsigned int data_len = er->er_data_len;		unsigned int copy;		unsigned int x;		ea->ea_num_ptrs = DIV_ROUND_UP(er->er_data_len, sdp->sd_jbsize);		for (x = 0; x < ea->ea_num_ptrs; x++) {			struct buffer_head *bh;			u64 block;			int mh_size = sizeof(struct gfs2_meta_header);			block = gfs2_alloc_meta(ip);			bh = gfs2_meta_new(ip->i_gl, block);			gfs2_trans_add_bh(ip->i_gl, bh, 1);			gfs2_metatype_set(bh, GFS2_METATYPE_ED, GFS2_FORMAT_ED);			ip->i_di.di_blocks++;			gfs2_set_inode_blocks(&ip->i_inode);			copy = data_len > sdp->sd_jbsize ? sdp->sd_jbsize :							   data_len;			memcpy(bh->b_data + mh_size, data, copy);			if (copy < sdp->sd_jbsize)				memset(bh->b_data + mh_size + copy, 0,				       sdp->sd_jbsize - copy);			*dataptr++ = cpu_to_be64(bh->b_blocknr);			data += copy;			data_len -= copy;			brelse(bh);		}		gfs2_assert_withdraw(sdp, !data_len);	}	return 0;}typedef int (*ea_skeleton_call_t) (struct gfs2_inode *ip,				   struct gfs2_ea_request *er, void *private);static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,			     unsigned int blks,			     ea_skeleton_call_t skeleton_call, void *private){	struct gfs2_alloc *al;	struct buffer_head *dibh;	int error;	al = gfs2_alloc_get(ip);	error = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);	if (error)		goto out;	error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);	if (error)		goto out_gunlock_q;	al->al_requested = blks;	error = gfs2_inplace_reserve(ip);	if (error)		goto out_gunlock_q;	error = gfs2_trans_begin(GFS2_SB(&ip->i_inode),				 blks + al->al_rgd->rd_length +				 RES_DINODE + RES_STATFS + RES_QUOTA, 0);	if (error)		goto out_ipres;	error = skeleton_call(ip, er, private);	if (error)		goto out_end_trans;	error = gfs2_meta_inode_buffer(ip, &dibh);	if (!error) {		if (er->er_flags & GFS2_ERF_MODE) {			gfs2_assert_withdraw(GFS2_SB(&ip->i_inode),					    (ip->i_inode.i_mode & S_IFMT) ==					    (er->er_mode & S_IFMT));			ip->i_inode.i_mode = er->er_mode;		}		ip->i_inode.i_ctime = CURRENT_TIME;		gfs2_trans_add_bh(ip->i_gl, dibh, 1);		gfs2_dinode_out(ip, dibh->b_data);		brelse(dibh);	}out_end_trans:	gfs2_trans_end(GFS2_SB(&ip->i_inode));out_ipres:	gfs2_inplace_release(ip);out_gunlock_q:	gfs2_quota_unlock(ip);out:	gfs2_alloc_put(ip);	return error;}static int ea_init_i(struct gfs2_inode *ip, struct gfs2_ea_request *er,		     void *private){	struct buffer_head *bh;	int error;	error = ea_alloc_blk(ip, &bh);	if (error)		return error;	ip->i_di.di_eattr = bh->b_blocknr;	error = ea_write(ip, GFS2_EA_BH2FIRST(bh), er);	brelse(bh);	return error;}/** * ea_init - initializes a new eattr block * @ip: * @er: * * Returns: errno */static int ea_init(struct gfs2_inode *ip, struct gfs2_ea_request *er){	unsigned int jbsize = GFS2_SB(&ip->i_inode)->sd_jbsize;	unsigned int blks = 1;	if (GFS2_EAREQ_SIZE_STUFFED(er) > jbsize)		blks += DIV_ROUND_UP(er->er_data_len, jbsize);	return ea_alloc_skeleton(ip, er, blks, ea_init_i, NULL);}static struct gfs2_ea_header *ea_split_ea(struct gfs2_ea_header *ea){	u32 ea_size = GFS2_EA_SIZE(ea);	struct gfs2_ea_header *new = (struct gfs2_ea_header *)((char *)ea +				     ea_size);	u32 new_size = GFS2_EA_REC_LEN(ea) - ea_size;	int last = ea->ea_flags & GFS2_EAFLAG_LAST;	ea->ea_rec_len = cpu_to_be32(ea_size);	ea->ea_flags ^= last;	new->ea_rec_len = cpu_to_be32(new_size);	new->ea_flags = last;	return new;}static void ea_set_remove_stuffed(struct gfs2_inode *ip,				  struct gfs2_ea_location *el){	struct gfs2_ea_header *ea = el->el_ea;	struct gfs2_ea_header *prev = el->el_prev;	u32 len;	gfs2_trans_add_bh(ip->i_gl, el->el_bh, 1);	if (!prev || !GFS2_EA_IS_STUFFED(ea)) {		ea->ea_type = GFS2_EATYPE_UNUSED;		return;	} else if (GFS2_EA2NEXT(prev) != ea) {		prev = GFS2_EA2NEXT(prev);		gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), GFS2_EA2NEXT(prev) == ea);	}	len = GFS2_EA_REC_LEN(prev) + GFS2_EA_REC_LEN(ea);	prev->ea_rec_len = cpu_to_be32(len);	if (GFS2_EA_IS_LAST(ea))		prev->ea_flags |= GFS2_EAFLAG_LAST;}struct ea_set {	int ea_split;	struct gfs2_ea_request *es_er;	struct gfs2_ea_location *es_el;	struct buffer_head *es_bh;	struct gfs2_ea_header *es_ea;};static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh,				 struct gfs2_ea_header *ea, struct ea_set *es){	struct gfs2_ea_request *er = es->es_er;	struct buffer_head *dibh;	int error;	error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), RES_DINODE + 2 * RES_EATTR, 0);	if (error)		return error;	gfs2_trans_add_bh(ip->i_gl, bh, 1);	if (es->ea_split)		ea = ea_split_ea(ea);	ea_write(ip, ea, er);	if (es->es_el)		ea_set_remove_stuffed(ip, es->es_el);	error = gfs2_meta_inode_buffer(ip, &dibh);	if (error)		goto out;	if (er->er_flags & GFS2_ERF_MODE) {		gfs2_assert_withdraw(GFS2_SB(&ip->i_inode),			(ip->i_inode.i_mode & S_IFMT) == (er->er_mode & S_IFMT));		ip->i_inode.i_mode = er->er_mode;	}	ip->i_inode.i_ctime = CURRENT_TIME;	gfs2_trans_add_bh(ip->i_gl, dibh, 1);	gfs2_dinode_out(ip, dibh->b_data);	brelse(dibh);out:	gfs2_trans_end(GFS2_SB(&ip->i_inode));	return error;}static int ea_set_simple_alloc(struct gfs2_inode *ip,			       struct gfs2_ea_request *er, void *private){	struct ea_set *es = private;	struct gfs2_ea_header *ea = es->es_ea;	int error;	gfs2_trans_add_bh(ip->i_gl, es->es_bh, 1);	if (es->ea_split)		ea = ea_split_ea(ea);	error = ea_write(ip, ea, er);	if (error)		return error;	if (es->es_el)		ea_set_remove_stuffed(ip, es->es_el);	return 0;}static int ea_set_simple(struct gfs2_inode *ip, struct buffer_head *bh,			 struct gfs2_ea_header *ea, struct gfs2_ea_header *prev,			 void *private){	struct ea_set *es = private;	unsigned int size;	int stuffed;	int error;	stuffed = ea_calc_size(GFS2_SB(&ip->i_inode), es->es_er, &size);	if (ea->ea_type == GFS2_EATYPE_UNUSED) {		if (GFS2_EA_REC_LEN(ea) < size)			return 0;		if (!GFS2_EA_IS_STUFFED(ea)) {			error = ea_remove_unstuffed(ip, bh, ea, prev, 1);			if (error)				return error;		}		es->ea_split = 0;	} else if (GFS2_EA_REC_LEN(ea) - GFS2_EA_SIZE(ea) >= size)		es->ea_split = 1;	else		return 0;	if (stuffed) {		error = ea_set_simple_noalloc(ip, bh, ea, es);		if (error)			return error;	} else {		unsigned int blks;		es->es_bh = bh;		es->es_ea = ea;		blks = 2 + DIV_ROUND_UP(es->es_er->er_data_len,					GFS2_SB(&ip->i_inode)->sd_jbsize);		error = ea_alloc_skeleton(ip, es->es_er, blks,					  ea_set_simple_alloc, es);		if (error)			return error;	}	return 1;}static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,			void *private){	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);	struct buffer_head *indbh, *newbh;	__be64 *eablk;	int error;	int mh_size = sizeof(struct gfs2_meta_header);	if (ip->i_di.di_flags & GFS2_DIF_EA_INDIRECT) {		__be64 *end;		error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr, DIO_WAIT,				       &indbh);		if (error)			return error;		if (gfs2_metatype_check(sdp, indbh, GFS2_METATYPE_IN)) {			error = -EIO;			goto out;		}		eablk = (__be64 *)(indbh->b_data + mh_size);		end = eablk + sdp->sd_inptrs;		for (; eablk < end; eablk++)			if (!*eablk)				break;		if (eablk == end) {			error = -ENOSPC;			goto out;		}		gfs2_trans_add_bh(ip->i_gl, indbh, 1);	} else {		u64 blk;		blk = gfs2_alloc_meta(ip);		indbh = gfs2_meta_new(ip->i_gl, blk);		gfs2_trans_add_bh(ip->i_gl, indbh, 1);		gfs2_metatype_set(indbh, GFS2_METATYPE_IN, GFS2_FORMAT_IN);		gfs2_buffer_clear_tail(indbh, mh_size);		eablk = (__be64 *)(indbh->b_data + mh_size);		*eablk = cpu_to_be64(ip->i_di.di_eattr);		ip->i_di.di_eattr = blk;		ip->i_di.di_flags |= GFS2_DIF_EA_INDIRECT;		ip->i_di.di_blocks++;		gfs2_set_inode_blocks(&ip->i_inode);		eablk++;	}	error = ea_alloc_blk(ip, &newbh);	if (error)		goto out;	*eablk = cpu_to_be64((u64)newbh->b_blocknr);	error = ea_write(ip, GFS2_EA_BH2FIRST(newbh), er);	brelse(newbh);	if (error)		goto out;	if (private)		ea_set_remove_stuffed(ip, private);out:	brelse(indbh);	return error;}static int ea_set_i(struct gfs2_inode *ip, struct gfs2_ea_request *er,		    struct gfs2_ea_location *el)

⌨️ 快捷键说明

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