mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 07:40:53 +07:00
This is possibly the smallest ever set of GFS2 patches for a merge
window. Also, most of them are bug fixes this time. Two of my three patches (moving gfs2_sync_meta and merging the two writepage implementations) are clean ups with the third (taking the glock ref in examine_bucket) being a fix for a difficult to hit race condition. The removal of an unused memory barrier is a clean up from Bob Peterson, and the "spectator" relates to a rarely used mount option. Ben Marzinski's patch fixes a corner case where the incorrect inode flags were being set, resulting in incorrect behaviour on fsync. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJSLYWjAAoJEMrg3m4a/8jSHBUQAIBXyrLypCJNJNpYreRlg4Te YZOqXMxqrfsWD5jkfWvxV/vZyVu6FEJRJRRwKoO8foZhnVIy2HiGdpFvwk4NMzGs Ah5cCaySgDhFIKXNq1CnhVZNpRU8N+Lf+8U2MwkpPUrT+KnZlDdG8COuHbWJ3/+t prqHy0N1oa8hgj3P0oDf3kyQKiB2MQVhORTBVOWaas1mzw8vsKRjvO7k5g0VPcfV VnIYzvQ033V6pW6ymWGcbz6us7hXeFJmXo4grAdLIclK6QDt1zPLVKlvk7X/Me52 PTxO5AP/Nw6AlJABTNy8UZ3uJO3QaiqhcIz+OzIXlYpsICqma30qkHHrWzOh0Q5F HrDqh03A2zuqigamVmsJr2+tbdLWxz72D6N3eFlIBLAw2JxILosCPcGc4UNzG/7g mFr6+LDnZXzFpjT6OBdepjVH06ZqfcV+nr3KhvmKQT+tkzTizArbt8JutOdKjahH 3+pXx/bA0B7LRVYymK5/xrfbjnQp629GG3QnGiI23gtDZ6eEzm663bQz6MTgjR88 H0nigLi8d2KmM8UnrZqq5nI+LirFD/IZ5DO47Vv6w3NCZW/ZpNOodlWkd1igvhHR ugTvKqyw2O9hImM8jPoRWbqL01RGTKTMMn/3cCCO8Uww7DpI4GLb48a39buYh4+2 kijIxCtntfQAOiR6MCvA =rsQv -----END PGP SIGNATURE----- Merge tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw Pull GFS2 updates from Steven Whitehouse: "This is possibly the smallest ever set of GFS2 patches for a merge window. Also, most of them are bug fixes this time. Two of my three patches (moving gfs2_sync_meta and merging the two writepage implementations) are clean ups with the third (taking the glock ref in examine_bucket) being a fix for a difficult to hit race condition. The removal of an unused memory barrier is a clean up from Bob Peterson, and the "spectator" relates to a rarely used mount option. Ben Marzinski's patch fixes a corner case where the incorrect inode flags were being set, resulting in incorrect behaviour on fsync" * tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw: GFS2: dirty inode correctly in gfs2_write_end GFS2: Don't flag consistency error if first mounter is a spectator GFS2: Remove unnecessary memory barrier GFS2: Merge ordered and writeback writepage GFS2: Take glock reference in examine_bucket() GFS2: Move gfs2_sync_meta to lops.c
This commit is contained in:
commit
6c337ad6cc
@ -122,14 +122,13 @@ static int gfs2_writepage_common(struct page *page,
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_writeback_writepage - Write page for writeback mappings
|
||||
* gfs2_writepage - Write page for writeback mappings
|
||||
* @page: The page
|
||||
* @wbc: The writeback control
|
||||
*
|
||||
*/
|
||||
|
||||
static int gfs2_writeback_writepage(struct page *page,
|
||||
struct writeback_control *wbc)
|
||||
static int gfs2_writepage(struct page *page, struct writeback_control *wbc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -140,32 +139,6 @@ static int gfs2_writeback_writepage(struct page *page,
|
||||
return nobh_writepage(page, gfs2_get_block_noalloc, wbc);
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_ordered_writepage - Write page for ordered data files
|
||||
* @page: The page to write
|
||||
* @wbc: The writeback control
|
||||
*
|
||||
*/
|
||||
|
||||
static int gfs2_ordered_writepage(struct page *page,
|
||||
struct writeback_control *wbc)
|
||||
{
|
||||
struct inode *inode = page->mapping->host;
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
int ret;
|
||||
|
||||
ret = gfs2_writepage_common(page, wbc);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
if (!page_has_buffers(page)) {
|
||||
create_empty_buffers(page, inode->i_sb->s_blocksize,
|
||||
(1 << BH_Dirty)|(1 << BH_Uptodate));
|
||||
}
|
||||
gfs2_page_add_databufs(ip, page, 0, inode->i_sb->s_blocksize-1);
|
||||
return block_write_full_page(page, gfs2_get_block_noalloc, wbc);
|
||||
}
|
||||
|
||||
/**
|
||||
* __gfs2_jdata_writepage - The core of jdata writepage
|
||||
* @page: The page to write
|
||||
@ -842,6 +815,8 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
|
||||
unsigned int from = pos & (PAGE_CACHE_SIZE - 1);
|
||||
unsigned int to = from + len;
|
||||
int ret;
|
||||
struct gfs2_trans *tr = current->journal_info;
|
||||
BUG_ON(!tr);
|
||||
|
||||
BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == NULL);
|
||||
|
||||
@ -852,8 +827,6 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
|
||||
goto failed;
|
||||
}
|
||||
|
||||
gfs2_trans_add_meta(ip->i_gl, dibh);
|
||||
|
||||
if (gfs2_is_stuffed(ip))
|
||||
return gfs2_stuffed_write_end(inode, dibh, pos, len, copied, page);
|
||||
|
||||
@ -861,6 +834,11 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
|
||||
gfs2_page_add_databufs(ip, page, from, to);
|
||||
|
||||
ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
|
||||
if (tr->tr_num_buf_new)
|
||||
__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
|
||||
else
|
||||
gfs2_trans_add_meta(ip->i_gl, dibh);
|
||||
|
||||
|
||||
if (inode == sdp->sd_rindex) {
|
||||
adjust_fs_space(inode);
|
||||
@ -1107,7 +1085,7 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
|
||||
}
|
||||
|
||||
static const struct address_space_operations gfs2_writeback_aops = {
|
||||
.writepage = gfs2_writeback_writepage,
|
||||
.writepage = gfs2_writepage,
|
||||
.writepages = gfs2_writepages,
|
||||
.readpage = gfs2_readpage,
|
||||
.readpages = gfs2_readpages,
|
||||
@ -1123,7 +1101,7 @@ static const struct address_space_operations gfs2_writeback_aops = {
|
||||
};
|
||||
|
||||
static const struct address_space_operations gfs2_ordered_aops = {
|
||||
.writepage = gfs2_ordered_writepage,
|
||||
.writepage = gfs2_writepage,
|
||||
.writepages = gfs2_writepages,
|
||||
.readpage = gfs2_readpage,
|
||||
.readpages = gfs2_readpages,
|
||||
|
@ -650,7 +650,7 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end,
|
||||
{
|
||||
struct address_space *mapping = file->f_mapping;
|
||||
struct inode *inode = mapping->host;
|
||||
int sync_state = inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC);
|
||||
int sync_state = inode->i_state & I_DIRTY;
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
int ret = 0, ret1 = 0;
|
||||
|
||||
@ -660,6 +660,8 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end,
|
||||
return ret1;
|
||||
}
|
||||
|
||||
if (!gfs2_is_jdata(ip))
|
||||
sync_state &= ~I_DIRTY_PAGES;
|
||||
if (datasync)
|
||||
sync_state &= ~I_DIRTY_SYNC;
|
||||
|
||||
|
@ -1411,7 +1411,6 @@ __acquires(&lru_lock)
|
||||
if (demote_ok(gl))
|
||||
handle_callback(gl, LM_ST_UNLOCKED, 0, false);
|
||||
WARN_ON(!test_and_clear_bit(GLF_LOCK, &gl->gl_flags));
|
||||
smp_mb__after_clear_bit();
|
||||
if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
|
||||
gfs2_glock_put_nolock(gl);
|
||||
spin_unlock(&gl->gl_spin);
|
||||
@ -1488,7 +1487,7 @@ static void examine_bucket(glock_examiner examiner, const struct gfs2_sbd *sdp,
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_bl_for_each_entry_rcu(gl, pos, head, gl_list) {
|
||||
if ((gl->gl_sbd == sdp) && atomic_read(&gl->gl_ref))
|
||||
if ((gl->gl_sbd == sdp) && atomic_inc_not_zero(&gl->gl_ref))
|
||||
examiner(gl);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
@ -1508,18 +1507,17 @@ static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
|
||||
* thaw_glock - thaw out a glock which has an unprocessed reply waiting
|
||||
* @gl: The glock to thaw
|
||||
*
|
||||
* N.B. When we freeze a glock, we leave a ref to the glock outstanding,
|
||||
* so this has to result in the ref count being dropped by one.
|
||||
*/
|
||||
|
||||
static void thaw_glock(struct gfs2_glock *gl)
|
||||
{
|
||||
if (!test_and_clear_bit(GLF_FROZEN, &gl->gl_flags))
|
||||
return;
|
||||
goto out;
|
||||
set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
|
||||
gfs2_glock_hold(gl);
|
||||
if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
|
||||
if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) {
|
||||
out:
|
||||
gfs2_glock_put(gl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1536,7 +1534,6 @@ static void clear_glock(struct gfs2_glock *gl)
|
||||
if (gl->gl_state != LM_ST_UNLOCKED)
|
||||
handle_callback(gl, LM_ST_UNLOCKED, 0, false);
|
||||
spin_unlock(&gl->gl_spin);
|
||||
gfs2_glock_hold(gl);
|
||||
if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
|
||||
gfs2_glock_put(gl);
|
||||
}
|
||||
|
@ -579,6 +579,24 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_meta_sync - Sync all buffers associated with a glock
|
||||
* @gl: The glock
|
||||
*
|
||||
*/
|
||||
|
||||
static void gfs2_meta_sync(struct gfs2_glock *gl)
|
||||
{
|
||||
struct address_space *mapping = gfs2_glock2aspace(gl);
|
||||
int error;
|
||||
|
||||
filemap_fdatawrite(mapping);
|
||||
error = filemap_fdatawait(mapping);
|
||||
|
||||
if (error)
|
||||
gfs2_io_error(gl->gl_sbd);
|
||||
}
|
||||
|
||||
static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
|
||||
|
@ -97,24 +97,6 @@ const struct address_space_operations gfs2_meta_aops = {
|
||||
.releasepage = gfs2_releasepage,
|
||||
};
|
||||
|
||||
/**
|
||||
* 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);
|
||||
int error;
|
||||
|
||||
filemap_fdatawrite(mapping);
|
||||
error = filemap_fdatawait(mapping);
|
||||
|
||||
if (error)
|
||||
gfs2_io_error(gl->gl_sbd);
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_getbuf - Get a buffer with a given address space
|
||||
* @gl: the glock
|
||||
|
@ -48,20 +48,16 @@ static inline struct gfs2_sbd *gfs2_mapping2sbd(struct address_space *mapping)
|
||||
return inode->i_sb->s_fs_info;
|
||||
}
|
||||
|
||||
void gfs2_meta_sync(struct gfs2_glock *gl);
|
||||
|
||||
struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno);
|
||||
int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno,
|
||||
int flags, struct buffer_head **bhp);
|
||||
int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh);
|
||||
struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create);
|
||||
|
||||
void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr,
|
||||
int meta);
|
||||
|
||||
void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen);
|
||||
|
||||
int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
|
||||
extern struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno);
|
||||
extern int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
|
||||
struct buffer_head **bhp);
|
||||
extern int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh);
|
||||
extern struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno,
|
||||
int create);
|
||||
extern void gfs2_remove_from_journal(struct buffer_head *bh,
|
||||
struct gfs2_trans *tr, int meta);
|
||||
extern void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen);
|
||||
extern int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
|
||||
struct buffer_head **bhp);
|
||||
|
||||
static inline int gfs2_meta_inode_buffer(struct gfs2_inode *ip,
|
||||
|
@ -646,6 +646,48 @@ static int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh)
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* check_journal_clean - Make sure a journal is clean for a spectator mount
|
||||
* @sdp: The GFS2 superblock
|
||||
* @jd: The journal descriptor
|
||||
*
|
||||
* Returns: 0 if the journal is clean or locked, else an error
|
||||
*/
|
||||
static int check_journal_clean(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd)
|
||||
{
|
||||
int error;
|
||||
struct gfs2_holder j_gh;
|
||||
struct gfs2_log_header_host head;
|
||||
struct gfs2_inode *ip;
|
||||
|
||||
ip = GFS2_I(jd->jd_inode);
|
||||
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_NOEXP |
|
||||
GL_EXACT | GL_NOCACHE, &j_gh);
|
||||
if (error) {
|
||||
fs_err(sdp, "Error locking journal for spectator mount.\n");
|
||||
return -EPERM;
|
||||
}
|
||||
error = gfs2_jdesc_check(jd);
|
||||
if (error) {
|
||||
fs_err(sdp, "Error checking journal for spectator mount.\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
error = gfs2_find_jhead(jd, &head);
|
||||
if (error) {
|
||||
fs_err(sdp, "Error parsing journal for spectator mount.\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
if (!(head.lh_flags & GFS2_LOG_HEAD_UNMOUNT)) {
|
||||
error = -EPERM;
|
||||
fs_err(sdp, "jid=%u: Journal is dirty, so the first mounter "
|
||||
"must not be a spectator.\n", jd->jd_jid);
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
gfs2_glock_dq_uninit(&j_gh);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int init_journal(struct gfs2_sbd *sdp, int undo)
|
||||
{
|
||||
struct inode *master = sdp->sd_master_dir->d_inode;
|
||||
@ -732,8 +774,15 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
|
||||
if (sdp->sd_lockstruct.ls_first) {
|
||||
unsigned int x;
|
||||
for (x = 0; x < sdp->sd_journals; x++) {
|
||||
error = gfs2_recover_journal(gfs2_jdesc_find(sdp, x),
|
||||
true);
|
||||
struct gfs2_jdesc *jd = gfs2_jdesc_find(sdp, x);
|
||||
|
||||
if (sdp->sd_args.ar_spectator) {
|
||||
error = check_journal_clean(sdp, jd);
|
||||
if (error)
|
||||
goto fail_jinode_gh;
|
||||
continue;
|
||||
}
|
||||
error = gfs2_recover_journal(jd, true);
|
||||
if (error) {
|
||||
fs_err(sdp, "error recovering journal %u: %d\n",
|
||||
x, error);
|
||||
|
Loading…
Reference in New Issue
Block a user