1b3b94faaSDavid Teigland /* 2b3b94faaSDavid Teigland * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 3da6dd40dSBob Peterson * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. 4b3b94faaSDavid Teigland * 5b3b94faaSDavid Teigland * This copyrighted material is made available to anyone wishing to use, 6b3b94faaSDavid Teigland * modify, copy, or redistribute it subject to the terms and conditions 7e9fc2aa0SSteven Whitehouse * of the GNU General Public License version 2. 8b3b94faaSDavid Teigland */ 9b3b94faaSDavid Teigland 10b3b94faaSDavid Teigland #include <linux/sched.h> 11b3b94faaSDavid Teigland #include <linux/slab.h> 12b3b94faaSDavid Teigland #include <linux/spinlock.h> 13b3b94faaSDavid Teigland #include <linux/completion.h> 14b3b94faaSDavid Teigland #include <linux/buffer_head.h> 155c676f6dSSteven Whitehouse #include <linux/gfs2_ondisk.h> 1671b86f56SSteven Whitehouse #include <linux/crc32.h> 17a25311c8SSteven Whitehouse #include <linux/delay.h> 18ec69b188SSteven Whitehouse #include <linux/kthread.h> 19ec69b188SSteven Whitehouse #include <linux/freezer.h> 20254db57fSSteven Whitehouse #include <linux/bio.h> 214667a0ecSSteven Whitehouse #include <linux/writeback.h> 224a36d08dSBob Peterson #include <linux/list_sort.h> 23b3b94faaSDavid Teigland 24b3b94faaSDavid Teigland #include "gfs2.h" 255c676f6dSSteven Whitehouse #include "incore.h" 26b3b94faaSDavid Teigland #include "bmap.h" 27b3b94faaSDavid Teigland #include "glock.h" 28b3b94faaSDavid Teigland #include "log.h" 29b3b94faaSDavid Teigland #include "lops.h" 30b3b94faaSDavid Teigland #include "meta_io.h" 315c676f6dSSteven Whitehouse #include "util.h" 3271b86f56SSteven Whitehouse #include "dir.h" 3363997775SSteven Whitehouse #include "trace_gfs2.h" 34b3b94faaSDavid Teigland 35b3b94faaSDavid Teigland /** 36b3b94faaSDavid Teigland * gfs2_struct2blk - compute stuff 37b3b94faaSDavid Teigland * @sdp: the filesystem 38b3b94faaSDavid Teigland * @nstruct: the number of structures 39b3b94faaSDavid Teigland * @ssize: the size of the structures 40b3b94faaSDavid Teigland * 41b3b94faaSDavid Teigland * Compute the number of log descriptor blocks needed to hold a certain number 42b3b94faaSDavid Teigland * of structures of a certain size. 43b3b94faaSDavid Teigland * 44b3b94faaSDavid Teigland * Returns: the number of blocks needed (minimum is always 1) 45b3b94faaSDavid Teigland */ 46b3b94faaSDavid Teigland 47b3b94faaSDavid Teigland unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct, 48b3b94faaSDavid Teigland unsigned int ssize) 49b3b94faaSDavid Teigland { 50b3b94faaSDavid Teigland unsigned int blks; 51b3b94faaSDavid Teigland unsigned int first, second; 52b3b94faaSDavid Teigland 53b3b94faaSDavid Teigland blks = 1; 54faa31ce8SSteven Whitehouse first = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_log_descriptor)) / ssize; 55b3b94faaSDavid Teigland 56b3b94faaSDavid Teigland if (nstruct > first) { 57568f4c96SSteven Whitehouse second = (sdp->sd_sb.sb_bsize - 58568f4c96SSteven Whitehouse sizeof(struct gfs2_meta_header)) / ssize; 595c676f6dSSteven Whitehouse blks += DIV_ROUND_UP(nstruct - first, second); 60b3b94faaSDavid Teigland } 61b3b94faaSDavid Teigland 62b3b94faaSDavid Teigland return blks; 63b3b94faaSDavid Teigland } 64b3b94faaSDavid Teigland 65ddacfaf7SSteven Whitehouse /** 661e1a3d03SSteven Whitehouse * gfs2_remove_from_ail - Remove an entry from the ail lists, updating counters 671e1a3d03SSteven Whitehouse * @mapping: The associated mapping (maybe NULL) 681e1a3d03SSteven Whitehouse * @bd: The gfs2_bufdata to remove 691e1a3d03SSteven Whitehouse * 70c618e87aSSteven Whitehouse * The ail lock _must_ be held when calling this function 711e1a3d03SSteven Whitehouse * 721e1a3d03SSteven Whitehouse */ 731e1a3d03SSteven Whitehouse 74f91a0d3eSSteven Whitehouse void gfs2_remove_from_ail(struct gfs2_bufdata *bd) 751e1a3d03SSteven Whitehouse { 761e1a3d03SSteven Whitehouse bd->bd_ail = NULL; 771ad38c43SSteven Whitehouse list_del_init(&bd->bd_ail_st_list); 781ad38c43SSteven Whitehouse list_del_init(&bd->bd_ail_gl_list); 791e1a3d03SSteven Whitehouse atomic_dec(&bd->bd_gl->gl_ail_count); 801e1a3d03SSteven Whitehouse brelse(bd->bd_bh); 811e1a3d03SSteven Whitehouse } 821e1a3d03SSteven Whitehouse 831e1a3d03SSteven Whitehouse /** 84ddacfaf7SSteven Whitehouse * gfs2_ail1_start_one - Start I/O on a part of the AIL 85ddacfaf7SSteven Whitehouse * @sdp: the filesystem 864667a0ecSSteven Whitehouse * @wbc: The writeback control structure 874667a0ecSSteven Whitehouse * @ai: The ail structure 88ddacfaf7SSteven Whitehouse * 89ddacfaf7SSteven Whitehouse */ 90ddacfaf7SSteven Whitehouse 914f1de018SSteven Whitehouse static int gfs2_ail1_start_one(struct gfs2_sbd *sdp, 924667a0ecSSteven Whitehouse struct writeback_control *wbc, 934667a0ecSSteven Whitehouse struct gfs2_ail *ai) 94d6a079e8SDave Chinner __releases(&sdp->sd_ail_lock) 95d6a079e8SDave Chinner __acquires(&sdp->sd_ail_lock) 96ddacfaf7SSteven Whitehouse { 975ac048bbSSteven Whitehouse struct gfs2_glock *gl = NULL; 984667a0ecSSteven Whitehouse struct address_space *mapping; 99ddacfaf7SSteven Whitehouse struct gfs2_bufdata *bd, *s; 100ddacfaf7SSteven Whitehouse struct buffer_head *bh; 101ddacfaf7SSteven Whitehouse 1024667a0ecSSteven Whitehouse list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list, bd_ail_st_list) { 103ddacfaf7SSteven Whitehouse bh = bd->bd_bh; 104ddacfaf7SSteven Whitehouse 105ddacfaf7SSteven Whitehouse gfs2_assert(sdp, bd->bd_ail == ai); 106ddacfaf7SSteven Whitehouse 107ddacfaf7SSteven Whitehouse if (!buffer_busy(bh)) { 10816615be1SSteven Whitehouse if (!buffer_uptodate(bh)) 109ddacfaf7SSteven Whitehouse gfs2_io_error_bh(sdp, bh); 110ddacfaf7SSteven Whitehouse list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); 111ddacfaf7SSteven Whitehouse continue; 112ddacfaf7SSteven Whitehouse } 113ddacfaf7SSteven Whitehouse 114ddacfaf7SSteven Whitehouse if (!buffer_dirty(bh)) 115ddacfaf7SSteven Whitehouse continue; 1165ac048bbSSteven Whitehouse if (gl == bd->bd_gl) 1175ac048bbSSteven Whitehouse continue; 1185ac048bbSSteven Whitehouse gl = bd->bd_gl; 119ddacfaf7SSteven Whitehouse list_move(&bd->bd_ail_st_list, &ai->ai_ail1_list); 1204667a0ecSSteven Whitehouse mapping = bh->b_page->mapping; 1214f1de018SSteven Whitehouse if (!mapping) 1224f1de018SSteven Whitehouse continue; 123d6a079e8SDave Chinner spin_unlock(&sdp->sd_ail_lock); 1244667a0ecSSteven Whitehouse generic_writepages(mapping, wbc); 125d6a079e8SDave Chinner spin_lock(&sdp->sd_ail_lock); 1264667a0ecSSteven Whitehouse if (wbc->nr_to_write <= 0) 127ddacfaf7SSteven Whitehouse break; 1284f1de018SSteven Whitehouse return 1; 129ddacfaf7SSteven Whitehouse } 1304f1de018SSteven Whitehouse 1314f1de018SSteven Whitehouse return 0; 1324667a0ecSSteven Whitehouse } 1334667a0ecSSteven Whitehouse 1344667a0ecSSteven Whitehouse 1354667a0ecSSteven Whitehouse /** 1364667a0ecSSteven Whitehouse * gfs2_ail1_flush - start writeback of some ail1 entries 1374667a0ecSSteven Whitehouse * @sdp: The super block 1384667a0ecSSteven Whitehouse * @wbc: The writeback control structure 1394667a0ecSSteven Whitehouse * 1404667a0ecSSteven Whitehouse * Writes back some ail1 entries, according to the limits in the 1414667a0ecSSteven Whitehouse * writeback control structure 1424667a0ecSSteven Whitehouse */ 1434667a0ecSSteven Whitehouse 1444667a0ecSSteven Whitehouse void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc) 1454667a0ecSSteven Whitehouse { 1464667a0ecSSteven Whitehouse struct list_head *head = &sdp->sd_ail1_list; 1474667a0ecSSteven Whitehouse struct gfs2_ail *ai; 1484667a0ecSSteven Whitehouse 149c83ae9caSSteven Whitehouse trace_gfs2_ail_flush(sdp, wbc, 1); 1504667a0ecSSteven Whitehouse spin_lock(&sdp->sd_ail_lock); 1514f1de018SSteven Whitehouse restart: 1524667a0ecSSteven Whitehouse list_for_each_entry_reverse(ai, head, ai_list) { 1534667a0ecSSteven Whitehouse if (wbc->nr_to_write <= 0) 1544667a0ecSSteven Whitehouse break; 1554f1de018SSteven Whitehouse if (gfs2_ail1_start_one(sdp, wbc, ai)) 1564f1de018SSteven Whitehouse goto restart; 1574667a0ecSSteven Whitehouse } 1584667a0ecSSteven Whitehouse spin_unlock(&sdp->sd_ail_lock); 159c83ae9caSSteven Whitehouse trace_gfs2_ail_flush(sdp, wbc, 0); 1604667a0ecSSteven Whitehouse } 1614667a0ecSSteven Whitehouse 1624667a0ecSSteven Whitehouse /** 1634667a0ecSSteven Whitehouse * gfs2_ail1_start - start writeback of all ail1 entries 1644667a0ecSSteven Whitehouse * @sdp: The superblock 1654667a0ecSSteven Whitehouse */ 1664667a0ecSSteven Whitehouse 1674667a0ecSSteven Whitehouse static void gfs2_ail1_start(struct gfs2_sbd *sdp) 1684667a0ecSSteven Whitehouse { 1694667a0ecSSteven Whitehouse struct writeback_control wbc = { 1704667a0ecSSteven Whitehouse .sync_mode = WB_SYNC_NONE, 1714667a0ecSSteven Whitehouse .nr_to_write = LONG_MAX, 1724667a0ecSSteven Whitehouse .range_start = 0, 1734667a0ecSSteven Whitehouse .range_end = LLONG_MAX, 1744667a0ecSSteven Whitehouse }; 1754667a0ecSSteven Whitehouse 1764667a0ecSSteven Whitehouse return gfs2_ail1_flush(sdp, &wbc); 177ddacfaf7SSteven Whitehouse } 178ddacfaf7SSteven Whitehouse 179ddacfaf7SSteven Whitehouse /** 180ddacfaf7SSteven Whitehouse * gfs2_ail1_empty_one - Check whether or not a trans in the AIL has been synced 181ddacfaf7SSteven Whitehouse * @sdp: the filesystem 182ddacfaf7SSteven Whitehouse * @ai: the AIL entry 183ddacfaf7SSteven Whitehouse * 184ddacfaf7SSteven Whitehouse */ 185ddacfaf7SSteven Whitehouse 1864667a0ecSSteven Whitehouse static void gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) 187ddacfaf7SSteven Whitehouse { 188ddacfaf7SSteven Whitehouse struct gfs2_bufdata *bd, *s; 189ddacfaf7SSteven Whitehouse struct buffer_head *bh; 190ddacfaf7SSteven Whitehouse 191ddacfaf7SSteven Whitehouse list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list, 192ddacfaf7SSteven Whitehouse bd_ail_st_list) { 193ddacfaf7SSteven Whitehouse bh = bd->bd_bh; 194ddacfaf7SSteven Whitehouse gfs2_assert(sdp, bd->bd_ail == ai); 1954667a0ecSSteven Whitehouse if (buffer_busy(bh)) 196ddacfaf7SSteven Whitehouse continue; 197ddacfaf7SSteven Whitehouse if (!buffer_uptodate(bh)) 198ddacfaf7SSteven Whitehouse gfs2_io_error_bh(sdp, bh); 199ddacfaf7SSteven Whitehouse list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); 200ddacfaf7SSteven Whitehouse } 201ddacfaf7SSteven Whitehouse 202ddacfaf7SSteven Whitehouse } 203ddacfaf7SSteven Whitehouse 2044667a0ecSSteven Whitehouse /** 2054667a0ecSSteven Whitehouse * gfs2_ail1_empty - Try to empty the ail1 lists 2064667a0ecSSteven Whitehouse * @sdp: The superblock 2074667a0ecSSteven Whitehouse * 2084667a0ecSSteven Whitehouse * Tries to empty the ail1 lists, starting with the oldest first 2094667a0ecSSteven Whitehouse */ 210b3b94faaSDavid Teigland 2114667a0ecSSteven Whitehouse static int gfs2_ail1_empty(struct gfs2_sbd *sdp) 212b3b94faaSDavid Teigland { 213b3b94faaSDavid Teigland struct gfs2_ail *ai, *s; 214b3b94faaSDavid Teigland int ret; 215b3b94faaSDavid Teigland 216d6a079e8SDave Chinner spin_lock(&sdp->sd_ail_lock); 217b3b94faaSDavid Teigland list_for_each_entry_safe_reverse(ai, s, &sdp->sd_ail1_list, ai_list) { 2184667a0ecSSteven Whitehouse gfs2_ail1_empty_one(sdp, ai); 2194667a0ecSSteven Whitehouse if (list_empty(&ai->ai_ail1_list)) 220b3b94faaSDavid Teigland list_move(&ai->ai_list, &sdp->sd_ail2_list); 2214667a0ecSSteven Whitehouse else 222b3b94faaSDavid Teigland break; 223b3b94faaSDavid Teigland } 224b3b94faaSDavid Teigland ret = list_empty(&sdp->sd_ail1_list); 225d6a079e8SDave Chinner spin_unlock(&sdp->sd_ail_lock); 226b3b94faaSDavid Teigland 227b3b94faaSDavid Teigland return ret; 228b3b94faaSDavid Teigland } 229b3b94faaSDavid Teigland 23026b06a69SSteven Whitehouse static void gfs2_ail1_wait(struct gfs2_sbd *sdp) 23126b06a69SSteven Whitehouse { 23226b06a69SSteven Whitehouse struct gfs2_ail *ai; 23326b06a69SSteven Whitehouse struct gfs2_bufdata *bd; 23426b06a69SSteven Whitehouse struct buffer_head *bh; 23526b06a69SSteven Whitehouse 23626b06a69SSteven Whitehouse spin_lock(&sdp->sd_ail_lock); 23726b06a69SSteven Whitehouse list_for_each_entry_reverse(ai, &sdp->sd_ail1_list, ai_list) { 23826b06a69SSteven Whitehouse list_for_each_entry(bd, &ai->ai_ail1_list, bd_ail_st_list) { 23926b06a69SSteven Whitehouse bh = bd->bd_bh; 24026b06a69SSteven Whitehouse if (!buffer_locked(bh)) 24126b06a69SSteven Whitehouse continue; 24226b06a69SSteven Whitehouse get_bh(bh); 24326b06a69SSteven Whitehouse spin_unlock(&sdp->sd_ail_lock); 24426b06a69SSteven Whitehouse wait_on_buffer(bh); 24526b06a69SSteven Whitehouse brelse(bh); 24626b06a69SSteven Whitehouse return; 24726b06a69SSteven Whitehouse } 24826b06a69SSteven Whitehouse } 24926b06a69SSteven Whitehouse spin_unlock(&sdp->sd_ail_lock); 25026b06a69SSteven Whitehouse } 251ddacfaf7SSteven Whitehouse 252ddacfaf7SSteven Whitehouse /** 253ddacfaf7SSteven Whitehouse * gfs2_ail2_empty_one - Check whether or not a trans in the AIL has been synced 254ddacfaf7SSteven Whitehouse * @sdp: the filesystem 255ddacfaf7SSteven Whitehouse * @ai: the AIL entry 256ddacfaf7SSteven Whitehouse * 257ddacfaf7SSteven Whitehouse */ 258ddacfaf7SSteven Whitehouse 259ddacfaf7SSteven Whitehouse static void gfs2_ail2_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) 260ddacfaf7SSteven Whitehouse { 261ddacfaf7SSteven Whitehouse struct list_head *head = &ai->ai_ail2_list; 262ddacfaf7SSteven Whitehouse struct gfs2_bufdata *bd; 263ddacfaf7SSteven Whitehouse 264ddacfaf7SSteven Whitehouse while (!list_empty(head)) { 265ddacfaf7SSteven Whitehouse bd = list_entry(head->prev, struct gfs2_bufdata, 266ddacfaf7SSteven Whitehouse bd_ail_st_list); 267ddacfaf7SSteven Whitehouse gfs2_assert(sdp, bd->bd_ail == ai); 268f91a0d3eSSteven Whitehouse gfs2_remove_from_ail(bd); 269ddacfaf7SSteven Whitehouse } 270ddacfaf7SSteven Whitehouse } 271ddacfaf7SSteven Whitehouse 272b3b94faaSDavid Teigland static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail) 273b3b94faaSDavid Teigland { 274b3b94faaSDavid Teigland struct gfs2_ail *ai, *safe; 275b3b94faaSDavid Teigland unsigned int old_tail = sdp->sd_log_tail; 276b3b94faaSDavid Teigland int wrap = (new_tail < old_tail); 277b3b94faaSDavid Teigland int a, b, rm; 278b3b94faaSDavid Teigland 279d6a079e8SDave Chinner spin_lock(&sdp->sd_ail_lock); 280b3b94faaSDavid Teigland 281b3b94faaSDavid Teigland list_for_each_entry_safe(ai, safe, &sdp->sd_ail2_list, ai_list) { 282b3b94faaSDavid Teigland a = (old_tail <= ai->ai_first); 283b3b94faaSDavid Teigland b = (ai->ai_first < new_tail); 284b3b94faaSDavid Teigland rm = (wrap) ? (a || b) : (a && b); 285b3b94faaSDavid Teigland if (!rm) 286b3b94faaSDavid Teigland continue; 287b3b94faaSDavid Teigland 288b3b94faaSDavid Teigland gfs2_ail2_empty_one(sdp, ai); 289b3b94faaSDavid Teigland list_del(&ai->ai_list); 290b3b94faaSDavid Teigland gfs2_assert_warn(sdp, list_empty(&ai->ai_ail1_list)); 291b3b94faaSDavid Teigland gfs2_assert_warn(sdp, list_empty(&ai->ai_ail2_list)); 292b3b94faaSDavid Teigland kfree(ai); 293b3b94faaSDavid Teigland } 294b3b94faaSDavid Teigland 295d6a079e8SDave Chinner spin_unlock(&sdp->sd_ail_lock); 296b3b94faaSDavid Teigland } 297b3b94faaSDavid Teigland 298b3b94faaSDavid Teigland /** 299b3b94faaSDavid Teigland * gfs2_log_reserve - Make a log reservation 300b3b94faaSDavid Teigland * @sdp: The GFS2 superblock 301b3b94faaSDavid Teigland * @blks: The number of blocks to reserve 302b3b94faaSDavid Teigland * 30389918647SSteven Whitehouse * Note that we never give out the last few blocks of the journal. Thats 3042332c443SRobert Peterson * due to the fact that there is a small number of header blocks 305b004157aSSteven Whitehouse * associated with each log flush. The exact number can't be known until 306b004157aSSteven Whitehouse * flush time, so we ensure that we have just enough free blocks at all 307b004157aSSteven Whitehouse * times to avoid running out during a log flush. 308b004157aSSteven Whitehouse * 3095e687eacSBenjamin Marzinski * We no longer flush the log here, instead we wake up logd to do that 3105e687eacSBenjamin Marzinski * for us. To avoid the thundering herd and to ensure that we deal fairly 3115e687eacSBenjamin Marzinski * with queued waiters, we use an exclusive wait. This means that when we 3125e687eacSBenjamin Marzinski * get woken with enough journal space to get our reservation, we need to 3135e687eacSBenjamin Marzinski * wake the next waiter on the list. 3145e687eacSBenjamin Marzinski * 315b3b94faaSDavid Teigland * Returns: errno 316b3b94faaSDavid Teigland */ 317b3b94faaSDavid Teigland 318b3b94faaSDavid Teigland int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) 319b3b94faaSDavid Teigland { 32089918647SSteven Whitehouse unsigned reserved_blks = 6 * (4096 / sdp->sd_vfs->s_blocksize); 3215e687eacSBenjamin Marzinski unsigned wanted = blks + reserved_blks; 3225e687eacSBenjamin Marzinski DEFINE_WAIT(wait); 3235e687eacSBenjamin Marzinski int did_wait = 0; 3245e687eacSBenjamin Marzinski unsigned int free_blocks; 325b3b94faaSDavid Teigland 326b3b94faaSDavid Teigland if (gfs2_assert_warn(sdp, blks) || 327b3b94faaSDavid Teigland gfs2_assert_warn(sdp, blks <= sdp->sd_jdesc->jd_blocks)) 328b3b94faaSDavid Teigland return -EINVAL; 3295e687eacSBenjamin Marzinski retry: 3305e687eacSBenjamin Marzinski free_blocks = atomic_read(&sdp->sd_log_blks_free); 3315e687eacSBenjamin Marzinski if (unlikely(free_blocks <= wanted)) { 3325e687eacSBenjamin Marzinski do { 3335e687eacSBenjamin Marzinski prepare_to_wait_exclusive(&sdp->sd_log_waitq, &wait, 3345e687eacSBenjamin Marzinski TASK_UNINTERRUPTIBLE); 3355e687eacSBenjamin Marzinski wake_up(&sdp->sd_logd_waitq); 3365e687eacSBenjamin Marzinski did_wait = 1; 3375e687eacSBenjamin Marzinski if (atomic_read(&sdp->sd_log_blks_free) <= wanted) 3385e687eacSBenjamin Marzinski io_schedule(); 3395e687eacSBenjamin Marzinski free_blocks = atomic_read(&sdp->sd_log_blks_free); 3405e687eacSBenjamin Marzinski } while(free_blocks <= wanted); 3415e687eacSBenjamin Marzinski finish_wait(&sdp->sd_log_waitq, &wait); 342b3b94faaSDavid Teigland } 3435e687eacSBenjamin Marzinski if (atomic_cmpxchg(&sdp->sd_log_blks_free, free_blocks, 3445e687eacSBenjamin Marzinski free_blocks - blks) != free_blocks) 3455e687eacSBenjamin Marzinski goto retry; 34663997775SSteven Whitehouse trace_gfs2_log_blocks(sdp, -blks); 3475e687eacSBenjamin Marzinski 3485e687eacSBenjamin Marzinski /* 3495e687eacSBenjamin Marzinski * If we waited, then so might others, wake them up _after_ we get 3505e687eacSBenjamin Marzinski * our share of the log. 3515e687eacSBenjamin Marzinski */ 3525e687eacSBenjamin Marzinski if (unlikely(did_wait)) 3535e687eacSBenjamin Marzinski wake_up(&sdp->sd_log_waitq); 354484adff8SSteven Whitehouse 355484adff8SSteven Whitehouse down_read(&sdp->sd_log_flush_lock); 356b3b94faaSDavid Teigland 357b3b94faaSDavid Teigland return 0; 358b3b94faaSDavid Teigland } 359b3b94faaSDavid Teigland 360b3b94faaSDavid Teigland /** 361b3b94faaSDavid Teigland * log_distance - Compute distance between two journal blocks 362b3b94faaSDavid Teigland * @sdp: The GFS2 superblock 363b3b94faaSDavid Teigland * @newer: The most recent journal block of the pair 364b3b94faaSDavid Teigland * @older: The older journal block of the pair 365b3b94faaSDavid Teigland * 366b3b94faaSDavid Teigland * Compute the distance (in the journal direction) between two 367b3b94faaSDavid Teigland * blocks in the journal 368b3b94faaSDavid Teigland * 369b3b94faaSDavid Teigland * Returns: the distance in blocks 370b3b94faaSDavid Teigland */ 371b3b94faaSDavid Teigland 372faa31ce8SSteven Whitehouse static inline unsigned int log_distance(struct gfs2_sbd *sdp, unsigned int newer, 373b3b94faaSDavid Teigland unsigned int older) 374b3b94faaSDavid Teigland { 375b3b94faaSDavid Teigland int dist; 376b3b94faaSDavid Teigland 377b3b94faaSDavid Teigland dist = newer - older; 378b3b94faaSDavid Teigland if (dist < 0) 379b3b94faaSDavid Teigland dist += sdp->sd_jdesc->jd_blocks; 380b3b94faaSDavid Teigland 381b3b94faaSDavid Teigland return dist; 382b3b94faaSDavid Teigland } 383b3b94faaSDavid Teigland 3842332c443SRobert Peterson /** 3852332c443SRobert Peterson * calc_reserved - Calculate the number of blocks to reserve when 3862332c443SRobert Peterson * refunding a transaction's unused buffers. 3872332c443SRobert Peterson * @sdp: The GFS2 superblock 3882332c443SRobert Peterson * 3892332c443SRobert Peterson * This is complex. We need to reserve room for all our currently used 3902332c443SRobert Peterson * metadata buffers (e.g. normal file I/O rewriting file time stamps) and 3912332c443SRobert Peterson * all our journaled data buffers for journaled files (e.g. files in the 3922332c443SRobert Peterson * meta_fs like rindex, or files for which chattr +j was done.) 3932332c443SRobert Peterson * If we don't reserve enough space, gfs2_log_refund and gfs2_log_flush 3942332c443SRobert Peterson * will count it as free space (sd_log_blks_free) and corruption will follow. 3952332c443SRobert Peterson * 3962332c443SRobert Peterson * We can have metadata bufs and jdata bufs in the same journal. So each 3972332c443SRobert Peterson * type gets its own log header, for which we need to reserve a block. 3982332c443SRobert Peterson * In fact, each type has the potential for needing more than one header 3992332c443SRobert Peterson * in cases where we have more buffers than will fit on a journal page. 4002332c443SRobert Peterson * Metadata journal entries take up half the space of journaled buffer entries. 4012332c443SRobert Peterson * Thus, metadata entries have buf_limit (502) and journaled buffers have 4022332c443SRobert Peterson * databuf_limit (251) before they cause a wrap around. 4032332c443SRobert Peterson * 4042332c443SRobert Peterson * Also, we need to reserve blocks for revoke journal entries and one for an 4052332c443SRobert Peterson * overall header for the lot. 4062332c443SRobert Peterson * 4072332c443SRobert Peterson * Returns: the number of blocks reserved 4082332c443SRobert Peterson */ 4092332c443SRobert Peterson static unsigned int calc_reserved(struct gfs2_sbd *sdp) 4102332c443SRobert Peterson { 4112332c443SRobert Peterson unsigned int reserved = 0; 4122332c443SRobert Peterson unsigned int mbuf_limit, metabufhdrs_needed; 4132332c443SRobert Peterson unsigned int dbuf_limit, databufhdrs_needed; 4142332c443SRobert Peterson unsigned int revokes = 0; 4152332c443SRobert Peterson 4162332c443SRobert Peterson mbuf_limit = buf_limit(sdp); 4172332c443SRobert Peterson metabufhdrs_needed = (sdp->sd_log_commited_buf + 4182332c443SRobert Peterson (mbuf_limit - 1)) / mbuf_limit; 4192332c443SRobert Peterson dbuf_limit = databuf_limit(sdp); 4202332c443SRobert Peterson databufhdrs_needed = (sdp->sd_log_commited_databuf + 4212332c443SRobert Peterson (dbuf_limit - 1)) / dbuf_limit; 4222332c443SRobert Peterson 4232e95e3f6SBenjamin Marzinski if (sdp->sd_log_commited_revoke > 0) 4242332c443SRobert Peterson revokes = gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke, 4252332c443SRobert Peterson sizeof(u64)); 4262332c443SRobert Peterson 4272332c443SRobert Peterson reserved = sdp->sd_log_commited_buf + metabufhdrs_needed + 4282332c443SRobert Peterson sdp->sd_log_commited_databuf + databufhdrs_needed + 4292332c443SRobert Peterson revokes; 4302332c443SRobert Peterson /* One for the overall header */ 4312332c443SRobert Peterson if (reserved) 4322332c443SRobert Peterson reserved++; 4332332c443SRobert Peterson return reserved; 4342332c443SRobert Peterson } 4352332c443SRobert Peterson 436b3b94faaSDavid Teigland static unsigned int current_tail(struct gfs2_sbd *sdp) 437b3b94faaSDavid Teigland { 438b3b94faaSDavid Teigland struct gfs2_ail *ai; 439b3b94faaSDavid Teigland unsigned int tail; 440b3b94faaSDavid Teigland 441d6a079e8SDave Chinner spin_lock(&sdp->sd_ail_lock); 442b3b94faaSDavid Teigland 443faa31ce8SSteven Whitehouse if (list_empty(&sdp->sd_ail1_list)) { 444b3b94faaSDavid Teigland tail = sdp->sd_log_head; 445faa31ce8SSteven Whitehouse } else { 446faa31ce8SSteven Whitehouse ai = list_entry(sdp->sd_ail1_list.prev, struct gfs2_ail, ai_list); 447b3b94faaSDavid Teigland tail = ai->ai_first; 448b3b94faaSDavid Teigland } 449b3b94faaSDavid Teigland 450d6a079e8SDave Chinner spin_unlock(&sdp->sd_ail_lock); 451b3b94faaSDavid Teigland 452b3b94faaSDavid Teigland return tail; 453b3b94faaSDavid Teigland } 454b3b94faaSDavid Teigland 4552332c443SRobert Peterson static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail) 456b3b94faaSDavid Teigland { 457b3b94faaSDavid Teigland unsigned int dist = log_distance(sdp, new_tail, sdp->sd_log_tail); 458b3b94faaSDavid Teigland 459b3b94faaSDavid Teigland ail2_empty(sdp, new_tail); 460b3b94faaSDavid Teigland 461fd041f0bSSteven Whitehouse atomic_add(dist, &sdp->sd_log_blks_free); 46263997775SSteven Whitehouse trace_gfs2_log_blocks(sdp, dist); 4635e687eacSBenjamin Marzinski gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <= 4645e687eacSBenjamin Marzinski sdp->sd_jdesc->jd_blocks); 465b3b94faaSDavid Teigland 466b3b94faaSDavid Teigland sdp->sd_log_tail = new_tail; 467b3b94faaSDavid Teigland } 468b3b94faaSDavid Teigland 469b3b94faaSDavid Teigland 47034cc1781SSteven Whitehouse static void log_flush_wait(struct gfs2_sbd *sdp) 471b3b94faaSDavid Teigland { 47216615be1SSteven Whitehouse DEFINE_WAIT(wait); 473b3b94faaSDavid Teigland 47416615be1SSteven Whitehouse if (atomic_read(&sdp->sd_log_in_flight)) { 47516615be1SSteven Whitehouse do { 47616615be1SSteven Whitehouse prepare_to_wait(&sdp->sd_log_flush_wait, &wait, 47716615be1SSteven Whitehouse TASK_UNINTERRUPTIBLE); 47816615be1SSteven Whitehouse if (atomic_read(&sdp->sd_log_in_flight)) 47916615be1SSteven Whitehouse io_schedule(); 48016615be1SSteven Whitehouse } while(atomic_read(&sdp->sd_log_in_flight)); 48116615be1SSteven Whitehouse finish_wait(&sdp->sd_log_flush_wait, &wait); 482b3b94faaSDavid Teigland } 483b3b94faaSDavid Teigland } 484b3b94faaSDavid Teigland 485*45138990SSteven Whitehouse static int ip_cmp(void *priv, struct list_head *a, struct list_head *b) 4864a36d08dSBob Peterson { 487*45138990SSteven Whitehouse struct gfs2_inode *ipa, *ipb; 4884a36d08dSBob Peterson 489*45138990SSteven Whitehouse ipa = list_entry(a, struct gfs2_inode, i_ordered); 490*45138990SSteven Whitehouse ipb = list_entry(b, struct gfs2_inode, i_ordered); 4914a36d08dSBob Peterson 492*45138990SSteven Whitehouse if (ipa->i_no_addr < ipb->i_no_addr) 4934a36d08dSBob Peterson return -1; 494*45138990SSteven Whitehouse if (ipa->i_no_addr > ipb->i_no_addr) 4954a36d08dSBob Peterson return 1; 4964a36d08dSBob Peterson return 0; 4974a36d08dSBob Peterson } 4984a36d08dSBob Peterson 499d7b616e2SSteven Whitehouse static void gfs2_ordered_write(struct gfs2_sbd *sdp) 500d7b616e2SSteven Whitehouse { 501*45138990SSteven Whitehouse struct gfs2_inode *ip; 502d7b616e2SSteven Whitehouse LIST_HEAD(written); 503d7b616e2SSteven Whitehouse 504*45138990SSteven Whitehouse spin_lock(&sdp->sd_ordered_lock); 505*45138990SSteven Whitehouse list_sort(NULL, &sdp->sd_log_le_ordered, &ip_cmp); 506d7b616e2SSteven Whitehouse while (!list_empty(&sdp->sd_log_le_ordered)) { 507*45138990SSteven Whitehouse ip = list_entry(sdp->sd_log_le_ordered.next, struct gfs2_inode, i_ordered); 508*45138990SSteven Whitehouse list_move(&ip->i_ordered, &written); 509*45138990SSteven Whitehouse if (ip->i_inode.i_mapping->nrpages == 0) 510d7b616e2SSteven Whitehouse continue; 511*45138990SSteven Whitehouse spin_unlock(&sdp->sd_ordered_lock); 512*45138990SSteven Whitehouse filemap_fdatawrite(ip->i_inode.i_mapping); 513*45138990SSteven Whitehouse spin_lock(&sdp->sd_ordered_lock); 514d7b616e2SSteven Whitehouse } 515d7b616e2SSteven Whitehouse list_splice(&written, &sdp->sd_log_le_ordered); 516*45138990SSteven Whitehouse spin_unlock(&sdp->sd_ordered_lock); 517d7b616e2SSteven Whitehouse } 518d7b616e2SSteven Whitehouse 519d7b616e2SSteven Whitehouse static void gfs2_ordered_wait(struct gfs2_sbd *sdp) 520d7b616e2SSteven Whitehouse { 521*45138990SSteven Whitehouse struct gfs2_inode *ip; 522d7b616e2SSteven Whitehouse 523*45138990SSteven Whitehouse spin_lock(&sdp->sd_ordered_lock); 524d7b616e2SSteven Whitehouse while (!list_empty(&sdp->sd_log_le_ordered)) { 525*45138990SSteven Whitehouse ip = list_entry(sdp->sd_log_le_ordered.next, struct gfs2_inode, i_ordered); 526*45138990SSteven Whitehouse list_del(&ip->i_ordered); 527*45138990SSteven Whitehouse WARN_ON(!test_and_clear_bit(GIF_ORDERED, &ip->i_flags)); 528*45138990SSteven Whitehouse if (ip->i_inode.i_mapping->nrpages == 0) 529d7b616e2SSteven Whitehouse continue; 530*45138990SSteven Whitehouse spin_unlock(&sdp->sd_ordered_lock); 531*45138990SSteven Whitehouse filemap_fdatawait(ip->i_inode.i_mapping); 532*45138990SSteven Whitehouse spin_lock(&sdp->sd_ordered_lock); 533d7b616e2SSteven Whitehouse } 534*45138990SSteven Whitehouse spin_unlock(&sdp->sd_ordered_lock); 535d7b616e2SSteven Whitehouse } 536*45138990SSteven Whitehouse 537*45138990SSteven Whitehouse void gfs2_ordered_del_inode(struct gfs2_inode *ip) 538*45138990SSteven Whitehouse { 539*45138990SSteven Whitehouse struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 540*45138990SSteven Whitehouse 541*45138990SSteven Whitehouse spin_lock(&sdp->sd_ordered_lock); 542*45138990SSteven Whitehouse if (test_and_clear_bit(GIF_ORDERED, &ip->i_flags)) 543*45138990SSteven Whitehouse list_del(&ip->i_ordered); 544*45138990SSteven Whitehouse spin_unlock(&sdp->sd_ordered_lock); 545d7b616e2SSteven Whitehouse } 546d7b616e2SSteven Whitehouse 547b3b94faaSDavid Teigland /** 54834cc1781SSteven Whitehouse * log_write_header - Get and initialize a journal header buffer 54934cc1781SSteven Whitehouse * @sdp: The GFS2 superblock 55034cc1781SSteven Whitehouse * 55134cc1781SSteven Whitehouse * Returns: the initialized log buffer descriptor 55234cc1781SSteven Whitehouse */ 55334cc1781SSteven Whitehouse 554fdb76a42SSteven Whitehouse static void log_write_header(struct gfs2_sbd *sdp, u32 flags) 55534cc1781SSteven Whitehouse { 55634cc1781SSteven Whitehouse struct gfs2_log_header *lh; 55734cc1781SSteven Whitehouse unsigned int tail; 55834cc1781SSteven Whitehouse u32 hash; 559e8c92ed7SSteven Whitehouse int rw = WRITE_FLUSH_FUA | REQ_META; 560e8c92ed7SSteven Whitehouse struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO); 561e8c92ed7SSteven Whitehouse lh = page_address(page); 562e8c92ed7SSteven Whitehouse clear_page(lh); 56334cc1781SSteven Whitehouse 56434cc1781SSteven Whitehouse gfs2_ail1_empty(sdp); 56534cc1781SSteven Whitehouse tail = current_tail(sdp); 56634cc1781SSteven Whitehouse 56734cc1781SSteven Whitehouse lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC); 56834cc1781SSteven Whitehouse lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH); 56934cc1781SSteven Whitehouse lh->lh_header.__pad0 = cpu_to_be64(0); 57034cc1781SSteven Whitehouse lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH); 57134cc1781SSteven Whitehouse lh->lh_header.mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid); 57234cc1781SSteven Whitehouse lh->lh_sequence = cpu_to_be64(sdp->sd_log_sequence++); 57334cc1781SSteven Whitehouse lh->lh_flags = cpu_to_be32(flags); 57434cc1781SSteven Whitehouse lh->lh_tail = cpu_to_be32(tail); 57534cc1781SSteven Whitehouse lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head); 576e8c92ed7SSteven Whitehouse hash = gfs2_disk_hash(page_address(page), sizeof(struct gfs2_log_header)); 57734cc1781SSteven Whitehouse lh->lh_hash = cpu_to_be32(hash); 57834cc1781SSteven Whitehouse 57934cc1781SSteven Whitehouse if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) { 58034cc1781SSteven Whitehouse gfs2_ordered_wait(sdp); 58134cc1781SSteven Whitehouse log_flush_wait(sdp); 582e8c92ed7SSteven Whitehouse rw = WRITE_SYNC | REQ_META | REQ_PRIO; 58334cc1781SSteven Whitehouse } 58434cc1781SSteven Whitehouse 585e8c92ed7SSteven Whitehouse sdp->sd_log_idle = (tail == sdp->sd_log_flush_head); 586e8c92ed7SSteven Whitehouse gfs2_log_write_page(sdp, page); 587e8c92ed7SSteven Whitehouse gfs2_log_flush_bio(sdp, rw); 588e8c92ed7SSteven Whitehouse log_flush_wait(sdp); 58934cc1781SSteven Whitehouse 59034cc1781SSteven Whitehouse if (sdp->sd_log_tail != tail) 59134cc1781SSteven Whitehouse log_pull_tail(sdp, tail); 59234cc1781SSteven Whitehouse } 59334cc1781SSteven Whitehouse 59434cc1781SSteven Whitehouse /** 595b09e593dSSteven Whitehouse * gfs2_log_flush - flush incore transaction(s) 596b3b94faaSDavid Teigland * @sdp: the filesystem 597b3b94faaSDavid Teigland * @gl: The glock structure to flush. If NULL, flush the whole incore log 598b3b94faaSDavid Teigland * 599b3b94faaSDavid Teigland */ 600b3b94faaSDavid Teigland 601ed4878e8SBob Peterson void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) 602b3b94faaSDavid Teigland { 603b3b94faaSDavid Teigland struct gfs2_ail *ai; 604b3b94faaSDavid Teigland 605484adff8SSteven Whitehouse down_write(&sdp->sd_log_flush_lock); 606f55ab26aSSteven Whitehouse 6072bcd610dSSteven Whitehouse /* Log might have been flushed while we waited for the flush lock */ 6082bcd610dSSteven Whitehouse if (gl && !test_bit(GLF_LFLUSH, &gl->gl_flags)) { 609484adff8SSteven Whitehouse up_write(&sdp->sd_log_flush_lock); 610f55ab26aSSteven Whitehouse return; 611f55ab26aSSteven Whitehouse } 61263997775SSteven Whitehouse trace_gfs2_log_flush(sdp, 1); 613f55ab26aSSteven Whitehouse 614b09e593dSSteven Whitehouse ai = kzalloc(sizeof(struct gfs2_ail), GFP_NOFS | __GFP_NOFAIL); 615b09e593dSSteven Whitehouse INIT_LIST_HEAD(&ai->ai_ail1_list); 616b09e593dSSteven Whitehouse INIT_LIST_HEAD(&ai->ai_ail2_list); 617b3b94faaSDavid Teigland 61816615be1SSteven Whitehouse if (sdp->sd_log_num_buf != sdp->sd_log_commited_buf) { 61916615be1SSteven Whitehouse printk(KERN_INFO "GFS2: log buf %u %u\n", sdp->sd_log_num_buf, 62016615be1SSteven Whitehouse sdp->sd_log_commited_buf); 62116615be1SSteven Whitehouse gfs2_assert_withdraw(sdp, 0); 62216615be1SSteven Whitehouse } 62316615be1SSteven Whitehouse if (sdp->sd_log_num_databuf != sdp->sd_log_commited_databuf) { 62416615be1SSteven Whitehouse printk(KERN_INFO "GFS2: log databuf %u %u\n", 62516615be1SSteven Whitehouse sdp->sd_log_num_databuf, sdp->sd_log_commited_databuf); 62616615be1SSteven Whitehouse gfs2_assert_withdraw(sdp, 0); 62716615be1SSteven Whitehouse } 628b3b94faaSDavid Teigland gfs2_assert_withdraw(sdp, 629b3b94faaSDavid Teigland sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke); 630b3b94faaSDavid Teigland 631b3b94faaSDavid Teigland sdp->sd_log_flush_head = sdp->sd_log_head; 632b3b94faaSDavid Teigland sdp->sd_log_flush_wrapped = 0; 633b3b94faaSDavid Teigland ai->ai_first = sdp->sd_log_flush_head; 634b3b94faaSDavid Teigland 635d7b616e2SSteven Whitehouse gfs2_ordered_write(sdp); 636b3b94faaSDavid Teigland lops_before_commit(sdp); 637e8c92ed7SSteven Whitehouse gfs2_log_flush_bio(sdp, WRITE); 638d7b616e2SSteven Whitehouse 63934cc1781SSteven Whitehouse if (sdp->sd_log_head != sdp->sd_log_flush_head) { 640fdb76a42SSteven Whitehouse log_write_header(sdp, 0); 64134cc1781SSteven Whitehouse } else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){ 642fd041f0bSSteven Whitehouse atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */ 64363997775SSteven Whitehouse trace_gfs2_log_blocks(sdp, -1); 644fdb76a42SSteven Whitehouse log_write_header(sdp, 0); 6452332c443SRobert Peterson } 646b3b94faaSDavid Teigland lops_after_commit(sdp, ai); 647fe1a698fSSteven Whitehouse 648fe1a698fSSteven Whitehouse gfs2_log_lock(sdp); 649b3b94faaSDavid Teigland sdp->sd_log_head = sdp->sd_log_flush_head; 650faa31ce8SSteven Whitehouse sdp->sd_log_blks_reserved = 0; 651faa31ce8SSteven Whitehouse sdp->sd_log_commited_buf = 0; 6522332c443SRobert Peterson sdp->sd_log_commited_databuf = 0; 653b3b94faaSDavid Teigland sdp->sd_log_commited_revoke = 0; 654b3b94faaSDavid Teigland 655d6a079e8SDave Chinner spin_lock(&sdp->sd_ail_lock); 656b3b94faaSDavid Teigland if (!list_empty(&ai->ai_ail1_list)) { 657b3b94faaSDavid Teigland list_add(&ai->ai_list, &sdp->sd_ail1_list); 658b3b94faaSDavid Teigland ai = NULL; 659b3b94faaSDavid Teigland } 660d6a079e8SDave Chinner spin_unlock(&sdp->sd_ail_lock); 661b3b94faaSDavid Teigland gfs2_log_unlock(sdp); 66263997775SSteven Whitehouse trace_gfs2_log_flush(sdp, 0); 663484adff8SSteven Whitehouse up_write(&sdp->sd_log_flush_lock); 664b3b94faaSDavid Teigland 665b3b94faaSDavid Teigland kfree(ai); 666b3b94faaSDavid Teigland } 667b3b94faaSDavid Teigland 668b3b94faaSDavid Teigland static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) 669b3b94faaSDavid Teigland { 6702332c443SRobert Peterson unsigned int reserved; 671ac39aaddSSteven Whitehouse unsigned int unused; 672b3b94faaSDavid Teigland 673b3b94faaSDavid Teigland gfs2_log_lock(sdp); 674b3b94faaSDavid Teigland 675b3b94faaSDavid Teigland sdp->sd_log_commited_buf += tr->tr_num_buf_new - tr->tr_num_buf_rm; 6762332c443SRobert Peterson sdp->sd_log_commited_databuf += tr->tr_num_databuf_new - 6772332c443SRobert Peterson tr->tr_num_databuf_rm; 6782332c443SRobert Peterson gfs2_assert_withdraw(sdp, (((int)sdp->sd_log_commited_buf) >= 0) || 6792332c443SRobert Peterson (((int)sdp->sd_log_commited_databuf) >= 0)); 680b3b94faaSDavid Teigland sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm; 6812332c443SRobert Peterson reserved = calc_reserved(sdp); 68262be1f71SRoel Kluin gfs2_assert_withdraw(sdp, sdp->sd_log_blks_reserved + tr->tr_reserved >= reserved); 683ac39aaddSSteven Whitehouse unused = sdp->sd_log_blks_reserved - reserved + tr->tr_reserved; 684ac39aaddSSteven Whitehouse atomic_add(unused, &sdp->sd_log_blks_free); 68563997775SSteven Whitehouse trace_gfs2_log_blocks(sdp, unused); 686fd041f0bSSteven Whitehouse gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <= 6872332c443SRobert Peterson sdp->sd_jdesc->jd_blocks); 688b3b94faaSDavid Teigland sdp->sd_log_blks_reserved = reserved; 689b3b94faaSDavid Teigland 690b3b94faaSDavid Teigland gfs2_log_unlock(sdp); 691b3b94faaSDavid Teigland } 692b3b94faaSDavid Teigland 693b3b94faaSDavid Teigland /** 694b3b94faaSDavid Teigland * gfs2_log_commit - Commit a transaction to the log 695b3b94faaSDavid Teigland * @sdp: the filesystem 696b3b94faaSDavid Teigland * @tr: the transaction 697b3b94faaSDavid Teigland * 6985e687eacSBenjamin Marzinski * We wake up gfs2_logd if the number of pinned blocks exceed thresh1 6995e687eacSBenjamin Marzinski * or the total number of used blocks (pinned blocks plus AIL blocks) 7005e687eacSBenjamin Marzinski * is greater than thresh2. 7015e687eacSBenjamin Marzinski * 7025e687eacSBenjamin Marzinski * At mount time thresh1 is 1/3rd of journal size, thresh2 is 2/3rd of 7035e687eacSBenjamin Marzinski * journal size. 7045e687eacSBenjamin Marzinski * 705b3b94faaSDavid Teigland * Returns: errno 706b3b94faaSDavid Teigland */ 707b3b94faaSDavid Teigland 708b3b94faaSDavid Teigland void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) 709b3b94faaSDavid Teigland { 710b3b94faaSDavid Teigland log_refund(sdp, tr); 711484adff8SSteven Whitehouse up_read(&sdp->sd_log_flush_lock); 712b3b94faaSDavid Teigland 7135e687eacSBenjamin Marzinski if (atomic_read(&sdp->sd_log_pinned) > atomic_read(&sdp->sd_log_thresh1) || 7145e687eacSBenjamin Marzinski ((sdp->sd_jdesc->jd_blocks - atomic_read(&sdp->sd_log_blks_free)) > 7155e687eacSBenjamin Marzinski atomic_read(&sdp->sd_log_thresh2))) 7165e687eacSBenjamin Marzinski wake_up(&sdp->sd_logd_waitq); 717faa31ce8SSteven Whitehouse } 718b3b94faaSDavid Teigland 719b3b94faaSDavid Teigland /** 720b3b94faaSDavid Teigland * gfs2_log_shutdown - write a shutdown header into a journal 721b3b94faaSDavid Teigland * @sdp: the filesystem 722b3b94faaSDavid Teigland * 723b3b94faaSDavid Teigland */ 724b3b94faaSDavid Teigland 725b3b94faaSDavid Teigland void gfs2_log_shutdown(struct gfs2_sbd *sdp) 726b3b94faaSDavid Teigland { 727484adff8SSteven Whitehouse down_write(&sdp->sd_log_flush_lock); 728b3b94faaSDavid Teigland 729b3b94faaSDavid Teigland gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved); 730b3b94faaSDavid Teigland gfs2_assert_withdraw(sdp, !sdp->sd_log_num_buf); 731b3b94faaSDavid Teigland gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); 732b3b94faaSDavid Teigland gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg); 733b3b94faaSDavid Teigland gfs2_assert_withdraw(sdp, !sdp->sd_log_num_databuf); 734b3b94faaSDavid Teigland gfs2_assert_withdraw(sdp, list_empty(&sdp->sd_ail1_list)); 735b3b94faaSDavid Teigland 736b3b94faaSDavid Teigland sdp->sd_log_flush_head = sdp->sd_log_head; 737b3b94faaSDavid Teigland sdp->sd_log_flush_wrapped = 0; 738b3b94faaSDavid Teigland 739fdb76a42SSteven Whitehouse log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT); 740b3b94faaSDavid Teigland 741fd041f0bSSteven Whitehouse gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks); 742a74604beSSteven Whitehouse gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail); 743a74604beSSteven Whitehouse gfs2_assert_warn(sdp, list_empty(&sdp->sd_ail2_list)); 744b3b94faaSDavid Teigland 745b3b94faaSDavid Teigland sdp->sd_log_head = sdp->sd_log_flush_head; 746b3b94faaSDavid Teigland sdp->sd_log_tail = sdp->sd_log_head; 747b3b94faaSDavid Teigland 748484adff8SSteven Whitehouse up_write(&sdp->sd_log_flush_lock); 749b3b94faaSDavid Teigland } 750b3b94faaSDavid Teigland 751a25311c8SSteven Whitehouse 752a25311c8SSteven Whitehouse /** 753a25311c8SSteven Whitehouse * gfs2_meta_syncfs - sync all the buffers in a filesystem 754a25311c8SSteven Whitehouse * @sdp: the filesystem 755a25311c8SSteven Whitehouse * 756a25311c8SSteven Whitehouse */ 757a25311c8SSteven Whitehouse 758a25311c8SSteven Whitehouse void gfs2_meta_syncfs(struct gfs2_sbd *sdp) 759a25311c8SSteven Whitehouse { 760a25311c8SSteven Whitehouse gfs2_log_flush(sdp, NULL); 761a25311c8SSteven Whitehouse for (;;) { 7625e687eacSBenjamin Marzinski gfs2_ail1_start(sdp); 76326b06a69SSteven Whitehouse gfs2_ail1_wait(sdp); 7644667a0ecSSteven Whitehouse if (gfs2_ail1_empty(sdp)) 765a25311c8SSteven Whitehouse break; 766a25311c8SSteven Whitehouse } 767380f7c65SSteven Whitehouse gfs2_log_flush(sdp, NULL); 768a25311c8SSteven Whitehouse } 769a25311c8SSteven Whitehouse 7705e687eacSBenjamin Marzinski static inline int gfs2_jrnl_flush_reqd(struct gfs2_sbd *sdp) 7715e687eacSBenjamin Marzinski { 7725e687eacSBenjamin Marzinski return (atomic_read(&sdp->sd_log_pinned) >= atomic_read(&sdp->sd_log_thresh1)); 7735e687eacSBenjamin Marzinski } 7745e687eacSBenjamin Marzinski 7755e687eacSBenjamin Marzinski static inline int gfs2_ail_flush_reqd(struct gfs2_sbd *sdp) 7765e687eacSBenjamin Marzinski { 7775e687eacSBenjamin Marzinski unsigned int used_blocks = sdp->sd_jdesc->jd_blocks - atomic_read(&sdp->sd_log_blks_free); 7785e687eacSBenjamin Marzinski return used_blocks >= atomic_read(&sdp->sd_log_thresh2); 7795e687eacSBenjamin Marzinski } 780ec69b188SSteven Whitehouse 781ec69b188SSteven Whitehouse /** 782ec69b188SSteven Whitehouse * gfs2_logd - Update log tail as Active Items get flushed to in-place blocks 783ec69b188SSteven Whitehouse * @sdp: Pointer to GFS2 superblock 784ec69b188SSteven Whitehouse * 785ec69b188SSteven Whitehouse * Also, periodically check to make sure that we're using the most recent 786ec69b188SSteven Whitehouse * journal index. 787ec69b188SSteven Whitehouse */ 788ec69b188SSteven Whitehouse 789ec69b188SSteven Whitehouse int gfs2_logd(void *data) 790ec69b188SSteven Whitehouse { 791ec69b188SSteven Whitehouse struct gfs2_sbd *sdp = data; 7925e687eacSBenjamin Marzinski unsigned long t = 1; 7935e687eacSBenjamin Marzinski DEFINE_WAIT(wait); 794ec69b188SSteven Whitehouse 795ec69b188SSteven Whitehouse while (!kthread_should_stop()) { 796ec69b188SSteven Whitehouse 7975e687eacSBenjamin Marzinski if (gfs2_jrnl_flush_reqd(sdp) || t == 0) { 7984667a0ecSSteven Whitehouse gfs2_ail1_empty(sdp); 799ec69b188SSteven Whitehouse gfs2_log_flush(sdp, NULL); 800ec69b188SSteven Whitehouse } 801ec69b188SSteven Whitehouse 8025e687eacSBenjamin Marzinski if (gfs2_ail_flush_reqd(sdp)) { 8035e687eacSBenjamin Marzinski gfs2_ail1_start(sdp); 80426b06a69SSteven Whitehouse gfs2_ail1_wait(sdp); 8054667a0ecSSteven Whitehouse gfs2_ail1_empty(sdp); 8065e687eacSBenjamin Marzinski gfs2_log_flush(sdp, NULL); 8075e687eacSBenjamin Marzinski } 8085e687eacSBenjamin Marzinski 80926b06a69SSteven Whitehouse if (!gfs2_ail_flush_reqd(sdp)) 8105e687eacSBenjamin Marzinski wake_up(&sdp->sd_log_waitq); 81126b06a69SSteven Whitehouse 812ec69b188SSteven Whitehouse t = gfs2_tune_get(sdp, gt_logd_secs) * HZ; 813a0acae0eSTejun Heo 814a0acae0eSTejun Heo try_to_freeze(); 8155e687eacSBenjamin Marzinski 8165e687eacSBenjamin Marzinski do { 8175e687eacSBenjamin Marzinski prepare_to_wait(&sdp->sd_logd_waitq, &wait, 8185f487490SSteven Whitehouse TASK_INTERRUPTIBLE); 8195e687eacSBenjamin Marzinski if (!gfs2_ail_flush_reqd(sdp) && 8205e687eacSBenjamin Marzinski !gfs2_jrnl_flush_reqd(sdp) && 8215e687eacSBenjamin Marzinski !kthread_should_stop()) 8225e687eacSBenjamin Marzinski t = schedule_timeout(t); 8235e687eacSBenjamin Marzinski } while(t && !gfs2_ail_flush_reqd(sdp) && 8245e687eacSBenjamin Marzinski !gfs2_jrnl_flush_reqd(sdp) && 8255e687eacSBenjamin Marzinski !kthread_should_stop()); 8265e687eacSBenjamin Marzinski finish_wait(&sdp->sd_logd_waitq, &wait); 827ec69b188SSteven Whitehouse } 828ec69b188SSteven Whitehouse 829ec69b188SSteven Whitehouse return 0; 830ec69b188SSteven Whitehouse } 831ec69b188SSteven Whitehouse 832