PERFORCE change 165463 for review

Gleb Kurtsou gk at FreeBSD.org
Tue Jun 30 10:52:34 UTC 2009


http://perforce.freebsd.org/chv.cgi?CH=165463

Change 165463 by gk at gk_h1 on 2009/06/30 10:52:23

	Store tweak and checksum in encrypted file name. Update lookup routines to perform readdir to do real lookup
	Do not use pefs_bypass as vnode bypass operation
	Add vop_mknode
	Use cached lookup

Affected files ...

.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs.h#4 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_crypto.c#1 add
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_subr.c#4 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vfsops.c#3 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vnops.c#4 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_xbase64.c#3 edit
.. //depot/projects/soc2009/gk_pefs/sys/modules/pefs/Makefile#4 edit

Differences ...

==== //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs.h#4 (text+ko) ====

@@ -37,62 +37,115 @@
  * $FreeBSD$
  */
 
+#include <sys/queue.h>
 #include <sys/uio.h>
 
-struct pefs_mount {
-	struct mount	*pm_vfs;
-	struct vnode	*pm_rootvp;	/* Reference to root pefs_node */
+#ifdef _KERNEL
+
+#define PEFS_BLOCK			16
+#define PEFS_TWEAK_SIZE			16
+#define PEFS_KEY_SIZE			64
+#define PEFS_NAME_CSUM_SIZE		2
+
+#define PEFS_NAME_NTOP_SIZE(a)		(((a) * 4 + 2)/3)
+#define PEFS_NAME_PTON_SIZE(a)		(((a) * 3)/4)
+
+SLIST_HEAD(pefs_key_head, pefs_key);
+
+struct pefs_key {
+	SLIST_ENTRY(pefs_key) pk_entry;
+	volatile u_int pk_refcnt;
+	char pk_name[PEFS_KEY_SIZE];
+	char pk_data[PEFS_KEY_SIZE];
 };
 
-#ifdef _KERNEL
+struct pefs_node_key {
+	struct pefs_key *pnk_key;
+	char pnk_tweak[PEFS_TWEAK_SIZE];
+};
 
-#define PEFS_BLOCK		16
+struct pefs_node {
+	LIST_ENTRY(pefs_node) pn_hash;	/* Hash list */
+	struct vnode *pn_lowervp;	/* VREFed once */
+	struct vnode *pn_vnode;		/* Back pointer */
+	struct pefs_node_key pn_key;
+};
 
-/*
- * A cache of vnode references
- */
-struct pefs_node {
-	LIST_ENTRY(pefs_node)	pn_hash;	/* Hash list */
-	struct vnode	        *pn_lowervp;	/* VREFed once */
-	struct vnode		*pn_vnode;	/* Back pointer */
+struct pefs_mount {
+	struct mount *pm_vfs;
+	struct vnode *pm_rootvp;	/* Reference to root pefs_node */
+	struct pefs_key_head pm_keys;
 };
 
 struct pefs_chunk {
 	int pc_iovcnt;
 	int pc_basescnt;
 	struct iovec *pc_iov;
-	int pc_size;
+	size_t pc_size;
+	size_t pc_capacity;
 	void **pc_bases;
 	struct uio pc_uio;
 };
 
-typedef void (*pefs_tr)(void *mem, size_t size, void *arg);
+static inline struct pefs_mount*
+VFS_TO_PEFS(struct mount *mp)
+{
+	MPASS(mp != NULL && mp->mnt_data != NULL);
+	return ((struct pefs_mount *)(mp->mnt_data));
+}
+
+static inline struct pefs_node*
+VP_TO_PN(struct vnode *vp)
+{
+	MPASS(vp != NULL && vp->v_data != NULL);
+	return ((struct pefs_node *)vp->v_data);
+}
+
+static inline struct vnode*
+PN_TO_VP(struct pefs_node *pn)
+{
+	MPASS(pn != NULL && pn->pn_vnode != NULL);
+	return (pn->pn_vnode);
+}
+
+#ifdef DIAGNOSTIC
+struct vnode *pefs_checkvp(struct vnode *vp, char *fil, int lno);
+#endif
+
+static inline struct vnode*
+PEFS_LOWERVP(struct vnode *vp)
+{
+	struct vnode *lvp;
 
-#define	MOUNTTOPEMOUNT(mp) ((struct pefs_mount *)((mp)->mnt_data))
-#define	VTOPE(vp) ((struct pefs_node *)(vp)->v_data)
-#define	PETOV(xp) ((xp)->pn_vnode)
+	MPASS(vp != NULL);
+#ifdef DIAGNOSTIC
+	pefs_checkvp((vp), __FILE__, __LINE__);
+#endif
+	lvp = VP_TO_PN(vp)->pn_lowervp;
+	MPASS(lvp != NULL);
+	return (lvp);
+}
 
 struct vfsconf;
 struct vop_generic_args;
 
 int pefs_init(struct vfsconf *vfsp);
 int pefs_uninit(struct vfsconf *vfsp);
-int pefs_nodeget(struct mount *mp, struct vnode *target, struct vnode **vpp);
-void pefs_hashrem(struct pefs_node *xp);
-int pefs_bypass(struct vop_generic_args *ap);
-int pefs_name_encrypt(const char *plain, size_t plain_len, char *enc, size_t enc_size);
-int pefs_name_decrypt(const char *enc, size_t enc_len, char *plain, size_t plain_size);
+int pefs_node_get(struct mount *mp, struct vnode *target, struct vnode **vpp);
+void pefs_node_free(struct pefs_node *xp);
 
-void pefs_xor(void *mem, size_t size);
+void pefs_data_encrypt(struct pefs_node *pn, off_t offset, struct pefs_chunk *pc);
+void pefs_data_encrypt_buf(struct pefs_node *pn, off_t offset, void *mem, size_t size);
+void pefs_data_decrypt(struct pefs_node *pn, off_t offset, struct pefs_chunk *pc);
+void pefs_data_decrypt_buf(struct pefs_node *pn, off_t offset, void *mem, size_t size);
 
-#define PEFS_NAME_NTOP_SIZE(a)		(((a) * 4 + 2)/3)
-#define PEFS_NAME_PTON_SIZE(a)		(((a) * 3)/4)
+int pefs_name_encrypt(struct pefs_node_key *pnk, const char *plain, size_t plain_len, char *enc, size_t enc_size);
+int pefs_name_decrypt(struct pefs_node_key *pnk, const char *enc, size_t enc_len, char *plain, size_t plain_size);
 int pefs_name_ntop(u_char const *src, size_t srclength, char *target, size_t targsize);
 int pefs_name_pton(char const *src, size_t srclen, u_char *target, size_t targsize);
 
-void pefs_xor_chunk(struct pefs_chunk *pc);
-
 struct pefs_chunk* pefs_chunk_create(size_t size);
+void pefs_chunk_restore(struct pefs_chunk* pc);
 void pefs_chunk_free(struct pefs_chunk* pc);
 struct uio* pefs_chunk_uio(struct pefs_chunk *pc, off_t uio_offset, enum uio_rw uio_rw);
 struct uio* pefs_chunk_uio_range(struct pefs_chunk *pc, size_t skip, size_t size, off_t uio_offset, enum uio_rw uio_rw);
@@ -102,17 +155,9 @@
 void pefs_chunk_crop(struct pefs_chunk *pc, size_t skip_begin, size_t skip_end);
 void pefs_chunk_shrink(struct pefs_chunk *pc, size_t size);
 
-#ifdef DIAGNOSTIC
-struct vnode *pefs_checkvp(struct vnode *vp, char *fil, int lno);
-#define	PEVPTOLOWERVP(vp) pefs_checkvp((vp), __FILE__, __LINE__)
-#else
-#define	PEVPTOLOWERVP(vp) (VTOPE(vp)->pn_lowervp)
-#endif
-
 extern struct vop_vector pefs_vnodeops;
 
 #ifdef MALLOC_DECLARE
-MALLOC_DECLARE(M_PEFSNODE);
 MALLOC_DECLARE(M_PEFSBUF);
 #endif
 

==== //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_subr.c#4 (text+ko) ====

@@ -69,7 +69,7 @@
 struct mtx pefs_hashmtx;
 
 static MALLOC_DEFINE(M_PEFSHASH, "pefs_hash", "PEFS hash table");
-MALLOC_DEFINE(M_PEFSNODE, "pefs_node", "PEFS vnode private part");
+static MALLOC_DEFINE(M_PEFSNODE, "pefs_node", "PEFS vnode private part");
 MALLOC_DEFINE(M_PEFSBUF, "pefs_buf", "PEFS buffers");
 
 /*
@@ -117,14 +117,14 @@
 	hd = PEFS_NHASH(lowervp);
 	mtx_lock(&pefs_hashmtx);
 	LIST_FOREACH(a, hd, pn_hash) {
-		if (a->pn_lowervp == lowervp && PETOV(a)->v_mount == mp) {
+		if (a->pn_lowervp == lowervp && PN_TO_VP(a)->v_mount == mp) {
 			/*
 			 * Since we have the lower node locked the pefs
 			 * node can not be in the process of recycling.  If
 			 * it had been recycled before we grabed the lower
 			 * lock it would not have been found on the hash.
 			 */
-			vp = PETOV(a);
+			vp = PN_TO_VP(a);
 			vref(vp);
 			mtx_unlock(&pefs_hashmtx);
 			return (vp);
@@ -149,12 +149,12 @@
 	mtx_lock(&pefs_hashmtx);
 	LIST_FOREACH(oxp, hd, pn_hash) {
 		if (oxp->pn_lowervp == xp->pn_lowervp &&
-		    PETOV(oxp)->v_mount == mp) {
+		    PN_TO_VP(oxp)->v_mount == mp) {
 			/*
 			 * See pefs_hashget for a description of this
 			 * operation.
 			 */
-			ovp = PETOV(oxp);
+			ovp = PN_TO_VP(oxp);
 			vref(ovp);
 			mtx_unlock(&pefs_hashmtx);
 			return (ovp);
@@ -186,7 +186,7 @@
  * the caller's "spare" reference to created pefs vnode.
  */
 int
-pefs_nodeget(struct mount *mp, struct vnode *lowervp, struct vnode **vpp)
+pefs_node_get(struct mount *mp, struct vnode *lowervp, struct vnode **vpp)
 {
 	struct pefs_node *xp;
 	struct vnode *vp;
@@ -213,7 +213,7 @@
 	 * elsewhere if MALLOC should block.
 	 */
 	xp = malloc(sizeof(struct pefs_node),
-	    M_PEFSNODE, M_WAITOK);
+	    M_PEFSNODE, M_WAITOK | M_ZERO);
 
 	error = getnewvnode("pefs", mp, &pefs_vnodeops, &vp);
 	if (error) {
@@ -227,7 +227,7 @@
 	vp->v_data = xp;
 	vp->v_vnlock = lowervp->v_vnlock;
 	if (vp->v_vnlock == NULL)
-		panic("pefs_nodeget: Passed a NULL vnlock.\n");
+		panic("pefs_node_get: Passed a NULL vnlock.\n");
 	error = insmntque1(vp, mp, pefs_insmntque_dtr, xp);
 	if (error != 0)
 		return (error);
@@ -249,82 +249,18 @@
 }
 
 /*
- * Remove node from hash.
+ * Remove node from hash and free it.
  */
 void
-pefs_hashrem(struct pefs_node *xp)
+pefs_node_free(struct pefs_node *xp)
 {
 
 	mtx_lock(&pefs_hashmtx);
 	LIST_REMOVE(xp, pn_hash);
 	mtx_unlock(&pefs_hashmtx);
+	free(xp, M_PEFSNODE);
 }
 
-void
-pefs_xor(void *mem, size_t size)
-{
-	char *b = (char *)mem;
-	char *e = b + size;
-
-	for (; b < e; b++) {
-		*b ^= 0xAA;
-	}
-}
-
-void
-pefs_xor_chunk(struct pefs_chunk *pc)
-{
-	long arg = 0;
-	char *mem;
-	size_t size;
-
-	while (1) {
-		mem = pefs_chunk_get(pc, &size, &arg);
-		if (mem == NULL)
-			break;
-		pefs_xor(mem, size);
-	}
-}
-
-int
-pefs_name_encrypt(const char *plain, size_t plain_len, char *enc, size_t enc_size)
-{
-	char b_static[64];
-	char *b;
-	int r;
-
-	if (plain_len <= sizeof(b_static))
-		b = b_static;
-	else
-		b = malloc(plain_len, M_PEFSBUF, M_WAITOK);
-	memcpy(b, plain, plain_len);
-	// FIXME
-	for (int i = 0; i < plain_len; i++)
-		b[i] ^= 0xAA;
-	r = pefs_name_ntop(b, plain_len, enc, enc_size);
-	// printf("pefs_name_encrypt: %d; %.*s => %.*s\n", r, plain_len, plain, r, enc);
-	if (b != b_static)
-		free(b, M_PEFSBUF);
-	return r;
-}
-
-int
-pefs_name_decrypt(const char *enc, size_t enc_len, char *plain, size_t plain_size)
-{
-	int r;
-
-	r = pefs_name_pton(enc, enc_len, plain, plain_size);
-	if (r > 0) {
-		// FIXME
-		for (int i = 0; i < r; i++)
-			plain[i] ^= 0xAA;
-	}
-	if (r < plain_size)
-		plain[r] = '\0';
-	// printf("pefs_name_decrypt: %d; %.*s => %.*s\n", r, enc_len, enc, r < 0 ? 0 : r, plain);
-	return r;
-}
-
 struct pefs_chunk*
 pefs_chunk_create(size_t size)
 {
@@ -357,6 +293,21 @@
 }
 
 void
+pefs_chunk_restore(struct pefs_chunk* pc)
+{
+	size_t size = pc->pc_capacity;
+	pc->pc_iov = (struct iovec *)(pc->pc_bases + pc->pc_basescnt);
+	pc->pc_iovcnt = pc->pc_basescnt;
+
+	for (int i = 0; i < pc->pc_iovcnt && size > 0; i++) {
+		int len = imin(PAGE_SIZE, size);
+		pc->pc_iov[i].iov_len = len;
+		pc->pc_iov[i].iov_base = pc->pc_bases[i];
+		size -= len;
+	}
+}
+
+void
 pefs_chunk_free(struct pefs_chunk* pc)
 {
 	for (int i = 0; i < pc->pc_basescnt; i++) {
@@ -518,7 +469,7 @@
 pefs_checkvp(struct vnode *vp, char *fil, int lno)
 {
 	int interlock = 0;
-	struct pefs_node *a = VTOPE(vp);
+	struct pefs_node *a = VP_TO_PN(vp);
 #ifdef notyet
 	/*
 	 * Can't do this check because vop_reclaim runs
@@ -559,7 +510,7 @@
 		VI_LOCK(vp);
 #ifdef notyet
 	printf("null %x/%d -> %x/%d [%s, %d]\n",
-	        PETOV(a), vrefcnt(PETOV(a)),
+	        PN_TO_VP(a), vrefcnt(PN_TO_VP(a)),
 		a->pn_lowervp, vrefcnt(a->pn_lowervp),
 		fil, lno);
 #endif

==== //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vfsops.c#3 (text+ko) ====

@@ -123,7 +123,7 @@
 	/*
 	 * Check multi null mount to avoid `lock against myself' panic.
 	 */
-	if (lowerrootvp == VTOPE(mp->mnt_vnodecovered)->pn_lowervp) {
+	if (lowerrootvp == VP_TO_PN(mp->mnt_vnodecovered)->pn_lowervp) {
 		PEFSDEBUG("pefs_mount: multi null mount?\n");
 		vput(lowerrootvp);
 		return (EDEADLK);
@@ -141,7 +141,7 @@
 	 * Save reference.  Each mount also holds
 	 * a reference on the root vnode.
 	 */
-	error = pefs_nodeget(mp, lowerrootvp, &vp);
+	error = pefs_node_get(mp, lowerrootvp, &vp);
 	/*
 	 * Make sure the node alias worked
 	 */
@@ -165,7 +165,7 @@
 	 */
 	VOP_UNLOCK(vp, 0);
 
-	if (PEVPTOLOWERVP(pm_rootvp)->v_mount->mnt_flag & MNT_LOCAL) {
+	if (PEFS_LOWERVP(pm_rootvp)->v_mount->mnt_flag & MNT_LOCAL) {
 		MNT_ILOCK(mp);
 		mp->mnt_flag |= MNT_LOCAL;
 		MNT_IUNLOCK(mp);
@@ -218,13 +218,13 @@
 	struct vnode *vp;
 
 	PEFSDEBUG("pefs_root(mp = %p, vp = %p->%p)\n", (void *)mp,
-	    (void *)MOUNTTOPEMOUNT(mp)->pm_rootvp,
-	    (void *)PEVPTOLOWERVP(MOUNTTOPEMOUNT(mp)->pm_rootvp));
+	    (void *)VFS_TO_PEFS(mp)->pm_rootvp,
+	    (void *)PEFS_LOWERVP(VFS_TO_PEFS(mp)->pm_rootvp));
 
 	/*
 	 * Return locked reference to root.
 	 */
-	vp = MOUNTTOPEMOUNT(mp)->pm_rootvp;
+	vp = VFS_TO_PEFS(mp)->pm_rootvp;
 	VREF(vp);
 
 #ifdef PEFSXXX_DEBUG
@@ -239,7 +239,7 @@
 static int
 pefs_quotactl(struct mount *mp, int cmd, uid_t uid, void *arg)
 {
-	return VFS_QUOTACTL(MOUNTTOPEMOUNT(mp)->pm_vfs, cmd, uid, arg);
+	return VFS_QUOTACTL(VFS_TO_PEFS(mp)->pm_vfs, cmd, uid, arg);
 }
 
 static int
@@ -249,12 +249,12 @@
 	struct statfs mstat;
 
 	PEFSDEBUG("pefs_statfs(mp = %p, vp = %p->%p)\n", (void *)mp,
-	    (void *)MOUNTTOPEMOUNT(mp)->pm_rootvp,
-	    (void *)PEVPTOLOWERVP(MOUNTTOPEMOUNT(mp)->pm_rootvp));
+	    (void *)VFS_TO_PEFS(mp)->pm_rootvp,
+	    (void *)PEFS_LOWERVP(VFS_TO_PEFS(mp)->pm_rootvp));
 
 	bzero(&mstat, sizeof(mstat));
 
-	error = VFS_STATFS(MOUNTTOPEMOUNT(mp)->pm_vfs, &mstat);
+	error = VFS_STATFS(VFS_TO_PEFS(mp)->pm_vfs, &mstat);
 	if (error)
 		return (error);
 
@@ -284,11 +284,11 @@
 pefs_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
 {
 	int error;
-	error = VFS_VGET(MOUNTTOPEMOUNT(mp)->pm_vfs, ino, flags, vpp);
+	error = VFS_VGET(VFS_TO_PEFS(mp)->pm_vfs, ino, flags, vpp);
 	if (error)
 		return (error);
 
-	return (pefs_nodeget(mp, *vpp, vpp));
+	return (pefs_node_get(mp, *vpp, vpp));
 }
 
 static int
@@ -296,11 +296,11 @@
 {
 	int error;
 
-	error = VFS_FHTOVP(MOUNTTOPEMOUNT(mp)->pm_vfs, fidp, vpp);
+	error = VFS_FHTOVP(VFS_TO_PEFS(mp)->pm_vfs, fidp, vpp);
 	if (error)
 		return (error);
 
-	error = pefs_nodeget(mp, *vpp, vpp);
+	error = pefs_node_get(mp, *vpp, vpp);
 	printf("pefs_fhtovp: error=%d; vp=%p; v_object=%p\n", error,
 			!error ? *vpp : NULL, !error ? (*vpp)->v_object : NULL);
 	if (error)
@@ -312,7 +312,7 @@
 static int
 pefs_extattrctl(struct mount *mp, int cmd, struct vnode *filename_vp, int namespace, const char *attrname)
 {
-	return VFS_EXTATTRCTL(MOUNTTOPEMOUNT(mp)->pm_vfs, cmd, filename_vp,
+	return VFS_EXTATTRCTL(VFS_TO_PEFS(mp)->pm_vfs, cmd, filename_vp,
 	    namespace, attrname);
 }
 

==== //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vnops.c#4 (text+ko) ====

@@ -68,45 +68,77 @@
 const static struct {
 	size_t namelen;
 	const char *name;
-} _pefs_name_shadow_list[] = {
-	{ 1, "." },
-	{ 2, ".." },
+} _pefs_name_skip_list[] = {
 	{ 4, ".zfs" },
 	{ 5, ".snap" },
 	{ 10, "lost+found" },
 	{ 0, NULL },
 };
 
-static int
-pefs_name_shadow(char *name, int namelen, /*OPTIONAL*/ struct componentname *cnp)
+struct pefs_enccn {
+	struct componentname pec_cn;
+	void *pec_buf;
+};
+
+static inline int
+pefs_name_skip(char *name, int namelen)
 {
-	if (cnp != NULL && cnp->cn_flags & ISDOTDOT)
-		return (0);
-	for (int i = 0; _pefs_name_shadow_list[i].namelen && _pefs_name_shadow_list[i].namelen <= namelen; i++) {
-		if (namelen == _pefs_name_shadow_list[i].namelen &&
-				memcmp(_pefs_name_shadow_list[i].name, name, namelen) == 0)
-			return (0);
+	if (name[0] == '.' && (namelen == 1 || (namelen == 2 && name[1] == '.')))
+		return (1);
+	for (int i = 0; _pefs_name_skip_list[i].namelen &&
+			_pefs_name_skip_list[i].namelen <= namelen; i++) {
+		if (namelen == _pefs_name_skip_list[i].namelen &&
+				memcmp(_pefs_name_skip_list[i].name, name, namelen) == 0)
+			return (1);
 	}
-	return (1);
+	return (0);
+}
+
+static void
+pefs_enccn_init(struct pefs_enccn *pec, char *encname, int encname_len, struct componentname *cnp)
+{
+	MPASS(pec != NULL && cnp != NULL);
+
+	if (encname_len >= MAXPATHLEN)
+		panic("invalid encrypted name length: %d", encname_len);
+
+	pec->pec_cn = *cnp;
+	pec->pec_buf = uma_zalloc(namei_zone, M_WAITOK);
+	memcpy(pec->pec_buf, encname, encname_len);
+	((char *) pec->pec_buf)[encname_len] = '\0';
+	pec->pec_cn.cn_pnbuf = pec->pec_buf;
+	pec->pec_cn.cn_nameptr = pec->pec_buf;
+	pec->pec_cn.cn_namelen = encname_len;
+	pec->pec_cn.cn_consume = 0; // XXX??
+	PEFSDEBUG("%s: name=%s len=%d\n", __func__, (char*)pec->pec_buf, encname_len);
 }
 
 static int
-pefs_cn_shadow_create(struct componentname *cnp, struct componentname *o_cnp)
+pefs_enccn_create(struct pefs_enccn *pec, struct pefs_key *pk, struct componentname *cnp)
 {
-	char *pnbuf;
+	struct pefs_node_key pnk;
 	int r;
 
-	pnbuf = uma_zalloc(namei_zone, M_WAITOK);
-	r = pefs_name_encrypt(cnp->cn_nameptr, cnp->cn_namelen, pnbuf, MAXPATHLEN);
+	MPASS(pec != NULL && cnp != NULL);
+
+	pec->pec_cn = *cnp;
+	if (/* pk == NULL || */ (cnp->cn_flags & ISDOTDOT) || pefs_name_skip(cnp->cn_nameptr, cnp->cn_namelen)) {
+		pefs_enccn_init(pec, cnp->cn_nameptr, cnp->cn_namelen, cnp);
+		return (0);
+	}
+	pec->pec_buf = uma_zalloc(namei_zone, M_WAITOK);
+	pnk.pnk_key = pk;
+	arc4rand(pnk.pnk_tweak, PEFS_TWEAK_SIZE, 0);
+	r = pefs_name_encrypt(&pnk, cnp->cn_nameptr, cnp->cn_namelen, pec->pec_buf, MAXPATHLEN);
 	if (r <= 0) {
-		uma_zfree(namei_zone, pnbuf);
+		uma_zfree(namei_zone, pec->pec_buf);
 		return (EIO);
 	}
-	*o_cnp = *cnp;
-	cnp->cn_pnbuf = pnbuf;
-	cnp->cn_nameptr = pnbuf;
-	cnp->cn_namelen = r;
-	cnp->cn_consume = 0; // XXX??
+	pec->pec_cn.cn_pnbuf = pec->pec_buf;
+	pec->pec_cn.cn_nameptr = pec->pec_buf;
+	pec->pec_cn.cn_namelen = r;
+	pec->pec_cn.cn_consume = 0; // XXX??
+	PEFSDEBUG("%s: cn_flags=%lu\n", __func__, cnp->cn_flags);
 
 	/*
 	printf("%s: ENC cn_nameiop=%lx, cn_pnbuf=%s; cn_nameptr=%.*s; cn_consume=%d, cn_namelen=%d\n",
@@ -117,14 +149,136 @@
 	return (0);
 }
 
-static void
-pefs_cn_shadow_finish(struct componentname *cnp, const struct componentname *o_cnp)
+static inline void
+pefs_enccn_free(struct pefs_enccn *pec)
+{
+	uma_zfree(namei_zone, pec->pec_buf);
+}
+
+static struct dirent*
+pefs_enccn_lookup_dirent(void *mem, size_t sz, char *name, int namelen, char *buf, size_t buf_sz)
+{
+	struct pefs_node_key pnk;
+	struct dirent *de;
+	int d_namelen;
+	int de_len;
+
+	PEFSDEBUG("%s: lookup %.*s (%d)\n", __func__, namelen, name, namelen);
+	for (de = (struct dirent*) mem; sz > 0;
+			sz -= de_len,
+			de = (struct dirent *)(((caddr_t)de) + de_len)) {
+		de_len = GENERIC_DIRSIZ(de);
+		if (pefs_name_skip(de->d_name, de->d_namlen))
+			continue;
+		d_namelen = pefs_name_decrypt(&pnk, de->d_name, de->d_namlen, buf, buf_sz);
+		PEFSDEBUG("%s =>; res=%d; %.*s --> %.*s\n", __func__, d_namelen,
+				de->d_namlen, de->d_name,
+				d_namelen < 0 ? 0 : d_namelen, buf);
+		if (d_namelen == namelen && memcmp(name, buf, namelen) == 0) {
+			PEFSDEBUG("%s: check dirent: %s\n", __func__, name);
+			return de;
+		}
+	}
+	return NULL;
+}
+
+static int
+pefs_enccn_lookup(struct pefs_enccn *pec, struct vnode *dvp, struct componentname *cnp)
+{
+	struct dirent *de;
+	struct pefs_chunk *pc;
+	struct uio *uio;
+	struct vnode *ldvp = PEFS_LOWERVP(dvp);
+	char *namebuf;
+	off_t offset;
+	int error, eofflag;
+
+	MPASS(pec != NULL && dvp != NULL && cnp != NULL);
+
+	if ((cnp->cn_flags & ISDOTDOT) || pefs_name_skip(cnp->cn_nameptr, cnp->cn_namelen)) {
+		pefs_enccn_init(pec, cnp->cn_nameptr, cnp->cn_namelen, cnp);
+		return (0);
+	}
+
+	const char *op;
+	switch (cnp->cn_nameiop & OPMASK) {
+	case LOOKUP:
+		op = "LOOKUP";
+		break;
+	case CREATE:
+		op = "CREATE";
+		break;
+	case DELETE:
+		op = "DELETE";
+		break;
+	case RENAME:
+		op = "RENAME";
+		break;
+	default:
+		op = NULL;
+	}
+	PEFSDEBUG("XXX pefs_enccn_lookup: name=%.*s op=%s\n", (int) cnp->cn_namelen, cnp->cn_nameptr, op);
+
+	pc = pefs_chunk_create(PAGE_SIZE);
+	namebuf = malloc(MAXNAMLEN + 1, M_PEFSBUF, M_WAITOK);
+	offset = 0;
+	eofflag = 0;
+	de = NULL;
+	while (!eofflag && de == NULL) {
+		long arg = 0;
+
+		uio = pefs_chunk_uio(pc, offset, UIO_READ);
+		offset = uio->uio_offset;
+		error = VOP_READDIR(ldvp, uio, cnp->cn_cred, &eofflag, NULL, NULL);
+		if (error) {
+			pefs_chunk_free(pc);
+			free(namebuf, M_PEFSBUF);
+			return (error);
+		}
+
+		printf("%s: size = %d\n", __func__, pc->pc_size - uio->uio_resid);
+		pefs_chunk_shrink(pc, pc->pc_size - uio->uio_resid);
+		while (1) {
+			size_t size;
+			char *mem;
+
+			mem = pefs_chunk_get(pc, &size, &arg);
+			if (mem == NULL)
+				break;
+			de = pefs_enccn_lookup_dirent(mem, size,
+					cnp->cn_nameptr, cnp->cn_namelen,
+					namebuf, MAXNAMLEN + 1);
+			if (de != NULL)
+				break;
+		}
+		pefs_chunk_restore(pc);
+	}
+
+	if (de != NULL) {
+		PEFSDEBUG("%s: dirent found: %.*s\n", __func__, de->d_namlen, de->d_name);
+		pefs_enccn_init(pec, de->d_name, de->d_namlen, cnp);
+	}
+
+	pefs_chunk_free(pc);
+	free(namebuf, M_PEFSBUF);
+
+	if (de == NULL)
+		return (ENOENT);
+	return (0);
+}
+
+static int
+pefs_enccn_lookup_create(struct pefs_enccn *pec, struct vnode *dvp, struct componentname *cnp)
 {
-	uma_zfree(namei_zone, cnp->cn_pnbuf);
-	cnp->cn_pnbuf = o_cnp->cn_pnbuf;
-	cnp->cn_nameptr = o_cnp->cn_nameptr;
-	cnp->cn_namelen = o_cnp->cn_namelen;
-	cnp->cn_consume = o_cnp->cn_consume;
+	int error;
+
+	error = pefs_enccn_lookup(pec, dvp, cnp);
+	PEFSDEBUG("%s: lookup error = %d\n", __func__, error);
+	if (error == ENOENT)
+		error = pefs_enccn_create(pec, NULL, cnp);
+	PEFSDEBUG("%s: returning = %d\n", __func__, error);
+
+	return (error);
 }
 
 /*
@@ -151,8 +305,8 @@
  * - all mapped vnodes are of our vnode-type (NEEDSWORK:
  *   problems on rmdir'ing mount points and renaming?)
  */
-int
-pefs_bypass(struct vop_generic_args *ap)
+static int
+pefs_bypass(struct vop_generic_args *ap, struct pefs_enccn *enccn)
 {
 	struct vnode **this_vp_p;
 	int error;
@@ -195,7 +349,7 @@
 			old_vps[i] = NULLVP;
 		} else {
 			old_vps[i] = *this_vp_p;
-			*(vps_p[i]) = PEVPTOLOWERVP(*this_vp_p);
+			*(vps_p[i]) = PEFS_LOWERVP(*this_vp_p);
 			/*
 			 * XXX - Several operations have the side effect
 			 * of vrele'ing their vp's.  We must account for
@@ -246,6 +400,10 @@
 	if (descp->vdesc_vpp_offset != VDESC_NO_OFFSET &&
 	    !(descp->vdesc_flags & VDESC_NOMAP_VPP) &&
 	    !error) {
+		if (enccn == NULL) {
+			printf("PANIC: vop_bypass: map of outgoing vnode without encrypted name: %s", descp->vdesc_name);
+			// panic("vop_bypass: map of outgoing vnode without encrypted name: %s", descp->vdesc_name);
+		}
 		/*
 		 * XXX - even though some ops have vpp returned vp's,
 		 * several ops actually vrele this before returning.
@@ -257,7 +415,7 @@
 		vppp = VOPARG_OFFSETTO(struct vnode***,
 				 descp->vdesc_vpp_offset,ap);
 		if (*vppp)
-			error = pefs_nodeget(old_vps[0]->v_mount, **vppp, *vppp);
+			error = pefs_node_get(old_vps[0]->v_mount, **vppp, *vppp);
 	}
 
  out:
@@ -270,14 +428,13 @@
  * if this layer is mounted read-only.
  */
 static int
-pefs_lookup(struct vop_lookup_args *ap)
+pefs_lookup(struct vop_cachedlookup_args *ap)
 {
 	struct componentname *cnp = ap->a_cnp;
-	struct componentname o_cnp = *ap->a_cnp;
 	struct vnode *dvp = ap->a_dvp;
 	struct vnode *vp, *ldvp, *lvp;
+	struct pefs_enccn enccn;
 	int flags = cnp->cn_flags;
-	int shadow;
 	int error;
 
 	PEFSDEBUG("%s: cn_nameiop=%lx, cn_pnbuf=%s; cn_nameptr=%.*s; cn_consume=%d, cn_namelen=%d\n",
@@ -288,38 +445,53 @@
 	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
 		return (EROFS);
 
-	shadow = pefs_name_shadow(cnp->cn_nameptr, cnp->cn_namelen, cnp);
-	if (shadow)
-		pefs_cn_shadow_create(cnp, &o_cnp);
+	error = pefs_enccn_lookup(&enccn, dvp, cnp);
+	if (error == ENOENT && (cnp->cn_flags & ISLASTCN) &&
+			(cnp->cn_nameiop == CREATE ||
+			 cnp->cn_nameiop == RENAME))
+		return EJUSTRETURN;
+	else if (error)
+		return (error);
 
 	/*
 	 * Although it is possible to call pefs_bypass(), we'll do
 	 * a direct call to reduce overhead
 	 */
-	ldvp = PEVPTOLOWERVP(dvp);
+	ldvp = PEFS_LOWERVP(dvp);
 	vp = lvp = NULL;
-	error = VOP_LOOKUP(ldvp, &lvp, cnp);
+	error = VOP_LOOKUP(ldvp, &lvp, &enccn.pec_cn);
 	if (error == EJUSTRETURN && (flags & ISLASTCN) &&
 	    (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
 	    (cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME))
 		error = EROFS;
 
-	if (shadow)
-		pefs_cn_shadow_finish(cnp, &o_cnp);
+	PEFSDEBUG("XXX %s: result=%d\n", __func__, error);
+
+	pefs_enccn_free(&enccn);
 
-	if ((error == 0 || error == EJUSTRETURN) && lvp != NULL) {
+	if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE) {
+		PEFSDEBUG("%s: cache_enter negative %.*s\n", __func__, (int) cnp->cn_namelen, cnp->cn_nameptr);
+		cache_enter(dvp, NULLVP, cnp);
+	} else if ((error == 0 || error == EJUSTRETURN) && lvp != NULL) {
 		if (ldvp == lvp) {
 			*ap->a_vpp = dvp;
 			VREF(dvp);
 			vrele(lvp);
 		} else {
-			error = pefs_nodeget(dvp->v_mount, lvp, &vp);
-			if (error)
+			error = pefs_node_get(dvp->v_mount, lvp, &vp);
+			if (error) {
 				vput(lvp);
-			else
+			} else {
 				*ap->a_vpp = vp;
+				if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE) {
+					PEFSDEBUG("%s: cache_enter %.*s\n", __func__, (int) cnp->cn_namelen, cnp->cn_nameptr);
+					cache_enter(dvp, vp, cnp);
+				}
+			}
 		}
 	}
+
+
 	return (error);
 }
 
@@ -330,14 +502,10 @@
 	struct vnode *vp, *ldvp;
 
 	vp = ap->a_vp;
-	ldvp = PEVPTOLOWERVP(vp);
-	retval = pefs_bypass(&ap->a_gen);
+	ldvp = PEFS_LOWERVP(vp);
+	retval = pefs_bypass(&ap->a_gen, NULL);
 	if (retval == 0) {
-		if (vp->v_type == VSOCK || vp->v_type == VFIFO) {
-			vp->v_object = ldvp->v_object;
-		} else {
-			vnode_create_vobject(vp, 0, ap->a_td);
-		}
+		vnode_create_vobject(vp, 0, ap->a_td);
 	}
 	return (retval);
 }
@@ -353,7 +521,7 @@
 	int resid, size;
 	int error;
 
-	lvp = PEVPTOLOWERVP(vp);
+	lvp = PEFS_LOWERVP(vp);
 	error = VOP_GETATTR(lvp, &o_va, cred);
 	if (error)
 		return (error);
@@ -377,7 +545,7 @@
 		for (off=o_va.va_size; size > 0;) {
 			int inc = min(size, pc_size_max);
 
-			if (inc != size && (off + inc) % PEFS_BLOCK) 
+			if (inc != size && (off + inc) % PEFS_BLOCK)
 				inc -= (off + inc) % PEFS_BLOCK;
 
 			puio = pefs_chunk_uio_range(pc, 0, inc, off, UIO_WRITE);
@@ -472,7 +640,7 @@
 		}
 	}
 
-	lvp = PEVPTOLOWERVP(vp);
+	lvp = PEFS_LOWERVP(vp);
 	return VOP_SETATTR(lvp, vap, cred);
 }
 
@@ -485,7 +653,7 @@
 	struct vattr *vap = ap->a_vap;
 	int error;
 
-	if ((error = pefs_bypass((struct vop_generic_args *)ap)) != 0)
+	if ((error = pefs_bypass((struct vop_generic_args *)ap, NULL)) != 0)
 		return (error);
 
 	vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
@@ -521,7 +689,7 @@
 			break;
 		}
 	}
-	return (pefs_bypass((struct vop_generic_args *)ap));
+	return (pefs_bypass((struct vop_generic_args *)ap, NULL));
 }
 
 /*
@@ -532,14 +700,15 @@
 static int
 pefs_rename(struct vop_rename_args *ap)
 {
+	struct vnode *fdvp = ap->a_fdvp;
+	struct vnode *fvp = ap->a_fvp;
 	struct vnode *tdvp = ap->a_tdvp;
-	struct vnode *fvp = ap->a_fvp;
-	struct vnode *fdvp = ap->a_fdvp;
 	struct vnode *tvp = ap->a_tvp;
 	struct componentname *fcnp = ap->a_fcnp;
 	struct componentname *tcnp = ap->a_tcnp;
-	struct componentname o_fcnp, o_tcnp;
-	int fshadow, tshadow, error;
+	struct pefs_enccn fenccn;
+	struct pefs_enccn tenccn;
+	int error;
 
 	/* Check for cross-device rename. */
 	if ((fvp->v_mount != tdvp->v_mount) ||
@@ -556,22 +725,32 @@
 	}
 
 
-	fshadow = pefs_name_shadow(fcnp->cn_nameptr, fcnp->cn_namelen, fcnp);
-	if (fshadow)
-		pefs_cn_shadow_create(fcnp, &o_fcnp);
-	tshadow = pefs_name_shadow(tcnp->cn_nameptr, tcnp->cn_namelen, tcnp);
-	if (tshadow)
-		pefs_cn_shadow_create(tcnp, &o_tcnp);
+	error = pefs_enccn_lookup(&fenccn, fdvp, fcnp);
+	if (error) {
+		return (error);
+	}
+	error = pefs_enccn_lookup_create(&tenccn, tdvp, tcnp);
+	if (error) {
+		pefs_enccn_free(&fenccn);
+		return (error);
+	}
 
 	PEFSDEBUG("%s: %.*s -> %.*s\n",
 			__func__, (int) fcnp->cn_namelen, fcnp->cn_nameptr,
 			(int) tcnp->cn_namelen, tcnp->cn_nameptr);
-	error = pefs_bypass((struct vop_generic_args *)ap);
+	ap->a_fcnp = &fenccn.pec_cn;
+	ap->a_tcnp = &tenccn.pec_cn;
+	error = pefs_bypass((struct vop_generic_args *)ap, NULL);
+	ap->a_fcnp = fcnp;
+	ap->a_tcnp = tcnp;
+
+	pefs_enccn_free(&fenccn);
+	pefs_enccn_free(&tenccn);
 
-	if (fshadow)
-		pefs_cn_shadow_finish(fcnp, &o_fcnp);
-	if (tshadow)
-		pefs_cn_shadow_finish(tcnp, &o_tcnp);
+	if (!error) {
+		cache_purge(fdvp);
+		cache_purge(fvp);
+	}
 
 	return (error);
 }
@@ -595,13 +774,13 @@
 		VI_LOCK(vp);
 		ap->a_flags = flags |= LK_INTERLOCK;
 	}
-	nn = VTOPE(vp);
+	nn = VP_TO_PN(vp);
 	/*
 	 * If we're still active we must ask the lower layer to
 	 * lock as ffs has special lock considerations in it's
 	 * vop lock.
 	 */
-	if (nn != NULL && (lvp = PEVPTOLOWERVP(vp)) != NULL) {
+	if (nn != NULL && (lvp = PEFS_LOWERVP(vp)) != NULL) {
 		VI_LOCK_FLAGS(lvp, MTX_DUPOK);
 		VI_UNLOCK(vp);
 		/*

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list