[Ocfs2-commits] mfasheh commits r2111 - trunk/fs/ocfs2/cluster
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Mon Apr 4 19:42:54 CDT 2005
Author: mfasheh
Signed-off-by: zab
Date: 2005-04-04 19:42:52 -0500 (Mon, 04 Apr 2005)
New Revision: 2111
Modified:
trunk/fs/ocfs2/cluster/heartbeat.c
Log:
* use bio's for heartbeat. this divorces heartbeat block size from ocfs2
block size and in the process fixes two problems:
- obviously, now hb can use a different block size from the fs, it defaults
Other sizes have had minimal testing so be warned.
- we no longer have to worry about set_blocksize messing up our buffer
heads as we don't use them anymore. ocfs2 blocksize detection was
freaking heartbeat out on some systems.
* add some trivial checking to see if a node is sharing our heartbeat slot.
* calculate block size / bits input in a common function
* add a check in hb_region_dev_read so we don't segfault on a read of an
unset region device.
Signed-off-by: zab
Modified: trunk/fs/ocfs2/cluster/heartbeat.c
===================================================================
--- trunk/fs/ocfs2/cluster/heartbeat.c 2005-04-04 22:30:11 UTC (rev 2110)
+++ trunk/fs/ocfs2/cluster/heartbeat.c 2005-04-05 00:42:52 UTC (rev 2111)
@@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
+#include <linux/bio.h>
#include <linux/mount.h>
#include <linux/vfs.h>
#include <linux/types.h>
@@ -97,15 +98,18 @@
#define hbprintk(x, arg...)
#define hbprintk0(x)
#else
-#define hbprintk(x, arg...) printk("(hb:%d) " x, current->pid, ##arg)
-#define hbprintk0(x) printk("(hb:%d) " x, current->pid)
+#define hbprintk(x, arg...) printk("(hb:(%d) %s:%d) " x, current->pid, \
+ __FUNCTION__, __LINE__, ##arg)
+#define hbprintk0(x) printk("(hb:(%d) %s:%d) " x, __FUNCTION__, \
+ __LINE__current->pid)
#endif
#define HB_THREAD_MS 2000 // every 2 seconds
+#define HB_DEFAULT_BLOCK_BITS 9
+
struct hb_disk_slot {
- struct buffer_head *ds_bh;
- u64 ds_block;
+ hb_disk_heartbeat_block *ds_raw_block;
u8 ds_node_num;
unsigned long ds_last_time;
u16 ds_equal_samples;
@@ -121,11 +125,20 @@
/* protected by the hr_callback_sem */
struct list_head hr_active_item;
struct task_struct *hr_task;
- u64 hr_block_bytes;
- u64 hr_block_bits;
- u64 hr_start_block;
- u8 hr_blocks;
+ unsigned int hr_fs_block_bytes;
+ unsigned int hr_fs_block_bits;
+ unsigned long long hr_fs_start_block;
+ unsigned int hr_fs_blocks;
+ /* will probably need: hr_start_block, hr_blocks */
+ unsigned int hr_blocks;
+ unsigned long long hr_start_block;
+ unsigned int hr_hb_block_bits;
+ unsigned int hr_hb_block_bytes;
+ unsigned int hr_hb_slots_per_page;
+
+ unsigned int hr_num_pages;
+ struct page **hr_slot_data;
struct block_device *hr_bdev;
struct hb_disk_slot *hr_slots;
/* a single hb-thread writer and many fill_node readers are protected */
@@ -138,17 +151,6 @@
atomic_t hr_steady_iterations;
};
-static void hb_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
-{
- if (uptodate)
- set_buffer_uptodate(bh);
- else {
- hbprintk("eek! EIO!\n");
- clear_buffer_uptodate(bh);
- }
- unlock_buffer(bh);
-}
-
static int hb_do_node_down(struct nm_node *node, int idx)
{
hbprintk("hb_do_node_down: node=%u\n", node->nd_num);
@@ -163,83 +165,179 @@
return 0;
}
-static inline void hb_submit_bh(int rw, struct buffer_head *bh)
+struct hb_bio_wait_ctxt {
+ struct completion wc_io_complete;
+};
+
+static int hb_bio_end_io(struct bio *bio,
+ unsigned int bytes_done,
+ int error)
{
-#if 0
- unsigned long long blocknr = bh->b_blocknr;
+ struct hb_bio_wait_ctxt *wc = bio->bi_private;
- hbprintk("submit_bh: rw=%s, blocknr=%llu, mapped=%s\n",
- rw==WRITE?"write":"read", blocknr,
- buffer_mapped(bh) ? "yes" : "no");
-#endif
- submit_bh(rw, bh);
- blk_run_address_space(bh->b_bdev->bd_inode->i_mapping);
+ if (error)
+ printk("ocfs2_heartbeat: IO Error %d\n", error);
+
+ if (bio->bi_size)
+ return 1;
+
+ complete(&wc->wc_io_complete);
+ return 0;
}
-/*
- * hr_region's block_bytes attribute defines the block size that we'll use to
- * calculate block offsets. The blocksize of the device might change under us,
- * though. this detects when that happens and tries to lookup the bh again
- * with the newer blocksize. The exciting wrinkle here is that its fatal to
- * call __getblk() with the wrong block size in some 2.6 kernels.
- *
- * We only ever use a few bytes of the block so it is ok that we return a
- * smaller bh than what is implied by blocksize_bits. We're just fixing up
- * addressing here.
- */
-static struct buffer_head *hb_getblk(struct block_device *bdev, int orig_blkno,
- int bits)
+static int hb_setup_read_bio(struct hb_region *reg,
+ struct bio **read_bio,
+ struct hb_bio_wait_ctxt *bio_wait)
{
- /* XXX getblk() takes an int block in 2.4 :/ */
- int blkno;
- int dev_bits;
- struct buffer_head *bh = NULL;
+ int status, i, num_pages, len;
+ unsigned int vec_len;
+ unsigned int bits = reg->hr_hb_block_bits;
+ unsigned int spp = reg->hr_hb_slots_per_page;
+ struct bio *bio = NULL;
+ struct page *page;
- blkno = orig_blkno;
+ num_pages = reg->hr_num_pages;
- dev_bits = bdev->bd_inode->i_blkbits;
- if (dev_bits < 0)
- goto out;
+ bio = bio_alloc(GFP_KERNEL, num_pages);
+ if (!bio) {
+ hbprintk("Could not alloc slots BIO!\n");
+ status = -ENOMEM;
+ goto bail;
+ }
- if (dev_bits < bits)
- blkno <<= bits - dev_bits;
- else if (dev_bits > bits)
- blkno >>= dev_bits - bits;
+ /* Must put everything in 512 byte sectors for the bio... */
+ bio->bi_sector = reg->hr_start_block >> (bits - 9);
+ bio->bi_bdev = reg->hr_bdev;
+ bio->bi_private = bio_wait;
+ bio->bi_end_io = hb_bio_end_io;
- bh = __getblk(bdev, blkno, 1 << dev_bits);
-out:
- return bh;
+ vec_len = PAGE_CACHE_SIZE;
+ for(i = 0; i < num_pages; i++) {
+ page = reg->hr_slot_data[i];
+
+ /* last page might be short */
+ if (i == (num_pages - 1))
+ vec_len = (reg->hr_blocks % spp) << bits;
+
+ len = bio_add_page(bio, page, vec_len, 0);
+ if (len != vec_len) {
+ bio_put(bio);
+
+ hbprintk("Error adding page to bio i = %d, vec_len = "
+ "%u, len = %d\n", i, vec_len, len);
+ status = -EIO;
+ goto bail;
+ }
+ }
+
+ *read_bio = bio;
+ status = 0;
+bail:
+ return status;
}
-static struct buffer_head *hb_get_locked_mapped(struct hb_region *reg,
- struct hb_disk_slot *slot)
+static int hb_setup_write_bio(struct hb_region *reg,
+ struct bio **write_bio,
+ struct hb_bio_wait_ctxt *bio_wait)
{
- struct buffer_head *bh = NULL;
+ int i, len, status;
+ unsigned int bits = reg->hr_hb_block_bits;
+ u64 write_block;
+ unsigned int start;
+ struct bio *bio = NULL;
+ struct page *page;
- bh = slot->ds_bh;
- if (bh) {
- lock_buffer(bh);
- if (buffer_mapped(bh))
- goto out;
- slot->ds_bh = NULL;
- unlock_buffer(bh);
- brelse(bh);
+ bio = bio_alloc(GFP_KERNEL, 1);
+ if (!bio) {
+ hbprintk("Could not alloc node BIO!\n");
+ status = -ENOMEM;
+ goto bail;
}
- slot->ds_bh = hb_getblk(reg->hr_bdev, slot->ds_block,
- reg->hr_block_bits);
- if (slot->ds_bh) {
- bh = slot->ds_bh;
- lock_buffer(bh);
+ /* find the page, and then the offset within */
+ i = nm_this_node() / reg->hr_hb_slots_per_page;
+ page = reg->hr_slot_data[i];
+ start = (nm_this_node() % reg->hr_hb_slots_per_page) << bits;
+
+ write_block = reg->hr_start_block + nm_this_node();
+ bio->bi_sector = write_block >> (bits - 9);
+ bio->bi_bdev = reg->hr_bdev;
+ bio->bi_private = bio_wait;
+ bio->bi_end_io = hb_bio_end_io;
+
+ len = bio_add_page(bio, page, reg->hr_hb_block_bytes, start);
+ if (len != reg->hr_hb_block_bytes) {
+ bio_put(bio);
+
+ hbprintk("Error adding my node bio len = %d\n", len);
+ status = -EIO;
+ goto bail;
}
-out:
- return bh;
+
+ *write_bio = bio;
+ status = 0;
+bail:
+
+ return status;
}
+/* We want to make sure that nobody is heartbeating on top of us --
+ * this will help detect an invalid configuration. */
+static int hb_check_last_timestamp(struct hb_region *reg)
+{
+ int node_num, ret;
+ struct hb_disk_slot *slot;
+ hb_disk_heartbeat_block *hb_block;
+
+ node_num = nm_this_node();
+
+ ret = 1;
+ slot = ®->hr_slots[node_num];
+ /* Don't check on our 1st timestamp */
+ if (slot->ds_last_time) {
+ hb_block = slot->ds_raw_block;
+
+ if (le64_to_cpu(hb_block->time) != slot->ds_last_time)
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static inline void hb_set_local_node_timestamp(struct hb_region *reg)
+{
+ int node_num;
+ u64 cputime;
+ struct hb_disk_slot *slot;
+ hb_disk_heartbeat_block *hb_block;
+
+ node_num = nm_this_node();
+ slot = ®->hr_slots[node_num];
+
+ hb_block = (hb_disk_heartbeat_block *) slot->ds_raw_block;
+ memset(hb_block, 0, reg->hr_hb_block_bytes);
+ /* TODO: time stuff */
+ cputime = OCFS_CURRENT_SECONDS;
+ if (!cputime)
+ cputime = 1;
+ hb_block->time = cpu_to_le64(cputime);
+}
+
+static void hb_wait_on_io(struct hb_region *reg,
+ struct hb_bio_wait_ctxt *wc)
+{
+ struct address_space *mapping = reg->hr_bdev->bd_inode->i_mapping;
+
+ blk_run_address_space(mapping);
+
+ wait_for_completion(&wc->wc_io_complete);
+}
+
static void hb_do_disk_heartbeat(struct hb_region *reg)
{
+ u64 cputime;
+ int i, ret, wrote = 0;
struct nm_node *node;
- struct buffer_head *bh;
struct hb_disk_slot *slot;
struct list_head *pos, *tmp;
hb_disk_heartbeat_block *hb_block;
@@ -248,60 +346,55 @@
* lists and the slot items */
LIST_HEAD(newborn);
LIST_HEAD(deceased);
- u64 cputime;
- int i, rw;
unsigned long configured_nodes[BITS_TO_LONGS(NM_MAX_NODES)];
+ struct bio *read_bio = NULL;
+ struct bio *write_bio = NULL;
+ struct hb_bio_wait_ctxt read_wc;
+ struct hb_bio_wait_ctxt write_wc;
if (nm_configured_node_map(configured_nodes, sizeof(configured_nodes)))
return;
- /* first we clear uptodate on other nodes slots and write our slot */
- i = -1;
- while((i = find_next_bit(configured_nodes, NM_MAX_NODES, i + 1)) < NM_MAX_NODES) {
- slot = ®->hr_slots[i];
+ init_completion(&read_wc.wc_io_complete);
+ ret = hb_setup_read_bio(reg, &read_bio, &read_wc);
+ if (ret < 0) {
+ hbprintk("ret = %d setting up read io\n", ret);
+ goto bail;
+ }
- bh = hb_get_locked_mapped(reg, slot);
- if (bh == NULL) {
- hbprintk("getblk failed in slot %d!\n", i);
- continue;
- }
+ init_completion(&write_wc.wc_io_complete);
+ ret = hb_setup_write_bio(reg, &write_bio, &write_wc);
+ if (ret < 0) {
+ hbprintk("ret = %d setting up read io\n", ret);
+ goto bail;
+ }
- if (slot->ds_node_num == nm_this_node()) {
- memset(bh->b_data, 0, bh->b_size);
- hb_block = (hb_disk_heartbeat_block *)bh->b_data;
- BUG_ON(bh->b_size < sizeof(*hb_block));
+ /* We 1st do a sync read of all slots */
+ bio_get(read_bio);
+ submit_bio(READ, read_bio);
+ hb_wait_on_io(reg, &read_wc);
- /* TODO: time stuff */
- cputime = OCFS_CURRENT_SECONDS;
- if (!cputime)
- cputime = 1;
- hb_block->time = cpu_to_le64(cputime);
+ /* With an up to date view of the slots, we can check that no
+ * other node has been improperly configured to heartbeat in
+ * our slot. */
+ if (!hb_check_last_timestamp(reg))
+ printk(KERN_CRIT "ocfs2_heartbeat: Another node is "
+ "heartbeating in our slot!\n");
- set_buffer_uptodate(bh);
- clear_buffer_dirty(bh);
- rw = WRITE;
- } else {
- clear_buffer_uptodate(bh);
- rw = READ;
- }
+ /* Set our raw timestamp */
+ hb_set_local_node_timestamp(reg);
- bh->b_end_io = hb_end_buffer_io_sync;
- hb_submit_bh(rw, bh);
- }
+ /* And fire off the write. Note that we don't wait on this I/O
+ * until later. */
+ bio_get(write_bio);
+ submit_bio(WRITE, write_bio);
+ wrote = 1;
- /* now we read again and see what other nodes have done */
i = -1;
while((i = find_next_bit(configured_nodes, NM_MAX_NODES, i + 1)) < NM_MAX_NODES) {
slot = ®->hr_slots[i];
+ hb_block = slot->ds_raw_block;
- bh = slot->ds_bh;
- if (bh == NULL) {
- hbprintk("no bh in slot %d!\n", i);
- continue;
- }
- wait_on_buffer(bh);
- hb_block = (hb_disk_heartbeat_block *)bh->b_data;
-
/* we don't care if these wrap.. the state transitions below
* clear at the right places */
cputime = le64_to_cpu(hb_block->time);
@@ -318,7 +411,7 @@
list_add_tail(&slot->ds_live_item, &newborn);
slot->ds_equal_samples = 0;
continue;
- }
+ }
/* live nodes only go dead after enough consequtive missed
* samples.. reset the missed counter whenever we see
@@ -377,6 +470,15 @@
hb_do_node_down(node, slot->ds_node_num);
nm_node_put(node);
}
+
+bail:
+ if (wrote) /* Make sure the write hits disk before we return. */
+ hb_wait_on_io(reg, &write_wc);
+
+ if (read_bio)
+ bio_put(read_bio);
+ if (write_bio)
+ bio_put(write_bio);
}
/*
@@ -389,7 +491,7 @@
struct hb_region *reg = data;
hbprintk("hb thread running\n");
-
+
while (!kthread_should_stop()) {
hb_do_disk_heartbeat(reg);
set_current_state(TASK_UNINTERRUPTIBLE);
@@ -453,56 +555,112 @@
* attributes might have built up. */
static void hb_region_release(struct config_item *item)
{
+ int i;
+ struct page *page;
struct hb_region *reg = to_hb_region(item);
- struct hb_disk_slot *slot;
- int i;
-
- /* with the thread down these bhs should be update/idle */
- for(i = 0; reg->hr_slots && i < reg->hr_blocks; i++) {
- slot = ®->hr_slots[i];
- if (slot->ds_bh)
- brelse(slot->ds_bh);
+ if (reg->hr_slot_data) {
+ for (i = 0; i < reg->hr_num_pages; i++) {
+ page = reg->hr_slot_data[i];
+ if (page)
+ __free_page(page);
+ }
+ kfree(reg->hr_slot_data);
}
if (reg->hr_bdev)
blkdev_put(reg->hr_bdev);
- kfree(reg->hr_slots); /* might be null if never activated */
+ if (reg->hr_slots)
+ kfree(reg->hr_slots);
kfree(reg);
}
-static ssize_t hb_region_block_bytes_read(struct hb_region *reg, char *page)
+static void hb_init_region_params(struct hb_region *reg,
+ unsigned int block_bits)
{
- return sprintf(page, "%lld\n", (long long)reg->hr_block_bytes);
+ reg->hr_hb_block_bits = block_bits;
+ reg->hr_hb_block_bytes = 1 << block_bits;
+ reg->hr_hb_slots_per_page = PAGE_CACHE_SIZE >> block_bits;
}
-static ssize_t hb_region_block_bytes_write(struct hb_region *reg,
- const char *page,
- size_t count)
+static int hb_read_block_input(struct hb_region *reg,
+ const char *page,
+ size_t count,
+ unsigned long *ret_bytes,
+ unsigned int *ret_bits)
{
- unsigned long long tmp;
+ unsigned long bytes;
char *p = (char *)page;
- tmp = simple_strtoull(p, &p, 0);
+ bytes = simple_strtoul(p, &p, 0);
if (!p || (*p && (*p != '\n')))
return -EINVAL;
- /* XXX probably very stupid. */
- if (tmp >= 65536) /* just so we can use hweight16 */
+ /* Heartbeat and fs min / max block sizes are the same. */
+ if (bytes > 4096 || bytes < 512)
return -ERANGE;
- if (hweight16(tmp) != 1)
+ if (hweight16(bytes) != 1)
return -EINVAL;
+ if (ret_bytes)
+ *ret_bytes = bytes;
+ if (ret_bits)
+ *ret_bits = ffs(bytes) - 1;
+
+ return 0;
+}
+
+static ssize_t hb_region_slot_bytes_read(struct hb_region *reg, char *page)
+{
+ return sprintf(page, "%u\n", reg->hr_hb_block_bytes);
+}
+
+static ssize_t hb_region_slot_bytes_write(struct hb_region *reg,
+ const char *page,
+ size_t count)
+{
+ int status;
+ unsigned int slot_bits;
+
+ status = hb_read_block_input(reg, page, count, NULL, &slot_bits);
+ if (status)
+ return status;
+
+ hb_init_region_params(reg, slot_bits);
+
+ hbprintk("Heartbeat region using %u sized slots\n", 1 << slot_bits);
+
+ return count;
+}
+
+static ssize_t hb_region_block_bytes_read(struct hb_region *reg, char *page)
+{
+ return sprintf(page, "%u\n", reg->hr_fs_block_bytes);
+}
+
+static ssize_t hb_region_block_bytes_write(struct hb_region *reg,
+ const char *page,
+ size_t count)
+{
+ int status;
+ unsigned long fs_bytes;
+ unsigned int fs_bits;
+
+ status = hb_read_block_input(reg, page, count, &fs_bytes, &fs_bits);
+ if (status)
+ return status;
+
/* XXX compare blocks against dev later on commit? */
- reg->hr_block_bytes = tmp;
- reg->hr_block_bits = ffs(reg->hr_block_bytes) - 1;
+ reg->hr_fs_block_bytes = (unsigned int) fs_bytes;
+ reg->hr_fs_block_bits = fs_bits;
return count;
}
+
static ssize_t hb_region_start_block_read(struct hb_region *reg, char *page)
{
- return sprintf(page, "%lld\n", (long long)reg->hr_start_block);
+ return sprintf(page, "%llu\n", reg->hr_fs_start_block);
}
static ssize_t hb_region_start_block_write(struct hb_region *reg,
@@ -517,44 +675,130 @@
return -EINVAL;
/* XXX compare blocks against dev later on commit? */
- reg->hr_start_block = tmp;
+ reg->hr_fs_start_block = tmp;
return count;
}
static ssize_t hb_region_blocks_read(struct hb_region *reg, char *page)
{
- return sprintf(page, "%d\n", reg->hr_blocks);
+ return sprintf(page, "%d\n", reg->hr_fs_blocks);
}
static ssize_t hb_region_blocks_write(struct hb_region *reg,
const char *page,
size_t count)
{
- unsigned long long tmp;
+ unsigned long tmp;
char *p = (char *)page;
- tmp = simple_strtoull(p, &p, 0);
+ tmp = simple_strtoul(p, &p, 0);
if (!p || (*p && (*p != '\n')))
return -EINVAL;
if (tmp >= NM_MAX_NODES)
return -ERANGE;
- reg->hr_slots = kcalloc(tmp, sizeof(struct hb_disk_slot), GFP_KERNEL);
- if (reg->hr_slots == NULL)
- return -ENOMEM;
+ reg->hr_fs_blocks = (unsigned int) tmp;
- reg->hr_blocks = tmp;
-
return count;
}
static ssize_t hb_region_dev_read(struct hb_region *reg, char *page)
{
- const char *str = bdevname(reg->hr_bdev, page);
- return sprintf(page, "%s\n", str);
+ unsigned int ret = 0;
+ const char *str;
+
+ if (reg->hr_bdev) {
+ str = bdevname(reg->hr_bdev, page);
+ ret = sprintf(page, "%s\n", str);
+ }
+ return ret;
}
+/* expects all hr_fs_ members to be filled, as well as hr->hr_bdev */
+static void hb_calculate_region_offsets(struct hb_region *reg)
+{
+ unsigned long long tmp_bytes;
+
+ /* for the # of hearbeat blocks, don't use more than the
+ * number of fs blocks allocated to the file system. We
+ * already know that hb block size can't be bigger than fs
+ * block size... */
+ reg->hr_blocks = reg->hr_fs_blocks;
+
+ tmp_bytes = reg->hr_fs_start_block << reg->hr_fs_block_bits;
+ reg->hr_start_block = tmp_bytes >> reg->hr_hb_block_bits;
+
+ hbprintk("fs_block_bytes = %u, fs_block_bits = %u\n",
+ reg->hr_fs_block_bytes, reg->hr_fs_block_bits);
+ hbprintk("fs_start_block = %llu\n", reg->hr_fs_start_block);
+ hbprintk("hr_start_block = %llu, hr_blocks = %u\n",
+ reg->hr_start_block, reg->hr_blocks);
+ hbprintk("hb block bytes = %u, hb block bits = %u\n",
+ reg->hr_hb_block_bytes, reg->hr_hb_block_bits);
+}
+
+static int hb_map_slot_data(struct hb_region *reg)
+{
+ int i, j;
+ unsigned int last_slot;
+ unsigned int spp = reg->hr_hb_slots_per_page;
+ struct page *page;
+ char *raw;
+ struct hb_disk_slot *slot;
+
+ reg->hr_slots = kcalloc(reg->hr_blocks,
+ sizeof(struct hb_disk_slot), GFP_KERNEL);
+ if (reg->hr_slots == NULL) {
+ hbprintk("%d\n", -ENOMEM);
+ return -ENOMEM;
+ }
+
+ for(i = 0; i < reg->hr_blocks; i++) {
+ slot = ®->hr_slots[i];
+ slot->ds_node_num = i;
+ INIT_LIST_HEAD(&slot->ds_live_item);
+ slot->ds_raw_block = NULL;
+ }
+
+ reg->hr_num_pages = (reg->hr_blocks + spp - 1) / spp;
+ hbprintk("Going to require %u pages to cover %u blocks at %u "
+ "blocks per page\n", reg->hr_num_pages, reg->hr_blocks,
+ spp);
+
+ reg->hr_slot_data = kcalloc(reg->hr_num_pages, sizeof(struct page *),
+ GFP_KERNEL);
+ if (!reg->hr_slot_data) {
+ hbprintk("%d\n", -ENOMEM);
+ return -ENOMEM;
+ }
+
+ for(i = 0; i < reg->hr_num_pages; i++) {
+ page = alloc_page(GFP_KERNEL);
+ if (!page) {
+ hbprintk("%d\n", -ENOMEM);
+ return -ENOMEM;
+ }
+
+ reg->hr_slot_data[i] = page;
+
+ last_slot = i * spp;
+ raw = page_address(page);
+ for (j = 0;
+ (j < spp) && ((j + last_slot) < reg->hr_blocks);
+ j++) {
+ BUG_ON((j + last_slot) >= reg->hr_blocks);
+
+ slot = ®->hr_slots[j + last_slot];
+ slot->ds_raw_block = (hb_disk_heartbeat_block *) raw;
+
+ raw += reg->hr_hb_block_bytes;
+ }
+ }
+
+ return 0;
+}
+
/* this is acting as commit; we set up all of hr_bdev and hr_task or nothing */
static ssize_t hb_region_dev_write(struct hb_region *reg, const char *page,
size_t count)
@@ -564,8 +808,6 @@
struct file *filp = NULL;
struct inode *inode = NULL;
ssize_t ret = -EINVAL;
- struct hb_disk_slot *slot;
- int i;
fd = simple_strtol(p, &p, 0);
if (!p || (*p && (*p != '\n')))
@@ -578,9 +820,12 @@
if (filp == NULL)
goto out;
- if (reg->hr_blocks == 0 || reg->hr_slots == NULL)
+ if (reg->hr_fs_blocks == 0 || reg->hr_fs_start_block == 0)
goto out;
+ if (reg->hr_hb_block_bits > reg->hr_fs_block_bits)
+ goto out;
+
inode = igrab(filp->f_mapping->host);
if (inode == NULL)
goto out;
@@ -593,11 +838,12 @@
}
inode = NULL;
- for(i = 0; i < reg->hr_blocks; i++) {
- slot = ®->hr_slots[i];
- slot->ds_block = reg->hr_start_block + i;
- slot->ds_node_num = i;
- INIT_LIST_HEAD(&slot->ds_live_item);
+ hb_calculate_region_offsets(reg);
+
+ ret = hb_map_slot_data(reg);
+ if (ret) {
+ hbprintk("Error %ld initializing slot data\n", (long) ret);
+ goto out;
}
atomic_set(®->hr_steady_iterations, 2);
@@ -637,6 +883,11 @@
ssize_t (*store)(struct hb_region *, const char *, size_t);
};
+static struct hb_region_attribute hb_region_attr_slot_size = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "slot_bytes", .ca_mode = S_IRUGO | S_IWUSR },
+ .show = hb_region_slot_bytes_read,
+ .store = hb_region_slot_bytes_write,
+};
static struct hb_region_attribute hb_region_attr_block_bytes = {
.attr = { .ca_owner = THIS_MODULE, .ca_name = "block_bytes", .ca_mode = S_IRUGO | S_IWUSR },
.show = hb_region_block_bytes_read,
@@ -659,6 +910,7 @@
};
static struct configfs_attribute *hb_region_attrs[] = {
+ &hb_region_attr_slot_size.attr,
&hb_region_attr_block_bytes.attr,
&hb_region_attr_start_block.attr,
&hb_region_attr_blocks.attr,
@@ -733,6 +985,7 @@
INIT_LIST_HEAD(®->hr_active_item);
rwlock_init(®->hr_slot_list_lock);
INIT_LIST_HEAD(®->hr_live_list);
+ hb_init_region_params(reg, HB_DEFAULT_BLOCK_BITS);
config_item_init_type_name(®->hr_item, name, &hb_region_type);
More information about the Ocfs2-commits
mailing list