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