Module Name:    src
Committed By:   tls
Date:           Sun Feb 10 16:26:35 UTC 2013

Modified Files:
        src/sys/dev/raidframe [tls-maxphys]: rf_disks.c
        src/sys/kern [tls-maxphys]: subr_disk.c
        src/sys/sys [tls-maxphys]: disk.h mount.h
        src/sys/ufs/ffs [tls-maxphys]: ffs_vfsops.c
        src/sys/ufs/ufs [tls-maxphys]: ufs_bmap.c ufs_extern.h ufs_readwrite.c
            ufs_vfsops.c

Log Message:
Add an accessor -- ufs_maxphys() -- to check the maximum transfer size
for a given UFS mountpoint, and move the code from mount that finds
the underlying disk and resets the mountpoint max transfer size into a
utility function, ufs_update_maxphys().

Add a global serial number that counts disk property changes to which
filesystems are meant to accomodate themselves.  Make ufs_maxphys()
check it.  This is a sort of flag-polling interface that avoids callbacks
into the filesystem code, but will require freezing filesystems and
draining in-flight transactions before a decrease in size that is
mandatory (like attaching a disk with a smaller maximum transfer size
as a spare in a RAIDframe set), rather than "advisory", like finding
out set geometry from a RAID controller long after boot and deciding
a smaller transfer size would be optimal, can be signalled.  Still, the
"advisory" case is the common one so this is progress.

Make a bit of an example of RAIDframe by making it bump this new
serial number when disks are added to the subsystem.  I will attack
one of the hardware RAID drivers (probably arcmsr) next.


To generate a diff of this commit:
cvs rdiff -u -r1.83 -r1.83.2.1 src/sys/dev/raidframe/rf_disks.c
cvs rdiff -u -r1.100.18.2 -r1.100.18.3 src/sys/kern/subr_disk.c
cvs rdiff -u -r1.57.2.1 -r1.57.2.2 src/sys/sys/disk.h
cvs rdiff -u -r1.207.6.2 -r1.207.6.3 src/sys/sys/mount.h
cvs rdiff -u -r1.278.2.2 -r1.278.2.3 src/sys/ufs/ffs/ffs_vfsops.c
cvs rdiff -u -r1.49.14.1 -r1.49.14.2 src/sys/ufs/ufs/ufs_bmap.c
cvs rdiff -u -r1.72 -r1.72.2.1 src/sys/ufs/ufs/ufs_extern.h
cvs rdiff -u -r1.104.2.1 -r1.104.2.2 src/sys/ufs/ufs/ufs_readwrite.c
cvs rdiff -u -r1.51 -r1.51.2.1 src/sys/ufs/ufs/ufs_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/dev/raidframe/rf_disks.c
diff -u src/sys/dev/raidframe/rf_disks.c:1.83 src/sys/dev/raidframe/rf_disks.c:1.83.2.1
--- src/sys/dev/raidframe/rf_disks.c:1.83	Thu Jul 19 22:47:52 2012
+++ src/sys/dev/raidframe/rf_disks.c	Sun Feb 10 16:26:33 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: rf_disks.c,v 1.83 2012/07/19 22:47:52 pooka Exp $	*/
+/*	$NetBSD: rf_disks.c,v 1.83.2.1 2013/02/10 16:26:33 tls Exp $	*/
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -60,7 +60,7 @@
  ***************************************************************/
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rf_disks.c,v 1.83 2012/07/19 22:47:52 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rf_disks.c,v 1.83.2.1 2013/02/10 16:26:33 tls Exp $");
 
 #include <dev/raidframe/raidframevar.h>
 
