summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Pouzenc <ludovic@pouzenc.fr>2015-08-30 19:04:19 +0200
committerLudovic Pouzenc <ludovic@pouzenc.fr>2015-08-30 19:04:19 +0200
commit08106a353fab69ee93e02a7d674c2597c0e37061 (patch)
treeaaa51b4c278f849c7ff3336fd447143d6b482b20
parent5d99eea1a574ad4030d66ae9448ad02c523d2adf (diff)
downloadraidguessfs-08106a353fab69ee93e02a7d674c2597c0e37061.tar.gz
raidguessfs-08106a353fab69ee93e02a7d674c2597c0e37061.tar.bz2
raidguessfs-08106a353fab69ee93e02a7d674c2597c0e37061.zip
raid_type as a config attr + code refactoring
-rw-r--r--mydisks.py1
-rw-r--r--myraid.py83
-rwxr-xr-xraidguessfs.py63
3 files changed, 81 insertions, 66 deletions
diff --git a/mydisks.py b/mydisks.py
index 4a79c81..070c188 100644
--- a/mydisks.py
+++ b/mydisks.py
@@ -26,6 +26,7 @@ class MyDisks():
def __init__(self, *args, **kwargs):
self.disks = []
self.disk_paths = []
+ self.sector_size = 512
self.disk_count = 0
self.disks_size = [0]
self.max_disks = 16
diff --git a/myraid.py b/myraid.py
index 5847e6e..35c1e2a 100644
--- a/myraid.py
+++ b/myraid.py
@@ -19,24 +19,24 @@
# along with RaidGuessFS. If not, see <http://www.gnu.org/licenses/>
import logging
-from myraidmaths import MyRaidMaths
+import myraidmaths
class MyRaid():
"""Auxiliary class, managing RAID layer"""
RAID_TYPES = [ '0', '1', '5', '5+0' ]
RAID5_LAYOUTS = [ 'la', 'ra', 'ls', 'rs' ]
- def __init__(self, *args, **kwargs):
- self.d = None
+ def __init__(self, mydisks):
+ self.d = mydisks
self.raid_start = 0
self.raid_end = 0
- self.raid_sector_size = 512 # TODO : should be self.d.sector_size
self.raid_chunk_size = 65536
self.raid_disk_order = []
self.raid_disk_count = 0
+ self.raid_type = '5'
self.raid_layout = 'ls'
self.raid_disks = []
- self.nested_subraid = 2
+ self.raid_subraid_count = 2
def get_raid_start(self):
return self.raid_start
@@ -53,9 +53,15 @@ class MyRaid():
def get_raid_disk_order_str(self):
return ' '.join(map(str,self.raid_disk_order))
+ def get_raid_type(self):
+ return self.raid_type
+
def get_raid_layout(self):
return self.raid_layout
+ def get_raid_subraid_count(self):
+ return self.raid_subraid_count
+
def set_disks(self, new_mydisks):
# FIXME : self.d don't need to be updaed (pass on __init__)
self.d = new_mydisks
@@ -89,75 +95,86 @@ class MyRaid():
self.raid_disk_order = new_raid_disk_order
self.raid_disks = [ self.d.disks[i] for i in self.raid_disk_order ]
+ def set_raid_type(self, new_raid_type):
+ if new_raid_type in MyRaid.RAID_TYPES:
+ self.raid_type = new_raid_type
+ else:
+ raise ValueError('raid_type has to be one of %s'%' '.join(MyRaid.RAID_TYPES))
+
+ def set_raid_subraid_count(self, new_raid_subraid_count):
+ """Update the number of subcomponents in nested RAID levels"""
+ self.raid_subraid_count = new_raid_subraid_count
+
def set_raid_layout(self, new_raid_layout):
+ """Update the kind of data/parity block layout for RAID5 family"""
if new_raid_layout in MyRaid.RAID5_LAYOUTS:
self.raid_layout = new_raid_layout
else:
- raise ValueError('raid_layout has to be one of %s'%' '.join(RAID_LAYOUTS))
+ raise ValueError('raid_layout has to be one of %s'%' '.join(MyRaid.RAID_LAYOUTS))
- def sizeof_raid_result(self, raid_type):
+ def sizeof_raid_result(self):
size = max(0, self.raid_end - self.raid_start)
return {
'0' : size * self.raid_disk_count,
'1' : size if self.raid_disk_count == 2 else 0,
'5' : size * (self.raid_disk_count - 1) if self.raid_disk_count >= 3 else 0,
'5+0': size * (self.raid_disk_count - 2) if self.raid_disk_count >= 6 and self.raid_disk_count % 2 == 0 else 0,
- }[raid_type]
+ }[self.raid_type]
- def sizeof_disk_xor(self, raid_type):
+ def sizeof_disk_xor(self):
return max(0, self.raid_end - self.raid_start)
- def sizeof_disk_parity(self, raid_type):
- size = max(0, self.raid_end - self.raid_start) / self.raid_sector_size * 16
+ def sizeof_disk_parity(self):
+ size = max(0, self.raid_end - self.raid_start) / self.d.sector_size * 16
return {
'0' : 64,
'1' : size if self.raid_disk_count == 2 else 64,
'5' : size if self.raid_disk_count >= 3 else 64,
'5+0': size if self.raid_disk_count >= 6 and self.raid_disk_count % 2 == 0 else 64,
- }[raid_type]
+ }[self.raid_type]
- def read_disk_xor(self,raid_type,offset,size):
+ def read_disk_xor(self,offset,size):
"""Returns raw bitwise XOR against a bunch of disks slice"""
- return MyRaidMaths.xor_blocks(self.raid_disks,offset,size)[1]
+ return myraidmaths.MyRaidMaths.xor_blocks(self.raid_disks,offset,size)[1]
- def read_disk_parity(self,raid_type,offset,size):
+ def read_disk_parity(self,offset,size):
"""Returns textual information about parity status of each sector"""
- logging.warn("Enter read_disk_parity(%s,%d,%d)"%(raid_type,offset,size))
+ logging.warn("Enter read_disk_parity(%d,%d)"%(offset,size))
msg = {
'0' : 'There no notion of parity in RAID 0 mode\n',
'1' : None if self.raid_disk_count == 2 else 'Wrong disk count (should be 2)\n',
'5' : None if self.raid_disk_count >= 3 else 'Wrong disk count (should be >=3)\n',
'5+0': None if self.raid_disk_count >= 6 and self.raid_disk_count % 2 == 0
else 'Wrong disk count (should be >=6 and even)\n',
- }[raid_type]
+ }[self.raid_type]
if msg:
return msg[offset:offset+size]
- start = self.raid_start + offset * self.raid_sector_size / 16
- end = start + size * self.raid_sector_size / 16
+ start = self.raid_start + offset * self.d.sector_size / 16
+ end = start + size * self.d.sector_size / 16
#TODO : improove for nested levels
- if raid_type in ['1','5', '5+0']:
+ if self.raid_type in ['1','5', '5+0']:
result = ''.join(
- [ '0x%011x %c\n'%( addr, MyRaidMaths.xor_blocks(self.raid_disks, addr, self.raid_sector_size)[0])
- for addr in xrange(start, end, self.raid_sector_size)
+ [ '0x%011x %c\n'%( addr, myraidmaths.MyRaidMaths.xor_blocks(self.raid_disks, addr, self.d.sector_size)[0])
+ for addr in xrange(start, end, self.d.sector_size)
])
else:
result = None
- logging.warn("Exit. read_disk_parity(%s,%d,%d)"%(raid_type,offset,size))
+ logging.warn("Exit. read_disk_parity(%d,%d)"%(offset,size))
return result
- def read_raid_result(self,raid_type,offset,size):
+ def read_raid_result(self,offset,size):
"""Returns actual RAID data"""
- res = MyRaidMaths.apply_raid_layout(offset, size, raid_type, self.raid_layout, self.raid_chunk_size, self.raid_disk_count, self.raid_start, self.nested_subraid);
+ res = myraidmaths.MyRaidMaths.apply_raid_layout(offset, size, self.raid_type, self.raid_layout, self.raid_chunk_size, self.raid_disk_count, self.raid_start, self.raid_subraid_count);
(segment_no, segment_off, stripe_no, subraid_no, par_disk, data_disk, off_disk, aligned_read_size) = res
logging.debug("raid.read_result(%s): offset=%d,segment_no=%d,segment_off=%d,stripe_no=%d,subraid_no=%d,par_disk=%d(disk%02d),data_disk=%d(disk%02d),off_disk=%d,aligned_read_size=%d,segment_off+aligned_read_size=%d"
- % (raid_type,offset,segment_no,segment_off,stripe_no,subraid_no,par_disk,self.raid_disk_order[par_disk],data_disk,self.raid_disk_order[data_disk],off_disk,aligned_read_size,segment_off+aligned_read_size) )
+ % (self.raid_type,offset,segment_no,segment_off,stripe_no,subraid_no,par_disk,self.raid_disk_order[par_disk],data_disk,self.raid_disk_order[data_disk],off_disk,aligned_read_size,segment_off+aligned_read_size) )
data_fd = self.raid_disks[data_disk]
@@ -176,29 +193,29 @@ class MyRaid():
other_fds.remove(data_fd)
data_arr = []
- for s in xrange(off_disk, off_disk+aligned_read_size, self.raid_sector_size):
- if self.d.is_readable(self.raid_disk_order[data_disk],s,self.raid_sector_size):
+ for s in xrange(off_disk, off_disk+aligned_read_size, self.d.sector_size):
+ if self.d.is_readable(self.raid_disk_order[data_disk],s,self.d.sector_size):
# Current sector is readable from data disk, read it
logging.debug('-> 0x%011x : readable'%s)
data_fd.seek(off_disk)
- data_arr.append(data_fd.read(self.raid_sector_size))
+ data_arr.append(data_fd.read(self.d.sector_size))
else:
# Current sector is dead on data disk, recover it if possible
recoverable = reduce(lambda a,b: a and b, [
- self.d.is_readable(other_disk,off_disk,self.raid_sector_size) for other_disk in other_disks
+ self.d.is_readable(other_disk,off_disk,self.d.sector_size) for other_disk in other_disks
])
if recoverable:
logging.info('-> 0x%011x : recoverable'%s)
- data_arr.append( MyRaidMaths.xor_blocks(other_fds, s,self.raid_sector_size)[1] )
+ data_arr.append( myraidmaths.MyRaidMaths.xor_blocks(other_fds, s,self.d.sector_size)[1] )
else:
logging.warn('-> 0x%011x : unrecoverable'%s)
- data_arr.append( '\0' * self.raid_sector_size)
+ data_arr.append( '\0' * self.d.sector_size)
data = ''.join(data_arr)
# Prevent short reads, seems mandatory for losetup'ing raid_result but kills performance
#TODO : make it activable per config
if aligned_read_size < size:
- return ''.join( (data, self.read_raid_result(raid_type,offset+aligned_read_size,size-aligned_read_size) ) )
+ return ''.join( (data, self.read_raid_result(offset + aligned_read_size, size - aligned_read_size) ) )
return data
diff --git a/raidguessfs.py b/raidguessfs.py
index bb26b3f..bd256bf 100755
--- a/raidguessfs.py
+++ b/raidguessfs.py
@@ -50,7 +50,7 @@ class RaidGuessFS(fuse.Fuse):
# Early initialisations (notably modules and the static directory tree part)
self.d = mydisks.MyDisks()
- self.raid = myraid.MyRaid()
+ self.raid = myraid.MyRaid(self.d)
self.bmp = mybinview.MyBinView()
self.st = mystat.MyStat()
self.tasks = mytasks.MyTasks(self.d)
@@ -63,7 +63,7 @@ class RaidGuessFS(fuse.Fuse):
self.settings = [
'disk_count',
'raid_start', 'raid_end', 'raid_chunk_size',
- 'raid_disk_order', 'raid_layout',
+ 'raid_type', 'raid_disk_order', 'raid_layout', 'raid_subraid_count',
'bmp_height', 'bmp_width', 'bmp_start_offset',
'task_start', 'task_kill', 'task_find_files_pathlist'
]
@@ -71,15 +71,15 @@ class RaidGuessFS(fuse.Fuse):
self.settings_getters = [
self.d.get_disk_count,
self.raid.get_raid_start, self.raid.get_raid_end, self.raid.get_raid_chunk_size,
- self.raid.get_raid_disk_order_str, self.raid.get_raid_layout,
+ self.raid.get_raid_type, self.raid.get_raid_disk_order_str, self.raid.get_raid_layout, self.raid.get_raid_subraid_count,
self.bmp.get_bmp_height, self.bmp.get_bmp_width, self.bmp.get_bmp_start_offset,
self.get_task_start, self.get_task_kill, self.tasks.get_find_files_pathlist_str,
]
self.settings_updaters = [
self.update_disk_count,
- self.update_raid_start, self.update_raid_end, self.update_raid_chunk_size, self.update_raid_disk_order,
- self.raid.set_raid_layout,
+ self.update_raid_start, self.update_raid_end, self.update_raid_chunk_size,
+ self.update_raid_type, self.update_raid_disk_order, self.raid.set_raid_layout, self.update_raid_subraid_count,
self.update_bmp_height, self.update_bmp_width, self.update_bmp_start_offset,
self.tasks.task_start, self.tasks.task_kill, self.tasks.append_find_files_pathlist
]
@@ -88,17 +88,12 @@ class RaidGuessFS(fuse.Fuse):
self.dentries = {
'/' : [ fuse.Direntry(name) for name in ['config','disk','raid','tasks','visual'] ],
'/config': [ fuse.Direntry(name) for name in self.settings ],
- '/raid' : [ fuse.Direntry(name) for name in myraid.MyRaid.RAID_TYPES ],
+ '/raid' : [ fuse.Direntry(name) for name in ['disk_parity','disk_xor','raid_result'] ],
'/tasks' : [ fuse.Direntry(name) for name in self.tasks.TASK_NAMES ],
'/disk' : [ ], # Filled in _refresh_disk_dentries()
'/visual': [ ], # Filled in _refresh_disk_dentries()
}
- for raid_type in myraid.MyRaid.RAID_TYPES:
- self.dentries.update( {
- '/raid/%s'%raid_type: [ fuse.Direntry(name) for name in ['disk_parity','disk_xor','raid_result'] ],
- }
- )
logging.debug("Exit. RaidGuessFS.__init__()")
def _refresh_disk_dentries(self):
@@ -124,12 +119,9 @@ class RaidGuessFS(fuse.Fuse):
def _refresh_raid_fattr(self):
"""Update the raid computed attributes after a config change"""
logging.debug("Enter _refresh_raid_fattr()")
-
- for raid_type in myraid.MyRaid.RAID_TYPES:
- self.fattr['/raid/%s/disk_parity'%raid_type].st_size = self.raid.sizeof_disk_parity(raid_type)
- self.fattr['/raid/%s/disk_xor' %raid_type].st_size = self.raid.sizeof_disk_xor (raid_type)
- self.fattr['/raid/%s/raid_result'%raid_type].st_size = self.raid.sizeof_raid_result(raid_type)
-
+ self.fattr['/raid/disk_parity'].st_size = self.raid.sizeof_disk_parity()
+ self.fattr['/raid/disk_xor' ].st_size = self.raid.sizeof_disk_xor()
+ self.fattr['/raid/raid_result'].st_size = self.raid.sizeof_raid_result()
logging.debug("Exit. _refresh_raid_fattr()")
def _split_path(self,path):
@@ -155,7 +147,6 @@ class RaidGuessFS(fuse.Fuse):
self.d.set_disk_count(i)
self.d.open_disks()
self._refresh_disk_dentries()
- self.raid.set_disks(self.d)
self.raid.set_raid_end(min(self.d.disks_size)-1)
self.update_raid_disk_order(range(i))
@@ -187,10 +178,22 @@ class RaidGuessFS(fuse.Fuse):
self.raid.set_raid_end(i)
self._refresh_raid_fattr()
+ def update_raid_subraid_count(self, arg):
+ i = self._aton(arg)
+ self.raid.set_subraid_count(i)
+ self._refresh_raid_fattr()
+
def update_raid_chunk_size(self, arg):
i = self._aton(arg,False)
self.raid.set_raid_chunk_size(i)
+ def update_raid_type(self, arg):
+ if arg in myraid.MyRaid.RAID_TYPES:
+ self.raid.set_raid_type(arg)
+ self._refresh_raid_fattr()
+ else:
+ raise ValueError('update_raid_type() : raid type could be in %s'%myraid.MyRaid.RAID_TYPES)
+
def update_raid_disk_order(self, arg):
logging.debug("Enter update_raid_disk_order(%s)"%arg)
if type(arg) is str:
@@ -233,13 +236,9 @@ class RaidGuessFS(fuse.Fuse):
'/tasks/%s'%s: self.st.make_fake_file(4096) for s in self.tasks.TASK_NAMES
})
- for raid_type in myraid.MyRaid.RAID_TYPES:
- self.fattr.update( {
- '/raid/%s/disk_parity'%raid_type: self.st.make_fake_file(0),
- '/raid/%s/disk_xor'%raid_type: self.st.make_fake_file(0),
- '/raid/%s/raid_result'%raid_type: self.st.make_fake_file(0),
- })
-
+ self.fattr.update( {
+ '/raid/%s'%s: self.st.make_fake_file(0) for s in ['disk_parity', 'disk_xor', 'raid_result']
+ })
self.d.set_disks_path([getattr(self.parser.values,'disk%02d'%d) for d in range(self.d.max_disks)])
self.update_disk_count(len(self.d.disk_paths))
@@ -311,14 +310,12 @@ class RaidGuessFS(fuse.Fuse):
return self.bmp.read(self.d.disks[i],offset,size)
if path_chuncks[0] == 'raid':
- raid_type=path_chuncks[2]
- if raid_type in myraid.MyRaid.RAID_TYPES:
- if path_chuncks[4] == 'disk_parity':
- return self.raid.read_disk_parity(raid_type,offset,size)
- if path_chuncks[4] == 'disk_xor':
- return self.raid.read_disk_xor(raid_type,offset,size)
- if path_chuncks[4] == 'raid_result':
- return self.raid.read_raid_result(raid_type,offset,size)
+ if path_chuncks[1] == 'disk_parity':
+ return self.raid.read_disk_parity(offset,size)
+ if path_chuncks[1] == 'disk_xor':
+ return self.raid.read_disk_xor(offset,size)
+ if path_chuncks[1] == 'raid_result':
+ return self.raid.read_raid_result(offset,size)
if path_chuncks[0] == 'tasks':
if path_chuncks[1] == 'find_bootsect':