@@ -8834,6 +8834,7 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct dentry *dentry,
88348834 __be32 status ;
88358835 struct nfsd_net * nn = net_generic (SVC_NET (rqstp ), nfsd_net_id );
88368836 struct file_lock_context * ctx ;
8837+ struct nfs4_delegation * dp = NULL ;
88378838 struct file_lease * fl ;
88388839 struct iattr attrs ;
88398840 struct nfs4_cb_fattr * ncf ;
@@ -8843,84 +8844,76 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct dentry *dentry,
88438844 ctx = locks_inode_context (inode );
88448845 if (!ctx )
88458846 return 0 ;
8847+
8848+ #define NON_NFSD_LEASE ((void *)1)
8849+
88468850 spin_lock (& ctx -> flc_lock );
88478851 for_each_file_lock (fl , & ctx -> flc_lease ) {
8848- unsigned char type = fl -> c .flc_type ;
8849-
88508852 if (fl -> c .flc_flags == FL_LAYOUT )
88518853 continue ;
8852- if (fl -> fl_lmops != & nfsd_lease_mng_ops ) {
8853- /*
8854- * non-nfs lease, if it's a lease with F_RDLCK then
8855- * we are done; there isn't any write delegation
8856- * on this inode
8857- */
8858- if (type == F_RDLCK )
8859- break ;
8860-
8861- nfsd_stats_wdeleg_getattr_inc (nn );
8862- spin_unlock (& ctx -> flc_lock );
8863-
8864- status = nfserrno (nfsd_open_break_lease (inode , NFSD_MAY_READ ));
8854+ if (fl -> c .flc_type == F_WRLCK ) {
8855+ if (fl -> fl_lmops == & nfsd_lease_mng_ops )
8856+ dp = fl -> c .flc_owner ;
8857+ else
8858+ dp = NON_NFSD_LEASE ;
8859+ }
8860+ break ;
8861+ }
8862+ if (dp == NULL || dp == NON_NFSD_LEASE ||
8863+ dp -> dl_recall .cb_clp == * (rqstp -> rq_lease_breaker )) {
8864+ spin_unlock (& ctx -> flc_lock );
8865+ if (dp == NON_NFSD_LEASE ) {
8866+ status = nfserrno (nfsd_open_break_lease (inode ,
8867+ NFSD_MAY_READ ));
88658868 if (status != nfserr_jukebox ||
88668869 !nfsd_wait_for_delegreturn (rqstp , inode ))
88678870 return status ;
8868- return 0 ;
88698871 }
8870- if ( type == F_WRLCK ) {
8871- struct nfs4_delegation * dp = fl -> c . flc_owner ;
8872+ return 0 ;
8873+ }
88728874
8873- if (dp -> dl_recall .cb_clp == * (rqstp -> rq_lease_breaker )) {
8874- spin_unlock (& ctx -> flc_lock );
8875- return 0 ;
8876- }
8877- nfsd_stats_wdeleg_getattr_inc (nn );
8878- dp = fl -> c .flc_owner ;
8879- refcount_inc (& dp -> dl_stid .sc_count );
8880- ncf = & dp -> dl_cb_fattr ;
8881- nfs4_cb_getattr (& dp -> dl_cb_fattr );
8882- spin_unlock (& ctx -> flc_lock );
8883- wait_on_bit_timeout (& ncf -> ncf_cb_flags , CB_GETATTR_BUSY ,
8884- TASK_INTERRUPTIBLE , NFSD_CB_GETATTR_TIMEOUT );
8885- if (ncf -> ncf_cb_status ) {
8886- /* Recall delegation only if client didn't respond */
8887- status = nfserrno (nfsd_open_break_lease (inode , NFSD_MAY_READ ));
8888- if (status != nfserr_jukebox ||
8889- !nfsd_wait_for_delegreturn (rqstp , inode )) {
8890- nfs4_put_stid (& dp -> dl_stid );
8891- return status ;
8892- }
8893- }
8894- if (!ncf -> ncf_file_modified &&
8895- (ncf -> ncf_initial_cinfo != ncf -> ncf_cb_change ||
8896- ncf -> ncf_cur_fsize != ncf -> ncf_cb_fsize ))
8897- ncf -> ncf_file_modified = true;
8898- if (ncf -> ncf_file_modified ) {
8899- int err ;
8900-
8901- /*
8902- * Per section 10.4.3 of RFC 8881, the server would
8903- * not update the file's metadata with the client's
8904- * modified size
8905- */
8906- attrs .ia_mtime = attrs .ia_ctime = current_time (inode );
8907- attrs .ia_valid = ATTR_MTIME | ATTR_CTIME | ATTR_DELEG ;
8908- inode_lock (inode );
8909- err = notify_change (& nop_mnt_idmap , dentry , & attrs , NULL );
8910- inode_unlock (inode );
8911- if (err ) {
8912- nfs4_put_stid (& dp -> dl_stid );
8913- return nfserrno (err );
8914- }
8915- ncf -> ncf_cur_fsize = ncf -> ncf_cb_fsize ;
8916- * size = ncf -> ncf_cur_fsize ;
8917- * modified = true;
8918- }
8919- nfs4_put_stid (& dp -> dl_stid );
8920- return 0 ;
8875+ nfsd_stats_wdeleg_getattr_inc (nn );
8876+ refcount_inc (& dp -> dl_stid .sc_count );
8877+ ncf = & dp -> dl_cb_fattr ;
8878+ nfs4_cb_getattr (& dp -> dl_cb_fattr );
8879+ spin_unlock (& ctx -> flc_lock );
8880+
8881+ wait_on_bit_timeout (& ncf -> ncf_cb_flags , CB_GETATTR_BUSY ,
8882+ TASK_INTERRUPTIBLE , NFSD_CB_GETATTR_TIMEOUT );
8883+ if (ncf -> ncf_cb_status ) {
8884+ /* Recall delegation only if client didn't respond */
8885+ status = nfserrno (nfsd_open_break_lease (inode , NFSD_MAY_READ ));
8886+ if (status != nfserr_jukebox ||
8887+ !nfsd_wait_for_delegreturn (rqstp , inode ))
8888+ goto out_status ;
8889+ }
8890+ if (!ncf -> ncf_file_modified &&
8891+ (ncf -> ncf_initial_cinfo != ncf -> ncf_cb_change ||
8892+ ncf -> ncf_cur_fsize != ncf -> ncf_cb_fsize ))
8893+ ncf -> ncf_file_modified = true;
8894+ if (ncf -> ncf_file_modified ) {
8895+ int err ;
8896+
8897+ /*
8898+ * Per section 10.4.3 of RFC 8881, the server would
8899+ * not update the file's metadata with the client's
8900+ * modified size
8901+ */
8902+ attrs .ia_mtime = attrs .ia_ctime = current_time (inode );
8903+ attrs .ia_valid = ATTR_MTIME | ATTR_CTIME | ATTR_DELEG ;
8904+ inode_lock (inode );
8905+ err = notify_change (& nop_mnt_idmap , dentry , & attrs , NULL );
8906+ inode_unlock (inode );
8907+ if (err ) {
8908+ status = nfserrno (err );
8909+ goto out_status ;
89218910 }
8922- break ;
8911+ ncf -> ncf_cur_fsize = ncf -> ncf_cb_fsize ;
8912+ * size = ncf -> ncf_cur_fsize ;
8913+ * modified = true;
89238914 }
8924- spin_unlock (& ctx -> flc_lock );
8925- return 0 ;
8915+ status = 0 ;
8916+ out_status :
8917+ nfs4_put_stid (& dp -> dl_stid );
8918+ return status ;
89268919}
0 commit comments