From a287d23dee468b6073fd7738ee269aebcd8d694b Mon Sep 17 00:00:00 2001 From: reinoud Date: Wed, 6 Aug 2008 13:41:12 +0000 Subject: [PATCH] Rewrite allocation scheme's determination and implementation replacing the old somewhat naive selection scheme that didn't allow different allocation settings for nodes, directory information (FIDs) and data. Also fix some curious side-effects of atime updates on RMW devices. --- sys/fs/udf/udf.h | 23 ++-- sys/fs/udf/udf_allocation.c | 178 +++++++++++++++++------------- sys/fs/udf/udf_strat_direct.c | 6 +- sys/fs/udf/udf_strat_rmw.c | 6 +- sys/fs/udf/udf_strat_sequential.c | 14 +-- sys/fs/udf/udf_subr.c | 128 +++++++++++---------- sys/fs/udf/udf_subr.h | 4 +- sys/fs/udf/udf_vfsops.c | 66 ++++++----- 8 files changed, 232 insertions(+), 193 deletions(-) diff --git a/sys/fs/udf/udf.h b/sys/fs/udf/udf.h index d7a52d1c42af..dbd5e94b8efc 100644 --- a/sys/fs/udf/udf.h +++ b/sys/fs/udf/udf.h @@ -1,4 +1,4 @@ -/* $NetBSD: udf.h,v 1.25 2008/07/29 10:08:16 reinoud Exp $ */ +/* $NetBSD: udf.h,v 1.26 2008/08/06 13:41:12 reinoud Exp $ */ /* * Copyright (c) 2006, 2008 Reinoud Zandijk @@ -147,6 +147,7 @@ extern int udf_verbose; /* RW content hint for allocation and other purposes */ +#define UDF_C_INVALID 0 /* not relevant */ #define UDF_C_PROCESSED 0 /* not relevant */ #define UDF_C_USERDATA 1 /* all but userdata is metadata */ #define UDF_C_DSCR 2 /* update sectornr and CRC */ @@ -155,7 +156,6 @@ extern int udf_verbose; #define UDF_C_METADATA_SBM 5 /* space bitmap, update sectornr and CRC */ #define UDF_C_EXTATTRS 6 /* dunno what to do yet */ - /* use unused b_freelistindex for our UDF_C_TYPE */ #define b_udf_c_type b_freelistindex @@ -172,6 +172,7 @@ extern int udf_verbose; /* allocation strategies */ +#define UDF_ALLOC_INVALID 0 #define UDF_ALLOC_SEQUENTIAL 1 /* linear on NWA */ #define UDF_ALLOC_VAT 2 /* VAT handling */ #define UDF_ALLOC_SPACEMAP 3 /* spacemaps */ @@ -283,20 +284,18 @@ struct udf_mount { int lvopen; /* logvol actions */ int lvclose; /* logvol actions */ - /* disc allocation / writing method */ - int lvreadwrite; /* error handling */ - int data_alloc; /* all userdata */ - int data_allocdscr; - int meta_alloc; /* all metadata */ - int meta_allocdscr; - int data_part; - int metadata_part; - kmutex_t allocate_mutex; - /* logical to physical translations */ int vtop[UDF_PMAPS+1]; /* vpartnr trans */ int vtop_tp[UDF_PMAPS+1]; /* type of trans */ + /* disc allocation / writing method */ + kmutex_t allocate_mutex; + int lvreadwrite; /* error handling */ + int vtop_alloc[UDF_PMAPS+1]; /* alloc scheme */ + int data_part; + int node_part; + int fids_part; + /* sequential track info */ struct mmc_trackinfo data_track; struct mmc_trackinfo metadata_track; diff --git a/sys/fs/udf/udf_allocation.c b/sys/fs/udf/udf_allocation.c index b76ebf57eabb..da6650b2d39c 100644 --- a/sys/fs/udf/udf_allocation.c +++ b/sys/fs/udf/udf_allocation.c @@ -1,4 +1,4 @@ -/* $NetBSD: udf_allocation.c,v 1.16 2008/07/28 19:41:13 reinoud Exp $ */ +/* $NetBSD: udf_allocation.c,v 1.17 2008/08/06 13:41:12 reinoud Exp $ */ /* * Copyright (c) 2006, 2008 Reinoud Zandijk @@ -28,7 +28,7 @@ #include #ifndef lint -__KERNEL_RCSID(0, "$NetBSD: udf_allocation.c,v 1.16 2008/07/28 19:41:13 reinoud Exp $"); +__KERNEL_RCSID(0, "$NetBSD: udf_allocation.c,v 1.17 2008/08/06 13:41:12 reinoud Exp $"); #endif /* not lint */ @@ -235,7 +235,9 @@ udf_assert_allocated(struct udf_mount *ump, uint16_t vpart_num, static void udf_node_sanity_check(struct udf_node *udf_node, - uint64_t *cnt_inflen, uint64_t *cnt_logblksrec) { + uint64_t *cnt_inflen, uint64_t *cnt_logblksrec) +{ + union dscrptr *dscr; struct file_entry *fe; struct extfile_entry *efe; struct icb_tag *icbtag; @@ -244,8 +246,9 @@ udf_node_sanity_check(struct udf_node *udf_node, uint32_t icbflags, addr_type; uint32_t len, lb_num, l_ea, l_ad, max_l_ad; uint16_t part_num; + uint8_t *data_pos; int dscr_size, lb_size, flags, whole_lb; - int slot, eof; + int i, slot, eof; // KASSERT(mutex_owned(&udf_node->ump->allocate_mutex)); @@ -257,24 +260,35 @@ udf_node_sanity_check(struct udf_node *udf_node, fe = udf_node->fe; efe = udf_node->efe; if (fe) { - icbtag = &fe->icbtag; - inflen = udf_rw64(fe->inf_len); + dscr = (union dscrptr *) fe; + icbtag = &fe->icbtag; + inflen = udf_rw64(fe->inf_len); dscr_size = sizeof(struct file_entry) -1; logblksrec = udf_rw64(fe->logblks_rec); l_ad = udf_rw32(fe->l_ad); l_ea = udf_rw32(fe->l_ea); } else { - icbtag = &efe->icbtag; - inflen = udf_rw64(efe->inf_len); + dscr = (union dscrptr *) efe; + icbtag = &efe->icbtag; + inflen = udf_rw64(efe->inf_len); dscr_size = sizeof(struct extfile_entry) -1; logblksrec = udf_rw64(efe->logblks_rec); l_ad = udf_rw32(efe->l_ad); l_ea = udf_rw32(efe->l_ea); } + data_pos = (uint8_t *) dscr + dscr_size + l_ea; max_l_ad = lb_size - dscr_size - l_ea; icbflags = udf_rw16(icbtag->flags); addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; + /* check if tail is zero */ + DPRINTF(PARANOIA, ("Sanity check blank tail\n")); + for (i = l_ad; i < max_l_ad; i++) { + if (data_pos[i] != 0) + printf( "sanity_check: violation: node byte %d " + "has value %d\n", i, data_pos[i]); + } + /* reset counters */ *cnt_inflen = 0; *cnt_logblksrec = 0; @@ -887,9 +901,8 @@ udf_bitmap_free(struct udf_bitmap *bitmap, uint32_t lb_num, uint32_t num_lb) /* allocate a contiguous sequence of sectornumbers */ static int -udf_allocate_space(struct udf_mount *ump, int ismetadata, int alloc_type, - int num_lb, uint16_t *alloc_partp, - uint64_t *lmapping) +udf_allocate_space(struct udf_mount *ump, int udf_c_type, + uint16_t vpart_num, uint32_t num_lb, uint64_t *lmapping) { struct mmc_trackinfo *alloc_track, *other_track; struct udf_bitmap *bitmap; @@ -898,26 +911,20 @@ udf_allocate_space(struct udf_mount *ump, int ismetadata, int alloc_type, uint64_t *lmappos; uint32_t ptov, lb_num, *freepos, free_lbs; int lb_size, alloc_num_lb; - int alloc_part; - int error; + int alloc_type, error; + int is_node; + DPRINTF(CALL, ("udf_allocate_space(ctype %d, vpart %d, num_lb %d\n", + udf_c_type, vpart_num, num_lb)); mutex_enter(&ump->allocate_mutex); lb_size = udf_rw32(ump->logical_vol->lb_size); KASSERT(lb_size == ump->discinfo.sector_size); - if (ismetadata) { - alloc_part = ump->metadata_part; - alloc_track = &ump->metadata_track; - other_track = &ump->data_track; - } else { - alloc_part = ump->data_part; - alloc_track = &ump->data_track; - other_track = &ump->metadata_track; - } - *alloc_partp = alloc_part; + /* XXX TODO check disc space */ - /* XXX check disc space */ + alloc_type = ump->vtop_alloc[vpart_num]; + is_node = (udf_c_type == UDF_C_NODE); lmappos = lmapping; error = 0; @@ -931,17 +938,29 @@ udf_allocate_space(struct udf_mount *ump, int ismetadata, int alloc_type, break; case UDF_ALLOC_SEQUENTIAL : /* sequential allocation on recordable media */ - /* get partition backing up this vpart_num */ - pdesc = ump->partitions[ump->vtop[alloc_part]]; + /* get partition backing up this vpart_num_num */ + pdesc = ump->partitions[ump->vtop[vpart_num]]; /* calculate offset from physical base partition */ ptov = udf_rw32(pdesc->start_loc); + /* get our track descriptors */ + if (vpart_num == ump->node_part) { + alloc_track = &ump->metadata_track; + other_track = &ump->data_track; + } else { + alloc_track = &ump->data_track; + other_track = &ump->metadata_track; + } + + /* allocate */ for (lb_num = 0; lb_num < num_lb; lb_num++) { *lmappos++ = alloc_track->next_writable - ptov; alloc_track->next_writable++; alloc_track->free_blocks--; } + + /* keep other track up-to-date */ if (alloc_track->tracknr == other_track->tracknr) memcpy(other_track, alloc_track, sizeof(struct mmc_trackinfo)); @@ -949,8 +968,8 @@ udf_allocate_space(struct udf_mount *ump, int ismetadata, int alloc_type, case UDF_ALLOC_SPACEMAP : /* try to allocate on unallocated bits */ alloc_num_lb = num_lb; - bitmap = &ump->part_unalloc_bits[alloc_part]; - udf_bitmap_allocate(bitmap, ismetadata, &alloc_num_lb, lmappos); + bitmap = &ump->part_unalloc_bits[vpart_num]; + udf_bitmap_allocate(bitmap, is_node, &alloc_num_lb, lmappos); ump->lvclose |= UDF_WRITE_PART_BITMAPS; /* have we allocated all? */ @@ -966,7 +985,7 @@ udf_allocate_space(struct udf_mount *ump, int ismetadata, int alloc_type, if (!error) { /* adjust freecount */ lvid = ump->logvol_integrity; - freepos = &lvid->tables[0] + alloc_part; + freepos = &lvid->tables[0] + vpart_num; free_lbs = udf_rw32(*freepos); *freepos = udf_rw32(free_lbs - num_lb); } @@ -975,11 +994,11 @@ udf_allocate_space(struct udf_mount *ump, int ismetadata, int alloc_type, /* allocate on metadata unallocated bits */ alloc_num_lb = num_lb; bitmap = &ump->metadata_unalloc_bits; - udf_bitmap_allocate(bitmap, ismetadata, &num_lb, lmappos); + udf_bitmap_allocate(bitmap, is_node, &alloc_num_lb, lmappos); ump->lvclose |= UDF_WRITE_PART_BITMAPS; /* have we allocated all? */ - if (num_lb) { + if (alloc_num_lb) { /* YIKES! TODO we need to extend the metadata partition */ /* free allocated piece for now */ lmappos = lmapping; @@ -991,7 +1010,7 @@ udf_allocate_space(struct udf_mount *ump, int ismetadata, int alloc_type, if (!error) { /* adjust freecount */ lvid = ump->logvol_integrity; - freepos = &lvid->tables[0] + alloc_part; + freepos = &lvid->tables[0] + vpart_num; free_lbs = udf_rw32(*freepos); *freepos = udf_rw32(free_lbs - num_lb); } @@ -1061,7 +1080,7 @@ udf_free_allocated_space(struct udf_mount *ump, uint32_t lb_num, if (bitmap->bits == NULL) bitmap = &ump->part_unalloc_bits[phys_part]; - /* if no bitmaps are defined, bail out */ + /* if no bitmaps are defined, bail out; XXX OK? */ if (bitmap->bits == NULL) break; @@ -1090,6 +1109,18 @@ udf_free_allocated_space(struct udf_mount *ump, uint32_t lb_num, break; case UDF_VTOP_TYPE_META : /* free space in the metadata bitmap */ + bitmap = &ump->metadata_unalloc_bits; + KASSERT(bitmap->bits); + + ump->lvclose |= UDF_WRITE_PART_BITMAPS; + udf_bitmap_free(bitmap, lb_num, num_lb); + + /* adjust freecount */ + lvid = ump->logvol_integrity; + freepos = &lvid->tables[0] + vpart_num; + free_lbs = udf_rw32(*freepos); + *freepos = udf_rw32(free_lbs + num_lb); + break; default: printf("ALERT: udf_free_allocated_space : allocation %d " "not implemented yet!\n", ump->vtop_tp[vpart_num]); @@ -1102,29 +1133,19 @@ udf_free_allocated_space(struct udf_mount *ump, uint32_t lb_num, /* --------------------------------------------------------------------- */ int -udf_pre_allocate_space(struct udf_mount *ump, int udf_c_type, int num_lb, - uint16_t *alloc_partp, uint64_t *lmapping) +udf_pre_allocate_space(struct udf_mount *ump, int udf_c_type, + uint32_t num_lb, uint16_t vpartnr, uint64_t *lmapping) { - int ismetadata, alloc_type; - - ismetadata = (udf_c_type == UDF_C_NODE); - alloc_type = ismetadata? ump->meta_alloc : ump->data_alloc; - -#ifdef DIAGNOSTIC - if ((alloc_type == UDF_ALLOC_VAT) && (udf_c_type != UDF_C_NODE)) { - panic("udf_pre_allocate_space: bad c_type on VAT!\n"); - } -#endif + /* TODO properly maintain uncomitted_lb per partition */ /* reserve size for VAT allocated data */ - if (alloc_type == UDF_ALLOC_VAT) { + if (ump->vtop_alloc[vpartnr] == UDF_ALLOC_VAT) { mutex_enter(&ump->allocate_mutex); ump->uncomitted_lb += num_lb; mutex_exit(&ump->allocate_mutex); } - return udf_allocate_space(ump, ismetadata, alloc_type, - num_lb, alloc_partp, lmapping); + return udf_allocate_space(ump, udf_c_type, vpartnr, num_lb, lmapping); } /* --------------------------------------------------------------------- */ @@ -1136,12 +1157,11 @@ udf_pre_allocate_space(struct udf_mount *ump, int udf_c_type, int num_lb, void udf_late_allocate_buf(struct udf_mount *ump, struct buf *buf, - uint64_t *lmapping, struct long_ad *node_ad_cpy, uint16_t *vpart_num) + uint64_t *lmapping, struct long_ad *node_ad_cpy, uint16_t *vpart_nump) { struct udf_node *udf_node = VTOI(buf->b_vp); int lb_size, blks, udf_c_type; - int ismetadata, alloc_type; - int num_lb; + int vpart_num, num_lb; int error, s; /* @@ -1158,27 +1178,26 @@ udf_late_allocate_buf(struct udf_mount *ump, struct buf *buf, KASSERT(lb_size == ump->discinfo.sector_size); - ismetadata = (udf_c_type == UDF_C_NODE); - alloc_type = ismetadata? ump->meta_alloc : ump->data_alloc; - -#ifdef DIAGNOSTIC - if ((alloc_type == UDF_ALLOC_VAT) && (udf_c_type != UDF_C_NODE)) { - panic("udf_late_allocate_buf: bad c_type on VAT!\n"); - } -#endif + /* select partition to record the buffer on */ + vpart_num = ump->data_part; + if (udf_c_type == UDF_C_NODE) + vpart_num = ump->node_part; + if (udf_c_type == UDF_C_FIDS) + vpart_num = ump->fids_part; + *vpart_nump = vpart_num; if (udf_c_type == UDF_C_NODE) { /* if not VAT, its allready allocated */ - if (alloc_type != UDF_ALLOC_VAT) + if (ump->vtop_alloc[ump->node_part] != UDF_ALLOC_VAT) return; - /* allocate sequential */ - alloc_type = UDF_ALLOC_SEQUENTIAL; + /* allocate on its backing sequential partition */ + vpart_num = ump->data_part; } - /* returns vpart_num on wich the allocation was done */ - error = udf_allocate_space(ump, ismetadata, alloc_type, - num_lb, vpart_num, lmapping); + /* do allocation on the selected partition */ + error = udf_allocate_space(ump, udf_c_type, + vpart_num, num_lb, lmapping); if (error) { /* ARGH! we've not done our accounting right! */ panic("UDF disc allocation accounting gone wrong"); @@ -1198,7 +1217,7 @@ udf_late_allocate_buf(struct udf_mount *ump, struct buf *buf, (udf_c_type == UDF_C_FIDS) || (udf_c_type == UDF_C_METADATA_SBM)) { - udf_record_allocation_in_node(ump, buf, *vpart_num, lmapping, + udf_record_allocation_in_node(ump, buf, vpart_num, lmapping, node_ad_cpy); /* decrement our outstanding bufs counter */ s = splbio(); @@ -1460,9 +1479,10 @@ udf_append_adslot(struct udf_node *udf_node, int *slot, struct long_ad *icb) { int icbflags, addr_type, adlen, extnr; int error; - /* determine what descriptor we are in */ lb_size = udf_rw32(ump->logical_vol->lb_size); + vpart_num = udf_rw16(udf_node->loc.loc.part_num); + /* determine what descriptor we are in */ fe = udf_node->fe; efe = udf_node->efe; if (fe) { @@ -1500,17 +1520,12 @@ udf_append_adslot(struct udf_node *udf_node, int *slot, struct long_ad *icb) { adlen = sizeof(struct long_ad); } - /* clean up given long_ad */ -#ifdef DIAGNOSTIC + /* clean up given long_ad since it can be a synthesized one */ flags = UDF_EXT_FLAGS(udf_rw32(icb->len)); if (flags == UDF_EXT_FREE) { - if ((udf_rw16(icb->loc.part_num) != 0) || - (udf_rw32(icb->loc.lb_num) != 0)) - printf("UDF: warning, cleaning long_ad marked free\n"); icb->loc.part_num = udf_rw16(0); icb->loc.lb_num = udf_rw32(0); } -#endif /* if offset too big, we go to the allocation extensions */ l_ad = udf_rw32(*l_ad_p); @@ -1592,8 +1607,9 @@ udf_append_adslot(struct udf_node *udf_node, int *slot, struct long_ad *icb) { l_icb = udf_node->ext_loc[extnr]; if (ext == NULL) { DPRINTF(ALLOC,("adding allocation extent %d\n", extnr)); + error = udf_pre_allocate_space(ump, UDF_C_NODE, 1, - &vpart_num, &lmapping); + vpart_num, &lmapping); lb_num = lmapping; if (error) return error; @@ -2128,10 +2144,11 @@ udf_grow_node(struct udf_node *udf_node, uint64_t new_size) uint64_t foffset, end_foffset; uint64_t orig_inflen, orig_lbrec, new_inflen, new_lbrec; uint32_t lb_size, dscr_size, crclen, lastblock_grow; - uint32_t len, flags, max_len; + uint32_t icbflags, len, flags, max_len; uint32_t max_l_ad, l_ad, l_ea; + uint16_t my_part, dst_part; uint8_t *data_pos, *evacuated_data; - int icbflags, addr_type; + int addr_type; int slot, cpy_slot; int isdir, eof, error; @@ -2234,10 +2251,15 @@ udf_grow_node(struct udf_node *udf_node, uint64_t new_size) } /* convert to a normal alloc and select type */ - isdir = (vp->v_type == VDIR); + isdir = (vp->v_type == VDIR); + my_part = udf_rw16(udf_node->loc.loc.part_num); + dst_part = isdir? ump->fids_part : ump->data_part; + addr_type = UDF_ICB_SHORT_ALLOC; + if (dst_part != my_part) + addr_type = UDF_ICB_LONG_ALLOC; icbflags &= ~UDF_ICB_TAG_FLAGS_ALLOC_MASK; - icbflags |= isdir ? ump->meta_allocdscr : ump->data_allocdscr; + icbflags |= addr_type; icbtag->flags = udf_rw16(icbflags); /* wipe old descriptor space */ diff --git a/sys/fs/udf/udf_strat_direct.c b/sys/fs/udf/udf_strat_direct.c index 56eba2d7ff16..7b0194f9a5e7 100644 --- a/sys/fs/udf/udf_strat_direct.c +++ b/sys/fs/udf/udf_strat_direct.c @@ -1,4 +1,4 @@ -/* $NetBSD: udf_strat_direct.c,v 1.3 2008/07/28 19:41:13 reinoud Exp $ */ +/* $NetBSD: udf_strat_direct.c,v 1.4 2008/08/06 13:41:12 reinoud Exp $ */ /* * Copyright (c) 2006, 2008 Reinoud Zandijk @@ -28,7 +28,7 @@ #include #ifndef lint -__KERNEL_RCSID(0, "$NetBSD: udf_strat_direct.c,v 1.3 2008/07/28 19:41:13 reinoud Exp $"); +__KERNEL_RCSID(0, "$NetBSD: udf_strat_direct.c,v 1.4 2008/08/06 13:41:12 reinoud Exp $"); #endif /* not lint */ @@ -362,7 +362,7 @@ udf_queue_buf_direct(struct udf_strat_args *args) if (buf->b_lblkno == 0) { /* update the tag location inside */ tag = (struct desc_tag *) buf->b_data; - tag->tag_loc = udf_rw32(buf->b_blkno); + tag->tag_loc = udf_rw32(*lmapping); udf_validate_tag_and_crc_sums(buf->b_data); } } diff --git a/sys/fs/udf/udf_strat_rmw.c b/sys/fs/udf/udf_strat_rmw.c index 463cacc7e48a..2d32867b267d 100644 --- a/sys/fs/udf/udf_strat_rmw.c +++ b/sys/fs/udf/udf_strat_rmw.c @@ -1,4 +1,4 @@ -/* $NetBSD: udf_strat_rmw.c,v 1.6 2008/07/28 19:41:13 reinoud Exp $ */ +/* $NetBSD: udf_strat_rmw.c,v 1.7 2008/08/06 13:41:12 reinoud Exp $ */ /* * Copyright (c) 2006, 2008 Reinoud Zandijk @@ -28,7 +28,7 @@ #include #ifndef lint -__KERNEL_RCSID(0, "$NetBSD: udf_strat_rmw.c,v 1.6 2008/07/28 19:41:13 reinoud Exp $"); +__KERNEL_RCSID(0, "$NetBSD: udf_strat_rmw.c,v 1.7 2008/08/06 13:41:12 reinoud Exp $"); #endif /* not lint */ @@ -925,7 +925,7 @@ udf_queuebuf_rmw(struct udf_strat_args *args) if (buf->b_lblkno == 0) { /* update the tag location inside */ tag = (struct desc_tag *) buf->b_data; - tag->tag_loc = udf_rw32(buf->b_blkno); + tag->tag_loc = udf_rw32(*lmapping); udf_validate_tag_and_crc_sums(buf->b_data); } } diff --git a/sys/fs/udf/udf_strat_sequential.c b/sys/fs/udf/udf_strat_sequential.c index aea8e09b1fe9..3e1625016dfe 100644 --- a/sys/fs/udf/udf_strat_sequential.c +++ b/sys/fs/udf/udf_strat_sequential.c @@ -1,4 +1,4 @@ -/* $NetBSD: udf_strat_sequential.c,v 1.3 2008/07/28 19:41:13 reinoud Exp $ */ +/* $NetBSD: udf_strat_sequential.c,v 1.4 2008/08/06 13:41:12 reinoud Exp $ */ /* * Copyright (c) 2006, 2008 Reinoud Zandijk @@ -28,7 +28,7 @@ #include #ifndef lint -__KERNEL_RCSID(0, "$NetBSD: udf_strat_sequential.c,v 1.3 2008/07/28 19:41:13 reinoud Exp $"); +__KERNEL_RCSID(0, "$NetBSD: udf_strat_sequential.c,v 1.4 2008/08/06 13:41:12 reinoud Exp $"); #endif /* not lint */ @@ -288,10 +288,6 @@ udf_queuebuf_seq(struct udf_strat_args *args) queue = UDF_SHED_SEQWRITING; if (what == UDF_C_DSCR) queue = UDF_SHED_WRITING; - if (what == UDF_C_NODE) { - if (ump->meta_alloc != UDF_ALLOC_VAT) - queue = UDF_SHED_WRITING; - } #if 0 if (queue == UDF_SHED_SEQWRITING) { /* TODO do add sector to uncommitted space */ @@ -325,9 +321,8 @@ udf_VAT_mapping_update(struct udf_mount *ump, struct buf *buf, uint32_t lb_map) int error; /* only interested when we're using a VAT */ - if (ump->meta_alloc != UDF_ALLOC_VAT) - return; KASSERT(ump->vat_node); + KASSERT(ump->vtop_alloc[ump->node_part] == UDF_ALLOC_VAT); /* only nodes are recorded in the VAT */ /* NOTE: and the fileset descriptor (FIXME ?) */ @@ -475,6 +470,9 @@ udf_issue_buf(struct udf_mount *ump, int queue, struct buf *buf) buf_len -= len; } } + + /* NOTE we can't have metadata space bitmap descriptors here */ + udf_fixup_node_internals(ump, buf->b_data, buf->b_udf_c_type); VOP_STRATEGY(ump->devvp, buf); } diff --git a/sys/fs/udf/udf_subr.c b/sys/fs/udf/udf_subr.c index 0c0430851e10..8f1903d33c78 100644 --- a/sys/fs/udf/udf_subr.c +++ b/sys/fs/udf/udf_subr.c @@ -1,4 +1,4 @@ -/* $NetBSD: udf_subr.c,v 1.70 2008/07/28 19:41:13 reinoud Exp $ */ +/* $NetBSD: udf_subr.c,v 1.71 2008/08/06 13:41:12 reinoud Exp $ */ /* * Copyright (c) 2006, 2008 Reinoud Zandijk @@ -29,7 +29,7 @@ #include #ifndef lint -__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.70 2008/07/28 19:41:13 reinoud Exp $"); +__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.71 2008/08/06 13:41:12 reinoud Exp $"); #endif /* not lint */ @@ -424,7 +424,8 @@ udf_check_track_metadata_overlap(struct udf_mount *ump, track_end = track_start + trackinfo->track_size; /* get our base partition extent */ - part = ump->partitions[ump->metadata_part]; + KASSERT(ump->node_part == ump->fids_part); + part = ump->partitions[ump->node_part]; phys_part_start = udf_rw32(part->start_loc); phys_part_end = phys_part_start + udf_rw32(part->part_len); @@ -495,7 +496,7 @@ udf_search_writing_tracks(struct udf_mount *ump) struct part_desc *part; uint32_t tracknr, start_track, num_tracks; uint32_t track_start, track_end, part_start, part_end; - int error; + int node_alloc, error; /* * in the CD/(HD)DVD/BD recordable device model a few tracks within @@ -546,8 +547,9 @@ udf_search_writing_tracks(struct udf_mount *ump) } /* check for overlap on metadata partition */ - if ((ump->meta_alloc == UDF_ALLOC_METASEQUENTIAL) || - (ump->meta_alloc == UDF_ALLOC_METABITMAP)) { + node_alloc = ump->vtop_alloc[ump->node_part]; + if ((node_alloc == UDF_ALLOC_METASEQUENTIAL) || + (node_alloc == UDF_ALLOC_METABITMAP)) { udf_check_track_metadata_overlap(ump, &trackinfo); } else { ump->metadata_track = trackinfo; @@ -1721,7 +1723,7 @@ udf_write_metadata_partition_spacetable(struct udf_mount *ump, int waitfor) DPRINTF(VOLUMES, ("Resize and write out metadata space bitmap from " "%"PRIu64" to %"PRIu64" bytes\n", inflen, new_inflen)); - error = udf_resize_node(bitmap_node, 0, &dummy); + error = udf_resize_node(bitmap_node, new_inflen, &dummy); if (error) printf("Error resizing metadata space bitmap\n"); @@ -1734,6 +1736,7 @@ udf_write_metadata_partition_spacetable(struct udf_mount *ump, int waitfor) bitmap_node->i_flags |= IN_MODIFIED; vflushbuf(bitmap_node->vnode, 1 /* sync */); + error = VOP_FSYNC(bitmap_node->vnode, FSCRED, FSYNC_WAIT, 0, 0); @@ -1764,7 +1767,7 @@ udf_process_vds(struct udf_mount *ump) { const char *check_name; char bits[128]; int pmap_stype, pmap_size; - int pmap_type, log_part, phys_part, raw_phys_part; + int pmap_type, log_part, phys_part, raw_phys_part, maps_on; int n_phys, n_virt, n_spar, n_meta; int len, error; @@ -1830,7 +1833,8 @@ udf_process_vds(struct udf_mount *ump) { return EINVAL; } - ump->data_part = ump->metadata_part = 0; + /* count types and set partition numbers */ + ump->data_part = ump->node_part = ump->fids_part = 0; n_phys = n_virt = n_spar = n_meta = 0; for (log_part = 0; log_part < n_pm; log_part++) { mapping = (union udf_pmap *) pmap_pos; @@ -1842,8 +1846,9 @@ udf_process_vds(struct udf_mount *ump) { raw_phys_part = udf_rw16(mapping->pm1.part_num); pmap_type = UDF_VTOP_TYPE_PHYS; n_phys++; - ump->data_part = log_part; - ump->metadata_part = log_part; + ump->data_part = log_part; + ump->node_part = log_part; + ump->fids_part = log_part; break; case 2: /* virtual/sparable/meta mapping */ map_name = mapping->pm2.part_id.id; @@ -1856,22 +1861,24 @@ udf_process_vds(struct udf_mount *ump) { if (strncmp(map_name, check_name, len) == 0) { pmap_type = UDF_VTOP_TYPE_VIRT; n_virt++; - ump->metadata_part = log_part; + ump->node_part = log_part; break; } check_name = "*UDF Sparable Partition"; if (strncmp(map_name, check_name, len) == 0) { pmap_type = UDF_VTOP_TYPE_SPARABLE; n_spar++; - ump->data_part = log_part; - ump->metadata_part = log_part; + ump->data_part = log_part; + ump->node_part = log_part; + ump->fids_part = log_part; break; } check_name = "*UDF Metadata Partition"; if (strncmp(map_name, check_name, len) == 0) { pmap_type = UDF_VTOP_TYPE_META; n_meta++; - ump->metadata_part = log_part; + ump->node_part = log_part; + ump->fids_part = log_part; break; } break; @@ -1919,39 +1926,35 @@ udf_process_vds(struct udf_mount *ump) { if (n_spar + n_phys == 0) return EINVAL; - /* determine allocation scheme's based on disc format */ - /* VAT's can only be on a sequential media */ - ump->data_alloc = UDF_ALLOC_SPACEMAP; - if (n_virt) - ump->data_alloc = UDF_ALLOC_SEQUENTIAL; - - ump->meta_alloc = UDF_ALLOC_SPACEMAP; - if (n_virt) - ump->meta_alloc = UDF_ALLOC_VAT; - if (n_meta) - ump->meta_alloc = UDF_ALLOC_METABITMAP; - - /* special cases for pseudo-overwrite */ - if (ump->discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE) { - ump->data_alloc = UDF_ALLOC_SEQUENTIAL; - if (n_meta) { - ump->meta_alloc = UDF_ALLOC_METASEQUENTIAL; - } else { - ump->meta_alloc = UDF_ALLOC_RELAXEDSEQUENTIAL; + /* select allocation type for each logical partition */ + for (log_part = 0; log_part < n_pm; log_part++) { + maps_on = ump->vtop[log_part]; + switch (ump->vtop_tp[log_part]) { + case UDF_VTOP_TYPE_PHYS : + assert(maps_on == log_part); + ump->vtop_alloc[log_part] = UDF_ALLOC_SPACEMAP; + break; + case UDF_VTOP_TYPE_VIRT : + ump->vtop_alloc[log_part] = UDF_ALLOC_VAT; + ump->vtop_alloc[maps_on] = UDF_ALLOC_SEQUENTIAL; + break; + case UDF_VTOP_TYPE_SPARABLE : + assert(maps_on == log_part); + ump->vtop_alloc[log_part] = UDF_ALLOC_SPACEMAP; + break; + case UDF_VTOP_TYPE_META : + ump->vtop_alloc[log_part] = UDF_ALLOC_METABITMAP; + if (ump->discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE) { + /* special case for UDF 2.60 */ + ump->vtop_alloc[log_part] = UDF_ALLOC_METASEQUENTIAL; + ump->vtop_alloc[maps_on] = UDF_ALLOC_SEQUENTIAL; + } + break; + default: + panic("bad alloction type in udf's ump->vtop\n"); } } - /* determine default allocation descriptors to use */ - ump->data_allocdscr = UDF_ICB_SHORT_ALLOC; - ump->meta_allocdscr = UDF_ICB_SHORT_ALLOC; - if (n_pm > 1) { - ump->data_allocdscr = UDF_ICB_LONG_ALLOC; - ump->meta_allocdscr = UDF_ICB_LONG_ALLOC; - /* metadata partitions are forced to have short */ - if (n_meta) - ump->meta_allocdscr = UDF_ICB_SHORT_ALLOC; - } - /* determine logical volume open/closure actions */ if (n_virt) { ump->lvopen = 0; @@ -1992,10 +1995,12 @@ udf_process_vds(struct udf_mount *ump) { ump->strategy = &udf_strat_rmw; /* print results */ - DPRINTF(VOLUMES, ("\tdata alloc scheme %d, meta alloc scheme %d\n", - ump->data_alloc, ump->meta_alloc)); - DPRINTF(VOLUMES, ("\tdata partition %d, metadata partition %d\n", - ump->data_part, ump->metadata_part)); + DPRINTF(VOLUMES, ("\tdata partition %d\n", ump->data_part)); + DPRINTF(VOLUMES, ("\t\talloc scheme %d\n", ump->vtop_alloc[ump->data_part])); + DPRINTF(VOLUMES, ("\tnode partition %d\n", ump->node_part)); + DPRINTF(VOLUMES, ("\t\talloc scheme %d\n", ump->vtop_alloc[ump->node_part])); + DPRINTF(VOLUMES, ("\tfids partition %d\n", ump->fids_part)); + DPRINTF(VOLUMES, ("\t\talloc scheme %d\n", ump->vtop_alloc[ump->fids_part])); bitmask_snprintf(ump->lvopen, UDFLOGVOL_BITS, bits, sizeof(bits)); DPRINTF(VOLUMES, ("\tactions on logvol open %s\n", bits)); @@ -3073,7 +3078,7 @@ udf_read_metadata_nodes(struct udf_mount *ump, union udf_pmap *mapping) } else { /* mounting read/write */ /* XXX DISABLED! metadata writing is not working yet XXX */ -/* if (error) */ + if (error) error = EROFS; } DPRINTFIF(VOLUMES, error, ("udf mount: failed to read " @@ -3471,11 +3476,10 @@ udf_close_logvol(struct udf_mount *ump, int mntflags) if (ump->lvclose & UDF_WRITE_VAT) { DPRINTF(VOLUMES, ("lvclose & UDF_WRITE_VAT\n")); - /* preprocess the VAT node; its modified on every writeout */ - DPRINTF(VOLUMES, ("writeout vat_node\n")); - udf_update_vat_descriptor(ump->vat_node->ump); - /* write out the VAT node */ + DPRINTF(VOLUMES, ("writeout vat_node\n")); + udf_writeout_vat(ump); + vflushbuf(ump->vat_node->vnode, 1 /* sync */); for (n = 0; n < 16; n++) { ump->vat_node->i_flags |= IN_MODIFIED; @@ -5421,7 +5425,6 @@ udf_get_node(struct udf_mount *ump, struct long_ad *node_icb_loc, /* --------------------------------------------------------------------- */ - int udf_writeout_node(struct udf_node *udf_node, int waitfor) { @@ -5453,7 +5456,7 @@ udf_writeout_node(struct udf_node *udf_node, int waitfor) /* if we were rebuild, write out the allocation extents */ if (udf_node->i_flags & IN_NODE_REBUILD) { - /* mark outstanding node dscriptors and issue them */ + /* mark outstanding node descriptors and issue them */ udf_node->outstanding_nodedscr += udf_node->num_extensions; for (extnr = 0; extnr < udf_node->num_extensions; extnr++) { loc = &udf_node->ext_loc[extnr]; @@ -5467,9 +5470,11 @@ udf_writeout_node(struct udf_node *udf_node, int waitfor) } if (udf_node->fe) { + KASSERT(udf_node->efe == NULL); dscr = (union dscrptr *) udf_node->fe; } else { KASSERT(udf_node->efe); + KASSERT(udf_node->fe == NULL); dscr = (union dscrptr *) udf_node->efe; } KASSERT(dscr); @@ -5589,8 +5594,9 @@ udf_create_node_raw(struct vnode *dvp, struct vnode **vpp, int udf_file_type, } /* get disc allocation for one logical block */ + vpart_num = ump->node_part; error = udf_pre_allocate_space(ump, UDF_C_NODE, 1, - &vpart_num, &lmapping); + vpart_num, &lmapping); lb_num = lmapping; if (error) { vlockmgr(nvp->v_vnlock, LK_RELEASE); @@ -5953,6 +5959,7 @@ int udf_update(struct vnode *vp, struct timespec *acc, struct timespec *mod, struct timespec *birth, int updflags) { + union dscrptr *dscrptr; struct udf_node *udf_node = VTOI(vp); struct udf_mount *ump = udf_node->ump; struct regid *impl_id; @@ -5973,13 +5980,20 @@ udf_update(struct vnode *vp, struct timespec *acc, /* set our implementation id */ if (udf_node->fe) { + dscrptr = (union dscrptr *) udf_node->fe; impl_id = &udf_node->fe->imp_id; } else { + dscrptr = (union dscrptr *) udf_node->efe; impl_id = &udf_node->efe->imp_id; } + + /* set our ID */ udf_set_regid(impl_id, IMPL_NAME); udf_add_impl_regid(ump, impl_id); + /* update our crc! on RMW we are not allowed to change a thing */ + udf_validate_tag_and_crc_sums(dscrptr); + /* if called when mounted readonly, never write back */ if (vp->v_mount->mnt_flag & MNT_RDONLY) return 0; diff --git a/sys/fs/udf/udf_subr.h b/sys/fs/udf/udf_subr.h index f77232a31288..d727abe90258 100644 --- a/sys/fs/udf/udf_subr.h +++ b/sys/fs/udf/udf_subr.h @@ -1,4 +1,4 @@ -/* $NetBSD: udf_subr.h,v 1.11 2008/07/28 19:41:13 reinoud Exp $ */ +/* $NetBSD: udf_subr.h,v 1.12 2008/08/06 13:41:12 reinoud Exp $ */ /* * Copyright (c) 2006, 2008 Reinoud Zandijk @@ -107,7 +107,7 @@ int udf_vat_write(struct udf_node *vat_node, uint8_t *blob, int size, uint32_t o /* disc allocation */ void udf_late_allocate_buf(struct udf_mount *ump, struct buf *buf, uint64_t *lmapping, struct long_ad *node_ad_cpy, uint16_t *vpart_num); void udf_free_allocated_space(struct udf_mount *ump, uint32_t lb_num, uint16_t vpart_num, uint32_t num_lb); -int udf_pre_allocate_space(struct udf_mount *ump, int udf_c_type, int num_lb, uint16_t *alloc_partp, uint64_t *lmapping); +int udf_pre_allocate_space(struct udf_mount *ump, int udf_c_type, uint32_t num_lb, uint16_t vpartnr, uint64_t *lmapping); int udf_grow_node(struct udf_node *node, uint64_t new_size); int udf_shrink_node(struct udf_node *node, uint64_t new_size); diff --git a/sys/fs/udf/udf_vfsops.c b/sys/fs/udf/udf_vfsops.c index ca96fd7a88a0..9c9cfa4e5eb2 100644 --- a/sys/fs/udf/udf_vfsops.c +++ b/sys/fs/udf/udf_vfsops.c @@ -1,4 +1,4 @@ -/* $NetBSD: udf_vfsops.c,v 1.46 2008/07/28 19:41:13 reinoud Exp $ */ +/* $NetBSD: udf_vfsops.c,v 1.47 2008/08/06 13:41:12 reinoud Exp $ */ /* * Copyright (c) 2006, 2008 Reinoud Zandijk @@ -28,7 +28,7 @@ #include #ifndef lint -__KERNEL_RCSID(0, "$NetBSD: udf_vfsops.c,v 1.46 2008/07/28 19:41:13 reinoud Exp $"); +__KERNEL_RCSID(0, "$NetBSD: udf_vfsops.c,v 1.47 2008/08/06 13:41:12 reinoud Exp $"); #endif /* not lint */ @@ -886,11 +886,42 @@ udf_statvfs(struct mount *mp, struct statvfs *sbp) * i.e. explicit syncing by the user? */ +static int +udf_sync_writeout_system_files(struct udf_mount *ump, int clearflags) +{ + int error; + + /* XXX lock for VAT en bitmaps? */ + /* metadata nodes are written synchronous */ + DPRINTF(CALL, ("udf_sync: syncing metadata\n")); + if (ump->lvclose & UDF_WRITE_VAT) + udf_writeout_vat(ump); + + error = 0; + if (ump->lvclose & UDF_WRITE_PART_BITMAPS) { + /* writeout metadata spacetable if existing */ + error = udf_write_metadata_partition_spacetable(ump, MNT_WAIT); + if (error) + printf( "udf_writeout_system_files : " + " writeout of metadata space bitmap failed\n"); + + /* writeout partition spacetables */ + error = udf_write_physical_partition_spacetables(ump, MNT_WAIT); + if (error) + printf( "udf_writeout_system_files : " + "writeout of space tables failed\n"); + if (!error && clearflags) + ump->lvclose &= ~UDF_WRITE_PART_BITMAPS; + } + + return error; +} + + int udf_sync(struct mount *mp, int waitfor, kauth_cred_t cred) { struct udf_mount *ump = VFSTOUDF(mp); - int error; DPRINTF(CALL, ("udf_sync called\n")); /* if called when mounted readonly, just ignore */ @@ -908,33 +939,8 @@ udf_sync(struct mount *mp, int waitfor, kauth_cred_t cred) /* pre-sync */ udf_do_sync(ump, cred, waitfor); - error = 0; -#if 0 - if (waitfor == MNT_WAIT) { - /* XXX lock for VAT en bitmaps? */ - /* metadata nodes are written synchronous */ - DPRINTF(CALL, ("udf_sync: syncing metadata\n")); - if (ump->lvclose & UDF_WRITE_VAT) - udf_writeout_vat(ump); - - if (ump->lvclose & UDF_WRITE_PART_BITMAPS) { - /* writeout metadata spacetable if existing */ - error = udf_write_metadata_partition_spacetable(ump, - waitfor); - if (error) - printf( "udf_sync: writeout of metadata space " - "bitmap failed\n"); - - /* writeout partition spacetables */ - error = udf_write_physical_partition_spacetables(ump, - waitfor); - if (error) - printf( "udf_sync: writeout of space tables " - "failed\n"); - ump->lvclose &= ~UDF_WRITE_PART_BITMAPS; - } - } -#endif + if (waitfor == MNT_WAIT) + udf_sync_writeout_system_files(ump, true); DPRINTF(CALL, ("end of udf_sync()\n")); ump->syncing = 0;