summaryrefslogtreecommitdiffstats
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 b92d730..0000000
--- a/fs/gfs2/unlinked.c
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License v.2.
- */
-
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <linux/kthread.h>
-#include <linux/gfs2_ondisk.h>
-
-#include "gfs2.h"
-#include "lm_interface.h"
-#include "incore.h"
-#include "bmap.h"
-#include "inode.h"
-#include "meta_io.h"
-#include "trans.h"
-#include "unlinked.h"
-#include "util.h"
-
-static int munge_ondisk(struct gfs2_sbd *sdp, unsigned int slot,
- struct gfs2_unlinked_tag *ut)
-{
- struct gfs2_inode *ip = sdp->sd_ut_inode->u.generic_ip;
- unsigned int block, offset;
- uint64_t dblock;
- int new = 0;
- struct buffer_head *bh;
- int error;
- int boundary;
-
- block = slot / sdp->sd_ut_per_block;
- offset = slot % sdp->sd_ut_per_block;
-
- error = gfs2_block_map(ip->i_vnode, block, &new, &dblock, &boundary);
- if (error)
- return error;
- error = gfs2_meta_read(ip->i_gl, dblock, DIO_START | DIO_WAIT, &bh);
- if (error)
- return error;
- if (gfs2_metatype_check(sdp, bh, GFS2_METATYPE_UT)) {
- error = -EIO;
- goto out;
- }
-
- mutex_lock(&sdp->sd_unlinked_mutex);
- gfs2_trans_add_bh(ip->i_gl, bh, 1);
- gfs2_unlinked_tag_out(ut, bh->b_data +
- sizeof(struct gfs2_meta_header) +
- offset * sizeof(struct gfs2_unlinked_tag));
- mutex_unlock(&sdp->sd_unlinked_mutex);
-
- out:
- brelse(bh);
-
- return error;
-}
-
-static void ul_hash(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
-{
- spin_lock(&sdp->sd_unlinked_spin);
- list_add(&ul->ul_list, &sdp->sd_unlinked_list);
- gfs2_assert(sdp, ul->ul_count);
- ul->ul_count++;
- atomic_inc(&sdp->sd_unlinked_count);
- spin_unlock(&sdp->sd_unlinked_spin);
-}
-
-static void ul_unhash(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
-{
- spin_lock(&sdp->sd_unlinked_spin);
- list_del_init(&ul->ul_list);
- gfs2_assert(sdp, ul->ul_count > 1);
- ul->ul_count--;
- gfs2_assert_warn(sdp, atomic_read(&sdp->sd_unlinked_count) > 0);
- atomic_dec(&sdp->sd_unlinked_count);
- spin_unlock(&sdp->sd_unlinked_spin);
-}
-
-static struct gfs2_unlinked *ul_fish(struct gfs2_sbd *sdp)
-{
- struct list_head *head;
- struct gfs2_unlinked *ul;
- int found = 0;
-
- if (sdp->sd_vfs->s_flags & MS_RDONLY)
- return NULL;
-
- spin_lock(&sdp->sd_unlinked_spin);
-
- head = &sdp->sd_unlinked_list;
-
- list_for_each_entry(ul, head, ul_list) {
- if (test_bit(ULF_LOCKED, &ul->ul_flags))
- continue;
-
- list_move_tail(&ul->ul_list, head);
- ul->ul_count++;
- set_bit(ULF_LOCKED, &ul->ul_flags);
- found = 1;
-
- break;
- }
-
- if (!found)
- ul = NULL;
-
- spin_unlock(&sdp->sd_unlinked_spin);
-
- return ul;
-}
-
-/**
- * enforce_limit - limit the number of inodes waiting to be deallocated
- * @sdp: the filesystem
- *
- * Returns: errno
- */
-
-static void enforce_limit(struct gfs2_sbd *sdp)
-{
- unsigned int tries = 0, min = 0;
- int error;
-
- if (atomic_read(&sdp->sd_unlinked_count) <
- gfs2_tune_get(sdp, gt_ilimit))
- return;
-
- tries = gfs2_tune_get(sdp, gt_ilimit_tries);
- min = gfs2_tune_get(sdp, gt_ilimit_min);
-
- while (tries--) {
- struct gfs2_unlinked *ul = ul_fish(sdp);
- if (!ul)
- break;
- error = gfs2_inode_dealloc(sdp, ul);
- gfs2_unlinked_put(sdp, ul);
-
- if (!error) {
- if (!--min)
- break;
- } else if (error != 1)
- break;
- }
-}
-
-static struct gfs2_unlinked *ul_alloc(struct gfs2_sbd *sdp)
-{
- struct gfs2_unlinked *ul;
-
- ul = kzalloc(sizeof(struct gfs2_unlinked), GFP_KERNEL);
- if (ul) {
- INIT_LIST_HEAD(&ul->ul_list);
- ul->ul_count = 1;
- set_bit(ULF_LOCKED, &ul->ul_flags);
- }
-
- return ul;
-}
-
-int gfs2_unlinked_get(struct gfs2_sbd *sdp, struct gfs2_unlinked **ul)
-{
- unsigned int c, o = 0, b;
- unsigned char byte = 0;
-
- enforce_limit(sdp);
-
- *ul = ul_alloc(sdp);
- if (!*ul)
- return -ENOMEM;
-
- spin_lock(&sdp->sd_unlinked_spin);
-
- for (c = 0; c < sdp->sd_unlinked_chunks; c++)
- for (o = 0; o < PAGE_SIZE; o++) {
- byte = sdp->sd_unlinked_bitmap[c][o];
- if (byte != 0xFF)
- goto found;
- }
-
- goto fail;
-
-found:
- for (b = 0; b < 8; b++)
- if (!(byte & (1 << b)))
- break;
- (*ul)->ul_slot = c * (8 * PAGE_SIZE) + o * 8 + b;
-
- if ((*ul)->ul_slot >= sdp->sd_unlinked_slots)
- goto fail;
-
- sdp->sd_unlinked_bitmap[c][o] |= 1 << b;
-
- spin_unlock(&sdp->sd_unlinked_spin);
-
- return 0;
-
-fail:
- spin_unlock(&sdp->sd_unlinked_spin);
- kfree(*ul);
- return -ENOSPC;
-}
-
-void gfs2_unlinked_put(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
-{
- gfs2_assert_warn(sdp, test_and_clear_bit(ULF_LOCKED, &ul->ul_flags));
-
- spin_lock(&sdp->sd_unlinked_spin);
- gfs2_assert(sdp, ul->ul_count);
- ul->ul_count--;
- if (!ul->ul_count) {
- gfs2_icbit_munge(sdp, sdp->sd_unlinked_bitmap, ul->ul_slot, 0);
- spin_unlock(&sdp->sd_unlinked_spin);
- kfree(ul);
- } else
- spin_unlock(&sdp->sd_unlinked_spin);
-}
-
-int gfs2_unlinked_ondisk_add(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
-{
- int error;
-
- gfs2_assert_warn(sdp, test_bit(ULF_LOCKED, &ul->ul_flags));
- gfs2_assert_warn(sdp, list_empty(&ul->ul_list));
-
- error = munge_ondisk(sdp, ul->ul_slot, &ul->ul_ut);
- if (!error)
- ul_hash(sdp, ul);
-
- return error;
-}
-
-int gfs2_unlinked_ondisk_munge(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
-{
- int error;
-
- gfs2_assert_warn(sdp, test_bit(ULF_LOCKED, &ul->ul_flags));
- gfs2_assert_warn(sdp, !list_empty(&ul->ul_list));
-
- error = munge_ondisk(sdp, ul->ul_slot, &ul->ul_ut);
-
- return error;
-}
-
-int gfs2_unlinked_ondisk_rm(struct gfs2_sbd *sdp, struct gfs2_unlinked *ul)
-{
- struct gfs2_unlinked_tag ut;
- int error;
-
- gfs2_assert_warn(sdp, test_bit(ULF_LOCKED, &ul->ul_flags));
- gfs2_assert_warn(sdp, !list_empty(&ul->ul_list));
-
- memset(&ut, 0, sizeof(struct gfs2_unlinked_tag));
-
- error = munge_ondisk(sdp, ul->ul_slot, &ut);
- if (error)
- return error;
-
- ul_unhash(sdp, ul);
-
- return 0;
-}
-
-/**
- * gfs2_unlinked_dealloc - Go through the list of inodes to be deallocated
- * @sdp: the filesystem
- *
- * Returns: errno
- */
-
-int gfs2_unlinked_dealloc(struct gfs2_sbd *sdp)
-{
- unsigned int hits, strikes;
- int error;
-
- for (;;) {
- hits = 0;
- strikes = 0;
-
- for (;;) {
- struct gfs2_unlinked *ul = ul_fish(sdp);
- if (!ul)
- return 0;
- error = gfs2_inode_dealloc(sdp, ul);
- gfs2_unlinked_put(sdp, ul);
-
- if (!error) {
- hits++;
- if (strikes)
- strikes--;
- } else if (error == 1) {
- strikes++;
- if (strikes >=
- atomic_read(&sdp->sd_unlinked_count)) {
- error = 0;
- break;
- }
- } else
- return error;
- }
-
- if (!hits || kthread_should_stop())
- break;
-
- cond_resched();
- }
-
- return 0;
-}
-
-int gfs2_unlinked_init(struct gfs2_sbd *sdp)
-{
- struct gfs2_inode *ip = sdp->sd_ut_inode->u.generic_ip;
- unsigned int blocks = ip->i_di.di_size >> sdp->sd_sb.sb_bsize_shift;
- unsigned int x, slot = 0;
- unsigned int found = 0;
- uint64_t dblock;
- uint32_t extlen = 0;
- int error;
-
- if (!ip->i_di.di_size ||
- ip->i_di.di_size > (64 << 20) ||
- ip->i_di.di_size & (sdp->sd_sb.sb_bsize - 1)) {
- gfs2_consist_inode(ip);
- return -EIO;
- }
- sdp->sd_unlinked_slots = blocks * sdp->sd_ut_per_block;
- sdp->sd_unlinked_chunks = DIV_ROUND_UP(sdp->sd_unlinked_slots,
- 8 * PAGE_SIZE);
-
- error = -ENOMEM;
-
- sdp->sd_unlinked_bitmap = kcalloc(sdp->sd_unlinked_chunks,
- sizeof(unsigned char *),
- GFP_KERNEL);
- if (!sdp->sd_unlinked_bitmap)
- return error;
-
- for (x = 0; x < sdp->sd_unlinked_chunks; x++) {
- sdp->sd_unlinked_bitmap[x] = kzalloc(PAGE_SIZE, GFP_KERNEL);
- if (!sdp->sd_unlinked_bitmap[x])
- goto fail;
- }
-
- for (x = 0; x < blocks; x++) {
- struct buffer_head *bh;
- unsigned int y;
-
- if (!extlen) {
- int new = 0;
- error = gfs2_extent_map(ip->i_vnode, x, &new, &dblock, &extlen);
- if (error)
- goto fail;
- }
- gfs2_meta_ra(ip->i_gl, dblock, extlen);
- error = gfs2_meta_read(ip->i_gl, dblock, DIO_START | DIO_WAIT,
- &bh);
- if (error)
- goto fail;
- error = -EIO;
- if (gfs2_metatype_check(sdp, bh, GFS2_METATYPE_UT)) {
- brelse(bh);
- goto fail;
- }
-
- for (y = 0;
- y < sdp->sd_ut_per_block && slot < sdp->sd_unlinked_slots;
- y++, slot++) {
- struct gfs2_unlinked_tag ut;
- struct gfs2_unlinked *ul;
-
- gfs2_unlinked_tag_in(&ut, bh->b_data +
- sizeof(struct gfs2_meta_header) +
- y * sizeof(struct gfs2_unlinked_tag));
- if (!ut.ut_inum.no_addr)
- continue;
-
- error = -ENOMEM;
- ul = ul_alloc(sdp);
- if (!ul) {
- brelse(bh);
- goto fail;
- }
- ul->ul_ut = ut;
- ul->ul_slot = slot;
-
- spin_lock(&sdp->sd_unlinked_spin);
- gfs2_icbit_munge(sdp, sdp->sd_unlinked_bitmap, slot, 1);
- spin_unlock(&sdp->sd_unlinked_spin);
- ul_hash(sdp, ul);
-
- gfs2_unlinked_put(sdp, ul);
- found++;
- }
-
- brelse(bh);
- dblock++;
- extlen--;
- }
-
- if (found)
- fs_info(sdp, "found %u unlinked inodes\n", found);
-
- return 0;
-
-fail:
- gfs2_unlinked_cleanup(sdp);
- return error;
-}
-
-/**
- * gfs2_unlinked_cleanup - get rid of any extra struct gfs2_unlinked structures
- * @sdp: the filesystem
- *
- */
-
-void gfs2_unlinked_cleanup(struct gfs2_sbd *sdp)
-{
- struct list_head *head = &sdp->sd_unlinked_list;
- struct gfs2_unlinked *ul;
- unsigned int x;
-
- spin_lock(&sdp->sd_unlinked_spin);
- while (!list_empty(head)) {
- ul = list_entry(head->next, struct gfs2_unlinked, ul_list);
-
- if (ul->ul_count > 1) {
- list_move_tail(&ul->ul_list, head);
- spin_unlock(&sdp->sd_unlinked_spin);
- schedule();
- spin_lock(&sdp->sd_unlinked_spin);
- continue;
- }
-
- list_del_init(&ul->ul_list);
- atomic_dec(&sdp->sd_unlinked_count);
-
- gfs2_assert_warn(sdp, ul->ul_count == 1);
- gfs2_assert_warn(sdp, !test_bit(ULF_LOCKED, &ul->ul_flags));
- kfree(ul);
- }
- spin_unlock(&sdp->sd_unlinked_spin);
-
- gfs2_assert_warn(sdp, !atomic_read(&sdp->sd_unlinked_count));
-
- if (sdp->sd_unlinked_bitmap) {
- for (x = 0; x < sdp->sd_unlinked_chunks; x++)
- kfree(sdp->sd_unlinked_bitmap[x]);
- kfree(sdp->sd_unlinked_bitmap);
- }
-}
-
OpenPOWER on IntegriCloud