int udf_do_newfs_prefix(void) { union dscrptr *zero_dscr; union dscrptr *dscr; struct mmc_trackinfo ti; uint32_t sparable_blocks; uint32_t sector_size, blockingnr; uint32_t cnt, loc, len; int sectcopy; int error, integrity_type; int data_part, metadata_part; /* init */ sector_size = mmc_discinfo.sector_size; /* determine span/size */ ti.tracknr = mmc_discinfo.first_track_last_session; error = udf_update_trackinfo(&mmc_discinfo, &ti); if (error) return error; if (mmc_discinfo.sector_size < context.sector_size) { fprintf(stderr, "Impossible to format: sectorsize too small\n"); return EIO; } context.sector_size = sector_size; /* determine blockingnr */ blockingnr = ti.packet_size; if (blockingnr <= 1) { /* paranoia on blockingnr */ switch (mmc_discinfo.mmc_profile) { case 0x08 : /* CDROM */ case 0x09 : /* CD-R */ case 0x0a : /* CD-RW */ blockingnr = 32; /* UDF requirement */ break; case 0x10 : /* DVDROM */ case 0x11 : /* DVD-R (DL) */ case 0x12 : /* DVD-RAM */ case 0x1b : /* DVD+R */ case 0x2b : /* DVD+R Dual layer */ case 0x13 : /* DVD-RW restricted overwrite */ case 0x14 : /* DVD-RW sequential */ blockingnr = 16; /* SCSI definition */ break; case 0x40 : /* BDROM */ case 0x41 : /* BD-R Sequential recording (SRM) */ case 0x42 : /* BD-R Random recording (RRM) */ case 0x43 : /* BD-RE */ case 0x51 : /* HD DVD-R */ case 0x52 : /* HD DVD-RW */ blockingnr = 32; /* SCSI definition */ break; default: break; } } if (blockingnr <= 0) { printf("Can't fixup blockingnumber for device " "type %d\n", mmc_discinfo.mmc_profile); printf("Device is not returning valid blocking" " number and media type is unknown.\n"); return EINVAL; } wrtrack_skew = ti.track_start % blockingnr; if (mmc_discinfo.mmc_class == MMC_CLASS_CD) { /* not too much for CD-RW, still 20MiB */ sparable_blocks = 32; } else { /* take a value for DVD*RW mainly, BD is `defect free' */ sparable_blocks = 512; } /* get layout */ error = udf_calculate_disc_layout(format_flags, context.min_udf, wrtrack_skew, ti.track_start, mmc_discinfo.last_possible_lba, context.sector_size, blockingnr, sparable_blocks, meta_fract); /* cache partition for we need it often */ data_part = context.data_part; metadata_part = context.metadata_part; /* Create sparing table descriptor if applicable */ if (format_flags & FORMAT_SPARABLE) { if ((error = udf_create_sparing_tabled())) return error; if (check_surface) { if ((error = udf_surface_check())) return error; } } /* Create a generic terminator descriptor (later reused) */ terminator_dscr = calloc(1, sector_size); if (terminator_dscr == NULL) return ENOMEM; udf_create_terminator(terminator_dscr, 0); /* * Start with wipeout of VRS1 upto start of partition. This allows * formatting for sequentials with the track reservation and it * cleans old rubbish on rewritables. For sequentuals without the * track reservation all is wiped from track start. */ if ((zero_dscr = calloc(1, context.sector_size)) == NULL) return ENOMEM; loc = (format_flags & FORMAT_TRACK512) ? layout.vds1 : ti.track_start; for (; loc < layout.part_start_lba; loc++) { if ((error = udf_write_sector(zero_dscr, loc))) { free(zero_dscr); return error; } } free(zero_dscr); /* Create anchors */ for (cnt = 0; cnt < 3; cnt++) { if ((error = udf_create_anchor(cnt))) { return error; } } /* * Create the two Volume Descriptor Sets (VDS) each containing the * following descriptors : primary volume, partition space, * unallocated space, logical volume, implementation use and the * terminator */ /* start of volume recognision sequence building */ context.vds_seq = 0; /* Create primary volume descriptor */ if ((error = udf_create_primaryd())) return error; /* Create partition descriptor */ if ((error = udf_create_partitiond(context.data_part, media_accesstype))) return error; /* Create unallocated space descriptor */ if ((error = udf_create_unalloc_spaced())) return error; /* Create logical volume descriptor */ if ((error = udf_create_logical_dscr(format_flags))) return error; /* Create implementation use descriptor */ /* TODO input of fields 1,2,3 and passing them */ if ((error = udf_create_impvold(NULL, NULL, NULL))) return error; /* write out what we've created so far */ /* writeout iso9660 vrs */ if ((error = udf_write_iso9660_vrs())) return error; /* Writeout anchors */ for (cnt = 0; cnt < 3; cnt++) { dscr = (union dscrptr *) context.anchors[cnt]; loc = layout.anchors[cnt]; if ((error = udf_write_dscr_phys(dscr, loc, 1))) return error; /* sequential media has only one anchor */ if (format_flags & FORMAT_SEQUENTIAL) break; } /* write out main and secondary VRS */ for (sectcopy = 1; sectcopy <= 2; sectcopy++) { loc = (sectcopy == 1) ? layout.vds1 : layout.vds2; /* primary volume descriptor */ dscr = (union dscrptr *) context.primary_vol; error = udf_write_dscr_phys(dscr, loc, 1); if (error) return error; loc++; /* partition descriptor(s) */ for (cnt = 0; cnt < UDF_PARTITIONS; cnt++) { dscr = (union dscrptr *) context.partitions[cnt]; if (dscr) { error = udf_write_dscr_phys(dscr, loc, 1); if (error) return error; loc++; } } /* unallocated space descriptor */ dscr = (union dscrptr *) context.unallocated; error = udf_write_dscr_phys(dscr, loc, 1); if (error) return error; loc++; /* logical volume descriptor */ dscr = (union dscrptr *) context.logical_vol; error = udf_write_dscr_phys(dscr, loc, 1); if (error) return error; loc++; /* implementation use descriptor */ dscr = (union dscrptr *) context.implementation; error = udf_write_dscr_phys(dscr, loc, 1); if (error) return error; loc++; /* terminator descriptor */ error = udf_write_dscr_phys(terminator_dscr, loc, 1); if (error) return error; loc++; } /* writeout the two sparable table descriptors (if needed) */ if (format_flags & FORMAT_SPARABLE) { for (sectcopy = 1; sectcopy <= 2; sectcopy++) { loc = (sectcopy == 1) ? layout.spt_1 : layout.spt_2; dscr = (union dscrptr *) context.sparing_table; len = layout.sparing_table_dscr_lbas; /* writeout */ error = udf_write_dscr_phys(dscr, loc, len); if (error) return error; } } /* * Create unallocated space bitmap descriptor. Sequential recorded * media report their own free/used space; no free/used space tables * should be recorded for these. */ if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) { error = udf_create_space_bitmap( layout.alloc_bitmap_dscr_size, layout.part_size_lba, &context.part_unalloc_bits[data_part]); if (error) return error; /* TODO: freed space bitmap if applicable */ /* mark space allocated for the unallocated space bitmap */ udf_mark_allocated(layout.unalloc_space, data_part, layout.alloc_bitmap_dscr_size); } /* * Create metadata partition file entries and allocate and init their * space and free space maps. */ if (format_flags & FORMAT_META) { error = udf_create_space_bitmap( layout.meta_bitmap_dscr_size, layout.meta_part_size_lba, &context.part_unalloc_bits[metadata_part]); if (error) return error; error = udf_create_meta_files(); if (error) return error; /* mark space allocated for meta partition and its bitmap */ udf_mark_allocated(layout.meta_file, data_part, 1); udf_mark_allocated(layout.meta_mirror, data_part, 1); udf_mark_allocated(layout.meta_bitmap, data_part, 1); udf_mark_allocated(layout.meta_part_start_lba, data_part, layout.meta_part_size_lba); /* mark space allocated for the unallocated space bitmap */ udf_mark_allocated(layout.meta_bitmap_space, data_part, layout.meta_bitmap_dscr_size); } /* create logical volume integrity descriptor */ context.num_files = 0; context.num_directories = 0; integrity_type = UDF_INTEGRITY_OPEN; if ((error = udf_create_lvintd(integrity_type))) return error; /* writeout initial open integrity sequence + terminator */ loc = layout.lvis; dscr = (union dscrptr *) context.logvol_integrity; error = udf_write_dscr_phys(dscr, loc, 1); if (error) return error; loc++; error = udf_write_dscr_phys(terminator_dscr, loc, 1); if (error) return error; /* create VAT if needed */ if (format_flags & FORMAT_VAT) { context.vat_allocated = context.sector_size; context.vat_contents = malloc(context.vat_allocated); assert(context.vat_contents); udf_prepend_VAT_file(); } /* create FSD and writeout */ if ((error = udf_create_fsd())) return error; udf_mark_allocated(layout.fsd, metadata_part, 1); dscr = (union dscrptr *) context.fileset_desc; error = udf_write_dscr_virt(dscr, layout.fsd, metadata_part, 1); return error; }
static void udf_doshedule(struct udf_mount *ump) { struct buf *buf; struct timespec now, *last; struct strat_private *priv = PRIV(ump); void (*b_callback)(struct buf *); int new_queue; int error; buf = bufq_get(priv->queues[priv->cur_queue]); if (buf) { /* transfer from the current queue to the device queue */ mutex_exit(&priv->discstrat_mutex); /* transform buffer to synchronous; XXX needed? */ b_callback = buf->b_iodone; buf->b_iodone = NULL; CLR(buf->b_flags, B_ASYNC); /* issue and wait on completion */ udf_issue_buf(ump, priv->cur_queue, buf); biowait(buf); mutex_enter(&priv->discstrat_mutex); /* if there is an error, repair this error, otherwise propagate */ if (buf->b_error && ((buf->b_flags & B_READ) == 0)) { /* check what we need to do */ panic("UDF write error, can't handle yet!\n"); } /* propagate result to higher layers */ if (b_callback) { buf->b_iodone = b_callback; (*buf->b_iodone)(buf); } return; } /* Check if we're idling in this state */ vfs_timestamp(&now); last = &priv->last_queued[priv->cur_queue]; if (ump->discinfo.mmc_class == MMC_CLASS_CD) { /* dont switch too fast for CD media; its expensive in time */ if (now.tv_sec - last->tv_sec < 3) return; } /* check if we can/should switch */ new_queue = priv->cur_queue; if (bufq_peek(priv->queues[UDF_SHED_READING])) new_queue = UDF_SHED_READING; if (bufq_peek(priv->queues[UDF_SHED_WRITING])) /* only for unmount */ new_queue = UDF_SHED_WRITING; if (bufq_peek(priv->queues[UDF_SHED_SEQWRITING])) new_queue = UDF_SHED_SEQWRITING; if (priv->cur_queue == UDF_SHED_READING) { if (new_queue == UDF_SHED_SEQWRITING) { /* TODO use flag to signal if this is needed */ mutex_exit(&priv->discstrat_mutex); /* update trackinfo for data and metadata */ error = udf_update_trackinfo(ump, &ump->data_track); assert(error == 0); error = udf_update_trackinfo(ump, &ump->metadata_track); assert(error == 0); mutex_enter(&priv->discstrat_mutex); __USE(error); } } if (new_queue != priv->cur_queue) { DPRINTF(SHEDULE, ("switching from %d to %d\n", priv->cur_queue, new_queue)); } priv->cur_queue = new_queue; }