Commit be1332c0 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gfs2-4.7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2

Pull GFS2 updates from Bob Peterson:
 "We've got nine patches this time:

   - Abhi Das has two patches that fix a GFS2 splice issue (and an
     adjustment).

   - Ben Marzinski has a patch which allows the proper unmount of a GFS2
     file system after hitting a withdraw error.

   - I have a patch to fix a problem where GFS2 would dereference an
     error value, plus three cosmetic / refactoring patches.

   - Daniel DeFreez has a patch to fix two glock reference count
     problems, where GFS2 was not properly "uninitializing" its glock
     holder on error paths.

   - Denys Vlasenko has a patch to change a function to not be inlined,
     thus reducing the memory footprint of the GFS2 module"

* tag 'gfs2-4.7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
  GFS2: Refactor gfs2_remove_from_journal
  GFS2: Remove allocation parms from gfs2_rbm_find
  gfs2: use inode_lock/unlock instead of accessing i_mutex directly
  GFS2: Add calls to gfs2_holder_uninit in two error handlers
  GFS2: Don't dereference inode in gfs2_inode_lookup until it's valid
  GFS2: fs/gfs2/glock.c: Deinline do_error, save 1856 bytes
  gfs2: Use gfs2 wrapper to sync inode before calling generic_file_splice_read()
  GFS2: Get rid of dead code in inode_go_demote_ok
  GFS2: ignore unlock failures after withdraw
