Mount/Unmount
mount(), umount2()
/etc/fstab, /proc/mounts
Key Terms:
What is Mounting?
Linux has a single directory tree rooted at /. All filesystems — whether on your hard disk, USB, or over the network — must be attached into this tree to be accessible. This attachment is called mounting.
A mount point is any directory in the existing tree where a new filesystem is attached. After mounting, the filesystem’s root appears at that directory.
# Mount filesystem on /dev/sdb1 at /mnt/usb:
mount /dev/sdb1 /mnt/usb
# Now access files:
ls /mnt/usb # shows files on USB
# Unmount when done:
umount /mnt/usb
| / (root) — sda6 ext4 filesystem | |||||||
| bin | etc | usr | home ← sda8 ext3 | proc ← procfs | sys ← sysfs | windows ← sda1 vfat | tmp |
| avr/ mtk/ → test/ ← sda9 reiserfs |
C/ explorer.exe |
||||||
Highlighted cells with ← are mount points where different filesystems are attached into the tree.
#include <sys/mount.h>
int mount(const char *source, /* device or special source */
const char *target, /* mount point directory */
const char *fstype, /* "ext4", "vfat", "tmpfs" ... */
unsigned long mountflags, /* OR'd flags from table below */
const void *data); /* fs-specific options string */
/* Returns 0 on success, -1 on error */
Key mountflags:
| Flag | Purpose |
|---|---|
MS_RDONLY |
Read-only mount — no new files can be created |
MS_NOSUID |
Disable setuid/setgid programs — security feature |
MS_NODEV |
Disallow access to device files on this FS |
MS_NOEXEC |
Don’t allow programs to execute from this FS |
MS_SYNCHRONOUS |
All writes synchronous (like O_SYNC on every file) |
MS_REMOUNT |
Change flags on already-mounted FS (e.g., ro to rw) |
MS_BIND |
Bind mount: make a directory visible at another location |
MS_NOATIME |
Don’t update access time — improves read performance |
MS_RELATIME |
Update atime only if older than mtime (default since 2.6.30) |
MS_MOVE |
Atomically move a mount point to a new location |
MS_REC |
Apply recursively to all submounts in a subtree |
MS_DIRSYNC |
Directory updates synchronous (create/rename/link) |
#include <stdio.h>
#include <sys/mount.h>
int main(void) {
/* Example 1: Mount ext4 filesystem read-write */
if (mount("/dev/sdb1", /* source: block device */
"/mnt/data", /* target: mount point */
"ext4", /* filesystem type */
0, /* flags: none = read-write */
NULL) /* no extra options */
== -1) {
perror("mount ext4");
return 1;
}
printf("Mounted /dev/sdb1 at /mnt/data\n");
/* Example 2: Mount read-only */
if (mount("/dev/sdb1", "/mnt/data_ro", "ext4",
MS_RDONLY, /* read-only flag */
NULL) == -1) {
perror("mount read-only");
}
/* Example 3: Remount existing mount as read-write */
/* (e.g., root fs is initially mounted ro, then remounted rw) */
if (mount("/dev/sda1", "/", NULL,
MS_REMOUNT, /* keep target=/, */
NULL) == -1) {
/* MS_REMOUNT ignores fstype, uses existing */
perror("remount");
}
/* Example 4: Mount with options string */
if (mount("/dev/sdb1", "/mnt/fat", "vfat",
MS_NOEXEC | MS_NOSUID,
"iocharset=utf8,umask=022") == -1) {
perror("mount vfat");
}
/* Example 5: Mount tmpfs (no device needed) */
if (mount("tmpfs", "/tmp/ramdisk", "tmpfs",
0,
"size=64m") == -1) { /* 64MB size limit */
perror("mount tmpfs");
}
return 0;
}
/* Must be run as root (CAP_SYS_ADMIN) */
#include <stdio.h>
#include <string.h>
#include <mntent.h> /* getmntent(), setmntent() */
/* /proc/mounts format (6 fields):
device mountpoint fstype options dump fsck_order */
void list_mounts_manual(void) {
FILE *fp;
char line[512];
char device[128], mountpoint[128], fstype[32];
char options[256];
int dump, fsck;
fp = fopen("/proc/mounts", "r");
if (!fp) { perror("fopen /proc/mounts"); return; }
printf("%-20s %-20s %-10s %s\n",
"Device", "Mount Point", "FS Type", "Options");
printf("%-20s %-20s %-10s %s\n",
"------", "-----------", "-------", "-------");
while (fgets(line, sizeof(line), fp)) {
sscanf(line, "%127s %127s %31s %255s %d %d",
device, mountpoint, fstype, options, &dump, &fsck);
printf("%-20s %-20s %-10s %s\n",
device, mountpoint, fstype, options);
}
fclose(fp);
}
/* Better: use mntent library (reads /etc/fstab or /proc/mounts) */
void list_mounts_mntent(void) {
FILE *fp;
struct mntent *mnt;
fp = setmntent("/proc/mounts", "r");
if (!fp) { perror("setmntent"); return; }
printf("\n=== Via getmntent() ===\n");
while ((mnt = getmntent(fp)) != NULL) {
printf("%-15s on %-20s type %-10s (%s)\n",
mnt->mnt_fsname, /* device */
mnt->mnt_dir, /* mount point */
mnt->mnt_type, /* fs type */
mnt->mnt_opts); /* options */
}
endmntent(fp);
}
int main(void) {
list_mounts_manual();
list_mounts_mntent();
return 0;
}
/* Sample output:
Device Mount Point FS Type Options
------ ----------- ------- -------
/dev/sda1 / ext4 rw,relatime
tmpfs /tmp tmpfs rw,nosuid
/dev/sdb1 /mnt/usb vfat rw,uid=1000
*/
#include <sys/mount.h>
int umount(const char *target); /* target = mount point */
int umount2(const char *target, int flags);
/* flags: MNT_DETACH, MNT_EXPIRE, MNT_FORCE, UMOUNT_NOFOLLOW */
Lazy unmount. Marks the mount so no new accesses allowed, but existing processes continue using it. Actually unmounts when all processes close their files.
Mark as “expirable”. First call fails with EAGAIN but marks it. If not used, a second call unmounts it. Good for automounting.
Force unmount even if busy (NFS only). May cause data loss. Use with caution.
#include <stdio.h>
#include <sys/mount.h>
#include <errno.h>
#include <string.h>
int safe_unmount(const char *mountpoint) {
/* Try normal unmount first */
if (umount(mountpoint) == 0) {
printf("Unmounted %s successfully\n", mountpoint);
return 0;
}
if (errno == EBUSY) {
printf("%s is busy. Trying lazy unmount...\n", mountpoint);
/* MNT_DETACH: stop new access, let existing finish */
if (umount2(mountpoint, MNT_DETACH) == 0) {
printf("Lazy unmount done — will complete when idle\n");
return 0;
}
}
fprintf(stderr, "umount failed: %s\n", strerror(errno));
return -1;
}
int main(void) {
/* Normal unmount */
safe_unmount("/mnt/usb");
/* Check if anything is keeping fs busy before unmounting:
lsof +D /mnt/usb shows open files
fuser -mv /mnt/usb shows processes using it
*/
/* Remount read-only before unmounting
(useful for safely removing storage) */
if (mount("", "/mnt/data", "",
MS_REMOUNT | MS_RDONLY, NULL) == 0) {
printf("Remounted read-only, safe to remove\n");
umount("/mnt/data");
}
return 0;
}
/* Shell equivalents:
umount /mnt/usb
umount -l /mnt/usb # lazy
umount -f /mnt/nfs # force (NFS only)
Find what's using a mount:
fuser -mv /mnt/usb
lsof +D /mnt/usb
*/
#include <stdio.h>
#include <mntent.h>
/* /etc/fstab: static table of filesystems to mount at boot.
Same format as /proc/mounts but maintained by admin, not kernel. */
int main(void) {
FILE *fp;
struct mntent *mnt;
fp = setmntent("/etc/fstab", "r");
if (!fp) { perror("setmntent /etc/fstab"); return 1; }
printf("Filesystems defined in /etc/fstab:\n\n");
printf("%-20s %-15s %-8s %-20s %s %s\n",
"Device", "MountPoint", "FSType", "Options",
"Dump", "Pass");
while ((mnt = getmntent(fp)) != NULL) {
/* Skip comments (lines starting with #) — handled by getmntent */
printf("%-20s %-15s %-8s %-20s %d %d\n",
mnt->mnt_fsname,
mnt->mnt_dir,
mnt->mnt_type,
mnt->mnt_opts,
mnt->mnt_freq, /* dump frequency */
mnt->mnt_passno); /* fsck pass order */
/* Check for specific options */
if (hasmntopt(mnt, "ro"))
printf(" ^ Note: mounted READ-ONLY\n");
if (hasmntopt(mnt, "noauto"))
printf(" ^ Note: not auto-mounted at boot\n");
}
endmntent(fp);
/* Show how to find specific entry */
printf("\n--- Looking for swap entries ---\n");
fp = setmntent("/etc/fstab", "r");
while ((mnt = getmntent(fp)) != NULL) {
if (strcmp(mnt->mnt_type, "swap") == 0)
printf("Swap: %s\n", mnt->mnt_fsname);
}
endmntent(fp);
return 0;
}
/* /etc/fstab example:
# <device> <mount> <type> <options> <dump> <pass>
UUID=abc-123 / ext4 errors=remount-ro 0 1
UUID=def-456 /home ext4 defaults 0 2
UUID=ghi-789 none swap sw 0 0
tmpfs /tmp tmpfs defaults,size=512m 0 0
*/
🎯 Interview Questions — Mounting and Unmounting
Q1. What is a mount point? What happens to files in a directory when a filesystem is mounted on it?
A mount point is a directory in the existing filesystem tree where a new filesystem is attached. Files that were in the mount point directory before mounting become temporarily hidden — only the new filesystem’s contents are visible. After unmounting, the original contents reappear. This is called mount stacking (since Linux 2.4).
Q2. What privilege is required to call mount()? Why?
CAP_SYS_ADMIN (effectively root). Mounting allows arbitrary filesystem code to run in kernel space and gives access to raw block devices, which could be used to bypass filesystem permissions. Unprivileged users can mount using FUSE or user-mountable entries in /etc/fstab.
Q3. What is the difference between MS_NOATIME and MS_RELATIME?
MS_NOATIME never updates the access timestamp (atime) — best performance. MS_RELATIME (default since Linux 2.6.30) updates atime only if it’s older than mtime or ctime, or older than 24 hours. MS_RELATIME gives most of the performance benefit while still letting programs detect recently-read files.
Q4. What is a lazy unmount (MNT_DETACH)?
With MNT_DETACH, the mount point is immediately marked so no new accesses are allowed, but processes that already have the filesystem open can continue using it. The filesystem is fully unmounted when all processes close their files. Useful for graceful migration off a busy filesystem without taking the system offline.
Q5. What is the difference between /proc/mounts, /etc/mtab, and /etc/fstab?
/proc/mounts is a kernel interface (always accurate, reflects real mount state). /etc/mtab is maintained by mount(8) commands and may be slightly more detailed but can become stale if mounts are done programmatically without updating it. /etc/fstab is manually edited by the admin and defines what should be mounted at boot; it’s not automatically updated by mounting/unmounting.
Q6. What does MS_REMOUNT do and when would you use it?
MS_REMOUNT changes the mount flags for an already-mounted filesystem without unmounting and remounting it. Use case: the root filesystem is mounted read-only by the kernel early in boot; init scripts use MS_REMOUNT to make it read-write. Another use: safely switching a filesystem read-only before maintenance without unmounting.
