Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:12.3
ocfs2-tools
0002-Break-a-chain-loop-in-group-desc.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0002-Break-a-chain-loop-in-group-desc.patch of Package ocfs2-tools
From 16f191550058a768935cab2fe575c48e64eba334 Mon Sep 17 00:00:00 2001 From: Goldwyn Rodrigues <rgoldwyn@suse.de> Date: Thu, 20 Sep 2012 20:12:14 -0500 Subject: [PATCH 2/2] Break a chain loop in group desc This patch detects and a loop by checking hops against the theoretical limit of number of chains in a chain_rec. If a loop is found, it breaks it by storing the block numbers and comparing with exiting block numbers. --- fsck.ocfs2/fsck.ocfs2.checks.8.in | 9 ++++++ fsck.ocfs2/pass0.c | 61 ++++++++++++++++++++++++++++++++++--- include/ocfs2-kernel/ocfs2_fs.h | 2 +- 3 files changed, 67 insertions(+), 5 deletions(-) Index: ocfs2-tools/fsck.ocfs2/fsck.ocfs2.checks.8.in =================================================================== --- ocfs2-tools.orig/fsck.ocfs2/fsck.ocfs2.checks.8.in 2012-09-25 11:12:57.000000000 -0500 +++ ocfs2-tools/fsck.ocfs2/fsck.ocfs2.checks.8.in 2012-09-25 11:13:03.000000000 -0500 @@ -202,6 +202,15 @@ valid in its bitmap. Answering yes decreases the number of recorded free bits so that it equals the total number of bits in the group descriptor's bitmap. +.SS "GROUP_CHAIN_LOOP" +A chain may loop if the next field of the group descriptor points to one of +the previous group descriptors in the chain. This causes the ocfs2 code, both +user space and kernel module to loop forever. + +Answering yes breaks the loop at an optimum location so that all the existing +group descriptors are in the chain. However, it cannot re-connect stray group +descriptors and must rely on the rest of the fsck code to fix it. + .SS "CHAIN_COUNT" The chain list embedded in an inode is limited by the block size and the number of bytes consumed by the rest of the inode. A chain list header was Index: ocfs2-tools/fsck.ocfs2/pass0.c =================================================================== --- ocfs2-tools.orig/fsck.ocfs2/pass0.c 2012-09-25 11:12:57.000000000 -0500 +++ ocfs2-tools/fsck.ocfs2/pass0.c 2012-09-25 11:13:03.000000000 -0500 @@ -666,6 +666,46 @@ out: return ret; } +static errcode_t break_loop(o2fsck_state *ost, struct ocfs2_chain_rec *chain, + unsigned int max_depth) +{ + uint64_t *list; + int i; + unsigned int depth = 0; + uint64_t blkno = chain->c_blkno; + char *buf; + struct ocfs2_group_desc *gd; + errcode_t ret = ocfs2_malloc0(sizeof(uint64_t) * max_depth, &list); + if (ret) + goto out; + ret = ocfs2_malloc_block(ost->ost_fs->fs_io, &buf); + if (ret) + goto out; + gd = (struct ocfs2_group_desc *)buf; + + while (blkno && (depth<=max_depth)) { + list[depth++] = blkno; + ret = ocfs2_read_group_desc(ost->ost_fs, blkno, buf); + if (ret) + goto out; + blkno = gd->bg_next_group; + for (i=0; i<depth; i++) + if (list[i]==blkno) { + gd->bg_next_group = 0; + verbosef("Breaking gd loop %"PRIu64"\n", blkno); + ret = ocfs2_write_group_desc(ost->ost_fs, + blkno, buf); + goto out; + } + } +out: + if (list) + ocfs2_free(&list); + if (buf) + ocfs2_free(&buf); + return ret; +} + /* this takes a slightly ridiculous number of arguments :/ */ static errcode_t check_chain(o2fsck_state *ost, struct ocfs2_dinode *di, @@ -675,7 +715,8 @@ static errcode_t check_chain(o2fsck_stat char *buf2, int *chain_changed, ocfs2_bitmap *allowed, - ocfs2_bitmap *forbidden) + ocfs2_bitmap *forbidden, + unsigned int max_depth) { struct ocfs2_group_desc *bg1 = (struct ocfs2_group_desc *)buf1; struct ocfs2_group_desc *bg2 = (struct ocfs2_group_desc *)buf2; @@ -792,6 +833,14 @@ static errcode_t check_chain(o2fsck_stat /* the loop will now start by reading bg1->next_group */ memcpy(buf1, buf2, ost->ost_fs->fs_blocksize); depth++; + if (depth > max_depth) { + if (prompt(ost, PY, PR_GROUP_CHAIN_LOOP, + "Loop detected in chain %d at block %"PRIu64 + ". Break the loop?",cs->cs_chain_no, + (uint64_t) chain->c_blkno)) + ret = break_loop(ost, chain, max_depth); + break; + } } /* we hit the premature end of a chain.. clear the last @@ -854,6 +903,7 @@ static errcode_t verify_chain_alloc(o2fs int changed = 0, trust_next_free = 1; errcode_t ret = 0; uint64_t chain_bytes; + unsigned int num_gds, max_chain_len; if (memcmp(di->i_signature, OCFS2_INODE_SIGNATURE, strlen(OCFS2_INODE_SIGNATURE))) { @@ -883,9 +933,12 @@ static errcode_t verify_chain_alloc(o2fs /* XXX should we check suballoc_node? */ cl = &di->id2.i_chain; + num_gds = (di->i_clusters + cl->cl_cpg)/cl->cl_cpg; + max_chain_len = (num_gds + cl->cl_count)/cl->cl_count; - verbosef("cl cpg %u bpc %u count %u next %u\n", - cl->cl_cpg, cl->cl_bpc, cl->cl_count, cl->cl_next_free_rec); + verbosef("cl cpg %u bpc %u count %u next %u gds %u max_ch_len %u\n", + cl->cl_cpg, cl->cl_bpc, cl->cl_count, cl->cl_next_free_rec, + num_gds, max_chain_len); max_count = ocfs2_chain_recs_per_inode(ost->ost_fs->fs_blocksize); @@ -948,7 +1001,7 @@ static errcode_t verify_chain_alloc(o2fs .cs_cpg = cl->cl_cpg, }; ret = check_chain(ost, di, &cs, cr, buf1, buf2, &changed, - allowed, forbidden); + allowed, forbidden, max_chain_len); /* XXX what? not checking ret? */ if (cr->c_blkno != 0) { Index: ocfs2-tools/include/ocfs2-kernel/ocfs2_fs.h =================================================================== --- ocfs2-tools.orig/include/ocfs2-kernel/ocfs2_fs.h 2012-09-25 11:12:57.000000000 -0500 +++ ocfs2-tools/include/ocfs2-kernel/ocfs2_fs.h 2012-09-25 11:13:03.000000000 -0500 @@ -1685,7 +1685,7 @@ static inline int ocfs2_sprintf_system_i } static inline void ocfs2_set_de_type(struct ocfs2_dir_entry *de, - umode_t mode) + unsigned short mode) { de->file_type = ocfs2_type_by_mode[(mode & S_IFMT)>>S_SHIFT]; }
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