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/conf/umount/umount_linux.c
47 * Linux method of unmounting filesystems: if umount(2) failed with EIO or
48 * ESTALE, try umount2(2) with MNT_FORCE+MNT_DETACH.
53 #endif /* HAVE_CONFIG_H */
59 umount_fs(char *mntdir
, const char *mnttabname
, u_int unmount_flags
)
61 mntlist
*mlist
, *mp
, *mp_save
= NULL
;
63 #ifdef HAVE_LOOP_DEVICE
64 char *opt
, *xopts
= NULL
;
65 char loopstr
[] = "loop=";
67 #endif /* HAVE_LOOP_DEVICE */
69 mp
= mlist
= read_mtab(mntdir
, mnttabname
);
72 * Search the mount table looking for
73 * the correct (ie last) matching entry
76 if (STREQ(mp
->mnt
->mnt_dir
, mntdir
))
82 plog(XLOG_ERROR
, "Couldn't find how to unmount %s", mntdir
);
83 /* Assume it is already unmounted */
88 dlog("Trying unmount(%s)", mp_save
->mnt
->mnt_dir
);
90 #ifdef MOUNT_TABLE_ON_FILE
92 * This unmount may hang leaving this process with an exclusive lock on
93 * /etc/mtab. Therefore it is necessary to unlock mtab, do the unmount,
94 * then lock mtab (again) and reread it and finally update it.
97 #endif /* MOUNT_TABLE_ON_FILE */
99 #if defined(HAVE_UMOUNT2) && defined(MNT2_GEN_OPT_DETACH)
101 * If user asked to try forced unmounts, then do a quick check to see if
102 * the mount point is hung badly. If so, then try to detach it by
103 * force; if the latter works, we're done.
105 if (unmount_flags
& AMU_UMOUNT_DETACH
) {
107 * Note: we pass both DETACH and FORCE flags, because umount2_fs below
108 * (on Linux), should try FORCE before DETACH (the latter always
111 error
= umount2_fs(mp_save
->mnt
->mnt_dir
,
112 unmount_flags
& (AMU_UMOUNT_DETACH
|AMU_UMOUNT_FORCE
));
114 #endif /* defined(HAVE_UMOUNT2) && defined(MNT2_GEN_OPT_DETACH) */
115 error
= UNMOUNT_TRAP(mp_save
->mnt
);
117 plog(XLOG_WARNING
, "unmount(%s) failed: %m", mp_save
->mnt
->mnt_dir
);
118 switch ((error
= errno
)) {
121 plog(XLOG_WARNING
, "unmount: %s is not mounted", mp_save
->mnt
->mnt_dir
);
122 error
= 0; /* Not really an error */
127 * This could happen if the kernel insists on following symlinks
128 * when we try to unmount a direct mountpoint. We need to propagate
129 * the error up so that the top layers know it failed and don't
130 * try to rmdir() the mountpoint or other silly things.
132 plog(XLOG_ERROR
, "mount point %s: %m", mp_save
->mnt
->mnt_dir
);
135 #if defined(HAVE_UMOUNT2) && defined(MNT2_GEN_OPT_FORCE)
138 * Caller determines if forced unmounts should be used now (for
139 * EBUSY). If caller asked to force an unmount, *and* the above
140 * "trivial" unmount attempt failed with EBUSY, then try to force
143 if (unmount_flags
& AMU_UMOUNT_FORCE
) {
144 error
= umount2_fs(mp_save
->mnt
->mnt_dir
,
145 unmount_flags
& AMU_UMOUNT_FORCE
);
147 plog(XLOG_WARNING
, "%s: unmount/force: %m",
148 mp_save
->mnt
->mnt_dir
);
153 #endif /* defined(HAVE_UMOUNT2) && defined(MNT2_GEN_OPT_FORCE) */
156 dlog("%s: unmount: %m", mp_save
->mnt
->mnt_dir
);
160 dlog("unmount(%s) succeeded", mp_save
->mnt
->mnt_dir
);
162 dlog("Finished unmount(%s)", mp_save
->mnt
->mnt_dir
);
165 * If we are successful or there was an ENOENT, remove
166 * the mount entry from the mtab file.
168 if (error
&& error
!= ENOENT
)
171 #ifdef HAVE_LOOP_DEVICE
172 /* look for loop=/dev/loopX in mnt_opts */
173 xopts
= strdup(mp_save
->mnt
->mnt_opts
); /* b/c strtok is destructive */
174 for (opt
= strtok(xopts
, ","); opt
; opt
= strtok(NULL
, ","))
175 if (NSTREQ(opt
, loopstr
, sizeof(loopstr
) - 1)) {
176 loopdev
= opt
+ sizeof(loopstr
) - 1;
177 if (delete_loop_device(loopdev
) < 0)
178 plog(XLOG_WARNING
, "unmount() failed to release loop device %s: %m", loopdev
);
180 plog(XLOG_INFO
, "unmount() released loop device %s OK", loopdev
);
185 #endif /* HAVE_LOOP_DEVICE */
187 #ifdef MOUNT_TABLE_ON_FILE
189 mp
= mlist
= read_mtab(mntdir
, mnttabname
);
192 * Search the mount table looking for
193 * the correct (ie last) matching entry
197 if (STREQ(mp
->mnt
->mnt_dir
, mntdir
))
203 mnt_free(mp_save
->mnt
);
205 rewrite_mtab(mlist
, mnttabname
);
207 #endif /* MOUNT_TABLE_ON_FILE */
216 #if defined(HAVE_UMOUNT2) && (defined(MNT2_GEN_OPT_FORCE) || defined(MNT2_GEN_OPT_DETACH))
218 * Force unmount, no questions asked, without touching mnttab file. Try
219 * detach first because it is safer: will remove the hung mnt point without
220 * affecting hung applications. "Force" is more risky: it will cause the
221 * kernel to return EIO to applications stuck on a stat(2) of Amd.
224 umount2_fs(const char *mntdir
, u_int unmount_flags
)
228 #ifdef MNT2_GEN_OPT_DETACH
229 if (unmount_flags
& AMU_UMOUNT_DETACH
) {
230 error
= umount2(mntdir
, MNT2_GEN_OPT_DETACH
);
231 if (error
< 0 && (errno
== EINVAL
|| errno
== ENOENT
))
232 error
= 0; /* ignore EINVAL/ENOENT */
233 if (error
< 0) { /* don't try FORCE if detach succeeded */
234 plog(XLOG_WARNING
, "%s: unmount/detach: %m", mntdir
);
235 /* fall through to try "force" (if flag specified) */
237 dlog("%s: unmount/detach: OK", mntdir
);
241 #endif /* MNT2_GEN_OPT_DETACH */
243 #ifdef MNT2_GEN_OPT_FORCE
244 if (unmount_flags
& AMU_UMOUNT_FORCE
) {
245 plog(XLOG_INFO
, "umount2_fs: trying unmount/forced on %s", mntdir
);
246 error
= umount2(mntdir
, MNT2_GEN_OPT_FORCE
);
247 if (error
< 0 && (errno
== EINVAL
|| errno
== ENOENT
))
248 error
= 0; /* ignore EINVAL/ENOENT */
250 plog(XLOG_WARNING
, "%s: unmount/force: %m", mntdir
);
252 dlog("%s: unmount/force: OK", mntdir
);
253 /* fall through to return whatever error we got (if any) */
255 #endif /* MNT2_GEN_OPT_FORCE */
259 #endif /* HAVE_UMOUNT2 && (MNT2_GEN_OPT_FORCE || MNT2_GEN_OPT_DETACH) */