mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-19 20:12:32 +00:00
gfs2 fixes
- Fix revoke processing at unmount and on read-only remount. - Refuse reading in inodes with an impossible indirect block height. - Various minor cleanups. -----BEGIN PGP SIGNATURE----- iQJIBAABCAAyFiEEJZs3krPW0xkhLMTc1b+f6wMTZToFAmRH00EUHGFncnVlbmJh QHJlZGhhdC5jb20ACgkQ1b+f6wMTZTpfSw//a0IG/6tVfPwlCPd1qPKN/JbxHQVa 3JtRJXr5+RJ3vIKmJb+AFfEiPHRKgCk28d9hMbW8j3ieKSy/dPJe8ARIZmu8phpK dOSiue87v4Pz6Tz2qpb6KgzUENohsqjTy0mEAEWxxZb7mWxUqj7t057hiEp/9NX6 jXcfoNInMxnf2HX3d11LoHXYOX37xvEjyhbZ4OmPn+xzmYQcfhuO96CTrIOe7lKe U8dbFzDwtoUxYljb16do0OLva/YxaNdH33yCzrixVi9ki1aCIH6A2paznlUCzgF1 wzOhzV3kbz5e4flov34X1Jnd5RVkBmzMMM5bkcJzNg6JOSGL0bLg0PGYiXASAfje KmsNVvq0yMWLLQIr2gMcEVI1IVDxkNKJruizbFfUs/SWHI55eDUZtI5jjA0v0cCw 5HRWialgCNdC9Wd/4HW+DfpztwxR5+j52TCtqgyRGQcGvkNtwGMeGgh9/sreuHhr 7Lod7LpBVmEzlXD97VIcJUcU2vhXtGA25pKXFHCilXh/MdA2UpmBWkVUkNVS/awr ZTzoi/WkUIWLLVHxHruLOoJBWit8Mhnuxh1rlY0WD3wDEbnwCZKX8ziTYIsVvkWc d/xjjafrolC6g1m/RoW3rXO/MLXaE0rRy4nb3MLhwsqaAQyZE6puwo40Kj/xNQqf 68kLauI2QFNpFm8= =l1E9 -----END PGP SIGNATURE----- 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()
This commit is contained in:
commit
e0fcc9c68d
@ -2035,14 +2035,6 @@ static int do_shrink(struct inode *inode, u64 newsize)
|
||||
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
|
||||
* @inode: The inode
|
||||
|
@ -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,
|
||||
unsigned *extlen, bool *new);
|
||||
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_file_dealloc(struct gfs2_inode *ip);
|
||||
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)
|
||||
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
|
||||
struct gfs2_trans tr;
|
||||
unsigned int revokes;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
revokes = atomic_read(&gl->gl_ail_count);
|
||||
|
||||
@ -124,15 +124,18 @@ static int gfs2_ail_empty_gl(struct gfs2_glock *gl)
|
||||
memset(&tr, 0, sizeof(tr));
|
||||
set_bit(TR_ONSTACK, &tr.tr_flags);
|
||||
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;
|
||||
}
|
||||
__gfs2_ail_flush(gl, 0, revokes);
|
||||
gfs2_trans_end(sdp);
|
||||
|
||||
flush:
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_AIL_EMPTY_GL);
|
||||
return 0;
|
||||
if (!ret)
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_AIL_EMPTY_GL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
|
||||
@ -326,7 +329,9 @@ static int inode_go_sync(struct gfs2_glock *gl)
|
||||
ret = gfs2_inode_metasync(gl);
|
||||
if (!error)
|
||||
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
|
||||
* so we have to clear it again here.
|
||||
@ -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)
|
||||
{
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
const struct gfs2_dinode *str = buf;
|
||||
struct timespec64 atime;
|
||||
u16 height, depth;
|
||||
@ -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() */
|
||||
gfs2_set_inode_flags(inode);
|
||||
height = be16_to_cpu(str->di_height);
|
||||
if (unlikely(height > GFS2_MAX_META_HEIGHT))
|
||||
if (unlikely(height > sdp->sd_max_height))
|
||||
goto corrupt;
|
||||
ip->i_height = (u8)height;
|
||||
|
||||
@ -534,12 +540,13 @@ static void inode_go_dump(struct seq_file *seq, struct gfs2_glock *gl,
|
||||
const char *fs_id_buf)
|
||||
{
|
||||
struct gfs2_inode *ip = gl->gl_object;
|
||||
struct inode *inode = &ip->i_inode;
|
||||
struct inode *inode;
|
||||
unsigned long nrpages;
|
||||
|
||||
if (ip == NULL)
|
||||
return;
|
||||
|
||||
inode = &ip->i_inode;
|
||||
xa_lock_irq(&inode->i_data.i_pages);
|
||||
nrpages = inode->i_data.nrpages;
|
||||
xa_unlock_irq(&inode->i_data.i_pages);
|
||||
|
@ -941,7 +941,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
|
||||
struct gfs2_sbd *sdp = GFS2_SB(dir);
|
||||
struct inode *inode = d_inode(old_dentry);
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_holder ghs[2];
|
||||
struct gfs2_holder d_gh, gh;
|
||||
struct buffer_head *dibh;
|
||||
struct gfs2_diradd da = { .bh = NULL, .save_loc = 1, };
|
||||
int error;
|
||||
@ -953,14 +953,14 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
|
||||
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1);
|
||||
gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, &d_gh);
|
||||
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)
|
||||
goto out_parent;
|
||||
|
||||
error = gfs2_glock_nq(ghs + 1); /* child */
|
||||
error = gfs2_glock_nq(&gh);
|
||||
if (error)
|
||||
goto out_child;
|
||||
|
||||
@ -992,9 +992,6 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
|
||||
error = -EPERM;
|
||||
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
|
||||
goto out_gunlock;
|
||||
error = -EINVAL;
|
||||
if (!ip->i_inode.i_nlink)
|
||||
goto out_gunlock;
|
||||
error = -EMLINK;
|
||||
if (ip->i_inode.i_nlink == (u32)-1)
|
||||
goto out_gunlock;
|
||||
@ -1049,13 +1046,13 @@ out_gunlock_q:
|
||||
gfs2_quota_unlock(dip);
|
||||
out_gunlock:
|
||||
gfs2_dir_no_add(&da);
|
||||
gfs2_glock_dq(ghs + 1);
|
||||
gfs2_glock_dq(&gh);
|
||||
out_child:
|
||||
gfs2_glock_dq(ghs);
|
||||
gfs2_glock_dq(&d_gh);
|
||||
out_parent:
|
||||
gfs2_qa_put(dip);
|
||||
gfs2_holder_uninit(ghs);
|
||||
gfs2_holder_uninit(ghs + 1);
|
||||
gfs2_holder_uninit(&d_gh);
|
||||
gfs2_holder_uninit(&gh);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -1146,7 +1143,7 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
|
||||
struct gfs2_sbd *sdp = GFS2_SB(dir);
|
||||
struct inode *inode = d_inode(dentry);
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_holder ghs[3];
|
||||
struct gfs2_holder d_gh, r_gh, gh;
|
||||
struct gfs2_rgrpd *rgd;
|
||||
int error;
|
||||
|
||||
@ -1156,21 +1153,21 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
|
||||
|
||||
error = -EROFS;
|
||||
|
||||
gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
|
||||
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1);
|
||||
gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, &d_gh);
|
||||
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
|
||||
|
||||
rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr, 1);
|
||||
if (!rgd)
|
||||
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)
|
||||
goto out_parent;
|
||||
|
||||
error = gfs2_glock_nq(ghs + 1); /* child */
|
||||
error = gfs2_glock_nq(&gh);
|
||||
if (error)
|
||||
goto out_child;
|
||||
|
||||
@ -1184,7 +1181,7 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
|
||||
goto out_rgrp;
|
||||
}
|
||||
|
||||
error = gfs2_glock_nq(ghs + 2); /* rgrp */
|
||||
error = gfs2_glock_nq(&r_gh); /* rgrp */
|
||||
if (error)
|
||||
goto out_rgrp;
|
||||
|
||||
@ -1200,16 +1197,16 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
|
||||
gfs2_trans_end(sdp);
|
||||
|
||||
out_gunlock:
|
||||
gfs2_glock_dq(ghs + 2);
|
||||
gfs2_glock_dq(&r_gh);
|
||||
out_rgrp:
|
||||
gfs2_glock_dq(ghs + 1);
|
||||
gfs2_glock_dq(&gh);
|
||||
out_child:
|
||||
gfs2_glock_dq(ghs);
|
||||
gfs2_glock_dq(&d_gh);
|
||||
out_parent:
|
||||
gfs2_holder_uninit(ghs + 2);
|
||||
gfs2_holder_uninit(&r_gh);
|
||||
out_inodes:
|
||||
gfs2_holder_uninit(ghs + 1);
|
||||
gfs2_holder_uninit(ghs);
|
||||
gfs2_holder_uninit(&gh);
|
||||
gfs2_holder_uninit(&d_gh);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -734,13 +734,11 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
|
||||
struct inode *master = d_inode(sdp->sd_master_dir);
|
||||
struct gfs2_holder ji_gh;
|
||||
struct gfs2_inode *ip;
|
||||
int jindex = 1;
|
||||
int error = 0;
|
||||
|
||||
if (undo) {
|
||||
jindex = 0;
|
||||
gfs2_holder_mark_uninitialized(&ji_gh);
|
||||
if (undo)
|
||||
goto fail_statfs;
|
||||
}
|
||||
|
||||
sdp->sd_jindex = gfs2_lookup_simple(master, "jindex");
|
||||
if (IS_ERR(sdp->sd_jindex)) {
|
||||
@ -852,7 +850,6 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
|
||||
sdp->sd_log_idle = 1;
|
||||
set_bit(SDF_JOURNAL_CHECKED, &sdp->sd_flags);
|
||||
gfs2_glock_dq_uninit(&ji_gh);
|
||||
jindex = 0;
|
||||
INIT_WORK(&sdp->sd_freeze_work, gfs2_freeze_func);
|
||||
return 0;
|
||||
|
||||
@ -869,7 +866,7 @@ fail_journal_gh:
|
||||
gfs2_glock_dq_uninit(&sdp->sd_journal_gh);
|
||||
fail_jindex:
|
||||
gfs2_jindex_free(sdp);
|
||||
if (jindex)
|
||||
if (gfs2_holder_initialized(&ji_gh))
|
||||
gfs2_glock_dq_uninit(&ji_gh);
|
||||
fail:
|
||||
iput(sdp->sd_jindex);
|
||||
|
@ -552,6 +552,15 @@ void gfs2_make_fs_ro(struct gfs2_sbd *sdp)
|
||||
gfs2_quota_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_LFC_MAKE_FS_RO);
|
||||
wait_event_timeout(sdp->sd_log_waitq,
|
||||
|
Loading…
x
Reference in New Issue
Block a user