diff options
author | eschrock <none@none> | 2006-04-08 23:33:38 -0700 |
---|---|---|
committer | eschrock <none@none> | 2006-04-08 23:33:38 -0700 |
commit | b468a217b67dc26ce21da5d5a2ca09bb6249e4fa (patch) | |
tree | 71b6bb81b469d8127e12b97549cb177aa5deac3e /usr/src | |
parent | 25cf1a301a396c38e8adf52c15f537b80d2483f7 (diff) | |
download | illumos-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.c | 28 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/sys/vdev_impl.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/vdev_disk.c | 20 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_fm.c | 8 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_vnops.c | 37 |
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); } |