Cleanup VAT writout. To prevent issues with the sequential writing strategy

trying to write on blocks that are lost due to the synchronisation, don't just
bluntly do synchronize device caches, but split out on strategies.
This commit is contained in:
reinoud 2016-05-24 09:55:57 +00:00
parent 6e3cf83f8e
commit 42866dd28d
8 changed files with 109 additions and 38 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf.h,v 1.51 2016/05/10 15:23:39 reinoud Exp $ */
/* $NetBSD: udf.h,v 1.52 2016/05/24 09:55:57 reinoud Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@ -76,7 +76,7 @@ extern int udf_verbose;
#define UDF_DEBUG_RESERVE 0x1000000
/* initial value of udf_verbose */
#define UDF_DEBUGGING 0
#define UDF_DEBUGGING (0)
#ifdef UDF_DEBUG
#define DPRINTF(name, arg) { \
@ -252,6 +252,7 @@ struct udf_strategy {
int (*read_logvol_dscr) (struct udf_strat_args *args);
int (*write_logvol_dscr) (struct udf_strat_args *args);
void (*queuebuf) (struct udf_strat_args *args);
void (*sync_caches) (struct udf_strat_args *args);
void (*discstrat_init) (struct udf_strat_args *args);
void (*discstrat_finish) (struct udf_strat_args *args);
};

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_readwrite.c,v 1.11 2011/06/12 03:35:55 rmind Exp $ */
/* $NetBSD: udf_readwrite.c,v 1.12 2016/05/24 09:55:57 reinoud Exp $ */
/*
* Copyright (c) 2007, 2008 Reinoud Zandijk
@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_readwrite.c,v 1.11 2011/06/12 03:35:55 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: udf_readwrite.c,v 1.12 2016/05/24 09:55:57 reinoud Exp $");
#endif /* not lint */
@ -695,6 +695,19 @@ udf_discstrat_queuebuf(struct udf_mount *ump, struct buf *nestbuf)
}
void
udf_synchronise_caches(struct udf_mount *ump)
{
struct udf_strategy *strategy = ump->strategy;
struct udf_strat_args args;
KASSERT(strategy);
args.ump = ump;
(strategy->sync_caches)(&args);
}
void
udf_discstrat_init(struct udf_mount *ump)
{

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_strat_bootstrap.c,v 1.4 2014/11/10 18:46:33 maxv Exp $ */
/* $NetBSD: udf_strat_bootstrap.c,v 1.5 2016/05/24 09:55:57 reinoud Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_strat_bootstrap.c,v 1.4 2014/11/10 18:46:33 maxv Exp $");
__KERNEL_RCSID(0, "$NetBSD: udf_strat_bootstrap.c,v 1.5 2016/05/24 09:55:57 reinoud Exp $");
#endif /* not lint */
@ -115,6 +115,14 @@ udf_queuebuf_bootstrap(struct udf_strat_args *args)
VOP_STRATEGY(ump->devvp, buf);
}
static void
udf_sync_caches_bootstrap(struct udf_strat_args *args)
{
/* empty */
}
static void
udf_discstrat_init_bootstrap(struct udf_strat_args *args)
{
@ -137,6 +145,7 @@ struct udf_strategy udf_strat_bootstrap =
udf_read_logvol_dscr_bootstrap,
udf_write_logvol_dscr_bootstrap,
udf_queuebuf_bootstrap,
udf_sync_caches_bootstrap,
udf_discstrat_init_bootstrap,
udf_discstrat_finish_bootstrap
};

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_strat_direct.c,v 1.13 2015/10/06 08:57:34 hannken Exp $ */
/* $NetBSD: udf_strat_direct.c,v 1.14 2016/05/24 09:55:57 reinoud Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_strat_direct.c,v 1.13 2015/10/06 08:57:34 hannken Exp $");
__KERNEL_RCSID(0, "$NetBSD: udf_strat_direct.c,v 1.14 2016/05/24 09:55:57 reinoud Exp $");
#endif /* not lint */
@ -392,6 +392,15 @@ udf_queue_buf_direct(struct udf_strat_args *args)
}
static void
udf_sync_caches_direct(struct udf_strat_args *args)
{
struct udf_mount *ump = args->ump;
udf_mmc_synchronise_caches(ump);
}
static void
udf_discstrat_init_direct(struct udf_strat_args *args)
{
@ -441,6 +450,7 @@ struct udf_strategy udf_strat_direct =
udf_read_nodedscr_direct,
udf_write_nodedscr_direct,
udf_queue_buf_direct,
udf_sync_caches_direct,
udf_discstrat_init_direct,
udf_discstrat_finish_direct
};

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_strat_rmw.c,v 1.27 2015/10/06 08:57:34 hannken Exp $ */
/* $NetBSD: udf_strat_rmw.c,v 1.28 2016/05/24 09:55:57 reinoud Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_strat_rmw.c,v 1.27 2015/10/06 08:57:34 hannken Exp $");
__KERNEL_RCSID(0, "$NetBSD: udf_strat_rmw.c,v 1.28 2016/05/24 09:55:57 reinoud Exp $");
#endif /* not lint */
@ -1005,6 +1005,16 @@ udf_queuebuf_rmw(struct udf_strat_args *args)
/* --------------------------------------------------------------------- */
static void
udf_sync_caches_rmw(struct udf_strat_args *args)
{
struct udf_mount *ump = args->ump;
udf_mmc_synchronise_caches(ump);
}
/* --------------------------------------------------------------------- */
static void
udf_shedule_read_callback(struct buf *buf)
{
@ -1495,6 +1505,7 @@ struct udf_strategy udf_strat_rmw =
udf_read_nodedscr_rmw,
udf_write_nodedscr_rmw,
udf_queuebuf_rmw,
udf_sync_caches_rmw,
udf_discstrat_init_rmw,
udf_discstrat_finish_rmw
};

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_strat_sequential.c,v 1.14 2015/10/06 08:57:34 hannken Exp $ */
/* $NetBSD: udf_strat_sequential.c,v 1.15 2016/05/24 09:55:57 reinoud Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_strat_sequential.c,v 1.14 2015/10/06 08:57:34 hannken Exp $");
__KERNEL_RCSID(0, "$NetBSD: udf_strat_sequential.c,v 1.15 2016/05/24 09:55:57 reinoud Exp $");
#endif /* not lint */
@ -86,6 +86,7 @@ struct strat_private {
kmutex_t discstrat_mutex; /* disc strategy */
int run_thread; /* thread control */
int sync_req; /* thread control */
int cur_queue;
struct disk_strategy old_strategy_setting;
@ -287,6 +288,30 @@ udf_queuebuf_seq(struct udf_strat_args *args)
/* --------------------------------------------------------------------- */
static void
udf_sync_caches_seq(struct udf_strat_args *args)
{
struct udf_mount *ump = args->ump;
struct strat_private *priv = PRIV(ump);
/* we might be called during unmount inadvertedly, be on safe side */
if (!priv)
return;
/* signal our thread that there might be something to do */
priv->sync_req = 1;
cv_signal(&priv->discstrat_cv);
mutex_enter(&priv->discstrat_mutex);
while (priv->sync_req) {
cv_timedwait(&priv->discstrat_cv,
&priv->discstrat_mutex, hz/8);
}
mutex_exit(&priv->discstrat_mutex);
}
/* --------------------------------------------------------------------- */
/* TODO convert to lb_size */
static void
udf_VAT_mapping_update(struct udf_mount *ump, struct buf *buf, uint32_t lb_map)
@ -539,7 +564,7 @@ udf_discstrat_thread(void *arg)
empty = 1;
mutex_enter(&priv->discstrat_mutex);
while (priv->run_thread || !empty) {
while (priv->run_thread || !empty || priv->sync_req) {
/* process the current selected queue */
udf_doshedule(ump);
empty = (bufq_peek(priv->queues[UDF_SHED_READING]) == NULL);
@ -547,9 +572,16 @@ udf_discstrat_thread(void *arg)
empty &= (bufq_peek(priv->queues[UDF_SHED_SEQWRITING]) == NULL);
/* wait for more if needed */
if (empty)
if (empty) {
if (priv->sync_req) {
/* on sync, we need to simulate a read->write transition */
udf_mmc_synchronise_caches(ump);
priv->cur_queue = UDF_SHED_READING;
priv->sync_req = 0;
}
cv_timedwait(&priv->discstrat_cv,
&priv->discstrat_mutex, hz/8);
}
}
mutex_exit(&priv->discstrat_mutex);
@ -621,6 +653,7 @@ udf_discstrat_init_seq(struct udf_strat_args *args)
/* create our disk strategy thread */
priv->run_thread = 1;
priv->sync_req = 0;
if (kthread_create(PRI_NONE, 0 /* KTHREAD_MPSAFE*/, NULL /* cpu_info*/,
udf_discstrat_thread, ump, &priv->queue_lwp,
"%s", "udf_rw")) {
@ -673,6 +706,7 @@ struct udf_strategy udf_strat_sequential =
udf_read_logvol_dscr_seq,
udf_write_logvol_dscr_seq,
udf_queuebuf_seq,
udf_sync_caches_seq,
udf_discstrat_init_seq,
udf_discstrat_finish_seq
};

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_subr.c,v 1.137 2016/05/10 15:23:39 reinoud Exp $ */
/* $NetBSD: udf_subr.c,v 1.138 2016/05/24 09:55:57 reinoud Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@ -29,7 +29,7 @@
#include <sys/cdefs.h>
#ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.137 2016/05/10 15:23:39 reinoud Exp $");
__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.138 2016/05/24 09:55:57 reinoud Exp $");
#endif /* not lint */
@ -319,27 +319,25 @@ udf_setup_writeparams(struct udf_mount *ump)
}
int
udf_synchronise_caches(struct udf_mount *ump)
void
udf_mmc_synchronise_caches(struct udf_mount *ump)
{
struct mmc_op mmc_op;
DPRINTF(CALL, ("udf_synchronise_caches()\n"));
DPRINTF(CALL, ("udf_mcc_synchronise_caches()\n"));
if (ump->vfs_mountp->mnt_flag & MNT_RDONLY)
return 0;
return;
/* discs are done now */
if (ump->discinfo.mmc_class == MMC_CLASS_DISC)
return 0;
return;
memset(&mmc_op, 0, sizeof(struct mmc_op));
mmc_op.operation = MMC_OP_SYNCHRONISECACHE;
/* ignore return code */
(void) VOP_IOCTL(ump->devvp, MMCOP, &mmc_op, FKIOCTL, NOCRED);
return 0;
}
/* --------------------------------------------------------------------- */
@ -2833,7 +2831,6 @@ udf_writeout_vat(struct udf_mount *ump)
if (error)
printf("udf_writeout_vat: error writing VAT node!\n");
out:
return error;
}
@ -3710,10 +3707,9 @@ udf_open_logvol(struct udf_mount *ump)
/* write out the VAT data and all its descriptors */
DPRINTF(VOLUMES, ("writeout vat_node\n"));
udf_writeout_vat(ump);
vflushbuf(ump->vat_node->vnode, 1 /* sync */);
(void) VOP_FSYNC(ump->vat_node->vnode,
FSCRED, FSYNC_WAIT, 0, 0);
/* force everything to be synchronized on the device */
(void) udf_synchronise_caches(ump);
}
}
@ -3763,15 +3759,6 @@ udf_close_logvol(struct udf_mount *ump, int mntflags)
/* write out the VAT data and all its descriptors */
DPRINTF(VOLUMES, ("writeout vat_node\n"));
udf_writeout_vat(ump);
(void) vflushbuf(ump->vat_node->vnode, FSYNC_WAIT);
(void) VOP_FSYNC(ump->vat_node->vnode,
FSCRED, FSYNC_WAIT, 0, 0);
if (ump->lvclose & UDF_CLOSE_SESSION) {
DPRINTF(VOLUMES, ("udf_close_logvol: closing session "
"as requested\n"));
}
/* at least two DVD packets and 3 CD-R packets */
nvats = 32;
@ -3806,6 +3793,9 @@ udf_close_logvol(struct udf_mount *ump, int mntflags)
if (!error)
nok++;
}
/* force everything to be synchronized on the device */
(void) udf_synchronise_caches(ump);
if (nok < 14) {
/* arbitrary; but at least one or two CD frames */
printf("writeout of at least 14 VATs failed\n");
@ -3817,6 +3807,8 @@ udf_close_logvol(struct udf_mount *ump, int mntflags)
/* finish closing of session */
if (ump->lvclose & UDF_CLOSE_SESSION) {
DPRINTF(VOLUMES, ("udf_close_logvol: closing session "
"as requested\n"));
error = udf_validate_session_start(ump);
if (error)
return error;

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_subr.h,v 1.19 2013/07/07 19:49:44 reinoud Exp $ */
/* $NetBSD: udf_subr.h,v 1.20 2016/05/24 09:55:57 reinoud Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@ -40,7 +40,8 @@ int udf_search_tracks(struct udf_mount *ump, struct udf_args *args,
int *first_tracknr, int *last_tracknr);
int udf_search_writing_tracks(struct udf_mount *ump);
int udf_setup_writeparams(struct udf_mount *ump);
int udf_synchronise_caches(struct udf_mount *ump);
void udf_mmc_synchronise_caches(struct udf_mount *ump);
void udf_synchronise_caches(struct udf_mount *ump);
/* tags operations */
int udf_fidsize(struct fileid_desc *fid);