socsvn commit: r237609 - soc2012/gpf/pefs_kmod/sys/fs/pefs

gpf at FreeBSD.org gpf at FreeBSD.org
Wed Jun 13 14:20:19 UTC 2012


Author: gpf
Date: Wed Jun 13 14:20:15 2012
New Revision: 237609
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=237609

Log:
  load checksum file header + the 2 hash tables to kernel land.
  The vnode used for the checksum file is a direct vnode of the lower vfs.
  We keep a reference (v_usecount) for our checksum vnode as long as the
  file system is alive. Hash tables are freed and checksumvp vrele'd during
  unmount.
  
  If error occurs during the load operation, mount still 'hangs'. Must have
  something to do with lowerrootvp.
  

Modified:
  soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs.h
  soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vfsops.c

Modified: soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs.h
==============================================================================
--- soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs.h	Wed Jun 13 11:59:47 2012	(r237608)
+++ soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs.h	Wed Jun 13 14:20:15 2012	(r237609)
@@ -120,9 +120,18 @@
 
 /* XXXgpf: fill this in */
 #define PEFS_FILE_CHECKSUM		".pefs.checksum"
+#define PEFS_CFH_SIZE 16
+#define PEFS_HT_CELL_SIZE 16
 
 struct pefs_checksum {
-	int	pcs_int;
+	uint8_t pcs_version;
+	uint8_t pcs_reserved;
+	uint8_t pcs_hash_len;
+	uint8_t pcs_hash_algo[8];
+	uint8_t pcs_offset_to_hash_table;
+	uint32_t pcs_hash_table_size;
+	char *pcs_table1, *pcs_table2;
+	struct vnode *pcs_checksumvp;
 };
 
 #define	PN_HASKEY			0x000001

Modified: soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vfsops.c
==============================================================================
--- soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vfsops.c	Wed Jun 13 11:59:47 2012	(r237608)
+++ soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vfsops.c	Wed Jun 13 14:20:15 2012	(r237609)
@@ -34,6 +34,7 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <sys/endian.h>
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/fcntl.h>
@@ -77,6 +78,7 @@
 };
 
 static MALLOC_DEFINE(M_PEFSMNT, "pefs_mount", "PEFS mount structure");
+static MALLOC_DEFINE(M_PEFSCSTABLE, "pefs_checksum_table", "PEFS checksum table");
 
 static void
 pefs_opt_set(struct mount *mp, int opt, struct pefs_mount *pm,
@@ -120,7 +122,7 @@
 	return (0);
 }
 
-/* xxxgpf: tmp 4 dbg purposes */
+/* XXXgpf: tmp 4 dbg purposes */
 static void
 pefs_dbg_vnode(struct vnode *vp, char *str)
 {
@@ -130,52 +132,178 @@
 	printf("%s writecount: %d\n", str, vp->v_writecount);
 }
 
-/*
- * XXXgpf:
- * get vp for checksum
- * read header info
- * then read index into 2 huge mallocd char*s
- * should also worry about pefs_init(), pefs_uninit(), and unmount
- */
+/* XXXgpf: tmp 4 dbg purposes */
+static void
+pefs_dbg_checksum_file(struct pefs_checksum *pcs)
+{
+	char *p;
+	int i;
+	uint32_t nhashes;
+	uint32_t offset;
+	uint64_t file_id;
+
+	/* print .pefs.checksum file header info */
+	printf("\n+++CHECKSUM FILE HEADER INFO+++\n");
+	printf("version = %x\nreserved = %d\nhash len = %d\noffset = %d\nsize = %d\nalgo = %s\n\n",
+		pcs->pcs_version, pcs->pcs_reserved, pcs->pcs_hash_len, pcs->pcs_offset_to_hash_table,
+		pcs->pcs_hash_table_size, pcs->pcs_hash_algo);
+
+	/* print table1 */
+	printf("+++HASH TABLE 1+++\n\n");
+	for (i = 0; i < pcs->pcs_hash_table_size; i++) {
+		p = &(pcs->pcs_table1[i * PEFS_HT_CELL_SIZE]);
+
+		memcpy(&nhashes, p, sizeof(nhashes));
+		nhashes = le32toh(nhashes);
+		if (nhashes != 0) {
+			p+=sizeof(nhashes);
+			memcpy(&offset, p, sizeof(offset));
+			offset = le32toh(offset);
+			p+=sizeof(offset);
+			memcpy(&file_id, p, sizeof(file_id));
+			file_id = le64toh(file_id);
+			printf("cell %d:\n", i);
+			printf("\thashes = %d\n\toffset = %d\n\tfile id = %llu\n",
+				nhashes, offset, file_id);
+		}
+		else
+			printf("cell %d: empty\n", i);
+	}
+
+	/* print table2 */
+	printf("\n+++HASH TABLE 2+++\n\n");
+	for (i = 0; i < pcs->pcs_hash_table_size; i++) {
+		p = &(pcs->pcs_table2[i * PEFS_HT_CELL_SIZE]);
+
+		memcpy(&nhashes, p, sizeof(nhashes));
+		nhashes = le32toh(nhashes);
+		if (nhashes != 0) {
+			p+=sizeof(nhashes);
+			memcpy(&offset, p, sizeof(offset));
+			offset = le32toh(offset);
+			p+=sizeof(offset);
+			memcpy(&file_id, p, sizeof(file_id));
+			file_id = le64toh(file_id);
+			printf("cell %d:\n", i);
+			printf("\thashes = %d\n\toffset = %d\n\tfile id = %llu\n",
+				nhashes, offset, file_id);
+		}
+		else
+			printf("cell %d: empty\n", i);
+	}
+}
+
 static int
 pefs_checksum_load(struct mount *mp)
 {
+	char *bufp, *path;
 	struct nameidata nd, *ndp = &nd;
-	struct pefs_mount *pm;
+	struct pefs_chunk pc;
+	struct pefs_mount *pm = VFS_TO_PEFS(mp);
+	struct pefs_checksum *pcs = &(pm->pm_checksum);
+	struct ucred *cred = mp->mnt_cred;
+	struct uio *puio;
 	struct vnode *checksumvp;
-	char path[MAXPATHLEN + 1];
+	uint32_t buflen, pathlen;
 	int error;
 
-	pm = VFS_TO_PEFS(mp);
-
-	printf("from = %s\n", mp->mnt_stat.f_mntfromname);
-	//printf("to = %s\n", mp->mnt_stat.f_mntonname);
-	snprintf(path, sizeof(path), "%s/%s", mp->mnt_stat.f_mntfromname, PEFS_FILE_CHECKSUM);
+	pcs->pcs_checksumvp = NULL;
+	pcs->pcs_table1 = NULL;
+	pcs->pcs_table2 = NULL;
+
+	pathlen = MAXPATHLEN + 1;
+	path = malloc(pathlen, M_TEMP, M_WAITOK);
+	snprintf(path, pathlen, "%s/%s", mp->mnt_stat.f_mntfromname, PEFS_FILE_CHECKSUM);
 	printf("path = %s\n", path);
 
+	/* grab a vp for our checksum file */
 	pefs_dbg_vnode(pm->pm_rootvp, "start rootvp");
-
-	NDINIT(ndp, LOOKUP, 0, UIO_SYSSPACE, path, curthread);
+	NDINIT(ndp, LOOKUP, LOCKLEAF, UIO_SYSSPACE, path, curthread);
 	error = namei(ndp);
-	
+	free(path, M_TEMP);
 	pefs_dbg_vnode(pm->pm_rootvp, "after namei rootvp");
-
 	if (error != 0) {
 		printf("pefs_checksum_load: namei error %d\n", error);
-		// tmp change
-		return (0);
+		return (error);
 	}
 
 	checksumvp = ndp->ni_vp;
-	NDFREE(ndp, NDF_NO_VP_RELE);
+	NDFREE(ndp, NDF_NO_VP_PUT);
 
-	/* XXXgpf: temporary vrele of checksumvp */
-	pefs_dbg_vnode(checksumvp, "before vrele checksumvp");
-	vrele(checksumvp);
-	pefs_dbg_vnode(checksumvp, "after vrele checksumvp");
+	/* read checksum file header info */
+	buflen = PEFS_CFH_SIZE;
+	pefs_chunk_create(&pc, NULL, buflen);
+	puio = pefs_chunk_uio(&pc, 0, UIO_READ);
 
+	error = VOP_READ(checksumvp, puio, IO_UNIT | IO_NODELOCKED, cred);
+	if (error != 0) {
+		printf("pefs_checksum_load: vop_read1 error %d\n", error);
+		pefs_chunk_free(&pc, NULL);
+		vput(checksumvp);
+		return (error);
+	}
+
+	bufp = pc.pc_base;
+	memcpy(&(pcs->pcs_version), bufp, sizeof(pcs->pcs_version));
+	bufp+=sizeof(pcs->pcs_version);
+	memcpy(&(pcs->pcs_reserved), bufp, sizeof(pcs->pcs_reserved));
+	bufp+=sizeof(pcs->pcs_reserved);
+	memcpy(&(pcs->pcs_hash_len), bufp, sizeof(pcs->pcs_hash_len));
+	bufp+=sizeof(pcs->pcs_hash_len);
+	memcpy(&(pcs->pcs_hash_algo), bufp, sizeof(pcs->pcs_hash_algo));
+	bufp+=sizeof(pcs->pcs_hash_algo);
+	memcpy(&(pcs->pcs_offset_to_hash_table), bufp, sizeof(pcs->pcs_offset_to_hash_table));
+	bufp+=sizeof(pcs->pcs_offset_to_hash_table);
+	memcpy(&(pcs->pcs_hash_table_size), bufp, sizeof(pcs->pcs_hash_table_size));
+	pcs->pcs_hash_table_size = le32toh(pcs->pcs_hash_table_size);
+
+	/* XXXgpf: [TODO] sanitize input, turn hash_algo to number */
+
+	pefs_chunk_free(&pc, NULL);
+
+	/* load and keep the 2 hash tables in kernel heap */
+	buflen = pcs->pcs_hash_table_size * PEFS_HT_CELL_SIZE;
+	pefs_chunk_create(&pc, NULL, buflen);
+	puio = pefs_chunk_uio(&pc, pcs->pcs_offset_to_hash_table, UIO_READ);
+
+	error = VOP_READ(checksumvp, puio, IO_UNIT | IO_NODELOCKED, cred);
+	if (error != 0) {
+		printf("pefs_checksum_load: vop_read2 error %d\n", error);
+		pefs_chunk_free(&pc, NULL);
+		vput(checksumvp);
+		return (error);
+	}
+
+	pcs->pcs_table1 = malloc(buflen, M_PEFSCSTABLE, M_WAITOK);
+	memcpy(pcs->pcs_table1, pc.pc_base, buflen);
+	pefs_chunk_free(&pc, NULL);
+
+	pefs_chunk_create(&pc, NULL, buflen);
+	puio = pefs_chunk_uio(&pc, pcs->pcs_offset_to_hash_table + buflen, UIO_READ);
+
+	error = VOP_READ(checksumvp, puio, IO_UNIT | IO_NODELOCKED, cred);
+	if (error != 0) {
+		printf("pefs_checksum_load: vop_read3 error %d\n", error);
+		pefs_chunk_free(&pc, NULL);
+		free(pcs->pcs_table1, M_PEFSCSTABLE);
+		vput(checksumvp);
+		return (error);
+	}
+
+	pcs->pcs_table2 = malloc(buflen, M_PEFSCSTABLE, M_WAITOK);
+	memcpy(pcs->pcs_table2, pc.pc_base, buflen);
+	pefs_chunk_free(&pc, NULL);
+
+	/* print everything */
+	pefs_dbg_checksum_file(pcs);
+
+	pefs_dbg_vnode(checksumvp, "before VOP_UNLOCK checksumvp");
+	/* keep the reference for checksumvp */
+	VOP_UNLOCK(checksumvp, 0);
+	pefs_dbg_vnode(checksumvp, "after VOP_UNLOCK checksumvp");
 	pefs_dbg_vnode(pm->pm_rootvp, "end rootvp");
-	
+	pcs->pcs_checksumvp = checksumvp;
+
 	return (0);
 }
 
