blob: 789953a2b6a8d9d7757203de4c0379bd0ec26a6f [file] [log] [blame]
David Teiglandb3b94fa2006-01-16 16:50:04 +00001/*
2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
Bob Petersonfe6c9912008-01-28 11:13:02 -06003 * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
David Teiglandb3b94fa2006-01-16 16:50:04 +00004 *
5 * This copyrighted material is made available to anyone wishing to use,
6 * modify, copy, or redistribute it subject to the terms and conditions
Steven Whitehousee9fc2aa2006-09-01 11:05:15 -04007 * of the GNU General Public License version 2.
David Teiglandb3b94fa2006-01-16 16:50:04 +00008 */
9
David Teiglandb3b94fa2006-01-16 16:50:04 +000010#include <linux/slab.h>
11#include <linux/spinlock.h>
12#include <linux/completion.h>
13#include <linux/buffer_head.h>
Steven Whitehousef42faf42006-01-30 18:34:10 +000014#include <linux/fs.h>
Steven Whitehouse5c676f62006-02-27 17:23:27 -050015#include <linux/gfs2_ondisk.h>
Bob Peterson1f466a42008-03-10 18:17:47 -050016#include <linux/prefetch.h>
Steven Whitehousef15ab562009-02-09 09:25:01 +000017#include <linux/blkdev.h>
David Teiglandb3b94fa2006-01-16 16:50:04 +000018
19#include "gfs2.h"
Steven Whitehouse5c676f62006-02-27 17:23:27 -050020#include "incore.h"
David Teiglandb3b94fa2006-01-16 16:50:04 +000021#include "glock.h"
22#include "glops.h"
David Teiglandb3b94fa2006-01-16 16:50:04 +000023#include "lops.h"
24#include "meta_io.h"
25#include "quota.h"
26#include "rgrp.h"
27#include "super.h"
28#include "trans.h"
Steven Whitehouse5c676f62006-02-27 17:23:27 -050029#include "util.h"
Benjamin Marzinski172e0452007-03-23 14:51:56 -060030#include "log.h"
Steven Whitehousec8cdf472007-06-08 10:05:33 +010031#include "inode.h"
Steven Whitehouse51ff87b2007-10-15 14:42:35 +010032#include "ops_address.h"
David Teiglandb3b94fa2006-01-16 16:50:04 +000033
Steven Whitehouse2c1e52a2006-09-05 15:41:57 -040034#define BFITNOENT ((u32)~0)
Bob Peterson6760bdc2007-07-24 14:09:32 -050035#define NO_BLOCK ((u64)~0)
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -040036
Bob Peterson1f466a42008-03-10 18:17:47 -050037#if BITS_PER_LONG == 32
38#define LBITMASK (0x55555555UL)
39#define LBITSKIP55 (0x55555555UL)
40#define LBITSKIP00 (0x00000000UL)
41#else
42#define LBITMASK (0x5555555555555555UL)
43#define LBITSKIP55 (0x5555555555555555UL)
44#define LBITSKIP00 (0x0000000000000000UL)
45#endif
46
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -040047/*
48 * These routines are used by the resource group routines (rgrp.c)
49 * to keep track of block allocation. Each block is represented by two
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -040050 * bits. So, each byte represents GFS2_NBBY (i.e. 4) blocks.
51 *
52 * 0 = Free
53 * 1 = Used (not metadata)
54 * 2 = Unlinked (still in use) inode
55 * 3 = Used (metadata)
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -040056 */
57
58static const char valid_change[16] = {
59 /* current */
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -040060 /* n */ 0, 1, 1, 1,
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -040061 /* e */ 1, 0, 0, 0,
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -040062 /* w */ 0, 0, 0, 1,
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -040063 1, 0, 0, 0
64};
65
Steven Whitehousec8cdf472007-06-08 10:05:33 +010066static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
Steven Whitehouseb45e41d2008-02-06 10:11:15 +000067 unsigned char old_state, unsigned char new_state,
68 unsigned int *n);
Steven Whitehousec8cdf472007-06-08 10:05:33 +010069
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -040070/**
71 * gfs2_setbit - Set a bit in the bitmaps
72 * @buffer: the buffer that holds the bitmaps
73 * @buflen: the length (in bytes) of the buffer
74 * @block: the block to set
75 * @new_state: the new state of the block
76 *
77 */
78
Steven Whitehouseb45e41d2008-02-06 10:11:15 +000079static inline void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buf1,
80 unsigned char *buf2, unsigned int offset,
81 unsigned int buflen, u32 block,
82 unsigned char new_state)
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -040083{
Steven Whitehouseb45e41d2008-02-06 10:11:15 +000084 unsigned char *byte1, *byte2, *end, cur_state;
85 const unsigned int bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE;
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -040086
Steven Whitehouseb45e41d2008-02-06 10:11:15 +000087 byte1 = buf1 + offset + (block / GFS2_NBBY);
88 end = buf1 + offset + buflen;
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -040089
Steven Whitehouseb45e41d2008-02-06 10:11:15 +000090 BUG_ON(byte1 >= end);
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -040091
Steven Whitehouseb45e41d2008-02-06 10:11:15 +000092 cur_state = (*byte1 >> bit) & GFS2_BIT_MASK;
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -040093
Steven Whitehouseb45e41d2008-02-06 10:11:15 +000094 if (unlikely(!valid_change[new_state * 4 + cur_state])) {
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -040095 gfs2_consist_rgrpd(rgd);
Steven Whitehouseb45e41d2008-02-06 10:11:15 +000096 return;
97 }
98 *byte1 ^= (cur_state ^ new_state) << bit;
99
100 if (buf2) {
101 byte2 = buf2 + offset + (block / GFS2_NBBY);
102 cur_state = (*byte2 >> bit) & GFS2_BIT_MASK;
103 *byte2 ^= (cur_state ^ new_state) << bit;
104 }
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -0400105}
106
107/**
108 * gfs2_testbit - test a bit in the bitmaps
109 * @buffer: the buffer that holds the bitmaps
110 * @buflen: the length (in bytes) of the buffer
111 * @block: the block to read
112 *
113 */
114
Steven Whitehouseb45e41d2008-02-06 10:11:15 +0000115static inline unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd,
116 const unsigned char *buffer,
117 unsigned int buflen, u32 block)
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -0400118{
Steven Whitehouseb45e41d2008-02-06 10:11:15 +0000119 const unsigned char *byte, *end;
120 unsigned char cur_state;
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -0400121 unsigned int bit;
122
123 byte = buffer + (block / GFS2_NBBY);
124 bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE;
125 end = buffer + buflen;
126
127 gfs2_assert(rgd->rd_sbd, byte < end);
128
129 cur_state = (*byte >> bit) & GFS2_BIT_MASK;
130
131 return cur_state;
132}
133
134/**
135 * gfs2_bitfit - Search an rgrp's bitmap buffer to find a bit-pair representing
136 * a block in a given allocation state.
137 * @buffer: the buffer that holds the bitmaps
138 * @buflen: the length (in bytes) of the buffer
139 * @goal: start search at this block's bit-pair (within @buffer)
Bob Peterson6760bdc2007-07-24 14:09:32 -0500140 * @old_state: GFS2_BLKST_XXX the state of the block we're looking for.
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -0400141 *
142 * Scope of @goal and returned block number is only within this bitmap buffer,
143 * not entire rgrp or filesystem. @buffer will be offset from the actual
144 * beginning of a bitmap block buffer, skipping any header structures.
145 *
146 * Return: the block number (bitmap buffer scope) that was found
147 */
148
Steven Whitehouse110acf32008-01-29 13:30:20 +0000149static u32 gfs2_bitfit(const u8 *buffer, unsigned int buflen, u32 goal,
150 u8 old_state)
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -0400151{
Bob Peterson1f466a42008-03-10 18:17:47 -0500152 const u8 *byte, *start, *end;
153 int bit, startbit;
154 u32 g1, g2, misaligned;
155 unsigned long *plong;
156 unsigned long lskipval;
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -0400157
Bob Peterson1f466a42008-03-10 18:17:47 -0500158 lskipval = (old_state & GFS2_BLKST_USED) ? LBITSKIP00 : LBITSKIP55;
159 g1 = (goal / GFS2_NBBY);
160 start = buffer + g1;
161 byte = start;
162 end = buffer + buflen;
163 g2 = ALIGN(g1, sizeof(unsigned long));
164 plong = (unsigned long *)(buffer + g2);
165 startbit = bit = (goal % GFS2_NBBY) * GFS2_BIT_SIZE;
166 misaligned = g2 - g1;
167 if (!misaligned)
168 goto ulong_aligned;
169/* parse the bitmap a byte at a time */
170misaligned:
171 while (byte < end) {
172 if (((*byte >> bit) & GFS2_BIT_MASK) == old_state) {
173 return goal +
174 (((byte - start) * GFS2_NBBY) +
175 ((bit - startbit) >> 1));
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -0400176 }
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -0400177 bit += GFS2_BIT_SIZE;
Bob Peterson1f466a42008-03-10 18:17:47 -0500178 if (bit >= GFS2_NBBY * GFS2_BIT_SIZE) {
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -0400179 bit = 0;
180 byte++;
Bob Peterson1f466a42008-03-10 18:17:47 -0500181 misaligned--;
182 if (!misaligned) {
183 plong = (unsigned long *)byte;
184 goto ulong_aligned;
185 }
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -0400186 }
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -0400187 }
Bob Peterson1f466a42008-03-10 18:17:47 -0500188 return BFITNOENT;
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -0400189
Bob Peterson1f466a42008-03-10 18:17:47 -0500190/* parse the bitmap a unsigned long at a time */
191ulong_aligned:
192 /* Stop at "end - 1" or else prefetch can go past the end and segfault.
193 We could "if" it but we'd lose some of the performance gained.
194 This way will only slow down searching the very last 4/8 bytes
195 depending on architecture. I've experimented with several ways
196 of writing this section such as using an else before the goto
197 but this one seems to be the fastest. */
Bob Peterson17c15da2008-06-18 11:30:40 -0500198 while ((unsigned char *)plong < end - sizeof(unsigned long)) {
Bob Peterson1f466a42008-03-10 18:17:47 -0500199 prefetch(plong + 1);
200 if (((*plong) & LBITMASK) != lskipval)
201 break;
202 plong++;
203 }
204 if ((unsigned char *)plong < end) {
205 byte = (const u8 *)plong;
206 misaligned += sizeof(unsigned long) - 1;
207 goto misaligned;
208 }
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -0400209 return BFITNOENT;
210}
211
212/**
213 * gfs2_bitcount - count the number of bits in a certain state
214 * @buffer: the buffer that holds the bitmaps
215 * @buflen: the length (in bytes) of the buffer
216 * @state: the state of the block we're looking for
217 *
218 * Returns: The number of bits
219 */
220
Steven Whitehouse110acf32008-01-29 13:30:20 +0000221static u32 gfs2_bitcount(struct gfs2_rgrpd *rgd, const u8 *buffer,
222 unsigned int buflen, u8 state)
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -0400223{
Steven Whitehouse110acf32008-01-29 13:30:20 +0000224 const u8 *byte = buffer;
225 const u8 *end = buffer + buflen;
226 const u8 state1 = state << 2;
227 const u8 state2 = state << 4;
228 const u8 state3 = state << 6;
Steven Whitehousecd915492006-09-04 12:49:07 -0400229 u32 count = 0;
Steven Whitehouse88c8ab1f2006-05-18 13:52:39 -0400230
231 for (; byte < end; byte++) {
232 if (((*byte) & 0x03) == state)
233 count++;
234 if (((*byte) & 0x0C) == state1)
235 count++;
236 if (((*byte) & 0x30) == state2)
237 count++;
238 if (((*byte) & 0xC0) == state3)
239 count++;
240 }
241
242 return count;
243}
244
David Teiglandb3b94fa2006-01-16 16:50:04 +0000245/**
246 * gfs2_rgrp_verify - Verify that a resource group is consistent
247 * @sdp: the filesystem
248 * @rgd: the rgrp
249 *
250 */
251
252void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd)
253{
254 struct gfs2_sbd *sdp = rgd->rd_sbd;
255 struct gfs2_bitmap *bi = NULL;
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100256 u32 length = rgd->rd_length;
Steven Whitehousecd915492006-09-04 12:49:07 -0400257 u32 count[4], tmp;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000258 int buf, x;
259
Steven Whitehousecd915492006-09-04 12:49:07 -0400260 memset(count, 0, 4 * sizeof(u32));
David Teiglandb3b94fa2006-01-16 16:50:04 +0000261
262 /* Count # blocks in each of 4 possible allocation states */
263 for (buf = 0; buf < length; buf++) {
264 bi = rgd->rd_bits + buf;
265 for (x = 0; x < 4; x++)
266 count[x] += gfs2_bitcount(rgd,
267 bi->bi_bh->b_data +
268 bi->bi_offset,
269 bi->bi_len, x);
270 }
271
Steven Whitehousecfc8b542008-11-04 10:25:13 +0000272 if (count[0] != rgd->rd_free) {
David Teiglandb3b94fa2006-01-16 16:50:04 +0000273 if (gfs2_consist_rgrpd(rgd))
274 fs_err(sdp, "free data mismatch: %u != %u\n",
Steven Whitehousecfc8b542008-11-04 10:25:13 +0000275 count[0], rgd->rd_free);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000276 return;
277 }
278
Steven Whitehouse73f74942008-11-04 10:32:57 +0000279 tmp = rgd->rd_data - rgd->rd_free - rgd->rd_dinodes;
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -0400280 if (count[1] + count[2] != tmp) {
David Teiglandb3b94fa2006-01-16 16:50:04 +0000281 if (gfs2_consist_rgrpd(rgd))
282 fs_err(sdp, "used data mismatch: %u != %u\n",
283 count[1], tmp);
284 return;
285 }
286
Steven Whitehouse73f74942008-11-04 10:32:57 +0000287 if (count[3] != rgd->rd_dinodes) {
David Teiglandb3b94fa2006-01-16 16:50:04 +0000288 if (gfs2_consist_rgrpd(rgd))
289 fs_err(sdp, "used metadata mismatch: %u != %u\n",
Steven Whitehouse73f74942008-11-04 10:32:57 +0000290 count[3], rgd->rd_dinodes);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000291 return;
292 }
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -0400293
294 if (count[2] > count[3]) {
295 if (gfs2_consist_rgrpd(rgd))
296 fs_err(sdp, "unlinked inodes > inodes: %u\n",
297 count[2]);
298 return;
299 }
300
David Teiglandb3b94fa2006-01-16 16:50:04 +0000301}
302
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100303static inline int rgrp_contains_block(struct gfs2_rgrpd *rgd, u64 block)
David Teiglandb3b94fa2006-01-16 16:50:04 +0000304{
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100305 u64 first = rgd->rd_data0;
306 u64 last = first + rgd->rd_data;
Steven Whitehouse16910422006-09-05 11:15:45 -0400307 return first <= block && block < last;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000308}
309
310/**
311 * gfs2_blk2rgrpd - Find resource group for a given data/meta block number
312 * @sdp: The GFS2 superblock
313 * @n: The data block number
314 *
315 * Returns: The resource group, or NULL if not found
316 */
317
Steven Whitehousecd915492006-09-04 12:49:07 -0400318struct gfs2_rgrpd *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, u64 blk)
David Teiglandb3b94fa2006-01-16 16:50:04 +0000319{
320 struct gfs2_rgrpd *rgd;
321
322 spin_lock(&sdp->sd_rindex_spin);
323
324 list_for_each_entry(rgd, &sdp->sd_rindex_mru_list, rd_list_mru) {
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100325 if (rgrp_contains_block(rgd, blk)) {
David Teiglandb3b94fa2006-01-16 16:50:04 +0000326 list_move(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list);
327 spin_unlock(&sdp->sd_rindex_spin);
328 return rgd;
329 }
330 }
331
332 spin_unlock(&sdp->sd_rindex_spin);
333
334 return NULL;
335}
336
337/**
338 * gfs2_rgrpd_get_first - get the first Resource Group in the filesystem
339 * @sdp: The GFS2 superblock
340 *
341 * Returns: The first rgrp in the filesystem
342 */
343
344struct gfs2_rgrpd *gfs2_rgrpd_get_first(struct gfs2_sbd *sdp)
345{
346 gfs2_assert(sdp, !list_empty(&sdp->sd_rindex_list));
347 return list_entry(sdp->sd_rindex_list.next, struct gfs2_rgrpd, rd_list);
348}
349
350/**
351 * gfs2_rgrpd_get_next - get the next RG
352 * @rgd: A RG
353 *
354 * Returns: The next rgrp
355 */
356
357struct gfs2_rgrpd *gfs2_rgrpd_get_next(struct gfs2_rgrpd *rgd)
358{
359 if (rgd->rd_list.next == &rgd->rd_sbd->sd_rindex_list)
360 return NULL;
361 return list_entry(rgd->rd_list.next, struct gfs2_rgrpd, rd_list);
362}
363
364static void clear_rgrpdi(struct gfs2_sbd *sdp)
365{
366 struct list_head *head;
367 struct gfs2_rgrpd *rgd;
368 struct gfs2_glock *gl;
369
370 spin_lock(&sdp->sd_rindex_spin);
371 sdp->sd_rindex_forward = NULL;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000372 spin_unlock(&sdp->sd_rindex_spin);
373
374 head = &sdp->sd_rindex_list;
375 while (!list_empty(head)) {
376 rgd = list_entry(head->next, struct gfs2_rgrpd, rd_list);
377 gl = rgd->rd_gl;
378
379 list_del(&rgd->rd_list);
380 list_del(&rgd->rd_list_mru);
381
382 if (gl) {
Steven Whitehouse5c676f62006-02-27 17:23:27 -0500383 gl->gl_object = NULL;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000384 gfs2_glock_put(gl);
385 }
386
387 kfree(rgd->rd_bits);
Bob Peterson6bdd9be2008-01-28 17:20:26 -0600388 kmem_cache_free(gfs2_rgrpd_cachep, rgd);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000389 }
390}
391
392void gfs2_clear_rgrpd(struct gfs2_sbd *sdp)
393{
Steven Whitehousef55ab262006-02-21 12:51:39 +0000394 mutex_lock(&sdp->sd_rindex_mutex);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000395 clear_rgrpdi(sdp);
Steven Whitehousef55ab262006-02-21 12:51:39 +0000396 mutex_unlock(&sdp->sd_rindex_mutex);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000397}
398
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100399static void gfs2_rindex_print(const struct gfs2_rgrpd *rgd)
400{
401 printk(KERN_INFO " ri_addr = %llu\n", (unsigned long long)rgd->rd_addr);
402 printk(KERN_INFO " ri_length = %u\n", rgd->rd_length);
403 printk(KERN_INFO " ri_data0 = %llu\n", (unsigned long long)rgd->rd_data0);
404 printk(KERN_INFO " ri_data = %u\n", rgd->rd_data);
405 printk(KERN_INFO " ri_bitbytes = %u\n", rgd->rd_bitbytes);
406}
407
David Teiglandb3b94fa2006-01-16 16:50:04 +0000408/**
409 * gfs2_compute_bitstructs - Compute the bitmap sizes
410 * @rgd: The resource group descriptor
411 *
412 * Calculates bitmap descriptors, one for each block that contains bitmap data
413 *
414 * Returns: errno
415 */
416
417static int compute_bitstructs(struct gfs2_rgrpd *rgd)
418{
419 struct gfs2_sbd *sdp = rgd->rd_sbd;
420 struct gfs2_bitmap *bi;
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100421 u32 length = rgd->rd_length; /* # blocks in hdr & bitmap */
Steven Whitehousecd915492006-09-04 12:49:07 -0400422 u32 bytes_left, bytes;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000423 int x;
424
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -0400425 if (!length)
426 return -EINVAL;
427
Steven Whitehousedd894be2006-07-27 14:29:00 -0400428 rgd->rd_bits = kcalloc(length, sizeof(struct gfs2_bitmap), GFP_NOFS);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000429 if (!rgd->rd_bits)
430 return -ENOMEM;
431
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100432 bytes_left = rgd->rd_bitbytes;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000433
434 for (x = 0; x < length; x++) {
435 bi = rgd->rd_bits + x;
436
437 /* small rgrp; bitmap stored completely in header block */
438 if (length == 1) {
439 bytes = bytes_left;
440 bi->bi_offset = sizeof(struct gfs2_rgrp);
441 bi->bi_start = 0;
442 bi->bi_len = bytes;
443 /* header block */
444 } else if (x == 0) {
445 bytes = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_rgrp);
446 bi->bi_offset = sizeof(struct gfs2_rgrp);
447 bi->bi_start = 0;
448 bi->bi_len = bytes;
449 /* last block */
450 } else if (x + 1 == length) {
451 bytes = bytes_left;
452 bi->bi_offset = sizeof(struct gfs2_meta_header);
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100453 bi->bi_start = rgd->rd_bitbytes - bytes_left;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000454 bi->bi_len = bytes;
455 /* other blocks */
456 } else {
Steven Whitehouse568f4c92006-02-27 12:00:42 -0500457 bytes = sdp->sd_sb.sb_bsize -
458 sizeof(struct gfs2_meta_header);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000459 bi->bi_offset = sizeof(struct gfs2_meta_header);
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100460 bi->bi_start = rgd->rd_bitbytes - bytes_left;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000461 bi->bi_len = bytes;
462 }
463
464 bytes_left -= bytes;
465 }
466
467 if (bytes_left) {
468 gfs2_consist_rgrpd(rgd);
469 return -EIO;
470 }
471 bi = rgd->rd_bits + (length - 1);
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100472 if ((bi->bi_start + bi->bi_len) * GFS2_NBBY != rgd->rd_data) {
David Teiglandb3b94fa2006-01-16 16:50:04 +0000473 if (gfs2_consist_rgrpd(rgd)) {
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100474 gfs2_rindex_print(rgd);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000475 fs_err(sdp, "start=%u len=%u offset=%u\n",
476 bi->bi_start, bi->bi_len, bi->bi_offset);
477 }
478 return -EIO;
479 }
480
481 return 0;
482}
483
484/**
Robert Peterson7ae8fa82007-05-09 09:37:57 -0500485 * gfs2_ri_total - Total up the file system space, according to the rindex.
486 *
487 */
488u64 gfs2_ri_total(struct gfs2_sbd *sdp)
489{
490 u64 total_data = 0;
491 struct inode *inode = sdp->sd_rindex;
492 struct gfs2_inode *ip = GFS2_I(inode);
Robert Peterson7ae8fa82007-05-09 09:37:57 -0500493 char buf[sizeof(struct gfs2_rindex)];
494 struct file_ra_state ra_state;
495 int error, rgrps;
496
497 mutex_lock(&sdp->sd_rindex_mutex);
498 file_ra_state_init(&ra_state, inode->i_mapping);
499 for (rgrps = 0;; rgrps++) {
500 loff_t pos = rgrps * sizeof(struct gfs2_rindex);
501
Steven Whitehousec9e98882008-11-04 09:47:33 +0000502 if (pos + sizeof(struct gfs2_rindex) >= ip->i_disksize)
Robert Peterson7ae8fa82007-05-09 09:37:57 -0500503 break;
504 error = gfs2_internal_read(ip, &ra_state, buf, &pos,
505 sizeof(struct gfs2_rindex));
506 if (error != sizeof(struct gfs2_rindex))
507 break;
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100508 total_data += be32_to_cpu(((struct gfs2_rindex *)buf)->ri_data);
Robert Peterson7ae8fa82007-05-09 09:37:57 -0500509 }
510 mutex_unlock(&sdp->sd_rindex_mutex);
511 return total_data;
512}
513
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100514static void gfs2_rindex_in(struct gfs2_rgrpd *rgd, const void *buf)
515{
516 const struct gfs2_rindex *str = buf;
517
518 rgd->rd_addr = be64_to_cpu(str->ri_addr);
519 rgd->rd_length = be32_to_cpu(str->ri_length);
520 rgd->rd_data0 = be64_to_cpu(str->ri_data0);
521 rgd->rd_data = be32_to_cpu(str->ri_data);
522 rgd->rd_bitbytes = be32_to_cpu(str->ri_bitbytes);
523}
524
Robert Peterson7ae8fa82007-05-09 09:37:57 -0500525/**
Robert Peterson6c532672007-05-10 16:54:38 -0500526 * read_rindex_entry - Pull in a new resource index entry from the disk
David Teiglandb3b94fa2006-01-16 16:50:04 +0000527 * @gl: The glock covering the rindex inode
528 *
Robert Peterson6c532672007-05-10 16:54:38 -0500529 * Returns: 0 on success, error code otherwise
530 */
531
532static int read_rindex_entry(struct gfs2_inode *ip,
533 struct file_ra_state *ra_state)
534{
535 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
536 loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex);
537 char buf[sizeof(struct gfs2_rindex)];
538 int error;
539 struct gfs2_rgrpd *rgd;
540
541 error = gfs2_internal_read(ip, ra_state, buf, &pos,
542 sizeof(struct gfs2_rindex));
543 if (!error)
544 return 0;
545 if (error != sizeof(struct gfs2_rindex)) {
546 if (error > 0)
547 error = -EIO;
548 return error;
549 }
550
Bob Peterson6bdd9be2008-01-28 17:20:26 -0600551 rgd = kmem_cache_zalloc(gfs2_rgrpd_cachep, GFP_NOFS);
Robert Peterson6c532672007-05-10 16:54:38 -0500552 error = -ENOMEM;
553 if (!rgd)
554 return error;
555
556 mutex_init(&rgd->rd_mutex);
557 lops_init_le(&rgd->rd_le, &gfs2_rg_lops);
558 rgd->rd_sbd = sdp;
559
560 list_add_tail(&rgd->rd_list, &sdp->sd_rindex_list);
561 list_add_tail(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list);
562
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100563 gfs2_rindex_in(rgd, buf);
Robert Peterson6c532672007-05-10 16:54:38 -0500564 error = compute_bitstructs(rgd);
565 if (error)
566 return error;
567
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100568 error = gfs2_glock_get(sdp, rgd->rd_addr,
Robert Peterson6c532672007-05-10 16:54:38 -0500569 &gfs2_rgrp_glops, CREATE, &rgd->rd_gl);
570 if (error)
571 return error;
572
573 rgd->rd_gl->gl_object = rgd;
Bob Petersoncf45b752008-01-31 10:31:39 -0600574 rgd->rd_flags &= ~GFS2_RDF_UPTODATE;
Steven Whitehousec8cdf472007-06-08 10:05:33 +0100575 rgd->rd_flags |= GFS2_RDF_CHECK;
Robert Peterson6c532672007-05-10 16:54:38 -0500576 return error;
577}
578
579/**
580 * gfs2_ri_update - Pull in a new resource index from the disk
581 * @ip: pointer to the rindex inode
582 *
David Teiglandb3b94fa2006-01-16 16:50:04 +0000583 * Returns: 0 on successful update, error code otherwise
584 */
585
586static int gfs2_ri_update(struct gfs2_inode *ip)
587{
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -0400588 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
589 struct inode *inode = &ip->i_inode;
Steven Whitehousef42faf42006-01-30 18:34:10 +0000590 struct file_ra_state ra_state;
Steven Whitehousec9e98882008-11-04 09:47:33 +0000591 u64 rgrp_count = ip->i_disksize;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000592 int error;
593
Robert Petersoncd81a4b2007-05-14 12:42:18 -0500594 if (do_div(rgrp_count, sizeof(struct gfs2_rindex))) {
David Teiglandb3b94fa2006-01-16 16:50:04 +0000595 gfs2_consist_inode(ip);
596 return -EIO;
597 }
598
599 clear_rgrpdi(sdp);
600
Steven Whitehousef42faf42006-01-30 18:34:10 +0000601 file_ra_state_init(&ra_state, inode->i_mapping);
Robert Petersoncd81a4b2007-05-14 12:42:18 -0500602 for (sdp->sd_rgrps = 0; sdp->sd_rgrps < rgrp_count; sdp->sd_rgrps++) {
Robert Peterson6c532672007-05-10 16:54:38 -0500603 error = read_rindex_entry(ip, &ra_state);
604 if (error) {
605 clear_rgrpdi(sdp);
606 return error;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000607 }
David Teiglandb3b94fa2006-01-16 16:50:04 +0000608 }
609
Bob Petersoncf45b752008-01-31 10:31:39 -0600610 sdp->sd_rindex_uptodate = 1;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000611 return 0;
Robert Peterson6c532672007-05-10 16:54:38 -0500612}
David Teiglandb3b94fa2006-01-16 16:50:04 +0000613
Robert Peterson6c532672007-05-10 16:54:38 -0500614/**
615 * gfs2_ri_update_special - Pull in a new resource index from the disk
616 *
617 * This is a special version that's safe to call from gfs2_inplace_reserve_i.
618 * In this case we know that we don't have any resource groups in memory yet.
619 *
620 * @ip: pointer to the rindex inode
621 *
622 * Returns: 0 on successful update, error code otherwise
623 */
624static int gfs2_ri_update_special(struct gfs2_inode *ip)
625{
626 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
627 struct inode *inode = &ip->i_inode;
628 struct file_ra_state ra_state;
629 int error;
630
631 file_ra_state_init(&ra_state, inode->i_mapping);
632 for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) {
633 /* Ignore partials */
634 if ((sdp->sd_rgrps + 1) * sizeof(struct gfs2_rindex) >
Steven Whitehousec9e98882008-11-04 09:47:33 +0000635 ip->i_disksize)
Robert Peterson6c532672007-05-10 16:54:38 -0500636 break;
637 error = read_rindex_entry(ip, &ra_state);
638 if (error) {
639 clear_rgrpdi(sdp);
640 return error;
641 }
642 }
643
Bob Petersoncf45b752008-01-31 10:31:39 -0600644 sdp->sd_rindex_uptodate = 1;
Robert Peterson6c532672007-05-10 16:54:38 -0500645 return 0;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000646}
647
648/**
649 * gfs2_rindex_hold - Grab a lock on the rindex
650 * @sdp: The GFS2 superblock
651 * @ri_gh: the glock holder
652 *
653 * We grab a lock on the rindex inode to make sure that it doesn't
654 * change whilst we are performing an operation. We keep this lock
655 * for quite long periods of time compared to other locks. This
656 * doesn't matter, since it is shared and it is very, very rarely
657 * accessed in the exclusive mode (i.e. only when expanding the filesystem).
658 *
659 * This makes sure that we're using the latest copy of the resource index
660 * special file, which might have been updated if someone expanded the
661 * filesystem (via gfs2_grow utility), which adds new resource groups.
662 *
663 * Returns: 0 on success, error code otherwise
664 */
665
666int gfs2_rindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ri_gh)
667{
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -0400668 struct gfs2_inode *ip = GFS2_I(sdp->sd_rindex);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000669 struct gfs2_glock *gl = ip->i_gl;
670 int error;
671
672 error = gfs2_glock_nq_init(gl, LM_ST_SHARED, 0, ri_gh);
673 if (error)
674 return error;
675
676 /* Read new copy from disk if we don't have the latest */
Bob Petersoncf45b752008-01-31 10:31:39 -0600677 if (!sdp->sd_rindex_uptodate) {
Steven Whitehousef55ab262006-02-21 12:51:39 +0000678 mutex_lock(&sdp->sd_rindex_mutex);
Bob Petersoncf45b752008-01-31 10:31:39 -0600679 if (!sdp->sd_rindex_uptodate) {
David Teiglandb3b94fa2006-01-16 16:50:04 +0000680 error = gfs2_ri_update(ip);
681 if (error)
682 gfs2_glock_dq_uninit(ri_gh);
683 }
Steven Whitehousef55ab262006-02-21 12:51:39 +0000684 mutex_unlock(&sdp->sd_rindex_mutex);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000685 }
686
687 return error;
688}
689
Bob Peterson42d52e32008-01-28 18:38:07 -0600690static void gfs2_rgrp_in(struct gfs2_rgrpd *rgd, const void *buf)
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100691{
692 const struct gfs2_rgrp *str = buf;
Bob Peterson42d52e32008-01-28 18:38:07 -0600693 u32 rg_flags;
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100694
Bob Peterson42d52e32008-01-28 18:38:07 -0600695 rg_flags = be32_to_cpu(str->rg_flags);
696 if (rg_flags & GFS2_RGF_NOALLOC)
697 rgd->rd_flags |= GFS2_RDF_NOALLOC;
698 else
699 rgd->rd_flags &= ~GFS2_RDF_NOALLOC;
Steven Whitehousecfc8b542008-11-04 10:25:13 +0000700 rgd->rd_free = be32_to_cpu(str->rg_free);
Steven Whitehouse73f74942008-11-04 10:32:57 +0000701 rgd->rd_dinodes = be32_to_cpu(str->rg_dinodes);
Steven Whitehoused8b71f72008-11-04 10:19:03 +0000702 rgd->rd_igeneration = be64_to_cpu(str->rg_igeneration);
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100703}
704
Bob Peterson42d52e32008-01-28 18:38:07 -0600705static void gfs2_rgrp_out(struct gfs2_rgrpd *rgd, void *buf)
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100706{
707 struct gfs2_rgrp *str = buf;
Bob Peterson42d52e32008-01-28 18:38:07 -0600708 u32 rg_flags = 0;
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100709
Bob Peterson42d52e32008-01-28 18:38:07 -0600710 if (rgd->rd_flags & GFS2_RDF_NOALLOC)
711 rg_flags |= GFS2_RGF_NOALLOC;
712 str->rg_flags = cpu_to_be32(rg_flags);
Steven Whitehousecfc8b542008-11-04 10:25:13 +0000713 str->rg_free = cpu_to_be32(rgd->rd_free);
Steven Whitehouse73f74942008-11-04 10:32:57 +0000714 str->rg_dinodes = cpu_to_be32(rgd->rd_dinodes);
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100715 str->__pad = cpu_to_be32(0);
Steven Whitehoused8b71f72008-11-04 10:19:03 +0000716 str->rg_igeneration = cpu_to_be64(rgd->rd_igeneration);
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100717 memset(&str->rg_reserved, 0, sizeof(str->rg_reserved));
718}
719
David Teiglandb3b94fa2006-01-16 16:50:04 +0000720/**
721 * gfs2_rgrp_bh_get - Read in a RG's header and bitmaps
722 * @rgd: the struct gfs2_rgrpd describing the RG to read in
723 *
724 * Read in all of a Resource Group's header and bitmap blocks.
725 * Caller must eventually call gfs2_rgrp_relse() to free the bitmaps.
726 *
727 * Returns: errno
728 */
729
730int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd)
731{
732 struct gfs2_sbd *sdp = rgd->rd_sbd;
733 struct gfs2_glock *gl = rgd->rd_gl;
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100734 unsigned int length = rgd->rd_length;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000735 struct gfs2_bitmap *bi;
736 unsigned int x, y;
737 int error;
738
Steven Whitehousef55ab262006-02-21 12:51:39 +0000739 mutex_lock(&rgd->rd_mutex);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000740
741 spin_lock(&sdp->sd_rindex_spin);
742 if (rgd->rd_bh_count) {
743 rgd->rd_bh_count++;
744 spin_unlock(&sdp->sd_rindex_spin);
Steven Whitehousef55ab262006-02-21 12:51:39 +0000745 mutex_unlock(&rgd->rd_mutex);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000746 return 0;
747 }
748 spin_unlock(&sdp->sd_rindex_spin);
749
750 for (x = 0; x < length; x++) {
751 bi = rgd->rd_bits + x;
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100752 error = gfs2_meta_read(gl, rgd->rd_addr + x, 0, &bi->bi_bh);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000753 if (error)
754 goto fail;
755 }
756
757 for (y = length; y--;) {
758 bi = rgd->rd_bits + y;
Steven Whitehouse7276b3b2006-09-21 17:05:23 -0400759 error = gfs2_meta_wait(sdp, bi->bi_bh);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000760 if (error)
761 goto fail;
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -0400762 if (gfs2_metatype_check(sdp, bi->bi_bh, y ? GFS2_METATYPE_RB :
David Teiglandb3b94fa2006-01-16 16:50:04 +0000763 GFS2_METATYPE_RG)) {
764 error = -EIO;
765 goto fail;
766 }
767 }
768
Bob Petersoncf45b752008-01-31 10:31:39 -0600769 if (!(rgd->rd_flags & GFS2_RDF_UPTODATE)) {
Bob Peterson42d52e32008-01-28 18:38:07 -0600770 gfs2_rgrp_in(rgd, (rgd->rd_bits[0].bi_bh)->b_data);
Bob Petersoncf45b752008-01-31 10:31:39 -0600771 rgd->rd_flags |= GFS2_RDF_UPTODATE;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000772 }
773
774 spin_lock(&sdp->sd_rindex_spin);
Steven Whitehousecfc8b542008-11-04 10:25:13 +0000775 rgd->rd_free_clone = rgd->rd_free;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000776 rgd->rd_bh_count++;
777 spin_unlock(&sdp->sd_rindex_spin);
778
Steven Whitehousef55ab262006-02-21 12:51:39 +0000779 mutex_unlock(&rgd->rd_mutex);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000780
781 return 0;
782
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -0400783fail:
David Teiglandb3b94fa2006-01-16 16:50:04 +0000784 while (x--) {
785 bi = rgd->rd_bits + x;
786 brelse(bi->bi_bh);
787 bi->bi_bh = NULL;
788 gfs2_assert_warn(sdp, !bi->bi_clone);
789 }
Steven Whitehousef55ab262006-02-21 12:51:39 +0000790 mutex_unlock(&rgd->rd_mutex);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000791
792 return error;
793}
794
795void gfs2_rgrp_bh_hold(struct gfs2_rgrpd *rgd)
796{
797 struct gfs2_sbd *sdp = rgd->rd_sbd;
798
799 spin_lock(&sdp->sd_rindex_spin);
800 gfs2_assert_warn(rgd->rd_sbd, rgd->rd_bh_count);
801 rgd->rd_bh_count++;
802 spin_unlock(&sdp->sd_rindex_spin);
803}
804
805/**
806 * gfs2_rgrp_bh_put - Release RG bitmaps read in with gfs2_rgrp_bh_get()
807 * @rgd: the struct gfs2_rgrpd describing the RG to read in
808 *
809 */
810
811void gfs2_rgrp_bh_put(struct gfs2_rgrpd *rgd)
812{
813 struct gfs2_sbd *sdp = rgd->rd_sbd;
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100814 int x, length = rgd->rd_length;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000815
816 spin_lock(&sdp->sd_rindex_spin);
817 gfs2_assert_warn(rgd->rd_sbd, rgd->rd_bh_count);
818 if (--rgd->rd_bh_count) {
819 spin_unlock(&sdp->sd_rindex_spin);
820 return;
821 }
822
823 for (x = 0; x < length; x++) {
824 struct gfs2_bitmap *bi = rgd->rd_bits + x;
825 kfree(bi->bi_clone);
826 bi->bi_clone = NULL;
827 brelse(bi->bi_bh);
828 bi->bi_bh = NULL;
829 }
830
831 spin_unlock(&sdp->sd_rindex_spin);
832}
833
Steven Whitehousef15ab562009-02-09 09:25:01 +0000834static void gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset,
835 const struct gfs2_bitmap *bi)
836{
837 struct super_block *sb = sdp->sd_vfs;
838 struct block_device *bdev = sb->s_bdev;
839 const unsigned int sects_per_blk = sdp->sd_sb.sb_bsize /
840 bdev_hardsect_size(sb->s_bdev);
841 u64 blk;
842 sector_t start;
843 sector_t nr_sects = 0;
844 int rv;
845 unsigned int x;
846
847 for (x = 0; x < bi->bi_len; x++) {
848 const u8 *orig = bi->bi_bh->b_data + bi->bi_offset + x;
849 const u8 *clone = bi->bi_clone + bi->bi_offset + x;
850 u8 diff = ~(*orig | (*orig >> 1)) & (*clone | (*clone >> 1));
851 diff &= 0x55;
852 if (diff == 0)
853 continue;
854 blk = offset + ((bi->bi_start + x) * GFS2_NBBY);
855 blk *= sects_per_blk; /* convert to sectors */
856 while(diff) {
857 if (diff & 1) {
858 if (nr_sects == 0)
859 goto start_new_extent;
860 if ((start + nr_sects) != blk) {
861 rv = blkdev_issue_discard(bdev, start,
862 nr_sects, GFP_NOFS);
863 if (rv)
864 goto fail;
865 nr_sects = 0;
866start_new_extent:
867 start = blk;
868 }
869 nr_sects += sects_per_blk;
870 }
871 diff >>= 2;
872 blk += sects_per_blk;
873 }
874 }
875 if (nr_sects) {
876 rv = blkdev_issue_discard(bdev, start, nr_sects, GFP_NOFS);
877 if (rv)
878 goto fail;
879 }
880 return;
881fail:
882 fs_warn(sdp, "error %d on discard request, turning discards off for this filesystem", rv);
883 sdp->sd_args.ar_discard = 0;
884}
885
David Teiglandb3b94fa2006-01-16 16:50:04 +0000886void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd)
887{
888 struct gfs2_sbd *sdp = rgd->rd_sbd;
Steven Whitehousebb8d8a62007-06-01 14:11:58 +0100889 unsigned int length = rgd->rd_length;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000890 unsigned int x;
891
892 for (x = 0; x < length; x++) {
893 struct gfs2_bitmap *bi = rgd->rd_bits + x;
894 if (!bi->bi_clone)
895 continue;
Steven Whitehousef15ab562009-02-09 09:25:01 +0000896 if (sdp->sd_args.ar_discard)
897 gfs2_rgrp_send_discards(sdp, rgd->rd_data0, bi);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000898 memcpy(bi->bi_clone + bi->bi_offset,
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -0400899 bi->bi_bh->b_data + bi->bi_offset, bi->bi_len);
David Teiglandb3b94fa2006-01-16 16:50:04 +0000900 }
901
902 spin_lock(&sdp->sd_rindex_spin);
Steven Whitehousecfc8b542008-11-04 10:25:13 +0000903 rgd->rd_free_clone = rgd->rd_free;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000904 spin_unlock(&sdp->sd_rindex_spin);
905}
906
907/**
908 * gfs2_alloc_get - get the struct gfs2_alloc structure for an inode
909 * @ip: the incore GFS2 inode structure
910 *
911 * Returns: the struct gfs2_alloc
912 */
913
914struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip)
915{
Steven Whitehouse6dbd8222008-01-10 15:18:55 +0000916 BUG_ON(ip->i_alloc != NULL);
917 ip->i_alloc = kzalloc(sizeof(struct gfs2_alloc), GFP_KERNEL);
918 return ip->i_alloc;
David Teiglandb3b94fa2006-01-16 16:50:04 +0000919}
920
921/**
David Teiglandb3b94fa2006-01-16 16:50:04 +0000922 * try_rgrp_fit - See if a given reservation will fit in a given RG
923 * @rgd: the RG data
924 * @al: the struct gfs2_alloc structure describing the reservation
925 *
926 * If there's room for the requested blocks to be allocated from the RG:
David Teiglandb3b94fa2006-01-16 16:50:04 +0000927 * Sets the $al_rgd field in @al.
928 *
929 * Returns: 1 on success (it fits), 0 on failure (it doesn't fit)
930 */
931
932static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al)
933{
934 struct gfs2_sbd *sdp = rgd->rd_sbd;
935 int ret = 0;
936
Bob Peterson42d52e32008-01-28 18:38:07 -0600937 if (rgd->rd_flags & GFS2_RDF_NOALLOC)
Steven Whitehousea43a4902007-04-02 10:48:17 +0100938 return 0;
939
David Teiglandb3b94fa2006-01-16 16:50:04 +0000940 spin_lock(&sdp->sd_rindex_spin);
941 if (rgd->rd_free_clone >= al->al_requested) {
942 al->al_rgd = rgd;
943 ret = 1;
944 }
945 spin_unlock(&sdp->sd_rindex_spin);
946
947 return ret;
948}
949
950/**
Steven Whitehousec8cdf472007-06-08 10:05:33 +0100951 * try_rgrp_unlink - Look for any unlinked, allocated, but unused inodes
952 * @rgd: The rgrp
953 *
954 * Returns: The inode, if one has been found
955 */
956
957static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked)
958{
959 struct inode *inode;
Bob Peterson6760bdc2007-07-24 14:09:32 -0500960 u32 goal = 0, block;
Wendy Chengbb9bcf02007-06-27 17:07:08 -0400961 u64 no_addr;
Bob Peterson5f3eae72007-08-08 16:52:09 -0500962 struct gfs2_sbd *sdp = rgd->rd_sbd;
Steven Whitehouseb45e41d2008-02-06 10:11:15 +0000963 unsigned int n;
Steven Whitehousec8cdf472007-06-08 10:05:33 +0100964
965 for(;;) {
Bob Peterson24c73872007-07-12 16:58:50 -0500966 if (goal >= rgd->rd_data)
967 break;
Bob Peterson5f3eae72007-08-08 16:52:09 -0500968 down_write(&sdp->sd_log_flush_lock);
Steven Whitehouseb45e41d2008-02-06 10:11:15 +0000969 n = 1;
Bob Peterson6760bdc2007-07-24 14:09:32 -0500970 block = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED,
Steven Whitehouseb45e41d2008-02-06 10:11:15 +0000971 GFS2_BLKST_UNLINKED, &n);
Bob Peterson5f3eae72007-08-08 16:52:09 -0500972 up_write(&sdp->sd_log_flush_lock);
Bob Peterson6760bdc2007-07-24 14:09:32 -0500973 if (block == BFITNOENT)
Bob Peterson24c73872007-07-12 16:58:50 -0500974 break;
Bob Peterson6760bdc2007-07-24 14:09:32 -0500975 /* rgblk_search can return a block < goal, so we need to
976 keep it marching forward. */
977 no_addr = block + rgd->rd_data0;
Bob Peterson24c73872007-07-12 16:58:50 -0500978 goal++;
Bob Peterson6760bdc2007-07-24 14:09:32 -0500979 if (*last_unlinked != NO_BLOCK && no_addr <= *last_unlinked)
Steven Whitehousec8cdf472007-06-08 10:05:33 +0100980 continue;
Wendy Chengbb9bcf02007-06-27 17:07:08 -0400981 *last_unlinked = no_addr;
982 inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN,
Benjamin Marzinski7a9f53b2007-09-18 13:33:18 -0500983 no_addr, -1, 1);
Steven Whitehousec8cdf472007-06-08 10:05:33 +0100984 if (!IS_ERR(inode))
985 return inode;
986 }
987
988 rgd->rd_flags &= ~GFS2_RDF_CHECK;
989 return NULL;
990}
991
992/**
David Teiglandb3b94fa2006-01-16 16:50:04 +0000993 * recent_rgrp_next - get next RG from "recent" list
994 * @cur_rgd: current rgrp
David Teiglandb3b94fa2006-01-16 16:50:04 +0000995 *
996 * Returns: The next rgrp in the recent list
997 */
998
Steven Whitehouse9cabcdb2008-07-10 15:54:12 +0100999static struct gfs2_rgrpd *recent_rgrp_next(struct gfs2_rgrpd *cur_rgd)
David Teiglandb3b94fa2006-01-16 16:50:04 +00001000{
1001 struct gfs2_sbd *sdp = cur_rgd->rd_sbd;
1002 struct list_head *head;
1003 struct gfs2_rgrpd *rgd;
1004
1005 spin_lock(&sdp->sd_rindex_spin);
Steven Whitehouse9cabcdb2008-07-10 15:54:12 +01001006 head = &sdp->sd_rindex_mru_list;
1007 if (unlikely(cur_rgd->rd_list_mru.next == head)) {
1008 spin_unlock(&sdp->sd_rindex_spin);
1009 return NULL;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001010 }
Steven Whitehouse9cabcdb2008-07-10 15:54:12 +01001011 rgd = list_entry(cur_rgd->rd_list_mru.next, struct gfs2_rgrpd, rd_list_mru);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001012 spin_unlock(&sdp->sd_rindex_spin);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001013 return rgd;
1014}
1015
1016/**
David Teiglandb3b94fa2006-01-16 16:50:04 +00001017 * forward_rgrp_get - get an rgrp to try next from full list
1018 * @sdp: The GFS2 superblock
1019 *
1020 * Returns: The rgrp to try next
1021 */
1022
1023static struct gfs2_rgrpd *forward_rgrp_get(struct gfs2_sbd *sdp)
1024{
1025 struct gfs2_rgrpd *rgd;
1026 unsigned int journals = gfs2_jindex_size(sdp);
1027 unsigned int rg = 0, x;
1028
1029 spin_lock(&sdp->sd_rindex_spin);
1030
1031 rgd = sdp->sd_rindex_forward;
1032 if (!rgd) {
1033 if (sdp->sd_rgrps >= journals)
1034 rg = sdp->sd_rgrps * sdp->sd_jdesc->jd_jid / journals;
1035
Steven Whitehouseb8e1aab2006-08-22 16:25:50 -04001036 for (x = 0, rgd = gfs2_rgrpd_get_first(sdp); x < rg;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001037 x++, rgd = gfs2_rgrpd_get_next(rgd))
1038 /* Do Nothing */;
1039
1040 sdp->sd_rindex_forward = rgd;
1041 }
1042
1043 spin_unlock(&sdp->sd_rindex_spin);
1044
1045 return rgd;
1046}
1047
1048/**
1049 * forward_rgrp_set - set the forward rgrp pointer
1050 * @sdp: the filesystem
1051 * @rgd: The new forward rgrp
1052 *
1053 */
1054
1055static void forward_rgrp_set(struct gfs2_sbd *sdp, struct gfs2_rgrpd *rgd)
1056{
1057 spin_lock(&sdp->sd_rindex_spin);
1058 sdp->sd_rindex_forward = rgd;
1059 spin_unlock(&sdp->sd_rindex_spin);
1060}
1061
1062/**
1063 * get_local_rgrp - Choose and lock a rgrp for allocation
1064 * @ip: the inode to reserve space for
1065 * @rgp: the chosen and locked rgrp
1066 *
1067 * Try to acquire rgrp in way which avoids contending with others.
1068 *
1069 * Returns: errno
1070 */
1071
Steven Whitehousec8cdf472007-06-08 10:05:33 +01001072static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
David Teiglandb3b94fa2006-01-16 16:50:04 +00001073{
Steven Whitehousec8cdf472007-06-08 10:05:33 +01001074 struct inode *inode = NULL;
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -04001075 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001076 struct gfs2_rgrpd *rgd, *begin = NULL;
Steven Whitehouse6dbd8222008-01-10 15:18:55 +00001077 struct gfs2_alloc *al = ip->i_alloc;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001078 int flags = LM_FLAG_TRY;
1079 int skipped = 0;
1080 int loops = 0;
Abhijith Das292c8c12007-11-29 14:13:54 -06001081 int error, rg_locked;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001082
Steven Whitehouse9cabcdb2008-07-10 15:54:12 +01001083 rgd = gfs2_blk2rgrpd(sdp, ip->i_goal);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001084
1085 while (rgd) {
Abhijith Das292c8c12007-11-29 14:13:54 -06001086 rg_locked = 0;
1087
1088 if (gfs2_glock_is_locked_by_me(rgd->rd_gl)) {
1089 rg_locked = 1;
1090 error = 0;
1091 } else {
1092 error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE,
1093 LM_FLAG_TRY, &al->al_rgd_gh);
1094 }
David Teiglandb3b94fa2006-01-16 16:50:04 +00001095 switch (error) {
1096 case 0:
1097 if (try_rgrp_fit(rgd, al))
1098 goto out;
Steven Whitehousec8cdf472007-06-08 10:05:33 +01001099 if (rgd->rd_flags & GFS2_RDF_CHECK)
1100 inode = try_rgrp_unlink(rgd, last_unlinked);
Abhijith Das292c8c12007-11-29 14:13:54 -06001101 if (!rg_locked)
1102 gfs2_glock_dq_uninit(&al->al_rgd_gh);
Steven Whitehousec8cdf472007-06-08 10:05:33 +01001103 if (inode)
1104 return inode;
Steven Whitehouse9cabcdb2008-07-10 15:54:12 +01001105 /* fall through */
David Teiglandb3b94fa2006-01-16 16:50:04 +00001106 case GLR_TRYFAILED:
Steven Whitehouse9cabcdb2008-07-10 15:54:12 +01001107 rgd = recent_rgrp_next(rgd);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001108 break;
1109
1110 default:
Steven Whitehousec8cdf472007-06-08 10:05:33 +01001111 return ERR_PTR(error);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001112 }
1113 }
1114
1115 /* Go through full list of rgrps */
1116
1117 begin = rgd = forward_rgrp_get(sdp);
1118
1119 for (;;) {
Abhijith Das292c8c12007-11-29 14:13:54 -06001120 rg_locked = 0;
1121
1122 if (gfs2_glock_is_locked_by_me(rgd->rd_gl)) {
1123 rg_locked = 1;
1124 error = 0;
1125 } else {
1126 error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, flags,
1127 &al->al_rgd_gh);
1128 }
David Teiglandb3b94fa2006-01-16 16:50:04 +00001129 switch (error) {
1130 case 0:
1131 if (try_rgrp_fit(rgd, al))
1132 goto out;
Steven Whitehousec8cdf472007-06-08 10:05:33 +01001133 if (rgd->rd_flags & GFS2_RDF_CHECK)
1134 inode = try_rgrp_unlink(rgd, last_unlinked);
Abhijith Das292c8c12007-11-29 14:13:54 -06001135 if (!rg_locked)
1136 gfs2_glock_dq_uninit(&al->al_rgd_gh);
Steven Whitehousec8cdf472007-06-08 10:05:33 +01001137 if (inode)
1138 return inode;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001139 break;
1140
1141 case GLR_TRYFAILED:
1142 skipped++;
1143 break;
1144
1145 default:
Steven Whitehousec8cdf472007-06-08 10:05:33 +01001146 return ERR_PTR(error);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001147 }
1148
1149 rgd = gfs2_rgrpd_get_next(rgd);
1150 if (!rgd)
1151 rgd = gfs2_rgrpd_get_first(sdp);
1152
1153 if (rgd == begin) {
Benjamin Marzinski172e0452007-03-23 14:51:56 -06001154 if (++loops >= 3)
Steven Whitehousec8cdf472007-06-08 10:05:33 +01001155 return ERR_PTR(-ENOSPC);
Benjamin Marzinski172e0452007-03-23 14:51:56 -06001156 if (!skipped)
1157 loops++;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001158 flags = 0;
Benjamin Marzinski172e0452007-03-23 14:51:56 -06001159 if (loops == 2)
1160 gfs2_log_flush(sdp, NULL);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001161 }
1162 }
1163
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -04001164out:
David Teiglandb3b94fa2006-01-16 16:50:04 +00001165 if (begin) {
Steven Whitehouse9cabcdb2008-07-10 15:54:12 +01001166 spin_lock(&sdp->sd_rindex_spin);
1167 list_move(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list);
1168 spin_unlock(&sdp->sd_rindex_spin);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001169 rgd = gfs2_rgrpd_get_next(rgd);
1170 if (!rgd)
1171 rgd = gfs2_rgrpd_get_first(sdp);
1172 forward_rgrp_set(sdp, rgd);
1173 }
1174
Steven Whitehousec8cdf472007-06-08 10:05:33 +01001175 return NULL;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001176}
1177
1178/**
1179 * gfs2_inplace_reserve_i - Reserve space in the filesystem
1180 * @ip: the inode to reserve space for
1181 *
1182 * Returns: errno
1183 */
1184
1185int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
1186{
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -04001187 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
Steven Whitehouse6dbd8222008-01-10 15:18:55 +00001188 struct gfs2_alloc *al = ip->i_alloc;
Steven Whitehousec8cdf472007-06-08 10:05:33 +01001189 struct inode *inode;
Robert Peterson7ae8fa82007-05-09 09:37:57 -05001190 int error = 0;
Bob Peterson6760bdc2007-07-24 14:09:32 -05001191 u64 last_unlinked = NO_BLOCK;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001192
1193 if (gfs2_assert_warn(sdp, al->al_requested))
1194 return -EINVAL;
1195
Steven Whitehousec8cdf472007-06-08 10:05:33 +01001196try_again:
Robert Peterson7ae8fa82007-05-09 09:37:57 -05001197 /* We need to hold the rindex unless the inode we're using is
1198 the rindex itself, in which case it's already held. */
1199 if (ip != GFS2_I(sdp->sd_rindex))
1200 error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
1201 else if (!sdp->sd_rgrps) /* We may not have the rindex read in, so: */
Robert Peterson6c532672007-05-10 16:54:38 -05001202 error = gfs2_ri_update_special(ip);
Robert Peterson7ae8fa82007-05-09 09:37:57 -05001203
David Teiglandb3b94fa2006-01-16 16:50:04 +00001204 if (error)
1205 return error;
1206
Steven Whitehousec8cdf472007-06-08 10:05:33 +01001207 inode = get_local_rgrp(ip, &last_unlinked);
1208 if (inode) {
Robert Peterson7ae8fa82007-05-09 09:37:57 -05001209 if (ip != GFS2_I(sdp->sd_rindex))
1210 gfs2_glock_dq_uninit(&al->al_ri_gh);
Steven Whitehousec8cdf472007-06-08 10:05:33 +01001211 if (IS_ERR(inode))
1212 return PTR_ERR(inode);
1213 iput(inode);
1214 gfs2_log_flush(sdp, NULL);
1215 goto try_again;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001216 }
1217
1218 al->al_file = file;
1219 al->al_line = line;
1220
1221 return 0;
1222}
1223
1224/**
1225 * gfs2_inplace_release - release an inplace reservation
1226 * @ip: the inode the reservation was taken out on
1227 *
1228 * Release a reservation made by gfs2_inplace_reserve().
1229 */
1230
1231void gfs2_inplace_release(struct gfs2_inode *ip)
1232{
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -04001233 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
Steven Whitehouse6dbd8222008-01-10 15:18:55 +00001234 struct gfs2_alloc *al = ip->i_alloc;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001235
1236 if (gfs2_assert_warn(sdp, al->al_alloced <= al->al_requested) == -1)
1237 fs_warn(sdp, "al_alloced = %u, al_requested = %u "
1238 "al_file = %s, al_line = %u\n",
1239 al->al_alloced, al->al_requested, al->al_file,
1240 al->al_line);
1241
1242 al->al_rgd = NULL;
Abhijith Das292c8c12007-11-29 14:13:54 -06001243 if (al->al_rgd_gh.gh_gl)
1244 gfs2_glock_dq_uninit(&al->al_rgd_gh);
Robert Peterson7ae8fa82007-05-09 09:37:57 -05001245 if (ip != GFS2_I(sdp->sd_rindex))
1246 gfs2_glock_dq_uninit(&al->al_ri_gh);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001247}
1248
1249/**
1250 * gfs2_get_block_type - Check a block in a RG is of given type
1251 * @rgd: the resource group holding the block
1252 * @block: the block number
1253 *
1254 * Returns: The block type (GFS2_BLKST_*)
1255 */
1256
Steven Whitehousecd915492006-09-04 12:49:07 -04001257unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block)
David Teiglandb3b94fa2006-01-16 16:50:04 +00001258{
1259 struct gfs2_bitmap *bi = NULL;
Steven Whitehousecd915492006-09-04 12:49:07 -04001260 u32 length, rgrp_block, buf_block;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001261 unsigned int buf;
1262 unsigned char type;
1263
Steven Whitehousebb8d8a62007-06-01 14:11:58 +01001264 length = rgd->rd_length;
1265 rgrp_block = block - rgd->rd_data0;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001266
1267 for (buf = 0; buf < length; buf++) {
1268 bi = rgd->rd_bits + buf;
1269 if (rgrp_block < (bi->bi_start + bi->bi_len) * GFS2_NBBY)
1270 break;
1271 }
1272
1273 gfs2_assert(rgd->rd_sbd, buf < length);
1274 buf_block = rgrp_block - bi->bi_start * GFS2_NBBY;
1275
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -04001276 type = gfs2_testbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
David Teiglandb3b94fa2006-01-16 16:50:04 +00001277 bi->bi_len, buf_block);
1278
1279 return type;
1280}
1281
1282/**
1283 * rgblk_search - find a block in @old_state, change allocation
1284 * state to @new_state
1285 * @rgd: the resource group descriptor
1286 * @goal: the goal block within the RG (start here to search for avail block)
1287 * @old_state: GFS2_BLKST_XXX the before-allocation state to find
1288 * @new_state: GFS2_BLKST_XXX the after-allocation block state
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001289 * @n: The extent length
David Teiglandb3b94fa2006-01-16 16:50:04 +00001290 *
1291 * Walk rgrp's bitmap to find bits that represent a block in @old_state.
1292 * Add the found bitmap buffer to the transaction.
1293 * Set the found bits to @new_state to change block's allocation state.
1294 *
1295 * This function never fails, because we wouldn't call it unless we
1296 * know (from reservation results, etc.) that a block is available.
1297 *
1298 * Scope of @goal and returned block is just within rgrp, not the whole
1299 * filesystem.
1300 *
1301 * Returns: the block number allocated
1302 */
1303
Steven Whitehousecd915492006-09-04 12:49:07 -04001304static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001305 unsigned char old_state, unsigned char new_state,
1306 unsigned int *n)
David Teiglandb3b94fa2006-01-16 16:50:04 +00001307{
1308 struct gfs2_bitmap *bi = NULL;
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001309 const u32 length = rgd->rd_length;
Steven Whitehousecd915492006-09-04 12:49:07 -04001310 u32 blk = 0;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001311 unsigned int buf, x;
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001312 const unsigned int elen = *n;
1313 const u8 *buffer;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001314
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001315 *n = 0;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001316 /* Find bitmap block that contains bits for goal block */
1317 for (buf = 0; buf < length; buf++) {
1318 bi = rgd->rd_bits + buf;
1319 if (goal < (bi->bi_start + bi->bi_len) * GFS2_NBBY)
1320 break;
1321 }
1322
1323 gfs2_assert(rgd->rd_sbd, buf < length);
1324
1325 /* Convert scope of "goal" from rgrp-wide to within found bit block */
1326 goal -= bi->bi_start * GFS2_NBBY;
1327
1328 /* Search (up to entire) bitmap in this rgrp for allocatable block.
1329 "x <= length", instead of "x < length", because we typically start
1330 the search in the middle of a bit block, but if we can't find an
1331 allocatable block anywhere else, we want to be able wrap around and
1332 search in the first part of our first-searched bit block. */
1333 for (x = 0; x <= length; x++) {
Bob Peterson5f3eae72007-08-08 16:52:09 -05001334 /* The GFS2_BLKST_UNLINKED state doesn't apply to the clone
1335 bitmaps, so we must search the originals for that. */
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001336 buffer = bi->bi_bh->b_data + bi->bi_offset;
Bob Peterson5f3eae72007-08-08 16:52:09 -05001337 if (old_state != GFS2_BLKST_UNLINKED && bi->bi_clone)
Steven Whitehouse110acf32008-01-29 13:30:20 +00001338 buffer = bi->bi_clone + bi->bi_offset;
1339
1340 blk = gfs2_bitfit(buffer, bi->bi_len, goal, old_state);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001341 if (blk != BFITNOENT)
1342 break;
1343
1344 /* Try next bitmap block (wrap back to rgrp header if at end) */
1345 buf = (buf + 1) % length;
1346 bi = rgd->rd_bits + buf;
1347 goal = 0;
1348 }
1349
Bob Peterson6760bdc2007-07-24 14:09:32 -05001350 if (blk != BFITNOENT && old_state != new_state) {
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001351 *n = 1;
Steven Whitehousec8cdf472007-06-08 10:05:33 +01001352 gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001353 gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset,
David Teiglandb3b94fa2006-01-16 16:50:04 +00001354 bi->bi_len, blk, new_state);
Steven Whitehouse9b8c81d2008-02-22 16:09:31 +00001355 goal = blk;
1356 while (*n < elen) {
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001357 goal++;
Steven Whitehouse9b8c81d2008-02-22 16:09:31 +00001358 if (goal >= (bi->bi_len * GFS2_NBBY))
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001359 break;
1360 if (gfs2_testbit(rgd, buffer, bi->bi_len, goal) !=
1361 GFS2_BLKST_FREE)
1362 break;
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001363 gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone,
Steven Whitehouse9b8c81d2008-02-22 16:09:31 +00001364 bi->bi_offset, bi->bi_len, goal,
1365 new_state);
1366 (*n)++;
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001367 }
Steven Whitehousec8cdf472007-06-08 10:05:33 +01001368 }
David Teiglandb3b94fa2006-01-16 16:50:04 +00001369
Steven Whitehouse6eefaf62007-07-17 10:26:56 +01001370 return (blk == BFITNOENT) ? blk : (bi->bi_start * GFS2_NBBY) + blk;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001371}
1372
1373/**
1374 * rgblk_free - Change alloc state of given block(s)
1375 * @sdp: the filesystem
1376 * @bstart: the start of a run of blocks to free
1377 * @blen: the length of the block run (all must lie within ONE RG!)
1378 * @new_state: GFS2_BLKST_XXX the after-allocation block state
1379 *
1380 * Returns: Resource group containing the block(s)
1381 */
1382
Steven Whitehousecd915492006-09-04 12:49:07 -04001383static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart,
1384 u32 blen, unsigned char new_state)
David Teiglandb3b94fa2006-01-16 16:50:04 +00001385{
1386 struct gfs2_rgrpd *rgd;
1387 struct gfs2_bitmap *bi = NULL;
Steven Whitehousecd915492006-09-04 12:49:07 -04001388 u32 length, rgrp_blk, buf_blk;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001389 unsigned int buf;
1390
1391 rgd = gfs2_blk2rgrpd(sdp, bstart);
1392 if (!rgd) {
1393 if (gfs2_consist(sdp))
Steven Whitehouse382066d2006-05-24 10:22:09 -04001394 fs_err(sdp, "block = %llu\n", (unsigned long long)bstart);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001395 return NULL;
1396 }
1397
Steven Whitehousebb8d8a62007-06-01 14:11:58 +01001398 length = rgd->rd_length;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001399
Steven Whitehousebb8d8a62007-06-01 14:11:58 +01001400 rgrp_blk = bstart - rgd->rd_data0;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001401
1402 while (blen--) {
1403 for (buf = 0; buf < length; buf++) {
1404 bi = rgd->rd_bits + buf;
1405 if (rgrp_blk < (bi->bi_start + bi->bi_len) * GFS2_NBBY)
1406 break;
1407 }
1408
1409 gfs2_assert(rgd->rd_sbd, buf < length);
1410
1411 buf_blk = rgrp_blk - bi->bi_start * GFS2_NBBY;
1412 rgrp_blk++;
1413
1414 if (!bi->bi_clone) {
1415 bi->bi_clone = kmalloc(bi->bi_bh->b_size,
Steven Whitehousedd894be2006-07-27 14:29:00 -04001416 GFP_NOFS | __GFP_NOFAIL);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001417 memcpy(bi->bi_clone + bi->bi_offset,
1418 bi->bi_bh->b_data + bi->bi_offset,
1419 bi->bi_len);
1420 }
Steven Whitehoused4e9c4c2006-01-18 11:19:28 +00001421 gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001422 gfs2_setbit(rgd, bi->bi_bh->b_data, NULL, bi->bi_offset,
David Teiglandb3b94fa2006-01-16 16:50:04 +00001423 bi->bi_len, buf_blk, new_state);
1424 }
1425
1426 return rgd;
1427}
1428
1429/**
Steven Whitehouse16394312008-02-01 14:52:30 +00001430 * gfs2_alloc_block - Allocate a block
1431 * @ip: the inode to allocate the block for
David Teiglandb3b94fa2006-01-16 16:50:04 +00001432 *
1433 * Returns: the allocated block
1434 */
1435
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001436u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n)
David Teiglandb3b94fa2006-01-16 16:50:04 +00001437{
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -04001438 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
Steven Whitehouse6dbd8222008-01-10 15:18:55 +00001439 struct gfs2_alloc *al = ip->i_alloc;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001440 struct gfs2_rgrpd *rgd = al->al_rgd;
Steven Whitehousecd915492006-09-04 12:49:07 -04001441 u32 goal, blk;
1442 u64 block;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001443
Steven Whitehousece276b02008-02-06 09:25:45 +00001444 if (rgrp_contains_block(rgd, ip->i_goal))
1445 goal = ip->i_goal - rgd->rd_data0;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001446 else
Steven Whitehouseac576cc2008-02-01 10:34:15 +00001447 goal = rgd->rd_last_alloc;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001448
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001449 blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED, n);
Steven Whitehouse6eefaf62007-07-17 10:26:56 +01001450 BUG_ON(blk == BFITNOENT);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001451
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001452 rgd->rd_last_alloc = blk;
Steven Whitehousebb8d8a62007-06-01 14:11:58 +01001453 block = rgd->rd_data0 + blk;
Steven Whitehousece276b02008-02-06 09:25:45 +00001454 ip->i_goal = block;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001455
Steven Whitehousecfc8b542008-11-04 10:25:13 +00001456 gfs2_assert_withdraw(sdp, rgd->rd_free >= *n);
1457 rgd->rd_free -= *n;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001458
Steven Whitehoused4e9c4c2006-01-18 11:19:28 +00001459 gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
Bob Peterson42d52e32008-01-28 18:38:07 -06001460 gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001461
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001462 al->al_alloced += *n;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001463
Andrew Pricead99f772008-05-01 11:55:38 +01001464 gfs2_statfs_change(sdp, 0, -(s64)*n, 0);
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001465 gfs2_quota_change(ip, *n, ip->i_inode.i_uid, ip->i_inode.i_gid);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001466
1467 spin_lock(&sdp->sd_rindex_spin);
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001468 rgd->rd_free_clone -= *n;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001469 spin_unlock(&sdp->sd_rindex_spin);
1470
1471 return block;
1472}
1473
1474/**
1475 * gfs2_alloc_di - Allocate a dinode
1476 * @dip: the directory that the inode is going in
1477 *
1478 * Returns: the block allocated
1479 */
1480
Steven Whitehouse4340fe62006-07-11 09:46:33 -04001481u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
David Teiglandb3b94fa2006-01-16 16:50:04 +00001482{
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -04001483 struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
Steven Whitehouse6dbd8222008-01-10 15:18:55 +00001484 struct gfs2_alloc *al = dip->i_alloc;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001485 struct gfs2_rgrpd *rgd = al->al_rgd;
Steven Whitehouse4340fe62006-07-11 09:46:33 -04001486 u32 blk;
1487 u64 block;
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001488 unsigned int n = 1;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001489
Steven Whitehouseac576cc2008-02-01 10:34:15 +00001490 blk = rgblk_search(rgd, rgd->rd_last_alloc,
Steven Whitehouseb45e41d2008-02-06 10:11:15 +00001491 GFS2_BLKST_FREE, GFS2_BLKST_DINODE, &n);
Steven Whitehouse6eefaf62007-07-17 10:26:56 +01001492 BUG_ON(blk == BFITNOENT);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001493
Steven Whitehouseac576cc2008-02-01 10:34:15 +00001494 rgd->rd_last_alloc = blk;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001495
Steven Whitehousebb8d8a62007-06-01 14:11:58 +01001496 block = rgd->rd_data0 + blk;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001497
Steven Whitehousecfc8b542008-11-04 10:25:13 +00001498 gfs2_assert_withdraw(sdp, rgd->rd_free);
1499 rgd->rd_free--;
Steven Whitehouse73f74942008-11-04 10:32:57 +00001500 rgd->rd_dinodes++;
Steven Whitehoused8b71f72008-11-04 10:19:03 +00001501 *generation = rgd->rd_igeneration++;
Steven Whitehoused4e9c4c2006-01-18 11:19:28 +00001502 gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
Bob Peterson42d52e32008-01-28 18:38:07 -06001503 gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001504
1505 al->al_alloced++;
1506
1507 gfs2_statfs_change(sdp, 0, -1, +1);
Steven Whitehouse5731be52008-02-01 13:16:55 +00001508 gfs2_trans_add_unrevoke(sdp, block, 1);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001509
1510 spin_lock(&sdp->sd_rindex_spin);
1511 rgd->rd_free_clone--;
1512 spin_unlock(&sdp->sd_rindex_spin);
1513
1514 return block;
1515}
1516
1517/**
1518 * gfs2_free_data - free a contiguous run of data block(s)
1519 * @ip: the inode these blocks are being freed from
1520 * @bstart: first block of a run of contiguous blocks
1521 * @blen: the length of the block run
1522 *
1523 */
1524
Steven Whitehousecd915492006-09-04 12:49:07 -04001525void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
David Teiglandb3b94fa2006-01-16 16:50:04 +00001526{
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -04001527 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001528 struct gfs2_rgrpd *rgd;
1529
1530 rgd = rgblk_free(sdp, bstart, blen, GFS2_BLKST_FREE);
1531 if (!rgd)
1532 return;
1533
Steven Whitehousecfc8b542008-11-04 10:25:13 +00001534 rgd->rd_free += blen;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001535
Steven Whitehoused4e9c4c2006-01-18 11:19:28 +00001536 gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
Bob Peterson42d52e32008-01-28 18:38:07 -06001537 gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001538
1539 gfs2_trans_add_rg(rgd);
1540
1541 gfs2_statfs_change(sdp, 0, +blen, 0);
Steven Whitehouse2933f922006-11-01 13:23:29 -05001542 gfs2_quota_change(ip, -(s64)blen, ip->i_inode.i_uid, ip->i_inode.i_gid);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001543}
1544
1545/**
1546 * gfs2_free_meta - free a contiguous run of data block(s)
1547 * @ip: the inode these blocks are being freed from
1548 * @bstart: first block of a run of contiguous blocks
1549 * @blen: the length of the block run
1550 *
1551 */
1552
Steven Whitehousecd915492006-09-04 12:49:07 -04001553void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
David Teiglandb3b94fa2006-01-16 16:50:04 +00001554{
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -04001555 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001556 struct gfs2_rgrpd *rgd;
1557
1558 rgd = rgblk_free(sdp, bstart, blen, GFS2_BLKST_FREE);
1559 if (!rgd)
1560 return;
1561
Steven Whitehousecfc8b542008-11-04 10:25:13 +00001562 rgd->rd_free += blen;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001563
Steven Whitehoused4e9c4c2006-01-18 11:19:28 +00001564 gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
Bob Peterson42d52e32008-01-28 18:38:07 -06001565 gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001566
1567 gfs2_trans_add_rg(rgd);
1568
1569 gfs2_statfs_change(sdp, 0, +blen, 0);
Steven Whitehouse2933f922006-11-01 13:23:29 -05001570 gfs2_quota_change(ip, -(s64)blen, ip->i_inode.i_uid, ip->i_inode.i_gid);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001571 gfs2_meta_wipe(ip, bstart, blen);
1572}
1573
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -04001574void gfs2_unlink_di(struct inode *inode)
1575{
1576 struct gfs2_inode *ip = GFS2_I(inode);
1577 struct gfs2_sbd *sdp = GFS2_SB(inode);
1578 struct gfs2_rgrpd *rgd;
Steven Whitehousedbb7cae2007-05-15 15:37:50 +01001579 u64 blkno = ip->i_no_addr;
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -04001580
1581 rgd = rgblk_free(sdp, blkno, 1, GFS2_BLKST_UNLINKED);
1582 if (!rgd)
1583 return;
1584 gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
Bob Peterson42d52e32008-01-28 18:38:07 -06001585 gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
Steven Whitehousefeaa7bb2006-06-14 15:32:57 -04001586 gfs2_trans_add_rg(rgd);
1587}
1588
Steven Whitehousecd915492006-09-04 12:49:07 -04001589static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno)
David Teiglandb3b94fa2006-01-16 16:50:04 +00001590{
1591 struct gfs2_sbd *sdp = rgd->rd_sbd;
1592 struct gfs2_rgrpd *tmp_rgd;
1593
1594 tmp_rgd = rgblk_free(sdp, blkno, 1, GFS2_BLKST_FREE);
1595 if (!tmp_rgd)
1596 return;
1597 gfs2_assert_withdraw(sdp, rgd == tmp_rgd);
1598
Steven Whitehouse73f74942008-11-04 10:32:57 +00001599 if (!rgd->rd_dinodes)
David Teiglandb3b94fa2006-01-16 16:50:04 +00001600 gfs2_consist_rgrpd(rgd);
Steven Whitehouse73f74942008-11-04 10:32:57 +00001601 rgd->rd_dinodes--;
Steven Whitehousecfc8b542008-11-04 10:25:13 +00001602 rgd->rd_free++;
David Teiglandb3b94fa2006-01-16 16:50:04 +00001603
Steven Whitehoused4e9c4c2006-01-18 11:19:28 +00001604 gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
Bob Peterson42d52e32008-01-28 18:38:07 -06001605 gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001606
1607 gfs2_statfs_change(sdp, 0, +1, -1);
1608 gfs2_trans_add_rg(rgd);
1609}
1610
David Teiglandb3b94fa2006-01-16 16:50:04 +00001611
1612void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip)
1613{
Steven Whitehousedbb7cae2007-05-15 15:37:50 +01001614 gfs2_free_uninit_di(rgd, ip->i_no_addr);
Steven Whitehouse2933f922006-11-01 13:23:29 -05001615 gfs2_quota_change(ip, -1, ip->i_inode.i_uid, ip->i_inode.i_gid);
Steven Whitehousedbb7cae2007-05-15 15:37:50 +01001616 gfs2_meta_wipe(ip, ip->i_no_addr, 1);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001617}
1618
1619/**
1620 * gfs2_rlist_add - add a RG to a list of RGs
1621 * @sdp: the filesystem
1622 * @rlist: the list of resource groups
1623 * @block: the block
1624 *
1625 * Figure out what RG a block belongs to and add that RG to the list
1626 *
1627 * FIXME: Don't use NOFAIL
1628 *
1629 */
1630
1631void gfs2_rlist_add(struct gfs2_sbd *sdp, struct gfs2_rgrp_list *rlist,
Steven Whitehousecd915492006-09-04 12:49:07 -04001632 u64 block)
David Teiglandb3b94fa2006-01-16 16:50:04 +00001633{
1634 struct gfs2_rgrpd *rgd;
1635 struct gfs2_rgrpd **tmp;
1636 unsigned int new_space;
1637 unsigned int x;
1638
1639 if (gfs2_assert_warn(sdp, !rlist->rl_ghs))
1640 return;
1641
1642 rgd = gfs2_blk2rgrpd(sdp, block);
1643 if (!rgd) {
1644 if (gfs2_consist(sdp))
Steven Whitehouse382066d2006-05-24 10:22:09 -04001645 fs_err(sdp, "block = %llu\n", (unsigned long long)block);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001646 return;
1647 }
1648
1649 for (x = 0; x < rlist->rl_rgrps; x++)
1650 if (rlist->rl_rgd[x] == rgd)
1651 return;
1652
1653 if (rlist->rl_rgrps == rlist->rl_space) {
1654 new_space = rlist->rl_space + 10;
1655
1656 tmp = kcalloc(new_space, sizeof(struct gfs2_rgrpd *),
Steven Whitehousedd894be2006-07-27 14:29:00 -04001657 GFP_NOFS | __GFP_NOFAIL);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001658
1659 if (rlist->rl_rgd) {
1660 memcpy(tmp, rlist->rl_rgd,
1661 rlist->rl_space * sizeof(struct gfs2_rgrpd *));
1662 kfree(rlist->rl_rgd);
1663 }
1664
1665 rlist->rl_space = new_space;
1666 rlist->rl_rgd = tmp;
1667 }
1668
1669 rlist->rl_rgd[rlist->rl_rgrps++] = rgd;
1670}
1671
1672/**
1673 * gfs2_rlist_alloc - all RGs have been added to the rlist, now allocate
1674 * and initialize an array of glock holders for them
1675 * @rlist: the list of resource groups
1676 * @state: the lock state to acquire the RG lock in
1677 * @flags: the modifier flags for the holder structures
1678 *
1679 * FIXME: Don't use NOFAIL
1680 *
1681 */
1682
Bob Petersonfe6c9912008-01-28 11:13:02 -06001683void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state)
David Teiglandb3b94fa2006-01-16 16:50:04 +00001684{
1685 unsigned int x;
1686
1687 rlist->rl_ghs = kcalloc(rlist->rl_rgrps, sizeof(struct gfs2_holder),
Steven Whitehousedd894be2006-07-27 14:29:00 -04001688 GFP_NOFS | __GFP_NOFAIL);
David Teiglandb3b94fa2006-01-16 16:50:04 +00001689 for (x = 0; x < rlist->rl_rgrps; x++)
1690 gfs2_holder_init(rlist->rl_rgd[x]->rd_gl,
Bob Petersonfe6c9912008-01-28 11:13:02 -06001691 state, 0,
David Teiglandb3b94fa2006-01-16 16:50:04 +00001692 &rlist->rl_ghs[x]);
1693}
1694
1695/**
1696 * gfs2_rlist_free - free a resource group list
1697 * @list: the list of resource groups
1698 *
1699 */
1700
1701void gfs2_rlist_free(struct gfs2_rgrp_list *rlist)
1702{
1703 unsigned int x;
1704
1705 kfree(rlist->rl_rgd);
1706
1707 if (rlist->rl_ghs) {
1708 for (x = 0; x < rlist->rl_rgrps; x++)
1709 gfs2_holder_uninit(&rlist->rl_ghs[x]);
1710 kfree(rlist->rl_ghs);
1711 }
1712}
1713