Skip to content

Commit b8c32db

Browse files
piastrysmfrench
authored andcommitted
CIFS: Request SMB2.1 leases
if server supports them and we need oplocks. Signed-off-by: Pavel Shilovsky <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 579f905 commit b8c32db

File tree

8 files changed

+256
-27
lines changed

8 files changed

+256
-27
lines changed

fs/cifs/cifsfs.c

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <linux/kthread.h>
3737
#include <linux/freezer.h>
3838
#include <linux/namei.h>
39+
#include <linux/random.h>
3940
#include <net/ipv6.h>
4041
#include "cifsfs.h"
4142
#include "cifspdu.h"
@@ -88,6 +89,10 @@ extern mempool_t *cifs_mid_poolp;
8889

8990
struct workqueue_struct *cifsiod_wq;
9091

92+
#ifdef CONFIG_CIFS_SMB2
93+
__u8 cifs_client_guid[SMB2_CLIENT_GUID_SIZE];
94+
#endif
95+
9196
static int
9297
cifs_read_super(struct super_block *sb)
9398
{
@@ -218,20 +223,25 @@ cifs_alloc_inode(struct super_block *sb)
218223
return NULL;
219224
cifs_inode->cifsAttrs = 0x20; /* default */
220225
cifs_inode->time = 0;
221-
/* Until the file is open and we have gotten oplock
222-
info back from the server, can not assume caching of
223-
file data or metadata */
226+
/*
227+
* Until the file is open and we have gotten oplock info back from the
228+
* server, can not assume caching of file data or metadata.
229+
*/
224230
cifs_set_oplock_level(cifs_inode, 0);
225231
cifs_inode->delete_pending = false;
226232
cifs_inode->invalid_mapping = false;
227233
cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
228234
cifs_inode->server_eof = 0;
229235
cifs_inode->uniqueid = 0;
230236
cifs_inode->createtime = 0;
231-
232-
/* Can not set i_flags here - they get immediately overwritten
233-
to zero by the VFS */
234-
/* cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;*/
237+
#ifdef CONFIG_CIFS_SMB2
238+
get_random_bytes(cifs_inode->lease_key, SMB2_LEASE_KEY_SIZE);
239+
#endif
240+
/*
241+
* Can not set i_flags here - they get immediately overwritten to zero
242+
* by the VFS.
243+
*/
244+
/* cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME; */
235245
INIT_LIST_HEAD(&cifs_inode->openFileList);
236246
INIT_LIST_HEAD(&cifs_inode->llist);
237247
return &cifs_inode->vfs_inode;
@@ -1107,6 +1117,10 @@ init_cifs(void)
11071117
spin_lock_init(&cifs_file_list_lock);
11081118
spin_lock_init(&GlobalMid_Lock);
11091119

1120+
#ifdef CONFIG_CIFS_SMB2
1121+
get_random_bytes(cifs_client_guid, SMB2_CLIENT_GUID_SIZE);
1122+
#endif
1123+
11101124
if (cifs_max_pending < 2) {
11111125
cifs_max_pending = 2;
11121126
cFYI(1, "cifs_max_pending set to min of 2");

fs/cifs/cifsglob.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,12 @@ struct smb_version_operations {
361361
const unsigned int);
362362
/* push brlocks from the cache to the server */
363363
int (*push_mand_locks)(struct cifsFileInfo *);
364+
/* get lease key of the inode */
365+
void (*get_lease_key)(struct inode *, struct cifs_fid *fid);
366+
/* set lease key of the inode */
367+
void (*set_lease_key)(struct inode *, struct cifs_fid *fid);
368+
/* generate new lease key */
369+
void (*new_lease_key)(struct cifs_fid *fid);
364370
};
365371

366372
struct smb_version_values {
@@ -895,6 +901,7 @@ struct cifs_fid {
895901
#ifdef CONFIG_CIFS_SMB2
896902
__u64 persistent_fid; /* persist file id for smb2 */
897903
__u64 volatile_fid; /* volatile file id for smb2 */
904+
__u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* lease key for smb2 */
898905
#endif
899906
};
900907

@@ -1012,6 +1019,9 @@ struct cifsInodeInfo {
10121019
u64 server_eof; /* current file size on server -- protected by i_lock */
10131020
u64 uniqueid; /* server inode number */
10141021
u64 createtime; /* creation time on server */
1022+
#ifdef CONFIG_CIFS_SMB2
1023+
__u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* lease key for this inode */
1024+
#endif
10151025
#ifdef CONFIG_CIFS_FSCACHE
10161026
struct fscache_cookie *fscache;
10171027
#endif

fs/cifs/dir.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,8 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
340340
rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb,
341341
xid, &fid->netfid);
342342
if (newinode) {
343+
if (server->ops->set_lease_key)
344+
server->ops->set_lease_key(newinode, fid);
343345
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
344346
newinode->i_mode = mode;
345347
if ((*oplock & CIFS_CREATE_ACTION) &&
@@ -418,6 +420,9 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
418420
tcon = tlink_tcon(tlink);
419421
server = tcon->ses->server;
420422

423+
if (server->ops->new_lease_key)
424+
server->ops->new_lease_key(&fid);
425+
421426
rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
422427
&oplock, &fid, opened);
423428

@@ -473,10 +478,14 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
473478
if (IS_ERR(tlink))
474479
goto out_free_xid;
475480

476-
rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
477-
&oplock, &fid, &created);
478481
tcon = tlink_tcon(tlink);
479482
server = tcon->ses->server;
483+
484+
if (server->ops->new_lease_key)
485+
server->ops->new_lease_key(&fid);
486+
487+
rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
488+
&oplock, &fid, &created);
480489
if (!rc && server->ops->close)
481490
server->ops->close(xid, tcon, &fid);
482491

fs/cifs/file.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,9 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
177177
int disposition;
178178
int create_options = CREATE_NOT_DIR;
179179
FILE_ALL_INFO *buf;
180+
struct TCP_Server_Info *server = tcon->ses->server;
180181

181-
if (!tcon->ses->server->ops->open)
182+
if (!server->ops->open)
182183
return -ENOSYS;
183184

184185
desired_access = cifs_convert_flags(f_flags);
@@ -218,9 +219,9 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
218219
if (backup_cred(cifs_sb))
219220
create_options |= CREATE_OPEN_BACKUP_INTENT;
220221

221-
rc = tcon->ses->server->ops->open(xid, tcon, full_path, disposition,
222-
desired_access, create_options, fid,
223-
oplock, buf, cifs_sb);
222+
rc = server->ops->open(xid, tcon, full_path, disposition,
223+
desired_access, create_options, fid, oplock, buf,
224+
cifs_sb);
224225

225226
if (rc)
226227
goto out;
@@ -372,6 +373,7 @@ int cifs_open(struct inode *inode, struct file *file)
372373
unsigned int xid;
373374
__u32 oplock;
374375
struct cifs_sb_info *cifs_sb;
376+
struct TCP_Server_Info *server;
375377
struct cifs_tcon *tcon;
376378
struct tcon_link *tlink;
377379
struct cifsFileInfo *cfile = NULL;
@@ -388,6 +390,7 @@ int cifs_open(struct inode *inode, struct file *file)
388390
return PTR_ERR(tlink);
389391
}
390392
tcon = tlink_tcon(tlink);
393+
server = tcon->ses->server;
391394

