bcachefs: Fix mtime/ctime updates

Also make inode flags consistent with how the rest of the inode is
updated

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2018-07-17 14:12:42 -04:00 committed by Kent Overstreet
parent 4e1ec2cc0d
commit 2ea9004864
7 changed files with 130 additions and 124 deletions

View File

@ -286,10 +286,9 @@ static int inode_update_for_set_acl_fn(struct bch_inode_info *inode,
void *p)
{
struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct timespec64 now = current_time(&inode->v);
umode_t mode = (unsigned long) p;
bi->bi_ctime = timespec_to_bch2_time(c, now);
bi->bi_ctime = bch2_current_time(c);
bi->bi_mode = mode;
return 0;
}

View File

@ -177,23 +177,40 @@ static int bch2_quota_reservation_add(struct bch_fs *c,
/* i_size updates: */
struct inode_new_size {
loff_t new_size;
u64 now;
unsigned fields;
};
static int inode_set_size(struct bch_inode_info *inode,
struct bch_inode_unpacked *bi,
void *p)
{
loff_t *new_i_size = p;
struct inode_new_size *s = p;
lockdep_assert_held(&inode->ei_update_lock);
bi->bi_size = s->new_size;
if (s->fields & ATTR_ATIME)
bi->bi_atime = s->now;
if (s->fields & ATTR_MTIME)
bi->bi_mtime = s->now;
if (s->fields & ATTR_CTIME)
bi->bi_ctime = s->now;
bi->bi_size = *new_i_size;
return 0;
}
static int __must_check bch2_write_inode_size(struct bch_fs *c,
struct bch_inode_info *inode,
loff_t new_size)
loff_t new_size, unsigned fields)
{
return __bch2_write_inode(c, inode, inode_set_size, &new_size, 0);
struct inode_new_size s = {
.new_size = new_size,
.now = bch2_current_time(c),
.fields = fields,
};
return bch2_write_inode(c, inode, inode_set_size, &s, fields);
}
static void i_sectors_acct(struct bch_fs *c, struct bch_inode_info *inode,
@ -241,6 +258,7 @@ static int i_sectors_dirty_finish_fn(struct bch_inode_info *inode,
struct bch_inode_unpacked *bi,
void *p)
{
struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct i_sectors_hook *h = p;
if (h->new_i_size != U64_MAX &&
@ -249,6 +267,7 @@ static int i_sectors_dirty_finish_fn(struct bch_inode_info *inode,
bi->bi_size = h->new_i_size;
bi->bi_sectors += h->sectors;
bi->bi_flags &= ~h->flags;
bi->bi_mtime = bi->bi_ctime = bch2_current_time(c);
return 0;
}
@ -259,7 +278,7 @@ static int i_sectors_dirty_finish(struct bch_fs *c, struct i_sectors_hook *h)
mutex_lock(&h->inode->ei_update_lock);
i_sectors_acct(c, h->inode, &h->quota_res, h->sectors);
ret = __bch2_write_inode(c, h->inode, i_sectors_dirty_finish_fn, h, 0);
ret = bch2_write_inode(c, h->inode, i_sectors_dirty_finish_fn, h, 0);
if (!ret && h->new_i_size != U64_MAX)
i_size_write(&h->inode->v, h->new_i_size);
@ -289,7 +308,7 @@ static int i_sectors_dirty_start(struct bch_fs *c, struct i_sectors_hook *h)
int ret;
mutex_lock(&h->inode->ei_update_lock);
ret = __bch2_write_inode(c, h->inode, i_sectors_dirty_start_fn, h, 0);
ret = bch2_write_inode(c, h->inode, i_sectors_dirty_start_fn, h, 0);
mutex_unlock(&h->inode->ei_update_lock);
return ret;
@ -2223,9 +2242,8 @@ static int bch2_extend(struct bch_inode_info *inode, struct iattr *iattr)
setattr_copy(NULL, &inode->v, iattr);
mutex_lock(&inode->ei_update_lock);
inode_set_ctime_current(&inode->v);
inode->v.i_mtime = inode_get_ctime(&inode->v);
ret = bch2_write_inode_size(c, inode, inode->v.i_size);
ret = bch2_write_inode_size(c, inode, inode->v.i_size,
ATTR_MTIME|ATTR_CTIME);
mutex_unlock(&inode->ei_update_lock);
return ret;
@ -2284,8 +2302,6 @@ int bch2_truncate(struct bch_inode_info *inode, struct iattr *iattr)
/* ATTR_MODE will never be set here, ns argument isn't needed: */
setattr_copy(NULL, &inode->v, iattr);
inode_set_ctime_current(&inode->v);
inode->v.i_mtime = inode_get_ctime(&inode->v);
out:
ret = i_sectors_dirty_finish(c, &i_sectors_hook) ?: ret;
err_put_pagecache:
@ -2617,7 +2633,7 @@ btree_iter_err:
i_size_write(&inode->v, end);
mutex_lock(&inode->ei_update_lock);
ret = bch2_write_inode_size(c, inode, inode->v.i_size);
ret = bch2_write_inode_size(c, inode, inode->v.i_size, 0);
mutex_unlock(&inode->ei_update_lock);
}
@ -2633,7 +2649,8 @@ btree_iter_err:
if (inode->ei_inode.bi_size != inode->v.i_size) {
mutex_lock(&inode->ei_update_lock);
ret = bch2_write_inode_size(c, inode, inode->v.i_size);
ret = bch2_write_inode_size(c, inode,
inode->v.i_size, 0);
mutex_unlock(&inode->ei_update_lock);
}
}

View File

@ -12,79 +12,6 @@
#define FS_IOC_GOINGDOWN _IOR('X', 125, __u32)
/* Inode flags: */
/* bcachefs inode flags -> vfs inode flags: */
static const unsigned bch_flags_to_vfs[] = {
[__BCH_INODE_SYNC] = S_SYNC,
[__BCH_INODE_IMMUTABLE] = S_IMMUTABLE,
[__BCH_INODE_APPEND] = S_APPEND,
[__BCH_INODE_NOATIME] = S_NOATIME,
};
/* bcachefs inode flags -> FS_IOC_GETFLAGS: */
static const unsigned bch_flags_to_uflags[] = {
[__BCH_INODE_SYNC] = FS_SYNC_FL,
[__BCH_INODE_IMMUTABLE] = FS_IMMUTABLE_FL,
[__BCH_INODE_APPEND] = FS_APPEND_FL,
[__BCH_INODE_NODUMP] = FS_NODUMP_FL,
[__BCH_INODE_NOATIME] = FS_NOATIME_FL,
};
/* bcachefs inode flags -> FS_IOC_FSGETXATTR: */
static const unsigned bch_flags_to_xflags[] = {
[__BCH_INODE_SYNC] = FS_XFLAG_SYNC,
[__BCH_INODE_IMMUTABLE] = FS_XFLAG_IMMUTABLE,
[__BCH_INODE_APPEND] = FS_XFLAG_APPEND,
[__BCH_INODE_NODUMP] = FS_XFLAG_NODUMP,
[__BCH_INODE_NOATIME] = FS_XFLAG_NOATIME,
//[__BCH_INODE_PROJINHERIT] = FS_XFLAG_PROJINHERIT;
};
#define set_flags(_map, _in, _out) \
do { \
unsigned _i; \
\
for (_i = 0; _i < ARRAY_SIZE(_map); _i++) \
if ((_in) & (1 << _i)) \
(_out) |= _map[_i]; \
else \
(_out) &= ~_map[_i]; \
} while (0)
#define map_flags(_map, _in) \
({ \
unsigned _out = 0; \
\
set_flags(_map, _in, _out); \
_out; \
})
#define map_flags_rev(_map, _in) \
({ \
unsigned _i, _out = 0; \
\
for (_i = 0; _i < ARRAY_SIZE(_map); _i++) \
if ((_in) & _map[_i]) { \
(_out) |= 1 << _i; \
(_in) &= ~_map[_i]; \
} \
(_out); \
})
#define map_defined(_map) \
({ \
unsigned _in = ~0; \
\
map_flags_rev(_map, _in); \
})
/* Set VFS inode flags from bcachefs inode: */
void bch2_inode_flags_to_vfs(struct bch_inode_info *inode)
{
set_flags(bch_flags_to_vfs, inode->ei_inode.bi_flags, inode->v.i_flags);
}
struct flags_set {
unsigned mask;
unsigned flags;
@ -96,6 +23,7 @@ static int bch2_inode_flags_set(struct bch_inode_info *inode,
struct bch_inode_unpacked *bi,
void *p)
{
struct bch_fs *c = inode->v.i_sb->s_fs_info;
/*
* We're relying on btree locking here for exclusion with other ioctl
* calls - use the flags in the btree (@bi), not inode->i_flags:
@ -108,14 +36,15 @@ static int bch2_inode_flags_set(struct bch_inode_info *inode,
!capable(CAP_LINUX_IMMUTABLE))
return -EPERM;
if (!S_ISREG(inode->v.i_mode) &&
!S_ISDIR(inode->v.i_mode) &&
if (!S_ISREG(bi->bi_mode) &&
!S_ISDIR(bi->bi_mode) &&
(newflags & (BCH_INODE_NODUMP|BCH_INODE_NOATIME)) != newflags)
return -EINVAL;
bi->bi_flags &= ~s->mask;
bi->bi_flags |= newflags;
inode_set_ctime_current(&inode->v);
bi->bi_ctime = timespec_to_bch2_time(c, current_time(&inode->v));
return 0;
}
@ -153,10 +82,8 @@ static int bch2_ioc_setflags(struct bch_fs *c,
}
mutex_lock(&inode->ei_update_lock);
ret = __bch2_write_inode(c, inode, bch2_inode_flags_set, &s, 0);
if (!ret)
bch2_inode_flags_to_vfs(inode);
ret = bch2_write_inode(c, inode, bch2_inode_flags_set, &s,
ATTR_CTIME);
mutex_unlock(&inode->ei_update_lock);
setflags_out:
@ -242,9 +169,8 @@ static int bch2_ioc_fssetxattr(struct bch_fs *c,
if (ret)
goto err_unlock;
ret = __bch2_write_inode(c, inode, fssetxattr_inode_update_fn, &s, 0);
if (!ret)
bch2_inode_flags_to_vfs(inode);
ret = bch2_write_inode(c, inode, fssetxattr_inode_update_fn, &s,
ATTR_CTIME);
err_unlock:
mutex_unlock(&inode->ei_update_lock);
err:

View File

@ -2,7 +2,78 @@
#ifndef _BCACHEFS_FS_IOCTL_H
#define _BCACHEFS_FS_IOCTL_H
void bch2_inode_flags_to_vfs(struct bch_inode_info *);
/* Inode flags: */
/* bcachefs inode flags -> vfs inode flags: */
static const unsigned bch_flags_to_vfs[] = {
[__BCH_INODE_SYNC] = S_SYNC,
[__BCH_INODE_IMMUTABLE] = S_IMMUTABLE,
[__BCH_INODE_APPEND] = S_APPEND,
[__BCH_INODE_NOATIME] = S_NOATIME,
};
/* bcachefs inode flags -> FS_IOC_GETFLAGS: */
static const unsigned bch_flags_to_uflags[] = {
[__BCH_INODE_SYNC] = FS_SYNC_FL,
[__BCH_INODE_IMMUTABLE] = FS_IMMUTABLE_FL,
[__BCH_INODE_APPEND] = FS_APPEND_FL,
[__BCH_INODE_NODUMP] = FS_NODUMP_FL,
[__BCH_INODE_NOATIME] = FS_NOATIME_FL,
};
/* bcachefs inode flags -> FS_IOC_FSGETXATTR: */
static const unsigned bch_flags_to_xflags[] = {
[__BCH_INODE_SYNC] = FS_XFLAG_SYNC,
[__BCH_INODE_IMMUTABLE] = FS_XFLAG_IMMUTABLE,
[__BCH_INODE_APPEND] = FS_XFLAG_APPEND,
[__BCH_INODE_NODUMP] = FS_XFLAG_NODUMP,
[__BCH_INODE_NOATIME] = FS_XFLAG_NOATIME,
//[__BCH_INODE_PROJINHERIT] = FS_XFLAG_PROJINHERIT;
};
#define set_flags(_map, _in, _out) \
do { \
unsigned _i; \
\
for (_i = 0; _i < ARRAY_SIZE(_map); _i++) \
if ((_in) & (1 << _i)) \
(_out) |= _map[_i]; \
else \
(_out) &= ~_map[_i]; \
} while (0)
#define map_flags(_map, _in) \
({ \
unsigned _out = 0; \
\
set_flags(_map, _in, _out); \
_out; \
})
#define map_flags_rev(_map, _in) \
({ \
unsigned _i, _out = 0; \
\
for (_i = 0; _i < ARRAY_SIZE(_map); _i++) \
if ((_in) & _map[_i]) { \
(_out) |= 1 << _i; \
(_in) &= ~_map[_i]; \
} \
(_out); \
})
#define map_defined(_map) \
({ \
unsigned _in = ~0; \
\
map_flags_rev(_map, _in); \
})
/* Set VFS inode flags from bcachefs inode: */
static inline void bch2_inode_flags_to_vfs(struct bch_inode_info *inode)
{
set_flags(bch_flags_to_vfs, inode->ei_inode.bi_flags, inode->v.i_flags);
}
long bch2_fs_file_ioctl(struct file *, unsigned, unsigned long);
long bch2_compat_fs_ioctl(struct file *, unsigned, unsigned long);

View File

@ -147,6 +147,8 @@ void bch2_inode_update_after_write(struct bch_fs *c,
inode->ei_inode = *bi;
inode->ei_qid = bch_qid(bi);
bch2_inode_flags_to_vfs(inode);
}
int __must_check bch2_write_inode_trans(struct btree_trans *trans,
@ -187,10 +189,10 @@ int __must_check bch2_write_inode_trans(struct btree_trans *trans,
return 0;
}
int __must_check __bch2_write_inode(struct bch_fs *c,
struct bch_inode_info *inode,
inode_set_fn set,
void *p, unsigned fields)
int __must_check bch2_write_inode(struct bch_fs *c,
struct bch_inode_info *inode,
inode_set_fn set,
void *p, unsigned fields)
{
struct btree_trans trans;
struct bch_inode_unpacked inode_u;
@ -271,9 +273,8 @@ static int inode_update_for_create_fn(struct bch_inode_info *inode,
{
struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct bch_inode_unpacked *new_inode = p;
struct timespec64 now = current_time(&inode->v);
bi->bi_mtime = bi->bi_ctime = timespec_to_bch2_time(c, now);
bi->bi_mtime = bi->bi_ctime = bch2_current_time(c);
if (S_ISDIR(new_inode->bi_mode))
bi->bi_nlink++;
@ -469,9 +470,8 @@ static int inode_update_for_link_fn(struct bch_inode_info *inode,
void *p)
{
struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct timespec64 now = current_time(&inode->v);
bi->bi_ctime = timespec_to_bch2_time(c, now);
bi->bi_ctime = bch2_current_time(c);
if (bi->bi_flags & BCH_INODE_UNLINKED)
bi->bi_flags &= ~BCH_INODE_UNLINKED;
@ -543,9 +543,8 @@ static int inode_update_dir_for_unlink_fn(struct bch_inode_info *inode,
{
struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct bch_inode_info *unlink_inode = p;
struct timespec64 now = current_time(&inode->v);
bi->bi_mtime = bi->bi_ctime = timespec_to_bch2_time(c, now);
bi->bi_mtime = bi->bi_ctime = bch2_current_time(c);
bi->bi_nlink -= S_ISDIR(unlink_inode->v.i_mode);
@ -557,9 +556,8 @@ static int inode_update_for_unlink_fn(struct bch_inode_info *inode,
void *p)
{
struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct timespec64 now = current_time(&inode->v);
bi->bi_ctime = timespec_to_bch2_time(c, now);
bi->bi_ctime = bch2_current_time(c);
if (bi->bi_nlink)
bi->bi_nlink--;
else
@ -740,8 +738,6 @@ static int bch2_rename2(struct mnt_idmap *idmap,
{
struct bch_fs *c = src_vdir->i_sb->s_fs_info;
struct rename_info i = {
.now = timespec_to_bch2_time(c,
current_time(src_vdir)),
.src_dir = to_bch_ei(src_vdir),
.dst_dir = to_bch_ei(dst_vdir),
.src_inode = to_bch_ei(src_dentry->d_inode),
@ -778,7 +774,7 @@ static int bch2_rename2(struct mnt_idmap *idmap,
bch2_trans_init(&trans, c);
retry:
bch2_trans_begin(&trans);
i.now = timespec_to_bch2_time(c, current_time(src_vdir)),
i.now = bch2_current_time(c);
ret = bch2_dirent_rename(&trans,
i.src_dir, &src_dentry->d_name,
@ -1271,8 +1267,6 @@ static void bch2_vfs_inode_init(struct bch_fs *c,
inode->ei_quota_reserved = 0;
inode->ei_str_hash = bch2_hash_info_init(c, bi);
bch2_inode_flags_to_vfs(inode);
inode->v.i_mapping->a_ops = &bch_address_space_operations;
switch (inode->v.i_mode & S_IFMT) {
@ -1346,8 +1340,8 @@ static int bch2_vfs_write_inode(struct inode *vinode,
int ret;
mutex_lock(&inode->ei_update_lock);
ret = __bch2_write_inode(c, inode, inode_update_times_fn, NULL,
ATTR_ATIME|ATTR_MTIME|ATTR_CTIME);
ret = bch2_write_inode(c, inode, inode_update_times_fn, NULL,
ATTR_ATIME|ATTR_MTIME|ATTR_CTIME);
mutex_unlock(&inode->ei_update_lock);
if (c->opts.journal_flush_disabled)

View File

@ -2,6 +2,7 @@
#ifndef _BCACHEFS_FS_H
#define _BCACHEFS_FS_H
#include "inode.h"
#include "opts.h"
#include "str_hash.h"
#include "quota_types.h"
@ -81,10 +82,8 @@ int __must_check bch2_write_inode_trans(struct btree_trans *,
struct bch_inode_info *,
struct bch_inode_unpacked *,
inode_set_fn, void *);
int __must_check __bch2_write_inode(struct bch_fs *, struct bch_inode_info *,
inode_set_fn, void *, unsigned);
int __must_check bch2_write_inode(struct bch_fs *,
struct bch_inode_info *);
int __must_check bch2_write_inode(struct bch_fs *, struct bch_inode_info *,
inode_set_fn, void *, unsigned);
void bch2_vfs_exit(void);
int bch2_vfs_init(void);

View File

@ -436,7 +436,7 @@ static int bch2_xattr_bcachefs_set(const struct xattr_handler *handler,
}
mutex_lock(&inode->ei_update_lock);
ret = __bch2_write_inode(c, inode, inode_opt_set_fn, &s, 0);
ret = bch2_write_inode(c, inode, inode_opt_set_fn, &s, 0);
mutex_unlock(&inode->ei_update_lock);
if (value &&