Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes
Pull gfs2 fixes from Steven Whitehouse: "There are four patches this time. The first fixes a problem where the wrong descriptor type was being written into the log for journaled data blocks. The second fixes a race relating to the deallocation of allocator data. The third provides a fallback if kmalloc is unable to satisfy a request to allocate a directory hash table. The fourth fixes the iopen glock caching so that inodes are deleted in a more timely manner after rmdir/unlink" * git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes: GFS2: Don't cache iopen glocks GFS2: Fall back to vmalloc if kmalloc fails for dir hash tables GFS2: Increase i_writecount during gfs2_setattr_size GFS2: Set log descriptor type for jdata blocks
This commit is contained in:
commit
6f66f9005b
|
@ -1286,17 +1286,26 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = get_write_access(inode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
inode_dio_wait(inode);
|
||||
|
||||
ret = gfs2_rs_alloc(GFS2_I(inode));
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
oldsize = inode->i_size;
|
||||
if (newsize >= oldsize)
|
||||
return do_grow(inode, newsize);
|
||||
if (newsize >= oldsize) {
|
||||
ret = do_grow(inode, newsize);
|
||||
goto out;
|
||||
}
|
||||
|
||||
return do_shrink(inode, oldsize, newsize);
|
||||
ret = do_shrink(inode, oldsize, newsize);
|
||||
out:
|
||||
put_write_access(inode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int gfs2_truncatei_resume(struct gfs2_inode *ip)
|
||||
|
|
|
@ -354,22 +354,31 @@ static __be64 *gfs2_dir_get_hash_table(struct gfs2_inode *ip)
|
|||
return ERR_PTR(-EIO);
|
||||
}
|
||||
|
||||
hc = kmalloc(hsize, GFP_NOFS);
|
||||
ret = -ENOMEM;
|
||||
hc = kmalloc(hsize, GFP_NOFS | __GFP_NOWARN);
|
||||
if (hc == NULL)
|
||||
hc = __vmalloc(hsize, GFP_NOFS, PAGE_KERNEL);
|
||||
|
||||
if (hc == NULL)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = gfs2_dir_read_data(ip, hc, hsize);
|
||||
if (ret < 0) {
|
||||
kfree(hc);
|
||||
if (is_vmalloc_addr(hc))
|
||||
vfree(hc);
|
||||
else
|
||||
kfree(hc);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
if (ip->i_hash_cache)
|
||||
kfree(hc);
|
||||
else
|
||||
if (ip->i_hash_cache) {
|
||||
if (is_vmalloc_addr(hc))
|
||||
vfree(hc);
|
||||
else
|
||||
kfree(hc);
|
||||
} else {
|
||||
ip->i_hash_cache = hc;
|
||||
}
|
||||
spin_unlock(&inode->i_lock);
|
||||
|
||||
return ip->i_hash_cache;
|
||||
|
@ -385,7 +394,10 @@ void gfs2_dir_hash_inval(struct gfs2_inode *ip)
|
|||
{
|
||||
__be64 *hc = ip->i_hash_cache;
|
||||
ip->i_hash_cache = NULL;
|
||||
kfree(hc);
|
||||
if (is_vmalloc_addr(hc))
|
||||
vfree(hc);
|
||||
else
|
||||
kfree(hc);
|
||||
}
|
||||
|
||||
static inline int gfs2_dirent_sentinel(const struct gfs2_dirent *dent)
|
||||
|
@ -1113,7 +1125,10 @@ static int dir_double_exhash(struct gfs2_inode *dip)
|
|||
if (IS_ERR(hc))
|
||||
return PTR_ERR(hc);
|
||||
|
||||
h = hc2 = kmalloc(hsize_bytes * 2, GFP_NOFS);
|
||||
h = hc2 = kmalloc(hsize_bytes * 2, GFP_NOFS | __GFP_NOWARN);
|
||||
if (hc2 == NULL)
|
||||
hc2 = __vmalloc(hsize_bytes * 2, GFP_NOFS, PAGE_KERNEL);
|
||||
|
||||
if (!hc2)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -1145,7 +1160,10 @@ fail:
|
|||
gfs2_dinode_out(dip, dibh->b_data);
|
||||
brelse(dibh);
|
||||
out_kfree:
|
||||
kfree(hc2);
|
||||
if (is_vmalloc_addr(hc2))
|
||||
vfree(hc2);
|
||||
else
|
||||
kfree(hc2);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1846,6 +1864,8 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
|
|||
memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));
|
||||
|
||||
ht = kzalloc(size, GFP_NOFS);
|
||||
if (ht == NULL)
|
||||
ht = vzalloc(size);
|
||||
if (!ht)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -1933,7 +1953,10 @@ out_rlist:
|
|||
gfs2_rlist_free(&rlist);
|
||||
gfs2_quota_unhold(dip);
|
||||
out:
|
||||
kfree(ht);
|
||||
if (is_vmalloc_addr(ht))
|
||||
vfree(ht);
|
||||
else
|
||||
kfree(ht);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -402,16 +402,20 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
|
|||
/* Update file times before taking page lock */
|
||||
file_update_time(vma->vm_file);
|
||||
|
||||
ret = get_write_access(inode);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = gfs2_rs_alloc(ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out_write_access;
|
||||
|
||||
gfs2_size_hint(vma->vm_file, pos, PAGE_CACHE_SIZE);
|
||||
|
||||
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
|
||||
ret = gfs2_glock_nq(&gh);
|
||||
if (ret)
|
||||
goto out;
|
||||
goto out_uninit;
|
||||
|
||||
set_bit(GLF_DIRTY, &ip->i_gl->gl_flags);
|
||||
set_bit(GIF_SW_PAGED, &ip->i_flags);
|
||||
|
@ -480,12 +484,15 @@ out_quota_unlock:
|
|||
gfs2_quota_unlock(ip);
|
||||
out_unlock:
|
||||
gfs2_glock_dq(&gh);
|
||||
out:
|
||||
out_uninit:
|
||||
gfs2_holder_uninit(&gh);
|
||||
if (ret == 0) {
|
||||
set_page_dirty(page);
|
||||
wait_for_stable_page(page);
|
||||
}
|
||||
out_write_access:
|
||||
put_write_access(inode);
|
||||
out:
|
||||
sb_end_pagefault(inode->i_sb);
|
||||
return block_page_mkwrite_return(ret);
|
||||
}
|
||||
|
@ -594,10 +601,10 @@ static int gfs2_release(struct inode *inode, struct file *file)
|
|||
kfree(file->private_data);
|
||||
file->private_data = NULL;
|
||||
|
||||
if ((file->f_mode & FMODE_WRITE) &&
|
||||
(atomic_read(&inode->i_writecount) == 1))
|
||||
gfs2_rs_delete(ip);
|
||||
if (!(file->f_mode & FMODE_WRITE))
|
||||
return 0;
|
||||
|
||||
gfs2_rs_delete(ip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -189,6 +189,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
|
|||
return inode;
|
||||
|
||||
fail_refresh:
|
||||
ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
|
||||
ip->i_iopen_gh.gh_gl->gl_object = NULL;
|
||||
gfs2_glock_dq_uninit(&ip->i_iopen_gh);
|
||||
fail_iopen:
|
||||
|
|
|
@ -419,7 +419,9 @@ static void gfs2_before_commit(struct gfs2_sbd *sdp, unsigned int limit,
|
|||
if (total > limit)
|
||||
num = limit;
|
||||
gfs2_log_unlock(sdp);
|
||||
page = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_METADATA, num + 1, num);
|
||||
page = gfs2_get_log_desc(sdp,
|
||||
is_databuf ? GFS2_LOG_DESC_JDATA :
|
||||
GFS2_LOG_DESC_METADATA, num + 1, num);
|
||||
ld = page_address(page);
|
||||
gfs2_log_lock(sdp);
|
||||
ptr = (__be64 *)(ld + 1);
|
||||
|
|
|
@ -638,8 +638,10 @@ void gfs2_rs_deltree(struct gfs2_blkreserv *rs)
|
|||
*/
|
||||
void gfs2_rs_delete(struct gfs2_inode *ip)
|
||||
{
|
||||
struct inode *inode = &ip->i_inode;
|
||||
|
||||
down_write(&ip->i_rw_mutex);
|
||||
if (ip->i_res) {
|
||||
if (ip->i_res && atomic_read(&inode->i_writecount) <= 1) {
|
||||
gfs2_rs_deltree(ip->i_res);
|
||||
BUG_ON(ip->i_res->rs_free);
|
||||
kmem_cache_free(gfs2_rsrv_cachep, ip->i_res);
|
||||
|
|
|
@ -1444,6 +1444,7 @@ static void gfs2_evict_inode(struct inode *inode)
|
|||
/* Must not read inode block until block type has been verified */
|
||||
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, &gh);
|
||||
if (unlikely(error)) {
|
||||
ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
|
||||
gfs2_glock_dq_uninit(&ip->i_iopen_gh);
|
||||
goto out;
|
||||
}
|
||||
|
@ -1514,8 +1515,10 @@ out_unlock:
|
|||
if (gfs2_rs_active(ip->i_res))
|
||||
gfs2_rs_deltree(ip->i_res);
|
||||
|
||||
if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags))
|
||||
if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) {
|
||||
ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
|
||||
gfs2_glock_dq(&ip->i_iopen_gh);
|
||||
}
|
||||
gfs2_holder_uninit(&ip->i_iopen_gh);
|
||||
gfs2_glock_dq_uninit(&gh);
|
||||
if (error && error != GLR_TRYFAILED && error != -EROFS)
|
||||
|
@ -1534,6 +1537,7 @@ out:
|
|||
ip->i_gl = NULL;
|
||||
if (ip->i_iopen_gh.gh_gl) {
|
||||
ip->i_iopen_gh.gh_gl->gl_object = NULL;
|
||||
ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
|
||||
gfs2_glock_dq_uninit(&ip->i_iopen_gh);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue