@@ -16,5 +16,5 @@ nfsd-$(CONFIG_NFSD_V2_ACL) += nfs2acl.o
nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o
nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o
nfsd-$(CONFIG_NFSD_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \
- nfs4acl.o nfs4callback.o nfs4recover.o
+ nfs4acl.o nfs4callback.o nfs4recover.o nfs4interssc.o
nfsd-$(CONFIG_NFSD_PNFS) += nfs4layouts.o blocklayout.o blocklayoutxdr.o
new file mode 100644
@@ -0,0 +1,110 @@
+/*
+ * linux/fs/nfsd/nfs4interssc.c
+ *
+ * Copyright (C) 2014 Andy Adamson <andros@netapp.com>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/nfs_fs.h>
+
+
+/* Inter server side copy module list */
+static DEFINE_SPINLOCK(ssc_spinlock);
+static LIST_HEAD(ssc_modules_tbl);
+
+static struct nfs42_inter_ssc_ops *
+find_ssc_module_locked(int version) {
+ struct nfs42_inter_ssc_ops *local;
+
+ list_for_each_entry(local, &ssc_modules_tbl, ssc_mtable)
+ if (local->ssc_version == version)
+ goto out;
+ local = NULL;
+out:
+ printk("%s: Searching for version %u, found %p\n", __func__, version,
+ local);
+ return local;
+};
+
+static struct nfs42_inter_ssc_ops *
+find_ssc_module(u32 version)
+{
+ struct nfs42_inter_ssc_ops *local;
+
+ spin_lock(&ssc_spinlock);
+ local = find_ssc_module_locked(version);
+ if (local != NULL && !try_module_get(local->ssc_owner)) {
+ printk("%s: Could not grab reference on module\n", __func__);
+ local = NULL;
+ }
+ spin_unlock(&ssc_spinlock);
+ return local;
+}
+
+/**
+ * Ref counting for icopp?
+ */
+void
+set_ssc_module(struct nfs42_inter_ssc_ops **icopp, u32 version) {
+ struct nfs42_inter_ssc_ops *icop;
+
+ icop = find_ssc_module(version);
+ if (icop == NULL) {
+ request_module("nfs42-interserver-copy");
+ icop = find_ssc_module(version);
+ if (icop == NULL) {
+ printk("%s: No Module found for %u.\n",
+ __func__, version);
+ *icopp = NULL;
+ return;
+ }
+ }
+ *icopp = icop;
+ return;
+};
+
+void
+unset_ssc_module(struct nfs42_inter_ssc_ops *icop)
+{
+ printk("--> %s\n", __func__);
+ module_put(icop->ssc_owner);
+}
+
+int
+nfsd4_register_intecopy_driver(struct nfs42_inter_ssc_ops *ico, u32 version)
+{
+ struct nfs42_inter_ssc_ops *tmp;
+ int status = -EINVAL;
+
+ if (version != 42) {
+ printk(KERN_ERR "NFS: %s invalid module version %d\n",
+ __func__, version);
+ return status;
+ }
+
+ spin_lock(&ssc_spinlock);
+ tmp = find_ssc_module_locked(version);
+ if (tmp == NULL) {
+ list_add(&ico->ssc_mtable, &ssc_modules_tbl);
+ status = 0;
+ printk("%s Registering version:%u name:%s\n", __func__,
+ ico->ssc_version, ico->ssc_name);
+ } else {
+ printk(KERN_ERR "NFS: %s Module version %d already loaded!\n",
+ __func__, ico->ssc_version);
+ }
+ spin_unlock(&ssc_spinlock);
+ return status;
+}
+EXPORT_SYMBOL_GPL(nfsd4_register_intecopy_driver);
+
+void
+nfsd4_unregister_intecopy_driver(struct nfs42_inter_ssc_ops *ico)
+{
+ printk("%s Deregistering version:%u\n", __func__, ico->ssc_version);
+ spin_lock(&ssc_spinlock);
+ list_del(&ico->ssc_mtable);
+ spin_unlock(&ssc_spinlock);
+}
+EXPORT_SYMBOL_GPL(nfsd4_unregister_intecopy_driver);