PERFORCE change 166406 for review

Gleb Kurtsou gk at FreeBSD.org
Wed Jul 22 13:01:33 UTC 2009


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

Change 166406 by gk at gk_h1 on 2009/07/22 13:00:50

	Add support for multiply keys per filesystem
	Replace sbin/mount_pefs with sbin/pefs (it also installs link to /sbin/mount_pefs)
	Configuration utility is capable of mounting/unmounting filesystems, adding/deleting keys

Affected files ...

.. //depot/projects/soc2009/gk_pefs/sbin/mount_pefs/Makefile#2 delete
.. //depot/projects/soc2009/gk_pefs/sbin/mount_pefs/mount_pefs.c#2 delete
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/Makefile#1 add
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_ctl.c#1 add
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_ctl.h#1 add
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_key.c#1 add
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_mount.c#1 add
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs.h#7 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_crypto.c#4 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_subr.c#7 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vfsops.c#6 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vnops.c#7 edit

Differences ...

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

@@ -38,29 +38,48 @@
  */
 
 #include <sys/param.h>
+#include <sys/ioccom.h>
 #include <sys/mutex.h>
 #include <sys/refcount.h>
 #include <sys/queue.h>
 #include <sys/uio.h>
 
-#ifdef _KERNEL
+#define PEFS_ALG_SALSA20		1
 
 #define PEFS_TWEAK_SIZE			8
 #define PEFS_KEY_BITS			256
 #define PEFS_KEY_SIZE			(PEFS_KEY_BITS / 8)
+#define PEFS_KEYID_SIZE			8
 #define PEFS_NAME_CSUM_SIZE		2
 
+struct pefs_xkey {
+	int pxk_index;
+	int pxk_alg;
+	char pxk_keyid[PEFS_KEYID_SIZE];
+	char pxk_key[PEFS_KEY_SIZE];
+};
+
+#define PEFS_GETKEY			_IOWR('p', 0, struct pefs_xkey)
+#define PEFS_ADDKEY			_IOWR('p', 1, struct pefs_xkey)
+#define PEFS_SETKEY			_IOWR('p', 2, struct pefs_xkey)
+#define PEFS_DELKEY			_IOWR('p', 3, struct pefs_xkey)
+#define PEFS_FLUSHKEYS			_IO('p', 4)
+
+#ifdef _KERNEL
+
 #define PEFS_NAME_NTOP_SIZE(a)		(((a) * 4 + 2)/3)
 #define PEFS_NAME_PTON_SIZE(a)		(((a) * 3)/4)
 
-LIST_HEAD(pefs_key_head, pefs_key);
+TAILQ_HEAD(pefs_key_head, pefs_key);
 
 struct pefs_key {
 	volatile u_int pk_refcnt;
-	LIST_ENTRY(pefs_key) pk_entry;
+	int pk_alg;
+	TAILQ_ENTRY(pefs_key) pk_entry;
 	struct mtx *pk_entry_lock;
 	char pk_name[PEFS_KEY_SIZE];
 	char pk_data[PEFS_KEY_SIZE];
+	char pk_keyid[PEFS_KEYID_SIZE];
 };
 
 struct pefs_tkey {
@@ -79,7 +98,7 @@
 };
 
 struct pefs_mount {
-	struct mount *pm_vfs;
+	struct mount *pm_lowervfs;
 	struct vnode *pm_rootvp;	/* Reference to root pefs_node */
 	struct mtx pm_keys_lock;
 	struct pefs_key_head pm_keys;
@@ -95,21 +114,21 @@
 	struct uio pc_uio;
 };
 
