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