⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ext3-extents-2.6.15.patch

📁 非常经典的一个分布式系统
💻 PATCH
📖 第 1 页 / 共 5 页
字号:
+		if (ext3_ext_check_header(eh))+			goto err;+	}++	path[ppos].p_depth = i;+	path[ppos].p_hdr = eh;+	path[ppos].p_ext = NULL;+	path[ppos].p_idx = NULL;++	if (ext3_ext_check_header(eh))+		goto err;++	/* find extent */+	ext3_ext_binsearch(tree, path + ppos, block);++	ext3_ext_show_path(tree, path);++	return path;++err:+	printk(KERN_ERR "EXT3-fs: header is corrupted!\n");+	if (path) {+		ext3_ext_drop_refs(path);+		kfree(path);+	}+	return ERR_PTR(-EIO);+}++/*+ * insert new index [logical;ptr] into the block at cupr+ * it check where to insert: before curp or after curp+ */+static int ext3_ext_insert_index(handle_t *handle,+				 struct ext3_extents_tree *tree,+				 struct ext3_ext_path *curp,+				 int logical, int ptr)+{+	struct ext3_extent_idx *ix;+	int len, err;++	if ((err = ext3_ext_get_access(handle, tree, curp)))+		return err;++	EXT_ASSERT(logical != curp->p_idx->ei_block);+	len = EXT_MAX_INDEX(curp->p_hdr) - curp->p_idx;+	if (logical > curp->p_idx->ei_block) {+		/* insert after */+		if (curp->p_idx != EXT_LAST_INDEX(curp->p_hdr)) {+			len = (len - 1) * sizeof(struct ext3_extent_idx);+			len = len < 0 ? 0 : len;+			ext_debug(tree, "insert new index %d after: %d. "+				  "move %d from 0x%p to 0x%p\n",+				  logical, ptr, len,+				  (curp->p_idx + 1), (curp->p_idx + 2));+			memmove(curp->p_idx + 2, curp->p_idx + 1, len);+		}+		ix = curp->p_idx + 1;+	} else {+		/* insert before */+		len = len * sizeof(struct ext3_extent_idx);+		len = len < 0 ? 0 : len;+		ext_debug(tree, "insert new index %d before: %d. "+			  "move %d from 0x%p to 0x%p\n",+			  logical, ptr, len,+			  curp->p_idx, (curp->p_idx + 1));+		memmove(curp->p_idx + 1, curp->p_idx, len);+		ix = curp->p_idx;+	}++	ix->ei_block = logical;+	ix->ei_leaf = ptr;+	ix->ei_leaf_hi = ix->ei_unused = 0;+	curp->p_hdr->eh_entries++;++	EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max);+	EXT_ASSERT(ix <= EXT_LAST_INDEX(curp->p_hdr));++	err = ext3_ext_dirty(handle, tree, curp);+	ext3_std_error(tree->inode->i_sb, err);++	return err;+}++/*+ * routine inserts new subtree into the path, using free index entry+ * at depth 'at:+ *  - allocates all needed blocks (new leaf and all intermediate index blocks)+ *  - makes decision where to split+ *  - moves remaining extens and index entries (right to the split point)+ *    into the newly allocated blocks+ *  - initialize subtree+ */+static int ext3_ext_split(handle_t *handle, struct ext3_extents_tree *tree,+			  struct ext3_ext_path *path,+			  struct ext3_extent *newext, int at)+{+	struct buffer_head *bh = NULL;+	int depth = EXT_DEPTH(tree);+	struct ext3_extent_header *neh;+	struct ext3_extent_idx *fidx;+	struct ext3_extent *ex;+	int i = at, k, m, a;+	unsigned long newblock, oldblock, border;+	int *ablocks = NULL; /* array of allocated blocks */+	int err = 0;++	/* make decision: where to split? */+	/* FIXME: now desicion is simplest: at current extent */++	/* if current leaf will be splitted, then we should use +	 * border from split point */+	EXT_ASSERT(path[depth].p_ext <= EXT_MAX_EXTENT(path[depth].p_hdr));+	if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {+		border = path[depth].p_ext[1].ee_block;+		ext_debug(tree, "leaf will be splitted."+			  " next leaf starts at %d\n",+			  (int)border);+	} else {+		border = newext->ee_block;+		ext_debug(tree, "leaf will be added."+			  " next leaf starts at %d\n",+			  (int)border);+	}++	/* +	 * if error occurs, then we break processing+	 * and turn filesystem read-only. so, index won't+	 * be inserted and tree will be in consistent+	 * state. next mount will repair buffers too+	 */++	/*+	 * get array to track all allocated blocks+	 * we need this to handle errors and free blocks+	 * upon them+	 */+	ablocks = kmalloc(sizeof(unsigned long) * depth, GFP_NOFS);+	if (!ablocks)+		return -ENOMEM;+	memset(ablocks, 0, sizeof(unsigned long) * depth);++	/* allocate all needed blocks */+	ext_debug(tree, "allocate %d blocks for indexes/leaf\n", depth - at);+	for (a = 0; a < depth - at; a++) {+		newblock = ext3_ext_new_block(handle, tree, path, newext, &err);+		if (newblock == 0)+			goto cleanup;+		ablocks[a] = newblock;+	}++	/* initialize new leaf */+	newblock = ablocks[--a];+	EXT_ASSERT(newblock);+	bh = sb_getblk(tree->inode->i_sb, newblock);+	if (!bh) {+		err = -EIO;+		goto cleanup;+	}+	lock_buffer(bh);++	if ((err = ext3_journal_get_create_access(handle, bh)))+		goto cleanup;++	neh = EXT_BLOCK_HDR(bh);+	neh->eh_entries = 0;+	neh->eh_max = ext3_ext_space_block(tree);+	neh->eh_magic = EXT3_EXT_MAGIC;+	neh->eh_depth = 0;+	ex = EXT_FIRST_EXTENT(neh);++	/* move remain of path[depth] to the new leaf */+	EXT_ASSERT(path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max);+	/* start copy from next extent */+	/* TODO: we could do it by single memmove */+	m = 0;+	path[depth].p_ext++;+	while (path[depth].p_ext <=+			EXT_MAX_EXTENT(path[depth].p_hdr)) {+		ext_debug(tree, "move %d:%d:%d in new leaf %lu\n",+			  path[depth].p_ext->ee_block,+			  path[depth].p_ext->ee_start,+			  path[depth].p_ext->ee_len,+			  newblock);+		memmove(ex++, path[depth].p_ext++, sizeof(struct ext3_extent));+		neh->eh_entries++;+		m++;+	}+	set_buffer_uptodate(bh);+	unlock_buffer(bh);++	if ((err = ext3_journal_dirty_metadata(handle, bh)))+		goto cleanup;	+	brelse(bh);+	bh = NULL;++	/* correct old leaf */+	if (m) {+		if ((err = ext3_ext_get_access(handle, tree, path + depth)))+			goto cleanup;+		path[depth].p_hdr->eh_entries -= m;+		if ((err = ext3_ext_dirty(handle, tree, path + depth)))+			goto cleanup;+		+	}++	/* create intermediate indexes */+	k = depth - at - 1;+	EXT_ASSERT(k >= 0);+	if (k)+		ext_debug(tree,	"create %d intermediate indices\n", k);+	/* insert new index into current index block */+	/* current depth stored in i var */+	i = depth - 1;+	while (k--) {+		oldblock = newblock;+		newblock = ablocks[--a];+		bh = sb_getblk(tree->inode->i_sb, newblock);+		if (!bh) {+			err = -EIO;+			goto cleanup;+		}+		lock_buffer(bh);++		if ((err = ext3_journal_get_create_access(handle, bh)))+			goto cleanup;++		neh = EXT_BLOCK_HDR(bh);+		neh->eh_entries = 1;+		neh->eh_magic = EXT3_EXT_MAGIC;+		neh->eh_max = ext3_ext_space_block_idx(tree);+		neh->eh_depth = depth - i; +		fidx = EXT_FIRST_INDEX(neh);+		fidx->ei_block = border;+		fidx->ei_leaf = oldblock;+		fidx->ei_leaf_hi = fidx->ei_unused = 0;++		ext_debug(tree,	"int.index at %d (block %lu): %lu -> %lu\n",+			  i, newblock, border, oldblock);+		/* copy indexes */+		m = 0;+		path[i].p_idx++;++		ext_debug(tree, "cur 0x%p, last 0x%p\n", path[i].p_idx,+			  EXT_MAX_INDEX(path[i].p_hdr));+		EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) ==+			   EXT_LAST_INDEX(path[i].p_hdr));+		while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) {+			ext_debug(tree, "%d: move %d:%d in new index %lu\n",+				  i, path[i].p_idx->ei_block,+				  path[i].p_idx->ei_leaf, newblock);+			memmove(++fidx, path[i].p_idx++,+				sizeof(struct ext3_extent_idx));+			neh->eh_entries++;+			EXT_ASSERT(neh->eh_entries <= neh->eh_max);+			m++;+		}+		set_buffer_uptodate(bh);+		unlock_buffer(bh);++		if ((err = ext3_journal_dirty_metadata(handle, bh)))+			goto cleanup;+		brelse(bh);+		bh = NULL;++		/* correct old index */+		if (m) {+			err = ext3_ext_get_access(handle, tree, path + i);+			if (err)+				goto cleanup;+			path[i].p_hdr->eh_entries -= m;+			err = ext3_ext_dirty(handle, tree, path + i);+			if (err)+				goto cleanup;+		}++		i--;+	}++	/* insert new index */+	if (!err)+		err = ext3_ext_insert_index(handle, tree, path + at,+					    border, newblock);++cleanup:+	if (bh) {+		if (buffer_locked(bh))+			unlock_buffer(bh);+		brelse(bh);+	}++	if (err) {+		/* free all allocated blocks in error case */+		for (i = 0; i < depth; i++) {+			if (!ablocks[i])+				continue;+			ext3_free_blocks(handle, tree->inode, ablocks[i], 1);+		}+	}+	kfree(ablocks);++	return err;+}++/*+ * routine implements tree growing procedure:+ *  - allocates new block+ *  - moves top-level data (index block or leaf) into the new block+ *  - initialize new top-level, creating index that points to the+ *    just created block+ */+static int ext3_ext_grow_indepth(handle_t *handle,+				 struct ext3_extents_tree *tree,+				 struct ext3_ext_path *path,+				 struct ext3_extent *newext)+{+	struct ext3_ext_path *curp = path;+	struct ext3_extent_header *neh;+	struct ext3_extent_idx *fidx;+	struct buffer_head *bh;+	unsigned long newblock;+	int err = 0;++	newblock = ext3_ext_new_block(handle, tree, path, newext, &err);+	if (newblock == 0)+		return err;++	bh = sb_getblk(tree->inode->i_sb, newblock);+	if (!bh) {+		err = -EIO;+		ext3_std_error(tree->inode->i_sb, err);+		return err;+	}+	lock_buffer(bh);++	if ((err = ext3_journal_get_create_access(handle, bh))) {+		unlock_buffer(bh);+		goto out;	+	}++	/* move top-level index/leaf into new block */+	memmove(bh->b_data, curp->p_hdr, tree->buffer_len);++	/* set size of new block */+	neh = EXT_BLOCK_HDR(bh);+	/* old root could have indexes or leaves+	 * so calculate eh_max right way */+	if (EXT_DEPTH(tree))+		neh->eh_max = ext3_ext_space_block_idx(tree);+	else+		neh->eh_max = ext3_ext_space_block(tree);+	neh->eh_magic = EXT3_EXT_MAGIC;+	set_buffer_uptodate(bh);+	unlock_buffer(bh);++	if ((err = ext3_journal_dirty_metadata(handle, bh)))+		goto out;++	/* create index in new top-level index: num,max,pointer */+	if ((err = ext3_ext_get_access(handle, tree, curp)))+		goto out;++	curp->p_hdr->eh_magic = EXT3_EXT_MAGIC;+	curp->p_hdr->eh_max = ext3_ext_space_root_idx(tree);+	curp->p_hdr->eh_entries = 1;+	curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr);+	/* FIXME: it works, but actually path[0] can be index */+	curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block;+	curp->p_idx->ei_leaf = newblock;+	curp->p_idx->ei_leaf_hi = curp->p_idx->ei_unused = 0;++	neh = EXT_ROOT_HDR(tree);+	fidx = EXT_FIRST_INDEX(neh);+	ext_debug(tree, "new root: num %d(%d), lblock %d, ptr %d\n",+		  neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf); ++	neh->eh_depth = path->p_depth + 1;+	err = ext3_ext_dirty(handle, tree, curp);+out:+	brelse(bh);++	return err;+}++/*+ * routine finds empty index and adds new leaf. if no free index found+ * then it requests in-depth growing+ */+static int ext3_ext_create_new_leaf(handle_t *handle,+				    struct ext3_extents_tree *tree,+				    struct ext3_ext_path *path,+				    struct ext3_extent *newext)+{+	struct ext3_ext_path *curp;+	int depth, i, err = 0;++repeat:+	i = depth = EXT_DEPTH(tree);+	+	/* walk up to the tree and look for free index entry */+	curp = path + depth;+	while (i > 0 && !EXT_HAS_FREE_INDEX(curp)) {+		i--;+		curp--;+	}++	/* we use already allocated block for index block+	 * so, subsequent data blocks should be contigoues */+	if (EXT_HAS_FREE_INDEX(curp)) {+		/* if we found index with free entry, then use that+		 * entry: create all needed subtree and add new leaf */+		err = ext3_ext_split(handle, tree, path, newext, i);++		/* refill path */+		ext3_ext_drop_refs(path);+		path = ext3_ext_find_extent(tree, newext->ee_block, path);+		if (IS_ERR(path))+			err = PTR_ERR(path);+	} else {+		/* tree is full, time to grow in depth */+		err = ext3_ext_grow_indepth(handle, tree, path, newext);++		/* refill path */+		ext3_ext_drop_refs(path);+		path = ext3_ext_find_extent(tree, newext->ee_block, path);+		if (IS_ERR(path))+			err = PTR_ERR(path);++		/*+		 * only first (depth 0 -> 1) produces free space+		 * in all other cases we have to split growed tree+		 */+		depth = EXT_DEPTH(tree);+		if (path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max) {+			/* now we need split */+			goto repeat;+		}+	}++	if (err)+		return err;++	return 0;+}++/*+ * returns allocated block in subsequent extent or EXT_MAX_BLOCK+ * NOTE: it consider block number from index entry as+ * allocated block. thus, index entries have to be consistent+ * with leafs+ */+static unsigned long+ext3_ext_next_allocated_block(struct ext3_ext_path *path)+{+	int depth;++	EXT_ASSERT(path != NULL);+	depth = path->p_depth;++	if (depth == 0 && path->p_ext == NULL)+		return EXT_MAX_BLOCK;++	/* FIXME: what if index isn't full ?! */+	while (depth >= 0) {+		if (depth == path->p_depth) {+			/* leaf */+			if (path[depth].p_ext !=+			    EXT_LAST_EXTENT(path[depth].p_hdr))+				return path[depth].p_ext[1].ee_block;+		} else {+			/* index */+			if (path[depth].p_idx !=+			    EXT_LAST_INDEX(path[depth].p_hdr))+				return path[depth].p_idx[1].ei_block;+		}+		depth--;        +	}++	return EXT_MAX_BLOCK;+}++/*+ * returns first allocated block from next leaf or EXT_MAX_BLOCK+ */+static unsigned ext3_ext_next_leaf_block(struct ext3_extents_tree *tree,+					 struct ext3_ext_path *path)+{+	int depth;++	EXT_ASSERT(path != NULL);+	depth = path->p_depth;+

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -