gfs2: Move the inode glock locking to gfs2_file_buffered_write
So far, for buffered writes, we were taking the inode glock in gfs2_iomap_begin and dropping it in gfs2_iomap_end with the intention of not holding the inode glock while iomap_write_actor faults in user pages. It turns out that iomap_write_actor is called inside iomap_begin ... iomap_end, so the user pages were still faulted in while holding the inode glock and the locking code in iomap_begin / iomap_end was completely pointless. Move the locking into gfs2_file_buffered_write instead. We'll take care of the potential deadlocks due to faulting in user pages while holding a glock in a subsequent patch. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
This commit is contained in:
parent
dc732906c2
commit
b924bdab74
|
@ -961,46 +961,6 @@ hole_found:
|
|||
goto out;
|
||||
}
|
||||
|
||||
static int gfs2_write_lock(struct inode *inode)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||
int error;
|
||||
|
||||
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh);
|
||||
error = gfs2_glock_nq(&ip->i_gh);
|
||||
if (error)
|
||||
goto out_uninit;
|
||||
if (&ip->i_inode == sdp->sd_rindex) {
|
||||
struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
|
||||
|
||||
error = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE,
|
||||
GL_NOCACHE, &m_ip->i_gh);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
}
|
||||
return 0;
|
||||
|
||||
out_unlock:
|
||||
gfs2_glock_dq(&ip->i_gh);
|
||||
out_uninit:
|
||||
gfs2_holder_uninit(&ip->i_gh);
|
||||
return error;
|
||||
}
|
||||
|
||||
static void gfs2_write_unlock(struct inode *inode)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||
|
||||
if (&ip->i_inode == sdp->sd_rindex) {
|
||||
struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
|
||||
|
||||
gfs2_glock_dq_uninit(&m_ip->i_gh);
|
||||
}
|
||||
gfs2_glock_dq_uninit(&ip->i_gh);
|
||||
}
|
||||
|
||||
static int gfs2_iomap_page_prepare(struct inode *inode, loff_t pos,
|
||||
unsigned len)
|
||||
{
|
||||
|
@ -1118,11 +1078,6 @@ out_qunlock:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static inline bool gfs2_iomap_need_write_lock(unsigned flags)
|
||||
{
|
||||
return (flags & IOMAP_WRITE) && !(flags & IOMAP_DIRECT);
|
||||
}
|
||||
|
||||
static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
|
||||
unsigned flags, struct iomap *iomap,
|
||||
struct iomap *srcmap)
|
||||
|
@ -1135,12 +1090,6 @@ static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
|
|||
iomap->flags |= IOMAP_F_BUFFER_HEAD;
|
||||
|
||||
trace_gfs2_iomap_start(ip, pos, length, flags);
|
||||
if (gfs2_iomap_need_write_lock(flags)) {
|
||||
ret = gfs2_write_lock(inode);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = __gfs2_iomap_get(inode, pos, length, flags, iomap, &mp);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
@ -1168,10 +1117,7 @@ static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
|
|||
ret = gfs2_iomap_begin_write(inode, pos, length, flags, iomap, &mp);
|
||||
|
||||
out_unlock:
|
||||
if (ret && gfs2_iomap_need_write_lock(flags))
|
||||
gfs2_write_unlock(inode);
|
||||
release_metapath(&mp);
|
||||
out:
|
||||
trace_gfs2_iomap_end(ip, iomap, ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1219,15 +1165,11 @@ static int gfs2_iomap_end(struct inode *inode, loff_t pos, loff_t length,
|
|||
}
|
||||
|
||||
if (unlikely(!written))
|
||||
goto out_unlock;
|
||||
return 0;
|
||||
|
||||
if (iomap->flags & IOMAP_F_SIZE_CHANGED)
|
||||
mark_inode_dirty(inode);
|
||||
set_bit(GLF_DIRTY, &ip->i_gl->gl_flags);
|
||||
|
||||
out_unlock:
|
||||
if (gfs2_iomap_need_write_lock(flags))
|
||||
gfs2_write_unlock(inode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -880,13 +880,40 @@ static ssize_t gfs2_file_buffered_write(struct kiocb *iocb, struct iov_iter *fro
|
|||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct inode *inode = file_inode(file);
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||
ssize_t ret;
|
||||
|
||||
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh);
|
||||
ret = gfs2_glock_nq(&ip->i_gh);
|
||||
if (ret)
|
||||
goto out_uninit;
|
||||
|
||||
if (inode == sdp->sd_rindex) {
|
||||
struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
|
||||
|
||||
ret = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE,
|
||||
GL_NOCACHE, &m_ip->i_gh);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
current->backing_dev_info = inode_to_bdi(inode);
|
||||
ret = iomap_file_buffered_write(iocb, from, &gfs2_iomap_ops);
|
||||
current->backing_dev_info = NULL;
|
||||
if (ret > 0)
|
||||
iocb->ki_pos += ret;
|
||||
|
||||
if (inode == sdp->sd_rindex) {
|
||||
struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
|
||||
|
||||
gfs2_glock_dq_uninit(&m_ip->i_gh);
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
gfs2_glock_dq(&ip->i_gh);
|
||||
out_uninit:
|
||||
gfs2_holder_uninit(&ip->i_gh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue