diff options
author | Jan Kara <jack@suse.cz> | 2022-10-06 14:25:16 +0300 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2023-01-09 12:39:52 +0300 |
commit | f2844803404d9729f893e279ddea12678710e7fb (patch) | |
tree | 25c3a97330aa7e1e37ca3de2b9155a37562c80bc /fs/udf/directory.c | |
parent | 6ec01a8020b54e278fecd1efe8603f8eb38fed84 (diff) | |
download | linux-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.c | 57 |
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, |