]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/staging/pohmelfs/netfs.h
Merge branch 'omap-pool'
[linux-2.6-omap-h63xx.git] / drivers / staging / pohmelfs / netfs.h
diff --git a/drivers/staging/pohmelfs/netfs.h b/drivers/staging/pohmelfs/netfs.h
new file mode 100644 (file)
index 0000000..2ff21ae
--- /dev/null
@@ -0,0 +1,932 @@
+/*
+ * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __NETFS_H
+#define __NETFS_H
+
+#include <linux/types.h>
+#include <linux/connector.h>
+
+#define POHMELFS_CN_IDX                        5
+#define POHMELFS_CN_VAL                        0
+
+#define POHMELFS_CTLINFO_ACK           1
+#define POHMELFS_NOINFO_ACK            2
+
+
+/*
+ * Network command structure.
+ * Will be extended.
+ */
+struct netfs_cmd
+{
+       __u16                   cmd;    /* Command number */
+       __u16                   csize;  /* Attached crypto information size */
+       __u16                   cpad;   /* Attached padding size */
+       __u16                   ext;    /* External flags */
+       __u32                   size;   /* Size of the attached data */
+       __u32                   trans;  /* Transaction id */
+       __u64                   id;     /* Object ID to operate on. Used for feedback.*/
+       __u64                   start;  /* Start of the object. */
+       __u64                   iv;     /* IV sequence */
+       __u8                    data[0];
+};
+
+static inline void netfs_convert_cmd(struct netfs_cmd *cmd)
+{
+       cmd->id = __be64_to_cpu(cmd->id);
+       cmd->start = __be64_to_cpu(cmd->start);
+       cmd->iv = __be64_to_cpu(cmd->iv);
+       cmd->cmd = __be16_to_cpu(cmd->cmd);
+       cmd->ext = __be16_to_cpu(cmd->ext);
+       cmd->csize = __be16_to_cpu(cmd->csize);
+       cmd->cpad = __be16_to_cpu(cmd->cpad);
+       cmd->size = __be32_to_cpu(cmd->size);
+}
+
+#define NETFS_TRANS_SINGLE_DST         (1<<0)
+
+enum {
+       NETFS_READDIR   = 1,    /* Read directory for given inode number */
+       NETFS_READ_PAGE,        /* Read data page from the server */
+       NETFS_WRITE_PAGE,       /* Write data page to the server */
+       NETFS_CREATE,           /* Create directory entry */
+       NETFS_REMOVE,           /* Remove directory entry */
+
+       NETFS_LOOKUP,           /* Lookup single object */
+       NETFS_LINK,             /* Create a link */
+       NETFS_TRANS,            /* Transaction */
+       NETFS_OPEN,             /* Open intent */
+       NETFS_INODE_INFO,       /* Metadata cache coherency synchronization message */
+
+       NETFS_PAGE_CACHE,       /* Page cache invalidation message */
+       NETFS_READ_PAGES,       /* Read multiple contiguous pages in one go */
+       NETFS_RENAME,           /* Rename object */
+       NETFS_CAPABILITIES,     /* Capabilities of the client, for example supported crypto */
+       NETFS_LOCK,             /* Distributed lock message */
+
+       NETFS_XATTR_SET,        /* Set extended attribute */
+       NETFS_XATTR_GET,        /* Get extended attribute */
+       NETFS_CMD_MAX
+};
+
+enum {
+       POHMELFS_FLAGS_ADD = 0, /* Network state control message for ADD */
+       POHMELFS_FLAGS_DEL,     /* Network state control message for DEL */
+       POHMELFS_FLAGS_SHOW,    /* Network state control message for SHOW */
+       POHMELFS_FLAGS_CRYPTO,  /* Crypto data control message */
+};
+
+/*
+ * Always wanted to copy it from socket headers into public one,
+ * since they are __KERNEL__ protected there.
+ */
+#define _K_SS_MAXSIZE  128
+
+struct saddr
+{
+       unsigned short          sa_family;
+       char                    addr[_K_SS_MAXSIZE];
+};
+
+enum {
+       POHMELFS_CRYPTO_HASH = 0,
+       POHMELFS_CRYPTO_CIPHER,
+};
+
+struct pohmelfs_crypto
+{
+       unsigned int            idx;            /* Config index */
+       unsigned short          strlen;         /* Size of the attached crypto string including 0-byte
+                                                * "cbc(aes)" for example */
+       unsigned short          type;           /* HMAC, cipher, both */
+       unsigned int            keysize;        /* Key size */
+       unsigned char           data[0];        /* Algorithm string, key and IV */
+};
+
+/*
+ * Configuration command used to create table of different remote servers.
+ */
+struct pohmelfs_ctl
+{
+       unsigned int            idx;            /* Config index */
+       unsigned int            type;           /* Socket type */
+       unsigned int            proto;          /* Socket protocol */
+       unsigned int            addrlen;        /* Size of the address */
+       unsigned short          unused;         /* Align structure by 4 bytes */
+       struct saddr            addr;           /* Remote server address */
+};
+
+/*
+ * Ack for userspace about requested command.
+ */
+struct pohmelfs_cn_ack
+{
+       struct cn_msg           msg;
+       int                     error;
+       int                     msg_num;
+       int                     unused[3];
+       struct pohmelfs_ctl     ctl;
+};
+
+/*
+ * Inode info structure used to sync with server.
+ * Check what stat() returns.
+ */
+struct netfs_inode_info
+{
+       unsigned int            mode;
+       unsigned int            nlink;
+       unsigned int            uid;
+       unsigned int            gid;
+       unsigned int            blocksize;
+       unsigned int            padding;
+       __u64                   ino;
+       __u64                   blocks;
+       __u64                   rdev;
+       __u64                   size;
+       __u64                   version;
+};
+
+static inline void netfs_convert_inode_info(struct netfs_inode_info *info)
+{
+       info->mode = __cpu_to_be32(info->mode);
+       info->nlink = __cpu_to_be32(info->nlink);
+       info->uid = __cpu_to_be32(info->uid);
+       info->gid = __cpu_to_be32(info->gid);
+       info->blocksize = __cpu_to_be32(info->blocksize);
+       info->blocks = __cpu_to_be64(info->blocks);
+       info->rdev = __cpu_to_be64(info->rdev);
+       info->size = __cpu_to_be64(info->size);
+       info->version = __cpu_to_be64(info->version);
+       info->ino = __cpu_to_be64(info->ino);
+}
+
+/*
+ * Cache state machine.
+ */
+enum {
+       NETFS_COMMAND_PENDING = 0,      /* Command is being executed */
+       NETFS_INODE_REMOTE_SYNCED,      /* Inode was synced to server */
+       NETFS_INODE_REMOTE_DIR_SYNCED,  /* Inode (directory) was synced from the server */
+       NETFS_INODE_OWNED,              /* Inode is owned by given host */
+       NETFS_INODE_NEED_FLUSH,         /* Inode has to be flushed to the server */
+};
+
+/*
+ * POHMELFS capabilities: information about supported
+ * crypto operations (hash/cipher, modes, key sizes and so on),
+ * root informaion (used/available size, number of objects, permissions)
+ */
+enum pohmelfs_capabilities {
+       POHMELFS_CRYPTO_CAPABILITIES = 0,
+       POHMELFS_ROOT_CAPABILITIES,
+};
+
+/* Read-only mount */
+#define POHMELFS_FLAGS_RO              (1<<0)
+/* Extended attributes support on/off */
+#define POHMELFS_FLAGS_XATTR           (1<<1)
+
+struct netfs_root_capabilities
+{
+       __u64                   nr_files;
+       __u64                   used, avail;
+       __u64                   flags;
+};
+
+static inline void netfs_convert_root_capabilities(struct netfs_root_capabilities *cap)
+{
+       cap->nr_files = __cpu_to_be64(cap->nr_files);
+       cap->used = __cpu_to_be64(cap->used);
+       cap->avail = __cpu_to_be64(cap->avail);
+       cap->flags = __cpu_to_be64(cap->flags);
+}
+
+struct netfs_crypto_capabilities
+{
+       unsigned short          hash_strlen;    /* Hash string length, like "hmac(sha1) including 0 byte "*/
+       unsigned short          cipher_strlen;  /* Cipher string length with the same format */
+       unsigned int            cipher_keysize; /* Cipher key size */
+};
+
+static inline void netfs_convert_crypto_capabilities(struct netfs_crypto_capabilities *cap)
+{
+       cap->hash_strlen = __cpu_to_be16(cap->hash_strlen);
+       cap->cipher_strlen = __cpu_to_be16(cap->cipher_strlen);
+       cap->cipher_keysize = __cpu_to_be32(cap->cipher_keysize);
+}
+
+enum pohmelfs_lock_type {
+       POHMELFS_LOCK_GRAB      = (1<<15),
+
+       POHMELFS_READ_LOCK      = 0,
+       POHMELFS_WRITE_LOCK,
+};
+
+struct netfs_lock
+{
+       __u64                   start;
+       __u64                   ino;
+       __u32                   size;
+       __u32                   type;
+};
+
+static inline void netfs_convert_lock(struct netfs_lock *lock)
+{
+       lock->start = __cpu_to_be64(lock->start);
+       lock->ino = __cpu_to_be64(lock->ino);
+       lock->size = __cpu_to_be32(lock->size);
+       lock->type = __cpu_to_be32(lock->type);
+}
+
+#ifdef __KERNEL__
+
+#include <linux/kernel.h>
+#include <linux/completion.h>
+#include <linux/rbtree.h>
+#include <linux/net.h>
+#include <linux/poll.h>
+
+/*
+ * Private POHMELFS cache of objects in directory.
+ */
+struct pohmelfs_name
+{
+       struct rb_node          hash_node;
+
+       struct list_head        sync_create_entry;
+
+       u64                     ino;
+
+       u32                     hash;
+       u32                     mode;
+       u32                     len;
+
+       char                    *data;
+};
+
+/*
+ * POHMELFS inode. Main object.
+ */
+struct pohmelfs_inode
+{
+       struct list_head        inode_entry;            /* Entry in superblock list.
+                                                        * Objects which are not bound to dentry require to be dropped
+                                                        * in ->put_super()
+                                                        */
+       struct rb_root          hash_root;              /* The same, but indexed by name hash and len */
+       struct mutex            offset_lock;            /* Protect both above trees */
+
+       struct list_head        sync_create_list;       /* List of created but not yet synced to the server children */
+
+       unsigned int            drop_count;
+
+       int                     lock_type;              /* How this inode is locked: read or write */
+
+       int                     error;                  /* Transaction error for given inode */
+
+       long                    state;                  /* State machine above */
+
+       u64                     ino;                    /* Inode number */
+       u64                     total_len;              /* Total length of all children names, used to create offsets */
+
+       struct inode            vfs_inode;
+};
+
+struct netfs_trans;
+typedef int (* netfs_trans_complete_t)(struct page **pages, unsigned int page_num,
+               void *private, int err);
+
+struct netfs_state;
+struct pohmelfs_sb;
+
+struct netfs_trans
+{
+       /*
+        * Transaction header and attached contiguous data live here.
+        */
+       struct iovec                    iovec;
+
+       /*
+        * Pages attached to transaction.
+        */
+       struct page                     **pages;
+
+       /*
+        * List and protecting lock for transaction destination
+        * network states.
+        */
+       spinlock_t                      dst_lock;
+       struct list_head                dst_list;
+
+       /*
+        * Number of users for given transaction.
+        * For example each network state attached to transaction
+        * via dst_list increases it.
+        */
+       atomic_t                        refcnt;
+
+       /*
+        * Number of pages attached to given transaction.
+        * Some slots in above page array can be NULL, since
+        * for example page can be under writeback already,
+        * so we skip it in this transaction.
+        */
+       unsigned int                    page_num;
+
+       /*
+        * Transaction flags: single dst or broadcast and so on.
+        */
+       unsigned int                    flags;
+
+       /*
+        * Size of the data, which can be placed into
+        * iovec.iov_base area.
+        */
+       unsigned int                    total_size;
+
+       /*
+        * Number of pages to be sent to remote server.
+        * Usually equal to above page_num, but in case of partial
+        * writeback it can accumulate only pages already completed
+        * previous writeback.
+        */
+       unsigned int                    attached_pages;
+
+       /*
+        * Attached number of bytes in all above pages.
+        */
+       unsigned int                    attached_size;
+
+       /*
+        * Unique transacton generation number.
+        * Used as identity in the network state tree of transactions.
+        */
+       unsigned int                    gen;
+
+       /*
+        * Transaction completion status.
+        */
+       int                             result;
+
+       /*
+        * Superblock this transaction belongs to
+        */
+       struct pohmelfs_sb              *psb;
+
+       /*
+        * Crypto engine, which processed this transaction.
+        * Can be not NULL only if crypto engine holds encrypted pages.
+        */
+       struct pohmelfs_crypto_engine   *eng;
+
+       /* Private data */
+       void                            *private;
+
+       /* Completion callback, invoked just before transaction is destroyed */
+       netfs_trans_complete_t          complete;
+};
+
+static inline int netfs_trans_cur_len(struct netfs_trans *t)
+{
+       return (signed)(t->total_size - t->iovec.iov_len);
+}
+
+static inline void *netfs_trans_current(struct netfs_trans *t)
+{
+       return t->iovec.iov_base + t->iovec.iov_len;
+}
+
+struct netfs_trans *netfs_trans_alloc(struct pohmelfs_sb *psb, unsigned int size,
+               unsigned int flags, unsigned int nr);
+void netfs_trans_free(struct netfs_trans *t);
+int netfs_trans_finish(struct netfs_trans *t, struct pohmelfs_sb *psb);
+int netfs_trans_finish_send(struct netfs_trans *t, struct pohmelfs_sb *psb);
+
+static inline void netfs_trans_reset(struct netfs_trans *t)
+{
+       t->complete = NULL;
+}
+
+struct netfs_trans_dst
+{
+       struct list_head                trans_entry;
+       struct rb_node                  state_entry;
+
+       unsigned long                   send_time;
+
+       /*
+        * Times this transaction was resent to its old or new,
+        * depending on flags, destinations. When it reaches maximum
+        * allowed number, specified in superblock->trans_retries,
+        * transaction will be freed with ETIMEDOUT error.
+        */
+       unsigned int                    retries;
+
+       struct netfs_trans              *trans;
+       struct netfs_state              *state;
+};
+
+struct netfs_trans_dst *netfs_trans_search(struct netfs_state *st, unsigned int gen);
+void netfs_trans_drop_dst(struct netfs_trans_dst *dst);
+void netfs_trans_drop_dst_nostate(struct netfs_trans_dst *dst);
+void netfs_trans_drop_trans(struct netfs_trans *t, struct netfs_state *st);
+void netfs_trans_drop_last(struct netfs_trans *t, struct netfs_state *st);
+int netfs_trans_resend(struct netfs_trans *t, struct pohmelfs_sb *psb);
+int netfs_trans_remove_nolock(struct netfs_trans_dst *dst, struct netfs_state *st);
+
+int netfs_trans_init(void);
+void netfs_trans_exit(void);
+
+struct pohmelfs_crypto_engine
+{
+       u64                             iv;             /* Crypto IV for current operation */
+       unsigned long                   timeout;        /* Crypto waiting timeout */
+       unsigned int                    size;           /* Size of crypto scratchpad */
+       void                            *data;          /* Temporal crypto scratchpad */
+       /*
+        * Crypto operations performed on objects.
+        */
+       struct crypto_hash              *hash;
+       struct crypto_ablkcipher        *cipher;
+
+       struct pohmelfs_crypto_thread   *thread;        /* Crypto thread which hosts this engine */
+
+       struct page                     **pages;
+       unsigned int                    page_num;
+};
+
+struct pohmelfs_crypto_thread
+{
+       struct list_head                thread_entry;
+
+       struct task_struct              *thread;
+       struct pohmelfs_sb              *psb;
+
+       struct pohmelfs_crypto_engine   eng;
+
+       struct netfs_trans              *trans;
+
+       wait_queue_head_t               wait;
+       int                             error;
+
+       unsigned int                    size;
+       struct page                     *page;
+};
+
+void pohmelfs_crypto_thread_make_ready(struct pohmelfs_crypto_thread *th);
+
+/*
+ * Network state, attached to one server.
+ */
+struct netfs_state
+{
+       struct mutex            __state_lock;           /* Can not allow to use the same socket simultaneously */
+       struct mutex            __state_send_lock;
+       struct netfs_cmd        cmd;                    /* Cached command */
+       struct netfs_inode_info info;                   /* Cached inode info */
+
+       void                    *data;                  /* Cached some data */
+       unsigned int            size;                   /* Size of that data */
+
+       struct pohmelfs_sb      *psb;                   /* Superblock */
+
+       struct task_struct      *thread;                /* Async receiving thread */
+
+       /* Waiting/polling machinery */
+       wait_queue_t            wait;
+       wait_queue_head_t       *whead;
+       wait_queue_head_t       thread_wait;
+
+       struct mutex            trans_lock;
+       struct rb_root          trans_root;
+
+       struct pohmelfs_ctl     ctl;                    /* Remote peer */
+
+       struct socket           *socket;                /* Socket object */
+       struct socket           *read_socket;           /* Cached pointer to socket object.
+                                                        * Used to determine if between lock drops socket was changed.
+                                                        * Never used to read data or any kind of access.
+                                                        */
+       /*
+        * Crypto engines to process incoming data.
+        */
+       struct pohmelfs_crypto_engine   eng;
+
+       int                     need_reset;
+};
+
+int netfs_state_init(struct netfs_state *st);
+void netfs_state_exit(struct netfs_state *st);
+
+static inline void netfs_state_lock_send(struct netfs_state *st)
+{
+       mutex_lock(&st->__state_send_lock);
+}
+
+static inline int netfs_state_trylock_send(struct netfs_state *st)
+{
+       return mutex_trylock(&st->__state_send_lock);
+}
+
+static inline void netfs_state_unlock_send(struct netfs_state *st)
+{
+       BUG_ON(!mutex_is_locked(&st->__state_send_lock));
+
+       mutex_unlock(&st->__state_send_lock);
+}
+
+static inline void netfs_state_lock(struct netfs_state *st)
+{
+       mutex_lock(&st->__state_lock);
+}
+
+static inline void netfs_state_unlock(struct netfs_state *st)
+{
+       BUG_ON(!mutex_is_locked(&st->__state_lock));
+
+       mutex_unlock(&st->__state_lock);
+}
+
+static inline unsigned int netfs_state_poll(struct netfs_state *st)
+{
+       unsigned int revents = POLLHUP | POLLERR;
+
+       netfs_state_lock(st);
+       if (st->socket)
+               revents = st->socket->ops->poll(NULL, st->socket, NULL);
+       netfs_state_unlock(st);
+
+       return revents;
+}
+
+struct pohmelfs_config;
+
+struct pohmelfs_sb
+{
+       struct rb_root          mcache_root;
+       struct mutex            mcache_lock;
+       atomic_long_t           mcache_gen;
+       unsigned long           mcache_timeout;
+
+       unsigned int            idx;
+
+       unsigned int            trans_retries;
+
+       atomic_t                trans_gen;
+
+       unsigned int            crypto_attached_size;
+       unsigned int            crypto_align_size;
+
+       unsigned int            crypto_fail_unsupported;
+
+       unsigned int            crypto_thread_num;
+       struct list_head        crypto_active_list, crypto_ready_list;
+       struct mutex            crypto_thread_lock;
+
+       unsigned int            trans_max_pages;
+       unsigned long           trans_data_size;
+       unsigned long           trans_timeout;
+
+       unsigned long           drop_scan_timeout;
+       unsigned long           trans_scan_timeout;
+
+       unsigned long           wait_on_page_timeout;
+
+       struct list_head        flush_list;
+       struct list_head        drop_list;
+       spinlock_t              ino_lock;
+       u64                     ino;
+
+       /*
+        * Remote nodes POHMELFS connected to.
+        */
+       struct list_head        state_list;
+       struct mutex            state_lock;
+
+       /*
+        * Currently active state to request data from.
+        */
+       struct pohmelfs_config  *active_state;
+
+
+       wait_queue_head_t       wait;
+
+       /*
+        * Timed checks: stale transactions, inodes to be freed and so on.
+        */
+       struct delayed_work     dwork;
+       struct delayed_work     drop_dwork;
+
+       struct super_block      *sb;
+
+       /*
+        * Algorithm strings.
+        */
+       char                    *hash_string;
+       char                    *cipher_string;
+
+       u8                      *hash_key;
+       u8                      *cipher_key;
+
+       /*
+        * Algorithm string lengths.
+        */
+       unsigned int            hash_strlen;
+       unsigned int            cipher_strlen;
+       unsigned int            hash_keysize;
+       unsigned int            cipher_keysize;
+
+       /*
+        * Controls whether to perfrom crypto processing or not.
+        */
+       int                     perform_crypto;
+
+       /*
+        * POHMELFS statistics.
+        */
+       u64                     total_size;
+       u64                     avail_size;
+       atomic_long_t           total_inodes;
+
+       /*
+        * Xattr support, read-only and so on.
+        */
+       u64                     state_flags;
+
+       /*
+        * Temporary storage to detect changes in the wait queue.
+        */
+       long                    flags;
+};
+
+static inline void netfs_trans_update(struct netfs_cmd *cmd,
+               struct netfs_trans *t, unsigned int size)
+{
+       unsigned int sz = ALIGN(size, t->psb->crypto_align_size);
+
+       t->iovec.iov_len += sizeof(struct netfs_cmd) + sz;
+       cmd->cpad = __cpu_to_be16(sz - size);
+}
+
+static inline struct pohmelfs_sb *POHMELFS_SB(struct super_block *sb)
+{
+       return sb->s_fs_info;
+}
+
+static inline struct pohmelfs_inode *POHMELFS_I(struct inode *inode)
+{
+       return container_of(inode, struct pohmelfs_inode, vfs_inode);
+}
+
+static inline u64 pohmelfs_new_ino(struct pohmelfs_sb *psb)
+{
+       u64 ino;
+
+       spin_lock(&psb->ino_lock);
+       ino = psb->ino++;
+       spin_unlock(&psb->ino_lock);
+
+       return ino;
+}
+
+static inline void pohmelfs_put_inode(struct pohmelfs_inode *pi)
+{
+       struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
+
+       spin_lock(&psb->ino_lock);
+       list_move_tail(&pi->inode_entry, &psb->drop_list);
+       pi->drop_count++;
+       spin_unlock(&psb->ino_lock);
+}
+
+struct pohmelfs_config
+{
+       struct list_head        config_entry;
+
+       struct netfs_state      state;
+};
+
+struct pohmelfs_config_group
+{
+       /*
+        * Entry in the global config group list.
+        */
+       struct list_head        group_entry;
+
+       /*
+        * Index of the current group.
+        */
+       unsigned int            idx;
+       /*
+        * Number of config_list entries in this group entry.
+        */
+       unsigned int            num_entry;
+       /*
+        * Algorithm strings.
+        */
+       char                    *hash_string;
+       char                    *cipher_string;
+
+       /*
+        * Algorithm string lengths.
+        */
+       unsigned int            hash_strlen;
+       unsigned int            cipher_strlen;
+
+       /*
+        * Key and its size.
+        */
+       unsigned int            hash_keysize;
+       unsigned int            cipher_keysize;
+       u8                      *hash_key;
+       u8                      *cipher_key;
+
+       /*
+        * List of config entries (network state info) for given idx.
+        */
+       struct list_head        config_list;
+};
+
+int __init pohmelfs_config_init(void);
+void pohmelfs_config_exit(void);
+int pohmelfs_copy_config(struct pohmelfs_sb *psb);
+int pohmelfs_copy_crypto(struct pohmelfs_sb *psb);
+int pohmelfs_config_check(struct pohmelfs_config *config, int idx);
+int pohmelfs_state_init_one(struct pohmelfs_sb *psb, struct pohmelfs_config *conf);
+
+extern const struct file_operations pohmelfs_dir_fops;
+extern const struct inode_operations pohmelfs_dir_inode_ops;
+
+int pohmelfs_state_init(struct pohmelfs_sb *psb);
+void pohmelfs_state_exit(struct pohmelfs_sb *psb);
+void pohmelfs_state_flush_transactions(struct netfs_state *st);
+
+void pohmelfs_fill_inode(struct inode *inode, struct netfs_inode_info *info);
+
+void pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *n);
+void pohmelfs_free_names(struct pohmelfs_inode *parent);
+struct pohmelfs_name *pohmelfs_search_hash(struct pohmelfs_inode *pi, u32 hash);
+
+void pohmelfs_inode_del_inode(struct pohmelfs_sb *psb, struct pohmelfs_inode *pi);
+
+struct pohmelfs_inode *pohmelfs_create_entry_local(struct pohmelfs_sb *psb,
+       struct pohmelfs_inode *parent, struct qstr *str, u64 start, int mode);
+
+int pohmelfs_write_create_inode(struct pohmelfs_inode *pi);
+
+int pohmelfs_write_inode_create(struct inode *inode, struct netfs_trans *trans);
+int pohmelfs_remove_child(struct pohmelfs_inode *parent, struct pohmelfs_name *n);
+
+struct pohmelfs_inode *pohmelfs_new_inode(struct pohmelfs_sb *psb,
+               struct pohmelfs_inode *parent, struct qstr *str,
+               struct netfs_inode_info *info, int link);
+
+int pohmelfs_setattr(struct dentry *dentry, struct iattr *attr);
+int pohmelfs_setattr_raw(struct inode *inode, struct iattr *attr);
+
+int pohmelfs_meta_command(struct pohmelfs_inode *pi, unsigned int cmd_op, unsigned int flags,
+               netfs_trans_complete_t complete, void *priv, u64 start);
+int pohmelfs_meta_command_data(struct pohmelfs_inode *pi, u64 id, unsigned int cmd_op, char *addon,
+               unsigned int flags, netfs_trans_complete_t complete, void *priv, u64 start);
+
+void pohmelfs_check_states(struct pohmelfs_sb *psb);
+void pohmelfs_switch_active(struct pohmelfs_sb *psb);
+
+int pohmelfs_construct_path_string(struct pohmelfs_inode *pi, void *data, int len);
+int pohmelfs_path_length(struct pohmelfs_inode *pi);
+
+struct pohmelfs_crypto_completion
+{
+       struct completion       complete;
+       int                     error;
+};
+
+int pohmelfs_trans_crypt(struct netfs_trans *t, struct pohmelfs_sb *psb);
+void pohmelfs_crypto_exit(struct pohmelfs_sb *psb);
+int pohmelfs_crypto_init(struct pohmelfs_sb *psb);
+
+int pohmelfs_crypto_engine_init(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb);
+void pohmelfs_crypto_engine_exit(struct pohmelfs_crypto_engine *e);
+
+int pohmelfs_crypto_process_input_data(struct pohmelfs_crypto_engine *e, u64 iv,
+               void *data, struct page *page, unsigned int size);
+int pohmelfs_crypto_process_input_page(struct pohmelfs_crypto_engine *e,
+               struct page *page, unsigned int size, u64 iv);
+
+static inline u64 pohmelfs_gen_iv(struct netfs_trans *t)
+{
+       u64 iv = t->gen;
+
+       iv <<= 32;
+       iv |= ((unsigned long)t) & 0xffffffff;
+
+       return iv;
+}
+
+int pohmelfs_data_lock(struct pohmelfs_inode *pi, u64 start, u32 size, int type);
+int pohmelfs_data_unlock(struct pohmelfs_inode *pi, u64 start, u32 size, int type);
+int pohmelfs_data_lock_response(struct netfs_state *st);
+
+static inline int pohmelfs_need_lock(struct pohmelfs_inode *pi, int type)
+{
+       if (test_bit(NETFS_INODE_OWNED, &pi->state)) {
+               if (type == pi->lock_type)
+                       return 0;
+               if ((type == POHMELFS_READ_LOCK) && (pi->lock_type == POHMELFS_WRITE_LOCK))
+                       return 0;
+       }
+
+       if (!test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state))
+               return 0;
+
+       return 1;
+}
+
+int __init pohmelfs_mcache_init(void);
+void pohmelfs_mcache_exit(void);
+
+//#define CONFIG_POHMELFS_DEBUG
+
+#ifdef CONFIG_POHMELFS_DEBUG
+#define dprintka(f, a...) printk(f, ##a)
+#define dprintk(f, a...) printk("%d: " f, task_pid_vnr(current), ##a)
+#else
+#define dprintka(f, a...) do {} while (0)
+#define dprintk(f, a...) do {} while (0)
+#endif
+
+static inline void netfs_trans_get(struct netfs_trans *t)
+{
+       atomic_inc(&t->refcnt);
+}
+
+static inline void netfs_trans_put(struct netfs_trans *t)
+{
+       if (atomic_dec_and_test(&t->refcnt)) {
+               dprintk("%s: t: %p, gen: %u, err: %d.\n",
+                       __func__, t, t->gen, t->result);
+               if (t->complete)
+                       t->complete(t->pages, t->page_num,
+                               t->private, t->result);
+               netfs_trans_free(t);
+       }
+}
+
+struct pohmelfs_mcache
+{
+       struct rb_node                  mcache_entry;
+       struct completion               complete;
+
+       atomic_t                        refcnt;
+
+       u64                             gen;
+
+       void                            *data;
+       u64                             start;
+       u32                             size;
+       int                             err;
+
+       struct netfs_inode_info         info;
+};
+
+struct pohmelfs_mcache *pohmelfs_mcache_alloc(struct pohmelfs_sb *psb, u64 start,
+               unsigned int size, void *data);
+void pohmelfs_mcache_free(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m);
+struct pohmelfs_mcache *pohmelfs_mcache_search(struct pohmelfs_sb *psb, u64 gen);
+void pohmelfs_mcache_remove_locked(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m);
+
+static inline void pohmelfs_mcache_get(struct pohmelfs_mcache *m)
+{
+       atomic_inc(&m->refcnt);
+}
+
+static inline void pohmelfs_mcache_put(struct pohmelfs_sb *psb,
+               struct pohmelfs_mcache *m)
+{
+       if (atomic_dec_and_test(&m->refcnt))
+               pohmelfs_mcache_free(psb, m);
+}
+
+int pohmelfs_ftrans_init(void);
+void pohmelfs_ftrans_exit(void);
+void pohmelfs_ftrans_update(u64 id);
+int pohmelfs_ftrans_check(u64 id);
+void pohmelfs_ftrans_clean(u64 id);
+
+#endif /* __KERNEL__*/
+
+#endif /* __NETFS_H */