17336d0e6SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2b3b94faaSDavid Teigland /*
3b3b94faaSDavid Teigland * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
4fe6c991cSBob Peterson * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
5b3b94faaSDavid Teigland */
6b3b94faaSDavid Teigland
7d77d1b58SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8d77d1b58SJoe Perches
9b3b94faaSDavid Teigland #include <linux/slab.h>
10b3b94faaSDavid Teigland #include <linux/spinlock.h>
11b3b94faaSDavid Teigland #include <linux/completion.h>
12b3b94faaSDavid Teigland #include <linux/buffer_head.h>
13f42faf4fSSteven Whitehouse #include <linux/fs.h>
145c676f6dSSteven Whitehouse #include <linux/gfs2_ondisk.h>
151f466a47SBob Peterson #include <linux/prefetch.h>
16f15ab561SSteven Whitehouse #include <linux/blkdev.h>
177c9ca621SBob Peterson #include <linux/rbtree.h>
189dbe9610SSteven Whitehouse #include <linux/random.h>
19b3b94faaSDavid Teigland
20b3b94faaSDavid Teigland #include "gfs2.h"
215c676f6dSSteven Whitehouse #include "incore.h"
22b3b94faaSDavid Teigland #include "glock.h"
23b3b94faaSDavid Teigland #include "glops.h"
24b3b94faaSDavid Teigland #include "lops.h"
25b3b94faaSDavid Teigland #include "meta_io.h"
26b3b94faaSDavid Teigland #include "quota.h"
27b3b94faaSDavid Teigland #include "rgrp.h"
28b3b94faaSDavid Teigland #include "super.h"
29b3b94faaSDavid Teigland #include "trans.h"
305c676f6dSSteven Whitehouse #include "util.h"
31172e045aSBenjamin Marzinski #include "log.h"
32c8cdf479SSteven Whitehouse #include "inode.h"
3363997775SSteven Whitehouse #include "trace_gfs2.h"
34850d2d91SAndrew Price #include "dir.h"
35b3b94faaSDavid Teigland
362c1e52aaSSteven Whitehouse #define BFITNOENT ((u32)~0)
376760bdcdSBob Peterson #define NO_BLOCK ((u64)~0)
3888c8ab1fSSteven Whitehouse
39c65b76b8SAndreas Gruenbacher struct gfs2_rbm {
40c65b76b8SAndreas Gruenbacher struct gfs2_rgrpd *rgd;
41c65b76b8SAndreas Gruenbacher u32 offset; /* The offset is bitmap relative */
42c65b76b8SAndreas Gruenbacher int bii; /* Bitmap index */
43c65b76b8SAndreas Gruenbacher };
44c65b76b8SAndreas Gruenbacher
rbm_bi(const struct gfs2_rbm * rbm)45c65b76b8SAndreas Gruenbacher static inline struct gfs2_bitmap *rbm_bi(const struct gfs2_rbm *rbm)
46c65b76b8SAndreas Gruenbacher {
47c65b76b8SAndreas Gruenbacher return rbm->rgd->rd_bits + rbm->bii;
48c65b76b8SAndreas Gruenbacher }
49c65b76b8SAndreas Gruenbacher
gfs2_rbm_to_block(const struct gfs2_rbm * rbm)50c65b76b8SAndreas Gruenbacher static inline u64 gfs2_rbm_to_block(const struct gfs2_rbm *rbm)
51c65b76b8SAndreas Gruenbacher {
52c65b76b8SAndreas Gruenbacher BUG_ON(rbm->offset >= rbm->rgd->rd_data);
53c65b76b8SAndreas Gruenbacher return rbm->rgd->rd_data0 + (rbm_bi(rbm)->bi_start * GFS2_NBBY) +
54c65b76b8SAndreas Gruenbacher rbm->offset;
55c65b76b8SAndreas Gruenbacher }
56c65b76b8SAndreas Gruenbacher
5788c8ab1fSSteven Whitehouse /*
5888c8ab1fSSteven Whitehouse * These routines are used by the resource group routines (rgrp.c)
5988c8ab1fSSteven Whitehouse * to keep track of block allocation. Each block is represented by two
60feaa7bbaSSteven Whitehouse * bits. So, each byte represents GFS2_NBBY (i.e. 4) blocks.
61feaa7bbaSSteven Whitehouse *
62feaa7bbaSSteven Whitehouse * 0 = Free
63feaa7bbaSSteven Whitehouse * 1 = Used (not metadata)
64feaa7bbaSSteven Whitehouse * 2 = Unlinked (still in use) inode
65feaa7bbaSSteven Whitehouse * 3 = Used (metadata)
6688c8ab1fSSteven Whitehouse */
6788c8ab1fSSteven Whitehouse
685ce13431SBob Peterson struct gfs2_extent {
695ce13431SBob Peterson struct gfs2_rbm rbm;
705ce13431SBob Peterson u32 len;
715ce13431SBob Peterson };
725ce13431SBob Peterson
7388c8ab1fSSteven Whitehouse static const char valid_change[16] = {
7488c8ab1fSSteven Whitehouse /* current */
75feaa7bbaSSteven Whitehouse /* n */ 0, 1, 1, 1,
7688c8ab1fSSteven Whitehouse /* e */ 1, 0, 0, 0,
77feaa7bbaSSteven Whitehouse /* w */ 0, 0, 0, 1,
7888c8ab1fSSteven Whitehouse 1, 0, 0, 0
7988c8ab1fSSteven Whitehouse };
8088c8ab1fSSteven Whitehouse
815ce13431SBob Peterson static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext,
823d39fcd1SAndreas Gruenbacher struct gfs2_blkreserv *rs, bool nowrap);
83ff7f4cb4SSteven Whitehouse
84ff7f4cb4SSteven Whitehouse
8588c8ab1fSSteven Whitehouse /**
8688c8ab1fSSteven Whitehouse * gfs2_setbit - Set a bit in the bitmaps
873e6339ddSSteven Whitehouse * @rbm: The position of the bit to set
883e6339ddSSteven Whitehouse * @do_clone: Also set the clone bitmap, if it exists
8988c8ab1fSSteven Whitehouse * @new_state: the new state of the block
9088c8ab1fSSteven Whitehouse *
9188c8ab1fSSteven Whitehouse */
9288c8ab1fSSteven Whitehouse
gfs2_setbit(const struct gfs2_rbm * rbm,bool do_clone,unsigned char new_state)933e6339ddSSteven Whitehouse static inline void gfs2_setbit(const struct gfs2_rbm *rbm, bool do_clone,
9406344b91SBob Peterson unsigned char new_state)
9588c8ab1fSSteven Whitehouse {
96b45e41d7SSteven Whitehouse unsigned char *byte1, *byte2, *end, cur_state;
97e579ed4fSBob Peterson struct gfs2_bitmap *bi = rbm_bi(rbm);
98281b4952SAndreas Gruenbacher unsigned int buflen = bi->bi_bytes;
993e6339ddSSteven Whitehouse const unsigned int bit = (rbm->offset % GFS2_NBBY) * GFS2_BIT_SIZE;
10088c8ab1fSSteven Whitehouse
101e579ed4fSBob Peterson byte1 = bi->bi_bh->b_data + bi->bi_offset + (rbm->offset / GFS2_NBBY);
102e579ed4fSBob Peterson end = bi->bi_bh->b_data + bi->bi_offset + buflen;
10388c8ab1fSSteven Whitehouse
104b45e41d7SSteven Whitehouse BUG_ON(byte1 >= end);
10588c8ab1fSSteven Whitehouse
106b45e41d7SSteven Whitehouse cur_state = (*byte1 >> bit) & GFS2_BIT_MASK;
10788c8ab1fSSteven Whitehouse
108b45e41d7SSteven Whitehouse if (unlikely(!valid_change[new_state * 4 + cur_state])) {
109e54c78a2SBob Peterson struct gfs2_sbd *sdp = rbm->rgd->rd_sbd;
110e54c78a2SBob Peterson
111e54c78a2SBob Peterson fs_warn(sdp, "buf_blk = 0x%x old_state=%d, new_state=%d\n",
112d77d1b58SJoe Perches rbm->offset, cur_state, new_state);
113e54c78a2SBob Peterson fs_warn(sdp, "rgrp=0x%llx bi_start=0x%x biblk: 0x%llx\n",
114e54c78a2SBob Peterson (unsigned long long)rbm->rgd->rd_addr, bi->bi_start,
115e54c78a2SBob Peterson (unsigned long long)bi->bi_bh->b_blocknr);
116281b4952SAndreas Gruenbacher fs_warn(sdp, "bi_offset=0x%x bi_bytes=0x%x block=0x%llx\n",
117281b4952SAndreas Gruenbacher bi->bi_offset, bi->bi_bytes,
118e54c78a2SBob Peterson (unsigned long long)gfs2_rbm_to_block(rbm));
11995c8e17fSBob Peterson dump_stack();
1203e6339ddSSteven Whitehouse gfs2_consist_rgrpd(rbm->rgd);
121b45e41d7SSteven Whitehouse return;
122b45e41d7SSteven Whitehouse }
123b45e41d7SSteven Whitehouse *byte1 ^= (cur_state ^ new_state) << bit;
124b45e41d7SSteven Whitehouse
125e579ed4fSBob Peterson if (do_clone && bi->bi_clone) {
126e579ed4fSBob Peterson byte2 = bi->bi_clone + bi->bi_offset + (rbm->offset / GFS2_NBBY);
127b45e41d7SSteven Whitehouse cur_state = (*byte2 >> bit) & GFS2_BIT_MASK;
128b45e41d7SSteven Whitehouse *byte2 ^= (cur_state ^ new_state) << bit;
129b45e41d7SSteven Whitehouse }
13088c8ab1fSSteven Whitehouse }
13188c8ab1fSSteven Whitehouse
13288c8ab1fSSteven Whitehouse /**
13388c8ab1fSSteven Whitehouse * gfs2_testbit - test a bit in the bitmaps
134c04a2ef3SSteven Whitehouse * @rbm: The bit to test
135dffe12a8SBob Peterson * @use_clone: If true, test the clone bitmap, not the official bitmap.
136dffe12a8SBob Peterson *
137dffe12a8SBob Peterson * Some callers like gfs2_unaligned_extlen need to test the clone bitmaps,
138dffe12a8SBob Peterson * not the "real" bitmaps, to avoid allocating recently freed blocks.
13988c8ab1fSSteven Whitehouse *
140c04a2ef3SSteven Whitehouse * Returns: The two bit block state of the requested bit
14188c8ab1fSSteven Whitehouse */
14288c8ab1fSSteven Whitehouse
gfs2_testbit(const struct gfs2_rbm * rbm,bool use_clone)143dffe12a8SBob Peterson static inline u8 gfs2_testbit(const struct gfs2_rbm *rbm, bool use_clone)
14488c8ab1fSSteven Whitehouse {
145e579ed4fSBob Peterson struct gfs2_bitmap *bi = rbm_bi(rbm);
146dffe12a8SBob Peterson const u8 *buffer;
147c04a2ef3SSteven Whitehouse const u8 *byte;
14888c8ab1fSSteven Whitehouse unsigned int bit;
14988c8ab1fSSteven Whitehouse
150dffe12a8SBob Peterson if (use_clone && bi->bi_clone)
151dffe12a8SBob Peterson buffer = bi->bi_clone;
152dffe12a8SBob Peterson else
153dffe12a8SBob Peterson buffer = bi->bi_bh->b_data;
154dffe12a8SBob Peterson buffer += bi->bi_offset;
155c04a2ef3SSteven Whitehouse byte = buffer + (rbm->offset / GFS2_NBBY);
156c04a2ef3SSteven Whitehouse bit = (rbm->offset % GFS2_NBBY) * GFS2_BIT_SIZE;
15788c8ab1fSSteven Whitehouse
158c04a2ef3SSteven Whitehouse return (*byte >> bit) & GFS2_BIT_MASK;
15988c8ab1fSSteven Whitehouse }
16088c8ab1fSSteven Whitehouse
16188c8ab1fSSteven Whitehouse /**
162223b2b88SSteven Whitehouse * gfs2_bit_search
163223b2b88SSteven Whitehouse * @ptr: Pointer to bitmap data
164223b2b88SSteven Whitehouse * @mask: Mask to use (normally 0x55555.... but adjusted for search start)
165223b2b88SSteven Whitehouse * @state: The state we are searching for
166223b2b88SSteven Whitehouse *
167223b2b88SSteven Whitehouse * We xor the bitmap data with a patter which is the bitwise opposite
168223b2b88SSteven Whitehouse * of what we are looking for, this gives rise to a pattern of ones
169223b2b88SSteven Whitehouse * wherever there is a match. Since we have two bits per entry, we
170223b2b88SSteven Whitehouse * take this pattern, shift it down by one place and then and it with
171223b2b88SSteven Whitehouse * the original. All the even bit positions (0,2,4, etc) then represent
172223b2b88SSteven Whitehouse * successful matches, so we mask with 0x55555..... to remove the unwanted
173223b2b88SSteven Whitehouse * odd bit positions.
174223b2b88SSteven Whitehouse *
175223b2b88SSteven Whitehouse * This allows searching of a whole u64 at once (32 blocks) with a
176223b2b88SSteven Whitehouse * single test (on 64 bit arches).
177223b2b88SSteven Whitehouse */
178223b2b88SSteven Whitehouse
gfs2_bit_search(const __le64 * ptr,u64 mask,u8 state)179223b2b88SSteven Whitehouse static inline u64 gfs2_bit_search(const __le64 *ptr, u64 mask, u8 state)
180223b2b88SSteven Whitehouse {
181223b2b88SSteven Whitehouse u64 tmp;
182223b2b88SSteven Whitehouse static const u64 search[] = {
183075ac448SHannes Eder [0] = 0xffffffffffffffffULL,
184075ac448SHannes Eder [1] = 0xaaaaaaaaaaaaaaaaULL,
185075ac448SHannes Eder [2] = 0x5555555555555555ULL,
186075ac448SHannes Eder [3] = 0x0000000000000000ULL,
187223b2b88SSteven Whitehouse };
188223b2b88SSteven Whitehouse tmp = le64_to_cpu(*ptr) ^ search[state];
189223b2b88SSteven Whitehouse tmp &= (tmp >> 1);
190223b2b88SSteven Whitehouse tmp &= mask;
191223b2b88SSteven Whitehouse return tmp;
192223b2b88SSteven Whitehouse }
193223b2b88SSteven Whitehouse
194223b2b88SSteven Whitehouse /**
1958e2e0047SBob Peterson * rs_cmp - multi-block reservation range compare
196c65b76b8SAndreas Gruenbacher * @start: start of the new reservation
1978e2e0047SBob Peterson * @len: number of blocks in the new reservation
1988e2e0047SBob Peterson * @rs: existing reservation to compare against
1998e2e0047SBob Peterson *
2008e2e0047SBob Peterson * returns: 1 if the block range is beyond the reach of the reservation
2018e2e0047SBob Peterson * -1 if the block range is before the start of the reservation
2028e2e0047SBob Peterson * 0 if the block range overlaps with the reservation
2038e2e0047SBob Peterson */
rs_cmp(u64 start,u32 len,struct gfs2_blkreserv * rs)204c65b76b8SAndreas Gruenbacher static inline int rs_cmp(u64 start, u32 len, struct gfs2_blkreserv *rs)
2058e2e0047SBob Peterson {
20607974d2aSAndreas Gruenbacher if (start >= rs->rs_start + rs->rs_requested)
2078e2e0047SBob Peterson return 1;
208c65b76b8SAndreas Gruenbacher if (rs->rs_start >= start + len)
2098e2e0047SBob Peterson return -1;
2108e2e0047SBob Peterson return 0;
2118e2e0047SBob Peterson }
2128e2e0047SBob Peterson
2138e2e0047SBob Peterson /**
21488c8ab1fSSteven Whitehouse * gfs2_bitfit - Search an rgrp's bitmap buffer to find a bit-pair representing
21588c8ab1fSSteven Whitehouse * a block in a given allocation state.
216886b1416SBob Peterson * @buf: the buffer that holds the bitmaps
217223b2b88SSteven Whitehouse * @len: the length (in bytes) of the buffer
21888c8ab1fSSteven Whitehouse * @goal: start search at this block's bit-pair (within @buffer)
219223b2b88SSteven Whitehouse * @state: GFS2_BLKST_XXX the state of the block we're looking for.
22088c8ab1fSSteven Whitehouse *
22188c8ab1fSSteven Whitehouse * Scope of @goal and returned block number is only within this bitmap buffer,
22288c8ab1fSSteven Whitehouse * not entire rgrp or filesystem. @buffer will be offset from the actual
223223b2b88SSteven Whitehouse * beginning of a bitmap block buffer, skipping any header structures, but
224223b2b88SSteven Whitehouse * headers are always a multiple of 64 bits long so that the buffer is
225223b2b88SSteven Whitehouse * always aligned to a 64 bit boundary.
226223b2b88SSteven Whitehouse *
227223b2b88SSteven Whitehouse * The size of the buffer is in bytes, but is it assumed that it is
228fd589a8fSAnand Gadiyar * always ok to read a complete multiple of 64 bits at the end
229223b2b88SSteven Whitehouse * of the block in case the end is no aligned to a natural boundary.
23088c8ab1fSSteven Whitehouse *
23188c8ab1fSSteven Whitehouse * Return: the block number (bitmap buffer scope) that was found
23288c8ab1fSSteven Whitehouse */
23388c8ab1fSSteven Whitehouse
gfs2_bitfit(const u8 * buf,const unsigned int len,u32 goal,u8 state)23402ab1721SHannes Eder static u32 gfs2_bitfit(const u8 *buf, const unsigned int len,
23502ab1721SHannes Eder u32 goal, u8 state)
23688c8ab1fSSteven Whitehouse {
237223b2b88SSteven Whitehouse u32 spoint = (goal << 1) & ((8*sizeof(u64)) - 1);
238223b2b88SSteven Whitehouse const __le64 *ptr = ((__le64 *)buf) + (goal >> 5);
239223b2b88SSteven Whitehouse const __le64 *end = (__le64 *)(buf + ALIGN(len, sizeof(u64)));
240223b2b88SSteven Whitehouse u64 tmp;
241075ac448SHannes Eder u64 mask = 0x5555555555555555ULL;
242223b2b88SSteven Whitehouse u32 bit;
24388c8ab1fSSteven Whitehouse
244223b2b88SSteven Whitehouse /* Mask off bits we don't care about at the start of the search */
245223b2b88SSteven Whitehouse mask <<= spoint;
246223b2b88SSteven Whitehouse tmp = gfs2_bit_search(ptr, mask, state);
247223b2b88SSteven Whitehouse ptr++;
248223b2b88SSteven Whitehouse while(tmp == 0 && ptr < end) {
249075ac448SHannes Eder tmp = gfs2_bit_search(ptr, 0x5555555555555555ULL, state);
250223b2b88SSteven Whitehouse ptr++;
2515fdc2eebSBob Peterson }
252223b2b88SSteven Whitehouse /* Mask off any bits which are more than len bytes from the start */
253223b2b88SSteven Whitehouse if (ptr == end && (len & (sizeof(u64) - 1)))
254223b2b88SSteven Whitehouse tmp &= (((u64)~0) >> (64 - 8*(len & (sizeof(u64) - 1))));
255223b2b88SSteven Whitehouse /* Didn't find anything, so return */
256223b2b88SSteven Whitehouse if (tmp == 0)
25788c8ab1fSSteven Whitehouse return BFITNOENT;
258223b2b88SSteven Whitehouse ptr--;
259d8bd504aSSteven Whitehouse bit = __ffs64(tmp);
260223b2b88SSteven Whitehouse bit /= 2; /* two bits per entry in the bitmap */
261223b2b88SSteven Whitehouse return (((const unsigned char *)ptr - buf) * GFS2_NBBY) + bit;
26288c8ab1fSSteven Whitehouse }
26388c8ab1fSSteven Whitehouse
26488c8ab1fSSteven Whitehouse /**
265ff7f4cb4SSteven Whitehouse * gfs2_rbm_from_block - Set the rbm based upon rgd and block number
266ff7f4cb4SSteven Whitehouse * @rbm: The rbm with rgd already set correctly
267ff7f4cb4SSteven Whitehouse * @block: The block number (filesystem relative)
268ff7f4cb4SSteven Whitehouse *
269ff7f4cb4SSteven Whitehouse * This sets the bi and offset members of an rbm based on a
270ff7f4cb4SSteven Whitehouse * resource group and a filesystem relative block number. The
271ff7f4cb4SSteven Whitehouse * resource group must be set in the rbm on entry, the bi and
272ff7f4cb4SSteven Whitehouse * offset members will be set by this function.
273ff7f4cb4SSteven Whitehouse *
274ff7f4cb4SSteven Whitehouse * Returns: 0 on success, or an error code
275ff7f4cb4SSteven Whitehouse */
276ff7f4cb4SSteven Whitehouse
gfs2_rbm_from_block(struct gfs2_rbm * rbm,u64 block)277ff7f4cb4SSteven Whitehouse static int gfs2_rbm_from_block(struct gfs2_rbm *rbm, u64 block)
278ff7f4cb4SSteven Whitehouse {
2793548fce1SAndreas Gruenbacher if (!rgrp_contains_block(rbm->rgd, block))
280ff7f4cb4SSteven Whitehouse return -E2BIG;
281e579ed4fSBob Peterson rbm->bii = 0;
2823548fce1SAndreas Gruenbacher rbm->offset = block - rbm->rgd->rd_data0;
283a68a0a35SBob Peterson /* Check if the block is within the first block */
284e579ed4fSBob Peterson if (rbm->offset < rbm_bi(rbm)->bi_blocks)
285a68a0a35SBob Peterson return 0;
286ff7f4cb4SSteven Whitehouse
287a68a0a35SBob Peterson /* Adjust for the size diff between gfs2_meta_header and gfs2_rgrp */
288a68a0a35SBob Peterson rbm->offset += (sizeof(struct gfs2_rgrp) -
289a68a0a35SBob Peterson sizeof(struct gfs2_meta_header)) * GFS2_NBBY;
290e579ed4fSBob Peterson rbm->bii = rbm->offset / rbm->rgd->rd_sbd->sd_blocks_per_bitmap;
291e579ed4fSBob Peterson rbm->offset -= rbm->bii * rbm->rgd->rd_sbd->sd_blocks_per_bitmap;
292ff7f4cb4SSteven Whitehouse return 0;
293ff7f4cb4SSteven Whitehouse }
294ff7f4cb4SSteven Whitehouse
295ff7f4cb4SSteven Whitehouse /**
2960eacdd16SAndreas Gruenbacher * gfs2_rbm_add - add a number of blocks to an rbm
297149ed7f5SBob Peterson * @rbm: The rbm with rgd already set correctly
2980eacdd16SAndreas Gruenbacher * @blocks: The number of blocks to add to rpm
299149ed7f5SBob Peterson *
3000eacdd16SAndreas Gruenbacher * This function takes an existing rbm structure and adds a number of blocks to
3010eacdd16SAndreas Gruenbacher * it.
302149ed7f5SBob Peterson *
3030eacdd16SAndreas Gruenbacher * Returns: True if the new rbm would point past the end of the rgrp.
304149ed7f5SBob Peterson */
305149ed7f5SBob Peterson
gfs2_rbm_add(struct gfs2_rbm * rbm,u32 blocks)3060eacdd16SAndreas Gruenbacher static bool gfs2_rbm_add(struct gfs2_rbm *rbm, u32 blocks)
307149ed7f5SBob Peterson {
3080eacdd16SAndreas Gruenbacher struct gfs2_rgrpd *rgd = rbm->rgd;
3090eacdd16SAndreas Gruenbacher struct gfs2_bitmap *bi = rgd->rd_bits + rbm->bii;
3100eacdd16SAndreas Gruenbacher
3110eacdd16SAndreas Gruenbacher if (rbm->offset + blocks < bi->bi_blocks) {
3120eacdd16SAndreas Gruenbacher rbm->offset += blocks;
313149ed7f5SBob Peterson return false;
314149ed7f5SBob Peterson }
3150eacdd16SAndreas Gruenbacher blocks -= bi->bi_blocks - rbm->offset;
316149ed7f5SBob Peterson
3170eacdd16SAndreas Gruenbacher for(;;) {
3180eacdd16SAndreas Gruenbacher bi++;
3190eacdd16SAndreas Gruenbacher if (bi == rgd->rd_bits + rgd->rd_length)
3200eacdd16SAndreas Gruenbacher return true;
3210eacdd16SAndreas Gruenbacher if (blocks < bi->bi_blocks) {
3220eacdd16SAndreas Gruenbacher rbm->offset = blocks;
3230eacdd16SAndreas Gruenbacher rbm->bii = bi - rgd->rd_bits;
324149ed7f5SBob Peterson return false;
325149ed7f5SBob Peterson }
3260eacdd16SAndreas Gruenbacher blocks -= bi->bi_blocks;
3270eacdd16SAndreas Gruenbacher }
3280eacdd16SAndreas Gruenbacher }
329149ed7f5SBob Peterson
330149ed7f5SBob Peterson /**
331ff7f4cb4SSteven Whitehouse * gfs2_unaligned_extlen - Look for free blocks which are not byte aligned
332ff7f4cb4SSteven Whitehouse * @rbm: Position to search (value/result)
333ff7f4cb4SSteven Whitehouse * @n_unaligned: Number of unaligned blocks to check
334ff7f4cb4SSteven Whitehouse * @len: Decremented for each block found (terminate on zero)
335ff7f4cb4SSteven Whitehouse *
336c65b76b8SAndreas Gruenbacher * Returns: true if a non-free block is encountered or the end of the resource
337c65b76b8SAndreas Gruenbacher * group is reached.
338ff7f4cb4SSteven Whitehouse */
339ff7f4cb4SSteven Whitehouse
gfs2_unaligned_extlen(struct gfs2_rbm * rbm,u32 n_unaligned,u32 * len)340ff7f4cb4SSteven Whitehouse static bool gfs2_unaligned_extlen(struct gfs2_rbm *rbm, u32 n_unaligned, u32 *len)
341ff7f4cb4SSteven Whitehouse {
342ff7f4cb4SSteven Whitehouse u32 n;
343ff7f4cb4SSteven Whitehouse u8 res;
344ff7f4cb4SSteven Whitehouse
345ff7f4cb4SSteven Whitehouse for (n = 0; n < n_unaligned; n++) {
346dffe12a8SBob Peterson res = gfs2_testbit(rbm, true);
347ff7f4cb4SSteven Whitehouse if (res != GFS2_BLKST_FREE)
348ff7f4cb4SSteven Whitehouse return true;
349ff7f4cb4SSteven Whitehouse (*len)--;
350ff7f4cb4SSteven Whitehouse if (*len == 0)
351ff7f4cb4SSteven Whitehouse return true;
3520eacdd16SAndreas Gruenbacher if (gfs2_rbm_add(rbm, 1))
353ff7f4cb4SSteven Whitehouse return true;
354ff7f4cb4SSteven Whitehouse }
355ff7f4cb4SSteven Whitehouse
356ff7f4cb4SSteven Whitehouse return false;
357ff7f4cb4SSteven Whitehouse }
358ff7f4cb4SSteven Whitehouse
359ff7f4cb4SSteven Whitehouse /**
360ff7f4cb4SSteven Whitehouse * gfs2_free_extlen - Return extent length of free blocks
36127ff6a0fSFabian Frederick * @rrbm: Starting position
362ff7f4cb4SSteven Whitehouse * @len: Max length to check
363ff7f4cb4SSteven Whitehouse *
364ff7f4cb4SSteven Whitehouse * Starting at the block specified by the rbm, see how many free blocks
365ff7f4cb4SSteven Whitehouse * there are, not reading more than len blocks ahead. This can be done
366ff7f4cb4SSteven Whitehouse * using memchr_inv when the blocks are byte aligned, but has to be done
367ff7f4cb4SSteven Whitehouse * on a block by block basis in case of unaligned blocks. Also this
368ff7f4cb4SSteven Whitehouse * function can cope with bitmap boundaries (although it must stop on
369ff7f4cb4SSteven Whitehouse * a resource group boundary)
370ff7f4cb4SSteven Whitehouse *
371ff7f4cb4SSteven Whitehouse * Returns: Number of free blocks in the extent
372ff7f4cb4SSteven Whitehouse */
373ff7f4cb4SSteven Whitehouse
gfs2_free_extlen(const struct gfs2_rbm * rrbm,u32 len)374ff7f4cb4SSteven Whitehouse static u32 gfs2_free_extlen(const struct gfs2_rbm *rrbm, u32 len)
375ff7f4cb4SSteven Whitehouse {
376ff7f4cb4SSteven Whitehouse struct gfs2_rbm rbm = *rrbm;
377ff7f4cb4SSteven Whitehouse u32 n_unaligned = rbm.offset & 3;
378ff7f4cb4SSteven Whitehouse u32 size = len;
379ff7f4cb4SSteven Whitehouse u32 bytes;
380ff7f4cb4SSteven Whitehouse u32 chunk_size;
381ff7f4cb4SSteven Whitehouse u8 *ptr, *start, *end;
382ff7f4cb4SSteven Whitehouse u64 block;
383e579ed4fSBob Peterson struct gfs2_bitmap *bi;
384ff7f4cb4SSteven Whitehouse
385ff7f4cb4SSteven Whitehouse if (n_unaligned &&
386ff7f4cb4SSteven Whitehouse gfs2_unaligned_extlen(&rbm, 4 - n_unaligned, &len))
387ff7f4cb4SSteven Whitehouse goto out;
388ff7f4cb4SSteven Whitehouse
3893701530aSBob Peterson n_unaligned = len & 3;
390ff7f4cb4SSteven Whitehouse /* Start is now byte aligned */
391ff7f4cb4SSteven Whitehouse while (len > 3) {
392e579ed4fSBob Peterson bi = rbm_bi(&rbm);
393e579ed4fSBob Peterson start = bi->bi_bh->b_data;
394e579ed4fSBob Peterson if (bi->bi_clone)
395e579ed4fSBob Peterson start = bi->bi_clone;
396e579ed4fSBob Peterson start += bi->bi_offset;
397281b4952SAndreas Gruenbacher end = start + bi->bi_bytes;
398ff7f4cb4SSteven Whitehouse BUG_ON(rbm.offset & 3);
399ff7f4cb4SSteven Whitehouse start += (rbm.offset / GFS2_NBBY);
400ff7f4cb4SSteven Whitehouse bytes = min_t(u32, len / GFS2_NBBY, (end - start));
401ff7f4cb4SSteven Whitehouse ptr = memchr_inv(start, 0, bytes);
402ff7f4cb4SSteven Whitehouse chunk_size = ((ptr == NULL) ? bytes : (ptr - start));
403ff7f4cb4SSteven Whitehouse chunk_size *= GFS2_NBBY;
404ff7f4cb4SSteven Whitehouse BUG_ON(len < chunk_size);
405ff7f4cb4SSteven Whitehouse len -= chunk_size;
406ff7f4cb4SSteven Whitehouse block = gfs2_rbm_to_block(&rbm);
40715bd50adSBob Peterson if (gfs2_rbm_from_block(&rbm, block + chunk_size)) {
40815bd50adSBob Peterson n_unaligned = 0;
409ff7f4cb4SSteven Whitehouse break;
41015bd50adSBob Peterson }
41115bd50adSBob Peterson if (ptr) {
41215bd50adSBob Peterson n_unaligned = 3;
41315bd50adSBob Peterson break;
41415bd50adSBob Peterson }
415ff7f4cb4SSteven Whitehouse n_unaligned = len & 3;
416ff7f4cb4SSteven Whitehouse }
417ff7f4cb4SSteven Whitehouse
418ff7f4cb4SSteven Whitehouse /* Deal with any bits left over at the end */
419ff7f4cb4SSteven Whitehouse if (n_unaligned)
420ff7f4cb4SSteven Whitehouse gfs2_unaligned_extlen(&rbm, n_unaligned, &len);
421ff7f4cb4SSteven Whitehouse out:
422ff7f4cb4SSteven Whitehouse return size - len;
423ff7f4cb4SSteven Whitehouse }
424ff7f4cb4SSteven Whitehouse
425ff7f4cb4SSteven Whitehouse /**
42688c8ab1fSSteven Whitehouse * gfs2_bitcount - count the number of bits in a certain state
427886b1416SBob Peterson * @rgd: the resource group descriptor
42888c8ab1fSSteven Whitehouse * @buffer: the buffer that holds the bitmaps
42988c8ab1fSSteven Whitehouse * @buflen: the length (in bytes) of the buffer
43088c8ab1fSSteven Whitehouse * @state: the state of the block we're looking for
43188c8ab1fSSteven Whitehouse *
43288c8ab1fSSteven Whitehouse * Returns: The number of bits
43388c8ab1fSSteven Whitehouse */
43488c8ab1fSSteven Whitehouse
gfs2_bitcount(struct gfs2_rgrpd * rgd,const u8 * buffer,unsigned int buflen,u8 state)435110acf38SSteven Whitehouse static u32 gfs2_bitcount(struct gfs2_rgrpd *rgd, const u8 *buffer,
436110acf38SSteven Whitehouse unsigned int buflen, u8 state)
43788c8ab1fSSteven Whitehouse {
438110acf38SSteven Whitehouse const u8 *byte = buffer;
439110acf38SSteven Whitehouse const u8 *end = buffer + buflen;
440110acf38SSteven Whitehouse const u8 state1 = state << 2;
441110acf38SSteven Whitehouse const u8 state2 = state << 4;
442110acf38SSteven Whitehouse const u8 state3 = state << 6;
443cd915493SSteven Whitehouse u32 count = 0;
44488c8ab1fSSteven Whitehouse
44588c8ab1fSSteven Whitehouse for (; byte < end; byte++) {
44688c8ab1fSSteven Whitehouse if (((*byte) & 0x03) == state)
44788c8ab1fSSteven Whitehouse count++;
44888c8ab1fSSteven Whitehouse if (((*byte) & 0x0C) == state1)
44988c8ab1fSSteven Whitehouse count++;
45088c8ab1fSSteven Whitehouse if (((*byte) & 0x30) == state2)
45188c8ab1fSSteven Whitehouse count++;
45288c8ab1fSSteven Whitehouse if (((*byte) & 0xC0) == state3)
45388c8ab1fSSteven Whitehouse count++;
45488c8ab1fSSteven Whitehouse }
45588c8ab1fSSteven Whitehouse
45688c8ab1fSSteven Whitehouse return count;
45788c8ab1fSSteven Whitehouse }
45888c8ab1fSSteven Whitehouse
459b3b94faaSDavid Teigland /**
460b3b94faaSDavid Teigland * gfs2_rgrp_verify - Verify that a resource group is consistent
461b3b94faaSDavid Teigland * @rgd: the rgrp
462b3b94faaSDavid Teigland *
463b3b94faaSDavid Teigland */
464b3b94faaSDavid Teigland
gfs2_rgrp_verify(struct gfs2_rgrpd * rgd)465b3b94faaSDavid Teigland void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd)
466b3b94faaSDavid Teigland {
467b3b94faaSDavid Teigland struct gfs2_sbd *sdp = rgd->rd_sbd;
468b3b94faaSDavid Teigland struct gfs2_bitmap *bi = NULL;
469bb8d8a6fSSteven Whitehouse u32 length = rgd->rd_length;
470cd915493SSteven Whitehouse u32 count[4], tmp;
471b3b94faaSDavid Teigland int buf, x;
472b3b94faaSDavid Teigland
473cd915493SSteven Whitehouse memset(count, 0, 4 * sizeof(u32));
474b3b94faaSDavid Teigland
475b3b94faaSDavid Teigland /* Count # blocks in each of 4 possible allocation states */
476b3b94faaSDavid Teigland for (buf = 0; buf < length; buf++) {
477b3b94faaSDavid Teigland bi = rgd->rd_bits + buf;
478b3b94faaSDavid Teigland for (x = 0; x < 4; x++)
479b3b94faaSDavid Teigland count[x] += gfs2_bitcount(rgd,
480b3b94faaSDavid Teigland bi->bi_bh->b_data +
481b3b94faaSDavid Teigland bi->bi_offset,
482281b4952SAndreas Gruenbacher bi->bi_bytes, x);
483b3b94faaSDavid Teigland }
484b3b94faaSDavid Teigland
485cfc8b549SSteven Whitehouse if (count[0] != rgd->rd_free) {
4868dc88ac6SAndreas Gruenbacher gfs2_lm(sdp, "free data mismatch: %u != %u\n",
487cfc8b549SSteven Whitehouse count[0], rgd->rd_free);
4888dc88ac6SAndreas Gruenbacher gfs2_consist_rgrpd(rgd);
489b3b94faaSDavid Teigland return;
490b3b94faaSDavid Teigland }
491b3b94faaSDavid Teigland
49273f74948SSteven Whitehouse tmp = rgd->rd_data - rgd->rd_free - rgd->rd_dinodes;
4936b946170SBenjamin Marzinski if (count[1] != tmp) {
4948dc88ac6SAndreas Gruenbacher gfs2_lm(sdp, "used data mismatch: %u != %u\n",
495b3b94faaSDavid Teigland count[1], tmp);
4968dc88ac6SAndreas Gruenbacher gfs2_consist_rgrpd(rgd);
497b3b94faaSDavid Teigland return;
498b3b94faaSDavid Teigland }
499b3b94faaSDavid Teigland
5006b946170SBenjamin Marzinski if (count[2] + count[3] != rgd->rd_dinodes) {
5018dc88ac6SAndreas Gruenbacher gfs2_lm(sdp, "used metadata mismatch: %u != %u\n",
5026b946170SBenjamin Marzinski count[2] + count[3], rgd->rd_dinodes);
5038dc88ac6SAndreas Gruenbacher gfs2_consist_rgrpd(rgd);
504b3b94faaSDavid Teigland return;
505b3b94faaSDavid Teigland }
506b3b94faaSDavid Teigland }
507b3b94faaSDavid Teigland
508b3b94faaSDavid Teigland /**
509b3b94faaSDavid Teigland * gfs2_blk2rgrpd - Find resource group for a given data/meta block number
510b3b94faaSDavid Teigland * @sdp: The GFS2 superblock
511886b1416SBob Peterson * @blk: The data block number
512886b1416SBob Peterson * @exact: True if this needs to be an exact match
513b3b94faaSDavid Teigland *
51490bcab99SSteven Whitehouse * The @exact argument should be set to true by most callers. The exception
51590bcab99SSteven Whitehouse * is when we need to match blocks which are not represented by the rgrp
51690bcab99SSteven Whitehouse * bitmap, but which are part of the rgrp (i.e. padding blocks) which are
51790bcab99SSteven Whitehouse * there for alignment purposes. Another way of looking at it is that @exact
51890bcab99SSteven Whitehouse * matches only valid data/metadata blocks, but with @exact false, it will
51990bcab99SSteven Whitehouse * match any block within the extent of the rgrp.
52090bcab99SSteven Whitehouse *
521b3b94faaSDavid Teigland * Returns: The resource group, or NULL if not found
522b3b94faaSDavid Teigland */
523b3b94faaSDavid Teigland
gfs2_blk2rgrpd(struct gfs2_sbd * sdp,u64 blk,bool exact)52466fc061bSSteven Whitehouse struct gfs2_rgrpd *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, u64 blk, bool exact)
525b3b94faaSDavid Teigland {
52666fc061bSSteven Whitehouse struct rb_node *n, *next;
527f75bbfb4SSteven Whitehouse struct gfs2_rgrpd *cur;
528b3b94faaSDavid Teigland
529b3b94faaSDavid Teigland spin_lock(&sdp->sd_rindex_spin);
53066fc061bSSteven Whitehouse n = sdp->sd_rindex_tree.rb_node;
53166fc061bSSteven Whitehouse while (n) {
53266fc061bSSteven Whitehouse cur = rb_entry(n, struct gfs2_rgrpd, rd_node);
53366fc061bSSteven Whitehouse next = NULL;
5347c9ca621SBob Peterson if (blk < cur->rd_addr)
53566fc061bSSteven Whitehouse next = n->rb_left;
536f75bbfb4SSteven Whitehouse else if (blk >= cur->rd_data0 + cur->rd_data)
53766fc061bSSteven Whitehouse next = n->rb_right;
53866fc061bSSteven Whitehouse if (next == NULL) {
539b3b94faaSDavid Teigland spin_unlock(&sdp->sd_rindex_spin);
54066fc061bSSteven Whitehouse if (exact) {
54166fc061bSSteven Whitehouse if (blk < cur->rd_addr)
54266fc061bSSteven Whitehouse return NULL;
54366fc061bSSteven Whitehouse if (blk >= cur->rd_data0 + cur->rd_data)
54466fc061bSSteven Whitehouse return NULL;
54566fc061bSSteven Whitehouse }
5467c9ca621SBob Peterson return cur;
547b3b94faaSDavid Teigland }
54866fc061bSSteven Whitehouse n = next;
549b3b94faaSDavid Teigland }
550b3b94faaSDavid Teigland spin_unlock(&sdp->sd_rindex_spin);
551b3b94faaSDavid Teigland
552b3b94faaSDavid Teigland return NULL;
553b3b94faaSDavid Teigland }
554b3b94faaSDavid Teigland
555b3b94faaSDavid Teigland /**
556b3b94faaSDavid Teigland * gfs2_rgrpd_get_first - get the first Resource Group in the filesystem
557b3b94faaSDavid Teigland * @sdp: The GFS2 superblock
558b3b94faaSDavid Teigland *
559b3b94faaSDavid Teigland * Returns: The first rgrp in the filesystem
560b3b94faaSDavid Teigland */
561b3b94faaSDavid Teigland
gfs2_rgrpd_get_first(struct gfs2_sbd * sdp)562b3b94faaSDavid Teigland struct gfs2_rgrpd *gfs2_rgrpd_get_first(struct gfs2_sbd *sdp)
563b3b94faaSDavid Teigland {
5647c9ca621SBob Peterson const struct rb_node *n;
5657c9ca621SBob Peterson struct gfs2_rgrpd *rgd;
5667c9ca621SBob Peterson
5678339ee54SSteven Whitehouse spin_lock(&sdp->sd_rindex_spin);
5687c9ca621SBob Peterson n = rb_first(&sdp->sd_rindex_tree);
5697c9ca621SBob Peterson rgd = rb_entry(n, struct gfs2_rgrpd, rd_node);
5708339ee54SSteven Whitehouse spin_unlock(&sdp->sd_rindex_spin);
5717c9ca621SBob Peterson
5727c9ca621SBob Peterson return rgd;
573b3b94faaSDavid Teigland }
574b3b94faaSDavid Teigland
575b3b94faaSDavid Teigland /**
576b3b94faaSDavid Teigland * gfs2_rgrpd_get_next - get the next RG
577886b1416SBob Peterson * @rgd: the resource group descriptor
578b3b94faaSDavid Teigland *
579b3b94faaSDavid Teigland * Returns: The next rgrp
580b3b94faaSDavid Teigland */
581b3b94faaSDavid Teigland
gfs2_rgrpd_get_next(struct gfs2_rgrpd * rgd)582b3b94faaSDavid Teigland struct gfs2_rgrpd *gfs2_rgrpd_get_next(struct gfs2_rgrpd *rgd)
583b3b94faaSDavid Teigland {
5847c9ca621SBob Peterson struct gfs2_sbd *sdp = rgd->rd_sbd;
5857c9ca621SBob Peterson const struct rb_node *n;
5867c9ca621SBob Peterson
5877c9ca621SBob Peterson spin_lock(&sdp->sd_rindex_spin);
5887c9ca621SBob Peterson n = rb_next(&rgd->rd_node);
5897c9ca621SBob Peterson if (n == NULL)
5907c9ca621SBob Peterson n = rb_first(&sdp->sd_rindex_tree);
5917c9ca621SBob Peterson
5927c9ca621SBob Peterson if (unlikely(&rgd->rd_node == n)) {
5937c9ca621SBob Peterson spin_unlock(&sdp->sd_rindex_spin);
594b3b94faaSDavid Teigland return NULL;
5957c9ca621SBob Peterson }
5967c9ca621SBob Peterson rgd = rb_entry(n, struct gfs2_rgrpd, rd_node);
5977c9ca621SBob Peterson spin_unlock(&sdp->sd_rindex_spin);
5987c9ca621SBob Peterson return rgd;
599b3b94faaSDavid Teigland }
600b3b94faaSDavid Teigland
check_and_update_goal(struct gfs2_inode * ip)60100a158beSAbhi Das void check_and_update_goal(struct gfs2_inode *ip)
60200a158beSAbhi Das {
60300a158beSAbhi Das struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
60400a158beSAbhi Das if (!ip->i_goal || gfs2_blk2rgrpd(sdp, ip->i_goal, 1) == NULL)
60500a158beSAbhi Das ip->i_goal = ip->i_no_addr;
60600a158beSAbhi Das }
60700a158beSAbhi Das
gfs2_free_clones(struct gfs2_rgrpd * rgd)6088339ee54SSteven Whitehouse void gfs2_free_clones(struct gfs2_rgrpd *rgd)
6098339ee54SSteven Whitehouse {
6108339ee54SSteven Whitehouse int x;
6118339ee54SSteven Whitehouse
6128339ee54SSteven Whitehouse for (x = 0; x < rgd->rd_length; x++) {
6138339ee54SSteven Whitehouse struct gfs2_bitmap *bi = rgd->rd_bits + x;
6148339ee54SSteven Whitehouse kfree(bi->bi_clone);
6158339ee54SSteven Whitehouse bi->bi_clone = NULL;
6168339ee54SSteven Whitehouse }
6178339ee54SSteven Whitehouse }
6188339ee54SSteven Whitehouse
dump_rs(struct seq_file * seq,const struct gfs2_blkreserv * rs,const char * fs_id_buf)6193792ce97SBob Peterson static void dump_rs(struct seq_file *seq, const struct gfs2_blkreserv *rs,
6203792ce97SBob Peterson const char *fs_id_buf)
6218e2e0047SBob Peterson {
622f85c10e2SBob Peterson struct gfs2_inode *ip = container_of(rs, struct gfs2_inode, i_res);
623f85c10e2SBob Peterson
624c65b76b8SAndreas Gruenbacher gfs2_print_dbg(seq, "%s B: n:%llu s:%llu f:%u\n",
625c65b76b8SAndreas Gruenbacher fs_id_buf,
626f85c10e2SBob Peterson (unsigned long long)ip->i_no_addr,
627c65b76b8SAndreas Gruenbacher (unsigned long long)rs->rs_start,
62807974d2aSAndreas Gruenbacher rs->rs_requested);
6298e2e0047SBob Peterson }
6308e2e0047SBob Peterson
6310a305e49SBob Peterson /**
6328e2e0047SBob Peterson * __rs_deltree - remove a multi-block reservation from the rgd tree
6338e2e0047SBob Peterson * @rs: The reservation to remove
6348e2e0047SBob Peterson *
6358e2e0047SBob Peterson */
__rs_deltree(struct gfs2_blkreserv * rs)63620095218SBob Peterson static void __rs_deltree(struct gfs2_blkreserv *rs)
6378e2e0047SBob Peterson {
6388e2e0047SBob Peterson struct gfs2_rgrpd *rgd;
6398e2e0047SBob Peterson
6408e2e0047SBob Peterson if (!gfs2_rs_active(rs))
6418e2e0047SBob Peterson return;
6428e2e0047SBob Peterson
643c65b76b8SAndreas Gruenbacher rgd = rs->rs_rgd;
6449e733d39SSteven Whitehouse trace_gfs2_rs(rs, TRACE_RS_TREEDEL);
6458e2e0047SBob Peterson rb_erase(&rs->rs_node, &rgd->rd_rstree);
64624d634e8SMichel Lespinasse RB_CLEAR_NODE(&rs->rs_node);
6478e2e0047SBob Peterson
64807974d2aSAndreas Gruenbacher if (rs->rs_requested) {
64907974d2aSAndreas Gruenbacher /* return requested blocks to the rgrp */
65007974d2aSAndreas Gruenbacher BUG_ON(rs->rs_rgd->rd_requested < rs->rs_requested);
65107974d2aSAndreas Gruenbacher rs->rs_rgd->rd_requested -= rs->rs_requested;
652a12c6fa1SAndreas Gruenbacher
6535ea5050cSBob Peterson /* The rgrp extent failure point is likely not to increase;
6545ea5050cSBob Peterson it will only do so if the freed blocks are somehow
6555ea5050cSBob Peterson contiguous with a span of free blocks that follows. Still,
6565ea5050cSBob Peterson it will force the number to be recalculated later. */
65707974d2aSAndreas Gruenbacher rgd->rd_extfail_pt += rs->rs_requested;
65807974d2aSAndreas Gruenbacher rs->rs_requested = 0;
6598e2e0047SBob Peterson }
6608e2e0047SBob Peterson }
6618e2e0047SBob Peterson
6628e2e0047SBob Peterson /**
6638e2e0047SBob Peterson * gfs2_rs_deltree - remove a multi-block reservation from the rgd tree
6648e2e0047SBob Peterson * @rs: The reservation to remove
6658e2e0047SBob Peterson *
6668e2e0047SBob Peterson */
gfs2_rs_deltree(struct gfs2_blkreserv * rs)66720095218SBob Peterson void gfs2_rs_deltree(struct gfs2_blkreserv *rs)
6688e2e0047SBob Peterson {
6698e2e0047SBob Peterson struct gfs2_rgrpd *rgd;
6708e2e0047SBob Peterson
671c65b76b8SAndreas Gruenbacher rgd = rs->rs_rgd;
6724a993fb1SSteven Whitehouse if (rgd) {
6738e2e0047SBob Peterson spin_lock(&rgd->rd_rsspin);
67420095218SBob Peterson __rs_deltree(rs);
67507974d2aSAndreas Gruenbacher BUG_ON(rs->rs_requested);
6768e2e0047SBob Peterson spin_unlock(&rgd->rd_rsspin);
6778e2e0047SBob Peterson }
6784a993fb1SSteven Whitehouse }
6798e2e0047SBob Peterson
6808e2e0047SBob Peterson /**
6811595548fSAndreas Gruenbacher * gfs2_rs_delete - delete a multi-block reservation
6820a305e49SBob Peterson * @ip: The inode for this reservation
6830a305e49SBob Peterson *
6840a305e49SBob Peterson */
gfs2_rs_delete(struct gfs2_inode * ip)6857336905aSAndreas Gruenbacher void gfs2_rs_delete(struct gfs2_inode *ip)
6860a305e49SBob Peterson {
6877336905aSAndreas Gruenbacher struct inode *inode = &ip->i_inode;
6887336905aSAndreas Gruenbacher
6890a305e49SBob Peterson down_write(&ip->i_rw_mutex);
6907336905aSAndreas Gruenbacher if (atomic_read(&inode->i_writecount) <= 1)
691a097dc7eSBob Peterson gfs2_rs_deltree(&ip->i_res);
6920a305e49SBob Peterson up_write(&ip->i_rw_mutex);
6930a305e49SBob Peterson }
6940a305e49SBob Peterson
6958e2e0047SBob Peterson /**
6968e2e0047SBob Peterson * return_all_reservations - return all reserved blocks back to the rgrp.
6978e2e0047SBob Peterson * @rgd: the rgrp that needs its space back
6988e2e0047SBob Peterson *
6998e2e0047SBob Peterson * We previously reserved a bunch of blocks for allocation. Now we need to
7008e2e0047SBob Peterson * give them back. This leave the reservation structures in tact, but removes
7018e2e0047SBob Peterson * all of their corresponding "no-fly zones".
7028e2e0047SBob Peterson */
return_all_reservations(struct gfs2_rgrpd * rgd)7038e2e0047SBob Peterson static void return_all_reservations(struct gfs2_rgrpd *rgd)
7048e2e0047SBob Peterson {
7058e2e0047SBob Peterson struct rb_node *n;
7068e2e0047SBob Peterson struct gfs2_blkreserv *rs;
7078e2e0047SBob Peterson
7088e2e0047SBob Peterson spin_lock(&rgd->rd_rsspin);
7098e2e0047SBob Peterson while ((n = rb_first(&rgd->rd_rstree))) {
7108e2e0047SBob Peterson rs = rb_entry(n, struct gfs2_blkreserv, rs_node);
71120095218SBob Peterson __rs_deltree(rs);
7128e2e0047SBob Peterson }
7138e2e0047SBob Peterson spin_unlock(&rgd->rd_rsspin);
7148e2e0047SBob Peterson }
7158e2e0047SBob Peterson
gfs2_clear_rgrpd(struct gfs2_sbd * sdp)7168339ee54SSteven Whitehouse void gfs2_clear_rgrpd(struct gfs2_sbd *sdp)
717b3b94faaSDavid Teigland {
7187c9ca621SBob Peterson struct rb_node *n;
719b3b94faaSDavid Teigland struct gfs2_rgrpd *rgd;
720b3b94faaSDavid Teigland struct gfs2_glock *gl;
721b3b94faaSDavid Teigland
7227c9ca621SBob Peterson while ((n = rb_first(&sdp->sd_rindex_tree))) {
7237c9ca621SBob Peterson rgd = rb_entry(n, struct gfs2_rgrpd, rd_node);
724b3b94faaSDavid Teigland gl = rgd->rd_gl;
725b3b94faaSDavid Teigland
7267c9ca621SBob Peterson rb_erase(n, &sdp->sd_rindex_tree);
727b3b94faaSDavid Teigland
728b3b94faaSDavid Teigland if (gl) {
729b3422cacSBob Peterson if (gl->gl_state != LM_ST_UNLOCKED) {
730b3422cacSBob Peterson gfs2_glock_cb(gl, LM_ST_UNLOCKED);
731b3422cacSBob Peterson flush_delayed_work(&gl->gl_work);
732b3422cacSBob Peterson }
73310283ea5SAndreas Gruenbacher gfs2_rgrp_brelse(rgd);
734b3422cacSBob Peterson glock_clear_object(gl, rgd);
735b3b94faaSDavid Teigland gfs2_glock_put(gl);
736b3b94faaSDavid Teigland }
737b3b94faaSDavid Teigland
7388339ee54SSteven Whitehouse gfs2_free_clones(rgd);
739d0f17d38SBob Peterson return_all_reservations(rgd);
740b3b94faaSDavid Teigland kfree(rgd->rd_bits);
74136e4ad03SBob Peterson rgd->rd_bits = NULL;
7426bdd9be6SBob Peterson kmem_cache_free(gfs2_rgrpd_cachep, rgd);
743b3b94faaSDavid Teigland }
744b3b94faaSDavid Teigland }
745b3b94faaSDavid Teigland
746b3b94faaSDavid Teigland /**
747c551f66cSLee Jones * compute_bitstructs - Compute the bitmap sizes
748b3b94faaSDavid Teigland * @rgd: The resource group descriptor
749b3b94faaSDavid Teigland *
750b3b94faaSDavid Teigland * Calculates bitmap descriptors, one for each block that contains bitmap data
751b3b94faaSDavid Teigland *
752b3b94faaSDavid Teigland * Returns: errno
753b3b94faaSDavid Teigland */
754b3b94faaSDavid Teigland
compute_bitstructs(struct gfs2_rgrpd * rgd)755b3b94faaSDavid Teigland static int compute_bitstructs(struct gfs2_rgrpd *rgd)
756b3b94faaSDavid Teigland {
757b3b94faaSDavid Teigland struct gfs2_sbd *sdp = rgd->rd_sbd;
758b3b94faaSDavid Teigland struct gfs2_bitmap *bi;
759bb8d8a6fSSteven Whitehouse u32 length = rgd->rd_length; /* # blocks in hdr & bitmap */
760cd915493SSteven Whitehouse u32 bytes_left, bytes;
761b3b94faaSDavid Teigland int x;
762b3b94faaSDavid Teigland
763feaa7bbaSSteven Whitehouse if (!length)
764feaa7bbaSSteven Whitehouse return -EINVAL;
765feaa7bbaSSteven Whitehouse
766dd894be8SSteven Whitehouse rgd->rd_bits = kcalloc(length, sizeof(struct gfs2_bitmap), GFP_NOFS);
767b3b94faaSDavid Teigland if (!rgd->rd_bits)
768b3b94faaSDavid Teigland return -ENOMEM;
769b3b94faaSDavid Teigland
770bb8d8a6fSSteven Whitehouse bytes_left = rgd->rd_bitbytes;
771b3b94faaSDavid Teigland
772b3b94faaSDavid Teigland for (x = 0; x < length; x++) {
773b3b94faaSDavid Teigland bi = rgd->rd_bits + x;
774b3b94faaSDavid Teigland
77560a0b8f9SSteven Whitehouse bi->bi_flags = 0;
776b3b94faaSDavid Teigland /* small rgrp; bitmap stored completely in header block */
777b3b94faaSDavid Teigland if (length == 1) {
778b3b94faaSDavid Teigland bytes = bytes_left;
779b3b94faaSDavid Teigland bi->bi_offset = sizeof(struct gfs2_rgrp);
780b3b94faaSDavid Teigland bi->bi_start = 0;
781281b4952SAndreas Gruenbacher bi->bi_bytes = bytes;
7827e230f57SBob Peterson bi->bi_blocks = bytes * GFS2_NBBY;
783b3b94faaSDavid Teigland /* header block */
784b3b94faaSDavid Teigland } else if (x == 0) {
785b3b94faaSDavid Teigland bytes = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_rgrp);
786b3b94faaSDavid Teigland bi->bi_offset = sizeof(struct gfs2_rgrp);
787b3b94faaSDavid Teigland bi->bi_start = 0;
788281b4952SAndreas Gruenbacher bi->bi_bytes = bytes;
7897e230f57SBob Peterson bi->bi_blocks = bytes * GFS2_NBBY;
790b3b94faaSDavid Teigland /* last block */
791b3b94faaSDavid Teigland } else if (x + 1 == length) {
792b3b94faaSDavid Teigland bytes = bytes_left;
793b3b94faaSDavid Teigland bi->bi_offset = sizeof(struct gfs2_meta_header);
794bb8d8a6fSSteven Whitehouse bi->bi_start = rgd->rd_bitbytes - bytes_left;
795281b4952SAndreas Gruenbacher bi->bi_bytes = bytes;
7967e230f57SBob Peterson bi->bi_blocks = bytes * GFS2_NBBY;
797b3b94faaSDavid Teigland /* other blocks */
798b3b94faaSDavid Teigland } else {
799568f4c96SSteven Whitehouse bytes = sdp->sd_sb.sb_bsize -
800568f4c96SSteven Whitehouse sizeof(struct gfs2_meta_header);
801b3b94faaSDavid Teigland bi->bi_offset = sizeof(struct gfs2_meta_header);
802bb8d8a6fSSteven Whitehouse bi->bi_start = rgd->rd_bitbytes - bytes_left;
803281b4952SAndreas Gruenbacher bi->bi_bytes = bytes;
8047e230f57SBob Peterson bi->bi_blocks = bytes * GFS2_NBBY;
805b3b94faaSDavid Teigland }
806b3b94faaSDavid Teigland
807b3b94faaSDavid Teigland bytes_left -= bytes;
808b3b94faaSDavid Teigland }
809b3b94faaSDavid Teigland
810b3b94faaSDavid Teigland if (bytes_left) {
811b3b94faaSDavid Teigland gfs2_consist_rgrpd(rgd);
812b3b94faaSDavid Teigland return -EIO;
813b3b94faaSDavid Teigland }
814b3b94faaSDavid Teigland bi = rgd->rd_bits + (length - 1);
815281b4952SAndreas Gruenbacher if ((bi->bi_start + bi->bi_bytes) * GFS2_NBBY != rgd->rd_data) {
8168dc88ac6SAndreas Gruenbacher gfs2_lm(sdp,
8178dc88ac6SAndreas Gruenbacher "ri_addr = %llu\n"
8188dc88ac6SAndreas Gruenbacher "ri_length = %u\n"
8198dc88ac6SAndreas Gruenbacher "ri_data0 = %llu\n"
8208dc88ac6SAndreas Gruenbacher "ri_data = %u\n"
8218dc88ac6SAndreas Gruenbacher "ri_bitbytes = %u\n"
8228dc88ac6SAndreas Gruenbacher "start=%u len=%u offset=%u\n",
8238dc88ac6SAndreas Gruenbacher (unsigned long long)rgd->rd_addr,
8248dc88ac6SAndreas Gruenbacher rgd->rd_length,
8258dc88ac6SAndreas Gruenbacher (unsigned long long)rgd->rd_data0,
8268dc88ac6SAndreas Gruenbacher rgd->rd_data,
8278dc88ac6SAndreas Gruenbacher rgd->rd_bitbytes,
828281b4952SAndreas Gruenbacher bi->bi_start, bi->bi_bytes, bi->bi_offset);
8298dc88ac6SAndreas Gruenbacher gfs2_consist_rgrpd(rgd);
830b3b94faaSDavid Teigland return -EIO;
831b3b94faaSDavid Teigland }
832b3b94faaSDavid Teigland
833b3b94faaSDavid Teigland return 0;
834b3b94faaSDavid Teigland }
835b3b94faaSDavid Teigland
836b3b94faaSDavid Teigland /**
8377ae8fa84SRobert Peterson * gfs2_ri_total - Total up the file system space, according to the rindex.
838886b1416SBob Peterson * @sdp: the filesystem
8397ae8fa84SRobert Peterson *
8407ae8fa84SRobert Peterson */
gfs2_ri_total(struct gfs2_sbd * sdp)8417ae8fa84SRobert Peterson u64 gfs2_ri_total(struct gfs2_sbd *sdp)
8427ae8fa84SRobert Peterson {
8437ae8fa84SRobert Peterson u64 total_data = 0;
8447ae8fa84SRobert Peterson struct inode *inode = sdp->sd_rindex;
8457ae8fa84SRobert Peterson struct gfs2_inode *ip = GFS2_I(inode);
8467ae8fa84SRobert Peterson char buf[sizeof(struct gfs2_rindex)];
8477ae8fa84SRobert Peterson int error, rgrps;
8487ae8fa84SRobert Peterson
8497ae8fa84SRobert Peterson for (rgrps = 0;; rgrps++) {
8507ae8fa84SRobert Peterson loff_t pos = rgrps * sizeof(struct gfs2_rindex);
8517ae8fa84SRobert Peterson
852bcd7278dSBob Peterson if (pos + sizeof(struct gfs2_rindex) > i_size_read(inode))
8537ae8fa84SRobert Peterson break;
8544306629eSAndrew Price error = gfs2_internal_read(ip, buf, &pos,
8557ae8fa84SRobert Peterson sizeof(struct gfs2_rindex));
8567ae8fa84SRobert Peterson if (error != sizeof(struct gfs2_rindex))
8577ae8fa84SRobert Peterson break;
858bb8d8a6fSSteven Whitehouse total_data += be32_to_cpu(((struct gfs2_rindex *)buf)->ri_data);
8597ae8fa84SRobert Peterson }
8607ae8fa84SRobert Peterson return total_data;
8617ae8fa84SRobert Peterson }
8627ae8fa84SRobert Peterson
rgd_insert(struct gfs2_rgrpd * rgd)8636aad1c3dSBob Peterson static int rgd_insert(struct gfs2_rgrpd *rgd)
8647c9ca621SBob Peterson {
8657c9ca621SBob Peterson struct gfs2_sbd *sdp = rgd->rd_sbd;
8667c9ca621SBob Peterson struct rb_node **newn = &sdp->sd_rindex_tree.rb_node, *parent = NULL;
8677c9ca621SBob Peterson
8687c9ca621SBob Peterson /* Figure out where to put new node */
8697c9ca621SBob Peterson while (*newn) {
8707c9ca621SBob Peterson struct gfs2_rgrpd *cur = rb_entry(*newn, struct gfs2_rgrpd,
8717c9ca621SBob Peterson rd_node);
8727c9ca621SBob Peterson
8737c9ca621SBob Peterson parent = *newn;
8747c9ca621SBob Peterson if (rgd->rd_addr < cur->rd_addr)
8757c9ca621SBob Peterson newn = &((*newn)->rb_left);
8767c9ca621SBob Peterson else if (rgd->rd_addr > cur->rd_addr)
8777c9ca621SBob Peterson newn = &((*newn)->rb_right);
8787c9ca621SBob Peterson else
8796aad1c3dSBob Peterson return -EEXIST;
8807c9ca621SBob Peterson }
8817c9ca621SBob Peterson
8827c9ca621SBob Peterson rb_link_node(&rgd->rd_node, parent, newn);
8837c9ca621SBob Peterson rb_insert_color(&rgd->rd_node, &sdp->sd_rindex_tree);
8846aad1c3dSBob Peterson sdp->sd_rgrps++;
8856aad1c3dSBob Peterson return 0;
8867c9ca621SBob Peterson }
8877c9ca621SBob Peterson
8887ae8fa84SRobert Peterson /**
8896c53267fSRobert Peterson * read_rindex_entry - Pull in a new resource index entry from the disk
8904306629eSAndrew Price * @ip: Pointer to the rindex inode
891b3b94faaSDavid Teigland *
8928339ee54SSteven Whitehouse * Returns: 0 on success, > 0 on EOF, error code otherwise
893b3b94faaSDavid Teigland */
894b3b94faaSDavid Teigland
read_rindex_entry(struct gfs2_inode * ip)8954306629eSAndrew Price static int read_rindex_entry(struct gfs2_inode *ip)
896b3b94faaSDavid Teigland {
897feaa7bbaSSteven Whitehouse struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
898f42faf4fSSteven Whitehouse loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex);
8998339ee54SSteven Whitehouse struct gfs2_rindex buf;
9006c53267fSRobert Peterson int error;
9016c53267fSRobert Peterson struct gfs2_rgrpd *rgd;
9027ae8fa84SRobert Peterson
9038339ee54SSteven Whitehouse if (pos >= i_size_read(&ip->i_inode))
9048339ee54SSteven Whitehouse return 1;
9058339ee54SSteven Whitehouse
9064306629eSAndrew Price error = gfs2_internal_read(ip, (char *)&buf, &pos,
907b3b94faaSDavid Teigland sizeof(struct gfs2_rindex));
9088339ee54SSteven Whitehouse
9098339ee54SSteven Whitehouse if (error != sizeof(struct gfs2_rindex))
9108339ee54SSteven Whitehouse return (error == 0) ? 1 : error;
911b3b94faaSDavid Teigland
9126bdd9be6SBob Peterson rgd = kmem_cache_zalloc(gfs2_rgrpd_cachep, GFP_NOFS);
913b3b94faaSDavid Teigland error = -ENOMEM;
914b3b94faaSDavid Teigland if (!rgd)
9156c53267fSRobert Peterson return error;
916b3b94faaSDavid Teigland
917b3b94faaSDavid Teigland rgd->rd_sbd = sdp;
9188339ee54SSteven Whitehouse rgd->rd_addr = be64_to_cpu(buf.ri_addr);
9198339ee54SSteven Whitehouse rgd->rd_length = be32_to_cpu(buf.ri_length);
9208339ee54SSteven Whitehouse rgd->rd_data0 = be64_to_cpu(buf.ri_data0);
9218339ee54SSteven Whitehouse rgd->rd_data = be32_to_cpu(buf.ri_data);
9228339ee54SSteven Whitehouse rgd->rd_bitbytes = be32_to_cpu(buf.ri_bitbytes);
9238e2e0047SBob Peterson spin_lock_init(&rgd->rd_rsspin);
9249e514605SAndreas Gruenbacher mutex_init(&rgd->rd_mutex);
9257c9ca621SBob Peterson
926bb8d8a6fSSteven Whitehouse error = gfs2_glock_get(sdp, rgd->rd_addr,
927b3b94faaSDavid Teigland &gfs2_rgrp_glops, CREATE, &rgd->rd_gl);
928b3b94faaSDavid Teigland if (error)
9298339ee54SSteven Whitehouse goto fail;
930b3b94faaSDavid Teigland
931428f651cSBob Peterson error = compute_bitstructs(rgd);
932428f651cSBob Peterson if (error)
933428f651cSBob Peterson goto fail_glock;
934428f651cSBob Peterson
9354e2f8849SDavid Teigland rgd->rd_rgl = (struct gfs2_rgrp_lvb *)rgd->rd_gl->gl_lksb.sb_lvbptr;
9364b3113a2SBob Peterson rgd->rd_flags &= ~GFS2_RDF_PREFERRED;
9377c9ca621SBob Peterson if (rgd->rd_data > sdp->sd_max_rg_data)
9387c9ca621SBob Peterson sdp->sd_max_rg_data = rgd->rd_data;
9398339ee54SSteven Whitehouse spin_lock(&sdp->sd_rindex_spin);
9406aad1c3dSBob Peterson error = rgd_insert(rgd);
9418339ee54SSteven Whitehouse spin_unlock(&sdp->sd_rindex_spin);
94236e4ad03SBob Peterson if (!error) {
9436f6597baSAndreas Gruenbacher glock_set_object(rgd->rd_gl, rgd);
9446aad1c3dSBob Peterson return 0;
94536e4ad03SBob Peterson }
9466aad1c3dSBob Peterson
9476aad1c3dSBob Peterson error = 0; /* someone else read in the rgrp; free it and ignore it */
948428f651cSBob Peterson fail_glock:
949c1ac539eSBob Peterson gfs2_glock_put(rgd->rd_gl);
9508339ee54SSteven Whitehouse
9518339ee54SSteven Whitehouse fail:
9528339ee54SSteven Whitehouse kfree(rgd->rd_bits);
95336e4ad03SBob Peterson rgd->rd_bits = NULL;
9548339ee54SSteven Whitehouse kmem_cache_free(gfs2_rgrpd_cachep, rgd);
9556c53267fSRobert Peterson return error;
9566c53267fSRobert Peterson }
9576c53267fSRobert Peterson
9586c53267fSRobert Peterson /**
9590e27c18cSBob Peterson * set_rgrp_preferences - Run all the rgrps, selecting some we prefer to use
9600e27c18cSBob Peterson * @sdp: the GFS2 superblock
9610e27c18cSBob Peterson *
9620e27c18cSBob Peterson * The purpose of this function is to select a subset of the resource groups
9630e27c18cSBob Peterson * and mark them as PREFERRED. We do it in such a way that each node prefers
9640e27c18cSBob Peterson * to use a unique set of rgrps to minimize glock contention.
9650e27c18cSBob Peterson */
set_rgrp_preferences(struct gfs2_sbd * sdp)9660e27c18cSBob Peterson static void set_rgrp_preferences(struct gfs2_sbd *sdp)
9670e27c18cSBob Peterson {
9680e27c18cSBob Peterson struct gfs2_rgrpd *rgd, *first;
9690e27c18cSBob Peterson int i;
9700e27c18cSBob Peterson
9710e27c18cSBob Peterson /* Skip an initial number of rgrps, based on this node's journal ID.
9720e27c18cSBob Peterson That should start each node out on its own set. */
9730e27c18cSBob Peterson rgd = gfs2_rgrpd_get_first(sdp);
9740e27c18cSBob Peterson for (i = 0; i < sdp->sd_lockstruct.ls_jid; i++)
9750e27c18cSBob Peterson rgd = gfs2_rgrpd_get_next(rgd);
9760e27c18cSBob Peterson first = rgd;
9770e27c18cSBob Peterson
9780e27c18cSBob Peterson do {
9790e27c18cSBob Peterson rgd->rd_flags |= GFS2_RDF_PREFERRED;
9800e27c18cSBob Peterson for (i = 0; i < sdp->sd_journals; i++) {
9810e27c18cSBob Peterson rgd = gfs2_rgrpd_get_next(rgd);
982959b6717SAbhi Das if (!rgd || rgd == first)
9830e27c18cSBob Peterson break;
9840e27c18cSBob Peterson }
985959b6717SAbhi Das } while (rgd && rgd != first);
9860e27c18cSBob Peterson }
9870e27c18cSBob Peterson
9880e27c18cSBob Peterson /**
9896c53267fSRobert Peterson * gfs2_ri_update - Pull in a new resource index from the disk
9906c53267fSRobert Peterson * @ip: pointer to the rindex inode
9916c53267fSRobert Peterson *
9926c53267fSRobert Peterson * Returns: 0 on successful update, error code otherwise
9936c53267fSRobert Peterson */
9946c53267fSRobert Peterson
gfs2_ri_update(struct gfs2_inode * ip)9958339ee54SSteven Whitehouse static int gfs2_ri_update(struct gfs2_inode *ip)
9966c53267fSRobert Peterson {
9976c53267fSRobert Peterson struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
9986c53267fSRobert Peterson int error;
9996c53267fSRobert Peterson
10008339ee54SSteven Whitehouse do {
10014306629eSAndrew Price error = read_rindex_entry(ip);
10028339ee54SSteven Whitehouse } while (error == 0);
10038339ee54SSteven Whitehouse
10048339ee54SSteven Whitehouse if (error < 0)
10056c53267fSRobert Peterson return error;
1006b3b94faaSDavid Teigland
100777872151SBob Peterson if (RB_EMPTY_ROOT(&sdp->sd_rindex_tree)) {
100877872151SBob Peterson fs_err(sdp, "no resource groups found in the file system.\n");
100977872151SBob Peterson return -ENOENT;
101077872151SBob Peterson }
10110e27c18cSBob Peterson set_rgrp_preferences(sdp);
10120e27c18cSBob Peterson
1013cf45b752SBob Peterson sdp->sd_rindex_uptodate = 1;
1014b3b94faaSDavid Teigland return 0;
10156c53267fSRobert Peterson }
1016b3b94faaSDavid Teigland
10176c53267fSRobert Peterson /**
10188339ee54SSteven Whitehouse * gfs2_rindex_update - Update the rindex if required
1019b3b94faaSDavid Teigland * @sdp: The GFS2 superblock
1020b3b94faaSDavid Teigland *
1021b3b94faaSDavid Teigland * We grab a lock on the rindex inode to make sure that it doesn't
1022b3b94faaSDavid Teigland * change whilst we are performing an operation. We keep this lock
1023b3b94faaSDavid Teigland * for quite long periods of time compared to other locks. This
1024b3b94faaSDavid Teigland * doesn't matter, since it is shared and it is very, very rarely
1025b3b94faaSDavid Teigland * accessed in the exclusive mode (i.e. only when expanding the filesystem).
1026b3b94faaSDavid Teigland *
1027b3b94faaSDavid Teigland * This makes sure that we're using the latest copy of the resource index
1028b3b94faaSDavid Teigland * special file, which might have been updated if someone expanded the
1029b3b94faaSDavid Teigland * filesystem (via gfs2_grow utility), which adds new resource groups.
1030b3b94faaSDavid Teigland *
10318339ee54SSteven Whitehouse * Returns: 0 on succeess, error code otherwise
1032b3b94faaSDavid Teigland */
1033b3b94faaSDavid Teigland
gfs2_rindex_update(struct gfs2_sbd * sdp)10348339ee54SSteven Whitehouse int gfs2_rindex_update(struct gfs2_sbd *sdp)
1035b3b94faaSDavid Teigland {
1036feaa7bbaSSteven Whitehouse struct gfs2_inode *ip = GFS2_I(sdp->sd_rindex);
1037b3b94faaSDavid Teigland struct gfs2_glock *gl = ip->i_gl;
10388339ee54SSteven Whitehouse struct gfs2_holder ri_gh;
10398339ee54SSteven Whitehouse int error = 0;
1040a365fbf3SSteven Whitehouse int unlock_required = 0;
1041b3b94faaSDavid Teigland
1042b3b94faaSDavid Teigland /* Read new copy from disk if we don't have the latest */
1043cf45b752SBob Peterson if (!sdp->sd_rindex_uptodate) {
1044a365fbf3SSteven Whitehouse if (!gfs2_glock_is_locked_by_me(gl)) {
10458339ee54SSteven Whitehouse error = gfs2_glock_nq_init(gl, LM_ST_SHARED, 0, &ri_gh);
1046b3b94faaSDavid Teigland if (error)
10476aad1c3dSBob Peterson return error;
1048a365fbf3SSteven Whitehouse unlock_required = 1;
1049a365fbf3SSteven Whitehouse }
10508339ee54SSteven Whitehouse if (!sdp->sd_rindex_uptodate)
10518339ee54SSteven Whitehouse error = gfs2_ri_update(ip);
1052a365fbf3SSteven Whitehouse if (unlock_required)
10538339ee54SSteven Whitehouse gfs2_glock_dq_uninit(&ri_gh);
1054b3b94faaSDavid Teigland }
1055b3b94faaSDavid Teigland
1056b3b94faaSDavid Teigland return error;
1057b3b94faaSDavid Teigland }
1058b3b94faaSDavid Teigland
gfs2_rgrp_in(struct gfs2_rgrpd * rgd,const void * buf)105942d52e38SBob Peterson static void gfs2_rgrp_in(struct gfs2_rgrpd *rgd, const void *buf)
1060bb8d8a6fSSteven Whitehouse {
1061bb8d8a6fSSteven Whitehouse const struct gfs2_rgrp *str = buf;
106242d52e38SBob Peterson u32 rg_flags;
1063bb8d8a6fSSteven Whitehouse
106442d52e38SBob Peterson rg_flags = be32_to_cpu(str->rg_flags);
106509010978SSteven Whitehouse rg_flags &= ~GFS2_RDF_MASK;
10661ce97e56SSteven Whitehouse rgd->rd_flags &= GFS2_RDF_MASK;
10671ce97e56SSteven Whitehouse rgd->rd_flags |= rg_flags;
1068cfc8b549SSteven Whitehouse rgd->rd_free = be32_to_cpu(str->rg_free);
106973f74948SSteven Whitehouse rgd->rd_dinodes = be32_to_cpu(str->rg_dinodes);
1070d8b71f73SSteven Whitehouse rgd->rd_igeneration = be64_to_cpu(str->rg_igeneration);
1071166725d9SAndrew Price /* rd_data0, rd_data and rd_bitbytes already set from rindex */
1072bb8d8a6fSSteven Whitehouse }
1073bb8d8a6fSSteven Whitehouse
gfs2_rgrp_ondisk2lvb(struct gfs2_rgrp_lvb * rgl,const void * buf)10743f30f929SBob Peterson static void gfs2_rgrp_ondisk2lvb(struct gfs2_rgrp_lvb *rgl, const void *buf)
10753f30f929SBob Peterson {
10763f30f929SBob Peterson const struct gfs2_rgrp *str = buf;
10773f30f929SBob Peterson
10783f30f929SBob Peterson rgl->rl_magic = cpu_to_be32(GFS2_MAGIC);
10793f30f929SBob Peterson rgl->rl_flags = str->rg_flags;
10803f30f929SBob Peterson rgl->rl_free = str->rg_free;
10813f30f929SBob Peterson rgl->rl_dinodes = str->rg_dinodes;
10823f30f929SBob Peterson rgl->rl_igeneration = str->rg_igeneration;
10833f30f929SBob Peterson rgl->__pad = 0UL;
10843f30f929SBob Peterson }
10853f30f929SBob Peterson
gfs2_rgrp_out(struct gfs2_rgrpd * rgd,void * buf)108642d52e38SBob Peterson static void gfs2_rgrp_out(struct gfs2_rgrpd *rgd, void *buf)
1087bb8d8a6fSSteven Whitehouse {
108865adc273SAndrew Price struct gfs2_rgrpd *next = gfs2_rgrpd_get_next(rgd);
1089bb8d8a6fSSteven Whitehouse struct gfs2_rgrp *str = buf;
1090850d2d91SAndrew Price u32 crc;
1091bb8d8a6fSSteven Whitehouse
109209010978SSteven Whitehouse str->rg_flags = cpu_to_be32(rgd->rd_flags & ~GFS2_RDF_MASK);
1093cfc8b549SSteven Whitehouse str->rg_free = cpu_to_be32(rgd->rd_free);
109473f74948SSteven Whitehouse str->rg_dinodes = cpu_to_be32(rgd->rd_dinodes);
109565adc273SAndrew Price if (next == NULL)
109665adc273SAndrew Price str->rg_skip = 0;
109765adc273SAndrew Price else if (next->rd_addr > rgd->rd_addr)
109865adc273SAndrew Price str->rg_skip = cpu_to_be32(next->rd_addr - rgd->rd_addr);
1099d8b71f73SSteven Whitehouse str->rg_igeneration = cpu_to_be64(rgd->rd_igeneration);
1100166725d9SAndrew Price str->rg_data0 = cpu_to_be64(rgd->rd_data0);
1101166725d9SAndrew Price str->rg_data = cpu_to_be32(rgd->rd_data);
1102166725d9SAndrew Price str->rg_bitbytes = cpu_to_be32(rgd->rd_bitbytes);
1103850d2d91SAndrew Price str->rg_crc = 0;
1104850d2d91SAndrew Price crc = gfs2_disk_hash(buf, sizeof(struct gfs2_rgrp));
1105850d2d91SAndrew Price str->rg_crc = cpu_to_be32(crc);
1106166725d9SAndrew Price
1107bb8d8a6fSSteven Whitehouse memset(&str->rg_reserved, 0, sizeof(str->rg_reserved));
11083f30f929SBob Peterson gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, buf);
1109bb8d8a6fSSteven Whitehouse }
1110bb8d8a6fSSteven Whitehouse
gfs2_rgrp_lvb_valid(struct gfs2_rgrpd * rgd)111190306c41SBenjamin Marzinski static int gfs2_rgrp_lvb_valid(struct gfs2_rgrpd *rgd)
111290306c41SBenjamin Marzinski {
111390306c41SBenjamin Marzinski struct gfs2_rgrp_lvb *rgl = rgd->rd_rgl;
111490306c41SBenjamin Marzinski struct gfs2_rgrp *str = (struct gfs2_rgrp *)rgd->rd_bits[0].bi_bh->b_data;
1115f29e62eeSBob Peterson struct gfs2_sbd *sdp = rgd->rd_sbd;
111672244b6bSBob Peterson int valid = 1;
111790306c41SBenjamin Marzinski
111872244b6bSBob Peterson if (rgl->rl_flags != str->rg_flags) {
1119f29e62eeSBob Peterson fs_warn(sdp, "GFS2: rgd: %llu lvb flag mismatch %u/%u",
112072244b6bSBob Peterson (unsigned long long)rgd->rd_addr,
112172244b6bSBob Peterson be32_to_cpu(rgl->rl_flags), be32_to_cpu(str->rg_flags));
112272244b6bSBob Peterson valid = 0;
112372244b6bSBob Peterson }
112472244b6bSBob Peterson if (rgl->rl_free != str->rg_free) {
1125f29e62eeSBob Peterson fs_warn(sdp, "GFS2: rgd: %llu lvb free mismatch %u/%u",
112672244b6bSBob Peterson (unsigned long long)rgd->rd_addr,
112772244b6bSBob Peterson be32_to_cpu(rgl->rl_free), be32_to_cpu(str->rg_free));
112872244b6bSBob Peterson valid = 0;
112972244b6bSBob Peterson }
113072244b6bSBob Peterson if (rgl->rl_dinodes != str->rg_dinodes) {
1131f29e62eeSBob Peterson fs_warn(sdp, "GFS2: rgd: %llu lvb dinode mismatch %u/%u",
113272244b6bSBob Peterson (unsigned long long)rgd->rd_addr,
113372244b6bSBob Peterson be32_to_cpu(rgl->rl_dinodes),
113472244b6bSBob Peterson be32_to_cpu(str->rg_dinodes));
113572244b6bSBob Peterson valid = 0;
113672244b6bSBob Peterson }
113772244b6bSBob Peterson if (rgl->rl_igeneration != str->rg_igeneration) {
1138f29e62eeSBob Peterson fs_warn(sdp, "GFS2: rgd: %llu lvb igen mismatch %llu/%llu",
1139f29e62eeSBob Peterson (unsigned long long)rgd->rd_addr,
114072244b6bSBob Peterson (unsigned long long)be64_to_cpu(rgl->rl_igeneration),
114172244b6bSBob Peterson (unsigned long long)be64_to_cpu(str->rg_igeneration));
114272244b6bSBob Peterson valid = 0;
114372244b6bSBob Peterson }
114472244b6bSBob Peterson return valid;
114590306c41SBenjamin Marzinski }
114690306c41SBenjamin Marzinski
count_unlinked(struct gfs2_rgrpd * rgd)114790306c41SBenjamin Marzinski static u32 count_unlinked(struct gfs2_rgrpd *rgd)
114890306c41SBenjamin Marzinski {
114990306c41SBenjamin Marzinski struct gfs2_bitmap *bi;
115090306c41SBenjamin Marzinski const u32 length = rgd->rd_length;
115190306c41SBenjamin Marzinski const u8 *buffer = NULL;
115290306c41SBenjamin Marzinski u32 i, goal, count = 0;
115390306c41SBenjamin Marzinski
115490306c41SBenjamin Marzinski for (i = 0, bi = rgd->rd_bits; i < length; i++, bi++) {
115590306c41SBenjamin Marzinski goal = 0;
115690306c41SBenjamin Marzinski buffer = bi->bi_bh->b_data + bi->bi_offset;
115790306c41SBenjamin Marzinski WARN_ON(!buffer_uptodate(bi->bi_bh));
1158281b4952SAndreas Gruenbacher while (goal < bi->bi_blocks) {
1159281b4952SAndreas Gruenbacher goal = gfs2_bitfit(buffer, bi->bi_bytes, goal,
116090306c41SBenjamin Marzinski GFS2_BLKST_UNLINKED);
116190306c41SBenjamin Marzinski if (goal == BFITNOENT)
116290306c41SBenjamin Marzinski break;
116390306c41SBenjamin Marzinski count++;
116490306c41SBenjamin Marzinski goal++;
116590306c41SBenjamin Marzinski }
116690306c41SBenjamin Marzinski }
116790306c41SBenjamin Marzinski
116890306c41SBenjamin Marzinski return count;
116990306c41SBenjamin Marzinski }
117090306c41SBenjamin Marzinski
rgrp_set_bitmap_flags(struct gfs2_rgrpd * rgd)1171560b8ebaSAndreas Gruenbacher static void rgrp_set_bitmap_flags(struct gfs2_rgrpd *rgd)
1172560b8ebaSAndreas Gruenbacher {
1173560b8ebaSAndreas Gruenbacher struct gfs2_bitmap *bi;
1174560b8ebaSAndreas Gruenbacher int x;
1175560b8ebaSAndreas Gruenbacher
1176560b8ebaSAndreas Gruenbacher if (rgd->rd_free) {
1177560b8ebaSAndreas Gruenbacher for (x = 0; x < rgd->rd_length; x++) {
1178560b8ebaSAndreas Gruenbacher bi = rgd->rd_bits + x;
1179560b8ebaSAndreas Gruenbacher clear_bit(GBF_FULL, &bi->bi_flags);
1180560b8ebaSAndreas Gruenbacher }
1181560b8ebaSAndreas Gruenbacher } else {
1182560b8ebaSAndreas Gruenbacher for (x = 0; x < rgd->rd_length; x++) {
1183560b8ebaSAndreas Gruenbacher bi = rgd->rd_bits + x;
1184560b8ebaSAndreas Gruenbacher set_bit(GBF_FULL, &bi->bi_flags);
1185560b8ebaSAndreas Gruenbacher }
1186560b8ebaSAndreas Gruenbacher }
1187560b8ebaSAndreas Gruenbacher }
118890306c41SBenjamin Marzinski
1189b3b94faaSDavid Teigland /**
11904b3113a2SBob Peterson * gfs2_rgrp_go_instantiate - Read in a RG's header and bitmaps
11914b3113a2SBob Peterson * @gh: the glock holder representing the rgrpd to read in
1192b3b94faaSDavid Teigland *
1193b3b94faaSDavid Teigland * Read in all of a Resource Group's header and bitmap blocks.
119410283ea5SAndreas Gruenbacher * Caller must eventually call gfs2_rgrp_brelse() to free the bitmaps.
1195b3b94faaSDavid Teigland *
1196b3b94faaSDavid Teigland * Returns: errno
1197b3b94faaSDavid Teigland */
1198b3b94faaSDavid Teigland
gfs2_rgrp_go_instantiate(struct gfs2_glock * gl)11995f38a4d3SAndreas Gruenbacher int gfs2_rgrp_go_instantiate(struct gfs2_glock *gl)
1200b3b94faaSDavid Teigland {
12014b3113a2SBob Peterson struct gfs2_rgrpd *rgd = gl->gl_object;
1202b3b94faaSDavid Teigland struct gfs2_sbd *sdp = rgd->rd_sbd;
1203bb8d8a6fSSteven Whitehouse unsigned int length = rgd->rd_length;
1204b3b94faaSDavid Teigland struct gfs2_bitmap *bi;
1205b3b94faaSDavid Teigland unsigned int x, y;
1206b3b94faaSDavid Teigland int error;
1207b3b94faaSDavid Teigland
120890306c41SBenjamin Marzinski if (rgd->rd_bits[0].bi_bh != NULL)
120990306c41SBenjamin Marzinski return 0;
121090306c41SBenjamin Marzinski
1211b3b94faaSDavid Teigland for (x = 0; x < length; x++) {
1212b3b94faaSDavid Teigland bi = rgd->rd_bits + x;
1213c8d57703SAndreas Gruenbacher error = gfs2_meta_read(gl, rgd->rd_addr + x, 0, 0, &bi->bi_bh);
1214b3b94faaSDavid Teigland if (error)
1215b3b94faaSDavid Teigland goto fail;
1216b3b94faaSDavid Teigland }
1217b3b94faaSDavid Teigland
1218b3b94faaSDavid Teigland for (y = length; y--;) {
1219b3b94faaSDavid Teigland bi = rgd->rd_bits + y;
12207276b3b0SSteven Whitehouse error = gfs2_meta_wait(sdp, bi->bi_bh);
1221b3b94faaSDavid Teigland if (error)
1222b3b94faaSDavid Teigland goto fail;
1223feaa7bbaSSteven Whitehouse if (gfs2_metatype_check(sdp, bi->bi_bh, y ? GFS2_METATYPE_RB :
1224b3b94faaSDavid Teigland GFS2_METATYPE_RG)) {
1225b3b94faaSDavid Teigland error = -EIO;
1226b3b94faaSDavid Teigland goto fail;
1227b3b94faaSDavid Teigland }
1228b3b94faaSDavid Teigland }
1229b3b94faaSDavid Teigland
123042d52e38SBob Peterson gfs2_rgrp_in(rgd, (rgd->rd_bits[0].bi_bh)->b_data);
1231560b8ebaSAndreas Gruenbacher rgrp_set_bitmap_flags(rgd);
12324b3113a2SBob Peterson rgd->rd_flags |= GFS2_RDF_CHECK;
1233cfc8b549SSteven Whitehouse rgd->rd_free_clone = rgd->rd_free;
1234c98c2ca5SBob Peterson GLOCK_BUG_ON(rgd->rd_gl, rgd->rd_reserved);
12355ea5050cSBob Peterson /* max out the rgrp allocation failure point */
12365ea5050cSBob Peterson rgd->rd_extfail_pt = rgd->rd_free;
1237951b4bd5SAl Viro if (cpu_to_be32(GFS2_MAGIC) != rgd->rd_rgl->rl_magic) {
123890306c41SBenjamin Marzinski rgd->rd_rgl->rl_unlinked = cpu_to_be32(count_unlinked(rgd));
123990306c41SBenjamin Marzinski gfs2_rgrp_ondisk2lvb(rgd->rd_rgl,
124090306c41SBenjamin Marzinski rgd->rd_bits[0].bi_bh->b_data);
1241f2e70d8fSBob Peterson } else if (sdp->sd_args.ar_rgrplvb) {
124290306c41SBenjamin Marzinski if (!gfs2_rgrp_lvb_valid(rgd)){
124390306c41SBenjamin Marzinski gfs2_consist_rgrpd(rgd);
124490306c41SBenjamin Marzinski error = -EIO;
124590306c41SBenjamin Marzinski goto fail;
124690306c41SBenjamin Marzinski }
124790306c41SBenjamin Marzinski if (rgd->rd_rgl->rl_unlinked == 0)
124890306c41SBenjamin Marzinski rgd->rd_flags &= ~GFS2_RDF_CHECK;
124990306c41SBenjamin Marzinski }
1250b3b94faaSDavid Teigland return 0;
1251b3b94faaSDavid Teigland
1252b3b94faaSDavid Teigland fail:
1253b3b94faaSDavid Teigland while (x--) {
1254b3b94faaSDavid Teigland bi = rgd->rd_bits + x;
1255b3b94faaSDavid Teigland brelse(bi->bi_bh);
1256b3b94faaSDavid Teigland bi->bi_bh = NULL;
1257b3b94faaSDavid Teigland gfs2_assert_warn(sdp, !bi->bi_clone);
1258b3b94faaSDavid Teigland }
1259b3b94faaSDavid Teigland return error;
1260b3b94faaSDavid Teigland }
1261b3b94faaSDavid Teigland
update_rgrp_lvb(struct gfs2_rgrpd * rgd,struct gfs2_holder * gh)1262f2e70d8fSBob Peterson static int update_rgrp_lvb(struct gfs2_rgrpd *rgd, struct gfs2_holder *gh)
126390306c41SBenjamin Marzinski {
126490306c41SBenjamin Marzinski u32 rl_flags;
126590306c41SBenjamin Marzinski
12664b3113a2SBob Peterson if (!test_bit(GLF_INSTANTIATE_NEEDED, &gh->gh_gl->gl_flags))
126790306c41SBenjamin Marzinski return 0;
126890306c41SBenjamin Marzinski
1269951b4bd5SAl Viro if (cpu_to_be32(GFS2_MAGIC) != rgd->rd_rgl->rl_magic)
1270f2e70d8fSBob Peterson return gfs2_instantiate(gh);
127190306c41SBenjamin Marzinski
127290306c41SBenjamin Marzinski rl_flags = be32_to_cpu(rgd->rd_rgl->rl_flags);
127390306c41SBenjamin Marzinski rl_flags &= ~GFS2_RDF_MASK;
127490306c41SBenjamin Marzinski rgd->rd_flags &= GFS2_RDF_MASK;
12754f36cb36SBob Peterson rgd->rd_flags |= (rl_flags | GFS2_RDF_CHECK);
127690306c41SBenjamin Marzinski if (rgd->rd_rgl->rl_unlinked == 0)
127790306c41SBenjamin Marzinski rgd->rd_flags &= ~GFS2_RDF_CHECK;
127890306c41SBenjamin Marzinski rgd->rd_free = be32_to_cpu(rgd->rd_rgl->rl_free);
1279560b8ebaSAndreas Gruenbacher rgrp_set_bitmap_flags(rgd);
128090306c41SBenjamin Marzinski rgd->rd_free_clone = rgd->rd_free;
1281c98c2ca5SBob Peterson GLOCK_BUG_ON(rgd->rd_gl, rgd->rd_reserved);
1282f38e998fSAndreas Gruenbacher /* max out the rgrp allocation failure point */
1283f38e998fSAndreas Gruenbacher rgd->rd_extfail_pt = rgd->rd_free;
128490306c41SBenjamin Marzinski rgd->rd_dinodes = be32_to_cpu(rgd->rd_rgl->rl_dinodes);
128590306c41SBenjamin Marzinski rgd->rd_igeneration = be64_to_cpu(rgd->rd_rgl->rl_igeneration);
128690306c41SBenjamin Marzinski return 0;
128790306c41SBenjamin Marzinski }
128890306c41SBenjamin Marzinski
1289b3b94faaSDavid Teigland /**
129039b0f1e9SBob Peterson * gfs2_rgrp_brelse - Release RG bitmaps read in with gfs2_rgrp_bh_get()
129139b0f1e9SBob Peterson * @rgd: The resource group
1292b3b94faaSDavid Teigland *
1293b3b94faaSDavid Teigland */
1294b3b94faaSDavid Teigland
gfs2_rgrp_brelse(struct gfs2_rgrpd * rgd)129539b0f1e9SBob Peterson void gfs2_rgrp_brelse(struct gfs2_rgrpd *rgd)
1296b3b94faaSDavid Teigland {
1297bb8d8a6fSSteven Whitehouse int x, length = rgd->rd_length;
1298b3b94faaSDavid Teigland
1299b3b94faaSDavid Teigland for (x = 0; x < length; x++) {
1300b3b94faaSDavid Teigland struct gfs2_bitmap *bi = rgd->rd_bits + x;
130190306c41SBenjamin Marzinski if (bi->bi_bh) {
1302b3b94faaSDavid Teigland brelse(bi->bi_bh);
1303b3b94faaSDavid Teigland bi->bi_bh = NULL;
1304b3b94faaSDavid Teigland }
130590306c41SBenjamin Marzinski }
1306f2e70d8fSBob Peterson set_bit(GLF_INSTANTIATE_NEEDED, &rgd->rd_gl->gl_flags);
130739b0f1e9SBob Peterson }
130839b0f1e9SBob Peterson
gfs2_rgrp_send_discards(struct gfs2_sbd * sdp,u64 offset,struct buffer_head * bh,const struct gfs2_bitmap * bi,unsigned minlen,u64 * ptrimmed)130966fc061bSSteven Whitehouse int gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset,
13107c9ca621SBob Peterson struct buffer_head *bh,
131166fc061bSSteven Whitehouse const struct gfs2_bitmap *bi, unsigned minlen, u64 *ptrimmed)
1312f15ab561SSteven Whitehouse {
1313f15ab561SSteven Whitehouse struct super_block *sb = sdp->sd_vfs;
1314f15ab561SSteven Whitehouse u64 blk;
131564d576baSSteven Whitehouse sector_t start = 0;
1316b2c87caeSBob Peterson sector_t nr_blks = 0;
1317f4a47561SAndrew Price int rv = -EIO;
1318f15ab561SSteven Whitehouse unsigned int x;
131966fc061bSSteven Whitehouse u32 trimmed = 0;
132066fc061bSSteven Whitehouse u8 diff;
1321f15ab561SSteven Whitehouse
1322281b4952SAndreas Gruenbacher for (x = 0; x < bi->bi_bytes; x++) {
132366fc061bSSteven Whitehouse const u8 *clone = bi->bi_clone ? bi->bi_clone : bi->bi_bh->b_data;
132466fc061bSSteven Whitehouse clone += bi->bi_offset;
132566fc061bSSteven Whitehouse clone += x;
132666fc061bSSteven Whitehouse if (bh) {
13277c9ca621SBob Peterson const u8 *orig = bh->b_data + bi->bi_offset + x;
132866fc061bSSteven Whitehouse diff = ~(*orig | (*orig >> 1)) & (*clone | (*clone >> 1));
132966fc061bSSteven Whitehouse } else {
133066fc061bSSteven Whitehouse diff = ~(*clone | (*clone >> 1));
133166fc061bSSteven Whitehouse }
1332f15ab561SSteven Whitehouse diff &= 0x55;
1333f15ab561SSteven Whitehouse if (diff == 0)
1334f15ab561SSteven Whitehouse continue;
1335f15ab561SSteven Whitehouse blk = offset + ((bi->bi_start + x) * GFS2_NBBY);
1336f15ab561SSteven Whitehouse while(diff) {
1337f15ab561SSteven Whitehouse if (diff & 1) {
1338b2c87caeSBob Peterson if (nr_blks == 0)
1339f15ab561SSteven Whitehouse goto start_new_extent;
1340b2c87caeSBob Peterson if ((start + nr_blks) != blk) {
1341b2c87caeSBob Peterson if (nr_blks >= minlen) {
1342b2c87caeSBob Peterson rv = sb_issue_discard(sb,
1343b2c87caeSBob Peterson start, nr_blks,
134466fc061bSSteven Whitehouse GFP_NOFS, 0);
1345f15ab561SSteven Whitehouse if (rv)
1346f15ab561SSteven Whitehouse goto fail;
1347b2c87caeSBob Peterson trimmed += nr_blks;
134866fc061bSSteven Whitehouse }
1349b2c87caeSBob Peterson nr_blks = 0;
1350f15ab561SSteven Whitehouse start_new_extent:
1351f15ab561SSteven Whitehouse start = blk;
1352f15ab561SSteven Whitehouse }
1353b2c87caeSBob Peterson nr_blks++;
1354f15ab561SSteven Whitehouse }
1355f15ab561SSteven Whitehouse diff >>= 2;
1356b2c87caeSBob Peterson blk++;
1357f15ab561SSteven Whitehouse }
1358f15ab561SSteven Whitehouse }
1359b2c87caeSBob Peterson if (nr_blks >= minlen) {
1360b2c87caeSBob Peterson rv = sb_issue_discard(sb, start, nr_blks, GFP_NOFS, 0);
1361f15ab561SSteven Whitehouse if (rv)
1362f15ab561SSteven Whitehouse goto fail;
1363b2c87caeSBob Peterson trimmed += nr_blks;
1364f15ab561SSteven Whitehouse }
136566fc061bSSteven Whitehouse if (ptrimmed)
136666fc061bSSteven Whitehouse *ptrimmed = trimmed;
136766fc061bSSteven Whitehouse return 0;
136866fc061bSSteven Whitehouse
1369f15ab561SSteven Whitehouse fail:
137066fc061bSSteven Whitehouse if (sdp->sd_args.ar_discard)
1371af38816eSAndreas Gruenbacher fs_warn(sdp, "error %d on discard request, turning discards off for this filesystem\n", rv);
1372f15ab561SSteven Whitehouse sdp->sd_args.ar_discard = 0;
1373f4a47561SAndrew Price return rv;
137466fc061bSSteven Whitehouse }
137566fc061bSSteven Whitehouse
137666fc061bSSteven Whitehouse /**
137766fc061bSSteven Whitehouse * gfs2_fitrim - Generate discard requests for unused bits of the filesystem
137866fc061bSSteven Whitehouse * @filp: Any file on the filesystem
137966fc061bSSteven Whitehouse * @argp: Pointer to the arguments (also used to pass result)
138066fc061bSSteven Whitehouse *
138166fc061bSSteven Whitehouse * Returns: 0 on success, otherwise error code
138266fc061bSSteven Whitehouse */
138366fc061bSSteven Whitehouse
gfs2_fitrim(struct file * filp,void __user * argp)138466fc061bSSteven Whitehouse int gfs2_fitrim(struct file *filp, void __user *argp)
138566fc061bSSteven Whitehouse {
1386496ad9aaSAl Viro struct inode *inode = file_inode(filp);
138766fc061bSSteven Whitehouse struct gfs2_sbd *sdp = GFS2_SB(inode);
13887b47ef52SChristoph Hellwig struct block_device *bdev = sdp->sd_vfs->s_bdev;
138966fc061bSSteven Whitehouse struct buffer_head *bh;
139066fc061bSSteven Whitehouse struct gfs2_rgrpd *rgd;
139166fc061bSSteven Whitehouse struct gfs2_rgrpd *rgd_end;
139266fc061bSSteven Whitehouse struct gfs2_holder gh;
139366fc061bSSteven Whitehouse struct fstrim_range r;
139466fc061bSSteven Whitehouse int ret = 0;
139566fc061bSSteven Whitehouse u64 amt;
139666fc061bSSteven Whitehouse u64 trimmed = 0;
1397076f0faaSLukas Czerner u64 start, end, minlen;
139866fc061bSSteven Whitehouse unsigned int x;
1399076f0faaSLukas Czerner unsigned bs_shift = sdp->sd_sb.sb_bsize_shift;
140066fc061bSSteven Whitehouse
140166fc061bSSteven Whitehouse if (!capable(CAP_SYS_ADMIN))
140266fc061bSSteven Whitehouse return -EPERM;
140366fc061bSSteven Whitehouse
1404c5c68724SBob Peterson if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))
1405c5c68724SBob Peterson return -EROFS;
1406c5c68724SBob Peterson
14077b47ef52SChristoph Hellwig if (!bdev_max_discard_sectors(bdev))
140866fc061bSSteven Whitehouse return -EOPNOTSUPP;
140966fc061bSSteven Whitehouse
14103a238adeSLukas Czerner if (copy_from_user(&r, argp, sizeof(r)))
141166fc061bSSteven Whitehouse return -EFAULT;
141266fc061bSSteven Whitehouse
14135e2f7d61SBob Peterson ret = gfs2_rindex_update(sdp);
14145e2f7d61SBob Peterson if (ret)
14155e2f7d61SBob Peterson return ret;
14165e2f7d61SBob Peterson
1417076f0faaSLukas Czerner start = r.start >> bs_shift;
1418076f0faaSLukas Czerner end = start + (r.len >> bs_shift);
141927ca8273SAndrew Price minlen = max_t(u64, r.minlen, sdp->sd_sb.sb_bsize);
14207b47ef52SChristoph Hellwig minlen = max_t(u64, minlen, bdev_discard_granularity(bdev)) >> bs_shift;
1421076f0faaSLukas Czerner
14226a98c333SAbhijith Das if (end <= start || minlen > sdp->sd_max_rg_data)
1423076f0faaSLukas Czerner return -EINVAL;
142466fc061bSSteven Whitehouse
14256a98c333SAbhijith Das rgd = gfs2_blk2rgrpd(sdp, start, 0);
14266a98c333SAbhijith Das rgd_end = gfs2_blk2rgrpd(sdp, end, 0);
14276a98c333SAbhijith Das
14286a98c333SAbhijith Das if ((gfs2_rgrpd_get_first(sdp) == gfs2_rgrpd_get_next(rgd_end))
14296a98c333SAbhijith Das && (start > rgd_end->rd_data0 + rgd_end->rd_data))
14306a98c333SAbhijith Das return -EINVAL; /* start is beyond the end of the fs */
14316a98c333SAbhijith Das
143266fc061bSSteven Whitehouse while (1) {
143366fc061bSSteven Whitehouse
14344fc7ec31SBob Peterson ret = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE,
14354fc7ec31SBob Peterson LM_FLAG_NODE_SCOPE, &gh);
143666fc061bSSteven Whitehouse if (ret)
143766fc061bSSteven Whitehouse goto out;
143866fc061bSSteven Whitehouse
143966fc061bSSteven Whitehouse if (!(rgd->rd_flags & GFS2_RGF_TRIMMED)) {
144066fc061bSSteven Whitehouse /* Trim each bitmap in the rgrp */
144166fc061bSSteven Whitehouse for (x = 0; x < rgd->rd_length; x++) {
144266fc061bSSteven Whitehouse struct gfs2_bitmap *bi = rgd->rd_bits + x;
14439e514605SAndreas Gruenbacher rgrp_lock_local(rgd);
1444076f0faaSLukas Czerner ret = gfs2_rgrp_send_discards(sdp,
1445076f0faaSLukas Czerner rgd->rd_data0, NULL, bi, minlen,
1446076f0faaSLukas Czerner &amt);
14479e514605SAndreas Gruenbacher rgrp_unlock_local(rgd);
144866fc061bSSteven Whitehouse if (ret) {
144966fc061bSSteven Whitehouse gfs2_glock_dq_uninit(&gh);
145066fc061bSSteven Whitehouse goto out;
145166fc061bSSteven Whitehouse }
145266fc061bSSteven Whitehouse trimmed += amt;
145366fc061bSSteven Whitehouse }
145466fc061bSSteven Whitehouse
145566fc061bSSteven Whitehouse /* Mark rgrp as having been trimmed */
145666fc061bSSteven Whitehouse ret = gfs2_trans_begin(sdp, RES_RG_HDR, 0);
145766fc061bSSteven Whitehouse if (ret == 0) {
145866fc061bSSteven Whitehouse bh = rgd->rd_bits[0].bi_bh;
14599e514605SAndreas Gruenbacher rgrp_lock_local(rgd);
146066fc061bSSteven Whitehouse rgd->rd_flags |= GFS2_RGF_TRIMMED;
1461350a9b0aSSteven Whitehouse gfs2_trans_add_meta(rgd->rd_gl, bh);
146266fc061bSSteven Whitehouse gfs2_rgrp_out(rgd, bh->b_data);
14639e514605SAndreas Gruenbacher rgrp_unlock_local(rgd);
146466fc061bSSteven Whitehouse gfs2_trans_end(sdp);
146566fc061bSSteven Whitehouse }
146666fc061bSSteven Whitehouse }
146766fc061bSSteven Whitehouse gfs2_glock_dq_uninit(&gh);
146866fc061bSSteven Whitehouse
146966fc061bSSteven Whitehouse if (rgd == rgd_end)
147066fc061bSSteven Whitehouse break;
147166fc061bSSteven Whitehouse
147266fc061bSSteven Whitehouse rgd = gfs2_rgrpd_get_next(rgd);
147366fc061bSSteven Whitehouse }
147466fc061bSSteven Whitehouse
147566fc061bSSteven Whitehouse out:
14766a98c333SAbhijith Das r.len = trimmed << bs_shift;
14773a238adeSLukas Czerner if (copy_to_user(argp, &r, sizeof(r)))
147866fc061bSSteven Whitehouse return -EFAULT;
147966fc061bSSteven Whitehouse
148066fc061bSSteven Whitehouse return ret;
1481f15ab561SSteven Whitehouse }
1482f15ab561SSteven Whitehouse
1483b3b94faaSDavid Teigland /**
14848e2e0047SBob Peterson * rs_insert - insert a new multi-block reservation into the rgrp's rb_tree
14858e2e0047SBob Peterson * @ip: the inode structure
14868e2e0047SBob Peterson *
14878e2e0047SBob Peterson */
rs_insert(struct gfs2_inode * ip)1488ff7f4cb4SSteven Whitehouse static void rs_insert(struct gfs2_inode *ip)
14898e2e0047SBob Peterson {
14908e2e0047SBob Peterson struct rb_node **newn, *parent = NULL;
14918e2e0047SBob Peterson int rc;
1492a097dc7eSBob Peterson struct gfs2_blkreserv *rs = &ip->i_res;
1493c65b76b8SAndreas Gruenbacher struct gfs2_rgrpd *rgd = rs->rs_rgd;
1494ff7f4cb4SSteven Whitehouse
1495ff7f4cb4SSteven Whitehouse BUG_ON(gfs2_rs_active(rs));
14968e2e0047SBob Peterson
14978e2e0047SBob Peterson spin_lock(&rgd->rd_rsspin);
14988e2e0047SBob Peterson newn = &rgd->rd_rstree.rb_node;
14998e2e0047SBob Peterson while (*newn) {
15008e2e0047SBob Peterson struct gfs2_blkreserv *cur =
15018e2e0047SBob Peterson rb_entry(*newn, struct gfs2_blkreserv, rs_node);
15028e2e0047SBob Peterson
15038e2e0047SBob Peterson parent = *newn;
150407974d2aSAndreas Gruenbacher rc = rs_cmp(rs->rs_start, rs->rs_requested, cur);
15058e2e0047SBob Peterson if (rc > 0)
15068e2e0047SBob Peterson newn = &((*newn)->rb_right);
15078e2e0047SBob Peterson else if (rc < 0)
15088e2e0047SBob Peterson newn = &((*newn)->rb_left);
15098e2e0047SBob Peterson else {
15108e2e0047SBob Peterson spin_unlock(&rgd->rd_rsspin);
1511ff7f4cb4SSteven Whitehouse WARN_ON(1);
1512ff7f4cb4SSteven Whitehouse return;
15138e2e0047SBob Peterson }
15148e2e0047SBob Peterson }
15158e2e0047SBob Peterson
15168e2e0047SBob Peterson rb_link_node(&rs->rs_node, parent, newn);
15178e2e0047SBob Peterson rb_insert_color(&rs->rs_node, &rgd->rd_rstree);
15188e2e0047SBob Peterson
15198e2e0047SBob Peterson /* Do our rgrp accounting for the reservation */
152007974d2aSAndreas Gruenbacher rgd->rd_requested += rs->rs_requested; /* blocks requested */
15218e2e0047SBob Peterson spin_unlock(&rgd->rd_rsspin);
15229e733d39SSteven Whitehouse trace_gfs2_rs(rs, TRACE_RS_INSERT);
15238e2e0047SBob Peterson }
15248e2e0047SBob Peterson
15258e2e0047SBob Peterson /**
1526c551f66cSLee Jones * rgd_free - return the number of free blocks we can allocate
1527f6753df3SBob Peterson * @rgd: the resource group
1528c551f66cSLee Jones * @rs: The reservation to free
1529f6753df3SBob Peterson *
1530f6753df3SBob Peterson * This function returns the number of free blocks for an rgrp.
1531f6753df3SBob Peterson * That's the clone-free blocks (blocks that are free, not including those
1532f6753df3SBob Peterson * still being used for unlinked files that haven't been deleted.)
1533f6753df3SBob Peterson *
1534f6753df3SBob Peterson * It also subtracts any blocks reserved by someone else, but does not
1535f6753df3SBob Peterson * include free blocks that are still part of our current reservation,
1536f6753df3SBob Peterson * because obviously we can (and will) allocate them.
1537f6753df3SBob Peterson */
rgd_free(struct gfs2_rgrpd * rgd,struct gfs2_blkreserv * rs)1538f6753df3SBob Peterson static inline u32 rgd_free(struct gfs2_rgrpd *rgd, struct gfs2_blkreserv *rs)
1539f6753df3SBob Peterson {
1540f6753df3SBob Peterson u32 tot_reserved, tot_free;
1541f6753df3SBob Peterson
154207974d2aSAndreas Gruenbacher if (WARN_ON_ONCE(rgd->rd_requested < rs->rs_requested))
1543f6753df3SBob Peterson return 0;
154407974d2aSAndreas Gruenbacher tot_reserved = rgd->rd_requested - rs->rs_requested;
1545f6753df3SBob Peterson
1546f6753df3SBob Peterson if (rgd->rd_free_clone < tot_reserved)
1547f6753df3SBob Peterson tot_reserved = 0;
1548f6753df3SBob Peterson
1549f6753df3SBob Peterson tot_free = rgd->rd_free_clone - tot_reserved;
1550f6753df3SBob Peterson
1551f6753df3SBob Peterson return tot_free;
1552f6753df3SBob Peterson }
1553f6753df3SBob Peterson
1554f6753df3SBob Peterson /**
1555ff7f4cb4SSteven Whitehouse * rg_mblk_search - find a group of multiple free blocks to form a reservation
15568e2e0047SBob Peterson * @rgd: the resource group descriptor
15578e2e0047SBob Peterson * @ip: pointer to the inode for which we're reserving blocks
15587b9cff46SSteven Whitehouse * @ap: the allocation parameters
15598e2e0047SBob Peterson *
15608e2e0047SBob Peterson */
15618e2e0047SBob Peterson
rg_mblk_search(struct gfs2_rgrpd * rgd,struct gfs2_inode * ip,const struct gfs2_alloc_parms * ap)1562ff7f4cb4SSteven Whitehouse static void rg_mblk_search(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip,
15637b9cff46SSteven Whitehouse const struct gfs2_alloc_parms *ap)
15648e2e0047SBob Peterson {
1565ff7f4cb4SSteven Whitehouse struct gfs2_rbm rbm = { .rgd = rgd, };
1566ff7f4cb4SSteven Whitehouse u64 goal;
1567a097dc7eSBob Peterson struct gfs2_blkreserv *rs = &ip->i_res;
1568ff7f4cb4SSteven Whitehouse u32 extlen;
1569725d0e9dSAndreas Gruenbacher u32 free_blocks, blocks_available;
1570ff7f4cb4SSteven Whitehouse int ret;
1571af21ca8eSBob Peterson struct inode *inode = &ip->i_inode;
15728e2e0047SBob Peterson
1573725d0e9dSAndreas Gruenbacher spin_lock(&rgd->rd_rsspin);
1574725d0e9dSAndreas Gruenbacher free_blocks = rgd_free(rgd, rs);
1575725d0e9dSAndreas Gruenbacher if (rgd->rd_free_clone < rgd->rd_requested)
1576725d0e9dSAndreas Gruenbacher free_blocks = 0;
1577725d0e9dSAndreas Gruenbacher blocks_available = rgd->rd_free_clone - rgd->rd_reserved;
1578725d0e9dSAndreas Gruenbacher if (rgd == rs->rs_rgd)
1579725d0e9dSAndreas Gruenbacher blocks_available += rs->rs_reserved;
1580725d0e9dSAndreas Gruenbacher spin_unlock(&rgd->rd_rsspin);
1581725d0e9dSAndreas Gruenbacher
1582af21ca8eSBob Peterson if (S_ISDIR(inode->i_mode))
1583af21ca8eSBob Peterson extlen = 1;
1584af21ca8eSBob Peterson else {
158521f09c43SAndreas Gruenbacher extlen = max_t(u32, atomic_read(&ip->i_sizehint), ap->target);
1586ad899458SAndreas Gruenbacher extlen = clamp(extlen, (u32)RGRP_RSRV_MINBLKS, free_blocks);
1587af21ca8eSBob Peterson }
1588725d0e9dSAndreas Gruenbacher if (free_blocks < extlen || blocks_available < extlen)
1589c743ffd0SSteven Whitehouse return;
1590c743ffd0SSteven Whitehouse
15918e2e0047SBob Peterson /* Find bitmap block that contains bits for goal block */
15928e2e0047SBob Peterson if (rgrp_contains_block(rgd, ip->i_goal))
1593ff7f4cb4SSteven Whitehouse goal = ip->i_goal;
15948e2e0047SBob Peterson else
1595ff7f4cb4SSteven Whitehouse goal = rgd->rd_last_alloc + rgd->rd_data0;
1596c743ffd0SSteven Whitehouse
1597ff7f4cb4SSteven Whitehouse if (WARN_ON(gfs2_rbm_from_block(&rbm, goal)))
1598c743ffd0SSteven Whitehouse return;
1599ff7f4cb4SSteven Whitehouse
16003d39fcd1SAndreas Gruenbacher ret = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, &extlen, &ip->i_res, true);
1601ff7f4cb4SSteven Whitehouse if (ret == 0) {
1602c65b76b8SAndreas Gruenbacher rs->rs_start = gfs2_rbm_to_block(&rbm);
160307974d2aSAndreas Gruenbacher rs->rs_requested = extlen;
1604ff7f4cb4SSteven Whitehouse rs_insert(ip);
160513d2eb01SBob Peterson } else {
160613d2eb01SBob Peterson if (goal == rgd->rd_last_alloc + rgd->rd_data0)
160713d2eb01SBob Peterson rgd->rd_last_alloc = 0;
16088e2e0047SBob Peterson }
1609b3e47ca0SBob Peterson }
1610b3e47ca0SBob Peterson
1611b3b94faaSDavid Teigland /**
16125b924ae2SSteven Whitehouse * gfs2_next_unreserved_block - Return next block that is not reserved
16135b924ae2SSteven Whitehouse * @rgd: The resource group
16145b924ae2SSteven Whitehouse * @block: The starting block
1615ff7f4cb4SSteven Whitehouse * @length: The required length
16163d39fcd1SAndreas Gruenbacher * @ignore_rs: Reservation to ignore
16175b924ae2SSteven Whitehouse *
16185b924ae2SSteven Whitehouse * If the block does not appear in any reservation, then return the
16195b924ae2SSteven Whitehouse * block number unchanged. If it does appear in the reservation, then
16205b924ae2SSteven Whitehouse * keep looking through the tree of reservations in order to find the
16215b924ae2SSteven Whitehouse * first block number which is not reserved.
16225b924ae2SSteven Whitehouse */
16235b924ae2SSteven Whitehouse
gfs2_next_unreserved_block(struct gfs2_rgrpd * rgd,u64 block,u32 length,struct gfs2_blkreserv * ignore_rs)16245b924ae2SSteven Whitehouse static u64 gfs2_next_unreserved_block(struct gfs2_rgrpd *rgd, u64 block,
1625ff7f4cb4SSteven Whitehouse u32 length,
16263d39fcd1SAndreas Gruenbacher struct gfs2_blkreserv *ignore_rs)
16275b924ae2SSteven Whitehouse {
16285b924ae2SSteven Whitehouse struct gfs2_blkreserv *rs;
16295b924ae2SSteven Whitehouse struct rb_node *n;
16305b924ae2SSteven Whitehouse int rc;
16315b924ae2SSteven Whitehouse
16325b924ae2SSteven Whitehouse spin_lock(&rgd->rd_rsspin);
1633ff7f4cb4SSteven Whitehouse n = rgd->rd_rstree.rb_node;
16345b924ae2SSteven Whitehouse while (n) {
16355b924ae2SSteven Whitehouse rs = rb_entry(n, struct gfs2_blkreserv, rs_node);
1636ff7f4cb4SSteven Whitehouse rc = rs_cmp(block, length, rs);
16375b924ae2SSteven Whitehouse if (rc < 0)
16385b924ae2SSteven Whitehouse n = n->rb_left;
16395b924ae2SSteven Whitehouse else if (rc > 0)
16405b924ae2SSteven Whitehouse n = n->rb_right;
16415b924ae2SSteven Whitehouse else
16425b924ae2SSteven Whitehouse break;
16435b924ae2SSteven Whitehouse }
16445b924ae2SSteven Whitehouse
16455b924ae2SSteven Whitehouse if (n) {
16463d39fcd1SAndreas Gruenbacher while (rs_cmp(block, length, rs) == 0 && rs != ignore_rs) {
164707974d2aSAndreas Gruenbacher block = rs->rs_start + rs->rs_requested;
1648ff7f4cb4SSteven Whitehouse n = n->rb_right;
16495b924ae2SSteven Whitehouse if (n == NULL)
16505b924ae2SSteven Whitehouse break;
16515b924ae2SSteven Whitehouse rs = rb_entry(n, struct gfs2_blkreserv, rs_node);
16525b924ae2SSteven Whitehouse }
16535b924ae2SSteven Whitehouse }
16545b924ae2SSteven Whitehouse
16555b924ae2SSteven Whitehouse spin_unlock(&rgd->rd_rsspin);
16565b924ae2SSteven Whitehouse return block;
16575b924ae2SSteven Whitehouse }
16585b924ae2SSteven Whitehouse
16595b924ae2SSteven Whitehouse /**
16605b924ae2SSteven Whitehouse * gfs2_reservation_check_and_update - Check for reservations during block alloc
16615b924ae2SSteven Whitehouse * @rbm: The current position in the resource group
16623d39fcd1SAndreas Gruenbacher * @rs: Our own reservation
1663ff7f4cb4SSteven Whitehouse * @minext: The minimum extent length
16645ce13431SBob Peterson * @maxext: A pointer to the maximum extent structure
16655b924ae2SSteven Whitehouse *
16665b924ae2SSteven Whitehouse * This checks the current position in the rgrp to see whether there is
16675b924ae2SSteven Whitehouse * a reservation covering this block. If not then this function is a
16685b924ae2SSteven Whitehouse * no-op. If there is, then the position is moved to the end of the
16695b924ae2SSteven Whitehouse * contiguous reservation(s) so that we are pointing at the first
16705b924ae2SSteven Whitehouse * non-reserved block.
16715b924ae2SSteven Whitehouse *
16725b924ae2SSteven Whitehouse * Returns: 0 if no reservation, 1 if @rbm has changed, otherwise an error
16735b924ae2SSteven Whitehouse */
16745b924ae2SSteven Whitehouse
gfs2_reservation_check_and_update(struct gfs2_rbm * rbm,struct gfs2_blkreserv * rs,u32 minext,struct gfs2_extent * maxext)16755b924ae2SSteven Whitehouse static int gfs2_reservation_check_and_update(struct gfs2_rbm *rbm,
16763d39fcd1SAndreas Gruenbacher struct gfs2_blkreserv *rs,
16775ce13431SBob Peterson u32 minext,
16785ce13431SBob Peterson struct gfs2_extent *maxext)
16795b924ae2SSteven Whitehouse {
16805b924ae2SSteven Whitehouse u64 block = gfs2_rbm_to_block(rbm);
1681ff7f4cb4SSteven Whitehouse u32 extlen = 1;
16825b924ae2SSteven Whitehouse u64 nblock;
16835b924ae2SSteven Whitehouse
1684ff7f4cb4SSteven Whitehouse /*
1685ff7f4cb4SSteven Whitehouse * If we have a minimum extent length, then skip over any extent
1686ff7f4cb4SSteven Whitehouse * which is less than the min extent length in size.
1687ff7f4cb4SSteven Whitehouse */
1688f38e998fSAndreas Gruenbacher if (minext > 1) {
1689ff7f4cb4SSteven Whitehouse extlen = gfs2_free_extlen(rbm, minext);
16905ce13431SBob Peterson if (extlen <= maxext->len)
1691ff7f4cb4SSteven Whitehouse goto fail;
1692ff7f4cb4SSteven Whitehouse }
1693ff7f4cb4SSteven Whitehouse
1694ff7f4cb4SSteven Whitehouse /*
1695ff7f4cb4SSteven Whitehouse * Check the extent which has been found against the reservations
1696ff7f4cb4SSteven Whitehouse * and skip if parts of it are already reserved
1697ff7f4cb4SSteven Whitehouse */
16983d39fcd1SAndreas Gruenbacher nblock = gfs2_next_unreserved_block(rbm->rgd, block, extlen, rs);
16995ce13431SBob Peterson if (nblock == block) {
17005ce13431SBob Peterson if (!minext || extlen >= minext)
17015b924ae2SSteven Whitehouse return 0;
17025ce13431SBob Peterson
17035ce13431SBob Peterson if (extlen > maxext->len) {
17045ce13431SBob Peterson maxext->len = extlen;
17055ce13431SBob Peterson maxext->rbm = *rbm;
17065ce13431SBob Peterson }
17070eacdd16SAndreas Gruenbacher } else {
17080eacdd16SAndreas Gruenbacher u64 len = nblock - block;
17090eacdd16SAndreas Gruenbacher if (len >= (u64)1 << 32)
17100eacdd16SAndreas Gruenbacher return -E2BIG;
17110eacdd16SAndreas Gruenbacher extlen = len;
17125ce13431SBob Peterson }
17130eacdd16SAndreas Gruenbacher fail:
17140eacdd16SAndreas Gruenbacher if (gfs2_rbm_add(rbm, extlen))
17150eacdd16SAndreas Gruenbacher return -E2BIG;
17165b924ae2SSteven Whitehouse return 1;
17175b924ae2SSteven Whitehouse }
17185b924ae2SSteven Whitehouse
17195b924ae2SSteven Whitehouse /**
17205b924ae2SSteven Whitehouse * gfs2_rbm_find - Look for blocks of a particular state
17215b924ae2SSteven Whitehouse * @rbm: Value/result starting position and final position
17225b924ae2SSteven Whitehouse * @state: The state which we want to find
1723f38e998fSAndreas Gruenbacher * @minext: Pointer to the requested extent length
17245ce13431SBob Peterson * This is updated to be the actual reservation size.
17253d39fcd1SAndreas Gruenbacher * @rs: Our own reservation (NULL to skip checking for reservations)
17265b924ae2SSteven Whitehouse * @nowrap: Stop looking at the end of the rgrp, rather than wrapping
17275b924ae2SSteven Whitehouse * around until we've reached the starting point.
17285b924ae2SSteven Whitehouse *
17295b924ae2SSteven Whitehouse * Side effects:
17305b924ae2SSteven Whitehouse * - If looking for free blocks, we set GBF_FULL on each bitmap which
17315b924ae2SSteven Whitehouse * has no free blocks in it.
17325ea5050cSBob Peterson * - If looking for free blocks, we set rd_extfail_pt on each rgrp which
17335ea5050cSBob Peterson * has come up short on a free block search.
17345b924ae2SSteven Whitehouse *
17355b924ae2SSteven Whitehouse * Returns: 0 on success, -ENOSPC if there is no block of the requested state
17365b924ae2SSteven Whitehouse */
17375b924ae2SSteven Whitehouse
gfs2_rbm_find(struct gfs2_rbm * rbm,u8 state,u32 * minext,struct gfs2_blkreserv * rs,bool nowrap)17385ce13431SBob Peterson static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext,
17393d39fcd1SAndreas Gruenbacher struct gfs2_blkreserv *rs, bool nowrap)
17405b924ae2SSteven Whitehouse {
174171921ef8SAndreas Gruenbacher bool scan_from_start = rbm->bii == 0 && rbm->offset == 0;
17425b924ae2SSteven Whitehouse struct buffer_head *bh;
174371921ef8SAndreas Gruenbacher int last_bii;
17445b924ae2SSteven Whitehouse u32 offset;
17455b924ae2SSteven Whitehouse u8 *buffer;
174671921ef8SAndreas Gruenbacher bool wrapped = false;
17475b924ae2SSteven Whitehouse int ret;
1748e579ed4fSBob Peterson struct gfs2_bitmap *bi;
17495ce13431SBob Peterson struct gfs2_extent maxext = { .rbm.rgd = rbm->rgd, };
17505b924ae2SSteven Whitehouse
175171921ef8SAndreas Gruenbacher /*
175271921ef8SAndreas Gruenbacher * Determine the last bitmap to search. If we're not starting at the
175371921ef8SAndreas Gruenbacher * beginning of a bitmap, we need to search that bitmap twice to scan
175471921ef8SAndreas Gruenbacher * the entire resource group.
17555b924ae2SSteven Whitehouse */
175671921ef8SAndreas Gruenbacher last_bii = rbm->bii - (rbm->offset == 0);
17575b924ae2SSteven Whitehouse
17585b924ae2SSteven Whitehouse while(1) {
1759e579ed4fSBob Peterson bi = rbm_bi(rbm);
17602fdc2fa2SAndreas Gruenbacher if (test_bit(GBF_FULL, &bi->bi_flags) &&
17615b924ae2SSteven Whitehouse (state == GFS2_BLKST_FREE))
17625b924ae2SSteven Whitehouse goto next_bitmap;
17635b924ae2SSteven Whitehouse
1764e579ed4fSBob Peterson bh = bi->bi_bh;
1765e579ed4fSBob Peterson buffer = bh->b_data + bi->bi_offset;
17665b924ae2SSteven Whitehouse WARN_ON(!buffer_uptodate(bh));
1767e579ed4fSBob Peterson if (state != GFS2_BLKST_UNLINKED && bi->bi_clone)
1768e579ed4fSBob Peterson buffer = bi->bi_clone + bi->bi_offset;
1769281b4952SAndreas Gruenbacher offset = gfs2_bitfit(buffer, bi->bi_bytes, rbm->offset, state);
177071921ef8SAndreas Gruenbacher if (offset == BFITNOENT) {
177171921ef8SAndreas Gruenbacher if (state == GFS2_BLKST_FREE && rbm->offset == 0)
177271921ef8SAndreas Gruenbacher set_bit(GBF_FULL, &bi->bi_flags);
177371921ef8SAndreas Gruenbacher goto next_bitmap;
177471921ef8SAndreas Gruenbacher }
17755b924ae2SSteven Whitehouse rbm->offset = offset;
1776bea906eeSAndreas Gruenbacher if (!rs || !minext)
17775b924ae2SSteven Whitehouse return 0;
17785b924ae2SSteven Whitehouse
17793d39fcd1SAndreas Gruenbacher ret = gfs2_reservation_check_and_update(rbm, rs, *minext,
17805ce13431SBob Peterson &maxext);
17815b924ae2SSteven Whitehouse if (ret == 0)
17825b924ae2SSteven Whitehouse return 0;
178371921ef8SAndreas Gruenbacher if (ret > 0)
17848d8b752aSBob Peterson goto next_iter;
17855d50d532SSteven Whitehouse if (ret == -E2BIG) {
1786e579ed4fSBob Peterson rbm->bii = 0;
17875d50d532SSteven Whitehouse rbm->offset = 0;
17885d50d532SSteven Whitehouse goto res_covered_end_of_rgrp;
17895d50d532SSteven Whitehouse }
17905b924ae2SSteven Whitehouse return ret;
17915b924ae2SSteven Whitehouse
17925b924ae2SSteven Whitehouse next_bitmap: /* Find next bitmap in the rgrp */
17935b924ae2SSteven Whitehouse rbm->offset = 0;
1794e579ed4fSBob Peterson rbm->bii++;
1795e579ed4fSBob Peterson if (rbm->bii == rbm->rgd->rd_length)
1796e579ed4fSBob Peterson rbm->bii = 0;
17975d50d532SSteven Whitehouse res_covered_end_of_rgrp:
179871921ef8SAndreas Gruenbacher if (rbm->bii == 0) {
179971921ef8SAndreas Gruenbacher if (wrapped)
18005b924ae2SSteven Whitehouse break;
180171921ef8SAndreas Gruenbacher wrapped = true;
180271921ef8SAndreas Gruenbacher if (nowrap)
180371921ef8SAndreas Gruenbacher break;
180471921ef8SAndreas Gruenbacher }
18058d8b752aSBob Peterson next_iter:
180671921ef8SAndreas Gruenbacher /* Have we scanned the entire resource group? */
180771921ef8SAndreas Gruenbacher if (wrapped && rbm->bii > last_bii)
18085b924ae2SSteven Whitehouse break;
18095b924ae2SSteven Whitehouse }
18105b924ae2SSteven Whitehouse
1811f38e998fSAndreas Gruenbacher if (state != GFS2_BLKST_FREE)
18125ce13431SBob Peterson return -ENOSPC;
18135ce13431SBob Peterson
18145ea5050cSBob Peterson /* If the extent was too small, and it's smaller than the smallest
18155ea5050cSBob Peterson to have failed before, remember for future reference that it's
18165ea5050cSBob Peterson useless to search this rgrp again for this amount or more. */
181771921ef8SAndreas Gruenbacher if (wrapped && (scan_from_start || rbm->bii > last_bii) &&
181871921ef8SAndreas Gruenbacher *minext < rbm->rgd->rd_extfail_pt)
1819f38e998fSAndreas Gruenbacher rbm->rgd->rd_extfail_pt = *minext - 1;
18205ea5050cSBob Peterson
18215ce13431SBob Peterson /* If the maximum extent we found is big enough to fulfill the
18225ce13431SBob Peterson minimum requirements, use it anyway. */
18235ce13431SBob Peterson if (maxext.len) {
18245ce13431SBob Peterson *rbm = maxext.rbm;
18255ce13431SBob Peterson *minext = maxext.len;
18265ce13431SBob Peterson return 0;
18275ce13431SBob Peterson }
18285ce13431SBob Peterson
18295b924ae2SSteven Whitehouse return -ENOSPC;
18305b924ae2SSteven Whitehouse }
18315b924ae2SSteven Whitehouse
18325b924ae2SSteven Whitehouse /**
1833c8cdf479SSteven Whitehouse * try_rgrp_unlink - Look for any unlinked, allocated, but unused inodes
1834c8cdf479SSteven Whitehouse * @rgd: The rgrp
1835886b1416SBob Peterson * @last_unlinked: block address of the last dinode we unlinked
1836886b1416SBob Peterson * @skip: block address we should explicitly not unlink
1837c8cdf479SSteven Whitehouse *
18381a0eae88SBob Peterson * Returns: 0 if no error
18391a0eae88SBob Peterson * The inode, if one has been found, in inode.
1840c8cdf479SSteven Whitehouse */
1841c8cdf479SSteven Whitehouse
try_rgrp_unlink(struct gfs2_rgrpd * rgd,u64 * last_unlinked,u64 skip)1842044b9414SSteven Whitehouse static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip)
1843c8cdf479SSteven Whitehouse {
18445b924ae2SSteven Whitehouse u64 block;
18455f3eae75SBob Peterson struct gfs2_sbd *sdp = rgd->rd_sbd;
1846044b9414SSteven Whitehouse struct gfs2_glock *gl;
1847044b9414SSteven Whitehouse struct gfs2_inode *ip;
1848044b9414SSteven Whitehouse int error;
1849044b9414SSteven Whitehouse int found = 0;
1850e579ed4fSBob Peterson struct gfs2_rbm rbm = { .rgd = rgd, .bii = 0, .offset = 0 };
1851c8cdf479SSteven Whitehouse
18525b924ae2SSteven Whitehouse while (1) {
18535ce13431SBob Peterson error = gfs2_rbm_find(&rbm, GFS2_BLKST_UNLINKED, NULL, NULL,
18548381e602SBob Peterson true);
18555b924ae2SSteven Whitehouse if (error == -ENOSPC)
18565b924ae2SSteven Whitehouse break;
18575b924ae2SSteven Whitehouse if (WARN_ON_ONCE(error))
185824c73873SBob Peterson break;
1859b3e47ca0SBob Peterson
18605b924ae2SSteven Whitehouse block = gfs2_rbm_to_block(&rbm);
18615b924ae2SSteven Whitehouse if (gfs2_rbm_from_block(&rbm, block + 1))
18625b924ae2SSteven Whitehouse break;
18635b924ae2SSteven Whitehouse if (*last_unlinked != NO_BLOCK && block <= *last_unlinked)
1864c8cdf479SSteven Whitehouse continue;
18655b924ae2SSteven Whitehouse if (block == skip)
18661e19a195SSteven Whitehouse continue;
18675b924ae2SSteven Whitehouse *last_unlinked = block;
1868044b9414SSteven Whitehouse
18695ea31bc0SBob Peterson error = gfs2_glock_get(sdp, block, &gfs2_iopen_glops, CREATE, &gl);
1870044b9414SSteven Whitehouse if (error)
1871044b9414SSteven Whitehouse continue;
1872044b9414SSteven Whitehouse
1873044b9414SSteven Whitehouse /* If the inode is already in cache, we can ignore it here
1874044b9414SSteven Whitehouse * because the existing inode disposal code will deal with
1875044b9414SSteven Whitehouse * it when all refs have gone away. Accessing gl_object like
1876044b9414SSteven Whitehouse * this is not safe in general. Here it is ok because we do
1877044b9414SSteven Whitehouse * not dereference the pointer, and we only need an approx
1878044b9414SSteven Whitehouse * answer to whether it is NULL or not.
1879044b9414SSteven Whitehouse */
1880044b9414SSteven Whitehouse ip = gl->gl_object;
1881044b9414SSteven Whitehouse
1882*e30cab28SAndreas Gruenbacher if (ip || !gfs2_queue_verify_delete(gl, false))
1883044b9414SSteven Whitehouse gfs2_glock_put(gl);
1884044b9414SSteven Whitehouse else
1885044b9414SSteven Whitehouse found++;
1886044b9414SSteven Whitehouse
1887044b9414SSteven Whitehouse /* Limit reclaim to sensible number of tasks */
188844ad37d6SBob Peterson if (found > NR_CPUS)
1889044b9414SSteven Whitehouse return;
1890c8cdf479SSteven Whitehouse }
1891c8cdf479SSteven Whitehouse
1892c8cdf479SSteven Whitehouse rgd->rd_flags &= ~GFS2_RDF_CHECK;
1893044b9414SSteven Whitehouse return;
1894c8cdf479SSteven Whitehouse }
1895c8cdf479SSteven Whitehouse
1896bcd97c06SSteven Whitehouse /**
1897bcd97c06SSteven Whitehouse * gfs2_rgrp_congested - Use stats to figure out whether an rgrp is congested
1898bcd97c06SSteven Whitehouse * @rgd: The rgrp in question
1899bcd97c06SSteven Whitehouse * @loops: An indication of how picky we can be (0=very, 1=less so)
1900bcd97c06SSteven Whitehouse *
1901bcd97c06SSteven Whitehouse * This function uses the recently added glock statistics in order to
1902bcd97c06SSteven Whitehouse * figure out whether a parciular resource group is suffering from
1903bcd97c06SSteven Whitehouse * contention from multiple nodes. This is done purely on the basis
1904bcd97c06SSteven Whitehouse * of timings, since this is the only data we have to work with and
1905bcd97c06SSteven Whitehouse * our aim here is to reject a resource group which is highly contended
1906bcd97c06SSteven Whitehouse * but (very important) not to do this too often in order to ensure that
1907bcd97c06SSteven Whitehouse * we do not land up introducing fragmentation by changing resource
1908bcd97c06SSteven Whitehouse * groups when not actually required.
1909bcd97c06SSteven Whitehouse *
1910bcd97c06SSteven Whitehouse * The calculation is fairly simple, we want to know whether the SRTTB
1911bcd97c06SSteven Whitehouse * (i.e. smoothed round trip time for blocking operations) to acquire
1912bcd97c06SSteven Whitehouse * the lock for this rgrp's glock is significantly greater than the
1913bcd97c06SSteven Whitehouse * time taken for resource groups on average. We introduce a margin in
1914bcd97c06SSteven Whitehouse * the form of the variable @var which is computed as the sum of the two
1915bcd97c06SSteven Whitehouse * respective variences, and multiplied by a factor depending on @loops
1916bcd97c06SSteven Whitehouse * and whether we have a lot of data to base the decision on. This is
1917bcd97c06SSteven Whitehouse * then tested against the square difference of the means in order to
1918bcd97c06SSteven Whitehouse * decide whether the result is statistically significant or not.
1919bcd97c06SSteven Whitehouse *
1920bcd97c06SSteven Whitehouse * Returns: A boolean verdict on the congestion status
1921bcd97c06SSteven Whitehouse */
1922bcd97c06SSteven Whitehouse
gfs2_rgrp_congested(const struct gfs2_rgrpd * rgd,int loops)1923bcd97c06SSteven Whitehouse static bool gfs2_rgrp_congested(const struct gfs2_rgrpd *rgd, int loops)
1924bcd97c06SSteven Whitehouse {
1925bcd97c06SSteven Whitehouse const struct gfs2_glock *gl = rgd->rd_gl;
192615562c43SBob Peterson const struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
1927bcd97c06SSteven Whitehouse struct gfs2_lkstats *st;
19284d207133SBen Hutchings u64 r_dcount, l_dcount;
19294d207133SBen Hutchings u64 l_srttb, a_srttb = 0;
1930bcd97c06SSteven Whitehouse s64 srttb_diff;
19314d207133SBen Hutchings u64 sqr_diff;
19324d207133SBen Hutchings u64 var;
19330166b197SBob Peterson int cpu, nonzero = 0;
1934bcd97c06SSteven Whitehouse
1935bcd97c06SSteven Whitehouse preempt_disable();
1936f4a3ae93SBob Peterson for_each_present_cpu(cpu) {
1937f4a3ae93SBob Peterson st = &per_cpu_ptr(sdp->sd_lkstats, cpu)->lkstats[LM_TYPE_RGRP];
19380166b197SBob Peterson if (st->stats[GFS2_LKS_SRTTB]) {
1939f4a3ae93SBob Peterson a_srttb += st->stats[GFS2_LKS_SRTTB];
19400166b197SBob Peterson nonzero++;
19410166b197SBob Peterson }
1942f4a3ae93SBob Peterson }
1943bcd97c06SSteven Whitehouse st = &this_cpu_ptr(sdp->sd_lkstats)->lkstats[LM_TYPE_RGRP];
19440166b197SBob Peterson if (nonzero)
19450166b197SBob Peterson do_div(a_srttb, nonzero);
1946bcd97c06SSteven Whitehouse r_dcount = st->stats[GFS2_LKS_DCOUNT];
1947bcd97c06SSteven Whitehouse var = st->stats[GFS2_LKS_SRTTVARB] +
1948bcd97c06SSteven Whitehouse gl->gl_stats.stats[GFS2_LKS_SRTTVARB];
1949bcd97c06SSteven Whitehouse preempt_enable();
1950bcd97c06SSteven Whitehouse
1951bcd97c06SSteven Whitehouse l_srttb = gl->gl_stats.stats[GFS2_LKS_SRTTB];
1952bcd97c06SSteven Whitehouse l_dcount = gl->gl_stats.stats[GFS2_LKS_DCOUNT];
1953bcd97c06SSteven Whitehouse
1954f4a3ae93SBob Peterson if ((l_dcount < 1) || (r_dcount < 1) || (a_srttb == 0))
1955bcd97c06SSteven Whitehouse return false;
1956bcd97c06SSteven Whitehouse
1957f4a3ae93SBob Peterson srttb_diff = a_srttb - l_srttb;
1958bcd97c06SSteven Whitehouse sqr_diff = srttb_diff * srttb_diff;
1959bcd97c06SSteven Whitehouse
1960bcd97c06SSteven Whitehouse var *= 2;
1961bcd97c06SSteven Whitehouse if (l_dcount < 8 || r_dcount < 8)
1962bcd97c06SSteven Whitehouse var *= 2;
1963bcd97c06SSteven Whitehouse if (loops == 1)
1964bcd97c06SSteven Whitehouse var *= 2;
1965bcd97c06SSteven Whitehouse
1966bcd97c06SSteven Whitehouse return ((srttb_diff < 0) && (sqr_diff > var));
1967bcd97c06SSteven Whitehouse }
1968bcd97c06SSteven Whitehouse
1969bcd97c06SSteven Whitehouse /**
1970bcd97c06SSteven Whitehouse * gfs2_rgrp_used_recently
1971bcd97c06SSteven Whitehouse * @rs: The block reservation with the rgrp to test
1972bcd97c06SSteven Whitehouse * @msecs: The time limit in milliseconds
1973bcd97c06SSteven Whitehouse *
1974bcd97c06SSteven Whitehouse * Returns: True if the rgrp glock has been used within the time limit
1975bcd97c06SSteven Whitehouse */
gfs2_rgrp_used_recently(const struct gfs2_blkreserv * rs,u64 msecs)1976bcd97c06SSteven Whitehouse static bool gfs2_rgrp_used_recently(const struct gfs2_blkreserv *rs,
1977bcd97c06SSteven Whitehouse u64 msecs)
1978bcd97c06SSteven Whitehouse {
1979bcd97c06SSteven Whitehouse u64 tdiff;
1980bcd97c06SSteven Whitehouse
1981bcd97c06SSteven Whitehouse tdiff = ktime_to_ns(ktime_sub(ktime_get_real(),
1982c65b76b8SAndreas Gruenbacher rs->rs_rgd->rd_gl->gl_dstamp));
1983bcd97c06SSteven Whitehouse
1984bcd97c06SSteven Whitehouse return tdiff > (msecs * 1000 * 1000);
1985bcd97c06SSteven Whitehouse }
1986bcd97c06SSteven Whitehouse
gfs2_orlov_skip(const struct gfs2_inode * ip)19879dbe9610SSteven Whitehouse static u32 gfs2_orlov_skip(const struct gfs2_inode *ip)
19889dbe9610SSteven Whitehouse {
19899dbe9610SSteven Whitehouse const struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
19909dbe9610SSteven Whitehouse u32 skip;
19919dbe9610SSteven Whitehouse
19929dbe9610SSteven Whitehouse get_random_bytes(&skip, sizeof(skip));
19939dbe9610SSteven Whitehouse return skip % sdp->sd_rgrps;
19949dbe9610SSteven Whitehouse }
19959dbe9610SSteven Whitehouse
gfs2_select_rgrp(struct gfs2_rgrpd ** pos,const struct gfs2_rgrpd * begin)1996c743ffd0SSteven Whitehouse static bool gfs2_select_rgrp(struct gfs2_rgrpd **pos, const struct gfs2_rgrpd *begin)
1997c743ffd0SSteven Whitehouse {
1998c743ffd0SSteven Whitehouse struct gfs2_rgrpd *rgd = *pos;
1999aa8920c9SSteven Whitehouse struct gfs2_sbd *sdp = rgd->rd_sbd;
2000c743ffd0SSteven Whitehouse
2001c743ffd0SSteven Whitehouse rgd = gfs2_rgrpd_get_next(rgd);
2002c743ffd0SSteven Whitehouse if (rgd == NULL)
2003aa8920c9SSteven Whitehouse rgd = gfs2_rgrpd_get_first(sdp);
2004c743ffd0SSteven Whitehouse *pos = rgd;
2005c743ffd0SSteven Whitehouse if (rgd != begin) /* If we didn't wrap */
2006c743ffd0SSteven Whitehouse return true;
2007c743ffd0SSteven Whitehouse return false;
2008c743ffd0SSteven Whitehouse }
2009c743ffd0SSteven Whitehouse
2010c8cdf479SSteven Whitehouse /**
20110e27c18cSBob Peterson * fast_to_acquire - determine if a resource group will be fast to acquire
2012c551f66cSLee Jones * @rgd: The rgrp
20130e27c18cSBob Peterson *
20140e27c18cSBob Peterson * If this is one of our preferred rgrps, it should be quicker to acquire,
20150e27c18cSBob Peterson * because we tried to set ourselves up as dlm lock master.
20160e27c18cSBob Peterson */
fast_to_acquire(struct gfs2_rgrpd * rgd)20170e27c18cSBob Peterson static inline int fast_to_acquire(struct gfs2_rgrpd *rgd)
20180e27c18cSBob Peterson {
20190e27c18cSBob Peterson struct gfs2_glock *gl = rgd->rd_gl;
20200e27c18cSBob Peterson
20210e27c18cSBob Peterson if (gl->gl_state != LM_ST_UNLOCKED && list_empty(&gl->gl_holders) &&
20220e27c18cSBob Peterson !test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags) &&
20230e27c18cSBob Peterson !test_bit(GLF_DEMOTE, &gl->gl_flags))
20240e27c18cSBob Peterson return 1;
20250e27c18cSBob Peterson if (rgd->rd_flags & GFS2_RDF_PREFERRED)
20260e27c18cSBob Peterson return 1;
20270e27c18cSBob Peterson return 0;
20280e27c18cSBob Peterson }
20290e27c18cSBob Peterson
20300e27c18cSBob Peterson /**
2031666d1d8aSBob Peterson * gfs2_inplace_reserve - Reserve space in the filesystem
2032b3b94faaSDavid Teigland * @ip: the inode to reserve space for
20337b9cff46SSteven Whitehouse * @ap: the allocation parameters
2034b3b94faaSDavid Teigland *
203525435e5eSAbhi Das * We try our best to find an rgrp that has at least ap->target blocks
203625435e5eSAbhi Das * available. After a couple of passes (loops == 2), the prospects of finding
203725435e5eSAbhi Das * such an rgrp diminish. At this stage, we return the first rgrp that has
2038725d0e9dSAndreas Gruenbacher * at least ap->min_target blocks available.
203925435e5eSAbhi Das *
204025435e5eSAbhi Das * Returns: 0 on success,
204125435e5eSAbhi Das * -ENOMEM if a suitable rgrp can't be found
204225435e5eSAbhi Das * errno otherwise
2043b3b94faaSDavid Teigland */
2044b3b94faaSDavid Teigland
gfs2_inplace_reserve(struct gfs2_inode * ip,struct gfs2_alloc_parms * ap)204525435e5eSAbhi Das int gfs2_inplace_reserve(struct gfs2_inode *ip, struct gfs2_alloc_parms *ap)
2046b3b94faaSDavid Teigland {
2047feaa7bbaSSteven Whitehouse struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
20488e2e0047SBob Peterson struct gfs2_rgrpd *begin = NULL;
2049a097dc7eSBob Peterson struct gfs2_blkreserv *rs = &ip->i_res;
20504fc7ec31SBob Peterson int error = 0, flags = LM_FLAG_NODE_SCOPE;
20519e514605SAndreas Gruenbacher bool rg_locked;
2052666d1d8aSBob Peterson u64 last_unlinked = NO_BLOCK;
20534272006dSAndreas Gruenbacher u32 target = ap->target;
20547c9ca621SBob Peterson int loops = 0;
2055725d0e9dSAndreas Gruenbacher u32 free_blocks, blocks_available, skip = 0;
2056725d0e9dSAndreas Gruenbacher
2057725d0e9dSAndreas Gruenbacher BUG_ON(rs->rs_reserved);
2058b3b94faaSDavid Teigland
205990306c41SBenjamin Marzinski if (sdp->sd_args.ar_rgrplvb)
206090306c41SBenjamin Marzinski flags |= GL_SKIP;
20614272006dSAndreas Gruenbacher if (gfs2_assert_warn(sdp, target))
2062c743ffd0SSteven Whitehouse return -EINVAL;
20638e2e0047SBob Peterson if (gfs2_rs_active(rs)) {
2064c65b76b8SAndreas Gruenbacher begin = rs->rs_rgd;
2065c65b76b8SAndreas Gruenbacher } else if (rs->rs_rgd &&
2066c65b76b8SAndreas Gruenbacher rgrp_contains_block(rs->rs_rgd, ip->i_goal)) {
2067c65b76b8SAndreas Gruenbacher begin = rs->rs_rgd;
20688e2e0047SBob Peterson } else {
206900a158beSAbhi Das check_and_update_goal(ip);
2070c65b76b8SAndreas Gruenbacher rs->rs_rgd = begin = gfs2_blk2rgrpd(sdp, ip->i_goal, 1);
20718e2e0047SBob Peterson }
20727b9cff46SSteven Whitehouse if (S_ISDIR(ip->i_inode.i_mode) && (ap->aflags & GFS2_AF_ORLOV))
20739dbe9610SSteven Whitehouse skip = gfs2_orlov_skip(ip);
2074c65b76b8SAndreas Gruenbacher if (rs->rs_rgd == NULL)
20757c9ca621SBob Peterson return -EBADSLT;
20767c9ca621SBob Peterson
20777c9ca621SBob Peterson while (loops < 3) {
2078725d0e9dSAndreas Gruenbacher struct gfs2_rgrpd *rgd;
2079725d0e9dSAndreas Gruenbacher
20809e514605SAndreas Gruenbacher rg_locked = gfs2_glock_is_locked_by_me(rs->rs_rgd->rd_gl);
20819e514605SAndreas Gruenbacher if (rg_locked) {
20829e514605SAndreas Gruenbacher rgrp_lock_local(rs->rs_rgd);
20839e514605SAndreas Gruenbacher } else {
20849dbe9610SSteven Whitehouse if (skip && skip--)
20859dbe9610SSteven Whitehouse goto next_rgrp;
20860e27c18cSBob Peterson if (!gfs2_rs_active(rs)) {
20870e27c18cSBob Peterson if (loops == 0 &&
2088c65b76b8SAndreas Gruenbacher !fast_to_acquire(rs->rs_rgd))
20890e27c18cSBob Peterson goto next_rgrp;
20900e27c18cSBob Peterson if ((loops < 2) &&
2091bcd97c06SSteven Whitehouse gfs2_rgrp_used_recently(rs, 1000) &&
2092c65b76b8SAndreas Gruenbacher gfs2_rgrp_congested(rs->rs_rgd, loops))
2093bcd97c06SSteven Whitehouse goto next_rgrp;
20940e27c18cSBob Peterson }
2095c65b76b8SAndreas Gruenbacher error = gfs2_glock_nq_init(rs->rs_rgd->rd_gl,
20968e2e0047SBob Peterson LM_ST_EXCLUSIVE, flags,
209721f09c43SAndreas Gruenbacher &ip->i_rgd_gh);
2098c743ffd0SSteven Whitehouse if (unlikely(error))
2099c743ffd0SSteven Whitehouse return error;
21009e514605SAndreas Gruenbacher rgrp_lock_local(rs->rs_rgd);
2101bcd97c06SSteven Whitehouse if (!gfs2_rs_active(rs) && (loops < 2) &&
2102c65b76b8SAndreas Gruenbacher gfs2_rgrp_congested(rs->rs_rgd, loops))
2103bcd97c06SSteven Whitehouse goto skip_rgrp;
2104c743ffd0SSteven Whitehouse if (sdp->sd_args.ar_rgrplvb) {
2105f2e70d8fSBob Peterson error = update_rgrp_lvb(rs->rs_rgd,
2106f2e70d8fSBob Peterson &ip->i_rgd_gh);
2107c743ffd0SSteven Whitehouse if (unlikely(error)) {
21089e514605SAndreas Gruenbacher rgrp_unlock_local(rs->rs_rgd);
210921f09c43SAndreas Gruenbacher gfs2_glock_dq_uninit(&ip->i_rgd_gh);
211090306c41SBenjamin Marzinski return error;
211190306c41SBenjamin Marzinski }
211290306c41SBenjamin Marzinski }
2113292c8c14SAbhijith Das }
2114c743ffd0SSteven Whitehouse
2115243fea4dSAndreas Gruenbacher /* Skip unusable resource groups */
2116c65b76b8SAndreas Gruenbacher if ((rs->rs_rgd->rd_flags & (GFS2_RGF_NOALLOC |
21175ea5050cSBob Peterson GFS2_RDF_ERROR)) ||
21184272006dSAndreas Gruenbacher (loops == 0 && target > rs->rs_rgd->rd_extfail_pt))
2119c743ffd0SSteven Whitehouse goto skip_rgrp;
2120c743ffd0SSteven Whitehouse
2121f2e70d8fSBob Peterson if (sdp->sd_args.ar_rgrplvb) {
2122f2e70d8fSBob Peterson error = gfs2_instantiate(&ip->i_rgd_gh);
2123f2e70d8fSBob Peterson if (error)
2124f2e70d8fSBob Peterson goto skip_rgrp;
2125f2e70d8fSBob Peterson }
2126c743ffd0SSteven Whitehouse
2127c743ffd0SSteven Whitehouse /* Get a reservation if we don't already have one */
2128c743ffd0SSteven Whitehouse if (!gfs2_rs_active(rs))
2129c65b76b8SAndreas Gruenbacher rg_mblk_search(rs->rs_rgd, ip, ap);
2130c743ffd0SSteven Whitehouse
2131c743ffd0SSteven Whitehouse /* Skip rgrps when we can't get a reservation on first pass */
2132c743ffd0SSteven Whitehouse if (!gfs2_rs_active(rs) && (loops < 1))
2133c743ffd0SSteven Whitehouse goto check_rgrp;
2134c743ffd0SSteven Whitehouse
2135c743ffd0SSteven Whitehouse /* If rgrp has enough free space, use it */
2136725d0e9dSAndreas Gruenbacher rgd = rs->rs_rgd;
2137725d0e9dSAndreas Gruenbacher spin_lock(&rgd->rd_rsspin);
2138725d0e9dSAndreas Gruenbacher free_blocks = rgd_free(rgd, rs);
2139725d0e9dSAndreas Gruenbacher blocks_available = rgd->rd_free_clone - rgd->rd_reserved;
2140725d0e9dSAndreas Gruenbacher if (free_blocks < target || blocks_available < target) {
2141725d0e9dSAndreas Gruenbacher spin_unlock(&rgd->rd_rsspin);
2142725d0e9dSAndreas Gruenbacher goto check_rgrp;
214354335b1fSSteven Whitehouse }
2144725d0e9dSAndreas Gruenbacher rs->rs_reserved = ap->target;
2145725d0e9dSAndreas Gruenbacher if (rs->rs_reserved > blocks_available)
2146725d0e9dSAndreas Gruenbacher rs->rs_reserved = blocks_available;
2147725d0e9dSAndreas Gruenbacher rgd->rd_reserved += rs->rs_reserved;
2148725d0e9dSAndreas Gruenbacher spin_unlock(&rgd->rd_rsspin);
21499e514605SAndreas Gruenbacher rgrp_unlock_local(rs->rs_rgd);
2150725d0e9dSAndreas Gruenbacher return 0;
2151c743ffd0SSteven Whitehouse check_rgrp:
2152c743ffd0SSteven Whitehouse /* Check for unlinked inodes which can be reclaimed */
2153c65b76b8SAndreas Gruenbacher if (rs->rs_rgd->rd_flags & GFS2_RDF_CHECK)
2154c65b76b8SAndreas Gruenbacher try_rgrp_unlink(rs->rs_rgd, &last_unlinked,
2155666d1d8aSBob Peterson ip->i_no_addr);
2156c743ffd0SSteven Whitehouse skip_rgrp:
21579e514605SAndreas Gruenbacher rgrp_unlock_local(rs->rs_rgd);
21589e514605SAndreas Gruenbacher
21591330edbeSBob Peterson /* Drop reservation, if we couldn't use reserved rgrp */
21601330edbeSBob Peterson if (gfs2_rs_active(rs))
21611330edbeSBob Peterson gfs2_rs_deltree(rs);
21621330edbeSBob Peterson
2163c743ffd0SSteven Whitehouse /* Unlock rgrp if required */
2164292c8c14SAbhijith Das if (!rg_locked)
216521f09c43SAndreas Gruenbacher gfs2_glock_dq_uninit(&ip->i_rgd_gh);
2166c743ffd0SSteven Whitehouse next_rgrp:
2167c743ffd0SSteven Whitehouse /* Find the next rgrp, and continue looking */
2168c65b76b8SAndreas Gruenbacher if (gfs2_select_rgrp(&rs->rs_rgd, begin))
2169c743ffd0SSteven Whitehouse continue;
21709dbe9610SSteven Whitehouse if (skip)
21719dbe9610SSteven Whitehouse continue;
2172666d1d8aSBob Peterson
2173c743ffd0SSteven Whitehouse /* If we've scanned all the rgrps, but found no free blocks
2174c743ffd0SSteven Whitehouse * then this checks for some less likely conditions before
2175c743ffd0SSteven Whitehouse * trying again.
2176c743ffd0SSteven Whitehouse */
2177172e045aSBenjamin Marzinski loops++;
217854335b1fSSteven Whitehouse /* Check that fs hasn't grown if writing to rindex */
2179c743ffd0SSteven Whitehouse if (ip == GFS2_I(sdp->sd_rindex) && !sdp->sd_rindex_uptodate) {
21800489b3f5SBenjamin Marzinski error = gfs2_ri_update(ip);
2181044b9414SSteven Whitehouse if (error)
2182cc0581bdSBob Peterson return error;
2183b3b94faaSDavid Teigland }
2184c743ffd0SSteven Whitehouse /* Flushing the log may release space */
21854272006dSAndreas Gruenbacher if (loops == 2) {
21864272006dSAndreas Gruenbacher if (ap->min_target)
21874272006dSAndreas Gruenbacher target = ap->min_target;
2188805c0907SBob Peterson gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
2189805c0907SBob Peterson GFS2_LFC_INPLACE_RESERVE);
2190c743ffd0SSteven Whitehouse }
21914272006dSAndreas Gruenbacher }
2192c743ffd0SSteven Whitehouse
2193c743ffd0SSteven Whitehouse return -ENOSPC;
2194c743ffd0SSteven Whitehouse }
2195b3b94faaSDavid Teigland
2196b3b94faaSDavid Teigland /**
2197b3b94faaSDavid Teigland * gfs2_inplace_release - release an inplace reservation
2198b3b94faaSDavid Teigland * @ip: the inode the reservation was taken out on
2199b3b94faaSDavid Teigland *
2200b3b94faaSDavid Teigland * Release a reservation made by gfs2_inplace_reserve().
2201b3b94faaSDavid Teigland */
2202b3b94faaSDavid Teigland
gfs2_inplace_release(struct gfs2_inode * ip)2203b3b94faaSDavid Teigland void gfs2_inplace_release(struct gfs2_inode *ip)
2204b3b94faaSDavid Teigland {
2205725d0e9dSAndreas Gruenbacher struct gfs2_blkreserv *rs = &ip->i_res;
2206725d0e9dSAndreas Gruenbacher
2207725d0e9dSAndreas Gruenbacher if (rs->rs_reserved) {
2208725d0e9dSAndreas Gruenbacher struct gfs2_rgrpd *rgd = rs->rs_rgd;
2209725d0e9dSAndreas Gruenbacher
2210725d0e9dSAndreas Gruenbacher spin_lock(&rgd->rd_rsspin);
2211c98c2ca5SBob Peterson GLOCK_BUG_ON(rgd->rd_gl, rgd->rd_reserved < rs->rs_reserved);
2212725d0e9dSAndreas Gruenbacher rgd->rd_reserved -= rs->rs_reserved;
2213725d0e9dSAndreas Gruenbacher spin_unlock(&rgd->rd_rsspin);
2214725d0e9dSAndreas Gruenbacher rs->rs_reserved = 0;
2215725d0e9dSAndreas Gruenbacher }
221621f09c43SAndreas Gruenbacher if (gfs2_holder_initialized(&ip->i_rgd_gh))
221721f09c43SAndreas Gruenbacher gfs2_glock_dq_uninit(&ip->i_rgd_gh);
2218b3b94faaSDavid Teigland }
2219b3b94faaSDavid Teigland
2220b3b94faaSDavid Teigland /**
2221b3e47ca0SBob Peterson * gfs2_alloc_extent - allocate an extent from a given bitmap
22224a993fb1SSteven Whitehouse * @rbm: the resource group information
2223b3e47ca0SBob Peterson * @dinode: TRUE if the first block we allocate is for a dinode
2224c04a2ef3SSteven Whitehouse * @n: The extent length (value/result)
2225b3e47ca0SBob Peterson *
2226c04a2ef3SSteven Whitehouse * Add the bitmap buffer to the transaction.
2227b3e47ca0SBob Peterson * Set the found bits to @new_state to change block's allocation state.
2228b3e47ca0SBob Peterson */
gfs2_alloc_extent(const struct gfs2_rbm * rbm,bool dinode,unsigned int * n)2229c04a2ef3SSteven Whitehouse static void gfs2_alloc_extent(const struct gfs2_rbm *rbm, bool dinode,
22304a993fb1SSteven Whitehouse unsigned int *n)
2231b3e47ca0SBob Peterson {
2232c04a2ef3SSteven Whitehouse struct gfs2_rbm pos = { .rgd = rbm->rgd, };
2233b3e47ca0SBob Peterson const unsigned int elen = *n;
2234c04a2ef3SSteven Whitehouse u64 block;
2235c04a2ef3SSteven Whitehouse int ret;
223660a0b8f9SSteven Whitehouse
2237c04a2ef3SSteven Whitehouse *n = 1;
2238c04a2ef3SSteven Whitehouse block = gfs2_rbm_to_block(rbm);
2239e579ed4fSBob Peterson gfs2_trans_add_meta(rbm->rgd->rd_gl, rbm_bi(rbm)->bi_bh);
22403e6339ddSSteven Whitehouse gfs2_setbit(rbm, true, dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED);
2241c04a2ef3SSteven Whitehouse block++;
2242b45e41d7SSteven Whitehouse while (*n < elen) {
2243c04a2ef3SSteven Whitehouse ret = gfs2_rbm_from_block(&pos, block);
2244dffe12a8SBob Peterson if (ret || gfs2_testbit(&pos, true) != GFS2_BLKST_FREE)
2245b45e41d7SSteven Whitehouse break;
2246e579ed4fSBob Peterson gfs2_trans_add_meta(pos.rgd->rd_gl, rbm_bi(&pos)->bi_bh);
22473e6339ddSSteven Whitehouse gfs2_setbit(&pos, true, GFS2_BLKST_USED);
22489b8c81d1SSteven Whitehouse (*n)++;
2249c04a2ef3SSteven Whitehouse block++;
2250b45e41d7SSteven Whitehouse }
2251b3b94faaSDavid Teigland }
2252b3b94faaSDavid Teigland
2253b3b94faaSDavid Teigland /**
2254b3b94faaSDavid Teigland * rgblk_free - Change alloc state of given block(s)
2255b3b94faaSDavid Teigland * @sdp: the filesystem
22560ddeded4SAndreas Gruenbacher * @rgd: the resource group the blocks are in
2257b3b94faaSDavid Teigland * @bstart: the start of a run of blocks to free
2258b3b94faaSDavid Teigland * @blen: the length of the block run (all must lie within ONE RG!)
2259b3b94faaSDavid Teigland * @new_state: GFS2_BLKST_XXX the after-allocation block state
2260b3b94faaSDavid Teigland */
2261b3b94faaSDavid Teigland
rgblk_free(struct gfs2_sbd * sdp,struct gfs2_rgrpd * rgd,u64 bstart,u32 blen,unsigned char new_state)22620ddeded4SAndreas Gruenbacher static void rgblk_free(struct gfs2_sbd *sdp, struct gfs2_rgrpd *rgd,
22630ddeded4SAndreas Gruenbacher u64 bstart, u32 blen, unsigned char new_state)
2264b3b94faaSDavid Teigland {
22653b1d0b9dSSteven Whitehouse struct gfs2_rbm rbm;
2266d24e0569SBob Peterson struct gfs2_bitmap *bi, *bi_prev = NULL;
2267b3b94faaSDavid Teigland
22680ddeded4SAndreas Gruenbacher rbm.rgd = rgd;
2269f654683dSAndreas Gruenbacher if (WARN_ON_ONCE(gfs2_rbm_from_block(&rbm, bstart)))
22700ddeded4SAndreas Gruenbacher return;
2271d24e0569SBob Peterson while (blen--) {
2272e579ed4fSBob Peterson bi = rbm_bi(&rbm);
2273d24e0569SBob Peterson if (bi != bi_prev) {
2274e579ed4fSBob Peterson if (!bi->bi_clone) {
2275e579ed4fSBob Peterson bi->bi_clone = kmalloc(bi->bi_bh->b_size,
2276dd894be8SSteven Whitehouse GFP_NOFS | __GFP_NOFAIL);
2277e579ed4fSBob Peterson memcpy(bi->bi_clone + bi->bi_offset,
2278d24e0569SBob Peterson bi->bi_bh->b_data + bi->bi_offset,
2279281b4952SAndreas Gruenbacher bi->bi_bytes);
2280b3b94faaSDavid Teigland }
2281e579ed4fSBob Peterson gfs2_trans_add_meta(rbm.rgd->rd_gl, bi->bi_bh);
2282d24e0569SBob Peterson bi_prev = bi;
2283d24e0569SBob Peterson }
22843e6339ddSSteven Whitehouse gfs2_setbit(&rbm, false, new_state);
22850eacdd16SAndreas Gruenbacher gfs2_rbm_add(&rbm, 1);
2286b3b94faaSDavid Teigland }
2287b3b94faaSDavid Teigland }
2288b3b94faaSDavid Teigland
2289b3b94faaSDavid Teigland /**
229009010978SSteven Whitehouse * gfs2_rgrp_dump - print out an rgrp
229109010978SSteven Whitehouse * @seq: The iterator
22920e539ca1SAndrew Price * @rgd: The rgrp in question
22933792ce97SBob Peterson * @fs_id_buf: pointer to file system id (if requested)
2294b3b94faaSDavid Teigland *
2295b3b94faaSDavid Teigland */
2296b3b94faaSDavid Teigland
gfs2_rgrp_dump(struct seq_file * seq,struct gfs2_rgrpd * rgd,const char * fs_id_buf)22970e539ca1SAndrew Price void gfs2_rgrp_dump(struct seq_file *seq, struct gfs2_rgrpd *rgd,
22983792ce97SBob Peterson const char *fs_id_buf)
229909010978SSteven Whitehouse {
23008e2e0047SBob Peterson struct gfs2_blkreserv *trs;
23018e2e0047SBob Peterson const struct rb_node *n;
23028e2e0047SBob Peterson
23039e514605SAndreas Gruenbacher spin_lock(&rgd->rd_rsspin);
2304725d0e9dSAndreas Gruenbacher gfs2_print_dbg(seq, "%s R: n:%llu f:%02x b:%u/%u i:%u q:%u r:%u e:%u\n",
23053792ce97SBob Peterson fs_id_buf,
230609010978SSteven Whitehouse (unsigned long long)rgd->rd_addr, rgd->rd_flags,
23078e2e0047SBob Peterson rgd->rd_free, rgd->rd_free_clone, rgd->rd_dinodes,
2308725d0e9dSAndreas Gruenbacher rgd->rd_requested, rgd->rd_reserved, rgd->rd_extfail_pt);
2309067a7c48SOsama Muhammad if (rgd->rd_sbd->sd_args.ar_rgrplvb && rgd->rd_rgl) {
231072244b6bSBob Peterson struct gfs2_rgrp_lvb *rgl = rgd->rd_rgl;
231172244b6bSBob Peterson
23123792ce97SBob Peterson gfs2_print_dbg(seq, "%s L: f:%02x b:%u i:%u\n", fs_id_buf,
231372244b6bSBob Peterson be32_to_cpu(rgl->rl_flags),
231472244b6bSBob Peterson be32_to_cpu(rgl->rl_free),
231572244b6bSBob Peterson be32_to_cpu(rgl->rl_dinodes));
231672244b6bSBob Peterson }
23178e2e0047SBob Peterson for (n = rb_first(&rgd->rd_rstree); n; n = rb_next(&trs->rs_node)) {
23188e2e0047SBob Peterson trs = rb_entry(n, struct gfs2_blkreserv, rs_node);
23193792ce97SBob Peterson dump_rs(seq, trs, fs_id_buf);
23208e2e0047SBob Peterson }
23218e2e0047SBob Peterson spin_unlock(&rgd->rd_rsspin);
232209010978SSteven Whitehouse }
232309010978SSteven Whitehouse
gfs2_rgrp_error(struct gfs2_rgrpd * rgd)23246050b9c7SSteven Whitehouse static void gfs2_rgrp_error(struct gfs2_rgrpd *rgd)
23256050b9c7SSteven Whitehouse {
23266050b9c7SSteven Whitehouse struct gfs2_sbd *sdp = rgd->rd_sbd;
232798fb0574SBob Peterson char fs_id_buf[sizeof(sdp->sd_fsname) + 7];
23283792ce97SBob Peterson
23296050b9c7SSteven Whitehouse fs_warn(sdp, "rgrp %llu has an error, marking it readonly until umount\n",
23306050b9c7SSteven Whitehouse (unsigned long long)rgd->rd_addr);
23316050b9c7SSteven Whitehouse fs_warn(sdp, "umount on all nodes and run fsck.gfs2 to fix the error\n");
23323792ce97SBob Peterson sprintf(fs_id_buf, "fsid=%s: ", sdp->sd_fsname);
23330e539ca1SAndrew Price gfs2_rgrp_dump(NULL, rgd, fs_id_buf);
23346050b9c7SSteven Whitehouse rgd->rd_flags |= GFS2_RDF_ERROR;
23356050b9c7SSteven Whitehouse }
23366050b9c7SSteven Whitehouse
233709010978SSteven Whitehouse /**
23385b924ae2SSteven Whitehouse * gfs2_adjust_reservation - Adjust (or remove) a reservation after allocation
23395b924ae2SSteven Whitehouse * @ip: The inode we have just allocated blocks for
23405b924ae2SSteven Whitehouse * @rbm: The start of the allocated blocks
23415b924ae2SSteven Whitehouse * @len: The extent length
23428e2e0047SBob Peterson *
23435b924ae2SSteven Whitehouse * Adjusts a reservation after an allocation has taken place. If the
23445b924ae2SSteven Whitehouse * reservation does not match the allocation, or if it is now empty
23455b924ae2SSteven Whitehouse * then it is removed.
23468e2e0047SBob Peterson */
23475b924ae2SSteven Whitehouse
gfs2_adjust_reservation(struct gfs2_inode * ip,const struct gfs2_rbm * rbm,unsigned len)23485b924ae2SSteven Whitehouse static void gfs2_adjust_reservation(struct gfs2_inode *ip,
23495b924ae2SSteven Whitehouse const struct gfs2_rbm *rbm, unsigned len)
23508e2e0047SBob Peterson {
2351a097dc7eSBob Peterson struct gfs2_blkreserv *rs = &ip->i_res;
23525b924ae2SSteven Whitehouse struct gfs2_rgrpd *rgd = rbm->rgd;
23538e2e0047SBob Peterson
2354725d0e9dSAndreas Gruenbacher BUG_ON(rs->rs_reserved < len);
2355725d0e9dSAndreas Gruenbacher rs->rs_reserved -= len;
23565b924ae2SSteven Whitehouse if (gfs2_rs_active(rs)) {
2357c65b76b8SAndreas Gruenbacher u64 start = gfs2_rbm_to_block(rbm);
2358c65b76b8SAndreas Gruenbacher
2359c65b76b8SAndreas Gruenbacher if (rs->rs_start == start) {
2360c65b76b8SAndreas Gruenbacher unsigned int rlen;
2361c65b76b8SAndreas Gruenbacher
2362c65b76b8SAndreas Gruenbacher rs->rs_start += len;
236307974d2aSAndreas Gruenbacher rlen = min(rs->rs_requested, len);
236407974d2aSAndreas Gruenbacher rs->rs_requested -= rlen;
236507974d2aSAndreas Gruenbacher rgd->rd_requested -= rlen;
23669e733d39SSteven Whitehouse trace_gfs2_rs(rs, TRACE_RS_CLAIM);
2367c65b76b8SAndreas Gruenbacher if (rs->rs_start < rgd->rd_data0 + rgd->rd_data &&
236807974d2aSAndreas Gruenbacher rs->rs_requested)
2369725d0e9dSAndreas Gruenbacher return;
23701a855033SBob Peterson /* We used up our block reservation, so we should
23711a855033SBob Peterson reserve more blocks next time. */
237221f09c43SAndreas Gruenbacher atomic_add(RGRP_RSRV_ADDBLKS, &ip->i_sizehint);
23735b924ae2SSteven Whitehouse }
237420095218SBob Peterson __rs_deltree(rs);
23755b924ae2SSteven Whitehouse }
23768e2e0047SBob Peterson }
23778e2e0047SBob Peterson
23788e2e0047SBob Peterson /**
23799e07f2cbSSteven Whitehouse * gfs2_set_alloc_start - Set starting point for block allocation
23809e07f2cbSSteven Whitehouse * @rbm: The rbm which will be set to the required location
23819e07f2cbSSteven Whitehouse * @ip: The gfs2 inode
23829e07f2cbSSteven Whitehouse * @dinode: Flag to say if allocation includes a new inode
23839e07f2cbSSteven Whitehouse *
23849e07f2cbSSteven Whitehouse * This sets the starting point from the reservation if one is active
23859e07f2cbSSteven Whitehouse * otherwise it falls back to guessing a start point based on the
23869e07f2cbSSteven Whitehouse * inode's goal block or the last allocation point in the rgrp.
23879e07f2cbSSteven Whitehouse */
23889e07f2cbSSteven Whitehouse
gfs2_set_alloc_start(struct gfs2_rbm * rbm,const struct gfs2_inode * ip,bool dinode)23899e07f2cbSSteven Whitehouse static void gfs2_set_alloc_start(struct gfs2_rbm *rbm,
23909e07f2cbSSteven Whitehouse const struct gfs2_inode *ip, bool dinode)
23919e07f2cbSSteven Whitehouse {
23929e07f2cbSSteven Whitehouse u64 goal;
23939e07f2cbSSteven Whitehouse
2394a097dc7eSBob Peterson if (gfs2_rs_active(&ip->i_res)) {
2395c65b76b8SAndreas Gruenbacher goal = ip->i_res.rs_start;
2396c65b76b8SAndreas Gruenbacher } else {
23979e07f2cbSSteven Whitehouse if (!dinode && rgrp_contains_block(rbm->rgd, ip->i_goal))
23989e07f2cbSSteven Whitehouse goal = ip->i_goal;
23999e07f2cbSSteven Whitehouse else
24009e07f2cbSSteven Whitehouse goal = rbm->rgd->rd_last_alloc + rbm->rgd->rd_data0;
2401c65b76b8SAndreas Gruenbacher }
2402f654683dSAndreas Gruenbacher if (WARN_ON_ONCE(gfs2_rbm_from_block(rbm, goal))) {
2403f654683dSAndreas Gruenbacher rbm->bii = 0;
2404f654683dSAndreas Gruenbacher rbm->offset = 0;
2405f654683dSAndreas Gruenbacher }
24069e07f2cbSSteven Whitehouse }
24079e07f2cbSSteven Whitehouse
24089e07f2cbSSteven Whitehouse /**
24096e87ed0fSBob Peterson * gfs2_alloc_blocks - Allocate one or more blocks of data and/or a dinode
241009010978SSteven Whitehouse * @ip: the inode to allocate the block for
241109010978SSteven Whitehouse * @bn: Used to return the starting block number
24128e2e0047SBob Peterson * @nblocks: requested number of blocks/extent length (value/result)
24136e87ed0fSBob Peterson * @dinode: 1 if we're allocating a dinode block, else 0
241409010978SSteven Whitehouse *
241509010978SSteven Whitehouse * Returns: 0 or error
241609010978SSteven Whitehouse */
241709010978SSteven Whitehouse
gfs2_alloc_blocks(struct gfs2_inode * ip,u64 * bn,unsigned int * nblocks,bool dinode)24186a8099edSSteven Whitehouse int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
2419d92445b2SAndreas Gruenbacher bool dinode)
2420b3b94faaSDavid Teigland {
2421feaa7bbaSSteven Whitehouse struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
2422d9ba7615SSteven Whitehouse struct buffer_head *dibh;
2423c65b76b8SAndreas Gruenbacher struct gfs2_rbm rbm = { .rgd = ip->i_res.rs_rgd, };
24243c5d785aSBob Peterson u64 block; /* block, within the file system scope */
2425f38e998fSAndreas Gruenbacher u32 minext = 1;
2426b2598965SAndreas Gruenbacher int error = -ENOSPC;
2427b3b94faaSDavid Teigland
2428725d0e9dSAndreas Gruenbacher BUG_ON(ip->i_res.rs_reserved < *nblocks);
2429725d0e9dSAndreas Gruenbacher
24309e514605SAndreas Gruenbacher rgrp_lock_local(rbm.rgd);
2431b2598965SAndreas Gruenbacher if (gfs2_rs_active(&ip->i_res)) {
24329e07f2cbSSteven Whitehouse gfs2_set_alloc_start(&rbm, ip, dinode);
24333d39fcd1SAndreas Gruenbacher error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, &minext, &ip->i_res, false);
2434b2598965SAndreas Gruenbacher }
2435137834a6SSteven Whitehouse if (error == -ENOSPC) {
24369e07f2cbSSteven Whitehouse gfs2_set_alloc_start(&rbm, ip, dinode);
2437f38e998fSAndreas Gruenbacher error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, &minext, NULL, false);
2438137834a6SSteven Whitehouse }
2439137834a6SSteven Whitehouse
244062e252eeSSteven Whitehouse /* Since all blocks are reserved in advance, this shouldn't happen */
24415b924ae2SSteven Whitehouse if (error) {
24425ea5050cSBob Peterson fs_warn(sdp, "inum=%llu error=%d, nblocks=%u, full=%d fail_pt=%d\n",
24439e733d39SSteven Whitehouse (unsigned long long)ip->i_no_addr, error, *nblocks,
24445ea5050cSBob Peterson test_bit(GBF_FULL, &rbm.rgd->rd_bits->bi_flags),
24455ea5050cSBob Peterson rbm.rgd->rd_extfail_pt);
244609010978SSteven Whitehouse goto rgrp_error;
24478e2e0047SBob Peterson }
2448b3b94faaSDavid Teigland
2449c04a2ef3SSteven Whitehouse gfs2_alloc_extent(&rbm, dinode, nblocks);
2450c04a2ef3SSteven Whitehouse block = gfs2_rbm_to_block(&rbm);
2451c743ffd0SSteven Whitehouse rbm.rgd->rd_last_alloc = block - rbm.rgd->rd_data0;
24523c5d785aSBob Peterson if (!dinode) {
24533ed08befSAndreas Gruenbacher ip->i_goal = block + *nblocks - 1;
2454d9ba7615SSteven Whitehouse error = gfs2_meta_inode_buffer(ip, &dibh);
2455d9ba7615SSteven Whitehouse if (error == 0) {
24563c5d785aSBob Peterson struct gfs2_dinode *di =
24573c5d785aSBob Peterson (struct gfs2_dinode *)dibh->b_data;
2458350a9b0aSSteven Whitehouse gfs2_trans_add_meta(ip->i_gl, dibh);
24593c5d785aSBob Peterson di->di_goal_meta = di->di_goal_data =
24603c5d785aSBob Peterson cpu_to_be64(ip->i_goal);
2461d9ba7615SSteven Whitehouse brelse(dibh);
2462d9ba7615SSteven Whitehouse }
24633c5d785aSBob Peterson }
2464725d0e9dSAndreas Gruenbacher spin_lock(&rbm.rgd->rd_rsspin);
2465725d0e9dSAndreas Gruenbacher gfs2_adjust_reservation(ip, &rbm, *nblocks);
2466725d0e9dSAndreas Gruenbacher if (rbm.rgd->rd_free < *nblocks || rbm.rgd->rd_reserved < *nblocks) {
2467e54c78a2SBob Peterson fs_warn(sdp, "nblocks=%u\n", *nblocks);
2468725d0e9dSAndreas Gruenbacher spin_unlock(&rbm.rgd->rd_rsspin);
246909010978SSteven Whitehouse goto rgrp_error;
24708e2e0047SBob Peterson }
2471c98c2ca5SBob Peterson GLOCK_BUG_ON(rbm.rgd->rd_gl, rbm.rgd->rd_reserved < *nblocks);
2472c98c2ca5SBob Peterson GLOCK_BUG_ON(rbm.rgd->rd_gl, rbm.rgd->rd_free_clone < *nblocks);
2473c98c2ca5SBob Peterson GLOCK_BUG_ON(rbm.rgd->rd_gl, rbm.rgd->rd_free < *nblocks);
2474725d0e9dSAndreas Gruenbacher rbm.rgd->rd_reserved -= *nblocks;
2475725d0e9dSAndreas Gruenbacher rbm.rgd->rd_free_clone -= *nblocks;
24764a993fb1SSteven Whitehouse rbm.rgd->rd_free -= *nblocks;
2477725d0e9dSAndreas Gruenbacher spin_unlock(&rbm.rgd->rd_rsspin);
24783c5d785aSBob Peterson if (dinode) {
2479d92445b2SAndreas Gruenbacher u64 generation;
2480d92445b2SAndreas Gruenbacher
24814a993fb1SSteven Whitehouse rbm.rgd->rd_dinodes++;
2482d92445b2SAndreas Gruenbacher generation = rbm.rgd->rd_igeneration++;
2483d92445b2SAndreas Gruenbacher if (generation == 0)
2484d92445b2SAndreas Gruenbacher generation = rbm.rgd->rd_igeneration++;
2485d92445b2SAndreas Gruenbacher ip->i_generation = generation;
24863c5d785aSBob Peterson }
2487b3b94faaSDavid Teigland
2488350a9b0aSSteven Whitehouse gfs2_trans_add_meta(rbm.rgd->rd_gl, rbm.rgd->rd_bits[0].bi_bh);
24894a993fb1SSteven Whitehouse gfs2_rgrp_out(rbm.rgd, rbm.rgd->rd_bits[0].bi_bh->b_data);
24909e514605SAndreas Gruenbacher rgrp_unlock_local(rbm.rgd);
2491b3b94faaSDavid Teigland
24926a8099edSSteven Whitehouse gfs2_statfs_change(sdp, 0, -(s64)*nblocks, dinode ? 1 : 0);
24933c5d785aSBob Peterson if (dinode)
2494fbb27873SAndreas Gruenbacher gfs2_trans_remove_revoke(sdp, block, *nblocks);
24956a8099edSSteven Whitehouse
2496fd4b4e04SSteven Whitehouse gfs2_quota_change(ip, *nblocks, ip->i_inode.i_uid, ip->i_inode.i_gid);
2497b3b94faaSDavid Teigland
24984a993fb1SSteven Whitehouse trace_gfs2_block_alloc(ip, rbm.rgd, block, *nblocks,
24996e87ed0fSBob Peterson dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED);
25006050b9c7SSteven Whitehouse *bn = block;
25016050b9c7SSteven Whitehouse return 0;
25026050b9c7SSteven Whitehouse
25036050b9c7SSteven Whitehouse rgrp_error:
25049e514605SAndreas Gruenbacher rgrp_unlock_local(rbm.rgd);
25054a993fb1SSteven Whitehouse gfs2_rgrp_error(rbm.rgd);
25066050b9c7SSteven Whitehouse return -EIO;
2507b3b94faaSDavid Teigland }
2508b3b94faaSDavid Teigland
2509b3b94faaSDavid Teigland /**
251046fcb2edSEric Sandeen * __gfs2_free_blocks - free a contiguous run of block(s)
2511b3b94faaSDavid Teigland * @ip: the inode these blocks are being freed from
25120ddeded4SAndreas Gruenbacher * @rgd: the resource group the blocks are in
2513b3b94faaSDavid Teigland * @bstart: first block of a run of contiguous blocks
2514b3b94faaSDavid Teigland * @blen: the length of the block run
251546fcb2edSEric Sandeen * @meta: 1 if the blocks represent metadata
2516b3b94faaSDavid Teigland *
2517b3b94faaSDavid Teigland */
2518b3b94faaSDavid Teigland
__gfs2_free_blocks(struct gfs2_inode * ip,struct gfs2_rgrpd * rgd,u64 bstart,u32 blen,int meta)25190ddeded4SAndreas Gruenbacher void __gfs2_free_blocks(struct gfs2_inode *ip, struct gfs2_rgrpd *rgd,
25200ddeded4SAndreas Gruenbacher u64 bstart, u32 blen, int meta)
2521b3b94faaSDavid Teigland {
2522feaa7bbaSSteven Whitehouse struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
2523b3b94faaSDavid Teigland
25249e514605SAndreas Gruenbacher rgrp_lock_local(rgd);
25250ddeded4SAndreas Gruenbacher rgblk_free(sdp, rgd, bstart, blen, GFS2_BLKST_FREE);
252641db1ab9SBob Peterson trace_gfs2_block_alloc(ip, rgd, bstart, blen, GFS2_BLKST_FREE);
2527cfc8b549SSteven Whitehouse rgd->rd_free += blen;
252866fc061bSSteven Whitehouse rgd->rd_flags &= ~GFS2_RGF_TRIMMED;
2529350a9b0aSSteven Whitehouse gfs2_trans_add_meta(rgd->rd_gl, rgd->rd_bits[0].bi_bh);
253042d52e38SBob Peterson gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
25319e514605SAndreas Gruenbacher rgrp_unlock_local(rgd);
2532b3b94faaSDavid Teigland
25336d3117b4SSteven Whitehouse /* Directories keep their data in the metadata address space */
253468942870SBob Peterson if (meta || ip->i_depth || gfs2_is_jdata(ip))
253568942870SBob Peterson gfs2_journal_wipe(ip, bstart, blen);
25364c16c36aSBob Peterson }
25374c16c36aSBob Peterson
25384c16c36aSBob Peterson /**
25394c16c36aSBob Peterson * gfs2_free_meta - free a contiguous run of data block(s)
25404c16c36aSBob Peterson * @ip: the inode these blocks are being freed from
25410ddeded4SAndreas Gruenbacher * @rgd: the resource group the blocks are in
25424c16c36aSBob Peterson * @bstart: first block of a run of contiguous blocks
25434c16c36aSBob Peterson * @blen: the length of the block run
25444c16c36aSBob Peterson *
25454c16c36aSBob Peterson */
25464c16c36aSBob Peterson
gfs2_free_meta(struct gfs2_inode * ip,struct gfs2_rgrpd * rgd,u64 bstart,u32 blen)25470ddeded4SAndreas Gruenbacher void gfs2_free_meta(struct gfs2_inode *ip, struct gfs2_rgrpd *rgd,
25480ddeded4SAndreas Gruenbacher u64 bstart, u32 blen)
2549b3b94faaSDavid Teigland {
2550feaa7bbaSSteven Whitehouse struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
2551b3b94faaSDavid Teigland
25520ddeded4SAndreas Gruenbacher __gfs2_free_blocks(ip, rgd, bstart, blen, 1);
2553b3b94faaSDavid Teigland gfs2_statfs_change(sdp, 0, +blen, 0);
25542933f925SSteven Whitehouse gfs2_quota_change(ip, -(s64)blen, ip->i_inode.i_uid, ip->i_inode.i_gid);
2555b3b94faaSDavid Teigland }
2556b3b94faaSDavid Teigland
gfs2_unlink_di(struct inode * inode)2557feaa7bbaSSteven Whitehouse void gfs2_unlink_di(struct inode *inode)
2558feaa7bbaSSteven Whitehouse {
2559feaa7bbaSSteven Whitehouse struct gfs2_inode *ip = GFS2_I(inode);
2560feaa7bbaSSteven Whitehouse struct gfs2_sbd *sdp = GFS2_SB(inode);
2561feaa7bbaSSteven Whitehouse struct gfs2_rgrpd *rgd;
2562dbb7cae2SSteven Whitehouse u64 blkno = ip->i_no_addr;
2563feaa7bbaSSteven Whitehouse
25640ddeded4SAndreas Gruenbacher rgd = gfs2_blk2rgrpd(sdp, blkno, true);
2565feaa7bbaSSteven Whitehouse if (!rgd)
2566feaa7bbaSSteven Whitehouse return;
25679e514605SAndreas Gruenbacher rgrp_lock_local(rgd);
25680ddeded4SAndreas Gruenbacher rgblk_free(sdp, rgd, blkno, 1, GFS2_BLKST_UNLINKED);
256941db1ab9SBob Peterson trace_gfs2_block_alloc(ip, rgd, blkno, 1, GFS2_BLKST_UNLINKED);
2570350a9b0aSSteven Whitehouse gfs2_trans_add_meta(rgd->rd_gl, rgd->rd_bits[0].bi_bh);
257142d52e38SBob Peterson gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
2572f5580d0fSBob Peterson be32_add_cpu(&rgd->rd_rgl->rl_unlinked, 1);
25739e514605SAndreas Gruenbacher rgrp_unlock_local(rgd);
2574feaa7bbaSSteven Whitehouse }
2575feaa7bbaSSteven Whitehouse
gfs2_free_di(struct gfs2_rgrpd * rgd,struct gfs2_inode * ip)2576a18c78c5SBob Peterson void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip)
2577b3b94faaSDavid Teigland {
2578b3b94faaSDavid Teigland struct gfs2_sbd *sdp = rgd->rd_sbd;
2579b3b94faaSDavid Teigland
25809e514605SAndreas Gruenbacher rgrp_lock_local(rgd);
25810ddeded4SAndreas Gruenbacher rgblk_free(sdp, rgd, ip->i_no_addr, 1, GFS2_BLKST_FREE);
258273f74948SSteven Whitehouse if (!rgd->rd_dinodes)
2583b3b94faaSDavid Teigland gfs2_consist_rgrpd(rgd);
258473f74948SSteven Whitehouse rgd->rd_dinodes--;
2585cfc8b549SSteven Whitehouse rgd->rd_free++;
2586b3b94faaSDavid Teigland
2587350a9b0aSSteven Whitehouse gfs2_trans_add_meta(rgd->rd_gl, rgd->rd_bits[0].bi_bh);
258842d52e38SBob Peterson gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
2589f5580d0fSBob Peterson be32_add_cpu(&rgd->rd_rgl->rl_unlinked, -1);
259017a59346SBob Peterson rgrp_unlock_local(rgd);
2591b3b94faaSDavid Teigland
2592b3b94faaSDavid Teigland gfs2_statfs_change(sdp, 0, +1, -1);
259341db1ab9SBob Peterson trace_gfs2_block_alloc(ip, rgd, ip->i_no_addr, 1, GFS2_BLKST_FREE);
25942933f925SSteven Whitehouse gfs2_quota_change(ip, -1, ip->i_inode.i_uid, ip->i_inode.i_gid);
259568942870SBob Peterson gfs2_journal_wipe(ip, ip->i_no_addr, 1);
2596b3b94faaSDavid Teigland }
2597b3b94faaSDavid Teigland
2598b3b94faaSDavid Teigland /**
2599acf7e244SSteven Whitehouse * gfs2_check_blk_type - Check the type of a block
2600acf7e244SSteven Whitehouse * @sdp: The superblock
2601acf7e244SSteven Whitehouse * @no_addr: The block number to check
2602acf7e244SSteven Whitehouse * @type: The block type we are looking for
2603acf7e244SSteven Whitehouse *
26049e514605SAndreas Gruenbacher * The inode glock of @no_addr must be held. The @type to check for is either
26059e514605SAndreas Gruenbacher * GFS2_BLKST_DINODE or GFS2_BLKST_UNLINKED; checking for type GFS2_BLKST_FREE
26069e514605SAndreas Gruenbacher * or GFS2_BLKST_USED would make no sense.
26079e514605SAndreas Gruenbacher *
2608acf7e244SSteven Whitehouse * Returns: 0 if the block type matches the expected type
2609acf7e244SSteven Whitehouse * -ESTALE if it doesn't match
2610acf7e244SSteven Whitehouse * or -ve errno if something went wrong while checking
2611acf7e244SSteven Whitehouse */
2612acf7e244SSteven Whitehouse
gfs2_check_blk_type(struct gfs2_sbd * sdp,u64 no_addr,unsigned int type)2613acf7e244SSteven Whitehouse int gfs2_check_blk_type(struct gfs2_sbd *sdp, u64 no_addr, unsigned int type)
2614acf7e244SSteven Whitehouse {
2615acf7e244SSteven Whitehouse struct gfs2_rgrpd *rgd;
26168339ee54SSteven Whitehouse struct gfs2_holder rgd_gh;
2617dffe12a8SBob Peterson struct gfs2_rbm rbm;
261858884c4dSBob Peterson int error = -EINVAL;
2619acf7e244SSteven Whitehouse
262066fc061bSSteven Whitehouse rgd = gfs2_blk2rgrpd(sdp, no_addr, 1);
2621acf7e244SSteven Whitehouse if (!rgd)
26228339ee54SSteven Whitehouse goto fail;
2623acf7e244SSteven Whitehouse
2624acf7e244SSteven Whitehouse error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_SHARED, 0, &rgd_gh);
2625acf7e244SSteven Whitehouse if (error)
26268339ee54SSteven Whitehouse goto fail;
2627acf7e244SSteven Whitehouse
2628dffe12a8SBob Peterson rbm.rgd = rgd;
2629dffe12a8SBob Peterson error = gfs2_rbm_from_block(&rbm, no_addr);
2630bc923818SZhang Qilong if (!WARN_ON_ONCE(error)) {
26319e514605SAndreas Gruenbacher /*
26329e514605SAndreas Gruenbacher * No need to take the local resource group lock here; the
26339e514605SAndreas Gruenbacher * inode glock of @no_addr provides the necessary
26349e514605SAndreas Gruenbacher * synchronization in case the block is an inode. (In case
26359e514605SAndreas Gruenbacher * the block is not an inode, the block type will not match
26369e514605SAndreas Gruenbacher * the @type we are looking for.)
26379e514605SAndreas Gruenbacher */
2638dffe12a8SBob Peterson if (gfs2_testbit(&rbm, false) != type)
2639acf7e244SSteven Whitehouse error = -ESTALE;
2640bc923818SZhang Qilong }
2641acf7e244SSteven Whitehouse
2642acf7e244SSteven Whitehouse gfs2_glock_dq_uninit(&rgd_gh);
2643bc923818SZhang Qilong
2644acf7e244SSteven Whitehouse fail:
2645acf7e244SSteven Whitehouse return error;
2646acf7e244SSteven Whitehouse }
2647acf7e244SSteven Whitehouse
2648acf7e244SSteven Whitehouse /**
2649b3b94faaSDavid Teigland * gfs2_rlist_add - add a RG to a list of RGs
265070b0c365SSteven Whitehouse * @ip: the inode
2651b3b94faaSDavid Teigland * @rlist: the list of resource groups
2652b3b94faaSDavid Teigland * @block: the block
2653b3b94faaSDavid Teigland *
2654b3b94faaSDavid Teigland * Figure out what RG a block belongs to and add that RG to the list
2655b3b94faaSDavid Teigland *
2656b3b94faaSDavid Teigland * FIXME: Don't use NOFAIL
2657b3b94faaSDavid Teigland *
2658b3b94faaSDavid Teigland */
2659b3b94faaSDavid Teigland
gfs2_rlist_add(struct gfs2_inode * ip,struct gfs2_rgrp_list * rlist,u64 block)266070b0c365SSteven Whitehouse void gfs2_rlist_add(struct gfs2_inode *ip, struct gfs2_rgrp_list *rlist,
2661cd915493SSteven Whitehouse u64 block)
2662b3b94faaSDavid Teigland {
266370b0c365SSteven Whitehouse struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
2664b3b94faaSDavid Teigland struct gfs2_rgrpd *rgd;
2665b3b94faaSDavid Teigland struct gfs2_rgrpd **tmp;
2666b3b94faaSDavid Teigland unsigned int new_space;
2667b3b94faaSDavid Teigland unsigned int x;
2668b3b94faaSDavid Teigland
2669b3b94faaSDavid Teigland if (gfs2_assert_warn(sdp, !rlist->rl_ghs))
2670b3b94faaSDavid Teigland return;
2671b3b94faaSDavid Teigland
267203f8c41cSAndreas Gruenbacher /*
267303f8c41cSAndreas Gruenbacher * The resource group last accessed is kept in the last position.
267403f8c41cSAndreas Gruenbacher */
267503f8c41cSAndreas Gruenbacher
267603f8c41cSAndreas Gruenbacher if (rlist->rl_rgrps) {
267703f8c41cSAndreas Gruenbacher rgd = rlist->rl_rgd[rlist->rl_rgrps - 1];
267803f8c41cSAndreas Gruenbacher if (rgrp_contains_block(rgd, block))
267903f8c41cSAndreas Gruenbacher return;
268066fc061bSSteven Whitehouse rgd = gfs2_blk2rgrpd(sdp, block, 1);
268103f8c41cSAndreas Gruenbacher } else {
2682c65b76b8SAndreas Gruenbacher rgd = ip->i_res.rs_rgd;
268303f8c41cSAndreas Gruenbacher if (!rgd || !rgrp_contains_block(rgd, block))
268403f8c41cSAndreas Gruenbacher rgd = gfs2_blk2rgrpd(sdp, block, 1);
268503f8c41cSAndreas Gruenbacher }
268603f8c41cSAndreas Gruenbacher
2687b3b94faaSDavid Teigland if (!rgd) {
268803f8c41cSAndreas Gruenbacher fs_err(sdp, "rlist_add: no rgrp for block %llu\n",
268903f8c41cSAndreas Gruenbacher (unsigned long long)block);
2690b3b94faaSDavid Teigland return;
2691b3b94faaSDavid Teigland }
2692b3b94faaSDavid Teigland
269303f8c41cSAndreas Gruenbacher for (x = 0; x < rlist->rl_rgrps; x++) {
269403f8c41cSAndreas Gruenbacher if (rlist->rl_rgd[x] == rgd) {
269503f8c41cSAndreas Gruenbacher swap(rlist->rl_rgd[x],
269603f8c41cSAndreas Gruenbacher rlist->rl_rgd[rlist->rl_rgrps - 1]);
2697b3b94faaSDavid Teigland return;
269803f8c41cSAndreas Gruenbacher }
269903f8c41cSAndreas Gruenbacher }
2700b3b94faaSDavid Teigland
2701b3b94faaSDavid Teigland if (rlist->rl_rgrps == rlist->rl_space) {
2702b3b94faaSDavid Teigland new_space = rlist->rl_space + 10;
2703b3b94faaSDavid Teigland
2704b3b94faaSDavid Teigland tmp = kcalloc(new_space, sizeof(struct gfs2_rgrpd *),
2705dd894be8SSteven Whitehouse GFP_NOFS | __GFP_NOFAIL);
2706b3b94faaSDavid Teigland
2707b3b94faaSDavid Teigland if (rlist->rl_rgd) {
2708b3b94faaSDavid Teigland memcpy(tmp, rlist->rl_rgd,
2709b3b94faaSDavid Teigland rlist->rl_space * sizeof(struct gfs2_rgrpd *));
2710b3b94faaSDavid Teigland kfree(rlist->rl_rgd);
2711b3b94faaSDavid Teigland }
2712b3b94faaSDavid Teigland
2713b3b94faaSDavid Teigland rlist->rl_space = new_space;
2714b3b94faaSDavid Teigland rlist->rl_rgd = tmp;
2715b3b94faaSDavid Teigland }
2716b3b94faaSDavid Teigland
2717b3b94faaSDavid Teigland rlist->rl_rgd[rlist->rl_rgrps++] = rgd;
2718b3b94faaSDavid Teigland }
2719b3b94faaSDavid Teigland
2720b3b94faaSDavid Teigland /**
2721b3b94faaSDavid Teigland * gfs2_rlist_alloc - all RGs have been added to the rlist, now allocate
2722b3b94faaSDavid Teigland * and initialize an array of glock holders for them
2723b3b94faaSDavid Teigland * @rlist: the list of resource groups
272444dab005SAndreas Gruenbacher * @state: the state we're requesting
272544dab005SAndreas Gruenbacher * @flags: the modifier flags
2726b3b94faaSDavid Teigland *
2727b3b94faaSDavid Teigland * FIXME: Don't use NOFAIL
2728b3b94faaSDavid Teigland *
2729b3b94faaSDavid Teigland */
2730b3b94faaSDavid Teigland
gfs2_rlist_alloc(struct gfs2_rgrp_list * rlist,unsigned int state,u16 flags)273144dab005SAndreas Gruenbacher void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist,
273244dab005SAndreas Gruenbacher unsigned int state, u16 flags)
2733b3b94faaSDavid Teigland {
2734b3b94faaSDavid Teigland unsigned int x;
2735b3b94faaSDavid Teigland
27366da2ec56SKees Cook rlist->rl_ghs = kmalloc_array(rlist->rl_rgrps,
27376da2ec56SKees Cook sizeof(struct gfs2_holder),
2738dd894be8SSteven Whitehouse GFP_NOFS | __GFP_NOFAIL);
2739b3b94faaSDavid Teigland for (x = 0; x < rlist->rl_rgrps; x++)
274044dab005SAndreas Gruenbacher gfs2_holder_init(rlist->rl_rgd[x]->rd_gl, state, flags,
274144dab005SAndreas Gruenbacher &rlist->rl_ghs[x]);
2742b3b94faaSDavid Teigland }
2743b3b94faaSDavid Teigland
2744b3b94faaSDavid Teigland /**
2745b3b94faaSDavid Teigland * gfs2_rlist_free - free a resource group list
274627ff6a0fSFabian Frederick * @rlist: the list of resource groups
2747b3b94faaSDavid Teigland *
2748b3b94faaSDavid Teigland */
2749b3b94faaSDavid Teigland
gfs2_rlist_free(struct gfs2_rgrp_list * rlist)2750b3b94faaSDavid Teigland void gfs2_rlist_free(struct gfs2_rgrp_list *rlist)
2751b3b94faaSDavid Teigland {
2752b3b94faaSDavid Teigland unsigned int x;
2753b3b94faaSDavid Teigland
2754b3b94faaSDavid Teigland kfree(rlist->rl_rgd);
2755b3b94faaSDavid Teigland
2756b3b94faaSDavid Teigland if (rlist->rl_ghs) {
2757b3b94faaSDavid Teigland for (x = 0; x < rlist->rl_rgrps; x++)
2758b3b94faaSDavid Teigland gfs2_holder_uninit(&rlist->rl_ghs[x]);
2759b3b94faaSDavid Teigland kfree(rlist->rl_ghs);
27608e2e0047SBob Peterson rlist->rl_ghs = NULL;
2761b3b94faaSDavid Teigland }
2762b3b94faaSDavid Teigland }
2763b3b94faaSDavid Teigland
rgrp_lock_local(struct gfs2_rgrpd * rgd)27649e514605SAndreas Gruenbacher void rgrp_lock_local(struct gfs2_rgrpd *rgd)
27659e514605SAndreas Gruenbacher {
27669e514605SAndreas Gruenbacher mutex_lock(&rgd->rd_mutex);
27679e514605SAndreas Gruenbacher }
27689e514605SAndreas Gruenbacher
rgrp_unlock_local(struct gfs2_rgrpd * rgd)27699e514605SAndreas Gruenbacher void rgrp_unlock_local(struct gfs2_rgrpd *rgd)
27709e514605SAndreas Gruenbacher {
27719e514605SAndreas Gruenbacher mutex_unlock(&rgd->rd_mutex);
27729e514605SAndreas Gruenbacher }
2773