@@ -2480,6 +2480,34 @@ int __ceph_setattr(struct mnt_idmap *idmap, struct inode *inode,
24802480 bool lock_snap_rwsem = false;
24812481 bool fill_fscrypt ;
24822482 int truncate_retry = 20 ; /* The RMW will take around 50ms */
2483+ struct dentry * dentry ;
2484+ char * path ;
2485+ int pathlen ;
2486+ u64 pathbase ;
2487+ bool do_sync = false;
2488+
2489+ dentry = d_find_alias (inode );
2490+ if (!dentry ) {
2491+ do_sync = true;
2492+ } else {
2493+ path = ceph_mdsc_build_path (mdsc , dentry , & pathlen , & pathbase , 0 );
2494+ if (IS_ERR (path )) {
2495+ do_sync = true;
2496+ err = 0 ;
2497+ } else {
2498+ err = ceph_mds_check_access (mdsc , path , MAY_WRITE );
2499+ }
2500+ ceph_mdsc_free_path (path , pathlen );
2501+ dput (dentry );
2502+
2503+ /* For none EACCES cases will let the MDS do the mds auth check */
2504+ if (err == - EACCES ) {
2505+ return err ;
2506+ } else if (err < 0 ) {
2507+ do_sync = true;
2508+ err = 0 ;
2509+ }
2510+ }
24832511
24842512retry :
24852513 prealloc_cf = ceph_alloc_cap_flush ();
@@ -2526,7 +2554,7 @@ int __ceph_setattr(struct mnt_idmap *idmap, struct inode *inode,
25262554 /* It should never be re-set once set */
25272555 WARN_ON_ONCE (ci -> fscrypt_auth );
25282556
2529- if (issued & CEPH_CAP_AUTH_EXCL ) {
2557+ if (! do_sync && ( issued & CEPH_CAP_AUTH_EXCL ) ) {
25302558 dirtied |= CEPH_CAP_AUTH_EXCL ;
25312559 kfree (ci -> fscrypt_auth );
25322560 ci -> fscrypt_auth = (u8 * )cia -> fscrypt_auth ;
@@ -2555,7 +2583,7 @@ int __ceph_setattr(struct mnt_idmap *idmap, struct inode *inode,
25552583 ceph_vinop (inode ),
25562584 from_kuid (& init_user_ns , inode -> i_uid ),
25572585 from_kuid (& init_user_ns , attr -> ia_uid ));
2558- if (issued & CEPH_CAP_AUTH_EXCL ) {
2586+ if (! do_sync && ( issued & CEPH_CAP_AUTH_EXCL ) ) {
25592587 inode -> i_uid = fsuid ;
25602588 dirtied |= CEPH_CAP_AUTH_EXCL ;
25612589 } else if ((issued & CEPH_CAP_AUTH_SHARED ) == 0 ||
@@ -2573,7 +2601,7 @@ int __ceph_setattr(struct mnt_idmap *idmap, struct inode *inode,
25732601 ceph_vinop (inode ),
25742602 from_kgid (& init_user_ns , inode -> i_gid ),
25752603 from_kgid (& init_user_ns , attr -> ia_gid ));
2576- if (issued & CEPH_CAP_AUTH_EXCL ) {
2604+ if (! do_sync && ( issued & CEPH_CAP_AUTH_EXCL ) ) {
25772605 inode -> i_gid = fsgid ;
25782606 dirtied |= CEPH_CAP_AUTH_EXCL ;
25792607 } else if ((issued & CEPH_CAP_AUTH_SHARED ) == 0 ||
@@ -2587,7 +2615,7 @@ int __ceph_setattr(struct mnt_idmap *idmap, struct inode *inode,
25872615 if (ia_valid & ATTR_MODE ) {
25882616 doutc (cl , "%p %llx.%llx mode 0%o -> 0%o\n" , inode ,
25892617 ceph_vinop (inode ), inode -> i_mode , attr -> ia_mode );
2590- if (issued & CEPH_CAP_AUTH_EXCL ) {
2618+ if (! do_sync && ( issued & CEPH_CAP_AUTH_EXCL ) ) {
25912619 inode -> i_mode = attr -> ia_mode ;
25922620 dirtied |= CEPH_CAP_AUTH_EXCL ;
25932621 } else if ((issued & CEPH_CAP_AUTH_SHARED ) == 0 ||
@@ -2606,11 +2634,11 @@ int __ceph_setattr(struct mnt_idmap *idmap, struct inode *inode,
26062634 inode , ceph_vinop (inode ),
26072635 atime .tv_sec , atime .tv_nsec ,
26082636 attr -> ia_atime .tv_sec , attr -> ia_atime .tv_nsec );
2609- if (issued & CEPH_CAP_FILE_EXCL ) {
2637+ if (! do_sync && ( issued & CEPH_CAP_FILE_EXCL ) ) {
26102638 ci -> i_time_warp_seq ++ ;
26112639 inode_set_atime_to_ts (inode , attr -> ia_atime );
26122640 dirtied |= CEPH_CAP_FILE_EXCL ;
2613- } else if ((issued & CEPH_CAP_FILE_WR ) &&
2641+ } else if (! do_sync && (issued & CEPH_CAP_FILE_WR ) &&
26142642 timespec64_compare (& atime ,
26152643 & attr -> ia_atime ) < 0 ) {
26162644 inode_set_atime_to_ts (inode , attr -> ia_atime );
@@ -2646,7 +2674,7 @@ int __ceph_setattr(struct mnt_idmap *idmap, struct inode *inode,
26462674 CEPH_FSCRYPT_BLOCK_SIZE ));
26472675 req -> r_fscrypt_file = attr -> ia_size ;
26482676 fill_fscrypt = true;
2649- } else if ((issued & CEPH_CAP_FILE_EXCL ) && attr -> ia_size >= isize ) {
2677+ } else if (! do_sync && (issued & CEPH_CAP_FILE_EXCL ) && attr -> ia_size >= isize ) {
26502678 if (attr -> ia_size > isize ) {
26512679 i_size_write (inode , attr -> ia_size );
26522680 inode -> i_blocks = calc_inode_blocks (attr -> ia_size );
@@ -2683,11 +2711,11 @@ int __ceph_setattr(struct mnt_idmap *idmap, struct inode *inode,
26832711 inode , ceph_vinop (inode ),
26842712 mtime .tv_sec , mtime .tv_nsec ,
26852713 attr -> ia_mtime .tv_sec , attr -> ia_mtime .tv_nsec );
2686- if (issued & CEPH_CAP_FILE_EXCL ) {
2714+ if (! do_sync && ( issued & CEPH_CAP_FILE_EXCL ) ) {
26872715 ci -> i_time_warp_seq ++ ;
26882716 inode_set_mtime_to_ts (inode , attr -> ia_mtime );
26892717 dirtied |= CEPH_CAP_FILE_EXCL ;
2690- } else if ((issued & CEPH_CAP_FILE_WR ) &&
2718+ } else if (! do_sync && (issued & CEPH_CAP_FILE_WR ) &&
26912719 timespec64_compare (& mtime , & attr -> ia_mtime ) < 0 ) {
26922720 inode_set_mtime_to_ts (inode , attr -> ia_mtime );
26932721 dirtied |= CEPH_CAP_FILE_WR ;
0 commit comments