Support for allocation extents descriptor writing to allow for arbitrary

heavily fragmented files.

Also fixing some (rare) allocation bugs and function name streamlining.

Tested on harddisc, CD-RW and CD-R i.e. all three basic backend classes.
This commit is contained in:
reinoud 2008-07-07 18:45:26 +00:00
parent a25c030645
commit 4d5c88faa5
8 changed files with 401 additions and 197 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf.h,v 1.16 2008/07/03 19:29:42 reinoud Exp $ */
/* $NetBSD: udf.h,v 1.17 2008/07/07 18:45:26 reinoud Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@ -64,12 +64,13 @@ extern int udf_verbose;
#define UDF_DEBUG_EXTATTR 0x002000
#define UDF_DEBUG_ALLOC 0x004000
#define UDF_DEBUG_ADWLK 0x008000
#define UDF_DEBUG_NOTIMPL 0x010000
#define UDF_DEBUG_SHEDULE 0x020000
#define UDF_DEBUG_ECCLINE 0x040000
#define UDF_DEBUG_SYNC 0x080000
#define UDF_DEBUG_PARANOIA 0x100000
#define UDF_DEBUG_NODEDUMP 0x200000
#define UDF_DEBUG_PARANOIDADWLK 0x010000
#define UDF_DEBUG_NOTIMPL 0x020000
#define UDF_DEBUG_SHEDULE 0x040000
#define UDF_DEBUG_ECCLINE 0x080000
#define UDF_DEBUG_SYNC 0x100000
#define UDF_DEBUG_PARANOIA 0x200000
#define UDF_DEBUG_NODEDUMP 0x400000
/* initial value of udf_verbose */
#define UDF_DEBUGGING 0

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_allocation.c,v 1.10 2008/07/03 18:03:01 reinoud Exp $ */
/* $NetBSD: udf_allocation.c,v 1.11 2008/07/07 18:45:26 reinoud Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_allocation.c,v 1.10 2008/07/03 18:03:01 reinoud Exp $");
__KERNEL_RCSID(0, "$NetBSD: udf_allocation.c,v 1.11 2008/07/07 18:45:26 reinoud Exp $");
#endif /* not lint */
@ -86,7 +86,7 @@ static void udf_record_allocation_in_node(struct udf_mount *ump,
*/
/* --------------------------------------------------------------------- */
//#ifdef DEBUG
#if 1
#if 1
static void
@ -94,14 +94,13 @@ udf_node_dump(struct udf_node *udf_node) {
struct file_entry *fe;
struct extfile_entry *efe;
struct icb_tag *icbtag;
struct short_ad *short_ad;
struct long_ad *long_ad;
struct long_ad s_ad;
uint64_t inflen;
uint32_t icbflags, addr_type, max_l_ad;
uint32_t icbflags, addr_type;
uint32_t len, lb_num;
uint8_t *data_pos;
uint32_t flags;
int part_num;
int adlen, ad_off, dscr_size, l_ea, l_ad, lb_size, flags;
int lb_size, eof, slot;
if ((udf_verbose & UDF_DEBUG_NODEDUMP) == 0)
return;
@ -113,57 +112,35 @@ udf_node_dump(struct udf_node *udf_node) {
if (fe) {
icbtag = &fe->icbtag;
inflen = udf_rw64(fe->inf_len);
dscr_size = sizeof(struct file_entry) -1;
l_ea = udf_rw32(fe->l_ea);
l_ad = udf_rw32(fe->l_ad);
data_pos = (uint8_t *) fe + dscr_size + l_ea;
} else {
icbtag = &efe->icbtag;
inflen = udf_rw64(efe->inf_len);
dscr_size = sizeof(struct extfile_entry) -1;
l_ea = udf_rw32(efe->l_ea);
l_ad = udf_rw32(efe->l_ad);
data_pos = (uint8_t *) efe + 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;
printf("udf_node_dump:\n");
printf("\tudf_node %p\n", udf_node);
printf("udf_node_dump %p :\n", udf_node);
if (addr_type == UDF_ICB_INTERN_ALLOC) {
printf("\t\tIntern alloc, len = %"PRIu64"\n", inflen);
printf("\tIntern alloc, len = %"PRIu64"\n", inflen);
return;
}
printf("\t\tInflen = %"PRIu64"\n", inflen);
printf("\t\tl_ad = %d\n", l_ad);
if (addr_type == UDF_ICB_SHORT_ALLOC) {
adlen = sizeof(struct short_ad);
} else {
adlen = sizeof(struct long_ad);
}
printf("\tInflen = %"PRIu64"\n", inflen);
printf("\t\t");
for (ad_off = 0; ad_off < l_ad; ad_off += adlen) {
if (addr_type == UDF_ICB_SHORT_ALLOC) {
short_ad = (struct short_ad *) (data_pos + ad_off);
len = udf_rw32(short_ad->len);
lb_num = udf_rw32(short_ad->lb_num);
part_num = -1;
flags = UDF_EXT_FLAGS(len);
len = UDF_EXT_LEN(len);
} else {
long_ad = (struct long_ad *) (data_pos + ad_off);
len = udf_rw32(long_ad->len);
lb_num = udf_rw32(long_ad->loc.lb_num);
part_num = udf_rw16(long_ad->loc.part_num);
flags = UDF_EXT_FLAGS(len);
len = UDF_EXT_LEN(len);
}
slot = 0;
for (;;) {
udf_get_adslot(udf_node, slot, &s_ad, &eof);
if (eof)
break;
part_num = udf_rw16(s_ad.loc.part_num);
lb_num = udf_rw32(s_ad.loc.lb_num);
len = udf_rw32(s_ad.len);
flags = UDF_EXT_FLAGS(len);
len = UDF_EXT_LEN(len);
printf("[");
if (part_num >= 0)
printf("part %d, ", part_num);
@ -171,10 +148,14 @@ udf_node_dump(struct udf_node *udf_node) {
if (flags)
printf(", flags %d", flags>>30);
printf("] ");
if (ad_off + adlen == l_ad)
printf("\n\t\tl_ad END\n\t\t");
if (flags == UDF_EXT_REDIRECT) {
printf("\n\textent END\n\tallocation extent\n\t\t");
}
slot++;
}
printf("\n");
printf("\n\tl_ad END\n\n");
}
#else
#define udf_node_dump(a)
@ -258,14 +239,13 @@ udf_node_sanity_check(struct udf_node *udf_node,
struct file_entry *fe;
struct extfile_entry *efe;
struct icb_tag *icbtag;
struct short_ad *short_ad;
struct long_ad *long_ad;
struct long_ad s_ad;
uint64_t inflen, logblksrec;
uint32_t icbflags, addr_type, max_l_ad;
uint32_t len, lb_num;
uint8_t *data_pos;
uint32_t icbflags, addr_type;
uint32_t len, lb_num, l_ea, l_ad, max_l_ad;
uint16_t part_num;
int adlen, ad_off, dscr_size, l_ea, l_ad, lb_size, flags, whole_lb;
int dscr_size, lb_size, flags, whole_lb;
int slot, eof;
// KASSERT(mutex_owned(&udf_node->ump->allocate_mutex));
@ -279,21 +259,19 @@ udf_node_sanity_check(struct udf_node *udf_node,
if (fe) {
icbtag = &fe->icbtag;
inflen = udf_rw64(fe->inf_len);
logblksrec = udf_rw64(fe->logblks_rec);
dscr_size = sizeof(struct file_entry) -1;
l_ea = udf_rw32(fe->l_ea);
logblksrec = udf_rw64(fe->logblks_rec);
l_ad = udf_rw32(fe->l_ad);
data_pos = (uint8_t *) fe + dscr_size + l_ea;
l_ea = udf_rw32(fe->l_ea);
} else {
icbtag = &efe->icbtag;
inflen = udf_rw64(efe->inf_len);
logblksrec = udf_rw64(efe->logblks_rec);
dscr_size = sizeof(struct extfile_entry) -1;
l_ea = udf_rw32(efe->l_ea);
logblksrec = udf_rw64(efe->logblks_rec);
l_ad = udf_rw32(efe->l_ad);
data_pos = (uint8_t *) efe + dscr_size + l_ea;
l_ea = udf_rw32(efe->l_ea);
}
max_l_ad = lb_size - 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;
@ -308,31 +286,21 @@ udf_node_sanity_check(struct udf_node *udf_node,
return;
}
if (addr_type == UDF_ICB_SHORT_ALLOC) {
adlen = sizeof(struct short_ad);
} else {
adlen = sizeof(struct long_ad);
}
/* start counting */
whole_lb = 1;
for (ad_off = 0; ad_off < l_ad; ad_off += adlen) {
slot = 0;
for (;;) {
udf_get_adslot(udf_node, slot, &s_ad, &eof);
if (eof)
break;
KASSERT(whole_lb == 1);
if (addr_type == UDF_ICB_SHORT_ALLOC) {
short_ad = (struct short_ad *) (data_pos + ad_off);
len = udf_rw32(short_ad->len);
lb_num = udf_rw32(short_ad->lb_num);
part_num = udf_rw16(udf_node->loc.loc.part_num);
flags = UDF_EXT_FLAGS(len);
len = UDF_EXT_LEN(len);
} else {
long_ad = (struct long_ad *) (data_pos + ad_off);
len = udf_rw32(long_ad->len);
lb_num = udf_rw32(long_ad->loc.lb_num);
part_num = udf_rw16(long_ad->loc.part_num);
flags = UDF_EXT_FLAGS(len);
len = UDF_EXT_LEN(len);
}
part_num = udf_rw16(s_ad.loc.part_num);
lb_num = udf_rw32(s_ad.loc.lb_num);
len = udf_rw32(s_ad.len);
flags = UDF_EXT_FLAGS(len);
len = UDF_EXT_LEN(len);
if (flags != UDF_EXT_REDIRECT) {
*cnt_inflen += len;
if (flags == UDF_EXT_ALLOCATED) {
@ -348,6 +316,8 @@ udf_node_sanity_check(struct udf_node *udf_node,
/* check whole lb */
whole_lb = ((len % lb_size) == 0);
slot++;
}
/* rest should be zero (ad_off > l_ad < max_l_ad - adlen) */
@ -1280,6 +1250,7 @@ udf_wipe_adslots(struct udf_node *udf_node)
for (extnr = 0; extnr < udf_node->num_extensions; extnr++) {
ext = udf_node->ext[extnr];
dscr_size = sizeof(struct alloc_ext_entry) -1;
data_pos = (uint8_t *) ext->data;
max_l_ad = lb_size - dscr_size;
memset(data_pos, 0, max_l_ad);
ext->l_ad = udf_rw32(0);
@ -1287,6 +1258,7 @@ udf_wipe_adslots(struct udf_node *udf_node)
crclen = dscr_size - UDF_DESC_TAG_LENGTH;
ext->tag.desc_crc_len = udf_rw32(crclen);
}
udf_node->i_flags |= IN_NODE_REBUILD;
}
/* --------------------------------------------------------------------- */
@ -1299,9 +1271,9 @@ udf_get_adslot(struct udf_node *udf_node, int slot, struct long_ad *icb,
struct alloc_ext_entry *ext;
struct icb_tag *icbtag;
struct short_ad *short_ad;
struct long_ad *long_ad;
struct long_ad *long_ad, l_icb;
uint32_t offset;
uint32_t lb_size, dscr_size, l_ea, l_ad, max_l_ad;
uint32_t lb_size, dscr_size, l_ea, l_ad, flags;
uint8_t *data_pos;
int icbflags, addr_type, adlen, extnr;
@ -1323,7 +1295,6 @@ udf_get_adslot(struct udf_node *udf_node, int slot, struct long_ad *icb,
l_ad = udf_rw32(efe->l_ad);
data_pos = (uint8_t *) efe + 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;
@ -1345,22 +1316,42 @@ udf_get_adslot(struct udf_node *udf_node, int slot, struct long_ad *icb,
/* if offset too big, we go to the allocation extensions */
offset = slot * adlen;
extnr = -1;
while (offset >= max_l_ad) {
extnr++;
offset -= max_l_ad;
ext = udf_node->ext[extnr];
dscr_size = sizeof(struct alloc_ext_entry) -1;
l_ad = udf_rw32(ext->l_ad);
max_l_ad = lb_size - dscr_size;
data_pos = (uint8_t *) ext + dscr_size;
if (extnr > udf_node->num_extensions) {
while (offset >= l_ad) {
/* check if our last entry is a redirect */
if (addr_type == UDF_ICB_SHORT_ALLOC) {
short_ad = (struct short_ad *) (data_pos + l_ad-adlen);
l_icb.len = short_ad->len;
l_icb.loc.part_num = udf_node->loc.loc.part_num;
l_icb.loc.lb_num = short_ad->lb_num;
} else {
KASSERT(addr_type == UDF_ICB_LONG_ALLOC);
long_ad = (struct long_ad *) (data_pos + l_ad-adlen);
l_icb = *long_ad;
}
flags = UDF_EXT_FLAGS(udf_rw32(l_icb.len));
if (flags != UDF_EXT_REDIRECT) {
l_ad = 0; /* force EOF */
break;
}
/* advance to next extent */
extnr++;
if (extnr >= udf_node->num_extensions) {
l_ad = 0; /* force EOF */
break;
}
offset = offset - l_ad;
ext = udf_node->ext[extnr];
dscr_size = sizeof(struct alloc_ext_entry) -1;
l_ad = udf_rw32(ext->l_ad);
data_pos = (uint8_t *) ext + dscr_size;
}
/* XXX l_ad == 0 should be enough to check */
*eof = (offset >= l_ad) || (l_ad == 0);
if (*eof) {
DPRINTF(PARANOIDADWLK, ("returning EOF, extnr %d, offset %d, "
"l_ad %d\n", extnr, offset, l_ad));
memset(icb, 0, sizeof(struct long_ad));
return;
}
@ -1375,27 +1366,35 @@ udf_get_adslot(struct udf_node *udf_node, int slot, struct long_ad *icb,
long_ad = (struct long_ad *) (data_pos + offset);
*icb = *long_ad;
}
DPRINTF(PARANOIDADWLK, ("returning element : v %d, lb %d, len %d, "
"flags %d\n", icb->loc.part_num, icb->loc.lb_num,
UDF_EXT_LEN(icb->len), UDF_EXT_FLAGS(icb->len)));
}
/* --------------------------------------------------------------------- */
int
udf_append_adslot(struct udf_node *udf_node, int slot, struct long_ad *icb) {
udf_append_adslot(struct udf_node *udf_node, int *slot, struct long_ad *icb) {
struct udf_mount *ump = udf_node->ump;
union dscrptr *dscr;
struct file_entry *fe;
struct extfile_entry *efe;
struct alloc_ext_entry *ext;
struct icb_tag *icbtag;
struct short_ad *short_ad;
struct long_ad *long_ad, o_icb;
struct long_ad *long_ad, o_icb, l_icb;
uint64_t logblks_rec, *logblks_rec_p;
uint32_t offset, rest, len;
uint64_t lmapping, pmapping;
uint32_t offset, rest, len, lb_num;
uint32_t lb_size, dscr_size, l_ea, l_ad, *l_ad_p, max_l_ad, crclen;
uint32_t flags;
uint16_t vpart_num;
uint8_t *data_pos;
int icbflags, addr_type, adlen, extnr;
int error;
/* determine what descriptor we are in */
lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size);
lb_size = udf_rw32(ump->logical_vol->lb_size);
fe = udf_node->fe;
efe = udf_node->efe;
@ -1436,7 +1435,8 @@ udf_append_adslot(struct udf_node *udf_node, int slot, struct long_ad *icb) {
/* clean up given long_ad */
#ifdef DIAGNOSTIC
if (UDF_EXT_FLAGS(udf_rw32(icb->len)) == UDF_EXT_FREE) {
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");
@ -1446,29 +1446,49 @@ udf_append_adslot(struct udf_node *udf_node, int slot, struct long_ad *icb) {
#endif
/* if offset too big, we go to the allocation extensions */
offset = slot * adlen;
extnr = 0;
while (offset > max_l_ad) {
offset -= max_l_ad;
l_ad = udf_rw32(*l_ad_p);
offset = (*slot) * adlen;
extnr = -1;
while (offset >= l_ad) {
/* check if our last entry is a redirect */
if (addr_type == UDF_ICB_SHORT_ALLOC) {
short_ad = (struct short_ad *) (data_pos + l_ad-adlen);
l_icb.len = short_ad->len;
l_icb.loc.part_num = udf_node->loc.loc.part_num;
l_icb.loc.lb_num = short_ad->lb_num;
} else {
KASSERT(addr_type == UDF_ICB_LONG_ALLOC);
long_ad = (struct long_ad *) (data_pos + l_ad-adlen);
l_icb = *long_ad;
}
flags = UDF_EXT_FLAGS(udf_rw32(l_icb.len));
if (flags != UDF_EXT_REDIRECT) {
/* only one past the last one is adressable */
break;
}
/* advance to next extent */
extnr++;
KASSERT(extnr < udf_node->num_extensions);
offset = offset - l_ad;
ext = udf_node->ext[extnr];
dscr = (union dscrptr *) ext;
dscr_size = sizeof(struct alloc_ext_entry) -1;
KASSERT(ext != NULL);
l_ad_p = &ext->l_ad;
max_l_ad = lb_size - dscr_size;
data_pos = (uint8_t *) dscr + dscr_size;
extnr++;
l_ad_p = &ext->l_ad;
l_ad = udf_rw32(*l_ad_p);
data_pos = (uint8_t *) ext + dscr_size;
}
DPRINTF(PARANOIDADWLK, ("append, ext %d, offset %d, l_ad %d\n",
extnr, offset, udf_rw32(*l_ad_p)));
KASSERT(l_ad == udf_rw32(*l_ad_p));
/* offset is offset within the current (E)FE/AED */
l_ad = udf_rw32(*l_ad_p);
crclen = udf_rw32(dscr->tag.desc_crc_len);
logblks_rec = udf_rw64(*logblks_rec_p);
if (extnr > udf_node->num_extensions)
return EFBIG; /* too fragmented */
/* overwriting old piece? */
if (offset < l_ad) {
/* overwrite entry; compensate for the old element */
@ -1492,15 +1512,83 @@ udf_append_adslot(struct udf_node *udf_node, int slot, struct long_ad *icb) {
}
}
/* calculate rest space in this descriptor */
rest = max_l_ad - offset;
/* check if we're not appending a redirection */
flags = UDF_EXT_FLAGS(udf_rw32(icb->len));
KASSERT(flags != UDF_EXT_REDIRECT);
/* round down available space */
rest = adlen * ((max_l_ad - offset) / adlen);
if (rest <= adlen) {
/* create redirect and link new allocation extension */
printf("udf_append_to_adslot: can't create allocation extention yet\n");
return EFBIG;
/* have to append aed, see if we already have a spare one */
extnr++;
ext = udf_node->ext[extnr];
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, &pmapping);
lb_num = lmapping;
if (error)
return error;
/* initialise pointer to location */
memset(&l_icb, 0, sizeof(struct long_ad));
l_icb.len = udf_rw32(lb_size | UDF_EXT_REDIRECT);
l_icb.loc.lb_num = udf_rw32(lb_num);
l_icb.loc.part_num = udf_rw16(vpart_num);
/* create new aed descriptor */
udf_create_logvol_dscr(ump, udf_node, &l_icb,
(union dscrptr **) &ext);
udf_inittag(ump, &ext->tag, TAGID_ALLOCEXTENT, lb_num);
dscr_size = sizeof(struct alloc_ext_entry) -1;
max_l_ad = lb_size - dscr_size;
memset(ext->data, 0, max_l_ad);
ext->l_ad = udf_rw32(0);
ext->tag.desc_crc_len =
udf_rw32(dscr_size - UDF_DESC_TAG_LENGTH);
/* declare aed */
udf_node->num_extensions++;
udf_node->ext_loc[extnr] = l_icb;
udf_node->ext[extnr] = ext;
}
/* add redirect and adjust l_ad and crclen for old descr */
if (addr_type == UDF_ICB_SHORT_ALLOC) {
short_ad = (struct short_ad *) (data_pos + offset);
short_ad->len = l_icb.len;
short_ad->lb_num = l_icb.loc.lb_num;
} else if (addr_type == UDF_ICB_LONG_ALLOC) {
long_ad = (struct long_ad *) (data_pos + offset);
*long_ad = l_icb;
}
l_ad += adlen;
crclen += adlen;
dscr->tag.desc_crc_len = udf_rw32(crclen);
*l_ad_p = udf_rw32(l_ad);
/* advance to the new extension */
KASSERT(ext != NULL);
dscr = (union dscrptr *) ext;
dscr_size = sizeof(struct alloc_ext_entry) -1;
max_l_ad = lb_size - dscr_size;
data_pos = (uint8_t *) dscr + dscr_size;
l_ad_p = &ext->l_ad;
l_ad = udf_rw32(*l_ad_p);
crclen = udf_rw32(dscr->tag.desc_crc_len);
offset = 0;
/* adjust callees slot count for link insert */
*slot += 1;
}
/* write out the element */
DPRINTF(PARANOIDADWLK, ("adding element : %p : v %d, lb %d, "
"len %d, flags %d\n", data_pos + offset,
icb->loc.part_num, icb->loc.lb_num,
UDF_EXT_LEN(icb->len), UDF_EXT_FLAGS(icb->len)));
if (addr_type == UDF_ICB_SHORT_ALLOC) {
short_ad = (struct short_ad *) (data_pos + offset);
short_ad->len = icb->len;
@ -1511,7 +1599,8 @@ udf_append_adslot(struct udf_node *udf_node, int slot, struct long_ad *icb) {
}
/* adjust logblks recorded count */
if (UDF_EXT_FLAGS(icb->len) == UDF_EXT_ALLOCATED)
flags = UDF_EXT_FLAGS(udf_rw32(icb->len));
if (flags == UDF_EXT_ALLOCATED)
logblks_rec += (UDF_EXT_LEN(icb->len) + lb_size -1) / lb_size;
*logblks_rec_p = udf_rw64(logblks_rec);
@ -1526,6 +1615,65 @@ udf_append_adslot(struct udf_node *udf_node, int slot, struct long_ad *icb) {
return 0;
}
/* --------------------------------------------------------------------- */
static void
udf_count_alloc_exts(struct udf_node *udf_node)
{
struct long_ad s_ad;
uint32_t lb_num, len, flags;
uint16_t vpart_num;
int slot, eof;
int num_extents, extnr;
int lb_size;
if (udf_node->num_extensions == 0)
return;
lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size);
/* count number of allocation extents in use */
num_extents = 0;
slot = 0;
for (;;) {
udf_get_adslot(udf_node, slot, &s_ad, &eof);
if (eof)
break;
len = udf_rw32(s_ad.len);
flags = UDF_EXT_FLAGS(len);
if (flags == UDF_EXT_REDIRECT)
num_extents++;
slot++;
}
DPRINTF(ALLOC, ("udf_count_alloc_ext counted %d live extents\n",
num_extents));
/* XXX choice: we could delay freeing them on node writeout */
/* free excess entries */
extnr = num_extents;
for (;extnr < udf_node->num_extensions; extnr++) {
DPRINTF(ALLOC, ("freeing alloc ext %d\n", extnr));
/* free dscriptor */
s_ad = udf_node->ext_loc[extnr];
udf_free_logvol_dscr(udf_node->ump, &s_ad,
udf_node->ext[extnr]);
udf_node->ext[extnr] = NULL;
/* free disc space */
lb_num = udf_rw32(s_ad.loc.lb_num);
vpart_num = udf_rw16(s_ad.loc.part_num);
udf_free_allocated_space(udf_node->ump, lb_num, vpart_num, 1);
memset(&udf_node->ext_loc[extnr], 0, sizeof(struct long_ad));
}
/* set our new number of allocation extents */
udf_node->num_extensions = num_extents;
}
/* --------------------------------------------------------------------- */
/*
@ -1855,7 +2003,7 @@ udf_record_allocation_in_node(struct udf_mount *ump, struct buf *buf,
UDF_EXT_LEN(udf_rw32(c_ad.len)),
UDF_EXT_FLAGS(udf_rw32(c_ad.len)) >> 30));
error = udf_append_adslot(udf_node, slot, &c_ad);
error = udf_append_adslot(udf_node, &slot, &c_ad);
if (error) {
buf->b_error = error;
goto out;
@ -1874,7 +2022,7 @@ udf_record_allocation_in_node(struct udf_mount *ump, struct buf *buf,
UDF_EXT_LEN(udf_rw32(c_ad.len)),
UDF_EXT_FLAGS(udf_rw32(c_ad.len)) >> 30));
error = udf_append_adslot(udf_node, slot, &c_ad);
error = udf_append_adslot(udf_node, &slot, &c_ad);
if (error) {
buf->b_error = error;
goto out;
@ -1882,6 +2030,8 @@ udf_record_allocation_in_node(struct udf_mount *ump, struct buf *buf,
}
out:
udf_count_alloc_exts(udf_node);
/* the node's descriptors should now be sane */
udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec);
UDF_UNLOCK_NODE(udf_node, 0);
@ -2094,7 +2244,7 @@ udf_grow_node(struct udf_node *udf_node, uint64_t new_size)
if (udf_ads_merge(lb_size, &c_ad, &s_ad)) {
/* not mergable (anymore) */
error = udf_append_adslot(udf_node, slot, &c_ad);
error = udf_append_adslot(udf_node, &slot, &c_ad);
if (error)
goto errorout;
slot++;
@ -2106,7 +2256,7 @@ udf_grow_node(struct udf_node *udf_node, uint64_t new_size)
/* if there is a rest piece in the accumulator, append it */
if (UDF_EXT_LEN(udf_rw32(c_ad.len)) > 0) {
error = udf_append_adslot(udf_node, slot, &c_ad);
error = udf_append_adslot(udf_node, &slot, &c_ad);
if (error)
goto errorout;
slot++;
@ -2114,7 +2264,7 @@ udf_grow_node(struct udf_node *udf_node, uint64_t new_size)
/* if there is a rest piece that didn't fit, append it */
if (UDF_EXT_LEN(udf_rw32(s_ad.len)) > 0) {
error = udf_append_adslot(udf_node, slot, &s_ad);
error = udf_append_adslot(udf_node, &slot, &s_ad);
if (error)
goto errorout;
slot++;
@ -2146,6 +2296,8 @@ errorout:
if (evacuated_data)
free(evacuated_data, M_UDFTEMP);
udf_count_alloc_exts(udf_node);
udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec);
UDF_UNLOCK_NODE(udf_node, 0);
@ -2444,7 +2596,7 @@ udf_shrink_node(struct udf_node *udf_node, uint64_t new_size)
UDF_EXT_LEN(udf_rw32(c_ad.len)),
UDF_EXT_FLAGS(udf_rw32(c_ad.len)) >> 30));
error = udf_append_adslot(udf_node, slot, &c_ad);
error = udf_append_adslot(udf_node, &slot, &c_ad);
if (error)
goto errorout; /* panic? */
c_ad = s_ad;
@ -2461,7 +2613,7 @@ udf_shrink_node(struct udf_node *udf_node, uint64_t new_size)
UDF_EXT_LEN(udf_rw32(c_ad.len)),
UDF_EXT_FLAGS(udf_rw32(c_ad.len)) >> 30));
error = udf_append_adslot(udf_node, slot, &c_ad);
error = udf_append_adslot(udf_node, &slot, &c_ad);
if (error)
goto errorout; /* panic? */
;
@ -2483,6 +2635,8 @@ udf_shrink_node(struct udf_node *udf_node, uint64_t new_size)
errorout:
free(node_ad_cpy, M_UDFMNT);
udf_count_alloc_exts(udf_node);
udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec);
UDF_UNLOCK_NODE(udf_node, 0);

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_strat_direct.c,v 1.1 2008/05/14 16:49:48 reinoud Exp $ */
/* $NetBSD: udf_strat_direct.c,v 1.2 2008/07/07 18:45:26 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.1 2008/05/14 16:49:48 reinoud Exp $");
__KERNEL_RCSID(0, "$NetBSD: udf_strat_direct.c,v 1.2 2008/07/07 18:45:26 reinoud Exp $");
#endif /* not lint */
@ -108,11 +108,6 @@ udf_wr_nodedscr_callback(struct buf *buf)
return;
}
/* XXX noone is waiting on this outstanding_nodedscr */
udf_node->outstanding_nodedscr--;
if (udf_node->outstanding_nodedscr == 0)
wakeup(&udf_node->outstanding_nodedscr);
/* XXX right flags to mark dirty again on error? */
if (buf->b_error) {
/* write error on `defect free' media??? how to solve? */
@ -120,10 +115,16 @@ udf_wr_nodedscr_callback(struct buf *buf)
udf_node->i_flags |= IN_MODIFIED | IN_ACCESSED;
}
/* first unlock the node */
KASSERT(udf_node->i_flags & IN_CALLBACK_ULK);
UDF_UNLOCK_NODE(udf_node, IN_CALLBACK_ULK);
/* decrement outstanding_nodedscr */
KASSERT(udf_node->outstanding_nodedscr >= 1);
udf_node->outstanding_nodedscr--;
if (udf_node->outstanding_nodedscr == 0) {
/* unlock the node */
KASSERT(udf_node->i_flags & IN_CALLBACK_ULK);
UDF_UNLOCK_NODE(udf_node, IN_CALLBACK_ULK);
wakeup(&udf_node->outstanding_nodedscr);
}
/* unreference the vnode so it can be recycled */
holdrele(udf_node->vnode);
@ -212,28 +213,33 @@ udf_write_nodedscr_direct(struct udf_strat_args *args)
sector = 0;
error = udf_translate_vtop(ump, icb, &sector, &dummy);
if (error)
return error;
goto out;
UDF_LOCK_NODE(udf_node, IN_CALLBACK_ULK);
/* add reference to the vnode to prevent recycling */
vhold(udf_node->vnode);
if (waitfor) {
DPRINTF(WRITE, ("udf_write_nodedscr: sync write\n"));
error = udf_write_phys_dscr_sync(ump, udf_node, UDF_C_NODE,
dscr, sector, logsector);
UDF_UNLOCK_NODE(udf_node, IN_CALLBACK_ULK);
} else {
DPRINTF(WRITE, ("udf_write_nodedscr: no wait, async write\n"));
/* add reference to the vnode to prevent recycling */
vhold(udf_node->vnode);
udf_node->outstanding_nodedscr++;
error = udf_write_phys_dscr_async(ump, udf_node, UDF_C_NODE,
dscr, sector, logsector, udf_wr_nodedscr_callback);
/* will be UNLOCKED in call back */
return error;
}
holdrele(udf_node->vnode);
out:
udf_node->outstanding_nodedscr--;
if (udf_node->outstanding_nodedscr == 0) {
UDF_UNLOCK_NODE(udf_node, 0);
wakeup(&udf_node->outstanding_nodedscr);
}
return error;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_strat_rmw.c,v 1.4 2008/06/17 14:14:05 reinoud Exp $ */
/* $NetBSD: udf_strat_rmw.c,v 1.5 2008/07/07 18:45:27 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.4 2008/06/17 14:14:05 reinoud Exp $");
__KERNEL_RCSID(0, "$NetBSD: udf_strat_rmw.c,v 1.5 2008/07/07 18:45:27 reinoud Exp $");
#endif /* not lint */
@ -505,7 +505,7 @@ udf_puteccline(struct udf_eccline *eccline)
/* --------------------------------------------------------------------- */
static int
udf_create_logvol_dscr_rmw(struct udf_strat_args *args)
udf_create_nodedscr_rmw(struct udf_strat_args *args)
{
union dscrptr **dscrptr = &args->dscr;
struct udf_mount *ump = args->ump;
@ -545,7 +545,7 @@ udf_create_logvol_dscr_rmw(struct udf_strat_args *args)
static void
udf_free_logvol_dscr_rmw(struct udf_strat_args *args)
udf_free_nodedscr_rmw(struct udf_strat_args *args)
{
struct udf_mount *ump = args->ump;
struct long_ad *icb = args->icb;
@ -573,7 +573,7 @@ udf_free_logvol_dscr_rmw(struct udf_strat_args *args)
static int
udf_read_logvol_dscr_rmw(struct udf_strat_args *args)
udf_read_nodedscr_rmw(struct udf_strat_args *args)
{
union dscrptr **dscrptr = &args->dscr;
struct udf_mount *ump = args->ump;
@ -660,7 +660,7 @@ udf_read_logvol_dscr_rmw(struct udf_strat_args *args)
static int
udf_write_logvol_dscr_rmw(struct udf_strat_args *args)
udf_write_nodedscr_rmw(struct udf_strat_args *args)
{
union dscrptr *dscrptr = args->dscr;
struct udf_mount *ump = args->ump;
@ -681,6 +681,9 @@ udf_write_logvol_dscr_rmw(struct udf_strat_args *args)
if (error)
return error;
/* add reference to the vnode to prevent recycling */
vhold(udf_node->vnode);
/* get our eccline */
eccline = udf_geteccline(ump, sectornr, 0);
eccsect = sectornr - eccline->start_sector;
@ -689,7 +692,7 @@ udf_write_logvol_dscr_rmw(struct udf_strat_args *args)
/* old callback still pending? */
if (eccline->bufs[eccsect]) {
DPRINTF(WRITE, ("udf_write_logvol_dscr_rmw: writing descriptor"
DPRINTF(WRITE, ("udf_write_nodedscr_rmw: writing descriptor"
" over buffer?\n"));
nestiobuf_done(eccline->bufs[eccsect],
eccline->bufs_len[eccsect],
@ -697,8 +700,6 @@ udf_write_logvol_dscr_rmw(struct udf_strat_args *args)
eccline->bufs[eccsect] = NULL;
}
UDF_LOCK_NODE(udf_node, IN_CALLBACK_ULK);
/* set sector number in the descriptor and validate */
dscrptr = (union dscrptr *)
(((uint8_t *) eccline->blob) + eccsect * sector_size);
@ -715,10 +716,16 @@ udf_write_logvol_dscr_rmw(struct udf_strat_args *args)
eccline->dirty |= bit;
KASSERT(udf_tagsize(dscrptr, sector_size) <= sector_size);
UDF_UNLOCK_NODE(udf_node, IN_CALLBACK_ULK);
udf_puteccline(eccline);
holdrele(udf_node->vnode);
udf_node->outstanding_nodedscr--;
if (udf_node->outstanding_nodedscr == 0) {
UDF_UNLOCK_NODE(udf_node, udf_node->i_flags & IN_CALLBACK_ULK);
wakeup(&udf_node->outstanding_nodedscr);
}
/* XXX waitfor not used */
return 0;
}
@ -1400,10 +1407,10 @@ udf_discstrat_finish_rmw(struct udf_strat_args *args)
struct udf_strategy udf_strat_rmw =
{
udf_create_logvol_dscr_rmw,
udf_free_logvol_dscr_rmw,
udf_read_logvol_dscr_rmw,
udf_write_logvol_dscr_rmw,
udf_create_nodedscr_rmw,
udf_free_nodedscr_rmw,
udf_read_nodedscr_rmw,
udf_write_nodedscr_rmw,
udf_queuebuf_rmw,
udf_discstrat_init_rmw,
udf_discstrat_finish_rmw

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_strat_sequential.c,v 1.1 2008/05/14 16:49:48 reinoud Exp $ */
/* $NetBSD: udf_strat_sequential.c,v 1.2 2008/07/07 18:45:27 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.1 2008/05/14 16:49:48 reinoud Exp $");
__KERNEL_RCSID(0, "$NetBSD: udf_strat_sequential.c,v 1.2 2008/07/07 18:45:27 reinoud Exp $");
#endif /* not lint */
@ -119,20 +119,22 @@ udf_wr_nodedscr_callback(struct buf *buf)
return;
}
/* XXX noone is waiting on this outstanding_nodedscr */
udf_node->outstanding_nodedscr--;
if (udf_node->outstanding_nodedscr == 0)
wakeup(&udf_node->outstanding_nodedscr);
/* XXX right flags to mark dirty again on error? */
if (buf->b_error) {
udf_node->i_flags |= IN_MODIFIED | IN_ACCESSED;
/* XXX TODO reshedule on error */
}
/* first unlock the node */
KASSERT(udf_node->i_flags & IN_CALLBACK_ULK);
UDF_UNLOCK_NODE(udf_node, IN_CALLBACK_ULK);
/* decrement outstanding_nodedscr */
KASSERT(udf_node->outstanding_nodedscr >= 1);
udf_node->outstanding_nodedscr--;
if (udf_node->outstanding_nodedscr == 0) {
/* first unlock the node */
KASSERT(udf_node->i_flags & IN_CALLBACK_ULK);
UDF_UNLOCK_NODE(udf_node, IN_CALLBACK_ULK);
wakeup(&udf_node->outstanding_nodedscr);
}
/* unreference the vnode so it can be recycled */
holdrele(udf_node->vnode);
@ -221,28 +223,32 @@ udf_write_logvol_dscr_seq(struct udf_strat_args *args)
if (ump->vtop_tp[vpart] != UDF_VTOP_TYPE_VIRT) {
error = udf_translate_vtop(ump, icb, &sectornr, &dummy);
if (error)
return error;
goto out;
}
UDF_LOCK_NODE(udf_node, IN_CALLBACK_ULK);
/* add reference to the vnode to prevent recycling */
vhold(udf_node->vnode);
if (waitfor) {
DPRINTF(WRITE, ("udf_write_logvol_dscr: sync write\n"));
error = udf_write_phys_dscr_sync(ump, udf_node, UDF_C_NODE,
dscr, sectornr, logsectornr);
UDF_UNLOCK_NODE(udf_node, IN_CALLBACK_ULK);
} else {
DPRINTF(WRITE, ("udf_write_logvol_dscr: no wait, async write\n"));
/* add reference to the vnode to prevent recycling */
vhold(udf_node->vnode);
udf_node->outstanding_nodedscr++;
error = udf_write_phys_dscr_async(ump, udf_node, UDF_C_NODE,
dscr, sectornr, logsectornr, udf_wr_nodedscr_callback);
/* will be UNLOCKED in call back */
return error;
}
holdrele(udf_node->vnode);
out:
udf_node->outstanding_nodedscr--;
if (udf_node->outstanding_nodedscr == 0) {
UDF_UNLOCK_NODE(udf_node, 0);
wakeup(&udf_node->outstanding_nodedscr);
}
return error;
@ -350,11 +356,10 @@ udf_VAT_mapping_update(struct udf_mount *ump, struct buf *buf)
return;
}
/* check for tag location is false for allocation extents */
KASSERT(fdscr->tag.tag_loc == udf_node->write_loc.loc.lb_num);
/* record new position in VAT file */
lb_num = udf_rw32(udf_node->write_loc.loc.lb_num);
lb_num = udf_rw32(fdscr->tag.tag_loc);
/* lb_num = udf_rw32(udf_node->write_loc.loc.lb_num); */
DPRINTF(TRANSLATE, ("VAT entry change (log %u -> phys %u)\n",
lb_num, lb_map));

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_subr.c,v 1.54 2008/06/25 16:06:29 reinoud Exp $ */
/* $NetBSD: udf_subr.c,v 1.55 2008/07/07 18:45:27 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.54 2008/06/25 16:06:29 reinoud Exp $");
__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.55 2008/07/07 18:45:27 reinoud Exp $");
#endif /* not lint */
@ -1908,7 +1908,7 @@ udf_update_logvolname(struct udf_mount *ump, char *logvol_id)
/* --------------------------------------------------------------------- */
static void
void
udf_inittag(struct udf_mount *ump, struct desc_tag *tag, int tagid,
uint32_t sector)
{
@ -4834,13 +4834,12 @@ udf_get_node(struct udf_mount *ump, struct long_ad *node_icb_loc,
/* --------------------------------------------------------------------- */
/* TODO !!!!! writeout alloc_ext_entry's!!! */
int
udf_writeout_node(struct udf_node *udf_node, int waitfor)
{
union dscrptr *dscr;
struct long_ad *loc;
int error;
int extnr, flags, error;
DPRINTF(NODE, ("udf_writeout_node called\n"));
@ -4854,9 +4853,31 @@ udf_writeout_node(struct udf_node *udf_node, int waitfor)
return 0;
}
/* lock node */
flags = waitfor ? 0 : IN_CALLBACK_ULK;
UDF_LOCK_NODE(udf_node, flags);
/* at least one descriptor writeout */
udf_node->outstanding_nodedscr = 1;
/* we're going to write out the descriptor so clear the flags */
udf_node->i_flags &= ~(IN_MODIFIED | IN_ACCESSED);
/* if we were rebuild, write out the allocation extents */
if (udf_node->i_flags & IN_NODE_REBUILD) {
/* mark outstanding node dscriptors 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];
dscr = (union dscrptr *) udf_node->ext[extnr];
error = udf_write_logvol_dscr(udf_node, dscr, loc, 0);
if (error)
return error;
}
/* mark allocation extents written out */
udf_node->i_flags &= ~(IN_NODE_REBUILD);
}
if (udf_node->fe) {
dscr = (union dscrptr *) udf_node->fe;
} else {
@ -5141,7 +5162,7 @@ udf_free_descriptor_space(struct udf_node *udf_node, struct long_ad *loc, void *
return;
/* got a descriptor here */
len = udf_rw32(loc->len);
len = UDF_EXT_LEN(udf_rw32(loc->len));
lb_num = udf_rw32(loc->loc.lb_num);
vpart_num = udf_rw16(loc->loc.part_num);

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_subr.h,v 1.7 2008/06/18 21:23:32 reinoud Exp $ */
/* $NetBSD: udf_subr.h,v 1.8 2008/07/07 18:45:27 reinoud Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@ -96,7 +96,7 @@ int udf_translate_vtop(struct udf_mount *ump, struct long_ad *icb_loc,
int udf_translate_file_extent(struct udf_node *node,
uint32_t from, uint32_t num_lb, uint64_t *map);
void udf_get_adslot(struct udf_node *udf_node, int slot, struct long_ad *icb, int *eof);
int udf_append_adslot(struct udf_node *udf_node, int slot, struct long_ad *icb);
int udf_append_adslot(struct udf_node *udf_node, int *slot, struct long_ad *icb);
int udf_vat_read(struct udf_node *vat_node, uint8_t *blob, int size, uint32_t offset);
int udf_vat_write(struct udf_node *vat_node, uint8_t *blob, int size, uint32_t offset);
@ -140,6 +140,7 @@ void udf_discstrat_queuebuf(struct udf_mount *ump, struct buf *nestbuf);
int udf_write_terminator(struct udf_mount *ump, uint32_t sector);
/* structure creators */
void udf_inittag(struct udf_mount *ump, struct desc_tag *tag, int tagid, uint32_t sector);
void udf_set_regid(struct regid *regid, char const *name);
void udf_add_domain_regid(struct udf_mount *ump, struct regid *regid);
void udf_add_udf_regid(struct udf_mount *ump, struct regid *regid);

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_vnops.c,v 1.23 2008/06/24 15:57:13 reinoud Exp $ */
/* $NetBSD: udf_vnops.c,v 1.24 2008/07/07 18:45:27 reinoud Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@ -32,7 +32,7 @@
#include <sys/cdefs.h>
#ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.23 2008/06/24 15:57:13 reinoud Exp $");
__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.24 2008/07/07 18:45:27 reinoud Exp $");
#endif /* not lint */
@ -2050,6 +2050,15 @@ udf_fsync(void *v)
wait = (ap->a_flags & FSYNC_WAIT) ? UPDATE_WAIT : 0;
vflushbuf(vp, wait);
if (udf_node == NULL) {
printf("udf_fsync() called on NULL udf_node!\n");
return 0;
}
if (vp->v_tag != VT_UDF) {
printf("udf_fsync() called on node not tagged as UDF node!\n");
return 0;
}
/* set our times */
udf_itimes(udf_node, NULL, NULL, NULL);