[f2fs] Correct attribute handlings
Set correct time to time values in Inode.
Change calculation of size of allocated blocks.
Test: fx test fs-tests
Failed tests: RwFullDiskTest.PartialWriteSucceedsForFullDisk/F2fs
Failed tests: WatcherTest.Add/F2fs, WatcherTest.Existing/F2fs, WatcherTest.Removed/F2fs
Change-Id: I9181d611e1291ce00a4533f445d40c8386fbe4fb
Reviewed-on: https://fuchsia-review.googlesource.com/c/third_party/f2fs/+/536511
Reviewed-by: Brett Wilson <brettw@google.com>
diff --git a/dir.cc b/dir.cc
index 1290ff5..33445df 100644
--- a/dir.cc
+++ b/dir.cc
@@ -10,13 +10,7 @@
Dir::Dir(F2fs *fs, ino_t ino) : VnodeF2fs(fs, ino) {}
-uint64_t Dir::DirBlocks() {
- // return ((uint64_t) (i_size_read(inode) + kPageCacheSize - 1))
- // >> kPageCacheShift;
- // return 0;
- // return Inode().i_blocks - 1;
- return (i_size_ + kBlockSize - 1) / kBlockSize;
-}
+uint64_t Dir::DirBlocks() { return GetBlocks(); }
unsigned int Dir::DirBuckets(unsigned int level) {
if (level < kMaxDirHashDepth / 2)
@@ -222,11 +216,9 @@
FlushDirtyDataPage(Vfs(), page);
#endif
- auto cur_time = time(nullptr);
- i_mtime_.tv_sec = cur_time;
- i_mtime_.tv_nsec = 0;
- i_ctime_.tv_sec = cur_time;
- i_ctime_.tv_nsec = 0;
+ clock_gettime(CLOCK_REALTIME, &i_mtime_);
+ i_ctime_ = i_mtime_;
+
MarkInodeDirty(this);
F2fsPutPage(page, 1);
}
@@ -305,11 +297,9 @@
ClearInodeFlag(&vnode->fi_, InodeInfoFlag::kNewInode);
}
- auto cur_time = time(nullptr);
- i_mtime_.tv_sec = cur_time;
- i_mtime_.tv_nsec = 0;
- i_ctime_.tv_sec = cur_time;
- i_ctime_.tv_nsec = 0;
+ clock_gettime(CLOCK_REALTIME, &i_mtime_);
+ i_ctime_ = i_mtime_;
+
if (fi_.i_current_depth != current_depth) {
fi_.i_current_depth = current_depth;
need_dir_update = true;
@@ -471,11 +461,8 @@
FlushDirtyDataPage(Vfs(), page);
#endif
- auto cur_time = time(nullptr);
- i_mtime_.tv_sec = cur_time;
- i_mtime_.tv_nsec = 0;
- i_ctime_.tv_sec = cur_time;
- i_ctime_.tv_nsec = 0;
+ clock_gettime(CLOCK_REALTIME, &i_mtime_);
+ i_ctime_ = i_mtime_;
if (vnode && S_ISDIR(vnode->i_mode_)) {
DropNlink();
@@ -485,13 +472,8 @@
}
if (vnode) {
- cur_time = time(nullptr);
- i_ctime_.tv_sec = cur_time;
- i_ctime_.tv_nsec = 0;
- i_mtime_.tv_sec = cur_time;
- i_mtime_.tv_nsec = 0;
- vnode->i_ctime_.tv_sec = cur_time;
- vnode->i_ctime_.tv_nsec = 0;
+ clock_gettime(CLOCK_REALTIME, &i_mtime_);
+ i_ctime_ = vnode->i_ctime_ = i_mtime_;
vnode->DropNlink();
if (S_ISDIR(vnode->i_mode_)) {
vnode->DropNlink();
diff --git a/file.cc b/file.cc
index 3b9b8a1..5817b38 100644
--- a/file.cc
+++ b/file.cc
@@ -385,11 +385,8 @@
if (zx_status_t ret = WriteBegin(n * kBlockSize + off_in_block, cur_len, &data_page);
ret != ZX_OK) {
if (off_in_buf > 0) {
- auto cur_time = time(nullptr);
- i_mtime_.tv_sec = cur_time;
- i_mtime_.tv_nsec = 0;
- i_ctime_.tv_sec = cur_time;
- i_ctime_.tv_nsec = 0;
+ clock_gettime(CLOCK_REALTIME, &i_mtime_);
+ i_ctime_ = i_mtime_;
MarkInodeDirty(this);
}
@@ -420,11 +417,8 @@
}
if (off_in_buf > 0) {
- auto cur_time = time(nullptr);
- i_mtime_.tv_sec = cur_time;
- i_mtime_.tv_nsec = 0;
- i_ctime_.tv_sec = cur_time;
- i_ctime_.tv_nsec = 0;
+ clock_gettime(CLOCK_REALTIME, &i_mtime_);
+ i_ctime_ = i_mtime_;
MarkInodeDirty(this);
}
diff --git a/mkfs.cc b/mkfs.cc
index a5be15f..8fcb2b8 100644
--- a/mkfs.cc
+++ b/mkfs.cc
@@ -743,12 +743,14 @@
raw_node->i.i_size = CpuToLe(1 * blk_size_bytes); /* dentry */
raw_node->i.i_blocks = CpuToLe(uint64_t{2});
- raw_node->i.i_atime = CpuToLe(static_cast<uint64_t>(time(nullptr)));
- raw_node->i.i_atime_nsec = 0;
- raw_node->i.i_ctime = CpuToLe(static_cast<uint64_t>(time(nullptr)));
- raw_node->i.i_ctime_nsec = 0;
- raw_node->i.i_mtime = CpuToLe(static_cast<uint64_t>(time(nullptr)));
- raw_node->i.i_mtime_nsec = 0;
+ timespec cur_time;
+ clock_gettime(CLOCK_REALTIME, &cur_time);
+ raw_node->i.i_atime = cur_time.tv_sec;
+ raw_node->i.i_atime_nsec = cur_time.tv_nsec;
+ raw_node->i.i_ctime = cur_time.tv_sec;
+ raw_node->i.i_ctime_nsec = cur_time.tv_nsec;
+ raw_node->i.i_mtime = cur_time.tv_sec;
+ raw_node->i.i_mtime_nsec = cur_time.tv_nsec;
raw_node->i.i_generation = 0;
raw_node->i.i_xattr_nid = 0;
raw_node->i.i_flags = 0;
diff --git a/namei.cc b/namei.cc
index a237dc8..43924cf 100644
--- a/namei.cc
+++ b/namei.cc
@@ -13,7 +13,6 @@
nid_t ino;
fbl::RefPtr<VnodeF2fs> vnode_refptr;
VnodeF2fs *vnode = nullptr;
- auto cur_time = time(nullptr);
do {
fbl::AutoLock lock(&sbi.fs_lock[static_cast<int>(LockType::kNodeNew)]);
@@ -42,13 +41,8 @@
vnode->i_nlink_ = 0;
vnode->i_blocks_ = 0;
- cur_time = time(nullptr);
- vnode->i_mtime_.tv_sec = cur_time;
- vnode->i_mtime_.tv_nsec = 0;
- vnode->i_atime_.tv_sec = cur_time;
- vnode->i_atime_.tv_nsec = 0;
- vnode->i_ctime_.tv_sec = cur_time;
- vnode->i_ctime_.tv_nsec = 0;
+ clock_gettime(CLOCK_REALTIME, &vnode->i_mtime_);
+ vnode->i_atime_ = vnode->i_ctime_ = vnode->i_mtime_;
vnode->i_generation_ = sbi.s_next_generation++;
@@ -133,13 +127,11 @@
zx_status_t Dir::Link(std::string_view name, fbl::RefPtr<fs::Vnode> _target) {
VnodeF2fs *target = static_cast<VnodeF2fs *>(_target.get());
- auto cur_time = time(nullptr);
fbl::AutoLock lock(&i_mutex_);
fbl::AutoLock tlock(&target->i_mutex_);
- target->i_ctime_.tv_sec = cur_time;
- target->i_ctime_.tv_nsec = 0;
+ clock_gettime(CLOCK_REALTIME, &target->i_ctime_);
#if 0 // porting needed
// AtomicInc(&inode->i_count);
@@ -385,7 +377,9 @@
DirEntry *old_dir_entry = nullptr;
DirEntry *old_entry;
DirEntry *new_entry;
- auto cur_time = time(nullptr);
+ timespec cur_time;
+
+ clock_gettime(CLOCK_REALTIME, &cur_time);
if (new_dir->i_nlink_ == 0)
return ZX_ERR_NOT_FOUND;
@@ -482,9 +476,7 @@
new_dir->SetLink(new_entry, new_page, old_vnode);
- cur_time = time(nullptr);
- new_vnode->i_ctime_.tv_sec = cur_time;
- new_vnode->i_ctime_.tv_nsec = 0;
+ new_vnode->i_ctime_ = cur_time;
if (old_dir_entry)
new_vnode->DropNlink();
new_vnode->DropNlink();
@@ -518,8 +510,7 @@
}
}
- old_vnode->i_ctime_.tv_sec = cur_time;
- old_vnode->i_ctime_.tv_nsec = 0;
+ old_vnode->i_ctime_ = cur_time;
SetInodeFlag(&old_vnode->fi_, InodeInfoFlag::kNeedCp);
MarkInodeDirty(old_vnode);
diff --git a/vnode.cc b/vnode.cc
index 90ac2ff..50595b5 100644
--- a/vnode.cc
+++ b/vnode.cc
@@ -157,10 +157,32 @@
a->mode = i_mode_;
a->inode = ino_;
a->content_size = i_size_;
- a->storage_size = i_blocks_ * kBlockSize;
+ a->storage_size = GetBlocks() * kBlockSize;
a->link_count = i_nlink_;
- a->creation_time = inode_.i_ctime;
- a->modification_time = inode_.i_mtime;
+ a->creation_time = zx_time_add_duration(ZX_SEC(i_ctime_.tv_sec), i_ctime_.tv_nsec);
+ a->modification_time = zx_time_add_duration(ZX_SEC(i_mtime_.tv_sec), i_mtime_.tv_nsec);
+
+ return ZX_OK;
+}
+
+zx_status_t VnodeF2fs::SetAttributes(fs::VnodeAttributesUpdate attr) {
+ bool need_inode_sync = false;
+
+ if (attr.has_creation_time()) {
+ i_ctime_ = zx_timespec_from_duration(attr.take_creation_time());
+ need_inode_sync = true;
+ }
+ if (attr.has_modification_time()) {
+ i_mtime_ = zx_timespec_from_duration(attr.take_modification_time());
+ need_inode_sync = true;
+ }
+ if (attr.any()) {
+ return ZX_ERR_INVALID_ARGS;
+ }
+
+ if (need_inode_sync) {
+ MarkInodeDirty(this);
+ }
return ZX_OK;
}
@@ -354,11 +376,8 @@
zx_status_t ret;
if (ret = TruncateBlocks(i_size_); ret == ZX_OK) {
- auto cur_time = time(nullptr);
- i_mtime_.tv_sec = cur_time;
- i_mtime_.tv_nsec = 0;
- i_ctime_.tv_sec = cur_time;
- i_ctime_.tv_nsec = 0;
+ clock_gettime(CLOCK_REALTIME, &i_mtime_);
+ i_ctime_ = i_mtime_;
MarkInodeDirty(this);
}
@@ -528,6 +547,8 @@
void VnodeF2fs::SetNlink(uint32_t nlink) { i_nlink_ = nlink; }
+uint64_t VnodeF2fs::GetBlocks() { return (i_size_ + kBlockSize - 1) / kBlockSize; }
+
void MarkInodeDirty(VnodeF2fs *vnode) { vnode->WriteInode(nullptr); }
void VnodeF2fs::Sync(SyncCallback closure) {
diff --git a/vnode.h b/vnode.h
index 4b8d8e8..399657a 100644
--- a/vnode.h
+++ b/vnode.h
@@ -44,6 +44,7 @@
Inode GetInode() const { return inode_; }
zx_status_t GetAttributes(fs::VnodeAttributes *a) final;
+ zx_status_t SetAttributes(fs::VnodeAttributesUpdate attr) final;
zx_status_t GetNodeInfoForProtocol([[maybe_unused]] fs::VnodeProtocol protocol,
[[maybe_unused]] fs::Rights rights,
@@ -112,6 +113,8 @@
void ClearNlink();
void SetNlink(uint32_t nlink);
+ uint64_t GetBlocks();
+
// TODO(unknown): non-public member variables
fbl::Mutex v_lock_;
mtx_t i_mutex_;