@@ -373,11 +501,19 @@
 	vfs_getnewfsid(mp);
 
 	if ((pm->pm_flags & PM_CHECKSUM) != 0) {
-		pefs_dbg_vnode(lowerrootvp, "BEFORE lowerootvp");
+		pefs_dbg_vnode(lowerrootvp, "BEFORE lowerrootvp");
 		error = pefs_checksum_load(mp);
-		pefs_dbg_vnode(lowerrootvp, "AFTER lowerootvp");
+		pefs_dbg_vnode(lowerrootvp, "AFTER lowerrootvp");
 		if (error != 0) {
-			/* XXXgpf: what should be done for lowerrootvp? vput? */
+			/*
+			 * XXXgpf: what should be done for lowerrootvp? vput?
+			 * pefs_dbg_vnode shows that at this point lowerootvp
+			 * is not locked, therefore just a vrele?
+			 * Whatever we do, if error occurs during pefs_checksum_load,
+			 * mount seems to 'hang'
+			 */
+			vrele(lowerrootvp);
+			pefs_dbg_vnode(lowerrootvp, "AFTER vrele lowerrootvp");
 			free(pm, M_PEFSMNT);
 			return (error);
 		}
@@ -412,6 +548,16 @@
 	 * Finally, throw away the pefs_mount structure
 	 */
 	pm = VFS_TO_PEFS(mp);
+	if ((pm->pm_flags & PM_CHECKSUM) != 0) {
+		/* free the hash tables from the heap */
+		if (pm->pm_checksum.pcs_table1 != NULL)
+			free(pm->pm_checksum.pcs_table1, M_PEFSCSTABLE);
+		if (pm->pm_checksum.pcs_table2 != NULL)
+			free(pm->pm_checksum.pcs_table2, M_PEFSCSTABLE);
+		/* vrele the checksum file's vnode */
+		if	(pm->pm_checksum.pcs_checksumvp != NULL)
+			vrele(pm->pm_checksum.pcs_checksumvp);
+	}
 	mp->mnt_data = 0;
 	pefs_key_remove_all(pm);
 	mtx_destroy(&pm->pm_keys_lock);


More information about the svn-soc-all mailing list