Commit e0fcc9c6 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull gfs2 updates from Andreas Gruenbacher:

 - Fix revoke processing at unmount and on read-only remount

 - Refuse reading in inodes with an impossible indirect block height

 - Various minor cleanups

* tag 'gfs2-v6.3-rc3-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
  gfs2: gfs2_ail_empty_gl no log flush on error
  gfs2: Issue message when revokes cannot be written
  gfs2: Perform second log flush in gfs2_make_fs_ro
  gfs2: return errors from gfs2_ail_empty_gl
  gfs2: Move variable assignment behind a null pointer check in inode_go_dump
  gfs2: Use gfs2_holder_initialized for jindex
  gfs2: Eliminate gfs2_trim_blocks
  gfs2: Fix inode height consistency check
  gfs2: Remove ghs[] from gfs2_unlink
  gfs2: Remove ghs[] from gfs2_link
  gfs2: Remove duplicate i_nlink check from gfs2_link()
parents 85d7ab24 644f6bf7
...@@ -2035,14 +2035,6 @@ static int do_shrink(struct inode *inode, u64 newsize) ...@@ -2035,14 +2035,6 @@ static int do_shrink(struct inode *inode, u64 newsize)
return error; return error;
} }
void gfs2_trim_blocks(struct inode *inode)
{
int ret;
ret = do_shrink(inode, inode->i_size);
WARN_ON(ret != 0);
}
/** /**
* do_grow - Touch and update inode size * do_grow - Touch and update inode size
* @inode: The inode * @inode: The inode
......
...@@ -58,7 +58,6 @@ extern int gfs2_get_extent(struct inode *inode, u64 lblock, u64 *dblock, ...@@ -58,7 +58,6 @@ extern int gfs2_get_extent(struct inode *inode, u64 lblock, u64 *dblock,
extern int gfs2_alloc_extent(struct inode *inode, u64 lblock, u64 *dblock, extern int gfs2_alloc_extent(struct inode *inode, u64 lblock, u64 *dblock,
unsigned *extlen, bool *new); unsigned *extlen, bool *new);
extern int gfs2_setattr_size(struct inode *inode, u64 size); extern int gfs2_setattr_size(struct inode *inode, u64 size);
extern void gfs2_trim_blocks(struct inode *inode);
extern int gfs2_truncatei_resume(struct gfs2_inode *ip); extern int gfs2_truncatei_resume(struct gfs2_inode *ip);
extern int gfs2_file_dealloc(struct gfs2_inode *ip); extern int gfs2_file_dealloc(struct gfs2_inode *ip);
extern int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, extern int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
......
...@@ -90,7 +90,7 @@ static int gfs2_ail_empty_gl(struct gfs2_glock *gl) ...@@ -90,7 +90,7 @@ static int gfs2_ail_empty_gl(struct gfs2_glock *gl)
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
struct gfs2_trans tr; struct gfs2_trans tr;
unsigned int revokes; unsigned int revokes;
int ret; int ret = 0;
revokes = atomic_read(&gl->gl_ail_count); revokes = atomic_read(&gl->gl_ail_count);
...@@ -124,15 +124,18 @@ static int gfs2_ail_empty_gl(struct gfs2_glock *gl) ...@@ -124,15 +124,18 @@ static int gfs2_ail_empty_gl(struct gfs2_glock *gl)
memset(&tr, 0, sizeof(tr)); memset(&tr, 0, sizeof(tr));
set_bit(TR_ONSTACK, &tr.tr_flags); set_bit(TR_ONSTACK, &tr.tr_flags);
ret = __gfs2_trans_begin(&tr, sdp, 0, revokes, _RET_IP_); ret = __gfs2_trans_begin(&tr, sdp, 0, revokes, _RET_IP_);
if (ret) if (ret) {
fs_err(sdp, "Transaction error %d: Unable to write revokes.", ret);
goto flush; goto flush;
}
__gfs2_ail_flush(gl, 0, revokes); __gfs2_ail_flush(gl, 0, revokes);
gfs2_trans_end(sdp); gfs2_trans_end(sdp);
flush: flush:
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL | if (!ret)
GFS2_LFC_AIL_EMPTY_GL); gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
return 0; GFS2_LFC_AIL_EMPTY_GL);
return ret;
} }
void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync) void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
...@@ -326,7 +329,9 @@ static int inode_go_sync(struct gfs2_glock *gl) ...@@ -326,7 +329,9 @@ static int inode_go_sync(struct gfs2_glock *gl)
ret = gfs2_inode_metasync(gl); ret = gfs2_inode_metasync(gl);
if (!error) if (!error)
error = ret; error = ret;
gfs2_ail_empty_gl(gl); ret = gfs2_ail_empty_gl(gl);
if (!error)
error = ret;
/* /*
* Writeback of the data mapping may cause the dirty flag to be set * Writeback of the data mapping may cause the dirty flag to be set
* so we have to clear it again here. * so we have to clear it again here.
...@@ -396,6 +401,7 @@ static int inode_go_demote_ok(const struct gfs2_glock *gl) ...@@ -396,6 +401,7 @@ static int inode_go_demote_ok(const struct gfs2_glock *gl)
static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
{ {
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
const struct gfs2_dinode *str = buf; const struct gfs2_dinode *str = buf;
struct timespec64 atime; struct timespec64 atime;
u16 height, depth; u16 height, depth;
...@@ -442,7 +448,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) ...@@ -442,7 +448,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
/* i_diskflags and i_eattr must be set before gfs2_set_inode_flags() */ /* i_diskflags and i_eattr must be set before gfs2_set_inode_flags() */
gfs2_set_inode_flags(inode); gfs2_set_inode_flags(inode);
height = be16_to_cpu(str->di_height); height = be16_to_cpu(str->di_height);
if (unlikely(height > GFS2_MAX_META_HEIGHT)) if (unlikely(height > sdp->sd_max_height))
goto corrupt; goto corrupt;
ip->i_height = (u8)height; ip->i_height = (u8)height;
...@@ -534,12 +540,13 @@ static void inode_go_dump(struct seq_file *seq, struct gfs2_glock *gl, ...@@ -534,12 +540,13 @@ static void inode_go_dump(struct seq_file *seq, struct gfs2_glock *gl,
const char *fs_id_buf) const char *fs_id_buf)
{ {
struct gfs2_inode *ip = gl->gl_object; struct gfs2_inode *ip = gl->gl_object;
struct inode *inode = &ip->i_inode; struct inode *inode;
unsigned long nrpages; unsigned long nrpages;
if (ip == NULL) if (ip == NULL)
return; return;
inode = &ip->i_inode;
xa_lock_irq(&inode->i_data.i_pages); xa_lock_irq(&inode->i_data.i_pages);
nrpages = inode->i_data.nrpages; nrpages = inode->i_data.nrpages;
xa_unlock_irq(&inode->i_data.i_pages); xa_unlock_irq(&inode->i_data.i_pages);
......
...@@ -941,7 +941,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, ...@@ -941,7 +941,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
struct gfs2_sbd *sdp = GFS2_SB(dir); struct gfs2_sbd *sdp = GFS2_SB(dir);
struct inode *inode = d_inode(old_dentry); struct inode *inode = d_inode(old_dentry);
struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_holder ghs[2]; struct gfs2_holder d_gh, gh;
struct buffer_head *dibh; struct buffer_head *dibh;
struct gfs2_diradd da = { .bh = NULL, .save_loc = 1, }; struct gfs2_diradd da = { .bh = NULL, .save_loc = 1, };
int error; int error;
...@@ -953,14 +953,14 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, ...@@ -953,14 +953,14 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
if (error) if (error)
return error; return error;
gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, &d_gh);
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
error = gfs2_glock_nq(ghs); /* parent */ error = gfs2_glock_nq(&d_gh);
if (error) if (error)
goto out_parent; goto out_parent;
error = gfs2_glock_nq(ghs + 1); /* child */ error = gfs2_glock_nq(&gh);
if (error) if (error)
goto out_child; goto out_child;
...@@ -992,9 +992,6 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, ...@@ -992,9 +992,6 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
error = -EPERM; error = -EPERM;
if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
goto out_gunlock; goto out_gunlock;
error = -EINVAL;
if (!ip->i_inode.i_nlink)
goto out_gunlock;
error = -EMLINK; error = -EMLINK;
if (ip->i_inode.i_nlink == (u32)-1) if (ip->i_inode.i_nlink == (u32)-1)
goto out_gunlock; goto out_gunlock;
...@@ -1049,13 +1046,13 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, ...@@ -1049,13 +1046,13 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
gfs2_quota_unlock(dip); gfs2_quota_unlock(dip);
out_gunlock: out_gunlock:
gfs2_dir_no_add(&da); gfs2_dir_no_add(&da);
gfs2_glock_dq(ghs + 1); gfs2_glock_dq(&gh);
out_child: out_child:
gfs2_glock_dq(ghs); gfs2_glock_dq(&d_gh);
out_parent: out_parent:
gfs2_qa_put(dip); gfs2_qa_put(dip);
gfs2_holder_uninit(ghs); gfs2_holder_uninit(&d_gh);
gfs2_holder_uninit(ghs + 1); gfs2_holder_uninit(&gh);
return error; return error;
} }
...@@ -1146,7 +1143,7 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1146,7 +1143,7 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
struct gfs2_sbd *sdp = GFS2_SB(dir); struct gfs2_sbd *sdp = GFS2_SB(dir);
struct inode *inode = d_inode(dentry); struct inode *inode = d_inode(dentry);
struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_holder ghs[3]; struct gfs2_holder d_gh, r_gh, gh;
struct gfs2_rgrpd *rgd; struct gfs2_rgrpd *rgd;
int error; int error;
...@@ -1156,21 +1153,21 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1156,21 +1153,21 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
error = -EROFS; error = -EROFS;
gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, &d_gh);
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr, 1); rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr, 1);
if (!rgd) if (!rgd)
goto out_inodes; goto out_inodes;
gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, LM_FLAG_NODE_SCOPE, ghs + 2); gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, LM_FLAG_NODE_SCOPE, &r_gh);
error = gfs2_glock_nq(ghs); /* parent */ error = gfs2_glock_nq(&d_gh);
if (error) if (error)
goto out_parent; goto out_parent;
error = gfs2_glock_nq(ghs + 1); /* child */ error = gfs2_glock_nq(&gh);
if (error) if (error)
goto out_child; goto out_child;
...@@ -1184,7 +1181,7 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1184,7 +1181,7 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
goto out_rgrp; goto out_rgrp;
} }
error = gfs2_glock_nq(ghs + 2); /* rgrp */ error = gfs2_glock_nq(&r_gh); /* rgrp */
if (error) if (error)
goto out_rgrp; goto out_rgrp;
...@@ -1200,16 +1197,16 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1200,16 +1197,16 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
gfs2_trans_end(sdp); gfs2_trans_end(sdp);
out_gunlock: out_gunlock:
gfs2_glock_dq(ghs + 2); gfs2_glock_dq(&r_gh);
out_rgrp: out_rgrp:
gfs2_glock_dq(ghs + 1); gfs2_glock_dq(&gh);
out_child: out_child:
gfs2_glock_dq(ghs); gfs2_glock_dq(&d_gh);
out_parent: out_parent:
gfs2_holder_uninit(ghs + 2); gfs2_holder_uninit(&r_gh);
out_inodes: out_inodes:
gfs2_holder_uninit(ghs + 1); gfs2_holder_uninit(&gh);
gfs2_holder_uninit(ghs); gfs2_holder_uninit(&d_gh);
return error; return error;
} }
......
...@@ -734,13 +734,11 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) ...@@ -734,13 +734,11 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
struct inode *master = d_inode(sdp->sd_master_dir); struct inode *master = d_inode(sdp->sd_master_dir);
struct gfs2_holder ji_gh; struct gfs2_holder ji_gh;
struct gfs2_inode *ip; struct gfs2_inode *ip;
int jindex = 1;
int error = 0; int error = 0;
if (undo) { gfs2_holder_mark_uninitialized(&ji_gh);
jindex = 0; if (undo)
goto fail_statfs; goto fail_statfs;
}
sdp->sd_jindex = gfs2_lookup_simple(master, "jindex"); sdp->sd_jindex = gfs2_lookup_simple(master, "jindex");
if (IS_ERR(sdp->sd_jindex)) { if (IS_ERR(sdp->sd_jindex)) {
...@@ -852,7 +850,6 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) ...@@ -852,7 +850,6 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
sdp->sd_log_idle = 1; sdp->sd_log_idle = 1;
set_bit(SDF_JOURNAL_CHECKED, &sdp->sd_flags); set_bit(SDF_JOURNAL_CHECKED, &sdp->sd_flags);
gfs2_glock_dq_uninit(&ji_gh); gfs2_glock_dq_uninit(&ji_gh);
jindex = 0;
INIT_WORK(&sdp->sd_freeze_work, gfs2_freeze_func); INIT_WORK(&sdp->sd_freeze_work, gfs2_freeze_func);
return 0; return 0;
...@@ -869,7 +866,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) ...@@ -869,7 +866,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
gfs2_glock_dq_uninit(&sdp->sd_journal_gh); gfs2_glock_dq_uninit(&sdp->sd_journal_gh);
fail_jindex: fail_jindex:
gfs2_jindex_free(sdp); gfs2_jindex_free(sdp);
if (jindex) if (gfs2_holder_initialized(&ji_gh))
gfs2_glock_dq_uninit(&ji_gh); gfs2_glock_dq_uninit(&ji_gh);
fail: fail:
iput(sdp->sd_jindex); iput(sdp->sd_jindex);
......
...@@ -552,6 +552,15 @@ void gfs2_make_fs_ro(struct gfs2_sbd *sdp) ...@@ -552,6 +552,15 @@ void gfs2_make_fs_ro(struct gfs2_sbd *sdp)
gfs2_quota_sync(sdp->sd_vfs, 0); gfs2_quota_sync(sdp->sd_vfs, 0);
gfs2_statfs_sync(sdp->sd_vfs, 0); gfs2_statfs_sync(sdp->sd_vfs, 0);
/* We do two log flushes here. The first one commits dirty inodes
* and rgrps to the journal, but queues up revokes to the ail list.
* The second flush writes out and removes the revokes.
*
* The first must be done before the FLUSH_SHUTDOWN code
* clears the LIVE flag, otherwise it will not be able to start
* a transaction to write its revokes, and the error will cause
* a withdraw of the file system. */
gfs2_log_flush(sdp, NULL, GFS2_LFC_MAKE_FS_RO);
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_SHUTDOWN | gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_SHUTDOWN |
GFS2_LFC_MAKE_FS_RO); GFS2_LFC_MAKE_FS_RO);
wait_event_timeout(sdp->sd_log_waitq, wait_event_timeout(sdp->sd_log_waitq,
......
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