parents e7f44b65 68cd4ce2
...@@ -977,7 +977,7 @@ static void gfs2_discard(struct gfs2_sbd *sdp, struct buffer_head *bh) ...@@ -977,7 +977,7 @@ static void gfs2_discard(struct gfs2_sbd *sdp, struct buffer_head *bh)
if (!list_empty(&bd->bd_list) && !buffer_pinned(bh)) if (!list_empty(&bd->bd_list) && !buffer_pinned(bh))
list_del_init(&bd->bd_list); list_del_init(&bd->bd_list);
else else
gfs2_remove_from_journal(bh, current->journal_info, 0); gfs2_remove_from_journal(bh, REMOVE_JDATA);
} }
bh->b_bdev = NULL; bh->b_bdev = NULL;
clear_buffer_mapped(bh); clear_buffer_mapped(bh);
...@@ -1063,7 +1063,7 @@ static ssize_t gfs2_direct_IO(struct kiocb *iocb, struct iov_iter *iter) ...@@ -1063,7 +1063,7 @@ static ssize_t gfs2_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, 0, &gh); gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, 0, &gh);
rv = gfs2_glock_nq(&gh); rv = gfs2_glock_nq(&gh);
if (rv) if (rv)
return rv; goto out_uninit;
rv = gfs2_ok_for_dio(ip, offset); rv = gfs2_ok_for_dio(ip, offset);
if (rv != 1) if (rv != 1)
goto out; /* dio not valid, fall back to buffered i/o */ goto out; /* dio not valid, fall back to buffered i/o */
...@@ -1102,6 +1102,7 @@ static ssize_t gfs2_direct_IO(struct kiocb *iocb, struct iov_iter *iter) ...@@ -1102,6 +1102,7 @@ static ssize_t gfs2_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
gfs2_get_block_direct, NULL, NULL, 0); gfs2_get_block_direct, NULL, NULL, 0);
out: out:
gfs2_glock_dq(&gh); gfs2_glock_dq(&gh);
out_uninit:
gfs2_holder_uninit(&gh); gfs2_holder_uninit(&gh);
return rv; return rv;
} }
......
...@@ -160,7 +160,7 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr) ...@@ -160,7 +160,7 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh); gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
error = gfs2_glock_nq(&gh); error = gfs2_glock_nq(&gh);
if (error) if (error)
return error; goto out_uninit;
fsflags = fsflags_cvt(gfs2_to_fsflags, ip->i_diskflags); fsflags = fsflags_cvt(gfs2_to_fsflags, ip->i_diskflags);
if (!S_ISDIR(inode->i_mode) && ip->i_diskflags & GFS2_DIF_JDATA) if (!S_ISDIR(inode->i_mode) && ip->i_diskflags & GFS2_DIF_JDATA)
...@@ -169,6 +169,7 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr) ...@@ -169,6 +169,7 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
error = -EFAULT; error = -EFAULT;
gfs2_glock_dq(&gh); gfs2_glock_dq(&gh);
out_uninit:
gfs2_holder_uninit(&gh); gfs2_holder_uninit(&gh);
return error; return error;
} }
...@@ -953,6 +954,30 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t le ...@@ -953,6 +954,30 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t le
return ret; return ret;
} }
static ssize_t gfs2_file_splice_read(struct file *in, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len,
unsigned int flags)
{
struct inode *inode = in->f_mapping->host;
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_holder gh;
int ret;
inode_lock(inode);
ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
if (ret) {
inode_unlock(inode);
return ret;
}
gfs2_glock_dq_uninit(&gh);
inode_unlock(inode);
return generic_file_splice_read(in, ppos, pipe, len, flags);
}
static ssize_t gfs2_file_splice_write(struct pipe_inode_info *pipe, static ssize_t gfs2_file_splice_write(struct pipe_inode_info *pipe,
struct file *out, loff_t *ppos, struct file *out, loff_t *ppos,
size_t len, unsigned int flags) size_t len, unsigned int flags)
...@@ -1115,7 +1140,7 @@ const struct file_operations gfs2_file_fops = { ...@@ -1115,7 +1140,7 @@ const struct file_operations gfs2_file_fops = {
.fsync = gfs2_fsync, .fsync = gfs2_fsync,
.lock = gfs2_lock, .lock = gfs2_lock,
.flock = gfs2_flock, .flock = gfs2_flock,
.splice_read = generic_file_splice_read, .splice_read = gfs2_file_splice_read,
.splice_write = gfs2_file_splice_write, .splice_write = gfs2_file_splice_write,
.setlease = simple_nosetlease, .setlease = simple_nosetlease,
.fallocate = gfs2_fallocate, .fallocate = gfs2_fallocate,
...@@ -1143,7 +1168,7 @@ const struct file_operations gfs2_file_fops_nolock = { ...@@ -1143,7 +1168,7 @@ const struct file_operations gfs2_file_fops_nolock = {
.open = gfs2_open, .open = gfs2_open,
.release = gfs2_release, .release = gfs2_release,
.fsync = gfs2_fsync, .fsync = gfs2_fsync,
.splice_read = generic_file_splice_read, .splice_read = gfs2_file_splice_read,
.splice_write = gfs2_file_splice_write, .splice_write = gfs2_file_splice_write,
.setlease = generic_setlease, .setlease = generic_setlease,
.fallocate = gfs2_fallocate, .fallocate = gfs2_fallocate,
......
...@@ -218,7 +218,7 @@ static void gfs2_holder_wake(struct gfs2_holder *gh) ...@@ -218,7 +218,7 @@ static void gfs2_holder_wake(struct gfs2_holder *gh)
* *
*/ */
static inline void do_error(struct gfs2_glock *gl, const int ret) static void do_error(struct gfs2_glock *gl, const int ret)
{ {
struct gfs2_holder *gh, *tmp; struct gfs2_holder *gh, *tmp;
...@@ -475,7 +475,14 @@ __acquires(&gl->gl_lockref.lock) ...@@ -475,7 +475,14 @@ __acquires(&gl->gl_lockref.lock)
if (sdp->sd_lockstruct.ls_ops->lm_lock) { if (sdp->sd_lockstruct.ls_ops->lm_lock) {
/* lock_dlm */ /* lock_dlm */
ret = sdp->sd_lockstruct.ls_ops->lm_lock(gl, target, lck_flags); ret = sdp->sd_lockstruct.ls_ops->lm_lock(gl, target, lck_flags);
if (ret) { if (ret == -EINVAL && gl->gl_target == LM_ST_UNLOCKED &&
target == LM_ST_UNLOCKED &&
test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags)) {
finish_xmote(gl, target);
if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
gfs2_glock_put(gl);
}
else if (ret) {
pr_err("lm_lock ret %d\n", ret); pr_err("lm_lock ret %d\n", ret);
GLOCK_BUG_ON(gl, 1); GLOCK_BUG_ON(gl, 1);
} }
......
...@@ -286,17 +286,10 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags) ...@@ -286,17 +286,10 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
static int inode_go_demote_ok(const struct gfs2_glock *gl) static int inode_go_demote_ok(const struct gfs2_glock *gl)
{ {
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
struct gfs2_holder *gh;
if (sdp->sd_jindex == gl->gl_object || sdp->sd_rindex == gl->gl_object) if (sdp->sd_jindex == gl->gl_object || sdp->sd_rindex == gl->gl_object)
return 0; return 0;
if (!list_empty(&gl->gl_holders)) {
gh = list_entry(gl->gl_holders.next, struct gfs2_holder, gh_list);
if (gh->gh_list.next != &gl->gl_holders)
return 0;
}
return 1; return 1;
} }
......
...@@ -93,12 +93,12 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, ...@@ -93,12 +93,12 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
int error; int error;
inode = iget_locked(sb, (unsigned long)no_addr); inode = iget_locked(sb, (unsigned long)no_addr);
ip = GFS2_I(inode);
ip->i_no_addr = no_addr;
if (!inode) if (!inode)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
ip = GFS2_I(inode);
ip->i_no_addr = no_addr;
if (inode->i_state & I_NEW) { if (inode->i_state & I_NEW) {
struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_sbd *sdp = GFS2_SB(inode);
ip->i_no_formal_ino = no_formal_ino; ip->i_no_formal_ino = no_formal_ino;
......
...@@ -325,18 +325,19 @@ int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh) ...@@ -325,18 +325,19 @@ int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh)
return 0; return 0;
} }
void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int meta) void gfs2_remove_from_journal(struct buffer_head *bh, int meta)
{ {
struct address_space *mapping = bh->b_page->mapping; struct address_space *mapping = bh->b_page->mapping;
struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping); struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping);
struct gfs2_bufdata *bd = bh->b_private; struct gfs2_bufdata *bd = bh->b_private;
struct gfs2_trans *tr = current->journal_info;
int was_pinned = 0; int was_pinned = 0;
if (test_clear_buffer_pinned(bh)) { if (test_clear_buffer_pinned(bh)) {
trace_gfs2_pin(bd, 0); trace_gfs2_pin(bd, 0);
atomic_dec(&sdp->sd_log_pinned); atomic_dec(&sdp->sd_log_pinned);
list_del_init(&bd->bd_list); list_del_init(&bd->bd_list);
if (meta) if (meta == REMOVE_META)
tr->tr_num_buf_rm++; tr->tr_num_buf_rm++;
else else
tr->tr_num_databuf_rm++; tr->tr_num_databuf_rm++;
...@@ -376,7 +377,7 @@ void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen) ...@@ -376,7 +377,7 @@ void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen)
if (bh) { if (bh) {
lock_buffer(bh); lock_buffer(bh);
gfs2_log_lock(sdp); gfs2_log_lock(sdp);
gfs2_remove_from_journal(bh, current->journal_info, 1); gfs2_remove_from_journal(bh, REMOVE_META);
gfs2_log_unlock(sdp); gfs2_log_unlock(sdp);
unlock_buffer(bh); unlock_buffer(bh);
brelse(bh); brelse(bh);
......
...@@ -57,8 +57,12 @@ extern int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags, ...@@ -57,8 +57,12 @@ extern int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
extern int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh); extern int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh);
extern struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, extern struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno,
int create); int create);
extern void gfs2_remove_from_journal(struct buffer_head *bh, enum {
struct gfs2_trans *tr, int meta); REMOVE_JDATA = 0,
REMOVE_META = 1,
};
extern void gfs2_remove_from_journal(struct buffer_head *bh, int meta);
extern void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen); extern void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen);
extern int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num, extern int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
struct buffer_head **bhp); struct buffer_head **bhp);
......
...@@ -73,8 +73,7 @@ static const char valid_change[16] = { ...@@ -73,8 +73,7 @@ static const char valid_change[16] = {
}; };
static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext, static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext,
const struct gfs2_inode *ip, bool nowrap, const struct gfs2_inode *ip, bool nowrap);
const struct gfs2_alloc_parms *ap);
/** /**
...@@ -1511,7 +1510,7 @@ static void rg_mblk_search(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip, ...@@ -1511,7 +1510,7 @@ static void rg_mblk_search(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip,
if (WARN_ON(gfs2_rbm_from_block(&rbm, goal))) if (WARN_ON(gfs2_rbm_from_block(&rbm, goal)))
return; return;
ret = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, &extlen, ip, true, ap); ret = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, &extlen, ip, true);
if (ret == 0) { if (ret == 0) {
rs->rs_rbm = rbm; rs->rs_rbm = rbm;
rs->rs_free = extlen; rs->rs_free = extlen;
...@@ -1638,7 +1637,6 @@ static int gfs2_reservation_check_and_update(struct gfs2_rbm *rbm, ...@@ -1638,7 +1637,6 @@ static int gfs2_reservation_check_and_update(struct gfs2_rbm *rbm,
* @ip: If set, check for reservations * @ip: If set, check for reservations
* @nowrap: Stop looking at the end of the rgrp, rather than wrapping * @nowrap: Stop looking at the end of the rgrp, rather than wrapping
* around until we've reached the starting point. * around until we've reached the starting point.
* @ap: the allocation parameters
* *
* Side effects: * Side effects:
* - If looking for free blocks, we set GBF_FULL on each bitmap which * - If looking for free blocks, we set GBF_FULL on each bitmap which
...@@ -1650,8 +1648,7 @@ static int gfs2_reservation_check_and_update(struct gfs2_rbm *rbm, ...@@ -1650,8 +1648,7 @@ static int gfs2_reservation_check_and_update(struct gfs2_rbm *rbm,
*/ */
static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext, static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext,
const struct gfs2_inode *ip, bool nowrap, const struct gfs2_inode *ip, bool nowrap)
const struct gfs2_alloc_parms *ap)
{ {
struct buffer_head *bh; struct buffer_head *bh;
int initial_bii; int initial_bii;
...@@ -1772,7 +1769,7 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip ...@@ -1772,7 +1769,7 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip
while (1) { while (1) {
down_write(&sdp->sd_log_flush_lock); down_write(&sdp->sd_log_flush_lock);
error = gfs2_rbm_find(&rbm, GFS2_BLKST_UNLINKED, NULL, NULL, error = gfs2_rbm_find(&rbm, GFS2_BLKST_UNLINKED, NULL, NULL,
true, NULL); true);
up_write(&sdp->sd_log_flush_lock); up_write(&sdp->sd_log_flush_lock);
if (error == -ENOSPC) if (error == -ENOSPC)
break; break;
...@@ -2329,12 +2326,11 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, ...@@ -2329,12 +2326,11 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
int error; int error;
gfs2_set_alloc_start(&rbm, ip, dinode); gfs2_set_alloc_start(&rbm, ip, dinode);
error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, NULL, ip, false, NULL); error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, NULL, ip, false);
if (error == -ENOSPC) { if (error == -ENOSPC) {
gfs2_set_alloc_start(&rbm, ip, dinode); gfs2_set_alloc_start(&rbm, ip, dinode);
error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, NULL, NULL, false, error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, NULL, NULL, false);
NULL);
} }
/* Since all blocks are reserved in advance, this shouldn't happen */ /* Since all blocks are reserved in advance, this shouldn't happen */
......
...@@ -68,6 +68,7 @@ int gfs2_lm_withdraw(struct gfs2_sbd *sdp, const char *fmt, ...) ...@@ -68,6 +68,7 @@ int gfs2_lm_withdraw(struct gfs2_sbd *sdp, const char *fmt, ...)
fs_err(sdp, "telling LM to unmount\n"); fs_err(sdp, "telling LM to unmount\n");
lm->lm_unmount(sdp); lm->lm_unmount(sdp);
} }
set_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags);
fs_err(sdp, "withdrawn\n"); fs_err(sdp, "withdrawn\n");
dump_stack(); dump_stack();
} }
......
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