diff options
Diffstat (limited to 'fs/gfs2')
| -rw-r--r-- | fs/gfs2/file.c | 14 | ||||
| -rw-r--r-- | fs/gfs2/lops.c | 16 | ||||
| -rw-r--r-- | fs/gfs2/quota.c | 7 | ||||
| -rw-r--r-- | fs/gfs2/rgrp.c | 33 | ||||
| -rw-r--r-- | fs/gfs2/super.c | 3 | ||||
| -rw-r--r-- | fs/gfs2/trans.c | 8 | 
6 files changed, 43 insertions, 38 deletions
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 0def0504afc..e056b4ce487 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -516,15 +516,13 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)  		struct gfs2_holder i_gh;  		int error; -		gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); -		error = gfs2_glock_nq(&i_gh); -		if (error == 0) { -			file_accessed(file); -			gfs2_glock_dq(&i_gh); -		} -		gfs2_holder_uninit(&i_gh); +		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, +					   &i_gh);  		if (error)  			return error; +		/* grab lock to update inode */ +		gfs2_glock_dq_uninit(&i_gh); +		file_accessed(file);  	}  	vma->vm_ops = &gfs2_vm_ops; @@ -677,10 +675,8 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov,  	size_t writesize = iov_length(iov, nr_segs);  	struct dentry *dentry = file->f_dentry;  	struct gfs2_inode *ip = GFS2_I(dentry->d_inode); -	struct gfs2_sbd *sdp;  	int ret; -	sdp = GFS2_SB(file->f_mapping->host);  	ret = gfs2_rs_alloc(ip);  	if (ret)  		return ret; diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 8ff95a2d54e..9ceccb1595a 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -393,12 +393,10 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)  	struct gfs2_meta_header *mh;  	struct gfs2_trans *tr; -	lock_buffer(bd->bd_bh); -	gfs2_log_lock(sdp);  	tr = current->journal_info;  	tr->tr_touched = 1;  	if (!list_empty(&bd->bd_list)) -		goto out; +		return;  	set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);  	set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);  	mh = (struct gfs2_meta_header *)bd->bd_bh->b_data; @@ -414,9 +412,6 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)  	sdp->sd_log_num_buf++;  	list_add(&bd->bd_list, &sdp->sd_log_le_buf);  	tr->tr_num_buf_new++; -out: -	gfs2_log_unlock(sdp); -	unlock_buffer(bd->bd_bh);  }  static void gfs2_check_magic(struct buffer_head *bh) @@ -621,7 +616,6 @@ static void revoke_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)  static void revoke_lo_before_commit(struct gfs2_sbd *sdp)  { -	struct gfs2_log_descriptor *ld;  	struct gfs2_meta_header *mh;  	unsigned int offset;  	struct list_head *head = &sdp->sd_log_le_revoke; @@ -634,7 +628,6 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp)  	length = gfs2_struct2blk(sdp, sdp->sd_log_num_revoke, sizeof(u64));  	page = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_REVOKE, length, sdp->sd_log_num_revoke); -	ld = page_address(page);  	offset = sizeof(struct gfs2_log_descriptor);  	list_for_each_entry(bd, head, bd_list) { @@ -777,12 +770,10 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)  	struct address_space *mapping = bd->bd_bh->b_page->mapping;  	struct gfs2_inode *ip = GFS2_I(mapping->host); -	lock_buffer(bd->bd_bh); -	gfs2_log_lock(sdp);  	if (tr)  		tr->tr_touched = 1;  	if (!list_empty(&bd->bd_list)) -		goto out; +		return;  	set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);  	set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);  	if (gfs2_is_jdata(ip)) { @@ -793,9 +784,6 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)  	} else {  		list_add_tail(&bd->bd_list, &sdp->sd_log_le_ordered);  	} -out: -	gfs2_log_unlock(sdp); -	unlock_buffer(bd->bd_bh);  }  /** diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 40c4b0d42fa..c5af8e18f27 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -497,8 +497,11 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)  	struct gfs2_quota_data **qd;  	int error; -	if (ip->i_res == NULL) -		gfs2_rs_alloc(ip); +	if (ip->i_res == NULL) { +		error = gfs2_rs_alloc(ip); +		if (error) +			return error; +	}  	qd = ip->i_res->rs_qa_qd; 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; diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index bc737261f23..d6488674d91 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -810,7 +810,8 @@ static void gfs2_dirty_inode(struct inode *inode, int flags)  			return;  		}  		need_unlock = 1; -	} +	} else if (WARN_ON_ONCE(ip->i_gl->gl_state != LM_ST_EXCLUSIVE)) +		return;  	if (current->journal_info == NULL) {  		ret = gfs2_trans_begin(sdp, RES_DINODE, 0); diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c index adbd27875ef..413627072f3 100644 --- a/fs/gfs2/trans.c +++ b/fs/gfs2/trans.c @@ -155,14 +155,22 @@ void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta)  	struct gfs2_sbd *sdp = gl->gl_sbd;  	struct gfs2_bufdata *bd; +	lock_buffer(bh); +	gfs2_log_lock(sdp);  	bd = bh->b_private;  	if (bd)  		gfs2_assert(sdp, bd->bd_gl == gl);  	else { +		gfs2_log_unlock(sdp); +		unlock_buffer(bh);  		gfs2_attach_bufdata(gl, bh, meta);  		bd = bh->b_private; +		lock_buffer(bh); +		gfs2_log_lock(sdp);  	}  	lops_add(sdp, bd); +	gfs2_log_unlock(sdp); +	unlock_buffer(bh);  }  void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)  |