diff --git a/qa/workunits/fs/misc/rstats.sh b/qa/workunits/fs/misc/rstats.sh index e6b3eddf287e8d..951cd274df7d5f 100755 --- a/qa/workunits/fs/misc/rstats.sh +++ b/qa/workunits/fs/misc/rstats.sh @@ -75,6 +75,11 @@ touch d1/d2/f3 # create new file wait_until_changed rctime check_rctime +old_value=`getfattr --only-value -n ceph.dir.rctime .` +setfattr -n "ceph.dir.rctime" -v `date -d 'now+1hour' +%s` . +wait_until_changed rctime +check_rctime + cd .. rm -rf rstats_testdir echo OK diff --git a/src/client/Client.cc b/src/client/Client.cc index 0c60a4af127602..86c0b0741f7e8e 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -12367,7 +12367,13 @@ const Client::VXattr Client::_dir_vxattrs[] = { XATTR_NAME_CEPH2(dir, rsubdirs, VXATTR_RSTAT), XATTR_NAME_CEPH2(dir, rsnaps, VXATTR_RSTAT), XATTR_NAME_CEPH2(dir, rbytes, VXATTR_RSTAT), - XATTR_NAME_CEPH2(dir, rctime, VXATTR_RSTAT), + { + name: "ceph.dir.rctime", + getxattr_cb: &Client::_vxattrcb_dir_rctime, + readonly: false, + exists_cb: NULL, + flags: 0, + }, { name: "ceph.quota", getxattr_cb: &Client::_vxattrcb_quota, diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 3d5fb415d23c7f..dc2fc1ff582fbc 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -5735,6 +5735,34 @@ void Server::handle_set_vxattr(MDRequestRef& mdr, CInode *cur) auto pi = cur->project_inode(mdr); cur->setxattr_ephemeral_dist(val); pip = pi.inode.get(); + } else if (name == "ceph.dir.rctime") { + if (!cur->is_dir()) { + respond_to_request(mdr, -EINVAL); + return; + } + + uint64_t sec, nsec = 0; + try { + if (auto pos = value.find('.', 0); pos != string::npos) { + sec = boost::lexical_cast(value.substr(0, pos)); + nsec = boost::lexical_cast(value.substr(pos+1)); + } else { + sec = boost::lexical_cast(value); + } + } catch (boost::bad_lexical_cast const&) { + dout(10) << "bad vxattr value, unable to parse utime_t for " << name << dendl; + respond_to_request(mdr, -EINVAL); + return; + } + utime_t val(sec, nsec); + + if (!xlock_policylock(mdr, cur)) + return; + + auto pi = cur->project_inode(mdr); + pi.inode->rstat.rctime = val; + mdr->no_early_reply = true; + pip = pi.inode.get(); } else { dout(10) << " unknown vxattr " << name << dendl; respond_to_request(mdr, -EINVAL); diff --git a/src/mds/Server.h b/src/mds/Server.h index df0b9cb16c420c..604911017670f1 100644 --- a/src/mds/Server.h +++ b/src/mds/Server.h @@ -414,7 +414,8 @@ class Server { xattr_name == "ceph.dir.subvolume"sv || xattr_name == "ceph.dir.pin"sv || xattr_name == "ceph.dir.pin.random"sv || - xattr_name == "ceph.dir.pin.distributed"sv; + xattr_name == "ceph.dir.pin.distributed"sv || + xattr_name == "ceph.dir.rctime"sv; } static bool is_allowed_ceph_xattr(std::string_view xattr_name) {