udf_readwrite.c revision 1.1.10.2 1 1.1.10.2 wrstuden /* $NetBSD: udf_readwrite.c,v 1.1.10.2 2008/06/23 05:02:14 wrstuden Exp $ */
2 1.1.10.2 wrstuden
3 1.1.10.2 wrstuden /*
4 1.1.10.2 wrstuden * Copyright (c) 2007, 2008 Reinoud Zandijk
5 1.1.10.2 wrstuden * All rights reserved.
6 1.1.10.2 wrstuden *
7 1.1.10.2 wrstuden * Redistribution and use in source and binary forms, with or without
8 1.1.10.2 wrstuden * modification, are permitted provided that the following conditions
9 1.1.10.2 wrstuden * are met:
10 1.1.10.2 wrstuden * 1. Redistributions of source code must retain the above copyright
11 1.1.10.2 wrstuden * notice, this list of conditions and the following disclaimer.
12 1.1.10.2 wrstuden * 2. Redistributions in binary form must reproduce the above copyright
13 1.1.10.2 wrstuden * notice, this list of conditions and the following disclaimer in the
14 1.1.10.2 wrstuden * documentation and/or other materials provided with the distribution.
15 1.1.10.2 wrstuden *
16 1.1.10.2 wrstuden * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 1.1.10.2 wrstuden * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 1.1.10.2 wrstuden * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 1.1.10.2 wrstuden * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 1.1.10.2 wrstuden * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 1.1.10.2 wrstuden * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 1.1.10.2 wrstuden * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 1.1.10.2 wrstuden * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 1.1.10.2 wrstuden * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 1.1.10.2 wrstuden * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 1.1.10.2 wrstuden *
27 1.1.10.2 wrstuden */
28 1.1.10.2 wrstuden
29 1.1.10.2 wrstuden #include <sys/cdefs.h>
30 1.1.10.2 wrstuden #ifndef lint
31 1.1.10.2 wrstuden __KERNEL_RCSID(0, "$NetBSD: udf_readwrite.c,v 1.1.10.2 2008/06/23 05:02:14 wrstuden Exp $");
32 1.1.10.2 wrstuden #endif /* not lint */
33 1.1.10.2 wrstuden
34 1.1.10.2 wrstuden
35 1.1.10.2 wrstuden #if defined(_KERNEL_OPT)
36 1.1.10.2 wrstuden #include "opt_quota.h"
37 1.1.10.2 wrstuden #include "opt_compat_netbsd.h"
38 1.1.10.2 wrstuden #endif
39 1.1.10.2 wrstuden
40 1.1.10.2 wrstuden #include <sys/param.h>
41 1.1.10.2 wrstuden #include <sys/systm.h>
42 1.1.10.2 wrstuden #include <sys/sysctl.h>
43 1.1.10.2 wrstuden #include <sys/namei.h>
44 1.1.10.2 wrstuden #include <sys/proc.h>
45 1.1.10.2 wrstuden #include <sys/kernel.h>
46 1.1.10.2 wrstuden #include <sys/vnode.h>
47 1.1.10.2 wrstuden #include <miscfs/genfs/genfs_node.h>
48 1.1.10.2 wrstuden #include <sys/mount.h>
49 1.1.10.2 wrstuden #include <sys/buf.h>
50 1.1.10.2 wrstuden #include <sys/file.h>
51 1.1.10.2 wrstuden #include <sys/device.h>
52 1.1.10.2 wrstuden #include <sys/disklabel.h>
53 1.1.10.2 wrstuden #include <sys/ioctl.h>
54 1.1.10.2 wrstuden #include <sys/malloc.h>
55 1.1.10.2 wrstuden #include <sys/dirent.h>
56 1.1.10.2 wrstuden #include <sys/stat.h>
57 1.1.10.2 wrstuden #include <sys/conf.h>
58 1.1.10.2 wrstuden #include <sys/kauth.h>
59 1.1.10.2 wrstuden #include <sys/kthread.h>
60 1.1.10.2 wrstuden #include <dev/clock_subr.h>
61 1.1.10.2 wrstuden
62 1.1.10.2 wrstuden #include <fs/udf/ecma167-udf.h>
63 1.1.10.2 wrstuden #include <fs/udf/udf_mount.h>
64 1.1.10.2 wrstuden
65 1.1.10.2 wrstuden #if defined(_KERNEL_OPT)
66 1.1.10.2 wrstuden #include "opt_udf.h"
67 1.1.10.2 wrstuden #endif
68 1.1.10.2 wrstuden
69 1.1.10.2 wrstuden #include "udf.h"
70 1.1.10.2 wrstuden #include "udf_subr.h"
71 1.1.10.2 wrstuden #include "udf_bswap.h"
72 1.1.10.2 wrstuden
73 1.1.10.2 wrstuden
74 1.1.10.2 wrstuden #define VTOI(vnode) ((struct udf_node *) vnode->v_data)
75 1.1.10.2 wrstuden
76 1.1.10.2 wrstuden /* --------------------------------------------------------------------- */
77 1.1.10.2 wrstuden
78 1.1.10.2 wrstuden void
79 1.1.10.2 wrstuden udf_fixup_fid_block(uint8_t *blob, int lb_size,
80 1.1.10.2 wrstuden int rfix_pos, int max_rfix_pos, uint32_t lb_num)
81 1.1.10.2 wrstuden {
82 1.1.10.2 wrstuden struct fileid_desc *fid;
83 1.1.10.2 wrstuden uint8_t *fid_pos;
84 1.1.10.2 wrstuden int fid_len, found;
85 1.1.10.2 wrstuden
86 1.1.10.2 wrstuden /* needs to be word aligned */
87 1.1.10.2 wrstuden KASSERT(rfix_pos % 4 == 0);
88 1.1.10.2 wrstuden
89 1.1.10.2 wrstuden /* first resync with the FID stream !!! */
90 1.1.10.2 wrstuden found = 0;
91 1.1.10.2 wrstuden while (rfix_pos + sizeof(struct desc_tag) <= max_rfix_pos) {
92 1.1.10.2 wrstuden fid_pos = blob + rfix_pos;
93 1.1.10.2 wrstuden fid = (struct fileid_desc *) fid_pos;
94 1.1.10.2 wrstuden if (udf_rw16(fid->tag.id) == TAGID_FID) {
95 1.1.10.2 wrstuden if (udf_check_tag((union dscrptr *) fid) == 0)
96 1.1.10.2 wrstuden found = 1;
97 1.1.10.2 wrstuden }
98 1.1.10.2 wrstuden if (found)
99 1.1.10.2 wrstuden break;
100 1.1.10.2 wrstuden /* try next location; can only be 4 bytes aligned */
101 1.1.10.2 wrstuden rfix_pos += 4;
102 1.1.10.2 wrstuden }
103 1.1.10.2 wrstuden
104 1.1.10.2 wrstuden /* walk over the fids */
105 1.1.10.2 wrstuden fid_pos = blob + rfix_pos;
106 1.1.10.2 wrstuden while (rfix_pos + sizeof(struct desc_tag) <= max_rfix_pos) {
107 1.1.10.2 wrstuden fid = (struct fileid_desc *) fid_pos;
108 1.1.10.2 wrstuden if (udf_rw16(fid->tag.id) != TAGID_FID) {
109 1.1.10.2 wrstuden /* end of FID stream; end of directory or currupted */
110 1.1.10.2 wrstuden break;
111 1.1.10.2 wrstuden }
112 1.1.10.2 wrstuden
113 1.1.10.2 wrstuden /* update sector number and recalculate checkum */
114 1.1.10.2 wrstuden fid->tag.tag_loc = udf_rw32(lb_num);
115 1.1.10.2 wrstuden udf_validate_tag_sum((union dscrptr *) fid);
116 1.1.10.2 wrstuden
117 1.1.10.2 wrstuden /* if the FID crosses the memory, we're done! */
118 1.1.10.2 wrstuden if (rfix_pos + UDF_FID_SIZE >= max_rfix_pos)
119 1.1.10.2 wrstuden break;
120 1.1.10.2 wrstuden
121 1.1.10.2 wrstuden fid_len = udf_fidsize(fid);
122 1.1.10.2 wrstuden fid_pos += fid_len;
123 1.1.10.2 wrstuden rfix_pos += fid_len;
124 1.1.10.2 wrstuden }
125 1.1.10.2 wrstuden }
126 1.1.10.2 wrstuden
127 1.1.10.2 wrstuden
128 1.1.10.2 wrstuden void
129 1.1.10.2 wrstuden udf_fixup_internal_extattr(uint8_t *blob, uint32_t lb_num)
130 1.1.10.2 wrstuden {
131 1.1.10.2 wrstuden struct desc_tag *tag;
132 1.1.10.2 wrstuden struct file_entry *fe;
133 1.1.10.2 wrstuden struct extfile_entry *efe;
134 1.1.10.2 wrstuden struct extattrhdr_desc *eahdr;
135 1.1.10.2 wrstuden int l_ea, error;
136 1.1.10.2 wrstuden
137 1.1.10.2 wrstuden /* get information from fe/efe */
138 1.1.10.2 wrstuden tag = (struct desc_tag *) blob;
139 1.1.10.2 wrstuden switch (udf_rw16(tag->id)) {
140 1.1.10.2 wrstuden case TAGID_FENTRY :
141 1.1.10.2 wrstuden fe = (struct file_entry *) blob;
142 1.1.10.2 wrstuden l_ea = udf_rw32(fe->l_ea);
143 1.1.10.2 wrstuden eahdr = (struct extattrhdr_desc *) fe->data;
144 1.1.10.2 wrstuden break;
145 1.1.10.2 wrstuden case TAGID_EXTFENTRY :
146 1.1.10.2 wrstuden efe = (struct extfile_entry *) blob;
147 1.1.10.2 wrstuden l_ea = udf_rw32(efe->l_ea);
148 1.1.10.2 wrstuden eahdr = (struct extattrhdr_desc *) efe->data;
149 1.1.10.2 wrstuden break;
150 1.1.10.2 wrstuden case TAGID_INDIRECTENTRY :
151 1.1.10.2 wrstuden case TAGID_ALLOCEXTENT :
152 1.1.10.2 wrstuden case TAGID_EXTATTR_HDR :
153 1.1.10.2 wrstuden return;
154 1.1.10.2 wrstuden default:
155 1.1.10.2 wrstuden panic("%s: passed bad tag\n", __FUNCTION__);
156 1.1.10.2 wrstuden }
157 1.1.10.2 wrstuden
158 1.1.10.2 wrstuden /* something recorded here? (why am i called?) */
159 1.1.10.2 wrstuden if (l_ea == 0)
160 1.1.10.2 wrstuden return;
161 1.1.10.2 wrstuden
162 1.1.10.2 wrstuden /* check extended attribute tag */
163 1.1.10.2 wrstuden /* TODO XXX what to do when we encounter an error here? */
164 1.1.10.2 wrstuden error = udf_check_tag(eahdr);
165 1.1.10.2 wrstuden if (error)
166 1.1.10.2 wrstuden return; /* for now */
167 1.1.10.2 wrstuden if (udf_rw16(eahdr->tag.id) != TAGID_EXTATTR_HDR)
168 1.1.10.2 wrstuden return; /* for now */
169 1.1.10.2 wrstuden error = udf_check_tag_payload(eahdr, sizeof(struct extattrhdr_desc));
170 1.1.10.2 wrstuden if (error)
171 1.1.10.2 wrstuden return; /* for now */
172 1.1.10.2 wrstuden
173 1.1.10.2 wrstuden DPRINTF(EXTATTR, ("node fixup: found %d bytes of extended attributes\n",
174 1.1.10.2 wrstuden l_ea));
175 1.1.10.2 wrstuden
176 1.1.10.2 wrstuden /* fixup eahdr tag */
177 1.1.10.2 wrstuden eahdr->tag.tag_loc = udf_rw32(lb_num);
178 1.1.10.2 wrstuden udf_validate_tag_sum((union dscrptr *) eahdr);
179 1.1.10.2 wrstuden }
180 1.1.10.2 wrstuden
181 1.1.10.2 wrstuden
182 1.1.10.2 wrstuden void
183 1.1.10.2 wrstuden udf_fixup_node_internals(struct udf_mount *ump, uint8_t *blob, int udf_c_type)
184 1.1.10.2 wrstuden {
185 1.1.10.2 wrstuden struct desc_tag *tag;
186 1.1.10.2 wrstuden struct file_entry *fe;
187 1.1.10.2 wrstuden struct extfile_entry *efe;
188 1.1.10.2 wrstuden uint32_t lb_size, lb_num;
189 1.1.10.2 wrstuden uint32_t rfid_pos, max_rfid_pos;
190 1.1.10.2 wrstuden int icbflags, addr_type, has_fids, l_ea;
191 1.1.10.2 wrstuden
192 1.1.10.2 wrstuden lb_size = udf_rw32(ump->logical_vol->lb_size);
193 1.1.10.2 wrstuden /* if its not a node we're done */
194 1.1.10.2 wrstuden if (udf_c_type != UDF_C_NODE)
195 1.1.10.2 wrstuden return;
196 1.1.10.2 wrstuden
197 1.1.10.2 wrstuden /* NOTE this could also be done in write_internal */
198 1.1.10.2 wrstuden /* start of a descriptor */
199 1.1.10.2 wrstuden has_fids = 0;
200 1.1.10.2 wrstuden max_rfid_pos = rfid_pos = lb_num = 0; /* shut up gcc! */
201 1.1.10.2 wrstuden
202 1.1.10.2 wrstuden tag = (struct desc_tag *) blob;
203 1.1.10.2 wrstuden switch (udf_rw16(tag->id)) {
204 1.1.10.2 wrstuden case TAGID_FENTRY :
205 1.1.10.2 wrstuden fe = (struct file_entry *) tag;
206 1.1.10.2 wrstuden l_ea = udf_rw32(fe->l_ea);
207 1.1.10.2 wrstuden icbflags = udf_rw16(fe->icbtag.flags);
208 1.1.10.2 wrstuden addr_type = (icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK);
209 1.1.10.2 wrstuden has_fids = (addr_type == UDF_ICB_INTERN_ALLOC);
210 1.1.10.2 wrstuden rfid_pos = UDF_FENTRY_SIZE + l_ea;
211 1.1.10.2 wrstuden max_rfid_pos = rfid_pos + udf_rw64(fe->inf_len);
212 1.1.10.2 wrstuden lb_num = udf_rw32(fe->tag.tag_loc);
213 1.1.10.2 wrstuden break;
214 1.1.10.2 wrstuden case TAGID_EXTFENTRY :
215 1.1.10.2 wrstuden efe = (struct extfile_entry *) tag;
216 1.1.10.2 wrstuden l_ea = udf_rw32(efe->l_ea);
217 1.1.10.2 wrstuden icbflags = udf_rw16(efe->icbtag.flags);
218 1.1.10.2 wrstuden addr_type = (icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK);
219 1.1.10.2 wrstuden has_fids = (addr_type == UDF_ICB_INTERN_ALLOC);
220 1.1.10.2 wrstuden rfid_pos = UDF_EXTFENTRY_SIZE + l_ea;
221 1.1.10.2 wrstuden max_rfid_pos = rfid_pos + udf_rw64(efe->inf_len);
222 1.1.10.2 wrstuden lb_num = udf_rw32(efe->tag.tag_loc);
223 1.1.10.2 wrstuden break;
224 1.1.10.2 wrstuden case TAGID_INDIRECTENTRY :
225 1.1.10.2 wrstuden case TAGID_ALLOCEXTENT :
226 1.1.10.2 wrstuden case TAGID_EXTATTR_HDR :
227 1.1.10.2 wrstuden l_ea = 0;
228 1.1.10.2 wrstuden has_fids = 0;
229 1.1.10.2 wrstuden break;
230 1.1.10.2 wrstuden default:
231 1.1.10.2 wrstuden panic("%s: passed bad tag\n", __FUNCTION__);
232 1.1.10.2 wrstuden break;
233 1.1.10.2 wrstuden }
234 1.1.10.2 wrstuden
235 1.1.10.2 wrstuden /* fixup internal extended attributes if present */
236 1.1.10.2 wrstuden if (l_ea)
237 1.1.10.2 wrstuden udf_fixup_internal_extattr(blob, lb_num);
238 1.1.10.2 wrstuden
239 1.1.10.2 wrstuden if (has_fids) {
240 1.1.10.2 wrstuden udf_fixup_fid_block(blob, lb_size, rfid_pos,
241 1.1.10.2 wrstuden max_rfid_pos, lb_num);
242 1.1.10.2 wrstuden }
243 1.1.10.2 wrstuden udf_validate_tag_and_crc_sums(blob);
244 1.1.10.2 wrstuden }
245 1.1.10.2 wrstuden
246 1.1.10.2 wrstuden /* --------------------------------------------------------------------- */
247 1.1.10.2 wrstuden
248 1.1.10.2 wrstuden /*
249 1.1.10.2 wrstuden * Set of generic descriptor readers and writers and their helper functions.
250 1.1.10.2 wrstuden * Descriptors inside `logical space' i.e. inside logically mapped partitions
251 1.1.10.2 wrstuden * can never be longer than one logical sector.
252 1.1.10.2 wrstuden *
253 1.1.10.2 wrstuden * NOTE that these functions *can* be used by the sheduler backends to read
254 1.1.10.2 wrstuden * node descriptors too.
255 1.1.10.2 wrstuden *
256 1.1.10.2 wrstuden * For reading, the size of allocated piece is returned in multiple of sector
257 1.1.10.2 wrstuden * size due to udf_calc_udf_malloc_size().
258 1.1.10.2 wrstuden */
259 1.1.10.2 wrstuden
260 1.1.10.2 wrstuden
261 1.1.10.2 wrstuden /* SYNC reading of n blocks from specified sector */
262 1.1.10.2 wrstuden /* NOTE only used by udf_read_phys_dscr */
263 1.1.10.2 wrstuden static int
264 1.1.10.2 wrstuden udf_read_phys_sectors(struct udf_mount *ump, int what, void *blob,
265 1.1.10.2 wrstuden uint32_t start, uint32_t sectors)
266 1.1.10.2 wrstuden {
267 1.1.10.2 wrstuden struct buf *buf, *nestbuf;
268 1.1.10.2 wrstuden uint32_t buf_offset;
269 1.1.10.2 wrstuden off_t lblkno, rblkno;
270 1.1.10.2 wrstuden int sector_size = ump->discinfo.sector_size;
271 1.1.10.2 wrstuden int blks = sector_size / DEV_BSIZE;
272 1.1.10.2 wrstuden int piece;
273 1.1.10.2 wrstuden int error;
274 1.1.10.2 wrstuden
275 1.1.10.2 wrstuden DPRINTF(READ, ("udf_intbreadn() : sectors = %d, sector_size = %d\n",
276 1.1.10.2 wrstuden sectors, sector_size));
277 1.1.10.2 wrstuden buf = getiobuf(ump->devvp, true);
278 1.1.10.2 wrstuden buf->b_flags = B_READ;
279 1.1.10.2 wrstuden buf->b_cflags = BC_BUSY; /* needed? */
280 1.1.10.2 wrstuden buf->b_iodone = NULL;
281 1.1.10.2 wrstuden buf->b_data = blob;
282 1.1.10.2 wrstuden buf->b_bcount = sectors * sector_size;
283 1.1.10.2 wrstuden buf->b_resid = buf->b_bcount;
284 1.1.10.2 wrstuden buf->b_bufsize = buf->b_bcount;
285 1.1.10.2 wrstuden buf->b_private = NULL; /* not needed yet */
286 1.1.10.2 wrstuden BIO_SETPRIO(buf, BPRIO_DEFAULT);
287 1.1.10.2 wrstuden buf->b_lblkno = buf->b_blkno = buf->b_rawblkno = start * blks;
288 1.1.10.2 wrstuden buf->b_proc = NULL;
289 1.1.10.2 wrstuden
290 1.1.10.2 wrstuden error = 0;
291 1.1.10.2 wrstuden buf_offset = 0;
292 1.1.10.2 wrstuden rblkno = start;
293 1.1.10.2 wrstuden lblkno = 0;
294 1.1.10.2 wrstuden while ((sectors > 0) && (error == 0)) {
295 1.1.10.2 wrstuden piece = MIN(MAXPHYS/sector_size, sectors);
296 1.1.10.2 wrstuden DPRINTF(READ, ("read in %d + %d\n", (uint32_t) rblkno, piece));
297 1.1.10.2 wrstuden
298 1.1.10.2 wrstuden nestbuf = getiobuf(NULL, true);
299 1.1.10.2 wrstuden nestiobuf_setup(buf, nestbuf, buf_offset, piece * sector_size);
300 1.1.10.2 wrstuden /* nestbuf is B_ASYNC */
301 1.1.10.2 wrstuden
302 1.1.10.2 wrstuden /* identify this nestbuf */
303 1.1.10.2 wrstuden nestbuf->b_lblkno = lblkno;
304 1.1.10.2 wrstuden
305 1.1.10.2 wrstuden /* CD shedules on raw blkno */
306 1.1.10.2 wrstuden nestbuf->b_blkno = rblkno * blks;
307 1.1.10.2 wrstuden nestbuf->b_proc = NULL;
308 1.1.10.2 wrstuden nestbuf->b_rawblkno = rblkno * blks;
309 1.1.10.2 wrstuden nestbuf->b_udf_c_type = what;
310 1.1.10.2 wrstuden
311 1.1.10.2 wrstuden udf_discstrat_queuebuf(ump, nestbuf);
312 1.1.10.2 wrstuden
313 1.1.10.2 wrstuden lblkno += piece;
314 1.1.10.2 wrstuden rblkno += piece;
315 1.1.10.2 wrstuden buf_offset += piece * sector_size;
316 1.1.10.2 wrstuden sectors -= piece;
317 1.1.10.2 wrstuden }
318 1.1.10.2 wrstuden error = biowait(buf);
319 1.1.10.2 wrstuden putiobuf(buf);
320 1.1.10.2 wrstuden
321 1.1.10.2 wrstuden return error;
322 1.1.10.2 wrstuden }
323 1.1.10.2 wrstuden
324 1.1.10.2 wrstuden
325 1.1.10.2 wrstuden /* synchronous generic descriptor read */
326 1.1.10.2 wrstuden int
327 1.1.10.2 wrstuden udf_read_phys_dscr(struct udf_mount *ump, uint32_t sector,
328 1.1.10.2 wrstuden struct malloc_type *mtype, union dscrptr **dstp)
329 1.1.10.2 wrstuden {
330 1.1.10.2 wrstuden union dscrptr *dst, *new_dst;
331 1.1.10.2 wrstuden uint8_t *pos;
332 1.1.10.2 wrstuden int sectors, dscrlen;
333 1.1.10.2 wrstuden int i, error, sector_size;
334 1.1.10.2 wrstuden
335 1.1.10.2 wrstuden sector_size = ump->discinfo.sector_size;
336 1.1.10.2 wrstuden
337 1.1.10.2 wrstuden *dstp = dst = NULL;
338 1.1.10.2 wrstuden dscrlen = sector_size;
339 1.1.10.2 wrstuden
340 1.1.10.2 wrstuden /* read initial piece */
341 1.1.10.2 wrstuden dst = malloc(sector_size, mtype, M_WAITOK);
342 1.1.10.2 wrstuden error = udf_read_phys_sectors(ump, UDF_C_DSCR, dst, sector, 1);
343 1.1.10.2 wrstuden DPRINTFIF(DESCRIPTOR, error, ("read error (%d)\n", error));
344 1.1.10.2 wrstuden
345 1.1.10.2 wrstuden if (!error) {
346 1.1.10.2 wrstuden /* check if its a valid tag */
347 1.1.10.2 wrstuden error = udf_check_tag(dst);
348 1.1.10.2 wrstuden if (error) {
349 1.1.10.2 wrstuden /* check if its an empty block */
350 1.1.10.2 wrstuden pos = (uint8_t *) dst;
351 1.1.10.2 wrstuden for (i = 0; i < sector_size; i++, pos++) {
352 1.1.10.2 wrstuden if (*pos) break;
353 1.1.10.2 wrstuden }
354 1.1.10.2 wrstuden if (i == sector_size) {
355 1.1.10.2 wrstuden /* return no error but with no dscrptr */
356 1.1.10.2 wrstuden /* dispose first block */
357 1.1.10.2 wrstuden free(dst, mtype);
358 1.1.10.2 wrstuden return 0;
359 1.1.10.2 wrstuden }
360 1.1.10.2 wrstuden }
361 1.1.10.2 wrstuden /* calculate descriptor size */
362 1.1.10.2 wrstuden dscrlen = udf_tagsize(dst, sector_size);
363 1.1.10.2 wrstuden }
364 1.1.10.2 wrstuden DPRINTFIF(DESCRIPTOR, error, ("bad tag checksum\n"));
365 1.1.10.2 wrstuden
366 1.1.10.2 wrstuden if (!error && (dscrlen > sector_size)) {
367 1.1.10.2 wrstuden DPRINTF(DESCRIPTOR, ("multi block descriptor read\n"));
368 1.1.10.2 wrstuden /*
369 1.1.10.2 wrstuden * Read the rest of descriptor. Since it is only used at mount
370 1.1.10.2 wrstuden * time its overdone to define and use a specific udf_intbreadn
371 1.1.10.2 wrstuden * for this alone.
372 1.1.10.2 wrstuden */
373 1.1.10.2 wrstuden
374 1.1.10.2 wrstuden new_dst = realloc(dst, dscrlen, mtype, M_WAITOK);
375 1.1.10.2 wrstuden if (new_dst == NULL) {
376 1.1.10.2 wrstuden free(dst, mtype);
377 1.1.10.2 wrstuden return ENOMEM;
378 1.1.10.2 wrstuden }
379 1.1.10.2 wrstuden dst = new_dst;
380 1.1.10.2 wrstuden
381 1.1.10.2 wrstuden sectors = (dscrlen + sector_size -1) / sector_size;
382 1.1.10.2 wrstuden DPRINTF(DESCRIPTOR, ("dscrlen = %d (%d blk)\n", dscrlen, sectors));
383 1.1.10.2 wrstuden
384 1.1.10.2 wrstuden pos = (uint8_t *) dst + sector_size;
385 1.1.10.2 wrstuden error = udf_read_phys_sectors(ump, UDF_C_DSCR, pos,
386 1.1.10.2 wrstuden sector + 1, sectors-1);
387 1.1.10.2 wrstuden
388 1.1.10.2 wrstuden DPRINTFIF(DESCRIPTOR, error, ("read error on multi (%d)\n",
389 1.1.10.2 wrstuden error));
390 1.1.10.2 wrstuden }
391 1.1.10.2 wrstuden if (!error) {
392 1.1.10.2 wrstuden error = udf_check_tag_payload(dst, dscrlen);
393 1.1.10.2 wrstuden DPRINTFIF(DESCRIPTOR, error, ("bad payload check sum\n"));
394 1.1.10.2 wrstuden }
395 1.1.10.2 wrstuden if (error && dst) {
396 1.1.10.2 wrstuden free(dst, mtype);
397 1.1.10.2 wrstuden dst = NULL;
398 1.1.10.2 wrstuden }
399 1.1.10.2 wrstuden *dstp = dst;
400 1.1.10.2 wrstuden
401 1.1.10.2 wrstuden return error;
402 1.1.10.2 wrstuden }
403 1.1.10.2 wrstuden
404 1.1.10.2 wrstuden
405 1.1.10.2 wrstuden static void
406 1.1.10.2 wrstuden udf_write_phys_buf(struct udf_mount *ump, int what, struct buf *buf)
407 1.1.10.2 wrstuden {
408 1.1.10.2 wrstuden struct buf *nestbuf;
409 1.1.10.2 wrstuden uint32_t buf_offset;
410 1.1.10.2 wrstuden off_t lblkno, rblkno;
411 1.1.10.2 wrstuden int sector_size = ump->discinfo.sector_size;
412 1.1.10.2 wrstuden int blks = sector_size / DEV_BSIZE;
413 1.1.10.2 wrstuden uint32_t sectors;
414 1.1.10.2 wrstuden int piece;
415 1.1.10.2 wrstuden int error;
416 1.1.10.2 wrstuden
417 1.1.10.2 wrstuden sectors = buf->b_bcount / sector_size;
418 1.1.10.2 wrstuden DPRINTF(WRITE, ("udf_intbwriten() : sectors = %d, sector_size = %d\n",
419 1.1.10.2 wrstuden sectors, sector_size));
420 1.1.10.2 wrstuden
421 1.1.10.2 wrstuden /* don't forget to increase pending count for the bwrite itself */
422 1.1.10.2 wrstuden /* panic("NO WRITING\n"); */
423 1.1.10.2 wrstuden if (buf->b_vp) {
424 1.1.10.2 wrstuden mutex_enter(&buf->b_vp->v_interlock);
425 1.1.10.2 wrstuden buf->b_vp->v_numoutput++;
426 1.1.10.2 wrstuden mutex_exit(&buf->b_vp->v_interlock);
427 1.1.10.2 wrstuden }
428 1.1.10.2 wrstuden
429 1.1.10.2 wrstuden error = 0;
430 1.1.10.2 wrstuden buf_offset = 0;
431 1.1.10.2 wrstuden rblkno = buf->b_blkno / blks;
432 1.1.10.2 wrstuden lblkno = 0;
433 1.1.10.2 wrstuden while ((sectors > 0) && (error == 0)) {
434 1.1.10.2 wrstuden piece = MIN(MAXPHYS/sector_size, sectors);
435 1.1.10.2 wrstuden DPRINTF(WRITE, ("write out %d + %d\n",
436 1.1.10.2 wrstuden (uint32_t) rblkno, piece));
437 1.1.10.2 wrstuden
438 1.1.10.2 wrstuden nestbuf = getiobuf(NULL, true);
439 1.1.10.2 wrstuden nestiobuf_setup(buf, nestbuf, buf_offset, piece * sector_size);
440 1.1.10.2 wrstuden /* nestbuf is B_ASYNC */
441 1.1.10.2 wrstuden
442 1.1.10.2 wrstuden /* identify this nestbuf */
443 1.1.10.2 wrstuden nestbuf->b_lblkno = lblkno;
444 1.1.10.2 wrstuden
445 1.1.10.2 wrstuden /* CD shedules on raw blkno */
446 1.1.10.2 wrstuden nestbuf->b_blkno = rblkno * blks;
447 1.1.10.2 wrstuden nestbuf->b_proc = NULL;
448 1.1.10.2 wrstuden nestbuf->b_rawblkno = rblkno * blks;
449 1.1.10.2 wrstuden nestbuf->b_udf_c_type = what;
450 1.1.10.2 wrstuden
451 1.1.10.2 wrstuden udf_discstrat_queuebuf(ump, nestbuf);
452 1.1.10.2 wrstuden
453 1.1.10.2 wrstuden lblkno += piece;
454 1.1.10.2 wrstuden rblkno += piece;
455 1.1.10.2 wrstuden buf_offset += piece * sector_size;
456 1.1.10.2 wrstuden sectors -= piece;
457 1.1.10.2 wrstuden }
458 1.1.10.2 wrstuden }
459 1.1.10.2 wrstuden
460 1.1.10.2 wrstuden
461 1.1.10.2 wrstuden /* synchronous generic descriptor write */
462 1.1.10.2 wrstuden int
463 1.1.10.2 wrstuden udf_write_phys_dscr_sync(struct udf_mount *ump, struct udf_node *udf_node, int what,
464 1.1.10.2 wrstuden union dscrptr *dscr, uint32_t sector, uint32_t logsector)
465 1.1.10.2 wrstuden {
466 1.1.10.2 wrstuden struct vnode *vp;
467 1.1.10.2 wrstuden struct buf *buf;
468 1.1.10.2 wrstuden int sector_size = ump->discinfo.sector_size;
469 1.1.10.2 wrstuden int blks = sector_size / DEV_BSIZE;
470 1.1.10.2 wrstuden int dscrlen;
471 1.1.10.2 wrstuden int error;
472 1.1.10.2 wrstuden
473 1.1.10.2 wrstuden /* set sector number in the descriptor and validate */
474 1.1.10.2 wrstuden dscr->tag.tag_loc = udf_rw32(logsector);
475 1.1.10.2 wrstuden udf_validate_tag_and_crc_sums(dscr);
476 1.1.10.2 wrstuden
477 1.1.10.2 wrstuden /* calculate descriptor size */
478 1.1.10.2 wrstuden dscrlen = udf_tagsize(dscr, sector_size);
479 1.1.10.2 wrstuden
480 1.1.10.2 wrstuden /* get transfer buffer */
481 1.1.10.2 wrstuden vp = udf_node ? udf_node->vnode : ump->devvp;
482 1.1.10.2 wrstuden buf = getiobuf(vp, true);
483 1.1.10.2 wrstuden buf->b_flags = B_WRITE;
484 1.1.10.2 wrstuden buf->b_cflags = BC_BUSY; /* needed? */
485 1.1.10.2 wrstuden buf->b_iodone = NULL;
486 1.1.10.2 wrstuden buf->b_data = (void *) dscr;
487 1.1.10.2 wrstuden buf->b_bcount = dscrlen;
488 1.1.10.2 wrstuden buf->b_resid = buf->b_bcount;
489 1.1.10.2 wrstuden buf->b_bufsize = buf->b_bcount;
490 1.1.10.2 wrstuden buf->b_private = NULL; /* not needed yet */
491 1.1.10.2 wrstuden BIO_SETPRIO(buf, BPRIO_DEFAULT);
492 1.1.10.2 wrstuden buf->b_lblkno = buf->b_blkno = buf->b_rawblkno = sector * blks;
493 1.1.10.2 wrstuden buf->b_proc = NULL;
494 1.1.10.2 wrstuden
495 1.1.10.2 wrstuden /* do the write, wait and return error */
496 1.1.10.2 wrstuden udf_write_phys_buf(ump, what, buf);
497 1.1.10.2 wrstuden error = biowait(buf);
498 1.1.10.2 wrstuden putiobuf(buf);
499 1.1.10.2 wrstuden
500 1.1.10.2 wrstuden return error;
501 1.1.10.2 wrstuden }
502 1.1.10.2 wrstuden
503 1.1.10.2 wrstuden
504 1.1.10.2 wrstuden /* asynchronous generic descriptor write */
505 1.1.10.2 wrstuden int
506 1.1.10.2 wrstuden udf_write_phys_dscr_async(struct udf_mount *ump, struct udf_node *udf_node,
507 1.1.10.2 wrstuden int what, union dscrptr *dscr,
508 1.1.10.2 wrstuden uint32_t sector, uint32_t logsector,
509 1.1.10.2 wrstuden void (*dscrwr_callback)(struct buf *))
510 1.1.10.2 wrstuden {
511 1.1.10.2 wrstuden struct vnode *vp;
512 1.1.10.2 wrstuden struct buf *buf;
513 1.1.10.2 wrstuden int dscrlen;
514 1.1.10.2 wrstuden int sector_size = ump->discinfo.sector_size;
515 1.1.10.2 wrstuden int blks = sector_size / DEV_BSIZE;
516 1.1.10.2 wrstuden
517 1.1.10.2 wrstuden KASSERT(dscrwr_callback);
518 1.1.10.2 wrstuden DPRINTF(NODE, ("udf_write_phys_dscr_async() called\n"));
519 1.1.10.2 wrstuden
520 1.1.10.2 wrstuden /* set sector number in the descriptor and validate */
521 1.1.10.2 wrstuden dscr->tag.tag_loc = udf_rw32(logsector);
522 1.1.10.2 wrstuden udf_validate_tag_and_crc_sums(dscr);
523 1.1.10.2 wrstuden
524 1.1.10.2 wrstuden /* calculate descriptor size */
525 1.1.10.2 wrstuden dscrlen = udf_tagsize(dscr, sector_size);
526 1.1.10.2 wrstuden
527 1.1.10.2 wrstuden /* get transfer buffer */
528 1.1.10.2 wrstuden vp = udf_node ? udf_node->vnode : ump->devvp;
529 1.1.10.2 wrstuden buf = getiobuf(vp, true);
530 1.1.10.2 wrstuden buf->b_flags = B_WRITE; // | B_ASYNC;
531 1.1.10.2 wrstuden buf->b_cflags = BC_BUSY;
532 1.1.10.2 wrstuden buf->b_iodone = dscrwr_callback;
533 1.1.10.2 wrstuden buf->b_data = dscr;
534 1.1.10.2 wrstuden buf->b_bcount = dscrlen;
535 1.1.10.2 wrstuden buf->b_resid = buf->b_bcount;
536 1.1.10.2 wrstuden buf->b_bufsize = buf->b_bcount;
537 1.1.10.2 wrstuden buf->b_private = NULL; /* not needed yet */
538 1.1.10.2 wrstuden BIO_SETPRIO(buf, BPRIO_DEFAULT);
539 1.1.10.2 wrstuden buf->b_lblkno = buf->b_blkno = buf->b_rawblkno = sector * blks;
540 1.1.10.2 wrstuden buf->b_proc = NULL;
541 1.1.10.2 wrstuden
542 1.1.10.2 wrstuden /* do the write and return no error */
543 1.1.10.2 wrstuden udf_write_phys_buf(ump, what, buf);
544 1.1.10.2 wrstuden return 0;
545 1.1.10.2 wrstuden }
546 1.1.10.2 wrstuden
547 1.1.10.2 wrstuden /* --------------------------------------------------------------------- */
548 1.1.10.2 wrstuden
549 1.1.10.2 wrstuden /* disc strategy dispatchers */
550 1.1.10.2 wrstuden
551 1.1.10.2 wrstuden int
552 1.1.10.2 wrstuden udf_create_logvol_dscr(struct udf_mount *ump, struct udf_node *udf_node, struct long_ad *icb,
553 1.1.10.2 wrstuden union dscrptr **dscrptr)
554 1.1.10.2 wrstuden {
555 1.1.10.2 wrstuden struct udf_strategy *strategy = ump->strategy;
556 1.1.10.2 wrstuden struct udf_strat_args args;
557 1.1.10.2 wrstuden int error;
558 1.1.10.2 wrstuden
559 1.1.10.2 wrstuden args.ump = ump;
560 1.1.10.2 wrstuden args.udf_node = udf_node;
561 1.1.10.2 wrstuden args.icb = icb;
562 1.1.10.2 wrstuden args.dscr = NULL;
563 1.1.10.2 wrstuden
564 1.1.10.2 wrstuden error = (strategy->create_logvol_dscr)(&args);
565 1.1.10.2 wrstuden *dscrptr = args.dscr;
566 1.1.10.2 wrstuden
567 1.1.10.2 wrstuden return error;
568 1.1.10.2 wrstuden }
569 1.1.10.2 wrstuden
570 1.1.10.2 wrstuden
571 1.1.10.2 wrstuden void
572 1.1.10.2 wrstuden udf_free_logvol_dscr(struct udf_mount *ump, struct long_ad *icb,
573 1.1.10.2 wrstuden void *dscr)
574 1.1.10.2 wrstuden {
575 1.1.10.2 wrstuden struct udf_strategy *strategy = ump->strategy;
576 1.1.10.2 wrstuden struct udf_strat_args args;
577 1.1.10.2 wrstuden
578 1.1.10.2 wrstuden args.ump = ump;
579 1.1.10.2 wrstuden args.icb = icb;
580 1.1.10.2 wrstuden args.dscr = dscr;
581 1.1.10.2 wrstuden
582 1.1.10.2 wrstuden (strategy->free_logvol_dscr)(&args);
583 1.1.10.2 wrstuden }
584 1.1.10.2 wrstuden
585 1.1.10.2 wrstuden
586 1.1.10.2 wrstuden int
587 1.1.10.2 wrstuden udf_read_logvol_dscr(struct udf_mount *ump, struct long_ad *icb,
588 1.1.10.2 wrstuden union dscrptr **dscrptr)
589 1.1.10.2 wrstuden {
590 1.1.10.2 wrstuden struct udf_strategy *strategy = ump->strategy;
591 1.1.10.2 wrstuden struct udf_strat_args args;
592 1.1.10.2 wrstuden int error;
593 1.1.10.2 wrstuden
594 1.1.10.2 wrstuden args.ump = ump;
595 1.1.10.2 wrstuden args.icb = icb;
596 1.1.10.2 wrstuden args.dscr = NULL;
597 1.1.10.2 wrstuden
598 1.1.10.2 wrstuden error = (strategy->read_logvol_dscr)(&args);
599 1.1.10.2 wrstuden *dscrptr = args.dscr;
600 1.1.10.2 wrstuden
601 1.1.10.2 wrstuden return error;
602 1.1.10.2 wrstuden }
603 1.1.10.2 wrstuden
604 1.1.10.2 wrstuden
605 1.1.10.2 wrstuden int
606 1.1.10.2 wrstuden udf_write_logvol_dscr(struct udf_node *udf_node, union dscrptr *dscr,
607 1.1.10.2 wrstuden struct long_ad *icb, int waitfor)
608 1.1.10.2 wrstuden {
609 1.1.10.2 wrstuden struct udf_strategy *strategy = udf_node->ump->strategy;
610 1.1.10.2 wrstuden struct udf_strat_args args;
611 1.1.10.2 wrstuden int error;
612 1.1.10.2 wrstuden
613 1.1.10.2 wrstuden args.ump = udf_node->ump;
614 1.1.10.2 wrstuden args.udf_node = udf_node;
615 1.1.10.2 wrstuden args.icb = icb;
616 1.1.10.2 wrstuden args.dscr = dscr;
617 1.1.10.2 wrstuden args.waitfor = waitfor;
618 1.1.10.2 wrstuden
619 1.1.10.2 wrstuden error = (strategy->write_logvol_dscr)(&args);
620 1.1.10.2 wrstuden return error;
621 1.1.10.2 wrstuden }
622 1.1.10.2 wrstuden
623 1.1.10.2 wrstuden
624 1.1.10.2 wrstuden void
625 1.1.10.2 wrstuden udf_discstrat_queuebuf(struct udf_mount *ump, struct buf *nestbuf)
626 1.1.10.2 wrstuden {
627 1.1.10.2 wrstuden struct udf_strategy *strategy = ump->strategy;
628 1.1.10.2 wrstuden struct udf_strat_args args;
629 1.1.10.2 wrstuden
630 1.1.10.2 wrstuden args.ump = ump;
631 1.1.10.2 wrstuden args.nestbuf = nestbuf;
632 1.1.10.2 wrstuden
633 1.1.10.2 wrstuden (strategy->queuebuf)(&args);
634 1.1.10.2 wrstuden }
635 1.1.10.2 wrstuden
636 1.1.10.2 wrstuden
637 1.1.10.2 wrstuden void
638 1.1.10.2 wrstuden udf_discstrat_init(struct udf_mount *ump)
639 1.1.10.2 wrstuden {
640 1.1.10.2 wrstuden struct udf_strategy *strategy = ump->strategy;
641 1.1.10.2 wrstuden struct udf_strat_args args;
642 1.1.10.2 wrstuden
643 1.1.10.2 wrstuden args.ump = ump;
644 1.1.10.2 wrstuden (strategy->discstrat_init)(&args);
645 1.1.10.2 wrstuden }
646 1.1.10.2 wrstuden
647 1.1.10.2 wrstuden
648 1.1.10.2 wrstuden void udf_discstrat_finish(struct udf_mount *ump)
649 1.1.10.2 wrstuden {
650 1.1.10.2 wrstuden struct udf_strategy *strategy = ump->strategy;
651 1.1.10.2 wrstuden struct udf_strat_args args;
652 1.1.10.2 wrstuden
653 1.1.10.2 wrstuden args.ump = ump;
654 1.1.10.2 wrstuden (strategy->discstrat_finish)(&args);
655 1.1.10.2 wrstuden }
656 1.1.10.2 wrstuden
657 1.1.10.2 wrstuden /* --------------------------------------------------------------------- */
658 1.1.10.2 wrstuden
659