diff options
author | OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> | 2014-05-13 20:57:45 +0900 |
---|---|---|
committer | Daniel Phillips <daniel@tux3.org> | 2014-05-13 20:57:45 +0900 |
commit | f82233703a6cb2d977d802d8403beafd4b180ee8 (patch) | |
tree | ab8c87974df6dd9ea6cb8a00bf03f99e7422bc15 | |
parent | 9f27a764bbc6b388a80dd1aaf8b86b5c7077511f (diff) | |
download | linux-tux3-f82233703a6cb2d977d802d8403beafd4b180ee8.tar.gz |
tux3: Fix timestamp update for special files
Special files are updating timestamps without locking and
change_begin/end now. This means, tux3 crashes at
tux3_mark_inode_dirty() because of no change_begin().
So, this adds ->update_time() handler to special files.
[FIXME: maybe, we should add lock for timestamp.]
And additionally, dir/symlink updates timestamps i_*time directly
(except i_atime), so this adds assertion in ->update_time() of
dir/symlink for debugging.
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
-rw-r--r-- | fs/tux3/inode.c | 56 | ||||
-rw-r--r-- | fs/tux3/namei.c | 3 | ||||
-rw-r--r-- | fs/tux3/tux3.h | 1 |
3 files changed, 58 insertions, 2 deletions
diff --git a/fs/tux3/inode.c b/fs/tux3/inode.c index 1bfb28f3f5c18..ef9ceeb629b28 100644 --- a/fs/tux3/inode.c +++ b/fs/tux3/inode.c @@ -846,6 +846,9 @@ int tux3_setattr(struct dentry *dentry, struct iattr *iattr) return err; } +/* + * Timestamp handler for regular file. + */ static int tux3_file_update_time(struct inode *inode, struct timespec *time, int flags) { @@ -866,6 +869,55 @@ static int tux3_file_update_time(struct inode *inode, struct timespec *time, return 0; } +/* + * Timestamp handler for directory/symlink. Timestamp is updated by + * directly, so this should not be called except atime. + */ +int tux3_no_update_time(struct inode *inode, struct timespec *time, int flags) +{ + /* FIXME: atime is not supported yet */ + if (flags & S_ATIME) + inode->i_atime = *time; + if (!(flags & ~S_ATIME)) + return 0; + + WARN(1, "update_time is called for inum %Lu, i_mode %x\n", + tux_inode(inode)->inum, inode->i_mode); + + return 0; +} + +/* + * Timestamp handler for special file. This is not called under + * change_{begin,end}() or ->i_mutex. + * + * FIXME: special file should also handle timestamp as transaction? + */ +static int tux3_special_update_time(struct inode *inode, struct timespec *time, + int flags) +{ + struct sb *sb = tux_sb(inode->i_sb); + + /* FIXME: atime is not supported yet */ + if (flags & S_ATIME) + inode->i_atime = *time; + if (!(flags & ~S_ATIME)) + return 0; + + /* FIXME: no i_mutex, so this is racy */ + change_begin(sb); + if (flags & S_VERSION) + inode_inc_iversion(inode); + if (flags & S_CTIME) + inode->i_ctime = *time; + if (flags & S_MTIME) + inode->i_mtime = *time; + mark_inode_dirty_sync(inode); + change_end(sb); + + return 0; +} + #include "inode_vfslib.c" static const struct file_operations tux_file_fops = { @@ -903,13 +955,14 @@ static const struct inode_operations tux_file_iops = { static const struct inode_operations tux_special_iops = { // .permission = ext4_permission, .setattr = tux3_setattr, - .getattr = tux3_getattr + .getattr = tux3_getattr, #ifdef CONFIG_EXT4DEV_FS_XATTR // .setxattr = generic_setxattr, // .getxattr = generic_getxattr, // .listxattr = ext4_listxattr, // .removexattr = generic_removexattr, #endif + .update_time = tux3_special_update_time, }; const struct inode_operations tux_symlink_iops = { @@ -924,6 +977,7 @@ const struct inode_operations tux_symlink_iops = { // .listxattr = ext4_listxattr, // .removexattr = generic_removexattr, #endif + .update_time = tux3_no_update_time, }; static void tux_setup_inode(struct inode *inode) diff --git a/fs/tux3/namei.c b/fs/tux3/namei.c index 853c60377f166..4a7e9bf1ad318 100644 --- a/fs/tux3/namei.c +++ b/fs/tux3/namei.c @@ -358,7 +358,7 @@ const struct inode_operations tux_dir_iops = { .mknod = tux3_mknod, .rename = tux3_rename, .setattr = tux3_setattr, - .getattr = tux3_getattr + .getattr = tux3_getattr, // .setxattr = generic_setxattr, // .getxattr = generic_getxattr, // .listxattr = ext3_listxattr, @@ -368,5 +368,6 @@ const struct inode_operations tux_dir_iops = { /* FIXME: why doesn't ext4 support this for directory? */ // .fallocate = ext4_fallocate, // .fiemap = ext4_fiemap, + .update_time = tux3_no_update_time, }; #endif /* !__KERNEL__ */ diff --git a/fs/tux3/tux3.h b/fs/tux3/tux3.h index 002d6d47c38ea..a6bb78d161ab6 100644 --- a/fs/tux3/tux3.h +++ b/fs/tux3/tux3.h @@ -687,6 +687,7 @@ extern const struct address_space_operations tux_vol_aops; int tux3_sync_file(struct file *file, loff_t start, loff_t end, int datasync); int tux3_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); int tux3_setattr(struct dentry *dentry, struct iattr *iattr); +int tux3_no_update_time(struct inode *inode, struct timespec *time, int flags); /* symlink.c */ extern const struct inode_operations tux_symlink_iops; |