|
@@ -23,6 +23,7 @@
|
|
|
#include "smb2proto.h"
|
|
|
#include "cifsproto.h"
|
|
|
#include "cifs_debug.h"
|
|
|
+#include "smb2status.h"
|
|
|
|
|
|
static int
|
|
|
change_conf(struct TCP_Server_Info *server)
|
|
@@ -207,13 +208,14 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
int rc;
|
|
|
__u64 persistent_fid, volatile_fid;
|
|
|
__le16 *utf16_path;
|
|
|
+ __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
|
|
|
|
|
|
utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
|
|
|
if (!utf16_path)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid,
|
|
|
- FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0, NULL);
|
|
|
+ FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0, &oplock, NULL);
|
|
|
if (rc) {
|
|
|
kfree(utf16_path);
|
|
|
return rc;
|
|
@@ -358,10 +360,10 @@ smb2_print_stats(struct seq_file *m, struct cifs_tcon *tcon)
|
|
|
static void
|
|
|
smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
|
|
|
{
|
|
|
- /* struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); */
|
|
|
+ struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
|
|
|
cfile->fid.persistent_fid = fid->persistent_fid;
|
|
|
cfile->fid.volatile_fid = fid->volatile_fid;
|
|
|
- /* cifs_set_oplock_level(cinode, oplock); */
|
|
|
+ smb2_set_oplock_level(cinode, oplock);
|
|
|
/* cinode->can_cache_brlcks = cinode->clientCanCacheAll; */
|
|
|
}
|
|
|
|
|
@@ -432,6 +434,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
{
|
|
|
__le16 *utf16_path;
|
|
|
int rc;
|
|
|
+ __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
|
|
|
__u64 persistent_fid, volatile_fid;
|
|
|
|
|
|
utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
|
|
@@ -440,7 +443,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
|
|
|
rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid,
|
|
|
FILE_READ_ATTRIBUTES | FILE_READ_DATA, FILE_OPEN, 0, 0,
|
|
|
- NULL);
|
|
|
+ &oplock, NULL);
|
|
|
kfree(utf16_path);
|
|
|
if (rc) {
|
|
|
cERROR(1, "open dir failed");
|
|
@@ -477,6 +480,28 @@ smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
return SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+* If we negotiate SMB2 protocol and get STATUS_PENDING - update
|
|
|
+* the number of credits and return true. Otherwise - return false.
|
|
|
+*/
|
|
|
+static bool
|
|
|
+smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length)
|
|
|
+{
|
|
|
+ struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
|
|
|
+
|
|
|
+ if (le32_to_cpu(hdr->Status) != STATUS_PENDING)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (!length) {
|
|
|
+ spin_lock(&server->req_lock);
|
|
|
+ server->credits += le16_to_cpu(hdr->CreditRequest);
|
|
|
+ spin_unlock(&server->req_lock);
|
|
|
+ wake_up(&server->request_q);
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
struct smb_version_operations smb21_operations = {
|
|
|
.setup_request = smb2_setup_request,
|
|
|
.setup_async_request = smb2_setup_async_request,
|
|
@@ -530,6 +555,7 @@ struct smb_version_operations smb21_operations = {
|
|
|
.query_dir_next = smb2_query_dir_next,
|
|
|
.close_dir = smb2_close_dir,
|
|
|
.calc_smb_size = smb2_calc_size,
|
|
|
+ .is_status_pending = smb2_is_status_pending,
|
|
|
};
|
|
|
|
|
|
struct smb_version_values smb21_values = {
|