-static inline struct pefs_mount*
+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*
+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*
+static inline struct vnode *
 PN_TO_VP(struct pefs_node *pn)
 {
 	MPASS(pn != NULL && pn->pn_vnode != NULL);
@@ -120,7 +139,7 @@
 struct vnode *pefs_checkvp(struct vnode *vp, char *fil, int lno);
 #endif
 
-static inline struct vnode*
+static inline struct vnode *
 PEFS_LOWERVP(struct vnode *vp)
 {
 	struct vnode *lvp;
@@ -146,15 +165,20 @@
 int pefs_node_get(struct mount *mp, struct vnode *lvp, struct vnode *ldvp, struct vnode **vpp, struct ucred *cred, struct pefs_tkey *ptk);
 void pefs_node_free(struct pefs_node *xp);
 int pefs_node_lookup_name(struct vnode *lvp, struct vnode *ldvp, struct ucred *cred, char *encname, int *encname_len);
-struct pefs_key* pefs_node_key(struct pefs_node *pn);
+struct pefs_key * pefs_node_key(struct pefs_node *pn);
 
-struct pefs_ctx *pefs_ctx_get(void);
+struct pefs_ctx * pefs_ctx_get(void);
 void pefs_ctx_free(struct pefs_ctx *ctx);
 
-struct pefs_key* pefs_key_get(char *passwd, int passwd_len);
-struct pefs_key* pefs_key_ref(struct pefs_key *pk);
+struct pefs_key * pefs_key_get(int alg, const char *key, const char *keyid);
+struct pefs_key * pefs_key_ref(struct pefs_key *pk);
 void pefs_key_release(struct pefs_key *pk);
 
+struct pefs_key * pefs_key_lookup(struct pefs_mount *pm, char *keyid);
+int pefs_key_add(struct pefs_mount *pm, int index, struct pefs_key *pk);
+void pefs_key_remove(struct pefs_mount *pm, struct pefs_key *pk);
+int pefs_key_remove_all(struct pefs_mount *pm);
+
 void pefs_data_encrypt(struct pefs_ctx *ctx, struct pefs_tkey *ptk, off_t offset, struct pefs_chunk *pc);
 void pefs_data_decrypt(struct pefs_ctx *ctx, struct pefs_tkey *ptk, off_t offset, struct pefs_chunk *pc);
 
@@ -164,12 +188,12 @@
 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);
 
-struct pefs_chunk* pefs_chunk_create(size_t size);
+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);
 void* pefs_chunk_pullup(struct pefs_chunk *pc, size_t size);
-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);
+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);
 void* pefs_chunk_get(struct pefs_chunk *pc, size_t *size, long *_state);
 void pefs_chunk_zero(struct pefs_chunk *pc);
 int pefs_chunk_copy(struct pefs_chunk *pc, size_t skip, struct uio *uio);
@@ -178,13 +202,13 @@
 
 extern struct vop_vector pefs_vnodeops;
 
-static inline struct pefs_key*
+static inline struct pefs_key *
 pefs_rootkey(struct pefs_mount *pm)
 {
 	struct pefs_key *pk;
 
 	mtx_lock(&pm->pm_keys_lock);
-	pk = LIST_FIRST(&pm->pm_keys);
+	pk = TAILQ_FIRST(&pm->pm_keys);
 	mtx_unlock(&pm->pm_keys_lock);
 
 	return (pk);

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

@@ -1,5 +1,6 @@
 /*-
- * Copyright (c) 2009 Gleb Kurtsou. All rights reserved.
+ * Copyright (c) 2009 Gleb Kurtsou <gk at FreeBSD.org>
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -44,16 +45,9 @@
 	0x5c, 0x83, 0xcb, 0x96, 0x2f, 0xaf, 0x3b, 0xb5,
 };
 
-#define MAGIC_KEYGEN_ITERATIONS		32
+#define MAGIC_KEYGEN_ITERATIONS		16
 
-static const uint8_t magic_key_keygen[PEFS_KEY_SIZE] = {
-	0xd2, 0x68, 0x7d, 0x52, 0xb7, 0xc1, 0xe0, 0xc7,
-	0x26, 0xf1, 0x53, 0xaf, 0xa1, 0x46, 0x7a, 0xc9,
-	0x3a, 0x37, 0xc6, 0xf6, 0x7d, 0xd3, 0xbe, 0xed,
-	0xf4, 0x52, 0x24, 0x9e, 0x6c, 0x85, 0xd9, 0x5c,
-};
-
-static const uint8_t magic_tweak_keygen[PEFS_TWEAK_SIZE] = {
+static const char magic_tweak_keygen[PEFS_TWEAK_SIZE] = {
 	0xc8, 0x27, 0xa3, 0x7e, 0xcf, 0x86, 0x3d, 0x0d,
 };
 
@@ -68,10 +62,10 @@
 pefs_crypto_init(void)
 {
 	pefs_ctx_zone = uma_zcreate("pefs_ctx", sizeof(struct pefs_ctx), 
-			NULL, NULL, NULL, (uma_fini) bzero, 
+			NULL, NULL, NULL, (uma_fini)bzero, 
 			UMA_ALIGN_PTR, 0);
 	pefs_key_zone = uma_zcreate("pefs_key", sizeof(struct pefs_key), 
-			NULL, NULL, NULL, (uma_fini) bzero, 
+			NULL, NULL, NULL, (uma_fini)bzero, 
 			UMA_ALIGN_PTR, 0);
 }
 
@@ -94,47 +88,50 @@
 	uma_zfree(pefs_ctx_zone, ctx);
 }
 
+/*
+ * This is not a key derivation function in common sense!
+ * Key should be cryptographically strong.
+ */
 static void
-pefs_key_generate(struct pefs_ctx *ctx, uint8_t *key)
+pefs_key_generate(struct pefs_ctx *ctx, char *key)
 {
-	uint8_t tweak[PEFS_TWEAK_SIZE];
+	char tweak[PEFS_TWEAK_SIZE];
 	int i, j;
 
 	memcpy(tweak, magic_tweak_keygen, PEFS_TWEAK_SIZE);
 
-	salsa20_keysetup(&ctx->pctx_salsa, magic_key_keygen, PEFS_KEY_BITS);
-	salsa20_ivsetup(&ctx->pctx_salsa, tweak, 0);
-	salsa20_crypt(&ctx->pctx_salsa, key, key, PEFS_KEY_SIZE);
-
 	for (i = 1; i < MAGIC_KEYGEN_ITERATIONS; i++) {
-		for (j = 0; j < PEFS_TWEAK_SIZE; j++)
-			tweak[j]++;
 		salsa20_keysetup(&ctx->pctx_salsa, key, PEFS_KEY_BITS);
 		salsa20_ivsetup(&ctx->pctx_salsa, tweak, i * 64);
 		salsa20_crypt(&ctx->pctx_salsa, key, key, PEFS_KEY_SIZE);
+		for (j = 0; j < PEFS_TWEAK_SIZE; j++)
+			tweak[j]++;
 	}
 }
 
 struct pefs_key *
-pefs_key_get(char *passwd, int passwd_len)
+pefs_key_get(int alg, const char *key, const char *keyid)
 {
 	struct pefs_ctx *ctx;
 	struct pefs_key *pk;
-	int i;
+
+	switch (alg) {
+	case PEFS_ALG_SALSA20:
+		break;
+	default:
+		return (NULL);
+	}
 
 	pk = uma_zalloc(pefs_key_zone, M_WAITOK | M_ZERO);
+	pk->pk_alg = alg;
 	refcount_init(&pk->pk_refcnt, 1);
-
-	if (passwd_len > PEFS_KEY_SIZE)
-		passwd_len = PEFS_KEY_SIZE;
-	memcpy(pk->pk_name, passwd, passwd_len);
-	for (i = passwd_len; i < PEFS_KEY_SIZE; i++)
-		pk->pk_name[i] = passwd[i % passwd_len];
+	memcpy(pk->pk_keyid, keyid, PEFS_KEYID_SIZE);
 
 	ctx = pefs_ctx_get();
+	memcpy(pk->pk_data, key, PEFS_KEY_SIZE);
+	pefs_key_generate(ctx, pk->pk_data);
+	memcpy(pk->pk_name, pk->pk_data, PEFS_KEY_SIZE);
 	pefs_key_generate(ctx, pk->pk_name);
-	memcpy(pk->pk_data, pk->pk_name, PEFS_KEY_SIZE);
-	pefs_key_generate(ctx, pk->pk_data);
 	pefs_ctx_free(ctx);
 
 	return (pk);
@@ -152,8 +149,95 @@
 {
 	if (pk == NULL)
 		return;
-	if (refcount_release(&pk->pk_refcnt))
+	if (pk->pk_refcnt == 0) {
+		PEFSDEBUG("!!!! pefs_key_release: zero reference count\n");
+		return;
+	}
+	if (refcount_release(&pk->pk_refcnt)) {
+		PEFSDEBUG("pefs_key_release: free pk=%p\n", pk);
 		uma_zfree(pefs_key_zone, pk);
+	}
+}
+
+struct pefs_key *
+pefs_key_lookup(struct pefs_mount *pm, char *keyid)
+{
+	struct pefs_key *pk;
+
+	mtx_assert(&pm->pm_keys_lock, MA_OWNED);
+	TAILQ_FOREACH(pk, &pm->pm_keys, pk_entry) {
+		if (memcmp(pk->pk_keyid, keyid, PEFS_KEYID_SIZE) == 0) {
+			return (pk);
+		}
+	}
+
+	return (NULL);
+}
+
+int
+pefs_key_add(struct pefs_mount *pm, int index, struct pefs_key *pk)
+{
+	struct pefs_key *i, *pk_pos;
+	int pos;
+
+	mtx_lock(&pm->pm_keys_lock);
+	if (index == 0 && !TAILQ_EMPTY(&pm->pm_keys)) {
+		mtx_unlock(&pm->pm_keys_lock);
+		return (EEXIST);
+	}
+	pk_pos = NULL;
+	pos = 0;
+	TAILQ_FOREACH(i, &pm->pm_keys, pk_entry) {
+		if (memcmp(pk->pk_keyid, i->pk_keyid, PEFS_KEYID_SIZE) == 0 ||
+		    memcmp(pk->pk_name, i->pk_name, PEFS_KEY_SIZE) == 0 ||
+		    memcmp(pk->pk_data, i->pk_data, PEFS_KEY_SIZE) == 0) {
+			mtx_unlock(&pm->pm_keys_lock);
+			return (EEXIST);
+		}
+		if (index == pos + 1) {
+			pk_pos = i;
+		}
+	}
+	pk->pk_entry_lock = &pm->pm_keys_lock;
+	if (TAILQ_EMPTY(&pm->pm_keys)) {
+		TAILQ_INSERT_HEAD(&pm->pm_keys, pk, pk_entry);
+		PEFSDEBUG("pefs_key_add: root key added: %p\n", pk);
+	} else if (pk_pos == NULL) {
+		TAILQ_INSERT_TAIL(&pm->pm_keys, pk, pk_entry);
+		PEFSDEBUG("pefs_key_add: tail key added: %p\n", pk);
+	} else {
+		TAILQ_INSERT_AFTER(&pm->pm_keys, pk_pos, pk, pk_entry);
+		PEFSDEBUG("pefs_key_add: key added at pos=%d: %p\n", pos, pk);
+	}
+	mtx_unlock(&pm->pm_keys_lock);
+
+	return (0);
+}
+
+void
+pefs_key_remove(struct pefs_mount *pm, struct pefs_key *pk)
+{
+	mtx_assert(&pm->pm_keys_lock, MA_OWNED);
+	MPASS(pk->pk_entry_lock != NULL);
+	TAILQ_REMOVE(&pm->pm_keys, pk, pk_entry);
+	pk->pk_entry_lock = NULL;
+	PEFSDEBUG("pefs_key_remove: pk=%p\n", pk);
+	pefs_key_release(pk);
+}
+
+int
+pefs_key_remove_all(struct pefs_mount *pm)
+{
+	int n = 0;
+
+	mtx_lock(&pm->pm_keys_lock);
+	while (!TAILQ_EMPTY(&pm->pm_keys)) {
+		pefs_key_remove(pm, TAILQ_FIRST(&pm->pm_keys));
+		n++;
+	}
+	mtx_unlock(&pm->pm_keys_lock);
+
+	return (n);
 }
 
 void
@@ -277,14 +361,20 @@
 int
 pefs_name_decrypt(struct pefs_ctx *ctx, struct pefs_key *pk, struct pefs_tkey *ptk, const char *enc, size_t enc_len, char *plain, size_t plain_size)
 {
-	u_short csum;
+	struct pefs_key *ki;
+	char *dec;
 	int free_ctx = 0;
-	int r;
+	int r, ki_rev;
 
 	if (pk == NULL) {
 		PEFSDEBUG("!!!! %s: NULL pk\n", __func__);
 		return (-1);
 	}
+	
+	if (enc == plain) {
+		PEFSDEBUG("pefs_name_decrypt: enc == plain\n");
+		return (-1);
+	}
 
 	r = pefs_name_pton(enc, enc_len, plain, plain_size);
 	if (r < 0 || r <= PEFS_TWEAK_SIZE + PEFS_NAME_CSUM_SIZE) {
@@ -297,29 +387,55 @@
 		free_ctx = 1;
 	}
 
-	salsa20_keysetup(&ctx->pctx_salsa, pk->pk_name, PEFS_KEY_BITS);
-	salsa20_ivsetup(&ctx->pctx_salsa, magic_tweak_name, 0);
-	salsa20_crypt(&ctx->pctx_salsa, plain, plain, r);
+	ki = pk;
+	ki_rev = 0;
+	if (plain_size >= r * 2)
+		dec = plain + r;
+	else
+		dec = plain;
+	do {
+		PEFSDEBUG("pefs_name_decrypt: check key %p\n", ki);
+		salsa20_keysetup(&ctx->pctx_salsa, ki->pk_name, PEFS_KEY_BITS);
+		salsa20_ivsetup(&ctx->pctx_salsa, magic_tweak_name, 0);
+		salsa20_crypt(&ctx->pctx_salsa, plain, dec, r);
+
+		if (pefs_name_checksum(dec, r) == 0)
+			break;
+
+		if (plain == dec) {
+			/* Restore previous value. */
+			salsa20_ivsetup(&ctx->pctx_salsa, magic_tweak_name, 0);
+			salsa20_crypt(&ctx->pctx_salsa, dec, plain, r);
+		}
+
+		if (!ki_rev) {
+			ki = TAILQ_NEXT(ki, pk_entry);
+			PEFSDEBUG("pefs_name_decrypt: next key %p\n", ki);
+			if (ki == NULL) {
+				ki_rev = 1;
+				ki = pk;
+			}
+		}
+		if (ki_rev) {
+			ki = TAILQ_PREV(ki, pefs_key_head, pk_entry);
+			PEFSDEBUG("pefs_name_decrypt: prev key %p\n", ki);
+		}
+	} while (ki != NULL);
 
 	if (free_ctx)
 		pefs_ctx_free(ctx);
 
-	csum = pefs_name_checksum(plain, r);
-	if (csum != 0) {
-		PEFSDEBUG("%s: invalid csum = %d\n", __func__, csum);
+	if (ki == NULL)
 		return (-1);
-	}
 
 	if (ptk) {
-		ptk->ptk_key = pk;
-		memcpy(plain, ptk->ptk_tweak, PEFS_TWEAK_SIZE);
+		ptk->ptk_key = ki;
+		memcpy(ptk->ptk_tweak, dec, PEFS_TWEAK_SIZE);
 	}
 
 	r -= PEFS_TWEAK_SIZE + PEFS_NAME_CSUM_SIZE;
-	memcpy(plain, plain + PEFS_TWEAK_SIZE, r);
-
-	if (r < plain_size)
-		plain[r] = '\0';
+	memcpy(plain, dec + PEFS_TWEAK_SIZE, r);
+	plain[r] = '\0';
 
 	PEFSDEBUG("pefs_name_decrypt: %d; %.*s => %.*s\n", r, enc_len, enc, r < 0 ? 0 : r, plain);
 

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

@@ -182,6 +182,7 @@
 	PEFSDEBUG("pefs_insmntque_dtr: free node %p\n", pn);
 	vp->v_data = NULL;
 	vp->v_vnlock = &vp->v_lock;
+	PEFSDEBUG("pefs_insmntque_dtr: pk=%p\n", pn->pn_tkey.ptk_key);
 	pefs_key_release(pn->pn_tkey.ptk_key);
 	uma_zfree(pefs_node_zone, pn);
 	vp->v_op = &dead_vnodeops;
@@ -321,6 +322,9 @@
 		if (xp->pn_tkey.ptk_key != NULL)
 			xp->pn_flags = PN_HASKEY;
 	}
+	if (xp->pn_tkey.ptk_key != NULL) {
+		PEFSDEBUG("pefs_node_get: node has key: pk_refcnt=%d\n", xp->pn_tkey.ptk_key->pk_refcnt);
+	}
 
 	error = getnewvnode("pefs", mp, &pefs_vnodeops, &vp);
 	if (error) {

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

@@ -133,20 +133,12 @@
 				M_PEFSMNT, M_WAITOK | M_ZERO);	/* XXX */
 
 	mtx_init(&xmp->pm_keys_lock, "pefs_mount lock", NULL, MTX_DEF);
-	LIST_INIT(&xmp->pm_keys);
-
-#if 0
-	// FIXME
-	struct pefs_key *pk;
-	pk = pefs_key_get("a", 1);
-	pk->pk_entry_lock = &xmp->pm_keys_lock;
-	LIST_INSERT_HEAD(&xmp->pm_keys, pk, pk_entry);
-#endif
+	TAILQ_INIT(&xmp->pm_keys);
 
 	/*
 	 * Save reference to underlying FS
 	 */
-	xmp->pm_vfs = lowerrootvp->v_mount;
+	xmp->pm_lowervfs = lowerrootvp->v_mount;
 
 	/*
 	 * Save reference.  Each mount also holds
@@ -219,15 +211,7 @@
 	 */
 	pm = VFS_TO_PEFS(mp);
 	mp->mnt_data = 0;
-	mtx_lock(&pm->pm_keys_lock);
-	while (!LIST_EMPTY(&pm->pm_keys)) {
-		struct pefs_key *pk = LIST_FIRST(&pm->pm_keys);
-
-		LIST_REMOVE(pk, pk_entry);
-		pk->pk_entry_lock = NULL;
-		pefs_key_release(pk);
-	}
-	mtx_unlock(&pm->pm_keys_lock);
+	pefs_key_remove_all(pm);
 	mtx_destroy(&pm->pm_keys_lock);
 	free(pm, M_PEFSMNT);
 	return 0;
@@ -248,10 +232,6 @@
 	vp = VFS_TO_PEFS(mp)->pm_rootvp;
 	VREF(vp);
 
-#ifdef PEFSXXX_DEBUG
-	if (VOP_ISLOCKED(vp))
-		panic("root vnode is locked.\n");
-#endif
 	vn_lock(vp, flags | LK_RETRY);
 	*vpp = vp;
 	return 0;
@@ -260,7 +240,7 @@
 static int
 pefs_quotactl(struct mount *mp, int cmd, uid_t uid, void *arg)
 {
-	return VFS_QUOTACTL(VFS_TO_PEFS(mp)->pm_vfs, cmd, uid, arg);
+	return VFS_QUOTACTL(VFS_TO_PEFS(mp)->pm_lowervfs, cmd, uid, arg);
 }
 
 static int
@@ -275,7 +255,7 @@
 
 	bzero(&mstat, sizeof(mstat));
 
-	error = VFS_STATFS(VFS_TO_PEFS(mp)->pm_vfs, &mstat);
+	error = VFS_STATFS(VFS_TO_PEFS(mp)->pm_lowervfs, &mstat);
 	if (error)
 		return (error);
 
@@ -305,7 +285,7 @@
 pefs_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
 {
 	int error;
-	error = VFS_VGET(VFS_TO_PEFS(mp)->pm_vfs, ino, flags, vpp);
+	error = VFS_VGET(VFS_TO_PEFS(mp)->pm_lowervfs, ino, flags, vpp);
 	if (error)
 		return (error);
 
@@ -317,7 +297,7 @@
 {
 	int error;
 
-	error = VFS_FHTOVP(VFS_TO_PEFS(mp)->pm_vfs, fidp, vpp);
+	error = VFS_FHTOVP(VFS_TO_PEFS(mp)->pm_lowervfs, fidp, vpp);
 	if (error)
 		return (error);
 
@@ -333,7 +313,7 @@
 static int
 pefs_extattrctl(struct mount *mp, int cmd, struct vnode *filename_vp, int namespace, const char *attrname)
 {
-	return VFS_EXTATTRCTL(VFS_TO_PEFS(mp)->pm_vfs, cmd, filename_vp,
+	return VFS_EXTATTRCTL(VFS_TO_PEFS(mp)->pm_lowervfs, cmd, filename_vp,
 	    namespace, attrname);
 }
 

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

@@ -131,12 +131,6 @@
 	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",
-			__func__, cnp->cn_nameiop, cnp->cn_pnbuf, (int) cnp->cn_namelen, cnp->cn_nameptr,
-			(int) cnp->cn_consume, (int) cnp->cn_namelen);
-	*/
-
 	return (0);
 }
 
@@ -300,6 +294,49 @@
 }
 
 /*
+ * Recycle vnodes using key pk.
+ * If pk is NULL recycle all vnodes with PN_HASKEY flag set.
+ */
+static int
+pefs_flushkey(struct mount *mp, struct pefs_key *pk)
+{
+	struct vnode *vp, *mvp;
+	struct pefs_node *pn;
+	int error;
+
+	PEFSDEBUG("pefs_flushkey: pk=%p\n", pk);
+	MNT_ILOCK(mp);
+loop:
+	MNT_VNODE_FOREACH(vp, mp, mvp) {
+		if (vp->v_type != VREG && vp->v_type != VDIR)
+			continue;
+		VI_LOCK(vp);
+		pn = VP_TO_PN(vp);
+		if ((pn->pn_flags & PN_HASKEY) && 
+		    (pk == NULL || pn->pn_tkey.ptk_key == pk)) {
+			vholdl(vp);
+			MNT_IUNLOCK(mp);
+			error = vn_lock(vp, LK_INTERLOCK | LK_EXCLUSIVE);
+			if (error) {
+				vdrop(vp);
+				MNT_ILOCK(mp);
+				MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp);
+				goto loop;
+			}
+			PEFSDEBUG("pefs_flushkey: pk=%p, vp=%p\n", pk, vp);
+			vgone(vp);
+			VOP_UNLOCK(vp, 0);
+			vdrop(vp);
+			MNT_ILOCK(mp);
+		} else {
+			VI_UNLOCK(vp);
+		}
+	}
+	MNT_IUNLOCK(mp);
+	return (0);
+}
+
+/*
  * This is the 10-Apr-92 bypass routine.
  *    This version has been optimized for speed, throwing away some
  * safety checks.  It should still always work, but it's not as
@@ -887,18 +924,14 @@
 static int
 pefs_inactive(struct vop_inactive_args *ap)
 {
-	/* Do not vrecycle vnode */
-#if 0
 	struct vnode *vp = ap->a_vp;
 	struct thread *td = ap->a_td;
+	struct pefs_node *pn = VP_TO_PN(vp);
 
-	PEFSDEBUG("pefs_inactive: recycle vnode: vp=%p\n", vp);
-	/*
-	 * If this is the last reference, then free up the vnode
-	 * so as not to tie up the lower vnodes.
-	 */
-	vrecycle(vp, td);
-#endif
+	if ((pn->pn_flags & PN_HASKEY) && pn->pn_tkey.ptk_key->pk_entry_lock == NULL) {
+		PEFSDEBUG("pefs_inactive: recycle vnode: vp=%p\n", vp);
+		vrecycle(vp, td);
+	}
 
 	return (0);
 }
@@ -910,8 +943,8 @@
 pefs_reclaim(struct vop_reclaim_args *ap)
 {
 	struct vnode *vp = ap->a_vp;
-	struct pefs_node *xp = VP_TO_PN(vp);
-	struct vnode *lowervp = xp->pn_lowervp;
+	struct pefs_node *pn = VP_TO_PN(vp);
+	struct vnode *lowervp = pn->pn_lowervp;
 
 	PEFSDEBUG("pefs_reclaim: vp=%p\n", vp);
 
@@ -919,7 +952,7 @@
 	cache_purge(vp);
 
 	if (lowervp)
-		pefs_node_free(xp);
+		pefs_node_free(pn);
 	/*
 	 * Use the interlock to protect the clearing of v_data to
 	 * prevent faults in pefs_lock().
@@ -941,8 +974,9 @@
 pefs_print(struct vop_print_args *ap)
 {
 	struct vnode *vp = ap->a_vp;
+	struct pefs_node *pn = VP_TO_PN(vp);
 
-	printf("\tvp=%p, lowervp=%p\n", vp, PEFS_LOWERVP(vp));
+	printf("\tvp=%p, lowervp=%p, flags=%04d\n", vp, pn->pn_lowervp, pn->pn_flags);
 	return (0);
 }
 
@@ -950,14 +984,14 @@
 static int
 pefs_getwritemount(struct vop_getwritemount_args *ap)
 {
-	struct pefs_node *xp;
+	struct pefs_node *pn;
 	struct vnode *lowervp;
 	struct vnode *vp;
 
 	vp = ap->a_vp;
 	VI_LOCK(vp);
-	xp = VP_TO_PN(vp);
-	if (xp && (lowervp = xp->pn_lowervp)) {
+	pn = VP_TO_PN(vp);
+	if (pn && (lowervp = pn->pn_lowervp)) {
 		VI_LOCK_FLAGS(lowervp, MTX_DUPOK);
 		VI_UNLOCK(vp);
 		vholdl(lowervp);
@@ -1043,13 +1077,13 @@
 		pn_key = pefs_node_key(pn);
 		buf = malloc(MAXNAMLEN + 1, M_PEFSBUF, M_WAITOK);
 
-		printf("%s: size = %d\n", __func__, o_resid - puio->uio_resid);
+		PEFSDEBUG("%s: size = %d\n", __func__, o_resid - puio->uio_resid);
 		pefs_chunk_shrink(pc, o_resid - puio->uio_resid);
 		while (1) {
 			mem = pefs_chunk_get(pc, &size, &arg);
 			if (mem == NULL)
 				break;
-			printf("%s: convert mem=%p; size=%d\n", __func__, mem, size);
+			PEFSDEBUG("%s: convert mem=%p; size=%d\n", __func__, mem, size);
 			pefs_readdir_decrypt(pn_key, pn->pn_flags, mem, size, buf, MAXNAMLEN + 1);
 		}
 		pefs_chunk_copy(pc, 0, uio);
@@ -1276,13 +1310,6 @@
 	if (!(pn->pn_flags & PN_HASKEY))
 		return (VOP_READLINK(lvp, uio, ap->a_cred));
 
-	/*
-	printf("%s: uio_offset=%ju, uio_resid=%u, uio_segflg:sysspace=%d, uio_rw=%x, ioveccnt=%d; iov_len[0]=%u\n",
-			__func__,
-			(intmax_t) uio->uio_offset, uio->uio_resid,
-			uio->uio_segflg == UIO_SYSSPACE, uio->uio_rw, uio->uio_iovcnt,
-			uio->uio_iov[0].iov_len);
-	*/
 	o_offset = uio->uio_offset;
 	o_resid = uio->uio_resid;
 	pc = pefs_chunk_create(o_resid);
@@ -1434,6 +1461,95 @@
 	return (error);
 }
 
+static int
+pefs_ioctl(struct vop_ioctl_args *ap)
+{
+	struct vnode *vp = ap->a_vp;
+	struct pefs_mount *pm = VFS_TO_PEFS(vp->v_mount);
+	struct pefs_xkey *xk = ap->a_data;
+	struct pefs_key *pk;
+	int error, i;
+
+	vn_lock(pm->pm_rootvp, LK_SHARED | LK_RETRY);
+	error = VOP_ACCESS(pm->pm_rootvp, VWRITE, ap->a_cred, ap->a_td);
+	VOP_UNLOCK(pm->pm_rootvp, 0);
+	if (error != 0)
+		return (error);
+
+	/*
+	 * Recycle all unused vnodes after adding/deleting keys to cleanup
+	 * caches. 
+	 */
+	switch (ap->a_command) {
+	case PEFS_GETKEY:
+		PEFSDEBUG("pefs_ioctl: get key: pm=%p, pxk_index=%d\n", pm, xk->pxk_index);
+		mtx_lock(&pm->pm_keys_lock);
+		i = 0;
+		TAILQ_FOREACH(pk, &pm->pm_keys, pk_entry) {
+			if (i++ == xk->pxk_index) {
+				memcpy(xk->pxk_keyid, pk->pk_keyid, PEFS_KEYID_SIZE);
+				xk->pxk_alg = pk->pk_alg;
+				break;
+			}
+		}
+		mtx_unlock(&pm->pm_keys_lock);
+		if (pk == NULL)
+			error = ENOENT;
+		break;
+	case PEFS_SETKEY:
+		mtx_lock(&pm->pm_keys_lock);
+		pk = pefs_key_lookup(pm, xk->pxk_keyid);
+		mtx_unlock(&pm->pm_keys_lock);
+		if (pk != NULL)
+			error = ENOTSUP; // FIXME
+		else
+			error = ENOENT;
+		PEFSDEBUG("pefs_ioctl: set key\n");
+		break;
+	case PEFS_ADDKEY:
+		PEFSDEBUG("pefs_ioctl: add key\n");
+		pk = pefs_key_get(xk->pxk_alg, xk->pxk_key, xk->pxk_keyid);
+		if (pk == NULL) {
+			error = ENOENT;
+			break;
+		}
+		error = pefs_key_add(pm, xk->pxk_index, pk);
+		if (error == 0)
+			vflush(vp->v_mount, 0, 0, ap->a_td);
+		else
+			pefs_key_release(pk);
+		break;
+	case PEFS_DELKEY:
+		PEFSDEBUG("pefs_ioctl: del key\n");
+		mtx_lock(&pm->pm_keys_lock);
+		pk = pefs_key_lookup(pm, xk->pxk_keyid);
+		if (pk != NULL) {
+			pefs_key_ref(pk);
+			pefs_key_remove(pm, pk);
+			mtx_unlock(&pm->pm_keys_lock);
+			vflush(vp->v_mount, 0, 0, ap->a_td);
+			pefs_flushkey(vp->v_mount, pk);
+			pefs_key_release(pk);
+		} else {
+			mtx_unlock(&pm->pm_keys_lock);
+			error = ENOENT;
+		}
+		break;
+	case PEFS_FLUSHKEYS:
+		PEFSDEBUG("pefs_ioctl: flush keys\n");
+		if (pefs_key_remove_all(pm)) {
+			vflush(vp->v_mount, 0, 0, ap->a_td);
+			pefs_flushkey(vp->v_mount, NULL);
+		}
+		break;
+	default:
+		error = ENOTTY;
+		break;
+	};
+
+	return (error);
+}
+
 /*
  * Global vfs data structures
  */
@@ -1473,4 +1589,6 @@
 	.vop_getpages =		vop_stdgetpages,
 	.vop_putpages =		vop_stdputpages,
 	.vop_fsync =		vop_stdfsync,
+	/* */
+	.vop_ioctl =		pefs_ioctl,
 };


More information about the p4-projects mailing list