aboutsummaryrefslogtreecommitdiff
path: root/contrib/amd/amd/amfs_nfsl.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/amd/amd/amfs_nfsl.c')
-rw-r--r--contrib/amd/amd/amfs_nfsl.c238
1 files changed, 238 insertions, 0 deletions
diff --git a/contrib/amd/amd/amfs_nfsl.c b/contrib/amd/amd/amfs_nfsl.c
new file mode 100644
index 000000000000..bb48f0efd255
--- /dev/null
+++ b/contrib/amd/amd/amfs_nfsl.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgment:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *
+ * File: am-utils/amd/amfs_nfsl.c
+ *
+ */
+
+/*
+ * NFSL: Network file system with local existence check. If the local
+ * path denoted by $rfs exists, it behaves as type:=link.
+ *
+ * Example:
+ * pkg type:=nfsl;rhost:=jonny;rfs:=/n/johnny/src/pkg;fs:=${rfs}
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amd.h>
+
+
+/* forward declarations */
+static char *amfs_nfsl_match(am_opts *fo);
+static int amfs_nfsl_init(mntfs *mf);
+static int amfs_nfsl_mount(am_node *mp, mntfs *mf);
+static int amfs_nfsl_umount(am_node *mp, mntfs *mf);
+static void amfs_nfsl_umounted(mntfs *mf);
+static fserver *amfs_nfsl_ffserver(mntfs *mf);
+
+/*
+ * NFS-Link operations
+ */
+am_ops amfs_nfsl_ops =
+{
+ "nfsl",
+ amfs_nfsl_match,
+ amfs_nfsl_init,
+ amfs_nfsl_mount,
+ amfs_nfsl_umount,
+ amfs_error_lookup_child,
+ amfs_error_mount_child,
+ amfs_error_readdir,
+ 0, /* amfs_nfsl_readlink */
+ 0, /* amfs_nfsl_mounted */
+ amfs_nfsl_umounted,
+ amfs_nfsl_ffserver,
+ 0, /* amfs_nfsl_get_wchan */
+ FS_MKMNT | FS_BACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+ AUTOFS_NFSL_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
+};
+
+
+/*
+ * Check that f/s has all needed fields.
+ * Returns: matched string if found, NULL otherwise.
+ */
+static char *
+amfs_nfsl_match(am_opts *fo)
+{
+ char *cp;
+ char *ho = fo->opt_rhost;
+ char *retval;
+ struct stat stb;
+
+ if (fo->opt_sublink)
+ cp = fo->opt_sublink;
+ else
+ cp = fo->opt_fs;
+
+ if (!cp || !ho) {
+ plog(XLOG_USER, "amfs_nfsl: host $fs and $rhost must be specified");
+ return NULL;
+ }
+
+ /*
+ * If this host is not the same as $rhost, or if link does not exist,
+ * call nfs_ops.fs_match().
+ * If link value exists (or same host), call amfs_link_ops.fs_match().
+ */
+ if (!STRCEQ(ho, am_get_hostname())) {
+ plog(XLOG_INFO, "amfs_nfsl: \"%s\" is not local host, using type:=nfs", ho);
+ retval = nfs_ops.fs_match(fo);
+ } else if (lstat(cp, &stb) < 0) {
+ plog(XLOG_INFO, "amfs_nfsl: \"%s\" does not exist, using type:=nfs", cp);
+ retval = nfs_ops.fs_match(fo);
+ } else {
+ plog(XLOG_INFO, "amfs_nfsl: \"%s\" exists, using type:=link", cp);
+ retval = amfs_link_ops.fs_match(fo);
+ }
+ return retval;
+}
+
+
+/*
+ * Initialize.
+ * Returns: 0 if OK, non-zero (errno) if failed.
+ */
+static int
+amfs_nfsl_init(mntfs *mf)
+{
+ int ret = 0;
+ if (mf->mf_flags & MFF_NFSLINK) {
+ if (amfs_link_ops.fs_init)
+ ret = amfs_link_ops.fs_init(mf);
+ } else {
+ if (nfs_ops.fs_init)
+ ret = nfs_ops.fs_init(mf);
+ }
+ return ret;
+}
+
+
+/*
+ * Mount vfs.
+ * Returns: 0 if OK, non-zero (errno) if failed.
+ */
+static int
+amfs_nfsl_mount(am_node *mp, mntfs *mf)
+{
+ int ret = 0;
+ if (mf->mf_flags & MFF_NFSLINK) {
+ if (amfs_link_ops.mount_fs)
+ ret = amfs_link_ops.mount_fs(mp, mf);
+ } else {
+ if (nfs_ops.mount_fs)
+ ret = nfs_ops.mount_fs(mp, mf);
+ }
+ return ret;
+}
+
+
+/*
+ * Unmount VFS.
+ * Returns: 0 if OK, non-zero (errno) if failed.
+ */
+static int
+amfs_nfsl_umount(am_node *mp, mntfs *mf)
+{
+ int ret = 0;
+ if (mf->mf_flags & MFF_NFSLINK) {
+ if (amfs_link_ops.umount_fs)
+ ret = amfs_link_ops.umount_fs(mp, mf);
+ } else {
+ if (nfs_ops.umount_fs)
+ ret = nfs_ops.umount_fs(mp, mf);
+ }
+ return ret;
+}
+
+
+/*
+ * Async unmount callback function.
+ * After the base umount() succeeds, we may want to take extra actions,
+ * such as informing remote mount daemons that we've unmounted them.
+ * See amfs_auto_umounted(), host_umounted(), nfs_umounted().
+ */
+static void
+amfs_nfsl_umounted(mntfs *mf)
+{
+ if (mf->mf_flags & MFF_NFSLINK) {
+ if (amfs_link_ops.umounted)
+ amfs_link_ops.umounted(mf);
+ } else {
+ if (nfs_ops.umounted)
+ nfs_ops.umounted(mf);
+ }
+}
+
+
+/*
+ * Find a file server.
+ * Returns: fserver of found server, or NULL if not found.
+ */
+static fserver *
+amfs_nfsl_ffserver(mntfs *mf)
+{
+ char *cp;
+ char *ho = mf->mf_fo->opt_rhost;
+ struct stat stb;
+
+ if (mf->mf_fo->opt_sublink)
+ cp = mf->mf_fo->opt_sublink;
+ else
+ cp = mf->mf_fo->opt_fs;
+
+ /*
+ * If this host is not the same as $rhost, or if link does not exist,
+ * call amfs_link_ops.ffserver().
+ * If link value exists (or same host), then call ops_nfs.ffserver().
+ */
+ if (!STRCEQ(ho, am_get_hostname()) || lstat(cp, &stb) < 0) {
+ return nfs_ops.ffserver(mf);
+ } else {
+ mf->mf_flags |= MFF_NFSLINK;
+ /* remove the FS_MKMNT flag, we don't want amd touching the mountpoint */
+ mf->mf_fsflags &= ~FS_MKMNT;
+ return amfs_link_ops.ffserver(mf);
+ }
+}