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>
