Commit b77a69b8 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'fs_for_v5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs

Pull UDF, reiserfs, ext2, quota fixes from Jan Kara:

 - a couple of UDF fixes for issues found by syzbot fuzzing

 - a couple of reiserfs fixes for issues found by syzbot fuzzing

 - some minor ext2 cleanups

 - quota patches to support grace times beyond year 2038 for XFS quota
   APIs

* tag 'fs_for_v5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  reiserfs: Fix oops during mount
  udf: Limit sparing table size
  udf: Remove pointless union in udf_inode_info
  udf: Avoid accessing uninitialized data on failed inode read
  quota: clear padding in v2r1_mem2diskdqb()
  reiserfs: Initialize inode keys properly
  udf: Fix memory leak when mounting
  udf: Remove redundant initialization of variable ret
  reiserfs: only call unlock_new_inode() if I_NEW
  ext2: Fix some kernel-doc warnings in balloc.c
  quota: Expand comment describing d_itimer
  quota: widen timestamps for the fs_disk_quota structure
  reiserfs: Fix memory leak in reiserfs_parse_options()
  udf: Use kvzalloc() in udf_sb_alloc_bitmap()
  ext2: remove duplicate include
parents ca5387e4 c2bb80b8
...@@ -189,7 +189,7 @@ static void group_adjust_blocks(struct super_block *sb, int group_no, ...@@ -189,7 +189,7 @@ static void group_adjust_blocks(struct super_block *sb, int group_no,
/** /**
* __rsv_window_dump() -- Dump the filesystem block allocation reservation map * __rsv_window_dump() -- Dump the filesystem block allocation reservation map
* @rb_root: root of per-filesystem reservation rb tree * @root: root of per-filesystem reservation rb tree
* @verbose: verbose mode * @verbose: verbose mode
* @fn: function which wishes to dump the reservation map * @fn: function which wishes to dump the reservation map
* *
...@@ -282,7 +282,7 @@ goal_in_my_reservation(struct ext2_reserve_window *rsv, ext2_grpblk_t grp_goal, ...@@ -282,7 +282,7 @@ goal_in_my_reservation(struct ext2_reserve_window *rsv, ext2_grpblk_t grp_goal,
/** /**
* search_reserve_window() * search_reserve_window()
* @rb_root: root of reservation tree * @root: root of reservation tree
* @goal: target allocation block * @goal: target allocation block
* *
* Find the reserved window which includes the goal, or the previous one * Find the reserved window which includes the goal, or the previous one
...@@ -859,7 +859,7 @@ static int find_next_reservable_window( ...@@ -859,7 +859,7 @@ static int find_next_reservable_window(
* *
* failed: we failed to find a reservation window in this group * failed: we failed to find a reservation window in this group
* *
* @rsv: the reservation * @my_rsv: the reservation
* *
* @grp_goal: The goal (group-relative). It is where the search for a * @grp_goal: The goal (group-relative). It is where the search for a
* free reservable space should start from. * free reservable space should start from.
......
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#include <linux/iomap.h> #include <linux/iomap.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/fiemap.h>
#include "ext2.h" #include "ext2.h"
#include "acl.h" #include "acl.h"
#include "xattr.h" #include "xattr.h"
......
...@@ -532,6 +532,14 @@ static inline u64 quota_btobb(u64 bytes) ...@@ -532,6 +532,14 @@ static inline u64 quota_btobb(u64 bytes)
return (bytes + (1 << XFS_BB_SHIFT) - 1) >> XFS_BB_SHIFT; return (bytes + (1 << XFS_BB_SHIFT) - 1) >> XFS_BB_SHIFT;
} }
static inline s64 copy_from_xfs_dqblk_ts(const struct fs_disk_quota *d,
__s32 timer, __s8 timer_hi)
{
if (d->d_fieldmask & FS_DQ_BIGTIME)
return (u32)timer | (s64)timer_hi << 32;
return timer;
}
static void copy_from_xfs_dqblk(struct qc_dqblk *dst, struct fs_disk_quota *src) static void copy_from_xfs_dqblk(struct qc_dqblk *dst, struct fs_disk_quota *src)
{ {
dst->d_spc_hardlimit = quota_bbtob(src->d_blk_hardlimit); dst->d_spc_hardlimit = quota_bbtob(src->d_blk_hardlimit);
...@@ -540,14 +548,17 @@ static void copy_from_xfs_dqblk(struct qc_dqblk *dst, struct fs_disk_quota *src) ...@@ -540,14 +548,17 @@ static void copy_from_xfs_dqblk(struct qc_dqblk *dst, struct fs_disk_quota *src)
dst->d_ino_softlimit = src->d_ino_softlimit; dst->d_ino_softlimit = src->d_ino_softlimit;
dst->d_space = quota_bbtob(src->d_bcount); dst->d_space = quota_bbtob(src->d_bcount);
dst->d_ino_count = src->d_icount; dst->d_ino_count = src->d_icount;
dst->d_ino_timer = src->d_itimer; dst->d_ino_timer = copy_from_xfs_dqblk_ts(src, src->d_itimer,
dst->d_spc_timer = src->d_btimer; src->d_itimer_hi);
dst->d_spc_timer = copy_from_xfs_dqblk_ts(src, src->d_btimer,
src->d_btimer_hi);
dst->d_ino_warns = src->d_iwarns; dst->d_ino_warns = src->d_iwarns;
dst->d_spc_warns = src->d_bwarns; dst->d_spc_warns = src->d_bwarns;
dst->d_rt_spc_hardlimit = quota_bbtob(src->d_rtb_hardlimit); dst->d_rt_spc_hardlimit = quota_bbtob(src->d_rtb_hardlimit);
dst->d_rt_spc_softlimit = quota_bbtob(src->d_rtb_softlimit); dst->d_rt_spc_softlimit = quota_bbtob(src->d_rtb_softlimit);
dst->d_rt_space = quota_bbtob(src->d_rtbcount); dst->d_rt_space = quota_bbtob(src->d_rtbcount);
dst->d_rt_spc_timer = src->d_rtbtimer; dst->d_rt_spc_timer = copy_from_xfs_dqblk_ts(src, src->d_rtbtimer,
src->d_rtbtimer_hi);
dst->d_rt_spc_warns = src->d_rtbwarns; dst->d_rt_spc_warns = src->d_rtbwarns;
dst->d_fieldmask = 0; dst->d_fieldmask = 0;
if (src->d_fieldmask & FS_DQ_ISOFT) if (src->d_fieldmask & FS_DQ_ISOFT)
...@@ -639,10 +650,26 @@ static int quota_setxquota(struct super_block *sb, int type, qid_t id, ...@@ -639,10 +650,26 @@ static int quota_setxquota(struct super_block *sb, int type, qid_t id,
return sb->s_qcop->set_dqblk(sb, qid, &qdq); return sb->s_qcop->set_dqblk(sb, qid, &qdq);
} }
static inline void copy_to_xfs_dqblk_ts(const struct fs_disk_quota *d,
__s32 *timer_lo, __s8 *timer_hi, s64 timer)
{
*timer_lo = timer;
if (d->d_fieldmask & FS_DQ_BIGTIME)
*timer_hi = timer >> 32;
}
static inline bool want_bigtime(s64 timer)
{
return timer > S32_MAX || timer < S32_MIN;
}
static void copy_to_xfs_dqblk(struct fs_disk_quota *dst, struct qc_dqblk *src, static void copy_to_xfs_dqblk(struct fs_disk_quota *dst, struct qc_dqblk *src,
int type, qid_t id) int type, qid_t id)
{ {
memset(dst, 0, sizeof(*dst)); memset(dst, 0, sizeof(*dst));
if (want_bigtime(src->d_ino_timer) || want_bigtime(src->d_spc_timer) ||
want_bigtime(src->d_rt_spc_timer))
dst->d_fieldmask |= FS_DQ_BIGTIME;
dst->d_version = FS_DQUOT_VERSION; dst->d_version = FS_DQUOT_VERSION;
dst->d_id = id; dst->d_id = id;
if (type == USRQUOTA) if (type == USRQUOTA)
...@@ -657,14 +684,17 @@ static void copy_to_xfs_dqblk(struct fs_disk_quota *dst, struct qc_dqblk *src, ...@@ -657,14 +684,17 @@ static void copy_to_xfs_dqblk(struct fs_disk_quota *dst, struct qc_dqblk *src,
dst->d_ino_softlimit = src->d_ino_softlimit; dst->d_ino_softlimit = src->d_ino_softlimit;
dst->d_bcount = quota_btobb(src->d_space); dst->d_bcount = quota_btobb(src->d_space);
dst->d_icount = src->d_ino_count; dst->d_icount = src->d_ino_count;
dst->d_itimer = src->d_ino_timer; copy_to_xfs_dqblk_ts(dst, &dst->d_itimer, &dst->d_itimer_hi,
dst->d_btimer = src->d_spc_timer; src->d_ino_timer);
copy_to_xfs_dqblk_ts(dst, &dst->d_btimer, &dst->d_btimer_hi,
src->d_spc_timer);
dst->d_iwarns = src->d_ino_warns; dst->d_iwarns = src->d_ino_warns;
dst->d_bwarns = src->d_spc_warns; dst->d_bwarns = src->d_spc_warns;
dst->d_rtb_hardlimit = quota_btobb(src->d_rt_spc_hardlimit); dst->d_rtb_hardlimit = quota_btobb(src->d_rt_spc_hardlimit);
dst->d_rtb_softlimit = quota_btobb(src->d_rt_spc_softlimit); dst->d_rtb_softlimit = quota_btobb(src->d_rt_spc_softlimit);
dst->d_rtbcount = quota_btobb(src->d_rt_space); dst->d_rtbcount = quota_btobb(src->d_rt_space);
dst->d_rtbtimer = src->d_rt_spc_timer; copy_to_xfs_dqblk_ts(dst, &dst->d_rtbtimer, &dst->d_rtbtimer_hi,
src->d_rt_spc_timer);
dst->d_rtbwarns = src->d_rt_spc_warns; dst->d_rtbwarns = src->d_rt_spc_warns;
} }
......
...@@ -282,6 +282,7 @@ static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot) ...@@ -282,6 +282,7 @@ static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot)
d->dqb_curspace = cpu_to_le64(m->dqb_curspace); d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
d->dqb_btime = cpu_to_le64(m->dqb_btime); d->dqb_btime = cpu_to_le64(m->dqb_btime);
d->dqb_id = cpu_to_le32(from_kqid(&init_user_ns, dquot->dq_id)); d->dqb_id = cpu_to_le32(from_kqid(&init_user_ns, dquot->dq_id));
d->dqb_pad = 0;
if (qtree_entry_unused(info, dp)) if (qtree_entry_unused(info, dp))
d->dqb_itime = cpu_to_le64(1); d->dqb_itime = cpu_to_le64(1);
} }
......
...@@ -1551,11 +1551,7 @@ void reiserfs_read_locked_inode(struct inode *inode, ...@@ -1551,11 +1551,7 @@ void reiserfs_read_locked_inode(struct inode *inode,
* set version 1, version 2 could be used too, because stat data * set version 1, version 2 could be used too, because stat data
* key is the same in both versions * key is the same in both versions
*/ */
key.version = KEY_FORMAT_3_5; _make_cpu_key(&key, KEY_FORMAT_3_5, dirino, inode->i_ino, 0, 0, 3);
key.on_disk_key.k_dir_id = dirino;
key.on_disk_key.k_objectid = inode->i_ino;
key.on_disk_key.k_offset = 0;
key.on_disk_key.k_type = 0;
/* look for the object's stat data */ /* look for the object's stat data */
retval = search_item(inode->i_sb, &key, &path_to_sd); retval = search_item(inode->i_sb, &key, &path_to_sd);
...@@ -2163,7 +2159,8 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, ...@@ -2163,7 +2159,8 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
out_inserted_sd: out_inserted_sd:
clear_nlink(inode); clear_nlink(inode);
th->t_trans_id = 0; /* so the caller can't use this handle later */ th->t_trans_id = 0; /* so the caller can't use this handle later */
unlock_new_inode(inode); /* OK to do even if we hadn't locked it */ if (inode->i_state & I_NEW)
unlock_new_inode(inode);
iput(inode); iput(inode);
return err; return err;
} }
......
...@@ -1258,6 +1258,10 @@ static int reiserfs_parse_options(struct super_block *s, ...@@ -1258,6 +1258,10 @@ static int reiserfs_parse_options(struct super_block *s,
"turned on."); "turned on.");
return 0; return 0;
} }
if (qf_names[qtype] !=
REISERFS_SB(s)->s_qf_names[qtype])
kfree(qf_names[qtype]);
qf_names[qtype] = NULL;
if (*arg) { /* Some filename specified? */ if (*arg) { /* Some filename specified? */
if (REISERFS_SB(s)->s_qf_names[qtype] if (REISERFS_SB(s)->s_qf_names[qtype]
&& strcmp(REISERFS_SB(s)->s_qf_names[qtype], && strcmp(REISERFS_SB(s)->s_qf_names[qtype],
...@@ -1287,10 +1291,6 @@ static int reiserfs_parse_options(struct super_block *s, ...@@ -1287,10 +1291,6 @@ static int reiserfs_parse_options(struct super_block *s,
else else
*mount_options |= 1 << REISERFS_GRPQUOTA; *mount_options |= 1 << REISERFS_GRPQUOTA;
} else { } else {
if (qf_names[qtype] !=
REISERFS_SB(s)->s_qf_names[qtype])
kfree(qf_names[qtype]);
qf_names[qtype] = NULL;
if (qtype == USRQUOTA) if (qtype == USRQUOTA)
*mount_options &= ~(1 << REISERFS_USRQUOTA); *mount_options &= ~(1 << REISERFS_USRQUOTA);
else else
......
...@@ -674,6 +674,13 @@ reiserfs_xattr_get(struct inode *inode, const char *name, void *buffer, ...@@ -674,6 +674,13 @@ reiserfs_xattr_get(struct inode *inode, const char *name, void *buffer,
if (get_inode_sd_version(inode) == STAT_DATA_V1) if (get_inode_sd_version(inode) == STAT_DATA_V1)
return -EOPNOTSUPP; return -EOPNOTSUPP;
/*
* priv_root needn't be initialized during mount so allow initial
* lookups to succeed.
*/
if (!REISERFS_SB(inode->i_sb)->priv_root)
return 0;
dentry = xattr_lookup(inode, name, XATTR_REPLACE); dentry = xattr_lookup(inode, name, XATTR_REPLACE);
if (IS_ERR(dentry)) { if (IS_ERR(dentry)) {
err = PTR_ERR(dentry); err = PTR_ERR(dentry);
......
...@@ -34,7 +34,7 @@ struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos, ...@@ -34,7 +34,7 @@ struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos,
fibh->soffset = fibh->eoffset; fibh->soffset = fibh->eoffset;
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
fi = udf_get_fileident(iinfo->i_ext.i_data - fi = udf_get_fileident(iinfo->i_data -
(iinfo->i_efe ? (iinfo->i_efe ?
sizeof(struct extendedFileEntry) : sizeof(struct extendedFileEntry) :
sizeof(struct fileEntry)), sizeof(struct fileEntry)),
......
...@@ -50,7 +50,7 @@ static void __udf_adinicb_readpage(struct page *page) ...@@ -50,7 +50,7 @@ static void __udf_adinicb_readpage(struct page *page)
* So just sample it once and use the same value everywhere. * So just sample it once and use the same value everywhere.
*/ */
kaddr = kmap_atomic(page); kaddr = kmap_atomic(page);
memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr, isize); memcpy(kaddr, iinfo->i_data + iinfo->i_lenEAttr, isize);
memset(kaddr + isize, 0, PAGE_SIZE - isize); memset(kaddr + isize, 0, PAGE_SIZE - isize);
flush_dcache_page(page); flush_dcache_page(page);
SetPageUptodate(page); SetPageUptodate(page);
...@@ -76,8 +76,7 @@ static int udf_adinicb_writepage(struct page *page, ...@@ -76,8 +76,7 @@ static int udf_adinicb_writepage(struct page *page,
BUG_ON(!PageLocked(page)); BUG_ON(!PageLocked(page));
kaddr = kmap_atomic(page); kaddr = kmap_atomic(page);
memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr, memcpy(iinfo->i_data + iinfo->i_lenEAttr, kaddr, i_size_read(inode));
i_size_read(inode));
SetPageUptodate(page); SetPageUptodate(page);
kunmap_atomic(kaddr); kunmap_atomic(kaddr);
mark_inode_dirty(inode); mark_inode_dirty(inode);
...@@ -215,7 +214,7 @@ long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -215,7 +214,7 @@ long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return put_user(UDF_I(inode)->i_lenEAttr, (int __user *)arg); return put_user(UDF_I(inode)->i_lenEAttr, (int __user *)arg);
case UDF_GETEABLOCK: case UDF_GETEABLOCK:
return copy_to_user((char __user *)arg, return copy_to_user((char __user *)arg,
UDF_I(inode)->i_ext.i_data, UDF_I(inode)->i_data,
UDF_I(inode)->i_lenEAttr) ? -EFAULT : 0; UDF_I(inode)->i_lenEAttr) ? -EFAULT : 0;
default: default:
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
......
...@@ -67,16 +67,16 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode) ...@@ -67,16 +67,16 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode)
iinfo->i_efe = 1; iinfo->i_efe = 1;
if (UDF_VERS_USE_EXTENDED_FE > sbi->s_udfrev) if (UDF_VERS_USE_EXTENDED_FE > sbi->s_udfrev)
sbi->s_udfrev = UDF_VERS_USE_EXTENDED_FE; sbi->s_udfrev = UDF_VERS_USE_EXTENDED_FE;
iinfo->i_ext.i_data = kzalloc(inode->i_sb->s_blocksize - iinfo->i_data = kzalloc(inode->i_sb->s_blocksize -
sizeof(struct extendedFileEntry), sizeof(struct extendedFileEntry),
GFP_KERNEL); GFP_KERNEL);
} else { } else {
iinfo->i_efe = 0; iinfo->i_efe = 0;
iinfo->i_ext.i_data = kzalloc(inode->i_sb->s_blocksize - iinfo->i_data = kzalloc(inode->i_sb->s_blocksize -
sizeof(struct fileEntry), sizeof(struct fileEntry),
GFP_KERNEL); GFP_KERNEL);
} }
if (!iinfo->i_ext.i_data) { if (!iinfo->i_data) {
iput(inode); iput(inode);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
......
...@@ -139,23 +139,26 @@ void udf_evict_inode(struct inode *inode) ...@@ -139,23 +139,26 @@ void udf_evict_inode(struct inode *inode)
struct udf_inode_info *iinfo = UDF_I(inode); struct udf_inode_info *iinfo = UDF_I(inode);
int want_delete = 0; int want_delete = 0;
if (!inode->i_nlink && !is_bad_inode(inode)) { if (!is_bad_inode(inode)) {
if (!inode->i_nlink) {
want_delete = 1; want_delete = 1;
udf_setsize(inode, 0); udf_setsize(inode, 0);
udf_update_inode(inode, IS_SYNC(inode)); udf_update_inode(inode, IS_SYNC(inode));
} }
truncate_inode_pages_final(&inode->i_data);
invalidate_inode_buffers(inode);
clear_inode(inode);
if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB &&
inode->i_size != iinfo->i_lenExtents) { inode->i_size != iinfo->i_lenExtents) {
udf_warn(inode->i_sb, "Inode %lu (mode %o) has inode size %llu different from extent length %llu. Filesystem need not be standards compliant.\n", udf_warn(inode->i_sb,
"Inode %lu (mode %o) has inode size %llu different from extent length %llu. Filesystem need not be standards compliant.\n",
inode->i_ino, inode->i_mode, inode->i_ino, inode->i_mode,
(unsigned long long)inode->i_size, (unsigned long long)inode->i_size,
(unsigned long long)iinfo->i_lenExtents); (unsigned long long)iinfo->i_lenExtents);
} }
kfree(iinfo->i_ext.i_data); }
iinfo->i_ext.i_data = NULL; truncate_inode_pages_final(&inode->i_data);
invalidate_inode_buffers(inode);
clear_inode(inode);
kfree(iinfo->i_data);
iinfo->i_data = NULL;
udf_clear_extent_cache(inode); udf_clear_extent_cache(inode);
if (want_delete) { if (want_delete) {
udf_free_inode(inode); udf_free_inode(inode);
...@@ -285,14 +288,14 @@ int udf_expand_file_adinicb(struct inode *inode) ...@@ -285,14 +288,14 @@ int udf_expand_file_adinicb(struct inode *inode)
kaddr = kmap_atomic(page); kaddr = kmap_atomic(page);
memset(kaddr + iinfo->i_lenAlloc, 0x00, memset(kaddr + iinfo->i_lenAlloc, 0x00,
PAGE_SIZE - iinfo->i_lenAlloc); PAGE_SIZE - iinfo->i_lenAlloc);
memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr, memcpy(kaddr, iinfo->i_data + iinfo->i_lenEAttr,
iinfo->i_lenAlloc); iinfo->i_lenAlloc);
flush_dcache_page(page); flush_dcache_page(page);
SetPageUptodate(page); SetPageUptodate(page);
kunmap_atomic(kaddr); kunmap_atomic(kaddr);
} }
down_write(&iinfo->i_data_sem); down_write(&iinfo->i_data_sem);
memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0x00, memset(iinfo->i_data + iinfo->i_lenEAttr, 0x00,
iinfo->i_lenAlloc); iinfo->i_lenAlloc);
iinfo->i_lenAlloc = 0; iinfo->i_lenAlloc = 0;
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD)) if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
...@@ -308,8 +311,7 @@ int udf_expand_file_adinicb(struct inode *inode) ...@@ -308,8 +311,7 @@ int udf_expand_file_adinicb(struct inode *inode)
lock_page(page); lock_page(page);
down_write(&iinfo->i_data_sem); down_write(&iinfo->i_data_sem);
kaddr = kmap_atomic(page); kaddr = kmap_atomic(page);
memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr, memcpy(iinfo->i_data + iinfo->i_lenEAttr, kaddr, inode->i_size);
inode->i_size);
kunmap_atomic(kaddr); kunmap_atomic(kaddr);
unlock_page(page); unlock_page(page);
iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
...@@ -396,8 +398,7 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, ...@@ -396,8 +398,7 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode,
} }
mark_buffer_dirty_inode(dbh, inode); mark_buffer_dirty_inode(dbh, inode);
memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0, memset(iinfo->i_data + iinfo->i_lenEAttr, 0, iinfo->i_lenAlloc);
iinfo->i_lenAlloc);
iinfo->i_lenAlloc = 0; iinfo->i_lenAlloc = 0;
eloc.logicalBlockNum = *block; eloc.logicalBlockNum = *block;
eloc.partitionReferenceNum = eloc.partitionReferenceNum =
...@@ -1260,7 +1261,7 @@ int udf_setsize(struct inode *inode, loff_t newsize) ...@@ -1260,7 +1261,7 @@ int udf_setsize(struct inode *inode, loff_t newsize)
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
down_write(&iinfo->i_data_sem); down_write(&iinfo->i_data_sem);
udf_clear_extent_cache(inode); udf_clear_extent_cache(inode);
memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr + newsize, memset(iinfo->i_data + iinfo->i_lenEAttr + newsize,
0x00, bsize - newsize - 0x00, bsize - newsize -
udf_file_entry_alloc_offset(inode)); udf_file_entry_alloc_offset(inode));
iinfo->i_lenAlloc = newsize; iinfo->i_lenAlloc = newsize;
...@@ -1411,7 +1412,7 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode) ...@@ -1411,7 +1412,7 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode)
sizeof(struct extendedFileEntry)); sizeof(struct extendedFileEntry));
if (ret) if (ret)
goto out; goto out;
memcpy(iinfo->i_ext.i_data, memcpy(iinfo->i_data,
bh->b_data + sizeof(struct extendedFileEntry), bh->b_data + sizeof(struct extendedFileEntry),
bs - sizeof(struct extendedFileEntry)); bs - sizeof(struct extendedFileEntry));
} else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_FE)) { } else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_FE)) {
...@@ -1420,7 +1421,7 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode) ...@@ -1420,7 +1421,7 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode)
ret = udf_alloc_i_data(inode, bs - sizeof(struct fileEntry)); ret = udf_alloc_i_data(inode, bs - sizeof(struct fileEntry));
if (ret) if (ret)
goto out; goto out;
memcpy(iinfo->i_ext.i_data, memcpy(iinfo->i_data,
bh->b_data + sizeof(struct fileEntry), bh->b_data + sizeof(struct fileEntry),
bs - sizeof(struct fileEntry)); bs - sizeof(struct fileEntry));
} else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_USE)) { } else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_USE)) {
...@@ -1433,7 +1434,7 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode) ...@@ -1433,7 +1434,7 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode)
sizeof(struct unallocSpaceEntry)); sizeof(struct unallocSpaceEntry));
if (ret) if (ret)
goto out; goto out;
memcpy(iinfo->i_ext.i_data, memcpy(iinfo->i_data,
bh->b_data + sizeof(struct unallocSpaceEntry), bh->b_data + sizeof(struct unallocSpaceEntry),
bs - sizeof(struct unallocSpaceEntry)); bs - sizeof(struct unallocSpaceEntry));
return 0; return 0;
...@@ -1614,8 +1615,8 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode) ...@@ -1614,8 +1615,8 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode)
static int udf_alloc_i_data(struct inode *inode, size_t size) static int udf_alloc_i_data(struct inode *inode, size_t size)
{ {
struct udf_inode_info *iinfo = UDF_I(inode); struct udf_inode_info *iinfo = UDF_I(inode);
iinfo->i_ext.i_data = kmalloc(size, GFP_KERNEL); iinfo->i_data = kmalloc(size, GFP_KERNEL);
if (!iinfo->i_ext.i_data) if (!iinfo->i_data)
return -ENOMEM; return -ENOMEM;
return 0; return 0;
} }
...@@ -1706,7 +1707,7 @@ static int udf_update_inode(struct inode *inode, int do_sync) ...@@ -1706,7 +1707,7 @@ static int udf_update_inode(struct inode *inode, int do_sync)
use->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc); use->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc);
memcpy(bh->b_data + sizeof(struct unallocSpaceEntry), memcpy(bh->b_data + sizeof(struct unallocSpaceEntry),
iinfo->i_ext.i_data, inode->i_sb->s_blocksize - iinfo->i_data, inode->i_sb->s_blocksize -
sizeof(struct unallocSpaceEntry)); sizeof(struct unallocSpaceEntry));
use->descTag.tagIdent = cpu_to_le16(TAG_IDENT_USE); use->descTag.tagIdent = cpu_to_le16(TAG_IDENT_USE);
crclen = sizeof(struct unallocSpaceEntry); crclen = sizeof(struct unallocSpaceEntry);
...@@ -1772,7 +1773,7 @@ static int udf_update_inode(struct inode *inode, int do_sync) ...@@ -1772,7 +1773,7 @@ static int udf_update_inode(struct inode *inode, int do_sync)
if (iinfo->i_efe == 0) { if (iinfo->i_efe == 0) {
memcpy(bh->b_data + sizeof(struct fileEntry), memcpy(bh->b_data + sizeof(struct fileEntry),
iinfo->i_ext.i_data, iinfo->i_data,
inode->i_sb->s_blocksize - sizeof(struct fileEntry)); inode->i_sb->s_blocksize - sizeof(struct fileEntry));
fe->logicalBlocksRecorded = cpu_to_le64(lb_recorded); fe->logicalBlocksRecorded = cpu_to_le64(lb_recorded);
...@@ -1791,7 +1792,7 @@ static int udf_update_inode(struct inode *inode, int do_sync) ...@@ -1791,7 +1792,7 @@ static int udf_update_inode(struct inode *inode, int do_sync)
crclen = sizeof(struct fileEntry); crclen = sizeof(struct fileEntry);
} else { } else {
memcpy(bh->b_data + sizeof(struct extendedFileEntry), memcpy(bh->b_data + sizeof(struct extendedFileEntry),
iinfo->i_ext.i_data, iinfo->i_data,
inode->i_sb->s_blocksize - inode->i_sb->s_blocksize -
sizeof(struct extendedFileEntry)); sizeof(struct extendedFileEntry));
efe->objectSize = efe->objectSize =
...@@ -2087,7 +2088,7 @@ void udf_write_aext(struct inode *inode, struct extent_position *epos, ...@@ -2087,7 +2088,7 @@ void udf_write_aext(struct inode *inode, struct extent_position *epos,
struct udf_inode_info *iinfo = UDF_I(inode); struct udf_inode_info *iinfo = UDF_I(inode);
if (!epos->bh) if (!epos->bh)
ptr = iinfo->i_ext.i_data + epos->offset - ptr = iinfo->i_data + epos->offset -
udf_file_entry_alloc_offset(inode) + udf_file_entry_alloc_offset(inode) +
iinfo->i_lenEAttr; iinfo->i_lenEAttr;
else else
...@@ -2179,7 +2180,7 @@ int8_t udf_current_aext(struct inode *inode, struct extent_position *epos, ...@@ -2179,7 +2180,7 @@ int8_t udf_current_aext(struct inode *inode, struct extent_position *epos,
if (!epos->bh) { if (!epos->bh) {
if (!epos->offset) if (!epos->offset)
epos->offset = udf_file_entry_alloc_offset(inode); epos->offset = udf_file_entry_alloc_offset(inode);
ptr = iinfo->i_ext.i_data + epos->offset - ptr = iinfo->i_data + epos->offset -
udf_file_entry_alloc_offset(inode) + udf_file_entry_alloc_offset(inode) +
iinfo->i_lenEAttr; iinfo->i_lenEAttr;
alen = udf_file_entry_alloc_offset(inode) + alen = udf_file_entry_alloc_offset(inode) +
......
...@@ -52,9 +52,9 @@ struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size, ...@@ -52,9 +52,9 @@ struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size,
uint16_t crclen; uint16_t crclen;
struct udf_inode_info *iinfo = UDF_I(inode); struct udf_inode_info *iinfo = UDF_I(inode);
ea = iinfo->i_ext.i_data; ea = iinfo->i_data;
if (iinfo->i_lenEAttr) { if (iinfo->i_lenEAttr) {
ad = iinfo->i_ext.i_data + iinfo->i_lenEAttr; ad = iinfo->i_data + iinfo->i_lenEAttr;
} else { } else {
ad = ea; ad = ea;
size += sizeof(struct extendedAttrHeaderDesc); size += sizeof(struct extendedAttrHeaderDesc);
...@@ -153,7 +153,7 @@ struct genericFormat *udf_get_extendedattr(struct inode *inode, uint32_t type, ...@@ -153,7 +153,7 @@ struct genericFormat *udf_get_extendedattr(struct inode *inode, uint32_t type,
uint32_t offset; uint32_t offset;
struct udf_inode_info *iinfo = UDF_I(inode); struct udf_inode_info *iinfo = UDF_I(inode);
ea = iinfo->i_ext.i_data; ea = iinfo->i_data;
if (iinfo->i_lenEAttr) { if (iinfo->i_lenEAttr) {
struct extendedAttrHeaderDesc *eahd; struct extendedAttrHeaderDesc *eahd;
......
...@@ -460,8 +460,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, ...@@ -460,8 +460,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
block = dinfo->i_location.logicalBlockNum; block = dinfo->i_location.logicalBlockNum;
fi = (struct fileIdentDesc *) fi = (struct fileIdentDesc *)
(dinfo->i_ext.i_data + (dinfo->i_data + fibh->soffset -
fibh->soffset -
udf_ext0_offset(dir) + udf_ext0_offset(dir) +
dinfo->i_lenEAttr); dinfo->i_lenEAttr);
} else { } else {
...@@ -940,7 +939,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, ...@@ -940,7 +939,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
mark_buffer_dirty_inode(epos.bh, inode); mark_buffer_dirty_inode(epos.bh, inode);
ea = epos.bh->b_data + udf_ext0_offset(inode); ea = epos.bh->b_data + udf_ext0_offset(inode);
} else } else
ea = iinfo->i_ext.i_data + iinfo->i_lenEAttr; ea = iinfo->i_data + iinfo->i_lenEAttr;
eoffset = sb->s_blocksize - udf_ext0_offset(inode); eoffset = sb->s_blocksize - udf_ext0_offset(inode);
pc = (struct pathComponent *)ea; pc = (struct pathComponent *)ea;
...@@ -1120,7 +1119,7 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1120,7 +1119,7 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,
retval = -EIO; retval = -EIO;
if (old_iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { if (old_iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
dir_fi = udf_get_fileident( dir_fi = udf_get_fileident(
old_iinfo->i_ext.i_data - old_iinfo->i_data -
(old_iinfo->i_efe ? (old_iinfo->i_efe ?
sizeof(struct extendedFileEntry) : sizeof(struct extendedFileEntry) :
sizeof(struct fileEntry)), sizeof(struct fileEntry)),
......
...@@ -65,7 +65,7 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block, ...@@ -65,7 +65,7 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block,
} }
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
loc = le32_to_cpu(((__le32 *)(iinfo->i_ext.i_data + loc = le32_to_cpu(((__le32 *)(iinfo->i_data +
vdata->s_start_offset))[block]); vdata->s_start_offset))[block]);
goto translate; goto translate;
} }
......
...@@ -168,7 +168,7 @@ static void init_once(void *foo) ...@@ -168,7 +168,7 @@ static void init_once(void *foo)
{ {
struct udf_inode_info *ei = (struct udf_inode_info *)foo; struct udf_inode_info *ei = (struct udf_inode_info *)foo;
ei->i_ext.i_data = NULL; ei->i_data = NULL;
inode_init_once(&ei->vfs_inode); inode_init_once(&ei->vfs_inode);
} }
...@@ -854,7 +854,7 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block) ...@@ -854,7 +854,7 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
uint8_t *outstr; uint8_t *outstr;
struct buffer_head *bh; struct buffer_head *bh;
uint16_t ident; uint16_t ident;
int ret = -ENOMEM; int ret;
struct timestamp *ts; struct timestamp *ts;
outstr = kmalloc(128, GFP_NOFS); outstr = kmalloc(128, GFP_NOFS);
...@@ -1006,18 +1006,10 @@ int udf_compute_nr_groups(struct super_block *sb, u32 partition) ...@@ -1006,18 +1006,10 @@ int udf_compute_nr_groups(struct super_block *sb, u32 partition)
static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index) static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index)
{ {
struct udf_bitmap *bitmap; struct udf_bitmap *bitmap;
int nr_groups; int nr_groups = udf_compute_nr_groups(sb, index);
int size;
nr_groups = udf_compute_nr_groups(sb, index);
size = sizeof(struct udf_bitmap) +
(sizeof(struct buffer_head *) * nr_groups);
if (size <= PAGE_SIZE)
bitmap = kzalloc(size, GFP_KERNEL);
else
bitmap = vzalloc(size); /* TODO: get rid of vzalloc */
bitmap = kvzalloc(struct_size(bitmap, s_block_bitmap, nr_groups),
GFP_KERNEL);
if (!bitmap) if (!bitmap)
return NULL; return NULL;
...@@ -1210,7 +1202,7 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) ...@@ -1210,7 +1202,7 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
vat20 = (struct virtualAllocationTable20 *)bh->b_data; vat20 = (struct virtualAllocationTable20 *)bh->b_data;
} else { } else {
vat20 = (struct virtualAllocationTable20 *) vat20 = (struct virtualAllocationTable20 *)
vati->i_ext.i_data; vati->i_data;
} }
map->s_type_specific.s_virtual.s_start_offset = map->s_type_specific.s_virtual.s_start_offset =
...@@ -1353,6 +1345,12 @@ static int udf_load_sparable_map(struct super_block *sb, ...@@ -1353,6 +1345,12 @@ static int udf_load_sparable_map(struct super_block *sb,
(int)spm->numSparingTables); (int)spm->numSparingTables);
return -EIO; return -EIO;
} }
if (le32_to_cpu(spm->sizeSparingTable) > sb->s_blocksize) {
udf_err(sb, "error loading logical volume descriptor: "
"Too big sparing table size (%u)\n",
le32_to_cpu(spm->sizeSparingTable));
return -EIO;
}
for (i = 0; i < spm->numSparingTables; i++) { for (i = 0; i < spm->numSparingTables; i++) {
loc = le32_to_cpu(spm->locSparingTable[i]); loc = le32_to_cpu(spm->locSparingTable[i]);
...@@ -1698,7 +1696,8 @@ static noinline int udf_process_sequence( ...@@ -1698,7 +1696,8 @@ static noinline int udf_process_sequence(
"Pointers (max %u supported)\n", "Pointers (max %u supported)\n",
UDF_MAX_TD_NESTING); UDF_MAX_TD_NESTING);
brelse(bh); brelse(bh);
return -EIO; ret = -EIO;
goto out;
} }
vdp = (struct volDescPtr *)bh->b_data; vdp = (struct volDescPtr *)bh->b_data;
...@@ -1718,7 +1717,8 @@ static noinline int udf_process_sequence( ...@@ -1718,7 +1717,8 @@ static noinline int udf_process_sequence(
curr = get_volume_descriptor_record(ident, bh, &data); curr = get_volume_descriptor_record(ident, bh, &data);
if (IS_ERR(curr)) { if (IS_ERR(curr)) {
brelse(bh); brelse(bh);
return PTR_ERR(curr); ret = PTR_ERR(curr);
goto out;
} }
/* Descriptor we don't care about? */ /* Descriptor we don't care about? */
if (!curr) if (!curr)
...@@ -1740,28 +1740,31 @@ static noinline int udf_process_sequence( ...@@ -1740,28 +1740,31 @@ static noinline int udf_process_sequence(
*/ */
if (!data.vds[VDS_POS_PRIMARY_VOL_DESC].block) { if (!data.vds[VDS_POS_PRIMARY_VOL_DESC].block) {
udf_err(sb, "Primary Volume Descriptor not found!\n"); udf_err(sb, "Primary Volume Descriptor not found!\n");
return -EAGAIN; ret = -EAGAIN;
goto out;
} }
ret = udf_load_pvoldesc(sb, data.vds[VDS_POS_PRIMARY_VOL_DESC].block); ret = udf_load_pvoldesc(sb, data.vds[VDS_POS_PRIMARY_VOL_DESC].block);
if (ret < 0) if (ret < 0)
return ret; goto out;
if (data.vds[VDS_POS_LOGICAL_VOL_DESC].block) { if (data.vds[VDS_POS_LOGICAL_VOL_DESC].block) {
ret = udf_load_logicalvol(sb, ret = udf_load_logicalvol(sb,
data.vds[VDS_POS_LOGICAL_VOL_DESC].block, data.vds[VDS_POS_LOGICAL_VOL_DESC].block,
fileset); fileset);
if (ret < 0) if (ret < 0)
return ret; goto out;
} }
/* Now handle prevailing Partition Descriptors */ /* Now handle prevailing Partition Descriptors */
for (i = 0; i < data.num_part_descs; i++) { for (i = 0; i < data.num_part_descs; i++) {
ret = udf_load_partdesc(sb, data.part_descs_loc[i].rec.block); ret = udf_load_partdesc(sb, data.part_descs_loc[i].rec.block);
if (ret < 0) if (ret < 0)
return ret; goto out;
} }
ret = 0;
return 0; out:
kfree(data.part_descs_loc);
return ret;
} }
/* /*
......
...@@ -122,7 +122,7 @@ static int udf_symlink_filler(struct file *file, struct page *page) ...@@ -122,7 +122,7 @@ static int udf_symlink_filler(struct file *file, struct page *page)
down_read(&iinfo->i_data_sem); down_read(&iinfo->i_data_sem);
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
symlink = iinfo->i_ext.i_data + iinfo->i_lenEAttr; symlink = iinfo->i_data + iinfo->i_lenEAttr;
} else { } else {
bh = sb_bread(inode->i_sb, pos); bh = sb_bread(inode->i_sb, pos);
......
...@@ -45,11 +45,7 @@ struct udf_inode_info { ...@@ -45,11 +45,7 @@ struct udf_inode_info {
unsigned i_strat4096 : 1; unsigned i_strat4096 : 1;
unsigned i_streamdir : 1; unsigned i_streamdir : 1;
unsigned reserved : 25; unsigned reserved : 25;
union {
struct short_ad *i_sad;
struct long_ad *i_lad;
__u8 *i_data; __u8 *i_data;
} i_ext;
struct kernel_lb_addr i_locStreamdir; struct kernel_lb_addr i_locStreamdir;
__u64 i_lenStreams; __u64 i_lenStreams;
struct rw_semaphore i_data_sem; struct rw_semaphore i_data_sem;
......
...@@ -61,12 +61,16 @@ typedef struct fs_disk_quota { ...@@ -61,12 +61,16 @@ typedef struct fs_disk_quota {
__u64 d_ino_softlimit;/* preferred inode limit */ __u64 d_ino_softlimit;/* preferred inode limit */
__u64 d_bcount; /* # disk blocks owned by the user */ __u64 d_bcount; /* # disk blocks owned by the user */
__u64 d_icount; /* # inodes owned by the user */ __u64 d_icount; /* # inodes owned by the user */
__s32 d_itimer; /* zero if within inode limits */ __s32 d_itimer; /* Zero if within inode limits. If
/* if not, we refuse service */ * not, we refuse service at this time
* (in seconds since Unix epoch) */
__s32 d_btimer; /* similar to above; for disk blocks */ __s32 d_btimer; /* similar to above; for disk blocks */
__u16 d_iwarns; /* # warnings issued wrt num inodes */ __u16 d_iwarns; /* # warnings issued wrt num inodes */
__u16 d_bwarns; /* # warnings issued wrt disk blocks */ __u16 d_bwarns; /* # warnings issued wrt disk blocks */
__s32 d_padding2; /* padding2 - for future use */ __s8 d_itimer_hi; /* upper 8 bits of timer values */
__s8 d_btimer_hi;
__s8 d_rtbtimer_hi;
__s8 d_padding2; /* padding2 - for future use */
__u64 d_rtb_hardlimit;/* absolute limit on realtime blks */ __u64 d_rtb_hardlimit;/* absolute limit on realtime blks */
__u64 d_rtb_softlimit;/* preferred limit on RT disk blks */ __u64 d_rtb_softlimit;/* preferred limit on RT disk blks */
__u64 d_rtbcount; /* # realtime blocks owned */ __u64 d_rtbcount; /* # realtime blocks owned */
...@@ -121,6 +125,12 @@ typedef struct fs_disk_quota { ...@@ -121,6 +125,12 @@ typedef struct fs_disk_quota {
#define FS_DQ_RTBCOUNT (1<<14) #define FS_DQ_RTBCOUNT (1<<14)
#define FS_DQ_ACCT_MASK (FS_DQ_BCOUNT | FS_DQ_ICOUNT | FS_DQ_RTBCOUNT) #define FS_DQ_ACCT_MASK (FS_DQ_BCOUNT | FS_DQ_ICOUNT | FS_DQ_RTBCOUNT)
/*
* Quota expiration timestamps are 40-bit signed integers, with the upper 8
* bits encoded in the _hi fields.
*/
#define FS_DQ_BIGTIME (1<<15)
/* /*
* Various flags related to quotactl(2). * Various flags related to quotactl(2).
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment