X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=fs%2Fgfs2%2Fglops.c;h=c4b0391b7aa23cbb5433d2235cc202793cf5797e;hb=a34fbc6363256387372331000462691bc4b3f5a9;hp=75d4c50cff45cf62dc5e55adf0ca87db549eb193;hpb=83b7a664a0c7c39ccfa4c72535dc1c001d4e7a18;p=powerpc.git diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 75d4c50cff..c4b0391b7a 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -4,7 +4,7 @@ * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU General Public License v.2. + * of the GNU General Public License version 2. */ #include @@ -13,9 +13,9 @@ #include #include #include +#include #include "gfs2.h" -#include "lm_interface.h" #include "incore.h" #include "bmap.h" #include "glock.h" @@ -26,118 +26,105 @@ #include "recovery.h" #include "rgrp.h" #include "util.h" - +#include "trans.h" /** - * gfs2_pte_inval - Sync and invalidate all PTEs associated with a glock + * ail_empty_gl - remove all buffers for a given lock from the AIL * @gl: the glock * + * None of the buffers should be dirty, locked, or pinned. */ -static void gfs2_pte_inval(struct gfs2_glock *gl) +static void gfs2_ail_empty_gl(struct gfs2_glock *gl) { - struct gfs2_inode *ip; - struct inode *inode; + struct gfs2_sbd *sdp = gl->gl_sbd; + unsigned int blocks; + struct list_head *head = &gl->gl_ail_list; + struct gfs2_bufdata *bd; + struct buffer_head *bh; + u64 blkno; + int error; - ip = gl->gl_object; - inode = &ip->i_inode; - if (!ip || !S_ISREG(ip->i_di.di_mode)) + blocks = atomic_read(&gl->gl_ail_count); + if (!blocks) return; - if (!test_bit(GIF_PAGED, &ip->i_flags)) + error = gfs2_trans_begin(sdp, 0, blocks); + if (gfs2_assert_withdraw(sdp, !error)) return; - unmap_shared_mapping_range(inode->i_mapping, 0, 0); - - if (test_bit(GIF_SW_PAGED, &ip->i_flags)) - set_bit(GLF_DIRTY, &gl->gl_flags); + gfs2_log_lock(sdp); + while (!list_empty(head)) { + bd = list_entry(head->next, struct gfs2_bufdata, + bd_ail_gl_list); + bh = bd->bd_bh; + blkno = bh->b_blocknr; + gfs2_assert_withdraw(sdp, !buffer_busy(bh)); - clear_bit(GIF_SW_PAGED, &ip->i_flags); -} + bd->bd_ail = NULL; + list_del(&bd->bd_ail_st_list); + list_del(&bd->bd_ail_gl_list); + atomic_dec(&gl->gl_ail_count); + brelse(bh); + gfs2_log_unlock(sdp); -/** - * gfs2_page_inval - Invalidate all pages associated with a glock - * @gl: the glock - * - */ + gfs2_trans_add_revoke(sdp, blkno); -static void gfs2_page_inval(struct gfs2_glock *gl) -{ - struct gfs2_inode *ip; - struct inode *inode; - - ip = gl->gl_object; - inode = &ip->i_inode; - if (!ip || !S_ISREG(ip->i_di.di_mode)) - return; + gfs2_log_lock(sdp); + } + gfs2_assert_withdraw(sdp, !atomic_read(&gl->gl_ail_count)); + gfs2_log_unlock(sdp); - truncate_inode_pages(inode->i_mapping, 0); - gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), !inode->i_mapping->nrpages); - clear_bit(GIF_PAGED, &ip->i_flags); + gfs2_trans_end(sdp); + gfs2_log_flush(sdp, NULL); } /** - * gfs2_page_sync - Sync the data pages (not metadata) associated with a glock + * gfs2_pte_inval - Sync and invalidate all PTEs associated with a glock * @gl: the glock - * @flags: DIO_START | DIO_WAIT * - * Syncs data (not metadata) for a regular file. - * No-op for all other types. */ -static void gfs2_page_sync(struct gfs2_glock *gl, int flags) +static void gfs2_pte_inval(struct gfs2_glock *gl) { struct gfs2_inode *ip; struct inode *inode; - struct address_space *mapping; - int error = 0; ip = gl->gl_object; inode = &ip->i_inode; - if (!ip || !S_ISREG(ip->i_di.di_mode)) + if (!ip || !S_ISREG(inode->i_mode)) return; - mapping = inode->i_mapping; - - if (flags & DIO_START) - filemap_fdatawrite(mapping); - if (!error && (flags & DIO_WAIT)) - error = filemap_fdatawait(mapping); + if (!test_bit(GIF_PAGED, &ip->i_flags)) + return; - /* Put back any errors cleared by filemap_fdatawait() - so they can be caught by someone who can pass them - up to user space. */ + unmap_shared_mapping_range(inode->i_mapping, 0, 0); - if (error == -ENOSPC) - set_bit(AS_ENOSPC, &mapping->flags); - else if (error) - set_bit(AS_EIO, &mapping->flags); + if (test_bit(GIF_SW_PAGED, &ip->i_flags)) + set_bit(GLF_DIRTY, &gl->gl_flags); + clear_bit(GIF_SW_PAGED, &ip->i_flags); } /** * meta_go_sync - sync out the metadata for this glock * @gl: the glock - * @flags: DIO_* * * Called when demoting or unlocking an EX glock. We must flush * to disk all dirty buffers/pages relating to this glock, and must not * not return to caller to demote/unlock the glock until I/O is complete. */ -static void meta_go_sync(struct gfs2_glock *gl, int flags) +static void meta_go_sync(struct gfs2_glock *gl) { - if (!(flags & DIO_METADATA)) + if (gl->gl_state != LM_ST_EXCLUSIVE) return; if (test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) { gfs2_log_flush(gl->gl_sbd, gl); - gfs2_meta_sync(gl, flags | DIO_START | DIO_WAIT); - if (flags & DIO_RELEASE) - gfs2_ail_empty_gl(gl); + gfs2_meta_sync(gl); + gfs2_ail_empty_gl(gl); } - - clear_bit(GLF_SYNC, &gl->gl_flags); } /** @@ -156,6 +143,37 @@ static void meta_go_inval(struct gfs2_glock *gl, int flags) gl->gl_vn++; } +/** + * inode_go_sync - Sync the dirty data and/or metadata for an inode glock + * @gl: the glock protecting the inode + * + */ + +static void inode_go_sync(struct gfs2_glock *gl) +{ + struct gfs2_inode *ip = gl->gl_object; + + if (ip && !S_ISREG(ip->i_inode.i_mode)) + ip = NULL; + + if (test_bit(GLF_DIRTY, &gl->gl_flags)) { + gfs2_log_flush(gl->gl_sbd, gl); + if (ip) + filemap_fdatawrite(ip->i_inode.i_mapping); + gfs2_meta_sync(gl); + if (ip) { + struct address_space *mapping = ip->i_inode.i_mapping; + int error = filemap_fdatawait(mapping); + if (error == -ENOSPC) + set_bit(AS_ENOSPC, &mapping->flags); + else if (error) + set_bit(AS_EIO, &mapping->flags); + } + clear_bit(GLF_DIRTY, &gl->gl_flags); + gfs2_ail_empty_gl(gl); + } +} + /** * inode_go_xmote_th - promote/demote a glock * @gl: the glock @@ -164,12 +182,12 @@ static void meta_go_inval(struct gfs2_glock *gl, int flags) * */ -static void inode_go_xmote_th(struct gfs2_glock *gl, unsigned int state, - int flags) +static void inode_go_xmote_th(struct gfs2_glock *gl) { if (gl->gl_state != LM_ST_UNLOCKED) gfs2_pte_inval(gl); - gfs2_glock_xmote_th(gl, state, flags); + if (gl->gl_state == LM_ST_EXCLUSIVE) + inode_go_sync(gl); } /** @@ -186,8 +204,7 @@ static void inode_go_xmote_bh(struct gfs2_glock *gl) if (gl->gl_state != LM_ST_UNLOCKED && (!gh || !(gh->gh_flags & GL_SKIP))) { - error = gfs2_meta_read(gl, gl->gl_name.ln_number, DIO_START, - &bh); + error = gfs2_meta_read(gl, gl->gl_name.ln_number, 0, &bh); if (!error) brelse(bh); } @@ -205,38 +222,8 @@ static void inode_go_xmote_bh(struct gfs2_glock *gl) static void inode_go_drop_th(struct gfs2_glock *gl) { gfs2_pte_inval(gl); - gfs2_glock_drop_th(gl); -} - -/** - * inode_go_sync - Sync the dirty data and/or metadata for an inode glock - * @gl: the glock protecting the inode - * @flags: - * - */ - -static void inode_go_sync(struct gfs2_glock *gl, int flags) -{ - int meta = (flags & DIO_METADATA); - int data = (flags & DIO_DATA); - - if (test_bit(GLF_DIRTY, &gl->gl_flags)) { - if (meta && data) { - gfs2_page_sync(gl, flags | DIO_START); - gfs2_log_flush(gl->gl_sbd, gl); - gfs2_meta_sync(gl, flags | DIO_START | DIO_WAIT); - gfs2_page_sync(gl, flags | DIO_WAIT); - clear_bit(GLF_DIRTY, &gl->gl_flags); - } else if (meta) { - gfs2_log_flush(gl->gl_sbd, gl); - gfs2_meta_sync(gl, flags | DIO_START | DIO_WAIT); - } else if (data) - gfs2_page_sync(gl, flags | DIO_START | DIO_WAIT); - if (flags & DIO_RELEASE) - gfs2_ail_empty_gl(gl); - } - - clear_bit(GLF_SYNC, &gl->gl_flags); + if (gl->gl_state == LM_ST_EXCLUSIVE) + inode_go_sync(gl); } /** @@ -248,15 +235,20 @@ static void inode_go_sync(struct gfs2_glock *gl, int flags) static void inode_go_inval(struct gfs2_glock *gl, int flags) { + struct gfs2_inode *ip = gl->gl_object; int meta = (flags & DIO_METADATA); - int data = (flags & DIO_DATA); if (meta) { gfs2_meta_inval(gl); - gl->gl_vn++; + if (ip) + set_bit(GIF_INVALID, &ip->i_flags); + } + + if (ip && S_ISREG(ip->i_inode.i_mode)) { + truncate_inode_pages(ip->i_inode.i_mapping, 0); + gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), !ip->i_inode.i_mapping->nrpages); + clear_bit(GIF_PAGED, &ip->i_flags); } - if (data) - gfs2_page_inval(gl); } /** @@ -298,16 +290,15 @@ static int inode_go_lock(struct gfs2_holder *gh) if (!ip) return 0; - if (ip->i_vn != gl->gl_vn) { + if (test_bit(GIF_INVALID, &ip->i_flags)) { error = gfs2_inode_refresh(ip); if (error) return error; - gfs2_inode_attr_in(ip); } if ((ip->i_di.di_flags & GFS2_DIF_TRUNC_IN_PROG) && (gl->gl_state == LM_ST_EXCLUSIVE) && - (gh->gh_flags & GL_LOCAL_EXCL)) + (gh->gh_state == LM_ST_EXCLUSIVE)) error = gfs2_truncatei_resume(ip); return error; @@ -326,45 +317,8 @@ static void inode_go_unlock(struct gfs2_holder *gh) struct gfs2_glock *gl = gh->gh_gl; struct gfs2_inode *ip = gl->gl_object; - if (ip) { - if (test_bit(GLF_DIRTY, &gl->gl_flags)) - gfs2_inode_attr_in(ip); - + if (ip) gfs2_meta_cache_flush(ip); - } -} - -/** - * inode_greedy - - * @gl: the glock - * - */ - -static void inode_greedy(struct gfs2_glock *gl) -{ - struct gfs2_sbd *sdp = gl->gl_sbd; - struct gfs2_inode *ip = gl->gl_object; - unsigned int quantum = gfs2_tune_get(sdp, gt_greedy_quantum); - unsigned int max = gfs2_tune_get(sdp, gt_greedy_max); - unsigned int new_time; - - spin_lock(&ip->i_spin); - - if (time_after(ip->i_last_pfault + quantum, jiffies)) { - new_time = ip->i_greedy + quantum; - if (new_time > max) - new_time = max; - } else { - new_time = ip->i_greedy - quantum; - if (!new_time || new_time > max) - new_time = 1; - } - - ip->i_greedy = new_time; - - spin_unlock(&ip->i_spin); - - iput(&ip->i_inode); } /** @@ -414,8 +368,7 @@ static void rgrp_go_unlock(struct gfs2_holder *gh) * */ -static void trans_go_xmote_th(struct gfs2_glock *gl, unsigned int state, - int flags) +static void trans_go_xmote_th(struct gfs2_glock *gl) { struct gfs2_sbd *sdp = gl->gl_sbd; @@ -424,8 +377,6 @@ static void trans_go_xmote_th(struct gfs2_glock *gl, unsigned int state, gfs2_meta_syncfs(sdp); gfs2_log_shutdown(sdp); } - - gfs2_glock_xmote_th(gl, state, flags); } /** @@ -439,13 +390,13 @@ static void trans_go_xmote_bh(struct gfs2_glock *gl) struct gfs2_sbd *sdp = gl->gl_sbd; struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode); struct gfs2_glock *j_gl = ip->i_gl; - struct gfs2_log_header head; + struct gfs2_log_header_host head; int error; if (gl->gl_state != LM_ST_UNLOCKED && test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { gfs2_meta_cache_flush(GFS2_I(sdp->sd_jdesc->jd_inode)); - j_gl->gl_ops->go_inval(j_gl, DIO_METADATA | DIO_DATA); + j_gl->gl_ops->go_inval(j_gl, DIO_METADATA); error = gfs2_find_jhead(sdp->sd_jdesc, &head); if (error) @@ -477,8 +428,6 @@ static void trans_go_drop_th(struct gfs2_glock *gl) gfs2_meta_syncfs(sdp); gfs2_log_shutdown(sdp); } - - gfs2_glock_drop_th(gl); } /** @@ -493,72 +442,56 @@ static int quota_go_demote_ok(struct gfs2_glock *gl) return !atomic_read(&gl->gl_lvb_count); } -struct gfs2_glock_operations gfs2_meta_glops = { - .go_xmote_th = gfs2_glock_xmote_th, - .go_drop_th = gfs2_glock_drop_th, - .go_type = LM_TYPE_META +const struct gfs2_glock_operations gfs2_meta_glops = { + .go_xmote_th = meta_go_sync, + .go_drop_th = meta_go_sync, + .go_type = LM_TYPE_META, }; -struct gfs2_glock_operations gfs2_inode_glops = { +const struct gfs2_glock_operations gfs2_inode_glops = { .go_xmote_th = inode_go_xmote_th, .go_xmote_bh = inode_go_xmote_bh, .go_drop_th = inode_go_drop_th, - .go_sync = inode_go_sync, .go_inval = inode_go_inval, .go_demote_ok = inode_go_demote_ok, .go_lock = inode_go_lock, .go_unlock = inode_go_unlock, - .go_greedy = inode_greedy, - .go_type = LM_TYPE_INODE + .go_type = LM_TYPE_INODE, }; -struct gfs2_glock_operations gfs2_rgrp_glops = { - .go_xmote_th = gfs2_glock_xmote_th, - .go_drop_th = gfs2_glock_drop_th, - .go_sync = meta_go_sync, +const struct gfs2_glock_operations gfs2_rgrp_glops = { .go_inval = meta_go_inval, .go_demote_ok = rgrp_go_demote_ok, .go_lock = rgrp_go_lock, .go_unlock = rgrp_go_unlock, - .go_type = LM_TYPE_RGRP + .go_type = LM_TYPE_RGRP, }; -struct gfs2_glock_operations gfs2_trans_glops = { +const struct gfs2_glock_operations gfs2_trans_glops = { .go_xmote_th = trans_go_xmote_th, .go_xmote_bh = trans_go_xmote_bh, .go_drop_th = trans_go_drop_th, - .go_type = LM_TYPE_NONDISK + .go_type = LM_TYPE_NONDISK, }; -struct gfs2_glock_operations gfs2_iopen_glops = { - .go_xmote_th = gfs2_glock_xmote_th, - .go_drop_th = gfs2_glock_drop_th, - .go_callback = gfs2_iopen_go_callback, - .go_type = LM_TYPE_IOPEN +const struct gfs2_glock_operations gfs2_iopen_glops = { + .go_type = LM_TYPE_IOPEN, }; -struct gfs2_glock_operations gfs2_flock_glops = { - .go_xmote_th = gfs2_glock_xmote_th, - .go_drop_th = gfs2_glock_drop_th, - .go_type = LM_TYPE_FLOCK +const struct gfs2_glock_operations gfs2_flock_glops = { + .go_type = LM_TYPE_FLOCK, }; -struct gfs2_glock_operations gfs2_nondisk_glops = { - .go_xmote_th = gfs2_glock_xmote_th, - .go_drop_th = gfs2_glock_drop_th, - .go_type = LM_TYPE_NONDISK +const struct gfs2_glock_operations gfs2_nondisk_glops = { + .go_type = LM_TYPE_NONDISK, }; -struct gfs2_glock_operations gfs2_quota_glops = { - .go_xmote_th = gfs2_glock_xmote_th, - .go_drop_th = gfs2_glock_drop_th, +const struct gfs2_glock_operations gfs2_quota_glops = { .go_demote_ok = quota_go_demote_ok, - .go_type = LM_TYPE_QUOTA + .go_type = LM_TYPE_QUOTA, }; -struct gfs2_glock_operations gfs2_journal_glops = { - .go_xmote_th = gfs2_glock_xmote_th, - .go_drop_th = gfs2_glock_drop_th, - .go_type = LM_TYPE_JOURNAL +const struct gfs2_glock_operations gfs2_journal_glops = { + .go_type = LM_TYPE_JOURNAL, };