aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/unlinked.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/unlinked.c')
-rw-r--r--fs/gfs2/unlinked.c459
1 files changed, 0 insertions, 459 deletions
diff --git a/fs/gfs2/unlinked.c b/fs/gfs2/unlinked.c
deleted file mode 100644
index b92d73002055..000000000000
--- a/fs/gfs2/unlinked.c
+++ /dev/null
@@ -1,459 +0,0 @@
1/*
2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
3 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
4 *
5 * This copyrighted material is made available to anyone wishing to use,
6 * modify, copy, or redistribute it subject to the terms and conditions
7 * of the GNU General Public License v.2.
8 */
9
10#include <linux/sched.h>
11#include <linux/slab.h>
12#include <linux/spinlock.h>
13#include <linux/completion.h>
14#include <linux/buffer_head.h>
15#include <linux/kthread.h>
16#include <linux/gfs2_ondisk.h>
17
18#include "gfs2.h"
19#include "lm_interface.h"
20#include "incore.h"
21#include "bmap.h"
22#include "inode.h"
23#include "meta_io.h"
24#include "trans.h"
25#include "unlinked.h"
26#include "util.h"
27
28static int munge_ondisk(struct gfs2_sbd *sdp, unsigned int slot,
29 struct gfs2_unlinked_tag *ut)
30{
31 struct gfs2_inode *ip = sdp->sd_ut_inode->u.generic_ip;
32 unsigned int block, offset;
33 uint64_t dblock;
34 int new = 0;
35 struct buffer_head *bh;
36 int error;
37 int boundary;
38
39 block = slot / sdp->sd_ut_per_block;
40 offset = slot % sdp->sd_ut_per_block;
41
42 error = gfs2_block_map(ip->i_vnode, block, &new, &dblock, &boundary);
43 if (error)
44 return error;
45 error = gfs2_meta_read(ip->i_gl, dblock, DIO_START | DIO_WAIT, &bh);
46 if (error)
47 return error;
48 if (gfs2_metatype_check(sdp, bh, GFS2_METATYPE_UT)) {
49 error = -EIO;
50 goto out;
51 }
52
53 mutex_lock(&sdp->sd_unlinked_mutex);
54 gfs2_trans_add_bh(ip->i_gl, bh, 1);
55 gfs2_unlinked_tag_out(ut, bh->b_data +
56 sizeof(struct gfs2_meta_header) +
57 offset * sizeof(struct gfs2_unlinked_tag));
58 mutex_unlock(&sdp->sd_unlinked_mutex);
59
60 out:
61 brelse(bh);
62
63 return error;
64}
65
66static void ul_hash(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
67{
68 spin_lock(&sdp->sd_unlinked_spin);
69 list_add(&ul->ul_list, &sdp->sd_unlinked_list);
70 gfs2_assert(sdp, ul->ul_count);
71 ul->ul_count++;
72 atomic_inc(&sdp->sd_unlinked_count);
73 spin_unlock(&sdp->sd_unlinked_spin);
74}
75
76static void ul_unhash(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
77{
78 spin_lock(&sdp->sd_unlinked_spin);
79 list_del_init(&ul->ul_list);
80 gfs2_assert(sdp, ul->ul_count > 1);
81 ul->ul_count--;
82 gfs2_assert_warn(sdp, atomic_read(&sdp->sd_unlinked_count) > 0);
83 atomic_dec(&sdp->sd_unlinked_count);
84 spin_unlock(&sdp->sd_unlinked_spin);
85}
86
87static struct gfs2_unlinked *ul_fish(struct gfs2_sbd *sdp)
88{
89 struct list_head *head;
90 struct gfs2_unlinked *ul;
91 int found = 0;
92
93 if (sdp->sd_vfs->s_flags & MS_RDONLY)
94 return NULL;
95
96 spin_lock(&sdp->sd_unlinked_spin);
97
98 head = &sdp->sd_unlinked_list;
99
100 list_for_each_entry(ul, head, ul_list) {
101 if (test_bit(ULF_LOCKED, &ul->ul_flags))
102 continue;
103
104 list_move_tail(&ul->ul_list, head);
105 ul->ul_count++;
106 set_bit(ULF_LOCKED, &ul->ul_flags);
107 found = 1;
108
109 break;
110 }
111
112 if (!found)
113 ul = NULL;
114
115 spin_unlock(&sdp->sd_unlinked_spin);
116
117 return ul;
118}
119
120/**
121 * enforce_limit - limit the number of inodes waiting to be deallocated
122 * @sdp: the filesystem
123 *
124 * Returns: errno
125 */
126
127static void enforce_limit(struct gfs2_sbd *sdp)
128{
129 unsigned int tries = 0, min = 0;
130 int error;
131
132 if (atomic_read(&sdp->sd_unlinked_count) <
133 gfs2_tune_get(sdp, gt_ilimit))
134 return;
135
136 tries = gfs2_tune_get(sdp, gt_ilimit_tries);
137 min = gfs2_tune_get(sdp, gt_ilimit_min);
138
139 while (tries--) {
140 struct gfs2_unlinked *ul = ul_fish(sdp);
141 if (!ul)
142 break;
143 error = gfs2_inode_dealloc(sdp, ul);
144 gfs2_unlinked_put(sdp, ul);
145
146 if (!error) {
147 if (!--min)
148 break;
149 } else if (error != 1)
150 break;
151 }
152}
153
154static struct gfs2_unlinked *ul_alloc(struct gfs2_sbd *sdp)
155{
156 struct gfs2_unlinked *ul;
157
158 ul = kzalloc(sizeof(struct gfs2_unlinked), GFP_KERNEL);
159 if (ul) {
160 INIT_LIST_HEAD(&ul->ul_list);
161 ul->ul_count = 1;
162 set_bit(ULF_LOCKED, &ul->ul_flags);
163 }
164
165 return ul;
166}
167
168int gfs2_unlinked_get(struct gfs2_sbd *sdp, struct gfs2_unlinked **ul)
169{
170 unsigned int c, o = 0, b;
171 unsigned char byte = 0;
172
173 enforce_limit(sdp);
174
175 *ul = ul_alloc(sdp);
176 if (!*ul)
177 return -ENOMEM;
178
179 spin_lock(&sdp->sd_unlinked_spin);
180
181 for (c = 0; c < sdp->sd_unlinked_chunks; c++)
182 for (o = 0; o < PAGE_SIZE; o++) {
183 byte = sdp->sd_unlinked_bitmap[c][o];
184 if (byte != 0xFF)
185 goto found;
186 }
187
188 goto fail;
189
190found:
191 for (b = 0; b < 8; b++)
192 if (!(byte & (1 << b)))
193 break;
194 (*ul)->ul_slot = c * (8 * PAGE_SIZE) + o * 8 + b;
195
196 if ((*ul)->ul_slot >= sdp->sd_unlinked_slots)
197 goto fail;
198
199 sdp->sd_unlinked_bitmap[c][o] |= 1 << b;
200
201 spin_unlock(&sdp->sd_unlinked_spin);
202
203 return 0;
204
205fail:
206 spin_unlock(&sdp->sd_unlinked_spin);
207 kfree(*ul);
208 return -ENOSPC;
209}
210
211void gfs2_unlinked_put(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
212{
213 gfs2_assert_warn(sdp, test_and_clear_bit(ULF_LOCKED, &ul->ul_flags));
214
215 spin_lock(&sdp->sd_unlinked_spin);
216 gfs2_assert(sdp, ul->ul_count);
217 ul->ul_count--;
218 if (!ul->ul_count) {
219 gfs2_icbit_munge(sdp, sdp->sd_unlinked_bitmap, ul->ul_slot, 0);
220 spin_unlock(&sdp->sd_unlinked_spin);
221 kfree(ul);
222 } else
223 spin_unlock(&sdp->sd_unlinked_spin);
224}
225
226int gfs2_unlinked_ondisk_add(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
227{
228 int error;
229
230 gfs2_assert_warn(sdp, test_bit(ULF_LOCKED, &ul->ul_flags));
231 gfs2_assert_warn(sdp, list_empty(&ul->ul_list));
232
233 error = munge_ondisk(sdp, ul->ul_slot, &ul->ul_ut);
234 if (!error)
235 ul_hash(sdp, ul);
236
237 return error;
238}
239
240int gfs2_unlinked_ondisk_munge(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
241{
242 int error;
243
244 gfs2_assert_warn(sdp, test_bit(ULF_LOCKED, &ul->ul_flags));
245 gfs2_assert_warn(sdp, !list_empty(&ul->ul_list));
246
247 error = munge_ondisk(sdp, ul->ul_slot, &ul->ul_ut);
248
249 return error;
250}
251
252int gfs2_unlinked_ondisk_rm(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
253{
254 struct gfs2_unlinked_tag ut;
255 int error;
256
257 gfs2_assert_warn(sdp, test_bit(ULF_LOCKED, &ul->ul_flags));
258 gfs2_assert_warn(sdp, !list_empty(&ul->ul_list));
259
260 memset(&ut, 0, sizeof(struct gfs2_unlinked_tag));
261
262 error = munge_ondisk(sdp, ul->ul_slot, &ut);
263 if (error)
264 return error;
265
266 ul_unhash(sdp, ul);
267
268 return 0;
269}
270
271/**
272 * gfs2_unlinked_dealloc - Go through the list of inodes to be deallocated
273 * @sdp: the filesystem
274 *
275 * Returns: errno
276 */
277
278int gfs2_unlinked_dealloc(struct gfs2_sbd *sdp)
279{
280 unsigned int hits, strikes;
281 int error;
282
283 for (;;) {
284 hits = 0;
285 strikes = 0;
286
287 for (;;) {
288 struct gfs2_unlinked *ul = ul_fish(sdp);
289 if (!ul)
290 return 0;
291 error = gfs2_inode_dealloc(sdp, ul);
292 gfs2_unlinked_put(sdp, ul);
293
294 if (!error) {
295 hits++;
296 if (strikes)
297 strikes--;
298 } else if (error == 1) {
299 strikes++;
300 if (strikes >=
301 atomic_read(&sdp->sd_unlinked_count)) {
302 error = 0;
303 break;
304 }
305 } else
306 return error;
307 }
308
309 if (!hits || kthread_should_stop())
310 break;
311
312 cond_resched();
313 }
314
315 return 0;
316}
317
318int gfs2_unlinked_init(struct gfs2_sbd *sdp)
319{
320 struct gfs2_inode *ip = sdp->sd_ut_inode->u.generic_ip;
321 unsigned int blocks = ip->i_di.di_size >> sdp->sd_sb.sb_bsize_shift;
322 unsigned int x, slot = 0;
323 unsigned int found = 0;
324 uint64_t dblock;
325 uint32_t extlen = 0;
326 int error;
327
328 if (!ip->i_di.di_size ||
329 ip->i_di.di_size > (64 << 20) ||
330 ip->i_di.di_size & (sdp->sd_sb.sb_bsize - 1)) {
331 gfs2_consist_inode(ip);
332 return -EIO;
333 }
334 sdp->sd_unlinked_slots = blocks * sdp->sd_ut_per_block;
335 sdp->sd_unlinked_chunks = DIV_ROUND_UP(sdp->sd_unlinked_slots,
336 8 * PAGE_SIZE);
337
338 error = -ENOMEM;
339
340 sdp->sd_unlinked_bitmap = kcalloc(sdp->sd_unlinked_chunks,
341 sizeof(unsigned char *),
342 GFP_KERNEL);
343 if (!sdp->sd_unlinked_bitmap)
344 return error;
345
346 for (x = 0; x < sdp->sd_unlinked_chunks; x++) {
347 sdp->sd_unlinked_bitmap[x] = kzalloc(PAGE_SIZE, GFP_KERNEL);
348 if (!sdp->sd_unlinked_bitmap[x])
349 goto fail;
350 }
351
352 for (x = 0; x < blocks; x++) {
353 struct buffer_head *bh;
354 unsigned int y;
355
356 if (!extlen) {
357 int new = 0;
358 error = gfs2_extent_map(ip->i_vnode, x, &new, &dblock, &extlen);
359 if (error)
360 goto fail;
361 }
362 gfs2_meta_ra(ip->i_gl, dblock, extlen);
363 error = gfs2_meta_read(ip->i_gl, dblock, DIO_START | DIO_WAIT,
364 &bh);
365 if (error)
366 goto fail;
367 error = -EIO;
368 if (gfs2_metatype_check(sdp, bh, GFS2_METATYPE_UT)) {
369 brelse(bh);
370 goto fail;
371 }
372
373 for (y = 0;
374 y < sdp->sd_ut_per_block && slot < sdp->sd_unlinked_slots;
375 y++, slot++) {
376 struct gfs2_unlinked_tag ut;
377 struct gfs2_unlinked *ul;
378
379 gfs2_unlinked_tag_in(&ut, bh->b_data +
380 sizeof(struct gfs2_meta_header) +
381 y * sizeof(struct gfs2_unlinked_tag));
382 if (!ut.ut_inum.no_addr)
383 continue;
384
385 error = -ENOMEM;
386 ul = ul_alloc(sdp);
387 if (!ul) {
388 brelse(bh);
389 goto fail;
390 }
391 ul->ul_ut = ut;
392 ul->ul_slot = slot;
393
394 spin_lock(&sdp->sd_unlinked_spin);
395 gfs2_icbit_munge(sdp, sdp->sd_unlinked_bitmap, slot, 1);
396 spin_unlock(&sdp->sd_unlinked_spin);
397 ul_hash(sdp, ul);
398
399 gfs2_unlinked_put(sdp, ul);
400 found++;
401 }
402
403 brelse(bh);
404 dblock++;
405 extlen--;
406 }
407
408 if (found)
409 fs_info(sdp, "found %u unlinked inodes\n", found);
410
411 return 0;
412
413fail:
414 gfs2_unlinked_cleanup(sdp);
415 return error;
416}
417
418/**
419 * gfs2_unlinked_cleanup - get rid of any extra struct gfs2_unlinked structures
420 * @sdp: the filesystem
421 *
422 */
423
424void gfs2_unlinked_cleanup(struct gfs2_sbd *sdp)
425{
426 struct list_head *head = &sdp->sd_unlinked_list;
427 struct gfs2_unlinked *ul;
428 unsigned int x;
429
430 spin_lock(&sdp->sd_unlinked_spin);
431 while (!list_empty(head)) {
432 ul = list_entry(head->next, struct gfs2_unlinked, ul_list);
433
434 if (ul->ul_count > 1) {
435 list_move_tail(&ul->ul_list, head);
436 spin_unlock(&sdp->sd_unlinked_spin);
437 schedule();
438 spin_lock(&sdp->sd_unlinked_spin);
439 continue;
440 }
441
442 list_del_init(&ul->ul_list);
443 atomic_dec(&sdp->sd_unlinked_count);
444
445 gfs2_assert_warn(sdp, ul->ul_count == 1);
446 gfs2_assert_warn(sdp, !test_bit(ULF_LOCKED, &ul->ul_flags));
447 kfree(ul);
448 }
449 spin_unlock(&sdp->sd_unlinked_spin);
450
451 gfs2_assert_warn(sdp, !atomic_read(&sdp->sd_unlinked_count));
452
453 if (sdp->sd_unlinked_bitmap) {
454 for (x = 0; x < sdp->sd_unlinked_chunks; x++)
455 kfree(sdp->sd_unlinked_bitmap[x]);
456 kfree(sdp->sd_unlinked_bitmap);
457 }
458}
459