Various gfs2 fixes
-----BEGIN PGP SIGNATURE----- iQJIBAABCAAyFiEEJZs3krPW0xkhLMTc1b+f6wMTZToFAl+j0ZsUHGFncnVlbmJh QHJlZGhhdC5jb20ACgkQ1b+f6wMTZTpJeRAAoTNP1n9Pa4B1Et76S7GJiaLExemK THT+hzXf5hGdd5x9nV12bhDb0OTTcZCcCXn2e7aPTBmACJpOcxjgHp0egchac1GV ea/1xkN9HJKGaWaFngUdNhlBJdea9a3QgJcXScSDRxLo7+6qIN98PsxGMu+rqicJ N2jKMYUgKpz51FCSSewS2zN0+ZKD8QnJNpVt9yH9lEeIb6cuMywYZk4+8XR2zLtv 7ttTIPm3qD6dUhaGn3Q/11pcHHVF5sJ3DfifMj9322p7osu+mYNYjHj9slXXZPpv LvvDBTH7k4+LjBT+0LJ8tWPAIPbG9PjC/jpOE3MKPQ/bMWGZup5Fvz9mPQZLK9Q8 6HwyvvcPxspYrQE3wHXu4vAKU+gJZYTIUgtDmykmAtcPIf0am4Qc2qhwHyGjS2CT 7LkLE3sT8wgsbRB4PrCq3gW64EZp59++X2RF5003gqiPJ9UL0feg+LMTkHHKR+if McPgOBEk3vkbYHUpKbOcP5Z3RuistiGwgYauWQXbB3tpPH40X9HZnD2cXS3iSU79 r/muaJBvjK4+H8OkRENNSyTWKZrKpbJ2zPQaVl1U+XaAFEA3kIgViEsgPAeh3eXY K4fbwJqx/daLlIZSouol9JCpSj8PHOukTaTj99LeDHesc8JmZ43ozCMzkT1mQM19 +S3I6LojyFRDjTg= =8z2V -----END PGP SIGNATURE----- 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
This commit is contained in:
Коммит
d1dd461207
|
@ -1078,7 +1078,8 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
|
|||
out_free:
|
||||
kfree(gl->gl_lksb.sb_lvbptr);
|
||||
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:
|
||||
return ret;
|
||||
|
|
|
@ -164,6 +164,31 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
|
|||
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
|
||||
* @gl: the glock
|
||||
|
@ -176,11 +201,7 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
|
|||
static int rgrp_go_sync(struct gfs2_glock *gl)
|
||||
{
|
||||
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
|
||||
struct address_space *mapping = &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;
|
||||
|
||||
if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
|
||||
|
@ -189,10 +210,7 @@ static int rgrp_go_sync(struct gfs2_glock *gl)
|
|||
|
||||
gfs2_log_flush(sdp, gl, GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_RGRP_GO_SYNC);
|
||||
filemap_fdatawrite_range(mapping, start, end);
|
||||
error = filemap_fdatawait_range(mapping, start, end);
|
||||
WARN_ON_ONCE(error && !gfs2_withdrawn(sdp));
|
||||
mapping_set_error(mapping, error);
|
||||
error = gfs2_rgrp_metasync(gl);
|
||||
if (!error)
|
||||
error = gfs2_ail_empty_gl(gl);
|
||||
gfs2_free_clones(rgd);
|
||||
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
@ -297,8 +332,7 @@ static int inode_go_sync(struct gfs2_glock *gl)
|
|||
error = filemap_fdatawait(mapping);
|
||||
mapping_set_error(mapping, error);
|
||||
}
|
||||
ret = filemap_fdatawait(metamapping);
|
||||
mapping_set_error(metamapping, ret);
|
||||
ret = gfs2_inode_metasync(gl);
|
||||
if (!error)
|
||||
error = ret;
|
||||
gfs2_ail_empty_gl(gl);
|
||||
|
|
|
@ -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_glops_list[];
|
||||
|
||||
extern int gfs2_inode_metasync(struct gfs2_glock *gl);
|
||||
extern void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync);
|
||||
|
||||
#endif /* __GLOPS_DOT_H__ */
|
||||
|
|
|
@ -180,7 +180,8 @@ 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);
|
||||
if (unlikely(error))
|
||||
goto fail;
|
||||
gfs2_cancel_delete_work(ip->i_iopen_gh.gh_gl);
|
||||
if (blktype != GFS2_BLKST_UNLINKED)
|
||||
gfs2_cancel_delete_work(ip->i_iopen_gh.gh_gl);
|
||||
glock_set_object(ip->i_iopen_gh.gh_gl, ip);
|
||||
gfs2_glock_put(io_gl);
|
||||
io_gl = NULL;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "incore.h"
|
||||
#include "inode.h"
|
||||
#include "glock.h"
|
||||
#include "glops.h"
|
||||
#include "log.h"
|
||||
#include "lops.h"
|
||||
#include "meta_io.h"
|
||||
|
@ -817,41 +818,19 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, u32 start,
|
|||
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)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
|
||||
struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
|
||||
|
||||
if (error) {
|
||||
gfs2_meta_sync(ip->i_gl);
|
||||
gfs2_inode_metasync(ip->i_gl);
|
||||
return;
|
||||
}
|
||||
if (pass != 1)
|
||||
return;
|
||||
|
||||
gfs2_meta_sync(ip->i_gl);
|
||||
gfs2_inode_metasync(ip->i_gl);
|
||||
|
||||
fs_info(sdp, "jid=%u: Replayed %u of %u blocks\n",
|
||||
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)
|
|||
struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
|
||||
|
||||
if (error) {
|
||||
gfs2_meta_sync(ip->i_gl);
|
||||
gfs2_inode_metasync(ip->i_gl);
|
||||
return;
|
||||
}
|
||||
if (pass != 1)
|
||||
return;
|
||||
|
||||
/* 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",
|
||||
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);
|
|||
extern void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh);
|
||||
extern int gfs2_find_jhead(struct gfs2_jdesc *jd,
|
||||
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)
|
||||
{
|
||||
unsigned int limit;
|
||||
|
|
|
@ -633,8 +633,10 @@ static int init_statfs(struct gfs2_sbd *sdp)
|
|||
if (IS_ERR(sdp->sd_statfs_inode)) {
|
||||
error = PTR_ERR(sdp->sd_statfs_inode);
|
||||
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");
|
||||
if (IS_ERR(pn)) {
|
||||
|
@ -682,15 +684,17 @@ free_local:
|
|||
iput(pn);
|
||||
put_statfs:
|
||||
iput(sdp->sd_statfs_inode);
|
||||
fail:
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Uninitialize and free up memory used by the list of statfs inodes */
|
||||
static void uninit_statfs(struct gfs2_sbd *sdp)
|
||||
{
|
||||
gfs2_glock_dq_uninit(&sdp->sd_sc_gh);
|
||||
free_local_statfs_inodes(sdp);
|
||||
if (!sdp->sd_args.ar_spectator) {
|
||||
gfs2_glock_dq_uninit(&sdp->sd_sc_gh);
|
||||
free_local_statfs_inodes(sdp);
|
||||
}
|
||||
iput(sdp->sd_statfs_inode);
|
||||
}
|
||||
|
||||
|
@ -704,7 +708,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
|
|||
|
||||
if (undo) {
|
||||
jindex = 0;
|
||||
goto fail_jinode_gh;
|
||||
goto fail_statfs;
|
||||
}
|
||||
|
||||
sdp->sd_jindex = gfs2_lookup_simple(master, "jindex");
|
||||
|
|
|
@ -349,7 +349,7 @@ static int update_statfs_inode(struct gfs2_jdesc *jd,
|
|||
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
gfs2_meta_sync(ip->i_gl);
|
||||
gfs2_inode_metasync(ip->i_gl);
|
||||
|
||||
out:
|
||||
return error;
|
||||
|
|
|
@ -719,9 +719,9 @@ void gfs2_clear_rgrpd(struct gfs2_sbd *sdp)
|
|||
}
|
||||
|
||||
gfs2_free_clones(rgd);
|
||||
return_all_reservations(rgd);
|
||||
kfree(rgd->rd_bits);
|
||||
rgd->rd_bits = NULL;
|
||||
return_all_reservations(rgd);
|
||||
kmem_cache_free(gfs2_rgrpd_cachep, rgd);
|
||||
}
|
||||
}
|
||||
|
@ -1370,6 +1370,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
|
|||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))
|
||||
return -EROFS;
|
||||
|
||||
if (!blk_queue_discard(q))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
|
|
|
@ -738,6 +738,7 @@ restart:
|
|||
gfs2_jindex_free(sdp);
|
||||
/* Take apart glock structures and buffer lists */
|
||||
gfs2_gl_hash_clear(sdp);
|
||||
truncate_inode_pages_final(&sdp->sd_aspace);
|
||||
gfs2_delete_debugfs_file(sdp);
|
||||
/* Unmount the locking protocol */
|
||||
gfs2_lm_unmount(sdp);
|
||||
|
|
Загрузка…
Ссылка в новой задаче