mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-30 17:36:41 +07:00
39fe7557b4
One of our users is complaining that his backup tool is upset on ext2 (while it's happy on ext3, xfs, ...) because of the mtime change. The problem is: mkdir foo mkdir bar mkdir foo/a Now under ext2: mv foo/a foo/b changes mtime of 'foo/a' (foo/b after the move). That does not really make sense and it does not happen under any other filesystem I've seen. More complicated is: mv foo/a bar/a This changes mtime of foo/a (bar/a after the move) and it makes some sense since we had to update parent directory pointer of foo/a. But again, no other filesystem does this. So after some thoughts I'd vote for consistency and change ext2 to behave the same as other filesystems. Do not update mtime of a moved directory. Specs don't say anything about it (neither that it should, nor that it should not be updated) and other common filesystems (ext3, ext4, xfs, reiserfs, fat, ...) don't do it. So let's become more consistent. Spotted by ronny.pretzsch@dfs.de, initial fix by Jörn Engel. Reported-by: <ronny.pretzsch@dfs.de> Cc: <hare@suse.de> Cc: Jörn Engel <joern@logfs.org> Signed-off-by: Jan Kara <jack@suse.cz> Cc: <linux-ext4@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
185 lines
6.3 KiB
C
185 lines
6.3 KiB
C
#include <linux/fs.h>
|
|
#include <linux/ext2_fs.h>
|
|
|
|
/*
|
|
* ext2 mount options
|
|
*/
|
|
struct ext2_mount_options {
|
|
unsigned long s_mount_opt;
|
|
uid_t s_resuid;
|
|
gid_t s_resgid;
|
|
};
|
|
|
|
/*
|
|
* second extended file system inode data in memory
|
|
*/
|
|
struct ext2_inode_info {
|
|
__le32 i_data[15];
|
|
__u32 i_flags;
|
|
__u32 i_faddr;
|
|
__u8 i_frag_no;
|
|
__u8 i_frag_size;
|
|
__u16 i_state;
|
|
__u32 i_file_acl;
|
|
__u32 i_dir_acl;
|
|
__u32 i_dtime;
|
|
|
|
/*
|
|
* i_block_group is the number of the block group which contains
|
|
* this file's inode. Constant across the lifetime of the inode,
|
|
* it is used for making block allocation decisions - we try to
|
|
* place a file's data blocks near its inode block, and new inodes
|
|
* near to their parent directory's inode.
|
|
*/
|
|
__u32 i_block_group;
|
|
|
|
/* block reservation info */
|
|
struct ext2_block_alloc_info *i_block_alloc_info;
|
|
|
|
__u32 i_dir_start_lookup;
|
|
#ifdef CONFIG_EXT2_FS_XATTR
|
|
/*
|
|
* Extended attributes can be read independently of the main file
|
|
* data. Taking i_mutex even when reading would cause contention
|
|
* between readers of EAs and writers of regular file data, so
|
|
* instead we synchronize on xattr_sem when reading or changing
|
|
* EAs.
|
|
*/
|
|
struct rw_semaphore xattr_sem;
|
|
#endif
|
|
#ifdef CONFIG_EXT2_FS_POSIX_ACL
|
|
struct posix_acl *i_acl;
|
|
struct posix_acl *i_default_acl;
|
|
#endif
|
|
rwlock_t i_meta_lock;
|
|
|
|
/*
|
|
* truncate_mutex is for serialising ext2_truncate() against
|
|
* ext2_getblock(). It also protects the internals of the inode's
|
|
* reservation data structures: ext2_reserve_window and
|
|
* ext2_reserve_window_node.
|
|
*/
|
|
struct mutex truncate_mutex;
|
|
struct inode vfs_inode;
|
|
struct list_head i_orphan; /* unlinked but open inodes */
|
|
};
|
|
|
|
/*
|
|
* Inode dynamic state flags
|
|
*/
|
|
#define EXT2_STATE_NEW 0x00000001 /* inode is newly created */
|
|
|
|
|
|
/*
|
|
* Function prototypes
|
|
*/
|
|
|
|
/*
|
|
* Ok, these declarations are also in <linux/kernel.h> but none of the
|
|
* ext2 source programs needs to include it so they are duplicated here.
|
|
*/
|
|
|
|
static inline struct ext2_inode_info *EXT2_I(struct inode *inode)
|
|
{
|
|
return container_of(inode, struct ext2_inode_info, vfs_inode);
|
|
}
|
|
|
|
/* balloc.c */
|
|
extern int ext2_bg_has_super(struct super_block *sb, int group);
|
|
extern unsigned long ext2_bg_num_gdb(struct super_block *sb, int group);
|
|
extern ext2_fsblk_t ext2_new_block(struct inode *, unsigned long, int *);
|
|
extern ext2_fsblk_t ext2_new_blocks(struct inode *, unsigned long,
|
|
unsigned long *, int *);
|
|
extern void ext2_free_blocks (struct inode *, unsigned long,
|
|
unsigned long);
|
|
extern unsigned long ext2_count_free_blocks (struct super_block *);
|
|
extern unsigned long ext2_count_dirs (struct super_block *);
|
|
extern void ext2_check_blocks_bitmap (struct super_block *);
|
|
extern struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
|
|
unsigned int block_group,
|
|
struct buffer_head ** bh);
|
|
extern void ext2_discard_reservation (struct inode *);
|
|
extern int ext2_should_retry_alloc(struct super_block *sb, int *retries);
|
|
extern void ext2_init_block_alloc_info(struct inode *);
|
|
extern void ext2_rsv_window_add(struct super_block *sb, struct ext2_reserve_window_node *rsv);
|
|
|
|
/* dir.c */
|
|
extern int ext2_add_link (struct dentry *, struct inode *);
|
|
extern ino_t ext2_inode_by_name(struct inode *, struct qstr *);
|
|
extern int ext2_make_empty(struct inode *, struct inode *);
|
|
extern struct ext2_dir_entry_2 * ext2_find_entry (struct inode *,struct qstr *, struct page **);
|
|
extern int ext2_delete_entry (struct ext2_dir_entry_2 *, struct page *);
|
|
extern int ext2_empty_dir (struct inode *);
|
|
extern struct ext2_dir_entry_2 * ext2_dotdot (struct inode *, struct page **);
|
|
extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page *, struct inode *, int);
|
|
|
|
/* ialloc.c */
|
|
extern struct inode * ext2_new_inode (struct inode *, int);
|
|
extern void ext2_free_inode (struct inode *);
|
|
extern unsigned long ext2_count_free_inodes (struct super_block *);
|
|
extern void ext2_check_inodes_bitmap (struct super_block *);
|
|
extern unsigned long ext2_count_free (struct buffer_head *, unsigned);
|
|
|
|
/* inode.c */
|
|
extern struct inode *ext2_iget (struct super_block *, unsigned long);
|
|
extern int ext2_write_inode (struct inode *, int);
|
|
extern void ext2_delete_inode (struct inode *);
|
|
extern int ext2_sync_inode (struct inode *);
|
|
extern int ext2_get_block(struct inode *, sector_t, struct buffer_head *, int);
|
|
extern void ext2_truncate (struct inode *);
|
|
extern int ext2_setattr (struct dentry *, struct iattr *);
|
|
extern void ext2_set_inode_flags(struct inode *inode);
|
|
extern void ext2_get_inode_flags(struct ext2_inode_info *);
|
|
extern int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
|
u64 start, u64 len);
|
|
int __ext2_write_begin(struct file *file, struct address_space *mapping,
|
|
loff_t pos, unsigned len, unsigned flags,
|
|
struct page **pagep, void **fsdata);
|
|
|
|
/* ioctl.c */
|
|
extern long ext2_ioctl(struct file *, unsigned int, unsigned long);
|
|
extern long ext2_compat_ioctl(struct file *, unsigned int, unsigned long);
|
|
|
|
/* namei.c */
|
|
struct dentry *ext2_get_parent(struct dentry *child);
|
|
|
|
/* super.c */
|
|
extern void ext2_error (struct super_block *, const char *, const char *, ...)
|
|
__attribute__ ((format (printf, 3, 4)));
|
|
extern void ext2_warning (struct super_block *, const char *, const char *, ...)
|
|
__attribute__ ((format (printf, 3, 4)));
|
|
extern void ext2_update_dynamic_rev (struct super_block *sb);
|
|
extern void ext2_write_super (struct super_block *);
|
|
|
|
/*
|
|
* Inodes and files operations
|
|
*/
|
|
|
|
/* dir.c */
|
|
extern const struct file_operations ext2_dir_operations;
|
|
|
|
/* file.c */
|
|
extern const struct inode_operations ext2_file_inode_operations;
|
|
extern const struct file_operations ext2_file_operations;
|
|
extern const struct file_operations ext2_xip_file_operations;
|
|
|
|
/* inode.c */
|
|
extern const struct address_space_operations ext2_aops;
|
|
extern const struct address_space_operations ext2_aops_xip;
|
|
extern const struct address_space_operations ext2_nobh_aops;
|
|
|
|
/* namei.c */
|
|
extern const struct inode_operations ext2_dir_inode_operations;
|
|
extern const struct inode_operations ext2_special_inode_operations;
|
|
|
|
/* symlink.c */
|
|
extern const struct inode_operations ext2_fast_symlink_inode_operations;
|
|
extern const struct inode_operations ext2_symlink_inode_operations;
|
|
|
|
static inline ext2_fsblk_t
|
|
ext2_group_first_block_no(struct super_block *sb, unsigned long group_no)
|
|
{
|
|
return group_no * (ext2_fsblk_t)EXT2_BLOCKS_PER_GROUP(sb) +
|
|
le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block);
|
|
}
|