mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-02 15:18:19 +00:00
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: jbd2: clean up jbd2_journal_try_to_free_buffers() ext4: Don't update ctime for non-extent-mapped inodes ext4: Fix up whitespace issues in fs/ext4/inode.c ext4: Fix 64-bit block type problem on 32-bit platforms ext4: teach the inode allocator to use a goal inode number ext4: Use a hash of the topdir directory name for the Orlov parent group ext4: document the "abort" mount option ext4: move the abort flag from s_mount_opts to s_mount_flags ext4: update the s_last_mounted field in the superblock ext4: change s_mount_opt to be an unsigned int ext4: online defrag -- Add EXT4_IOC_MOVE_EXT ioctl ext4: avoid unnecessary spinlock in critical POSIX ACL path ext3: avoid unnecessary spinlock in critical POSIX ACL path ext4: convert instrumentation from markers to tracepoints jbd2: convert instrumentation from markers to tracepoints
This commit is contained in:
commit
0732f87761
24 changed files with 2621 additions and 324 deletions
|
@ -79,3 +79,13 @@ Description:
|
||||||
This file is read-only and shows the number of
|
This file is read-only and shows the number of
|
||||||
kilobytes of data that have been written to this
|
kilobytes of data that have been written to this
|
||||||
filesystem since it was mounted.
|
filesystem since it was mounted.
|
||||||
|
|
||||||
|
What: /sys/fs/ext4/<disk>/inode_goal
|
||||||
|
Date: June 2008
|
||||||
|
Contact: "Theodore Ts'o" <tytso@mit.edu>
|
||||||
|
Description:
|
||||||
|
Tuning parameter which (if non-zero) controls the goal
|
||||||
|
inode used by the inode allocator in p0reference to
|
||||||
|
all other allocation hueristics. This is intended for
|
||||||
|
debugging use only, and should be 0 on production
|
||||||
|
systems.
|
||||||
|
|
|
@ -235,6 +235,10 @@ minixdf Make 'df' act like Minix.
|
||||||
|
|
||||||
debug Extra debugging information is sent to syslog.
|
debug Extra debugging information is sent to syslog.
|
||||||
|
|
||||||
|
abort Simulate the effects of calling ext4_abort() for
|
||||||
|
debugging purposes. This is normally used while
|
||||||
|
remounting a filesystem which is already mounted.
|
||||||
|
|
||||||
errors=remount-ro Remount the filesystem read-only on an error.
|
errors=remount-ro Remount the filesystem read-only on an error.
|
||||||
errors=continue Keep going on a filesystem error.
|
errors=continue Keep going on a filesystem error.
|
||||||
errors=panic Panic and halt the machine if an error occurs.
|
errors=panic Panic and halt the machine if an error occurs.
|
||||||
|
|
|
@ -6,7 +6,7 @@ obj-$(CONFIG_EXT4_FS) += ext4.o
|
||||||
|
|
||||||
ext4-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
|
ext4-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 migrate.o mballoc.o block_validity.o
|
ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o
|
||||||
|
|
||||||
ext4-$(CONFIG_EXT4_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
|
ext4-$(CONFIG_EXT4_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
|
||||||
ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o
|
ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o
|
||||||
|
|
|
@ -352,6 +352,7 @@ struct ext4_new_group_data {
|
||||||
/* note ioctl 10 reserved for an early version of the FIEMAP ioctl */
|
/* note ioctl 10 reserved for an early version of the FIEMAP ioctl */
|
||||||
/* note ioctl 11 reserved for filesystem-independent FIEMAP ioctl */
|
/* note ioctl 11 reserved for filesystem-independent FIEMAP ioctl */
|
||||||
#define EXT4_IOC_ALLOC_DA_BLKS _IO('f', 12)
|
#define EXT4_IOC_ALLOC_DA_BLKS _IO('f', 12)
|
||||||
|
#define EXT4_IOC_MOVE_EXT _IOWR('f', 15, struct move_extent)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ioctl commands in 32 bit emulation
|
* ioctl commands in 32 bit emulation
|
||||||
|
@ -447,6 +448,15 @@ struct ext4_inode {
|
||||||
__le32 i_version_hi; /* high 32 bits for 64-bit version */
|
__le32 i_version_hi; /* high 32 bits for 64-bit version */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct move_extent {
|
||||||
|
__u32 reserved; /* should be zero */
|
||||||
|
__u32 donor_fd; /* donor file descriptor */
|
||||||
|
__u64 orig_start; /* logical start offset in block for orig */
|
||||||
|
__u64 donor_start; /* logical start offset in block for donor */
|
||||||
|
__u64 len; /* block length to be moved */
|
||||||
|
__u64 moved_len; /* moved block length */
|
||||||
|
};
|
||||||
|
#define MAX_DEFRAG_SIZE ((1UL<<31) - 1)
|
||||||
|
|
||||||
#define EXT4_EPOCH_BITS 2
|
#define EXT4_EPOCH_BITS 2
|
||||||
#define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
|
#define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
|
||||||
|
@ -674,7 +684,6 @@ struct ext4_inode_info {
|
||||||
#define EXT4_MOUNT_ERRORS_PANIC 0x00040 /* Panic on errors */
|
#define EXT4_MOUNT_ERRORS_PANIC 0x00040 /* Panic on errors */
|
||||||
#define EXT4_MOUNT_MINIX_DF 0x00080 /* Mimics the Minix statfs */
|
#define EXT4_MOUNT_MINIX_DF 0x00080 /* Mimics the Minix statfs */
|
||||||
#define EXT4_MOUNT_NOLOAD 0x00100 /* Don't use existing journal*/
|
#define EXT4_MOUNT_NOLOAD 0x00100 /* Don't use existing journal*/
|
||||||
#define EXT4_MOUNT_ABORT 0x00200 /* Fatal error detected */
|
|
||||||
#define EXT4_MOUNT_DATA_FLAGS 0x00C00 /* Mode for data writes: */
|
#define EXT4_MOUNT_DATA_FLAGS 0x00C00 /* Mode for data writes: */
|
||||||
#define EXT4_MOUNT_JOURNAL_DATA 0x00400 /* Write data to journal */
|
#define EXT4_MOUNT_JOURNAL_DATA 0x00400 /* Write data to journal */
|
||||||
#define EXT4_MOUNT_ORDERED_DATA 0x00800 /* Flush data before commit */
|
#define EXT4_MOUNT_ORDERED_DATA 0x00800 /* Flush data before commit */
|
||||||
|
@ -696,17 +705,10 @@ struct ext4_inode_info {
|
||||||
#define EXT4_MOUNT_DATA_ERR_ABORT 0x10000000 /* Abort on file data write */
|
#define EXT4_MOUNT_DATA_ERR_ABORT 0x10000000 /* Abort on file data write */
|
||||||
#define EXT4_MOUNT_BLOCK_VALIDITY 0x20000000 /* Block validity checking */
|
#define EXT4_MOUNT_BLOCK_VALIDITY 0x20000000 /* Block validity checking */
|
||||||
|
|
||||||
/* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */
|
|
||||||
#ifndef _LINUX_EXT2_FS_H
|
|
||||||
#define clear_opt(o, opt) o &= ~EXT4_MOUNT_##opt
|
#define clear_opt(o, opt) o &= ~EXT4_MOUNT_##opt
|
||||||
#define set_opt(o, opt) o |= EXT4_MOUNT_##opt
|
#define set_opt(o, opt) o |= EXT4_MOUNT_##opt
|
||||||
#define test_opt(sb, opt) (EXT4_SB(sb)->s_mount_opt & \
|
#define test_opt(sb, opt) (EXT4_SB(sb)->s_mount_opt & \
|
||||||
EXT4_MOUNT_##opt)
|
EXT4_MOUNT_##opt)
|
||||||
#else
|
|
||||||
#define EXT2_MOUNT_NOLOAD EXT4_MOUNT_NOLOAD
|
|
||||||
#define EXT2_MOUNT_ABORT EXT4_MOUNT_ABORT
|
|
||||||
#define EXT2_MOUNT_DATA_FLAGS EXT4_MOUNT_DATA_FLAGS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ext4_set_bit ext2_set_bit
|
#define ext4_set_bit ext2_set_bit
|
||||||
#define ext4_set_bit_atomic ext2_set_bit_atomic
|
#define ext4_set_bit_atomic ext2_set_bit_atomic
|
||||||
|
@ -824,6 +826,13 @@ struct ext4_super_block {
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* run-time mount flags
|
||||||
|
*/
|
||||||
|
#define EXT4_MF_MNTDIR_SAMPLED 0x0001
|
||||||
|
#define EXT4_MF_FS_ABORTED 0x0002 /* Fatal error detected */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fourth extended-fs super-block data in memory
|
* fourth extended-fs super-block data in memory
|
||||||
*/
|
*/
|
||||||
|
@ -842,7 +851,8 @@ struct ext4_sb_info {
|
||||||
struct buffer_head * s_sbh; /* Buffer containing the super block */
|
struct buffer_head * s_sbh; /* Buffer containing the super block */
|
||||||
struct ext4_super_block *s_es; /* Pointer to the super block in the buffer */
|
struct ext4_super_block *s_es; /* Pointer to the super block in the buffer */
|
||||||
struct buffer_head **s_group_desc;
|
struct buffer_head **s_group_desc;
|
||||||
unsigned long s_mount_opt;
|
unsigned int s_mount_opt;
|
||||||
|
unsigned int s_mount_flags;
|
||||||
ext4_fsblk_t s_sb_block;
|
ext4_fsblk_t s_sb_block;
|
||||||
uid_t s_resuid;
|
uid_t s_resuid;
|
||||||
gid_t s_resgid;
|
gid_t s_resgid;
|
||||||
|
@ -853,6 +863,7 @@ struct ext4_sb_info {
|
||||||
int s_inode_size;
|
int s_inode_size;
|
||||||
int s_first_ino;
|
int s_first_ino;
|
||||||
unsigned int s_inode_readahead_blks;
|
unsigned int s_inode_readahead_blks;
|
||||||
|
unsigned int s_inode_goal;
|
||||||
spinlock_t s_next_gen_lock;
|
spinlock_t s_next_gen_lock;
|
||||||
u32 s_next_generation;
|
u32 s_next_generation;
|
||||||
u32 s_hash_seed[4];
|
u32 s_hash_seed[4];
|
||||||
|
@ -1305,7 +1316,8 @@ extern int ext4fs_dirhash(const char *name, int len, struct
|
||||||
dx_hash_info *hinfo);
|
dx_hash_info *hinfo);
|
||||||
|
|
||||||
/* ialloc.c */
|
/* ialloc.c */
|
||||||
extern struct inode * ext4_new_inode(handle_t *, struct inode *, int);
|
extern struct inode *ext4_new_inode(handle_t *, struct inode *, int,
|
||||||
|
const struct qstr *qstr, __u32 goal);
|
||||||
extern void ext4_free_inode(handle_t *, struct inode *);
|
extern void ext4_free_inode(handle_t *, struct inode *);
|
||||||
extern struct inode * ext4_orphan_get(struct super_block *, unsigned long);
|
extern struct inode * ext4_orphan_get(struct super_block *, unsigned long);
|
||||||
extern unsigned long ext4_count_free_inodes(struct super_block *);
|
extern unsigned long ext4_count_free_inodes(struct super_block *);
|
||||||
|
@ -1329,7 +1341,7 @@ extern void ext4_discard_preallocations(struct inode *);
|
||||||
extern int __init init_ext4_mballoc(void);
|
extern int __init init_ext4_mballoc(void);
|
||||||
extern void exit_ext4_mballoc(void);
|
extern void exit_ext4_mballoc(void);
|
||||||
extern void ext4_mb_free_blocks(handle_t *, struct inode *,
|
extern void ext4_mb_free_blocks(handle_t *, struct inode *,
|
||||||
unsigned long, unsigned long, int, unsigned long *);
|
ext4_fsblk_t, unsigned long, int, unsigned long *);
|
||||||
extern int ext4_mb_add_groupinfo(struct super_block *sb,
|
extern int ext4_mb_add_groupinfo(struct super_block *sb,
|
||||||
ext4_group_t i, struct ext4_group_desc *desc);
|
ext4_group_t i, struct ext4_group_desc *desc);
|
||||||
extern void ext4_mb_update_group_info(struct ext4_group_info *grp,
|
extern void ext4_mb_update_group_info(struct ext4_group_info *grp,
|
||||||
|
@ -1647,6 +1659,11 @@ extern int ext4_get_blocks(handle_t *handle, struct inode *inode,
|
||||||
struct buffer_head *bh, int flags);
|
struct buffer_head *bh, int flags);
|
||||||
extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
||||||
__u64 start, __u64 len);
|
__u64 start, __u64 len);
|
||||||
|
/* move_extent.c */
|
||||||
|
extern int ext4_move_extents(struct file *o_filp, struct file *d_filp,
|
||||||
|
__u64 start_orig, __u64 start_donor,
|
||||||
|
__u64 len, __u64 *moved_len);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add new method to test wether block and inode bitmaps are properly
|
* Add new method to test wether block and inode bitmaps are properly
|
||||||
|
|
|
@ -221,12 +221,16 @@ static inline int ext4_ext_get_actual_len(struct ext4_extent *ext)
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks);
|
extern int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks);
|
||||||
|
extern ext4_fsblk_t ext_pblock(struct ext4_extent *ex);
|
||||||
extern ext4_fsblk_t idx_pblock(struct ext4_extent_idx *);
|
extern ext4_fsblk_t idx_pblock(struct ext4_extent_idx *);
|
||||||
extern void ext4_ext_store_pblock(struct ext4_extent *, ext4_fsblk_t);
|
extern void ext4_ext_store_pblock(struct ext4_extent *, ext4_fsblk_t);
|
||||||
extern int ext4_extent_tree_init(handle_t *, struct inode *);
|
extern int ext4_extent_tree_init(handle_t *, struct inode *);
|
||||||
extern int ext4_ext_calc_credits_for_single_extent(struct inode *inode,
|
extern int ext4_ext_calc_credits_for_single_extent(struct inode *inode,
|
||||||
int num,
|
int num,
|
||||||
struct ext4_ext_path *path);
|
struct ext4_ext_path *path);
|
||||||
|
extern int ext4_can_extents_be_merged(struct inode *inode,
|
||||||
|
struct ext4_extent *ex1,
|
||||||
|
struct ext4_extent *ex2);
|
||||||
extern int ext4_ext_try_to_merge(struct inode *inode,
|
extern int ext4_ext_try_to_merge(struct inode *inode,
|
||||||
struct ext4_ext_path *path,
|
struct ext4_ext_path *path,
|
||||||
struct ext4_extent *);
|
struct ext4_extent *);
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
* ext_pblock:
|
* ext_pblock:
|
||||||
* combine low and high parts of physical block number into ext4_fsblk_t
|
* combine low and high parts of physical block number into ext4_fsblk_t
|
||||||
*/
|
*/
|
||||||
static ext4_fsblk_t ext_pblock(struct ext4_extent *ex)
|
ext4_fsblk_t ext_pblock(struct ext4_extent *ex)
|
||||||
{
|
{
|
||||||
ext4_fsblk_t block;
|
ext4_fsblk_t block;
|
||||||
|
|
||||||
|
@ -1417,7 +1417,7 @@ static int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
|
ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
|
||||||
struct ext4_extent *ex2)
|
struct ext4_extent *ex2)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include <linux/time.h>
|
#include <linux/time.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/jbd2.h>
|
#include <linux/jbd2.h>
|
||||||
|
#include <linux/mount.h>
|
||||||
|
#include <linux/path.h>
|
||||||
#include "ext4.h"
|
#include "ext4.h"
|
||||||
#include "ext4_jbd2.h"
|
#include "ext4_jbd2.h"
|
||||||
#include "xattr.h"
|
#include "xattr.h"
|
||||||
|
@ -145,6 +147,38 @@ static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ext4_file_open(struct inode * inode, struct file * filp)
|
||||||
|
{
|
||||||
|
struct super_block *sb = inode->i_sb;
|
||||||
|
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
|
||||||
|
struct vfsmount *mnt = filp->f_path.mnt;
|
||||||
|
struct path path;
|
||||||
|
char buf[64], *cp;
|
||||||
|
|
||||||
|
if (unlikely(!(sbi->s_mount_flags & EXT4_MF_MNTDIR_SAMPLED) &&
|
||||||
|
!(sb->s_flags & MS_RDONLY))) {
|
||||||
|
sbi->s_mount_flags |= EXT4_MF_MNTDIR_SAMPLED;
|
||||||
|
/*
|
||||||
|
* Sample where the filesystem has been mounted and
|
||||||
|
* store it in the superblock for sysadmin convenience
|
||||||
|
* when trying to sort through large numbers of block
|
||||||
|
* devices or filesystem images.
|
||||||
|
*/
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
path.mnt = mnt->mnt_parent;
|
||||||
|
path.dentry = mnt->mnt_mountpoint;
|
||||||
|
path_get(&path);
|
||||||
|
cp = d_path(&path, buf, sizeof(buf));
|
||||||
|
path_put(&path);
|
||||||
|
if (!IS_ERR(cp)) {
|
||||||
|
memcpy(sbi->s_es->s_last_mounted, cp,
|
||||||
|
sizeof(sbi->s_es->s_last_mounted));
|
||||||
|
sb->s_dirt = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return generic_file_open(inode, filp);
|
||||||
|
}
|
||||||
|
|
||||||
const struct file_operations ext4_file_operations = {
|
const struct file_operations ext4_file_operations = {
|
||||||
.llseek = generic_file_llseek,
|
.llseek = generic_file_llseek,
|
||||||
.read = do_sync_read,
|
.read = do_sync_read,
|
||||||
|
@ -156,7 +190,7 @@ const struct file_operations ext4_file_operations = {
|
||||||
.compat_ioctl = ext4_compat_ioctl,
|
.compat_ioctl = ext4_compat_ioctl,
|
||||||
#endif
|
#endif
|
||||||
.mmap = ext4_file_mmap,
|
.mmap = ext4_file_mmap,
|
||||||
.open = generic_file_open,
|
.open = ext4_file_open,
|
||||||
.release = ext4_release_file,
|
.release = ext4_release_file,
|
||||||
.fsync = ext4_sync_file,
|
.fsync = ext4_sync_file,
|
||||||
.splice_read = generic_file_splice_read,
|
.splice_read = generic_file_splice_read,
|
||||||
|
|
|
@ -28,10 +28,12 @@
|
||||||
#include <linux/writeback.h>
|
#include <linux/writeback.h>
|
||||||
#include <linux/jbd2.h>
|
#include <linux/jbd2.h>
|
||||||
#include <linux/blkdev.h>
|
#include <linux/blkdev.h>
|
||||||
#include <linux/marker.h>
|
|
||||||
#include "ext4.h"
|
#include "ext4.h"
|
||||||
#include "ext4_jbd2.h"
|
#include "ext4_jbd2.h"
|
||||||
|
|
||||||
|
#include <trace/events/ext4.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* akpm: A new design for ext4_sync_file().
|
* akpm: A new design for ext4_sync_file().
|
||||||
*
|
*
|
||||||
|
@ -52,9 +54,7 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
|
||||||
|
|
||||||
J_ASSERT(ext4_journal_current_handle() == NULL);
|
J_ASSERT(ext4_journal_current_handle() == NULL);
|
||||||
|
|
||||||
trace_mark(ext4_sync_file, "dev %s datasync %d ino %ld parent %ld",
|
trace_ext4_sync_file(file, dentry, datasync);
|
||||||
inode->i_sb->s_id, datasync, inode->i_ino,
|
|
||||||
dentry->d_parent->d_inode->i_ino);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* data=writeback:
|
* data=writeback:
|
||||||
|
|
|
@ -23,11 +23,14 @@
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/blkdev.h>
|
#include <linux/blkdev.h>
|
||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
|
|
||||||
#include "ext4.h"
|
#include "ext4.h"
|
||||||
#include "ext4_jbd2.h"
|
#include "ext4_jbd2.h"
|
||||||
#include "xattr.h"
|
#include "xattr.h"
|
||||||
#include "acl.h"
|
#include "acl.h"
|
||||||
|
|
||||||
|
#include <trace/events/ext4.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ialloc.c contains the inodes allocation and deallocation routines
|
* ialloc.c contains the inodes allocation and deallocation routines
|
||||||
*/
|
*/
|
||||||
|
@ -208,11 +211,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
|
||||||
|
|
||||||
ino = inode->i_ino;
|
ino = inode->i_ino;
|
||||||
ext4_debug("freeing inode %lu\n", ino);
|
ext4_debug("freeing inode %lu\n", ino);
|
||||||
trace_mark(ext4_free_inode,
|
trace_ext4_free_inode(inode);
|
||||||
"dev %s ino %lu mode %d uid %lu gid %lu bocks %llu",
|
|
||||||
sb->s_id, inode->i_ino, inode->i_mode,
|
|
||||||
(unsigned long) inode->i_uid, (unsigned long) inode->i_gid,
|
|
||||||
(unsigned long long) inode->i_blocks);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: we must free any quota before locking the superblock,
|
* Note: we must free any quota before locking the superblock,
|
||||||
|
@ -471,7 +470,8 @@ void get_orlov_stats(struct super_block *sb, ext4_group_t g,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int find_group_orlov(struct super_block *sb, struct inode *parent,
|
static int find_group_orlov(struct super_block *sb, struct inode *parent,
|
||||||
ext4_group_t *group, int mode)
|
ext4_group_t *group, int mode,
|
||||||
|
const struct qstr *qstr)
|
||||||
{
|
{
|
||||||
ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
|
ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
|
||||||
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||||
|
@ -486,6 +486,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
|
||||||
struct ext4_group_desc *desc;
|
struct ext4_group_desc *desc;
|
||||||
struct orlov_stats stats;
|
struct orlov_stats stats;
|
||||||
int flex_size = ext4_flex_bg_size(sbi);
|
int flex_size = ext4_flex_bg_size(sbi);
|
||||||
|
struct dx_hash_info hinfo;
|
||||||
|
|
||||||
ngroups = real_ngroups;
|
ngroups = real_ngroups;
|
||||||
if (flex_size > 1) {
|
if (flex_size > 1) {
|
||||||
|
@ -507,7 +508,13 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
|
||||||
int best_ndir = inodes_per_group;
|
int best_ndir = inodes_per_group;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
get_random_bytes(&grp, sizeof(grp));
|
if (qstr) {
|
||||||
|
hinfo.hash_version = DX_HASH_HALF_MD4;
|
||||||
|
hinfo.seed = sbi->s_hash_seed;
|
||||||
|
ext4fs_dirhash(qstr->name, qstr->len, &hinfo);
|
||||||
|
grp = hinfo.hash;
|
||||||
|
} else
|
||||||
|
get_random_bytes(&grp, sizeof(grp));
|
||||||
parent_group = (unsigned)grp % ngroups;
|
parent_group = (unsigned)grp % ngroups;
|
||||||
for (i = 0; i < ngroups; i++) {
|
for (i = 0; i < ngroups; i++) {
|
||||||
g = (parent_group + i) % ngroups;
|
g = (parent_group + i) % ngroups;
|
||||||
|
@ -650,7 +657,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
|
||||||
*group = parent_group + flex_size;
|
*group = parent_group + flex_size;
|
||||||
if (*group > ngroups)
|
if (*group > ngroups)
|
||||||
*group = 0;
|
*group = 0;
|
||||||
return find_group_orlov(sb, parent, group, mode);
|
return find_group_orlov(sb, parent, group, mode, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -791,7 +798,8 @@ static int ext4_claim_inode(struct super_block *sb,
|
||||||
* For other inodes, search forward from the parent directory's block
|
* For other inodes, search forward from the parent directory's block
|
||||||
* group to find a free inode.
|
* group to find a free inode.
|
||||||
*/
|
*/
|
||||||
struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
|
struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
|
||||||
|
const struct qstr *qstr, __u32 goal)
|
||||||
{
|
{
|
||||||
struct super_block *sb;
|
struct super_block *sb;
|
||||||
struct buffer_head *inode_bitmap_bh = NULL;
|
struct buffer_head *inode_bitmap_bh = NULL;
|
||||||
|
@ -815,14 +823,23 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
|
||||||
|
|
||||||
sb = dir->i_sb;
|
sb = dir->i_sb;
|
||||||
ngroups = ext4_get_groups_count(sb);
|
ngroups = ext4_get_groups_count(sb);
|
||||||
trace_mark(ext4_request_inode, "dev %s dir %lu mode %d", sb->s_id,
|
trace_ext4_request_inode(dir, mode);
|
||||||
dir->i_ino, mode);
|
|
||||||
inode = new_inode(sb);
|
inode = new_inode(sb);
|
||||||
if (!inode)
|
if (!inode)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
ei = EXT4_I(inode);
|
ei = EXT4_I(inode);
|
||||||
sbi = EXT4_SB(sb);
|
sbi = EXT4_SB(sb);
|
||||||
|
|
||||||
|
if (!goal)
|
||||||
|
goal = sbi->s_inode_goal;
|
||||||
|
|
||||||
|
if (goal && goal < le32_to_cpu(sbi->s_es->s_inodes_count)) {
|
||||||
|
group = (goal - 1) / EXT4_INODES_PER_GROUP(sb);
|
||||||
|
ino = (goal - 1) % EXT4_INODES_PER_GROUP(sb);
|
||||||
|
ret2 = 0;
|
||||||
|
goto got_group;
|
||||||
|
}
|
||||||
|
|
||||||
if (sbi->s_log_groups_per_flex && test_opt(sb, OLDALLOC)) {
|
if (sbi->s_log_groups_per_flex && test_opt(sb, OLDALLOC)) {
|
||||||
ret2 = find_group_flex(sb, dir, &group);
|
ret2 = find_group_flex(sb, dir, &group);
|
||||||
if (ret2 == -1) {
|
if (ret2 == -1) {
|
||||||
|
@ -841,7 +858,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
|
||||||
if (test_opt(sb, OLDALLOC))
|
if (test_opt(sb, OLDALLOC))
|
||||||
ret2 = find_group_dir(sb, dir, &group);
|
ret2 = find_group_dir(sb, dir, &group);
|
||||||
else
|
else
|
||||||
ret2 = find_group_orlov(sb, dir, &group, mode);
|
ret2 = find_group_orlov(sb, dir, &group, mode, qstr);
|
||||||
} else
|
} else
|
||||||
ret2 = find_group_other(sb, dir, &group, mode);
|
ret2 = find_group_other(sb, dir, &group, mode);
|
||||||
|
|
||||||
|
@ -851,7 +868,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
|
||||||
if (ret2 == -1)
|
if (ret2 == -1)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
for (i = 0; i < ngroups; i++) {
|
for (i = 0; i < ngroups; i++, ino = 0) {
|
||||||
err = -EIO;
|
err = -EIO;
|
||||||
|
|
||||||
gdp = ext4_get_group_desc(sb, group, &group_desc_bh);
|
gdp = ext4_get_group_desc(sb, group, &group_desc_bh);
|
||||||
|
@ -863,8 +880,6 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
|
||||||
if (!inode_bitmap_bh)
|
if (!inode_bitmap_bh)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
ino = 0;
|
|
||||||
|
|
||||||
repeat_in_this_group:
|
repeat_in_this_group:
|
||||||
ino = ext4_find_next_zero_bit((unsigned long *)
|
ino = ext4_find_next_zero_bit((unsigned long *)
|
||||||
inode_bitmap_bh->b_data,
|
inode_bitmap_bh->b_data,
|
||||||
|
@ -1047,8 +1062,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
ext4_debug("allocating inode %lu\n", inode->i_ino);
|
ext4_debug("allocating inode %lu\n", inode->i_ino);
|
||||||
trace_mark(ext4_allocate_inode, "dev %s ino %lu dir %lu mode %d",
|
trace_ext4_allocate_inode(inode, dir, mode);
|
||||||
sb->s_id, inode->i_ino, dir->i_ino, mode);
|
|
||||||
goto really_out;
|
goto really_out;
|
||||||
fail:
|
fail:
|
||||||
ext4_std_error(sb, err);
|
ext4_std_error(sb, err);
|
||||||
|
|
251
fs/ext4/inode.c
251
fs/ext4/inode.c
|
@ -37,11 +37,14 @@
|
||||||
#include <linux/namei.h>
|
#include <linux/namei.h>
|
||||||
#include <linux/uio.h>
|
#include <linux/uio.h>
|
||||||
#include <linux/bio.h>
|
#include <linux/bio.h>
|
||||||
|
|
||||||
#include "ext4_jbd2.h"
|
#include "ext4_jbd2.h"
|
||||||
#include "xattr.h"
|
#include "xattr.h"
|
||||||
#include "acl.h"
|
#include "acl.h"
|
||||||
#include "ext4_extents.h"
|
#include "ext4_extents.h"
|
||||||
|
|
||||||
|
#include <trace/events/ext4.h>
|
||||||
|
|
||||||
#define MPAGE_DA_EXTENT_TAIL 0x01
|
#define MPAGE_DA_EXTENT_TAIL 0x01
|
||||||
|
|
||||||
static inline int ext4_begin_ordered_truncate(struct inode *inode,
|
static inline int ext4_begin_ordered_truncate(struct inode *inode,
|
||||||
|
@ -78,7 +81,7 @@ static int ext4_inode_is_fast_symlink(struct inode *inode)
|
||||||
* If the handle isn't valid we're not journaling so there's nothing to do.
|
* If the handle isn't valid we're not journaling so there's nothing to do.
|
||||||
*/
|
*/
|
||||||
int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode,
|
int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode,
|
||||||
struct buffer_head *bh, ext4_fsblk_t blocknr)
|
struct buffer_head *bh, ext4_fsblk_t blocknr)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -90,7 +93,7 @@ int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode,
|
||||||
BUFFER_TRACE(bh, "enter");
|
BUFFER_TRACE(bh, "enter");
|
||||||
|
|
||||||
jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, "
|
jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, "
|
||||||
"data mode %lx\n",
|
"data mode %x\n",
|
||||||
bh, is_metadata, inode->i_mode,
|
bh, is_metadata, inode->i_mode,
|
||||||
test_opt(inode->i_sb, DATA_FLAGS));
|
test_opt(inode->i_sb, DATA_FLAGS));
|
||||||
|
|
||||||
|
@ -329,8 +332,8 @@ static inline void add_chain(Indirect *p, struct buffer_head *bh, __le32 *v)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int ext4_block_to_path(struct inode *inode,
|
static int ext4_block_to_path(struct inode *inode,
|
||||||
ext4_lblk_t i_block,
|
ext4_lblk_t i_block,
|
||||||
ext4_lblk_t offsets[4], int *boundary)
|
ext4_lblk_t offsets[4], int *boundary)
|
||||||
{
|
{
|
||||||
int ptrs = EXT4_ADDR_PER_BLOCK(inode->i_sb);
|
int ptrs = EXT4_ADDR_PER_BLOCK(inode->i_sb);
|
||||||
int ptrs_bits = EXT4_ADDR_PER_BLOCK_BITS(inode->i_sb);
|
int ptrs_bits = EXT4_ADDR_PER_BLOCK_BITS(inode->i_sb);
|
||||||
|
@ -362,9 +365,9 @@ static int ext4_block_to_path(struct inode *inode,
|
||||||
final = ptrs;
|
final = ptrs;
|
||||||
} else {
|
} else {
|
||||||
ext4_warning(inode->i_sb, "ext4_block_to_path",
|
ext4_warning(inode->i_sb, "ext4_block_to_path",
|
||||||
"block %lu > max in inode %lu",
|
"block %lu > max in inode %lu",
|
||||||
i_block + direct_blocks +
|
i_block + direct_blocks +
|
||||||
indirect_blocks + double_blocks, inode->i_ino);
|
indirect_blocks + double_blocks, inode->i_ino);
|
||||||
}
|
}
|
||||||
if (boundary)
|
if (boundary)
|
||||||
*boundary = final - 1 - (i_block & (ptrs - 1));
|
*boundary = final - 1 - (i_block & (ptrs - 1));
|
||||||
|
@ -385,19 +388,19 @@ static int __ext4_check_blockref(const char *function, struct inode *inode,
|
||||||
ext4_error(inode->i_sb, function,
|
ext4_error(inode->i_sb, function,
|
||||||
"invalid block reference %u "
|
"invalid block reference %u "
|
||||||
"in inode #%lu", blk, inode->i_ino);
|
"in inode #%lu", blk, inode->i_ino);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define ext4_check_indirect_blockref(inode, bh) \
|
#define ext4_check_indirect_blockref(inode, bh) \
|
||||||
__ext4_check_blockref(__func__, inode, (__le32 *)(bh)->b_data, \
|
__ext4_check_blockref(__func__, inode, (__le32 *)(bh)->b_data, \
|
||||||
EXT4_ADDR_PER_BLOCK((inode)->i_sb))
|
EXT4_ADDR_PER_BLOCK((inode)->i_sb))
|
||||||
|
|
||||||
#define ext4_check_inode_blockref(inode) \
|
#define ext4_check_inode_blockref(inode) \
|
||||||
__ext4_check_blockref(__func__, inode, EXT4_I(inode)->i_data, \
|
__ext4_check_blockref(__func__, inode, EXT4_I(inode)->i_data, \
|
||||||
EXT4_NDIR_BLOCKS)
|
EXT4_NDIR_BLOCKS)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -552,7 +555,7 @@ static ext4_fsblk_t ext4_find_near(struct inode *inode, Indirect *ind)
|
||||||
* returns it.
|
* returns it.
|
||||||
*/
|
*/
|
||||||
static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block,
|
static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block,
|
||||||
Indirect *partial)
|
Indirect *partial)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* XXX need to get goal block from mballoc's data structures
|
* XXX need to get goal block from mballoc's data structures
|
||||||
|
@ -574,7 +577,7 @@ static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block,
|
||||||
* direct and indirect blocks.
|
* direct and indirect blocks.
|
||||||
*/
|
*/
|
||||||
static int ext4_blks_to_allocate(Indirect *branch, int k, unsigned int blks,
|
static int ext4_blks_to_allocate(Indirect *branch, int k, unsigned int blks,
|
||||||
int blocks_to_boundary)
|
int blocks_to_boundary)
|
||||||
{
|
{
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
|
|
||||||
|
@ -610,9 +613,9 @@ static int ext4_blks_to_allocate(Indirect *branch, int k, unsigned int blks,
|
||||||
* direct blocks
|
* direct blocks
|
||||||
*/
|
*/
|
||||||
static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
|
static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
|
||||||
ext4_lblk_t iblock, ext4_fsblk_t goal,
|
ext4_lblk_t iblock, ext4_fsblk_t goal,
|
||||||
int indirect_blks, int blks,
|
int indirect_blks, int blks,
|
||||||
ext4_fsblk_t new_blocks[4], int *err)
|
ext4_fsblk_t new_blocks[4], int *err)
|
||||||
{
|
{
|
||||||
struct ext4_allocation_request ar;
|
struct ext4_allocation_request ar;
|
||||||
int target, i;
|
int target, i;
|
||||||
|
@ -683,10 +686,10 @@ static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
|
||||||
}
|
}
|
||||||
if (!*err) {
|
if (!*err) {
|
||||||
if (target == blks) {
|
if (target == blks) {
|
||||||
/*
|
/*
|
||||||
* save the new block number
|
* save the new block number
|
||||||
* for the first direct block
|
* for the first direct block
|
||||||
*/
|
*/
|
||||||
new_blocks[index] = current_block;
|
new_blocks[index] = current_block;
|
||||||
}
|
}
|
||||||
blk_allocated += ar.len;
|
blk_allocated += ar.len;
|
||||||
|
@ -728,9 +731,9 @@ static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
|
||||||
* as described above and return 0.
|
* as described above and return 0.
|
||||||
*/
|
*/
|
||||||
static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
|
static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
|
||||||
ext4_lblk_t iblock, int indirect_blks,
|
ext4_lblk_t iblock, int indirect_blks,
|
||||||
int *blks, ext4_fsblk_t goal,
|
int *blks, ext4_fsblk_t goal,
|
||||||
ext4_lblk_t *offsets, Indirect *branch)
|
ext4_lblk_t *offsets, Indirect *branch)
|
||||||
{
|
{
|
||||||
int blocksize = inode->i_sb->s_blocksize;
|
int blocksize = inode->i_sb->s_blocksize;
|
||||||
int i, n = 0;
|
int i, n = 0;
|
||||||
|
@ -777,7 +780,7 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
|
||||||
* the chain to point to the new allocated
|
* the chain to point to the new allocated
|
||||||
* data blocks numbers
|
* data blocks numbers
|
||||||
*/
|
*/
|
||||||
for (i=1; i < num; i++)
|
for (i = 1; i < num; i++)
|
||||||
*(branch[n].p + i) = cpu_to_le32(++current_block);
|
*(branch[n].p + i) = cpu_to_le32(++current_block);
|
||||||
}
|
}
|
||||||
BUFFER_TRACE(bh, "marking uptodate");
|
BUFFER_TRACE(bh, "marking uptodate");
|
||||||
|
@ -820,7 +823,8 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
|
||||||
* chain to new block and return 0.
|
* chain to new block and return 0.
|
||||||
*/
|
*/
|
||||||
static int ext4_splice_branch(handle_t *handle, struct inode *inode,
|
static int ext4_splice_branch(handle_t *handle, struct inode *inode,
|
||||||
ext4_lblk_t block, Indirect *where, int num, int blks)
|
ext4_lblk_t block, Indirect *where, int num,
|
||||||
|
int blks)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
@ -852,10 +856,6 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We are done with atomic stuff, now do the rest of housekeeping */
|
/* We are done with atomic stuff, now do the rest of housekeeping */
|
||||||
|
|
||||||
inode->i_ctime = ext4_current_time(inode);
|
|
||||||
ext4_mark_inode_dirty(handle, inode);
|
|
||||||
|
|
||||||
/* had we spliced it onto indirect block? */
|
/* had we spliced it onto indirect block? */
|
||||||
if (where->bh) {
|
if (where->bh) {
|
||||||
/*
|
/*
|
||||||
|
@ -874,8 +874,8 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* OK, we spliced it into the inode itself on a direct block.
|
* OK, we spliced it into the inode itself on a direct block.
|
||||||
* Inode was dirtied above.
|
|
||||||
*/
|
*/
|
||||||
|
ext4_mark_inode_dirty(handle, inode);
|
||||||
jbd_debug(5, "splicing direct\n");
|
jbd_debug(5, "splicing direct\n");
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
|
@ -921,9 +921,9 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
|
||||||
* blocks.
|
* blocks.
|
||||||
*/
|
*/
|
||||||
static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
|
static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
|
||||||
ext4_lblk_t iblock, unsigned int maxblocks,
|
ext4_lblk_t iblock, unsigned int maxblocks,
|
||||||
struct buffer_head *bh_result,
|
struct buffer_head *bh_result,
|
||||||
int flags)
|
int flags)
|
||||||
{
|
{
|
||||||
int err = -EIO;
|
int err = -EIO;
|
||||||
ext4_lblk_t offsets[4];
|
ext4_lblk_t offsets[4];
|
||||||
|
@ -939,7 +939,7 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
|
||||||
J_ASSERT(!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL));
|
J_ASSERT(!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL));
|
||||||
J_ASSERT(handle != NULL || (flags & EXT4_GET_BLOCKS_CREATE) == 0);
|
J_ASSERT(handle != NULL || (flags & EXT4_GET_BLOCKS_CREATE) == 0);
|
||||||
depth = ext4_block_to_path(inode, iblock, offsets,
|
depth = ext4_block_to_path(inode, iblock, offsets,
|
||||||
&blocks_to_boundary);
|
&blocks_to_boundary);
|
||||||
|
|
||||||
if (depth == 0)
|
if (depth == 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -987,8 +987,8 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
|
||||||
* Block out ext4_truncate while we alter the tree
|
* Block out ext4_truncate while we alter the tree
|
||||||
*/
|
*/
|
||||||
err = ext4_alloc_branch(handle, inode, iblock, indirect_blks,
|
err = ext4_alloc_branch(handle, inode, iblock, indirect_blks,
|
||||||
&count, goal,
|
&count, goal,
|
||||||
offsets + (partial - chain), partial);
|
offsets + (partial - chain), partial);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The ext4_splice_branch call will free and forget any buffers
|
* The ext4_splice_branch call will free and forget any buffers
|
||||||
|
@ -999,7 +999,7 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode,
|
||||||
*/
|
*/
|
||||||
if (!err)
|
if (!err)
|
||||||
err = ext4_splice_branch(handle, inode, iblock,
|
err = ext4_splice_branch(handle, inode, iblock,
|
||||||
partial, indirect_blks, count);
|
partial, indirect_blks, count);
|
||||||
else
|
else
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
@ -1405,8 +1405,7 @@ static int walk_page_buffers(handle_t *handle,
|
||||||
|
|
||||||
for (bh = head, block_start = 0;
|
for (bh = head, block_start = 0;
|
||||||
ret == 0 && (bh != head || !block_start);
|
ret == 0 && (bh != head || !block_start);
|
||||||
block_start = block_end, bh = next)
|
block_start = block_end, bh = next) {
|
||||||
{
|
|
||||||
next = bh->b_this_page;
|
next = bh->b_this_page;
|
||||||
block_end = block_start + blocksize;
|
block_end = block_start + blocksize;
|
||||||
if (block_end <= from || block_start >= to) {
|
if (block_end <= from || block_start >= to) {
|
||||||
|
@ -1447,7 +1446,7 @@ static int walk_page_buffers(handle_t *handle,
|
||||||
* write.
|
* write.
|
||||||
*/
|
*/
|
||||||
static int do_journal_get_write_access(handle_t *handle,
|
static int do_journal_get_write_access(handle_t *handle,
|
||||||
struct buffer_head *bh)
|
struct buffer_head *bh)
|
||||||
{
|
{
|
||||||
if (!buffer_mapped(bh) || buffer_freed(bh))
|
if (!buffer_mapped(bh) || buffer_freed(bh))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1455,27 +1454,24 @@ static int do_journal_get_write_access(handle_t *handle,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ext4_write_begin(struct file *file, struct address_space *mapping,
|
static int ext4_write_begin(struct file *file, struct address_space *mapping,
|
||||||
loff_t pos, unsigned len, unsigned flags,
|
loff_t pos, unsigned len, unsigned flags,
|
||||||
struct page **pagep, void **fsdata)
|
struct page **pagep, void **fsdata)
|
||||||
{
|
{
|
||||||
struct inode *inode = mapping->host;
|
struct inode *inode = mapping->host;
|
||||||
int ret, needed_blocks;
|
int ret, needed_blocks;
|
||||||
handle_t *handle;
|
handle_t *handle;
|
||||||
int retries = 0;
|
int retries = 0;
|
||||||
struct page *page;
|
struct page *page;
|
||||||
pgoff_t index;
|
pgoff_t index;
|
||||||
unsigned from, to;
|
unsigned from, to;
|
||||||
|
|
||||||
trace_mark(ext4_write_begin,
|
trace_ext4_write_begin(inode, pos, len, flags);
|
||||||
"dev %s ino %lu pos %llu len %u flags %u",
|
|
||||||
inode->i_sb->s_id, inode->i_ino,
|
|
||||||
(unsigned long long) pos, len, flags);
|
|
||||||
/*
|
/*
|
||||||
* Reserve one block more for addition to orphan list in case
|
* Reserve one block more for addition to orphan list in case
|
||||||
* we allocate blocks but write fails for some reason
|
* we allocate blocks but write fails for some reason
|
||||||
*/
|
*/
|
||||||
needed_blocks = ext4_writepage_trans_blocks(inode) + 1;
|
needed_blocks = ext4_writepage_trans_blocks(inode) + 1;
|
||||||
index = pos >> PAGE_CACHE_SHIFT;
|
index = pos >> PAGE_CACHE_SHIFT;
|
||||||
from = pos & (PAGE_CACHE_SIZE - 1);
|
from = pos & (PAGE_CACHE_SIZE - 1);
|
||||||
to = from + len;
|
to = from + len;
|
||||||
|
|
||||||
|
@ -1550,9 +1546,9 @@ static int write_end_fn(handle_t *handle, struct buffer_head *bh)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ext4_generic_write_end(struct file *file,
|
static int ext4_generic_write_end(struct file *file,
|
||||||
struct address_space *mapping,
|
struct address_space *mapping,
|
||||||
loff_t pos, unsigned len, unsigned copied,
|
loff_t pos, unsigned len, unsigned copied,
|
||||||
struct page *page, void *fsdata)
|
struct page *page, void *fsdata)
|
||||||
{
|
{
|
||||||
int i_size_changed = 0;
|
int i_size_changed = 0;
|
||||||
struct inode *inode = mapping->host;
|
struct inode *inode = mapping->host;
|
||||||
|
@ -1603,18 +1599,15 @@ static int ext4_generic_write_end(struct file *file,
|
||||||
* buffers are managed internally.
|
* buffers are managed internally.
|
||||||
*/
|
*/
|
||||||
static int ext4_ordered_write_end(struct file *file,
|
static int ext4_ordered_write_end(struct file *file,
|
||||||
struct address_space *mapping,
|
struct address_space *mapping,
|
||||||
loff_t pos, unsigned len, unsigned copied,
|
loff_t pos, unsigned len, unsigned copied,
|
||||||
struct page *page, void *fsdata)
|
struct page *page, void *fsdata)
|
||||||
{
|
{
|
||||||
handle_t *handle = ext4_journal_current_handle();
|
handle_t *handle = ext4_journal_current_handle();
|
||||||
struct inode *inode = mapping->host;
|
struct inode *inode = mapping->host;
|
||||||
int ret = 0, ret2;
|
int ret = 0, ret2;
|
||||||
|
|
||||||
trace_mark(ext4_ordered_write_end,
|
trace_ext4_ordered_write_end(inode, pos, len, copied);
|
||||||
"dev %s ino %lu pos %llu len %u copied %u",
|
|
||||||
inode->i_sb->s_id, inode->i_ino,
|
|
||||||
(unsigned long long) pos, len, copied);
|
|
||||||
ret = ext4_jbd2_file_inode(handle, inode);
|
ret = ext4_jbd2_file_inode(handle, inode);
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
|
@ -1650,18 +1643,15 @@ static int ext4_ordered_write_end(struct file *file,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ext4_writeback_write_end(struct file *file,
|
static int ext4_writeback_write_end(struct file *file,
|
||||||
struct address_space *mapping,
|
struct address_space *mapping,
|
||||||
loff_t pos, unsigned len, unsigned copied,
|
loff_t pos, unsigned len, unsigned copied,
|
||||||
struct page *page, void *fsdata)
|
struct page *page, void *fsdata)
|
||||||
{
|
{
|
||||||
handle_t *handle = ext4_journal_current_handle();
|
handle_t *handle = ext4_journal_current_handle();
|
||||||
struct inode *inode = mapping->host;
|
struct inode *inode = mapping->host;
|
||||||
int ret = 0, ret2;
|
int ret = 0, ret2;
|
||||||
|
|
||||||
trace_mark(ext4_writeback_write_end,
|
trace_ext4_writeback_write_end(inode, pos, len, copied);
|
||||||
"dev %s ino %lu pos %llu len %u copied %u",
|
|
||||||
inode->i_sb->s_id, inode->i_ino,
|
|
||||||
(unsigned long long) pos, len, copied);
|
|
||||||
ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
|
ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
|
||||||
page, fsdata);
|
page, fsdata);
|
||||||
copied = ret2;
|
copied = ret2;
|
||||||
|
@ -1694,9 +1684,9 @@ static int ext4_writeback_write_end(struct file *file,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ext4_journalled_write_end(struct file *file,
|
static int ext4_journalled_write_end(struct file *file,
|
||||||
struct address_space *mapping,
|
struct address_space *mapping,
|
||||||
loff_t pos, unsigned len, unsigned copied,
|
loff_t pos, unsigned len, unsigned copied,
|
||||||
struct page *page, void *fsdata)
|
struct page *page, void *fsdata)
|
||||||
{
|
{
|
||||||
handle_t *handle = ext4_journal_current_handle();
|
handle_t *handle = ext4_journal_current_handle();
|
||||||
struct inode *inode = mapping->host;
|
struct inode *inode = mapping->host;
|
||||||
|
@ -1705,10 +1695,7 @@ static int ext4_journalled_write_end(struct file *file,
|
||||||
unsigned from, to;
|
unsigned from, to;
|
||||||
loff_t new_i_size;
|
loff_t new_i_size;
|
||||||
|
|
||||||
trace_mark(ext4_journalled_write_end,
|
trace_ext4_journalled_write_end(inode, pos, len, copied);
|
||||||
"dev %s ino %lu pos %llu len %u copied %u",
|
|
||||||
inode->i_sb->s_id, inode->i_ino,
|
|
||||||
(unsigned long long) pos, len, copied);
|
|
||||||
from = pos & (PAGE_CACHE_SIZE - 1);
|
from = pos & (PAGE_CACHE_SIZE - 1);
|
||||||
to = from + len;
|
to = from + len;
|
||||||
|
|
||||||
|
@ -1854,7 +1841,7 @@ static void ext4_da_release_space(struct inode *inode, int to_free)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ext4_da_page_release_reservation(struct page *page,
|
static void ext4_da_page_release_reservation(struct page *page,
|
||||||
unsigned long offset)
|
unsigned long offset)
|
||||||
{
|
{
|
||||||
int to_release = 0;
|
int to_release = 0;
|
||||||
struct buffer_head *head, *bh;
|
struct buffer_head *head, *bh;
|
||||||
|
@ -2554,9 +2541,7 @@ static int ext4_da_writepage(struct page *page,
|
||||||
struct buffer_head *page_bufs;
|
struct buffer_head *page_bufs;
|
||||||
struct inode *inode = page->mapping->host;
|
struct inode *inode = page->mapping->host;
|
||||||
|
|
||||||
trace_mark(ext4_da_writepage,
|
trace_ext4_da_writepage(inode, page);
|
||||||
"dev %s ino %lu page_index %lu",
|
|
||||||
inode->i_sb->s_id, inode->i_ino, page->index);
|
|
||||||
size = i_size_read(inode);
|
size = i_size_read(inode);
|
||||||
if (page->index == size >> PAGE_CACHE_SHIFT)
|
if (page->index == size >> PAGE_CACHE_SHIFT)
|
||||||
len = size & ~PAGE_CACHE_MASK;
|
len = size & ~PAGE_CACHE_MASK;
|
||||||
|
@ -2667,19 +2652,7 @@ static int ext4_da_writepages(struct address_space *mapping,
|
||||||
int needed_blocks, ret = 0, nr_to_writebump = 0;
|
int needed_blocks, ret = 0, nr_to_writebump = 0;
|
||||||
struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb);
|
struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb);
|
||||||
|
|
||||||
trace_mark(ext4_da_writepages,
|
trace_ext4_da_writepages(inode, wbc);
|
||||||
"dev %s ino %lu nr_t_write %ld "
|
|
||||||
"pages_skipped %ld range_start %llu "
|
|
||||||
"range_end %llu nonblocking %d "
|
|
||||||
"for_kupdate %d for_reclaim %d "
|
|
||||||
"for_writepages %d range_cyclic %d",
|
|
||||||
inode->i_sb->s_id, inode->i_ino,
|
|
||||||
wbc->nr_to_write, wbc->pages_skipped,
|
|
||||||
(unsigned long long) wbc->range_start,
|
|
||||||
(unsigned long long) wbc->range_end,
|
|
||||||
wbc->nonblocking, wbc->for_kupdate,
|
|
||||||
wbc->for_reclaim, wbc->for_writepages,
|
|
||||||
wbc->range_cyclic);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No pages to write? This is mainly a kludge to avoid starting
|
* No pages to write? This is mainly a kludge to avoid starting
|
||||||
|
@ -2693,13 +2666,13 @@ static int ext4_da_writepages(struct address_space *mapping,
|
||||||
* If the filesystem has aborted, it is read-only, so return
|
* If the filesystem has aborted, it is read-only, so return
|
||||||
* right away instead of dumping stack traces later on that
|
* right away instead of dumping stack traces later on that
|
||||||
* will obscure the real source of the problem. We test
|
* will obscure the real source of the problem. We test
|
||||||
* EXT4_MOUNT_ABORT instead of sb->s_flag's MS_RDONLY because
|
* EXT4_MF_FS_ABORTED instead of sb->s_flag's MS_RDONLY because
|
||||||
* the latter could be true if the filesystem is mounted
|
* the latter could be true if the filesystem is mounted
|
||||||
* read-only, and in that case, ext4_da_writepages should
|
* read-only, and in that case, ext4_da_writepages should
|
||||||
* *never* be called, so if that ever happens, we would want
|
* *never* be called, so if that ever happens, we would want
|
||||||
* the stack trace.
|
* the stack trace.
|
||||||
*/
|
*/
|
||||||
if (unlikely(sbi->s_mount_opt & EXT4_MOUNT_ABORT))
|
if (unlikely(sbi->s_mount_flags & EXT4_MF_FS_ABORTED))
|
||||||
return -EROFS;
|
return -EROFS;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2845,14 +2818,7 @@ static int ext4_da_writepages(struct address_space *mapping,
|
||||||
if (!no_nrwrite_index_update)
|
if (!no_nrwrite_index_update)
|
||||||
wbc->no_nrwrite_index_update = 0;
|
wbc->no_nrwrite_index_update = 0;
|
||||||
wbc->nr_to_write -= nr_to_writebump;
|
wbc->nr_to_write -= nr_to_writebump;
|
||||||
trace_mark(ext4_da_writepage_result,
|
trace_ext4_da_writepages_result(inode, wbc, ret, pages_written);
|
||||||
"dev %s ino %lu ret %d pages_written %d "
|
|
||||||
"pages_skipped %ld congestion %d "
|
|
||||||
"more_io %d no_nrwrite_index_update %d",
|
|
||||||
inode->i_sb->s_id, inode->i_ino, ret,
|
|
||||||
pages_written, wbc->pages_skipped,
|
|
||||||
wbc->encountered_congestion, wbc->more_io,
|
|
||||||
wbc->no_nrwrite_index_update);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2884,8 +2850,8 @@ static int ext4_nonda_switch(struct super_block *sb)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
|
static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
|
||||||
loff_t pos, unsigned len, unsigned flags,
|
loff_t pos, unsigned len, unsigned flags,
|
||||||
struct page **pagep, void **fsdata)
|
struct page **pagep, void **fsdata)
|
||||||
{
|
{
|
||||||
int ret, retries = 0;
|
int ret, retries = 0;
|
||||||
struct page *page;
|
struct page *page;
|
||||||
|
@ -2904,11 +2870,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
|
||||||
len, flags, pagep, fsdata);
|
len, flags, pagep, fsdata);
|
||||||
}
|
}
|
||||||
*fsdata = (void *)0;
|
*fsdata = (void *)0;
|
||||||
|
trace_ext4_da_write_begin(inode, pos, len, flags);
|
||||||
trace_mark(ext4_da_write_begin,
|
|
||||||
"dev %s ino %lu pos %llu len %u flags %u",
|
|
||||||
inode->i_sb->s_id, inode->i_ino,
|
|
||||||
(unsigned long long) pos, len, flags);
|
|
||||||
retry:
|
retry:
|
||||||
/*
|
/*
|
||||||
* With delayed allocation, we don't log the i_disksize update
|
* With delayed allocation, we don't log the i_disksize update
|
||||||
|
@ -2959,7 +2921,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
|
||||||
* when write to the end of file but not require block allocation
|
* when write to the end of file but not require block allocation
|
||||||
*/
|
*/
|
||||||
static int ext4_da_should_update_i_disksize(struct page *page,
|
static int ext4_da_should_update_i_disksize(struct page *page,
|
||||||
unsigned long offset)
|
unsigned long offset)
|
||||||
{
|
{
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
struct inode *inode = page->mapping->host;
|
struct inode *inode = page->mapping->host;
|
||||||
|
@ -2978,9 +2940,9 @@ static int ext4_da_should_update_i_disksize(struct page *page,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ext4_da_write_end(struct file *file,
|
static int ext4_da_write_end(struct file *file,
|
||||||
struct address_space *mapping,
|
struct address_space *mapping,
|
||||||
loff_t pos, unsigned len, unsigned copied,
|
loff_t pos, unsigned len, unsigned copied,
|
||||||
struct page *page, void *fsdata)
|
struct page *page, void *fsdata)
|
||||||
{
|
{
|
||||||
struct inode *inode = mapping->host;
|
struct inode *inode = mapping->host;
|
||||||
int ret = 0, ret2;
|
int ret = 0, ret2;
|
||||||
|
@ -3001,10 +2963,7 @@ static int ext4_da_write_end(struct file *file,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trace_mark(ext4_da_write_end,
|
trace_ext4_da_write_end(inode, pos, len, copied);
|
||||||
"dev %s ino %lu pos %llu len %u copied %u",
|
|
||||||
inode->i_sb->s_id, inode->i_ino,
|
|
||||||
(unsigned long long) pos, len, copied);
|
|
||||||
start = pos & (PAGE_CACHE_SIZE - 1);
|
start = pos & (PAGE_CACHE_SIZE - 1);
|
||||||
end = start + copied - 1;
|
end = start + copied - 1;
|
||||||
|
|
||||||
|
@ -3237,7 +3196,7 @@ static int bput_one(handle_t *handle, struct buffer_head *bh)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int __ext4_normal_writepage(struct page *page,
|
static int __ext4_normal_writepage(struct page *page,
|
||||||
struct writeback_control *wbc)
|
struct writeback_control *wbc)
|
||||||
{
|
{
|
||||||
struct inode *inode = page->mapping->host;
|
struct inode *inode = page->mapping->host;
|
||||||
|
|
||||||
|
@ -3249,15 +3208,13 @@ static int __ext4_normal_writepage(struct page *page,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ext4_normal_writepage(struct page *page,
|
static int ext4_normal_writepage(struct page *page,
|
||||||
struct writeback_control *wbc)
|
struct writeback_control *wbc)
|
||||||
{
|
{
|
||||||
struct inode *inode = page->mapping->host;
|
struct inode *inode = page->mapping->host;
|
||||||
loff_t size = i_size_read(inode);
|
loff_t size = i_size_read(inode);
|
||||||
loff_t len;
|
loff_t len;
|
||||||
|
|
||||||
trace_mark(ext4_normal_writepage,
|
trace_ext4_normal_writepage(inode, page);
|
||||||
"dev %s ino %lu page_index %lu",
|
|
||||||
inode->i_sb->s_id, inode->i_ino, page->index);
|
|
||||||
J_ASSERT(PageLocked(page));
|
J_ASSERT(PageLocked(page));
|
||||||
if (page->index == size >> PAGE_CACHE_SHIFT)
|
if (page->index == size >> PAGE_CACHE_SHIFT)
|
||||||
len = size & ~PAGE_CACHE_MASK;
|
len = size & ~PAGE_CACHE_MASK;
|
||||||
|
@ -3287,7 +3244,7 @@ static int ext4_normal_writepage(struct page *page,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __ext4_journalled_writepage(struct page *page,
|
static int __ext4_journalled_writepage(struct page *page,
|
||||||
struct writeback_control *wbc)
|
struct writeback_control *wbc)
|
||||||
{
|
{
|
||||||
struct address_space *mapping = page->mapping;
|
struct address_space *mapping = page->mapping;
|
||||||
struct inode *inode = mapping->host;
|
struct inode *inode = mapping->host;
|
||||||
|
@ -3337,15 +3294,13 @@ static int __ext4_journalled_writepage(struct page *page,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ext4_journalled_writepage(struct page *page,
|
static int ext4_journalled_writepage(struct page *page,
|
||||||
struct writeback_control *wbc)
|
struct writeback_control *wbc)
|
||||||
{
|
{
|
||||||
struct inode *inode = page->mapping->host;
|
struct inode *inode = page->mapping->host;
|
||||||
loff_t size = i_size_read(inode);
|
loff_t size = i_size_read(inode);
|
||||||
loff_t len;
|
loff_t len;
|
||||||
|
|
||||||
trace_mark(ext4_journalled_writepage,
|
trace_ext4_journalled_writepage(inode, page);
|
||||||
"dev %s ino %lu page_index %lu",
|
|
||||||
inode->i_sb->s_id, inode->i_ino, page->index);
|
|
||||||
J_ASSERT(PageLocked(page));
|
J_ASSERT(PageLocked(page));
|
||||||
if (page->index == size >> PAGE_CACHE_SHIFT)
|
if (page->index == size >> PAGE_CACHE_SHIFT)
|
||||||
len = size & ~PAGE_CACHE_MASK;
|
len = size & ~PAGE_CACHE_MASK;
|
||||||
|
@ -3442,8 +3397,8 @@ static int ext4_releasepage(struct page *page, gfp_t wait)
|
||||||
* VFS code falls back into buffered path in that case so we are safe.
|
* VFS code falls back into buffered path in that case so we are safe.
|
||||||
*/
|
*/
|
||||||
static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb,
|
static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb,
|
||||||
const struct iovec *iov, loff_t offset,
|
const struct iovec *iov, loff_t offset,
|
||||||
unsigned long nr_segs)
|
unsigned long nr_segs)
|
||||||
{
|
{
|
||||||
struct file *file = iocb->ki_filp;
|
struct file *file = iocb->ki_filp;
|
||||||
struct inode *inode = file->f_mapping->host;
|
struct inode *inode = file->f_mapping->host;
|
||||||
|
@ -3763,7 +3718,8 @@ static inline int all_zeroes(__le32 *p, __le32 *q)
|
||||||
* (no partially truncated stuff there). */
|
* (no partially truncated stuff there). */
|
||||||
|
|
||||||
static Indirect *ext4_find_shared(struct inode *inode, int depth,
|
static Indirect *ext4_find_shared(struct inode *inode, int depth,
|
||||||
ext4_lblk_t offsets[4], Indirect chain[4], __le32 *top)
|
ext4_lblk_t offsets[4], Indirect chain[4],
|
||||||
|
__le32 *top)
|
||||||
{
|
{
|
||||||
Indirect *partial, *p;
|
Indirect *partial, *p;
|
||||||
int k, err;
|
int k, err;
|
||||||
|
@ -3819,8 +3775,10 @@ static Indirect *ext4_find_shared(struct inode *inode, int depth,
|
||||||
* than `count' because there can be holes in there.
|
* than `count' because there can be holes in there.
|
||||||
*/
|
*/
|
||||||
static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
|
static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
|
||||||
struct buffer_head *bh, ext4_fsblk_t block_to_free,
|
struct buffer_head *bh,
|
||||||
unsigned long count, __le32 *first, __le32 *last)
|
ext4_fsblk_t block_to_free,
|
||||||
|
unsigned long count, __le32 *first,
|
||||||
|
__le32 *last)
|
||||||
{
|
{
|
||||||
__le32 *p;
|
__le32 *p;
|
||||||
if (try_to_extend_transaction(handle, inode)) {
|
if (try_to_extend_transaction(handle, inode)) {
|
||||||
|
@ -3837,10 +3795,11 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Any buffers which are on the journal will be in memory. We find
|
* Any buffers which are on the journal will be in memory. We
|
||||||
* them on the hash table so jbd2_journal_revoke() will run jbd2_journal_forget()
|
* find them on the hash table so jbd2_journal_revoke() will
|
||||||
* on them. We've already detached each block from the file, so
|
* run jbd2_journal_forget() on them. We've already detached
|
||||||
* bforget() in jbd2_journal_forget() should be safe.
|
* each block from the file, so bforget() in
|
||||||
|
* jbd2_journal_forget() should be safe.
|
||||||
*
|
*
|
||||||
* AKPM: turn on bforget in jbd2_journal_forget()!!!
|
* AKPM: turn on bforget in jbd2_journal_forget()!!!
|
||||||
*/
|
*/
|
||||||
|
@ -4212,7 +4171,7 @@ void ext4_truncate(struct inode *inode)
|
||||||
(__le32*)partial->bh->b_data+addr_per_block,
|
(__le32*)partial->bh->b_data+addr_per_block,
|
||||||
(chain+n-1) - partial);
|
(chain+n-1) - partial);
|
||||||
BUFFER_TRACE(partial->bh, "call brelse");
|
BUFFER_TRACE(partial->bh, "call brelse");
|
||||||
brelse (partial->bh);
|
brelse(partial->bh);
|
||||||
partial--;
|
partial--;
|
||||||
}
|
}
|
||||||
do_indirects:
|
do_indirects:
|
||||||
|
@ -4453,8 +4412,9 @@ void ext4_get_inode_flags(struct ext4_inode_info *ei)
|
||||||
if (flags & S_DIRSYNC)
|
if (flags & S_DIRSYNC)
|
||||||
ei->i_flags |= EXT4_DIRSYNC_FL;
|
ei->i_flags |= EXT4_DIRSYNC_FL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode,
|
static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode,
|
||||||
struct ext4_inode_info *ei)
|
struct ext4_inode_info *ei)
|
||||||
{
|
{
|
||||||
blkcnt_t i_blocks ;
|
blkcnt_t i_blocks ;
|
||||||
struct inode *inode = &(ei->vfs_inode);
|
struct inode *inode = &(ei->vfs_inode);
|
||||||
|
@ -4569,7 +4529,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
|
||||||
EXT4_GOOD_OLD_INODE_SIZE +
|
EXT4_GOOD_OLD_INODE_SIZE +
|
||||||
ei->i_extra_isize;
|
ei->i_extra_isize;
|
||||||
if (*magic == cpu_to_le32(EXT4_XATTR_MAGIC))
|
if (*magic == cpu_to_le32(EXT4_XATTR_MAGIC))
|
||||||
ei->i_state |= EXT4_STATE_XATTR;
|
ei->i_state |= EXT4_STATE_XATTR;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
ei->i_extra_isize = 0;
|
ei->i_extra_isize = 0;
|
||||||
|
@ -4603,15 +4563,15 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
|
||||||
!ext4_inode_is_fast_symlink(inode)))
|
!ext4_inode_is_fast_symlink(inode)))
|
||||||
/* Validate extent which is part of inode */
|
/* Validate extent which is part of inode */
|
||||||
ret = ext4_ext_check_inode(inode);
|
ret = ext4_ext_check_inode(inode);
|
||||||
} else if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
|
} else if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
|
||||||
(S_ISLNK(inode->i_mode) &&
|
(S_ISLNK(inode->i_mode) &&
|
||||||
!ext4_inode_is_fast_symlink(inode))) {
|
!ext4_inode_is_fast_symlink(inode))) {
|
||||||
/* Validate block references which are part of inode */
|
/* Validate block references which are part of inode */
|
||||||
ret = ext4_check_inode_blockref(inode);
|
ret = ext4_check_inode_blockref(inode);
|
||||||
}
|
}
|
||||||
if (ret) {
|
if (ret) {
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
goto bad_inode;
|
goto bad_inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (S_ISREG(inode->i_mode)) {
|
if (S_ISREG(inode->i_mode)) {
|
||||||
|
@ -4795,8 +4755,9 @@ static int ext4_do_update_inode(handle_t *handle,
|
||||||
cpu_to_le32(new_encode_dev(inode->i_rdev));
|
cpu_to_le32(new_encode_dev(inode->i_rdev));
|
||||||
raw_inode->i_block[2] = 0;
|
raw_inode->i_block[2] = 0;
|
||||||
}
|
}
|
||||||
} else for (block = 0; block < EXT4_N_BLOCKS; block++)
|
} else
|
||||||
raw_inode->i_block[block] = ei->i_data[block];
|
for (block = 0; block < EXT4_N_BLOCKS; block++)
|
||||||
|
raw_inode->i_block[block] = ei->i_data[block];
|
||||||
|
|
||||||
raw_inode->i_disk_version = cpu_to_le32(inode->i_version);
|
raw_inode->i_disk_version = cpu_to_le32(inode->i_version);
|
||||||
if (ei->i_extra_isize) {
|
if (ei->i_extra_isize) {
|
||||||
|
@ -5150,7 +5111,7 @@ int ext4_chunk_trans_blocks(struct inode *inode, int nrblocks)
|
||||||
* Give this, we know that the caller already has write access to iloc->bh.
|
* Give this, we know that the caller already has write access to iloc->bh.
|
||||||
*/
|
*/
|
||||||
int ext4_mark_iloc_dirty(handle_t *handle,
|
int ext4_mark_iloc_dirty(handle_t *handle,
|
||||||
struct inode *inode, struct ext4_iloc *iloc)
|
struct inode *inode, struct ext4_iloc *iloc)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <linux/compat.h>
|
#include <linux/compat.h>
|
||||||
#include <linux/smp_lock.h>
|
#include <linux/smp_lock.h>
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
|
#include <linux/file.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include "ext4_jbd2.h"
|
#include "ext4_jbd2.h"
|
||||||
#include "ext4.h"
|
#include "ext4.h"
|
||||||
|
@ -213,6 +214,41 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case EXT4_IOC_MOVE_EXT: {
|
||||||
|
struct move_extent me;
|
||||||
|
struct file *donor_filp;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (copy_from_user(&me,
|
||||||
|
(struct move_extent __user *)arg, sizeof(me)))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
donor_filp = fget(me.donor_fd);
|
||||||
|
if (!donor_filp)
|
||||||
|
return -EBADF;
|
||||||
|
|
||||||
|
if (!capable(CAP_DAC_OVERRIDE)) {
|
||||||
|
if ((current->real_cred->fsuid != inode->i_uid) ||
|
||||||
|
!(inode->i_mode & S_IRUSR) ||
|
||||||
|
!(donor_filp->f_dentry->d_inode->i_mode &
|
||||||
|
S_IRUSR)) {
|
||||||
|
fput(donor_filp);
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ext4_move_extents(filp, donor_filp, me.orig_start,
|
||||||
|
me.donor_start, me.len, &me.moved_len);
|
||||||
|
fput(donor_filp);
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
if (copy_to_user((struct move_extent *)arg,
|
||||||
|
&me, sizeof(me)))
|
||||||
|
return -EFAULT;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
case EXT4_IOC_GROUP_ADD: {
|
case EXT4_IOC_GROUP_ADD: {
|
||||||
struct ext4_new_group_data input;
|
struct ext4_new_group_data input;
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mballoc.h"
|
#include "mballoc.h"
|
||||||
|
#include <trace/events/ext4.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MUSTDO:
|
* MUSTDO:
|
||||||
* - test ext4_ext_search_left() and ext4_ext_search_right()
|
* - test ext4_ext_search_left() and ext4_ext_search_right()
|
||||||
|
@ -340,8 +342,6 @@ static void ext4_mb_generate_from_freelist(struct super_block *sb, void *bitmap,
|
||||||
ext4_group_t group);
|
ext4_group_t group);
|
||||||
static void release_blocks_on_commit(journal_t *journal, transaction_t *txn);
|
static void release_blocks_on_commit(journal_t *journal, transaction_t *txn);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static inline void *mb_correct_addr_and_bit(int *bit, void *addr)
|
static inline void *mb_correct_addr_and_bit(int *bit, void *addr)
|
||||||
{
|
{
|
||||||
#if BITS_PER_LONG == 64
|
#if BITS_PER_LONG == 64
|
||||||
|
@ -2859,9 +2859,8 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
|
||||||
discard_block = (ext4_fsblk_t) entry->group * EXT4_BLOCKS_PER_GROUP(sb)
|
discard_block = (ext4_fsblk_t) entry->group * EXT4_BLOCKS_PER_GROUP(sb)
|
||||||
+ entry->start_blk
|
+ entry->start_blk
|
||||||
+ le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
|
+ le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
|
||||||
trace_mark(ext4_discard_blocks, "dev %s blk %llu count %u",
|
trace_ext4_discard_blocks(sb, (unsigned long long)discard_block,
|
||||||
sb->s_id, (unsigned long long) discard_block,
|
entry->count);
|
||||||
entry->count);
|
|
||||||
sb_issue_discard(sb, discard_block, entry->count);
|
sb_issue_discard(sb, discard_block, entry->count);
|
||||||
|
|
||||||
kmem_cache_free(ext4_free_ext_cachep, entry);
|
kmem_cache_free(ext4_free_ext_cachep, entry);
|
||||||
|
@ -3629,10 +3628,7 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
|
||||||
|
|
||||||
mb_debug("new inode pa %p: %llu/%u for %u\n", pa,
|
mb_debug("new inode pa %p: %llu/%u for %u\n", pa,
|
||||||
pa->pa_pstart, pa->pa_len, pa->pa_lstart);
|
pa->pa_pstart, pa->pa_len, pa->pa_lstart);
|
||||||
trace_mark(ext4_mb_new_inode_pa,
|
trace_ext4_mb_new_inode_pa(ac, pa);
|
||||||
"dev %s ino %lu pstart %llu len %u lstart %u",
|
|
||||||
sb->s_id, ac->ac_inode->i_ino,
|
|
||||||
pa->pa_pstart, pa->pa_len, pa->pa_lstart);
|
|
||||||
|
|
||||||
ext4_mb_use_inode_pa(ac, pa);
|
ext4_mb_use_inode_pa(ac, pa);
|
||||||
atomic_add(pa->pa_free, &EXT4_SB(sb)->s_mb_preallocated);
|
atomic_add(pa->pa_free, &EXT4_SB(sb)->s_mb_preallocated);
|
||||||
|
@ -3691,9 +3687,8 @@ ext4_mb_new_group_pa(struct ext4_allocation_context *ac)
|
||||||
pa->pa_type = MB_GROUP_PA;
|
pa->pa_type = MB_GROUP_PA;
|
||||||
|
|
||||||
mb_debug("new group pa %p: %llu/%u for %u\n", pa,
|
mb_debug("new group pa %p: %llu/%u for %u\n", pa,
|
||||||
pa->pa_pstart, pa->pa_len, pa->pa_lstart);
|
pa->pa_pstart, pa->pa_len, pa->pa_lstart);
|
||||||
trace_mark(ext4_mb_new_group_pa, "dev %s pstart %llu len %u lstart %u",
|
trace_ext4_mb_new_group_pa(ac, pa);
|
||||||
sb->s_id, pa->pa_pstart, pa->pa_len, pa->pa_lstart);
|
|
||||||
|
|
||||||
ext4_mb_use_group_pa(ac, pa);
|
ext4_mb_use_group_pa(ac, pa);
|
||||||
atomic_add(pa->pa_free, &EXT4_SB(sb)->s_mb_preallocated);
|
atomic_add(pa->pa_free, &EXT4_SB(sb)->s_mb_preallocated);
|
||||||
|
@ -3783,10 +3778,8 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
|
||||||
ext4_mb_store_history(ac);
|
ext4_mb_store_history(ac);
|
||||||
}
|
}
|
||||||
|
|
||||||
trace_mark(ext4_mb_release_inode_pa,
|
trace_ext4_mb_release_inode_pa(ac, pa, grp_blk_start + bit,
|
||||||
"dev %s ino %lu block %llu count %u",
|
next - bit);
|
||||||
sb->s_id, pa->pa_inode->i_ino, grp_blk_start + bit,
|
|
||||||
next - bit);
|
|
||||||
mb_free_blocks(pa->pa_inode, e4b, bit, next - bit);
|
mb_free_blocks(pa->pa_inode, e4b, bit, next - bit);
|
||||||
bit = next + 1;
|
bit = next + 1;
|
||||||
}
|
}
|
||||||
|
@ -3820,8 +3813,7 @@ ext4_mb_release_group_pa(struct ext4_buddy *e4b,
|
||||||
if (ac)
|
if (ac)
|
||||||
ac->ac_op = EXT4_MB_HISTORY_DISCARD;
|
ac->ac_op = EXT4_MB_HISTORY_DISCARD;
|
||||||
|
|
||||||
trace_mark(ext4_mb_release_group_pa, "dev %s pstart %llu len %d",
|
trace_ext4_mb_release_group_pa(ac, pa);
|
||||||
sb->s_id, pa->pa_pstart, pa->pa_len);
|
|
||||||
BUG_ON(pa->pa_deleted == 0);
|
BUG_ON(pa->pa_deleted == 0);
|
||||||
ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit);
|
ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit);
|
||||||
BUG_ON(group != e4b->bd_group && pa->pa_len != 0);
|
BUG_ON(group != e4b->bd_group && pa->pa_len != 0);
|
||||||
|
@ -3889,6 +3881,8 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
|
||||||
|
|
||||||
INIT_LIST_HEAD(&list);
|
INIT_LIST_HEAD(&list);
|
||||||
ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
|
ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
|
||||||
|
if (ac)
|
||||||
|
ac->ac_sb = sb;
|
||||||
repeat:
|
repeat:
|
||||||
ext4_lock_group(sb, group);
|
ext4_lock_group(sb, group);
|
||||||
list_for_each_entry_safe(pa, tmp,
|
list_for_each_entry_safe(pa, tmp,
|
||||||
|
@ -3987,12 +3981,15 @@ void ext4_discard_preallocations(struct inode *inode)
|
||||||
}
|
}
|
||||||
|
|
||||||
mb_debug("discard preallocation for inode %lu\n", inode->i_ino);
|
mb_debug("discard preallocation for inode %lu\n", inode->i_ino);
|
||||||
trace_mark(ext4_discard_preallocations, "dev %s ino %lu", sb->s_id,
|
trace_ext4_discard_preallocations(inode);
|
||||||
inode->i_ino);
|
|
||||||
|
|
||||||
INIT_LIST_HEAD(&list);
|
INIT_LIST_HEAD(&list);
|
||||||
|
|
||||||
ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
|
ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
|
||||||
|
if (ac) {
|
||||||
|
ac->ac_sb = sb;
|
||||||
|
ac->ac_inode = inode;
|
||||||
|
}
|
||||||
repeat:
|
repeat:
|
||||||
/* first, collect all pa's in the inode */
|
/* first, collect all pa's in the inode */
|
||||||
spin_lock(&ei->i_prealloc_lock);
|
spin_lock(&ei->i_prealloc_lock);
|
||||||
|
@ -4276,6 +4273,8 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb,
|
||||||
|
|
||||||
INIT_LIST_HEAD(&discard_list);
|
INIT_LIST_HEAD(&discard_list);
|
||||||
ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
|
ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
|
||||||
|
if (ac)
|
||||||
|
ac->ac_sb = sb;
|
||||||
|
|
||||||
spin_lock(&lg->lg_prealloc_lock);
|
spin_lock(&lg->lg_prealloc_lock);
|
||||||
list_for_each_entry_rcu(pa, &lg->lg_prealloc_list[order],
|
list_for_each_entry_rcu(pa, &lg->lg_prealloc_list[order],
|
||||||
|
@ -4445,8 +4444,7 @@ static int ext4_mb_discard_preallocations(struct super_block *sb, int needed)
|
||||||
int ret;
|
int ret;
|
||||||
int freed = 0;
|
int freed = 0;
|
||||||
|
|
||||||
trace_mark(ext4_mb_discard_preallocations, "dev %s needed %d",
|
trace_ext4_mb_discard_preallocations(sb, needed);
|
||||||
sb->s_id, needed);
|
|
||||||
for (i = 0; i < ngroups && needed > 0; i++) {
|
for (i = 0; i < ngroups && needed > 0; i++) {
|
||||||
ret = ext4_mb_discard_group_preallocations(sb, i, needed);
|
ret = ext4_mb_discard_group_preallocations(sb, i, needed);
|
||||||
freed += ret;
|
freed += ret;
|
||||||
|
@ -4475,17 +4473,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
|
||||||
sb = ar->inode->i_sb;
|
sb = ar->inode->i_sb;
|
||||||
sbi = EXT4_SB(sb);
|
sbi = EXT4_SB(sb);
|
||||||
|
|
||||||
trace_mark(ext4_request_blocks, "dev %s flags %u len %u ino %lu "
|
trace_ext4_request_blocks(ar);
|
||||||
"lblk %llu goal %llu lleft %llu lright %llu "
|
|
||||||
"pleft %llu pright %llu ",
|
|
||||||
sb->s_id, ar->flags, ar->len,
|
|
||||||
ar->inode ? ar->inode->i_ino : 0,
|
|
||||||
(unsigned long long) ar->logical,
|
|
||||||
(unsigned long long) ar->goal,
|
|
||||||
(unsigned long long) ar->lleft,
|
|
||||||
(unsigned long long) ar->lright,
|
|
||||||
(unsigned long long) ar->pleft,
|
|
||||||
(unsigned long long) ar->pright);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For delayed allocation, we could skip the ENOSPC and
|
* For delayed allocation, we could skip the ENOSPC and
|
||||||
|
@ -4521,7 +4509,10 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
|
||||||
}
|
}
|
||||||
|
|
||||||
ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
|
ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
|
||||||
if (!ac) {
|
if (ac) {
|
||||||
|
ac->ac_sb = sb;
|
||||||
|
ac->ac_inode = ar->inode;
|
||||||
|
} else {
|
||||||
ar->len = 0;
|
ar->len = 0;
|
||||||
*errp = -ENOMEM;
|
*errp = -ENOMEM;
|
||||||
goto out1;
|
goto out1;
|
||||||
|
@ -4594,18 +4585,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
|
||||||
reserv_blks);
|
reserv_blks);
|
||||||
}
|
}
|
||||||
|
|
||||||
trace_mark(ext4_allocate_blocks,
|
trace_ext4_allocate_blocks(ar, (unsigned long long)block);
|
||||||
"dev %s block %llu flags %u len %u ino %lu "
|
|
||||||
"logical %llu goal %llu lleft %llu lright %llu "
|
|
||||||
"pleft %llu pright %llu ",
|
|
||||||
sb->s_id, (unsigned long long) block,
|
|
||||||
ar->flags, ar->len, ar->inode ? ar->inode->i_ino : 0,
|
|
||||||
(unsigned long long) ar->logical,
|
|
||||||
(unsigned long long) ar->goal,
|
|
||||||
(unsigned long long) ar->lleft,
|
|
||||||
(unsigned long long) ar->lright,
|
|
||||||
(unsigned long long) ar->pleft,
|
|
||||||
(unsigned long long) ar->pright);
|
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
@ -4709,7 +4689,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
|
||||||
* Main entry point into mballoc to free blocks
|
* Main entry point into mballoc to free blocks
|
||||||
*/
|
*/
|
||||||
void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
|
void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
|
||||||
unsigned long block, unsigned long count,
|
ext4_fsblk_t block, unsigned long count,
|
||||||
int metadata, unsigned long *freed)
|
int metadata, unsigned long *freed)
|
||||||
{
|
{
|
||||||
struct buffer_head *bitmap_bh = NULL;
|
struct buffer_head *bitmap_bh = NULL;
|
||||||
|
@ -4735,15 +4715,12 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
|
||||||
block + count > ext4_blocks_count(es)) {
|
block + count > ext4_blocks_count(es)) {
|
||||||
ext4_error(sb, __func__,
|
ext4_error(sb, __func__,
|
||||||
"Freeing blocks not in datazone - "
|
"Freeing blocks not in datazone - "
|
||||||
"block = %lu, count = %lu", block, count);
|
"block = %llu, count = %lu", block, count);
|
||||||
goto error_return;
|
goto error_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ext4_debug("freeing block %lu\n", block);
|
ext4_debug("freeing block %llu\n", block);
|
||||||
trace_mark(ext4_free_blocks,
|
trace_ext4_free_blocks(inode, block, count, metadata);
|
||||||
"dev %s block %llu count %lu metadata %d ino %lu",
|
|
||||||
sb->s_id, (unsigned long long) block, count, metadata,
|
|
||||||
inode ? inode->i_ino : 0);
|
|
||||||
|
|
||||||
ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
|
ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
|
||||||
if (ac) {
|
if (ac) {
|
||||||
|
@ -4784,7 +4761,7 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
|
||||||
|
|
||||||
ext4_error(sb, __func__,
|
ext4_error(sb, __func__,
|
||||||
"Freeing blocks in system zone - "
|
"Freeing blocks in system zone - "
|
||||||
"Block = %lu, count = %lu", block, count);
|
"Block = %llu, count = %lu", block, count);
|
||||||
/* err = 0. ext4_std_error should be a no op */
|
/* err = 0. ext4_std_error should be a no op */
|
||||||
goto error_return;
|
goto error_return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
#include <linux/blkdev.h>
|
#include <linux/blkdev.h>
|
||||||
#include <linux/marker.h>
|
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include "ext4_jbd2.h"
|
#include "ext4_jbd2.h"
|
||||||
#include "ext4.h"
|
#include "ext4.h"
|
||||||
|
|
|
@ -458,6 +458,7 @@ int ext4_ext_migrate(struct inode *inode)
|
||||||
struct inode *tmp_inode = NULL;
|
struct inode *tmp_inode = NULL;
|
||||||
struct list_blocks_struct lb;
|
struct list_blocks_struct lb;
|
||||||
unsigned long max_entries;
|
unsigned long max_entries;
|
||||||
|
__u32 goal;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the filesystem does not support extents, or the inode
|
* If the filesystem does not support extents, or the inode
|
||||||
|
@ -483,9 +484,10 @@ int ext4_ext_migrate(struct inode *inode)
|
||||||
retval = PTR_ERR(handle);
|
retval = PTR_ERR(handle);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
tmp_inode = ext4_new_inode(handle,
|
goal = (((inode->i_ino - 1) / EXT4_INODES_PER_GROUP(inode->i_sb)) *
|
||||||
inode->i_sb->s_root->d_inode,
|
EXT4_INODES_PER_GROUP(inode->i_sb)) + 1;
|
||||||
S_IFREG);
|
tmp_inode = ext4_new_inode(handle, inode->i_sb->s_root->d_inode,
|
||||||
|
S_IFREG, 0, goal);
|
||||||
if (IS_ERR(tmp_inode)) {
|
if (IS_ERR(tmp_inode)) {
|
||||||
retval = -ENOMEM;
|
retval = -ENOMEM;
|
||||||
ext4_journal_stop(handle);
|
ext4_journal_stop(handle);
|
||||||
|
|
1320
fs/ext4/move_extent.c
Normal file
1320
fs/ext4/move_extent.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1782,7 +1782,7 @@ static int ext4_create(struct inode *dir, struct dentry *dentry, int mode,
|
||||||
if (IS_DIRSYNC(dir))
|
if (IS_DIRSYNC(dir))
|
||||||
ext4_handle_sync(handle);
|
ext4_handle_sync(handle);
|
||||||
|
|
||||||
inode = ext4_new_inode (handle, dir, mode);
|
inode = ext4_new_inode(handle, dir, mode, &dentry->d_name, 0);
|
||||||
err = PTR_ERR(inode);
|
err = PTR_ERR(inode);
|
||||||
if (!IS_ERR(inode)) {
|
if (!IS_ERR(inode)) {
|
||||||
inode->i_op = &ext4_file_inode_operations;
|
inode->i_op = &ext4_file_inode_operations;
|
||||||
|
@ -1816,7 +1816,7 @@ static int ext4_mknod(struct inode *dir, struct dentry *dentry,
|
||||||
if (IS_DIRSYNC(dir))
|
if (IS_DIRSYNC(dir))
|
||||||
ext4_handle_sync(handle);
|
ext4_handle_sync(handle);
|
||||||
|
|
||||||
inode = ext4_new_inode(handle, dir, mode);
|
inode = ext4_new_inode(handle, dir, mode, &dentry->d_name, 0);
|
||||||
err = PTR_ERR(inode);
|
err = PTR_ERR(inode);
|
||||||
if (!IS_ERR(inode)) {
|
if (!IS_ERR(inode)) {
|
||||||
init_special_inode(inode, inode->i_mode, rdev);
|
init_special_inode(inode, inode->i_mode, rdev);
|
||||||
|
@ -1853,7 +1853,8 @@ static int ext4_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
||||||
if (IS_DIRSYNC(dir))
|
if (IS_DIRSYNC(dir))
|
||||||
ext4_handle_sync(handle);
|
ext4_handle_sync(handle);
|
||||||
|
|
||||||
inode = ext4_new_inode(handle, dir, S_IFDIR | mode);
|
inode = ext4_new_inode(handle, dir, S_IFDIR | mode,
|
||||||
|
&dentry->d_name, 0);
|
||||||
err = PTR_ERR(inode);
|
err = PTR_ERR(inode);
|
||||||
if (IS_ERR(inode))
|
if (IS_ERR(inode))
|
||||||
goto out_stop;
|
goto out_stop;
|
||||||
|
@ -2264,7 +2265,8 @@ static int ext4_symlink(struct inode *dir,
|
||||||
if (IS_DIRSYNC(dir))
|
if (IS_DIRSYNC(dir))
|
||||||
ext4_handle_sync(handle);
|
ext4_handle_sync(handle);
|
||||||
|
|
||||||
inode = ext4_new_inode(handle, dir, S_IFLNK|S_IRWXUGO);
|
inode = ext4_new_inode(handle, dir, S_IFLNK|S_IRWXUGO,
|
||||||
|
&dentry->d_name, 0);
|
||||||
err = PTR_ERR(inode);
|
err = PTR_ERR(inode);
|
||||||
if (IS_ERR(inode))
|
if (IS_ERR(inode))
|
||||||
goto out_stop;
|
goto out_stop;
|
||||||
|
|
|
@ -37,7 +37,6 @@
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
#include <linux/ctype.h>
|
#include <linux/ctype.h>
|
||||||
#include <linux/marker.h>
|
|
||||||
#include <linux/log2.h>
|
#include <linux/log2.h>
|
||||||
#include <linux/crc16.h>
|
#include <linux/crc16.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
@ -47,6 +46,9 @@
|
||||||
#include "xattr.h"
|
#include "xattr.h"
|
||||||
#include "acl.h"
|
#include "acl.h"
|
||||||
|
|
||||||
|
#define CREATE_TRACE_POINTS
|
||||||
|
#include <trace/events/ext4.h>
|
||||||
|
|
||||||
static int default_mb_history_length = 1000;
|
static int default_mb_history_length = 1000;
|
||||||
|
|
||||||
module_param_named(default_mb_history_length, default_mb_history_length,
|
module_param_named(default_mb_history_length, default_mb_history_length,
|
||||||
|
@ -301,7 +303,7 @@ static void ext4_handle_error(struct super_block *sb)
|
||||||
if (!test_opt(sb, ERRORS_CONT)) {
|
if (!test_opt(sb, ERRORS_CONT)) {
|
||||||
journal_t *journal = EXT4_SB(sb)->s_journal;
|
journal_t *journal = EXT4_SB(sb)->s_journal;
|
||||||
|
|
||||||
EXT4_SB(sb)->s_mount_opt |= EXT4_MOUNT_ABORT;
|
EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED;
|
||||||
if (journal)
|
if (journal)
|
||||||
jbd2_journal_abort(journal, -EIO);
|
jbd2_journal_abort(journal, -EIO);
|
||||||
}
|
}
|
||||||
|
@ -414,7 +416,7 @@ void ext4_abort(struct super_block *sb, const char *function,
|
||||||
ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
|
ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
|
||||||
EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
|
EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
|
||||||
sb->s_flags |= MS_RDONLY;
|
sb->s_flags |= MS_RDONLY;
|
||||||
EXT4_SB(sb)->s_mount_opt |= EXT4_MOUNT_ABORT;
|
EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED;
|
||||||
if (EXT4_SB(sb)->s_journal)
|
if (EXT4_SB(sb)->s_journal)
|
||||||
jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
|
jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
|
||||||
}
|
}
|
||||||
|
@ -1474,7 +1476,7 @@ static int parse_options(char *options, struct super_block *sb,
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case Opt_abort:
|
case Opt_abort:
|
||||||
set_opt(sbi->s_mount_opt, ABORT);
|
sbi->s_mount_flags |= EXT4_MF_FS_ABORTED;
|
||||||
break;
|
break;
|
||||||
case Opt_nobarrier:
|
case Opt_nobarrier:
|
||||||
clear_opt(sbi->s_mount_opt, BARRIER);
|
clear_opt(sbi->s_mount_opt, BARRIER);
|
||||||
|
@ -1653,7 +1655,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
|
||||||
ext4_commit_super(sb, 1);
|
ext4_commit_super(sb, 1);
|
||||||
if (test_opt(sb, DEBUG))
|
if (test_opt(sb, DEBUG))
|
||||||
printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%u, "
|
printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%u, "
|
||||||
"bpg=%lu, ipg=%lu, mo=%04lx]\n",
|
"bpg=%lu, ipg=%lu, mo=%04x]\n",
|
||||||
sb->s_blocksize,
|
sb->s_blocksize,
|
||||||
sbi->s_groups_count,
|
sbi->s_groups_count,
|
||||||
EXT4_BLOCKS_PER_GROUP(sb),
|
EXT4_BLOCKS_PER_GROUP(sb),
|
||||||
|
@ -2204,6 +2206,7 @@ EXT4_RO_ATTR(session_write_kbytes);
|
||||||
EXT4_RO_ATTR(lifetime_write_kbytes);
|
EXT4_RO_ATTR(lifetime_write_kbytes);
|
||||||
EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show,
|
EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show,
|
||||||
inode_readahead_blks_store, s_inode_readahead_blks);
|
inode_readahead_blks_store, s_inode_readahead_blks);
|
||||||
|
EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
|
||||||
EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats);
|
EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats);
|
||||||
EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan);
|
EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan);
|
||||||
EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan);
|
EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan);
|
||||||
|
@ -2216,6 +2219,7 @@ static struct attribute *ext4_attrs[] = {
|
||||||
ATTR_LIST(session_write_kbytes),
|
ATTR_LIST(session_write_kbytes),
|
||||||
ATTR_LIST(lifetime_write_kbytes),
|
ATTR_LIST(lifetime_write_kbytes),
|
||||||
ATTR_LIST(inode_readahead_blks),
|
ATTR_LIST(inode_readahead_blks),
|
||||||
|
ATTR_LIST(inode_goal),
|
||||||
ATTR_LIST(mb_stats),
|
ATTR_LIST(mb_stats),
|
||||||
ATTR_LIST(mb_max_to_scan),
|
ATTR_LIST(mb_max_to_scan),
|
||||||
ATTR_LIST(mb_min_to_scan),
|
ATTR_LIST(mb_min_to_scan),
|
||||||
|
@ -3346,7 +3350,7 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
tid_t target;
|
tid_t target;
|
||||||
|
|
||||||
trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait);
|
trace_ext4_sync_fs(sb, wait);
|
||||||
if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) {
|
if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) {
|
||||||
if (wait)
|
if (wait)
|
||||||
jbd2_log_wait_commit(EXT4_SB(sb)->s_journal, target);
|
jbd2_log_wait_commit(EXT4_SB(sb)->s_journal, target);
|
||||||
|
@ -3450,7 +3454,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
|
||||||
goto restore_opts;
|
goto restore_opts;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sbi->s_mount_opt & EXT4_MOUNT_ABORT)
|
if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED)
|
||||||
ext4_abort(sb, __func__, "Abort forced by user");
|
ext4_abort(sb, __func__, "Abort forced by user");
|
||||||
|
|
||||||
sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
|
sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
|
||||||
|
@ -3465,7 +3469,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
|
||||||
|
|
||||||
if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY) ||
|
if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY) ||
|
||||||
n_blocks_count > ext4_blocks_count(es)) {
|
n_blocks_count > ext4_blocks_count(es)) {
|
||||||
if (sbi->s_mount_opt & EXT4_MOUNT_ABORT) {
|
if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) {
|
||||||
err = -EROFS;
|
err = -EROFS;
|
||||||
goto restore_opts;
|
goto restore_opts;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
#include <linux/time.h>
|
#include <linux/time.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/jbd2.h>
|
#include <linux/jbd2.h>
|
||||||
#include <linux/marker.h>
|
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <trace/events/jbd2.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unlink a buffer from a transaction checkpoint list.
|
* Unlink a buffer from a transaction checkpoint list.
|
||||||
|
@ -358,8 +358,7 @@ int jbd2_log_do_checkpoint(journal_t *journal)
|
||||||
* journal straight away.
|
* journal straight away.
|
||||||
*/
|
*/
|
||||||
result = jbd2_cleanup_journal_tail(journal);
|
result = jbd2_cleanup_journal_tail(journal);
|
||||||
trace_mark(jbd2_checkpoint, "dev %s need_checkpoint %d",
|
trace_jbd2_checkpoint(journal, result);
|
||||||
journal->j_devname, result);
|
|
||||||
jbd_debug(1, "cleanup_journal_tail returned %d\n", result);
|
jbd_debug(1, "cleanup_journal_tail returned %d\n", result);
|
||||||
if (result <= 0)
|
if (result <= 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
#include <linux/time.h>
|
#include <linux/time.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/jbd2.h>
|
#include <linux/jbd2.h>
|
||||||
#include <linux/marker.h>
|
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
|
@ -26,6 +25,7 @@
|
||||||
#include <linux/writeback.h>
|
#include <linux/writeback.h>
|
||||||
#include <linux/backing-dev.h>
|
#include <linux/backing-dev.h>
|
||||||
#include <linux/bio.h>
|
#include <linux/bio.h>
|
||||||
|
#include <trace/events/jbd2.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Default IO end handler for temporary BJ_IO buffer_heads.
|
* Default IO end handler for temporary BJ_IO buffer_heads.
|
||||||
|
@ -253,6 +253,7 @@ static int journal_submit_data_buffers(journal_t *journal,
|
||||||
* block allocation with delalloc. We need to write
|
* block allocation with delalloc. We need to write
|
||||||
* only allocated blocks here.
|
* only allocated blocks here.
|
||||||
*/
|
*/
|
||||||
|
trace_jbd2_submit_inode_data(jinode->i_vfs_inode);
|
||||||
err = journal_submit_inode_data_buffers(mapping);
|
err = journal_submit_inode_data_buffers(mapping);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = err;
|
ret = err;
|
||||||
|
@ -394,8 +395,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
|
||||||
commit_transaction = journal->j_running_transaction;
|
commit_transaction = journal->j_running_transaction;
|
||||||
J_ASSERT(commit_transaction->t_state == T_RUNNING);
|
J_ASSERT(commit_transaction->t_state == T_RUNNING);
|
||||||
|
|
||||||
trace_mark(jbd2_start_commit, "dev %s transaction %d",
|
trace_jbd2_start_commit(journal, commit_transaction);
|
||||||
journal->j_devname, commit_transaction->t_tid);
|
|
||||||
jbd_debug(1, "JBD: starting commit of transaction %d\n",
|
jbd_debug(1, "JBD: starting commit of transaction %d\n",
|
||||||
commit_transaction->t_tid);
|
commit_transaction->t_tid);
|
||||||
|
|
||||||
|
@ -409,6 +409,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
|
||||||
*/
|
*/
|
||||||
if (commit_transaction->t_synchronous_commit)
|
if (commit_transaction->t_synchronous_commit)
|
||||||
write_op = WRITE_SYNC_PLUG;
|
write_op = WRITE_SYNC_PLUG;
|
||||||
|
trace_jbd2_commit_locking(journal, commit_transaction);
|
||||||
stats.u.run.rs_wait = commit_transaction->t_max_wait;
|
stats.u.run.rs_wait = commit_transaction->t_max_wait;
|
||||||
stats.u.run.rs_locked = jiffies;
|
stats.u.run.rs_locked = jiffies;
|
||||||
stats.u.run.rs_running = jbd2_time_diff(commit_transaction->t_start,
|
stats.u.run.rs_running = jbd2_time_diff(commit_transaction->t_start,
|
||||||
|
@ -484,6 +485,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
|
||||||
*/
|
*/
|
||||||
jbd2_journal_switch_revoke_table(journal);
|
jbd2_journal_switch_revoke_table(journal);
|
||||||
|
|
||||||
|
trace_jbd2_commit_flushing(journal, commit_transaction);
|
||||||
stats.u.run.rs_flushing = jiffies;
|
stats.u.run.rs_flushing = jiffies;
|
||||||
stats.u.run.rs_locked = jbd2_time_diff(stats.u.run.rs_locked,
|
stats.u.run.rs_locked = jbd2_time_diff(stats.u.run.rs_locked,
|
||||||
stats.u.run.rs_flushing);
|
stats.u.run.rs_flushing);
|
||||||
|
@ -520,6 +522,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
|
||||||
commit_transaction->t_state = T_COMMIT;
|
commit_transaction->t_state = T_COMMIT;
|
||||||
spin_unlock(&journal->j_state_lock);
|
spin_unlock(&journal->j_state_lock);
|
||||||
|
|
||||||
|
trace_jbd2_commit_logging(journal, commit_transaction);
|
||||||
stats.u.run.rs_logging = jiffies;
|
stats.u.run.rs_logging = jiffies;
|
||||||
stats.u.run.rs_flushing = jbd2_time_diff(stats.u.run.rs_flushing,
|
stats.u.run.rs_flushing = jbd2_time_diff(stats.u.run.rs_flushing,
|
||||||
stats.u.run.rs_logging);
|
stats.u.run.rs_logging);
|
||||||
|
@ -1054,9 +1057,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
|
||||||
if (journal->j_commit_callback)
|
if (journal->j_commit_callback)
|
||||||
journal->j_commit_callback(journal, commit_transaction);
|
journal->j_commit_callback(journal, commit_transaction);
|
||||||
|
|
||||||
trace_mark(jbd2_end_commit, "dev %s transaction %d head %d",
|
trace_jbd2_end_commit(journal, commit_transaction);
|
||||||
journal->j_devname, commit_transaction->t_tid,
|
|
||||||
journal->j_tail_sequence);
|
|
||||||
jbd_debug(1, "JBD: commit %d complete, head %d\n",
|
jbd_debug(1, "JBD: commit %d complete, head %d\n",
|
||||||
journal->j_commit_sequence, journal->j_tail_sequence);
|
journal->j_commit_sequence, journal->j_tail_sequence);
|
||||||
if (to_free)
|
if (to_free)
|
||||||
|
|
|
@ -38,6 +38,10 @@
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/math64.h>
|
#include <linux/math64.h>
|
||||||
|
#include <linux/hash.h>
|
||||||
|
|
||||||
|
#define CREATE_TRACE_POINTS
|
||||||
|
#include <trace/events/jbd2.h>
|
||||||
|
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
|
@ -2377,6 +2381,71 @@ static void __exit journal_exit(void)
|
||||||
jbd2_journal_destroy_caches();
|
jbd2_journal_destroy_caches();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* jbd2_dev_to_name is a utility function used by the jbd2 and ext4
|
||||||
|
* tracing infrastructure to map a dev_t to a device name.
|
||||||
|
*
|
||||||
|
* The caller should use rcu_read_lock() in order to make sure the
|
||||||
|
* device name stays valid until its done with it. We use
|
||||||
|
* rcu_read_lock() as well to make sure we're safe in case the caller
|
||||||
|
* gets sloppy, and because rcu_read_lock() is cheap and can be safely
|
||||||
|
* nested.
|
||||||
|
*/
|
||||||
|
struct devname_cache {
|
||||||
|
struct rcu_head rcu;
|
||||||
|
dev_t device;
|
||||||
|
char devname[BDEVNAME_SIZE];
|
||||||
|
};
|
||||||
|
#define CACHE_SIZE_BITS 6
|
||||||
|
static struct devname_cache *devcache[1 << CACHE_SIZE_BITS];
|
||||||
|
static DEFINE_SPINLOCK(devname_cache_lock);
|
||||||
|
|
||||||
|
static void free_devcache(struct rcu_head *rcu)
|
||||||
|
{
|
||||||
|
kfree(rcu);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *jbd2_dev_to_name(dev_t device)
|
||||||
|
{
|
||||||
|
int i = hash_32(device, CACHE_SIZE_BITS);
|
||||||
|
char *ret;
|
||||||
|
struct block_device *bd;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
if (devcache[i] && devcache[i]->device == device) {
|
||||||
|
ret = devcache[i]->devname;
|
||||||
|
rcu_read_unlock();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
spin_lock(&devname_cache_lock);
|
||||||
|
if (devcache[i]) {
|
||||||
|
if (devcache[i]->device == device) {
|
||||||
|
ret = devcache[i]->devname;
|
||||||
|
spin_unlock(&devname_cache_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
call_rcu(&devcache[i]->rcu, free_devcache);
|
||||||
|
}
|
||||||
|
devcache[i] = kmalloc(sizeof(struct devname_cache), GFP_KERNEL);
|
||||||
|
if (!devcache[i]) {
|
||||||
|
spin_unlock(&devname_cache_lock);
|
||||||
|
return "NODEV-ALLOCFAILURE"; /* Something non-NULL */
|
||||||
|
}
|
||||||
|
devcache[i]->device = device;
|
||||||
|
bd = bdget(device);
|
||||||
|
if (bd) {
|
||||||
|
bdevname(bd, devcache[i]->devname);
|
||||||
|
bdput(bd);
|
||||||
|
} else
|
||||||
|
__bdevname(device, devcache[i]->devname);
|
||||||
|
ret = devcache[i]->devname;
|
||||||
|
spin_unlock(&devname_cache_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(jbd2_dev_to_name);
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
module_init(journal_init);
|
module_init(journal_init);
|
||||||
module_exit(journal_exit);
|
module_exit(journal_exit);
|
||||||
|
|
|
@ -1547,36 +1547,6 @@ __journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* jbd2_journal_try_to_free_buffers() could race with
|
|
||||||
* jbd2_journal_commit_transaction(). The later might still hold the
|
|
||||||
* reference count to the buffers when inspecting them on
|
|
||||||
* t_syncdata_list or t_locked_list.
|
|
||||||
*
|
|
||||||
* jbd2_journal_try_to_free_buffers() will call this function to
|
|
||||||
* wait for the current transaction to finish syncing data buffers, before
|
|
||||||
* try to free that buffer.
|
|
||||||
*
|
|
||||||
* Called with journal->j_state_lock hold.
|
|
||||||
*/
|
|
||||||
static void jbd2_journal_wait_for_transaction_sync_data(journal_t *journal)
|
|
||||||
{
|
|
||||||
transaction_t *transaction;
|
|
||||||
tid_t tid;
|
|
||||||
|
|
||||||
spin_lock(&journal->j_state_lock);
|
|
||||||
transaction = journal->j_committing_transaction;
|
|
||||||
|
|
||||||
if (!transaction) {
|
|
||||||
spin_unlock(&journal->j_state_lock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tid = transaction->t_tid;
|
|
||||||
spin_unlock(&journal->j_state_lock);
|
|
||||||
jbd2_log_wait_commit(journal, tid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* int jbd2_journal_try_to_free_buffers() - try to free page buffers.
|
* int jbd2_journal_try_to_free_buffers() - try to free page buffers.
|
||||||
* @journal: journal for operation
|
* @journal: journal for operation
|
||||||
|
@ -1649,25 +1619,6 @@ int jbd2_journal_try_to_free_buffers(journal_t *journal,
|
||||||
|
|
||||||
ret = try_to_free_buffers(page);
|
ret = try_to_free_buffers(page);
|
||||||
|
|
||||||
/*
|
|
||||||
* There are a number of places where jbd2_journal_try_to_free_buffers()
|
|
||||||
* could race with jbd2_journal_commit_transaction(), the later still
|
|
||||||
* holds the reference to the buffers to free while processing them.
|
|
||||||
* try_to_free_buffers() failed to free those buffers. Some of the
|
|
||||||
* caller of releasepage() request page buffers to be dropped, otherwise
|
|
||||||
* treat the fail-to-free as errors (such as generic_file_direct_IO())
|
|
||||||
*
|
|
||||||
* So, if the caller of try_to_release_page() wants the synchronous
|
|
||||||
* behaviour(i.e make sure buffers are dropped upon return),
|
|
||||||
* let's wait for the current transaction to finish flush of
|
|
||||||
* dirty data buffers, then try to free those buffers again,
|
|
||||||
* with the journal locked.
|
|
||||||
*/
|
|
||||||
if (ret == 0 && (gfp_mask & __GFP_WAIT) && (gfp_mask & __GFP_FS)) {
|
|
||||||
jbd2_journal_wait_for_transaction_sync_data(journal);
|
|
||||||
ret = try_to_free_buffers(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
busy:
|
busy:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1315,6 +1315,12 @@ extern int jbd_blocks_per_page(struct inode *inode);
|
||||||
#define BUFFER_TRACE2(bh, bh2, info) do {} while (0)
|
#define BUFFER_TRACE2(bh, bh2, info) do {} while (0)
|
||||||
#define JBUFFER_TRACE(jh, info) do {} while (0)
|
#define JBUFFER_TRACE(jh, info) do {} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* jbd2_dev_to_name is a utility function used by the jbd2 and ext4
|
||||||
|
* tracing infrastructure to map a dev_t to a device name.
|
||||||
|
*/
|
||||||
|
extern const char *jbd2_dev_to_name(dev_t device);
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
|
|
||||||
#endif /* _LINUX_JBD2_H */
|
#endif /* _LINUX_JBD2_H */
|
||||||
|
|
719
include/trace/events/ext4.h
Normal file
719
include/trace/events/ext4.h
Normal file
|
@ -0,0 +1,719 @@
|
||||||
|
#if !defined(_TRACE_EXT4_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||||
|
#define _TRACE_EXT4_H
|
||||||
|
|
||||||
|
#undef TRACE_SYSTEM
|
||||||
|
#define TRACE_SYSTEM ext4
|
||||||
|
|
||||||
|
#include <linux/writeback.h>
|
||||||
|
#include "../../../fs/ext4/ext4.h"
|
||||||
|
#include "../../../fs/ext4/mballoc.h"
|
||||||
|
#include <linux/tracepoint.h>
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_free_inode,
|
||||||
|
TP_PROTO(struct inode *inode),
|
||||||
|
|
||||||
|
TP_ARGS(inode),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( umode_t, mode )
|
||||||
|
__field( uid_t, uid )
|
||||||
|
__field( gid_t, gid )
|
||||||
|
__field( blkcnt_t, blocks )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = inode->i_sb->s_dev;
|
||||||
|
__entry->ino = inode->i_ino;
|
||||||
|
__entry->mode = inode->i_mode;
|
||||||
|
__entry->uid = inode->i_uid;
|
||||||
|
__entry->gid = inode->i_gid;
|
||||||
|
__entry->blocks = inode->i_blocks;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu mode %d uid %u gid %u blocks %llu",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->mode,
|
||||||
|
__entry->uid, __entry->gid, __entry->blocks)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_request_inode,
|
||||||
|
TP_PROTO(struct inode *dir, int mode),
|
||||||
|
|
||||||
|
TP_ARGS(dir, mode),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, dir )
|
||||||
|
__field( umode_t, mode )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = dir->i_sb->s_dev;
|
||||||
|
__entry->dir = dir->i_ino;
|
||||||
|
__entry->mode = mode;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s dir %lu mode %d",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->dir, __entry->mode)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_allocate_inode,
|
||||||
|
TP_PROTO(struct inode *inode, struct inode *dir, int mode),
|
||||||
|
|
||||||
|
TP_ARGS(inode, dir, mode),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( ino_t, dir )
|
||||||
|
__field( umode_t, mode )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = inode->i_sb->s_dev;
|
||||||
|
__entry->ino = inode->i_ino;
|
||||||
|
__entry->dir = dir->i_ino;
|
||||||
|
__entry->mode = mode;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu dir %lu mode %d",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->dir, __entry->mode)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_write_begin,
|
||||||
|
|
||||||
|
TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
|
||||||
|
unsigned int flags),
|
||||||
|
|
||||||
|
TP_ARGS(inode, pos, len, flags),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( loff_t, pos )
|
||||||
|
__field( unsigned int, len )
|
||||||
|
__field( unsigned int, flags )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = inode->i_sb->s_dev;
|
||||||
|
__entry->ino = inode->i_ino;
|
||||||
|
__entry->pos = pos;
|
||||||
|
__entry->len = len;
|
||||||
|
__entry->flags = flags;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu pos %llu len %u flags %u",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pos, __entry->len,
|
||||||
|
__entry->flags)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_ordered_write_end,
|
||||||
|
TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
|
||||||
|
unsigned int copied),
|
||||||
|
|
||||||
|
TP_ARGS(inode, pos, len, copied),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( loff_t, pos )
|
||||||
|
__field( unsigned int, len )
|
||||||
|
__field( unsigned int, copied )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = inode->i_sb->s_dev;
|
||||||
|
__entry->ino = inode->i_ino;
|
||||||
|
__entry->pos = pos;
|
||||||
|
__entry->len = len;
|
||||||
|
__entry->copied = copied;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu pos %llu len %u copied %u",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pos, __entry->len,
|
||||||
|
__entry->copied)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_writeback_write_end,
|
||||||
|
TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
|
||||||
|
unsigned int copied),
|
||||||
|
|
||||||
|
TP_ARGS(inode, pos, len, copied),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( loff_t, pos )
|
||||||
|
__field( unsigned int, len )
|
||||||
|
__field( unsigned int, copied )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = inode->i_sb->s_dev;
|
||||||
|
__entry->ino = inode->i_ino;
|
||||||
|
__entry->pos = pos;
|
||||||
|
__entry->len = len;
|
||||||
|
__entry->copied = copied;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu pos %llu len %u copied %u",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pos, __entry->len,
|
||||||
|
__entry->copied)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_journalled_write_end,
|
||||||
|
TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
|
||||||
|
unsigned int copied),
|
||||||
|
TP_ARGS(inode, pos, len, copied),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( loff_t, pos )
|
||||||
|
__field( unsigned int, len )
|
||||||
|
__field( unsigned int, copied )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = inode->i_sb->s_dev;
|
||||||
|
__entry->ino = inode->i_ino;
|
||||||
|
__entry->pos = pos;
|
||||||
|
__entry->len = len;
|
||||||
|
__entry->copied = copied;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu pos %llu len %u copied %u",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pos, __entry->len,
|
||||||
|
__entry->copied)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_da_writepage,
|
||||||
|
TP_PROTO(struct inode *inode, struct page *page),
|
||||||
|
|
||||||
|
TP_ARGS(inode, page),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( pgoff_t, index )
|
||||||
|
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = inode->i_sb->s_dev;
|
||||||
|
__entry->ino = inode->i_ino;
|
||||||
|
__entry->index = page->index;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu page_index %lu",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->index)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_da_writepages,
|
||||||
|
TP_PROTO(struct inode *inode, struct writeback_control *wbc),
|
||||||
|
|
||||||
|
TP_ARGS(inode, wbc),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( long, nr_to_write )
|
||||||
|
__field( long, pages_skipped )
|
||||||
|
__field( loff_t, range_start )
|
||||||
|
__field( loff_t, range_end )
|
||||||
|
__field( char, nonblocking )
|
||||||
|
__field( char, for_kupdate )
|
||||||
|
__field( char, for_reclaim )
|
||||||
|
__field( char, for_writepages )
|
||||||
|
__field( char, range_cyclic )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = inode->i_sb->s_dev;
|
||||||
|
__entry->ino = inode->i_ino;
|
||||||
|
__entry->nr_to_write = wbc->nr_to_write;
|
||||||
|
__entry->pages_skipped = wbc->pages_skipped;
|
||||||
|
__entry->range_start = wbc->range_start;
|
||||||
|
__entry->range_end = wbc->range_end;
|
||||||
|
__entry->nonblocking = wbc->nonblocking;
|
||||||
|
__entry->for_kupdate = wbc->for_kupdate;
|
||||||
|
__entry->for_reclaim = wbc->for_reclaim;
|
||||||
|
__entry->for_writepages = wbc->for_writepages;
|
||||||
|
__entry->range_cyclic = wbc->range_cyclic;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu nr_t_write %ld pages_skipped %ld range_start %llu range_end %llu nonblocking %d for_kupdate %d for_reclaim %d for_writepages %d range_cyclic %d",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->nr_to_write,
|
||||||
|
__entry->pages_skipped, __entry->range_start,
|
||||||
|
__entry->range_end, __entry->nonblocking,
|
||||||
|
__entry->for_kupdate, __entry->for_reclaim,
|
||||||
|
__entry->for_writepages, __entry->range_cyclic)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_da_writepages_result,
|
||||||
|
TP_PROTO(struct inode *inode, struct writeback_control *wbc,
|
||||||
|
int ret, int pages_written),
|
||||||
|
|
||||||
|
TP_ARGS(inode, wbc, ret, pages_written),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( int, ret )
|
||||||
|
__field( int, pages_written )
|
||||||
|
__field( long, pages_skipped )
|
||||||
|
__field( char, encountered_congestion )
|
||||||
|
__field( char, more_io )
|
||||||
|
__field( char, no_nrwrite_index_update )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = inode->i_sb->s_dev;
|
||||||
|
__entry->ino = inode->i_ino;
|
||||||
|
__entry->ret = ret;
|
||||||
|
__entry->pages_written = pages_written;
|
||||||
|
__entry->pages_skipped = wbc->pages_skipped;
|
||||||
|
__entry->encountered_congestion = wbc->encountered_congestion;
|
||||||
|
__entry->more_io = wbc->more_io;
|
||||||
|
__entry->no_nrwrite_index_update = wbc->no_nrwrite_index_update;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu ret %d pages_written %d pages_skipped %ld congestion %d more_io %d no_nrwrite_index_update %d",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->ret,
|
||||||
|
__entry->pages_written, __entry->pages_skipped,
|
||||||
|
__entry->encountered_congestion, __entry->more_io,
|
||||||
|
__entry->no_nrwrite_index_update)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_da_write_begin,
|
||||||
|
TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
|
||||||
|
unsigned int flags),
|
||||||
|
|
||||||
|
TP_ARGS(inode, pos, len, flags),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( loff_t, pos )
|
||||||
|
__field( unsigned int, len )
|
||||||
|
__field( unsigned int, flags )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = inode->i_sb->s_dev;
|
||||||
|
__entry->ino = inode->i_ino;
|
||||||
|
__entry->pos = pos;
|
||||||
|
__entry->len = len;
|
||||||
|
__entry->flags = flags;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu pos %llu len %u flags %u",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pos, __entry->len,
|
||||||
|
__entry->flags)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_da_write_end,
|
||||||
|
TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
|
||||||
|
unsigned int copied),
|
||||||
|
|
||||||
|
TP_ARGS(inode, pos, len, copied),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( loff_t, pos )
|
||||||
|
__field( unsigned int, len )
|
||||||
|
__field( unsigned int, copied )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = inode->i_sb->s_dev;
|
||||||
|
__entry->ino = inode->i_ino;
|
||||||
|
__entry->pos = pos;
|
||||||
|
__entry->len = len;
|
||||||
|
__entry->copied = copied;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu pos %llu len %u copied %u",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pos, __entry->len,
|
||||||
|
__entry->copied)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_normal_writepage,
|
||||||
|
TP_PROTO(struct inode *inode, struct page *page),
|
||||||
|
|
||||||
|
TP_ARGS(inode, page),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( pgoff_t, index )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = inode->i_sb->s_dev;
|
||||||
|
__entry->ino = inode->i_ino;
|
||||||
|
__entry->index = page->index;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu page_index %lu",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->index)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_journalled_writepage,
|
||||||
|
TP_PROTO(struct inode *inode, struct page *page),
|
||||||
|
|
||||||
|
TP_ARGS(inode, page),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( pgoff_t, index )
|
||||||
|
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = inode->i_sb->s_dev;
|
||||||
|
__entry->ino = inode->i_ino;
|
||||||
|
__entry->index = page->index;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu page_index %lu",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->index)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_discard_blocks,
|
||||||
|
TP_PROTO(struct super_block *sb, unsigned long long blk,
|
||||||
|
unsigned long long count),
|
||||||
|
|
||||||
|
TP_ARGS(sb, blk, count),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( __u64, blk )
|
||||||
|
__field( __u64, count )
|
||||||
|
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = sb->s_dev;
|
||||||
|
__entry->blk = blk;
|
||||||
|
__entry->count = count;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s blk %llu count %llu",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->blk, __entry->count)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_mb_new_inode_pa,
|
||||||
|
TP_PROTO(struct ext4_allocation_context *ac,
|
||||||
|
struct ext4_prealloc_space *pa),
|
||||||
|
|
||||||
|
TP_ARGS(ac, pa),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( __u64, pa_pstart )
|
||||||
|
__field( __u32, pa_len )
|
||||||
|
__field( __u64, pa_lstart )
|
||||||
|
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = ac->ac_sb->s_dev;
|
||||||
|
__entry->ino = ac->ac_inode->i_ino;
|
||||||
|
__entry->pa_pstart = pa->pa_pstart;
|
||||||
|
__entry->pa_len = pa->pa_len;
|
||||||
|
__entry->pa_lstart = pa->pa_lstart;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu pstart %llu len %u lstart %llu",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pa_pstart,
|
||||||
|
__entry->pa_len, __entry->pa_lstart)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_mb_new_group_pa,
|
||||||
|
TP_PROTO(struct ext4_allocation_context *ac,
|
||||||
|
struct ext4_prealloc_space *pa),
|
||||||
|
|
||||||
|
TP_ARGS(ac, pa),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( __u64, pa_pstart )
|
||||||
|
__field( __u32, pa_len )
|
||||||
|
__field( __u64, pa_lstart )
|
||||||
|
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = ac->ac_sb->s_dev;
|
||||||
|
__entry->ino = ac->ac_inode->i_ino;
|
||||||
|
__entry->pa_pstart = pa->pa_pstart;
|
||||||
|
__entry->pa_len = pa->pa_len;
|
||||||
|
__entry->pa_lstart = pa->pa_lstart;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu pstart %llu len %u lstart %llu",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->pa_pstart,
|
||||||
|
__entry->pa_len, __entry->pa_lstart)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_mb_release_inode_pa,
|
||||||
|
TP_PROTO(struct ext4_allocation_context *ac,
|
||||||
|
struct ext4_prealloc_space *pa,
|
||||||
|
unsigned long long block, unsigned int count),
|
||||||
|
|
||||||
|
TP_ARGS(ac, pa, block, count),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( __u64, block )
|
||||||
|
__field( __u32, count )
|
||||||
|
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = ac->ac_sb->s_dev;
|
||||||
|
__entry->ino = ac->ac_inode->i_ino;
|
||||||
|
__entry->block = block;
|
||||||
|
__entry->count = count;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu block %llu count %u",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->block,
|
||||||
|
__entry->count)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_mb_release_group_pa,
|
||||||
|
TP_PROTO(struct ext4_allocation_context *ac,
|
||||||
|
struct ext4_prealloc_space *pa),
|
||||||
|
|
||||||
|
TP_ARGS(ac, pa),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( __u64, pa_pstart )
|
||||||
|
__field( __u32, pa_len )
|
||||||
|
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = ac->ac_sb->s_dev;
|
||||||
|
__entry->ino = ac->ac_inode->i_ino;
|
||||||
|
__entry->pa_pstart = pa->pa_pstart;
|
||||||
|
__entry->pa_len = pa->pa_len;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s pstart %llu len %u",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->pa_pstart, __entry->pa_len)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_discard_preallocations,
|
||||||
|
TP_PROTO(struct inode *inode),
|
||||||
|
|
||||||
|
TP_ARGS(inode),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = inode->i_sb->s_dev;
|
||||||
|
__entry->ino = inode->i_ino;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_mb_discard_preallocations,
|
||||||
|
TP_PROTO(struct super_block *sb, int needed),
|
||||||
|
|
||||||
|
TP_ARGS(sb, needed),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( int, needed )
|
||||||
|
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = sb->s_dev;
|
||||||
|
__entry->needed = needed;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s needed %d",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->needed)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_request_blocks,
|
||||||
|
TP_PROTO(struct ext4_allocation_request *ar),
|
||||||
|
|
||||||
|
TP_ARGS(ar),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( unsigned int, flags )
|
||||||
|
__field( unsigned int, len )
|
||||||
|
__field( __u64, logical )
|
||||||
|
__field( __u64, goal )
|
||||||
|
__field( __u64, lleft )
|
||||||
|
__field( __u64, lright )
|
||||||
|
__field( __u64, pleft )
|
||||||
|
__field( __u64, pright )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = ar->inode->i_sb->s_dev;
|
||||||
|
__entry->ino = ar->inode->i_ino;
|
||||||
|
__entry->flags = ar->flags;
|
||||||
|
__entry->len = ar->len;
|
||||||
|
__entry->logical = ar->logical;
|
||||||
|
__entry->goal = ar->goal;
|
||||||
|
__entry->lleft = ar->lleft;
|
||||||
|
__entry->lright = ar->lright;
|
||||||
|
__entry->pleft = ar->pleft;
|
||||||
|
__entry->pright = ar->pright;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu flags %u len %u lblk %llu goal %llu lleft %llu lright %llu pleft %llu pright %llu ",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->flags,
|
||||||
|
__entry->len,
|
||||||
|
(unsigned long long) __entry->logical,
|
||||||
|
(unsigned long long) __entry->goal,
|
||||||
|
(unsigned long long) __entry->lleft,
|
||||||
|
(unsigned long long) __entry->lright,
|
||||||
|
(unsigned long long) __entry->pleft,
|
||||||
|
(unsigned long long) __entry->pright)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_allocate_blocks,
|
||||||
|
TP_PROTO(struct ext4_allocation_request *ar, unsigned long long block),
|
||||||
|
|
||||||
|
TP_ARGS(ar, block),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( __u64, block )
|
||||||
|
__field( unsigned int, flags )
|
||||||
|
__field( unsigned int, len )
|
||||||
|
__field( __u64, logical )
|
||||||
|
__field( __u64, goal )
|
||||||
|
__field( __u64, lleft )
|
||||||
|
__field( __u64, lright )
|
||||||
|
__field( __u64, pleft )
|
||||||
|
__field( __u64, pright )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = ar->inode->i_sb->s_dev;
|
||||||
|
__entry->ino = ar->inode->i_ino;
|
||||||
|
__entry->block = block;
|
||||||
|
__entry->flags = ar->flags;
|
||||||
|
__entry->len = ar->len;
|
||||||
|
__entry->logical = ar->logical;
|
||||||
|
__entry->goal = ar->goal;
|
||||||
|
__entry->lleft = ar->lleft;
|
||||||
|
__entry->lright = ar->lright;
|
||||||
|
__entry->pleft = ar->pleft;
|
||||||
|
__entry->pright = ar->pright;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu flags %u len %u block %llu lblk %llu goal %llu lleft %llu lright %llu pleft %llu pright %llu ",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->flags,
|
||||||
|
__entry->len, __entry->block,
|
||||||
|
(unsigned long long) __entry->logical,
|
||||||
|
(unsigned long long) __entry->goal,
|
||||||
|
(unsigned long long) __entry->lleft,
|
||||||
|
(unsigned long long) __entry->lright,
|
||||||
|
(unsigned long long) __entry->pleft,
|
||||||
|
(unsigned long long) __entry->pright)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_free_blocks,
|
||||||
|
TP_PROTO(struct inode *inode, __u64 block, unsigned long count,
|
||||||
|
int metadata),
|
||||||
|
|
||||||
|
TP_ARGS(inode, block, count, metadata),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( __u64, block )
|
||||||
|
__field( unsigned long, count )
|
||||||
|
__field( int, metadata )
|
||||||
|
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = inode->i_sb->s_dev;
|
||||||
|
__entry->ino = inode->i_ino;
|
||||||
|
__entry->block = block;
|
||||||
|
__entry->count = count;
|
||||||
|
__entry->metadata = metadata;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu block %llu count %lu metadata %d",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->block,
|
||||||
|
__entry->count, __entry->metadata)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_sync_file,
|
||||||
|
TP_PROTO(struct file *file, struct dentry *dentry, int datasync),
|
||||||
|
|
||||||
|
TP_ARGS(file, dentry, datasync),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
__field( ino_t, parent )
|
||||||
|
__field( int, datasync )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = dentry->d_inode->i_sb->s_dev;
|
||||||
|
__entry->ino = dentry->d_inode->i_ino;
|
||||||
|
__entry->datasync = datasync;
|
||||||
|
__entry->parent = dentry->d_parent->d_inode->i_ino;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %ld parent %ld datasync %d ",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->parent,
|
||||||
|
__entry->datasync)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(ext4_sync_fs,
|
||||||
|
TP_PROTO(struct super_block *sb, int wait),
|
||||||
|
|
||||||
|
TP_ARGS(sb, wait),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( int, wait )
|
||||||
|
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = sb->s_dev;
|
||||||
|
__entry->wait = wait;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s wait %d", jbd2_dev_to_name(__entry->dev),
|
||||||
|
__entry->wait)
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif /* _TRACE_EXT4_H */
|
||||||
|
|
||||||
|
/* This part must be outside protection */
|
||||||
|
#include <trace/define_trace.h>
|
168
include/trace/events/jbd2.h
Normal file
168
include/trace/events/jbd2.h
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
#if !defined(_TRACE_JBD2_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||||
|
#define _TRACE_JBD2_H
|
||||||
|
|
||||||
|
#include <linux/jbd2.h>
|
||||||
|
#include <linux/tracepoint.h>
|
||||||
|
|
||||||
|
#undef TRACE_SYSTEM
|
||||||
|
#define TRACE_SYSTEM jbd2
|
||||||
|
|
||||||
|
TRACE_EVENT(jbd2_checkpoint,
|
||||||
|
|
||||||
|
TP_PROTO(journal_t *journal, int result),
|
||||||
|
|
||||||
|
TP_ARGS(journal, result),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( int, result )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = journal->j_fs_dev->bd_dev;
|
||||||
|
__entry->result = result;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s result %d",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->result)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(jbd2_start_commit,
|
||||||
|
|
||||||
|
TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
|
||||||
|
|
||||||
|
TP_ARGS(journal, commit_transaction),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( char, sync_commit )
|
||||||
|
__field( int, transaction )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = journal->j_fs_dev->bd_dev;
|
||||||
|
__entry->sync_commit = commit_transaction->t_synchronous_commit;
|
||||||
|
__entry->transaction = commit_transaction->t_tid;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s transaction %d sync %d",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->transaction,
|
||||||
|
__entry->sync_commit)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(jbd2_commit_locking,
|
||||||
|
|
||||||
|
TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
|
||||||
|
|
||||||
|
TP_ARGS(journal, commit_transaction),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( char, sync_commit )
|
||||||
|
__field( int, transaction )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = journal->j_fs_dev->bd_dev;
|
||||||
|
__entry->sync_commit = commit_transaction->t_synchronous_commit;
|
||||||
|
__entry->transaction = commit_transaction->t_tid;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s transaction %d sync %d",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->transaction,
|
||||||
|
__entry->sync_commit)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(jbd2_commit_flushing,
|
||||||
|
|
||||||
|
TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
|
||||||
|
|
||||||
|
TP_ARGS(journal, commit_transaction),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( char, sync_commit )
|
||||||
|
__field( int, transaction )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = journal->j_fs_dev->bd_dev;
|
||||||
|
__entry->sync_commit = commit_transaction->t_synchronous_commit;
|
||||||
|
__entry->transaction = commit_transaction->t_tid;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s transaction %d sync %d",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->transaction,
|
||||||
|
__entry->sync_commit)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(jbd2_commit_logging,
|
||||||
|
|
||||||
|
TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
|
||||||
|
|
||||||
|
TP_ARGS(journal, commit_transaction),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( char, sync_commit )
|
||||||
|
__field( int, transaction )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = journal->j_fs_dev->bd_dev;
|
||||||
|
__entry->sync_commit = commit_transaction->t_synchronous_commit;
|
||||||
|
__entry->transaction = commit_transaction->t_tid;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s transaction %d sync %d",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->transaction,
|
||||||
|
__entry->sync_commit)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(jbd2_end_commit,
|
||||||
|
TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
|
||||||
|
|
||||||
|
TP_ARGS(journal, commit_transaction),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( char, sync_commit )
|
||||||
|
__field( int, transaction )
|
||||||
|
__field( int, head )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = journal->j_fs_dev->bd_dev;
|
||||||
|
__entry->sync_commit = commit_transaction->t_synchronous_commit;
|
||||||
|
__entry->transaction = commit_transaction->t_tid;
|
||||||
|
__entry->head = journal->j_tail_sequence;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s transaction %d sync %d head %d",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->transaction,
|
||||||
|
__entry->sync_commit, __entry->head)
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(jbd2_submit_inode_data,
|
||||||
|
TP_PROTO(struct inode *inode),
|
||||||
|
|
||||||
|
TP_ARGS(inode),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( dev_t, dev )
|
||||||
|
__field( ino_t, ino )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = inode->i_sb->s_dev;
|
||||||
|
__entry->ino = inode->i_ino;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("dev %s ino %lu",
|
||||||
|
jbd2_dev_to_name(__entry->dev), __entry->ino)
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif /* _TRACE_JBD2_H */
|
||||||
|
|
||||||
|
/* This part must be outside protection */
|
||||||
|
#include <trace/define_trace.h>
|
Loading…
Reference in a new issue