static int do_umount(struct vfsmount *mnt, int flags) { struct super_block * sb = mnt->mnt_sb; int retval = 0; printk("do_umount\n"); /* * If we may have to abort operations to get out of this * mount, and they will themselves hold resources we must * allow the fs to do things. In the Unix tradition of * 'Gee thats tricky lets do it in userspace' the umount_begin * might fail to complete on the first run through as other tasks * must return, and the like. Thats for the mount program to worry * about for the moment. */ lock_kernel(); if( (flags&MNT_FORCE) && sb->s_op->umount_begin) sb->s_op->umount_begin(sb); unlock_kernel(); spin_lock(&dcache_lock); if (atomic_read(&sb->s_active) == 1) { /* last instance - try to be smart */ spin_unlock(&dcache_lock); lock_kernel(); DQUOT_OFF(sb); // acct_auto_close(sb->s_dev); unlock_kernel(); spin_lock(&dcache_lock); } retval = -EBUSY; if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) { // if (!list_empty(&mnt->mnt_list)) // umount_tree(mnt); __mntput(mnt); // free it --sadyc retval = 0; } spin_unlock(&dcache_lock); return retval; }
/* do_emergency_sync helper function */ static void go_sync(struct super_block *sb, int remount_flag) { int orig_loglevel; orig_loglevel = console_loglevel; console_loglevel = 7; printk(KERN_INFO "%sing device %s ... ", remount_flag ? "Remount" : "Sync", kdevname(sb->s_dev)); if (remount_flag) { /* Remount R/O */ int ret, flags; struct list_head *p; if (sb->s_flags & MS_RDONLY) { printk("R/O\n"); return; } file_list_lock(); for (p = sb->s_files.next; p != &sb->s_files; p = p->next) { struct file *file = list_entry(p, struct file, f_list); if (file->f_dentry && file_count(file) && S_ISREG(file->f_dentry->d_inode->i_mode)) file->f_mode &= ~2; } file_list_unlock(); DQUOT_OFF(sb); fsync_dev(sb->s_dev); flags = MS_RDONLY; if (sb->s_op && sb->s_op->remount_fs) { ret = sb->s_op->remount_fs(sb, &flags, NULL); if (ret) printk("error %d\n", ret); else { sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); printk("OK\n"); } } else printk("nothing to do\n"); } else { /* Sync only */
static void go_sync(kdev_t dev, int remount_flag) { printk(KERN_INFO "%sing device %s ... ", remount_flag ? "Remount" : "Sync", kdevname(dev)); if (remount_flag) { /* Remount R/O */ struct super_block *sb = get_super(dev); struct vfsmount *vfsmnt; int ret, flags; if (!sb) { printk("Superblock not found\n"); return; } if (sb->s_flags & MS_RDONLY) { printk("R/O\n"); return; } DQUOT_OFF(dev); fsync_dev(dev); flags = MS_RDONLY; if (sb->s_op && sb->s_op->remount_fs) { ret = sb->s_op->remount_fs(sb, &flags, NULL); if (ret) printk("error %d\n", ret); else { sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); if ((vfsmnt = lookup_vfsmnt(sb->s_dev))) vfsmnt->mnt_flags = sb->s_flags; printk("OK\n"); } } else printk("nothing to do\n"); } else { fsync_dev(dev); /* Sync only */ printk("OK\n"); } }
static int do_umount(kdev_t dev, int unmount_root, int flags) { struct super_block * sb; int retval; retval = -ENOENT; sb = get_super(dev); if (!sb || !sb->s_root) goto out; /* * Before checking whether the filesystem is still busy, * make sure the kernel doesn't hold any quota files open * on the device. If the umount fails, too bad -- there * are no quotas running any more. Just turn them on again. */ DQUOT_OFF(dev); acct_auto_close(dev); /* * If we may have to abort operations to get out of this * mount, and they will themselves hold resources we must * allow the fs to do things. In the Unix tradition of * 'Gee thats tricky lets do it in userspace' the umount_begin * might fail to complete on the first run through as other tasks * must return, and the like. Thats for the mount program to worry * about for the moment. */ if( (flags&MNT_FORCE) && sb->s_op->umount_begin) sb->s_op->umount_begin(sb); /* * Shrink dcache, then fsync. This guarantees that if the * filesystem is quiescent at this point, then (a) only the * root entry should be in use and (b) that root entry is * clean. */ shrink_dcache_sb(sb); fsync_dev(dev); if (dev==ROOT_DEV && !unmount_root) { /* * Special case for "unmounting" root ... * we just try to remount it readonly. */ retval = 0; if (!(sb->s_flags & MS_RDONLY)) retval = do_remount_sb(sb, MS_RDONLY, 0); return retval; } retval = d_umount(sb); if (retval) goto out; if (sb->s_op) { if (sb->s_op->write_super && sb->s_dirt) sb->s_op->write_super(sb); } lock_super(sb); if (sb->s_op) { if (sb->s_op->put_super) sb->s_op->put_super(sb); } /* Forget any remaining inodes */ if (invalidate_inodes(sb)) { printk("VFS: Busy inodes after unmount. " "Self-destruct in 5 seconds. Have a nice day...\n"); } sb->s_dev = 0; /* Free the superblock */ unlock_super(sb); remove_vfsmnt(dev); out: return retval; }