Loading fs/cifs/cifsglob.h +2 −0 Original line number Diff line number Diff line Loading @@ -328,6 +328,8 @@ struct smb_version_operations { struct cifs_fid *); /* calculate a size of SMB message */ unsigned int (*calc_smb_size)(void *); /* check for STATUS_PENDING and process it in a positive case */ bool (*is_status_pending)(char *, struct TCP_Server_Info *, int); }; struct smb_version_values { Loading fs/cifs/connect.c +4 −0 Original line number Diff line number Diff line Loading @@ -819,6 +819,10 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) cifs_dump_mem("Bad SMB: ", buf, min_t(unsigned int, server->total_read, 48)); if (server->ops->is_status_pending && server->ops->is_status_pending(buf, server, length)) return -1; if (!mid) return length; Loading fs/cifs/smb2file.c +22 −2 Original line number Diff line number Diff line Loading @@ -34,6 +34,26 @@ #include "fscache.h" #include "smb2proto.h" void smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock) { oplock &= 0xFF; if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE) { cinode->clientCanCacheAll = true; cinode->clientCanCacheRead = true; cFYI(1, "Exclusive Oplock granted on inode %p", &cinode->vfs_inode); } else if (oplock == SMB2_OPLOCK_LEVEL_II) { cinode->clientCanCacheAll = false; cinode->clientCanCacheRead = true; cFYI(1, "Level II Oplock granted on inode %p", &cinode->vfs_inode); } else { cinode->clientCanCacheAll = false; cinode->clientCanCacheRead = false; } } int smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path, int disposition, int desired_access, int create_options, Loading @@ -58,10 +78,11 @@ smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path, } desired_access |= FILE_READ_ATTRIBUTES; *oplock = SMB2_OPLOCK_LEVEL_EXCLUSIVE; rc = SMB2_open(xid, tcon, smb2_path, &fid->persistent_fid, &fid->volatile_fid, desired_access, disposition, 0, 0, smb2_data); 0, 0, (__u8 *)oplock, smb2_data); if (rc) goto out; Loading @@ -79,7 +100,6 @@ smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path, } out: *oplock = 0; kfree(smb2_data); kfree(smb2_path); return rc; Loading fs/cifs/smb2inode.c +2 −1 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, int rc, tmprc = 0; 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) Loading @@ -54,7 +55,7 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid, desired_access, create_disposition, file_attributes, create_options, NULL); create_options, &oplock, NULL); if (rc) { kfree(utf16_path); return rc; Loading fs/cifs/smb2ops.c +30 −4 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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; Loading Loading @@ -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; */ } Loading Loading @@ -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); Loading @@ -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"); Loading Loading @@ -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, Loading Loading @@ -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 = { Loading Loading
fs/cifs/cifsglob.h +2 −0 Original line number Diff line number Diff line Loading @@ -328,6 +328,8 @@ struct smb_version_operations { struct cifs_fid *); /* calculate a size of SMB message */ unsigned int (*calc_smb_size)(void *); /* check for STATUS_PENDING and process it in a positive case */ bool (*is_status_pending)(char *, struct TCP_Server_Info *, int); }; struct smb_version_values { Loading
fs/cifs/connect.c +4 −0 Original line number Diff line number Diff line Loading @@ -819,6 +819,10 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) cifs_dump_mem("Bad SMB: ", buf, min_t(unsigned int, server->total_read, 48)); if (server->ops->is_status_pending && server->ops->is_status_pending(buf, server, length)) return -1; if (!mid) return length; Loading
fs/cifs/smb2file.c +22 −2 Original line number Diff line number Diff line Loading @@ -34,6 +34,26 @@ #include "fscache.h" #include "smb2proto.h" void smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock) { oplock &= 0xFF; if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE) { cinode->clientCanCacheAll = true; cinode->clientCanCacheRead = true; cFYI(1, "Exclusive Oplock granted on inode %p", &cinode->vfs_inode); } else if (oplock == SMB2_OPLOCK_LEVEL_II) { cinode->clientCanCacheAll = false; cinode->clientCanCacheRead = true; cFYI(1, "Level II Oplock granted on inode %p", &cinode->vfs_inode); } else { cinode->clientCanCacheAll = false; cinode->clientCanCacheRead = false; } } int smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path, int disposition, int desired_access, int create_options, Loading @@ -58,10 +78,11 @@ smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path, } desired_access |= FILE_READ_ATTRIBUTES; *oplock = SMB2_OPLOCK_LEVEL_EXCLUSIVE; rc = SMB2_open(xid, tcon, smb2_path, &fid->persistent_fid, &fid->volatile_fid, desired_access, disposition, 0, 0, smb2_data); 0, 0, (__u8 *)oplock, smb2_data); if (rc) goto out; Loading @@ -79,7 +100,6 @@ smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path, } out: *oplock = 0; kfree(smb2_data); kfree(smb2_path); return rc; Loading
fs/cifs/smb2inode.c +2 −1 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, int rc, tmprc = 0; 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) Loading @@ -54,7 +55,7 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid, desired_access, create_disposition, file_attributes, create_options, NULL); create_options, &oplock, NULL); if (rc) { kfree(utf16_path); return rc; Loading
fs/cifs/smb2ops.c +30 −4 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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; Loading Loading @@ -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; */ } Loading Loading @@ -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); Loading @@ -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"); Loading Loading @@ -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, Loading Loading @@ -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 = { Loading