]> Git Repo - linux.git/blob - fs/udf/directory.c
Merge branches 'pm-cpuidle' and 'pm-em'
[linux.git] / fs / udf / directory.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * directory.c
4  *
5  * PURPOSE
6  *      Directory related functions
7  *
8  */
9
10 #include "udfdecl.h"
11 #include "udf_i.h"
12
13 #include <linux/fs.h>
14 #include <linux/string.h>
15 #include <linux/bio.h>
16 #include <linux/crc-itu-t.h>
17 #include <linux/iversion.h>
18
19 static int udf_verify_fi(struct udf_fileident_iter *iter)
20 {
21         unsigned int len;
22
23         if (iter->fi.descTag.tagIdent != cpu_to_le16(TAG_IDENT_FID)) {
24                 udf_err(iter->dir->i_sb,
25                         "directory (ino %lu) has entry at pos %llu with incorrect tag %x\n",
26                         iter->dir->i_ino, (unsigned long long)iter->pos,
27                         le16_to_cpu(iter->fi.descTag.tagIdent));
28                 return -EFSCORRUPTED;
29         }
30         len = udf_dir_entry_len(&iter->fi);
31         if (le16_to_cpu(iter->fi.lengthOfImpUse) & 3) {
32                 udf_err(iter->dir->i_sb,
33                         "directory (ino %lu) has entry at pos %llu with unaligned length of impUse field\n",
34                         iter->dir->i_ino, (unsigned long long)iter->pos);
35                 return -EFSCORRUPTED;
36         }
37         /*
38          * This is in fact allowed by the spec due to long impUse field but
39          * we don't support it. If there is real media with this large impUse
40          * field, support can be added.
41          */
42         if (len > 1 << iter->dir->i_blkbits) {
43                 udf_err(iter->dir->i_sb,
44                         "directory (ino %lu) has too big (%u) entry at pos %llu\n",
45                         iter->dir->i_ino, len, (unsigned long long)iter->pos);
46                 return -EFSCORRUPTED;
47         }
48         if (iter->pos + len > iter->dir->i_size) {
49                 udf_err(iter->dir->i_sb,
50                         "directory (ino %lu) has entry past directory size at pos %llu\n",
51                         iter->dir->i_ino, (unsigned long long)iter->pos);
52                 return -EFSCORRUPTED;
53         }
54         if (udf_dir_entry_len(&iter->fi) !=
55             sizeof(struct tag) + le16_to_cpu(iter->fi.descTag.descCRCLength)) {
56                 udf_err(iter->dir->i_sb,
57                         "directory (ino %lu) has entry where CRC length (%u) does not match entry length (%u)\n",
58                         iter->dir->i_ino,
59                         (unsigned)le16_to_cpu(iter->fi.descTag.descCRCLength),
60                         (unsigned)(udf_dir_entry_len(&iter->fi) -
61                                                         sizeof(struct tag)));
62                 return -EFSCORRUPTED;
63         }
64         return 0;
65 }
66
67 static int udf_copy_fi(struct udf_fileident_iter *iter)
68 {
69         struct udf_inode_info *iinfo = UDF_I(iter->dir);
70         u32 blksize = 1 << iter->dir->i_blkbits;
71         u32 off, len, nameoff;
72         int err;
73
74         /* Skip copying when we are at EOF */
75         if (iter->pos >= iter->dir->i_size) {
76                 iter->name = NULL;
77                 return 0;
78         }
79         if (iter->dir->i_size < iter->pos + sizeof(struct fileIdentDesc)) {
80                 udf_err(iter->dir->i_sb,
81                         "directory (ino %lu) has entry straddling EOF\n",
82                         iter->dir->i_ino);
83                 return -EFSCORRUPTED;
84         }
85         if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
86                 memcpy(&iter->fi, iinfo->i_data + iinfo->i_lenEAttr + iter->pos,
87                        sizeof(struct fileIdentDesc));
88                 err = udf_verify_fi(iter);
89                 if (err < 0)
90                         return err;
91                 iter->name = iinfo->i_data + iinfo->i_lenEAttr + iter->pos +
92                         sizeof(struct fileIdentDesc) +
93                         le16_to_cpu(iter->fi.lengthOfImpUse);
94                 return 0;
95         }
96
97         off = iter->pos & (blksize - 1);
98         len = min_t(u32, sizeof(struct fileIdentDesc), blksize - off);
99         memcpy(&iter->fi, iter->bh[0]->b_data + off, len);
100         if (len < sizeof(struct fileIdentDesc))
101                 memcpy((char *)(&iter->fi) + len, iter->bh[1]->b_data,
102                        sizeof(struct fileIdentDesc) - len);
103         err = udf_verify_fi(iter);
104         if (err < 0)
105                 return err;
106
107         /* Handle directory entry name */
108         nameoff = off + sizeof(struct fileIdentDesc) +
109                                 le16_to_cpu(iter->fi.lengthOfImpUse);
110         if (off + udf_dir_entry_len(&iter->fi) <= blksize) {
111                 iter->name = iter->bh[0]->b_data + nameoff;
112         } else if (nameoff >= blksize) {
113                 iter->name = iter->bh[1]->b_data + (nameoff - blksize);
114         } else {
115                 iter->name = iter->namebuf;
116                 len = blksize - nameoff;
117                 memcpy(iter->name, iter->bh[0]->b_data + nameoff, len);
118                 memcpy(iter->name + len, iter->bh[1]->b_data,
119                        iter->fi.lengthFileIdent - len);
120         }
121         return 0;
122 }
123
124 /* Readahead 8k once we are at 8k boundary */
125 static void udf_readahead_dir(struct udf_fileident_iter *iter)
126 {
127         unsigned int ralen = 16 >> (iter->dir->i_blkbits - 9);
128         struct buffer_head *tmp, *bha[16];
129         int i, num;
130         udf_pblk_t blk;
131
132         if (iter->loffset & (ralen - 1))
133                 return;
134
135         if (iter->loffset + ralen > (iter->elen >> iter->dir->i_blkbits))
136                 ralen = (iter->elen >> iter->dir->i_blkbits) - iter->loffset;
137         num = 0;
138         for (i = 0; i < ralen; i++) {
139                 blk = udf_get_lb_pblock(iter->dir->i_sb, &iter->eloc,
140                                         iter->loffset + i);
141                 tmp = sb_getblk(iter->dir->i_sb, blk);
142                 if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
143                         bha[num++] = tmp;
144                 else
145                         brelse(tmp);
146         }
147         if (num) {
148                 bh_readahead_batch(num, bha, REQ_RAHEAD);
149                 for (i = 0; i < num; i++)
150                         brelse(bha[i]);
151         }
152 }
153
154 static struct buffer_head *udf_fiiter_bread_blk(struct udf_fileident_iter *iter)
155 {
156         udf_pblk_t blk;
157
158         udf_readahead_dir(iter);
159         blk = udf_get_lb_pblock(iter->dir->i_sb, &iter->eloc, iter->loffset);
160         return sb_bread(iter->dir->i_sb, blk);
161 }
162
163 /*
164  * Updates loffset to point to next directory block; eloc, elen & epos are
165  * updated if we need to traverse to the next extent as well.
166  */
167 static int udf_fiiter_advance_blk(struct udf_fileident_iter *iter)
168 {
169         int8_t etype = -1;
170         int err = 0;
171
172         iter->loffset++;
173         if (iter->loffset < DIV_ROUND_UP(iter->elen, 1<<iter->dir->i_blkbits))
174                 return 0;
175
176         iter->loffset = 0;
177         err = udf_next_aext(iter->dir, &iter->epos, &iter->eloc,
178                             &iter->elen, &etype, 1);
179         if (err < 0)
180                 return err;
181         else if (err == 0 || etype != (EXT_RECORDED_ALLOCATED >> 30)) {
182                 if (iter->pos == iter->dir->i_size) {
183                         iter->elen = 0;
184                         return 0;
185                 }
186                 udf_err(iter->dir->i_sb,
187                         "extent after position %llu not allocated in directory (ino %lu)\n",
188                         (unsigned long long)iter->pos, iter->dir->i_ino);
189                 return -EFSCORRUPTED;
190         }
191         return 0;
192 }
193
194 static int udf_fiiter_load_bhs(struct udf_fileident_iter *iter)
195 {
196         int blksize = 1 << iter->dir->i_blkbits;
197         int off = iter->pos & (blksize - 1);
198         int err;
199         struct fileIdentDesc *fi;
200
201         /* Is there any further extent we can map from? */
202         if (!iter->bh[0] && iter->elen) {
203                 iter->bh[0] = udf_fiiter_bread_blk(iter);
204                 if (!iter->bh[0]) {
205                         err = -ENOMEM;
206                         goto out_brelse;
207                 }
208                 if (!buffer_uptodate(iter->bh[0])) {
209                         err = -EIO;
210                         goto out_brelse;
211                 }
212         }
213         /* There's no next block so we are done */
214         if (iter->pos >= iter->dir->i_size)
215                 return 0;
216         /* Need to fetch next block as well? */
217         if (off + sizeof(struct fileIdentDesc) > blksize)
218                 goto fetch_next;
219         fi = (struct fileIdentDesc *)(iter->bh[0]->b_data + off);
220         /* Need to fetch next block to get name? */
221         if (off + udf_dir_entry_len(fi) > blksize) {
222 fetch_next:
223                 err = udf_fiiter_advance_blk(iter);
224                 if (err)
225                         goto out_brelse;
226                 iter->bh[1] = udf_fiiter_bread_blk(iter);
227                 if (!iter->bh[1]) {
228                         err = -ENOMEM;
229                         goto out_brelse;
230                 }
231                 if (!buffer_uptodate(iter->bh[1])) {
232                         err = -EIO;
233                         goto out_brelse;
234                 }
235         }
236         return 0;
237 out_brelse:
238         brelse(iter->bh[0]);
239         brelse(iter->bh[1]);
240         iter->bh[0] = iter->bh[1] = NULL;
241         return err;
242 }
243
244 int udf_fiiter_init(struct udf_fileident_iter *iter, struct inode *dir,
245                     loff_t pos)
246 {
247         struct udf_inode_info *iinfo = UDF_I(dir);
248         int err = 0;
249         int8_t etype;
250
251         iter->dir = dir;
252         iter->bh[0] = iter->bh[1] = NULL;
253         iter->pos = pos;
254         iter->elen = 0;
255         iter->epos.bh = NULL;
256         iter->name = NULL;
257         /*
258          * When directory is verified, we don't expect directory iteration to
259          * fail and it can be difficult to undo without corrupting filesystem.
260          * So just do not allow memory allocation failures here.
261          */
262         iter->namebuf = kmalloc(UDF_NAME_LEN_CS0, GFP_KERNEL | __GFP_NOFAIL);
263
264         if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
265                 err = udf_copy_fi(iter);
266                 goto out;
267         }
268
269         err = inode_bmap(dir, iter->pos >> dir->i_blkbits, &iter->epos,
270                          &iter->eloc, &iter->elen, &iter->loffset, &etype);
271         if (err <= 0 || etype != (EXT_RECORDED_ALLOCATED >> 30)) {
272                 if (pos == dir->i_size)
273                         return 0;
274                 udf_err(dir->i_sb,
275                         "position %llu not allocated in directory (ino %lu)\n",
276                         (unsigned long long)pos, dir->i_ino);
277                 err = -EFSCORRUPTED;
278                 goto out;
279         }
280         err = udf_fiiter_load_bhs(iter);
281         if (err < 0)
282                 goto out;
283         err = udf_copy_fi(iter);
284 out:
285         if (err < 0)
286                 udf_fiiter_release(iter);
287         return err;
288 }
289
290 int udf_fiiter_advance(struct udf_fileident_iter *iter)
291 {
292         unsigned int oldoff, len;
293         int blksize = 1 << iter->dir->i_blkbits;
294         int err;
295
296         oldoff = iter->pos & (blksize - 1);
297         len = udf_dir_entry_len(&iter->fi);
298         iter->pos += len;
299         if (UDF_I(iter->dir)->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
300                 if (oldoff + len >= blksize) {
301                         brelse(iter->bh[0]);
302                         iter->bh[0] = NULL;
303                         /* Next block already loaded? */
304                         if (iter->bh[1]) {
305                                 iter->bh[0] = iter->bh[1];
306                                 iter->bh[1] = NULL;
307                         } else {
308                                 err = udf_fiiter_advance_blk(iter);
309                                 if (err < 0)
310                                         return err;
311                         }
312                 }
313                 err = udf_fiiter_load_bhs(iter);
314                 if (err < 0)
315                         return err;
316         }
317         return udf_copy_fi(iter);
318 }
319
320 void udf_fiiter_release(struct udf_fileident_iter *iter)
321 {
322         iter->dir = NULL;
323         brelse(iter->bh[0]);
324         brelse(iter->bh[1]);
325         iter->bh[0] = iter->bh[1] = NULL;
326         kfree(iter->namebuf);
327         iter->namebuf = NULL;
328 }
329
330 static void udf_copy_to_bufs(void *buf1, int len1, void *buf2, int len2,
331                              int off, void *src, int len)
332 {
333         int copy;
334
335         if (off >= len1) {
336                 off -= len1;
337         } else {
338                 copy = min(off + len, len1) - off;
339                 memcpy(buf1 + off, src, copy);
340                 src += copy;
341                 len -= copy;
342                 off = 0;
343         }
344         if (len > 0) {
345                 if (WARN_ON_ONCE(off + len > len2 || !buf2))
346                         return;
347                 memcpy(buf2 + off, src, len);
348         }
349 }
350
351 static uint16_t udf_crc_fi_bufs(void *buf1, int len1, void *buf2, int len2,
352                                 int off, int len)
353 {
354         int copy;
355         uint16_t crc = 0;
356
357         if (off >= len1) {
358                 off -= len1;
359         } else {
360                 copy = min(off + len, len1) - off;
361                 crc = crc_itu_t(crc, buf1 + off, copy);
362                 len -= copy;
363                 off = 0;
364         }
365         if (len > 0) {
366                 if (WARN_ON_ONCE(off + len > len2 || !buf2))
367                         return 0;
368                 crc = crc_itu_t(crc, buf2 + off, len);
369         }
370         return crc;
371 }
372
373 static void udf_copy_fi_to_bufs(char *buf1, int len1, char *buf2, int len2,
374                                 int off, struct fileIdentDesc *fi,
375                                 uint8_t *impuse, uint8_t *name)
376 {
377         uint16_t crc;
378         int fioff = off;
379         int crcoff = off + sizeof(struct tag);
380         unsigned int crclen = udf_dir_entry_len(fi) - sizeof(struct tag);
381         char zeros[UDF_NAME_PAD] = {};
382         int endoff = off + udf_dir_entry_len(fi);
383
384         udf_copy_to_bufs(buf1, len1, buf2, len2, off, fi,
385                          sizeof(struct fileIdentDesc));
386         off += sizeof(struct fileIdentDesc);
387         if (impuse)
388                 udf_copy_to_bufs(buf1, len1, buf2, len2, off, impuse,
389                                  le16_to_cpu(fi->lengthOfImpUse));
390         off += le16_to_cpu(fi->lengthOfImpUse);
391         if (name) {
392                 udf_copy_to_bufs(buf1, len1, buf2, len2, off, name,
393                                  fi->lengthFileIdent);
394                 off += fi->lengthFileIdent;
395                 udf_copy_to_bufs(buf1, len1, buf2, len2, off, zeros,
396                                  endoff - off);
397         }
398
399         crc = udf_crc_fi_bufs(buf1, len1, buf2, len2, crcoff, crclen);
400         fi->descTag.descCRC = cpu_to_le16(crc);
401         fi->descTag.descCRCLength = cpu_to_le16(crclen);
402         fi->descTag.tagChecksum = udf_tag_checksum(&fi->descTag);
403
404         udf_copy_to_bufs(buf1, len1, buf2, len2, fioff, fi, sizeof(struct tag));
405 }
406
407 void udf_fiiter_write_fi(struct udf_fileident_iter *iter, uint8_t *impuse)
408 {
409         struct udf_inode_info *iinfo = UDF_I(iter->dir);
410         void *buf1, *buf2 = NULL;
411         int len1, len2 = 0, off;
412         int blksize = 1 << iter->dir->i_blkbits;
413
414         off = iter->pos & (blksize - 1);
415         if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
416                 buf1 = iinfo->i_data + iinfo->i_lenEAttr;
417                 len1 = iter->dir->i_size;
418         } else {
419                 buf1 = iter->bh[0]->b_data;
420                 len1 = blksize;
421                 if (iter->bh[1]) {
422                         buf2 = iter->bh[1]->b_data;
423                         len2 = blksize;
424                 }
425         }
426
427         udf_copy_fi_to_bufs(buf1, len1, buf2, len2, off, &iter->fi, impuse,
428                             iter->name == iter->namebuf ? iter->name : NULL);
429
430         if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
431                 mark_inode_dirty(iter->dir);
432         } else {
433                 mark_buffer_dirty_inode(iter->bh[0], iter->dir);
434                 if (iter->bh[1])
435                         mark_buffer_dirty_inode(iter->bh[1], iter->dir);
436         }
437         inode_inc_iversion(iter->dir);
438 }
439
440 void udf_fiiter_update_elen(struct udf_fileident_iter *iter, uint32_t new_elen)
441 {
442         struct udf_inode_info *iinfo = UDF_I(iter->dir);
443         int diff = new_elen - iter->elen;
444
445         /* Skip update when we already went past the last extent */
446         if (!iter->elen)
447                 return;
448         iter->elen = new_elen;
449         if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
450                 iter->epos.offset -= sizeof(struct short_ad);
451         else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
452                 iter->epos.offset -= sizeof(struct long_ad);
453         udf_write_aext(iter->dir, &iter->epos, &iter->eloc, iter->elen, 1);
454         iinfo->i_lenExtents += diff;
455         mark_inode_dirty(iter->dir);
456 }
457
458 /* Append new block to directory. @iter is expected to point at EOF */
459 int udf_fiiter_append_blk(struct udf_fileident_iter *iter)
460 {
461         struct udf_inode_info *iinfo = UDF_I(iter->dir);
462         int blksize = 1 << iter->dir->i_blkbits;
463         struct buffer_head *bh;
464         sector_t block;
465         uint32_t old_elen = iter->elen;
466         int err;
467         int8_t etype;
468
469         if (WARN_ON_ONCE(iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB))
470                 return -EINVAL;
471
472         /* Round up last extent in the file */
473         udf_fiiter_update_elen(iter, ALIGN(iter->elen, blksize));
474
475         /* Allocate new block and refresh mapping information */
476         block = iinfo->i_lenExtents >> iter->dir->i_blkbits;
477         bh = udf_bread(iter->dir, block, 1, &err);
478         if (!bh) {
479                 udf_fiiter_update_elen(iter, old_elen);
480                 return err;
481         }
482         err = inode_bmap(iter->dir, block, &iter->epos, &iter->eloc, &iter->elen,
483                    &iter->loffset, &etype);
484         if (err <= 0 || etype != (EXT_RECORDED_ALLOCATED >> 30)) {
485                 udf_err(iter->dir->i_sb,
486                         "block %llu not allocated in directory (ino %lu)\n",
487                         (unsigned long long)block, iter->dir->i_ino);
488                 return -EFSCORRUPTED;
489         }
490         if (!(iter->pos & (blksize - 1))) {
491                 brelse(iter->bh[0]);
492                 iter->bh[0] = bh;
493         } else {
494                 iter->bh[1] = bh;
495         }
496         return 0;
497 }
498
499 struct short_ad *udf_get_fileshortad(uint8_t *ptr, int maxoffset, uint32_t *offset,
500                               int inc)
501 {
502         struct short_ad *sa;
503
504         if ((!ptr) || (!offset)) {
505                 pr_err("%s: invalidparms\n", __func__);
506                 return NULL;
507         }
508
509         if ((*offset + sizeof(struct short_ad)) > maxoffset)
510                 return NULL;
511         else {
512                 sa = (struct short_ad *)ptr;
513                 if (sa->extLength == 0)
514                         return NULL;
515         }
516
517         if (inc)
518                 *offset += sizeof(struct short_ad);
519         return sa;
520 }
521
522 struct long_ad *udf_get_filelongad(uint8_t *ptr, int maxoffset, uint32_t *offset, int inc)
523 {
524         struct long_ad *la;
525
526         if ((!ptr) || (!offset)) {
527                 pr_err("%s: invalidparms\n", __func__);
528                 return NULL;
529         }
530
531         if ((*offset + sizeof(struct long_ad)) > maxoffset)
532                 return NULL;
533         else {
534                 la = (struct long_ad *)ptr;
535                 if (la->extLength == 0)
536                         return NULL;
537         }
538
539         if (inc)
540                 *offset += sizeof(struct long_ad);
541         return la;
542 }
This page took 0.064046 seconds and 4 git commands to generate.