This commit is contained in:
Mark Brown
2026-07-31 13:10:23 +01:00
23 changed files with 187 additions and 268 deletions
-1
View File
@@ -9908,7 +9908,6 @@ F: net/core/failover.c
FANOTIFY
M: Jan Kara <jack@suse.cz>
R: Amir Goldstein <amir73il@gmail.com>
R: Matthew Bobrowski <repnop@google.com>
L: linux-fsdevel@vger.kernel.org
S: Maintained
F: fs/notify/fanotify/
@@ -973,7 +973,6 @@ CONFIG_FS_VERITY=y
CONFIG_FANOTIFY=y
CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
CONFIG_QUOTA=y
# CONFIG_PRINT_QUOTA_WARNING is not set
CONFIG_QFMT_V1=m
CONFIG_QFMT_V2=m
CONFIG_AUTOFS_FS=y
@@ -1004,7 +1004,6 @@ CONFIG_FS_VERITY=y
CONFIG_FANOTIFY=y
CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
CONFIG_QUOTA=y
# CONFIG_PRINT_QUOTA_WARNING is not set
CONFIG_QFMT_V1=m
CONFIG_QFMT_V2=m
CONFIG_AUTOFS_FS=y
-1
View File
@@ -140,7 +140,6 @@ CONFIG_EXT4_FS_SECURITY=y
CONFIG_EXT4_FS=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
CONFIG_QFMT_V2=m
CONFIG_AUTOFS_FS=m
CONFIG_FUSE_FS=m
-1
View File
@@ -238,7 +238,6 @@ CONFIG_XFS_FS=m
CONFIG_XFS_QUOTA=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
CONFIG_QFMT_V2=m
CONFIG_AUTOFS_FS=m
CONFIG_FUSE_FS=m
-1
View File
@@ -303,7 +303,6 @@ CONFIG_XFS_FS=y
CONFIG_XFS_QUOTA=y
CONFIG_XFS_POSIX_ACL=y
CONFIG_QUOTA=y
# CONFIG_PRINT_QUOTA_WARNING is not set
CONFIG_AUTOFS_FS=y
CONFIG_FUSE_FS=m
CONFIG_ISO9660_FS=m
-27
View File
@@ -1032,33 +1032,6 @@ out:
return ret;
}
#ifdef CONFIG_PRINT_QUOTA_WARNING
/**
* tty_write_message - write a message to a certain tty, not just the console.
* @tty: the destination tty_struct
* @msg: the message to write
*
* This is used for messages that need to be redirected to a specific tty. We
* don't put it into the syslog queue right now maybe in the future if really
* needed.
*
* We must still hold the BTM and test the CLOSING flag for the moment.
*
* This function is DEPRECATED, do not use in new code.
*/
void tty_write_message(struct tty_struct *tty, char *msg)
{
if (tty) {
mutex_lock(&tty->atomic_write_lock);
tty_lock(tty);
if (tty->ops->write && tty->count > 0)
tty->ops->write(tty, msg, strlen(msg));
tty_unlock(tty);
tty_write_unlock(tty);
}
}
#endif
static ssize_t file_tty_write(struct file *file, struct kiocb *iocb, struct iov_iter *from)
{
struct tty_struct *tty = file_tty(file);
+5 -9
View File
@@ -779,16 +779,12 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
inode_set_ctime_current(inode);
if (IS_SYNC(inode)) {
error = sync_inode_metadata(inode, 1);
/* In case sync failed due to ENOSPC the inode was actually
* written (only some dirty data were not) so we just proceed
* as if nothing happened and cleanup the unused block */
if (error && error != -ENOSPC) {
if (new_bh && new_bh != old_bh) {
dquot_free_block_nodirty(inode, 1);
mark_inode_dirty(inode);
}
/*
* Inode writeout failed. Backing everything out is complex so
* let's just leave it for e2fsck to cleanup the mess.
*/
if (error)
goto cleanup;
}
} else
mark_inode_dirty(inode);
+5 -2
View File
@@ -65,12 +65,14 @@ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,
/* Empty block? */
if (block_size == 0) {
for ( i = 0 ; i < pcount ; i++ ) {
unsigned int off = i ? 0 : poffset;
if (!pages[i])
continue;
memzero_page(pages[i], 0, PAGE_SIZE);
memzero_page(pages[i], off, PAGE_SIZE - off);
SetPageUptodate(pages[i]);
}
return ((loff_t)pcount) << PAGE_SHIFT;
return (((loff_t)pcount) << PAGE_SHIFT) - poffset;
}
/* Because zlib is not thread-safe, do all the I/O at the top. */
@@ -291,6 +293,7 @@ static int zisofs_fill_pages(struct inode *inode, int full_page, int pcount,
memzero_page(*pages, poffset, PAGE_SIZE - poffset);
SetPageUptodate(*pages);
}
brelse(bh);
return 0;
}
+4 -27
View File
@@ -84,7 +84,7 @@ int get_acorn_filename(struct iso_directory_record *de,
*/
static int do_isofs_readdir(struct inode *inode, struct file *file,
struct dir_context *ctx,
char *tmpname, struct iso_directory_record *tmpde)
char *tmpname)
{
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
@@ -133,26 +133,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *file,
offset_saved = offset;
offset += de_len;
/* Make sure we have a full directory entry */
if (offset >= bufsize) {
int slop = bufsize - offset + de_len;
memcpy(tmpde, de, slop);
offset &= bufsize - 1;
block++;
brelse(bh);
bh = NULL;
if (offset) {
bh = isofs_bread(inode, block);
if (!bh)
return 0;
memcpy((void *) tmpde + slop, bh->b_data, offset);
}
de = tmpde;
}
/* Basic sanity check, whether name doesn't exceed dir entry */
if (de_len < sizeof(struct iso_directory_record) ||
de_len < de->name_len[0] +
sizeof(struct iso_directory_record)) {
if (!isofs_dir_record_valid(de, offset_saved, bufsize)) {
printk(KERN_NOTICE "iso9660: Corrupted directory entry"
" in block %lu of inode %llu\n", block,
inode->i_ino);
@@ -254,16 +235,13 @@ static int isofs_readdir(struct file *file, struct dir_context *ctx)
{
int result;
char *tmpname;
struct iso_directory_record *tmpde;
struct inode *inode = file_inode(file);
tmpname = kmalloc(PAGE_SIZE, GFP_KERNEL);
tmpname = kmalloc(1024, GFP_KERNEL);
if (tmpname == NULL)
return -ENOMEM;
tmpde = (struct iso_directory_record *) (tmpname+1024);
result = do_isofs_readdir(inode, file, ctx, tmpname, tmpde);
result = do_isofs_readdir(inode, file, ctx, tmpname);
kfree(tmpname);
return result;
@@ -300,4 +278,3 @@ const struct inode_operations isofs_dir_inode_operations =
.fileattr_get = isofs_fileattr_get,
};
+9 -1
View File
@@ -83,13 +83,21 @@ static struct dentry *isofs_export_get_parent(struct dentry *child)
/* This is the "." entry. */
de = (struct iso_directory_record*)bh->b_data;
if (!isofs_dir_record_valid(de, 0, child_inode->i_sb->s_blocksize) ||
isonum_711(de->name_len) != 1 || de->name[0] != 0) {
printk(KERN_ERR "isofs: Unable to find the \".\" directory for NFS.\n");
rv = ERR_PTR(-EACCES);
goto out;
}
/* The ".." entry is always the second entry. */
parent_offset = (unsigned long)isonum_711(de->length);
de = (struct iso_directory_record*)(bh->b_data + parent_offset);
/* Verify it is in fact the ".." entry. */
if ((isonum_711(de->name_len) != 1) || (de->name[0] != 1)) {
if (!isofs_dir_record_valid(de, parent_offset,
child_inode->i_sb->s_blocksize) ||
isonum_711(de->name_len) != 1 || de->name[0] != 1) {
printk(KERN_ERR "isofs: Unable to find the \"..\" "
"directory for NFS.\n");
rv = ERR_PTR(-EACCES);
+3
View File
@@ -115,6 +115,9 @@ struct inode; /* To make gcc happy */
extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *, int relocated);
extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *);
extern int isofs_name_translate(struct iso_directory_record *, char *, struct inode *);
bool isofs_dir_record_valid(struct iso_directory_record *de,
unsigned long offset,
unsigned long bufsize);
int get_joliet_filename(struct iso_directory_record *, unsigned char *, struct inode *);
int get_acorn_filename(struct iso_directory_record *, char *, struct inode *);
+29 -30
View File
@@ -10,6 +10,26 @@
#include <linux/gfp.h>
#include "isofs.h"
bool isofs_dir_record_valid(struct iso_directory_record *de,
unsigned long offset,
unsigned long bufsize)
{
unsigned int len;
unsigned int name_len;
unsigned long min_len = offsetof(struct iso_directory_record, name);
if (offset > bufsize || bufsize - offset < min_len)
return false;
len = isonum_711(de->length);
name_len = isonum_711(de->name_len);
if (len < min_len || name_len > len - min_len)
return false;
if (len > bufsize - offset)
return false;
return true;
}
static int
isofs_cmp(struct dentry *dentry, const char *compare, int dlen)
{
@@ -28,7 +48,7 @@ isofs_cmp(struct dentry *dentry, const char *compare, int dlen)
static unsigned long
isofs_find_entry(struct inode *dir, struct dentry *dentry,
unsigned long *block_rv, unsigned long *offset_rv,
char *tmpname, struct iso_directory_record *tmpde)
char *tmpname)
{
unsigned long bufsize = ISOFS_BUFFER_SIZE(dir);
unsigned char bufbits = ISOFS_BUFFER_BITS(dir);
@@ -71,33 +91,15 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
offset += de_len;
f_pos += de_len;
/* Make sure we have a full directory entry */
if (offset >= bufsize) {
int slop = bufsize - offset + de_len;
memcpy(tmpde, de, slop);
offset &= bufsize - 1;
block++;
brelse(bh);
bh = NULL;
if (offset) {
bh = isofs_bread(dir, block);
if (!bh)
return 0;
memcpy((void *) tmpde + slop, bh->b_data, offset);
}
de = tmpde;
}
dlen = de->name_len[0];
dpnt = de->name;
/* Basic sanity check, whether name doesn't exceed dir entry */
if (de_len < dlen + sizeof(struct iso_directory_record)) {
if (!isofs_dir_record_valid(de, offset_saved, bufsize)) {
printk(KERN_NOTICE "iso9660: Corrupted directory entry"
" in block %lu of inode %llu\n", block,
dir->i_ino);
brelse(bh);
return 0;
}
dlen = de->name_len[0];
dpnt = de->name;
if (sbi->s_rock &&
((i = get_rock_ridge_filename(de, tmpname, dir)))) {
@@ -149,17 +151,14 @@ struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, unsigned i
unsigned long block;
unsigned long offset;
struct inode *inode;
struct page *page;
char *tmpname;
page = alloc_page(GFP_USER);
if (!page)
tmpname = kmalloc(1024, GFP_USER);
if (!tmpname)
return ERR_PTR(-ENOMEM);
found = isofs_find_entry(dir, dentry,
&block, &offset,
page_address(page),
1024 + page_address(page));
__free_page(page);
found = isofs_find_entry(dir, dentry, &block, &offset, tmpname);
kfree(tmpname);
inode = found ? isofs_iget(dir->i_sb, block, offset) : NULL;
+1
View File
@@ -599,6 +599,7 @@ static struct fanotify_event *fanotify_alloc_perm_event(const void *data,
pevent->hdr.pad = 0;
pevent->hdr.len = 0;
pevent->state = FAN_EVENT_INIT;
pevent->watchdog_cnt = 0;
pevent->path = *path;
/* NULL ppos means no range info */
pevent->ppos = range ? &range->pos : NULL;
-10
View File
@@ -25,16 +25,6 @@ config QUOTA_NETLINK_INTERFACE
hardlimit, etc.) will be reported through netlink interface. If unsure,
say Y.
config PRINT_QUOTA_WARNING
bool "Print quota warnings to console (OBSOLETE)"
depends on QUOTA && BROKEN
default y
help
If you say Y here, quota warnings (about exceeding softlimit, reaching
hardlimit, etc.) will be printed to the process' controlling terminal.
Note that this behavior is currently deprecated and may go away in
future. Please use notification via netlink socket instead.
config QUOTA_DEBUG
bool "Additional quota sanity checks"
depends on QUOTA
+2 -79
View File
@@ -153,7 +153,7 @@ void __quota_error(struct super_block *sb, const char *func,
}
EXPORT_SYMBOL(__quota_error);
#if defined(CONFIG_QUOTA_DEBUG) || defined(CONFIG_PRINT_QUOTA_WARNING)
#ifdef CONFIG_QUOTA_DEBUG
static char *quotatypes[] = INITQFNAMES;
#endif
static struct quota_format_type *quota_formats; /* List of registered formats */
@@ -1208,72 +1208,6 @@ static int warning_issued(struct dquot *dquot, const int warntype)
return test_and_set_bit(flag, &dquot->dq_flags);
}
#ifdef CONFIG_PRINT_QUOTA_WARNING
static int flag_print_warnings = 1;
static int need_print_warning(struct dquot_warn *warn)
{
if (!flag_print_warnings)
return 0;
switch (warn->w_dq_id.type) {
case USRQUOTA:
return uid_eq(current_fsuid(), warn->w_dq_id.uid);
case GRPQUOTA:
return in_group_p(warn->w_dq_id.gid);
case PRJQUOTA:
return 1;
}
return 0;
}
/* Print warning to user which exceeded quota */
static void print_warning(struct dquot_warn *warn)
{
char *msg = NULL;
struct tty_struct *tty;
int warntype = warn->w_type;
if (warntype == QUOTA_NL_IHARDBELOW ||
warntype == QUOTA_NL_ISOFTBELOW ||
warntype == QUOTA_NL_BHARDBELOW ||
warntype == QUOTA_NL_BSOFTBELOW || !need_print_warning(warn))
return;
tty = get_current_tty();
if (!tty)
return;
tty_write_message(tty, warn->w_sb->s_id);
if (warntype == QUOTA_NL_ISOFTWARN || warntype == QUOTA_NL_BSOFTWARN)
tty_write_message(tty, ": warning, ");
else
tty_write_message(tty, ": write failed, ");
tty_write_message(tty, quotatypes[warn->w_dq_id.type]);
switch (warntype) {
case QUOTA_NL_IHARDWARN:
msg = " file limit reached.\r\n";
break;
case QUOTA_NL_ISOFTLONGWARN:
msg = " file quota exceeded too long.\r\n";
break;
case QUOTA_NL_ISOFTWARN:
msg = " file quota exceeded.\r\n";
break;
case QUOTA_NL_BHARDWARN:
msg = " block limit reached.\r\n";
break;
case QUOTA_NL_BSOFTLONGWARN:
msg = " block quota exceeded too long.\r\n";
break;
case QUOTA_NL_BSOFTWARN:
msg = " block quota exceeded.\r\n";
break;
}
tty_write_message(tty, msg);
tty_kref_put(tty);
}
#endif
static void prepare_warning(struct dquot_warn *warn, struct dquot *dquot,
int warntype)
{
@@ -1296,9 +1230,7 @@ static void flush_warnings(struct dquot_warn *warn)
for (i = 0; i < MAXQUOTAS; i++) {
if (warn[i].w_type == QUOTA_NL_NOWARN)
continue;
#ifdef CONFIG_PRINT_QUOTA_WARNING
print_warning(&warn[i]);
#endif
quota_send_warning(warn[i].w_dq_id,
warn[i].w_sb->s_dev, warn[i].w_type);
}
@@ -3008,15 +2940,6 @@ static const struct ctl_table fs_dqstats_table[] = {
.mode = 0444,
.proc_handler = do_proc_dqstats,
},
#ifdef CONFIG_PRINT_QUOTA_WARNING
{
.procname = "warnings",
.data = &flag_print_warnings,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
#endif
};
static int __init dquot_init(void)
+10 -2
View File
@@ -502,6 +502,8 @@ static int udf_table_prealloc_blocks(struct super_block *sb,
int8_t etype = -1;
struct udf_inode_info *iinfo;
int ret = 0;
/* AED block freed by udf_delete_aext(), released after unlock */
struct kernel_lb_addr freed = { .partitionReferenceNum = 0xFFFF };
if (first_block >= sbi->s_partmaps[partition].s_partition_len)
return 0;
@@ -541,7 +543,7 @@ static int udf_table_prealloc_blocks(struct super_block *sb,
udf_write_aext(table, &epos, &eloc,
(etype << 30) | elen, 1);
} else
udf_delete_aext(table, epos);
udf_delete_aext(table, epos, &freed);
} else {
alloc_count = 0;
}
@@ -552,6 +554,8 @@ err_out:
if (alloc_count)
udf_add_free_space(sb, partition, -alloc_count);
mutex_unlock(&sbi->s_alloc_mutex);
if (freed.partitionReferenceNum != 0xFFFF)
udf_free_blocks(sb, table, &freed, 0, 1);
return alloc_count;
}
@@ -560,6 +564,8 @@ static udf_pblk_t udf_table_new_block(struct super_block *sb,
uint32_t goal, int *err)
{
struct udf_sb_info *sbi = UDF_SB(sb);
/* AED block freed by udf_delete_aext(), released after unlock */
struct kernel_lb_addr freed = { .partitionReferenceNum = 0xFFFF };
uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF;
udf_pblk_t newblock = 0;
uint32_t adsize;
@@ -643,12 +649,14 @@ static udf_pblk_t udf_table_new_block(struct super_block *sb,
if (goal_elen)
udf_write_aext(table, &goal_epos, &goal_eloc, goal_elen, 1);
else
udf_delete_aext(table, goal_epos);
udf_delete_aext(table, goal_epos, &freed);
brelse(goal_epos.bh);
udf_add_free_space(sb, partition, -1);
mutex_unlock(&sbi->s_alloc_mutex);
if (freed.partitionReferenceNum != 0xFFFF)
udf_free_blocks(sb, table, &freed, 0, 1);
*err = 0;
return newblock;
}
+99 -63
View File
@@ -336,65 +336,6 @@ const struct address_space_operations udf_aops = {
.migrate_folio = buffer_migrate_folio,
};
/*
* Expand file stored in ICB to a normal one-block-file
*
* This function requires i_mutex held
*/
int udf_expand_file_adinicb(struct inode *inode)
{
struct folio *folio;
struct udf_inode_info *iinfo = UDF_I(inode);
int err;
WARN_ON_ONCE(!inode_is_locked(inode));
if (!iinfo->i_lenAlloc) {
down_write(&iinfo->i_data_sem);
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
else
iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
up_write(&iinfo->i_data_sem);
mark_inode_dirty(inode);
return 0;
}
folio = __filemap_get_folio(inode->i_mapping, 0,
FGP_LOCK | FGP_ACCESSED | FGP_CREAT, GFP_KERNEL);
if (IS_ERR(folio))
return PTR_ERR(folio);
if (!folio_test_uptodate(folio))
udf_adinicb_read_folio(folio);
down_write(&iinfo->i_data_sem);
memset(iinfo->i_data + iinfo->i_lenEAttr, 0x00,
iinfo->i_lenAlloc);
iinfo->i_lenAlloc = 0;
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
else
iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
folio_mark_dirty(folio);
folio_unlock(folio);
up_write(&iinfo->i_data_sem);
err = filemap_fdatawrite(inode->i_mapping);
if (err) {
/* Restore everything back so that we don't lose data... */
folio_lock(folio);
down_write(&iinfo->i_data_sem);
memcpy_from_folio(iinfo->i_data + iinfo->i_lenEAttr,
folio, 0, inode->i_size);
folio_unlock(folio);
iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
iinfo->i_lenAlloc = inode->i_size;
up_write(&iinfo->i_data_sem);
}
folio_put(folio);
mark_inode_dirty(inode);
return err;
}
#define UDF_MAP_CREATE 0x01 /* Mapping can allocate new blocks */
#define UDF_MAP_NOPREALLOC 0x02 /* Do not preallocate blocks */
@@ -455,6 +396,76 @@ out_read:
return ret;
}
/*
* Expand file stored in ICB to a normal one-block-file
*
* This function requires i_mutex held
*/
int udf_expand_file_adinicb(struct inode *inode)
{
struct folio *folio;
struct udf_inode_info *iinfo = UDF_I(inode);
struct udf_map_rq map = {
.lblk = 0,
.iflags = UDF_MAP_CREATE,
};
int err;
WARN_ON_ONCE(!inode_is_locked(inode));
if (!iinfo->i_lenAlloc) {
down_write(&iinfo->i_data_sem);
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
else
iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
up_write(&iinfo->i_data_sem);
mark_inode_dirty(inode);
return 0;
}
folio = __filemap_get_folio(inode->i_mapping, 0,
FGP_LOCK | FGP_ACCESSED | FGP_CREAT, GFP_KERNEL);
if (IS_ERR(folio))
return PTR_ERR(folio);
if (!folio_test_uptodate(folio))
udf_adinicb_read_folio(folio);
down_write(&iinfo->i_data_sem);
memset(iinfo->i_data + iinfo->i_lenEAttr, 0x00,
iinfo->i_lenAlloc);
iinfo->i_lenAlloc = 0;
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
else
iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
up_write(&iinfo->i_data_sem);
/* Allocate the block underlying the data */
err = udf_map_block(inode, &map);
if (err < 0)
goto restore;
folio_mark_dirty(folio);
folio_unlock(folio);
err = filemap_fdatawrite(inode->i_mapping);
if (err) {
/* Restore everything back so that we don't lose data... */
folio_lock(folio);
restore:
down_write(&iinfo->i_data_sem);
memcpy_from_folio(iinfo->i_data + iinfo->i_lenEAttr,
folio, 0, inode->i_size);
iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
iinfo->i_lenAlloc = inode->i_size;
up_write(&iinfo->i_data_sem);
folio_unlock(folio);
}
folio_put(folio);
mark_inode_dirty(inode);
return err;
}
static int __udf_get_block(struct inode *inode, sector_t block,
struct buffer_head *bh_result, int flags)
{
@@ -531,7 +542,7 @@ static int udf_do_extend_file(struct inode *inode,
sb->s_blocksize - 1) & ~(sb->s_blocksize - 1));
iinfo->i_lenExtents =
(iinfo->i_lenExtents + sb->s_blocksize - 1) &
~(sb->s_blocksize - 1);
~((u64)sb->s_blocksize - 1);
}
add = 0;
@@ -1204,7 +1215,7 @@ static int udf_update_extents(struct inode *inode, struct kernel_long_ad *laarr,
if (startnum > endnum) {
for (i = 0; i < (startnum - endnum); i++)
udf_delete_aext(inode, *epos);
udf_delete_aext(inode, *epos, NULL);
} else if (startnum < endnum) {
for (i = 0; i < (endnum - startnum); i++) {
err = udf_insert_aext(inode, *epos,
@@ -1475,6 +1486,10 @@ reread:
iinfo->i_lenAlloc = le32_to_cpu(
((struct unallocSpaceEntry *)bh->b_data)->
lengthAllocDescs);
if (iinfo->i_lenAlloc > bs - sizeof(struct unallocSpaceEntry)) {
ret = -EFSCORRUPTED;
goto out;
}
ret = udf_alloc_i_data(inode, bs -
sizeof(struct unallocSpaceEntry));
if (ret)
@@ -1482,6 +1497,7 @@ reread:
memcpy(iinfo->i_data,
bh->b_data + sizeof(struct unallocSpaceEntry),
bs - sizeof(struct unallocSpaceEntry));
brelse(bh);
return 0;
}
@@ -2299,6 +2315,13 @@ int udf_current_aext(struct inode *inode, struct extent_position *epos,
return -EINVAL;
}
if (eloc->partitionReferenceNum >= UDF_SB(inode->i_sb)->s_partitions) {
udf_debug("invalid partition reference %u (partitions %u)\n",
eloc->partitionReferenceNum,
UDF_SB(inode->i_sb)->s_partitions);
return -EFSCORRUPTED;
}
return 1;
}
@@ -2328,7 +2351,8 @@ static int udf_insert_aext(struct inode *inode, struct extent_position epos,
return ret;
}
int8_t udf_delete_aext(struct inode *inode, struct extent_position epos)
int8_t udf_delete_aext(struct inode *inode, struct extent_position epos,
struct kernel_lb_addr *freed)
{
struct extent_position oepos;
int adsize;
@@ -2378,7 +2402,19 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos)
elen = 0;
if (epos.bh != oepos.bh) {
udf_free_blocks(inode->i_sb, inode, &epos.block, 0, 1);
/*
* The block that held the now-empty allocation extent must be
* returned to free space. When the caller already holds
* s_alloc_mutex (the space-table allocator in balloc.c),
* freeing it inline would recurse through udf_free_blocks()
* into udf_table_free_blocks() and deadlock re-acquiring
* s_alloc_mutex. In that case report the block to the caller,
* which frees it after dropping the lock.
*/
if (freed)
*freed = epos.block;
else
udf_free_blocks(inode->i_sb, inode, &epos.block, 0, 1);
udf_write_aext(inode, &oepos, &eloc, elen, 1);
udf_write_aext(inode, &oepos, &eloc, elen, 1);
if (!oepos.bh) {
+1 -1
View File
@@ -55,7 +55,7 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block,
map = &sbi->s_partmaps[partition];
vdata = &map->s_type_specific.s_virtual;
if (block > vdata->s_num_entries) {
if (block >= vdata->s_num_entries) {
udf_debug("Trying to access block beyond end of VAT (%u max %u)\n",
block, vdata->s_num_entries);
return 0xFFFFFFFF;
+14 -9
View File
@@ -2054,6 +2054,17 @@ static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt,
return 0;
}
static void udf_mark_buffer_dirty(struct buffer_head *bh)
{
/*
* We set buffer uptodate unconditionally here to avoid spurious
* warnings from mark_buffer_dirty() when previous EIO has marked
* the buffer as !uptodate
*/
set_buffer_uptodate(bh);
mark_buffer_dirty(bh);
}
static void udf_finalize_lvid(struct logicalVolIntegrityDesc *lvid)
{
struct timespec64 ts;
@@ -2089,7 +2100,7 @@ static void udf_open_lvid(struct super_block *sb)
UDF_SET_FLAG(sb, UDF_FLAG_INCONSISTENT);
udf_finalize_lvid(lvid);
mark_buffer_dirty(bh);
udf_mark_buffer_dirty(bh);
sbi->s_lvid_dirty = 0;
mutex_unlock(&sbi->s_alloc_mutex);
/* Make opening of filesystem visible on the media immediately */
@@ -2122,14 +2133,8 @@ static void udf_close_lvid(struct super_block *sb)
if (!UDF_QUERY_FLAG(sb, UDF_FLAG_INCONSISTENT))
lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE);
/*
* We set buffer uptodate unconditionally here to avoid spurious
* warnings from mark_buffer_dirty() when previous EIO has marked
* the buffer as !uptodate
*/
set_buffer_uptodate(bh);
udf_finalize_lvid(lvid);
mark_buffer_dirty(bh);
udf_mark_buffer_dirty(bh);
sbi->s_lvid_dirty = 0;
mutex_unlock(&sbi->s_alloc_mutex);
/* Make closing of filesystem visible on the media immediately */
@@ -2411,7 +2416,7 @@ static int udf_sync_fs(struct super_block *sb, int wait)
* Blockdevice will be synced later so we don't have to submit
* the buffer for IO
*/
mark_buffer_dirty(bh);
udf_mark_buffer_dirty(bh);
sbi->s_lvid_dirty = 0;
}
mutex_unlock(&sbi->s_alloc_mutex);

Some files were not shown because too many files have changed in this diff Show More