From owner-freebsd-current Wed Jan 22 13:40:15 2003 Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1191137B401 for ; Wed, 22 Jan 2003 13:40:11 -0800 (PST) Received: from TheWorld.com (pcls4.std.com [199.172.62.106]) by mx1.FreeBSD.org (Postfix) with ESMTP id 582DC43E4A for ; Wed, 22 Jan 2003 13:40:06 -0800 (PST) (envelope-from bein@world.std.com) Received: from world.std.com (hannigan@world-f.std.com [199.172.62.5]) by TheWorld.com (8.9.3/8.9.3) with ESMTP id QAA18440; Wed, 22 Jan 2003 16:40:04 -0500 Received: (from bein@localhost) by world.std.com (8.9.3/8.9.3) id QAA03217; Wed, 22 Jan 2003 16:39:46 -0500 (EST) Date: 22 Jan 2003 16:37:53 EST From: David Bein Subject: 5.0 ufs read-only mount bug To: freebsd-current@freebsd.org Message-Id: <1043271473/bein@world.std.com> Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG 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