Module Name:    src
Committed By:   riastradh
Date:           Sun Feb 23 08:39:19 UTC 2020

Modified Files:
        src/sys/ufs/lfs: lfs_vfsops.c

Log Message:
Teach lfs to transition ro<->rw.


To generate a diff of this commit:
cvs rdiff -u -r1.370 -r1.371 src/sys/ufs/lfs/lfs_vfsops.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/ufs/lfs/lfs_vfsops.c
diff -u src/sys/ufs/lfs/lfs_vfsops.c:1.370 src/sys/ufs/lfs/lfs_vfsops.c:1.371
--- src/sys/ufs/lfs/lfs_vfsops.c:1.370	Tue Feb 18 20:23:17 2020
+++ src/sys/ufs/lfs/lfs_vfsops.c	Sun Feb 23 08:39:18 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: lfs_vfsops.c,v 1.370 2020/02/18 20:23:17 chs Exp $	*/
+/*	$NetBSD: lfs_vfsops.c,v 1.371 2020/02/23 08:39:18 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2007, 2007
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c,v 1.370 2020/02/18 20:23:17 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c,v 1.371 2020/02/23 08:39:18 riastradh Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_lfs.h"
@@ -120,6 +120,7 @@ MODULE(MODULE_CLASS_VFS, lfs, NULL);
 
 static int lfs_gop_write(struct vnode *, struct vm_page **, int, int);
 static int lfs_mountfs(struct vnode *, struct mount *, struct lwp *);
+static int lfs_flushfiles(struct mount *, int);
 
 static struct sysctllog *lfs_sysctl_log;
 
@@ -755,23 +756,18 @@ lfs_mount(struct mount *mp, const char *
 		ump = VFSTOULFS(mp);
 		fs = ump->um_lfs;
 
-		if (fs->lfs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
+		if (!fs->lfs_ronly && (mp->mnt_iflag & IMNT_WANTRDONLY)) {
 			/*
 			 * Changing from read/write to read-only.
-			 * XXX: shouldn't we sync here? or does vfs do that?
 			 */
-#ifdef LFS_QUOTA2
-			/* XXX: quotas should remain on when readonly */
-			if (fs->lfs_use_quota2) {
-				error = lfsquota2_umount(mp, 0);
-				if (error) {
-					return error;
-				}
-			}
-#endif
-		}
-
-		if (fs->lfs_ronly && (mp->mnt_iflag & IMNT_WANTRDWR)) {
+			int flags = WRITECLOSE;
+			if (mp->mnt_flag & MNT_FORCE)
+				flags |= FORCECLOSE;
+			error = lfs_flushfiles(mp, flags);
+			if (error)
+				return error;
+			fs->lfs_ronly = 1;
+		} else if (fs->lfs_ronly && (mp->mnt_iflag & IMNT_WANTRDWR)) {
 			/*
 			 * Changing from read-only to read/write.
 			 * Note in the superblocks that we're writing.
@@ -805,8 +801,9 @@ lfs_mount(struct mount *mp, const char *
 				lfs_writesuper(fs, lfs_sb_getsboff(fs, 1));
 			}
 		}
+
 		if (args->fspec == NULL)
-			return EINVAL;
+			return 0;
 	}
 
 	error = set_statvfs_info(path, UIO_USERSPACE, args->fspec,
@@ -1137,6 +1134,7 @@ lfs_mountfs(struct vnode *devvp, struct 
 	mp->mnt_stat.f_iosize = lfs_sb_getbsize(fs);
 	mp->mnt_flag |= MNT_LOCAL;
 	mp->mnt_fs_bshift = lfs_sb_getbshift(fs);
+	mp->mnt_iflag |= IMNT_CAN_RWTORO;
 	if (fs->um_maxsymlinklen > 0)
 		mp->mnt_iflag |= IMNT_DTYPE;
 	else
@@ -1328,22 +1326,72 @@ out:
 int
 lfs_unmount(struct mount *mp, int mntflags)
 {
-	struct lwp *l = curlwp;
 	struct ulfsmount *ump;
 	struct lfs *fs;
-	int error, flags, ronly;
-	vnode_t *vp;
+	int error, ronly;
+
+	ump = VFSTOULFS(mp);
+	fs = ump->um_lfs;
 
-	flags = 0;
-	if (mntflags & MNT_FORCE)
-		flags |= FORCECLOSE;
+	error = lfs_flushfiles(mp, mntflags & MNT_FORCE ? FORCECLOSE : 0);
+	if (error)
+		return error;
+
+	/* Finish with the Ifile, now that we're done with it */
+	vgone(fs->lfs_ivnode);
+
+	ronly = !fs->lfs_ronly;
+	if (fs->lfs_devvp->v_type != VBAD)
+		spec_node_setmountedfs(fs->lfs_devvp, NULL);
+	vn_lock(fs->lfs_devvp, LK_EXCLUSIVE | LK_RETRY);
+	error = VOP_CLOSE(fs->lfs_devvp,
+	    ronly ? FREAD : FREAD|FWRITE, NOCRED);
+	vput(fs->lfs_devvp);
+
+	/* Complain about page leakage */
+	if (fs->lfs_pages > 0)
+		printf("lfs_unmount: still claim %d pages (%d in subsystem)\n",
+			fs->lfs_pages, lfs_subsys_pages);
+
+	/* Free per-mount data structures */
+	free(fs->lfs_ino_bitmap, M_SEGMENT);
+	free(fs->lfs_suflags[0], M_SEGMENT);
+	free(fs->lfs_suflags[1], M_SEGMENT);
+	free(fs->lfs_suflags, M_SEGMENT);
+	lfs_free_resblks(fs);
+	cv_destroy(&fs->lfs_sleeperscv);
+	cv_destroy(&fs->lfs_diropscv);
+	cv_destroy(&fs->lfs_stopcv);
+	cv_destroy(&fs->lfs_nextsegsleep);
+
+	rw_destroy(&fs->lfs_fraglock);
+	rw_destroy(&fs->lfs_iflock);
+
+	kmem_free(fs, sizeof(struct lfs));
+	kmem_free(ump, sizeof(*ump));
+
+	mp->mnt_data = NULL;
+	mp->mnt_flag &= ~MNT_LOCAL;
+	return (error);
+}
+
+static int
+lfs_flushfiles(struct mount *mp, int flags)
+{
+	struct lwp *l = curlwp;
+	struct ulfsmount *ump;
+	struct lfs *fs;
+	struct vnode *vp;
+	int error;
 
 	ump = VFSTOULFS(mp);
 	fs = ump->um_lfs;
 
 	/* Two checkpoints */
-	lfs_segwrite(mp, SEGM_CKP | SEGM_SYNC);
-	lfs_segwrite(mp, SEGM_CKP | SEGM_SYNC);
+	if (!fs->lfs_ronly) {
+		lfs_segwrite(mp, SEGM_CKP | SEGM_SYNC);
+		lfs_segwrite(mp, SEGM_CKP | SEGM_SYNC);
+	}
 
 	/* wake up the cleaner so it can die */
 	/* XXX: shouldn't this be *after* the error cases below? */
@@ -1383,51 +1431,18 @@ lfs_unmount(struct mount *mp, int mntfla
 	mutex_exit(vp->v_interlock);
 
 	/* Explicitly write the superblock, to update serial and pflags */
-	lfs_sb_setpflags(fs, lfs_sb_getpflags(fs) | LFS_PF_CLEAN);
-	lfs_writesuper(fs, lfs_sb_getsboff(fs, 0));
-	lfs_writesuper(fs, lfs_sb_getsboff(fs, 1));
+	if (!fs->lfs_ronly) {
+		lfs_sb_setpflags(fs, lfs_sb_getpflags(fs) | LFS_PF_CLEAN);
+		lfs_writesuper(fs, lfs_sb_getsboff(fs, 0));
+		lfs_writesuper(fs, lfs_sb_getsboff(fs, 1));
+	}
 	mutex_enter(&lfs_lock);
 	while (fs->lfs_iocount)
 		mtsleep(&fs->lfs_iocount, PRIBIO + 1, "lfs_umount", 0,
 			&lfs_lock);
 	mutex_exit(&lfs_lock);
 
-	/* Finish with the Ifile, now that we're done with it */
-	vgone(fs->lfs_ivnode);
-
-	ronly = !fs->lfs_ronly;
-	if (fs->lfs_devvp->v_type != VBAD)
-		spec_node_setmountedfs(fs->lfs_devvp, NULL);
-	vn_lock(fs->lfs_devvp, LK_EXCLUSIVE | LK_RETRY);
-	error = VOP_CLOSE(fs->lfs_devvp,
-	    ronly ? FREAD : FREAD|FWRITE, NOCRED);
-	vput(fs->lfs_devvp);
-
-	/* Complain about page leakage */
-	if (fs->lfs_pages > 0)
-		printf("lfs_unmount: still claim %d pages (%d in subsystem)\n",
-			fs->lfs_pages, lfs_subsys_pages);
-
-	/* Free per-mount data structures */
-	free(fs->lfs_ino_bitmap, M_SEGMENT);
-	free(fs->lfs_suflags[0], M_SEGMENT);
-	free(fs->lfs_suflags[1], M_SEGMENT);
-	free(fs->lfs_suflags, M_SEGMENT);
-	lfs_free_resblks(fs);
-	cv_destroy(&fs->lfs_sleeperscv);
-	cv_destroy(&fs->lfs_diropscv);
-	cv_destroy(&fs->lfs_stopcv);
-	cv_destroy(&fs->lfs_nextsegsleep);
-
-	rw_destroy(&fs->lfs_fraglock);
-	rw_destroy(&fs->lfs_iflock);
-
-	kmem_free(fs, sizeof(struct lfs));
-	kmem_free(ump, sizeof(*ump));
-
-	mp->mnt_data = NULL;
-	mp->mnt_flag &= ~MNT_LOCAL;
-	return (error);
+	return 0;
 }
 
 /*

Reply via email to