diff --git a/qa/workunits/fs/misc/rstats.sh b/qa/workunits/fs/misc/rstats.sh index e6b3eddf287e8..951cd274df7d5 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 86e01944f2e6b..2298d0074678b 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -12918,7 +12918,13 @@ const Client::VXattr Client::_dir_vxattrs[] = { XATTR_NAME_CEPH(dir, rsubdirs, VXATTR_RSTAT), XATTR_NAME_CEPH(dir, rsnaps, VXATTR_RSTAT), XATTR_NAME_CEPH(dir, rbytes, VXATTR_RSTAT), - XATTR_NAME_CEPH(dir, rctime, VXATTR_RSTAT), + { + name: "ceph.dir.rctime", + getxattr_cb: &Client::_vxattrcb_dir_rctime, + readonly: false, + exists_cb: NULL, + flags: VXATTR_RSTAT, + }, { name: "ceph.quota", getxattr_cb: &Client::_vxattrcb_quota, diff --git a/src/mds/Server.cc b/src/mds/Server.cc index b0113d73fb50f..86b73b27ef97f 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -5324,6 +5324,21 @@ bool Server::xlock_policylock(MDRequestRef& mdr, CInode *in, bool want_layout, b return true; } +bool Server::wrlock_nestlock(MDRequestRef& mdr, CInode *in) +{ + if (mdr->locking_state & MutationImpl::ALL_LOCKED) + return true; + + MutationImpl::LockOpVec lov; + lov.add_wrlock(&in->nestlock); + + if (!mds->locker->acquire_locks(mdr, lov)) + return false; + + mdr->locking_state |= MutationImpl::ALL_LOCKED; + return true; +} + CInode* Server::try_get_auth_inode(MDRequestRef& mdr, inodeno_t ino) { CInode *in = mdcache->get_inode(ino); @@ -5861,6 +5876,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 (!wrlock_nestlock(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, -CEPHFS_EINVAL); diff --git a/src/mds/Server.h b/src/mds/Server.h index 76f38717c7265..b0d5161b10c36 100644 --- a/src/mds/Server.h +++ b/src/mds/Server.h @@ -206,6 +206,7 @@ class Server { bool xlock_policylock(MDRequestRef& mdr, CInode *in, bool want_layout=false, bool xlock_snaplock=false); + bool wrlock_nestlock(MDRequestRef& mdr, CInode *in); CInode* try_get_auth_inode(MDRequestRef& mdr, inodeno_t ino); void handle_client_setattr(MDRequestRef& mdr); void handle_client_setlayout(MDRequestRef& mdr); @@ -418,7 +419,8 @@ class Server { xattr_name == "ceph.dir.subvolume" || xattr_name == "ceph.dir.pin" || xattr_name == "ceph.dir.pin.random" || - xattr_name == "ceph.dir.pin.distributed"; + xattr_name == "ceph.dir.pin.distributed" || + xattr_name == "ceph.dir.rctime"; } static bool is_allowed_ceph_xattr(std::string_view xattr_name) {