summaryrefslogtreecommitdiff
path: root/fs/udf/directory.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2022-10-06 14:25:16 +0300
committerJan Kara <jack@suse.cz>2023-01-09 12:39:52 +0300
commitf2844803404d9729f893e279ddea12678710e7fb (patch)
tree25c3a97330aa7e1e37ca3de2b9155a37562c80bc /fs/udf/directory.c
parent6ec01a8020b54e278fecd1efe8603f8eb38fed84 (diff)
downloadlinux-f2844803404d9729f893e279ddea12678710e7fb.tar.xz
udf: Implement adding of dir entries using new iteration code
Implement function udf_fiiter_add_entry() adding new directory entries using new directory iteration code. Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/udf/directory.c')
-rw-r--r--fs/udf/directory.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/fs/udf/directory.c b/fs/udf/directory.c
index 2842c463725c..be85d1b2a6cf 100644
--- a/fs/udf/directory.c
+++ b/fs/udf/directory.c
@@ -413,6 +413,63 @@ void udf_fiiter_write_fi(struct udf_fileident_iter *iter, uint8_t *impuse)
inode_inc_iversion(iter->dir);
}
+void udf_fiiter_update_elen(struct udf_fileident_iter *iter, uint32_t new_elen)
+{
+ struct udf_inode_info *iinfo = UDF_I(iter->dir);
+ int diff = new_elen - iter->elen;
+
+ /* Skip update when we already went past the last extent */
+ if (!iter->elen)
+ return;
+ iter->elen = new_elen;
+ if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
+ iter->epos.offset -= sizeof(struct short_ad);
+ else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
+ iter->epos.offset -= sizeof(struct long_ad);
+ udf_write_aext(iter->dir, &iter->epos, &iter->eloc, iter->elen, 1);
+ iinfo->i_lenExtents += diff;
+ mark_inode_dirty(iter->dir);
+}
+
+/* Append new block to directory. @iter is expected to point at EOF */
+int udf_fiiter_append_blk(struct udf_fileident_iter *iter)
+{
+ struct udf_inode_info *iinfo = UDF_I(iter->dir);
+ int blksize = 1 << iter->dir->i_blkbits;
+ struct buffer_head *bh;
+ sector_t block;
+ uint32_t old_elen = iter->elen;
+ int err;
+
+ if (WARN_ON_ONCE(iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB))
+ return -EINVAL;
+
+ /* Round up last extent in the file */
+ udf_fiiter_update_elen(iter, ALIGN(iter->elen, blksize));
+
+ /* Allocate new block and refresh mapping information */
+ block = iinfo->i_lenExtents >> iter->dir->i_blkbits;
+ bh = udf_bread(iter->dir, block, 1, &err);
+ if (!bh) {
+ udf_fiiter_update_elen(iter, old_elen);
+ return err;
+ }
+ if (inode_bmap(iter->dir, block, &iter->epos, &iter->eloc, &iter->elen,
+ &iter->loffset) != (EXT_RECORDED_ALLOCATED >> 30)) {
+ udf_err(iter->dir->i_sb,
+ "block %llu not allocated in directory (ino %lu)\n",
+ (unsigned long long)block, iter->dir->i_ino);
+ return -EFSCORRUPTED;
+ }
+ if (!(iter->pos & (blksize - 1))) {
+ brelse(iter->bh[0]);
+ iter->bh[0] = bh;
+ } else {
+ iter->bh[1] = bh;
+ }
+ return 0;
+}
+
struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos,
struct udf_fileident_bh *fibh,
struct fileIdentDesc *cfi,