392395
full_path = build_path_from_dentry(file->f_path.dentry);
393396
if (full_path == NULL) {
@@ -432,6 +435,9 @@ int cifs_open(struct inode *inode, struct file *file)
432435
}
433436

434437
if (!posix_open_ok) {
438+
if (server->ops->get_lease_key)
439+
server->ops->get_lease_key(inode, &fid);
440+
435441
rc = cifs_nt_open(full_path, inode, cifs_sb, tcon,
436442
file->f_flags, &oplock, &fid, xid);
437443
if (rc)
@@ -440,8 +446,8 @@ int cifs_open(struct inode *inode, struct file *file)
440446

441447
cfile = cifs_new_fileinfo(&fid, file, tlink, oplock);
442448
if (cfile == NULL) {
443-
if (tcon->ses->server->ops->close)
444-
tcon->ses->server->ops->close(xid, tcon, &fid);
449+
if (server->ops->close)
450+
server->ops->close(xid, tcon, &fid);
445451
rc = -ENOMEM;
446452
goto out;
447453
}
@@ -567,6 +573,9 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
567573
if (backup_cred(cifs_sb))
568574
create_options |= CREATE_OPEN_BACKUP_INTENT;
569575

576+
if (server->ops->get_lease_key)
577+
server->ops->get_lease_key(inode, &fid);
578+
570579
/*
571580
* Can not refresh inode by passing in file_info buf to be returned by
572581
* CIFSSMBOpen and then calling get_inode_info with returned buf since

fs/cifs/smb2file.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path,
6363
int rc;
6464
__le16 *smb2_path;
6565
struct smb2_file_all_info *smb2_data = NULL;
66+
__u8 smb2_oplock[17];
6667

6768
smb2_path = cifs_convert_path_to_utf16(path, cifs_sb);
6869
if (smb2_path == NULL) {
@@ -78,11 +79,14 @@ smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path,
7879
}
7980

8081
desired_access |= FILE_READ_ATTRIBUTES;
81-
*oplock = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
82+
*smb2_oplock = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
83+
84+
if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)
85+
memcpy(smb2_oplock + 1, fid->lease_key, SMB2_LEASE_KEY_SIZE);
8286

8387
rc = SMB2_open(xid, tcon, smb2_path, &fid->persistent_fid,
8488
&fid->volatile_fid, desired_access, disposition,
85-
0, 0, (__u8 *)oplock, smb2_data);
89+
0, 0, smb2_oplock, smb2_data);
8690
if (rc)
8791
goto out;
8892

@@ -99,6 +103,7 @@ smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path,
99103
move_smb2_info_to_cifs(buf, smb2_data);
100104
}
101105

106+
*oplock = *smb2_oplock;
102107
out:
103108
kfree(smb2_data);
104109
kfree(smb2_path);

fs/cifs/smb2ops.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,24 @@ smb2_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
555555
current->tgid, length, offset, type, wait);
556556
}
557557

558+
static void
559+
smb2_get_lease_key(struct inode *inode, struct cifs_fid *fid)
560+
{
561+
memcpy(fid->lease_key, CIFS_I(inode)->lease_key, SMB2_LEASE_KEY_SIZE);
562+
}
563+
564+
static void
565+
smb2_set_lease_key(struct inode *inode, struct cifs_fid *fid)
566+
{
567+
memcpy(CIFS_I(inode)->lease_key, fid->lease_key, SMB2_LEASE_KEY_SIZE);
568+
}
569+
570+
static void
571+
smb2_new_lease_key(struct cifs_fid *fid)
572+
{
573+
get_random_bytes(fid->lease_key, SMB2_LEASE_KEY_SIZE);
574+
}
575+
558576
struct smb_version_operations smb21_operations = {
559577
.compare_fids = smb2_compare_fids,
560578
.setup_request = smb2_setup_request,
@@ -616,6 +634,9 @@ struct smb_version_operations smb21_operations = {
616634
.mand_lock = smb2_mand_lock,
617635
.mand_unlock_range = smb2_unlock_range,
618636
.push_mand_locks = smb2_push_mandatory_locks,
637+
.get_lease_key = smb2_get_lease_key,
638+
.set_lease_key = smb2_set_lease_key,
639+
.new_lease_key = smb2_new_lease_key,
619640
};
620641

621642
struct smb_version_values smb21_values = {

0 commit comments

Comments
 (0)