Commit 8cd226ca authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (50 commits)
  jbd2: sparse pointer use of zero as null
  jbd2: Use round-jiffies() function for the "5 second" ext4/jbd2 wakeup
  jbd2: Mark jbd2 slabs as SLAB_TEMPORARY
  jbd2: add lockdep support
  ext4: Use the ext4_ext_actual_len() helper function
  ext4: fix uniniatilized extent splitting error
  ext4: Check for return value from sb_set_blocksize
  ext4: Add stripe= option to /proc/mounts
  ext4: Enable the multiblock allocator by default
  ext4: Add multi block allocator for ext4
  ext4: Add new functions for searching extent tree
  ext4: Add ext4_find_next_bit()
  ext4: fix up EXT4FS_DEBUG builds
  ext4: Fix ext4_show_options to show the correct mount options.
  ext4: Add EXT4_IOC_MIGRATE ioctl
  ext4: Add inode version support in ext4
  vfs: Add 64 bit i_version support
  ext4: Add the journal checksum feature
  jbd2: jbd2 stats through procfs
  ext4: Take read lock during overwrite case.
  ...
parents 6b11d817 4019191b
...@@ -86,9 +86,21 @@ Alex is working on a new set of patches right now. ...@@ -86,9 +86,21 @@ Alex is working on a new set of patches right now.
When mounting an ext4 filesystem, the following option are accepted: When mounting an ext4 filesystem, the following option are accepted:
(*) == default (*) == default
extents ext4 will use extents to address file data. The extents (*) ext4 will use extents to address file data. The
file system will no longer be mountable by ext3. file system will no longer be mountable by ext3.
noextents ext4 will not use extents for newly created files
journal_checksum Enable checksumming of the journal transactions.
This will allow the recovery code in e2fsck and the
kernel to detect corruption in the kernel. It is a
compatible change and will be ignored by older kernels.
journal_async_commit Commit block can be written to disk without waiting
for descriptor blocks. If enabled older kernels cannot
mount the device. This will enable 'journal_checksum'
internally.
journal=update Update the ext4 file system's journal to the current journal=update Update the ext4 file system's journal to the current
format. format.
...@@ -196,6 +208,12 @@ nobh (a) cache disk block mapping information ...@@ -196,6 +208,12 @@ nobh (a) cache disk block mapping information
"nobh" option tries to avoid associating buffer "nobh" option tries to avoid associating buffer
heads (supported only for "writeback" mode). heads (supported only for "writeback" mode).
mballoc (*) Use the multiple block allocator for block allocation
nomballoc disabled multiple block allocator for block allocation.
stripe=n Number of filesystem blocks that mballoc will try
to use for allocation size and alignment. For RAID5/6
systems this should be the number of data
disks * RAID chunk size in file system blocks.
Data Mode Data Mode
--------- ---------
......
...@@ -857,6 +857,45 @@ CPUs. ...@@ -857,6 +857,45 @@ CPUs.
The "procs_blocked" line gives the number of processes currently blocked, The "procs_blocked" line gives the number of processes currently blocked,
waiting for I/O to complete. waiting for I/O to complete.
1.9 Ext4 file system parameters
------------------------------
Ext4 file system have one directory per partition under /proc/fs/ext4/
# ls /proc/fs/ext4/hdc/
group_prealloc max_to_scan mb_groups mb_history min_to_scan order2_req
stats stream_req
mb_groups:
This file gives the details of mutiblock allocator buddy cache of free blocks
mb_history:
Multiblock allocation history.
stats:
This file indicate whether the multiblock allocator should start collecting
statistics. The statistics are shown during unmount
group_prealloc:
The multiblock allocator normalize the block allocation request to
group_prealloc filesystem blocks if we don't have strip value set.
The stripe value can be specified at mount time or during mke2fs.
max_to_scan:
How long multiblock allocator can look for a best extent (in found extents)
min_to_scan:
How long multiblock allocator must look for a best extent
order2_req:
Multiblock allocator use 2^N search using buddies only for requests greater
than or equal to order2_req. The request size is specfied in file system
blocks. A value of 2 indicate only if the requests are greater than or equal
to 4 blocks.
stream_req:
Files smaller than stream_req are served by the stream allocator, whose
purpose is to pack requests as close each to other as possible to
produce smooth I/O traffic. Avalue of 16 indicate that file smaller than 16
filesystem block size will use group based preallocation.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
Summary Summary
......
...@@ -236,6 +236,7 @@ config JBD_DEBUG ...@@ -236,6 +236,7 @@ config JBD_DEBUG
config JBD2 config JBD2
tristate tristate
select CRC32
help help
This is a generic journaling layer for block devices that support This is a generic journaling layer for block devices that support
both 32-bit and 64-bit block numbers. It is currently used by both 32-bit and 64-bit block numbers. It is currently used by
......
...@@ -546,11 +546,11 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, ...@@ -546,11 +546,11 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
dentry->d_op = &afs_fs_dentry_operations; dentry->d_op = &afs_fs_dentry_operations;
d_add(dentry, inode); d_add(dentry, inode);
_leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%lu }", _leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%llu }",
fid.vnode, fid.vnode,
fid.unique, fid.unique,
dentry->d_inode->i_ino, dentry->d_inode->i_ino,
dentry->d_inode->i_version); (unsigned long long)dentry->d_inode->i_version);
return NULL; return NULL;
} }
...@@ -630,9 +630,10 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) ...@@ -630,9 +630,10 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
* been deleted and replaced, and the original vnode ID has * been deleted and replaced, and the original vnode ID has
* been reused */ * been reused */
if (fid.unique != vnode->fid.unique) { if (fid.unique != vnode->fid.unique) {
_debug("%s: file deleted (uq %u -> %u I:%lu)", _debug("%s: file deleted (uq %u -> %u I:%llu)",
dentry->d_name.name, fid.unique, dentry->d_name.name, fid.unique,
vnode->fid.unique, dentry->d_inode->i_version); vnode->fid.unique,
(unsigned long long)dentry->d_inode->i_version);
spin_lock(&vnode->lock); spin_lock(&vnode->lock);
set_bit(AFS_VNODE_DELETED, &vnode->flags); set_bit(AFS_VNODE_DELETED, &vnode->flags);
spin_unlock(&vnode->lock); spin_unlock(&vnode->lock);
......
...@@ -301,7 +301,8 @@ int afs_getattr(struct vfsmount *mnt, struct dentry *dentry, ...@@ -301,7 +301,8 @@ int afs_getattr(struct vfsmount *mnt, struct dentry *dentry,
inode = dentry->d_inode; inode = dentry->d_inode;
_enter("{ ino=%lu v=%lu }", inode->i_ino, inode->i_version); _enter("{ ino=%lu v=%llu }", inode->i_ino,
(unsigned long long)inode->i_version);
generic_fillattr(inode, stat); generic_fillattr(inode, stat);
return 0; return 0;
......
...@@ -3213,6 +3213,50 @@ static int buffer_cpu_notify(struct notifier_block *self, ...@@ -3213,6 +3213,50 @@ static int buffer_cpu_notify(struct notifier_block *self,
return NOTIFY_OK; return NOTIFY_OK;
} }
/**
* bh_uptodate_or_lock: Test whether the buffer is uptodate
* @bh: struct buffer_head
*
* Return true if the buffer is up-to-date and false,
* with the buffer locked, if not.
*/
int bh_uptodate_or_lock(struct buffer_head *bh)
{
if (!buffer_uptodate(bh)) {
lock_buffer(bh);
if (!buffer_uptodate(bh))
return 0;
unlock_buffer(bh);
}
return 1;
}
EXPORT_SYMBOL(bh_uptodate_or_lock);
/**
* bh_submit_read: Submit a locked buffer for reading
* @bh: struct buffer_head
*
* Returns zero on success and -EIO on error.
*/
int bh_submit_read(struct buffer_head *bh)
{
BUG_ON(!buffer_locked(bh));
if (buffer_uptodate(bh)) {
unlock_buffer(bh);
return 0;
}
get_bh(bh);
bh->b_end_io = end_buffer_read_sync;
submit_bh(READ, bh);
wait_on_buffer(bh);
if (buffer_uptodate(bh))
return 0;
return -EIO;
}
EXPORT_SYMBOL(bh_submit_read);
void __init buffer_init(void) void __init buffer_init(void)
{ {
int nrpages; int nrpages;
......
...@@ -680,11 +680,31 @@ static int ext2_check_descriptors (struct super_block * sb) ...@@ -680,11 +680,31 @@ static int ext2_check_descriptors (struct super_block * sb)
static loff_t ext2_max_size(int bits) static loff_t ext2_max_size(int bits)
{ {
loff_t res = EXT2_NDIR_BLOCKS; loff_t res = EXT2_NDIR_BLOCKS;
/* This constant is calculated to be the largest file size for a int meta_blocks;
* dense, 4k-blocksize file such that the total number of loff_t upper_limit;
/* This is calculated to be the largest file size for a
* dense, file such that the total number of
* sectors in the file, including data and all indirect blocks, * sectors in the file, including data and all indirect blocks,
* does not exceed 2^32. */ * does not exceed 2^32 -1
const loff_t upper_limit = 0x1ff7fffd000LL; * __u32 i_blocks representing the total number of
* 512 bytes blocks of the file
*/
upper_limit = (1LL << 32) - 1;
/* total blocks in file system block size */
upper_limit >>= (bits - 9);
/* indirect blocks */
meta_blocks = 1;
/* double indirect blocks */
meta_blocks += 1 + (1LL << (bits-2));
/* tripple indirect blocks */
meta_blocks += 1 + (1LL << (bits-2)) + (1LL << (2*(bits-2)));
upper_limit -= meta_blocks;
upper_limit <<= bits;
res += 1LL << (bits-2); res += 1LL << (bits-2);
res += 1LL << (2*(bits-2)); res += 1LL << (2*(bits-2));
...@@ -692,6 +712,10 @@ static loff_t ext2_max_size(int bits) ...@@ -692,6 +712,10 @@ static loff_t ext2_max_size(int bits)
res <<= bits; res <<= bits;
if (res > upper_limit) if (res > upper_limit)
res = upper_limit; res = upper_limit;
if (res > MAX_LFS_FILESIZE)
res = MAX_LFS_FILESIZE;
return res; return res;
} }
......
...@@ -1436,11 +1436,31 @@ static void ext3_orphan_cleanup (struct super_block * sb, ...@@ -1436,11 +1436,31 @@ static void ext3_orphan_cleanup (struct super_block * sb,
static loff_t ext3_max_size(int bits) static loff_t ext3_max_size(int bits)
{ {
loff_t res = EXT3_NDIR_BLOCKS; loff_t res = EXT3_NDIR_BLOCKS;
/* This constant is calculated to be the largest file size for a int meta_blocks;
* dense, 4k-blocksize file such that the total number of loff_t upper_limit;
/* This is calculated to be the largest file size for a
* dense, file such that the total number of
* sectors in the file, including data and all indirect blocks, * sectors in the file, including data and all indirect blocks,
* does not exceed 2^32. */ * does not exceed 2^32 -1
const loff_t upper_limit = 0x1ff7fffd000LL; * __u32 i_blocks representing the total number of
* 512 bytes blocks of the file
*/
upper_limit = (1LL << 32) - 1;
/* total blocks in file system block size */
upper_limit >>= (bits - 9);
/* indirect blocks */
meta_blocks = 1;
/* double indirect blocks */
meta_blocks += 1 + (1LL << (bits-2));
/* tripple indirect blocks */
meta_blocks += 1 + (1LL << (bits-2)) + (1LL << (2*(bits-2)));
upper_limit -= meta_blocks;
upper_limit <<= bits;
res += 1LL << (bits-2); res += 1LL << (bits-2);
res += 1LL << (2*(bits-2)); res += 1LL << (2*(bits-2));
...@@ -1448,6 +1468,10 @@ static loff_t ext3_max_size(int bits) ...@@ -1448,6 +1468,10 @@ static loff_t ext3_max_size(int bits)
res <<= bits; res <<= bits;
if (res > upper_limit) if (res > upper_limit)
res = upper_limit; res = upper_limit;
if (res > MAX_LFS_FILESIZE)
res = MAX_LFS_FILESIZE;
return res; return res;
} }
......
...@@ -6,7 +6,7 @@ obj-$(CONFIG_EXT4DEV_FS) += ext4dev.o ...@@ -6,7 +6,7 @@ obj-$(CONFIG_EXT4DEV_FS) += ext4dev.o
ext4dev-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ ext4dev-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \ ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \
ext4_jbd2.o ext4_jbd2.o migrate.o mballoc.o
ext4dev-$(CONFIG_EXT4DEV_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o ext4dev-$(CONFIG_EXT4DEV_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
ext4dev-$(CONFIG_EXT4DEV_FS_POSIX_ACL) += acl.o ext4dev-$(CONFIG_EXT4DEV_FS_POSIX_ACL) += acl.o
......
This diff is collapsed.
...@@ -67,7 +67,7 @@ int ext4_check_dir_entry (const char * function, struct inode * dir, ...@@ -67,7 +67,7 @@ int ext4_check_dir_entry (const char * function, struct inode * dir,
unsigned long offset) unsigned long offset)
{ {
const char * error_msg = NULL; const char * error_msg = NULL;
const int rlen = le16_to_cpu(de->rec_len); const int rlen = ext4_rec_len_from_disk(de->rec_len);
if (rlen < EXT4_DIR_REC_LEN(1)) if (rlen < EXT4_DIR_REC_LEN(1))
error_msg = "rec_len is smaller than minimal"; error_msg = "rec_len is smaller than minimal";
...@@ -124,7 +124,7 @@ static int ext4_readdir(struct file * filp, ...@@ -124,7 +124,7 @@ static int ext4_readdir(struct file * filp,
offset = filp->f_pos & (sb->s_blocksize - 1); offset = filp->f_pos & (sb->s_blocksize - 1);
while (!error && !stored && filp->f_pos < inode->i_size) { while (!error && !stored && filp->f_pos < inode->i_size) {
unsigned long blk = filp->f_pos >> EXT4_BLOCK_SIZE_BITS(sb); ext4_lblk_t blk = filp->f_pos >> EXT4_BLOCK_SIZE_BITS(sb);
struct buffer_head map_bh; struct buffer_head map_bh;
struct buffer_head *bh = NULL; struct buffer_head *bh = NULL;
...@@ -172,10 +172,10 @@ static int ext4_readdir(struct file * filp, ...@@ -172,10 +172,10 @@ static int ext4_readdir(struct file * filp,
* least that it is non-zero. A * least that it is non-zero. A
* failure will be detected in the * failure will be detected in the
* dirent test below. */ * dirent test below. */
if (le16_to_cpu(de->rec_len) < if (ext4_rec_len_from_disk(de->rec_len)
EXT4_DIR_REC_LEN(1)) < EXT4_DIR_REC_LEN(1))
break; break;
i += le16_to_cpu(de->rec_len); i += ext4_rec_len_from_disk(de->rec_len);
} }
offset = i; offset = i;
filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
...@@ -197,7 +197,7 @@ static int ext4_readdir(struct file * filp, ...@@ -197,7 +197,7 @@ static int ext4_readdir(struct file * filp,
ret = stored; ret = stored;
goto out; goto out;
} }
offset += le16_to_cpu(de->rec_len); offset += ext4_rec_len_from_disk(de->rec_len);
if (le32_to_cpu(de->inode)) { if (le32_to_cpu(de->inode)) {
/* We might block in the next section /* We might block in the next section
* if the data destination is * if the data destination is
...@@ -219,7 +219,7 @@ static int ext4_readdir(struct file * filp, ...@@ -219,7 +219,7 @@ static int ext4_readdir(struct file * filp,
goto revalidate; goto revalidate;
stored ++; stored ++;
} }
filp->f_pos += le16_to_cpu(de->rec_len); filp->f_pos += ext4_rec_len_from_disk(de->rec_len);
} }
offset = 0; offset = 0;
brelse (bh); brelse (bh);
......
This diff is collapsed.
...@@ -37,9 +37,9 @@ static int ext4_release_file (struct inode * inode, struct file * filp) ...@@ -37,9 +37,9 @@ static int ext4_release_file (struct inode * inode, struct file * filp)
if ((filp->f_mode & FMODE_WRITE) && if ((filp->f_mode & FMODE_WRITE) &&
(atomic_read(&inode->i_writecount) == 1)) (atomic_read(&inode->i_writecount) == 1))
{ {
mutex_lock(&EXT4_I(inode)->truncate_mutex); down_write(&EXT4_I(inode)->i_data_sem);
ext4_discard_reservation(inode); ext4_discard_reservation(inode);
mutex_unlock(&EXT4_I(inode)->truncate_mutex); up_write(&EXT4_I(inode)->i_data_sem);
} }
if (is_dx(inode) && filp->private_data) if (is_dx(inode) && filp->private_data)
ext4_htree_free_dir_info(filp->private_data); ext4_htree_free_dir_info(filp->private_data);
...@@ -56,8 +56,25 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov, ...@@ -56,8 +56,25 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
ssize_t ret; ssize_t ret;
int err; int err;
ret = generic_file_aio_write(iocb, iov, nr_segs, pos); /*
* If we have encountered a bitmap-format file, the size limit
* is smaller than s_maxbytes, which is for extent-mapped files.
*/
if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) {
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
size_t length = iov_length(iov, nr_segs);
if (pos > sbi->s_bitmap_maxbytes)
return -EFBIG;
if (pos + length > sbi->s_bitmap_maxbytes) {
nr_segs = iov_shorten((struct iovec *)iov, nr_segs,
sbi->s_bitmap_maxbytes - pos);
}
}
ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
/* /*
* Skip flushing if there was an error, or if nothing was written. * Skip flushing if there was an error, or if nothing was written.
*/ */
......
...@@ -14,14 +14,16 @@ extern __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 group, ...@@ -14,14 +14,16 @@ extern __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 group,
extern int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 group, extern int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 group,
struct ext4_group_desc *gdp); struct ext4_group_desc *gdp);
struct buffer_head *read_block_bitmap(struct super_block *sb, struct buffer_head *read_block_bitmap(struct super_block *sb,
unsigned int block_group); ext4_group_t block_group);
extern unsigned ext4_init_block_bitmap(struct super_block *sb, extern unsigned ext4_init_block_bitmap(struct super_block *sb,
struct buffer_head *bh, int group, struct buffer_head *bh,
ext4_group_t group,
struct ext4_group_desc *desc); struct ext4_group_desc *desc);
#define ext4_free_blocks_after_init(sb, group, desc) \ #define ext4_free_blocks_after_init(sb, group, desc) \
ext4_init_block_bitmap(sb, NULL, group, desc) ext4_init_block_bitmap(sb, NULL, group, desc)
extern unsigned ext4_init_inode_bitmap(struct super_block *sb, extern unsigned ext4_init_inode_bitmap(struct super_block *sb,
struct buffer_head *bh, int group, struct buffer_head *bh,
ext4_group_t group,
struct ext4_group_desc *desc); struct ext4_group_desc *desc);
extern void mark_bitmap_end(int start_bit, int end_bit, char *bitmap); extern void mark_bitmap_end(int start_bit, int end_bit, char *bitmap);
#endif /* _LINUX_EXT4_GROUP_H */ #endif /* _LINUX_EXT4_GROUP_H */
This diff is collapsed.
This diff is collapsed.
...@@ -199,7 +199,7 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, ...@@ -199,7 +199,7 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
* need to allocate reservation structure for this inode * need to allocate reservation structure for this inode
* before set the window size * before set the window size
*/ */
mutex_lock(&ei->truncate_mutex); down_write(&ei->i_data_sem);
if (!ei->i_block_alloc_info) if (!ei->i_block_alloc_info)
ext4_init_block_alloc_info(inode); ext4_init_block_alloc_info(inode);
...@@ -207,7 +207,7 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, ...@@ -207,7 +207,7 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
struct ext4_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node; struct ext4_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node;
rsv->rsv_goal_size = rsv_window_size; rsv->rsv_goal_size = rsv_window_size;
} }
mutex_unlock(&ei->truncate_mutex); up_write(&ei->i_data_sem);
return 0; return 0;
} }
case EXT4_IOC_GROUP_EXTEND: { case EXT4_IOC_GROUP_EXTEND: {
...@@ -254,6 +254,9 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, ...@@ -254,6 +254,9 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
return err; return err;
} }
case EXT4_IOC_MIGRATE:
return ext4_ext_migrate(inode, filp, cmd, arg);
default: default:
return -ENOTTY; return -ENOTTY;
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -28,7 +28,7 @@ static int verify_group_input(struct super_block *sb, ...@@ -28,7 +28,7 @@ static int verify_group_input(struct super_block *sb,
struct ext4_super_block *es = sbi->s_es; struct ext4_super_block *es = sbi->s_es;
ext4_fsblk_t start = ext4_blocks_count(es); ext4_fsblk_t start = ext4_blocks_count(es);
ext4_fsblk_t end = start + input->blocks_count; ext4_fsblk_t end = start + input->blocks_count;
unsigned group = input->group; ext4_group_t group = input->group;
ext4_fsblk_t itend = input->inode_table + sbi->s_itb_per_group; ext4_fsblk_t itend = input->inode_table + sbi->s_itb_per_group;
unsigned overhead = ext4_bg_has_super(sb, group) ? unsigned overhead = ext4_bg_has_super(sb, group) ?
(1 + ext4_bg_num_gdb(sb, group) + (1 + ext4_bg_num_gdb(sb, group) +
...@@ -206,7 +206,7 @@ static int setup_new_group_blocks(struct super_block *sb, ...@@ -206,7 +206,7 @@ static int setup_new_group_blocks(struct super_block *sb,
} }
if (ext4_bg_has_super(sb, input->group)) { if (ext4_bg_has_super(sb, input->group)) {
ext4_debug("mark backup superblock %#04lx (+0)\n", start); ext4_debug("mark backup superblock %#04llx (+0)\n", start);
ext4_set_bit(0, bh->b_data); ext4_set_bit(0, bh->b_data);
} }
...@@ -215,7 +215,7 @@ static int setup_new_group_blocks(struct super_block *sb, ...@@ -215,7 +215,7 @@ static int setup_new_group_blocks(struct super_block *sb,
i < gdblocks; i++, block++, bit++) { i < gdblocks; i++, block++, bit++) {
struct buffer_head *gdb; struct buffer_head *gdb;
ext4_debug("update backup group %#04lx (+%d)\n", block, bit); ext4_debug("update backup group %#04llx (+%d)\n", block, bit);
if ((err = extend_or_restart_transaction(handle, 1, bh))) if ((err = extend_or_restart_transaction(handle, 1, bh)))
goto exit_bh; goto exit_bh;
...@@ -243,7 +243,7 @@ static int setup_new_group_blocks(struct super_block *sb, ...@@ -243,7 +243,7 @@ static int setup_new_group_blocks(struct super_block *sb,
i < reserved_gdb; i++, block++, bit++) { i < reserved_gdb; i++, block++, bit++) {
struct buffer_head *gdb; struct buffer_head *gdb;
ext4_debug("clear reserved block %#04lx (+%d)\n", block, bit); ext4_debug("clear reserved block %#04llx (+%d)\n", block, bit);
if ((err = extend_or_restart_transaction(handle, 1, bh))) if ((err = extend_or_restart_transaction(handle, 1, bh)))
goto exit_bh; goto exit_bh;
...@@ -256,10 +256,10 @@ static int setup_new_group_blocks(struct super_block *sb, ...@@ -256,10 +256,10 @@ static int setup_new_group_blocks(struct super_block *sb,
ext4_set_bit(bit, bh->b_data); ext4_set_bit(bit, bh->b_data);
brelse(gdb); brelse(gdb);
} }
ext4_debug("mark block bitmap %#04x (+%ld)\n", input->block_bitmap, ext4_debug("mark block bitmap %#04llx (+%llu)\n", input->block_bitmap,
input->block_bitmap - start); input->block_bitmap - start);
ext4_set_bit(input->block_bitmap - start, bh->b_data); ext4_set_bit(input->block_bitmap - start, bh->b_data);
ext4_debug("mark inode bitmap %#04x (+%ld)\n", input->inode_bitmap, ext4_debug("mark inode bitmap %#04llx (+%llu)\n", input->inode_bitmap,
input->inode_bitmap - start); input->inode_bitmap - start);
ext4_set_bit(input->inode_bitmap - start, bh->b_data); ext4_set_bit(input->inode_bitmap - start, bh->b_data);
...@@ -268,7 +268,7 @@ static int setup_new_group_blocks(struct super_block *sb, ...@@ -268,7 +268,7 @@ static int setup_new_group_blocks(struct super_block *sb,
i < sbi->s_itb_per_group; i++, bit++, block++) { i < sbi->s_itb_per_group; i++, bit++, block++) {
struct buffer_head *it; struct buffer_head *it;
ext4_debug("clear inode block %#04lx (+%d)\n", block, bit); ext4_debug("clear inode block %#04llx (+%d)\n", block, bit);
if ((err = extend_or_restart_transaction(handle, 1, bh))) if ((err = extend_or_restart_transaction(handle, 1, bh)))
goto exit_bh; goto exit_bh;
...@@ -291,7 +291,7 @@ static int setup_new_group_blocks(struct super_block *sb, ...@@ -291,7 +291,7 @@ static int setup_new_group_blocks(struct super_block *sb,
brelse(bh); brelse(bh);
/* Mark unused entries in inode bitmap used */ /* Mark unused entries in inode bitmap used */
ext4_debug("clear inode bitmap %#04x (+%ld)\n", ext4_debug("clear inode bitmap %#04llx (+%llu)\n",
input->inode_bitmap, input->inode_bitmap - start); input->inode_bitmap, input->inode_bitmap - start);
if (IS_ERR(bh = bclean(handle, sb, input->inode_bitmap))) { if (IS_ERR(bh = bclean(handle, sb, input->inode_bitmap))) {
err = PTR_ERR(bh); err = PTR_ERR(bh);
...@@ -357,7 +357,7 @@ static int verify_reserved_gdb(struct super_block *sb, ...@@ -357,7 +357,7 @@ static int verify_reserved_gdb(struct super_block *sb,
struct buffer_head *primary) struct buffer_head *primary)
{ {
const ext4_fsblk_t blk = primary->b_blocknr; const ext4_fsblk_t blk = primary->b_blocknr;
const unsigned long end = EXT4_SB(sb)->s_groups_count; const ext4_group_t end = EXT4_SB(sb)->s_groups_count;
unsigned three = 1; unsigned three = 1;
unsigned five = 5; unsigned five = 5;
unsigned seven = 7; unsigned seven = 7;
...@@ -656,12 +656,12 @@ static void update_backups(struct super_block *sb, ...@@ -656,12 +656,12 @@ static void update_backups(struct super_block *sb,
int blk_off, char *data, int size) int blk_off, char *data, int size)
{ {
struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_sb_info *sbi = EXT4_SB(sb);
const unsigned long last = sbi->s_groups_count; const ext4_group_t last = sbi->s_groups_count;
const int bpg = EXT4_BLOCKS_PER_GROUP(sb); const int bpg = EXT4_BLOCKS_PER_GROUP(sb);
unsigned three = 1; unsigned three = 1;
unsigned five = 5; unsigned five = 5;
unsigned seven = 7; unsigned seven = 7;
unsigned group; ext4_group_t group;
int rest = sb->s_blocksize - size; int rest = sb->s_blocksize - size;
handle_t *handle; handle_t *handle;
int err = 0, err2; int err = 0, err2;
...@@ -716,7 +716,7 @@ static void update_backups(struct super_block *sb, ...@@ -716,7 +716,7 @@ static void update_backups(struct super_block *sb,
exit_err: exit_err:
if (err) { if (err) {
ext4_warning(sb, __FUNCTION__, ext4_warning(sb, __FUNCTION__,
"can't update backup for group %d (err %d), " "can't update backup for group %lu (err %d), "
"forcing fsck on next reboot", group, err); "forcing fsck on next reboot", group, err);
sbi->s_mount_state &= ~EXT4_VALID_FS; sbi->s_mount_state &= ~EXT4_VALID_FS;
sbi->s_es->s_state &= cpu_to_le16(~EXT4_VALID_FS); sbi->s_es->s_state &= cpu_to_le16(~EXT4_VALID_FS);
...@@ -952,7 +952,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es, ...@@ -952,7 +952,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
ext4_fsblk_t n_blocks_count) ext4_fsblk_t n_blocks_count)
{ {
ext4_fsblk_t o_blocks_count; ext4_fsblk_t o_blocks_count;
unsigned long o_groups_count; ext4_group_t o_groups_count;
ext4_grpblk_t last; ext4_grpblk_t last;
ext4_grpblk_t add; ext4_grpblk_t add;
struct buffer_head * bh; struct buffer_head * bh;
...@@ -1054,7 +1054,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es, ...@@ -1054,7 +1054,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
ext4_journal_dirty_metadata(handle, EXT4_SB(sb)->s_sbh); ext4_journal_dirty_metadata(handle, EXT4_SB(sb)->s_sbh);
sb->s_dirt = 1; sb->s_dirt = 1;
unlock_super(sb); unlock_super(sb);
ext4_debug("freeing blocks %lu through %llu\n", o_blocks_count, ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count,
o_blocks_count + add); o_blocks_count + add);
ext4_free_blocks_sb(handle, sb, o_blocks_count, add, &freed_blocks); ext4_free_blocks_sb(handle, sb, o_blocks_count, add, &freed_blocks);
ext4_debug("freed blocks %llu through %llu\n", o_blocks_count, ext4_debug("freed blocks %llu through %llu\n", o_blocks_count,
......
This diff is collapsed.
...@@ -480,7 +480,7 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, ...@@ -480,7 +480,7 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
ea_bdebug(bh, "refcount now=0; freeing"); ea_bdebug(bh, "refcount now=0; freeing");
if (ce) if (ce)
mb_cache_entry_free(ce); mb_cache_entry_free(ce);
ext4_free_blocks(handle, inode, bh->b_blocknr, 1); ext4_free_blocks(handle, inode, bh->b_blocknr, 1, 1);
get_bh(bh); get_bh(bh);
ext4_forget(handle, 1, inode, bh, bh->b_blocknr); ext4_forget(handle, 1, inode, bh, bh->b_blocknr);
} else { } else {
...@@ -821,7 +821,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, ...@@ -821,7 +821,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
new_bh = sb_getblk(sb, block); new_bh = sb_getblk(sb, block);
if (!new_bh) { if (!new_bh) {
getblk_failed: getblk_failed:
ext4_free_blocks(handle, inode, block, 1); ext4_free_blocks(handle, inode, block, 1, 1);
error = -EIO; error = -EIO;
goto cleanup; goto cleanup;
} }
......
...@@ -1276,6 +1276,11 @@ void file_update_time(struct file *file) ...@@ -1276,6 +1276,11 @@ void file_update_time(struct file *file)
sync_it = 1; sync_it = 1;
} }
if (IS_I_VERSION(inode)) {
inode_inc_iversion(inode);
sync_it = 1;
}
if (sync_it) if (sync_it)
mark_inode_dirty_sync(inode); mark_inode_dirty_sync(inode);
} }
......
...@@ -232,7 +232,8 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count) ...@@ -232,7 +232,8 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
* Called under jbd_lock_bh_state(jh2bh(jh)), and drops it * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
*/ */
static int __process_buffer(journal_t *journal, struct journal_head *jh, static int __process_buffer(journal_t *journal, struct journal_head *jh,
struct buffer_head **bhs, int *batch_count) struct buffer_head **bhs, int *batch_count,
transaction_t *transaction)
{ {
struct buffer_head *bh = jh2bh(jh); struct buffer_head *bh = jh2bh(jh);
int ret = 0; int ret = 0;
...@@ -250,6 +251,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, ...@@ -250,6 +251,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
transaction_t *t = jh->b_transaction; transaction_t *t = jh->b_transaction;
tid_t tid = t->t_tid; tid_t tid = t->t_tid;
transaction->t_chp_stats.cs_forced_to_close++;
spin_unlock(&journal->j_list_lock); spin_unlock(&journal->j_list_lock);
jbd_unlock_bh_state(bh); jbd_unlock_bh_state(bh);
jbd2_log_start_commit(journal, tid); jbd2_log_start_commit(journal, tid);
...@@ -279,6 +281,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, ...@@ -279,6 +281,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
bhs[*batch_count] = bh; bhs[*batch_count] = bh;
__buffer_relink_io(jh); __buffer_relink_io(jh);
jbd_unlock_bh_state(bh); jbd_unlock_bh_state(bh);
transaction->t_chp_stats.cs_written++;
(*batch_count)++; (*batch_count)++;
if (*batch_count == NR_BATCH) { if (*batch_count == NR_BATCH) {
spin_unlock(&journal->j_list_lock); spin_unlock(&journal->j_list_lock);
...@@ -322,6 +325,8 @@ int jbd2_log_do_checkpoint(journal_t *journal) ...@@ -322,6 +325,8 @@ int jbd2_log_do_checkpoint(journal_t *journal)
if (!journal->j_checkpoint_transactions) if (!journal->j_checkpoint_transactions)
goto out; goto out;
transaction = journal->j_checkpoint_transactions; transaction = journal->j_checkpoint_transactions;
if (transaction->t_chp_stats.cs_chp_time == 0)
transaction->t_chp_stats.cs_chp_time = jiffies;
this_tid = transaction->t_tid; this_tid = transaction->t_tid;
restart: restart:
/* /*
...@@ -346,7 +351,8 @@ int jbd2_log_do_checkpoint(journal_t *journal) ...@@ -346,7 +351,8 @@ int jbd2_log_do_checkpoint(journal_t *journal)
retry = 1; retry = 1;
break; break;
} }
retry = __process_buffer(journal, jh, bhs,&batch_count); retry = __process_buffer(journal, jh, bhs, &batch_count,
transaction);
if (!retry && lock_need_resched(&journal->j_list_lock)){ if (!retry && lock_need_resched(&journal->j_list_lock)){
spin_unlock(&journal->j_list_lock); spin_unlock(&journal->j_list_lock);
retry = 1; retry = 1;
...@@ -602,15 +608,15 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) ...@@ -602,15 +608,15 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
/* /*
* There is one special case to worry about: if we have just pulled the * There is one special case to worry about: if we have just pulled the
* buffer off a committing transaction's forget list, then even if the * buffer off a running or committing transaction's checkpoing list,
* checkpoint list is empty, the transaction obviously cannot be * then even if the checkpoint list is empty, the transaction obviously
* dropped! * cannot be dropped!
* *
* The locking here around j_committing_transaction is a bit sleazy. * The locking here around t_state is a bit sleazy.
* See the comment at the end of jbd2_journal_commit_transaction(). * See the comment at the end of jbd2_journal_commit_transaction().
*/ */
if (transaction == journal->j_committing_transaction) { if (transaction->t_state != T_FINISHED) {
JBUFFER_TRACE(jh, "belongs to committing transaction"); JBUFFER_TRACE(jh, "belongs to running/committing transaction");
goto out; goto out;
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -171,13 +171,15 @@ int __init jbd2_journal_init_revoke_caches(void) ...@@ -171,13 +171,15 @@ int __init jbd2_journal_init_revoke_caches(void)
{ {
jbd2_revoke_record_cache = kmem_cache_create("jbd2_revoke_record", jbd2_revoke_record_cache = kmem_cache_create("jbd2_revoke_record",
sizeof(struct jbd2_revoke_record_s), sizeof(struct jbd2_revoke_record_s),
0, SLAB_HWCACHE_ALIGN, NULL); 0,
SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY,
NULL);
if (jbd2_revoke_record_cache == 0) if (jbd2_revoke_record_cache == 0)
return -ENOMEM; return -ENOMEM;
jbd2_revoke_table_cache = kmem_cache_create("jbd2_revoke_table", jbd2_revoke_table_cache = kmem_cache_create("jbd2_revoke_table",
sizeof(struct jbd2_revoke_table_s), sizeof(struct jbd2_revoke_table_s),
0, 0, NULL); 0, SLAB_TEMPORARY, NULL);
if (jbd2_revoke_table_cache == 0) { if (jbd2_revoke_table_cache == 0) {
kmem_cache_destroy(jbd2_revoke_record_cache); kmem_cache_destroy(jbd2_revoke_record_cache);
jbd2_revoke_record_cache = NULL; jbd2_revoke_record_cache = NULL;
......
This diff is collapsed.
...@@ -446,6 +446,7 @@ unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to) ...@@ -446,6 +446,7 @@ unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to)
} }
return seg; return seg;
} }
EXPORT_SYMBOL(iov_shorten);
ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov, ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn) unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn)
......
...@@ -310,6 +310,8 @@ static inline int constant_fls(int x) ...@@ -310,6 +310,8 @@ static inline int constant_fls(int x)
_find_first_zero_bit_le(p,sz) _find_first_zero_bit_le(p,sz)
#define ext2_find_next_zero_bit(p,sz,off) \ #define ext2_find_next_zero_bit(p,sz,off) \
_find_next_zero_bit_le(p,sz,off) _find_next_zero_bit_le(p,sz,off)
#define ext2_find_next_bit(p, sz, off) \
_find_next_bit_le(p, sz, off)
/* /*
* Minix is defined to use little-endian byte ordering. * Minix is defined to use little-endian byte ordering.
......
...@@ -14,5 +14,7 @@ ...@@ -14,5 +14,7 @@
generic_find_first_zero_le_bit((unsigned long *)(addr), (size)) generic_find_first_zero_le_bit((unsigned long *)(addr), (size))
#define ext2_find_next_zero_bit(addr, size, off) \ #define ext2_find_next_zero_bit(addr, size, off) \
generic_find_next_zero_le_bit((unsigned long *)(addr), (size), (off)) generic_find_next_zero_le_bit((unsigned long *)(addr), (size), (off))
#define ext2_find_next_bit(addr, size, off) \
generic_find_next_le_bit((unsigned long *)(addr), (size), (off))
#endif /* _ASM_GENERIC_BITOPS_EXT2_NON_ATOMIC_H_ */ #endif /* _ASM_GENERIC_BITOPS_EXT2_NON_ATOMIC_H_ */
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#define generic___test_and_clear_le_bit(nr, addr) __test_and_clear_bit(nr, addr) #define generic___test_and_clear_le_bit(nr, addr) __test_and_clear_bit(nr, addr)
#define generic_find_next_zero_le_bit(addr, size, offset) find_next_zero_bit(addr, size, offset) #define generic_find_next_zero_le_bit(addr, size, offset) find_next_zero_bit(addr, size, offset)
#define generic_find_next_le_bit(addr, size, offset) \
find_next_bit(addr, size, offset)
#elif defined(__BIG_ENDIAN) #elif defined(__BIG_ENDIAN)
...@@ -42,6 +44,8 @@ ...@@ -42,6 +44,8 @@
extern unsigned long generic_find_next_zero_le_bit(const unsigned long *addr, extern unsigned long generic_find_next_zero_le_bit(const unsigned long *addr,
unsigned long size, unsigned long offset); unsigned long size, unsigned long offset);
extern unsigned long generic_find_next_le_bit(const unsigned long *addr,
unsigned long size, unsigned long offset);
#else #else
#error "Please fix <asm/byteorder.h>" #error "Please fix <asm/byteorder.h>"
......
...@@ -410,6 +410,8 @@ static inline int ext2_find_next_zero_bit(const void *vaddr, unsigned size, ...@@ -410,6 +410,8 @@ static inline int ext2_find_next_zero_bit(const void *vaddr, unsigned size,
res = ext2_find_first_zero_bit (p, size - 32 * (p - addr)); res = ext2_find_first_zero_bit (p, size - 32 * (p - addr));
return (p - addr) * 32 + res; return (p - addr) * 32 + res;
} }
#define ext2_find_next_bit(addr, size, off) \
generic_find_next_le_bit((unsigned long *)(addr), (size), (off))
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -294,6 +294,8 @@ static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned lon ...@@ -294,6 +294,8 @@ static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned lon
return result + ffz(__swab32(tmp)); return result + ffz(__swab32(tmp));
} }
#define ext2_find_next_bit(addr, size, off) \
generic_find_next_le_bit((unsigned long *)(addr), (size), (off))
#include <asm-generic/bitops/minix.h> #include <asm-generic/bitops/minix.h>
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -359,6 +359,8 @@ static __inline__ int test_le_bit(unsigned long nr, ...@@ -359,6 +359,8 @@ static __inline__ int test_le_bit(unsigned long nr,
unsigned long generic_find_next_zero_le_bit(const unsigned long *addr, unsigned long generic_find_next_zero_le_bit(const unsigned long *addr,
unsigned long size, unsigned long offset); unsigned long size, unsigned long offset);
unsigned long generic_find_next_le_bit(const unsigned long *addr,
unsigned long size, unsigned long offset);
/* Bitmap functions for the ext2 filesystem */ /* Bitmap functions for the ext2 filesystem */
#define ext2_set_bit(nr,addr) \ #define ext2_set_bit(nr,addr) \
...@@ -378,6 +380,8 @@ unsigned long generic_find_next_zero_le_bit(const unsigned long *addr, ...@@ -378,6 +380,8 @@ unsigned long generic_find_next_zero_le_bit(const unsigned long *addr,
#define ext2_find_next_zero_bit(addr, size, off) \ #define ext2_find_next_zero_bit(addr, size, off) \
generic_find_next_zero_le_bit((unsigned long*)addr, size, off) generic_find_next_zero_le_bit((unsigned long*)addr, size, off)
#define ext2_find_next_bit(addr, size, off) \
generic_find_next_le_bit((unsigned long *)addr, size, off)
/* Bitmap functions for the minix filesystem. */ /* Bitmap functions for the minix filesystem. */
#define minix_test_and_set_bit(nr,addr) \ #define minix_test_and_set_bit(nr,addr) \
......
...@@ -772,6 +772,8 @@ static inline int sched_find_first_bit(unsigned long *b) ...@@ -772,6 +772,8 @@ static inline int sched_find_first_bit(unsigned long *b)
test_and_clear_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr) test_and_clear_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
#define ext2_test_bit(nr, addr) \ #define ext2_test_bit(nr, addr) \
test_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr) test_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
#define ext2_find_next_bit(addr, size, off) \
generic_find_next_le_bit((unsigned long *)(addr), (size), (off))
#ifndef __s390x__ #ifndef __s390x__
......
...@@ -192,6 +192,8 @@ int sync_dirty_buffer(struct buffer_head *bh); ...@@ -192,6 +192,8 @@ int sync_dirty_buffer(struct buffer_head *bh);
int submit_bh(int, struct buffer_head *); int submit_bh(int, struct buffer_head *);
void write_boundary_block(struct block_device *bdev, void write_boundary_block(struct block_device *bdev,
sector_t bblock, unsigned blocksize); sector_t bblock, unsigned blocksize);
int bh_uptodate_or_lock(struct buffer_head *bh);
int bh_submit_read(struct buffer_head *bh);
extern int buffer_heads_over_limit; extern int buffer_heads_over_limit;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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