Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:12.2
s390-tools
s390-tools-sles11sp2-cmsfs-fuse-fba.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File s390-tools-sles11sp2-cmsfs-fuse-fba.patch of Package s390-tools
Description: cmsfs-fuse: Add support for FBA-512 disks Symptom: FBA-512 disks can not be mounted with cmsfs-fuse. Problem: For FBA-512 disks the label information is at a different position. Also the formatted block size may differ from the disk block size. Solution: Extend the label detection to work with FBA-512 disks and read the formatted block size always from the label. Problem-ID: 75986 --- cmsfs-fuse/cmsfs-fuse.c | 9 +---- cmsfs-fuse/cmsfs-fuse.h | 4 +- cmsfs-fuse/dasd.c | 84 ++++++++++++++++++++++++++++++------------------ 3 files changed, 58 insertions(+), 39 deletions(-) --- a/cmsfs-fuse/cmsfs-fuse.c +++ b/cmsfs-fuse/cmsfs-fuse.c @@ -92,8 +92,6 @@ static void usage(const char *progname) static char CODEPAGE_EDF[] = "CP1047"; static char CODEPAGE_LINUX[] = "ISO-8859-1"; -#define USED_BLOCK_ADDR (cmsfs.blksize * 2 + 32) - #define READDIR_FILE_ENTRY -1 #define READDIR_END_OF_DIR -2 #define READDIR_DIR_ENTRY -3 @@ -318,7 +316,7 @@ int _read(void *buf, size_t size, off_t (addr & ~DATA_BLOCK_MASK)) DIE("read: crossing blocks addr: %lx size: %ld\n", addr, size); - if (addr < cmsfs.fdir || addr > cmsfs.size) + if (addr < cmsfs.label || addr > cmsfs.size) return -EIO; memcpy(buf, cmsfs.map + addr, size); @@ -331,8 +329,7 @@ int _write(const void *buf, size_t size, (addr & ~DATA_BLOCK_MASK)) DIE("write: crossing blocks addr: %x size: %d\n", (int)addr, (int)size); - - if ((addr < (2 * cmsfs.blksize)) || (addr > cmsfs.size)) + if (addr < cmsfs.label || addr > cmsfs.size) return -EIO; if (buf == NULL) @@ -2024,7 +2021,7 @@ static void update_block_count(void) { int rc; - rc = _write(&cmsfs.used_blocks, sizeof(unsigned int), USED_BLOCK_ADDR); + rc = _write(&cmsfs.used_blocks, sizeof(unsigned int), cmsfs.label + 32); BUG(rc < 0); } --- a/cmsfs-fuse/cmsfs-fuse.h +++ b/cmsfs-fuse/cmsfs-fuse.h @@ -50,12 +50,12 @@ struct cmsfs { int blksize; /* number of 512 byte blocks per block */ int nr_blocks_512; - /* disk info */ - unsigned int format; /* device is read only */ int readonly; /* access permission for other users */ int allow_other; + /* offset to label */ + off_t label; /* offset to file directory root FST */ off_t fdir; /* offset to allocation map */ --- a/cmsfs-fuse/dasd.c +++ b/cmsfs-fuse/dasd.c @@ -79,18 +79,9 @@ static int disk_supported(int fd, struct { unsigned int cms_id = VOL_LABEL_EBCDIC; struct cms_label label; - int offset, rc; - - /* check that this is a ldl disk */ - if (cmsfs->format != DASD_FORMAT_LDL) { - fprintf(stderr, COMP "Disk not LDL formatted\n"); - return 0; - } - - /* label is on block number 3 */ - offset = 2 * cmsfs->blksize; + int rc; - rc = lseek(fd, offset, SEEK_SET); + rc = lseek(fd, cmsfs->label, SEEK_SET); if (rc < 0) { perror(COMP "lseek failed"); return 0; @@ -103,11 +94,35 @@ static int disk_supported(int fd, struct } /* check that the label contains the CMS1 string */ - if (memcmp(label.id, &cms_id, sizeof(cms_id)) != 0) { - fprintf(stderr, COMP "Disk is not a CMS disk\n"); + if (memcmp(label.id, &cms_id, sizeof(cms_id)) != 0) + return 0; + + /* label sanity checks */ + if (label.blocksize != 4096 && + label.blocksize != 2048 && + label.blocksize != 1024 && + label.blocksize != 512) { + fprintf(stderr, COMP "Invalid disk block size!\n"); + return 0; + } + + if (label.dop != 4 && label.dop != 5) { + fprintf(stderr, COMP "Invalid disk origin pointer!\n"); return 0; } + if (label.fst_entry_size != sizeof(struct fst_entry)) { + fprintf(stderr, COMP "Invalid FST entry size!\n"); + return 0; + } + + if (label.fst_per_block != label.blocksize / label.fst_entry_size) { + fprintf(stderr, COMP "Invalid FST per block value!\n"); + return 0; + } + + /* set the blocksize to the formatted one */ + cmsfs->blksize = label.blocksize; DEBUG(" DOP: %d", label.dop); /* block number 5 means 0x4000... */ cmsfs->fdir = (label.dop - 1) * cmsfs->blksize; @@ -117,10 +132,11 @@ static int disk_supported(int fd, struct cmsfs->used_blocks = label.used_blocks; DEBUG(" Total blocks: %d Used blocks: %d", cmsfs->total_blocks, cmsfs->used_blocks); + return 1; } -static void get_device_info_bdev(int fd, struct cmsfs *cmsfs) +static void get_device_info_ioctl(int fd, struct cmsfs *cmsfs) { struct dasd_info2 *info = NULL; @@ -137,11 +153,15 @@ static void get_device_info_bdev(int fd, if (ioctl(fd, BIODASDINFO, info) != 0) DIE("ioctl dasd info failed\n"); } - cmsfs->format = info->format; + + /* check that this is a ldl disk */ + if (info->format != DASD_FORMAT_LDL) + DIE("Disk not LDL formatted\n"); + free(info); } -static int blocksizes[] = { 4096, 512, 2048, 1024 }; +static int label_offsets[] = { 4096, 512, 2048, 1024, 8192 }; static void get_device_info_file(int fd, struct cmsfs *cmsfs) { @@ -151,14 +171,14 @@ static void get_device_info_file(int fd, off_t offset; int rc; - cmsfs->blksize = 0; + cmsfs->label = 0; /* * Read the blocksize from label. Unfortunately the blocksize * position depends on the blocksize... time for some heuristics. */ - for (i = 0; i < ARRAY_SIZE(blocksizes); i++) { - offset = blocksizes[i] * 2; + for (i = 0; i < ARRAY_SIZE(label_offsets); i++) { + offset = label_offsets[i]; rc = lseek(fd, offset, SEEK_SET); if (rc < 0) @@ -170,19 +190,13 @@ static void get_device_info_file(int fd, /* check if the label contains the CMS1 string */ if (memcmp(label, &cms_id, sizeof(cms_id)) == 0) { - cmsfs->blksize = blocksizes[i]; + cmsfs->label = offset; break; } } - if (!cmsfs->blksize) - DIE("Error detecting blocksize from file!\n"); - - /* - * Hardcoded since the label doesn't contain that info. - * Checking the disk identifier must be sufficient. - */ - cmsfs->format = DASD_FORMAT_LDL; + if (!cmsfs->label) + DIE("Error CMS1 label not found!\n"); } int get_device_info(struct cmsfs *cmsfs) @@ -208,9 +222,17 @@ int get_device_info(struct cmsfs *cmsfs) if (fstat(fd, &stat) < 0) DIE_PERROR("fstat failed"); - if (S_ISBLK(stat.st_mode)) - get_device_info_bdev(fd, cmsfs); - else if (S_ISREG(stat.st_mode)) + if (S_ISBLK(stat.st_mode)) { + get_device_info_ioctl(fd, cmsfs); + cmsfs->label = 2 * cmsfs->blksize; + + /* FBA disks have a different label location */ + if (!disk_supported(fd, cmsfs)) { + cmsfs->label = cmsfs->blksize; + if (!disk_supported(fd, cmsfs)) + goto error; + } + } else if (S_ISREG(stat.st_mode)) get_device_info_file(fd, cmsfs); else goto error;
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor