On Tue, Mar 29, 2022 at 09:06:23AM -0700, dai.ngo@xxxxxxxxxx wrote: > > On 3/29/22 8:24 AM, J. Bruce Fields wrote: > >On Thu, Mar 24, 2022 at 09:34:45PM -0700, Dai Ngo wrote: > >>Update nfs4_get_vfs_file and nfs4_upgrade_open to handle share > >>reservation conflict with courtesy client. > >> > >>Update nfs4_get_vfs_file and nfs4_upgrade_open to handle share > >>reservation conflict with courtesy client. > >> > >>When we have deny/access conflict we walk the fi_stateids of the > >>file in question, looking for open stateid and check the deny/access > >>of that stateid against the one from the open request. If there is > >>a conflict then we check if the client that owns that stateid is > >>a courtesy client. If it is then we set the client state to > >>CLIENT_EXPIRED and allow the open request to continue. We have > >>to scan all the stateid's of the file since the conflict can be > >>caused by multiple open stateid's. > >> > >>Client with CLIENT_EXPIRED is expired by the laundromat. > >> > >>Signed-off-by: Dai Ngo <dai.ngo@xxxxxxxxxx> > >>--- > >> fs/nfsd/nfs4state.c | 85 +++++++++++++++++++++++++++++++++++++++++++++-------- > >> 1 file changed, 72 insertions(+), 13 deletions(-) > >> > >>diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c > >>index f20c75890594..fe8969ba94b3 100644 > >>--- a/fs/nfsd/nfs4state.c > >>+++ b/fs/nfsd/nfs4state.c > >>@@ -701,9 +701,56 @@ __nfs4_file_get_access(struct nfs4_file *fp, u32 access) > >> atomic_inc(&fp->fi_access[O_RDONLY]); > >> } > >>+/* > >>+ * Check if courtesy clients have conflicting access and resolve it if possible > >>+ * > >>+ * access: is op_share_access if share_access is true. > >>+ * Check if access mode, op_share_access, would conflict with > >>+ * the current deny mode of the file 'fp'. > >>+ * access: is op_share_deny if share_access is false. > >>+ * Check if the deny mode, op_share_deny, would conflict with > >>+ * current access of the file 'fp'. > >>+ * stp: skip checking this entry. > >>+ * new_stp: normal open, not open upgrade. > >>+ * > >>+ * Function returns: > >>+ * false - access/deny mode conflict with normal client. > >>+ * true - no conflict or conflict with courtesy client(s) is resolved. > >>+ */ > >>+static bool > >>+nfs4_resolve_deny_conflicts_locked(struct nfs4_file *fp, bool new_stp, > >>+ struct nfs4_ol_stateid *stp, u32 access, bool share_access) > >>+{ > >>+ struct nfs4_ol_stateid *st; > >>+ struct nfs4_client *clp; > >>+ bool conflict = true; > >>+ unsigned char bmap; > >>+ > >>+ lockdep_assert_held(&fp->fi_lock); > >>+ list_for_each_entry(st, &fp->fi_stateids, st_perfile) { > >>+ /* ignore lock stateid */ > >>+ if (st->st_openstp) > >>+ continue; > >>+ if (st == stp && new_stp) > >>+ continue; > >>+ /* check file access against deny mode or vice versa */ > >>+ bmap = share_access ? st->st_deny_bmap : st->st_access_bmap; > >>+ if (!(access & bmap_to_share_mode(bmap))) > >>+ continue; > >As I said before, I recommend just doing *both* checks here. Then you > >can remove the "bool share_access" argument. I think that'll make the > >code easier to read. > > Bruce, I'm not clear how to check both here as I mentioned in my previous > email. > > nfs4_resolve_deny_conflicts_locked is called from nfs4_file_get_access > and nfs4_file_check_deny to check either access or deny mode separately > so how do we check both access and deny in nfs4_resolve_deny_conflicts_locked? Sorry, I forgot. Uh, I guess on a quick skim I don't see a way to do that nicely, so, fine, I'm OK with it as is. --b.