From d65f42dab501fc4f8813ddf1d6c9af68deab7a77 Mon Sep 17 00:00:00 2001 From: Theodore DeRego Date: Mon, 14 Dec 2015 11:46:34 -1000 Subject: [PATCH] zfs --- filesystem/apps/zfs/block_ptr.rs | 91 -------------------------------- filesystem/apps/zfs/main.rs | 7 ++- filesystem/apps/zfs/metaslab.rs | 69 +++++++++++++++++++++--- filesystem/apps/zfs/spa.rs | 13 +++-- filesystem/apps/zfs/taskq.rs | 6 ++- filesystem/apps/zfs/vdev.rs | 49 ++++++++--------- filesystem/apps/zfs/zio.rs | 5 +- 7 files changed, 109 insertions(+), 131 deletions(-) diff --git a/filesystem/apps/zfs/block_ptr.rs b/filesystem/apps/zfs/block_ptr.rs index 63646c8d5..6e776286c 100644 --- a/filesystem/apps/zfs/block_ptr.rs +++ b/filesystem/apps/zfs/block_ptr.rs @@ -36,97 +36,6 @@ impl BlockPtr { pub fn psize(&self) -> u64 { ((self.flags_size >> 16) & 0xFFFF) + 1 } - -#define BP_GET_LSIZE(bp) \ - (BP_IS_EMBEDDED(bp) ? \ - (BPE_GET_ETYPE(bp) == BP_EMBEDDED_TYPE_DATA ? BPE_GET_LSIZE(bp) : 0): \ - BF64_GET_SB((bp)->blk_prop, 0, SPA_LSIZEBITS, SPA_MINBLOCKSHIFT, 1)) -#define BP_SET_LSIZE(bp, x) do { \ - ASSERT(!BP_IS_EMBEDDED(bp)); \ - BF64_SET_SB((bp)->blk_prop, \ - 0, SPA_LSIZEBITS, SPA_MINBLOCKSHIFT, 1, x); \ -_NOTE(CONSTCOND) } while (0) - -#define BP_GET_PSIZE(bp) \ - (BP_IS_EMBEDDED(bp) ? 0 : \ - BF64_GET_SB((bp)->blk_prop, 16, SPA_PSIZEBITS, SPA_MINBLOCKSHIFT, 1)) -#define BP_SET_PSIZE(bp, x) do { \ - ASSERT(!BP_IS_EMBEDDED(bp)); \ - BF64_SET_SB((bp)->blk_prop, \ - 16, SPA_PSIZEBITS, SPA_MINBLOCKSHIFT, 1, x); \ -_NOTE(CONSTCOND) } while (0) - -#define BP_GET_COMPRESS(bp) BF64_GET((bp)->blk_prop, 32, 7) -#define BP_SET_COMPRESS(bp, x) BF64_SET((bp)->blk_prop, 32, 7, x) - -#define BP_IS_EMBEDDED(bp) BF64_GET((bp)->blk_prop, 39, 1) -#define BP_SET_EMBEDDED(bp, x) BF64_SET((bp)->blk_prop, 39, 1, x) - -#define BP_GET_CHECKSUM(bp) \ - (BP_IS_EMBEDDED(bp) ? ZIO_CHECKSUM_OFF : \ - BF64_GET((bp)->blk_prop, 40, 8)) -#define BP_SET_CHECKSUM(bp, x) do { \ - ASSERT(!BP_IS_EMBEDDED(bp)); \ - BF64_SET((bp)->blk_prop, 40, 8, x); \ -_NOTE(CONSTCOND) } while (0) - -#define BP_GET_TYPE(bp) BF64_GET((bp)->blk_prop, 48, 8) -#define BP_SET_TYPE(bp, x) BF64_SET((bp)->blk_prop, 48, 8, x) - -#define BP_GET_LEVEL(bp) BF64_GET((bp)->blk_prop, 56, 5) -#define BP_SET_LEVEL(bp, x) BF64_SET((bp)->blk_prop, 56, 5, x) - -#define BP_GET_DEDUP(bp) BF64_GET((bp)->blk_prop, 62, 1) -#define BP_SET_DEDUP(bp, x) BF64_SET((bp)->blk_prop, 62, 1, x) - -#define BP_GET_BYTEORDER(bp) BF64_GET((bp)->blk_prop, 63, 1) -#define BP_SET_BYTEORDER(bp, x) BF64_SET((bp)->blk_prop, 63, 1, x) - -#define BP_PHYSICAL_BIRTH(bp) \ - (BP_IS_EMBEDDED(bp) ? 0 : \ - (bp)->blk_phys_birth ? (bp)->blk_phys_birth : (bp)->blk_birth) - -#define BP_SET_BIRTH(bp, logical, physical) \ -{ \ - ASSERT(!BP_IS_EMBEDDED(bp)); \ - (bp)->blk_birth = (logical); \ - (bp)->blk_phys_birth = ((logical) == (physical) ? 0 : (physical)); \ -} - -#define BP_GET_FILL(bp) (BP_IS_EMBEDDED(bp) ? 1 : (bp)->blk_fill) - -#define BP_GET_ASIZE(bp) \ - (BP_IS_EMBEDDED(bp) ? 0 : \ - DVA_GET_ASIZE(&(bp)->blk_dva[0]) + \ - DVA_GET_ASIZE(&(bp)->blk_dva[1]) + \ - DVA_GET_ASIZE(&(bp)->blk_dva[2])) - -#define BP_GET_UCSIZE(bp) \ - ((BP_GET_LEVEL(bp) > 0 || DMU_OT_IS_METADATA(BP_GET_TYPE(bp))) ? \ - BP_GET_PSIZE(bp) : BP_GET_LSIZE(bp)) - -#define BP_GET_NDVAS(bp) \ - (BP_IS_EMBEDDED(bp) ? 0 : \ - !!DVA_GET_ASIZE(&(bp)->blk_dva[0]) + \ - !!DVA_GET_ASIZE(&(bp)->blk_dva[1]) + \ - !!DVA_GET_ASIZE(&(bp)->blk_dva[2])) - -#define BP_COUNT_GANG(bp) \ - (BP_IS_EMBEDDED(bp) ? 0 : \ - (DVA_GET_GANG(&(bp)->blk_dva[0]) + \ - DVA_GET_GANG(&(bp)->blk_dva[1]) + \ - DVA_GET_GANG(&(bp)->blk_dva[2]))) - -#define DVA_EQUAL(dva1, dva2) \ - ((dva1)->dva_word[1] == (dva2)->dva_word[1] && \ - (dva1)->dva_word[0] == (dva2)->dva_word[0]) - -#define BP_EQUAL(bp1, bp2) \ - (BP_PHYSICAL_BIRTH(bp1) == BP_PHYSICAL_BIRTH(bp2) && \ - (bp1)->blk_birth == (bp2)->blk_birth && \ - DVA_EQUAL(&(bp1)->blk_dva[0], &(bp2)->blk_dva[0]) && \ - DVA_EQUAL(&(bp1)->blk_dva[1], &(bp2)->blk_dva[1]) && \ - DVA_EQUAL(&(bp1)->blk_dva[2], &(bp2)->blk_dva[2])) } impl FromBytes for BlockPtr { } diff --git a/filesystem/apps/zfs/main.rs b/filesystem/apps/zfs/main.rs index ab86020af..5a3f4ffa0 100644 --- a/filesystem/apps/zfs/main.rs +++ b/filesystem/apps/zfs/main.rs @@ -494,13 +494,12 @@ impl Zfs { space_map_phys); // println!("got space map: {:?}", &space_map.unwrap()[0..64]); - let mut range_tree: avl::Tree = + let mut range_tree: avl::Tree = avl::Tree::new(Box::new(|x| x.offset())); - space_map::load_space_map_avl(&space_map::SpaceMap { size: 30 }, + /*space_map::load_space_map_avl(&space_map::SpaceMap { size: 30 }, &mut range_tree, &space_map.unwrap(), - space_map::MapType::Alloc).unwrap(); + space_map::MapType::Alloc).unwrap();*/ } else { println!("Invalid metaslab_array NvValue \ type. Expected Uint64."); diff --git a/filesystem/apps/zfs/metaslab.rs b/filesystem/apps/zfs/metaslab.rs index 1f8cb3f64..2921f1927 100644 --- a/filesystem/apps/zfs/metaslab.rs +++ b/filesystem/apps/zfs/metaslab.rs @@ -1,3 +1,5 @@ +use std::cmp; + use super::avl; use super::space_map; use super::taskq::{self, Taskq}; @@ -53,7 +55,7 @@ struct MetaslabGroup { bias: i64, activation_count: i64, ms_class: MetaslabClass, - vdev: vdev::TreeIndex, + //vdev: vdev::TreeIndex, taskq: Taskq, //prev: *MetaslabGroup, //next: *MetaslabGroup, @@ -62,7 +64,7 @@ struct MetaslabGroup { } impl MetaslabGroup { - pub fn create(ms_class: metaslab_class_t, vdev: vdev::TreeIndex) -> Self { + pub fn create(ms_class: MetaslabClass) -> Self { let metaslab_key = Box::new(|ms| (ms.weight, ms.start)); let taskq = Taskq::new("metaslab_group_taskq".to_string(), metaslab_load_pct, maxclsyspri, 10, std::u64::MAX, TASKQ_THREADS_CPU_PCT | TASKQ_DYNAMIC); @@ -76,7 +78,7 @@ impl MetaslabGroup { bias: 0, activation_count: 0, ms_class: ms_class, - vdev: vdev, + //vdev: vdev, taskq: taskq, //prev: *MetaslabGroup, //next: *MetaslabGroup, @@ -90,6 +92,36 @@ impl MetaslabGroup { start: m.start, weight: m.weight }); } + + pub fn activate(&mut self) { + /*metaslab_class_t *mc = self.class; + metaslab_group_t *mgprev, *mgnext; + + //assert!(spa_config_held(ms_class.spa, SCL_ALLOC, RW_WRITER)); + + assert!(ms_class.rotor != mg); + assert!(self.prev == NULL); + assert!(self.next == NULL); + assert!(self.activation_count <= 0); + + if (++self.activation_count <= 0) + return; + + self.aliquot = metaslab_aliquot * cmp::max(1, self.vdev->vdev_children); + metaslab_group_alloc_update(mg); + + if (mgprev = ms_class.rotor) == NULL { + self.prev = mg; + self.next = mg; + } else { + mgnext = mgprev->mg_next; + self.prev = mgprev; + self.next = mgnext; + mgprev->mg_next = mg; + mgnext->mg_prev = mg; + } + ms_class.rotor = mg;*/ + } } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -309,6 +341,26 @@ impl Metaslab { //cv_wait(&msp->ms_load_cv, &msp->ms_lock); } } + + fn activate(&mut self, activation_weight: u64) -> zfs::Result<()> { + assert!(MUTEX_HELD(&self.lock)); + + if self.weight & METASLAB_ACTIVE_MASK == 0 { + self.load_wait(); + if !self.loaded { + if let Err(e) = self.load() { + metaslab_group_sort(self.group, msp, 0); + return e; + } + } + + metaslab_group_sort(self.group, self, self.weight | activation_weight); + } + assert!(self.loaded); + assert!(self.weight & METASLAB_ACTIVE_MASK); + + Ok(()) + } } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -321,7 +373,7 @@ struct MetaslabOps { //////////////////////////////////////////////////////////////////////////////////////////////////// // The first-fit block allocator -/*fn metaslab_ff_alloc(ms: &mut Metaslab, size: u64) -> u64 { +fn metaslab_ff_alloc(ms: &mut Metaslab, size: u64) -> u64 { // Find the largest power of 2 block size that evenly divides the // requested size. This is used to try to allocate blocks with similar // alignment from the same area of the metaslab (i.e. same cursor @@ -331,8 +383,13 @@ struct MetaslabOps { let ref mut cursor = ms.lbas[util::highbit64(align) - 1]; let ref mut tree = ms.tree; - return metaslab_block_picker(tree, cursor, size, align); -}*/ + //return metaslab_block_picker(tree, cursor, size, align); + return 0; +} + +static metaslab_ff_ops: MetaslabOps = MetaslabOps { alloc: metaslab_ff_alloc }; + +static zfs_metaslab_ops: MetaslabOps = metaslab_ff_ops; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/filesystem/apps/zfs/spa.rs b/filesystem/apps/zfs/spa.rs index 87b8751b6..fc01ca332 100644 --- a/filesystem/apps/zfs/spa.rs +++ b/filesystem/apps/zfs/spa.rs @@ -2,6 +2,7 @@ use std::{Box, String, ToString, Vec}; use std::cmp; use super::avl; +use super::dsl_pool; use super::nvpair::{NvList, NvValue}; use super::txg; use super::uberblock::Uberblock; @@ -21,6 +22,9 @@ pub struct Spa { state: zfs::PoolState, load_state: zfs::SpaLoadState, zio_taskq: [[SpaTaskqs; zio::NUM_TASKQ_TYPES]; zio::NUM_TYPES], + //dsl_pool: DslPool, + normal_class: MetaslabClass, // normal data class + log_class: MetaslabClass, // intent log data class first_txg: u64, vdev_tree: vdev::Tree, root_vdev: vdev::TreeIndex, @@ -67,12 +71,18 @@ impl Spa { let nvroot: &NvList = try!(config.get("vdev_tree").ok_or(zfs::Error::Invalid)); try!(vdev_tree.parse(nvroot, None, vdev_alloc_type)) }; + + let normal_class = MetaslabClass::create(self, metaslab::zfs_metaslab_ops); + let log_class = MetaslabClass::create(self, metaslab::zfs_metaslab_ops); Ok(Spa { name: name, config: config, state: zfs::PoolState::Uninitialized, load_state: zfs::SpaLoadState::None, + //dsl_pool: blah, + normal_class: normal_class, + log_class: log_class, first_txg: 0, vdev_tree: vdev_tree, root_vdev: root_vdev, @@ -163,9 +173,6 @@ impl Spa { self.state = zfs::PoolState::Active; - // self.normal_class = MetaslabClass::create(self, zfs_metaslab_ops); - // self.log_class = MetaslabClass::create(self, zfs_metaslab_ops); - // TODO: maybe start the spa thread self.create_zio_taskqs(); diff --git a/filesystem/apps/zfs/taskq.rs b/filesystem/apps/zfs/taskq.rs index cfcfa463b..b36a56004 100644 --- a/filesystem/apps/zfs/taskq.rs +++ b/filesystem/apps/zfs/taskq.rs @@ -3,6 +3,8 @@ use std::cmp; //use std::sync::mpsc::{channel, Sender, Receiver}; use std::thread; +use super::zfs; + const TQENT_FLAG_PREALLOC: u64 = 0x1; // taskq_dispatch_ent used const TASKQ_PREPOPULATE: u64 = 0x0001; @@ -203,9 +205,9 @@ impl Taskq { return 0; }*/ - pub fn empty_ent(&self) -> bool { + /*pub fn empty_ent(&self) -> bool { self.next == NULL - } + }*/ /*fn taskq_init_ent(taskq_ent_t *t) { t.next = NULL; diff --git a/filesystem/apps/zfs/vdev.rs b/filesystem/apps/zfs/vdev.rs index c98b1ad21..49bd9c1d7 100644 --- a/filesystem/apps/zfs/vdev.rs +++ b/filesystem/apps/zfs/vdev.rs @@ -3,6 +3,7 @@ use std::{Box, String, ToString, Vec, cmp, mem}; use super::from_bytes::FromBytes; use super::metaslab::{Metaslab, MetaslabGroup}; use super::nvpair::{NvList, NvValue}; +use super::uberblock; use super::util; use super::vdev_file::VdevFile; use super::zfs; @@ -106,16 +107,18 @@ pub struct Top { ms_group: MetaslabGroup, // metaslab group metaslabs: Vec, // in-memory metaslab array is_hole: bool, + removing: bool, // device is being removed? } impl Top { - pub fn new(ms_array: u64, ms_shift: u64) -> Self { + pub fn new(ms_array: u64, ms_shift: u64, ms_group: MetaslabGroup) -> Self { Top { ms_array: ms_array, ms_shift: ms_shift, - ms_group: MetaslabGroup, + ms_group: ms_group, metaslabs: vec![], - is_hole: false, /* TODO: zol checks vdev_ops for this, but idk what to do yet */ + is_hole: false, // TODO: zol checks vdev_ops for this, but idk what to do yet + removing: false, } } } @@ -221,26 +224,24 @@ impl Vdev { let mut vdev_top = None; - // If we're a top-level vdev, try to load the allocation parameters, create the vdev::Top, - // and create the metaslab group + // If we're a top-level vdev, try to load the allocation parameters, + // create the metaslab group, and create the vdev::Top if parent && !parent.parent { + let mut ms_array = 0; + let mut ms_shift = 0; if alloc_type == AllocType::Load || alloc_type == AllocType::Split { - let ms_array = try!(nv.get("metaslab_array").ok_or(zfs::Error::Invalid)); - let ms_shift = try!(nv.get("metaslab_shift").ok_or(zfs::Error::Invalid)); + ms_array = try!(nv.get("metaslab_array").ok_or(zfs::Error::Invalid)); + ms_shift = try!(nv.get("metaslab_shift").ok_or(zfs::Error::Invalid)); let asize = try!(nv.get("asize").ok_or(zfs::Error::Invalid)); //let removing = try!(nv.get("removing").ok_or(zfs::Error::Invalid)); - - vdev_top = Some(Top::new(ms_array, ms_shift)); - /*nvlist_lookup_uint64(nv, ZPOOL_CONFIG_METASLAB_ARRAY, &vd->vdev_ms_array); - nvlist_lookup_uint64(nv, ZPOOL_CONFIG_METASLAB_SHIFT, &vd->vdev_ms_shift); - nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ASIZE, &vd->vdev_asize); - nvlist_lookup_uint64(nv, ZPOOL_CONFIG_REMOVING, &vd->vdev_removing);*/ } - if alloc_type != VDEV_ALLOC_ATTACH { + if alloc_type != AllocType::Attach { assert!(alloc_type == AllocType::Load || alloc_type == AllocType::Add || alloc_type == AllocType::Split || alloc_type == AllocType::RootPool); - //vd.vdev_mg = metaslab_group_create(islog ? spa_log_class(spa) : spa_normal_class(spa), vd); + let ms_group = MetaslabGroup::create(spa.normal_class()); + + vdev_top = Some(Top::new(ms_array, ms_shift, ms_group)); } } @@ -255,7 +256,7 @@ impl Vdev { } fn metaslab_init(&mut self, txg: u64) -> zfs::Result<()> { - spa_t *spa = self.spa; + //spa_t *spa = self.spa; //objset_t *mos = spa->spa_meta_objset; // We assume this is a top-level vdev @@ -297,8 +298,8 @@ impl Vdev { // If the vdev is being removed we don't activate // the metaslabs since we want to ensure that no new // allocations are performed on this device. - if old_count == 0 && !vd.removing { - metaslab_group_activate(vd.mg); + if old_count == 0 && !top.removing { + //metaslab_group_activate(vd.mg); } //if (txg == 0) @@ -482,13 +483,13 @@ impl Tree { const DIRTY_METASLAB: u64 = 0x01; const DIRTY_DTL: u64 = 0x02; -const VDEV_RAIDZ_MAXPARITY: usize = 3; +const RAIDZ_MAXPARITY: usize = 3; -const VDEV_PAD_SIZE: u64 = 8 << 10; -/* 2 padding areas (vl_pad1 and vl_pad2) to skip */ -const VDEV_SKIP_SIZE: u64 = VDEV_PAD_SIZE * 2; -const VDEV_PHYS_SIZE: u64 = 112 << 10; -const VDEV_UBERBLOCK_RING: u64 = 128 << 10; +const PAD_SIZE: u64 = 8 << 10; +// 2 padding areas (vl_pad1 and vl_pad2) to skip +const SKIP_SIZE: u64 = PAD_SIZE * 2; +const PHYS_SIZE: u64 = 112 << 10; +const UBERBLOCK_RING: u64 = 128 << 10; // The largest uberblock we support is 8k. const MAX_UBERBLOCK_SHIFT: u64 = 13; diff --git a/filesystem/apps/zfs/zio.rs b/filesystem/apps/zfs/zio.rs index d7736d87d..8b61ccc29 100644 --- a/filesystem/apps/zfs/zio.rs +++ b/filesystem/apps/zfs/zio.rs @@ -94,6 +94,7 @@ impl Reader { //////////////////////////////////////////////////////////////////////////////////////////////////// +/* pub struct Zio { // Core information about this IO //bookmark: ZBookmarkPhys, @@ -249,7 +250,7 @@ impl Zio { } if zb != NULL { - zio->bookmark = *zb; + zio.bookmark = *zb; } if let Some(pio) = pio { @@ -946,3 +947,5 @@ const CLAIM_PIPELINE = INTERLOCK_STAGES | STAGE_DVA_CLAIM; const IOCTL_PIPELINE = INTERLOCK_STAGES | STAGE_VDEV_IO_START | STAGE_VDEV_IO_ASSESS; const BLOCKING_STAGES = STAGE_DVA_ALLOCATE | STAGE_DVA_CLAIM | STAGE_VDEV_IO_START; + +*/