diff options
-rw-r--r-- | myraid.py | 110 | ||||
-rwxr-xr-x | raidguessfs.py | 26 |
2 files changed, 79 insertions, 57 deletions
@@ -32,18 +32,6 @@ class MyRaid(): self.raid_disk_count = 0 self.raid_types = [ '0', '1', '5', '5+0' ] - def get_raid_size(self, raid_type): - size = self.raid_end - self.raid_start - if size <= 0: - return 0 - else: - return { - '0': size * self.raid_disk_count, - '1': size, - '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] - def get_raid_start(self): return self.raid_start @@ -84,34 +72,32 @@ class MyRaid(): self.raid_disk_order = new_raid_disk_order self.raid_disk_count = len(new_raid_disk_order) + def sizeof_raid_result(self, raid_type): + size = self.raid_end - self.raid_start + if size <= 0 : + return 0 + else: + return { + '0' : size * self.raid_disk_count, + '1' : size, + '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] - def read_data(self,raid_type,disks,offset,size): - """TODO""" - disk_count = len(self.raid_disk_order) - - # This code is RAID 5 only - - slice_no = offset / self.raid_chunk_size - slice_off = offset % self.raid_chunk_size - segment=slice_no/(disk_count-1) - par_disk=(disk_count-1) - (segment % disk_count) # TODO : equivalent a : segment-1 % disk_count ? - data_disk=( par_disk + 1 + (slice_no % (disk_count-1)) ) % disk_count - off_disk = self.raid_start + segment * self.raid_chunk_size + slice_off - - size2 = min(size, (slice_no+1) * self.raid_chunk_size - offset) - - logging.info("raid.read_data(%s): offset=%d,slice_no=%d,slice_off=%d,segment=%d,par_disk=%d,data_disk=%d,off_disk=%d,size2=%d,slice_off+size2=%d" - % (raid_type,offset,slice_no,slice_off,segment,par_disk,data_disk,off_disk,size2,slice_off+size2) ) + def sizeof_disk_parity(self, raid_type): + return self.sizeof_disk_xor(raid_type) / self.raid_sector_size * 16 - data_fd = disks[self.raid_disk_order[data_disk]] - data_fd.seek(off_disk) - data = data_fd.read(size2) - - # This kills performance but don't make short reads before EOF - #if size2 < size: - # data += self.read_data(self,raid_type,disks,offset+size2,size-size2) - - return data + def sizeof_disk_xor(self, raid_type): + size = self.raid_end - self.raid_start + if size <= 0: + return 0 + else: + return { + '0' : 0, # TODO Could contain some plain text error message + '1' : size, + '5' : size if self.raid_disk_count >= 3 else 0, + '5+0': size if self.raid_disk_count >= 6 and self.raid_disk_count % 2 == 0 else 0, + }[raid_type] def xor_blocks(self,fd_list, offset, size): """TODO""" @@ -149,22 +135,56 @@ class MyRaid(): result = 'b' logging.info("Exit. xor_blocks(fd_list,%d,%d)"%(offset, size)) - return result - - def check_data(self,raid_type,disks,offset,size): - """TODO""" - logging.warn("Enter check_data(%s,disks,%d,%d)"%(raid_type,offset,size)) #import binascii #logging.warn(binascii.hexlify(numpy_b1)) + return (result,numpy_b1) - #result = ''.join([ self.xor_blocks(disks, (offset+i)*self.raid_sector_size, self.raid_sector_size) for i in range(size)]) - result = ''.join([ '0x%011x %c\n'%( (offset/16+i)*self.raid_sector_size, self.xor_blocks(disks, (offset/16+i)*self.raid_sector_size, self.raid_sector_size)) for i in range(size/16) ]) + def read_disk_parity(self,raid_type,disks,offset,size): + """TODO""" + logging.warn("Enter check_data(%s,disks,%d,%d)"%(raid_type,offset,size)) # TODO donner des offests RAID et pas disques + #result = ''.join([ '0x%011x %c\n'%( (offset/16+i)*self.raid_sector_size, self.xor_blocks(disks, (offset/16+i)*self.raid_sector_size, self.raid_sector_size)) for i in range(size/16) ]) + start = self.raid_start + offset * self.raid_sector_size / 16 + end = start + size * self.raid_sector_size / 16 + result = ''.join( + [ '0x%011x %c\n'%( addr, self.xor_blocks(disks, addr, self.raid_sector_size)[0]) + for addr in range(start, end, self.raid_sector_size) + ]) logging.warn("Exit. check_data(%s,disks,%d,%d)"%(raid_type,offset,size)) return result + def read_disk_xor(self,raid_type,disks,offset,size): + return self.xor_blocks(disks,offset,size)[1].tostring() + + def read_raid_result(self,raid_type,disks,offset,size): + """TODO""" + disk_count = len(self.raid_disk_order) + + # This code is RAID 5 only (left-assymetric) + + slice_no = offset / self.raid_chunk_size + slice_off = offset % self.raid_chunk_size + segment=slice_no/(disk_count-1) + par_disk=(disk_count-1) - (segment % disk_count) # TODO : equivalent a : segment-1 % disk_count ? + data_disk=( par_disk + 1 + (slice_no % (disk_count-1)) ) % disk_count + off_disk = self.raid_start + segment * self.raid_chunk_size + slice_off + + size2 = min(size, (slice_no+1) * self.raid_chunk_size - offset) + + logging.info("raid.read_result(%s): offset=%d,slice_no=%d,slice_off=%d,segment=%d,par_disk=%d,data_disk=%d,off_disk=%d,size2=%d,slice_off+size2=%d" + % (raid_type,offset,slice_no,slice_off,segment,par_disk,data_disk,off_disk,size2,slice_off+size2) ) + + data_fd = disks[self.raid_disk_order[data_disk]] + data_fd.seek(off_disk) + data = data_fd.read(size2) + + # This kills performance but don't make short reads before EOF + #if size2 < size: + # data += self.read_result(self,raid_type,disks,offset+size2,size-size2) + + return data diff --git a/raidguessfs.py b/raidguessfs.py index 6b78a7d..c9c3833 100755 --- a/raidguessfs.py +++ b/raidguessfs.py @@ -87,8 +87,7 @@ class RaidGuessFS(fuse.Fuse): for raid_type in self.raid.raid_types: self.dentries.update( { - # TODO : all type of raid don't need the same pseudo files - '/raid/%s'%raid_type: [ fuse.Direntry(name) for name in ['result','data_xor','parity'] ], + '/raid/%s'%raid_type: [ fuse.Direntry(name) for name in ['disk_parity','disk_xor','raid_result'] ], } ) logging.debug("Exit. RaidGuessFS.__init__()") @@ -118,9 +117,9 @@ class RaidGuessFS(fuse.Fuse): logging.debug("Enter _refresh_raid_fattr()") for raid_type in self.raid.raid_types: - self.fattr['/raid/%s/data_xor'%raid_type].st_size = 0 # self.raid.raid_size - self.fattr['/raid/%s/parity'%raid_type].st_size = min(self.d.disks_size) / self.raid.raid_sector_size * 16 - self.fattr['/raid/%s/result'%raid_type].st_size = self.raid.get_raid_size(raid_type) + 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) logging.debug("Exit. _refresh_raid_fattr()") @@ -210,9 +209,9 @@ class RaidGuessFS(fuse.Fuse): } for raid_type in self.raid.raid_types: self.fattr.update( { - '/raid/%s/data_xor'%raid_type: self.st.make_fake_file(0), - '/raid/%s/parity'%raid_type: self.st.make_fake_file(0), - '/raid/%s/result'%raid_type: self.st.make_fake_file(0), + '/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.d.set_disks_path([getattr(self.parser.values,'disk%02d'%d) for d in range(self.d.max_disks)]) @@ -280,10 +279,12 @@ class RaidGuessFS(fuse.Fuse): if path_chuncks[0] == 'raid': raid_type=path_chuncks[2] if raid_type in self.raid.raid_types: - if path_chuncks[4] == 'result': - return self.raid.read_data(raid_type,self.d.disks,offset,size) - if path_chuncks[4] == 'parity': - return self.raid.check_data(raid_type,self.d.disks,offset,size) + if path_chuncks[4] == 'disk_parity': + return self.raid.read_disk_parity(raid_type,self.d.disks,offset,size) + if path_chuncks[4] == 'disk_xor': + return self.raid.read_disk_xor(raid_type,self.d.disks,offset,size) + if path_chuncks[4] == 'raid_result': + return self.raid.read_raid_result(raid_type,self.d.disks,offset,size) except Exception as e: logging.exception(e) @@ -334,6 +335,7 @@ RaidGuessFS is a pseudo-filesystem that allows to guess parameters and disk orde server.multithreaded = False cwd = os.getcwd() + # TODO : only 2 parameters, but taking a parametrized string for num in range(server.d.max_disks): server.parser.add_option( mountopt="disk%02d"%num, |