diff options
Diffstat (limited to 'fs/gfs2/aops.c')
| -rw-r--r-- | fs/gfs2/aops.c | 39 | 
1 files changed, 39 insertions, 0 deletions
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 03ebb439ace..7ebae9a4ecc 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c @@ -624,6 +624,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,  {  	struct gfs2_inode *ip = GFS2_I(mapping->host);  	struct gfs2_sbd *sdp = GFS2_SB(mapping->host); +	struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);  	unsigned int data_blocks = 0, ind_blocks = 0, rblocks;  	int alloc_required;  	int error = 0; @@ -637,6 +638,14 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,  	error = gfs2_glock_nq(&ip->i_gh);  	if (unlikely(error))  		goto out_uninit; +	if (&ip->i_inode == sdp->sd_rindex) { +		error = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, +					   GL_NOCACHE, &m_ip->i_gh); +		if (unlikely(error)) { +			gfs2_glock_dq(&ip->i_gh); +			goto out_uninit; +		} +	}  	error = gfs2_write_alloc_required(ip, pos, len, &alloc_required);  	if (error) @@ -667,6 +676,8 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,  		rblocks += data_blocks ? data_blocks : 1;  	if (ind_blocks || data_blocks)  		rblocks += RES_STATFS + RES_QUOTA; +	if (&ip->i_inode == sdp->sd_rindex) +		rblocks += 2 * RES_STATFS;  	error = gfs2_trans_begin(sdp, rblocks,  				 PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize); @@ -712,6 +723,10 @@ out_alloc_put:  		gfs2_alloc_put(ip);  	}  out_unlock: +	if (&ip->i_inode == sdp->sd_rindex) { +		gfs2_glock_dq(&m_ip->i_gh); +		gfs2_holder_uninit(&m_ip->i_gh); +	}  	gfs2_glock_dq(&ip->i_gh);  out_uninit:  	gfs2_holder_uninit(&ip->i_gh); @@ -725,14 +740,21 @@ out_uninit:  static void adjust_fs_space(struct inode *inode)  {  	struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; +	struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); +	struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode);  	struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;  	struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; +	struct buffer_head *m_bh, *l_bh;  	u64 fs_total, new_free;  	/* Total up the file system space, according to the latest rindex. */  	fs_total = gfs2_ri_total(sdp); +	if (gfs2_meta_inode_buffer(m_ip, &m_bh) != 0) +		return;  	spin_lock(&sdp->sd_statfs_spin); +	gfs2_statfs_change_in(m_sc, m_bh->b_data + +			      sizeof(struct gfs2_dinode));  	if (fs_total > (m_sc->sc_total + l_sc->sc_total))  		new_free = fs_total - (m_sc->sc_total + l_sc->sc_total);  	else @@ -741,6 +763,13 @@ static void adjust_fs_space(struct inode *inode)  	fs_warn(sdp, "File system extended by %llu blocks.\n",  		(unsigned long long)new_free);  	gfs2_statfs_change(sdp, new_free, new_free, 0); + +	if (gfs2_meta_inode_buffer(l_ip, &l_bh) != 0) +		goto out; +	update_statfs(sdp, m_bh, l_bh); +	brelse(l_bh); +out: +	brelse(m_bh);  }  /** @@ -763,6 +792,7 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh,  {  	struct gfs2_inode *ip = GFS2_I(inode);  	struct gfs2_sbd *sdp = GFS2_SB(inode); +	struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);  	u64 to = pos + copied;  	void *kaddr;  	unsigned char *buf = dibh->b_data + sizeof(struct gfs2_dinode); @@ -794,6 +824,10 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh,  	brelse(dibh);  	gfs2_trans_end(sdp); +	if (inode == sdp->sd_rindex) { +		gfs2_glock_dq(&m_ip->i_gh); +		gfs2_holder_uninit(&m_ip->i_gh); +	}  	gfs2_glock_dq(&ip->i_gh);  	gfs2_holder_uninit(&ip->i_gh);  	return copied; @@ -823,6 +857,7 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,  	struct inode *inode = page->mapping->host;  	struct gfs2_inode *ip = GFS2_I(inode);  	struct gfs2_sbd *sdp = GFS2_SB(inode); +	struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);  	struct buffer_head *dibh;  	struct gfs2_alloc *al = ip->i_alloc;  	unsigned int from = pos & (PAGE_CACHE_SIZE - 1); @@ -865,6 +900,10 @@ failed:  		gfs2_quota_unlock(ip);  		gfs2_alloc_put(ip);  	} +	if (inode == sdp->sd_rindex) { +		gfs2_glock_dq(&m_ip->i_gh); +		gfs2_holder_uninit(&m_ip->i_gh); +	}  	gfs2_glock_dq(&ip->i_gh);  	gfs2_holder_uninit(&ip->i_gh);  	return ret;  |