Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 8 Aug 2018 12:07:46 +0000 (UTC)
From:      Fedor Uporov <fsu@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r337453 - head/sys/fs/ext2fs
Message-ID:  <201808081207.w78C7kK2031172@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: fsu
Date: Wed Aug  8 12:07:45 2018
New Revision: 337453
URL: https://svnweb.freebsd.org/changeset/base/337453

Log:
  Fix directory blocks checksum updating logic.
  
  The checksum updating functions were not called in case of dir index inode splitting
  and in case of dir entry removing, when the entry was first in the block.
  Fix and move the dir entry adding logic when i_count == 0 to new function.
  
  MFC after:      3 months

Modified:
  head/sys/fs/ext2fs/ext2_htree.c
  head/sys/fs/ext2fs/ext2_lookup.c

Modified: head/sys/fs/ext2fs/ext2_htree.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_htree.c	Wed Aug  8 07:58:29 2018	(r337452)
+++ head/sys/fs/ext2fs/ext2_htree.c	Wed Aug  8 12:07:45 2018	(r337453)
@@ -800,7 +800,7 @@ ext2_htree_add_entry(struct vnode *dvp, struct ext2fs_
 		cursize = roundup(ip->i_size, blksize);
 		dirsize = cursize + blksize;
 		blknum = dirsize / blksize - 1;
-
+		ext2_dx_csum_set(ip, (struct ext2fs_direct_2 *)newidxblock);
 		error = ext2_htree_append_block(dvp, newidxblock,
 		    cnp, blksize);
 		if (error)

Modified: head/sys/fs/ext2fs/ext2_lookup.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_lookup.c	Wed Aug  8 07:58:29 2018	(r337452)
+++ head/sys/fs/ext2fs/ext2_lookup.c	Wed Aug  8 12:07:45 2018	(r337453)
@@ -859,6 +859,68 @@ ext2_dirbadentry(struct vnode *dp, struct ext2fs_direc
 }
 
 /*
+ * Insert an entry into the fresh directory block.
+ * Initialize entry tail if the metadata_csum feature is turned on.
+ */
+static int
+ext2_add_first_entry(struct vnode *dvp, struct ext2fs_direct_2 *entry,
+    struct componentname *cnp)
+{
+	struct inode *dp;
+	struct iovec aiov;
+	struct uio auio;
+	char* buf = NULL;
+	int dirblksize, error;
+
+	dp = VTOI(dvp);
+	dirblksize = dp->i_e2fs->e2fs_bsize;
+
+	if (dp->i_offset & (dirblksize - 1))
+		panic("ext2_add_first_entry: bad directory offset");
+
+	if (EXT2_HAS_RO_COMPAT_FEATURE(dp->i_e2fs,
+	    EXT2F_ROCOMPAT_METADATA_CKSUM)) {
+		entry->e2d_reclen = dirblksize - sizeof(struct ext2fs_direct_tail);
+		buf = malloc(dirblksize, M_TEMP, M_WAITOK);
+		if (!buf) {
+			error = ENOMEM;
+			goto out;
+		}
+		memcpy(buf, entry, EXT2_DIR_REC_LEN(entry->e2d_namlen));
+		ext2_init_dirent_tail(EXT2_DIRENT_TAIL(buf, dirblksize));
+		ext2_dirent_csum_set(dp, (struct ext2fs_direct_2 *)buf);
+
+		auio.uio_offset = dp->i_offset;
+		auio.uio_resid = dirblksize;
+		aiov.iov_len = auio.uio_resid;
+		aiov.iov_base = (caddr_t)buf;
+	} else {
+		entry->e2d_reclen = dirblksize;
+		auio.uio_offset = dp->i_offset;
+		auio.uio_resid = EXT2_DIR_REC_LEN(entry->e2d_namlen);
+		aiov.iov_len = auio.uio_resid;
+		aiov.iov_base = (caddr_t)entry;
+	}
+
+	auio.uio_iov = &aiov;
+	auio.uio_iovcnt = 1;
+	auio.uio_rw = UIO_WRITE;
+	auio.uio_segflg = UIO_SYSSPACE;
+	auio.uio_td = (struct thread *)0;
+	error = VOP_WRITE(dvp, &auio, IO_SYNC, cnp->cn_cred);
+	if (error)
+		goto out;
+
+	dp->i_size = roundup2(dp->i_size, dirblksize);
+	dp->i_flag |= IN_CHANGE;
+
+out:
+	free(buf, M_TEMP);
+	return (error);
+
+}
+
+/*
  * Write a directory entry after a call to namei, using the parameters
  * that it left in nameidata.  The argument ip is the inode which the new
  * directory entry will refer to.  Dvp is a pointer to the directory to
@@ -871,7 +933,6 @@ ext2_direnter(struct inode *ip, struct vnode *dvp, str
 {
 	struct inode *dp;
 	struct ext2fs_direct_2 newdir;
-	struct buf *bp;
 	int DIRBLKSIZ = ip->i_e2fs->e2fs_bsize;
 	int error;
 
@@ -911,36 +972,15 @@ ext2_direnter(struct inode *ip, struct vnode *dvp, str
 		}
 	}
 
-	if (dp->i_count == 0) {
-		/*
-		 * If dp->i_count is 0, then namei could find no
-		 * space in the directory. Here, dp->i_offset will
-		 * be on a directory block boundary and we will write the
-		 * new entry into a fresh block.
-		 */
-		if (dp->i_offset & (DIRBLKSIZ - 1))
-			panic("ext2_direnter: newblk");
+	/*
+	 * If dp->i_count is 0, then namei could find no
+	 * space in the directory. Here, dp->i_offset will
+	 * be on a directory block boundary and we will write the
+	 * new entry into a fresh block.
+	 */
+	if (dp->i_count == 0)
+		return ext2_add_first_entry(dvp, &newdir, cnp);
 
-		newdir.e2d_reclen = DIRBLKSIZ;
-
-		bp = getblk(ip->i_devvp, lblkno(dp->i_e2fs, dp->i_offset),
-		    DIRBLKSIZ, 0, 0, 0);
-		if (!bp)
-			return (EIO);
-
-		memcpy(bp->b_data, &newdir, sizeof(struct ext2fs_direct_2));
-
-		ext2_dirent_csum_set(dp, (struct ext2fs_direct_2 *)bp->b_data);
-		error = bwrite(bp);
-		if (error)
-			return (error);
-
-		dp->i_size = roundup2(dp->i_size, DIRBLKSIZ);
-		dp->i_flag |= IN_CHANGE;
-
-		return (0);
-	}
-
 	error = ext2_add_entry(dvp, &newdir);
 	if (!error && dp->i_endoff && dp->i_endoff < dp->i_size)
 		error = ext2_truncate(dvp, (off_t)dp->i_endoff, IO_SYNC,
@@ -1071,6 +1111,7 @@ ext2_dirremove(struct vnode *dvp, struct componentname
 		    &bp)) != 0)
 			return (error);
 		ep->e2d_ino = 0;
+		ext2_dirent_csum_set(dp, (struct ext2fs_direct_2 *)bp->b_data);
 		error = bwrite(bp);
 		dp->i_flag |= IN_CHANGE | IN_UPDATE;
 		return (error);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201808081207.w78C7kK2031172>