summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEnzo Matsumiya <ematsumiya@suse.de>2024-11-13 18:41:57 -0300
committerEnzo Matsumiya <ematsumiya@suse.de>2024-11-14 15:54:44 -0300
commita10fb4913a4ad6d10166d1feba26fbc8b9deb322 (patch)
treed7a5040015e7e1ef691debcce7314ecf12bd1501
parente0566abf2543a74e339660f0ffe45498dd439100 (diff)
downloadlinux-a10fb4913a4ad6d10166d1feba26fbc8b9deb322.tar.gz
linux-a10fb4913a4ad6d10166d1feba26fbc8b9deb322.tar.bz2
linux-a10fb4913a4ad6d10166d1feba26fbc8b9deb322.zip
smb: client: remove ->set_oplock_level op
Add set_oplock_level() that chooses the correct function based if SMB 2.1 or >= 3.0. Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
-rw-r--r--fs/smb/client/cifsglob.h3
-rw-r--r--fs/smb/client/smb2ops.c114
2 files changed, 58 insertions, 59 deletions
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index 5a8ed847bdc7..0e2a532ff1ab 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -302,9 +302,6 @@ struct smb_version_operations {
struct TCP_Server_Info *server);
int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *,
bool allocate_crypto);
- /* set oplock level for the inode */
- void (*set_oplock_level)(struct cifsInodeInfo *, __u32, unsigned int,
- bool *);
/* create lease context buffer for CREATE request */
char * (*create_lease_buf)(u8 *lease_key, u8 oplock);
/* parse lease context buffer and return oplock/epoch info */
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 416104bc0966..6018411f9cbf 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -1388,6 +1388,9 @@ void smb2_print_stats(struct seq_file *m, struct cifs_tcon *tcon)
atomic_read(&failed[SMB2_OPLOCK_BREAK_HE]));
}
+static void set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, unsigned int epoch,
+ bool *purge_cache, u16 protocol_id);
+
void smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
{
struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
@@ -1399,8 +1402,7 @@ void smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock
#ifdef CONFIG_CIFS_DEBUG2
cfile->fid.mid = fid->mid;
#endif /* CIFS_DEBUG2 */
- server->ops->set_oplock_level(cinode, oplock, fid->epoch,
- &fid->purge_cache);
+ set_oplock_level(cinode, oplock, fid->epoch, &fid->purge_cache, server->vals->protocol_id);
cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode);
memcpy(cfile->fid.create_guid, fid->create_guid, 16);
}
@@ -3846,50 +3848,16 @@ static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode,
return -EOPNOTSUPP;
}
-static void
-smb2_downgrade_oplock(struct TCP_Server_Info *server,
- struct cifsInodeInfo *cinode, __u32 oplock,
- unsigned int epoch, bool *purge_cache)
-{
- server->ops->set_oplock_level(cinode, oplock, 0, NULL);
-}
-
-static void
-smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
- unsigned int epoch, bool *purge_cache);
-
-static void
-smb3_downgrade_oplock(struct TCP_Server_Info *server,
- struct cifsInodeInfo *cinode, __u32 oplock,
- unsigned int epoch, bool *purge_cache)
-{
- unsigned int old_state = cinode->oplock;
- unsigned int old_epoch = cinode->epoch;
- unsigned int new_state;
-
- if (epoch > old_epoch) {
- smb21_set_oplock_level(cinode, oplock, 0, NULL);
- cinode->epoch = epoch;
- }
-
- new_state = cinode->oplock;
- *purge_cache = false;
-
- if ((old_state & CIFS_CACHE_READ_FLG) != 0 &&
- (new_state & CIFS_CACHE_READ_FLG) == 0)
- *purge_cache = true;
- else if (old_state == new_state && (epoch - old_epoch > 1))
- *purge_cache = true;
-}
-
-static void
-smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
- unsigned int epoch, bool *purge_cache)
+static void __set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, unsigned int epoch,
+ bool *purge_cache)
{
oplock &= 0xFF;
cinode->lease_granted = false;
+
if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
return;
+
+ cinode->oplock = 0;
if (oplock == SMB2_OPLOCK_LEVEL_BATCH) {
cinode->oplock = CIFS_CACHE_RHW_FLG;
cifs_dbg(FYI, "Batch Oplock granted on inode %p\n",
@@ -3902,13 +3870,11 @@ smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
cinode->oplock = CIFS_CACHE_READ_FLG;
cifs_dbg(FYI, "Level II Oplock granted on inode %p\n",
&cinode->netfs.inode);
- } else
- cinode->oplock = 0;
+ }
}
-static void
-smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
- unsigned int epoch, bool *purge_cache)
+static void smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, unsigned int epoch,
+ bool *purge_cache)
{
char message[5] = {0};
unsigned int new_oplock = 0;
@@ -3920,8 +3886,7 @@ smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
/* Check if the server granted an oplock rather than a lease */
if (oplock & SMB2_OPLOCK_LEVEL_EXCLUSIVE)
- return smb2_set_oplock_level(cinode, oplock, epoch,
- purge_cache);
+ return __set_oplock_level(cinode, oplock, epoch, purge_cache);
if (oplock & SMB2_LEASE_READ_CACHING_HE) {
new_oplock |= CIFS_CACHE_READ_FLG;
@@ -3939,13 +3904,11 @@ smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
strscpy(message, "None");
cinode->oplock = new_oplock;
- cifs_dbg(FYI, "%s Lease granted on inode %p\n", message,
- &cinode->netfs.inode);
+ cifs_dbg(FYI, "%s Lease granted on inode %p\n", message, &cinode->netfs.inode);
}
-static void
-smb3_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
- unsigned int epoch, bool *purge_cache)
+static void smb3_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, unsigned int epoch,
+ bool *purge_cache)
{
unsigned int old_oplock = cinode->oplock;
@@ -3978,6 +3941,48 @@ smb3_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
}
}
+static void set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, unsigned int epoch,
+ bool *purge_cache, u16 protocol_id)
+{
+ if (protocol_id >= SMB30_PROT_ID)
+ smb3_set_oplock_level(cinode, oplock, epoch, purge_cache);
+ else if (protocol_id == SMB21_PROT_ID)
+ smb21_set_oplock_level(cinode, oplock, epoch, purge_cache);
+ else
+ pr_warn_once("unsupported protocol id 0x%x\n", protocol_id);
+}
+
+static void smb2_downgrade_oplock(struct TCP_Server_Info *server, struct cifsInodeInfo *cinode,
+ __u32 oplock, unsigned int epoch, bool *purge_cache)
+{
+ WARN_ON(server->vals->protocol_id != SMB21_PROT_ID);
+
+ set_oplock_level(cinode, oplock, 0, NULL, server->vals->protocol_id);
+}
+
+static void
+smb3_downgrade_oplock(struct TCP_Server_Info *server,
+ struct cifsInodeInfo *cinode, __u32 oplock,
+ unsigned int epoch, bool *purge_cache)
+{
+ unsigned int old_state = cinode->oplock;
+ unsigned int old_epoch = cinode->epoch;
+ unsigned int new_state;
+
+ if (epoch > old_epoch) {
+ smb21_set_oplock_level(cinode, oplock, 0, NULL);
+ cinode->epoch = epoch;
+ }
+
+ new_state = cinode->oplock;
+ *purge_cache = false;
+
+ if ((old_state & CIFS_CACHE_READ_FLG) != 0 &&
+ (new_state & CIFS_CACHE_READ_FLG) == 0)
+ *purge_cache = true;
+ else if (old_state == new_state && (epoch - old_epoch > 1))
+ *purge_cache = true;
+}
bool smb21_is_read_op(__u32 oplock)
{
@@ -5086,7 +5091,6 @@ struct smb_version_operations smb21_operations = {
.qfs_tcon = smb2_qfs_tcon,
.queryfs = smb2_queryfs,
.calc_signature = smb2_calc_signature,
- .set_oplock_level = smb21_set_oplock_level,
.create_lease_buf = smb2_create_lease_buf,
.parse_lease_buf = smb2_parse_lease_buf,
};
@@ -5102,7 +5106,6 @@ struct smb_version_operations smb30_operations = {
.queryfs = smb2_queryfs,
.generate_signingkey = generate_smb30signingkey,
.calc_signature = smb3_calc_signature,
- .set_oplock_level = smb3_set_oplock_level,
.create_lease_buf = smb3_create_lease_buf,
.parse_lease_buf = smb3_parse_lease_buf,
.duplicate_extents = smb2_duplicate_extents,
@@ -5123,7 +5126,6 @@ struct smb_version_operations smb311_operations = {
.queryfs = smb311_queryfs,
.generate_signingkey = generate_smb311signingkey,
.calc_signature = smb3_calc_signature,
- .set_oplock_level = smb3_set_oplock_level,
.create_lease_buf = smb3_create_lease_buf,
.parse_lease_buf = smb3_parse_lease_buf,
.duplicate_extents = smb2_duplicate_extents,