[Ocfs2-tools-commits] zab commits r335 - trunk/fsck.ocfs2

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Sat Oct 16 16:34:00 CDT 2004


Author: zab
Date: 2004-10-16 16:33:57 -0500 (Sat, 16 Oct 2004)
New Revision: 335

Modified:
   trunk/fsck.ocfs2/pass1.c
Log:
o make sure symlink's null-termed data matches i_size


Modified: trunk/fsck.ocfs2/pass1.c
===================================================================
--- trunk/fsck.ocfs2/pass1.c	2004-10-16 21:33:09 UTC (rev 334)
+++ trunk/fsck.ocfs2/pass1.c	2004-10-16 21:33:57 UTC (rev 335)
@@ -109,7 +109,9 @@
 	} else if (S_ISREG(di->i_mode)) {
 		ocfs2_bitmap_set(ost->ost_reg_inodes, blkno, NULL);
 	} else if (S_ISLNK(di->i_mode)) {
-		/* make sure fast symlinks are ok, etc */
+		/* we only make sure a link's i_size matches
+		 * the link names length in the file data later when
+		 * we walk the inode's blocks */
 	} else {
 		if (!S_ISCHR(di->i_mode) && !S_ISBLK(di->i_mode) &&
 			!S_ISFIFO(di->i_mode) && !S_ISSOCK(di->i_mode))
@@ -125,10 +127,13 @@
 }
 
 struct verifying_blocks {
-       unsigned		vb_mark_dir_blocks;	
+       unsigned		vb_clear:1,
+       			vb_saw_link_null:1,
+       			vb_link_read_error:1;
+
+       uint64_t		vb_link_len;
        uint64_t		vb_num_blocks;	
        uint64_t		vb_last_block;	
-       int		vb_clear;
        int		vb_errors;
        o2fsck_state 	*vb_ost;
        ocfs2_dinode	*vb_di;
@@ -142,6 +147,102 @@
 		vb->vb_last_block = bcount;
 }
 
+static void process_link_block(struct verifying_blocks *vb, uint64_t blkno)
+{
+	char *buf, *null;
+	errcode_t ret;
+	unsigned int blocksize = vb->vb_ost->ost_fs->fs_blocksize;
+
+	if (vb->vb_saw_link_null)
+		return;
+
+	ret = ocfs2_malloc_blocks(vb->vb_ost->ost_fs->fs_io, 1, &buf);
+	if (ret)
+		fatal_error(ret, "while allocating room to read a block of "
+				 "link data");
+
+	ret = io_read_block(vb->vb_ost->ost_fs->fs_io, blkno, 1, buf);
+	if (ret) {
+		goto out;
+	}
+
+	null = memchr(buf, 0, blocksize);
+	if (null != NULL) {
+		vb->vb_link_len += null - buf;
+		vb->vb_saw_link_null = 1;
+	} else {
+		vb->vb_link_len += blocksize;
+	}
+
+out:
+	ocfs2_free(&buf);
+}
+
+/* XXX maybe this should be a helper in libocfs2? */
+static uint64_t blocks_holding_bytes(ocfs2_filesys *fs, uint64_t bytes)
+{
+	int b_bits = OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;
+
+	return (bytes +  fs->fs_blocksize - 1) >> b_bits;
+}
+
+static void check_link_data(struct verifying_blocks *vb)
+{
+	ocfs2_dinode *di = vb->vb_di;
+	o2fsck_state *ost = vb->vb_ost;
+	uint64_t expected;
+
+	verbosef("found a link: num %"PRIu64" last %"PRIu64" len "
+		"%"PRIu64" null %d error %d\n", vb->vb_num_blocks, 
+		vb->vb_last_block, vb->vb_link_len, vb->vb_saw_link_null, 
+		vb->vb_link_read_error);
+
+	if (vb->vb_link_read_error) {
+		if (prompt(ost, PY, "There was an error reading a data block "
+			   "for symlink inode %"PRIu64".  Clear the inode?",
+			   di->i_blkno)) {
+			vb->vb_clear = 1;
+			return;
+		}
+	}
+
+	/* XXX this could offer to null terminate */
+	if (!vb->vb_saw_link_null) {
+		if (prompt(ost, PY, "The target of symlink inode %"PRIu64" "
+			   "isn't null terminated.  Clear the inode?",
+			   di->i_blkno)) {
+			vb->vb_clear = 1;
+			return;
+		}
+	}
+
+	expected = blocks_holding_bytes(ost->ost_fs, vb->vb_link_len + 1);
+
+	if (di->i_size != vb->vb_link_len) {
+		if (prompt(ost, PY, "The target of symlink inode %"PRIu64" "
+			   "is %"PRIu64" bytes long on disk, but i_size is "
+			   "%"PRIu64" bytes long.  Update i_size to reflect "
+			   "the length on disk?",
+			   di->i_blkno, vb->vb_link_len, di->i_size)) {
+			di->i_size = vb->vb_link_len;
+			o2fsck_write_inode(ost->ost_fs, di->i_blkno, di);
+			return;
+		}
+	}
+
+	/* maybe we don't shrink link target allocations, I don't know,
+	 * someone will holler if this is wrong :) */
+	if (vb->vb_num_blocks != expected) {
+		if (prompt(ost, PN, "The target of symlink inode %"PRIu64" "
+			   "fits in %"PRIu64" blocks but the inode has "
+			   "%"PRIu64" allocated.  Clear the inode?", expected,
+			   di->i_blkno)) {
+			vb->vb_clear = 1;
+			return;
+		}
+	}
+}
+
 static int verify_block(ocfs2_filesys *fs,
 			    uint64_t blkno,
 			    uint64_t bcount,
@@ -181,6 +282,9 @@
 					bcount);
 	}
 
+	if (S_ISLNK(di->i_mode))
+		process_link_block(vb, blkno);
+
 	vb_saw_block(vb, bcount);
 
 	return 0;
@@ -231,11 +335,6 @@
 	vb.vb_ost = ost;
 	vb.vb_di = di;
 
-	/* XXX it isn't enough to just walk the blocks.  We want to mark
-	 * metadata blocks in the extents as used and otherwise validate them
-	 * while we're at it. */
-
-
 	if (di->i_flags & OCFS2_LOCAL_ALLOC_FL)
 		ret = 0; /* nothing to iterate over in this case */
 	else if (di->i_flags & OCFS2_CHAIN_FL)
@@ -253,6 +352,9 @@
 			         "%"PRIu64, di->i_blkno);	
 	}
 
+	if (S_ISLNK(di->i_mode))
+		check_link_data(&vb);
+
 	if (S_ISDIR(di->i_mode) && vb.vb_num_blocks == 0) {
 		if (prompt(ost, PY, "Inode %"PRIu64" is a zero length "
 			   "directory, clear it?", di->i_blkno)) {



More information about the Ocfs2-tools-commits mailing list