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