Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a93864d9 authored by Ronnie Sahlberg's avatar Ronnie Sahlberg Committed by Steve French
Browse files

cifs: add lease tracking to the cached root fid



Use a read lease for the cached root fid so that we can detect
when the content of the directory changes (via a break) at which time
we close the handle. On next access to the root the handle will be reopened
and cached again.

Signed-off-by: default avatarRonnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 2fbb5644
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -883,6 +883,14 @@ cap_unix(struct cifs_ses *ses)
	return ses->server->vals->cap_unix & ses->capabilities;
}

struct cached_fid {
	bool is_valid:1;	/* Do we have a useable root fid */
	struct cifs_fid *fid;
	struct mutex fid_mutex;
	struct cifs_tcon *tcon;
	struct work_struct lease_break;
};

/*
 * there is one of these for each connection to a resource on a particular
 * session
@@ -987,9 +995,7 @@ struct cifs_tcon {
	struct fscache_cookie *fscache;	/* cookie for share */
#endif
	struct list_head pending_opens;	/* list of incomplete opens */
	bool valid_root_fid:1;	/* Do we have a useable root fid */
	struct mutex prfid_mutex; /* prevents reopen race after dead ses*/
	struct cifs_fid *prfid;	/* handle to the directory at top of share */
	struct cached_fid crfid; /* Cached root fid */
	/* BB add field for back pointer to sb struct(s)? */
};

+1 −0
Original line number Diff line number Diff line
@@ -552,6 +552,7 @@ enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
struct cifs_aio_ctx *cifs_aio_ctx_alloc(void);
void cifs_aio_ctx_release(struct kref *refcount);
int setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw);
void smb2_cached_lease_break(struct work_struct *work);

int cifs_alloc_hash(const char *name, struct crypto_shash **shash,
		    struct sdesc **sdesc);
+4 −4
Original line number Diff line number Diff line
@@ -107,10 +107,10 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
	}
	spin_unlock(&tcon->open_file_lock);

	mutex_lock(&tcon->prfid_mutex);
	tcon->valid_root_fid = false;
	memset(tcon->prfid, 0, sizeof(struct cifs_fid));
	mutex_unlock(&tcon->prfid_mutex);
	mutex_lock(&tcon->crfid.fid_mutex);
	tcon->crfid.is_valid = false;
	memset(tcon->crfid.fid, 0, sizeof(struct cifs_fid));
	mutex_unlock(&tcon->crfid.fid_mutex);

	/*
	 * BB Add call to invalidate_inodes(sb) for all superblocks mounted
+4 −3
Original line number Diff line number Diff line
@@ -117,8 +117,9 @@ tconInfoAlloc(void)
		INIT_LIST_HEAD(&ret_buf->openFileList);
		INIT_LIST_HEAD(&ret_buf->tcon_list);
		spin_lock_init(&ret_buf->open_file_lock);
		mutex_init(&ret_buf->prfid_mutex);
		ret_buf->prfid = kzalloc(sizeof(struct cifs_fid), GFP_KERNEL);
		mutex_init(&ret_buf->crfid.fid_mutex);
		ret_buf->crfid.fid = kzalloc(sizeof(struct cifs_fid),
					     GFP_KERNEL);
#ifdef CONFIG_CIFS_STATS
		spin_lock_init(&ret_buf->stat_lock);
#endif
@@ -136,7 +137,7 @@ tconInfoFree(struct cifs_tcon *buf_to_free)
	atomic_dec(&tconInfoAllocCount);
	kfree(buf_to_free->nativeFileSystem);
	kzfree(buf_to_free->password);
	kfree(buf_to_free->prfid);
	kfree(buf_to_free->crfid.fid);
	kfree(buf_to_free);
}

+15 −1
Original line number Diff line number Diff line
@@ -492,10 +492,11 @@ cifs_ses_oplock_break(struct work_struct *work)
{
	struct smb2_lease_break_work *lw = container_of(work,
				struct smb2_lease_break_work, lease_break);
	int rc;
	int rc = 0;

	rc = SMB2_lease_break(0, tlink_tcon(lw->tlink), lw->lease_key,
			      lw->lease_state);

	cifs_dbg(FYI, "Lease release rc %d\n", rc);
	cifs_put_tlink(lw->tlink);
	kfree(lw);
@@ -561,6 +562,7 @@ smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp,

		open->oplock = lease_state;
	}

	return found;
}

@@ -603,6 +605,18 @@ smb2_is_valid_lease_break(char *buffer)
					return true;
				}
				spin_unlock(&tcon->open_file_lock);

				if (tcon->crfid.is_valid &&
				    !memcmp(rsp->LeaseKey,
					    tcon->crfid.fid->lease_key,
					    SMB2_LEASE_KEY_SIZE)) {
					INIT_WORK(&tcon->crfid.lease_break,
						  smb2_cached_lease_break);
					queue_work(cifsiod_wq,
						   &tcon->crfid.lease_break);
					spin_unlock(&cifs_tcp_ses_lock);
					return true;
				}
			}
		}
	}
Loading