From: Kay Sievers Date: Sun, 23 Oct 2005 14:08:56 +0000 (+0200) Subject: volume_id: add OVFS Version 1 X-Git-Tag: 174~2522 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=0ecc6c1b1957e367852bf2dbf3fbc406762d272d volume_id: add OVFS Version 1 Signed-off-by: Kay Sievers --- diff --git a/extras/volume_id/volume_id/Makefile.inc b/extras/volume_id/volume_id/Makefile.inc index 71f4ea286..80f451d58 100644 --- a/extras/volume_id/volume_id/Makefile.inc +++ b/extras/volume_id/volume_id/Makefile.inc @@ -27,7 +27,7 @@ VOLUME_ID_OBJS= \ $(VOLUME_ID_BASE)/sysv.o \ $(VOLUME_ID_BASE)/minix.o \ $(VOLUME_ID_BASE)/luks.o \ - $(VOLUME_ID_BASE)/ocfs2.o \ + $(VOLUME_ID_BASE)/ocfs.o \ $(VOLUME_ID_BASE)/volume_id.o \ $(VOLUME_ID_BASE)/util.o @@ -59,6 +59,6 @@ VOLUME_ID_HEADERS= \ $(VOLUME_ID_BASE)/sysv.h \ $(VOLUME_ID_BASE)/minix.h \ $(VOLUME_ID_BASE)/luks.h \ - $(VOLUME_ID_BASE)/ocfs2.h \ + $(VOLUME_ID_BASE)/ocfs.h \ $(VOLUME_ID_BASE)/volume_id.h \ $(VOLUME_ID_BASE)/util.h diff --git a/extras/volume_id/volume_id/ocfs.c b/extras/volume_id/volume_id/ocfs.c new file mode 100644 index 000000000..81b4e2d04 --- /dev/null +++ b/extras/volume_id/volume_id/ocfs.c @@ -0,0 +1,194 @@ +/* + * volume_id - reads filesystem label and uuid + * + * Copyright (C) 2004 Andre Masella + * Copyright (C) 2005 Kay Sievers + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2 of the License. + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include + +#include "volume_id.h" +#include "logging.h" +#include "util.h" +#include "ocfs.h" + + +struct ocfs1_super_block_header { + uint32_t minor_version; + uint32_t major_version; + uint8_t signature[128]; + uint8_t mount_point[128]; + uint64_t serial_num; + uint64_t device_size; + uint64_t start_off; + uint64_t bitmap_off; + uint64_t publ_off; + uint64_t vote_off; + uint64_t root_bitmap_off; + uint64_t data_start_off; + uint64_t root_bitmap_size; + uint64_t root_off; + uint64_t root_size; + uint64_t cluster_size; + uint64_t num_nodes; + uint64_t num_clusters; + uint64_t dir_node_size; + uint64_t file_node_size; + uint64_t internal_off; + uint64_t node_cfg_off; + uint64_t node_cfg_size; + uint64_t new_cfg_off; + uint32_t prot_bits; + int32_t excl_mount; +} __attribute__((__packed__)); + +struct ocfs1_super_block_label { + struct ocfs1_disk_lock { + uint32_t curr_master; + uint8_t file_lock; + uint8_t compat_pad[3]; + uint64_t last_write_time; + uint64_t last_read_time; + uint32_t writer_node_num; + uint32_t reader_node_num; + uint64_t oin_node_map; + uint64_t dlock_seq_num; + } disk_lock __attribute__((__packed__)); + uint8_t label[64]; + uint16_t label_len; + uint8_t vol_id[16]; + uint16_t vol_id_len; + uint8_t cluster_name[64]; + uint16_t cluster_name_len; +} __attribute__((__packed__)); + +struct ocfs2_super_block { + uint8_t i_signature[8]; + uint32_t i_generation; + int16_t i_suballoc_slot; + uint16_t i_suballoc_bit; + uint32_t i_reserved0; + uint32_t i_clusters; + uint32_t i_uid; + uint32_t i_gid; + uint64_t i_size; + uint16_t i_mode; + uint16_t i_links_count; + uint32_t i_flags; + uint64_t i_atime; + uint64_t i_ctime; + uint64_t i_mtime; + uint64_t i_dtime; + uint64_t i_blkno; + uint64_t i_last_eb_blk; + uint32_t i_fs_generation; + uint32_t i_atime_nsec; + uint32_t i_ctime_nsec; + uint32_t i_mtime_nsec; + uint64_t i_reserved1[9]; + uint64_t i_pad1; + uint16_t s_major_rev_level; + uint16_t s_minor_rev_level; + uint16_t s_mnt_count; + int16_t s_max_mnt_count; + uint16_t s_state; + uint16_t s_errors; + uint32_t s_checkinterval; + uint64_t s_lastcheck; + uint32_t s_creator_os; + uint32_t s_feature_compat; + uint32_t s_feature_incompat; + uint32_t s_feature_ro_compat; + uint64_t s_root_blkno; + uint64_t s_system_dir_blkno; + uint32_t s_blocksize_bits; + uint32_t s_clustersize_bits; + uint16_t s_max_slots; + uint16_t s_reserved1; + uint32_t s_reserved2; + uint64_t s_first_cluster_group; + uint8_t s_label[64]; + uint8_t s_uuid[16]; +} __attribute__((__packed__)); + +int volume_id_probe_ocfs1(struct volume_id *id, uint64_t off) +{ + const uint8_t *buf; + struct ocfs1_super_block_header *osh; + struct ocfs1_super_block_label *osl; + + buf = volume_id_get_buffer(id, off, 0x200); + if (buf == NULL) + return -1; + + osh = (struct ocfs1_super_block_header *) buf; + if (memcmp(osh->signature, "OracleCFS", 9) != 0) + return -1; + snprintf(id->type_version, sizeof(id->type_version)-1, + "%u.%u", osh->major_version, osh->minor_version); + + dbg("found OracleCFS signature, now reading label"); + buf = volume_id_get_buffer(id, off + 0x200, 0x200); + if (buf == NULL) + return -1; + + osl = (struct ocfs1_super_block_label *) buf; + volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); + if (osl->label_len <= 64) { + volume_id_set_label_raw(id, osl->label, 64); + volume_id_set_label_string(id, osl->label, 64); + } + if (osl->vol_id_len == 16) + volume_id_set_uuid(id, osl->vol_id, UUID_DCE); + id->type = "ocfs"; + return 0; +} + +#define OCFS2_MAX_BLOCKSIZE 0x1000 +#define OCFS2_SUPER_BLOCK_BLKNO 2 + +int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off) +{ + const uint8_t *buf; + struct ocfs2_super_block *os; + size_t blksize; + + dbg("probing at offset 0x%llx", (unsigned long long) off); + + for (blksize = 0x200; blksize <= OCFS2_MAX_BLOCKSIZE; blksize >>= 1) { + buf = volume_id_get_buffer(id, off + OCFS2_SUPER_BLOCK_BLKNO * blksize, 0x200); + if (buf == NULL) + return -1; + + os = (struct ocfs2_super_block *) buf; + if (memcmp(os->i_signature, "OCFSV2", 6) != 0) + continue; + + volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); + volume_id_set_label_raw(id, os->s_label, 64); + volume_id_set_label_string(id, os->s_label, 64); + volume_id_set_uuid(id, os->s_uuid, UUID_DCE); + snprintf(id->type_version, sizeof(id->type_version)-1, + "%u.%u", os->s_major_rev_level, os->s_minor_rev_level); + id->type = "ocfs2"; + return 0; + } + return -1; +} diff --git a/extras/volume_id/volume_id/ocfs2.h b/extras/volume_id/volume_id/ocfs.h similarity index 58% rename from extras/volume_id/volume_id/ocfs2.h rename to extras/volume_id/volume_id/ocfs.h index 24b43b187..9d46b28dc 100644 --- a/extras/volume_id/volume_id/ocfs2.h +++ b/extras/volume_id/volume_id/ocfs.h @@ -1,16 +1,18 @@ /* * volume_id - reads filesystem label and uuid * - * Copyright (C) Andre Masella + * Copyright (C) 2004 Andre Masella + * Copyright (C) 2005 Kay Sievers * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation version 2 of the License. */ -#ifndef _VOLUME_ID_OCFS2_ -#define _VOLUME_ID_OCFS2_ +#ifndef _VOLUME_ID_OCFS1_ +#define _VOLUME_ID_OCFS1_ +extern int volume_id_probe_ocfs1(struct volume_id *id, uint64_t off); extern int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off); #endif diff --git a/extras/volume_id/volume_id/ocfs2.c b/extras/volume_id/volume_id/ocfs2.c deleted file mode 100644 index 3a771123f..000000000 --- a/extras/volume_id/volume_id/ocfs2.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * volume_id - reads filesystem label and uuid - * - * Copyright (C) Andre Masella - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 of the License. - */ - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE 1 -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include -#include -#include -#include - -#include "volume_id.h" -#include "logging.h" -#include "util.h" -#include "ocfs2.h" - - -/* All these values are taken from ocfs2-tools's ocfs2_fs.h */ -#define OCFS2_VOL_UUID_LEN 16 -#define OCFS2_MAX_VOL_LABEL_LEN 64 -#define OCFS2_SUPERBLOCK_OFFSET 0x2000 - - -/* This is the superblock. The OCFS2 header files have structs in structs. -This is one has been simplified since we only care about the superblock. -*/ - -struct ocfs2_super_block { - uint8_t i_signature[8]; /* Signature for validation */ - uint32_t i_generation; /* Generation number */ - int16_t i_suballoc_slot; /* Slot suballocator this inode belongs to */ - uint16_t i_suballoc_bit; /* Bit offset in suballocator block group */ - uint32_t i_reserved0; - uint32_t i_clusters; /* Cluster count */ - uint32_t i_uid; /* Owner UID */ - uint32_t i_gid; /* Owning GID */ - uint64_t i_size; /* Size in bytes */ - uint16_t i_mode; /* File mode */ - uint16_t i_links_count; /* Links count */ - uint32_t i_flags; /* File flags */ - uint64_t i_atime; /* Access time */ - uint64_t i_ctime; /* Creation time */ - uint64_t i_mtime; /* Modification time */ - uint64_t i_dtime; /* Deletion time */ - uint64_t i_blkno; /* Offset on disk, in blocks */ - uint64_t i_last_eb_blk; /* Pointer to last extent block */ - uint32_t i_fs_generation; /* Generation per fs-instance */ - uint32_t i_atime_nsec; - uint32_t i_ctime_nsec; - uint32_t i_mtime_nsec; - uint64_t i_reserved1[9]; - uint64_t i_pad1; /* Generic way to refer to this 64bit union */ - /* Normally there is a union of the different block types, but we only care about the superblock. */ - uint16_t s_major_rev_level; - uint16_t s_minor_rev_level; - uint16_t s_mnt_count; - int16_t s_max_mnt_count; - uint16_t s_state; /* File system state */ - uint16_t s_errors; /* Behaviour when detecting errors */ - uint32_t s_checkinterval; /* Max time between checks */ - uint64_t s_lastcheck; /* Time of last check */ - uint32_t s_creator_os; /* OS */ - uint32_t s_feature_compat; /* Compatible feature set */ - uint32_t s_feature_incompat; /* Incompatible feature set */ - uint32_t s_feature_ro_compat; /* Readonly-compatible feature set */ - uint64_t s_root_blkno; /* Offset, in blocks, of root directory dinode */ - uint64_t s_system_dir_blkno; /* Offset, in blocks, of system directory dinode */ - uint32_t s_blocksize_bits; /* Blocksize for this fs */ - uint32_t s_clustersize_bits; /* Clustersize for this fs */ - uint16_t s_max_slots; /* Max number of simultaneous mounts before tunefs required */ - uint16_t s_reserved1; - uint32_t s_reserved2; - uint64_t s_first_cluster_group; /* Block offset of 1st cluster group header */ - uint8_t s_label[OCFS2_MAX_VOL_LABEL_LEN]; /* Label for mounting, etc. */ - uint8_t s_uuid[OCFS2_VOL_UUID_LEN]; /* 128-bit uuid */ -} __attribute__((__packed__)); - -int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off) -{ - struct ocfs2_super_block *os; - - dbg("probing at offset 0x%llx", (unsigned long long) off); - - os = (struct ocfs2_super_block *) volume_id_get_buffer(id, off + OCFS2_SUPERBLOCK_OFFSET, 0x200); - if (os == NULL) - return -1; - - if (memcmp(os->i_signature, "OCFSV2", 6) != 0) { - return -1; - } - - volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); - volume_id_set_label_raw(id, os->s_label, OCFS2_MAX_VOL_LABEL_LEN < VOLUME_ID_LABEL_SIZE ? - OCFS2_MAX_VOL_LABEL_LEN : VOLUME_ID_LABEL_SIZE); - volume_id_set_label_string(id, os->s_label, OCFS2_MAX_VOL_LABEL_LEN < VOLUME_ID_LABEL_SIZE ? - OCFS2_MAX_VOL_LABEL_LEN : VOLUME_ID_LABEL_SIZE); - volume_id_set_uuid(id, os->s_uuid, UUID_DCE); - id->type = "ocfs2"; - return 0; -} diff --git a/extras/volume_id/volume_id/volume_id.c b/extras/volume_id/volume_id/volume_id.c index d1a6a5f0f..25bcd9535 100644 --- a/extras/volume_id/volume_id/volume_id.c +++ b/extras/volume_id/volume_id/volume_id.c @@ -58,7 +58,7 @@ #include "minix.h" #include "mac.h" #include "msdos.h" -#include "ocfs2.h" +#include "ocfs.h" int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size) { @@ -156,6 +156,9 @@ int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size) if (volume_id_probe_minix(id, off) == 0) goto exit; + if (volume_id_probe_ocfs1(id, off) == 0) + goto exit; + if (volume_id_probe_ocfs2(id, off) == 0) goto exit;