Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes
Pull gfs2 fixes from Steven Whitehouse: "Here are a number of GFS2 bug fixes. There are three from Andy Price which fix various issues spotted by automated code analysis. There are two from Lukas Czerner fixing my mistaken assumptions as to how FITRIM should work. Finally Ben Marzinski has fixed a bug relating to mmap and atime and also a bug relating to a locking issue in the transaction code." * git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes: GFS2: Test bufdata with buffer locked and gfs2_log_lock held GFS2: Don't call file_accessed() with a shared glock GFS2: Fix FITRIM argument handling GFS2: Require user to provide argument for FITRIM GFS2: Clean up some unused assignments GFS2: Fix possible null pointer deref in gfs2_rs_alloc GFS2: Fix an unchecked error from gfs2_rs_alloc
This commit is contained in:
Коммит
0e4a43ed08
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче