对于硬盘的坏道的确没有什么好的办法,ata协议中的smart命令本意上是好的,但是很多的硬盘厂商并没有很好的实现smart的功能;硬盘的相关错误信息会存在相应的扇区里,但是这些扇区相当于一个环形的缓冲区,所以记录的错误信息有限,如果需要完整的硬盘坏道信息,smart就无能为力了。通过完整的读一遍硬盘可以找出坏道的完整信息,但是读牵涉到了DMA的数据传输过程所以效率较低;ata的协议里READ VERIFY (EXT)命令大大提高效率,该命令是NO DATA类型的;以下是具体的代码:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define ATA_DRQ (1 << 3) /* data request i/o */

#define ATA_ERR (1 << 0) /* have an error */

#define DRIVER_SENSE 0x08

#define CONDITION_GOOD 0x02

#define ATA_PASS_THRU_12 12

#define ATA_12 0xa1

#define ATA_PASS_THRU_16 16

#define ATA_16 0x85

#define CMD_NO_DATA (3 << 1)

#define FOR_SENSE_DATA 0x20

#define CMD_VERIFY_EXT 0x42

#define CMD_VERIFT 0x40

#define u64 unsigned long long

#define u32 unsigned int

#define u8 unsigned char

struct ata_taskfile {

u8 hob_feature;

u8 hob_nsect;

u8 hob_lbal;

u8 hob_lbam;

u8 hob_lbah;

u8 feature;

u8 nsect;

u8 lbal;

u8 lbam;

u8 lbah;

u8 device;

u8 command;

};

static u64 get_disk_size(const char *name)

{

const char *ptr = name + strlen(name) - 3;

u64 size;

char buff[128];

FILE *fp;

sprintf(buff,"/sys/block/%s/size",ptr);

if(NULL == (fp = fopen(buff,"r"))){

perror("fopen");

return 0;

}

fscanf(fp,"%lld",&size);

fclose(fp);

return size;

}

static void init_taskfile(struct ata_taskfile *tf,u64 lba,u32 nsect)

{

memset((void *)tf,0,sizeof(*tf));

tf->command = CMD_VERIFY_EXT;

tf->device = 1 << 6;

tf->lbal = lba;

tf->lbam = lba >> 8;

tf->lbah = lba >> 16;

tf->nsect = nsect;

tf->hob_nsect = nsect >> 8;

tf->hob_lbal = lba >> 24;

tf->hob_lbam = lba >> 32;

tf->hob_lbah = lba >> 40;

}

static int sg_ioctl(int fd,struct ata_taskfile *tf)

{

u8 sense_buffer[32];

u8 cdb[ATA_PASS_THRU_16];

sg_io_hdr_t sg_io;

int err = 0;

memset(sense_buffer,0,32);

memset((void *)&sg_io,0,sizeof(sg_io_hdr_t));

memset(cdb,0,ATA_PASS_THRU_16);

cdb[0] = ATA_16;

cdb[1] = CMD_NO_DATA;

cdb[2] = FOR_SENSE_DATA;

cdb[4] = tf->feature;

cdb[6] = tf->nsect;

cdb[8] = tf->lbal;

cdb[10] = tf->lbam;

cdb[12] = tf->lbah;

cdb[13] = tf->device;

cdb[14] = tf->command;

cdb[1] |= 1;

cdb[3] = tf->hob_feature;

cdb[5] = tf->hob_nsect;

cdb[7] = tf->hob_lbal;

cdb[9] = tf->hob_lbam;

cdb[11] = tf->hob_lbah;

sg_io.cmd_len = ATA_PASS_THRU_16;

sg_io.interface_id = ’S’;

sg_io.cmdp = cdb;

sg_io.mx_sb_len = sizeof(sense_buffer);

sg_io.sbp = sense_buffer;

sg_io.dxfer_direction = SG_DXFER_NONE;

sg_io.timeout = 0; //sg default time 75s

if((err = ioctl(fd,SG_IO,&sg_io)) == -1)

{

perror("SG_IO");

return err;

}

if(sg_io.host_status || DRIVER_SENSE != sg_io.driver_status

|| (sg_io.status && CONDITION_GOOD != sg_io.status))

{

printf("SG_IO: bad response/n");

errno = EBADE;

return -1;

}

if(0x72 != sense_buffer[0] || sense_buffer[7] < 14

|| 0x09 != sense_buffer[8] || sense_buffer[9] < 0x0c)

{

printf("SG_IO:bad sense buffer 0x%x 0x%x 0x%x 0x%x/n",

sense_buffer[0],sense_buffer[7],sense_buffer[8],sense_buffer[9]);

errno = EBADE;

return -1;

}

if(sense_buffer[21] & (ATA_DRQ | ATA_ERR))

{

printf("I/O error, cmd = 0x%02x status = 0x%02x error = 0x%02x/n",

tf->command, sense_buffer[21], sense_buffer[11]);

errno = EIO;

return -1;

}

return 0;

}

int ata_ioctl(int fd,u64 lba,u32 nsec)

{

unsigned char cdb[7];

int err = 0;

cdb[0] = CMD_VERIFT;

cdb[1] = 0x00;

cdb[2] = nsec;

cdb[3] = (lba >> 0) & 0xFF;

cdb[4] = (lba >> 8) & 0xFF;

cdb[5] = (lba >> 16) & 0xFF;

cdb[6] = 0x40 | ((lba >> 24) & 0xFF);

if (-1 == (err = ioctl(fd, HDIO_DRIVE_TASK, (void *)cdb))) {

perror("HDIO_DRIVE_TASK");

return -1;

}

return 0;

}

int disk_verify_sectors(const char *name,int fd, u64 start, u32 size)

{

static u64 capacity = 0;

struct ata_taskfile tf;

if(0 == capacity){

capacity = get_disk_size(name);

}

init_taskfile(&tf,start,size);

return sg_ioctl(fd,&tf);

}

int main(int argc, char *argv[])

{

u64 offset = 0;

int fd;

u64 capacity;

struct timeval t1,t2;

int size;

if (argc < 3) {

printf("Usage: ./exec devname size/n");

printf("@devname:device name/n"

"@size:per verifying sectors/n");

return 0;

}

capacity = get_disk_size(argv[1]);

printf("disk capacity = %lld/n",capacity);

size = atoi(argv[2]);

printf("verfy disk granularity %d/n",size);

if(-1 == (fd = open(argv[1],O_RDWR))){

perror("open");

return fd;

}

gettimeofday(&t1,NULL);

while(1) {

if((offset + size) > capacity){

size = offset - capacity;

capacity = 0;

}

if (disk_verify_sectors(argv[1],fd,offset, size) < 0) {

printf("%s:sectors between %Lu - %Lu error/n",

argv[1],offset, offset+size);

}

offset += size;

if(0 == capacity)

break;

}

gettimeofday(&t2,NULL);

printf("%s:verify over/n",argv[1]);

printf("kill time = %ld s/n",(t2.tv_sec - t1.tv_sec));

close(fd);

return 0;

}

今天在实验室碰到一台机器,根分区和/upgrade分区变成了read-only system.当碰到这个问题的时候,我的第一反应很可能硬件出现了故障,我使用了如下的方法来检测和排除故障:

使用dmesg检查是否有关于磁盘错误的信息,果不其然发现大量磁盘扇区错误的信息,如下: end_request:I/O error, dev 03:06 (sda), sector

从上面的输出我们判定扇区可能出现了问题,使用badblocks -s -v -o /root/badblocks.log /dev/sda 检查硬盘是否产生坏道并输出到badblocks.log中。log大约是这样的模

式:64039224 64039240 64039241 64039242 64039243 64039256 64039257 64039258 64039259 687056

可修复修复坏道修复方法:1 使用 badblocks -s -w  /dev/sda END START END代表需要修复的扇区末端,START代表需要修复的扇区起始端。2 使用fsck -a /dev/sda1

磁盘坏道分为三种:0磁道坏道,逻辑坏道,硬盘坏道。其中逻辑坏道可以使用上面的方法修复,0磁道坏道的修复方法是隔离0磁道,使用fdsk划分区的时候从1磁道开始划分区。如果是硬盘坏道的话,只能隔离不能修复。硬盘坏道的监测方法:使用上述方法检测修复后,再使用badblocks -s -v -o /root/badblocks.log /dev/sda监

测看是否还有坏道存在,如果坏道还是存在的话说明坏道属于硬盘坏道。硬盘坏道隔离方法,首先记录监测出的硬盘坏道,然后分区的时候把硬盘坏道所在的扇区分

在一个分区(大小一般大于坏扇区大小),划分出的坏道分区不使用即可达到隔离的目的。隔离只是暂时方案,建议尽快更换硬盘,因为坏道会扩散,以免以后出现

严重的数据问题。

linux硬盘坏了无法查看分区,Linux 磁盘坏道检测和修复 查看硬盘坏道代码相关推荐

  1. linux lvm 8e下继续划分分区,linux下LVM学习_逻辑卷管理

    一.LVM介绍 LVM是 Logical Volume Manager(逻辑卷管理)的简写,它是Linux环境下对磁盘分区进行管理的一种机制,通过LVM可以在不停机的情况下调整分区大小,提高了磁盘分区 ...

  2. omv检查硬盘坏道_坏道检测与修复

    本软件提供了磁盘坏道检测功能及有限的坏道修复功能.为确保检查结果的准确性,建议在WinPE环境下进行检测,并且在检测坏道期间不要对磁盘做其他操作. 1. 要使用本功能,首先选择需要检测坏道的磁盘,然后 ...

  3. 对症下药 硬盘坏道检测与修复全攻略(组图)

    所有的电脑都要使用到硬盘,我们日常使用的所有数据都存储在硬盘上.硬盘作为电脑不可缺少的重要部件之一而被大家广泛认识.而短短的几年时间里,硬盘从几十MB发展到现在的几百GB,而TB级别的硬盘也已经出现, ...

  4. 硬盘坏道检测和修复(HDDL、MHDD、THDD)图文教程

    硬盘坏道检测和修复(HDDL.MHDD.THDD)图文教程 dgisxazsc dgisxazsc 点击放大dgisxazsc dgisxazsc 还有一种情况就是用MHDD测试时开始可能全盘都没有坏 ...

  5. linux格式化该新添加的分区,Linux下添加新硬盘及分区格式化要点

    预备知识 在为主机添加硬盘前,首先要了解linux系统下对硬盘和分区的命名方法. 在Linux下对IDE的设备是以hd命名的,第一个ide设备是hda,第二个是hdb.依此类推 一般主板上有两个IDE ...

  6. linux查看分区或磁盘的block和inode的大小和软硬连接区别

    查看block大小 dumpe2fs  /dev/sda1|grep -i "block size"(block默认大小1k(boot分区)或4K(非系统分区默认为4K)) 查看I ...

  7. linux最多创建几个扩展分区,Linux分区:最多支持四个主分区、扩展分区

    简介: ①,分区方式 a)mbr分区: 最多支持四个主分区,系统只能安装在主分区中,扩展分区占用一个主分区,MBR最多支持2TB,但兼容性最好. b)gtp分区: 支持无限多个主分区(例如,但可以限制 ...

  8. Linux 磁盘坏道检测和修复

    使用dmesg检查是否有关于磁盘错误的信息  使用badblocks -s -v -o /root/badblocks.log /dev/sda 检查硬盘是否产生坏道并输出到badblocks.log ...

  9. linux坏道检测修复脚本,Linux 磁盘坏道检测和修复

    使用dmesg检查是否有关于磁盘错误的信息,果不其然发现大量磁盘扇区错误的信息,如下: end_request:I/O error, dev 03:06 (sda), sector 从上面的输出我们判 ...

  10. 硬盘坏道检测和修复(HDDL、MHDD、THDD、HDDSPEED)图文教程、下载

    硬盘出现了坏道,我们都希望能修好再用,可以省一笔银子,很多网友希望自己能够维修,免得被JS宰一刀,JS有PC3000.HRT等专业工具,似乎什么都能修,可实际下来的结果往往不是那样,可我们自己修更不理 ...

最新文章

  1. NLP.TM | GloVe模型及其Python实现
  2. tensorfllow MNIST机器学习入门
  3. SpringBoot中整合freemarker时配置文件application.properties示例代码
  4. Linux下的文件共享全攻略系列之一:Samba服务器简介与快速配置指南
  5. Linux下的Keyboard子系统
  6. mysql 记录更新 内部_MySQL 入门(1):查询和更新的内部实现
  7. 视频剪辑什么鬼?Python 带你高效创作短视频
  8. 计算机组成原理所需芯片数,计算机组成原理-微电子学院微电子试验教学中心.PPT...
  9. springboot使用netty容器_Spring Boot 2 实战:使用 Undertow 来替代Tomcat
  10. 2017年给自己定个小目标!
  11. OpenCV --- 实现两幅图像并排合并(ROI)
  12. CSS从入门到精通(CSS背景和列表)
  13. java基础-基础类型包装类型
  14. 【python】蔡勒公式计算日期
  15. 【rmzt:suika动漫美女可爱主题】
  16. AndroidVideoCache-视频边播放边缓存的代理策略
  17. 虚拟主机是干什么用的
  18. 从零开始的运维之路【标题党】
  19. 科维的时间管理法—《可以量化的管…
  20. 如何以身作则,做孩子的榜样

热门文章

  1. 数独大师级技巧_零基础入手攻克专家级数独难题实战案例
  2. python webp图片转化格式
  3. 数据版吐槽大会: 国产综艺节目年终盘点
  4. 跨数据库分布式实时事务 - 基于RabbitMQ实时消息队列服务实现
  5. 超过4g文件怎么放进u盘Linux,怎么用U盘装大于4G的系统 U盘装系统不能放超过4G镜像的解决方法...
  6. Composition
  7. 微信公众号和服务器的关系,微信公众号、订阅号、服务号之间的关系和区别
  8. Maximum Likelihood 最大似然估计
  9. Win10 Edge浏览器如何截网页长图
  10. ei拼音的四个声调对应的字_幼儿园学前班拼音教案复习ei以及四声调