Changes for gfs2:
- Use asynchronous glocks and timeouts to recover from deadlocks during rename and exchange: the lock ordering constraints the vfs uses are not sufficient to prevent deadlocks across multiple nodes. - Add support for IOMAP_ZERO and use iomap_zero_range to replace gfs2 specific code. - Various other minor fixes and cleanups. -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJdg3/uAAoJENW/n+sDE2U60QYQAIkbRCwr068kHFlCKd9p764O Qa8gyp+Jhz9xlI8onNmFrPtEsLPscJLQ8HETrBn7lcb2fa4KBr9cfXt4I7nxObsL t8E7QxQJ8LVK0vzMJvXUzyPBxnSUsxMCewoXLtsHYKf+XkB/TocWKbaFHKOB8FrP fkdPE43H84HUZzGSMb+XLl0/4BZTxSE3Gy9lUfnMrVQwmi0sk7JNdN8SpIYgibIp pyEZUjwXO/l4NwuAyhzRv+4OTW9PYAtKLkVVz13vPFc3d51a9yAgVIDdDEKY6Lhl NYEhsRPoSCcqrLBc/Xuk54pxRx+mdjdPhO25Jdfc5f6ZT9tewHErnfKZlMFFt+gg pd+oFfwfAM7H2qOY4FXgKSfRq4Pu/bSuxFA62IHAvxKiCDA2q+eeHxUtq5yvGc57 qJhZOf5TIzrVNzMCQkuBkM44CzFZffqg62AgN7XSBw/4A1A65DSAzL+g5Tyr6vWH ZGYTnqJunr4HbCS/VU4OhgCB3+l9QX8PC6ok5a4Uqc5Oj6bGGd94y8BZsYeKhGp2 u2tv3TpwAOnNjEUUDSCRfeQYah+qIUETevxZinHeg21yxyZT97SXiKm/h4uiBwUm ECsHw0+gzWEZXR+CDHsfc6qpmYHTYHv4u5z8Oya+fdlFzH2MUGnZlgs5GXAwE24k HnxpOvThElLJO0+UMlAS =tUTY -----END PGP SIGNATURE----- Merge tag 'gfs2-for-5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2 Pull gfs2 updates from Andreas Gruenbacher: - Use asynchronous glocks and timeouts to recover from deadlocks during rename and exchange: the lock ordering constraints the vfs uses are not sufficient to prevent deadlocks across multiple nodes. - Add support for IOMAP_ZERO and use iomap_zero_range to replace gfs2 specific code. - Various other minor fixes and cleanups. * tag 'gfs2-for-5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2: gfs2: clear buf_in_tr when ending a transaction in sweep_bh_for_rgrps gfs2: Improve mmap write vs. truncate consistency gfs2: Use async glocks for rename gfs2: create function gfs2_glock_update_hold_time gfs2: separate holder for rgrps in gfs2_rename gfs2: Delete an unnecessary check before brelse() gfs2: Minor PAGE_SIZE arithmetic cleanups gfs2: Fix recovery slot bumping gfs2: Fix possible fs name overflows gfs2: untangle the logic in gfs2_drevalidate gfs2: Always mark inode dirty in fallocate gfs2: Minor gfs2_alloc_inode cleanup gfs2: implement gfs2_block_zero_range using iomap_zero_range gfs2: Add support for IOMAP_ZERO gfs2: gfs2_iomap_begin cleanup
This commit is contained in:
commit
f7c3bf8fa7
@ -243,7 +243,7 @@ static int gfs2_write_jdata_pagevec(struct address_space *mapping,
|
|||||||
{
|
{
|
||||||
struct inode *inode = mapping->host;
|
struct inode *inode = mapping->host;
|
||||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||||
unsigned nrblocks = nr_pages * (PAGE_SIZE/inode->i_sb->s_blocksize);
|
unsigned nrblocks = nr_pages * (PAGE_SIZE >> inode->i_blkbits);
|
||||||
int i;
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -552,7 +552,7 @@ int gfs2_internal_read(struct gfs2_inode *ip, char *buf, loff_t *pos,
|
|||||||
unsigned size)
|
unsigned size)
|
||||||
{
|
{
|
||||||
struct address_space *mapping = ip->i_inode.i_mapping;
|
struct address_space *mapping = ip->i_inode.i_mapping;
|
||||||
unsigned long index = *pos / PAGE_SIZE;
|
unsigned long index = *pos >> PAGE_SHIFT;
|
||||||
unsigned offset = *pos & (PAGE_SIZE - 1);
|
unsigned offset = *pos & (PAGE_SIZE - 1);
|
||||||
unsigned copied = 0;
|
unsigned copied = 0;
|
||||||
unsigned amt;
|
unsigned amt;
|
||||||
|
195
fs/gfs2/bmap.c
195
fs/gfs2/bmap.c
@ -1065,54 +1065,38 @@ static int gfs2_iomap_begin_write(struct inode *inode, loff_t pos,
|
|||||||
{
|
{
|
||||||
struct gfs2_inode *ip = GFS2_I(inode);
|
struct gfs2_inode *ip = GFS2_I(inode);
|
||||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||||
unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
|
bool unstuff;
|
||||||
bool unstuff, alloc_required;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = gfs2_write_lock(inode);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
unstuff = gfs2_is_stuffed(ip) &&
|
unstuff = gfs2_is_stuffed(ip) &&
|
||||||
pos + length > gfs2_max_stuffed_size(ip);
|
pos + length > gfs2_max_stuffed_size(ip);
|
||||||
|
|
||||||
ret = gfs2_iomap_get(inode, pos, length, flags, iomap, mp);
|
if (unstuff || iomap->type == IOMAP_HOLE) {
|
||||||
if (ret)
|
unsigned int data_blocks, ind_blocks;
|
||||||
goto out_unlock;
|
struct gfs2_alloc_parms ap = {};
|
||||||
|
unsigned int rblocks;
|
||||||
|
struct gfs2_trans *tr;
|
||||||
|
|
||||||
alloc_required = unstuff || iomap->type == IOMAP_HOLE;
|
|
||||||
|
|
||||||
if (alloc_required || gfs2_is_jdata(ip))
|
|
||||||
gfs2_write_calc_reserv(ip, iomap->length, &data_blocks,
|
gfs2_write_calc_reserv(ip, iomap->length, &data_blocks,
|
||||||
&ind_blocks);
|
&ind_blocks);
|
||||||
|
ap.target = data_blocks + ind_blocks;
|
||||||
if (alloc_required) {
|
|
||||||
struct gfs2_alloc_parms ap = {
|
|
||||||
.target = data_blocks + ind_blocks
|
|
||||||
};
|
|
||||||
|
|
||||||
ret = gfs2_quota_lock_check(ip, &ap);
|
ret = gfs2_quota_lock_check(ip, &ap);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_unlock;
|
return ret;
|
||||||
|
|
||||||
ret = gfs2_inplace_reserve(ip, &ap);
|
ret = gfs2_inplace_reserve(ip, &ap);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_qunlock;
|
goto out_qunlock;
|
||||||
}
|
|
||||||
|
|
||||||
rblocks = RES_DINODE + ind_blocks;
|
rblocks = RES_DINODE + ind_blocks;
|
||||||
if (gfs2_is_jdata(ip))
|
if (gfs2_is_jdata(ip))
|
||||||
rblocks += data_blocks;
|
rblocks += data_blocks;
|
||||||
if (ind_blocks || data_blocks)
|
if (ind_blocks || data_blocks)
|
||||||
rblocks += RES_STATFS + RES_QUOTA;
|
rblocks += RES_STATFS + RES_QUOTA;
|
||||||
if (inode == sdp->sd_rindex)
|
if (inode == sdp->sd_rindex)
|
||||||
rblocks += 2 * RES_STATFS;
|
rblocks += 2 * RES_STATFS;
|
||||||
if (alloc_required)
|
|
||||||
rblocks += gfs2_rg_blocks(ip, data_blocks + ind_blocks);
|
rblocks += gfs2_rg_blocks(ip, data_blocks + ind_blocks);
|
||||||
|
|
||||||
if (unstuff || iomap->type == IOMAP_HOLE) {
|
|
||||||
struct gfs2_trans *tr;
|
|
||||||
|
|
||||||
ret = gfs2_trans_begin(sdp, rblocks,
|
ret = gfs2_trans_begin(sdp, rblocks,
|
||||||
iomap->length >> inode->i_blkbits);
|
iomap->length >> inode->i_blkbits);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -1153,16 +1137,17 @@ static int gfs2_iomap_begin_write(struct inode *inode, loff_t pos,
|
|||||||
out_trans_end:
|
out_trans_end:
|
||||||
gfs2_trans_end(sdp);
|
gfs2_trans_end(sdp);
|
||||||
out_trans_fail:
|
out_trans_fail:
|
||||||
if (alloc_required)
|
gfs2_inplace_release(ip);
|
||||||
gfs2_inplace_release(ip);
|
|
||||||
out_qunlock:
|
out_qunlock:
|
||||||
if (alloc_required)
|
gfs2_quota_unlock(ip);
|
||||||
gfs2_quota_unlock(ip);
|
|
||||||
out_unlock:
|
|
||||||
gfs2_write_unlock(inode);
|
|
||||||
return ret;
|
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,
|
static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
|
||||||
unsigned flags, struct iomap *iomap)
|
unsigned flags, struct iomap *iomap)
|
||||||
{
|
{
|
||||||
@ -1173,20 +1158,43 @@ static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
|
|||||||
iomap->flags |= IOMAP_F_BUFFER_HEAD;
|
iomap->flags |= IOMAP_F_BUFFER_HEAD;
|
||||||
|
|
||||||
trace_gfs2_iomap_start(ip, pos, length, flags);
|
trace_gfs2_iomap_start(ip, pos, length, flags);
|
||||||
if ((flags & IOMAP_WRITE) && !(flags & IOMAP_DIRECT)) {
|
if (gfs2_iomap_need_write_lock(flags)) {
|
||||||
ret = gfs2_iomap_begin_write(inode, pos, length, flags, iomap, &mp);
|
ret = gfs2_write_lock(inode);
|
||||||
} else {
|
if (ret)
|
||||||
ret = gfs2_iomap_get(inode, pos, length, flags, iomap, &mp);
|
goto out;
|
||||||
|
|
||||||
/*
|
|
||||||
* Silently fall back to buffered I/O for stuffed files or if
|
|
||||||
* we've hot a hole (see gfs2_file_direct_write).
|
|
||||||
*/
|
|
||||||
if ((flags & IOMAP_WRITE) && (flags & IOMAP_DIRECT) &&
|
|
||||||
iomap->type != IOMAP_MAPPED)
|
|
||||||
ret = -ENOTBLK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = gfs2_iomap_get(inode, pos, length, flags, iomap, &mp);
|
||||||
|
if (ret)
|
||||||
|
goto out_unlock;
|
||||||
|
|
||||||
|
switch(flags & (IOMAP_WRITE | IOMAP_ZERO)) {
|
||||||
|
case IOMAP_WRITE:
|
||||||
|
if (flags & IOMAP_DIRECT) {
|
||||||
|
/*
|
||||||
|
* Silently fall back to buffered I/O for stuffed files
|
||||||
|
* or if we've got a hole (see gfs2_file_direct_write).
|
||||||
|
*/
|
||||||
|
if (iomap->type != IOMAP_MAPPED)
|
||||||
|
ret = -ENOTBLK;
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IOMAP_ZERO:
|
||||||
|
if (iomap->type == IOMAP_HOLE)
|
||||||
|
goto out_unlock;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
release_metapath(&mp);
|
||||||
|
out:
|
||||||
trace_gfs2_iomap_end(ip, iomap, ret);
|
trace_gfs2_iomap_end(ip, iomap, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1197,8 +1205,18 @@ static int gfs2_iomap_end(struct inode *inode, loff_t pos, loff_t length,
|
|||||||
struct gfs2_inode *ip = GFS2_I(inode);
|
struct gfs2_inode *ip = GFS2_I(inode);
|
||||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||||
|
|
||||||
if ((flags & (IOMAP_WRITE | IOMAP_DIRECT)) != IOMAP_WRITE)
|
switch (flags & (IOMAP_WRITE | IOMAP_ZERO)) {
|
||||||
goto out;
|
case IOMAP_WRITE:
|
||||||
|
if (flags & IOMAP_DIRECT)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case IOMAP_ZERO:
|
||||||
|
if (iomap->type == IOMAP_HOLE)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!gfs2_is_stuffed(ip))
|
if (!gfs2_is_stuffed(ip))
|
||||||
gfs2_ordered_add_inode(ip);
|
gfs2_ordered_add_inode(ip);
|
||||||
@ -1231,8 +1249,8 @@ static int gfs2_iomap_end(struct inode *inode, loff_t pos, loff_t length,
|
|||||||
set_bit(GLF_DIRTY, &ip->i_gl->gl_flags);
|
set_bit(GLF_DIRTY, &ip->i_gl->gl_flags);
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
gfs2_write_unlock(inode);
|
if (gfs2_iomap_need_write_lock(flags))
|
||||||
out:
|
gfs2_write_unlock(inode);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1330,76 +1348,10 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* gfs2_block_zero_range - Deal with zeroing out data
|
|
||||||
*
|
|
||||||
* This is partly borrowed from ext3.
|
|
||||||
*/
|
|
||||||
static int gfs2_block_zero_range(struct inode *inode, loff_t from,
|
static int gfs2_block_zero_range(struct inode *inode, loff_t from,
|
||||||
unsigned int length)
|
unsigned int length)
|
||||||
{
|
{
|
||||||
struct address_space *mapping = inode->i_mapping;
|
return iomap_zero_range(inode, from, length, NULL, &gfs2_iomap_ops);
|
||||||
struct gfs2_inode *ip = GFS2_I(inode);
|
|
||||||
unsigned long index = from >> PAGE_SHIFT;
|
|
||||||
unsigned offset = from & (PAGE_SIZE-1);
|
|
||||||
unsigned blocksize, iblock, pos;
|
|
||||||
struct buffer_head *bh;
|
|
||||||
struct page *page;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
page = find_or_create_page(mapping, index, GFP_NOFS);
|
|
||||||
if (!page)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
blocksize = inode->i_sb->s_blocksize;
|
|
||||||
iblock = index << (PAGE_SHIFT - inode->i_sb->s_blocksize_bits);
|
|
||||||
|
|
||||||
if (!page_has_buffers(page))
|
|
||||||
create_empty_buffers(page, blocksize, 0);
|
|
||||||
|
|
||||||
/* Find the buffer that contains "offset" */
|
|
||||||
bh = page_buffers(page);
|
|
||||||
pos = blocksize;
|
|
||||||
while (offset >= pos) {
|
|
||||||
bh = bh->b_this_page;
|
|
||||||
iblock++;
|
|
||||||
pos += blocksize;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = 0;
|
|
||||||
|
|
||||||
if (!buffer_mapped(bh)) {
|
|
||||||
gfs2_block_map(inode, iblock, bh, 0);
|
|
||||||
/* unmapped? It's a hole - nothing to do */
|
|
||||||
if (!buffer_mapped(bh))
|
|
||||||
goto unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ok, it's mapped. Make sure it's up-to-date */
|
|
||||||
if (PageUptodate(page))
|
|
||||||
set_buffer_uptodate(bh);
|
|
||||||
|
|
||||||
if (!buffer_uptodate(bh)) {
|
|
||||||
err = -EIO;
|
|
||||||
ll_rw_block(REQ_OP_READ, 0, 1, &bh);
|
|
||||||
wait_on_buffer(bh);
|
|
||||||
/* Uhhuh. Read error. Complain and punt. */
|
|
||||||
if (!buffer_uptodate(bh))
|
|
||||||
goto unlock;
|
|
||||||
err = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gfs2_is_jdata(ip))
|
|
||||||
gfs2_trans_add_data(ip->i_gl, bh);
|
|
||||||
else
|
|
||||||
gfs2_ordered_add_inode(ip);
|
|
||||||
|
|
||||||
zero_user(page, offset, length);
|
|
||||||
mark_buffer_dirty(bh);
|
|
||||||
unlock:
|
|
||||||
unlock_page(page);
|
|
||||||
put_page(page);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GFS2_JTRUNC_REVOKES 8192
|
#define GFS2_JTRUNC_REVOKES 8192
|
||||||
@ -1680,6 +1632,7 @@ out_unlock:
|
|||||||
brelse(dibh);
|
brelse(dibh);
|
||||||
up_write(&ip->i_rw_mutex);
|
up_write(&ip->i_rw_mutex);
|
||||||
gfs2_trans_end(sdp);
|
gfs2_trans_end(sdp);
|
||||||
|
buf_in_tr = false;
|
||||||
}
|
}
|
||||||
gfs2_glock_dq_uninit(rd_gh);
|
gfs2_glock_dq_uninit(rd_gh);
|
||||||
cond_resched();
|
cond_resched();
|
||||||
@ -2187,7 +2140,7 @@ static int do_grow(struct inode *inode, u64 size)
|
|||||||
if (error)
|
if (error)
|
||||||
goto do_end_trans;
|
goto do_end_trans;
|
||||||
|
|
||||||
i_size_write(inode, size);
|
truncate_setsize(inode, size);
|
||||||
ip->i_inode.i_mtime = ip->i_inode.i_ctime = current_time(&ip->i_inode);
|
ip->i_inode.i_mtime = ip->i_inode.i_ctime = current_time(&ip->i_inode);
|
||||||
gfs2_trans_add_meta(ip->i_gl, dibh);
|
gfs2_trans_add_meta(ip->i_gl, dibh);
|
||||||
gfs2_dinode_out(ip, dibh->b_data);
|
gfs2_dinode_out(ip, dibh->b_data);
|
||||||
|
@ -38,7 +38,7 @@ static int gfs2_drevalidate(struct dentry *dentry, unsigned int flags)
|
|||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct gfs2_holder d_gh;
|
struct gfs2_holder d_gh;
|
||||||
struct gfs2_inode *ip = NULL;
|
struct gfs2_inode *ip = NULL;
|
||||||
int error;
|
int error, valid = 0;
|
||||||
int had_lock = 0;
|
int had_lock = 0;
|
||||||
|
|
||||||
if (flags & LOOKUP_RCU)
|
if (flags & LOOKUP_RCU)
|
||||||
@ -51,53 +51,30 @@ static int gfs2_drevalidate(struct dentry *dentry, unsigned int flags)
|
|||||||
|
|
||||||
if (inode) {
|
if (inode) {
|
||||||
if (is_bad_inode(inode))
|
if (is_bad_inode(inode))
|
||||||
goto invalid;
|
goto out;
|
||||||
ip = GFS2_I(inode);
|
ip = GFS2_I(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
|
if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL) {
|
||||||
goto valid;
|
valid = 1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL);
|
had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL);
|
||||||
if (!had_lock) {
|
if (!had_lock) {
|
||||||
error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
|
error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
|
||||||
if (error)
|
if (error)
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
error = gfs2_dir_check(d_inode(parent), &dentry->d_name, ip);
|
|
||||||
switch (error) {
|
|
||||||
case 0:
|
|
||||||
if (!inode)
|
|
||||||
goto invalid_gunlock;
|
|
||||||
break;
|
|
||||||
case -ENOENT:
|
|
||||||
if (!inode)
|
|
||||||
goto valid_gunlock;
|
|
||||||
goto invalid_gunlock;
|
|
||||||
default:
|
|
||||||
goto fail_gunlock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
valid_gunlock:
|
error = gfs2_dir_check(d_inode(parent), &dentry->d_name, ip);
|
||||||
|
valid = inode ? !error : (error == -ENOENT);
|
||||||
|
|
||||||
if (!had_lock)
|
if (!had_lock)
|
||||||
gfs2_glock_dq_uninit(&d_gh);
|
gfs2_glock_dq_uninit(&d_gh);
|
||||||
valid:
|
out:
|
||||||
dput(parent);
|
dput(parent);
|
||||||
return 1;
|
return valid;
|
||||||
|
|
||||||
invalid_gunlock:
|
|
||||||
if (!had_lock)
|
|
||||||
gfs2_glock_dq_uninit(&d_gh);
|
|
||||||
invalid:
|
|
||||||
dput(parent);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fail_gunlock:
|
|
||||||
gfs2_glock_dq_uninit(&d_gh);
|
|
||||||
fail:
|
|
||||||
dput(parent);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gfs2_dhash(const struct dentry *dentry, struct qstr *str)
|
static int gfs2_dhash(const struct dentry *dentry, struct qstr *str)
|
||||||
|
@ -1463,8 +1463,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, struct dir_context *ctx,
|
|||||||
sort_offset : entries, copied);
|
sort_offset : entries, copied);
|
||||||
out_free:
|
out_free:
|
||||||
for(i = 0; i < leaf; i++)
|
for(i = 0; i < leaf; i++)
|
||||||
if (larr[i])
|
brelse(larr[i]);
|
||||||
brelse(larr[i]);
|
|
||||||
kvfree(larr);
|
kvfree(larr);
|
||||||
out:
|
out:
|
||||||
return error;
|
return error;
|
||||||
|
@ -32,8 +32,7 @@ extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
|
|||||||
const struct gfs2_inode *ip, struct gfs2_diradd *da);
|
const struct gfs2_inode *ip, struct gfs2_diradd *da);
|
||||||
static inline void gfs2_dir_no_add(struct gfs2_diradd *da)
|
static inline void gfs2_dir_no_add(struct gfs2_diradd *da)
|
||||||
{
|
{
|
||||||
if (da->bh)
|
brelse(da->bh);
|
||||||
brelse(da->bh);
|
|
||||||
da->bh = NULL;
|
da->bh = NULL;
|
||||||
}
|
}
|
||||||
extern int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry);
|
extern int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry);
|
||||||
|
@ -1049,7 +1049,7 @@ static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t
|
|||||||
rblocks += data_blocks ? data_blocks : 1;
|
rblocks += data_blocks ? data_blocks : 1;
|
||||||
|
|
||||||
error = gfs2_trans_begin(sdp, rblocks,
|
error = gfs2_trans_begin(sdp, rblocks,
|
||||||
PAGE_SIZE/sdp->sd_sb.sb_bsize);
|
PAGE_SIZE >> inode->i_blkbits);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_trans_fail;
|
goto out_trans_fail;
|
||||||
|
|
||||||
@ -1065,11 +1065,10 @@ static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t
|
|||||||
gfs2_quota_unlock(ip);
|
gfs2_quota_unlock(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(mode & FALLOC_FL_KEEP_SIZE) && (pos + count) > inode->i_size) {
|
if (!(mode & FALLOC_FL_KEEP_SIZE) && (pos + count) > inode->i_size)
|
||||||
i_size_write(inode, pos + count);
|
i_size_write(inode, pos + count);
|
||||||
file_update_time(file);
|
file_update_time(file);
|
||||||
mark_inode_dirty(inode);
|
mark_inode_dirty(inode);
|
||||||
}
|
|
||||||
|
|
||||||
if ((file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host))
|
if ((file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host))
|
||||||
return vfs_fsync_range(file, pos, pos + count - 1,
|
return vfs_fsync_range(file, pos, pos + count - 1,
|
||||||
|
115
fs/gfs2/glock.c
115
fs/gfs2/glock.c
@ -305,6 +305,11 @@ static void gfs2_holder_wake(struct gfs2_holder *gh)
|
|||||||
clear_bit(HIF_WAIT, &gh->gh_iflags);
|
clear_bit(HIF_WAIT, &gh->gh_iflags);
|
||||||
smp_mb__after_atomic();
|
smp_mb__after_atomic();
|
||||||
wake_up_bit(&gh->gh_iflags, HIF_WAIT);
|
wake_up_bit(&gh->gh_iflags, HIF_WAIT);
|
||||||
|
if (gh->gh_flags & GL_ASYNC) {
|
||||||
|
struct gfs2_sbd *sdp = gh->gh_gl->gl_name.ln_sbd;
|
||||||
|
|
||||||
|
wake_up(&sdp->sd_async_glock_wait);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -931,6 +936,17 @@ void gfs2_holder_uninit(struct gfs2_holder *gh)
|
|||||||
gh->gh_ip = 0;
|
gh->gh_ip = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gfs2_glock_update_hold_time(struct gfs2_glock *gl,
|
||||||
|
unsigned long start_time)
|
||||||
|
{
|
||||||
|
/* Have we waited longer that a second? */
|
||||||
|
if (time_after(jiffies, start_time + HZ)) {
|
||||||
|
/* Lengthen the minimum hold time. */
|
||||||
|
gl->gl_hold_time = min(gl->gl_hold_time + GL_GLOCK_HOLD_INCR,
|
||||||
|
GL_GLOCK_MAX_HOLD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gfs2_glock_wait - wait on a glock acquisition
|
* gfs2_glock_wait - wait on a glock acquisition
|
||||||
* @gh: the glock holder
|
* @gh: the glock holder
|
||||||
@ -940,18 +956,99 @@ void gfs2_holder_uninit(struct gfs2_holder *gh)
|
|||||||
|
|
||||||
int gfs2_glock_wait(struct gfs2_holder *gh)
|
int gfs2_glock_wait(struct gfs2_holder *gh)
|
||||||
{
|
{
|
||||||
unsigned long time1 = jiffies;
|
unsigned long start_time = jiffies;
|
||||||
|
|
||||||
might_sleep();
|
might_sleep();
|
||||||
wait_on_bit(&gh->gh_iflags, HIF_WAIT, TASK_UNINTERRUPTIBLE);
|
wait_on_bit(&gh->gh_iflags, HIF_WAIT, TASK_UNINTERRUPTIBLE);
|
||||||
if (time_after(jiffies, time1 + HZ)) /* have we waited > a second? */
|
gfs2_glock_update_hold_time(gh->gh_gl, start_time);
|
||||||
/* Lengthen the minimum hold time. */
|
|
||||||
gh->gh_gl->gl_hold_time = min(gh->gh_gl->gl_hold_time +
|
|
||||||
GL_GLOCK_HOLD_INCR,
|
|
||||||
GL_GLOCK_MAX_HOLD);
|
|
||||||
return gh->gh_error;
|
return gh->gh_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int glocks_pending(unsigned int num_gh, struct gfs2_holder *ghs)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_gh; i++)
|
||||||
|
if (test_bit(HIF_WAIT, &ghs[i].gh_iflags))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gfs2_glock_async_wait - wait on multiple asynchronous glock acquisitions
|
||||||
|
* @num_gh: the number of holders in the array
|
||||||
|
* @ghs: the glock holder array
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, meaning all glocks have been granted and are held.
|
||||||
|
* -ESTALE if the request timed out, meaning all glocks were released,
|
||||||
|
* and the caller should retry the operation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int gfs2_glock_async_wait(unsigned int num_gh, struct gfs2_holder *ghs)
|
||||||
|
{
|
||||||
|
struct gfs2_sbd *sdp = ghs[0].gh_gl->gl_name.ln_sbd;
|
||||||
|
int i, ret = 0, timeout = 0;
|
||||||
|
unsigned long start_time = jiffies;
|
||||||
|
bool keep_waiting;
|
||||||
|
|
||||||
|
might_sleep();
|
||||||
|
/*
|
||||||
|
* Total up the (minimum hold time * 2) of all glocks and use that to
|
||||||
|
* determine the max amount of time we should wait.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < num_gh; i++)
|
||||||
|
timeout += ghs[i].gh_gl->gl_hold_time << 1;
|
||||||
|
|
||||||
|
wait_for_dlm:
|
||||||
|
if (!wait_event_timeout(sdp->sd_async_glock_wait,
|
||||||
|
!glocks_pending(num_gh, ghs), timeout))
|
||||||
|
ret = -ESTALE; /* request timed out. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If dlm granted all our requests, we need to adjust the glock
|
||||||
|
* minimum hold time values according to how long we waited.
|
||||||
|
*
|
||||||
|
* If our request timed out, we need to repeatedly release any held
|
||||||
|
* glocks we acquired thus far to allow dlm to acquire the remaining
|
||||||
|
* glocks without deadlocking. We cannot currently cancel outstanding
|
||||||
|
* glock acquisitions.
|
||||||
|
*
|
||||||
|
* The HIF_WAIT bit tells us which requests still need a response from
|
||||||
|
* dlm.
|
||||||
|
*
|
||||||
|
* If dlm sent us any errors, we return the first error we find.
|
||||||
|
*/
|
||||||
|
keep_waiting = false;
|
||||||
|
for (i = 0; i < num_gh; i++) {
|
||||||
|
/* Skip holders we have already dequeued below. */
|
||||||
|
if (!gfs2_holder_queued(&ghs[i]))
|
||||||
|
continue;
|
||||||
|
/* Skip holders with a pending DLM response. */
|
||||||
|
if (test_bit(HIF_WAIT, &ghs[i].gh_iflags)) {
|
||||||
|
keep_waiting = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test_bit(HIF_HOLDER, &ghs[i].gh_iflags)) {
|
||||||
|
if (ret == -ESTALE)
|
||||||
|
gfs2_glock_dq(&ghs[i]);
|
||||||
|
else
|
||||||
|
gfs2_glock_update_hold_time(ghs[i].gh_gl,
|
||||||
|
start_time);
|
||||||
|
}
|
||||||
|
if (!ret)
|
||||||
|
ret = ghs[i].gh_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keep_waiting)
|
||||||
|
goto wait_for_dlm;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this point, we've either acquired all locks or released them all.
|
||||||
|
*/
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* handle_callback - process a demote request
|
* handle_callback - process a demote request
|
||||||
* @gl: the glock
|
* @gl: the glock
|
||||||
@ -1018,9 +1115,9 @@ __acquires(&gl->gl_lockref.lock)
|
|||||||
struct gfs2_holder *gh2;
|
struct gfs2_holder *gh2;
|
||||||
int try_futile = 0;
|
int try_futile = 0;
|
||||||
|
|
||||||
BUG_ON(gh->gh_owner_pid == NULL);
|
GLOCK_BUG_ON(gl, gh->gh_owner_pid == NULL);
|
||||||
if (test_and_set_bit(HIF_WAIT, &gh->gh_iflags))
|
if (test_and_set_bit(HIF_WAIT, &gh->gh_iflags))
|
||||||
BUG();
|
GLOCK_BUG_ON(gl, true);
|
||||||
|
|
||||||
if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) {
|
if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) {
|
||||||
if (test_bit(GLF_LOCK, &gl->gl_flags))
|
if (test_bit(GLF_LOCK, &gl->gl_flags))
|
||||||
@ -1788,8 +1885,8 @@ void gfs2_dump_glock(struct seq_file *seq, struct gfs2_glock *gl, bool fsid)
|
|||||||
unsigned long long dtime;
|
unsigned long long dtime;
|
||||||
const struct gfs2_holder *gh;
|
const struct gfs2_holder *gh;
|
||||||
char gflags_buf[32];
|
char gflags_buf[32];
|
||||||
char fs_id_buf[GFS2_FSNAME_LEN + 3 * sizeof(int) + 2];
|
|
||||||
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
|
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
|
||||||
|
char fs_id_buf[sizeof(sdp->sd_fsname) + 7];
|
||||||
|
|
||||||
memset(fs_id_buf, 0, sizeof(fs_id_buf));
|
memset(fs_id_buf, 0, sizeof(fs_id_buf));
|
||||||
if (fsid && sdp) /* safety precaution */
|
if (fsid && sdp) /* safety precaution */
|
||||||
|
@ -190,6 +190,7 @@ extern void gfs2_holder_uninit(struct gfs2_holder *gh);
|
|||||||
extern int gfs2_glock_nq(struct gfs2_holder *gh);
|
extern int gfs2_glock_nq(struct gfs2_holder *gh);
|
||||||
extern int gfs2_glock_poll(struct gfs2_holder *gh);
|
extern int gfs2_glock_poll(struct gfs2_holder *gh);
|
||||||
extern int gfs2_glock_wait(struct gfs2_holder *gh);
|
extern int gfs2_glock_wait(struct gfs2_holder *gh);
|
||||||
|
extern int gfs2_glock_async_wait(unsigned int num_gh, struct gfs2_holder *ghs);
|
||||||
extern void gfs2_glock_dq(struct gfs2_holder *gh);
|
extern void gfs2_glock_dq(struct gfs2_holder *gh);
|
||||||
extern void gfs2_glock_dq_wait(struct gfs2_holder *gh);
|
extern void gfs2_glock_dq_wait(struct gfs2_holder *gh);
|
||||||
extern void gfs2_glock_dq_uninit(struct gfs2_holder *gh);
|
extern void gfs2_glock_dq_uninit(struct gfs2_holder *gh);
|
||||||
@ -260,6 +261,11 @@ static inline bool gfs2_holder_initialized(struct gfs2_holder *gh)
|
|||||||
return gh->gh_gl;
|
return gh->gh_gl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool gfs2_holder_queued(struct gfs2_holder *gh)
|
||||||
|
{
|
||||||
|
return !list_empty(&gh->gh_list);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* glock_set_object - set the gl_object field of a glock
|
* glock_set_object - set the gl_object field of a glock
|
||||||
* @gl: the glock
|
* @gl: the glock
|
||||||
|
@ -725,6 +725,7 @@ struct gfs2_sbd {
|
|||||||
struct gfs2_glock *sd_freeze_gl;
|
struct gfs2_glock *sd_freeze_gl;
|
||||||
struct work_struct sd_freeze_work;
|
struct work_struct sd_freeze_work;
|
||||||
wait_queue_head_t sd_glock_wait;
|
wait_queue_head_t sd_glock_wait;
|
||||||
|
wait_queue_head_t sd_async_glock_wait;
|
||||||
atomic_t sd_glock_disposal;
|
atomic_t sd_glock_disposal;
|
||||||
struct completion sd_locking_init;
|
struct completion sd_locking_init;
|
||||||
struct completion sd_wdack;
|
struct completion sd_wdack;
|
||||||
|
@ -1348,7 +1348,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
|
|||||||
struct gfs2_inode *ip = GFS2_I(d_inode(odentry));
|
struct gfs2_inode *ip = GFS2_I(d_inode(odentry));
|
||||||
struct gfs2_inode *nip = NULL;
|
struct gfs2_inode *nip = NULL;
|
||||||
struct gfs2_sbd *sdp = GFS2_SB(odir);
|
struct gfs2_sbd *sdp = GFS2_SB(odir);
|
||||||
struct gfs2_holder ghs[5], r_gh;
|
struct gfs2_holder ghs[4], r_gh, rd_gh;
|
||||||
struct gfs2_rgrpd *nrgd;
|
struct gfs2_rgrpd *nrgd;
|
||||||
unsigned int num_gh;
|
unsigned int num_gh;
|
||||||
int dir_rename = 0;
|
int dir_rename = 0;
|
||||||
@ -1357,6 +1357,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
|
|||||||
int error;
|
int error;
|
||||||
|
|
||||||
gfs2_holder_mark_uninitialized(&r_gh);
|
gfs2_holder_mark_uninitialized(&r_gh);
|
||||||
|
gfs2_holder_mark_uninitialized(&rd_gh);
|
||||||
if (d_really_is_positive(ndentry)) {
|
if (d_really_is_positive(ndentry)) {
|
||||||
nip = GFS2_I(d_inode(ndentry));
|
nip = GFS2_I(d_inode(ndentry));
|
||||||
if (ip == nip)
|
if (ip == nip)
|
||||||
@ -1387,24 +1388,19 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
|
|||||||
}
|
}
|
||||||
|
|
||||||
num_gh = 1;
|
num_gh = 1;
|
||||||
gfs2_holder_init(odip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
|
gfs2_holder_init(odip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, ghs);
|
||||||
if (odip != ndip) {
|
if (odip != ndip) {
|
||||||
gfs2_holder_init(ndip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh);
|
gfs2_holder_init(ndip->i_gl, LM_ST_EXCLUSIVE,GL_ASYNC,
|
||||||
|
ghs + num_gh);
|
||||||
num_gh++;
|
num_gh++;
|
||||||
}
|
}
|
||||||
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh);
|
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, ghs + num_gh);
|
||||||
num_gh++;
|
num_gh++;
|
||||||
|
|
||||||
if (nip) {
|
if (nip) {
|
||||||
gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh);
|
gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC,
|
||||||
|
ghs + num_gh);
|
||||||
num_gh++;
|
num_gh++;
|
||||||
/* grab the resource lock for unlink flag twiddling
|
|
||||||
* this is the case of the target file already existing
|
|
||||||
* so we unlink before doing the rename
|
|
||||||
*/
|
|
||||||
nrgd = gfs2_blk2rgrpd(sdp, nip->i_no_addr, 1);
|
|
||||||
if (nrgd)
|
|
||||||
gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (x = 0; x < num_gh; x++) {
|
for (x = 0; x < num_gh; x++) {
|
||||||
@ -1412,6 +1408,25 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
|
|||||||
if (error)
|
if (error)
|
||||||
goto out_gunlock;
|
goto out_gunlock;
|
||||||
}
|
}
|
||||||
|
error = gfs2_glock_async_wait(num_gh, ghs);
|
||||||
|
if (error)
|
||||||
|
goto out_gunlock;
|
||||||
|
|
||||||
|
if (nip) {
|
||||||
|
/* Grab the resource group glock for unlink flag twiddling.
|
||||||
|
* This is the case where the target dinode already exists
|
||||||
|
* so we unlink before doing the rename.
|
||||||
|
*/
|
||||||
|
nrgd = gfs2_blk2rgrpd(sdp, nip->i_no_addr, 1);
|
||||||
|
if (!nrgd) {
|
||||||
|
error = -ENOENT;
|
||||||
|
goto out_gunlock;
|
||||||
|
}
|
||||||
|
error = gfs2_glock_nq_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0,
|
||||||
|
&rd_gh);
|
||||||
|
if (error)
|
||||||
|
goto out_gunlock;
|
||||||
|
}
|
||||||
|
|
||||||
error = -ENOENT;
|
error = -ENOENT;
|
||||||
if (ip->i_inode.i_nlink == 0)
|
if (ip->i_inode.i_nlink == 0)
|
||||||
@ -1541,8 +1556,12 @@ out_gunlock_q:
|
|||||||
gfs2_quota_unlock(ndip);
|
gfs2_quota_unlock(ndip);
|
||||||
out_gunlock:
|
out_gunlock:
|
||||||
gfs2_dir_no_add(&da);
|
gfs2_dir_no_add(&da);
|
||||||
|
if (gfs2_holder_initialized(&rd_gh))
|
||||||
|
gfs2_glock_dq_uninit(&rd_gh);
|
||||||
|
|
||||||
while (x--) {
|
while (x--) {
|
||||||
gfs2_glock_dq(ghs + x);
|
if (gfs2_holder_queued(ghs + x))
|
||||||
|
gfs2_glock_dq(ghs + x);
|
||||||
gfs2_holder_uninit(ghs + x);
|
gfs2_holder_uninit(ghs + x);
|
||||||
}
|
}
|
||||||
out_gunlock_r:
|
out_gunlock_r:
|
||||||
@ -1572,7 +1591,7 @@ static int gfs2_exchange(struct inode *odir, struct dentry *odentry,
|
|||||||
struct gfs2_inode *oip = GFS2_I(odentry->d_inode);
|
struct gfs2_inode *oip = GFS2_I(odentry->d_inode);
|
||||||
struct gfs2_inode *nip = GFS2_I(ndentry->d_inode);
|
struct gfs2_inode *nip = GFS2_I(ndentry->d_inode);
|
||||||
struct gfs2_sbd *sdp = GFS2_SB(odir);
|
struct gfs2_sbd *sdp = GFS2_SB(odir);
|
||||||
struct gfs2_holder ghs[5], r_gh;
|
struct gfs2_holder ghs[4], r_gh;
|
||||||
unsigned int num_gh;
|
unsigned int num_gh;
|
||||||
unsigned int x;
|
unsigned int x;
|
||||||
umode_t old_mode = oip->i_inode.i_mode;
|
umode_t old_mode = oip->i_inode.i_mode;
|
||||||
@ -1606,15 +1625,16 @@ static int gfs2_exchange(struct inode *odir, struct dentry *odentry,
|
|||||||
}
|
}
|
||||||
|
|
||||||
num_gh = 1;
|
num_gh = 1;
|
||||||
gfs2_holder_init(odip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
|
gfs2_holder_init(odip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, ghs);
|
||||||
if (odip != ndip) {
|
if (odip != ndip) {
|
||||||
gfs2_holder_init(ndip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh);
|
gfs2_holder_init(ndip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC,
|
||||||
|
ghs + num_gh);
|
||||||
num_gh++;
|
num_gh++;
|
||||||
}
|
}
|
||||||
gfs2_holder_init(oip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh);
|
gfs2_holder_init(oip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, ghs + num_gh);
|
||||||
num_gh++;
|
num_gh++;
|
||||||
|
|
||||||
gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh);
|
gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, ghs + num_gh);
|
||||||
num_gh++;
|
num_gh++;
|
||||||
|
|
||||||
for (x = 0; x < num_gh; x++) {
|
for (x = 0; x < num_gh; x++) {
|
||||||
@ -1623,6 +1643,10 @@ static int gfs2_exchange(struct inode *odir, struct dentry *odentry,
|
|||||||
goto out_gunlock;
|
goto out_gunlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error = gfs2_glock_async_wait(num_gh, ghs);
|
||||||
|
if (error)
|
||||||
|
goto out_gunlock;
|
||||||
|
|
||||||
error = -ENOENT;
|
error = -ENOENT;
|
||||||
if (oip->i_inode.i_nlink == 0 || nip->i_inode.i_nlink == 0)
|
if (oip->i_inode.i_nlink == 0 || nip->i_inode.i_nlink == 0)
|
||||||
goto out_gunlock;
|
goto out_gunlock;
|
||||||
@ -1683,7 +1707,8 @@ out_end_trans:
|
|||||||
gfs2_trans_end(sdp);
|
gfs2_trans_end(sdp);
|
||||||
out_gunlock:
|
out_gunlock:
|
||||||
while (x--) {
|
while (x--) {
|
||||||
gfs2_glock_dq(ghs + x);
|
if (gfs2_holder_queued(ghs + x))
|
||||||
|
gfs2_glock_dq(ghs + x);
|
||||||
gfs2_holder_uninit(ghs + x);
|
gfs2_holder_uninit(ghs + x);
|
||||||
}
|
}
|
||||||
out_gunlock_r:
|
out_gunlock_r:
|
||||||
|
@ -1035,12 +1035,12 @@ static int set_recover_size(struct gfs2_sbd *sdp, struct dlm_slot *slots,
|
|||||||
}
|
}
|
||||||
|
|
||||||
old_size = ls->ls_recover_size;
|
old_size = ls->ls_recover_size;
|
||||||
|
new_size = old_size;
|
||||||
if (old_size >= max_jid + 1)
|
while (new_size < max_jid + 1)
|
||||||
|
new_size += RECOVER_SIZE_INC;
|
||||||
|
if (new_size == old_size)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
new_size = old_size + RECOVER_SIZE_INC;
|
|
||||||
|
|
||||||
submit = kcalloc(new_size, sizeof(uint32_t), GFP_NOFS);
|
submit = kcalloc(new_size, sizeof(uint32_t), GFP_NOFS);
|
||||||
result = kcalloc(new_size, sizeof(uint32_t), GFP_NOFS);
|
result = kcalloc(new_size, sizeof(uint32_t), GFP_NOFS);
|
||||||
if (!submit || !result) {
|
if (!submit || !result) {
|
||||||
|
@ -87,6 +87,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
|
|||||||
gfs2_tune_init(&sdp->sd_tune);
|
gfs2_tune_init(&sdp->sd_tune);
|
||||||
|
|
||||||
init_waitqueue_head(&sdp->sd_glock_wait);
|
init_waitqueue_head(&sdp->sd_glock_wait);
|
||||||
|
init_waitqueue_head(&sdp->sd_async_glock_wait);
|
||||||
atomic_set(&sdp->sd_glock_disposal, 0);
|
atomic_set(&sdp->sd_glock_disposal, 0);
|
||||||
init_completion(&sdp->sd_locking_init);
|
init_completion(&sdp->sd_locking_init);
|
||||||
init_completion(&sdp->sd_wdack);
|
init_completion(&sdp->sd_wdack);
|
||||||
|
@ -774,7 +774,7 @@ static int gfs2_write_disk_quota(struct gfs2_inode *ip, struct gfs2_quota *qp,
|
|||||||
nbytes = sizeof(struct gfs2_quota);
|
nbytes = sizeof(struct gfs2_quota);
|
||||||
|
|
||||||
pg_beg = loc >> PAGE_SHIFT;
|
pg_beg = loc >> PAGE_SHIFT;
|
||||||
pg_off = loc % PAGE_SIZE;
|
pg_off = offset_in_page(loc);
|
||||||
|
|
||||||
/* If the quota straddles a page boundary, split the write in two */
|
/* If the quota straddles a page boundary, split the write in two */
|
||||||
if ((pg_off + nbytes) > PAGE_SIZE) {
|
if ((pg_off + nbytes) > PAGE_SIZE) {
|
||||||
|
@ -2285,7 +2285,7 @@ void gfs2_rgrp_dump(struct seq_file *seq, struct gfs2_glock *gl,
|
|||||||
static void gfs2_rgrp_error(struct gfs2_rgrpd *rgd)
|
static void gfs2_rgrp_error(struct gfs2_rgrpd *rgd)
|
||||||
{
|
{
|
||||||
struct gfs2_sbd *sdp = rgd->rd_sbd;
|
struct gfs2_sbd *sdp = rgd->rd_sbd;
|
||||||
char fs_id_buf[GFS2_FSNAME_LEN + 3 * sizeof(int) + 2];
|
char fs_id_buf[sizeof(sdp->sd_fsname) + 7];
|
||||||
|
|
||||||
fs_warn(sdp, "rgrp %llu has an error, marking it readonly until umount\n",
|
fs_warn(sdp, "rgrp %llu has an error, marking it readonly until umount\n",
|
||||||
(unsigned long long)rgd->rd_addr);
|
(unsigned long long)rgd->rd_addr);
|
||||||
|
@ -1722,13 +1722,13 @@ static struct inode *gfs2_alloc_inode(struct super_block *sb)
|
|||||||
struct gfs2_inode *ip;
|
struct gfs2_inode *ip;
|
||||||
|
|
||||||
ip = kmem_cache_alloc(gfs2_inode_cachep, GFP_KERNEL);
|
ip = kmem_cache_alloc(gfs2_inode_cachep, GFP_KERNEL);
|
||||||
if (ip) {
|
if (!ip)
|
||||||
ip->i_flags = 0;
|
return NULL;
|
||||||
ip->i_gl = NULL;
|
ip->i_flags = 0;
|
||||||
memset(&ip->i_res, 0, sizeof(ip->i_res));
|
ip->i_gl = NULL;
|
||||||
RB_CLEAR_NODE(&ip->i_res.rs_node);
|
memset(&ip->i_res, 0, sizeof(ip->i_res));
|
||||||
ip->i_rahead = 0;
|
RB_CLEAR_NODE(&ip->i_res.rs_node);
|
||||||
}
|
ip->i_rahead = 0;
|
||||||
return &ip->i_inode;
|
return &ip->i_inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ int gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd, int cluster_wide,
|
|||||||
const char *function, char *file, unsigned int line)
|
const char *function, char *file, unsigned int line)
|
||||||
{
|
{
|
||||||
struct gfs2_sbd *sdp = rgd->rd_sbd;
|
struct gfs2_sbd *sdp = rgd->rd_sbd;
|
||||||
char fs_id_buf[GFS2_FSNAME_LEN + 3 * sizeof(int) + 2];
|
char fs_id_buf[sizeof(sdp->sd_fsname) + 7];
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
sprintf(fs_id_buf, "fsid=%s: ", sdp->sd_fsname);
|
sprintf(fs_id_buf, "fsid=%s: ", sdp->sd_fsname);
|
||||||
|
Loading…
Reference in New Issue
Block a user