diff options
Diffstat (limited to 'fs/gfs2/rgrp.c')
| -rw-r--r-- | fs/gfs2/rgrp.c | 33 | 
1 files changed, 21 insertions, 12 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 3cc402ce6fe..38fe18f2f05 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -553,7 +553,6 @@ void gfs2_free_clones(struct gfs2_rgrpd *rgd)   */  int gfs2_rs_alloc(struct gfs2_inode *ip)  { -	int error = 0;  	struct gfs2_blkreserv *res;  	if (ip->i_res) @@ -561,7 +560,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip)  	res = kmem_cache_zalloc(gfs2_rsrv_cachep, GFP_NOFS);  	if (!res) -		error = -ENOMEM; +		return -ENOMEM;  	RB_CLEAR_NODE(&res->rs_node); @@ -571,7 +570,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip)  	else  		ip->i_res = res;  	up_write(&ip->i_rw_mutex); -	return error; +	return 0;  }  static void dump_rs(struct seq_file *seq, const struct gfs2_blkreserv *rs) @@ -1263,7 +1262,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp)  	int ret = 0;  	u64 amt;  	u64 trimmed = 0; +	u64 start, end, minlen;  	unsigned int x; +	unsigned bs_shift = sdp->sd_sb.sb_bsize_shift;  	if (!capable(CAP_SYS_ADMIN))  		return -EPERM; @@ -1271,19 +1272,25 @@ int gfs2_fitrim(struct file *filp, void __user *argp)  	if (!blk_queue_discard(q))  		return -EOPNOTSUPP; -	if (argp == NULL) { -		r.start = 0; -		r.len = ULLONG_MAX; -		r.minlen = 0; -	} else if (copy_from_user(&r, argp, sizeof(r))) +	if (copy_from_user(&r, argp, sizeof(r)))  		return -EFAULT;  	ret = gfs2_rindex_update(sdp);  	if (ret)  		return ret; -	rgd = gfs2_blk2rgrpd(sdp, r.start, 0); -	rgd_end = gfs2_blk2rgrpd(sdp, r.start + r.len, 0); +	start = r.start >> bs_shift; +	end = start + (r.len >> bs_shift); +	minlen = max_t(u64, r.minlen, +		       q->limits.discard_granularity) >> bs_shift; + +	rgd = gfs2_blk2rgrpd(sdp, start, 0); +	rgd_end = gfs2_blk2rgrpd(sdp, end - 1, 0); + +	if (end <= start || +	    minlen > sdp->sd_max_rg_data || +	    start > rgd_end->rd_data0 + rgd_end->rd_data) +		return -EINVAL;  	while (1) { @@ -1295,7 +1302,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp)  			/* Trim each bitmap in the rgrp */  			for (x = 0; x < rgd->rd_length; x++) {  				struct gfs2_bitmap *bi = rgd->rd_bits + x; -				ret = gfs2_rgrp_send_discards(sdp, rgd->rd_data0, NULL, bi, r.minlen, &amt); +				ret = gfs2_rgrp_send_discards(sdp, +						rgd->rd_data0, NULL, bi, minlen, +						&amt);  				if (ret) {  					gfs2_glock_dq_uninit(&gh);  					goto out; @@ -1324,7 +1333,7 @@ int gfs2_fitrim(struct file *filp, void __user *argp)  out:  	r.len = trimmed << 9; -	if (argp && copy_to_user(argp, &r, sizeof(r))) +	if (copy_to_user(argp, &r, sizeof(r)))  		return -EFAULT;  	return ret;  |