* Request a filesystem to suspend write operations. */
| 1993 | * Request a filesystem to suspend write operations. |
| 1994 | */ |
| 1995 | int |
| 1996 | vfs_write_suspend(struct mount *mp, int flags) |
| 1997 | { |
| 1998 | int error; |
| 1999 | |
| 2000 | vfs_op_enter(mp); |
| 2001 | |
| 2002 | MNT_ILOCK(mp); |
| 2003 | vfs_assert_mount_counters(mp); |
| 2004 | if (mp->mnt_susp_owner == curthread) { |
| 2005 | vfs_op_exit_locked(mp); |
| 2006 | MNT_IUNLOCK(mp); |
| 2007 | return (EALREADY); |
| 2008 | } |
| 2009 | while (mp->mnt_kern_flag & MNTK_SUSPEND) |
| 2010 | msleep(&mp->mnt_flag, MNT_MTX(mp), PUSER - 1, "wsuspfs", 0); |
| 2011 | |
| 2012 | /* |
| 2013 | * Unmount holds a write reference on the mount point. If we |
| 2014 | * own busy reference and drain for writers, we deadlock with |
| 2015 | * the reference draining in the unmount path. Callers of |
| 2016 | * vfs_write_suspend() must specify VS_SKIP_UNMOUNT if |
| 2017 | * vfs_busy() reference is owned and caller is not in the |
| 2018 | * unmount context. |
| 2019 | */ |
| 2020 | if ((flags & VS_SKIP_UNMOUNT) != 0 && |
| 2021 | (mp->mnt_kern_flag & MNTK_UNMOUNT) != 0) { |
| 2022 | vfs_op_exit_locked(mp); |
| 2023 | MNT_IUNLOCK(mp); |
| 2024 | return (EBUSY); |
| 2025 | } |
| 2026 | |
| 2027 | mp->mnt_kern_flag |= MNTK_SUSPEND; |
| 2028 | mp->mnt_susp_owner = curthread; |
| 2029 | if (mp->mnt_writeopcount > 0) |
| 2030 | (void) msleep(&mp->mnt_writeopcount, |
| 2031 | MNT_MTX(mp), (PUSER - 1)|PDROP, "suspwt", 0); |
| 2032 | else |
| 2033 | MNT_IUNLOCK(mp); |
| 2034 | if ((error = VFS_SYNC(mp, MNT_SUSPEND)) != 0) { |
| 2035 | vfs_write_resume(mp, 0); |
| 2036 | /* vfs_write_resume does vfs_op_exit() for us */ |
| 2037 | } |
| 2038 | return (error); |
| 2039 | } |
| 2040 | |
| 2041 | /* |
| 2042 | * Request a filesystem to resume write operations. |
no test coverage detected