@@ -2480,6 +2480,34 @@ int __ceph_setattr(struct mnt_idmap *idmap, struct inode *inode,
2480
2480
bool lock_snap_rwsem = false;
2481
2481
bool fill_fscrypt ;
2482
2482
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
+ }
2483
2511
2484
2512
retry :
2485
2513
prealloc_cf = ceph_alloc_cap_flush ();
@@ -2526,7 +2554,7 @@ int __ceph_setattr(struct mnt_idmap *idmap, struct inode *inode,
2526
2554
/* It should never be re-set once set */
2527
2555
WARN_ON_ONCE (ci -> fscrypt_auth );
2528
2556
2529
- if (issued & CEPH_CAP_AUTH_EXCL ) {
2557
+ if (! do_sync && ( issued & CEPH_CAP_AUTH_EXCL ) ) {
2530
2558
dirtied |= CEPH_CAP_AUTH_EXCL ;
2531
2559
kfree (ci -> fscrypt_auth );
2532
2560
ci -> fscrypt_auth = (u8 * )cia -> fscrypt_auth ;
@@ -2555,7 +2583,7 @@ int __ceph_setattr(struct mnt_idmap *idmap, struct inode *inode,
2555
2583
ceph_vinop (inode ),
2556
2584
from_kuid (& init_user_ns , inode -> i_uid ),
2557
2585
from_kuid (& init_user_ns , attr -> ia_uid ));
2558
- if (issued & CEPH_CAP_AUTH_EXCL ) {
2586
+ if (! do_sync && ( issued & CEPH_CAP_AUTH_EXCL ) ) {
2559
2587
inode -> i_uid = fsuid ;
2560
2588
dirtied |= CEPH_CAP_AUTH_EXCL ;
2561
2589
} else if ((issued & CEPH_CAP_AUTH_SHARED ) == 0 ||
@@ -2573,7 +2601,7 @@ int __ceph_setattr(struct mnt_idmap *idmap, struct inode *inode,
2573
2601
ceph_vinop (inode ),
2574
2602
from_kgid (& init_user_ns , inode -> i_gid ),
2575
2603
from_kgid (& init_user_ns , attr -> ia_gid ));
2576
- if (issued & CEPH_CAP_AUTH_EXCL ) {
2604
+ if (! do_sync && ( issued & CEPH_CAP_AUTH_EXCL ) ) {
2577
2605
inode -> i_gid = fsgid ;
2578
2606
dirtied |= CEPH_CAP_AUTH_EXCL ;
2579
2607
} else if ((issued & CEPH_CAP_AUTH_SHARED ) == 0 ||
@@ -2587,7 +2615,7 @@ int __ceph_setattr(struct mnt_idmap *idmap, struct inode *inode,
2587
2615
if (ia_valid & ATTR_MODE ) {
2588
2616
doutc (cl , "%p %llx.%llx mode 0%o -> 0%o\n" , inode ,
2589
2617
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 ) ) {
2591
2619
inode -> i_mode = attr -> ia_mode ;
2592
2620
dirtied |= CEPH_CAP_AUTH_EXCL ;
2593
2621
} else if ((issued & CEPH_CAP_AUTH_SHARED ) == 0 ||
@@ -2606,11 +2634,11 @@ int __ceph_setattr(struct mnt_idmap *idmap, struct inode *inode,
2606
2634
inode , ceph_vinop (inode ),
2607
2635
atime .tv_sec , atime .tv_nsec ,
2608
2636
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 ) ) {
2610
2638
ci -> i_time_warp_seq ++ ;
2611
2639
inode_set_atime_to_ts (inode , attr -> ia_atime );
2612
2640
dirtied |= CEPH_CAP_FILE_EXCL ;
2613
- } else if ((issued & CEPH_CAP_FILE_WR ) &&
2641
+ } else if (! do_sync && (issued & CEPH_CAP_FILE_WR ) &&
2614
2642
timespec64_compare (& atime ,
2615
2643
& attr -> ia_atime ) < 0 ) {
2616
2644
inode_set_atime_to_ts (inode , attr -> ia_atime );
@@ -2646,7 +2674,7 @@ int __ceph_setattr(struct mnt_idmap *idmap, struct inode *inode,
2646
2674
CEPH_FSCRYPT_BLOCK_SIZE ));
2647
2675
req -> r_fscrypt_file = attr -> ia_size ;
2648
2676
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 ) {
2650
2678
if (attr -> ia_size > isize ) {
2651
2679
i_size_write (inode , attr -> ia_size );
2652
2680
inode -> i_blocks = calc_inode_blocks (attr -> ia_size );
@@ -2683,11 +2711,11 @@ int __ceph_setattr(struct mnt_idmap *idmap, struct inode *inode,
2683
2711
inode , ceph_vinop (inode ),
2684
2712
mtime .tv_sec , mtime .tv_nsec ,
2685
2713
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 ) ) {
2687
2715
ci -> i_time_warp_seq ++ ;
2688
2716
inode_set_mtime_to_ts (inode , attr -> ia_mtime );
2689
2717
dirtied |= CEPH_CAP_FILE_EXCL ;
2690
- } else if ((issued & CEPH_CAP_FILE_WR ) &&
2718
+ } else if (! do_sync && (issued & CEPH_CAP_FILE_WR ) &&
2691
2719
timespec64_compare (& mtime , & attr -> ia_mtime ) < 0 ) {
2692
2720
inode_set_mtime_to_ts (inode , attr -> ia_mtime );
2693
2721
dirtied |= CEPH_CAP_FILE_WR ;
0 commit comments