@@ -5914,6 +5914,28 @@ static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
59145914 }
59155915}
59165916
5917+ static bool
5918+ nfs4_delegation_stat (struct nfs4_delegation * dp , struct svc_fh * currentfh ,
5919+ struct kstat * stat )
5920+ {
5921+ struct nfsd_file * nf = find_rw_file (dp -> dl_stid .sc_file );
5922+ struct path path ;
5923+ int rc ;
5924+
5925+ if (!nf )
5926+ return false;
5927+
5928+ path .mnt = currentfh -> fh_export -> ex_path .mnt ;
5929+ path .dentry = file_dentry (nf -> nf_file );
5930+
5931+ rc = vfs_getattr (& path , stat ,
5932+ (STATX_SIZE | STATX_CTIME | STATX_CHANGE_COOKIE ),
5933+ AT_STATX_SYNC_AS_STAT );
5934+
5935+ nfsd_file_put (nf );
5936+ return rc == 0 ;
5937+ }
5938+
59175939/*
59185940 * The Linux NFS server does not offer write delegations to NFSv4.0
59195941 * clients in order to avoid conflicts between write delegations and
@@ -5949,7 +5971,6 @@ nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
59495971 int cb_up ;
59505972 int status = 0 ;
59515973 struct kstat stat ;
5952- struct path path ;
59535974
59545975 cb_up = nfsd4_cb_channel_good (oo -> oo_owner .so_client );
59555976 open -> op_recall = false;
@@ -5985,20 +6006,16 @@ nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
59856006 memcpy (& open -> op_delegate_stateid , & dp -> dl_stid .sc_stateid , sizeof (dp -> dl_stid .sc_stateid ));
59866007
59876008 if (open -> op_share_access & NFS4_SHARE_ACCESS_WRITE ) {
5988- open -> op_delegate_type = NFS4_OPEN_DELEGATE_WRITE ;
5989- trace_nfsd_deleg_write (& dp -> dl_stid .sc_stateid );
5990- path .mnt = currentfh -> fh_export -> ex_path .mnt ;
5991- path .dentry = currentfh -> fh_dentry ;
5992- if (vfs_getattr (& path , & stat ,
5993- (STATX_SIZE | STATX_CTIME | STATX_CHANGE_COOKIE ),
5994- AT_STATX_SYNC_AS_STAT )) {
6009+ if (!nfs4_delegation_stat (dp , currentfh , & stat )) {
59956010 nfs4_put_stid (& dp -> dl_stid );
59966011 destroy_delegation (dp );
59976012 goto out_no_deleg ;
59986013 }
6014+ open -> op_delegate_type = NFS4_OPEN_DELEGATE_WRITE ;
59996015 dp -> dl_cb_fattr .ncf_cur_fsize = stat .size ;
60006016 dp -> dl_cb_fattr .ncf_initial_cinfo =
60016017 nfsd4_change_attribute (& stat , d_inode (currentfh -> fh_dentry ));
6018+ trace_nfsd_deleg_write (& dp -> dl_stid .sc_stateid );
60026019 } else {
60036020 open -> op_delegate_type = NFS4_OPEN_DELEGATE_READ ;
60046021 trace_nfsd_deleg_read (& dp -> dl_stid .sc_stateid );
0 commit comments