diff options
author | Pavel Shilovsky <pshilovsky@samba.org> | 2012-09-18 16:20:33 -0700 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2012-09-24 21:46:30 -0500 |
commit | 2e44b2887882134abf353b28867b82645e9f0856 (patch) | |
tree | 963236eb542e26b046960f72f9ec47ae8e339a76 /fs/cifs/smb2ops.c | |
parent | d324f08d6a87149597817f4496ef0f7ac185e8da (diff) | |
download | linux-2e44b2887882134abf353b28867b82645e9f0856.tar.bz2 |
CIFS: Process oplocks for SMB2
Signed-off-by: Pavel Shilovsky <piastryyy@gmail.com>
Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs/smb2ops.c')
-rw-r--r-- | fs/cifs/smb2ops.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 0fa086c1b5dc..2d88c90ded0c 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -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 = { |