Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
f7ba7fe6
Commit
f7ba7fe6
authored
Sep 19, 2012
by
Pavel Shilovsky
Committed by
Steve French
Sep 24, 2012
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
CIFS: Add brlock support for SMB2
Signed-off-by:
Pavel Shilovsky
<
pshilovsky@etersoft.ru
>
parent
027e8eec
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
210 additions
and
5 deletions
+210
-5
fs/cifs/cifsproto.h
fs/cifs/cifsproto.h
+4
-0
fs/cifs/file.c
fs/cifs/file.c
+3
-5
fs/cifs/smb2file.c
fs/cifs/smb2file.c
+97
-0
fs/cifs/smb2ops.c
fs/cifs/smb2ops.c
+13
-0
fs/cifs/smb2pdu.c
fs/cifs/smb2pdu.c
+59
-0
fs/cifs/smb2pdu.h
fs/cifs/smb2pdu.h
+24
-0
fs/cifs/smb2proto.h
fs/cifs/smb2proto.h
+10
-0
No files found.
fs/cifs/cifsproto.h
View file @
f7ba7fe6
...
...
@@ -190,6 +190,10 @@ extern void cifs_dfs_release_automount_timer(void);
void
cifs_proc_init
(
void
);
void
cifs_proc_clean
(
void
);
extern
void
cifs_move_llist
(
struct
list_head
*
source
,
struct
list_head
*
dest
);
extern
void
cifs_free_llist
(
struct
list_head
*
llist
);
extern
void
cifs_del_lock_waiters
(
struct
cifsLockInfo
*
lock
);
extern
int
cifs_negotiate_protocol
(
const
unsigned
int
xid
,
struct
cifs_ses
*
ses
);
extern
int
cifs_setup_session
(
const
unsigned
int
xid
,
struct
cifs_ses
*
ses
,
...
...
fs/cifs/file.c
View file @
f7ba7fe6
...
...
@@ -288,8 +288,6 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
return
cfile
;
}
static
void
cifs_del_lock_waiters
(
struct
cifsLockInfo
*
lock
);
struct
cifsFileInfo
*
cifsFileInfo_get
(
struct
cifsFileInfo
*
cifs_file
)
{
...
...
@@ -696,7 +694,7 @@ cifs_lock_init(__u64 offset, __u64 length, __u8 type)
return
lock
;
}
static
void
void
cifs_del_lock_waiters
(
struct
cifsLockInfo
*
lock
)
{
struct
cifsLockInfo
*
li
,
*
tmp
;
...
...
@@ -1229,7 +1227,7 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u32 type,
return
0
;
}
static
void
void
cifs_move_llist
(
struct
list_head
*
source
,
struct
list_head
*
dest
)
{
struct
list_head
*
li
,
*
tmp
;
...
...
@@ -1237,7 +1235,7 @@ cifs_move_llist(struct list_head *source, struct list_head *dest)
list_move
(
li
,
dest
);
}
static
void
void
cifs_free_llist
(
struct
list_head
*
llist
)
{
struct
cifsLockInfo
*
li
,
*
tmp
;
...
...
fs/cifs/smb2file.c
View file @
f7ba7fe6
...
...
@@ -104,3 +104,100 @@ smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path,
kfree
(
smb2_path
);
return
rc
;
}
int
smb2_unlock_range
(
struct
cifsFileInfo
*
cfile
,
struct
file_lock
*
flock
,
const
unsigned
int
xid
)
{
int
rc
=
0
,
stored_rc
;
unsigned
int
max_num
,
num
=
0
,
max_buf
;
struct
smb2_lock_element
*
buf
,
*
cur
;
struct
cifs_tcon
*
tcon
=
tlink_tcon
(
cfile
->
tlink
);
struct
cifsInodeInfo
*
cinode
=
CIFS_I
(
cfile
->
dentry
->
d_inode
);
struct
cifsLockInfo
*
li
,
*
tmp
;
__u64
length
=
1
+
flock
->
fl_end
-
flock
->
fl_start
;
struct
list_head
tmp_llist
;
INIT_LIST_HEAD
(
&
tmp_llist
);
/*
* Accessing maxBuf is racy with cifs_reconnect - need to store value
* and check it for zero before using.
*/
max_buf
=
tcon
->
ses
->
server
->
maxBuf
;
if
(
!
max_buf
)
return
-
EINVAL
;
max_num
=
max_buf
/
sizeof
(
struct
smb2_lock_element
);
buf
=
kzalloc
(
max_num
*
sizeof
(
struct
smb2_lock_element
),
GFP_KERNEL
);
if
(
!
buf
)
return
-
ENOMEM
;
cur
=
buf
;
mutex_lock
(
&
cinode
->
lock_mutex
);
list_for_each_entry_safe
(
li
,
tmp
,
&
cfile
->
llist
->
locks
,
llist
)
{
if
(
flock
->
fl_start
>
li
->
offset
||
(
flock
->
fl_start
+
length
)
<
(
li
->
offset
+
li
->
length
))
continue
;
if
(
current
->
tgid
!=
li
->
pid
)
continue
;
if
(
cinode
->
can_cache_brlcks
)
{
/*
* We can cache brlock requests - simply remove a lock
* from the file's list.
*/
list_del
(
&
li
->
llist
);
cifs_del_lock_waiters
(
li
);
kfree
(
li
);
continue
;
}
cur
->
Length
=
cpu_to_le64
(
li
->
length
);
cur
->
Offset
=
cpu_to_le64
(
li
->
offset
);
cur
->
Flags
=
cpu_to_le32
(
SMB2_LOCKFLAG_UNLOCK
);
/*
* We need to save a lock here to let us add it again to the
* file's list if the unlock range request fails on the server.
*/
list_move
(
&
li
->
llist
,
&
tmp_llist
);
if
(
++
num
==
max_num
)
{
stored_rc
=
smb2_lockv
(
xid
,
tcon
,
cfile
->
fid
.
persistent_fid
,
cfile
->
fid
.
volatile_fid
,
current
->
tgid
,
num
,
buf
);
if
(
stored_rc
)
{
/*
* We failed on the unlock range request - add
* all locks from the tmp list to the head of
* the file's list.
*/
cifs_move_llist
(
&
tmp_llist
,
&
cfile
->
llist
->
locks
);
rc
=
stored_rc
;
}
else
/*
* The unlock range request succeed - free the
* tmp list.
*/
cifs_free_llist
(
&
tmp_llist
);
cur
=
buf
;
num
=
0
;
}
else
cur
++
;
}
if
(
num
)
{
stored_rc
=
smb2_lockv
(
xid
,
tcon
,
cfile
->
fid
.
persistent_fid
,
cfile
->
fid
.
volatile_fid
,
current
->
tgid
,
num
,
buf
);
if
(
stored_rc
)
{
cifs_move_llist
(
&
tmp_llist
,
&
cfile
->
llist
->
locks
);
rc
=
stored_rc
;
}
else
cifs_free_llist
(
&
tmp_llist
);
}
mutex_unlock
(
&
cinode
->
lock_mutex
);
kfree
(
buf
);
return
rc
;
}
fs/cifs/smb2ops.c
View file @
f7ba7fe6
...
...
@@ -544,6 +544,17 @@ smb2_compare_fids(struct cifsFileInfo *ob1, struct cifsFileInfo *ob2)
ob1
->
fid
.
volatile_fid
==
ob2
->
fid
.
volatile_fid
;
}
static
int
smb2_mand_lock
(
const
unsigned
int
xid
,
struct
cifsFileInfo
*
cfile
,
__u64
offset
,
__u64
length
,
__u32
type
,
int
lock
,
int
unlock
,
bool
wait
)
{
if
(
unlock
&&
!
lock
)
type
=
SMB2_LOCKFLAG_UNLOCK
;
return
SMB2_lock
(
xid
,
tlink_tcon
(
cfile
->
tlink
),
cfile
->
fid
.
persistent_fid
,
cfile
->
fid
.
volatile_fid
,
current
->
tgid
,
length
,
offset
,
type
,
wait
);
}
struct
smb_version_operations
smb21_operations
=
{
.
compare_fids
=
smb2_compare_fids
,
.
setup_request
=
smb2_setup_request
,
...
...
@@ -602,6 +613,8 @@ struct smb_version_operations smb21_operations = {
.
is_status_pending
=
smb2_is_status_pending
,
.
oplock_response
=
smb2_oplock_response
,
.
queryfs
=
smb2_queryfs
,
.
mand_lock
=
smb2_mand_lock
,
.
mand_unlock_range
=
smb2_unlock_range
,
};
struct
smb_version_values
smb21_values
=
{
...
...
fs/cifs/smb2pdu.c
View file @
f7ba7fe6
...
...
@@ -2047,3 +2047,62 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
free_rsp_buf
(
resp_buftype
,
iov
.
iov_base
);
return
rc
;
}
int
smb2_lockv
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
__u64
persist_fid
,
const
__u64
volatile_fid
,
const
__u32
pid
,
const
__u32
num_lock
,
struct
smb2_lock_element
*
buf
)
{
int
rc
=
0
;
struct
smb2_lock_req
*
req
=
NULL
;
struct
kvec
iov
[
2
];
int
resp_buf_type
;
unsigned
int
count
;
cFYI
(
1
,
"smb2_lockv num lock %d"
,
num_lock
);
rc
=
small_smb2_init
(
SMB2_LOCK
,
tcon
,
(
void
**
)
&
req
);
if
(
rc
)
return
rc
;
req
->
hdr
.
ProcessId
=
cpu_to_le32
(
pid
);
req
->
LockCount
=
cpu_to_le16
(
num_lock
);
req
->
PersistentFileId
=
persist_fid
;
req
->
VolatileFileId
=
volatile_fid
;
count
=
num_lock
*
sizeof
(
struct
smb2_lock_element
);
inc_rfc1001_len
(
req
,
count
-
sizeof
(
struct
smb2_lock_element
));
iov
[
0
].
iov_base
=
(
char
*
)
req
;
/* 4 for rfc1002 length field and count for all locks */
iov
[
0
].
iov_len
=
get_rfc1002_length
(
req
)
+
4
-
count
;
iov
[
1
].
iov_base
=
(
char
*
)
buf
;
iov
[
1
].
iov_len
=
count
;
cifs_stats_inc
(
&
tcon
->
stats
.
cifs_stats
.
num_locks
);
rc
=
SendReceive2
(
xid
,
tcon
->
ses
,
iov
,
2
,
&
resp_buf_type
,
CIFS_NO_RESP
);
if
(
rc
)
{
cFYI
(
1
,
"Send error in smb2_lockv = %d"
,
rc
);
cifs_stats_fail_inc
(
tcon
,
SMB2_LOCK_HE
);
}
return
rc
;
}
int
SMB2_lock
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
__u64
persist_fid
,
const
__u64
volatile_fid
,
const
__u32
pid
,
const
__u64
length
,
const
__u64
offset
,
const
__u32
lock_flags
,
const
bool
wait
)
{
struct
smb2_lock_element
lock
;
lock
.
Offset
=
cpu_to_le64
(
offset
);
lock
.
Length
=
cpu_to_le64
(
length
);
lock
.
Flags
=
cpu_to_le32
(
lock_flags
);
if
(
!
wait
&&
lock_flags
!=
SMB2_LOCKFLAG_UNLOCK
)
lock
.
Flags
|=
cpu_to_le32
(
SMB2_LOCKFLAG_FAIL_IMMEDIATELY
);
return
smb2_lockv
(
xid
,
tcon
,
persist_fid
,
volatile_fid
,
pid
,
1
,
&
lock
);
}
fs/cifs/smb2pdu.h
View file @
f7ba7fe6
...
...
@@ -531,6 +531,30 @@ struct smb2_write_rsp {
#define SMB2_LOCKFLAG_UNLOCK 0x0004
#define SMB2_LOCKFLAG_FAIL_IMMEDIATELY 0x0010
struct
smb2_lock_element
{
__le64
Offset
;
__le64
Length
;
__le32
Flags
;
__le32
Reserved
;
}
__packed
;
struct
smb2_lock_req
{
struct
smb2_hdr
hdr
;
__le16
StructureSize
;
/* Must be 48 */
__le16
LockCount
;
__le32
Reserved
;
__u64
PersistentFileId
;
/* opaque endianness */
__u64
VolatileFileId
;
/* opaque endianness */
/* Followed by at least one */
struct
smb2_lock_element
locks
[
1
];
}
__packed
;
struct
smb2_lock_rsp
{
struct
smb2_hdr
hdr
;
__le16
StructureSize
;
/* Must be 4 */
__le16
Reserved
;
}
__packed
;
struct
smb2_echo_req
{
struct
smb2_hdr
hdr
;
__le16
StructureSize
;
/* Must be 4 */
...
...
fs/cifs/smb2proto.h
View file @
f7ba7fe6
...
...
@@ -84,6 +84,8 @@ extern int smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon,
struct
cifs_fid
*
fid
,
__u32
*
oplock
,
FILE_ALL_INFO
*
buf
,
struct
cifs_sb_info
*
cifs_sb
);
extern
void
smb2_set_oplock_level
(
struct
cifsInodeInfo
*
cinode
,
__u32
oplock
);
extern
int
smb2_unlock_range
(
struct
cifsFileInfo
*
cfile
,
struct
file_lock
*
flock
,
const
unsigned
int
xid
);
/*
* SMB2 Worker functions - most of protocol specific implementation details
...
...
@@ -140,5 +142,13 @@ extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
extern
int
SMB2_QFS_info
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
u64
persistent_file_id
,
u64
volatile_file_id
,
struct
kstatfs
*
FSData
);
extern
int
SMB2_lock
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
__u64
persist_fid
,
const
__u64
volatile_fid
,
const
__u32
pid
,
const
__u64
length
,
const
__u64
offset
,
const
__u32
lockFlags
,
const
bool
wait
);
extern
int
smb2_lockv
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
__u64
persist_fid
,
const
__u64
volatile_fid
,
const
__u32
pid
,
const
__u32
num_lock
,
struct
smb2_lock_element
*
buf
);
#endif
/* _SMB2PROTO_H */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment