Skip site navigation (1)Skip section navigation (2)
Date:      22 Jan 2003 16:37:53 EST
From:      David Bein <bein@world.std.com>
To:        freebsd-current@freebsd.org
Subject:   5.0 ufs read-only mount bug
Message-ID:  <1043271473/bein@world.std.com>

next in thread | raw e-mail | index | archive | help
Hi ...

  I have recently been upgrading to 5.0 [now on RELEASE!] and
I have one patch I've been applying which solves a problem
introduced by a change in ffs_mountfs() where a read-only
mount request insists on opening the device in R/W mode.
This is fine for the reasons it was done, but it means
you can't mount -o ro a ufs filesystem which is on a
read-only medium [e.g. a network disk replica or perhaps
a ufs filesystem on a CDROM]. Enclosed are suggested patches
which preserve the intent of the changes as of 5.0, but
allow a read-only mount on a read-only device to work as
well. If a mount is done with this, then mount -u -o rw is
not allowed. Needless to say, if you really want to mount
it for writing, you need to copy the image to a writable
medium. Enclosed are diffs [relative to 5.0-RELEASE].

--David

# diff -c ufs/ufs/ufsmount.h.orig ufs/ufs/ufsmount.h
*** ufs/ufs/ufsmount.h.orig	Sun Dec 29 09:54:20 2002
--- ufs/ufs/ufsmount.h	Wed Jan 15 12:10:43 2003
***************
*** 84,90 ****
--- 84,93 ----
  	int	(*um_valloc)(struct vnode *, int, struct ucred *, struct vnode **);
  	int	(*um_vfree)(struct vnode *, ino_t, int);
  	void	(*um_ifree)(struct ufsmount *, struct inode *);
+ 	int	um_fmode;	/* FREAD or FREAD|FWRITE */
  };
+ 
+ #define __UFSMOUNT_FMODE__
  
  #define UFS_BALLOC(aa, bb, cc, dd, ee, ff) VFSTOUFS((aa)->v_mount)->um_balloc(aa, bb, cc, dd, ee, ff)
  #define UFS_BLKATOFF(aa, bb, cc, dd) VFSTOUFS((aa)->v_mount)->um_blkatoff(aa, bb, cc, dd)

# diff -c ufs/ffs/ffs_vfsops.c.orig ufs/ffs/ffs_vfsops.c
*** ufs/ffs/ffs_vfsops.c.orig	Sun Dec 29 09:54:19 2002
--- ufs/ffs/ffs_vfsops.c	Wed Jan 15 12:14:33 2003
***************
*** 244,249 ****
--- 244,256 ----
  		    (error = ffs_reload(mp, ndp->ni_cnd.cn_cred, td)) != 0)
  			return (error);
  		if (fs->fs_ronly && (mp->mnt_kern_flag & MNTK_WANTRDWR)) {
+ #if defined(__UFSMOUNT_FMODE__)
+ 			/*
+ 			 * Disallow this if devvp is read-only ...
+ 			 */
+ 			if (ump->um_fmode != (FREAD|FWRITE))
+ 				return(EROFS);
+ #endif	/* defined(__UFSMOUNT_FMODE__) */
  			/*
  			 * If upgrade to read-write by non-root, then verify
  			 * that user has necessary permissions on the device.
***************
*** 569,574 ****
--- 576,584 ----
  	struct ucred *cred;
  	size_t strsize;
  	int ncount;
+ #if defined(__UFSMOUNT_FMODE__)
+ 	int um_fmode = 0;
+ #endif	/* defined(__UFSMOUNT_FMODE__) */
  
  	dev = devvp->v_rdev;
  	cred = td ? td->td_ucred : NOCRED;
***************
*** 607,612 ****
--- 617,638 ----
  
  	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
  	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
+ #if defined(__UFSMOUNT_FMODE__)
+ 	/*
+ 	 * Try to open R/W, but if that fails, try just for read
+ 	 * but only if this is a read-only mount. We remember how
+ 	 * we did this so that we can disallow upgrades to R/W
+ 	 * if ump->um_fmode == FREAD.
+ 	 */
+ 	um_fmode = FREAD|FWRITE;
+ again:
+ 	if ((error = VOP_OPEN(devvp, um_fmode, FSCRED, td)) != 0) {
+ 		if ((um_fmode != FREAD) && (ronly != 0)) {
+ 			um_fmode = FREAD;
+ 			goto again;
+ 		}
+ 	}
+ #else	/* !defined(__UFSMOUNT_FMODE__) */
  	/*
  	 * XXX: We don't re-VOP_OPEN in FREAD|FWRITE mode if the filesystem
  	 * XXX: is subsequently remounted, so open it FREAD|FWRITE from the
***************
*** 617,622 ****
--- 643,649 ----
  #else
  	error = VOP_OPEN(devvp, FREAD|FWRITE, FSCRED, td);
  #endif
+ #endif	/* !defined(__UFSMOUNT_FMODE__) */
  	VOP_UNLOCK(devvp, 0, td);
  	if (error)
  		return (error);
***************
*** 687,692 ****
--- 714,722 ----
  		fs->fs_pendinginodes = 0;
  	}
  	ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK | M_ZERO);
+ #if defined(__UFSMOUNT_FMODE__)
+ 	ump->um_fmode = um_fmode;
+ #endif	/* defined(__UFSMOUNT_FMODE__) */
  	ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
  	    M_WAITOK);
  	if (fs->fs_magic == FS_UFS1_MAGIC) {
***************
*** 829,839 ****
--- 859,873 ----
  	if (bp)
  		brelse(bp);
  	/* XXX: see comment above VOP_OPEN */
+ #if defined(__UFSMOUNT_FMODE__)
+ 	(void)VOP_CLOSE(devvp, um_fmode, cred, td);
+ #else	/* !defined(__UFSMOUNT_FMODE__) */
  #ifdef notyet
  	(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, td);
  #else
  	(void)VOP_CLOSE(devvp, FREAD|FWRITE, cred, td);
  #endif
+ #endif	/* !defined(__UFSMOUNT_FMODE__) */
  	if (ump) {
  		free(ump->um_fs, M_UFSMNT);
  		free(ump, M_UFSMNT);
***************
*** 988,993 ****
--- 1022,1030 ----
  	ump->um_devvp->v_rdev->si_mountpoint = NULL;
  
  	vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, td, 0, 0);
+ #if defined(__UFSMOUNT_FMODE__)
+ 	error = VOP_CLOSE(ump->um_devvp, ump->um_fmode, NOCRED, td);
+ #else	/* !defined(__UFSMOUNT_FMODE__) */
  	/* XXX: see comment above VOP_OPEN */
  #ifdef notyet
  	error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
***************
*** 995,1000 ****
--- 1032,1038 ----
  #else
  	error = VOP_CLOSE(ump->um_devvp, FREAD|FWRITE, NOCRED, td);
  #endif
+ #endif	/* !defined(__UFSMOUNT_FMODE__) */
  
  	vrele(ump->um_devvp);
  

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1043271473/bein>