diff options
| author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-08-04 10:26:03 +1000 | 
|---|---|---|
| committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-08-04 10:26:03 +1000 | 
| commit | 412a4ac5e9cf7fdeb6af562c25547a9b9da7674f (patch) | |
| tree | a8ce13cbc9c47c99799e5e3e3ad26ba78274ee73 /fs/ocfs2/xattr.c | |
| parent | e8e5c2155b0035b6e04f29be67f6444bc914005b (diff) | |
| parent | 0c2daaafcdec726e89cbccca61d576de8429c537 (diff) | |
| download | olio-linux-3.10-412a4ac5e9cf7fdeb6af562c25547a9b9da7674f.tar.xz olio-linux-3.10-412a4ac5e9cf7fdeb6af562c25547a9b9da7674f.zip  | |
Merge commit 'gcl/next' into next
Diffstat (limited to 'fs/ocfs2/xattr.c')
| -rw-r--r-- | fs/ocfs2/xattr.c | 198 | 
1 files changed, 134 insertions, 64 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index e97b34842cf..d03469f6180 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -709,7 +709,7 @@ static int ocfs2_xattr_extend_allocation(struct inode *inode,  					 struct ocfs2_xattr_value_buf *vb,  					 struct ocfs2_xattr_set_ctxt *ctxt)  { -	int status = 0; +	int status = 0, credits;  	handle_t *handle = ctxt->handle;  	enum ocfs2_alloc_restarted why;  	u32 prev_clusters, logical_start = le32_to_cpu(vb->vb_xv->xr_clusters); @@ -719,38 +719,54 @@ static int ocfs2_xattr_extend_allocation(struct inode *inode,  	ocfs2_init_xattr_value_extent_tree(&et, INODE_CACHE(inode), vb); -	status = vb->vb_access(handle, INODE_CACHE(inode), vb->vb_bh, -			      OCFS2_JOURNAL_ACCESS_WRITE); -	if (status < 0) { -		mlog_errno(status); -		goto leave; -	} +	while (clusters_to_add) { +		status = vb->vb_access(handle, INODE_CACHE(inode), vb->vb_bh, +				       OCFS2_JOURNAL_ACCESS_WRITE); +		if (status < 0) { +			mlog_errno(status); +			break; +		} -	prev_clusters = le32_to_cpu(vb->vb_xv->xr_clusters); -	status = ocfs2_add_clusters_in_btree(handle, -					     &et, -					     &logical_start, -					     clusters_to_add, -					     0, -					     ctxt->data_ac, -					     ctxt->meta_ac, -					     &why); -	if (status < 0) { -		mlog_errno(status); -		goto leave; -	} +		prev_clusters = le32_to_cpu(vb->vb_xv->xr_clusters); +		status = ocfs2_add_clusters_in_btree(handle, +						     &et, +						     &logical_start, +						     clusters_to_add, +						     0, +						     ctxt->data_ac, +						     ctxt->meta_ac, +						     &why); +		if ((status < 0) && (status != -EAGAIN)) { +			if (status != -ENOSPC) +				mlog_errno(status); +			break; +		} -	ocfs2_journal_dirty(handle, vb->vb_bh); +		ocfs2_journal_dirty(handle, vb->vb_bh); -	clusters_to_add -= le32_to_cpu(vb->vb_xv->xr_clusters) - prev_clusters; +		clusters_to_add -= le32_to_cpu(vb->vb_xv->xr_clusters) - +					 prev_clusters; -	/* -	 * We should have already allocated enough space before the transaction, -	 * so no need to restart. -	 */ -	BUG_ON(why != RESTART_NONE || clusters_to_add); +		if (why != RESTART_NONE && clusters_to_add) { +			/* +			 * We can only fail in case the alloc file doesn't give +			 * up enough clusters. +			 */ +			BUG_ON(why == RESTART_META); -leave: +			mlog(0, "restarting xattr value extension for %u" +			     " clusters,.\n", clusters_to_add); +			credits = ocfs2_calc_extend_credits(inode->i_sb, +							    &vb->vb_xv->xr_list, +							    clusters_to_add); +			status = ocfs2_extend_trans(handle, credits); +			if (status < 0) { +				status = -ENOMEM; +				mlog_errno(status); +				break; +			} +		} +	}  	return status;  } @@ -6788,16 +6804,15 @@ out:  	return ret;  } -static int ocfs2_reflink_xattr_buckets(handle_t *handle, +static int ocfs2_reflink_xattr_bucket(handle_t *handle,  				u64 blkno, u64 new_blkno, u32 clusters, +				u32 *cpos, int num_buckets,  				struct ocfs2_alloc_context *meta_ac,  				struct ocfs2_alloc_context *data_ac,  				struct ocfs2_reflink_xattr_tree_args *args)  {  	int i, j, ret = 0;  	struct super_block *sb = args->reflink->old_inode->i_sb; -	u32 bpc = ocfs2_xattr_buckets_per_cluster(OCFS2_SB(sb)); -	u32 num_buckets = clusters * bpc;  	int bpb = args->old_bucket->bu_blocks;  	struct ocfs2_xattr_value_buf vb = {  		.vb_access = ocfs2_journal_access, @@ -6816,14 +6831,6 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle,  			break;  		} -		/* -		 * The real bucket num in this series of blocks is stored -		 * in the 1st bucket. -		 */ -		if (i == 0) -			num_buckets = le16_to_cpu( -				bucket_xh(args->old_bucket)->xh_num_buckets); -  		ret = ocfs2_xattr_bucket_journal_access(handle,  						args->new_bucket,  						OCFS2_JOURNAL_ACCESS_CREATE); @@ -6837,6 +6844,18 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle,  			       bucket_block(args->old_bucket, j),  			       sb->s_blocksize); +		/* +		 * Record the start cpos so that we can use it to initialize +		 * our xattr tree we also set the xh_num_bucket for the new +		 * bucket. +		 */ +		if (i == 0) { +			*cpos = le32_to_cpu(bucket_xh(args->new_bucket)-> +					    xh_entries[0].xe_name_hash); +			bucket_xh(args->new_bucket)->xh_num_buckets = +				cpu_to_le16(num_buckets); +		} +  		ocfs2_xattr_bucket_journal_dirty(handle, args->new_bucket);  		ret = ocfs2_reflink_xattr_header(handle, args->reflink, @@ -6866,6 +6885,7 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle,  		}  		ocfs2_xattr_bucket_journal_dirty(handle, args->new_bucket); +  		ocfs2_xattr_bucket_relse(args->old_bucket);  		ocfs2_xattr_bucket_relse(args->new_bucket);  	} @@ -6874,6 +6894,75 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle,  	ocfs2_xattr_bucket_relse(args->new_bucket);  	return ret;  } + +static int ocfs2_reflink_xattr_buckets(handle_t *handle, +				struct inode *inode, +				struct ocfs2_reflink_xattr_tree_args *args, +				struct ocfs2_extent_tree *et, +				struct ocfs2_alloc_context *meta_ac, +				struct ocfs2_alloc_context *data_ac, +				u64 blkno, u32 cpos, u32 len) +{ +	int ret, first_inserted = 0; +	u32 p_cluster, num_clusters, reflink_cpos = 0; +	u64 new_blkno; +	unsigned int num_buckets, reflink_buckets; +	unsigned int bpc = +		ocfs2_xattr_buckets_per_cluster(OCFS2_SB(inode->i_sb)); + +	ret = ocfs2_read_xattr_bucket(args->old_bucket, blkno); +	if (ret) { +		mlog_errno(ret); +		goto out; +	} +	num_buckets = le16_to_cpu(bucket_xh(args->old_bucket)->xh_num_buckets); +	ocfs2_xattr_bucket_relse(args->old_bucket); + +	while (len && num_buckets) { +		ret = ocfs2_claim_clusters(handle, data_ac, +					   1, &p_cluster, &num_clusters); +		if (ret) { +			mlog_errno(ret); +			goto out; +		} + +		new_blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cluster); +		reflink_buckets = min(num_buckets, bpc * num_clusters); + +		ret = ocfs2_reflink_xattr_bucket(handle, blkno, +						 new_blkno, num_clusters, +						 &reflink_cpos, reflink_buckets, +						 meta_ac, data_ac, args); +		if (ret) { +			mlog_errno(ret); +			goto out; +		} + +		/* +		 * For the 1st allocated cluster, we make it use the same cpos +		 * so that the xattr tree looks the same as the original one +		 * in the most case. +		 */ +		if (!first_inserted) { +			reflink_cpos = cpos; +			first_inserted = 1; +		} +		ret = ocfs2_insert_extent(handle, et, reflink_cpos, new_blkno, +					  num_clusters, 0, meta_ac); +		if (ret) +			mlog_errno(ret); + +		mlog(0, "insert new xattr extent rec start %llu len %u to %u\n", +		     (unsigned long long)new_blkno, num_clusters, reflink_cpos); + +		len -= num_clusters; +		blkno += ocfs2_clusters_to_blocks(inode->i_sb, num_clusters); +		num_buckets -= reflink_buckets; +	} +out: +	return ret; +} +  /*   * Create the same xattr extent record in the new inode's xattr tree.   */ @@ -6885,8 +6974,6 @@ static int ocfs2_reflink_xattr_rec(struct inode *inode,  				   void *para)  {  	int ret, credits = 0; -	u32 p_cluster, num_clusters; -	u64 new_blkno;  	handle_t *handle;  	struct ocfs2_reflink_xattr_tree_args *args =  			(struct ocfs2_reflink_xattr_tree_args *)para; @@ -6895,6 +6982,9 @@ static int ocfs2_reflink_xattr_rec(struct inode *inode,  	struct ocfs2_alloc_context *data_ac = NULL;  	struct ocfs2_extent_tree et; +	mlog(0, "reflink xattr buckets %llu len %u\n", +	     (unsigned long long)blkno, len); +  	ocfs2_init_xattr_tree_extent_tree(&et,  					  INODE_CACHE(args->reflink->new_inode),  					  args->new_blk_bh); @@ -6914,32 +7004,12 @@ static int ocfs2_reflink_xattr_rec(struct inode *inode,  		goto out;  	} -	ret = ocfs2_claim_clusters(handle, data_ac, -				   len, &p_cluster, &num_clusters); -	if (ret) { -		mlog_errno(ret); -		goto out_commit; -	} - -	new_blkno = ocfs2_clusters_to_blocks(osb->sb, p_cluster); - -	mlog(0, "reflink xattr buckets %llu to %llu, len %u\n", -	     (unsigned long long)blkno, (unsigned long long)new_blkno, len); -	ret = ocfs2_reflink_xattr_buckets(handle, blkno, new_blkno, len, -					  meta_ac, data_ac, args); -	if (ret) { -		mlog_errno(ret); -		goto out_commit; -	} - -	mlog(0, "insert new xattr extent rec start %llu len %u to %u\n", -	     (unsigned long long)new_blkno, len, cpos); -	ret = ocfs2_insert_extent(handle, &et, cpos, new_blkno, -				  len, 0, meta_ac); +	ret = ocfs2_reflink_xattr_buckets(handle, inode, args, &et, +					  meta_ac, data_ac, +					  blkno, cpos, len);  	if (ret)  		mlog_errno(ret); -out_commit:  	ocfs2_commit_trans(osb, handle);  out:  |