summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authoreschrock <none@none>2006-04-08 23:33:38 -0700
committereschrock <none@none>2006-04-08 23:33:38 -0700
commitb468a217b67dc26ce21da5d5a2ca09bb6249e4fa (patch)
tree71b6bb81b469d8127e12b97549cb177aa5deac3e /usr/src
parent25cf1a301a396c38e8adf52c15f537b80d2483f7 (diff)
downloadillumos-gate-b468a217b67dc26ce21da5d5a2ca09bb6249e4fa.tar.gz
6407791 bringover into ZFS results in s. files newer than extracted source
6409927 failed DKIOCFLUSHWRITECACHE ioctls should not generate ereports 6410371 need to reserve more pool names
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/lib/libzfs/common/libzfs_pool.c28
-rw-r--r--usr/src/uts/common/fs/zfs/sys/vdev_impl.h1
-rw-r--r--usr/src/uts/common/fs/zfs/vdev_disk.c20
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_fm.c8
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_vnops.c37
5 files changed, 88 insertions, 6 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs_pool.c b/usr/src/lib/libzfs/common/libzfs_pool.c
index 2889725027..1fe6fa2d27 100644
--- a/usr/src/lib/libzfs/common/libzfs_pool.c
+++ b/usr/src/lib/libzfs/common/libzfs_pool.c
@@ -46,12 +46,30 @@
* 'buf'.
*/
static int
-zpool_name_valid(const char *pool, char *buf, size_t buflen)
+zpool_name_valid(const char *pool, boolean_t isopen, char *buf, size_t buflen)
{
namecheck_err_t why;
char what;
+ int ret;
+
+ ret = pool_namecheck(pool, &why, &what);
+
+ /*
+ * The rules for reserved pool names were extended at a later point.
+ * But we need to support users with existing pools that may now be
+ * invalid. So we only check for this expanded set of names during a
+ * create (or import), and only in userland.
+ */
+ if (ret == 0 && !isopen &&
+ (strncmp(pool, "mirror", 6) == 0 ||
+ strncmp(pool, "raidz", 5) == 0 ||
+ strncmp(pool, "spare", 5) == 0)) {
+ ret = -1;
+ why = NAME_ERR_RESERVED;
+ }
+
- if (pool_namecheck(pool, &why, &what) != 0) {
+ if (ret != 0) {
if (buf != NULL) {
switch (why) {
case NAME_ERR_TOOLONG:
@@ -142,7 +160,7 @@ zpool_open_canfail(const char *pool)
/*
* Make sure the pool name is valid.
*/
- if (!zpool_name_valid(pool, NULL, 0)) {
+ if (!zpool_name_valid(pool, B_TRUE, NULL, 0)) {
zfs_error(dgettext(TEXT_DOMAIN, "cannot open '%s': invalid "
"pool name"), pool);
return (NULL);
@@ -338,7 +356,7 @@ zpool_create(const char *pool, nvlist_t *nvroot, const char *altroot)
int err;
char reason[64];
- if (!zpool_name_valid(pool, reason, sizeof (reason))) {
+ if (!zpool_name_valid(pool, B_FALSE, reason, sizeof (reason))) {
zfs_error(dgettext(TEXT_DOMAIN, "cannot create '%s': %s"),
pool, reason);
return (-1);
@@ -688,7 +706,7 @@ zpool_import(nvlist_t *config, const char *newname, const char *altroot)
&origname) == 0);
if (newname != NULL) {
- if (!zpool_name_valid(newname, NULL, 0)) {
+ if (!zpool_name_valid(newname, B_FALSE, NULL, 0)) {
zfs_error(dgettext(TEXT_DOMAIN, "cannot import '%s': "
"invalid pool name"), newname);
return (-1);
diff --git a/usr/src/uts/common/fs/zfs/sys/vdev_impl.h b/usr/src/uts/common/fs/zfs/sys/vdev_impl.h
index 8c094fba12..9ea2ca5373 100644
--- a/usr/src/uts/common/fs/zfs/sys/vdev_impl.h
+++ b/usr/src/uts/common/fs/zfs/sys/vdev_impl.h
@@ -173,6 +173,7 @@ struct vdev {
vdev_cache_t vdev_cache; /* physical block cache */
uint64_t vdev_not_present; /* not present during import */
hrtime_t vdev_last_try; /* last reopen time */
+ boolean_t vdev_nowritecache; /* true if flushwritecache failed */
/*
* For DTrace to work in userland (libzpool) context, these fields must
diff --git a/usr/src/uts/common/fs/zfs/vdev_disk.c b/usr/src/uts/common/fs/zfs/vdev_disk.c
index 0b4c2c9696..2c50ba3837 100644
--- a/usr/src/uts/common/fs/zfs/vdev_disk.c
+++ b/usr/src/uts/common/fs/zfs/vdev_disk.c
@@ -174,6 +174,12 @@ vdev_disk_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift)
*ashift = highbit(MAX(dkm.dki_lbsize, SPA_MINBLOCKSIZE)) - 1;
+ /*
+ * Clear the nowritecache bit, so that on a vdev_reopen() we will
+ * try again.
+ */
+ vd->vdev_nowritecache = B_FALSE;
+
return (0);
}
@@ -249,6 +255,11 @@ vdev_disk_io_start(zio_t *zio)
case DKIOCFLUSHWRITECACHE:
+ if (vd->vdev_nowritecache) {
+ zio->io_error = ENOTSUP;
+ break;
+ }
+
zio->io_dk_callback.dkc_callback = vdev_disk_ioctl_done;
zio->io_dk_callback.dkc_cookie = zio;
@@ -263,8 +274,17 @@ vdev_disk_io_start(zio_t *zio)
* upon completion.
*/
return;
+ } else if (error == ENOTSUP) {
+ /*
+ * If we get ENOTSUP, we know that no future
+ * attempts will ever succeed. In this case we
+ * set a persistent bit so that we don't bother
+ * with the ioctl in the future.
+ */
+ vd->vdev_nowritecache = B_TRUE;
}
zio->io_error = error;
+
break;
default:
diff --git a/usr/src/uts/common/fs/zfs/zfs_fm.c b/usr/src/uts/common/fs/zfs/zfs_fm.c
index 007445c713..f0fdb8f6ea 100644
--- a/usr/src/uts/common/fs/zfs/zfs_fm.c
+++ b/usr/src/uts/common/fs/zfs/zfs_fm.c
@@ -122,6 +122,14 @@ zfs_ereport_post(const char *subclass, spa_t *spa, vdev_t *vd, zio_t *zio,
if (zio && zio_should_retry(zio))
return;
+ /*
+ * If this is not a read or write zio, ignore the error. This can occur
+ * if the DKIOCFLUSHWRITECACHE ioctl fails.
+ */
+ if (zio && zio->io_type != ZIO_TYPE_READ &&
+ zio->io_type != ZIO_TYPE_WRITE)
+ return;
+
if ((ereport = fm_nvlist_create(NULL)) == NULL)
return;
diff --git a/usr/src/uts/common/fs/zfs/zfs_vnops.c b/usr/src/uts/common/fs/zfs/zfs_vnops.c
index 76e2069e63..67e886cac2 100644
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c
@@ -1815,13 +1815,22 @@ update:
return (error);
}
-/* ARGSUSED */
static int
zfs_fsync(vnode_t *vp, int syncflag, cred_t *cr)
{
znode_t *zp = VTOZ(vp);
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+ /*
+ * Regardless of whether this is required for standards conformance,
+ * this is the logical behavior when fsync() is called on a file with
+ * dirty pages. We use B_ASYNC since the ZIL transactions are already
+ * going to be pushed out as part of the zil_commit().
+ */
+ if (vn_has_cached_data(vp) && !(syncflag & FNODSYNC) &&
+ (vp->v_type == VREG) && !(IS_SWAPVP(vp)))
+ (void) VOP_PUTPAGE(vp, (offset_t)0, (size_t)0, B_ASYNC, cr);
+
ZFS_ENTER(zfsvfs);
zil_commit(zfsvfs->z_log, zp->z_last_itx, FSYNC);
ZFS_EXIT(zfsvfs);
@@ -3358,6 +3367,27 @@ zfs_addmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
return (0);
}
+/*
+ * The reason we push dirty pages as part of zfs_delmap() is so that we get a
+ * more accurate mtime for the associated file. Since we don't have a way of
+ * detecting when the data was actually modified, we have to resort to
+ * heuristics. If an explicit msync() is done, then we mark the mtime when the
+ * last page is pushed. The problem occurs when the msync() call is omitted,
+ * which by far the most common case:
+ *
+ * open()
+ * mmap()
+ * <modify memory>
+ * munmap()
+ * close()
+ * <time lapse>
+ * putpage() via fsflush
+ *
+ * If we wait until fsflush to come along, we can have a modification time that
+ * is some arbitrary point in the future. In order to prevent this in the
+ * common case, we flush pages whenever a (MAP_SHARED, PROT_WRITE) mapping is
+ * torn down.
+ */
/* ARGSUSED */
static int
zfs_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
@@ -3367,6 +3397,11 @@ zfs_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
ASSERT3U(VTOZ(vp)->z_mapcnt, >=, pages);
atomic_add_64(&VTOZ(vp)->z_mapcnt, -pages);
+
+ if ((flags & MAP_SHARED) && (prot & PROT_WRITE) &&
+ vn_has_cached_data(vp))
+ (void) VOP_PUTPAGE(vp, off, len, B_ASYNC, cr);
+
return (0);
}