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.
10 * This code is derived from software contributed to Berkeley by
11 * Jan-Simon Pendry at Imperial College, London.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
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.
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
42 * File: am-utils/amd/ops_cachefs.c
47 * Caching filesystem (Solaris 2.x)
52 #endif /* HAVE_CONFIG_H */
56 /* forward declarations */
57 static char *cachefs_match(am_opts
*fo
);
58 static int cachefs_init(mntfs
*mf
);
59 static int cachefs_mount(am_node
*am
, mntfs
*mf
);
60 static int cachefs_umount(am_node
*am
, mntfs
*mf
);
73 amfs_error_lookup_child
,
74 amfs_error_mount_child
,
76 0, /* cachefs_readlink */
77 0, /* cachefs_mounted */
78 0, /* cachefs_umounted */
79 amfs_generic_find_srvr
,
80 0, /* cachefs_get_wchan */
81 FS_MKMNT
| FS_NOTIMEOUT
| FS_UBACKGROUND
| FS_AMQINFO
, /* nfs_fs_flags */
83 AUTOFS_CACHEFS_FS_FLAGS
,
84 #endif /* HAVE_FS_AUTOFS */
89 * Check that f/s has all needed fields.
90 * Returns: matched string if found, NULL otherwise.
93 cachefs_match(am_opts
*fo
)
96 if (!fo
->opt_rfs
|| !fo
->opt_fs
|| !fo
->opt_cachedir
) {
97 plog(XLOG_USER
, "cachefs: must specify cachedir, rfs, and fs");
101 dlog("CACHEFS: using cache directory \"%s\"", fo
->opt_cachedir
);
103 /* determine magic cookie to put in mtab */
104 return strdup(fo
->opt_cachedir
);
110 * Returns: 0 if OK, non-zero (errno) if failed.
113 cachefs_init(mntfs
*mf
)
116 * Save cache directory name
118 if (!mf
->mf_private
) {
119 mf
->mf_private
= (voidp
) strdup(mf
->mf_fo
->opt_cachedir
);
120 mf
->mf_prfree
= (void (*)(voidp
)) free
;
128 * mntpt is the mount point ($fs) [XXX: was 'dir']
129 * backdir is the mounted pathname ($rfs) [XXX: was 'fs_name']
130 * cachedir is the cache directory ($cachedir)
133 mount_cachefs(char *mntdir
, char *backdir
, char *cachedir
,
134 char *opts
, int on_autofs
)
140 MTYPE_TYPE type
= MOUNT_TYPE_CACHEFS
; /* F/S mount type */
142 memset((voidp
) &ca
, 0, sizeof(ca
)); /* Paranoid */
145 * Fill in the mount structure
147 memset((voidp
) &mnt
, 0, sizeof(mnt
));
148 mnt
.mnt_dir
= mntdir
;
149 mnt
.mnt_fsname
= backdir
;
150 mnt
.mnt_type
= MNTTAB_TYPE_CACHEFS
;
153 flags
= compute_mount_flags(&mnt
);
154 #ifdef HAVE_FS_AUTOFS
156 flags
|= autofs_compute_mount_flags(&mnt
);
157 #endif /* HAVE_FS_AUTOFS */
159 /* Fill in cachefs mount arguments */
163 * (1) cache directory is NOT checked for sanity beforehand, nor is it
164 * purged. Maybe it should be purged first?
165 * (2) cache directory is NOT locked. Should we?
169 ca
.cfs_options
.opt_flags
= CFS_WRITE_AROUND
| CFS_ACCESS_BACKFS
;
170 /* cache population size */
171 ca
.cfs_options
.opt_popsize
= DEF_POP_SIZE
; /* default: 64K */
173 ca
.cfs_options
.opt_fgsize
= DEF_FILEGRP_SIZE
; /* default: 256 */
175 /* CFS ID for file system (must be unique) */
176 ca
.cfs_fsid
= cachedir
;
178 /* CFS fscdir name */
179 memset(ca
.cfs_cacheid
, 0, sizeof(ca
.cfs_cacheid
));
181 * Append cacheid and mountpoint.
182 * sizeof(cfs_cacheid) should be C_MAX_MOUNT_FSCDIRNAME as per
183 * <sys/fs/cachefs_fs.h> (checked on Solaris 8).
185 xsnprintf(ca
.cfs_cacheid
, sizeof(ca
.cfs_cacheid
),
186 "%s:%s", ca
.cfs_fsid
, mntdir
);
187 /* convert '/' to '_' (Solaris does that...) */
189 while ((cp
= strpbrk(cp
, "/")) != NULL
)
192 /* path for this cache dir */
193 ca
.cfs_cachedir
= cachedir
;
195 /* back filesystem dir */
196 ca
.cfs_backfs
= backdir
;
198 /* same as nfs values (XXX: need to handle these options) */
205 * Call generic mount routine
207 return mount_fs(&mnt
, flags
, (caddr_t
) &ca
, 0, type
, 0, NULL
, mnttab_file_name
, on_autofs
);
212 cachefs_mount(am_node
*am
, mntfs
*mf
)
214 int on_autofs
= mf
->mf_flags
& MFF_ON_AUTOFS
;
217 error
= mount_cachefs(mf
->mf_mount
,
219 mf
->mf_fo
->opt_cachedir
,
224 /* according to Solaris, if errno==ESRCH, "options to not match" */
226 plog(XLOG_ERROR
, "mount_cachefs: options to no match: %m");
228 plog(XLOG_ERROR
, "mount_cachefs: %m");
237 cachefs_umount(am_node
*am
, mntfs
*mf
)
239 int unmount_flags
= (mf
->mf_flags
& MFF_ON_AUTOFS
) ? AMU_UMOUNT_AUTOFS
: 0;
242 error
= UMOUNT_FS(mf
->mf_mount
, mnttab_file_name
, unmount_flags
);
245 * In the case of cachefs, we must fsck the cache directory. Otherwise,
246 * it will remain inconsistent, and the next cachefs mount will fail
247 * with the error "no space left on device" (ENOSPC).
249 * XXX: this is hacky! use fork/exec/wait instead...
252 char *cachedir
= NULL
;
255 cachedir
= (char *) mf
->mf_private
;
256 plog(XLOG_INFO
, "running fsck on cache directory \"%s\"", cachedir
);
257 xsnprintf(cmd
, sizeof(cmd
), "fsck -F cachefs %s", cachedir
);