Commit 0e4a43ed authored by Linus Torvalds's avatar Linus Torvalds

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
parents 826389d1 96e5d1d3
...@@ -516,15 +516,13 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -516,15 +516,13 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
struct gfs2_holder i_gh; struct gfs2_holder i_gh;
int error; int error;
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY,
error = gfs2_glock_nq(&i_gh); &i_gh);
if (error == 0) {
file_accessed(file);
gfs2_glock_dq(&i_gh);
}
gfs2_holder_uninit(&i_gh);
if (error) if (error)
return error; return error;
/* grab lock to update inode */
gfs2_glock_dq_uninit(&i_gh);
file_accessed(file);
} }
vma->vm_ops = &gfs2_vm_ops; vma->vm_ops = &gfs2_vm_ops;
...@@ -677,10 +675,8 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov, ...@@ -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); size_t writesize = iov_length(iov, nr_segs);
struct dentry *dentry = file->f_dentry; struct dentry *dentry = file->f_dentry;
struct gfs2_inode *ip = GFS2_I(dentry->d_inode); struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
struct gfs2_sbd *sdp;
int ret; int ret;
sdp = GFS2_SB(file->f_mapping->host);
ret = gfs2_rs_alloc(ip); ret = gfs2_rs_alloc(ip);
if (ret) if (ret)
return ret; return ret;
......
...@@ -393,12 +393,10 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) ...@@ -393,12 +393,10 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
struct gfs2_meta_header *mh; struct gfs2_meta_header *mh;
struct gfs2_trans *tr; struct gfs2_trans *tr;
lock_buffer(bd->bd_bh);
gfs2_log_lock(sdp);
tr = current->journal_info; tr = current->journal_info;
tr->tr_touched = 1; tr->tr_touched = 1;
if (!list_empty(&bd->bd_list)) if (!list_empty(&bd->bd_list))
goto out; return;
set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
mh = (struct gfs2_meta_header *)bd->bd_bh->b_data; 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) ...@@ -414,9 +412,6 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
sdp->sd_log_num_buf++; sdp->sd_log_num_buf++;
list_add(&bd->bd_list, &sdp->sd_log_le_buf); list_add(&bd->bd_list, &sdp->sd_log_le_buf);
tr->tr_num_buf_new++; tr->tr_num_buf_new++;
out:
gfs2_log_unlock(sdp);
unlock_buffer(bd->bd_bh);
} }
static void gfs2_check_magic(struct buffer_head *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) ...@@ -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) static void revoke_lo_before_commit(struct gfs2_sbd *sdp)
{ {
struct gfs2_log_descriptor *ld;
struct gfs2_meta_header *mh; struct gfs2_meta_header *mh;
unsigned int offset; unsigned int offset;
struct list_head *head = &sdp->sd_log_le_revoke; struct list_head *head = &sdp->sd_log_le_revoke;
...@@ -634,7 +628,6 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp) ...@@ -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)); 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); 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); offset = sizeof(struct gfs2_log_descriptor);
list_for_each_entry(bd, head, bd_list) { 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) ...@@ -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 address_space *mapping = bd->bd_bh->b_page->mapping;
struct gfs2_inode *ip = GFS2_I(mapping->host); struct gfs2_inode *ip = GFS2_I(mapping->host);
lock_buffer(bd->bd_bh);
gfs2_log_lock(sdp);
if (tr) if (tr)
tr->tr_touched = 1; tr->tr_touched = 1;
if (!list_empty(&bd->bd_list)) if (!list_empty(&bd->bd_list))
goto out; return;
set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
if (gfs2_is_jdata(ip)) { if (gfs2_is_jdata(ip)) {
...@@ -793,9 +784,6 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) ...@@ -793,9 +784,6 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
} else { } else {
list_add_tail(&bd->bd_list, &sdp->sd_log_le_ordered); 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) ...@@ -497,8 +497,11 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)
struct gfs2_quota_data **qd; struct gfs2_quota_data **qd;
int error; int error;
if (ip->i_res == NULL) if (ip->i_res == NULL) {
gfs2_rs_alloc(ip); error = gfs2_rs_alloc(ip);
if (error)
return error;
}
qd = ip->i_res->rs_qa_qd; qd = ip->i_res->rs_qa_qd;
......
...@@ -553,7 +553,6 @@ void gfs2_free_clones(struct gfs2_rgrpd *rgd) ...@@ -553,7 +553,6 @@ void gfs2_free_clones(struct gfs2_rgrpd *rgd)
*/ */
int gfs2_rs_alloc(struct gfs2_inode *ip) int gfs2_rs_alloc(struct gfs2_inode *ip)
{ {
int error = 0;
struct gfs2_blkreserv *res; struct gfs2_blkreserv *res;
if (ip->i_res) if (ip->i_res)
...@@ -561,7 +560,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip) ...@@ -561,7 +560,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip)
res = kmem_cache_zalloc(gfs2_rsrv_cachep, GFP_NOFS); res = kmem_cache_zalloc(gfs2_rsrv_cachep, GFP_NOFS);
if (!res) if (!res)
error = -ENOMEM; return -ENOMEM;
RB_CLEAR_NODE(&res->rs_node); RB_CLEAR_NODE(&res->rs_node);
...@@ -571,7 +570,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip) ...@@ -571,7 +570,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip)
else else
ip->i_res = res; ip->i_res = res;
up_write(&ip->i_rw_mutex); up_write(&ip->i_rw_mutex);
return error; return 0;
} }
static void dump_rs(struct seq_file *seq, const struct gfs2_blkreserv *rs) 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) ...@@ -1263,7 +1262,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
int ret = 0; int ret = 0;
u64 amt; u64 amt;
u64 trimmed = 0; u64 trimmed = 0;
u64 start, end, minlen;
unsigned int x; unsigned int x;
unsigned bs_shift = sdp->sd_sb.sb_bsize_shift;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
...@@ -1271,19 +1272,25 @@ int gfs2_fitrim(struct file *filp, void __user *argp) ...@@ -1271,19 +1272,25 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
if (!blk_queue_discard(q)) if (!blk_queue_discard(q))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (argp == NULL) { if (copy_from_user(&r, argp, sizeof(r)))
r.start = 0;
r.len = ULLONG_MAX;
r.minlen = 0;
} else if (copy_from_user(&r, argp, sizeof(r)))
return -EFAULT; return -EFAULT;
ret = gfs2_rindex_update(sdp); ret = gfs2_rindex_update(sdp);
if (ret) if (ret)
return ret; return ret;
rgd = gfs2_blk2rgrpd(sdp, r.start, 0); start = r.start >> bs_shift;
rgd_end = gfs2_blk2rgrpd(sdp, r.start + r.len, 0); 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) { while (1) {
...@@ -1295,7 +1302,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp) ...@@ -1295,7 +1302,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
/* Trim each bitmap in the rgrp */ /* Trim each bitmap in the rgrp */
for (x = 0; x < rgd->rd_length; x++) { for (x = 0; x < rgd->rd_length; x++) {
struct gfs2_bitmap *bi = rgd->rd_bits + 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) { if (ret) {
gfs2_glock_dq_uninit(&gh); gfs2_glock_dq_uninit(&gh);
goto out; goto out;
...@@ -1324,7 +1333,7 @@ int gfs2_fitrim(struct file *filp, void __user *argp) ...@@ -1324,7 +1333,7 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
out: out:
r.len = trimmed << 9; r.len = trimmed << 9;
if (argp && copy_to_user(argp, &r, sizeof(r))) if (copy_to_user(argp, &r, sizeof(r)))
return -EFAULT; return -EFAULT;
return ret; return ret;
......
...@@ -810,7 +810,8 @@ static void gfs2_dirty_inode(struct inode *inode, int flags) ...@@ -810,7 +810,8 @@ static void gfs2_dirty_inode(struct inode *inode, int flags)
return; return;
} }
need_unlock = 1; need_unlock = 1;
} } else if (WARN_ON_ONCE(ip->i_gl->gl_state != LM_ST_EXCLUSIVE))
return;
if (current->journal_info == NULL) { if (current->journal_info == NULL) {
ret = gfs2_trans_begin(sdp, RES_DINODE, 0); 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) ...@@ -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_sbd *sdp = gl->gl_sbd;
struct gfs2_bufdata *bd; struct gfs2_bufdata *bd;
lock_buffer(bh);
gfs2_log_lock(sdp);
bd = bh->b_private; bd = bh->b_private;
if (bd) if (bd)
gfs2_assert(sdp, bd->bd_gl == gl); gfs2_assert(sdp, bd->bd_gl == gl);
else { else {
gfs2_log_unlock(sdp);
unlock_buffer(bh);
gfs2_attach_bufdata(gl, bh, meta); gfs2_attach_bufdata(gl, bh, meta);
bd = bh->b_private; bd = bh->b_private;
lock_buffer(bh);
gfs2_log_lock(sdp);
} }
lops_add(sdp, bd); lops_add(sdp, bd);
gfs2_log_unlock(sdp);
unlock_buffer(bh);
} }
void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment