staging: pohmelfs: remove drivers/staging/pohmelfs
Evgeniy Polyakov [Wed, 8 Feb 2012 23:44:50 +0000 (02:44 +0300)]
New pohmelfs is coming, and it is time to remove deadly old design
https://lkml.org/lkml/2012/2/8/293

Signed-off-by: Evgeniy Polyakov <zbr@ioremap.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

14 files changed:
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/pohmelfs/Kconfig [deleted file]
drivers/staging/pohmelfs/Makefile [deleted file]
drivers/staging/pohmelfs/config.c [deleted file]
drivers/staging/pohmelfs/crypto.c [deleted file]
drivers/staging/pohmelfs/dir.c [deleted file]
drivers/staging/pohmelfs/inode.c [deleted file]
drivers/staging/pohmelfs/lock.c [deleted file]
drivers/staging/pohmelfs/mcache.c [deleted file]
drivers/staging/pohmelfs/net.c [deleted file]
drivers/staging/pohmelfs/netfs.h [deleted file]
drivers/staging/pohmelfs/path_entry.c [deleted file]
drivers/staging/pohmelfs/trans.c [deleted file]

index b31194c..9e63472 100644 (file)
@@ -60,8 +60,6 @@ source "drivers/staging/rts5139/Kconfig"
 
 source "drivers/staging/frontier/Kconfig"
 
-source "drivers/staging/pohmelfs/Kconfig"
-
 source "drivers/staging/phison/Kconfig"
 
 source "drivers/staging/line6/Kconfig"
index b5813c4..943e148 100644 (file)
@@ -22,7 +22,6 @@ obj-$(CONFIG_R8712U)          += rtl8712/
 obj-$(CONFIG_RTS_PSTOR)                += rts_pstor/
 obj-$(CONFIG_RTS5139)          += rts5139/
 obj-$(CONFIG_TRANZPORT)                += frontier/
-obj-$(CONFIG_POHMELFS)         += pohmelfs/
 obj-$(CONFIG_IDE_PHISON)       += phison/
 obj-$(CONFIG_LINE6_USB)                += line6/
 obj-$(CONFIG_USB_SERIAL_QUATECH2)      += serqt_usb2/
diff --git a/drivers/staging/pohmelfs/Kconfig b/drivers/staging/pohmelfs/Kconfig
deleted file mode 100644 (file)
index 8d53b1a..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-config POHMELFS
-       tristate "POHMELFS filesystem support"
-       depends on NET
-       select CONNECTOR
-       select CRYPTO
-       select CRYPTO_BLKCIPHER
-       select CRYPTO_HMAC
-       help
-         POHMELFS stands for Parallel Optimized Host Message Exchange Layered
-         File System.  This is a network filesystem which supports coherent
-         caching of data and metadata on clients.
-
-config POHMELFS_DEBUG
-       bool "POHMELFS debugging"
-       depends on POHMELFS
-       default n
-       help
-         Turns on excessive POHMELFS debugging facilities.
-         You usually do not want to slow things down noticeably and get really
-         lots of kernel messages in syslog.
diff --git a/drivers/staging/pohmelfs/Makefile b/drivers/staging/pohmelfs/Makefile
deleted file mode 100644 (file)
index 196561c..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_POHMELFS) += pohmelfs.o
-
-pohmelfs-y := inode.o config.o dir.o net.o path_entry.o trans.o crypto.o lock.o mcache.o
diff --git a/drivers/staging/pohmelfs/config.c b/drivers/staging/pohmelfs/config.c
deleted file mode 100644 (file)
index b6c42cb..0000000
+++ /dev/null
@@ -1,611 +0,0 @@
-/*
- * 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/connector.h>
-#include <linux/crypto.h>
-#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/string.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-
-#include "netfs.h"
-
-/*
- * Global configuration list.
- * Each client can be asked to get one of them.
- *
- * Allows to provide remote server address (ipv4/v6/whatever), port
- * and so on via kernel connector.
- */
-
-static struct cb_id pohmelfs_cn_id = {.idx = POHMELFS_CN_IDX, .val = POHMELFS_CN_VAL};
-static LIST_HEAD(pohmelfs_config_list);
-static DEFINE_MUTEX(pohmelfs_config_lock);
-
-static inline int pohmelfs_config_eql(struct pohmelfs_ctl *sc, struct pohmelfs_ctl *ctl)
-{
-       if (sc->idx == ctl->idx && sc->type == ctl->type &&
-                       sc->proto == ctl->proto &&
-                       sc->addrlen == ctl->addrlen &&
-                       !memcmp(&sc->addr, &ctl->addr, ctl->addrlen))
-               return 1;
-
-       return 0;
-}
-
-static struct pohmelfs_config_group *pohmelfs_find_config_group(unsigned int idx)
-{
-       struct pohmelfs_config_group *g, *group = NULL;
-
-       list_for_each_entry(g, &pohmelfs_config_list, group_entry) {
-               if (g->idx == idx) {
-                       group = g;
-                       break;
-               }
-       }
-
-       return group;
-}
-
-static struct pohmelfs_config_group *pohmelfs_find_create_config_group(unsigned int idx)
-{
-       struct pohmelfs_config_group *g;
-
-       g = pohmelfs_find_config_group(idx);
-       if (g)
-               return g;
-
-       g = kzalloc(sizeof(struct pohmelfs_config_group), GFP_KERNEL);
-       if (!g)
-               return NULL;
-
-       INIT_LIST_HEAD(&g->config_list);
-       g->idx = idx;
-       g->num_entry = 0;
-
-       list_add_tail(&g->group_entry, &pohmelfs_config_list);
-
-       return g;
-}
-
-static inline void pohmelfs_insert_config_entry(struct pohmelfs_sb *psb, struct pohmelfs_config *dst)
-{
-       struct pohmelfs_config *tmp;
-
-       INIT_LIST_HEAD(&dst->config_entry);
-
-       list_for_each_entry(tmp, &psb->state_list, config_entry) {
-               if (dst->state.ctl.prio > tmp->state.ctl.prio)
-                       list_add_tail(&dst->config_entry, &tmp->config_entry);
-       }
-       if (list_empty(&dst->config_entry))
-               list_add_tail(&dst->config_entry, &psb->state_list);
-}
-
-static int pohmelfs_move_config_entry(struct pohmelfs_sb *psb,
-               struct pohmelfs_config *dst, struct pohmelfs_config *new)
-{
-       if ((dst->state.ctl.prio == new->state.ctl.prio) &&
-               (dst->state.ctl.perm == new->state.ctl.perm))
-               return 0;
-
-       dprintk("%s: dst: prio: %d, perm: %x, new: prio: %d, perm: %d.\n",
-                       __func__, dst->state.ctl.prio, dst->state.ctl.perm,
-                       new->state.ctl.prio, new->state.ctl.perm);
-       dst->state.ctl.prio = new->state.ctl.prio;
-       dst->state.ctl.perm = new->state.ctl.perm;
-
-       list_del_init(&dst->config_entry);
-       pohmelfs_insert_config_entry(psb, dst);
-       return 0;
-}
-
-/*
- * pohmelfs_copy_config() is used to copy new state configs from the
- * config group (controlled by the netlink messages) into the superblock.
- * This happens either at startup time where no transactions can access
- * the list of the configs (and thus list of the network states), or at
- * run-time, where it is protected by the psb->state_lock.
- */
-int pohmelfs_copy_config(struct pohmelfs_sb *psb)
-{
-       struct pohmelfs_config_group *g;
-       struct pohmelfs_config *c, *dst;
-       int err = -ENODEV;
-
-       mutex_lock(&pohmelfs_config_lock);
-
-       g = pohmelfs_find_config_group(psb->idx);
-       if (!g)
-               goto out_unlock;
-
-       /*
-        * Run over all entries in given config group and try to create and
-        * initialize those, which do not exist in superblock list.
-        * Skip all existing entries.
-        */
-
-       list_for_each_entry(c, &g->config_list, config_entry) {
-               err = 0;
-               list_for_each_entry(dst, &psb->state_list, config_entry) {
-                       if (pohmelfs_config_eql(&dst->state.ctl, &c->state.ctl)) {
-                               err = pohmelfs_move_config_entry(psb, dst, c);
-                               if (!err)
-                                       err = -EEXIST;
-                               break;
-                       }
-               }
-
-               if (err)
-                       continue;
-
-               dst = kzalloc(sizeof(struct pohmelfs_config), GFP_KERNEL);
-               if (!dst) {
-                       err = -ENOMEM;
-                       break;
-               }
-
-               memcpy(&dst->state.ctl, &c->state.ctl, sizeof(struct pohmelfs_ctl));
-
-               pohmelfs_insert_config_entry(psb, dst);
-
-               err = pohmelfs_state_init_one(psb, dst);
-               if (err) {
-                       list_del(&dst->config_entry);
-                       kfree(dst);
-               }
-
-               err = 0;
-       }
-
-out_unlock:
-       mutex_unlock(&pohmelfs_config_lock);
-
-       return err;
-}
-
-int pohmelfs_copy_crypto(struct pohmelfs_sb *psb)
-{
-       struct pohmelfs_config_group *g;
-       int err = -ENOENT;
-
-       mutex_lock(&pohmelfs_config_lock);
-       g = pohmelfs_find_config_group(psb->idx);
-       if (!g)
-               goto err_out_exit;
-
-       if (g->hash_string) {
-               err = -ENOMEM;
-               psb->hash_string = kstrdup(g->hash_string, GFP_KERNEL);
-               if (!psb->hash_string)
-                       goto err_out_exit;
-               psb->hash_strlen = g->hash_strlen;
-       }
-
-       if (g->cipher_string) {
-               psb->cipher_string = kstrdup(g->cipher_string, GFP_KERNEL);
-               if (!psb->cipher_string)
-                       goto err_out_free_hash_string;
-               psb->cipher_strlen = g->cipher_strlen;
-       }
-
-       if (g->hash_keysize) {
-               psb->hash_key = kmemdup(g->hash_key, g->hash_keysize,
-                                       GFP_KERNEL);
-               if (!psb->hash_key)
-                       goto err_out_free_cipher_string;
-               psb->hash_keysize = g->hash_keysize;
-       }
-
-       if (g->cipher_keysize) {
-               psb->cipher_key = kmemdup(g->cipher_key, g->cipher_keysize,
-                                         GFP_KERNEL);
-               if (!psb->cipher_key)
-                       goto err_out_free_hash;
-               psb->cipher_keysize = g->cipher_keysize;
-       }
-
-       mutex_unlock(&pohmelfs_config_lock);
-
-       return 0;
-
-err_out_free_hash:
-       kfree(psb->hash_key);
-err_out_free_cipher_string:
-       kfree(psb->cipher_string);
-err_out_free_hash_string:
-       kfree(psb->hash_string);
-err_out_exit:
-       mutex_unlock(&pohmelfs_config_lock);
-       return err;
-}
-
-static int pohmelfs_send_reply(int err, int msg_num, int action, struct cn_msg *msg, struct pohmelfs_ctl *ctl)
-{
-       struct pohmelfs_cn_ack *ack;
-
-       ack = kzalloc(sizeof(struct pohmelfs_cn_ack), GFP_KERNEL);
-       if (!ack)
-               return -ENOMEM;
-
-       memcpy(&ack->msg, msg, sizeof(struct cn_msg));
-
-       if (action == POHMELFS_CTLINFO_ACK)
-               memcpy(&ack->ctl, ctl, sizeof(struct pohmelfs_ctl));
-
-       ack->msg.len = sizeof(struct pohmelfs_cn_ack) - sizeof(struct cn_msg);
-       ack->msg.ack = msg->ack + 1;
-       ack->error = err;
-       ack->msg_num = msg_num;
-
-       cn_netlink_send(&ack->msg, 0, GFP_KERNEL);
-       kfree(ack);
-       return 0;
-}
-
-static int pohmelfs_cn_disp(struct cn_msg *msg)
-{
-       struct pohmelfs_config_group *g;
-       struct pohmelfs_ctl *ctl = (struct pohmelfs_ctl *)msg->data;
-       struct pohmelfs_config *c, *tmp;
-       int err = 0, i = 1;
-
-       if (msg->len != sizeof(struct pohmelfs_ctl))
-               return -EBADMSG;
-
-       mutex_lock(&pohmelfs_config_lock);
-
-       g = pohmelfs_find_config_group(ctl->idx);
-       if (!g) {
-               pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL);
-               goto out_unlock;
-       }
-
-       list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) {
-               struct pohmelfs_ctl *sc = &c->state.ctl;
-               if (pohmelfs_send_reply(err, g->num_entry - i, POHMELFS_CTLINFO_ACK, msg, sc)) {
-                       err = -ENOMEM;
-                       goto out_unlock;
-               }
-               i += 1;
-       }
-
- out_unlock:
-       mutex_unlock(&pohmelfs_config_lock);
-       return err;
-}
-
-static int pohmelfs_cn_dump(struct cn_msg *msg)
-{
-       struct pohmelfs_config_group *g;
-       struct pohmelfs_config *c, *tmp;
-       int err = 0, i = 1;
-       int total_msg = 0;
-
-       if (msg->len != sizeof(struct pohmelfs_ctl))
-               return -EBADMSG;
-
-       mutex_lock(&pohmelfs_config_lock);
-
-       list_for_each_entry(g, &pohmelfs_config_list, group_entry)
-               total_msg += g->num_entry;
-       if (total_msg == 0) {
-               if (pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL))
-                       err = -ENOMEM;
-               goto out_unlock;
-       }
-
-       list_for_each_entry(g, &pohmelfs_config_list, group_entry) {
-               list_for_each_entry_safe(c, tmp, &g->config_list,
-                                        config_entry) {
-                       struct pohmelfs_ctl *sc = &c->state.ctl;
-                       if (pohmelfs_send_reply(err, total_msg - i,
-                                               POHMELFS_CTLINFO_ACK, msg,
-                                               sc)) {
-                               err = -ENOMEM;
-                               goto out_unlock;
-                       }
-                       i += 1;
-               }
-       }
-
-out_unlock:
-       mutex_unlock(&pohmelfs_config_lock);
-       return err;
-}
-
-static int pohmelfs_cn_flush(struct cn_msg *msg)
-{
-       struct pohmelfs_config_group *g;
-       struct pohmelfs_ctl *ctl = (struct pohmelfs_ctl *)msg->data;
-       struct pohmelfs_config *c, *tmp;
-       int err = 0;
-
-       if (msg->len != sizeof(struct pohmelfs_ctl))
-               return -EBADMSG;
-
-       mutex_lock(&pohmelfs_config_lock);
-
-       if (ctl->idx != POHMELFS_NULL_IDX) {
-               g = pohmelfs_find_config_group(ctl->idx);
-
-               if (!g)
-                       goto out_unlock;
-
-               list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) {
-                       list_del(&c->config_entry);
-                       g->num_entry--;
-                       kfree(c);
-               }
-       } else {
-               list_for_each_entry(g, &pohmelfs_config_list, group_entry) {
-                       list_for_each_entry_safe(c, tmp, &g->config_list,
-                                                config_entry) {
-                               list_del(&c->config_entry);
-                               g->num_entry--;
-                               kfree(c);
-                       }
-               }
-       }
-
-out_unlock:
-       mutex_unlock(&pohmelfs_config_lock);
-       pohmelfs_cn_dump(msg);
-
-       return err;
-}
-
-static int pohmelfs_modify_config(struct pohmelfs_ctl *old, struct pohmelfs_ctl *new)
-{
-       old->perm = new->perm;
-       old->prio = new->prio;
-       return 0;
-}
-
-static int pohmelfs_cn_ctl(struct cn_msg *msg, int action)
-{
-       struct pohmelfs_config_group *g;
-       struct pohmelfs_ctl *ctl = (struct pohmelfs_ctl *)msg->data;
-       struct pohmelfs_config *c, *tmp;
-       int err = 0;
-
-       if (msg->len != sizeof(struct pohmelfs_ctl))
-               return -EBADMSG;
-
-       mutex_lock(&pohmelfs_config_lock);
-
-       g = pohmelfs_find_create_config_group(ctl->idx);
-       if (!g) {
-               err = -ENOMEM;
-               goto out_unlock;
-       }
-
-       list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) {
-               struct pohmelfs_ctl *sc = &c->state.ctl;
-
-               if (pohmelfs_config_eql(sc, ctl)) {
-                       if (action == POHMELFS_FLAGS_ADD) {
-                               err = -EEXIST;
-                               goto out_unlock;
-                       } else if (action == POHMELFS_FLAGS_DEL) {
-                               list_del(&c->config_entry);
-                               g->num_entry--;
-                               kfree(c);
-                               goto out_unlock;
-                       } else if (action == POHMELFS_FLAGS_MODIFY) {
-                               err = pohmelfs_modify_config(sc, ctl);
-                               goto out_unlock;
-                       } else {
-                               err = -EEXIST;
-                               goto out_unlock;
-                       }
-               }
-       }
-       if (action == POHMELFS_FLAGS_DEL) {
-               err = -EBADMSG;
-               goto out_unlock;
-       }
-
-       c = kzalloc(sizeof(struct pohmelfs_config), GFP_KERNEL);
-       if (!c) {
-               err = -ENOMEM;
-               goto out_unlock;
-       }
-       memcpy(&c->state.ctl, ctl, sizeof(struct pohmelfs_ctl));
-       g->num_entry++;
-
-       list_add_tail(&c->config_entry, &g->config_list);
-
- out_unlock:
-       mutex_unlock(&pohmelfs_config_lock);
-       if (pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL))
-               err = -ENOMEM;
-
-       return err;
-}
-
-static int pohmelfs_crypto_hash_init(struct pohmelfs_config_group *g, struct pohmelfs_crypto *c)
-{
-       char *algo = (char *)c->data;
-       u8 *key = (u8 *)(algo + c->strlen);
-
-       if (g->hash_string)
-               return -EEXIST;
-
-       g->hash_string = kstrdup(algo, GFP_KERNEL);
-       if (!g->hash_string)
-               return -ENOMEM;
-       g->hash_strlen = c->strlen;
-       g->hash_keysize = c->keysize;
-
-       g->hash_key = kmemdup(key, c->keysize, GFP_KERNEL);
-       if (!g->hash_key) {
-               kfree(g->hash_string);
-               return -ENOMEM;
-       }
-
-       return 0;
-}
-
-static int pohmelfs_crypto_cipher_init(struct pohmelfs_config_group *g, struct pohmelfs_crypto *c)
-{
-       char *algo = (char *)c->data;
-       u8 *key = (u8 *)(algo + c->strlen);
-
-       if (g->cipher_string)
-               return -EEXIST;
-
-       g->cipher_string = kstrdup(algo, GFP_KERNEL);
-       if (!g->cipher_string)
-               return -ENOMEM;
-       g->cipher_strlen = c->strlen;
-       g->cipher_keysize = c->keysize;
-
-       g->cipher_key = kmemdup(key, c->keysize, GFP_KERNEL);
-       if (!g->cipher_key) {
-               kfree(g->cipher_string);
-               return -ENOMEM;
-       }
-
-       return 0;
-}
-
-static int pohmelfs_cn_crypto(struct cn_msg *msg)
-{
-       struct pohmelfs_crypto *crypto = (struct pohmelfs_crypto *)msg->data;
-       struct pohmelfs_config_group *g;
-       int err = 0;
-
-       dprintk("%s: idx: %u, strlen: %u, type: %u, keysize: %u, algo: %s.\n",
-                       __func__, crypto->idx, crypto->strlen, crypto->type,
-                       crypto->keysize, (char *)crypto->data);
-
-       mutex_lock(&pohmelfs_config_lock);
-       g = pohmelfs_find_create_config_group(crypto->idx);
-       if (!g) {
-               err = -ENOMEM;
-               goto out_unlock;
-       }
-
-       switch (crypto->type) {
-       case POHMELFS_CRYPTO_HASH:
-                       err = pohmelfs_crypto_hash_init(g, crypto);
-                       break;
-       case POHMELFS_CRYPTO_CIPHER:
-                       err = pohmelfs_crypto_cipher_init(g, crypto);
-                       break;
-       default:
-                       err = -ENOTSUPP;
-                       break;
-       }
-
-out_unlock:
-       mutex_unlock(&pohmelfs_config_lock);
-       if (pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL))
-               err = -ENOMEM;
-
-       return err;
-}
-
-static void pohmelfs_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
-{
-       int err;
-
-       if (!cap_raised(current_cap(), CAP_SYS_ADMIN))
-               return;
-
-       switch (msg->flags) {
-       case POHMELFS_FLAGS_ADD:
-       case POHMELFS_FLAGS_DEL:
-       case POHMELFS_FLAGS_MODIFY:
-                       err = pohmelfs_cn_ctl(msg, msg->flags);
-                       break;
-       case POHMELFS_FLAGS_FLUSH:
-                       err = pohmelfs_cn_flush(msg);
-                       break;
-       case POHMELFS_FLAGS_SHOW:
-                       err = pohmelfs_cn_disp(msg);
-                       break;
-       case POHMELFS_FLAGS_DUMP:
-                       err = pohmelfs_cn_dump(msg);
-                       break;
-       case POHMELFS_FLAGS_CRYPTO:
-                       err = pohmelfs_cn_crypto(msg);
-                       break;
-       default:
-                       err = -ENOSYS;
-                       break;
-       }
-}
-
-int pohmelfs_config_check(struct pohmelfs_config *config, int idx)
-{
-       struct pohmelfs_ctl *ctl = &config->state.ctl;
-       struct pohmelfs_config *tmp;
-       int err = -ENOENT;
-       struct pohmelfs_ctl *sc;
-       struct pohmelfs_config_group *g;
-
-       mutex_lock(&pohmelfs_config_lock);
-
-       g = pohmelfs_find_config_group(ctl->idx);
-       if (g) {
-               list_for_each_entry(tmp, &g->config_list, config_entry) {
-                       sc = &tmp->state.ctl;
-
-                       if (pohmelfs_config_eql(sc, ctl)) {
-                               err = 0;
-                               break;
-                       }
-               }
-       }
-
-       mutex_unlock(&pohmelfs_config_lock);
-
-       return err;
-}
-
-int __init pohmelfs_config_init(void)
-{
-       /* XXX remove (void *) cast when vanilla connector got synced */
-       return cn_add_callback(&pohmelfs_cn_id, "pohmelfs", (void *)pohmelfs_cn_callback);
-}
-
-void pohmelfs_config_exit(void)
-{
-       struct pohmelfs_config *c, *tmp;
-       struct pohmelfs_config_group *g, *gtmp;
-
-       cn_del_callback(&pohmelfs_cn_id);
-
-       mutex_lock(&pohmelfs_config_lock);
-       list_for_each_entry_safe(g, gtmp, &pohmelfs_config_list, group_entry) {
-               list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) {
-                       list_del(&c->config_entry);
-                       kfree(c);
-               }
-
-               list_del(&g->group_entry);
-
-               kfree(g->hash_string);
-
-               kfree(g->cipher_string);
-
-               kfree(g);
-       }
-       mutex_unlock(&pohmelfs_config_lock);
-}
diff --git a/drivers/staging/pohmelfs/crypto.c b/drivers/staging/pohmelfs/crypto.c
deleted file mode 100644 (file)
index ad92771..0000000
+++ /dev/null
@@ -1,878 +0,0 @@
-/*
- * 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.
- */
-
-#include <linux/crypto.h>
-#include <linux/highmem.h>
-#include <linux/kthread.h>
-#include <linux/pagemap.h>
-#include <linux/scatterlist.h>
-#include <linux/slab.h>
-
-#include "netfs.h"
-
-static struct crypto_hash *pohmelfs_init_hash(struct pohmelfs_sb *psb)
-{
-       int err;
-       struct crypto_hash *hash;
-
-       hash = crypto_alloc_hash(psb->hash_string, 0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR(hash)) {
-               err = PTR_ERR(hash);
-               dprintk("%s: idx: %u: failed to allocate hash '%s', err: %d.\n",
-                               __func__, psb->idx, psb->hash_string, err);
-               goto err_out_exit;
-       }
-
-       psb->crypto_attached_size = crypto_hash_digestsize(hash);
-
-       if (!psb->hash_keysize)
-               return hash;
-
-       err = crypto_hash_setkey(hash, psb->hash_key, psb->hash_keysize);
-       if (err) {
-               dprintk("%s: idx: %u: failed to set key for hash '%s', err: %d.\n",
-                               __func__, psb->idx, psb->hash_string, err);
-               goto err_out_free;
-       }
-
-       return hash;
-
-err_out_free:
-       crypto_free_hash(hash);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-static struct crypto_ablkcipher *pohmelfs_init_cipher(struct pohmelfs_sb *psb)
-{
-       int err = -EINVAL;
-       struct crypto_ablkcipher *cipher;
-
-       if (!psb->cipher_keysize)
-               goto err_out_exit;
-
-       cipher = crypto_alloc_ablkcipher(psb->cipher_string, 0, 0);
-       if (IS_ERR(cipher)) {
-               err = PTR_ERR(cipher);
-               dprintk("%s: idx: %u: failed to allocate cipher '%s', err: %d.\n",
-                               __func__, psb->idx, psb->cipher_string, err);
-               goto err_out_exit;
-       }
-
-       crypto_ablkcipher_clear_flags(cipher, ~0);
-
-       err = crypto_ablkcipher_setkey(cipher, psb->cipher_key, psb->cipher_keysize);
-       if (err) {
-               dprintk("%s: idx: %u: failed to set key for cipher '%s', err: %d.\n",
-                               __func__, psb->idx, psb->cipher_string, err);
-               goto err_out_free;
-       }
-
-       return cipher;
-
-err_out_free:
-       crypto_free_ablkcipher(cipher);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-int pohmelfs_crypto_engine_init(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb)
-{
-       int err;
-
-       e->page_num = 0;
-
-       e->size = PAGE_SIZE;
-       e->data = kmalloc(e->size, GFP_KERNEL);
-       if (!e->data) {
-               err = -ENOMEM;
-               goto err_out_exit;
-       }
-
-       if (psb->hash_string) {
-               e->hash = pohmelfs_init_hash(psb);
-               if (IS_ERR(e->hash)) {
-                       err = PTR_ERR(e->hash);
-                       e->hash = NULL;
-                       goto err_out_free;
-               }
-       }
-
-       if (psb->cipher_string) {
-               e->cipher = pohmelfs_init_cipher(psb);
-               if (IS_ERR(e->cipher)) {
-                       err = PTR_ERR(e->cipher);
-                       e->cipher = NULL;
-                       goto err_out_free_hash;
-               }
-       }
-
-       return 0;
-
-err_out_free_hash:
-       crypto_free_hash(e->hash);
-err_out_free:
-       kfree(e->data);
-err_out_exit:
-       return err;
-}
-
-void pohmelfs_crypto_engine_exit(struct pohmelfs_crypto_engine *e)
-{
-       crypto_free_hash(e->hash);
-       crypto_free_ablkcipher(e->cipher);
-       kfree(e->data);
-}
-
-static void pohmelfs_crypto_complete(struct crypto_async_request *req, int err)
-{
-       struct pohmelfs_crypto_completion *c = req->data;
-
-       if (err == -EINPROGRESS)
-               return;
-
-       dprintk("%s: req: %p, err: %d.\n", __func__, req, err);
-       c->error = err;
-       complete(&c->complete);
-}
-
-static int pohmelfs_crypto_process(struct ablkcipher_request *req,
-               struct scatterlist *sg_dst, struct scatterlist *sg_src,
-               void *iv, int enc, unsigned long timeout)
-{
-       struct pohmelfs_crypto_completion complete;
-       int err;
-
-       init_completion(&complete.complete);
-       complete.error = -EINPROGRESS;
-
-       ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-                                       pohmelfs_crypto_complete, &complete);
-
-       ablkcipher_request_set_crypt(req, sg_src, sg_dst, sg_src->length, iv);
-
-       if (enc)
-               err = crypto_ablkcipher_encrypt(req);
-       else
-               err = crypto_ablkcipher_decrypt(req);
-
-       switch (err) {
-       case -EINPROGRESS:
-       case -EBUSY:
-               err = wait_for_completion_interruptible_timeout(&complete.complete,
-                                       timeout);
-               if (!err)
-                       err = -ETIMEDOUT;
-               else if (err > 0)
-                       err = complete.error;
-               break;
-       default:
-               break;
-       }
-
-       return err;
-}
-
-int pohmelfs_crypto_process_input_data(struct pohmelfs_crypto_engine *e, u64 cmd_iv,
-               void *data, struct page *page, unsigned int size)
-{
-       int err;
-       struct scatterlist sg;
-
-       if (!e->cipher && !e->hash)
-               return 0;
-
-       dprintk("%s: eng: %p, iv: %llx, data: %p, page: %p/%lu, size: %u.\n",
-               __func__, e, cmd_iv, data, page, (page) ? page->index : 0, size);
-
-       if (data) {
-               sg_init_one(&sg, data, size);
-       } else {
-               sg_init_table(&sg, 1);
-               sg_set_page(&sg, page, size, 0);
-       }
-
-       if (e->cipher) {
-               struct ablkcipher_request *req = e->data + crypto_hash_digestsize(e->hash);
-               u8 iv[32];
-
-               memset(iv, 0, sizeof(iv));
-               memcpy(iv, &cmd_iv, sizeof(cmd_iv));
-
-               ablkcipher_request_set_tfm(req, e->cipher);
-
-               err = pohmelfs_crypto_process(req, &sg, &sg, iv, 0, e->timeout);
-               if (err)
-                       goto err_out_exit;
-       }
-
-       if (e->hash) {
-               struct hash_desc desc;
-               void *dst = e->data + e->size/2;
-
-               desc.tfm = e->hash;
-               desc.flags = 0;
-
-               err = crypto_hash_init(&desc);
-               if (err)
-                       goto err_out_exit;
-
-               err = crypto_hash_update(&desc, &sg, size);
-               if (err)
-                       goto err_out_exit;
-
-               err = crypto_hash_final(&desc, dst);
-               if (err)
-                       goto err_out_exit;
-
-               err = !!memcmp(dst, e->data, crypto_hash_digestsize(e->hash));
-
-               if (err) {
-#ifdef CONFIG_POHMELFS_DEBUG
-                       unsigned int i;
-                       unsigned char *recv = e->data, *calc = dst;
-
-                       dprintk("%s: eng: %p, hash: %p, cipher: %p: iv : %llx, hash mismatch (recv/calc): ",
-                                       __func__, e, e->hash, e->cipher, cmd_iv);
-                       for (i = 0; i < crypto_hash_digestsize(e->hash); ++i) {
-#if 0
-                               dprintka("%02x ", recv[i]);
-                               if (recv[i] != calc[i]) {
-                                       dprintka("| calc byte: %02x.\n", calc[i]);
-                                       break;
-                               }
-#else
-                               dprintka("%02x/%02x ", recv[i], calc[i]);
-#endif
-                       }
-                       dprintk("\n");
-#endif
-                       goto err_out_exit;
-               } else {
-                       dprintk("%s: eng: %p, hash: %p, cipher: %p: hashes matched.\n",
-                                       __func__, e, e->hash, e->cipher);
-               }
-       }
-
-       dprintk("%s: eng: %p, size: %u, hash: %p, cipher: %p: completed.\n",
-                       __func__, e, e->size, e->hash, e->cipher);
-
-       return 0;
-
-err_out_exit:
-       dprintk("%s: eng: %p, hash: %p, cipher: %p: err: %d.\n",
-                       __func__, e, e->hash, e->cipher, err);
-       return err;
-}
-
-static int pohmelfs_trans_iter(struct netfs_trans *t, struct pohmelfs_crypto_engine *e,
-               int (*iterator) (struct pohmelfs_crypto_engine *e,
-                                 struct scatterlist *dst,
-                                 struct scatterlist *src))
-{
-       void *data = t->iovec.iov_base + sizeof(struct netfs_cmd) + t->psb->crypto_attached_size;
-       unsigned int size = t->iovec.iov_len - sizeof(struct netfs_cmd) - t->psb->crypto_attached_size;
-       struct netfs_cmd *cmd = data;
-       unsigned int sz, pages = t->attached_pages, i, csize, cmd_cmd, dpage_idx;
-       struct scatterlist sg_src, sg_dst;
-       int err;
-
-       while (size) {
-               cmd = data;
-               cmd_cmd = __be16_to_cpu(cmd->cmd);
-               csize = __be32_to_cpu(cmd->size);
-               cmd->iv = __cpu_to_be64(e->iv);
-
-               if (cmd_cmd == NETFS_READ_PAGES || cmd_cmd == NETFS_READ_PAGE)
-                       csize = __be16_to_cpu(cmd->ext);
-
-               sz = csize + __be16_to_cpu(cmd->cpad) + sizeof(struct netfs_cmd);
-
-               dprintk("%s: size: %u, sz: %u, cmd_size: %u, cmd_cpad: %u.\n",
-                               __func__, size, sz, __be32_to_cpu(cmd->size), __be16_to_cpu(cmd->cpad));
-
-               data += sz;
-               size -= sz;
-
-               sg_init_one(&sg_src, cmd->data, sz - sizeof(struct netfs_cmd));
-               sg_init_one(&sg_dst, cmd->data, sz - sizeof(struct netfs_cmd));
-
-               err = iterator(e, &sg_dst, &sg_src);
-               if (err)
-                       return err;
-       }
-
-       if (!pages)
-               return 0;
-
-       dpage_idx = 0;
-       for (i = 0; i < t->page_num; ++i) {
-               struct page *page = t->pages[i];
-               struct page *dpage = e->pages[dpage_idx];
-
-               if (!page)
-                       continue;
-
-               sg_init_table(&sg_src, 1);
-               sg_init_table(&sg_dst, 1);
-               sg_set_page(&sg_src, page, page_private(page), 0);
-               sg_set_page(&sg_dst, dpage, page_private(page), 0);
-
-               err = iterator(e, &sg_dst, &sg_src);
-               if (err)
-                       return err;
-
-               pages--;
-               if (!pages)
-                       break;
-               dpage_idx++;
-       }
-
-       return 0;
-}
-
-static int pohmelfs_encrypt_iterator(struct pohmelfs_crypto_engine *e,
-               struct scatterlist *sg_dst, struct scatterlist *sg_src)
-{
-       struct ablkcipher_request *req = e->data;
-       u8 iv[32];
-
-       memset(iv, 0, sizeof(iv));
-
-       memcpy(iv, &e->iv, sizeof(e->iv));
-
-       return pohmelfs_crypto_process(req, sg_dst, sg_src, iv, 1, e->timeout);
-}
-
-static int pohmelfs_encrypt(struct pohmelfs_crypto_thread *tc)
-{
-       struct netfs_trans *t = tc->trans;
-       struct pohmelfs_crypto_engine *e = &tc->eng;
-       struct ablkcipher_request *req = e->data;
-
-       memset(req, 0, sizeof(struct ablkcipher_request));
-       ablkcipher_request_set_tfm(req, e->cipher);
-
-       e->iv = pohmelfs_gen_iv(t);
-
-       return pohmelfs_trans_iter(t, e, pohmelfs_encrypt_iterator);
-}
-
-static int pohmelfs_hash_iterator(struct pohmelfs_crypto_engine *e,
-               struct scatterlist *sg_dst, struct scatterlist *sg_src)
-{
-       return crypto_hash_update(e->data, sg_src, sg_src->length);
-}
-
-static int pohmelfs_hash(struct pohmelfs_crypto_thread *tc)
-{
-       struct pohmelfs_crypto_engine *e = &tc->eng;
-       struct hash_desc *desc = e->data;
-       unsigned char *dst = tc->trans->iovec.iov_base + sizeof(struct netfs_cmd);
-       int err;
-
-       desc->tfm = e->hash;
-       desc->flags = 0;
-
-       err = crypto_hash_init(desc);
-       if (err)
-               return err;
-
-       err = pohmelfs_trans_iter(tc->trans, e, pohmelfs_hash_iterator);
-       if (err)
-               return err;
-
-       err = crypto_hash_final(desc, dst);
-       if (err)
-               return err;
-
-       {
-               unsigned int i;
-               dprintk("%s: ", __func__);
-               for (i = 0; i < tc->psb->crypto_attached_size; ++i)
-                       dprintka("%02x ", dst[i]);
-               dprintka("\n");
-       }
-
-       return 0;
-}
-
-static void pohmelfs_crypto_pages_free(struct pohmelfs_crypto_engine *e)
-{
-       unsigned int i;
-
-       for (i = 0; i < e->page_num; ++i)
-               __free_page(e->pages[i]);
-       kfree(e->pages);
-}
-
-static int pohmelfs_crypto_pages_alloc(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb)
-{
-       unsigned int i;
-
-       e->pages = kmalloc(psb->trans_max_pages * sizeof(struct page *), GFP_KERNEL);
-       if (!e->pages)
-               return -ENOMEM;
-
-       for (i = 0; i < psb->trans_max_pages; ++i) {
-               e->pages[i] = alloc_page(GFP_KERNEL);
-               if (!e->pages[i])
-                       break;
-       }
-
-       e->page_num = i;
-       if (!e->page_num)
-               goto err_out_free;
-
-       return 0;
-
-err_out_free:
-       kfree(e->pages);
-       return -ENOMEM;
-}
-
-static void pohmelfs_sys_crypto_exit_one(struct pohmelfs_crypto_thread *t)
-{
-       struct pohmelfs_sb *psb = t->psb;
-
-       if (t->thread)
-               kthread_stop(t->thread);
-
-       mutex_lock(&psb->crypto_thread_lock);
-       list_del(&t->thread_entry);
-       psb->crypto_thread_num--;
-       mutex_unlock(&psb->crypto_thread_lock);
-
-       pohmelfs_crypto_engine_exit(&t->eng);
-       pohmelfs_crypto_pages_free(&t->eng);
-       kfree(t);
-}
-
-static int pohmelfs_crypto_finish(struct netfs_trans *t, struct pohmelfs_sb *psb, int err)
-{
-       struct netfs_cmd *cmd = t->iovec.iov_base;
-       netfs_convert_cmd(cmd);
-
-       if (likely(!err))
-               err = netfs_trans_finish_send(t, psb);
-
-       t->result = err;
-       netfs_trans_put(t);
-
-       return err;
-}
-
-void pohmelfs_crypto_thread_make_ready(struct pohmelfs_crypto_thread *th)
-{
-       struct pohmelfs_sb *psb = th->psb;
-
-       th->page = NULL;
-       th->trans = NULL;
-
-       mutex_lock(&psb->crypto_thread_lock);
-       list_move_tail(&th->thread_entry, &psb->crypto_ready_list);
-       mutex_unlock(&psb->crypto_thread_lock);
-       wake_up(&psb->wait);
-}
-
-static int pohmelfs_crypto_thread_trans(struct pohmelfs_crypto_thread *t)
-{
-       struct netfs_trans *trans;
-       int err = 0;
-
-       trans = t->trans;
-       trans->eng = NULL;
-
-       if (t->eng.hash) {
-               err = pohmelfs_hash(t);
-               if (err)
-                       goto out_complete;
-       }
-
-       if (t->eng.cipher) {
-               err = pohmelfs_encrypt(t);
-               if (err)
-                       goto out_complete;
-               trans->eng = &t->eng;
-       }
-
-out_complete:
-       t->page = NULL;
-       t->trans = NULL;
-
-       if (!trans->eng)
-               pohmelfs_crypto_thread_make_ready(t);
-
-       pohmelfs_crypto_finish(trans, t->psb, err);
-       return err;
-}
-
-static int pohmelfs_crypto_thread_page(struct pohmelfs_crypto_thread *t)
-{
-       struct pohmelfs_crypto_engine *e = &t->eng;
-       struct page *page = t->page;
-       int err;
-
-       WARN_ON(!PageChecked(page));
-
-       err = pohmelfs_crypto_process_input_data(e, e->iv, NULL, page, t->size);
-       if (!err)
-               SetPageUptodate(page);
-       else
-               SetPageError(page);
-       unlock_page(page);
-       page_cache_release(page);
-
-       pohmelfs_crypto_thread_make_ready(t);
-
-       return err;
-}
-
-static int pohmelfs_crypto_thread_func(void *data)
-{
-       struct pohmelfs_crypto_thread *t = data;
-
-       while (!kthread_should_stop()) {
-               wait_event_interruptible(t->wait, kthread_should_stop() ||
-                               t->trans || t->page);
-
-               if (kthread_should_stop())
-                       break;
-
-               if (!t->trans && !t->page)
-                       continue;
-
-               dprintk("%s: thread: %p, trans: %p, page: %p.\n",
-                               __func__, t, t->trans, t->page);
-
-               if (t->trans)
-                       pohmelfs_crypto_thread_trans(t);
-               else if (t->page)
-                       pohmelfs_crypto_thread_page(t);
-       }
-
-       return 0;
-}
-
-static void pohmelfs_crypto_flush(struct pohmelfs_sb *psb, struct list_head *head)
-{
-       while (!list_empty(head)) {
-               struct pohmelfs_crypto_thread *t = NULL;
-
-               mutex_lock(&psb->crypto_thread_lock);
-               if (!list_empty(head)) {
-                       t = list_first_entry(head, struct pohmelfs_crypto_thread, thread_entry);
-                       list_del_init(&t->thread_entry);
-               }
-               mutex_unlock(&psb->crypto_thread_lock);
-
-               if (t)
-                       pohmelfs_sys_crypto_exit_one(t);
-       }
-}
-
-static void pohmelfs_sys_crypto_exit(struct pohmelfs_sb *psb)
-{
-       while (!list_empty(&psb->crypto_active_list) || !list_empty(&psb->crypto_ready_list)) {
-               dprintk("%s: crypto_thread_num: %u.\n", __func__, psb->crypto_thread_num);
-               pohmelfs_crypto_flush(psb, &psb->crypto_active_list);
-               pohmelfs_crypto_flush(psb, &psb->crypto_ready_list);
-       }
-}
-
-static int pohmelfs_sys_crypto_init(struct pohmelfs_sb *psb)
-{
-       unsigned int i;
-       struct pohmelfs_crypto_thread *t;
-       struct pohmelfs_config *c;
-       struct netfs_state *st;
-       int err;
-
-       list_for_each_entry(c, &psb->state_list, config_entry) {
-               st = &c->state;
-
-               err = pohmelfs_crypto_engine_init(&st->eng, psb);
-               if (err)
-                       goto err_out_exit;
-
-               dprintk("%s: st: %p, eng: %p, hash: %p, cipher: %p.\n",
-                               __func__, st, &st->eng, &st->eng.hash, &st->eng.cipher);
-       }
-
-       for (i = 0; i < psb->crypto_thread_num; ++i) {
-               err = -ENOMEM;
-               t = kzalloc(sizeof(struct pohmelfs_crypto_thread), GFP_KERNEL);
-               if (!t)
-                       goto err_out_free_state_engines;
-
-               init_waitqueue_head(&t->wait);
-
-               t->psb = psb;
-               t->trans = NULL;
-               t->eng.thread = t;
-
-               err = pohmelfs_crypto_engine_init(&t->eng, psb);
-               if (err)
-                       goto err_out_free_state_engines;
-
-               err = pohmelfs_crypto_pages_alloc(&t->eng, psb);
-               if (err)
-                       goto err_out_free;
-
-               t->thread = kthread_run(pohmelfs_crypto_thread_func, t,
-                               "pohmelfs-crypto-%d-%d", psb->idx, i);
-               if (IS_ERR(t->thread)) {
-                       err = PTR_ERR(t->thread);
-                       t->thread = NULL;
-                       goto err_out_free;
-               }
-
-               if (t->eng.cipher)
-                       psb->crypto_align_size = crypto_ablkcipher_blocksize(t->eng.cipher);
-
-               mutex_lock(&psb->crypto_thread_lock);
-               list_add_tail(&t->thread_entry, &psb->crypto_ready_list);
-               mutex_unlock(&psb->crypto_thread_lock);
-       }
-
-       psb->crypto_thread_num = i;
-       return 0;
-
-err_out_free:
-       pohmelfs_sys_crypto_exit_one(t);
-err_out_free_state_engines:
-       list_for_each_entry(c, &psb->state_list, config_entry) {
-               st = &c->state;
-               pohmelfs_crypto_engine_exit(&st->eng);
-       }
-err_out_exit:
-       pohmelfs_sys_crypto_exit(psb);
-       return err;
-}
-
-void pohmelfs_crypto_exit(struct pohmelfs_sb *psb)
-{
-       pohmelfs_sys_crypto_exit(psb);
-
-       kfree(psb->hash_string);
-       kfree(psb->cipher_string);
-}
-
-static int pohmelfs_crypt_init_complete(struct page **pages, unsigned int page_num,
-               void *private, int err)
-{
-       struct pohmelfs_sb *psb = private;
-
-       psb->flags = -err;
-       dprintk("%s: err: %d.\n", __func__, err);
-
-       wake_up(&psb->wait);
-
-       return err;
-}
-
-static int pohmelfs_crypto_init_handshake(struct pohmelfs_sb *psb)
-{
-       struct netfs_trans *t;
-       struct netfs_crypto_capabilities *cap;
-       struct netfs_cmd *cmd;
-       char *str;
-       int err = -ENOMEM, size;
-
-       size = sizeof(struct netfs_crypto_capabilities) +
-               psb->cipher_strlen + psb->hash_strlen + 2; /* 0 bytes */
-
-       t = netfs_trans_alloc(psb, size, 0, 0);
-       if (!t)
-               goto err_out_exit;
-
-       t->complete = pohmelfs_crypt_init_complete;
-       t->private = psb;
-
-       cmd = netfs_trans_current(t);
-       cap = (struct netfs_crypto_capabilities *)(cmd + 1);
-       str = (char *)(cap + 1);
-
-       cmd->cmd = NETFS_CAPABILITIES;
-       cmd->id = POHMELFS_CRYPTO_CAPABILITIES;
-       cmd->size = size;
-       cmd->start = 0;
-       cmd->ext = 0;
-       cmd->csize = 0;
-
-       netfs_convert_cmd(cmd);
-       netfs_trans_update(cmd, t, size);
-
-       cap->hash_strlen = psb->hash_strlen;
-       if (cap->hash_strlen) {
-               sprintf(str, "%s", psb->hash_string);
-               str += cap->hash_strlen;
-       }
-
-       cap->cipher_strlen = psb->cipher_strlen;
-       cap->cipher_keysize = psb->cipher_keysize;
-       if (cap->cipher_strlen)
-               sprintf(str, "%s", psb->cipher_string);
-
-       netfs_convert_crypto_capabilities(cap);
-
-       psb->flags = ~0;
-       err = netfs_trans_finish(t, psb);
-       if (err)
-               goto err_out_exit;
-
-       err = wait_event_interruptible_timeout(psb->wait, (psb->flags != ~0),
-                       psb->wait_on_page_timeout);
-       if (!err)
-               err = -ETIMEDOUT;
-       else if (err > 0)
-               err = -psb->flags;
-
-       if (!err)
-               psb->perform_crypto = 1;
-       psb->flags = 0;
-
-       /*
-        * At this point NETFS_CAPABILITIES response command
-        * should setup superblock in a way, which is acceptable
-        * for both client and server, so if server refuses connection,
-        * it will send error in transaction response.
-        */
-
-       if (err)
-               goto err_out_exit;
-
-       return 0;
-
-err_out_exit:
-       return err;
-}
-
-int pohmelfs_crypto_init(struct pohmelfs_sb *psb)
-{
-       int err;
-
-       if (!psb->cipher_string && !psb->hash_string)
-               return 0;
-
-       err = pohmelfs_crypto_init_handshake(psb);
-       if (err)
-               return err;
-
-       err = pohmelfs_sys_crypto_init(psb);
-       if (err)
-               return err;
-
-       return 0;
-}
-
-static int pohmelfs_crypto_thread_get(struct pohmelfs_sb *psb,
-               int (*action)(struct pohmelfs_crypto_thread *t, void *data), void *data)
-{
-       struct pohmelfs_crypto_thread *t = NULL;
-       int err;
-
-       while (!t) {
-               err = wait_event_interruptible_timeout(psb->wait,
-                               !list_empty(&psb->crypto_ready_list),
-                               psb->wait_on_page_timeout);
-
-               t = NULL;
-               err = 0;
-               mutex_lock(&psb->crypto_thread_lock);
-               if (!list_empty(&psb->crypto_ready_list)) {
-                       t = list_entry(psb->crypto_ready_list.prev,
-                                       struct pohmelfs_crypto_thread,
-                                       thread_entry);
-
-                       list_move_tail(&t->thread_entry,
-                                       &psb->crypto_active_list);
-
-                       action(t, data);
-                       wake_up(&t->wait);
-
-               }
-               mutex_unlock(&psb->crypto_thread_lock);
-       }
-
-       return err;
-}
-
-static int pohmelfs_trans_crypt_action(struct pohmelfs_crypto_thread *t, void *data)
-{
-       struct netfs_trans *trans = data;
-
-       netfs_trans_get(trans);
-       t->trans = trans;
-
-       dprintk("%s: t: %p, gen: %u, thread: %p.\n", __func__, trans, trans->gen, t);
-       return 0;
-}
-
-int pohmelfs_trans_crypt(struct netfs_trans *trans, struct pohmelfs_sb *psb)
-{
-       if ((!psb->hash_string && !psb->cipher_string) || !psb->perform_crypto) {
-               netfs_trans_get(trans);
-               return pohmelfs_crypto_finish(trans, psb, 0);
-       }
-
-       return pohmelfs_crypto_thread_get(psb, pohmelfs_trans_crypt_action, trans);
-}
-
-struct pohmelfs_crypto_input_action_data {
-       struct page                     *page;
-       struct pohmelfs_crypto_engine   *e;
-       u64                             iv;
-       unsigned int                    size;
-};
-
-static int pohmelfs_crypt_input_page_action(struct pohmelfs_crypto_thread *t, void *data)
-{
-       struct pohmelfs_crypto_input_action_data *act = data;
-
-       memcpy(t->eng.data, act->e->data, t->psb->crypto_attached_size);
-
-       t->size = act->size;
-       t->eng.iv = act->iv;
-
-       t->page = act->page;
-       return 0;
-}
-
-int pohmelfs_crypto_process_input_page(struct pohmelfs_crypto_engine *e,
-               struct page *page, unsigned int size, u64 iv)
-{
-       struct inode *inode = page->mapping->host;
-       struct pohmelfs_crypto_input_action_data act;
-       int err = -ENOENT;
-
-       act.page = page;
-       act.e = e;
-       act.size = size;
-       act.iv = iv;
-
-       err = pohmelfs_crypto_thread_get(POHMELFS_SB(inode->i_sb),
-                       pohmelfs_crypt_input_page_action, &act);
-       if (err)
-               goto err_out_exit;
-
-       return 0;
-
-err_out_exit:
-       SetPageUptodate(page);
-       page_cache_release(page);
-
-       return err;
-}
diff --git a/drivers/staging/pohmelfs/dir.c b/drivers/staging/pohmelfs/dir.c
deleted file mode 100644 (file)
index 2ee4491..0000000
+++ /dev/null
@@ -1,1102 +0,0 @@
-/*
- * 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/jhash.h>
-#include <linux/namei.h>
-#include <linux/slab.h>
-#include <linux/pagemap.h>
-
-#include "netfs.h"
-
-static int pohmelfs_cmp_hash(struct pohmelfs_name *n, u32 hash)
-{
-       if (n->hash > hash)
-               return -1;
-       if (n->hash < hash)
-               return 1;
-
-       return 0;
-}
-
-static struct pohmelfs_name *pohmelfs_search_hash_unprecise(struct pohmelfs_inode *pi, u32 hash)
-{
-       struct rb_node *n = pi->hash_root.rb_node;
-       struct pohmelfs_name *tmp = NULL;
-       int cmp;
-
-       while (n) {
-               tmp = rb_entry(n, struct pohmelfs_name, hash_node);
-
-               cmp = pohmelfs_cmp_hash(tmp, hash);
-               if (cmp < 0)
-                       n = n->rb_left;
-               else if (cmp > 0)
-                       n = n->rb_right;
-               else
-                       break;
-
-       }
-
-       return tmp;
-}
-
-struct pohmelfs_name *pohmelfs_search_hash(struct pohmelfs_inode *pi, u32 hash)
-{
-       struct pohmelfs_name *tmp;
-
-       tmp = pohmelfs_search_hash_unprecise(pi, hash);
-       if (tmp && (tmp->hash == hash))
-               return tmp;
-
-       return NULL;
-}
-
-static void __pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
-{
-       rb_erase(&node->hash_node, &parent->hash_root);
-}
-
-/*
- * Remove name cache entry from its caches and free it.
- */
-static void pohmelfs_name_free(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
-{
-       __pohmelfs_name_del(parent, node);
-       list_del(&node->sync_create_entry);
-       kfree(node);
-}
-
-static struct pohmelfs_name *pohmelfs_insert_hash(struct pohmelfs_inode *pi,
-               struct pohmelfs_name *new)
-{
-       struct rb_node **n = &pi->hash_root.rb_node, *parent = NULL;
-       struct pohmelfs_name *ret = NULL, *tmp;
-       int cmp;
-
-       while (*n) {
-               parent = *n;
-
-               tmp = rb_entry(parent, struct pohmelfs_name, hash_node);
-
-               cmp = pohmelfs_cmp_hash(tmp, new->hash);
-               if (cmp < 0)
-                       n = &parent->rb_left;
-               else if (cmp > 0)
-                       n = &parent->rb_right;
-               else {
-                       ret = tmp;
-                       break;
-               }
-       }
-
-       if (ret) {
-               printk("%s: exist: parent: %llu, ino: %llu, hash: %x, len: %u, data: '%s', "
-                                       "new: ino: %llu, hash: %x, len: %u, data: '%s'.\n",
-                               __func__, pi->ino,
-                               ret->ino, ret->hash, ret->len, ret->data,
-                               new->ino, new->hash, new->len, new->data);
-               ret->ino = new->ino;
-               return ret;
-       }
-
-       rb_link_node(&new->hash_node, parent, n);
-       rb_insert_color(&new->hash_node, &pi->hash_root);
-
-       return NULL;
-}
-
-/*
- * Free name cache for given inode.
- */
-void pohmelfs_free_names(struct pohmelfs_inode *parent)
-{
-       struct rb_node *rb_node;
-       struct pohmelfs_name *n;
-
-       for (rb_node = rb_first(&parent->hash_root); rb_node;) {
-               n = rb_entry(rb_node, struct pohmelfs_name, hash_node);
-               rb_node = rb_next(rb_node);
-
-               pohmelfs_name_free(parent, n);
-       }
-}
-
-static void pohmelfs_fix_offset(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
-{
-       parent->total_len -= node->len;
-}
-
-/*
- * Free name cache entry helper.
- */
-void pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *node)
-{
-       pohmelfs_fix_offset(parent, node);
-       pohmelfs_name_free(parent, node);
-}
-
-/*
- * Insert new name cache entry into all hash cache.
- */
-static int pohmelfs_insert_name(struct pohmelfs_inode *parent, struct pohmelfs_name *n)
-{
-       struct pohmelfs_name *name;
-
-       name = pohmelfs_insert_hash(parent, n);
-       if (name)
-               return -EEXIST;
-
-       parent->total_len += n->len;
-       list_add_tail(&n->sync_create_entry, &parent->sync_create_list);
-
-       return 0;
-}
-
-/*
- * Allocate new name cache entry.
- */
-static struct pohmelfs_name *pohmelfs_name_alloc(unsigned int len)
-{
-       struct pohmelfs_name *n;
-
-       n = kzalloc(sizeof(struct pohmelfs_name) + len, GFP_KERNEL);
-       if (!n)
-               return NULL;
-
-       INIT_LIST_HEAD(&n->sync_create_entry);
-
-       n->data = (char *)(n+1);
-
-       return n;
-}
-
-/*
- * Add new name entry into directory's cache.
- */
-static int pohmelfs_add_dir(struct pohmelfs_sb *psb, struct pohmelfs_inode *parent,
-               struct pohmelfs_inode *npi, struct qstr *str, unsigned int mode, int link)
-{
-       int err = -ENOMEM;
-       struct pohmelfs_name *n;
-
-       n = pohmelfs_name_alloc(str->len + 1);
-       if (!n)
-               goto err_out_exit;
-
-       n->ino = npi->ino;
-       n->mode = mode;
-       n->len = str->len;
-       n->hash = str->hash;
-       sprintf(n->data, "%s", str->name);
-
-       mutex_lock(&parent->offset_lock);
-       err = pohmelfs_insert_name(parent, n);
-       mutex_unlock(&parent->offset_lock);
-
-       if (err) {
-               if (err != -EEXIST)
-                       goto err_out_free;
-               kfree(n);
-       }
-
-       return 0;
-
-err_out_free:
-       kfree(n);
-err_out_exit:
-       return err;
-}
-
-/*
- * Create new inode for given parameters (name, inode info, parent).
- * This does not create object on the server, it will be synced there during writeback.
- */
-struct pohmelfs_inode *pohmelfs_new_inode(struct pohmelfs_sb *psb,
-               struct pohmelfs_inode *parent, struct qstr *str,
-               struct netfs_inode_info *info, int link)
-{
-       struct inode *new = NULL;
-       struct pohmelfs_inode *npi;
-       int err = -EEXIST;
-
-       dprintk("%s: creating inode: parent: %llu, ino: %llu, str: %p.\n",
-                       __func__, (parent) ? parent->ino : 0, info->ino, str);
-
-       err = -ENOMEM;
-       new = iget_locked(psb->sb, info->ino);
-       if (!new)
-               goto err_out_exit;
-
-       npi = POHMELFS_I(new);
-       npi->ino = info->ino;
-       err = 0;
-
-       if (new->i_state & I_NEW) {
-               dprintk("%s: filling VFS inode: %lu/%llu.\n",
-                               __func__, new->i_ino, info->ino);
-               pohmelfs_fill_inode(new, info);
-
-               if (S_ISDIR(info->mode)) {
-                       struct qstr s;
-
-                       s.name = ".";
-                       s.len = 1;
-                       s.hash = jhash(s.name, s.len, 0);
-
-                       err = pohmelfs_add_dir(psb, npi, npi, &s, info->mode, 0);
-                       if (err)
-                               goto err_out_put;
-
-                       s.name = "..";
-                       s.len = 2;
-                       s.hash = jhash(s.name, s.len, 0);
-
-                       err = pohmelfs_add_dir(psb, npi, (parent) ? parent : npi, &s,
-                                       (parent) ? parent->vfs_inode.i_mode : npi->vfs_inode.i_mode, 0);
-                       if (err)
-                               goto err_out_put;
-               }
-       }
-
-       if (str) {
-               if (parent) {
-                       err = pohmelfs_add_dir(psb, parent, npi, str, info->mode, link);
-
-                       dprintk("%s: %s inserted name: '%s', new_offset: %llu, ino: %llu, parent: %llu.\n",
-                                       __func__, (err) ? "unsuccessfully" : "successfully",
-                                       str->name, parent->total_len, info->ino, parent->ino);
-
-                       if (err && err != -EEXIST)
-                               goto err_out_put;
-               }
-       }
-
-       if (new->i_state & I_NEW) {
-               if (parent)
-                       mark_inode_dirty(&parent->vfs_inode);
-               mark_inode_dirty(new);
-       }
-
-       set_bit(NETFS_INODE_OWNED, &npi->state);
-       npi->lock_type = POHMELFS_WRITE_LOCK;
-       unlock_new_inode(new);
-
-       return npi;
-
-err_out_put:
-       printk("%s: putting inode: %p, npi: %p, error: %d.\n", __func__, new, npi, err);
-       iput(new);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-static int pohmelfs_remote_sync_complete(struct page **pages, unsigned int page_num,
-               void *private, int err)
-{
-       struct pohmelfs_inode *pi = private;
-       struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
-
-       dprintk("%s: ino: %llu, err: %d.\n", __func__, pi->ino, err);
-
-       if (err)
-               pi->error = err;
-       wake_up(&psb->wait);
-       pohmelfs_put_inode(pi);
-
-       return err;
-}
-
-/*
- * Receive directory content from the server.
- * This should be only done for objects, which were not created locally,
- * and which were not synced previously.
- */
-static int pohmelfs_sync_remote_dir(struct pohmelfs_inode *pi)
-{
-       struct inode *inode = &pi->vfs_inode;
-       struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-       long ret = psb->wait_on_page_timeout;
-       int err;
-
-       dprintk("%s: dir: %llu, state: %lx: remote_synced: %d.\n",
-               __func__, pi->ino, pi->state, test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state));
-
-       if (test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state))
-               return 0;
-
-       if (!igrab(inode)) {
-               err = -ENOENT;
-               goto err_out_exit;
-       }
-
-       err = pohmelfs_meta_command(pi, NETFS_READDIR, NETFS_TRANS_SINGLE_DST,
-                       pohmelfs_remote_sync_complete, pi, 0);
-       if (err)
-               goto err_out_exit;
-
-       pi->error = 0;
-       ret = wait_event_interruptible_timeout(psb->wait,
-                       test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state) || pi->error, ret);
-       dprintk("%s: awake dir: %llu, ret: %ld, err: %d.\n", __func__, pi->ino, ret, pi->error);
-       if (ret <= 0) {
-               err = ret;
-               if (!err)
-                       err = -ETIMEDOUT;
-               goto err_out_exit;
-       }
-
-       if (pi->error)
-               return pi->error;
-
-       return 0;
-
-err_out_exit:
-       clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
-
-       return err;
-}
-
-static int pohmelfs_dir_open(struct inode *inode, struct file *file)
-{
-       file->private_data = NULL;
-       return 0;
-}
-
-/*
- * VFS readdir callback. Syncs directory content from server if needed,
- * and provides direntry info to the userspace.
- */
-static int pohmelfs_readdir(struct file *file, void *dirent, filldir_t filldir)
-{
-       struct inode *inode = file->f_path.dentry->d_inode;
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       struct pohmelfs_name *n;
-       struct rb_node *rb_node;
-       int err = 0, mode;
-       u64 len;
-
-       dprintk("%s: parent: %llu, fpos: %llu, hash: %08lx.\n",
-                       __func__, pi->ino, (u64)file->f_pos,
-                       (unsigned long)file->private_data);
-#if 0
-       err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_READ_LOCK);
-       if (err)
-               return err;
-#endif
-       err = pohmelfs_sync_remote_dir(pi);
-       if (err)
-               return err;
-
-       if (file->private_data && (file->private_data == (void *)(unsigned long)file->f_pos))
-               return 0;
-
-       mutex_lock(&pi->offset_lock);
-       n = pohmelfs_search_hash_unprecise(pi, (unsigned long)file->private_data);
-
-       while (n) {
-               mode = (n->mode >> 12) & 15;
-
-               dprintk("%s: offset: %llu, parent ino: %llu, name: '%s', len: %u, ino: %llu, "
-                               "mode: %o/%o, fpos: %llu, hash: %08x.\n",
-                               __func__, file->f_pos, pi->ino, n->data, n->len,
-                               n->ino, n->mode, mode, file->f_pos, n->hash);
-
-               file->private_data = (void *)(unsigned long)n->hash;
-
-               len = n->len;
-               err = filldir(dirent, n->data, n->len, file->f_pos, n->ino, mode);
-
-               if (err < 0) {
-                       dprintk("%s: err: %d.\n", __func__, err);
-                       err = 0;
-                       break;
-               }
-
-               file->f_pos += len;
-
-               rb_node = rb_next(&n->hash_node);
-
-               if (!rb_node || (rb_node == &n->hash_node)) {
-                       file->private_data = (void *)(unsigned long)file->f_pos;
-                       break;
-               }
-
-               n = rb_entry(rb_node, struct pohmelfs_name, hash_node);
-       }
-       mutex_unlock(&pi->offset_lock);
-
-       return err;
-}
-
-static loff_t pohmelfs_dir_lseek(struct file *file, loff_t offset, int origin)
-{
-       file->f_pos = offset;
-       file->private_data = NULL;
-       return offset;
-}
-
-const struct file_operations pohmelfs_dir_fops = {
-       .open = pohmelfs_dir_open,
-       .read = generic_read_dir,
-       .llseek = pohmelfs_dir_lseek,
-       .readdir = pohmelfs_readdir,
-};
-
-/*
- * Lookup single object on server.
- */
-static int pohmelfs_lookup_single(struct pohmelfs_inode *parent,
-               struct qstr *str, u64 ino)
-{
-       struct pohmelfs_sb *psb = POHMELFS_SB(parent->vfs_inode.i_sb);
-       long ret = msecs_to_jiffies(5000);
-       int err;
-
-       set_bit(NETFS_COMMAND_PENDING, &parent->state);
-       err = pohmelfs_meta_command_data(parent, parent->ino, NETFS_LOOKUP,
-                       (char *)str->name, NETFS_TRANS_SINGLE_DST, NULL, NULL, ino);
-       if (err)
-               goto err_out_exit;
-
-       err = 0;
-       ret = wait_event_interruptible_timeout(psb->wait,
-                       !test_bit(NETFS_COMMAND_PENDING, &parent->state), ret);
-       if (ret <= 0) {
-               err = ret;
-               if (!err)
-                       err = -ETIMEDOUT;
-       }
-
-       if (err)
-               goto err_out_exit;
-
-       return 0;
-
-err_out_exit:
-       clear_bit(NETFS_COMMAND_PENDING, &parent->state);
-
-       printk("%s: failed: parent: %llu, ino: %llu, name: '%s', err: %d.\n",
-                       __func__, parent->ino, ino, str->name, err);
-
-       return err;
-}
-
-/*
- * VFS lookup callback.
- * We first try to get inode number from local name cache, if we have one,
- * then inode can be found in inode cache. If there is no inode or no object in
- * local cache, try to lookup it on server. This only should be done for directories,
- * which were not created locally, otherwise remote server does not know about dir at all,
- * so no need to try to know that.
- */
-struct dentry *pohmelfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
-{
-       struct pohmelfs_inode *parent = POHMELFS_I(dir);
-       struct pohmelfs_name *n;
-       struct inode *inode = NULL;
-       unsigned long ino = 0;
-       int err, lock_type = POHMELFS_READ_LOCK, need_lock = 1;
-       struct qstr str = dentry->d_name;
-
-       if ((nd->intent.open.flags & O_ACCMODE) != O_RDONLY)
-               lock_type = POHMELFS_WRITE_LOCK;
-
-       if (test_bit(NETFS_INODE_OWNED, &parent->state)) {
-               if (lock_type == parent->lock_type)
-                       need_lock = 0;
-               if ((lock_type == POHMELFS_READ_LOCK) && (parent->lock_type == POHMELFS_WRITE_LOCK))
-                       need_lock = 0;
-       }
-
-       if ((lock_type == POHMELFS_READ_LOCK) && !test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &parent->state))
-               need_lock = 1;
-
-       str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
-
-       mutex_lock(&parent->offset_lock);
-       n = pohmelfs_search_hash(parent, str.hash);
-       if (n)
-               ino = n->ino;
-       mutex_unlock(&parent->offset_lock);
-
-       dprintk("%s: start ino: %lu, inode: %p, name: '%s', hash: %x, parent_state: %lx, need_lock: %d.\n",
-                       __func__, ino, inode, str.name, str.hash, parent->state, need_lock);
-
-       if (ino) {
-               inode = ilookup(dir->i_sb, ino);
-               if (inode)
-                       goto out;
-       }
-
-       dprintk("%s: no inode dir: %p, dir_ino: %llu, name: '%s', len: %u, dir_state: %lx, ino: %lu.\n",
-                       __func__, dir, parent->ino,
-                       str.name, str.len, parent->state, ino);
-
-       if (!ino) {
-               if (!need_lock)
-                       goto out;
-       }
-
-       err = pohmelfs_data_lock(parent, 0, ~0, lock_type);
-       if (err)
-               goto out;
-
-       err = pohmelfs_lookup_single(parent, &str, ino);
-       if (err)
-               goto out;
-
-       if (!ino) {
-               mutex_lock(&parent->offset_lock);
-               n = pohmelfs_search_hash(parent, str.hash);
-               if (n)
-                       ino = n->ino;
-               mutex_unlock(&parent->offset_lock);
-       }
-
-       if (ino) {
-               inode = ilookup(dir->i_sb, ino);
-               dprintk("%s: second lookup ino: %lu, inode: %p, name: '%s', hash: %x.\n",
-                               __func__, ino, inode, str.name, str.hash);
-               if (!inode) {
-                       dprintk("%s: No inode for ino: %lu, name: '%s', hash: %x.\n",
-                               __func__, ino, str.name, str.hash);
-                       /* return NULL; */
-                       return ERR_PTR(-EACCES);
-               }
-       } else {
-               printk("%s: No inode number : name: '%s', hash: %x.\n",
-                       __func__, str.name, str.hash);
-       }
-out:
-       return d_splice_alias(inode, dentry);
-}
-
-/*
- * Create new object in local cache. Object will be synced to server
- * during writeback for given inode.
- */
-struct pohmelfs_inode *pohmelfs_create_entry_local(struct pohmelfs_sb *psb,
-       struct pohmelfs_inode *parent, struct qstr *str, u64 start, umode_t mode)
-{
-       struct pohmelfs_inode *npi;
-       int err = -ENOMEM;
-       struct netfs_inode_info info;
-
-       dprintk("%s: name: '%s', mode: %ho, start: %llu.\n",
-                       __func__, str->name, mode, start);
-
-       info.mode = mode;
-       info.ino = start;
-
-       if (!start)
-               info.ino = pohmelfs_new_ino(psb);
-
-       info.nlink = S_ISDIR(mode) ? 2 : 1;
-       info.uid = current_fsuid();
-       info.gid = current_fsgid();
-       info.size = 0;
-       info.blocksize = 512;
-       info.blocks = 0;
-       info.rdev = 0;
-       info.version = 0;
-
-       npi = pohmelfs_new_inode(psb, parent, str, &info, !!start);
-       if (IS_ERR(npi)) {
-               err = PTR_ERR(npi);
-               goto err_out_unlock;
-       }
-
-       return npi;
-
-err_out_unlock:
-       dprintk("%s: err: %d.\n", __func__, err);
-       return ERR_PTR(err);
-}
-
-/*
- * Create local object and bind it to dentry.
- */
-static int pohmelfs_create_entry(struct inode *dir, struct dentry *dentry,
-                                u64 start, umode_t mode)
-{
-       struct pohmelfs_sb *psb = POHMELFS_SB(dir->i_sb);
-       struct pohmelfs_inode *npi, *parent;
-       struct qstr str = dentry->d_name;
-       int err;
-
-       parent = POHMELFS_I(dir);
-
-       err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK);
-       if (err)
-               return err;
-
-       str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
-
-       npi = pohmelfs_create_entry_local(psb, parent, &str, start, mode);
-       if (IS_ERR(npi))
-               return PTR_ERR(npi);
-
-       d_instantiate(dentry, &npi->vfs_inode);
-
-       dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n",
-                       __func__, parent->ino, npi->ino, dentry->d_name.name,
-                       (signed)dir->i_nlink, (signed)npi->vfs_inode.i_nlink);
-
-       return 0;
-}
-
-/*
- * VFS create and mkdir callbacks.
- */
-static int pohmelfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-               struct nameidata *nd)
-{
-       return pohmelfs_create_entry(dir, dentry, 0, mode);
-}
-
-static int pohmelfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
-{
-       int err;
-
-       inode_inc_link_count(dir);
-       err = pohmelfs_create_entry(dir, dentry, 0, mode | S_IFDIR);
-       if (err)
-               inode_dec_link_count(dir);
-
-       return err;
-}
-
-static int pohmelfs_remove_entry(struct inode *dir, struct dentry *dentry)
-{
-       struct pohmelfs_sb *psb = POHMELFS_SB(dir->i_sb);
-       struct inode *inode = dentry->d_inode;
-       struct pohmelfs_inode *parent = POHMELFS_I(dir), *pi = POHMELFS_I(inode);
-       struct pohmelfs_name *n;
-       int err = -ENOENT;
-       struct qstr str = dentry->d_name;
-
-       err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK);
-       if (err)
-               return err;
-
-       str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
-
-       dprintk("%s: dir_ino: %llu, inode: %llu, name: '%s', nlink: %d.\n",
-                       __func__, parent->ino, pi->ino,
-                       str.name, (signed)inode->i_nlink);
-
-       BUG_ON(!inode);
-
-       mutex_lock(&parent->offset_lock);
-       n = pohmelfs_search_hash(parent, str.hash);
-       if (n) {
-               pohmelfs_fix_offset(parent, n);
-               if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state))
-                       pohmelfs_remove_child(pi, n);
-
-               pohmelfs_name_free(parent, n);
-               err = 0;
-       }
-       mutex_unlock(&parent->offset_lock);
-
-       if (!err) {
-               psb->avail_size += inode->i_size;
-
-               pohmelfs_inode_del_inode(psb, pi);
-
-               mark_inode_dirty(dir);
-
-               inode->i_ctime = dir->i_ctime;
-               if (inode->i_nlink)
-                       inode_dec_link_count(inode);
-       }
-
-       return err;
-}
-
-/*
- * Unlink and rmdir VFS callbacks.
- */
-static int pohmelfs_unlink(struct inode *dir, struct dentry *dentry)
-{
-       return pohmelfs_remove_entry(dir, dentry);
-}
-
-static int pohmelfs_rmdir(struct inode *dir, struct dentry *dentry)
-{
-       int err;
-       struct inode *inode = dentry->d_inode;
-
-       dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n",
-                       __func__, POHMELFS_I(dir)->ino, POHMELFS_I(inode)->ino,
-                       dentry->d_name.name, (signed)dir->i_nlink, (signed)inode->i_nlink);
-
-       err = pohmelfs_remove_entry(dir, dentry);
-       if (!err) {
-               inode_dec_link_count(dir);
-               inode_dec_link_count(inode);
-       }
-
-       return err;
-}
-
-/*
- * Link creation is synchronous.
- * I'm lazy.
- * Earth is somewhat round.
- */
-static int pohmelfs_create_link(struct pohmelfs_inode *parent, struct qstr *obj,
-               struct pohmelfs_inode *target, struct qstr *tstr)
-{
-       struct super_block *sb = parent->vfs_inode.i_sb;
-       struct pohmelfs_sb *psb = POHMELFS_SB(sb);
-       struct netfs_cmd *cmd;
-       struct netfs_trans *t;
-       void *data;
-       int err, parent_len, target_len = 0, cur_len, path_size = 0;
-
-       err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK);
-       if (err)
-               return err;
-
-       err = sb->s_op->write_inode(&parent->vfs_inode, 0);
-       if (err)
-               goto err_out_exit;
-
-       if (tstr)
-               target_len = tstr->len;
-
-       parent_len = pohmelfs_path_length(parent);
-       if (target)
-               target_len += pohmelfs_path_length(target);
-
-       if (parent_len < 0) {
-               err = parent_len;
-               goto err_out_exit;
-       }
-
-       if (target_len < 0) {
-               err = target_len;
-               goto err_out_exit;
-       }
-
-       t = netfs_trans_alloc(psb, parent_len + target_len + obj->len + 2, 0, 0);
-       if (!t) {
-               err = -ENOMEM;
-               goto err_out_exit;
-       }
-       cur_len = netfs_trans_cur_len(t);
-
-       cmd = netfs_trans_current(t);
-       if (IS_ERR(cmd)) {
-               err = PTR_ERR(cmd);
-               goto err_out_free;
-       }
-
-       data = (void *)(cmd + 1);
-       cur_len -= sizeof(struct netfs_cmd);
-
-       err = pohmelfs_construct_path_string(parent, data, parent_len);
-       if (err > 0) {
-               /* Do not place null-byte before the slash */
-               path_size = err - 1;
-               cur_len -= path_size;
-
-               err = snprintf(data + path_size, cur_len, "/%s|", obj->name);
-
-               path_size += err;
-               cur_len -= err;
-
-               cmd->ext = path_size - 1; /* No | symbol */
-
-               if (target) {
-                       err = pohmelfs_construct_path_string(target, data + path_size, target_len);
-                       if (err > 0) {
-                               path_size += err;
-                               cur_len -= err;
-                       }
-               }
-       }
-
-       if (err < 0)
-               goto err_out_free;
-
-       cmd->start = 0;
-
-       if (!target && tstr) {
-               if (tstr->len > cur_len - 1) {
-                       err = -ENAMETOOLONG;
-                       goto err_out_free;
-               }
-
-               err = snprintf(data + path_size, cur_len, "%s", tstr->name) + 1; /* 0-byte */
-               path_size += err;
-               cur_len -= err;
-               cmd->start = 1;
-       }
-
-       dprintk("%s: parent: %llu, obj: '%s', target_inode: %llu, target_str: '%s', full: '%s'.\n",
-                       __func__, parent->ino, obj->name, (target) ? target->ino : 0, (tstr) ? tstr->name : NULL,
-                       (char *)data);
-
-       cmd->cmd = NETFS_LINK;
-       cmd->size = path_size;
-       cmd->id = parent->ino;
-
-       netfs_convert_cmd(cmd);
-
-       netfs_trans_update(cmd, t, path_size);
-
-       err = netfs_trans_finish(t, psb);
-       if (err)
-               goto err_out_exit;
-
-       return 0;
-
-err_out_free:
-       t->result = err;
-       netfs_trans_put(t);
-err_out_exit:
-       return err;
-}
-
-/*
- *  VFS hard and soft link callbacks.
- */
-static int pohmelfs_link(struct dentry *old_dentry, struct inode *dir,
-       struct dentry *dentry)
-{
-       struct inode *inode = old_dentry->d_inode;
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       int err;
-       struct qstr str = dentry->d_name;
-
-       str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
-
-       err = inode->i_sb->s_op->write_inode(inode, 0);
-       if (err)
-               return err;
-
-       err = pohmelfs_create_link(POHMELFS_I(dir), &str, pi, NULL);
-       if (err)
-               return err;
-
-       return pohmelfs_create_entry(dir, dentry, pi->ino, inode->i_mode);
-}
-
-static int pohmelfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
-{
-       struct qstr sym_str;
-       struct qstr str = dentry->d_name;
-       struct inode *inode;
-       int err;
-
-       str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0);
-
-       sym_str.name = symname;
-       sym_str.len = strlen(symname);
-
-       err = pohmelfs_create_link(POHMELFS_I(dir), &str, NULL, &sym_str);
-       if (err)
-               goto err_out_exit;
-
-       err = pohmelfs_create_entry(dir, dentry, 0, S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
-       if (err)
-               goto err_out_exit;
-
-       inode = dentry->d_inode;
-
-       err = page_symlink(inode, symname, sym_str.len + 1);
-       if (err)
-               goto err_out_put;
-
-       return 0;
-
-err_out_put:
-       iput(inode);
-err_out_exit:
-       return err;
-}
-
-static int pohmelfs_send_rename(struct pohmelfs_inode *pi, struct pohmelfs_inode *parent,
-               struct qstr *str)
-{
-       int path_len, err, total_len = 0, inode_len, parent_len;
-       char *path;
-       struct netfs_trans *t;
-       struct netfs_cmd *cmd;
-       struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
-
-       parent_len = pohmelfs_path_length(parent);
-       inode_len = pohmelfs_path_length(pi);
-
-       if (parent_len < 0 || inode_len < 0)
-               return -EINVAL;
-
-       path_len = parent_len + inode_len + str->len + 3;
-
-       t = netfs_trans_alloc(psb, path_len, 0, 0);
-       if (!t)
-               return -ENOMEM;
-
-       cmd = netfs_trans_current(t);
-       path = (char *)(cmd + 1);
-
-       err = pohmelfs_construct_path_string(pi, path, inode_len);
-       if (err < 0)
-               goto err_out_unlock;
-
-       cmd->ext = err;
-
-       path += err;
-       total_len += err;
-       path_len -= err;
-
-       *path = '|';
-       path++;
-       total_len++;
-       path_len--;
-
-       err = pohmelfs_construct_path_string(parent, path, parent_len);
-       if (err < 0)
-               goto err_out_unlock;
-
-       /*
-        * Do not place a null-byte before the final slash and the name.
-        */
-       err--;
-       path += err;
-       total_len += err;
-       path_len -= err;
-
-       err = snprintf(path, path_len - 1, "/%s", str->name);
-
-       total_len += err + 1; /* 0 symbol */
-       path_len -= err + 1;
-
-       cmd->cmd = NETFS_RENAME;
-       cmd->id = pi->ino;
-       cmd->start = parent->ino;
-       cmd->size = total_len;
-
-       netfs_convert_cmd(cmd);
-
-       netfs_trans_update(cmd, t, total_len);
-
-       return netfs_trans_finish(t, psb);
-
-err_out_unlock:
-       netfs_trans_free(t);
-       return err;
-}
-
-static int pohmelfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-                       struct inode *new_dir, struct dentry *new_dentry)
-{
-       struct inode *inode = old_dentry->d_inode;
-       struct pohmelfs_inode *old_parent, *pi, *new_parent;
-       struct qstr str = new_dentry->d_name;
-       struct pohmelfs_name *n;
-       unsigned int old_hash;
-       int err = -ENOENT;
-
-       pi = POHMELFS_I(inode);
-       old_parent = POHMELFS_I(old_dir);
-
-       if (new_dir)
-               new_dir->i_sb->s_op->write_inode(new_dir, 0);
-
-       old_hash = jhash(old_dentry->d_name.name, old_dentry->d_name.len, 0);
-       str.hash = jhash(new_dentry->d_name.name, new_dentry->d_name.len, 0);
-
-       str.len = new_dentry->d_name.len;
-       str.name = new_dentry->d_name.name;
-       str.hash = jhash(new_dentry->d_name.name, new_dentry->d_name.len, 0);
-
-       if (new_dir) {
-               new_parent = POHMELFS_I(new_dir);
-               err = -ENOTEMPTY;
-
-               if (S_ISDIR(inode->i_mode) &&
-                               new_parent->total_len <= 3)
-                       goto err_out_exit;
-       } else {
-               new_parent = old_parent;
-       }
-
-       dprintk("%s: ino: %llu, parent: %llu, name: '%s' -> parent: %llu, name: '%s', i_size: %llu.\n",
-                       __func__, pi->ino, old_parent->ino, old_dentry->d_name.name,
-                       new_parent->ino, new_dentry->d_name.name, inode->i_size);
-
-       if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state) &&
-                       test_bit(NETFS_INODE_OWNED, &pi->state)) {
-               err = pohmelfs_send_rename(pi, new_parent, &str);
-               if (err)
-                       goto err_out_exit;
-       }
-
-       n = pohmelfs_name_alloc(str.len + 1);
-       if (!n)
-               goto err_out_exit;
-
-       mutex_lock(&new_parent->offset_lock);
-       n->ino = pi->ino;
-       n->mode = inode->i_mode;
-       n->len = str.len;
-       n->hash = str.hash;
-       sprintf(n->data, "%s", str.name);
-
-       err = pohmelfs_insert_name(new_parent, n);
-       mutex_unlock(&new_parent->offset_lock);
-
-       if (err)
-               goto err_out_exit;
-
-       mutex_lock(&old_parent->offset_lock);
-       n = pohmelfs_search_hash(old_parent, old_hash);
-       if (n)
-               pohmelfs_name_del(old_parent, n);
-       mutex_unlock(&old_parent->offset_lock);
-
-       mark_inode_dirty(inode);
-       mark_inode_dirty(&new_parent->vfs_inode);
-
-       WARN_ON_ONCE(list_empty(&inode->i_dentry));
-
-       return 0;
-
-err_out_exit:
-
-       clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
-
-       return err;
-}
-
-/*
- * POHMELFS directory inode operations.
- */
-const struct inode_operations pohmelfs_dir_inode_ops = {
-       .link           = pohmelfs_link,
-       .symlink        = pohmelfs_symlink,
-       .unlink         = pohmelfs_unlink,
-       .mkdir          = pohmelfs_mkdir,
-       .rmdir          = pohmelfs_rmdir,
-       .create         = pohmelfs_create,
-       .lookup         = pohmelfs_lookup,
-       .setattr        = pohmelfs_setattr,
-       .rename         = pohmelfs_rename,
-};
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c
deleted file mode 100644 (file)
index 807e3f3..0000000
+++ /dev/null
@@ -1,2055 +0,0 @@
-/*
- * 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.
- */
-
-#include <linux/module.h>
-#include <linux/backing-dev.h>
-#include <linux/crypto.h>
-#include <linux/fs.h>
-#include <linux/jhash.h>
-#include <linux/hash.h>
-#include <linux/ktime.h>
-#include <linux/mm.h>
-#include <linux/mount.h>
-#include <linux/pagemap.h>
-#include <linux/pagevec.h>
-#include <linux/parser.h>
-#include <linux/swap.h>
-#include <linux/slab.h>
-#include <linux/statfs.h>
-#include <linux/writeback.h>
-#include <linux/prefetch.h>
-
-#include "netfs.h"
-
-#define POHMELFS_MAGIC_NUM     0x504f482e
-
-static struct kmem_cache *pohmelfs_inode_cache;
-static atomic_t psb_bdi_num = ATOMIC_INIT(0);
-
-/*
- * Removes inode from all trees, drops local name cache and removes all queued
- * requests for object removal.
- */
-void pohmelfs_inode_del_inode(struct pohmelfs_sb *psb, struct pohmelfs_inode *pi)
-{
-       mutex_lock(&pi->offset_lock);
-       pohmelfs_free_names(pi);
-       mutex_unlock(&pi->offset_lock);
-
-       dprintk("%s: deleted stuff in ino: %llu.\n", __func__, pi->ino);
-}
-
-/*
- * Sync inode to server.
- * Returns zero in success and negative error value otherwise.
- * It will gather path to root directory into structures containing
- * creation mode, permissions and names, so that the whole path
- * to given inode could be created using only single network command.
- */
-int pohmelfs_write_inode_create(struct inode *inode, struct netfs_trans *trans)
-{
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       int err = -ENOMEM, size;
-       struct netfs_cmd *cmd;
-       void *data;
-       int cur_len = netfs_trans_cur_len(trans);
-
-       if (unlikely(cur_len < 0))
-               return -ETOOSMALL;
-
-       cmd = netfs_trans_current(trans);
-       cur_len -= sizeof(struct netfs_cmd);
-
-       data = (void *)(cmd + 1);
-
-       err = pohmelfs_construct_path_string(pi, data, cur_len);
-       if (err < 0)
-               goto err_out_exit;
-
-       size = err;
-
-       cmd->start = i_size_read(inode);
-       cmd->cmd = NETFS_CREATE;
-       cmd->size = size;
-       cmd->id = pi->ino;
-       cmd->ext = inode->i_mode;
-
-       netfs_convert_cmd(cmd);
-
-       netfs_trans_update(cmd, trans, size);
-
-       return 0;
-
-err_out_exit:
-       printk("%s: completed ino: %llu, err: %d.\n", __func__, pi->ino, err);
-       return err;
-}
-
-static int pohmelfs_write_trans_complete(struct page **pages, unsigned int page_num,
-               void *private, int err)
-{
-       unsigned i;
-
-       dprintk("%s: pages: %lu-%lu, page_num: %u, err: %d.\n",
-                       __func__, pages[0]->index, pages[page_num-1]->index,
-                       page_num, err);
-
-       for (i = 0; i < page_num; i++) {
-               struct page *page = pages[i];
-
-               if (!page)
-                       continue;
-
-               end_page_writeback(page);
-
-               if (err < 0) {
-                       SetPageError(page);
-                       set_page_dirty(page);
-               }
-
-               unlock_page(page);
-               page_cache_release(page);
-
-               /* dprintk("%s: %3u/%u: page: %p.\n", __func__, i, page_num, page); */
-       }
-       return err;
-}
-
-static int pohmelfs_inode_has_dirty_pages(struct address_space *mapping, pgoff_t index)
-{
-       int ret;
-       struct page *page;
-
-       rcu_read_lock();
-       ret = radix_tree_gang_lookup_tag(&mapping->page_tree,
-                               (void **)&page, index, 1, PAGECACHE_TAG_DIRTY);
-       rcu_read_unlock();
-       return ret;
-}
-
-static int pohmelfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
-{
-       struct inode *inode = mapping->host;
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-       int err = 0;
-       int done = 0;
-       int nr_pages;
-       pgoff_t index;
-       pgoff_t end;            /* Inclusive */
-       int scanned = 0;
-       int range_whole = 0;
-
-       if (wbc->range_cyclic) {
-               index = mapping->writeback_index; /* Start from prev offset */
-               end = -1;
-       } else {
-               index = wbc->range_start >> PAGE_CACHE_SHIFT;
-               end = wbc->range_end >> PAGE_CACHE_SHIFT;
-               if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
-                       range_whole = 1;
-               scanned = 1;
-       }
-retry:
-       while (!done && (index <= end)) {
-               unsigned int i = min(end - index, (pgoff_t)psb->trans_max_pages);
-               int path_len;
-               struct netfs_trans *trans;
-
-               err = pohmelfs_inode_has_dirty_pages(mapping, index);
-               if (!err)
-                       break;
-
-               err = pohmelfs_path_length(pi);
-               if (err < 0)
-                       break;
-
-               path_len = err;
-
-               if (path_len <= 2) {
-                       err = -ENOENT;
-                       break;
-               }
-
-               trans = netfs_trans_alloc(psb, path_len, 0, i);
-               if (!trans) {
-                       err = -ENOMEM;
-                       break;
-               }
-               trans->complete = &pohmelfs_write_trans_complete;
-
-               trans->page_num = nr_pages = find_get_pages_tag(mapping, &index,
-                               PAGECACHE_TAG_DIRTY, trans->page_num,
-                               trans->pages);
-
-               dprintk("%s: t: %p, nr_pages: %u, end: %lu, index: %lu, max: %u.\n",
-                               __func__, trans, nr_pages, end, index, trans->page_num);
-
-               if (!nr_pages)
-                       goto err_out_reset;
-
-               err = pohmelfs_write_inode_create(inode, trans);
-               if (err)
-                       goto err_out_reset;
-
-               err = 0;
-               scanned = 1;
-
-               for (i = 0; i < trans->page_num; i++) {
-                       struct page *page = trans->pages[i];
-
-                       lock_page(page);
-
-                       if (unlikely(page->mapping != mapping))
-                               goto out_continue;
-
-                       if (!wbc->range_cyclic && page->index > end) {
-                               done = 1;
-                               goto out_continue;
-                       }
-
-                       if (wbc->sync_mode != WB_SYNC_NONE)
-                               wait_on_page_writeback(page);
-
-                       if (PageWriteback(page) ||
-                           !clear_page_dirty_for_io(page)) {
-                               dprintk("%s: not clear for io page: %p, writeback: %d.\n",
-                                               __func__, page, PageWriteback(page));
-                               goto out_continue;
-                       }
-
-                       set_page_writeback(page);
-
-                       trans->attached_size += page_private(page);
-                       trans->attached_pages++;
-#if 0
-                       dprintk("%s: %u/%u added trans: %p, gen: %u, page: %p, [High: %d], size: %lu, idx: %lu.\n",
-                                       __func__, i, trans->page_num, trans, trans->gen, page,
-                                       !!PageHighMem(page), page_private(page), page->index);
-#endif
-                       wbc->nr_to_write--;
-
-                       if (wbc->nr_to_write <= 0)
-                               done = 1;
-
-                       continue;
-out_continue:
-                       unlock_page(page);
-                       trans->pages[i] = NULL;
-               }
-
-               err = netfs_trans_finish(trans, psb);
-               if (err)
-                       break;
-
-               continue;
-
-err_out_reset:
-               trans->result = err;
-               netfs_trans_reset(trans);
-               netfs_trans_put(trans);
-               break;
-       }
-
-       if (!scanned && !done) {
-               /*
-                * We hit the last page and there is more work to be done: wrap
-                * back to the start of the file
-                */
-               scanned = 1;
-               index = 0;
-               goto retry;
-       }
-
-       if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
-               mapping->writeback_index = index;
-
-       return err;
-}
-
-/*
- * Inode writeback creation completion callback.
- * Only invoked for just created inodes, which do not have pages attached,
- * like dirs and empty files.
- */
-static int pohmelfs_write_inode_complete(struct page **pages, unsigned int page_num,
-               void *private, int err)
-{
-       struct inode *inode = private;
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-
-       if (inode) {
-               if (err) {
-                       mark_inode_dirty(inode);
-                       clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
-               } else {
-                       set_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
-               }
-
-               pohmelfs_put_inode(pi);
-       }
-
-       return err;
-}
-
-int pohmelfs_write_create_inode(struct pohmelfs_inode *pi)
-{
-       struct netfs_trans *t;
-       struct inode *inode = &pi->vfs_inode;
-       struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-       int err;
-
-       if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state))
-               return 0;
-
-       dprintk("%s: started ino: %llu.\n", __func__, pi->ino);
-
-       err = pohmelfs_path_length(pi);
-       if (err < 0)
-               goto err_out_exit;
-
-       t = netfs_trans_alloc(psb, err + 1, 0, 0);
-       if (!t) {
-               err = -ENOMEM;
-               goto err_out_exit;
-       }
-       t->complete = pohmelfs_write_inode_complete;
-       t->private = igrab(inode);
-       if (!t->private) {
-               err = -ENOENT;
-               goto err_out_put;
-       }
-
-       err = pohmelfs_write_inode_create(inode, t);
-       if (err)
-               goto err_out_put;
-
-       netfs_trans_finish(t, POHMELFS_SB(inode->i_sb));
-
-       return 0;
-
-err_out_put:
-       t->result = err;
-       netfs_trans_put(t);
-err_out_exit:
-       return err;
-}
-
-/*
- * Sync all not-yet-created children in given directory to the server.
- */
-static int pohmelfs_write_inode_create_children(struct inode *inode)
-{
-       struct pohmelfs_inode *parent = POHMELFS_I(inode);
-       struct super_block *sb = inode->i_sb;
-       struct pohmelfs_name *n;
-
-       while (!list_empty(&parent->sync_create_list)) {
-               n = NULL;
-               mutex_lock(&parent->offset_lock);
-               if (!list_empty(&parent->sync_create_list)) {
-                       n = list_first_entry(&parent->sync_create_list,
-                               struct pohmelfs_name, sync_create_entry);
-                       list_del_init(&n->sync_create_entry);
-               }
-               mutex_unlock(&parent->offset_lock);
-
-               if (!n)
-                       break;
-
-               inode = ilookup(sb, n->ino);
-
-               dprintk("%s: parent: %llu, ino: %llu, inode: %p.\n",
-                               __func__, parent->ino, n->ino, inode);
-
-               if (inode && (inode->i_state & I_DIRTY)) {
-                       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-                       pohmelfs_write_create_inode(pi);
-                       /* pohmelfs_meta_command(pi, NETFS_INODE_INFO, 0, NULL, NULL, 0); */
-                       iput(inode);
-               }
-       }
-
-       return 0;
-}
-
-/*
- * Removes given child from given inode on server.
- */
-int pohmelfs_remove_child(struct pohmelfs_inode *pi, struct pohmelfs_name *n)
-{
-       return pohmelfs_meta_command_data(pi, pi->ino, NETFS_REMOVE, NULL, 0, NULL, NULL, 0);
-}
-
-/*
- * Writeback for given inode.
- */
-static int pohmelfs_write_inode(struct inode *inode,
-                               struct writeback_control *wbc)
-{
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-
-       pohmelfs_write_create_inode(pi);
-       pohmelfs_write_inode_create_children(inode);
-
-       return 0;
-}
-
-/*
- * It is not exported, sorry...
- */
-static inline wait_queue_head_t *page_waitqueue(struct page *page)
-{
-       const struct zone *zone = page_zone(page);
-
-       return &zone->wait_table[hash_ptr(page, zone->wait_table_bits)];
-}
-
-static int pohmelfs_wait_on_page_locked(struct page *page)
-{
-       struct pohmelfs_sb *psb = POHMELFS_SB(page->mapping->host->i_sb);
-       long ret = psb->wait_on_page_timeout;
-       DEFINE_WAIT_BIT(wait, &page->flags, PG_locked);
-       int err = 0;
-
-       if (!PageLocked(page))
-               return 0;
-
-       for (;;) {
-               prepare_to_wait(page_waitqueue(page),
-                               &wait.wait, TASK_INTERRUPTIBLE);
-
-               dprintk("%s: page: %p, locked: %d, uptodate: %d, error: %d, flags: %lx.\n",
-                               __func__, page, PageLocked(page), PageUptodate(page),
-                               PageError(page), page->flags);
-
-               if (!PageLocked(page))
-                       break;
-
-               if (!signal_pending(current)) {
-                       ret = schedule_timeout(ret);
-                       if (!ret)
-                               break;
-                       continue;
-               }
-               ret = -ERESTARTSYS;
-               break;
-       }
-       finish_wait(page_waitqueue(page), &wait.wait);
-
-       if (!ret)
-               err = -ETIMEDOUT;
-
-
-       if (!err)
-               SetPageUptodate(page);
-
-       if (err)
-               printk("%s: page: %p, uptodate: %d, locked: %d, err: %d.\n",
-                       __func__, page, PageUptodate(page), PageLocked(page), err);
-
-       return err;
-}
-
-static int pohmelfs_read_page_complete(struct page **pages, unsigned int page_num,
-               void *private, int err)
-{
-       struct page *page = private;
-
-       if (PageChecked(page))
-               return err;
-
-       if (err < 0) {
-               dprintk("%s: page: %p, err: %d.\n", __func__, page, err);
-               SetPageError(page);
-       }
-
-       unlock_page(page);
-
-       return err;
-}
-
-/*
- * Read a page from remote server.
- * Function will wait until page is unlocked.
- */
-static int pohmelfs_readpage(struct file *file, struct page *page)
-{
-       struct inode *inode = page->mapping->host;
-       struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       struct netfs_trans *t;
-       struct netfs_cmd *cmd;
-       int err, path_len;
-       void *data;
-       u64 isize;
-
-       err = pohmelfs_data_lock(pi, page->index << PAGE_CACHE_SHIFT,
-                       PAGE_SIZE, POHMELFS_READ_LOCK);
-       if (err)
-               goto err_out_exit;
-
-       isize = i_size_read(inode);
-       if (isize <= page->index << PAGE_CACHE_SHIFT) {
-               SetPageUptodate(page);
-               unlock_page(page);
-               return 0;
-       }
-
-       path_len = pohmelfs_path_length(pi);
-       if (path_len < 0) {
-               err = path_len;
-               goto err_out_exit;
-       }
-
-       t = netfs_trans_alloc(psb, path_len, NETFS_TRANS_SINGLE_DST, 0);
-       if (!t) {
-               err = -ENOMEM;
-               goto err_out_exit;
-       }
-
-       t->complete = pohmelfs_read_page_complete;
-       t->private = page;
-
-       cmd = netfs_trans_current(t);
-       data = (void *)(cmd + 1);
-
-       err = pohmelfs_construct_path_string(pi, data, path_len);
-       if (err < 0)
-               goto err_out_free;
-
-       path_len = err;
-
-       cmd->id = pi->ino;
-       cmd->start = page->index;
-       cmd->start <<= PAGE_CACHE_SHIFT;
-       cmd->size = PAGE_CACHE_SIZE + path_len;
-       cmd->cmd = NETFS_READ_PAGE;
-       cmd->ext = path_len;
-
-       dprintk("%s: path: '%s', page: %p, ino: %llu, start: %llu, size: %lu.\n",
-                       __func__, (char *)data, page, pi->ino, cmd->start, PAGE_CACHE_SIZE);
-
-       netfs_convert_cmd(cmd);
-       netfs_trans_update(cmd, t, path_len);
-
-       err = netfs_trans_finish(t, psb);
-       if (err)
-               goto err_out_return;
-
-       return pohmelfs_wait_on_page_locked(page);
-
-err_out_free:
-       t->result = err;
-       netfs_trans_put(t);
-err_out_exit:
-       SetPageError(page);
-       if (PageLocked(page))
-               unlock_page(page);
-err_out_return:
-       printk("%s: page: %p, start: %lu, size: %lu, err: %d.\n",
-               __func__, page, page->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE, err);
-
-       return err;
-}
-
-/*
- * Write begin/end magic.
- * Allocates a page and writes inode if it was not synced to server before.
- */
-static int pohmelfs_write_begin(struct file *file, struct address_space *mapping,
-               loff_t pos, unsigned len, unsigned flags,
-               struct page **pagep, void **fsdata)
-{
-       struct inode *inode = mapping->host;
-       struct page *page;
-       pgoff_t index;
-       unsigned start, end;
-       int err;
-
-       *pagep = NULL;
-
-       index = pos >> PAGE_CACHE_SHIFT;
-       start = pos & (PAGE_CACHE_SIZE - 1);
-       end = start + len;
-
-       page = grab_cache_page(mapping, index);
-#if 0
-       dprintk("%s: page: %p pos: %llu, len: %u, index: %lu, start: %u, end: %u, uptodate: %d.\n",
-                       __func__, page, pos, len, index, start, end, PageUptodate(page));
-#endif
-       if (!page) {
-               err = -ENOMEM;
-               goto err_out_exit;
-       }
-
-       while (!PageUptodate(page)) {
-               if (start && test_bit(NETFS_INODE_REMOTE_SYNCED, &POHMELFS_I(inode)->state)) {
-                       err = pohmelfs_readpage(file, page);
-                       if (err)
-                               goto err_out_exit;
-
-                       lock_page(page);
-                       continue;
-               }
-
-               if (len != PAGE_CACHE_SIZE) {
-                       void *kaddr = kmap_atomic(page, KM_USER0);
-
-                       memset(kaddr + start, 0, PAGE_CACHE_SIZE - start);
-                       flush_dcache_page(page);
-                       kunmap_atomic(kaddr, KM_USER0);
-               }
-               SetPageUptodate(page);
-       }
-
-       set_page_private(page, end);
-
-       *pagep = page;
-
-       return 0;
-
-err_out_exit:
-       page_cache_release(page);
-       *pagep = NULL;
-
-       return err;
-}
-
-static int pohmelfs_write_end(struct file *file, struct address_space *mapping,
-                       loff_t pos, unsigned len, unsigned copied,
-                       struct page *page, void *fsdata)
-{
-       struct inode *inode = mapping->host;
-
-       if (copied != len) {
-               unsigned from = pos & (PAGE_CACHE_SIZE - 1);
-               void *kaddr = kmap_atomic(page, KM_USER0);
-
-               memset(kaddr + from + copied, 0, len - copied);
-               flush_dcache_page(page);
-               kunmap_atomic(kaddr, KM_USER0);
-       }
-
-       SetPageUptodate(page);
-       set_page_dirty(page);
-#if 0
-       dprintk("%s: page: %p [U: %d, D: %d, L: %d], pos: %llu, len: %u, copied: %u.\n",
-                       __func__, page,
-                       PageUptodate(page), PageDirty(page), PageLocked(page),
-                       pos, len, copied);
-#endif
-       flush_dcache_page(page);
-
-       unlock_page(page);
-       page_cache_release(page);
-
-       if (pos + copied > inode->i_size) {
-               struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-
-               psb->avail_size -= pos + copied - inode->i_size;
-
-               i_size_write(inode, pos + copied);
-       }
-
-       return copied;
-}
-
-static int pohmelfs_readpages_trans_complete(struct page **__pages, unsigned int page_num,
-               void *private, int err)
-{
-       struct pohmelfs_inode *pi = private;
-       unsigned int i, num;
-       struct page **pages, *page = (struct page *)__pages;
-       loff_t index = page->index;
-
-       pages = kzalloc(sizeof(void *) * page_num, GFP_NOIO);
-       if (!pages)
-               return -ENOMEM;
-
-       num = find_get_pages_contig(pi->vfs_inode.i_mapping, index, page_num, pages);
-       if (num <= 0) {
-               err = num;
-               goto err_out_free;
-       }
-
-       for (i = 0; i < num; ++i) {
-               page = pages[i];
-
-               if (err)
-                       printk("%s: %u/%u: page: %p, index: %lu, uptodate: %d, locked: %d, err: %d.\n",
-                               __func__, i, num, page, page->index,
-                               PageUptodate(page), PageLocked(page), err);
-
-               if (!PageChecked(page)) {
-                       if (err < 0)
-                               SetPageError(page);
-                       unlock_page(page);
-               }
-               page_cache_release(page);
-               page_cache_release(page);
-       }
-
-err_out_free:
-       kfree(pages);
-       return err;
-}
-
-static int pohmelfs_send_readpages(struct pohmelfs_inode *pi, struct page *first, unsigned int num)
-{
-       struct netfs_trans *t;
-       struct netfs_cmd *cmd;
-       struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
-       int err, path_len;
-       void *data;
-
-       err = pohmelfs_data_lock(pi, first->index << PAGE_CACHE_SHIFT,
-                       num * PAGE_SIZE, POHMELFS_READ_LOCK);
-       if (err)
-               goto err_out_exit;
-
-       path_len = pohmelfs_path_length(pi);
-       if (path_len < 0) {
-               err = path_len;
-               goto err_out_exit;
-       }
-
-       t = netfs_trans_alloc(psb, path_len, NETFS_TRANS_SINGLE_DST, 0);
-       if (!t) {
-               err = -ENOMEM;
-               goto err_out_exit;
-       }
-
-       cmd = netfs_trans_current(t);
-       data = (void *)(cmd + 1);
-
-       t->complete = pohmelfs_readpages_trans_complete;
-       t->private = pi;
-       t->page_num = num;
-       t->pages = (struct page **)first;
-
-       err = pohmelfs_construct_path_string(pi, data, path_len);
-       if (err < 0)
-               goto err_out_put;
-
-       path_len = err;
-
-       cmd->cmd = NETFS_READ_PAGES;
-       cmd->start = first->index;
-       cmd->start <<= PAGE_CACHE_SHIFT;
-       cmd->size = (num << 8 | PAGE_CACHE_SHIFT);
-       cmd->id = pi->ino;
-       cmd->ext = path_len;
-
-       dprintk("%s: t: %p, gen: %u, path: '%s', path_len: %u, "
-                       "start: %lu, num: %u.\n",
-                       __func__, t, t->gen, (char *)data, path_len,
-                       first->index, num);
-
-       netfs_convert_cmd(cmd);
-       netfs_trans_update(cmd, t, path_len);
-
-       return netfs_trans_finish(t, psb);
-
-err_out_put:
-       netfs_trans_free(t);
-err_out_exit:
-       pohmelfs_readpages_trans_complete((struct page **)first, num, pi, err);
-       return err;
-}
-
-#define list_to_page(head) (list_entry((head)->prev, struct page, lru))
-
-static int pohmelfs_readpages(struct file *file, struct address_space *mapping,
-                       struct list_head *pages, unsigned nr_pages)
-{
-       unsigned int page_idx, num = 0;
-       struct page *page = NULL, *first = NULL;
-
-       for (page_idx = 0; page_idx < nr_pages; page_idx++) {
-               page = list_to_page(pages);
-
-               prefetchw(&page->flags);
-               list_del(&page->lru);
-
-               if (!add_to_page_cache_lru(page, mapping,
-                                       page->index, GFP_KERNEL)) {
-
-                       if (!num) {
-                               num = 1;
-                               first = page;
-                               continue;
-                       }
-
-                       dprintk("%s: added to lru page: %p, page_index: %lu, first_index: %lu.\n",
-                                       __func__, page, page->index, first->index);
-
-                       if (unlikely(first->index + num != page->index) || (num > 500)) {
-                               pohmelfs_send_readpages(POHMELFS_I(mapping->host),
-                                               first, num);
-                               first = page;
-                               num = 0;
-                       }
-
-                       num++;
-               }
-       }
-       pohmelfs_send_readpages(POHMELFS_I(mapping->host), first, num);
-
-       /*
-        * This will be sync read, so when last page is processed,
-        * all previous are alerady unlocked and ready to be used.
-        */
-       return 0;
-}
-
-/*
- * Small address space operations for POHMELFS.
- */
-const struct address_space_operations pohmelfs_aops = {
-       .readpage               = pohmelfs_readpage,
-       .readpages              = pohmelfs_readpages,
-       .writepages             = pohmelfs_writepages,
-       .write_begin            = pohmelfs_write_begin,
-       .write_end              = pohmelfs_write_end,
-       .set_page_dirty         = __set_page_dirty_nobuffers,
-};
-
-static void pohmelfs_i_callback(struct rcu_head *head)
-{
-       struct inode *inode = container_of(head, struct inode, i_rcu);
-       kmem_cache_free(pohmelfs_inode_cache, POHMELFS_I(inode));
-}
-
-/*
- * ->destroy_inode() callback. Deletes inode from the caches
- *  and frees private data.
- */
-static void pohmelfs_destroy_inode(struct inode *inode)
-{
-       struct super_block *sb = inode->i_sb;
-       struct pohmelfs_sb *psb = POHMELFS_SB(sb);
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-
-       /* pohmelfs_data_unlock(pi, 0, inode->i_size, POHMELFS_READ_LOCK); */
-
-       pohmelfs_inode_del_inode(psb, pi);
-
-       dprintk("%s: pi: %p, inode: %p, ino: %llu.\n",
-               __func__, pi, &pi->vfs_inode, pi->ino);
-       atomic_long_dec(&psb->total_inodes);
-       call_rcu(&inode->i_rcu, pohmelfs_i_callback);
-}
-
-/*
- * ->alloc_inode() callback. Allocates inode and initializes private data.
- */
-static struct inode *pohmelfs_alloc_inode(struct super_block *sb)
-{
-       struct pohmelfs_inode *pi;
-
-       pi = kmem_cache_alloc(pohmelfs_inode_cache, GFP_NOIO);
-       if (!pi)
-               return NULL;
-
-       pi->hash_root = RB_ROOT;
-       mutex_init(&pi->offset_lock);
-
-       INIT_LIST_HEAD(&pi->sync_create_list);
-
-       INIT_LIST_HEAD(&pi->inode_entry);
-
-       pi->lock_type = 0;
-       pi->state = 0;
-       pi->total_len = 0;
-       pi->drop_count = 0;
-
-       dprintk("%s: pi: %p, inode: %p.\n", __func__, pi, &pi->vfs_inode);
-
-       atomic_long_inc(&POHMELFS_SB(sb)->total_inodes);
-
-       return &pi->vfs_inode;
-}
-
-/*
- * We want fsync() to work on POHMELFS.
- */
-static int pohmelfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
-{
-       struct inode *inode = file->f_mapping->host;
-       int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
-       if (!err) {
-               mutex_lock(&inode->i_mutex);
-               err = sync_inode_metadata(inode, 1);
-               mutex_unlock(&inode->i_mutex);
-       }
-       return err;
-}
-
-ssize_t pohmelfs_write(struct file *file, const char __user *buf,
-               size_t len, loff_t *ppos)
-{
-       struct address_space *mapping = file->f_mapping;
-       struct inode *inode = mapping->host;
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len };
-       struct kiocb kiocb;
-       ssize_t ret;
-       loff_t pos = *ppos;
-
-       init_sync_kiocb(&kiocb, file);
-       kiocb.ki_pos = pos;
-       kiocb.ki_left = len;
-
-       dprintk("%s: len: %zu, pos: %llu.\n", __func__, len, pos);
-
-       mutex_lock(&inode->i_mutex);
-       ret = pohmelfs_data_lock(pi, pos, len, POHMELFS_WRITE_LOCK);
-       if (ret)
-               goto err_out_unlock;
-
-       ret = __generic_file_aio_write(&kiocb, &iov, 1, &kiocb.ki_pos);
-       *ppos = kiocb.ki_pos;
-
-       mutex_unlock(&inode->i_mutex);
-       WARN_ON(ret < 0);
-
-       if (ret > 0) {
-               ssize_t err;
-
-               err = generic_write_sync(file, pos, ret);
-               if (err < 0)
-                       ret = err;
-               WARN_ON(ret < 0);
-       }
-
-       return ret;
-
-err_out_unlock:
-       mutex_unlock(&inode->i_mutex);
-       return ret;
-}
-
-static const struct file_operations pohmelfs_file_ops = {
-       .open           = generic_file_open,
-       .fsync          = pohmelfs_fsync,
-
-       .llseek         = generic_file_llseek,
-
-       .read           = do_sync_read,
-       .aio_read       = generic_file_aio_read,
-
-       .mmap           = generic_file_mmap,
-
-       .splice_read    = generic_file_splice_read,
-       .splice_write   = generic_file_splice_write,
-
-       .write          = pohmelfs_write,
-       .aio_write      = generic_file_aio_write,
-};
-
-const struct inode_operations pohmelfs_symlink_inode_operations = {
-       .readlink       = generic_readlink,
-       .follow_link    = page_follow_link_light,
-       .put_link       = page_put_link,
-};
-
-int pohmelfs_setattr_raw(struct inode *inode, struct iattr *attr)
-{
-       int err;
-
-       err = inode_change_ok(inode, attr);
-       if (err) {
-               dprintk("%s: ino: %llu, inode changes are not allowed.\n", __func__, POHMELFS_I(inode)->ino);
-               goto err_out_exit;
-       }
-
-       if ((attr->ia_valid & ATTR_SIZE) &&
-           attr->ia_size != i_size_read(inode)) {
-               err = vmtruncate(inode, attr->ia_size);
-               if (err) {
-                       dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino);
-                       goto err_out_exit;
-               }
-       }
-
-       setattr_copy(inode, attr);
-       mark_inode_dirty(inode);
-
-       dprintk("%s: ino: %llu, mode: %o -> %o, uid: %u -> %u, gid: %u -> %u, size: %llu -> %llu.\n",
-                       __func__, POHMELFS_I(inode)->ino, inode->i_mode, attr->ia_mode,
-                       inode->i_uid, attr->ia_uid, inode->i_gid, attr->ia_gid, inode->i_size, attr->ia_size);
-
-       return 0;
-
-err_out_exit:
-       return err;
-}
-
-int pohmelfs_setattr(struct dentry *dentry, struct iattr *attr)
-{
-       struct inode *inode = dentry->d_inode;
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       int err;
-
-       err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_WRITE_LOCK);
-       if (err)
-               goto err_out_exit;
-
-       err = security_inode_setattr(dentry, attr);
-       if (err)
-               goto err_out_exit;
-
-       err = pohmelfs_setattr_raw(inode, attr);
-       if (err)
-               goto err_out_exit;
-
-       return 0;
-
-err_out_exit:
-       return err;
-}
-
-static int pohmelfs_send_xattr_req(struct pohmelfs_inode *pi, u64 id, u64 start,
-               const char *name, const void *value, size_t attrsize, int command)
-{
-       struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
-       int err, path_len, namelen = strlen(name) + 1; /* 0-byte */
-       struct netfs_trans *t;
-       struct netfs_cmd *cmd;
-       void *data;
-
-       dprintk("%s: id: %llu, start: %llu, name: '%s', attrsize: %zu, cmd: %d.\n",
-                       __func__, id, start, name, attrsize, command);
-
-       path_len = pohmelfs_path_length(pi);
-       if (path_len < 0) {
-               err = path_len;
-               goto err_out_exit;
-       }
-
-       t = netfs_trans_alloc(psb, namelen + path_len + attrsize, 0, 0);
-       if (!t) {
-               err = -ENOMEM;
-               goto err_out_exit;
-       }
-
-       cmd = netfs_trans_current(t);
-       data = cmd + 1;
-
-       path_len = pohmelfs_construct_path_string(pi, data, path_len);
-       if (path_len < 0) {
-               err = path_len;
-               goto err_out_put;
-       }
-       data += path_len;
-
-       /*
-        * 'name' is a NUL-terminated string already and
-        * 'namelen' includes 0-byte.
-        */
-       memcpy(data, name, namelen);
-       data += namelen;
-
-       memcpy(data, value, attrsize);
-
-       cmd->cmd = command;
-       cmd->id = id;
-       cmd->start = start;
-       cmd->size = attrsize + namelen + path_len;
-       cmd->ext = path_len;
-       cmd->csize = 0;
-       cmd->cpad = 0;
-
-       netfs_convert_cmd(cmd);
-       netfs_trans_update(cmd, t, namelen + path_len + attrsize);
-
-       return netfs_trans_finish(t, psb);
-
-err_out_put:
-       t->result = err;
-       netfs_trans_put(t);
-err_out_exit:
-       return err;
-}
-
-static int pohmelfs_setxattr(struct dentry *dentry, const char *name,
-               const void *value, size_t attrsize, int flags)
-{
-       struct inode *inode = dentry->d_inode;
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-
-       if (!(psb->state_flags & POHMELFS_FLAGS_XATTR))
-               return -EOPNOTSUPP;
-
-       return pohmelfs_send_xattr_req(pi, flags, attrsize, name,
-                       value, attrsize, NETFS_XATTR_SET);
-}
-
-static ssize_t pohmelfs_getxattr(struct dentry *dentry, const char *name,
-               void *value, size_t attrsize)
-{
-       struct inode *inode = dentry->d_inode;
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-       struct pohmelfs_mcache *m;
-       int err;
-       long timeout = psb->mcache_timeout;
-
-       if (!(psb->state_flags & POHMELFS_FLAGS_XATTR))
-               return -EOPNOTSUPP;
-
-       m = pohmelfs_mcache_alloc(psb, 0, attrsize, value);
-       if (IS_ERR(m))
-               return PTR_ERR(m);
-
-       dprintk("%s: ino: %llu, name: '%s', size: %zu.\n",
-                       __func__, pi->ino, name, attrsize);
-
-       err = pohmelfs_send_xattr_req(pi, m->gen, attrsize, name, value, 0, NETFS_XATTR_GET);
-       if (err)
-               goto err_out_put;
-
-       do {
-               err = wait_for_completion_timeout(&m->complete, timeout);
-               if (err) {
-                       err = m->err;
-                       break;
-               }
-
-               /*
-                * This loop is a bit ugly, since it waits until reference counter
-                * hits 1 and then puts the object here. Main goal is to prevent race with
-                * the network thread, when it can start processing the given request, i.e.
-                * increase its reference counter but yet not complete it, while
-                * we will exit from ->getxattr() with timeout, and although request
-                * will not be freed (its reference counter was increased by network
-                * thread), data pointer provided by user may be released, so we will
-                * overwrite an already freed area in the network thread.
-                *
-                * Now after timeout we remove request from the cache, so it can not be
-                * found by network thread, and wait for its reference counter to hit 1,
-                * i.e. if network thread already started to process this request, we wait
-                * for it to finish, and then free object locally. If reference counter is
-                * already 1, i.e. request is not used by anyone else, we can free it without
-                * problem.
-                */
-               err = -ETIMEDOUT;
-               timeout = HZ;
-
-               pohmelfs_mcache_remove_locked(psb, m);
-       } while (atomic_read(&m->refcnt) != 1);
-
-       pohmelfs_mcache_put(psb, m);
-
-       dprintk("%s: ino: %llu, err: %d.\n", __func__, pi->ino, err);
-
-       return err;
-
-err_out_put:
-       pohmelfs_mcache_put(psb, m);
-       return err;
-}
-
-static int pohmelfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
-{
-       struct inode *inode = dentry->d_inode;
-#if 0
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-       int err;
-
-       err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_READ_LOCK);
-       if (err)
-               return err;
-       dprintk("%s: ino: %llu, mode: %o, uid: %u, gid: %u, size: %llu.\n",
-                       __func__, pi->ino, inode->i_mode, inode->i_uid,
-                       inode->i_gid, inode->i_size);
-#endif
-
-       generic_fillattr(inode, stat);
-       return 0;
-}
-
-const struct inode_operations pohmelfs_file_inode_operations = {
-       .setattr        = pohmelfs_setattr,
-       .getattr        = pohmelfs_getattr,
-       .setxattr       = pohmelfs_setxattr,
-       .getxattr       = pohmelfs_getxattr,
-};
-
-/*
- * Fill inode data: mode, size, operation callbacks and so on...
- */
-void pohmelfs_fill_inode(struct inode *inode, struct netfs_inode_info *info)
-{
-       inode->i_mode = info->mode;
-       set_nlink(inode, info->nlink);
-       inode->i_uid = info->uid;
-       inode->i_gid = info->gid;
-       inode->i_blocks = info->blocks;
-       inode->i_rdev = info->rdev;
-       inode->i_size = info->size;
-       inode->i_version = info->version;
-       inode->i_blkbits = ffs(info->blocksize);
-
-       dprintk("%s: inode: %p, num: %lu/%llu inode is regular: %d, dir: %d, link: %d, mode: %o, size: %llu.\n",
-                       __func__, inode, inode->i_ino, info->ino,
-                       S_ISREG(inode->i_mode), S_ISDIR(inode->i_mode),
-                       S_ISLNK(inode->i_mode), inode->i_mode, inode->i_size);
-
-       inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-
-       /*
-        * i_mapping is a pointer to i_data during inode initialization.
-        */
-       inode->i_data.a_ops = &pohmelfs_aops;
-
-       if (S_ISREG(inode->i_mode)) {
-               inode->i_fop = &pohmelfs_file_ops;
-               inode->i_op = &pohmelfs_file_inode_operations;
-       } else if (S_ISDIR(inode->i_mode)) {
-               inode->i_fop = &pohmelfs_dir_fops;
-               inode->i_op = &pohmelfs_dir_inode_ops;
-       } else if (S_ISLNK(inode->i_mode)) {
-               inode->i_op = &pohmelfs_symlink_inode_operations;
-               inode->i_fop = &pohmelfs_file_ops;
-       } else {
-               inode->i_fop = &generic_ro_fops;
-       }
-}
-
-static int pohmelfs_drop_inode(struct inode *inode)
-{
-       struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-       struct pohmelfs_inode *pi = POHMELFS_I(inode);
-
-       spin_lock(&psb->ino_lock);
-       list_del_init(&pi->inode_entry);
-       spin_unlock(&psb->ino_lock);
-
-       return generic_drop_inode(inode);
-}
-
-static struct pohmelfs_inode *pohmelfs_get_inode_from_list(struct pohmelfs_sb *psb,
-               struct list_head *head, unsigned int *count)
-{
-       struct pohmelfs_inode *pi = NULL;
-
-       spin_lock(&psb->ino_lock);
-       if (!list_empty(head)) {
-               pi = list_entry(head->next, struct pohmelfs_inode,
-                                       inode_entry);
-               list_del_init(&pi->inode_entry);
-               *count = pi->drop_count;
-               pi->drop_count = 0;
-       }
-       spin_unlock(&psb->ino_lock);
-
-       return pi;
-}
-
-static void pohmelfs_flush_transactions(struct pohmelfs_sb *psb)
-{
-       struct pohmelfs_config *c;
-
-       mutex_lock(&psb->state_lock);
-       list_for_each_entry(c, &psb->state_list, config_entry) {
-               pohmelfs_state_flush_transactions(&c->state);
-       }
-       mutex_unlock(&psb->state_lock);
-}
-
-/*
- * ->put_super() callback. Invoked before superblock is destroyed,
- *  so it has to clean all private data.
- */
-static void pohmelfs_put_super(struct super_block *sb)
-{
-       struct pohmelfs_sb *psb = POHMELFS_SB(sb);
-       struct pohmelfs_inode *pi;
-       unsigned int count = 0;
-       unsigned int in_drop_list = 0;
-       struct inode *inode, *tmp;
-
-       dprintk("%s.\n", __func__);
-
-       /*
-        * Kill pending transactions, which could affect inodes in-flight.
-        */
-       pohmelfs_flush_transactions(psb);
-
-       while ((pi = pohmelfs_get_inode_from_list(psb, &psb->drop_list, &count))) {
-               inode = &pi->vfs_inode;
-
-               dprintk("%s: ino: %llu, pi: %p, inode: %p, count: %u.\n",
-                               __func__, pi->ino, pi, inode, count);
-
-               if (atomic_read(&inode->i_count) != count) {
-                       printk("%s: ino: %llu, pi: %p, inode: %p, count: %u, i_count: %d.\n",
-                                       __func__, pi->ino, pi, inode, count,
-                                       atomic_read(&inode->i_count));
-                       count = atomic_read(&inode->i_count);
-                       in_drop_list++;
-               }
-
-               while (count--)
-                       iput(&pi->vfs_inode);
-       }
-
-       list_for_each_entry_safe(inode, tmp, &sb->s_inodes, i_sb_list) {
-               pi = POHMELFS_I(inode);
-
-               dprintk("%s: ino: %llu, pi: %p, inode: %p, i_count: %u.\n",
-                               __func__, pi->ino, pi, inode, atomic_read(&inode->i_count));
-
-               /*
-                * These are special inodes, they were created during
-                * directory reading or lookup, and were not bound to dentry,
-                * so they live here with reference counter being 1 and prevent
-                * umount from succeed since it believes that they are busy.
-                */
-               count = atomic_read(&inode->i_count);
-               if (count) {
-                       list_del_init(&inode->i_sb_list);
-                       while (count--)
-                               iput(&pi->vfs_inode);
-               }
-       }
-
-       psb->trans_scan_timeout = psb->drop_scan_timeout = 0;
-       cancel_delayed_work_sync(&psb->dwork);
-       cancel_delayed_work_sync(&psb->drop_dwork);
-       flush_scheduled_work();
-
-       dprintk("%s: stopped workqueues.\n", __func__);
-
-       pohmelfs_crypto_exit(psb);
-       pohmelfs_state_exit(psb);
-
-       bdi_destroy(&psb->bdi);
-
-       kfree(psb);
-       sb->s_fs_info = NULL;
-}
-
-static int pohmelfs_statfs(struct dentry *dentry, struct kstatfs *buf)
-{
-       struct super_block *sb = dentry->d_sb;
-       struct pohmelfs_sb *psb = POHMELFS_SB(sb);
-
-       /*
-        * There are no filesystem size limits yet.
-        */
-       memset(buf, 0, sizeof(struct kstatfs));
-
-       buf->f_type = POHMELFS_MAGIC_NUM; /* 'POH.' */
-       buf->f_bsize = sb->s_blocksize;
-       buf->f_files = psb->ino;
-       buf->f_namelen = 255;
-       buf->f_files = atomic_long_read(&psb->total_inodes);
-       buf->f_bfree = buf->f_bavail = psb->avail_size >> PAGE_SHIFT;
-       buf->f_blocks = psb->total_size >> PAGE_SHIFT;
-
-       dprintk("%s: total: %llu, avail: %llu, inodes: %llu, bsize: %lu.\n",
-               __func__, psb->total_size, psb->avail_size, buf->f_files, sb->s_blocksize);
-
-       return 0;
-}
-
-static int pohmelfs_show_options(struct seq_file *seq, struct dentry *root)
-{
-       struct pohmelfs_sb *psb = POHMELFS_SB(root->d_sb);
-
-       seq_printf(seq, ",idx=%u", psb->idx);
-       seq_printf(seq, ",trans_scan_timeout=%u", jiffies_to_msecs(psb->trans_scan_timeout));
-       seq_printf(seq, ",drop_scan_timeout=%u", jiffies_to_msecs(psb->drop_scan_timeout));
-       seq_printf(seq, ",wait_on_page_timeout=%u", jiffies_to_msecs(psb->wait_on_page_timeout));
-       seq_printf(seq, ",trans_retries=%u", psb->trans_retries);
-       seq_printf(seq, ",crypto_thread_num=%u", psb->crypto_thread_num);
-       seq_printf(seq, ",trans_max_pages=%u", psb->trans_max_pages);
-       seq_printf(seq, ",mcache_timeout=%u", jiffies_to_msecs(psb->mcache_timeout));
-       if (psb->crypto_fail_unsupported)
-               seq_printf(seq, ",crypto_fail_unsupported");
-
-       return 0;
-}
-
-enum {
-       pohmelfs_opt_idx,
-       pohmelfs_opt_crypto_thread_num,
-       pohmelfs_opt_trans_max_pages,
-       pohmelfs_opt_crypto_fail_unsupported,
-
-       /* Remountable options */
-       pohmelfs_opt_trans_scan_timeout,
-       pohmelfs_opt_drop_scan_timeout,
-       pohmelfs_opt_wait_on_page_timeout,
-       pohmelfs_opt_trans_retries,
-       pohmelfs_opt_mcache_timeout,
-};
-
-static struct match_token pohmelfs_tokens[] = {
-       {pohmelfs_opt_idx, "idx=%u"},
-       {pohmelfs_opt_crypto_thread_num, "crypto_thread_num=%u"},
-       {pohmelfs_opt_trans_max_pages, "trans_max_pages=%u"},
-       {pohmelfs_opt_crypto_fail_unsupported, "crypto_fail_unsupported"},
-       {pohmelfs_opt_trans_scan_timeout, "trans_scan_timeout=%u"},
-       {pohmelfs_opt_drop_scan_timeout, "drop_scan_timeout=%u"},
-       {pohmelfs_opt_wait_on_page_timeout, "wait_on_page_timeout=%u"},
-       {pohmelfs_opt_trans_retries, "trans_retries=%u"},
-       {pohmelfs_opt_mcache_timeout, "mcache_timeout=%u"},
-};
-
-static int pohmelfs_parse_options(char *options, struct pohmelfs_sb *psb, int remount)
-{
-       char *p;
-       substring_t args[MAX_OPT_ARGS];
-       int option, err;
-
-       if (!options)
-               return 0;
-
-       while ((p = strsep(&options, ",")) != NULL) {
-               int token;
-               if (!*p)
-                       continue;
-
-               token = match_token(p, pohmelfs_tokens, args);
-
-               err = match_int(&args[0], &option);
-               if (err)
-                       return err;
-
-               if (remount && token <= pohmelfs_opt_crypto_fail_unsupported)
-                       continue;
-
-               switch (token) {
-               case pohmelfs_opt_idx:
-                       psb->idx = option;
-                       break;
-               case pohmelfs_opt_trans_scan_timeout:
-                       psb->trans_scan_timeout = msecs_to_jiffies(option);
-                       break;
-               case pohmelfs_opt_drop_scan_timeout:
-                       psb->drop_scan_timeout = msecs_to_jiffies(option);
-                       break;
-               case pohmelfs_opt_wait_on_page_timeout:
-                       psb->wait_on_page_timeout = msecs_to_jiffies(option);
-                       break;
-               case pohmelfs_opt_mcache_timeout:
-                       psb->mcache_timeout = msecs_to_jiffies(option);
-                       break;
-               case pohmelfs_opt_trans_retries:
-                       psb->trans_retries = option;
-                       break;
-               case pohmelfs_opt_crypto_thread_num:
-                       psb->crypto_thread_num = option;
-                       break;
-               case pohmelfs_opt_trans_max_pages:
-                       psb->trans_max_pages = option;
-                       break;
-               case pohmelfs_opt_crypto_fail_unsupported:
-                       psb->crypto_fail_unsupported = 1;
-                       break;
-               default:
-                       return -EINVAL;
-               }
-       }
-
-       return 0;
-}
-
-static int pohmelfs_remount(struct super_block *sb, int *flags, char *data)
-{
-       int err;
-       struct pohmelfs_sb *psb = POHMELFS_SB(sb);
-       unsigned long old_sb_flags = sb->s_flags;
-
-       err = pohmelfs_parse_options(data, psb, 1);
-       if (err)
-               goto err_out_restore;
-
-       if (!(*flags & MS_RDONLY))
-               sb->s_flags &= ~MS_RDONLY;
-       return 0;
-
-err_out_restore:
-       sb->s_flags = old_sb_flags;
-       return err;
-}
-
-static void pohmelfs_flush_inode(struct pohmelfs_inode *pi, unsigned int count)
-{
-       struct inode *inode = &pi->vfs_inode;
-
-       dprintk("%s: %p: ino: %llu, owned: %d.\n",
-               __func__, inode, pi->ino, test_bit(NETFS_INODE_OWNED, &pi->state));
-
-       mutex_lock(&inode->i_mutex);
-       if (test_and_clear_bit(NETFS_INODE_OWNED, &pi->state)) {
-               filemap_fdatawrite(inode->i_mapping);
-               inode->i_sb->s_op->write_inode(inode, 0);
-       }
-
-#ifdef POHMELFS_TRUNCATE_ON_INODE_FLUSH
-       truncate_inode_pages(inode->i_mapping, 0);
-#endif
-
-       pohmelfs_data_unlock(pi, 0, ~0, POHMELFS_WRITE_LOCK);
-       mutex_unlock(&inode->i_mutex);
-}
-
-static void pohmelfs_put_inode_count(struct pohmelfs_inode *pi, unsigned int count)
-{
-       dprintk("%s: ino: %llu, pi: %p, inode: %p, count: %u.\n",
-                       __func__, pi->ino, pi, &pi->vfs_inode, count);
-
-       if (test_and_clear_bit(NETFS_INODE_NEED_FLUSH, &pi->state))
-               pohmelfs_flush_inode(pi, count);
-
-       while (count--)
-               iput(&pi->vfs_inode);
-}
-
-static void pohmelfs_drop_scan(struct work_struct *work)
-{
-       struct pohmelfs_sb *psb =
-               container_of(work, struct pohmelfs_sb, drop_dwork.work);
-       struct pohmelfs_inode *pi;
-       unsigned int count = 0;
-
-       while ((pi = pohmelfs_get_inode_from_list(psb, &psb->drop_list, &count)))
-               pohmelfs_put_inode_count(pi, count);
-
-       pohmelfs_check_states(psb);
-
-       if (psb->drop_scan_timeout)
-               schedule_delayed_work(&psb->drop_dwork, psb->drop_scan_timeout);
-}
-
-/*
- * Run through all transactions starting from the oldest,
- * drop transaction from current state and try to send it
- * to all remote nodes, which are currently installed.
- */
-static void pohmelfs_trans_scan_state(struct netfs_state *st)
-{
-       struct rb_node *rb_node;
-       struct netfs_trans_dst *dst;
-       struct pohmelfs_sb *psb = st->psb;
-       unsigned int timeout = psb->trans_scan_timeout;
-       struct netfs_trans *t;
-       int err;
-
-       mutex_lock(&st->trans_lock);
-       for (rb_node = rb_first(&st->trans_root); rb_node; ) {
-               dst = rb_entry(rb_node, struct netfs_trans_dst, state_entry);
-               t = dst->trans;
-
-               if (timeout && time_after(dst->send_time + timeout, jiffies)
-                               && dst->retries == 0)
-                       break;
-
-               dprintk("%s: t: %p, gen: %u, st: %p, retries: %u, max: %u.\n",
-                       __func__, t, t->gen, st, dst->retries, psb->trans_retries);
-               netfs_trans_get(t);
-
-               rb_node = rb_next(rb_node);
-
-               err = -ETIMEDOUT;
-               if (timeout && (++dst->retries < psb->trans_retries))
-                       err = netfs_trans_resend(t, psb);
-
-               if (err || (t->flags & NETFS_TRANS_SINGLE_DST)) {
-                       if (netfs_trans_remove_nolock(dst, st))
-                               netfs_trans_drop_dst_nostate(dst);
-               }
-
-               t->result = err;
-               netfs_trans_put(t);
-       }
-       mutex_unlock(&st->trans_lock);
-}
-
-/*
- * Walk through all installed network states and resend all
- * transactions, which are old enough.
- */
-static void pohmelfs_trans_scan(struct work_struct *work)
-{
-       struct pohmelfs_sb *psb =
-               container_of(work, struct pohmelfs_sb, dwork.work);
-       struct netfs_state *st;
-       struct pohmelfs_config *c;
-
-       mutex_lock(&psb->state_lock);
-       list_for_each_entry(c, &psb->state_list, config_entry) {
-               st = &c->state;
-
-               pohmelfs_trans_scan_state(st);
-       }
-       mutex_unlock(&psb->state_lock);
-
-       /*
-        * If no timeout specified then system is in the middle of umount process,
-        * so no need to reschedule scanning process again.
-        */
-       if (psb->trans_scan_timeout)
-               schedule_delayed_work(&psb->dwork, psb->trans_scan_timeout);
-}
-
-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)
-{
-       struct inode *inode = &pi->vfs_inode;
-       struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-       int err = 0, sz;
-       struct netfs_trans *t;
-       int path_len, addon_len = 0;
-       void *data;
-       struct netfs_inode_info *info;
-       struct netfs_cmd *cmd;
-
-       dprintk("%s: ino: %llu, cmd: %u, addon: %p.\n", __func__, pi->ino, cmd_op, addon);
-
-       path_len = pohmelfs_path_length(pi);
-       if (path_len < 0) {
-               err = path_len;
-               goto err_out_exit;
-       }
-
-       if (addon)
-               addon_len = strlen(addon) + 1; /* 0-byte */
-       sz = addon_len;
-
-       if (cmd_op == NETFS_INODE_INFO)
-               sz += sizeof(struct netfs_inode_info);
-
-       t = netfs_trans_alloc(psb, sz + path_len, flags, 0);
-       if (!t) {
-               err = -ENOMEM;
-               goto err_out_exit;
-       }
-       t->complete = complete;
-       t->private = priv;
-
-       cmd = netfs_trans_current(t);
-       data = (void *)(cmd + 1);
-
-       if (cmd_op == NETFS_INODE_INFO) {
-               info = (struct netfs_inode_info *)(cmd + 1);
-               data = (void *)(info + 1);
-
-               /*
-                * We are under i_mutex, can read and change whatever we want...
-                */
-               info->mode = inode->i_mode;
-               info->nlink = inode->i_nlink;
-               info->uid = inode->i_uid;
-               info->gid = inode->i_gid;
-               info->blocks = inode->i_blocks;
-               info->rdev = inode->i_rdev;
-               info->size = inode->i_size;
-               info->version = inode->i_version;
-
-               netfs_convert_inode_info(info);
-       }
-
-       path_len = pohmelfs_construct_path_string(pi, data, path_len);
-       if (path_len < 0)
-               goto err_out_free;
-
-       dprintk("%s: path_len: %d.\n", __func__, path_len);
-
-       if (addon) {
-               path_len--; /* Do not place null-byte before the addon */
-               path_len += sprintf(data + path_len, "/%s", addon) + 1; /* 0 - byte */
-       }
-
-       sz += path_len;
-
-       cmd->cmd = cmd_op;
-       cmd->ext = path_len;
-       cmd->size = sz;
-       cmd->id = id;
-       cmd->start = start;
-
-       netfs_convert_cmd(cmd);
-       netfs_trans_update(cmd, t, sz);
-
-       /*
-        * Note, that it is possible to leak error here: transaction callback will not
-        * be invoked for allocation path failure.
-        */
-       return netfs_trans_finish(t, psb);
-
-err_out_free:
-       netfs_trans_free(t);
-err_out_exit:
-       if (complete)
-               complete(NULL, 0, priv, err);
-       return err;
-}
-
-int pohmelfs_meta_command(struct pohmelfs_inode *pi, unsigned int cmd_op, unsigned int flags,
-               netfs_trans_complete_t complete, void *priv, u64 start)
-{
-       return pohmelfs_meta_command_data(pi, pi->ino, cmd_op, NULL, flags, complete, priv, start);
-}
-
-/*
- * Send request and wait for POHMELFS root capabilities response,
- * which will update server's informaion about size of the export,
- * permissions, number of objects, available size and so on.
- */
-static int pohmelfs_root_handshake(struct pohmelfs_sb *psb)
-{
-       struct netfs_trans *t;
-       struct netfs_cmd *cmd;
-       int err = -ENOMEM;
-
-       t = netfs_trans_alloc(psb, 0, 0, 0);
-       if (!t)
-               goto err_out_exit;
-
-       cmd = netfs_trans_current(t);
-
-       cmd->cmd = NETFS_CAPABILITIES;
-       cmd->id = POHMELFS_ROOT_CAPABILITIES;
-       cmd->size = 0;
-       cmd->start = 0;
-       cmd->ext = 0;
-       cmd->csize = 0;
-
-       netfs_convert_cmd(cmd);
-       netfs_trans_update(cmd, t, 0);
-
-       err = netfs_trans_finish(t, psb);
-       if (err)
-               goto err_out_exit;
-
-       psb->flags = ~0;
-       err = wait_event_interruptible_timeout(psb->wait,
-                       (psb->flags != ~0),
-                       psb->wait_on_page_timeout);
-       if (!err)
-               err = -ETIMEDOUT;
-       else if (err > 0)
-               err = -psb->flags;
-
-       if (err)
-               goto err_out_exit;
-
-       return 0;
-
-err_out_exit:
-       return err;
-}
-
-static int pohmelfs_show_stats(struct seq_file *m, struct dentry *root)
-{
-       struct netfs_state *st;
-       struct pohmelfs_ctl *ctl;
-       struct pohmelfs_sb *psb = POHMELFS_SB(root->d_sb);
-       struct pohmelfs_config *c;
-
-       mutex_lock(&psb->state_lock);
-
-       seq_printf(m, "\nidx addr(:port) socket_type protocol active priority permissions\n");
-
-       list_for_each_entry(c, &psb->state_list, config_entry) {
-               st = &c->state;
-               ctl = &st->ctl;
-
-               seq_printf(m, "%u ", ctl->idx);
-               if (ctl->addr.sa_family == AF_INET) {
-                       struct sockaddr_in *sin = (struct sockaddr_in *)&st->ctl.addr;
-                       seq_printf(m, "%pI4:%u", &sin->sin_addr.s_addr, ntohs(sin->sin_port));
-               } else if (ctl->addr.sa_family == AF_INET6) {
-                       struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&st->ctl.addr;
-                       seq_printf(m, "%pi6:%u", &sin->sin6_addr, ntohs(sin->sin6_port));
-               } else {
-                       unsigned int i;
-                       for (i = 0; i < ctl->addrlen; ++i)
-                               seq_printf(m, "%02x.", ctl->addr.addr[i]);
-               }
-
-               seq_printf(m, " %u %u %d %u %x\n",
-                               ctl->type, ctl->proto,
-                               st->socket != NULL,
-                               ctl->prio, ctl->perm);
-       }
-       mutex_unlock(&psb->state_lock);
-
-       return 0;
-}
-
-static const struct super_operations pohmelfs_sb_ops = {
-       .alloc_inode    = pohmelfs_alloc_inode,
-       .destroy_inode  = pohmelfs_destroy_inode,
-       .drop_inode     = pohmelfs_drop_inode,
-       .write_inode    = pohmelfs_write_inode,
-       .put_super      = pohmelfs_put_super,
-       .remount_fs     = pohmelfs_remount,
-       .statfs         = pohmelfs_statfs,
-       .show_options   = pohmelfs_show_options,
-       .show_stats     = pohmelfs_show_stats,
-};
-
-/*
- * Allocate private superblock and create root dir.
- */
-static int pohmelfs_fill_super(struct super_block *sb, void *data, int silent)
-{
-       struct pohmelfs_sb *psb;
-       int err = -ENOMEM;
-       struct inode *root;
-       struct pohmelfs_inode *npi;
-       struct qstr str;
-
-       psb = kzalloc(sizeof(struct pohmelfs_sb), GFP_KERNEL);
-       if (!psb)
-               goto err_out_exit;
-
-       err = bdi_init(&psb->bdi);
-       if (err)
-               goto err_out_free_sb;
-
-       err = bdi_register(&psb->bdi, NULL, "pfs-%d", atomic_inc_return(&psb_bdi_num));
-       if (err) {
-               bdi_destroy(&psb->bdi);
-               goto err_out_free_sb;
-       }
-
-       sb->s_fs_info = psb;
-       sb->s_op = &pohmelfs_sb_ops;
-       sb->s_magic = POHMELFS_MAGIC_NUM;
-       sb->s_maxbytes = MAX_LFS_FILESIZE;
-       sb->s_blocksize = PAGE_SIZE;
-       sb->s_bdi = &psb->bdi;
-
-       psb->sb = sb;
-
-       psb->ino = 2;
-       psb->idx = 0;
-       psb->active_state = NULL;
-       psb->trans_retries = 5;
-       psb->trans_data_size = PAGE_SIZE;
-       psb->drop_scan_timeout = msecs_to_jiffies(1000);
-       psb->trans_scan_timeout = msecs_to_jiffies(5000);
-       psb->wait_on_page_timeout = msecs_to_jiffies(5000);
-       init_waitqueue_head(&psb->wait);
-
-       spin_lock_init(&psb->ino_lock);
-
-       INIT_LIST_HEAD(&psb->drop_list);
-
-       mutex_init(&psb->mcache_lock);
-       psb->mcache_root = RB_ROOT;
-       psb->mcache_timeout = msecs_to_jiffies(5000);
-       atomic_long_set(&psb->mcache_gen, 0);
-
-       psb->trans_max_pages = 100;
-
-       psb->crypto_align_size = 16;
-       psb->crypto_attached_size = 0;
-       psb->hash_strlen = 0;
-       psb->cipher_strlen = 0;
-       psb->perform_crypto = 0;
-       psb->crypto_thread_num = 2;
-       psb->crypto_fail_unsupported = 0;
-       mutex_init(&psb->crypto_thread_lock);
-       INIT_LIST_HEAD(&psb->crypto_ready_list);
-       INIT_LIST_HEAD(&psb->crypto_active_list);
-
-       atomic_set(&psb->trans_gen, 1);
-       atomic_long_set(&psb->total_inodes, 0);
-
-       mutex_init(&psb->state_lock);
-       INIT_LIST_HEAD(&psb->state_list);
-
-       err = pohmelfs_parse_options((char *) data, psb, 0);
-       if (err)
-               goto err_out_free_bdi;
-
-       err = pohmelfs_copy_crypto(psb);
-       if (err)
-               goto err_out_free_bdi;
-
-       err = pohmelfs_state_init(psb);
-       if (err)
-               goto err_out_free_strings;
-
-       err = pohmelfs_crypto_init(psb);
-       if (err)
-               goto err_out_state_exit;
-
-       err = pohmelfs_root_handshake(psb);
-       if (err)
-               goto err_out_crypto_exit;
-
-       str.name = "/";
-       str.hash = jhash("/", 1, 0);
-       str.len = 1;
-
-       npi = pohmelfs_create_entry_local(psb, NULL, &str, 0, 0755|S_IFDIR);
-       if (IS_ERR(npi)) {
-               err = PTR_ERR(npi);
-               goto err_out_crypto_exit;
-       }
-       set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state);
-       clear_bit(NETFS_INODE_OWNED, &npi->state);
-
-       root = &npi->vfs_inode;
-
-       sb->s_root = d_alloc_root(root);
-       if (!sb->s_root)
-               goto err_out_put_root;
-
-       INIT_DELAYED_WORK(&psb->drop_dwork, pohmelfs_drop_scan);
-       schedule_delayed_work(&psb->drop_dwork, psb->drop_scan_timeout);
-
-       INIT_DELAYED_WORK(&psb->dwork, pohmelfs_trans_scan);
-       schedule_delayed_work(&psb->dwork, psb->trans_scan_timeout);
-
-       return 0;
-
-err_out_put_root:
-       iput(root);
-err_out_crypto_exit:
-       pohmelfs_crypto_exit(psb);
-err_out_state_exit:
-       pohmelfs_state_exit(psb);
-err_out_free_strings:
-       kfree(psb->cipher_string);
-       kfree(psb->hash_string);
-err_out_free_bdi:
-       bdi_destroy(&psb->bdi);
-err_out_free_sb:
-       kfree(psb);
-err_out_exit:
-
-       dprintk("%s: err: %d.\n", __func__, err);
-       return err;
-}
-
-/*
- * Some VFS magic here...
- */
-static struct dentry *pohmelfs_mount(struct file_system_type *fs_type,
-       int flags, const char *dev_name, void *data)
-{
-       return mount_nodev(fs_type, flags, data, pohmelfs_fill_super);
-}
-
-/*
- * We need this to sync all inodes earlier, since when writeback
- * is invoked from the umount/mntput path dcache is already shrunk,
- * see generic_shutdown_super(), and no inodes can access the path.
- */
-static void pohmelfs_kill_super(struct super_block *sb)
-{
-       sync_inodes_sb(sb);
-       kill_anon_super(sb);
-}
-
-static struct file_system_type pohmel_fs_type = {
-       .owner          = THIS_MODULE,
-       .name           = "pohmel",
-       .mount          = pohmelfs_mount,
-       .kill_sb        = pohmelfs_kill_super,
-};
-
-/*
- * Cache and module initializations and freeing routings.
- */
-static void pohmelfs_init_once(void *data)
-{
-       struct pohmelfs_inode *pi = data;
-
-       inode_init_once(&pi->vfs_inode);
-}
-
-static int __init pohmelfs_init_inodecache(void)
-{
-       pohmelfs_inode_cache = kmem_cache_create("pohmelfs_inode_cache",
-                               sizeof(struct pohmelfs_inode),
-                               0, (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD),
-                               pohmelfs_init_once);
-       if (!pohmelfs_inode_cache)
-               return -ENOMEM;
-
-       return 0;
-}
-
-static void pohmelfs_destroy_inodecache(void)
-{
-       kmem_cache_destroy(pohmelfs_inode_cache);
-}
-
-static int __init init_pohmel_fs(void)
-{
-       int err;
-
-       err = pohmelfs_config_init();
-       if (err)
-               goto err_out_exit;
-
-       err = pohmelfs_init_inodecache();
-       if (err)
-               goto err_out_config_exit;
-
-       err = pohmelfs_mcache_init();
-       if (err)
-               goto err_out_destroy;
-
-       err = netfs_trans_init();
-       if (err)
-               goto err_out_mcache_exit;
-
-       err = register_filesystem(&pohmel_fs_type);
-       if (err)
-               goto err_out_trans;
-
-       return 0;
-
-err_out_trans:
-       netfs_trans_exit();
-err_out_mcache_exit:
-       pohmelfs_mcache_exit();
-err_out_destroy:
-       pohmelfs_destroy_inodecache();
-err_out_config_exit:
-       pohmelfs_config_exit();
-err_out_exit:
-       return err;
-}
-
-static void __exit exit_pohmel_fs(void)
-{
-       unregister_filesystem(&pohmel_fs_type);
-       pohmelfs_destroy_inodecache();
-       pohmelfs_mcache_exit();
-       pohmelfs_config_exit();
-       netfs_trans_exit();
-}
-
-module_init(init_pohmel_fs);
-module_exit(exit_pohmel_fs);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
-MODULE_DESCRIPTION("Pohmel filesystem");
diff --git a/drivers/staging/pohmelfs/lock.c b/drivers/staging/pohmelfs/lock.c
deleted file mode 100644 (file)
index 6710114..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * 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.
- */
-
-#include <linux/module.h>
-#include <linux/backing-dev.h>
-#include <linux/fs.h>
-#include <linux/fsnotify.h>
-#include <linux/mempool.h>
-
-#include "netfs.h"
-
-static int pohmelfs_send_lock_trans(struct pohmelfs_inode *pi,
-               u64 id, u64 start, u32 size, int type)
-{
-       struct inode *inode = &pi->vfs_inode;
-       struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-       struct netfs_trans *t;
-       struct netfs_cmd *cmd;
-       int path_len, err;
-       void *data;
-       struct netfs_lock *l;
-       int isize = (type & POHMELFS_LOCK_GRAB) ? 0 : sizeof(struct netfs_inode_info);
-
-       err = pohmelfs_path_length(pi);
-       if (err < 0)
-               goto err_out_exit;
-
-       path_len = err;
-
-       err = -ENOMEM;
-       t = netfs_trans_alloc(psb, path_len + sizeof(struct netfs_lock) + isize,
-                       NETFS_TRANS_SINGLE_DST, 0);
-       if (!t)
-               goto err_out_exit;
-
-       cmd = netfs_trans_current(t);
-       data = cmd + 1;
-
-       err = pohmelfs_construct_path_string(pi, data, path_len);
-       if (err < 0)
-               goto err_out_free;
-       path_len = err;
-
-       l = data + path_len;
-
-       l->start = start;
-       l->size = size;
-       l->type = type;
-       l->ino = pi->ino;
-
-       cmd->cmd = NETFS_LOCK;
-       cmd->start = 0;
-       cmd->id = id;
-       cmd->size = sizeof(struct netfs_lock) + path_len + isize;
-       cmd->ext = path_len;
-       cmd->csize = 0;
-
-       netfs_convert_cmd(cmd);
-       netfs_convert_lock(l);
-
-       if (isize) {
-               struct netfs_inode_info *info = (struct netfs_inode_info *)(l + 1);
-
-               info->mode = inode->i_mode;
-               info->nlink = inode->i_nlink;
-               info->uid = inode->i_uid;
-               info->gid = inode->i_gid;
-               info->blocks = inode->i_blocks;
-               info->rdev = inode->i_rdev;
-               info->size = inode->i_size;
-               info->version = inode->i_version;
-
-               netfs_convert_inode_info(info);
-       }
-
-       netfs_trans_update(cmd, t, path_len + sizeof(struct netfs_lock) + isize);
-
-       return netfs_trans_finish(t, psb);
-
-err_out_free:
-       netfs_trans_free(t);
-err_out_exit:
-       printk("%s: err: %d.\n", __func__, err);
-       return err;
-}
-
-int pohmelfs_data_lock(struct pohmelfs_inode *pi, u64 start, u32 size, int type)
-{
-       struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
-       struct pohmelfs_mcache *m;
-       int err = -ENOMEM;
-       struct iattr iattr;
-       struct inode *inode = &pi->vfs_inode;
-
-       dprintk("%s: %p: ino: %llu, start: %llu, size: %u, "
-                       "type: %d, locked as: %d, owned: %d.\n",
-                       __func__, &pi->vfs_inode, pi->ino,
-                       start, size, type, pi->lock_type,
-                       !!test_bit(NETFS_INODE_OWNED, &pi->state));
-
-       if (!pohmelfs_need_lock(pi, type))
-               return 0;
-
-       m = pohmelfs_mcache_alloc(psb, start, size, NULL);
-       if (IS_ERR(m))
-               return PTR_ERR(m);
-
-       err = pohmelfs_send_lock_trans(pi, m->gen, start, size,
-                       type | POHMELFS_LOCK_GRAB);
-       if (err)
-               goto err_out_put;
-
-       err = wait_for_completion_timeout(&m->complete, psb->mcache_timeout);
-       if (err)
-               err = m->err;
-       else
-               err = -ETIMEDOUT;
-
-       if (err) {
-               printk("%s: %p: ino: %llu, mgen: %llu, start: %llu, size: %u, err: %d.\n",
-                       __func__, &pi->vfs_inode, pi->ino, m->gen, start, size, err);
-       }
-
-       if (err && (err != -ENOENT))
-               goto err_out_put;
-
-       if (!err) {
-               netfs_convert_inode_info(&m->info);
-
-               iattr.ia_valid = ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_SIZE | ATTR_ATIME;
-               iattr.ia_mode = m->info.mode;
-               iattr.ia_uid = m->info.uid;
-               iattr.ia_gid = m->info.gid;
-               iattr.ia_size = m->info.size;
-               iattr.ia_atime = CURRENT_TIME;
-
-               dprintk("%s: %p: ino: %llu, mgen: %llu, start: %llu, isize: %llu -> %llu.\n",
-                       __func__, &pi->vfs_inode, pi->ino, m->gen, start, inode->i_size, m->info.size);
-
-               err = pohmelfs_setattr_raw(inode, &iattr);
-               if (!err) {
-                       struct dentry *dentry = d_find_alias(inode);
-                       if (dentry) {
-                               fsnotify_change(dentry, iattr.ia_valid);
-                               dput(dentry);
-                       }
-               }
-       }
-
-       pi->lock_type = type;
-       set_bit(NETFS_INODE_OWNED, &pi->state);
-
-       pohmelfs_mcache_put(psb, m);
-
-       return 0;
-
-err_out_put:
-       pohmelfs_mcache_put(psb, m);
-       return err;
-}
-
-int pohmelfs_data_unlock(struct pohmelfs_inode *pi, u64 start, u32 size, int type)
-{
-       dprintk("%s: %p: ino: %llu, start: %llu, size: %u, type: %d.\n",
-                       __func__, &pi->vfs_inode, pi->ino, start, size, type);
-       pi->lock_type = 0;
-       clear_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state);
-       clear_bit(NETFS_INODE_OWNED, &pi->state);
-       return pohmelfs_send_lock_trans(pi, pi->ino, start, size, type);
-}
diff --git a/drivers/staging/pohmelfs/mcache.c b/drivers/staging/pohmelfs/mcache.c
deleted file mode 100644 (file)
index e22665c..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 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.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/mempool.h>
-
-#include "netfs.h"
-
-static struct kmem_cache *pohmelfs_mcache_cache;
-static mempool_t *pohmelfs_mcache_pool;
-
-static inline int pohmelfs_mcache_cmp(u64 gen, u64 new)
-{
-       if (gen < new)
-               return 1;
-       if (gen > new)
-               return -1;
-       return 0;
-}
-
-struct pohmelfs_mcache *pohmelfs_mcache_search(struct pohmelfs_sb *psb, u64 gen)
-{
-       struct rb_root *root = &psb->mcache_root;
-       struct rb_node *n = root->rb_node;
-       struct pohmelfs_mcache *tmp, *ret = NULL;
-       int cmp;
-
-       while (n) {
-               tmp = rb_entry(n, struct pohmelfs_mcache, mcache_entry);
-
-               cmp = pohmelfs_mcache_cmp(tmp->gen, gen);
-               if (cmp < 0)
-                       n = n->rb_left;
-               else if (cmp > 0)
-                       n = n->rb_right;
-               else {
-                       ret = tmp;
-                       pohmelfs_mcache_get(ret);
-                       break;
-               }
-       }
-
-       return ret;
-}
-
-static int pohmelfs_mcache_insert(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
-{
-       struct rb_root *root = &psb->mcache_root;
-       struct rb_node **n = &root->rb_node, *parent = NULL;
-       struct pohmelfs_mcache *ret = NULL, *tmp;
-       int cmp;
-
-       while (*n) {
-               parent = *n;
-
-               tmp = rb_entry(parent, struct pohmelfs_mcache, mcache_entry);
-
-               cmp = pohmelfs_mcache_cmp(tmp->gen, m->gen);
-               if (cmp < 0)
-                       n = &parent->rb_left;
-               else if (cmp > 0)
-                       n = &parent->rb_right;
-               else {
-                       ret = tmp;
-                       break;
-               }
-       }
-
-       if (ret)
-               return -EEXIST;
-
-       rb_link_node(&m->mcache_entry, parent, n);
-       rb_insert_color(&m->mcache_entry, root);
-
-       return 0;
-}
-
-static int pohmelfs_mcache_remove(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
-{
-       if (m && m->mcache_entry.rb_parent_color) {
-               rb_erase(&m->mcache_entry, &psb->mcache_root);
-               m->mcache_entry.rb_parent_color = 0;
-               return 1;
-       }
-       return 0;
-}
-
-void pohmelfs_mcache_remove_locked(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
-{
-       mutex_lock(&psb->mcache_lock);
-       pohmelfs_mcache_remove(psb, m);
-       mutex_unlock(&psb->mcache_lock);
-}
-
-struct pohmelfs_mcache *pohmelfs_mcache_alloc(struct pohmelfs_sb *psb, u64 start,
-               unsigned int size, void *data)
-{
-       struct pohmelfs_mcache *m;
-       int err = -ENOMEM;
-
-       m = mempool_alloc(pohmelfs_mcache_pool, GFP_KERNEL);
-       if (!m)
-               goto err_out_exit;
-
-       init_completion(&m->complete);
-       m->err = 0;
-       atomic_set(&m->refcnt, 1);
-       m->data = data;
-       m->start = start;
-       m->size = size;
-       m->gen = atomic_long_inc_return(&psb->mcache_gen);
-
-       mutex_lock(&psb->mcache_lock);
-       err = pohmelfs_mcache_insert(psb, m);
-       mutex_unlock(&psb->mcache_lock);
-       if (err)
-               goto err_out_free;
-
-       return m;
-
-err_out_free:
-       mempool_free(m, pohmelfs_mcache_pool);
-err_out_exit:
-       return ERR_PTR(err);
-}
-
-void pohmelfs_mcache_free(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
-{
-       pohmelfs_mcache_remove_locked(psb, m);
-
-       mempool_free(m, pohmelfs_mcache_pool);
-}
-
-int __init pohmelfs_mcache_init(void)
-{
-       pohmelfs_mcache_cache = kmem_cache_create("pohmelfs_mcache_cache",
-                               sizeof(struct pohmelfs_mcache),
-                               0, (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD), NULL);
-       if (!pohmelfs_mcache_cache)
-               goto err_out_exit;
-
-       pohmelfs_mcache_pool = mempool_create_slab_pool(256, pohmelfs_mcache_cache);
-       if (!pohmelfs_mcache_pool)
-               goto err_out_free;
-
-       return 0;
-
-err_out_free:
-       kmem_cache_destroy(pohmelfs_mcache_cache);
-err_out_exit:
-       return -ENOMEM;
-}
-
-void pohmelfs_mcache_exit(void)
-{
-       mempool_destroy(pohmelfs_mcache_pool);
-       kmem_cache_destroy(pohmelfs_mcache_cache);
-}
diff --git a/drivers/staging/pohmelfs/net.c b/drivers/staging/pohmelfs/net.c
deleted file mode 100644 (file)
index b2e9186..0000000
+++ /dev/null
@@ -1,1209 +0,0 @@
-/*
- * 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.
- */
-
-#include <linux/fsnotify.h>
-#include <linux/jhash.h>
-#include <linux/in.h>
-#include <linux/in6.h>
-#include <linux/kthread.h>
-#include <linux/pagemap.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/swap.h>
-#include <linux/syscalls.h>
-#include <linux/vmalloc.h>
-
-#include "netfs.h"
-
-/*
- * Async machinery lives here.
- * All commands being sent to server do _not_ require sync reply,
- * instead, if it is really needed, like readdir or readpage, caller
- * sleeps waiting for data, which will be placed into provided buffer
- * and caller will be awakened.
- *
- * Every command response can come without some listener. For example
- * readdir response will add new objects into cache without appropriate
- * request from userspace. This is used in cache coherency.
- *
- * If object is not found for given data, it is discarded.
- *
- * All requests are received by dedicated kernel thread.
- */
-
-/*
- * Basic network sending/receiving functions.
- * Blocked mode is used.
- */
-static int netfs_data_recv(struct netfs_state *st, void *buf, u64 size)
-{
-       struct msghdr msg;
-       struct kvec iov;
-       int err;
-
-       BUG_ON(!size);
-
-       iov.iov_base = buf;
-       iov.iov_len = size;
-
-       msg.msg_iov = (struct iovec *)&iov;
-       msg.msg_iovlen = 1;
-       msg.msg_name = NULL;
-       msg.msg_namelen = 0;
-       msg.msg_control = NULL;
-       msg.msg_controllen = 0;
-       msg.msg_flags = MSG_DONTWAIT;
-
-       err = kernel_recvmsg(st->socket, &msg, &iov, 1, iov.iov_len,
-                       msg.msg_flags);
-       if (err <= 0) {
-               printk("%s: failed to recv data: size: %llu, err: %d.\n", __func__, size, err);
-               if (err == 0)
-                       err = -ECONNRESET;
-       }
-
-       return err;
-}
-
-static int pohmelfs_data_recv(struct netfs_state *st, void *data, unsigned int size)
-{
-       unsigned int revents = 0;
-       unsigned int err_mask = POLLERR | POLLHUP | POLLRDHUP;
-       unsigned int mask = err_mask | POLLIN;
-       int err = 0;
-
-       while (size && !err) {
-               revents = netfs_state_poll(st);
-
-               if (!(revents & mask)) {
-                       DEFINE_WAIT(wait);
-
-                       for (;;) {
-                               prepare_to_wait(&st->thread_wait, &wait, TASK_INTERRUPTIBLE);
-                               if (kthread_should_stop())
-                                       break;
-
-                               revents = netfs_state_poll(st);
-
-                               if (revents & mask)
-                                       break;
-
-                               if (signal_pending(current))
-                                       break;
-
-                               schedule();
-                               continue;
-                       }
-                       finish_wait(&st->thread_wait, &wait);
-               }
-
-               err = 0;
-               netfs_state_lock(st);
-               if (st->socket && (st->read_socket == st->socket) && (revents & POLLIN)) {
-                       err = netfs_data_recv(st, data, size);
-                       if (err > 0) {
-                               data += err;
-                               size -= err;
-                               err = 0;
-                       } else if (err == 0)
-                               err = -ECONNRESET;
-               }
-
-               if (revents & err_mask) {
-                       printk("%s: revents: %x, socket: %p, size: %u, err: %d.\n",
-                                       __func__, revents, st->socket, size, err);
-                       err = -ECONNRESET;
-               }
-               netfs_state_unlock(st);
-
-               if (err < 0) {
-                       if (netfs_state_trylock_send(st)) {
-                               netfs_state_exit(st);
-                               err = netfs_state_init(st);
-                               if (!err)
-                                       err = -EAGAIN;
-                               netfs_state_unlock_send(st);
-                       } else {
-                               st->need_reset = 1;
-                       }
-               }
-
-               if (kthread_should_stop())
-                       err = -ENODEV;
-
-               if (err)
-                       printk("%s: socket: %p, read_socket: %p, revents: %x, rev_error: %d, "
-                                       "should_stop: %d, size: %u, err: %d.\n",
-                               __func__, st->socket, st->read_socket,
-                               revents, revents & err_mask, kthread_should_stop(), size, err);
-       }
-
-       return err;
-}
-
-int pohmelfs_data_recv_and_check(struct netfs_state *st, void *data, unsigned int size)
-{
-       struct netfs_cmd *cmd = &st->cmd;
-       int err;
-
-       err = pohmelfs_data_recv(st, data, size);
-       if (err)
-               return err;
-
-       return pohmelfs_crypto_process_input_data(&st->eng, cmd->iv, data, NULL, size);
-}
-
-/*
- * Polling machinery.
- */
-
-struct netfs_poll_helper {
-       poll_table              pt;
-       struct netfs_state      *st;
-};
-
-static int netfs_queue_wake(wait_queue_t *wait, unsigned mode, int sync, void *key)
-{
-       struct netfs_state *st = container_of(wait, struct netfs_state, wait);
-
-       wake_up(&st->thread_wait);
-       return 1;
-}
-
-static void netfs_queue_func(struct file *file, wait_queue_head_t *whead,
-                                poll_table *pt)
-{
-       struct netfs_state *st = container_of(pt, struct netfs_poll_helper, pt)->st;
-
-       st->whead = whead;
-       init_waitqueue_func_entry(&st->wait, netfs_queue_wake);
-       add_wait_queue(whead, &st->wait);
-}
-
-static void netfs_poll_exit(struct netfs_state *st)
-{
-       if (st->whead) {
-               remove_wait_queue(st->whead, &st->wait);
-               st->whead = NULL;
-       }
-}
-
-static int netfs_poll_init(struct netfs_state *st)
-{
-       struct netfs_poll_helper ph;
-
-       ph.st = st;
-       init_poll_funcptr(&ph.pt, &netfs_queue_func);
-
-       st->socket->ops->poll(NULL, st->socket, &ph.pt);
-       return 0;
-}
-
-/*
- * Get response for readpage command. We search inode and page in its mapping
- * and copy data into. If it was async request, then we queue page into shared
- * data and wakeup listener, who will copy it to userspace.
- *
- * There is a work in progress of allowing to call copy_to_user() directly from
- * async receiving kernel thread.
- */
-static int pohmelfs_read_page_response(struct netfs_state *st)
-{
-       struct pohmelfs_sb *psb = st->psb;
-       struct netfs_cmd *cmd = &st->cmd;
-       struct inode *inode;
-       struct page *page;
-       int err = 0;
-
-       if (cmd->size > PAGE_CACHE_SIZE) {
-               err = -EINVAL;
-               goto err_out_exit;
-       }
-
-       inode = ilookup(st->psb->sb, cmd->id);
-       if (!inode) {
-               printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id);
-               err = -ENOENT;
-               goto err_out_exit;
-       }
-
-       page = find_get_page(inode->i_mapping, cmd->start >> PAGE_CACHE_SHIFT);
-       if (!page || !PageLocked(page)) {
-               printk("%s: failed to find/lock page: page: %p, id: %llu, start: %llu, index: %llu.\n",
-                               __func__, page, cmd->id, cmd->start, cmd->start >> PAGE_CACHE_SHIFT);
-
-               while (cmd->size) {
-                       unsigned int sz = min(cmd->size, st->size);
-
-                       err = pohmelfs_data_recv(st, st->data, sz);
-                       if (err)
-                               break;
-
-                       cmd->size -= sz;
-               }
-
-               err = -ENODEV;
-               if (page)
-                       goto err_out_page_put;
-               goto err_out_put;
-       }
-
-       if (cmd->size) {
-               void *addr;
-
-               addr = kmap(page);
-               err = pohmelfs_data_recv(st, addr, cmd->size);
-               kunmap(page);
-
-               if (err)
-                       goto err_out_page_unlock;
-       }
-
-       dprintk("%s: page: %p, start: %llu, size: %u, locked: %d.\n",
-               __func__, page, cmd->start, cmd->size, PageLocked(page));
-
-       SetPageChecked(page);
-       if ((psb->hash_string || psb->cipher_string) && psb->perform_crypto && cmd->size) {
-               err = pohmelfs_crypto_process_input_page(&st->eng, page, cmd->size, cmd->iv);
-               if (err < 0)
-                       goto err_out_page_unlock;
-       } else {
-               SetPageUptodate(page);
-               unlock_page(page);
-               page_cache_release(page);
-       }
-
-       pohmelfs_put_inode(POHMELFS_I(inode));
-       wake_up(&st->psb->wait);
-
-       return 0;
-
-err_out_page_unlock:
-       SetPageError(page);
-       unlock_page(page);
-err_out_page_put:
-       page_cache_release(page);
-err_out_put:
-       pohmelfs_put_inode(POHMELFS_I(inode));
-err_out_exit:
-       wake_up(&st->psb->wait);
-       return err;
-}
-
-static int pohmelfs_check_name(struct pohmelfs_inode *parent, struct qstr *str,
-               struct netfs_inode_info *info)
-{
-       struct inode *inode;
-       struct pohmelfs_name *n;
-       int err = 0;
-       u64 ino = 0;
-
-       mutex_lock(&parent->offset_lock);
-       n = pohmelfs_search_hash(parent, str->hash);
-       if (n)
-               ino = n->ino;
-       mutex_unlock(&parent->offset_lock);
-
-       if (!ino)
-               goto out;
-
-       inode = ilookup(parent->vfs_inode.i_sb, ino);
-       if (!inode)
-               goto out;
-
-       dprintk("%s: parent: %llu, inode: %llu.\n", __func__, parent->ino, ino);
-
-       pohmelfs_fill_inode(inode, info);
-       pohmelfs_put_inode(POHMELFS_I(inode));
-       err = -EEXIST;
-out:
-       return err;
-}
-
-/*
- * Readdir response from server. If special field is set, we wakeup
- * listener (readdir() call), which will copy data to userspace.
- */
-static int pohmelfs_readdir_response(struct netfs_state *st)
-{
-       struct inode *inode;
-       struct netfs_cmd *cmd = &st->cmd;
-       struct netfs_inode_info *info;
-       struct pohmelfs_inode *parent = NULL, *npi;
-       int err = 0, last = cmd->ext;
-       struct qstr str;
-
-       if (cmd->size > st->size)
-               return -EINVAL;
-
-       inode = ilookup(st->psb->sb, cmd->id);
-       if (!inode) {
-               printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id);
-               return -ENOENT;
-       }
-       parent = POHMELFS_I(inode);
-
-       if (!cmd->size && cmd->start) {
-               err = -cmd->start;
-               goto out;
-       }
-
-       if (cmd->size) {
-               char *name;
-
-               err = pohmelfs_data_recv_and_check(st, st->data, cmd->size);
-               if (err)
-                       goto err_out_put;
-
-               info = (struct netfs_inode_info *)(st->data);
-
-               name = (char *)(info + 1);
-               str.len = cmd->size - sizeof(struct netfs_inode_info) - 1 - cmd->cpad;
-               name[str.len] = 0;
-               str.name = name;
-               str.hash = jhash(str.name, str.len, 0);
-
-               netfs_convert_inode_info(info);
-
-               if (parent) {
-                       err = pohmelfs_check_name(parent, &str, info);
-                       if (err) {
-                               if (err == -EEXIST)
-                                       err = 0;
-                               goto out;
-                       }
-               }
-
-               info->ino = cmd->start;
-               if (!info->ino)
-                       info->ino = pohmelfs_new_ino(st->psb);
-
-               dprintk("%s: parent: %llu, ino: %llu, name: '%s', hash: %x, len: %u, mode: %o.\n",
-                               __func__, parent->ino, info->ino, str.name, str.hash, str.len,
-                               info->mode);
-
-               npi = pohmelfs_new_inode(st->psb, parent, &str, info, 0);
-               if (IS_ERR(npi)) {
-                       err = PTR_ERR(npi);
-
-                       if (err != -EEXIST)
-                               goto err_out_put;
-               } else {
-                       struct dentry *dentry, *alias, *pd;
-
-                       set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state);
-                       clear_bit(NETFS_INODE_OWNED, &npi->state);
-
-                       pd = d_find_alias(&parent->vfs_inode);
-                       if (pd) {
-                               str.hash = full_name_hash(str.name, str.len);
-                               dentry = d_alloc(pd, &str);
-                               if (dentry) {
-                                       alias = d_materialise_unique(dentry, &npi->vfs_inode);
-                                       if (alias)
-                                               dput(alias);
-                               }
-
-                               dput(dentry);
-                               dput(pd);
-                       }
-               }
-       }
-out:
-       if (last) {
-               set_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &parent->state);
-               set_bit(NETFS_INODE_REMOTE_SYNCED, &parent->state);
-               wake_up(&st->psb->wait);
-       }
-       pohmelfs_put_inode(parent);
-
-       return err;
-
-err_out_put:
-       clear_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &parent->state);
-       printk("%s: parent: %llu, ino: %llu, cmd_id: %llu.\n", __func__, parent->ino, cmd->start, cmd->id);
-       pohmelfs_put_inode(parent);
-       wake_up(&st->psb->wait);
-       return err;
-}
-
-/*
- * Lookup command response.
- * It searches for inode to be looked at (if it exists) and substitutes
- * its inode information (size, permission, mode and so on), if inode does
- * not exist, new one will be created and inserted into caches.
- */
-static int pohmelfs_lookup_response(struct netfs_state *st)
-{
-       struct inode *inode = NULL;
-       struct netfs_cmd *cmd = &st->cmd;
-       struct netfs_inode_info *info;
-       struct pohmelfs_inode *parent = NULL, *npi;
-       int err = -EINVAL;
-       char *name;
-
-       inode = ilookup(st->psb->sb, cmd->id);
-       if (!inode) {
-               printk("%s: lookup response: id: %llu, start: %llu, size: %u.\n",
-                               __func__, cmd->id, cmd->start, cmd->size);
-               err = -ENOENT;
-               goto err_out_exit;
-       }
-       parent = POHMELFS_I(inode);
-
-       if (!cmd->size) {
-               err = -cmd->start;
-               goto err_out_put;
-       }
-
-       if (cmd->size < sizeof(struct netfs_inode_info)) {
-               printk("%s: broken lookup response: id: %llu, start: %llu, size: %u.\n",
-                               __func__, cmd->id, cmd->start, cmd->size);
-               err = -EINVAL;
-               goto err_out_put;
-       }
-
-       err = pohmelfs_data_recv_and_check(st, st->data, cmd->size);
-       if (err)
-               goto err_out_put;
-
-       info = (struct netfs_inode_info *)(st->data);
-       name = (char *)(info + 1);
-
-       netfs_convert_inode_info(info);
-
-       info->ino = cmd->start;
-       if (!info->ino)
-               info->ino = pohmelfs_new_ino(st->psb);
-
-       dprintk("%s: parent: %llu, ino: %llu, name: '%s', start: %llu.\n",
-                       __func__, parent->ino, info->ino, name, cmd->start);
-
-       if (cmd->start)
-               npi = pohmelfs_new_inode(st->psb, parent, NULL, info, 0);
-       else {
-               struct qstr str;
-
-               str.name = name;
-               str.len = cmd->size - sizeof(struct netfs_inode_info) - 1 - cmd->cpad;
-               str.hash = jhash(name, str.len, 0);
-
-               npi = pohmelfs_new_inode(st->psb, parent, &str, info, 0);
-       }
-       if (IS_ERR(npi)) {
-               err = PTR_ERR(npi);
-
-               if (err != -EEXIST)
-                       goto err_out_put;
-       } else {
-               set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state);
-               clear_bit(NETFS_INODE_OWNED, &npi->state);
-       }
-
-       clear_bit(NETFS_COMMAND_PENDING, &parent->state);
-       pohmelfs_put_inode(parent);
-
-       wake_up(&st->psb->wait);
-
-       return 0;
-
-err_out_put:
-       pohmelfs_put_inode(parent);
-err_out_exit:
-       clear_bit(NETFS_COMMAND_PENDING, &parent->state);
-       wake_up(&st->psb->wait);
-       printk("%s: inode: %p, id: %llu, start: %llu, size: %u, err: %d.\n",
-                       __func__, inode, cmd->id, cmd->start, cmd->size, err);
-       return err;
-}
-
-/*
- * Create response, just marks local inode as 'created', so that writeback
- * for any of its children (or own) would not try to sync it again.
- */
-static int pohmelfs_create_response(struct netfs_state *st)
-{
-       struct inode *inode;
-       struct netfs_cmd *cmd = &st->cmd;
-       struct pohmelfs_inode *pi;
-
-       inode = ilookup(st->psb->sb, cmd->id);
-       if (!inode) {
-               printk("%s: failed to find inode: id: %llu, start: %llu.\n",
-                               __func__, cmd->id, cmd->start);
-               goto err_out_exit;
-       }
-
-       pi = POHMELFS_I(inode);
-
-       /*
-        * To lock or not to lock?
-        * We actually do not care if it races...
-        */
-       if (cmd->start)
-               make_bad_inode(inode);
-       set_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
-
-       pohmelfs_put_inode(pi);
-
-       wake_up(&st->psb->wait);
-       return 0;
-
-err_out_exit:
-       wake_up(&st->psb->wait);
-       return -ENOENT;
-}
-
-/*
- * Object remove response. Just says that remove request has been received.
- * Used in cache coherency protocol.
- */
-static int pohmelfs_remove_response(struct netfs_state *st)
-{
-       struct netfs_cmd *cmd = &st->cmd;
-       int err;
-
-       err = pohmelfs_data_recv_and_check(st, st->data, cmd->size);
-       if (err)
-               return err;
-
-       dprintk("%s: parent: %llu, path: '%s'.\n", __func__, cmd->id, (char *)st->data);
-
-       return 0;
-}
-
-/*
- * Transaction reply processing.
- *
- * Find transaction based on its generation number, bump its reference counter,
- * so that none could free it under us, drop from the trees and lists and
- * drop reference counter. When it hits zero (when all destinations replied
- * and all timeout handled by async scanning code), completion will be called
- * and transaction will be freed.
- */
-static int pohmelfs_transaction_response(struct netfs_state *st)
-{
-       struct netfs_trans_dst *dst;
-       struct netfs_trans *t = NULL;
-       struct netfs_cmd *cmd = &st->cmd;
-       short err = (signed)cmd->ext;
-
-       mutex_lock(&st->trans_lock);
-       dst = netfs_trans_search(st, cmd->start);
-       if (dst) {
-               netfs_trans_remove_nolock(dst, st);
-               t = dst->trans;
-       }
-       mutex_unlock(&st->trans_lock);
-
-       if (!t) {
-               printk("%s: failed to find transaction: start: %llu: id: %llu, size: %u, ext: %u.\n",
-                               __func__, cmd->start, cmd->id, cmd->size, cmd->ext);
-               err = -EINVAL;
-               goto out;
-       }
-
-       t->result = err;
-       netfs_trans_drop_dst_nostate(dst);
-
-out:
-       wake_up(&st->psb->wait);
-       return err;
-}
-
-/*
- * Inode metadata cache coherency message.
- */
-static int pohmelfs_page_cache_response(struct netfs_state *st)
-{
-       struct netfs_cmd *cmd = &st->cmd;
-       struct inode *inode;
-
-       dprintk("%s: st: %p, id: %llu, start: %llu, size: %u.\n", __func__, st, cmd->id, cmd->start, cmd->size);
-
-       inode = ilookup(st->psb->sb, cmd->id);
-       if (!inode) {
-               printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id);
-               return -ENOENT;
-       }
-
-       set_bit(NETFS_INODE_NEED_FLUSH, &POHMELFS_I(inode)->state);
-       pohmelfs_put_inode(POHMELFS_I(inode));
-
-       return 0;
-}
-
-/*
- * Root capabilities response: export statistics
- * like used and available size, number of files and dirs,
- * permissions.
- */
-static int pohmelfs_root_cap_response(struct netfs_state *st)
-{
-       struct netfs_cmd *cmd = &st->cmd;
-       struct netfs_root_capabilities *cap;
-       struct pohmelfs_sb *psb = st->psb;
-
-       if (cmd->size != sizeof(struct netfs_root_capabilities)) {
-               psb->flags = EPROTO;
-               wake_up(&psb->wait);
-               return -EPROTO;
-       }
-
-       cap = st->data;
-
-       netfs_convert_root_capabilities(cap);
-
-       if (psb->total_size < cap->used + cap->avail)
-               psb->total_size = cap->used + cap->avail;
-       if (cap->avail)
-               psb->avail_size = cap->avail;
-       psb->state_flags = cap->flags;
-
-       if (psb->state_flags & POHMELFS_FLAGS_RO) {
-               psb->sb->s_flags |= MS_RDONLY;
-               printk(KERN_INFO "Mounting POHMELFS (%d) read-only.\n", psb->idx);
-       }
-
-       if (psb->state_flags & POHMELFS_FLAGS_XATTR)
-               printk(KERN_INFO "Mounting POHMELFS (%d) "
-                       "with extended attributes support.\n", psb->idx);
-
-       if (atomic_long_read(&psb->total_inodes) <= 1)
-               atomic_long_set(&psb->total_inodes, cap->nr_files);
-
-       dprintk("%s: total: %llu, avail: %llu, flags: %llx, inodes: %llu.\n",
-               __func__, psb->total_size, psb->avail_size, psb->state_flags, cap->nr_files);
-
-       psb->flags = 0;
-       wake_up(&psb->wait);
-       return 0;
-}
-
-/*
- * Crypto capabilities of the server, where it says that
- * it supports or does not requested hash/cipher algorithms.
- */
-static int pohmelfs_crypto_cap_response(struct netfs_state *st)
-{
-       struct netfs_cmd *cmd = &st->cmd;
-       struct netfs_crypto_capabilities *cap;
-       struct pohmelfs_sb *psb = st->psb;
-       int err = 0;
-
-       if (cmd->size != sizeof(struct netfs_crypto_capabilities)) {
-               psb->flags = EPROTO;
-               wake_up(&psb->wait);
-               return -EPROTO;
-       }
-
-       cap = st->data;
-
-       dprintk("%s: cipher '%s': %s, hash: '%s': %s.\n",
-                       __func__,
-                       psb->cipher_string, (cap->cipher_strlen) ? "SUPPORTED" : "NOT SUPPORTED",
-                       psb->hash_string, (cap->hash_strlen) ? "SUPPORTED" : "NOT SUPPORTED");
-
-       if (!cap->hash_strlen) {
-               if (psb->hash_strlen && psb->crypto_fail_unsupported)
-                       err = -ENOTSUPP;
-               psb->hash_strlen = 0;
-               kfree(psb->hash_string);
-               psb->hash_string = NULL;
-       }
-
-       if (!cap->cipher_strlen) {
-               if (psb->cipher_strlen && psb->crypto_fail_unsupported)
-                       err = -ENOTSUPP;
-               psb->cipher_strlen = 0;
-               kfree(psb->cipher_string);
-               psb->cipher_string = NULL;
-       }
-
-       return err;
-}
-
-/*
- * Capabilities handshake response.
- */
-static int pohmelfs_capabilities_response(struct netfs_state *st)
-{
-       struct netfs_cmd *cmd = &st->cmd;
-       int err = 0;
-
-       err = pohmelfs_data_recv(st, st->data, cmd->size);
-       if (err)
-               return err;
-
-       switch (cmd->id) {
-       case POHMELFS_CRYPTO_CAPABILITIES:
-                       return pohmelfs_crypto_cap_response(st);
-       case POHMELFS_ROOT_CAPABILITIES:
-                       return pohmelfs_root_cap_response(st);
-       default:
-                       break;
-       }
-       return -EINVAL;
-}
-
-/*
- * Receiving extended attribute.
- * Does not work properly if received size is more than requested one,
- * it should not happen with current request/reply model though.
- */
-static int pohmelfs_getxattr_response(struct netfs_state *st)
-{
-       struct pohmelfs_sb *psb = st->psb;
-       struct netfs_cmd *cmd = &st->cmd;
-       struct pohmelfs_mcache *m;
-       short error = (signed short)cmd->ext, err;
-       unsigned int sz, total_size;
-
-       m = pohmelfs_mcache_search(psb, cmd->id);
-
-       dprintk("%s: id: %llu, gen: %llu, err: %d.\n",
-               __func__, cmd->id, (m) ? m->gen : 0, error);
-
-       if (!m) {
-               printk("%s: failed to find getxattr cache entry: id: %llu.\n", __func__, cmd->id);
-               return -ENOENT;
-       }
-
-       if (cmd->size) {
-               sz = min_t(unsigned int, cmd->size, m->size);
-               err = pohmelfs_data_recv_and_check(st, m->data, sz);
-               if (err) {
-                       error = err;
-                       goto out;
-               }
-
-               m->size = sz;
-               total_size = cmd->size - sz;
-
-               while (total_size) {
-                       sz = min(total_size, st->size);
-
-                       err = pohmelfs_data_recv_and_check(st, st->data, sz);
-                       if (err) {
-                               error = err;
-                               break;
-                       }
-
-                       total_size -= sz;
-               }
-       }
-
-out:
-       m->err = error;
-       complete(&m->complete);
-       pohmelfs_mcache_put(psb, m);
-
-       return error;
-}
-
-int pohmelfs_data_lock_response(struct netfs_state *st)
-{
-       struct pohmelfs_sb *psb = st->psb;
-       struct netfs_cmd *cmd = &st->cmd;
-       struct pohmelfs_mcache *m;
-       short err = (signed short)cmd->ext;
-       u64 id = cmd->id;
-
-       m = pohmelfs_mcache_search(psb, id);
-
-       dprintk("%s: id: %llu, gen: %llu, err: %d.\n",
-               __func__, cmd->id, (m) ? m->gen : 0, err);
-
-       if (!m) {
-               pohmelfs_data_recv(st, st->data, cmd->size);
-               printk("%s: failed to find data lock response: id: %llu.\n", __func__, cmd->id);
-               return -ENOENT;
-       }
-
-       if (cmd->size)
-               err = pohmelfs_data_recv_and_check(st, &m->info, cmd->size);
-
-       m->err = err;
-       complete(&m->complete);
-       pohmelfs_mcache_put(psb, m);
-
-       return err;
-}
-
-static void __inline__ netfs_state_reset(struct netfs_state *st)
-{
-       netfs_state_lock_send(st);
-       netfs_state_exit(st);
-       netfs_state_init(st);
-       netfs_state_unlock_send(st);
-}
-
-/*
- * Main receiving function, called from dedicated kernel thread.
- */
-static int pohmelfs_recv(void *data)
-{
-       int err = -EINTR;
-       struct netfs_state *st = data;
-       struct netfs_cmd *cmd = &st->cmd;
-
-       while (!kthread_should_stop()) {
-               /*
-                * If socket will be reset after this statement, then
-                * pohmelfs_data_recv() will just fail and loop will
-                * start again, so it can be done without any locks.
-                *
-                * st->read_socket is needed to prevents state machine
-                * breaking between this data reading and subsequent one
-                * in protocol specific functions during connection reset.
-                * In case of reset we have to read next command and do
-                * not expect data for old command to magically appear in
-                * new connection.
-                */
-               st->read_socket = st->socket;
-               err = pohmelfs_data_recv(st, cmd, sizeof(struct netfs_cmd));
-               if (err) {
-                       msleep(1000);
-                       continue;
-               }
-
-               netfs_convert_cmd(cmd);
-
-               dprintk("%s: cmd: %u, id: %llu, start: %llu, size: %u, "
-                               "ext: %u, csize: %u, cpad: %u.\n",
-                               __func__, cmd->cmd, cmd->id, cmd->start,
-                               cmd->size, cmd->ext, cmd->csize, cmd->cpad);
-
-               if (cmd->csize) {
-                       struct pohmelfs_crypto_engine *e = &st->eng;
-
-                       if (unlikely(cmd->csize > e->size/2)) {
-                               netfs_state_reset(st);
-                               continue;
-                       }
-
-                       if (e->hash && unlikely(cmd->csize != st->psb->crypto_attached_size)) {
-                               dprintk("%s: cmd: cmd: %u, id: %llu, start: %llu, size: %u, "
-                                               "csize: %u != digest size %u.\n",
-                                               __func__, cmd->cmd, cmd->id, cmd->start, cmd->size,
-                                               cmd->csize, st->psb->crypto_attached_size);
-                               netfs_state_reset(st);
-                               continue;
-                       }
-
-                       err = pohmelfs_data_recv(st, e->data, cmd->csize);
-                       if (err) {
-                               netfs_state_reset(st);
-                               continue;
-                       }
-
-#ifdef CONFIG_POHMELFS_DEBUG
-                       {
-                               unsigned int i;
-                               unsigned char *hash = e->data;
-
-                               dprintk("%s: received hash: ", __func__);
-                               for (i = 0; i < cmd->csize; ++i)
-                                       printk("%02x ", hash[i]);
-
-                               printk("\n");
-                       }
-#endif
-                       cmd->size -= cmd->csize;
-               }
-
-               /*
-                * This should catch protocol breakage and random garbage instead of commands.
-                */
-               if (unlikely((cmd->size > st->size) && (cmd->cmd != NETFS_XATTR_GET))) {
-                       netfs_state_reset(st);
-                       continue;
-               }
-
-               switch (cmd->cmd) {
-               case NETFS_READ_PAGE:
-                               err = pohmelfs_read_page_response(st);
-                               break;
-               case NETFS_READDIR:
-                               err = pohmelfs_readdir_response(st);
-                               break;
-               case NETFS_LOOKUP:
-                               err = pohmelfs_lookup_response(st);
-                               break;
-               case NETFS_CREATE:
-                               err = pohmelfs_create_response(st);
-                               break;
-               case NETFS_REMOVE:
-                               err = pohmelfs_remove_response(st);
-                               break;
-               case NETFS_TRANS:
-                               err = pohmelfs_transaction_response(st);
-                               break;
-               case NETFS_PAGE_CACHE:
-                               err = pohmelfs_page_cache_response(st);
-                               break;
-               case NETFS_CAPABILITIES:
-                               err = pohmelfs_capabilities_response(st);
-                               break;
-               case NETFS_LOCK:
-                               err = pohmelfs_data_lock_response(st);
-                               break;
-               case NETFS_XATTR_GET:
-                               err = pohmelfs_getxattr_response(st);
-                               break;
-               default:
-                               printk("%s: wrong cmd: %u, id: %llu, start: %llu, size: %u, ext: %u.\n",
-                                       __func__, cmd->cmd, cmd->id, cmd->start, cmd->size, cmd->ext);
-                               netfs_state_reset(st);
-                               break;
-               }
-       }
-
-       while (!kthread_should_stop())
-               schedule_timeout_uninterruptible(msecs_to_jiffies(10));
-
-       return err;
-}
-
-int netfs_state_init(struct netfs_state *st)
-{
-       int err;
-       struct pohmelfs_ctl *ctl = &st->ctl;
-
-       err = sock_create(ctl->addr.sa_family, ctl->type, ctl->proto, &st->socket);
-       if (err) {
-               printk("%s: failed to create a socket: family: %d, type: %d, proto: %d, err: %d.\n",
-                               __func__, ctl->addr.sa_family, ctl->type, ctl->proto, err);
-               goto err_out_exit;
-       }
-
-       st->socket->sk->sk_allocation = GFP_NOIO;
-       st->socket->sk->sk_sndtimeo = st->socket->sk->sk_rcvtimeo = msecs_to_jiffies(60000);
-
-       err = kernel_connect(st->socket, (struct sockaddr *)&ctl->addr, ctl->addrlen, 0);
-       if (err) {
-               printk("%s: failed to connect to server: idx: %u, err: %d.\n",
-                               __func__, st->psb->idx, err);
-               goto err_out_release;
-       }
-       st->socket->sk->sk_sndtimeo = st->socket->sk->sk_rcvtimeo = msecs_to_jiffies(60000);
-
-       err = netfs_poll_init(st);
-       if (err)
-               goto err_out_release;
-
-       if (st->socket->ops->family == AF_INET) {
-               struct sockaddr_in *sin = (struct sockaddr_in *)&ctl->addr;
-               printk(KERN_INFO "%s: (re)connected to peer %pi4:%d.\n", __func__,
-                       &sin->sin_addr.s_addr, ntohs(sin->sin_port));
-       } else if (st->socket->ops->family == AF_INET6) {
-               struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&ctl->addr;
-               printk(KERN_INFO "%s: (re)connected to peer %pi6:%d", __func__,
-                               &sin->sin6_addr, ntohs(sin->sin6_port));
-       }
-
-       return 0;
-
-err_out_release:
-       sock_release(st->socket);
-err_out_exit:
-       st->socket = NULL;
-       return err;
-}
-
-void netfs_state_exit(struct netfs_state *st)
-{
-       if (st->socket) {
-               netfs_poll_exit(st);
-               st->socket->ops->shutdown(st->socket, 2);
-
-               if (st->socket->ops->family == AF_INET) {
-                       struct sockaddr_in *sin = (struct sockaddr_in *)&st->ctl.addr;
-                       printk(KERN_INFO "%s: disconnected from peer %pi4:%d.\n", __func__,
-                               &sin->sin_addr.s_addr, ntohs(sin->sin_port));
-               } else if (st->socket->ops->family == AF_INET6) {
-                       struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&st->ctl.addr;
-                       printk(KERN_INFO "%s: disconnected from peer %pi6:%d", __func__,
-                               &sin->sin6_addr, ntohs(sin->sin6_port));
-               }
-
-               sock_release(st->socket);
-               st->socket = NULL;
-               st->read_socket = NULL;
-               st->need_reset = 0;
-       }
-}
-
-int pohmelfs_state_init_one(struct pohmelfs_sb *psb, struct pohmelfs_config *conf)
-{
-       struct netfs_state *st = &conf->state;
-       int err = -ENOMEM;
-
-       mutex_init(&st->__state_lock);
-       mutex_init(&st->__state_send_lock);
-       init_waitqueue_head(&st->thread_wait);
-
-       st->psb = psb;
-       st->trans_root = RB_ROOT;
-       mutex_init(&st->trans_lock);
-
-       st->size = psb->trans_data_size;
-       st->data = kmalloc(st->size, GFP_KERNEL);
-       if (!st->data)
-               goto err_out_exit;
-
-       if (psb->perform_crypto) {
-               err = pohmelfs_crypto_engine_init(&st->eng, psb);
-               if (err)
-                       goto err_out_free_data;
-       }
-
-       err = netfs_state_init(st);
-       if (err)
-               goto err_out_free_engine;
-
-       st->thread = kthread_run(pohmelfs_recv, st, "pohmelfs/%u", psb->idx);
-       if (IS_ERR(st->thread)) {
-               err = PTR_ERR(st->thread);
-               goto err_out_netfs_exit;
-       }
-
-       if (!psb->active_state)
-               psb->active_state = conf;
-
-       dprintk("%s: conf: %p, st: %p, socket: %p.\n",
-                       __func__, conf, st, st->socket);
-       return 0;
-
-err_out_netfs_exit:
-       netfs_state_exit(st);
-err_out_free_engine:
-       pohmelfs_crypto_engine_exit(&st->eng);
-err_out_free_data:
-       kfree(st->data);
-err_out_exit:
-       return err;
-
-}
-
-void pohmelfs_state_flush_transactions(struct netfs_state *st)
-{
-       struct rb_node *rb_node;
-       struct netfs_trans_dst *dst;
-
-       mutex_lock(&st->trans_lock);
-       for (rb_node = rb_first(&st->trans_root); rb_node; ) {
-               dst = rb_entry(rb_node, struct netfs_trans_dst, state_entry);
-               rb_node = rb_next(rb_node);
-
-               dst->trans->result = -EINVAL;
-               netfs_trans_remove_nolock(dst, st);
-               netfs_trans_drop_dst_nostate(dst);
-       }
-       mutex_unlock(&st->trans_lock);
-}
-
-static void pohmelfs_state_exit_one(struct pohmelfs_config *c)
-{
-       struct netfs_state *st = &c->state;
-
-       dprintk("%s: exiting, st: %p.\n", __func__, st);
-       if (st->thread) {
-               kthread_stop(st->thread);
-               st->thread = NULL;
-       }
-
-       netfs_state_lock_send(st);
-       netfs_state_exit(st);
-       netfs_state_unlock_send(st);
-
-       pohmelfs_state_flush_transactions(st);
-
-       pohmelfs_crypto_engine_exit(&st->eng);
-       kfree(st->data);
-
-       kfree(c);
-}
-
-/*
- * Initialize network stack. It searches for given ID in global
- * configuration table, this contains information of the remote server
- * (address (any supported by socket interface) and port, protocol and so on).
- */
-int pohmelfs_state_init(struct pohmelfs_sb *psb)
-{
-       int err = -ENOMEM;
-
-       err = pohmelfs_copy_config(psb);
-       if (err) {
-               pohmelfs_state_exit(psb);
-               return err;
-       }
-
-       return 0;
-}
-
-void pohmelfs_state_exit(struct pohmelfs_sb *psb)
-{
-       struct pohmelfs_config *c, *tmp;
-
-       list_for_each_entry_safe(c, tmp, &psb->state_list, config_entry) {
-               list_del(&c->config_entry);
-               pohmelfs_state_exit_one(c);
-       }
-}
-
-void pohmelfs_switch_active(struct pohmelfs_sb *psb)
-{
-       struct pohmelfs_config *c = psb->active_state;
-
-       if (!list_empty(&psb->state_list)) {
-               if (c->config_entry.next != &psb->state_list) {
-                       psb->active_state = list_entry(c->config_entry.next,
-                               struct pohmelfs_config, config_entry);
-               } else {
-                       psb->active_state = list_entry(psb->state_list.next,
-                               struct pohmelfs_config, config_entry);
-               }
-
-               dprintk("%s: empty: %d, active %p -> %p.\n",
-                       __func__, list_empty(&psb->state_list), c,
-                       psb->active_state);
-       } else
-               psb->active_state = NULL;
-}
-
-void pohmelfs_check_states(struct pohmelfs_sb *psb)
-{
-       struct pohmelfs_config *c, *tmp;
-       LIST_HEAD(delete_list);
-
-       mutex_lock(&psb->state_lock);
-       list_for_each_entry_safe(c, tmp, &psb->state_list, config_entry) {
-               if (pohmelfs_config_check(c, psb->idx)) {
-
-                       if (psb->active_state == c)
-                               pohmelfs_switch_active(psb);
-                       list_move(&c->config_entry, &delete_list);
-               }
-       }
-       pohmelfs_copy_config(psb);
-       mutex_unlock(&psb->state_lock);
-
-       list_for_each_entry_safe(c, tmp, &delete_list, config_entry) {
-               list_del(&c->config_entry);
-               pohmelfs_state_exit_one(c);
-       }
-}
diff --git a/drivers/staging/pohmelfs/netfs.h b/drivers/staging/pohmelfs/netfs.h
deleted file mode 100644 (file)
index f26894f..0000000
+++ /dev/null
@@ -1,919 +0,0 @@
-/*
- * 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>
-#include <linux/backing-dev.h>
-
-#define POHMELFS_CN_IDX                        5
-#define POHMELFS_CN_VAL                        0
-
-#define POHMELFS_CTLINFO_ACK           1
-#define POHMELFS_NOINFO_ACK            2
-
-#define POHMELFS_NULL_IDX              65535
-
-/*
- * 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 */
-       POHMELFS_FLAGS_MODIFY,  /* Network state modification message */
-       POHMELFS_FLAGS_DUMP,    /* Network state control message for SHOW ALL */
-       POHMELFS_FLAGS_FLUSH,   /* Network state control message for FLUSH */
-};
-
-/*
- * 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 */
-};
-
-#define POHMELFS_IO_PERM_READ          (1<<0)
-#define POHMELFS_IO_PERM_WRITE         (1<<1)
-
-/*
- * Configuration command used to create table of different remote servers.
- */
-struct pohmelfs_ctl {
-       __u32                   idx;            /* Config index */
-       __u32                   type;           /* Socket type */
-       __u32                   proto;          /* Socket protocol */
-       __u16                   addrlen;        /* Size of the address */
-       __u16                   perm;           /* IO permission */
-       __u16                   prio;           /* IO priority */
-       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 information (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;
-
-       struct backing_dev_info bdi;
-
-       /*
-        * 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, umode_t 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);
-}
-
-/*#define POHMELFS_TRUNCATE_ON_INODE_FLUSH
- */
-
-#endif /* __KERNEL__*/
-
-#endif /* __NETFS_H */
diff --git a/drivers/staging/pohmelfs/path_entry.c b/drivers/staging/pohmelfs/path_entry.c
deleted file mode 100644 (file)
index 400a9fc..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 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.
- */
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/ktime.h>
-#include <linux/fs_struct.h>
-#include <linux/pagemap.h>
-#include <linux/writeback.h>
-#include <linux/mount.h>
-#include <linux/mm.h>
-
-#include "netfs.h"
-
-#define UNHASHED_OBSCURE_STRING_SIZE           sizeof(" (deleted)")
-
-/*
- * Create path from root for given inode.
- * Path is formed as set of stuctures, containing name of the object
- * and its inode data (mode, permissions and so on).
- */
-int pohmelfs_construct_path_string(struct pohmelfs_inode *pi, void *data, int len)
-{
-       struct path path;
-       struct dentry *d;
-       char *ptr;
-       int err = 0, strlen, reduce = 0;
-
-       d = d_find_alias(&pi->vfs_inode);
-       if (!d) {
-               printk("%s: no alias, list_empty: %d.\n", __func__, list_empty(&pi->vfs_inode.i_dentry));
-               return -ENOENT;
-       }
-
-       spin_lock(&current->fs->lock);
-       path.mnt = mntget(current->fs->root.mnt);
-       spin_unlock(&current->fs->lock);
-
-       path.dentry = d;
-
-       if (!IS_ROOT(d) && d_unhashed(d))
-               reduce = 1;
-
-       ptr = d_path(&path, data, len);
-       if (IS_ERR(ptr)) {
-               err = PTR_ERR(ptr);
-               goto out;
-       }
-
-       if (reduce && len >= UNHASHED_OBSCURE_STRING_SIZE) {
-               char *end = data + len - UNHASHED_OBSCURE_STRING_SIZE;
-               *end = '\0';
-       }
-
-       strlen = len - (ptr - (char *)data);
-       memmove(data, ptr, strlen);
-       ptr = data;
-
-       err = strlen;
-
-       dprintk("%s: dname: '%s', len: %u, maxlen: %u, name: '%s', strlen: %d.\n",
-                       __func__, d->d_name.name, d->d_name.len, len, ptr, strlen);
-
-out:
-       dput(d);
-       mntput(path.mnt);
-
-       return err;
-}
-
-int pohmelfs_path_length(struct pohmelfs_inode *pi)
-{
-       struct dentry *d, *root, *first;
-       int len;
-       unsigned seq;
-
-       first = d_find_alias(&pi->vfs_inode);
-       if (!first) {
-               dprintk("%s: ino: %llu, mode: %o.\n", __func__, pi->ino, pi->vfs_inode.i_mode);
-               return -ENOENT;
-       }
-
-       spin_lock(&current->fs->lock);
-       root = dget(current->fs->root.dentry);
-       spin_unlock(&current->fs->lock);
-
-rename_retry:
-       len = 1; /* Root slash */
-       d = first;
-       seq = read_seqbegin(&rename_lock);
-       rcu_read_lock();
-
-       if (!IS_ROOT(d) && d_unhashed(d))
-               len += UNHASHED_OBSCURE_STRING_SIZE; /* Obscure " (deleted)" string */
-
-       while (d && d != root && !IS_ROOT(d)) {
-               len += d->d_name.len + 1; /* Plus slash */
-               d = d->d_parent;
-       }
-       rcu_read_unlock();
-       if (read_seqretry(&rename_lock, seq))
-               goto rename_retry;
-
-       dput(root);
-       dput(first);
-
-       return len + 1; /* Including zero-byte */
-}
diff --git a/drivers/staging/pohmelfs/trans.c b/drivers/staging/pohmelfs/trans.c
deleted file mode 100644 (file)
index 06c1a74..0000000
+++ /dev/null
@@ -1,706 +0,0 @@
-/*
- * 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.
- */
-
-#include <linux/module.h>
-#include <linux/crypto.h>
-#include <linux/fs.h>
-#include <linux/jhash.h>
-#include <linux/hash.h>
-#include <linux/ktime.h>
-#include <linux/mempool.h>
-#include <linux/mm.h>
-#include <linux/mount.h>
-#include <linux/pagemap.h>
-#include <linux/parser.h>
-#include <linux/poll.h>
-#include <linux/swap.h>
-#include <linux/slab.h>
-#include <linux/statfs.h>
-#include <linux/writeback.h>
-
-#include "netfs.h"
-
-static struct kmem_cache *netfs_trans_dst;
-static mempool_t *netfs_trans_dst_pool;
-
-static void netfs_trans_init_static(struct netfs_trans *t, int num, int size)
-{
-       t->page_num = num;
-       t->total_size = size;
-       atomic_set(&t->refcnt, 1);
-
-       spin_lock_init(&t->dst_lock);
-       INIT_LIST_HEAD(&t->dst_list);
-}
-
-static int netfs_trans_send_pages(struct netfs_trans *t, struct netfs_state *st)
-{
-       int err = 0;
-       unsigned int i, attached_pages = t->attached_pages, ci;
-       struct msghdr msg;
-       struct page **pages = (t->eng) ? t->eng->pages : t->pages;
-       struct page *p;
-       unsigned int size;
-
-       msg.msg_name = NULL;
-       msg.msg_namelen = 0;
-       msg.msg_control = NULL;
-       msg.msg_controllen = 0;
-       msg.msg_flags = MSG_WAITALL | MSG_MORE;
-
-       ci = 0;
-       for (i = 0; i < t->page_num; ++i) {
-               struct page *page = pages[ci];
-               struct netfs_cmd cmd;
-               struct iovec io;
-
-               p = t->pages[i];
-
-               if (!p)
-                       continue;
-
-               size = page_private(p);
-
-               io.iov_base = &cmd;
-               io.iov_len = sizeof(struct netfs_cmd);
-
-               cmd.cmd = NETFS_WRITE_PAGE;
-               cmd.ext = 0;
-               cmd.id = 0;
-               cmd.size = size;
-               cmd.start = p->index;
-               cmd.start <<= PAGE_CACHE_SHIFT;
-               cmd.csize = 0;
-               cmd.cpad = 0;
-               cmd.iv = pohmelfs_gen_iv(t);
-
-               netfs_convert_cmd(&cmd);
-
-               msg.msg_iov = &io;
-               msg.msg_iovlen = 1;
-               msg.msg_flags = MSG_WAITALL | MSG_MORE;
-
-               err = kernel_sendmsg(st->socket, &msg, (struct kvec *)msg.msg_iov, 1, sizeof(struct netfs_cmd));
-               if (err <= 0) {
-                       printk("%s: %d/%d failed to send transaction header: t: %p, gen: %u, err: %d.\n",
-                                       __func__, i, t->page_num, t, t->gen, err);
-                       if (err == 0)
-                               err = -ECONNRESET;
-                       goto err_out;
-               }
-
-               msg.msg_flags = MSG_WAITALL | (attached_pages == 1 ? 0 :
-                               MSG_MORE);
-
-               err = kernel_sendpage(st->socket, page, 0, size, msg.msg_flags);
-               if (err <= 0) {
-                       printk("%s: %d/%d failed to send transaction page: t: %p, gen: %u, size: %u, err: %d.\n",
-                                       __func__, i, t->page_num, t, t->gen, size, err);
-                       if (err == 0)
-                               err = -ECONNRESET;
-                       goto err_out;
-               }
-
-               dprintk("%s: %d/%d sent t: %p, gen: %u, page: %p/%p, size: %u.\n",
-                       __func__, i, t->page_num, t, t->gen, page, p, size);
-
-               err = 0;
-               attached_pages--;
-               if (!attached_pages)
-                       break;
-               ci++;
-
-               continue;
-
-err_out:
-               printk("%s: t: %p, gen: %u, err: %d.\n", __func__, t, t->gen, err);
-               netfs_state_exit(st);
-               break;
-       }
-
-       return err;
-}
-
-int netfs_trans_send(struct netfs_trans *t, struct netfs_state *st)
-{
-       int err;
-       struct msghdr msg;
-
-       BUG_ON(!t->iovec.iov_len);
-       BUG_ON(t->iovec.iov_len > 1024*1024*1024);
-
-       netfs_state_lock_send(st);
-       if (!st->socket) {
-               err = netfs_state_init(st);
-               if (err)
-                       goto err_out_unlock_return;
-       }
-
-       msg.msg_iov = &t->iovec;
-       msg.msg_iovlen = 1;
-       msg.msg_name = NULL;
-       msg.msg_namelen = 0;
-       msg.msg_control = NULL;
-       msg.msg_controllen = 0;
-       msg.msg_flags = MSG_WAITALL;
-
-       if (t->attached_pages)
-               msg.msg_flags |= MSG_MORE;
-
-       err = kernel_sendmsg(st->socket, &msg, (struct kvec *)msg.msg_iov, 1, t->iovec.iov_len);
-       if (err <= 0) {
-               printk("%s: failed to send contig transaction: t: %p, gen: %u, size: %zu, err: %d.\n",
-                               __func__, t, t->gen, t->iovec.iov_len, err);
-               if (err == 0)
-                       err = -ECONNRESET;
-               goto err_out_unlock_return;
-       }
-
-       dprintk("%s: sent %s transaction: t: %p, gen: %u, size: %zu, page_num: %u.\n",
-                       __func__, (t->page_num) ? "partial" : "full",
-                       t, t->gen, t->iovec.iov_len, t->page_num);
-
-       err = 0;
-       if (t->attached_pages)
-               err = netfs_trans_send_pages(t, st);
-
-err_out_unlock_return:
-
-       if (st->need_reset)
-               netfs_state_exit(st);
-
-       netfs_state_unlock_send(st);
-
-       dprintk("%s: t: %p, gen: %u, err: %d.\n",
-               __func__, t, t->gen, err);
-
-       t->result = err;
-       return err;
-}
-
-static inline int netfs_trans_cmp(unsigned int gen, unsigned int new)
-{
-       if (gen < new)
-               return 1;
-       if (gen > new)
-               return -1;
-       return 0;
-}
-
-struct netfs_trans_dst *netfs_trans_search(struct netfs_state *st, unsigned int gen)
-{
-       struct rb_root *root = &st->trans_root;
-       struct rb_node *n = root->rb_node;
-       struct netfs_trans_dst *tmp, *ret = NULL;
-       struct netfs_trans *t;
-       int cmp;
-
-       while (n) {
-               tmp = rb_entry(n, struct netfs_trans_dst, state_entry);
-               t = tmp->trans;
-
-               cmp = netfs_trans_cmp(t->gen, gen);
-               if (cmp < 0)
-                       n = n->rb_left;
-               else if (cmp > 0)
-                       n = n->rb_right;
-               else {
-                       ret = tmp;
-                       break;
-               }
-       }
-
-       return ret;
-}
-
-static int netfs_trans_insert(struct netfs_trans_dst *ndst, struct netfs_state *st)
-{
-       struct rb_root *root = &st->trans_root;
-       struct rb_node **n = &root->rb_node, *parent = NULL;
-       struct netfs_trans_dst *ret = NULL, *tmp;
-       struct netfs_trans *t = NULL, *new = ndst->trans;
-       int cmp;
-
-       while (*n) {
-               parent = *n;
-
-               tmp = rb_entry(parent, struct netfs_trans_dst, state_entry);
-               t = tmp->trans;
-
-               cmp = netfs_trans_cmp(t->gen, new->gen);
-               if (cmp < 0)
-                       n = &parent->rb_left;
-               else if (cmp > 0)
-                       n = &parent->rb_right;
-               else {
-                       ret = tmp;
-                       break;
-               }
-       }
-
-       if (ret) {
-               printk("%s: exist: old: gen: %u, flags: %x, send_time: %lu, "
-                               "new: gen: %u, flags: %x, send_time: %lu.\n",
-                       __func__, t->gen, t->flags, ret->send_time,
-                       new->gen, new->flags, ndst->send_time);
-               return -EEXIST;
-       }
-
-       rb_link_node(&ndst->state_entry, parent, n);
-       rb_insert_color(&ndst->state_entry, root);
-       ndst->send_time = jiffies;
-
-       return 0;
-}
-
-int netfs_trans_remove_nolock(struct netfs_trans_dst *dst, struct netfs_state *st)
-{
-       if (dst && dst->state_entry.rb_parent_color) {
-               rb_erase(&dst->state_entry, &st->trans_root);
-               dst->state_entry.rb_parent_color = 0;
-               return 1;
-       }
-       return 0;
-}
-
-static int netfs_trans_remove_state(struct netfs_trans_dst *dst)
-{
-       int ret;
-       struct netfs_state *st = dst->state;
-
-       mutex_lock(&st->trans_lock);
-       ret = netfs_trans_remove_nolock(dst, st);
-       mutex_unlock(&st->trans_lock);
-
-       return ret;
-}
-
-/*
- * Create new destination for given transaction associated with given network state.
- * Transaction's reference counter is bumped and will be dropped when either
- * reply is received or when async timeout detection task will fail resending
- * and drop transaction.
- */
-static int netfs_trans_push_dst(struct netfs_trans *t, struct netfs_state *st)
-{
-       struct netfs_trans_dst *dst;
-       int err;
-
-       dst = mempool_alloc(netfs_trans_dst_pool, GFP_KERNEL);
-       if (!dst)
-               return -ENOMEM;
-
-       dst->retries = 0;
-       dst->send_time = 0;
-       dst->state = st;
-       dst->trans = t;
-       netfs_trans_get(t);
-
-       mutex_lock(&st->trans_lock);
-       err = netfs_trans_insert(dst, st);
-       mutex_unlock(&st->trans_lock);
-
-       if (err)
-               goto err_out_free;
-
-       spin_lock(&t->dst_lock);
-       list_add_tail(&dst->trans_entry, &t->dst_list);
-       spin_unlock(&t->dst_lock);
-
-       return 0;
-
-err_out_free:
-       t->result = err;
-       netfs_trans_put(t);
-       mempool_free(dst, netfs_trans_dst_pool);
-       return err;
-}
-
-static void netfs_trans_free_dst(struct netfs_trans_dst *dst)
-{
-       netfs_trans_put(dst->trans);
-       mempool_free(dst, netfs_trans_dst_pool);
-}
-
-static void netfs_trans_remove_dst(struct netfs_trans_dst *dst)
-{
-       if (netfs_trans_remove_state(dst))
-               netfs_trans_free_dst(dst);
-}
-
-/*
- * Drop destination transaction entry when we know it.
- */
-void netfs_trans_drop_dst(struct netfs_trans_dst *dst)
-{
-       struct netfs_trans *t = dst->trans;
-
-       spin_lock(&t->dst_lock);
-       list_del_init(&dst->trans_entry);
-       spin_unlock(&t->dst_lock);
-
-       netfs_trans_remove_dst(dst);
-}
-
-/*
- * Drop destination transaction entry when we know it and when we
- * already removed dst from state tree.
- */
-void netfs_trans_drop_dst_nostate(struct netfs_trans_dst *dst)
-{
-       struct netfs_trans *t = dst->trans;
-
-       spin_lock(&t->dst_lock);
-       list_del_init(&dst->trans_entry);
-       spin_unlock(&t->dst_lock);
-
-       netfs_trans_free_dst(dst);
-}
-
-/*
- * This drops destination transaction entry from appropriate network state
- * tree and drops related reference counter. It is possible that transaction
- * will be freed here if its reference counter hits zero.
- * Destination transaction entry will be freed.
- */
-void netfs_trans_drop_trans(struct netfs_trans *t, struct netfs_state *st)
-{
-       struct netfs_trans_dst *dst, *tmp, *ret = NULL;
-
-       spin_lock(&t->dst_lock);
-       list_for_each_entry_safe(dst, tmp, &t->dst_list, trans_entry) {
-               if (dst->state == st) {
-                       ret = dst;
-                       list_del(&dst->trans_entry);
-                       break;
-               }
-       }
-       spin_unlock(&t->dst_lock);
-
-       if (ret)
-               netfs_trans_remove_dst(ret);
-}
-
-/*
- * This drops destination transaction entry from appropriate network state
- * tree and drops related reference counter. It is possible that transaction
- * will be freed here if its reference counter hits zero.
- * Destination transaction entry will be freed.
- */
-void netfs_trans_drop_last(struct netfs_trans *t, struct netfs_state *st)
-{
-       struct netfs_trans_dst *dst, *tmp, *ret;
-
-       spin_lock(&t->dst_lock);
-       ret = list_entry(t->dst_list.prev, struct netfs_trans_dst, trans_entry);
-       if (ret->state != st) {
-               ret = NULL;
-               list_for_each_entry_safe(dst, tmp, &t->dst_list, trans_entry) {
-                       if (dst->state == st) {
-                               ret = dst;
-                               list_del_init(&dst->trans_entry);
-                               break;
-                       }
-               }
-       } else {
-               list_del(&ret->trans_entry);
-       }
-       spin_unlock(&t->dst_lock);
-
-       if (ret)
-               netfs_trans_remove_dst(ret);
-}
-
-static int netfs_trans_push(struct netfs_trans *t, struct netfs_state *st)
-{
-       int err;
-
-       err = netfs_trans_push_dst(t, st);
-       if (err)
-               return err;
-
-       err = netfs_trans_send(t, st);
-       if (err)
-               goto err_out_free;
-
-       if (t->flags & NETFS_TRANS_SINGLE_DST)
-               pohmelfs_switch_active(st->psb);
-
-       return 0;
-
-err_out_free:
-       t->result = err;
-       netfs_trans_drop_last(t, st);
-
-       return err;
-}
-
-int netfs_trans_finish_send(struct netfs_trans *t, struct pohmelfs_sb *psb)
-{
-       struct pohmelfs_config *c;
-       int err = -ENODEV;
-       struct netfs_state *st;
-#if 0
-       dprintk("%s: t: %p, gen: %u, size: %u, page_num: %u, active: %p.\n",
-               __func__, t, t->gen, t->iovec.iov_len, t->page_num, psb->active_state);
-#endif
-       mutex_lock(&psb->state_lock);
-       list_for_each_entry(c, &psb->state_list, config_entry) {
-               st = &c->state;
-
-               if (t->flags & NETFS_TRANS_SINGLE_DST) {
-                       if (!(st->ctl.perm & POHMELFS_IO_PERM_READ))
-                               continue;
-               } else {
-                       if (!(st->ctl.perm & POHMELFS_IO_PERM_WRITE))
-                               continue;
-               }
-
-               if (psb->active_state && (psb->active_state->state.ctl.prio >= st->ctl.prio) &&
-                               (t->flags & NETFS_TRANS_SINGLE_DST))
-                       st = &psb->active_state->state;
-
-               err = netfs_trans_push(t, st);
-               if (!err && (t->flags & NETFS_TRANS_SINGLE_DST))
-                       break;
-       }
-
-       mutex_unlock(&psb->state_lock);
-#if 0
-       dprintk("%s: fully sent t: %p, gen: %u, size: %u, page_num: %u, err: %d.\n",
-               __func__, t, t->gen, t->iovec.iov_len, t->page_num, err);
-#endif
-       if (err)
-               t->result = err;
-       return err;
-}
-
-int netfs_trans_finish(struct netfs_trans *t, struct pohmelfs_sb *psb)
-{
-       int err;
-       struct netfs_cmd *cmd = t->iovec.iov_base;
-
-       t->gen = atomic_inc_return(&psb->trans_gen);
-
-       cmd->size = t->iovec.iov_len - sizeof(struct netfs_cmd) +
-               t->attached_size + t->attached_pages * sizeof(struct netfs_cmd);
-       cmd->cmd = NETFS_TRANS;
-       cmd->start = t->gen;
-       cmd->id = 0;
-
-       if (psb->perform_crypto) {
-               cmd->ext = psb->crypto_attached_size;
-               cmd->csize = psb->crypto_attached_size;
-       }
-
-       dprintk("%s: t: %u, size: %u, iov_len: %zu, attached_size: %u, attached_pages: %u.\n",
-                       __func__, t->gen, cmd->size, t->iovec.iov_len, t->attached_size, t->attached_pages);
-       err = pohmelfs_trans_crypt(t, psb);
-       if (err) {
-               t->result = err;
-               netfs_convert_cmd(cmd);
-               dprintk("%s: trans: %llu, crypto_attached_size: %u, attached_size: %u, attached_pages: %d, trans_size: %u, err: %d.\n",
-                       __func__, cmd->start, psb->crypto_attached_size, t->attached_size, t->attached_pages, cmd->size, err);
-       }
-       netfs_trans_put(t);
-       return err;
-}
-
-/*
- * Resend transaction to remote server(s).
- * If new servers were added into superblock, we can try to send data
- * to them too.
- *
- * It is called under superblock's state_lock, so we can safely
- * dereference psb->state_list. Also, transaction's reference counter is
- * bumped, so it can not go away under us, thus we can safely access all
- * its members. State is locked.
- *
- * This function returns 0 if transaction was successfully sent to at
- * least one destination target.
- */
-int netfs_trans_resend(struct netfs_trans *t, struct pohmelfs_sb *psb)
-{
-       struct netfs_trans_dst *dst;
-       struct netfs_state *st;
-       struct pohmelfs_config *c;
-       int err, exist, error = -ENODEV;
-
-       list_for_each_entry(c, &psb->state_list, config_entry) {
-               st = &c->state;
-
-               exist = 0;
-               spin_lock(&t->dst_lock);
-               list_for_each_entry(dst, &t->dst_list, trans_entry) {
-                       if (st == dst->state) {
-                               exist = 1;
-                               break;
-                       }
-               }
-               spin_unlock(&t->dst_lock);
-
-               if (exist) {
-                       if (!(t->flags & NETFS_TRANS_SINGLE_DST) ||
-                                       (c->config_entry.next == &psb->state_list)) {
-                               dprintk("%s: resending st: %p, t: %p, gen: %u.\n",
-                                               __func__, st, t, t->gen);
-                               err = netfs_trans_send(t, st);
-                               if (!err)
-                                       error = 0;
-                       }
-                       continue;
-               }
-
-               dprintk("%s: pushing/resending st: %p, t: %p, gen: %u.\n",
-                               __func__, st, t, t->gen);
-               err = netfs_trans_push(t, st);
-               if (err)
-                       continue;
-               error = 0;
-               if (t->flags & NETFS_TRANS_SINGLE_DST)
-                       break;
-       }
-
-       t->result = error;
-       return error;
-}
-
-void *netfs_trans_add(struct netfs_trans *t, unsigned int size)
-{
-       struct iovec *io = &t->iovec;
-       void *ptr;
-
-       if (size > t->total_size) {
-               ptr = ERR_PTR(-EINVAL);
-               goto out;
-       }
-
-       if (io->iov_len + size > t->total_size) {
-               dprintk("%s: too big size t: %p, gen: %u, iov_len: %zu, size: %u, total: %u.\n",
-                               __func__, t, t->gen, io->iov_len, size, t->total_size);
-               ptr = ERR_PTR(-E2BIG);
-               goto out;
-       }
-
-       ptr = io->iov_base + io->iov_len;
-       io->iov_len += size;
-
-out:
-       dprintk("%s: t: %p, gen: %u, size: %u, total: %zu.\n",
-               __func__, t, t->gen, size, io->iov_len);
-       return ptr;
-}
-
-void netfs_trans_free(struct netfs_trans *t)
-{
-       if (t->eng)
-               pohmelfs_crypto_thread_make_ready(t->eng->thread);
-       kfree(t);
-}
-
-struct netfs_trans *netfs_trans_alloc(struct pohmelfs_sb *psb, unsigned int size,
-               unsigned int flags, unsigned int nr)
-{
-       struct netfs_trans *t;
-       unsigned int num, cont, pad, size_no_trans;
-       unsigned int crypto_added = 0;
-       struct netfs_cmd *cmd;
-
-       if (psb->perform_crypto)
-               crypto_added = psb->crypto_attached_size;
-
-       /*
-        * |sizeof(struct netfs_trans)|
-        * |sizeof(struct netfs_cmd)| - transaction header
-        * |size| - buffer with requested size
-        * |padding| - crypto padding, zero bytes
-        * |nr * sizeof(struct page *)| - array of page pointers
-        *
-        * Overall size should be less than PAGE_SIZE for guaranteed allocation.
-        */
-
-       cont = size;
-       size = ALIGN(size, psb->crypto_align_size);
-       pad = size - cont;
-
-       size_no_trans = size + sizeof(struct netfs_cmd) * 2 + crypto_added;
-
-       cont = sizeof(struct netfs_trans) + size_no_trans;
-
-       num = (PAGE_SIZE - cont)/sizeof(struct page *);
-
-       if (nr > num)
-               nr = num;
-
-       t = kzalloc(cont + nr*sizeof(struct page *), GFP_NOIO);
-       if (!t)
-               goto err_out_exit;
-
-       t->iovec.iov_base = (void *)(t + 1);
-       t->pages = (struct page **)(t->iovec.iov_base + size_no_trans);
-
-       /*
-        * Reserving space for transaction header.
-        */
-       t->iovec.iov_len = sizeof(struct netfs_cmd) + crypto_added;
-
-       netfs_trans_init_static(t, nr, size_no_trans);
-
-       t->flags = flags;
-       t->psb = psb;
-
-       cmd = (struct netfs_cmd *)t->iovec.iov_base;
-
-       cmd->size = size;
-       cmd->cpad = pad;
-       cmd->csize = crypto_added;
-
-       dprintk("%s: t: %p, gen: %u, size: %u, padding: %u, align_size: %u, flags: %x, "
-                       "page_num: %u, base: %p, pages: %p.\n",
-                       __func__, t, t->gen, size, pad, psb->crypto_align_size, flags, nr,
-                       t->iovec.iov_base, t->pages);
-
-       return t;
-
-err_out_exit:
-       return NULL;
-}
-
-int netfs_trans_init(void)
-{
-       int err = -ENOMEM;
-
-       netfs_trans_dst = kmem_cache_create("netfs_trans_dst", sizeof(struct netfs_trans_dst),
-                       0, 0, NULL);
-       if (!netfs_trans_dst)
-               goto err_out_exit;
-
-       netfs_trans_dst_pool = mempool_create_slab_pool(256, netfs_trans_dst);
-       if (!netfs_trans_dst_pool)
-               goto err_out_free;
-
-       return 0;
-
-err_out_free:
-       kmem_cache_destroy(netfs_trans_dst);
-err_out_exit:
-       return err;
-}
-
-void netfs_trans_exit(void)
-{
-       mempool_destroy(netfs_trans_dst_pool);
-       kmem_cache_destroy(netfs_trans_dst);
-}