aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>2014-05-13 20:57:45 +0900
committerDaniel Phillips <daniel@tux3.org>2014-05-13 20:57:45 +0900
commitf82233703a6cb2d977d802d8403beafd4b180ee8 (patch)
treeab8c87974df6dd9ea6cb8a00bf03f99e7422bc15
parent9f27a764bbc6b388a80dd1aaf8b86b5c7077511f (diff)
downloadlinux-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.c56
-rw-r--r--fs/tux3/namei.c3
-rw-r--r--fs/tux3/tux3.h1
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;