@@ -80,6 +80,8 @@ __KERNEL_RCSID(0, "$NetBSD: rf_disks.c,v
 #include <sys/vnode.h>
 #include <sys/namei.h> /* for pathbuf */
 #include <sys/kauth.h>
+#include <sys/atomic.h>
+#include <sys/disk.h>
 
 static int rf_AllocDiskStructures(RF_Raid_t *, RF_Config_t *);
 static void rf_print_label_status( RF_Raid_t *, int, char *,
@@ -649,6 +651,15 @@ rf_ConfigureDisk(RF_Raid_t *raidPtr, cha
 		diskPtr->numBlocks = diskPtr->numBlocks *
 			rf_sizePercentage / 100;
 	}
+
+	/*
+	 * Tell the rest of the kernel to check whether anything's
+	 * maximum transfer size has changed -- like, for example,
+	 * a filesystem that might be mounted on a set where we're
+	 * adding a spare with a smaller maximum transfer size than
+	 * the original set members.
+	 */
+	atomic_inc_uint(&disk_serial);
 	return (0);
 }
 

Index: src/sys/kern/subr_disk.c
diff -u src/sys/kern/subr_disk.c:1.100.18.2 src/sys/kern/subr_disk.c:1.100.18.3
--- src/sys/kern/subr_disk.c:1.100.18.2	Sun Dec  2 05:46:40 2012
+++ src/sys/kern/subr_disk.c	Sun Feb 10 16:26:33 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_disk.c,v 1.100.18.2 2012/12/02 05:46:40 tls Exp $	*/
+/*	$NetBSD: subr_disk.c,v 1.100.18.3 2013/02/10 16:26:33 tls Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 1999, 2000, 2009 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_disk.c,v 1.100.18.2 2012/12/02 05:46:40 tls Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_disk.c,v 1.100.18.3 2013/02/10 16:26:33 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -80,6 +80,8 @@ __KERNEL_RCSID(0, "$NetBSD: subr_disk.c,
 #include <sys/sysctl.h>
 #include <lib/libkern/libkern.h>
 
+unsigned int	disk_serial;
+
 /*
  * Compute checksum for disk label.
  */

Index: src/sys/sys/disk.h
diff -u src/sys/sys/disk.h:1.57.2.1 src/sys/sys/disk.h:1.57.2.2
--- src/sys/sys/disk.h:1.57.2.1	Wed Sep 12 06:15:35 2012
+++ src/sys/sys/disk.h	Sun Feb 10 16:26:34 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: disk.h,v 1.57.2.1 2012/09/12 06:15:35 tls Exp $	*/
+/*	$NetBSD: disk.h,v 1.57.2.2 2013/02/10 16:26:34 tls Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 2004 The NetBSD Foundation, Inc.
@@ -509,7 +509,7 @@ struct disk_strategy {
 
 #ifdef _KERNEL
 extern	int disk_count;			/* number of disks in global disklist */
-
+extern	unsigned int disk_serial;	/* some disk's properties changed */
 struct proc;
 
 void	disk_attach(struct disk *);

Index: src/sys/sys/mount.h
diff -u src/sys/sys/mount.h:1.207.6.2 src/sys/sys/mount.h:1.207.6.3
--- src/sys/sys/mount.h:1.207.6.2	Tue Nov 20 03:02:51 2012
+++ src/sys/sys/mount.h	Sun Feb 10 16:26:34 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: mount.h,v 1.207.6.2 2012/11/20 03:02:51 tls Exp $	*/
+/*	$NetBSD: mount.h,v 1.207.6.3 2013/02/10 16:26:34 tls Exp $	*/
 
 /*
  * Copyright (c) 1989, 1991, 1993
@@ -122,6 +122,7 @@ struct mount {
 	int		mnt_iflag;		/* internal flags */
 	int		mnt_fs_bshift;		/* offset shift for lblkno */
 	int		mnt_dev_bshift;		/* shift for device sectors */
+	unsigned int	mnt_dev_serial;		/* when maxphys etc. updated */
 	uint32_t	mnt_maxphys;		/* largest xfer allowed */
 	struct statvfs	mnt_stat;		/* cache of filesystem stats */
 	specificdata_reference

Index: src/sys/ufs/ffs/ffs_vfsops.c
diff -u src/sys/ufs/ffs/ffs_vfsops.c:1.278.2.2 src/sys/ufs/ffs/ffs_vfsops.c:1.278.2.3
--- src/sys/ufs/ffs/ffs_vfsops.c:1.278.2.2	Tue Nov 20 03:02:53 2012
+++ src/sys/ufs/ffs/ffs_vfsops.c	Sun Feb 10 16:26:34 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: ffs_vfsops.c,v 1.278.2.2 2012/11/20 03:02:53 tls Exp $	*/
+/*	$NetBSD: ffs_vfsops.c,v 1.278.2.3 2013/02/10 16:26:34 tls Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.278.2.2 2012/11/20 03:02:53 tls Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.278.2.3 2013/02/10 16:26:34 tls Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_ffs.h"
@@ -881,7 +881,6 @@ ffs_mountfs(struct vnode *devvp, struct 
 	struct buf *bp;
 	struct fs *fs;
 	dev_t dev;
-	struct disk *diskp;
 	struct dkwedge_info dkw;
 	void *space;
 	daddr_t sblockloc, fsblockloc;
@@ -897,9 +896,6 @@ ffs_mountfs(struct vnode *devvp, struct 
 	int32_t fsbsize;
 
 	dev = devvp->v_rdev;
-	if ((diskp = disk_find_blk(dev)) == NULL) {
-		panic("no disk for device %d %d", major(dev), DISKUNIT(dev));
-	}
 
 	cred = l ? l->l_cred : NOCRED;
 
@@ -922,13 +918,6 @@ ffs_mountfs(struct vnode *devvp, struct 
 	if (error)
 		return error;
 
-	/*
-	 * Get the maximum I/O size for the underlying device.
-	 */
-	mp->mnt_maxphys = disk_maxphys(diskp);
-	aprint_debug("ffs_mount: disk %s maxphys %d\n",
-		     diskp->dk_name, mp->mnt_maxphys);
-
 	ump = kmem_zalloc(sizeof(*ump), KM_SLEEP);
 	mutex_init(&ump->um_lock, MUTEX_DEFAULT, IPL_NONE);
 	error = ffs_snapshot_init(ump);
@@ -1270,8 +1259,13 @@ ffs_mountfs(struct vnode *devvp, struct 
 	for (i = 0; i < MAXQUOTAS; i++)
 		ump->um_quotas[i] = NULLVP;
 	devvp->v_specmountpoint = mp;
+
+	/* Before we start WAPBL or touch any snapshots, adjust maxphys */
+	ufs_update_maxphys(mp);
+
 	if (ronly == 0 && fs->fs_snapinum[0] != 0)
 		ffs_snapshot_mount(mp);
+
 #ifdef WAPBL
 	if (!ronly) {
 		KDASSERT(fs->fs_ronly == 0);

Index: src/sys/ufs/ufs/ufs_bmap.c
diff -u src/sys/ufs/ufs/ufs_bmap.c:1.49.14.1 src/sys/ufs/ufs/ufs_bmap.c:1.49.14.2
--- src/sys/ufs/ufs/ufs_bmap.c:1.49.14.1	Tue Oct  9 21:53:03 2012
+++ src/sys/ufs/ufs/ufs_bmap.c	Sun Feb 10 16:26:34 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_bmap.c,v 1.49.14.1 2012/10/09 21:53:03 bouyer Exp $	*/
+/*	$NetBSD: ufs_bmap.c,v 1.49.14.2 2013/02/10 16:26:34 tls Exp $	*/
 
 /*
  * Copyright (c) 1989, 1991, 1993
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_bmap.c,v 1.49.14.1 2012/10/09 21:53:03 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_bmap.c,v 1.49.14.2 2013/02/10 16:26:34 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -143,7 +143,7 @@ ufs_bmaparray(struct vnode *vp, daddr_t 
 		 * don't create a block larger than the device can handle.
 		 */
 		*runp = 0;
-		maxrun = mp->mnt_maxphys / mp->mnt_stat.f_iosize - 1;
+		maxrun = ufs_maxphys(mp) / mp->mnt_stat.f_iosize - 1;
 	}
 
 	if (bn >= 0 && bn < NDADDR) {

Index: src/sys/ufs/ufs/ufs_extern.h
diff -u src/sys/ufs/ufs/ufs_extern.h:1.72 src/sys/ufs/ufs/ufs_extern.h:1.72.2.1
--- src/sys/ufs/ufs/ufs_extern.h:1.72	Wed May  9 00:21:18 2012
+++ src/sys/ufs/ufs/ufs_extern.h	Sun Feb 10 16:26:34 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_extern.h,v 1.72 2012/05/09 00:21:18 riastradh Exp $	*/
+/*	$NetBSD: ufs_extern.h,v 1.72.2.1 2013/02/10 16:26:34 tls Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993, 1994
@@ -35,6 +35,7 @@
 #define _UFS_UFS_EXTERN_H_
 
 #include <sys/mutex.h>
+#include <sys/disk.h>
 
 struct buf;
 struct componentname;
@@ -188,9 +189,20 @@ void	ufs_reinit(void);
 void	ufs_done(void);
 int	ufs_start(struct mount *, int);
 int	ufs_root(struct mount *, struct vnode **);
+void	ufs_update_maxphys(struct mount *);
 int	ufs_quotactl(struct mount *, struct quotactl_args *);
 int	ufs_fhtovp(struct mount *, struct ufid *, struct vnode **);
 
+static inline uint32_t
+ufs_maxphys(struct mount *mp)
+{
+	while (__predict_false(mp->mnt_dev_serial != disk_serial)) {
+		ufs_update_maxphys(mp);
+	}
+
+	return mp->mnt_maxphys;
+}
+
 /* ufs_vnops.c */
 void	ufs_vinit(struct mount *, int (**)(void *),
 		  int (**)(void *), struct vnode **);

Index: src/sys/ufs/ufs/ufs_readwrite.c
diff -u src/sys/ufs/ufs/ufs_readwrite.c:1.104.2.1 src/sys/ufs/ufs/ufs_readwrite.c:1.104.2.2
--- src/sys/ufs/ufs/ufs_readwrite.c:1.104.2.1	Sun Oct 14 14:33:32 2012
+++ src/sys/ufs/ufs/ufs_readwrite.c	Sun Feb 10 16:26:34 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_readwrite.c,v 1.104.2.1 2012/10/14 14:33:32 tls Exp $	*/
+/*	$NetBSD: ufs_readwrite.c,v 1.104.2.2 2013/02/10 16:26:34 tls Exp $	*/
 
 /*-
  * Copyright (c) 1993
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: ufs_readwrite.c,v 1.104.2.1 2012/10/14 14:33:32 tls Exp $");
+__KERNEL_RCSID(1, "$NetBSD: ufs_readwrite.c,v 1.104.2.2 2013/02/10 16:26:34 tls Exp $");
 
 #ifdef LFS_READWRITE
 #define	FS			struct lfs
@@ -415,7 +415,7 @@ WRITE(void *v)
 
 #ifndef LFS_READWRITE
 		{
-			int maximum = vp->v_mount->mnt_maxphys;
+			int maximum = ufs_maxphys(vp->v_mount);
 			off_t oldchunk, newchunk;
 
 			oldchunk = (oldoff / maximum) * maximum;

Index: src/sys/ufs/ufs/ufs_vfsops.c
diff -u src/sys/ufs/ufs/ufs_vfsops.c:1.51 src/sys/ufs/ufs/ufs_vfsops.c:1.51.2.1
--- src/sys/ufs/ufs/ufs_vfsops.c:1.51	Wed Apr  4 19:52:48 2012
+++ src/sys/ufs/ufs/ufs_vfsops.c	Sun Feb 10 16:26:34 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_vfsops.c,v 1.51 2012/04/04 19:52:48 tron Exp $	*/
+/*	$NetBSD: ufs_vfsops.c,v 1.51.2.1 2013/02/10 16:26:34 tls Exp $	*/
 
 /*
  * Copyright (c) 1991, 1993, 1994
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_vfsops.c,v 1.51 2012/04/04 19:52:48 tron Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_vfsops.c,v 1.51.2.1 2013/02/10 16:26:34 tls Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_ffs.h"
@@ -52,6 +52,8 @@ __KERNEL_RCSID(0, "$NetBSD: ufs_vfsops.c
 #include <sys/vnode.h>
 #include <sys/kmem.h>
 #include <sys/kauth.h>
+#include <sys/disk.h>
+#include <sys/disklabel.h>
 
 #include <miscfs/specfs/specdev.h>
 
@@ -97,6 +99,36 @@ ufs_root(struct mount *mp, struct vnode 
 }
 
 /*
+ * Get (from disk) and set (to mount structure) maximum I/O size
+ */
+
+void
+ufs_update_maxphys(struct mount *mp)
+{
+	struct ufsmount *ump;
+	dev_t dev;
+	struct disk *diskp;
+
+	ump = VFSTOUFS(mp);
+	dev = ump->um_dev;
+
+	mutex_enter(&mp->mnt_updating);
+
+	if ((diskp = disk_find_blk(dev)) == NULL) {
+		panic("no disk for device %d %d", major(dev), DISKUNIT(dev));
+	}
+
+	/*
+	 * Get the maximum I/O size for the underlying device.
+	 */
+	mp->mnt_dev_serial = disk_serial;
+	mp->mnt_maxphys = disk_maxphys(diskp);
+	aprint_debug("ufs_update_maxphys: disk %s maxphys %d\n",
+		     diskp->dk_name, mp->mnt_maxphys);
+	mutex_exit(&mp->mnt_updating);
+}
+
+/*
  * Do operations associated with quotas
  */
 int

Reply via email to