1/* $NetBSD: amfs_nfsl.c,v 1.1.1.2 2009/03/20 20:26:49 christos Exp $ */ 2 3/* 4 * Copyright (c) 1997-2009 Erez Zadok 5 * Copyright (c) 1990 Jan-Simon Pendry 6 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 7 * Copyright (c) 1990 The Regents of the University of California. 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to Berkeley by 11 * Jan-Simon Pendry at Imperial College, London. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgment: 23 * This product includes software developed by the University of 24 * California, Berkeley and its contributors. 25 * 4. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * 42 * File: am-utils/amd/amfs_nfsl.c 43 * 44 */ 45 46/* 47 * NFSL: Network file system with local existence check. If the local 48 * path denoted by $rfs exists, it behaves as type:=link. 49 * 50 * Example: 51 * pkg type:=nfsl;rhost:=jonny;rfs:=/n/johnny/src/pkg;fs:=${rfs} 52 */ 53 54#ifdef HAVE_CONFIG_H 55# include <config.h> 56#endif /* HAVE_CONFIG_H */ 57#include <am_defs.h> 58#include <amd.h> 59 60 61/* forward declarations */ 62static char *amfs_nfsl_match(am_opts *fo); 63static int amfs_nfsl_init(mntfs *mf); 64static int amfs_nfsl_mount(am_node *mp, mntfs *mf); 65static int amfs_nfsl_umount(am_node *mp, mntfs *mf); 66static void amfs_nfsl_umounted(mntfs *mf); 67static fserver *amfs_nfsl_ffserver(mntfs *mf); 68 69/* 70 * NFS-Link operations 71 */ 72am_ops amfs_nfsl_ops = 73{ 74 "nfsl", 75 amfs_nfsl_match, 76 amfs_nfsl_init, 77 amfs_nfsl_mount, 78 amfs_nfsl_umount, 79 amfs_error_lookup_child, 80 amfs_error_mount_child, 81 amfs_error_readdir, 82 0, /* amfs_nfsl_readlink */ 83 0, /* amfs_nfsl_mounted */ 84 amfs_nfsl_umounted, 85 amfs_nfsl_ffserver, 86 0, /* amfs_nfsl_get_wchan */ 87 FS_MKMNT | FS_BACKGROUND | FS_AMQINFO, /* nfs_fs_flags */ 88#ifdef HAVE_FS_AUTOFS 89 AUTOFS_NFSL_FS_FLAGS, 90#endif /* HAVE_FS_AUTOFS */ 91}; 92 93 94/* 95 * Check that f/s has all needed fields. 96 * Returns: matched string if found, NULL otherwise. 97 */ 98static char * 99amfs_nfsl_match(am_opts *fo) 100{ 101 char *cp; 102 char *ho = fo->opt_rhost; 103 char *retval; 104 struct stat stb; 105 106 if (fo->opt_sublink && fo->opt_sublink[0]) 107 cp = fo->opt_sublink; 108 else 109 cp = fo->opt_fs; 110 111 if (!cp || !ho) { 112 plog(XLOG_USER, "amfs_nfsl: host $fs and $rhost must be specified"); 113 return NULL; 114 } 115 116 /* 117 * If this host is not the same as $rhost, or if link does not exist, 118 * call nfs_ops.fs_match(). 119 * If link value exists (or same host), call amfs_link_ops.fs_match(). 120 */ 121 if (!STRCEQ(ho, am_get_hostname())) { 122 plog(XLOG_INFO, "amfs_nfsl: \"%s\" is not local host, using type:=nfs", ho); 123 retval = nfs_ops.fs_match(fo); 124 } else if (lstat(cp, &stb) < 0) { 125 plog(XLOG_INFO, "amfs_nfsl: \"%s\" does not exist, using type:=nfs", cp); 126 retval = nfs_ops.fs_match(fo); 127 } else { 128 plog(XLOG_INFO, "amfs_nfsl: \"%s\" exists, using type:=link", cp); 129 retval = amfs_link_ops.fs_match(fo); 130 } 131 return retval; 132} 133 134 135/* 136 * Initialize. 137 * Returns: 0 if OK, non-zero (errno) if failed. 138 */ 139static int 140amfs_nfsl_init(mntfs *mf) 141{ 142 int ret = 0; 143 if (mf->mf_flags & MFF_NFSLINK) { 144 if (amfs_link_ops.fs_init) 145 ret = amfs_link_ops.fs_init(mf); 146 } else { 147 if (nfs_ops.fs_init) 148 ret = nfs_ops.fs_init(mf); 149 } 150 return ret; 151} 152 153 154/* 155 * Mount vfs. 156 * Returns: 0 if OK, non-zero (errno) if failed. 157 */ 158static int 159amfs_nfsl_mount(am_node *mp, mntfs *mf) 160{ 161 int ret = 0; 162 if (mf->mf_flags & MFF_NFSLINK) { 163 if (amfs_link_ops.mount_fs) 164 ret = amfs_link_ops.mount_fs(mp, mf); 165 } else { 166 if (nfs_ops.mount_fs) 167 ret = nfs_ops.mount_fs(mp, mf); 168 } 169 return ret; 170} 171 172 173/* 174 * Unmount VFS. 175 * Returns: 0 if OK, non-zero (errno) if failed. 176 */ 177static int 178amfs_nfsl_umount(am_node *mp, mntfs *mf) 179{ 180 int ret = 0; 181 if (mf->mf_flags & MFF_NFSLINK) { 182 if (amfs_link_ops.umount_fs) 183 ret = amfs_link_ops.umount_fs(mp, mf); 184 } else { 185 if (nfs_ops.umount_fs) 186 ret = nfs_ops.umount_fs(mp, mf); 187 } 188 return ret; 189} 190 191 192/* 193 * Async unmount callback function. 194 * After the base umount() succeeds, we may want to take extra actions, 195 * such as informing remote mount daemons that we've unmounted them. 196 * See amfs_auto_umounted(), host_umounted(), nfs_umounted(). 197 */ 198static void 199amfs_nfsl_umounted(mntfs *mf) 200{ 201 if (mf->mf_flags & MFF_NFSLINK) { 202 if (amfs_link_ops.umounted) 203 amfs_link_ops.umounted(mf); 204 } else { 205 if (nfs_ops.umounted) 206 nfs_ops.umounted(mf); 207 } 208} 209 210 211/* 212 * Find a file server. 213 * Returns: fserver of found server, or NULL if not found. 214 */ 215static fserver * 216amfs_nfsl_ffserver(mntfs *mf) 217{ 218 char *cp; 219 char *ho = mf->mf_fo->opt_rhost; 220 struct stat stb; 221 222 if (mf->mf_fo->opt_sublink && mf->mf_fo->opt_sublink[0]) 223 cp = mf->mf_fo->opt_sublink; 224 else 225 cp = mf->mf_fo->opt_fs; 226 227 /* 228 * If this host is not the same as $rhost, or if link does not exist, 229 * call amfs_link_ops.ffserver(). 230 * If link value exists (or same host), then call ops_nfs.ffserver(). 231 */ 232 if (!STRCEQ(ho, am_get_hostname()) || lstat(cp, &stb) < 0) { 233 return nfs_ops.ffserver(mf); 234 } else { 235 mf->mf_flags |= MFF_NFSLINK; 236 /* remove the FS_MKMNT flag, we don't want amd touching the mountpoint */ 237 mf->mf_fsflags &= ~FS_MKMNT; 238 return amfs_link_ops.ffserver(mf); 239 } 240} 241