* Secondary suspension. Used by operations such as vop_inactive * routines that are needed by the higher level functions. These * are allowed to proceed until all the higher level functions have * completed (indicated by mnt_writeopcount dropping to zero). At that * time, these operations are halted until the suspension is over. */
| 1874 | * time, these operations are halted until the suspension is over. |
| 1875 | */ |
| 1876 | int |
| 1877 | vn_start_secondary_write(struct vnode *vp, struct mount **mpp, int flags) |
| 1878 | { |
| 1879 | struct mount *mp; |
| 1880 | int error; |
| 1881 | |
| 1882 | KASSERT((flags & V_MNTREF) == 0 || (*mpp != NULL && vp == NULL), |
| 1883 | ("V_MNTREF requires mp")); |
| 1884 | |
| 1885 | retry: |
| 1886 | if (vp != NULL) { |
| 1887 | if ((error = VOP_GETWRITEMOUNT(vp, mpp)) != 0) { |
| 1888 | *mpp = NULL; |
| 1889 | if (error != EOPNOTSUPP) |
| 1890 | return (error); |
| 1891 | return (0); |
| 1892 | } |
| 1893 | } |
| 1894 | /* |
| 1895 | * If we are not suspended or have not yet reached suspended |
| 1896 | * mode, then let the operation proceed. |
| 1897 | */ |
| 1898 | if ((mp = *mpp) == NULL) |
| 1899 | return (0); |
| 1900 | |
| 1901 | /* |
| 1902 | * VOP_GETWRITEMOUNT() returns with the mp refcount held through |
| 1903 | * a vfs_ref(). |
| 1904 | * As long as a vnode is not provided we need to acquire a |
| 1905 | * refcount for the provided mountpoint too, in order to |
| 1906 | * emulate a vfs_ref(). |
| 1907 | */ |
| 1908 | MNT_ILOCK(mp); |
| 1909 | if (vp == NULL && (flags & V_MNTREF) == 0) |
| 1910 | MNT_REF(mp); |
| 1911 | if ((mp->mnt_kern_flag & (MNTK_SUSPENDED | MNTK_SUSPEND2)) == 0) { |
| 1912 | mp->mnt_secondary_writes++; |
| 1913 | mp->mnt_secondary_accwrites++; |
| 1914 | MNT_IUNLOCK(mp); |
| 1915 | return (0); |
| 1916 | } |
| 1917 | if (flags & V_NOWAIT) { |
| 1918 | MNT_REL(mp); |
| 1919 | MNT_IUNLOCK(mp); |
| 1920 | return (EWOULDBLOCK); |
| 1921 | } |
| 1922 | /* |
| 1923 | * Wait for the suspension to finish. |
| 1924 | */ |
| 1925 | error = msleep(&mp->mnt_flag, MNT_MTX(mp), (PUSER - 1) | PDROP | |
| 1926 | ((mp->mnt_vfc->vfc_flags & VFCF_SBDRY) != 0 ? (flags & PCATCH) : 0), |
| 1927 | "suspfs", 0); |
| 1928 | vfs_rel(mp); |
| 1929 | if (error == 0) |
| 1930 | goto retry; |
| 1931 | return (error); |
| 1932 | } |
| 1933 |