mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge branch 'for_next' of https://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs.git
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
Reference in New Issue
Block a user