Commit d1dd4612 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull gfs2 fixes from Andreas Gruenbacher:
 "Various gfs2 fixes"

* tag 'gfs2-v5.10-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
  gfs2: Wake up when sd_glock_disposal becomes zero
  gfs2: Don't call cancel_delayed_work_sync from within delete work function
  gfs2: check for live vs. read-only file system in gfs2_fitrim
  gfs2: don't initialize statfs_change inodes in spectator mode
  gfs2: Split up gfs2_meta_sync into inode and rgrp versions
  gfs2: init_journal's undo directive should also undo the statfs inodes
  gfs2: Add missing truncate_inode_pages_final for sd_aspace
  gfs2: Free rd_bits later in gfs2_clear_rgrpd to fix use-after-free
parents e2557a2c da7d554f
...@@ -1078,7 +1078,8 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, ...@@ -1078,7 +1078,8 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
out_free: out_free:
kfree(gl->gl_lksb.sb_lvbptr); kfree(gl->gl_lksb.sb_lvbptr);
kmem_cache_free(cachep, gl); kmem_cache_free(cachep, gl);
atomic_dec(&sdp->sd_glock_disposal); if (atomic_dec_and_test(&sdp->sd_glock_disposal))
wake_up(&sdp->sd_glock_wait);
out: out:
return ret; return ret;
......
...@@ -164,6 +164,31 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync) ...@@ -164,6 +164,31 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
GFS2_LFC_AIL_FLUSH); GFS2_LFC_AIL_FLUSH);
} }
/**
* gfs2_rgrp_metasync - sync out the metadata of a resource group
* @gl: the glock protecting the resource group
*
*/
static int gfs2_rgrp_metasync(struct gfs2_glock *gl)
{
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
struct address_space *metamapping = &sdp->sd_aspace;
struct gfs2_rgrpd *rgd = gfs2_glock2rgrp(gl);
const unsigned bsize = sdp->sd_sb.sb_bsize;
loff_t start = (rgd->rd_addr * bsize) & PAGE_MASK;
loff_t end = PAGE_ALIGN((rgd->rd_addr + rgd->rd_length) * bsize) - 1;
int error;
filemap_fdatawrite_range(metamapping, start, end);
error = filemap_fdatawait_range(metamapping, start, end);
WARN_ON_ONCE(error && !gfs2_withdrawn(sdp));
mapping_set_error(metamapping, error);
if (error)
gfs2_io_error(sdp);
return error;
}
/** /**
* rgrp_go_sync - sync out the metadata for this glock * rgrp_go_sync - sync out the metadata for this glock
* @gl: the glock * @gl: the glock
...@@ -176,11 +201,7 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync) ...@@ -176,11 +201,7 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
static int rgrp_go_sync(struct gfs2_glock *gl) static int rgrp_go_sync(struct gfs2_glock *gl)
{ {
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
struct address_space *mapping = &sdp->sd_aspace;
struct gfs2_rgrpd *rgd = gfs2_glock2rgrp(gl); struct gfs2_rgrpd *rgd = gfs2_glock2rgrp(gl);
const unsigned bsize = sdp->sd_sb.sb_bsize;
loff_t start = (rgd->rd_addr * bsize) & PAGE_MASK;
loff_t end = PAGE_ALIGN((rgd->rd_addr + rgd->rd_length) * bsize) - 1;
int error; int error;
if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
...@@ -189,10 +210,7 @@ static int rgrp_go_sync(struct gfs2_glock *gl) ...@@ -189,10 +210,7 @@ static int rgrp_go_sync(struct gfs2_glock *gl)
gfs2_log_flush(sdp, gl, GFS2_LOG_HEAD_FLUSH_NORMAL | gfs2_log_flush(sdp, gl, GFS2_LOG_HEAD_FLUSH_NORMAL |
GFS2_LFC_RGRP_GO_SYNC); GFS2_LFC_RGRP_GO_SYNC);
filemap_fdatawrite_range(mapping, start, end); error = gfs2_rgrp_metasync(gl);
error = filemap_fdatawait_range(mapping, start, end);
WARN_ON_ONCE(error && !gfs2_withdrawn(sdp));
mapping_set_error(mapping, error);
if (!error) if (!error)
error = gfs2_ail_empty_gl(gl); error = gfs2_ail_empty_gl(gl);
gfs2_free_clones(rgd); gfs2_free_clones(rgd);
...@@ -266,7 +284,24 @@ static void gfs2_clear_glop_pending(struct gfs2_inode *ip) ...@@ -266,7 +284,24 @@ static void gfs2_clear_glop_pending(struct gfs2_inode *ip)
} }
/** /**
* inode_go_sync - Sync the dirty data and/or metadata for an inode glock * gfs2_inode_metasync - sync out the metadata of an inode
* @gl: the glock protecting the inode
*
*/
int gfs2_inode_metasync(struct gfs2_glock *gl)
{
struct address_space *metamapping = gfs2_glock2aspace(gl);
int error;
filemap_fdatawrite(metamapping);
error = filemap_fdatawait(metamapping);
if (error)
gfs2_io_error(gl->gl_name.ln_sbd);
return error;
}
/**
* inode_go_sync - Sync the dirty metadata of an inode
* @gl: the glock protecting the inode * @gl: the glock protecting the inode
* *
*/ */
...@@ -297,8 +332,7 @@ static int inode_go_sync(struct gfs2_glock *gl) ...@@ -297,8 +332,7 @@ static int inode_go_sync(struct gfs2_glock *gl)
error = filemap_fdatawait(mapping); error = filemap_fdatawait(mapping);
mapping_set_error(mapping, error); mapping_set_error(mapping, error);
} }
ret = filemap_fdatawait(metamapping); ret = gfs2_inode_metasync(gl);
mapping_set_error(metamapping, ret);
if (!error) if (!error)
error = ret; error = ret;
gfs2_ail_empty_gl(gl); gfs2_ail_empty_gl(gl);
......
...@@ -22,6 +22,7 @@ extern const struct gfs2_glock_operations gfs2_quota_glops; ...@@ -22,6 +22,7 @@ extern const struct gfs2_glock_operations gfs2_quota_glops;
extern const struct gfs2_glock_operations gfs2_journal_glops; extern const struct gfs2_glock_operations gfs2_journal_glops;
extern const struct gfs2_glock_operations *gfs2_glops_list[]; extern const struct gfs2_glock_operations *gfs2_glops_list[];
extern int gfs2_inode_metasync(struct gfs2_glock *gl);
extern void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync); extern void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync);
#endif /* __GLOPS_DOT_H__ */ #endif /* __GLOPS_DOT_H__ */
...@@ -180,6 +180,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, ...@@ -180,6 +180,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh); error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
if (unlikely(error)) if (unlikely(error))
goto fail; goto fail;
if (blktype != GFS2_BLKST_UNLINKED)
gfs2_cancel_delete_work(ip->i_iopen_gh.gh_gl); gfs2_cancel_delete_work(ip->i_iopen_gh.gh_gl);
glock_set_object(ip->i_iopen_gh.gh_gl, ip); glock_set_object(ip->i_iopen_gh.gh_gl, ip);
gfs2_glock_put(io_gl); gfs2_glock_put(io_gl);
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "incore.h" #include "incore.h"
#include "inode.h" #include "inode.h"
#include "glock.h" #include "glock.h"
#include "glops.h"
#include "log.h" #include "log.h"
#include "lops.h" #include "lops.h"
#include "meta_io.h" #include "meta_io.h"
...@@ -817,41 +818,19 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, u32 start, ...@@ -817,41 +818,19 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, u32 start,
return error; return error;
} }
/**
* gfs2_meta_sync - Sync all buffers associated with a glock
* @gl: The glock
*
*/
void gfs2_meta_sync(struct gfs2_glock *gl)
{
struct address_space *mapping = gfs2_glock2aspace(gl);
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
int error;
if (mapping == NULL)
mapping = &sdp->sd_aspace;
filemap_fdatawrite(mapping);
error = filemap_fdatawait(mapping);
if (error)
gfs2_io_error(gl->gl_name.ln_sbd);
}
static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass) static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
{ {
struct gfs2_inode *ip = GFS2_I(jd->jd_inode); struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
if (error) { if (error) {
gfs2_meta_sync(ip->i_gl); gfs2_inode_metasync(ip->i_gl);
return; return;
} }
if (pass != 1) if (pass != 1)
return; return;
gfs2_meta_sync(ip->i_gl); gfs2_inode_metasync(ip->i_gl);
fs_info(sdp, "jid=%u: Replayed %u of %u blocks\n", fs_info(sdp, "jid=%u: Replayed %u of %u blocks\n",
jd->jd_jid, jd->jd_replayed_blocks, jd->jd_found_blocks); jd->jd_jid, jd->jd_replayed_blocks, jd->jd_found_blocks);
...@@ -1060,14 +1039,14 @@ static void databuf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass) ...@@ -1060,14 +1039,14 @@ static void databuf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
if (error) { if (error) {
gfs2_meta_sync(ip->i_gl); gfs2_inode_metasync(ip->i_gl);
return; return;
} }
if (pass != 1) if (pass != 1)
return; return;
/* data sync? */ /* data sync? */
gfs2_meta_sync(ip->i_gl); gfs2_inode_metasync(ip->i_gl);
fs_info(sdp, "jid=%u: Replayed %u of %u data blocks\n", fs_info(sdp, "jid=%u: Replayed %u of %u data blocks\n",
jd->jd_jid, jd->jd_replayed_blocks, jd->jd_found_blocks); jd->jd_jid, jd->jd_replayed_blocks, jd->jd_found_blocks);
......
...@@ -27,8 +27,6 @@ extern void gfs2_log_submit_bio(struct bio **biop, int opf); ...@@ -27,8 +27,6 @@ extern void gfs2_log_submit_bio(struct bio **biop, int opf);
extern void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh); extern void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh);
extern int gfs2_find_jhead(struct gfs2_jdesc *jd, extern int gfs2_find_jhead(struct gfs2_jdesc *jd,
struct gfs2_log_header_host *head, bool keep_cache); struct gfs2_log_header_host *head, bool keep_cache);
extern void gfs2_meta_sync(struct gfs2_glock *gl);
static inline unsigned int buf_limit(struct gfs2_sbd *sdp) static inline unsigned int buf_limit(struct gfs2_sbd *sdp)
{ {
unsigned int limit; unsigned int limit;
......
...@@ -633,8 +633,10 @@ static int init_statfs(struct gfs2_sbd *sdp) ...@@ -633,8 +633,10 @@ static int init_statfs(struct gfs2_sbd *sdp)
if (IS_ERR(sdp->sd_statfs_inode)) { if (IS_ERR(sdp->sd_statfs_inode)) {
error = PTR_ERR(sdp->sd_statfs_inode); error = PTR_ERR(sdp->sd_statfs_inode);
fs_err(sdp, "can't read in statfs inode: %d\n", error); fs_err(sdp, "can't read in statfs inode: %d\n", error);
goto fail; goto out;
} }
if (sdp->sd_args.ar_spectator)
goto out;
pn = gfs2_lookup_simple(master, "per_node"); pn = gfs2_lookup_simple(master, "per_node");
if (IS_ERR(pn)) { if (IS_ERR(pn)) {
...@@ -682,15 +684,17 @@ static int init_statfs(struct gfs2_sbd *sdp) ...@@ -682,15 +684,17 @@ static int init_statfs(struct gfs2_sbd *sdp)
iput(pn); iput(pn);
put_statfs: put_statfs:
iput(sdp->sd_statfs_inode); iput(sdp->sd_statfs_inode);
fail: out:
return error; return error;
} }
/* Uninitialize and free up memory used by the list of statfs inodes */ /* Uninitialize and free up memory used by the list of statfs inodes */
static void uninit_statfs(struct gfs2_sbd *sdp) static void uninit_statfs(struct gfs2_sbd *sdp)
{ {
if (!sdp->sd_args.ar_spectator) {
gfs2_glock_dq_uninit(&sdp->sd_sc_gh); gfs2_glock_dq_uninit(&sdp->sd_sc_gh);
free_local_statfs_inodes(sdp); free_local_statfs_inodes(sdp);
}
iput(sdp->sd_statfs_inode); iput(sdp->sd_statfs_inode);
} }
...@@ -704,7 +708,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) ...@@ -704,7 +708,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
if (undo) { if (undo) {
jindex = 0; jindex = 0;
goto fail_jinode_gh; goto fail_statfs;
} }
sdp->sd_jindex = gfs2_lookup_simple(master, "jindex"); sdp->sd_jindex = gfs2_lookup_simple(master, "jindex");
......
...@@ -349,7 +349,7 @@ static int update_statfs_inode(struct gfs2_jdesc *jd, ...@@ -349,7 +349,7 @@ static int update_statfs_inode(struct gfs2_jdesc *jd,
mark_buffer_dirty(bh); mark_buffer_dirty(bh);
brelse(bh); brelse(bh);
gfs2_meta_sync(ip->i_gl); gfs2_inode_metasync(ip->i_gl);
out: out:
return error; return error;
......
...@@ -719,9 +719,9 @@ void gfs2_clear_rgrpd(struct gfs2_sbd *sdp) ...@@ -719,9 +719,9 @@ void gfs2_clear_rgrpd(struct gfs2_sbd *sdp)
} }
gfs2_free_clones(rgd); gfs2_free_clones(rgd);
return_all_reservations(rgd);
kfree(rgd->rd_bits); kfree(rgd->rd_bits);
rgd->rd_bits = NULL; rgd->rd_bits = NULL;
return_all_reservations(rgd);
kmem_cache_free(gfs2_rgrpd_cachep, rgd); kmem_cache_free(gfs2_rgrpd_cachep, rgd);
} }
} }
...@@ -1370,6 +1370,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp) ...@@ -1370,6 +1370,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))
return -EROFS;
if (!blk_queue_discard(q)) if (!blk_queue_discard(q))
return -EOPNOTSUPP; return -EOPNOTSUPP;
......
...@@ -738,6 +738,7 @@ static void gfs2_put_super(struct super_block *sb) ...@@ -738,6 +738,7 @@ static void gfs2_put_super(struct super_block *sb)
gfs2_jindex_free(sdp); gfs2_jindex_free(sdp);
/* Take apart glock structures and buffer lists */ /* Take apart glock structures and buffer lists */
gfs2_gl_hash_clear(sdp); gfs2_gl_hash_clear(sdp);
truncate_inode_pages_final(&sdp->sd_aspace);
gfs2_delete_debugfs_file(sdp); gfs2_delete_debugfs_file(sdp);
/* Unmount the locking protocol */ /* Unmount the locking protocol */
gfs2_lm_unmount(sdp); gfs2_lm_unmount(sdp);
......
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