We've only got 9 GFS2 patches for this merge window:
1. Abhi Das contributed a patch to report journal recovery times more accurately during journal replay. 2. Andreas Gruenbacher contributed a patch to fix fallocate chunk size. 3. Andreas added a patch to correctly dirty inodes during rename. 4. Andreas added a patch to improve the comment for function gfs2_block_map. 5. Andreas added a patch to improve kernel trace point iomap end: The physical block address was added. 6. Andreas added a patch to fix a nasty file system corruption bug that surfaced in xfstests 476 in punch-hole/truncate. 7. Andreas fixed a problem Christoph Helwig pointed out, namely, that GFS2 was misusing the IOMAP_ZERO flag. The zeroing of new blocks was moved to the proper fallocate code. 8. I contributed a patch to declare function gfs2_remove_from_ail as static. 9. I added a patch to only set PageChecked for jdata page writes. -----BEGIN PGP SIGNATURE----- iQEcBAABAgAGBQJaw7mxAAoJENeLYdPf93o7kbUH/3MVpJKJe+jdtb5zMGE+byPZ T4x+kjZcGwIjWtqIMnga2X1mMIpJ/MCQzZriT+zno2BRRxPS8MQsKp9rcmEGiwoP mKZnVGm85xvBDg/JaAnCOeH2S90BlXX3roaB4U4031tAmcZOz/tVbBiTCBXbZ7FP F9tnKt/CkRwBBE8CBvstpgYYvbM+kkfiQ8x38FJFx79lOBytIRhPCHpbR3mgko+p HrJNTadGJie65nsplKZcQpDQTPrslwP/ynyGh313ReztThHfCB6teL6sNOgJ5u+T ThCA95QesH3P45Dd+xl/SuCDd0pZLLslNgOl/q7qiFWaoxFFBKldN3Bnc7ItnDw= =iw4e -----END PGP SIGNATURE----- Merge tag 'gfs2-4.17.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2 Pull gfs2 updates from Bob Peterson: "We've only got nine GFS2 patches for this merge window: - report journal recovery times more accurately during journal replay (Abhi Das) - fix fallocate chunk size (Andreas Gruenbacher) - correctly dirty inodes during rename (Andreas Gruenbacher) - improve the comment for function gfs2_block_map (Andreas Gruenbacher) - improve kernel trace point iomap end: The physical block address was added (Andreas Gruenbacher) - fix a nasty file system corruption bug that surfaced in xfstests 476 in punch-hole/truncate (Andreas Gruenbacher) - fix a problem Christoph Helwig pointed out, namely, that GFS2 was misusing the IOMAP_ZERO flag. The zeroing of new blocks was moved to the proper fallocate code (Andreas Gruenbacher) - declare function gfs2_remove_from_ail as static (Bob Peterson) - only set PageChecked for jdata page writes (Bob Peterson)" * tag 'gfs2-4.17.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2: gfs2: time journal recovery steps accurately gfs2: Zero out fallocated blocks in fallocate_chunk gfs2: Check for the end of metadata in punch_hole gfs2: gfs2_iomap_end tracepoint: log block address gfs2: Improve gfs2_block_map comment GFS2: Only set PageChecked for jdata pages GFS2: Make function gfs2_remove_from_ail static gfs2: Dirty source inode during rename gfs2: Fix fallocate chunk size
This commit is contained in:
commit
2bd99df54f
@ -940,13 +940,13 @@ failed:
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_set_page_dirty - Page dirtying function
|
||||
* jdata_set_page_dirty - Page dirtying function
|
||||
* @page: The page to dirty
|
||||
*
|
||||
* Returns: 1 if it dirtyed the page, or 0 otherwise
|
||||
*/
|
||||
|
||||
static int gfs2_set_page_dirty(struct page *page)
|
||||
static int jdata_set_page_dirty(struct page *page)
|
||||
{
|
||||
SetPageChecked(page);
|
||||
return __set_page_dirty_buffers(page);
|
||||
@ -1214,7 +1214,7 @@ static const struct address_space_operations gfs2_ordered_aops = {
|
||||
.readpages = gfs2_readpages,
|
||||
.write_begin = gfs2_write_begin,
|
||||
.write_end = gfs2_write_end,
|
||||
.set_page_dirty = gfs2_set_page_dirty,
|
||||
.set_page_dirty = __set_page_dirty_buffers,
|
||||
.bmap = gfs2_bmap,
|
||||
.invalidatepage = gfs2_invalidatepage,
|
||||
.releasepage = gfs2_releasepage,
|
||||
@ -1231,7 +1231,7 @@ static const struct address_space_operations gfs2_jdata_aops = {
|
||||
.readpages = gfs2_readpages,
|
||||
.write_begin = gfs2_write_begin,
|
||||
.write_end = gfs2_write_end,
|
||||
.set_page_dirty = gfs2_set_page_dirty,
|
||||
.set_page_dirty = jdata_set_page_dirty,
|
||||
.bmap = gfs2_bmap,
|
||||
.invalidatepage = gfs2_invalidatepage,
|
||||
.releasepage = gfs2_releasepage,
|
||||
|
@ -491,14 +491,12 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||
struct super_block *sb = sdp->sd_vfs;
|
||||
struct buffer_head *dibh = mp->mp_bh[0];
|
||||
u64 bn;
|
||||
unsigned n, i, blks, alloced = 0, iblks = 0, branch_start = 0;
|
||||
unsigned dblks = 0;
|
||||
unsigned ptrs_per_blk;
|
||||
const unsigned end_of_metadata = mp->mp_fheight - 1;
|
||||
int ret;
|
||||
enum alloc_state state;
|
||||
__be64 *ptr;
|
||||
__be64 zero_bn = 0;
|
||||
@ -607,15 +605,6 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
|
||||
iomap->flags |= IOMAP_F_NEW;
|
||||
while (n-- > 0)
|
||||
*ptr++ = cpu_to_be64(bn++);
|
||||
if (flags & IOMAP_ZERO) {
|
||||
ret = sb_issue_zeroout(sb, iomap->addr >> inode->i_blkbits,
|
||||
dblks, GFP_NOFS);
|
||||
if (ret) {
|
||||
fs_err(sdp,
|
||||
"Failed to zero data buffers\n");
|
||||
flags &= ~IOMAP_ZERO;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while (iomap->addr == IOMAP_NULL_ADDR);
|
||||
@ -812,15 +801,22 @@ do_alloc:
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_block_map - Map a block from an inode to a disk block
|
||||
* gfs2_block_map - Map one or more blocks of an inode to a disk block
|
||||
* @inode: The inode
|
||||
* @lblock: The logical block number
|
||||
* @bh_map: The bh to be mapped
|
||||
* @create: True if its ok to alloc blocks to satify the request
|
||||
*
|
||||
* Sets buffer_mapped() if successful, sets buffer_boundary() if a
|
||||
* read of metadata will be required before the next block can be
|
||||
* mapped. Sets buffer_new() if new blocks were allocated.
|
||||
* The size of the requested mapping is defined in bh_map->b_size.
|
||||
*
|
||||
* Clears buffer_mapped(bh_map) and leaves bh_map->b_size unchanged
|
||||
* when @lblock is not mapped. Sets buffer_mapped(bh_map) and
|
||||
* bh_map->b_size to indicate the size of the mapping when @lblock and
|
||||
* successive blocks are mapped, up to the requested size.
|
||||
*
|
||||
* Sets buffer_boundary() if a read of metadata will be required
|
||||
* before the next block can be mapped. Sets buffer_new() if new
|
||||
* blocks were allocated.
|
||||
*
|
||||
* Returns: errno
|
||||
*/
|
||||
@ -839,8 +835,6 @@ int gfs2_block_map(struct inode *inode, sector_t lblock,
|
||||
|
||||
if (create)
|
||||
flags |= IOMAP_WRITE;
|
||||
if (buffer_zeronew(bh_map))
|
||||
flags |= IOMAP_ZERO;
|
||||
ret = gfs2_iomap_begin(inode, (loff_t)lblock << inode->i_blkbits,
|
||||
bh_map->b_size, flags, &iomap);
|
||||
if (ret) {
|
||||
@ -1344,6 +1338,7 @@ static inline bool walk_done(struct gfs2_sbd *sdp,
|
||||
static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length)
|
||||
{
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
u64 maxsize = sdp->sd_heightsize[ip->i_height];
|
||||
struct metapath mp = {};
|
||||
struct buffer_head *dibh, *bh;
|
||||
struct gfs2_holder rd_gh;
|
||||
@ -1359,6 +1354,14 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length)
|
||||
u64 prev_bnr = 0;
|
||||
__be64 *start, *end;
|
||||
|
||||
if (offset >= maxsize) {
|
||||
/*
|
||||
* The starting point lies beyond the allocated meta-data;
|
||||
* there are no blocks do deallocate.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The start position of the hole is defined by lblock, start_list, and
|
||||
* start_aligned. The end position of the hole is defined by lend,
|
||||
@ -1372,7 +1375,6 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length)
|
||||
*/
|
||||
|
||||
if (length) {
|
||||
u64 maxsize = sdp->sd_heightsize[ip->i_height];
|
||||
u64 end_offset = offset + length;
|
||||
u64 lend;
|
||||
|
||||
|
@ -1940,7 +1940,6 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
|
||||
{
|
||||
struct buffer_head *bh;
|
||||
struct gfs2_dirent *dent;
|
||||
int error;
|
||||
|
||||
dent = gfs2_dirent_search(&dip->i_inode, filename, gfs2_dirent_find, &bh);
|
||||
if (!dent) {
|
||||
@ -1953,18 +1952,10 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
|
||||
gfs2_trans_add_meta(dip->i_gl, bh);
|
||||
gfs2_inum_out(nip, dent);
|
||||
dent->de_type = cpu_to_be16(new_type);
|
||||
|
||||
if (dip->i_diskflags & GFS2_DIF_EXHASH) {
|
||||
brelse(bh);
|
||||
error = gfs2_meta_inode_buffer(dip, &bh);
|
||||
if (error)
|
||||
return error;
|
||||
gfs2_trans_add_meta(dip->i_gl, bh);
|
||||
}
|
||||
brelse(bh);
|
||||
|
||||
dip->i_inode.i_mtime = dip->i_inode.i_ctime = current_time(&dip->i_inode);
|
||||
gfs2_dinode_out(dip, bh->b_data);
|
||||
brelse(bh);
|
||||
mark_inode_dirty_sync(&dip->i_inode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -729,11 +729,12 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
|
||||
int mode)
|
||||
{
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
loff_t end = offset + len;
|
||||
struct buffer_head *dibh;
|
||||
struct iomap iomap;
|
||||
int error;
|
||||
unsigned int nr_blks;
|
||||
sector_t lblock = offset >> inode->i_blkbits;
|
||||
|
||||
error = gfs2_meta_inode_buffer(ip, &dibh);
|
||||
if (unlikely(error))
|
||||
@ -747,21 +748,19 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (len) {
|
||||
struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 };
|
||||
bh_map.b_size = len;
|
||||
set_buffer_zeronew(&bh_map);
|
||||
|
||||
error = gfs2_block_map(inode, lblock, &bh_map, 1);
|
||||
if (unlikely(error))
|
||||
while (offset < end) {
|
||||
error = gfs2_iomap_begin(inode, offset, end - offset,
|
||||
IOMAP_WRITE, &iomap);
|
||||
if (error)
|
||||
goto out;
|
||||
len -= bh_map.b_size;
|
||||
nr_blks = bh_map.b_size >> inode->i_blkbits;
|
||||
lblock += nr_blks;
|
||||
if (!buffer_new(&bh_map))
|
||||
offset = iomap.offset + iomap.length;
|
||||
if (iomap.type != IOMAP_HOLE)
|
||||
continue;
|
||||
if (unlikely(!buffer_zeronew(&bh_map))) {
|
||||
error = -EIO;
|
||||
error = sb_issue_zeroout(sb, iomap.addr >> inode->i_blkbits,
|
||||
iomap.length >> inode->i_blkbits,
|
||||
GFP_NOFS);
|
||||
if (error) {
|
||||
fs_err(GFS2_SB(inode), "Failed to zero data buffers\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@ -809,7 +808,7 @@ static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_alloc_parms ap = { .aflags = 0, };
|
||||
unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
|
||||
loff_t bytes, max_bytes, max_blks = UINT_MAX;
|
||||
loff_t bytes, max_bytes, max_blks;
|
||||
int error;
|
||||
const loff_t pos = offset;
|
||||
const loff_t count = len;
|
||||
@ -861,7 +860,8 @@ static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t
|
||||
return error;
|
||||
/* ap.allowed tells us how many blocks quota will allow
|
||||
* us to write. Check if this reduces max_blks */
|
||||
if (ap.allowed && ap.allowed < max_blks)
|
||||
max_blks = UINT_MAX;
|
||||
if (ap.allowed)
|
||||
max_blks = ap.allowed;
|
||||
|
||||
error = gfs2_inplace_reserve(ip, &ap);
|
||||
|
@ -130,15 +130,12 @@ static inline bool gfs2_rbm_eq(const struct gfs2_rbm *rbm1,
|
||||
enum gfs2_state_bits {
|
||||
BH_Pinned = BH_PrivateStart,
|
||||
BH_Escaped = BH_PrivateStart + 1,
|
||||
BH_Zeronew = BH_PrivateStart + 2,
|
||||
};
|
||||
|
||||
BUFFER_FNS(Pinned, pinned)
|
||||
TAS_BUFFER_FNS(Pinned, pinned)
|
||||
BUFFER_FNS(Escaped, escaped)
|
||||
TAS_BUFFER_FNS(Escaped, escaped)
|
||||
BUFFER_FNS(Zeronew, zeronew)
|
||||
TAS_BUFFER_FNS(Zeronew, zeronew)
|
||||
|
||||
struct gfs2_bufdata {
|
||||
struct buffer_head *bd_bh;
|
||||
|
@ -1326,19 +1326,11 @@ static int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
|
||||
static int update_moved_ino(struct gfs2_inode *ip, struct gfs2_inode *ndip,
|
||||
int dir_rename)
|
||||
{
|
||||
int error;
|
||||
struct buffer_head *dibh;
|
||||
|
||||
if (dir_rename)
|
||||
return gfs2_dir_mvino(ip, &gfs2_qdotdot, ndip, DT_DIR);
|
||||
|
||||
error = gfs2_meta_inode_buffer(ip, &dibh);
|
||||
if (error)
|
||||
return error;
|
||||
ip->i_inode.i_ctime = current_time(&ip->i_inode);
|
||||
gfs2_trans_add_meta(ip->i_gl, dibh);
|
||||
gfs2_dinode_out(ip, dibh->b_data);
|
||||
brelse(dibh);
|
||||
mark_inode_dirty_sync(&ip->i_inode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
|
||||
*
|
||||
*/
|
||||
|
||||
void gfs2_remove_from_ail(struct gfs2_bufdata *bd)
|
||||
static void gfs2_remove_from_ail(struct gfs2_bufdata *bd)
|
||||
{
|
||||
bd->bd_tr = NULL;
|
||||
list_del_init(&bd->bd_ail_st_list);
|
||||
|
@ -70,7 +70,6 @@ extern void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
|
||||
extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
|
||||
u32 type);
|
||||
extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
|
||||
extern void gfs2_remove_from_ail(struct gfs2_bufdata *bd);
|
||||
extern void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc);
|
||||
|
||||
extern void gfs2_log_shutdown(struct gfs2_sbd *sdp);
|
||||
|
@ -45,6 +45,8 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip,
|
||||
{
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
int ret;
|
||||
|
||||
ap->allowed = UINT_MAX; /* Assume we are permitted a whole lot */
|
||||
if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
|
||||
return 0;
|
||||
ret = gfs2_quota_lock(ip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE);
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/gfs2_ondisk.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/crc32c.h>
|
||||
#include <linux/ktime.h>
|
||||
|
||||
#include "gfs2.h"
|
||||
#include "incore.h"
|
||||
@ -409,12 +410,13 @@ void gfs2_recover_func(struct work_struct *work)
|
||||
struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
|
||||
struct gfs2_log_header_host head;
|
||||
struct gfs2_holder j_gh, ji_gh, thaw_gh;
|
||||
unsigned long t;
|
||||
ktime_t t_start, t_jlck, t_jhd, t_tlck, t_rep;
|
||||
int ro = 0;
|
||||
unsigned int pass;
|
||||
int error;
|
||||
int jlocked = 0;
|
||||
|
||||
t_start = ktime_get();
|
||||
if (sdp->sd_args.ar_spectator ||
|
||||
(jd->jd_jid != sdp->sd_lockstruct.ls_jid)) {
|
||||
fs_info(sdp, "jid=%u: Trying to acquire journal lock...\n",
|
||||
@ -446,6 +448,7 @@ void gfs2_recover_func(struct work_struct *work)
|
||||
fs_info(sdp, "jid=%u, already locked for use\n", jd->jd_jid);
|
||||
}
|
||||
|
||||
t_jlck = ktime_get();
|
||||
fs_info(sdp, "jid=%u: Looking at journal...\n", jd->jd_jid);
|
||||
|
||||
error = gfs2_jdesc_check(jd);
|
||||
@ -455,13 +458,12 @@ void gfs2_recover_func(struct work_struct *work)
|
||||
error = gfs2_find_jhead(jd, &head);
|
||||
if (error)
|
||||
goto fail_gunlock_ji;
|
||||
t_jhd = ktime_get();
|
||||
|
||||
if (!(head.lh_flags & GFS2_LOG_HEAD_UNMOUNT)) {
|
||||
fs_info(sdp, "jid=%u: Acquiring the transaction lock...\n",
|
||||
jd->jd_jid);
|
||||
|
||||
t = jiffies;
|
||||
|
||||
/* Acquire a shared hold on the freeze lock */
|
||||
|
||||
error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED,
|
||||
@ -495,6 +497,7 @@ void gfs2_recover_func(struct work_struct *work)
|
||||
goto fail_gunlock_thaw;
|
||||
}
|
||||
|
||||
t_tlck = ktime_get();
|
||||
fs_info(sdp, "jid=%u: Replaying journal...\n", jd->jd_jid);
|
||||
|
||||
for (pass = 0; pass < 2; pass++) {
|
||||
@ -509,9 +512,14 @@ void gfs2_recover_func(struct work_struct *work)
|
||||
clean_journal(jd, &head);
|
||||
|
||||
gfs2_glock_dq_uninit(&thaw_gh);
|
||||
t = DIV_ROUND_UP(jiffies - t, HZ);
|
||||
fs_info(sdp, "jid=%u: Journal replayed in %lus\n",
|
||||
jd->jd_jid, t);
|
||||
t_rep = ktime_get();
|
||||
fs_info(sdp, "jid=%u: Journal replayed in %lldms [jlck:%lldms, "
|
||||
"jhead:%lldms, tlck:%lldms, replay:%lldms]\n",
|
||||
jd->jd_jid, ktime_ms_delta(t_rep, t_start),
|
||||
ktime_ms_delta(t_jlck, t_start),
|
||||
ktime_ms_delta(t_jhd, t_jlck),
|
||||
ktime_ms_delta(t_tlck, t_jhd),
|
||||
ktime_ms_delta(t_rep, t_tlck));
|
||||
}
|
||||
|
||||
gfs2_recovery_done(sdp, jd->jd_jid, LM_RD_SUCCESS);
|
||||
|
@ -515,6 +515,7 @@ TRACE_EVENT(gfs2_iomap_end,
|
||||
__field( u64, inum )
|
||||
__field( loff_t, offset )
|
||||
__field( ssize_t, length )
|
||||
__field( sector_t, pblock )
|
||||
__field( u16, flags )
|
||||
__field( u16, type )
|
||||
__field( int, ret )
|
||||
@ -525,16 +526,20 @@ TRACE_EVENT(gfs2_iomap_end,
|
||||
__entry->inum = ip->i_no_addr;
|
||||
__entry->offset = iomap->offset;
|
||||
__entry->length = iomap->length;
|
||||
__entry->pblock = iomap->addr == IOMAP_NULL_ADDR ? 0 :
|
||||
(iomap->addr >> ip->i_inode.i_blkbits);
|
||||
__entry->flags = iomap->flags;
|
||||
__entry->type = iomap->type;
|
||||
__entry->ret = ret;
|
||||
),
|
||||
|
||||
TP_printk("%u,%u bmap %llu iomap end %llu/%lu ty:%d flags:%08x rc:%d",
|
||||
TP_printk("%u,%u bmap %llu iomap end %llu/%lu to %llu ty:%d flags:%08x rc:%d",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
(unsigned long long)__entry->inum,
|
||||
(unsigned long long)__entry->offset,
|
||||
(unsigned long)__entry->length, (u16)__entry->type,
|
||||
(unsigned long)__entry->length,
|
||||
(long long)__entry->pblock,
|
||||
(u16)__entry->type,
|
||||
(u16)__entry->flags, __entry->ret)
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user