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
2dc51bdf
Commit
2dc51bdf
authored
Apr 13, 2003
by
Steve French
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://linux.bkbits.net/linux-2.5
into hostme.bitkeeper.com:/ua/repos/c/cifs/linux-2.5cifs
parents
7b87c44e
8d2ccdc9
Changes
13
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
520 additions
and
150 deletions
+520
-150
fs/cifs/CHANGES
fs/cifs/CHANGES
+17
-0
fs/cifs/cifs_debug.c
fs/cifs/cifs_debug.c
+46
-0
fs/cifs/cifsfs.c
fs/cifs/cifsfs.c
+66
-7
fs/cifs/cifsglob.h
fs/cifs/cifsglob.h
+20
-6
fs/cifs/cifspdu.h
fs/cifs/cifspdu.h
+10
-3
fs/cifs/cifsproto.h
fs/cifs/cifsproto.h
+7
-1
fs/cifs/cifssmb.c
fs/cifs/cifssmb.c
+46
-10
fs/cifs/connect.c
fs/cifs/connect.c
+1
-2
fs/cifs/file.c
fs/cifs/file.c
+222
-96
fs/cifs/inode.c
fs/cifs/inode.c
+12
-12
fs/cifs/link.c
fs/cifs/link.c
+28
-13
fs/cifs/misc.c
fs/cifs/misc.c
+11
-0
fs/cifs/transport.c
fs/cifs/transport.c
+34
-0
No files found.
fs/cifs/CHANGES
View file @
2dc51bdf
Version 0.73
------------
unload nls if mount fails.
Version 0.72
------------
Add resume key support to search (readdir) code to workaround
Windows bug. Add /proc/fs/cifs/LookupCacheEnable which
allows disabling caching of attribute information for
lookups.
Version 0.71
------------
Add more oplock handling (distributed caching code). Remove
dead code. Remove excessive stack space utilization from
symlink routines.
Version 0.70
------------
Fix oops in get dfs referral (triggered when null path sent in to
...
...
fs/cifs/cifs_debug.c
View file @
2dc51bdf
...
...
@@ -185,6 +185,8 @@ static read_proc_t cifsFYI_read;
static
write_proc_t
cifsFYI_write
;
static
read_proc_t
oplockEnabled_read
;
static
write_proc_t
oplockEnabled_write
;
static
read_proc_t
lookupFlag_read
;
static
write_proc_t
lookupFlag_write
;
static
read_proc_t
traceSMB_read
;
static
write_proc_t
traceSMB_write
;
static
read_proc_t
multiuser_mount_read
;
...
...
@@ -243,6 +245,12 @@ cifs_proc_init(void)
if
(
pde
)
pde
->
write_proc
=
extended_security_write
;
pde
=
create_proc_read_entry
(
"LookupCacheEnable"
,
0
,
proc_fs_cifs
,
lookupFlag_read
,
0
);
if
(
pde
)
pde
->
write_proc
=
lookupFlag_write
;
pde
=
create_proc_read_entry
(
"NTLMV2Enabled"
,
0
,
proc_fs_cifs
,
ntlmv2_enabled_read
,
0
);
...
...
@@ -353,6 +361,44 @@ oplockEnabled_write(struct file *file, const char *buffer,
return
count
;
}
static
int
lookupFlag_read
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
{
int
len
;
len
=
sprintf
(
page
,
"%d
\n
"
,
lookupCacheEnabled
);
len
-=
off
;
*
start
=
page
+
off
;
if
(
len
>
count
)
len
=
count
;
else
*
eof
=
1
;
if
(
len
<
0
)
len
=
0
;
return
len
;
}
static
int
lookupFlag_write
(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
char
c
;
int
rc
;
rc
=
get_user
(
c
,
buffer
);
if
(
rc
)
return
rc
;
if
(
c
==
'0'
||
c
==
'n'
||
c
==
'N'
)
lookupCacheEnabled
=
0
;
else
if
(
c
==
'1'
||
c
==
'y'
||
c
==
'Y'
)
lookupCacheEnabled
=
1
;
return
count
;
}
static
int
traceSMB_read
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
...
...
fs/cifs/cifsfs.c
View file @
2dc51bdf
...
...
@@ -48,11 +48,13 @@ int cifsFYI = 0;
int
cifsERROR
=
1
;
int
traceSMB
=
0
;
unsigned
int
oplockEnabled
=
0
;
unsigned
int
lookupCacheEnabled
=
1
;
unsigned
int
multiuser_mount
=
0
;
unsigned
int
extended_security
=
0
;
unsigned
int
ntlmv2_support
=
0
;
unsigned
int
sign_CIFS_PDUs
=
0
;
unsigned
int
CIFSMaximumBufferSize
=
CIFS_MAX_MSGSIZE
;
struct
task_struct
*
oplockThread
=
NULL
;
extern
int
cifs_mount
(
struct
super_block
*
,
struct
cifs_sb_info
*
,
char
*
,
char
*
);
...
...
@@ -107,6 +109,8 @@ cifs_read_super(struct super_block *sb, void *data, char *devname, int silent)
iput
(
inode
);
out_mount_failed:
if
(
cifs_sb
->
local_nls
)
unload_nls
(
cifs_sb
->
local_nls
);
if
(
cifs_sb
)
kfree
(
cifs_sb
);
return
-
EINVAL
;
...
...
@@ -175,6 +179,7 @@ static int cifs_permission(struct inode * inode, int mask)
static
kmem_cache_t
*
cifs_inode_cachep
;
kmem_cache_t
*
cifs_req_cachep
;
kmem_cache_t
*
cifs_mid_cachep
;
kmem_cache_t
*
cifs_oplock_cachep
;
static
struct
inode
*
cifs_alloc_inode
(
struct
super_block
*
sb
)
...
...
@@ -394,6 +399,13 @@ cifs_init_mids(void)
SLAB_HWCACHE_ALIGN
,
NULL
,
NULL
);
if
(
cifs_mid_cachep
==
NULL
)
return
-
ENOMEM
;
cifs_oplock_cachep
=
kmem_cache_create
(
"cifs_oplock_structs"
,
sizeof
(
struct
oplock_q_entry
),
0
,
SLAB_HWCACHE_ALIGN
,
NULL
,
NULL
);
if
(
cifs_oplock_cachep
==
NULL
)
{
kmem_cache_destroy
(
cifs_mid_cachep
);
return
-
ENOMEM
;
}
return
0
;
}
...
...
@@ -404,6 +416,49 @@ cifs_destroy_mids(void)
if
(
kmem_cache_destroy
(
cifs_mid_cachep
))
printk
(
KERN_WARNING
"cifs_destroy_mids: error not all structures were freed
\n
"
);
if
(
kmem_cache_destroy
(
cifs_oplock_cachep
))
printk
(
KERN_WARNING
"error not all oplock structures were freed
\n
"
);}
static
int
cifs_oplock_thread
(
void
*
dummyarg
)
{
struct
list_head
*
tmp
;
struct
oplock_q_entry
*
oplock_item
;
struct
file
*
pfile
;
struct
cifsTconInfo
*
pTcon
;
int
rc
;
daemonize
(
"cifsoplockd"
);
allow_signal
(
SIGKILL
);
oplockThread
=
current
;
while
(
1
)
{
set_current_state
(
TASK_INTERRUPTIBLE
);
schedule_timeout
(
100
*
HZ
);
/* BB add missing code */
cFYI
(
1
,(
"oplock thread woken up - flush inode"
));
/* BB remove */
write_lock
(
&
GlobalMid_Lock
);
list_for_each
(
tmp
,
&
GlobalOplock_Q
)
{
oplock_item
=
list_entry
(
tmp
,
struct
oplock_q_entry
,
qhead
);
if
(
oplock_item
)
{
pTcon
=
oplock_item
->
tcon
;
pfile
=
oplock_item
->
file_to_flush
;
cFYI
(
1
,(
"process item on queue"
));
/* BB remove */
DeleteOplockQEntry
(
oplock_item
);
write_unlock
(
&
GlobalMid_Lock
);
rc
=
filemap_fdatawrite
(
pfile
->
f_dentry
->
d_inode
->
i_mapping
);
cFYI
(
1
,(
"Oplock flush file %p rc %d"
,
pfile
,
rc
));
/* send oplock break */
write_lock
(
&
GlobalMid_Lock
);
}
else
break
;
cFYI
(
1
,(
"next time through list"
));
/* BB remove */
}
write_unlock
(
&
GlobalMid_Lock
);
cFYI
(
1
,(
"next time through while loop"
));
/* BB remove */
}
}
static
int
__init
...
...
@@ -416,7 +471,7 @@ init_cifs(void)
INIT_LIST_HEAD
(
&
GlobalServerList
);
/* BB not implemented yet */
INIT_LIST_HEAD
(
&
GlobalSMBSessionList
);
INIT_LIST_HEAD
(
&
GlobalTreeConnectionList
);
INIT_LIST_HEAD
(
&
GlobalOplock_Q
);
/*
* Initialize Global counters
*/
...
...
@@ -437,9 +492,11 @@ init_cifs(void)
rc
=
cifs_init_request_bufs
();
if
(
!
rc
)
{
rc
=
register_filesystem
(
&
cifs_fs_type
);
if
(
!
rc
)
if
(
!
rc
)
{
kernel_thread
(
cifs_oplock_thread
,
NULL
,
CLONE_FS
|
CLONE_FILES
|
CLONE_VM
);
return
rc
;
/* Success */
else
}
else
cifs_destroy_request_bufs
();
}
cifs_destroy_mids
();
...
...
@@ -463,6 +520,8 @@ exit_cifs(void)
cifs_destroy_inodecache
();
cifs_destroy_mids
();
cifs_destroy_request_bufs
();
if
(
oplockThread
)
send_sig
(
SIGKILL
,
oplockThread
,
1
);
}
MODULE_AUTHOR
(
"Steve French <sfrench@us.ibm.com>"
);
...
...
fs/cifs/cifsglob.h
View file @
2dc51bdf
...
...
@@ -199,7 +199,7 @@ struct cifsLockInfo {
struct
cifsFileInfo
{
struct
list_head
tlist
;
/* pointer to next fid owned by tcon */
struct
list_head
flist
;
/* next fid (file instance) for this inode */
unsigned
int
uid
;
/* allows
you to find
which FileInfo structure */
unsigned
int
uid
;
/* allows
finding
which FileInfo structure */
__u32
pid
;
/* process id who opened file */
__u16
netfid
;
/* file id from remote */
/* BB add lock scope info here if needed */
;
...
...
@@ -207,6 +207,10 @@ struct cifsFileInfo {
struct
file
*
pfile
;
/* needed for writepage */
int
endOfSearch
:
1
;
/* we have reached end of search */
int
closePend
:
1
;
/* file is marked to close */
int
emptyDir
:
1
;
char
*
search_resume_name
;
unsigned
int
resume_name_length
;
__u32
resume_key
;
};
/*
...
...
@@ -222,6 +226,7 @@ struct cifsInodeInfo {
unsigned
long
time
;
/* jiffies of last update/check of inode */
int
clientCanCacheRead
:
1
;
/* read oplock */
int
clientCanCacheAll
:
1
;
/* read and writebehind oplock */
int
oplockPending
:
1
;
struct
inode
vfs_inode
;
};
...
...
@@ -251,6 +256,12 @@ struct mid_q_entry {
int
midState
;
/* wish this were enum but can not pass to wait_event */
};
struct
oplock_q_entry
{
struct
list_head
qhead
;
struct
file
*
file_to_flush
;
struct
cifsTconInfo
*
tcon
;
};
#define MID_FREE 0
#define MID_REQUEST_ALLOCATED 1
#define MID_REQUEST_SUBMITTED 2
...
...
@@ -301,6 +312,8 @@ GLOBAL_EXTERN struct list_head GlobalSMBSessionList;
GLOBAL_EXTERN
struct
list_head
GlobalTreeConnectionList
;
GLOBAL_EXTERN
rwlock_t
GlobalSMBSeslock
;
/* protects list inserts on 3 above */
GLOBAL_EXTERN
struct
list_head
GlobalOplock_Q
;
/*
* Global transaction id (XID) information
*/
...
...
@@ -327,6 +340,7 @@ GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions
have the uid/password or Kerberos credential
or equivalent for current user */
GLOBAL_EXTERN
unsigned
int
oplockEnabled
;
GLOBAL_EXTERN
unsigned
int
lookupCacheEnabled
;
GLOBAL_EXTERN
unsigned
int
extended_security
;
/* if on, session setup sent
with more secure ntlmssp2 challenge/resp */
GLOBAL_EXTERN
unsigned
int
ntlmv2_support
;
/* better optional password hash */
...
...
fs/cifs/cifspdu.h
View file @
2dc51bdf
...
...
@@ -38,6 +38,7 @@
#define SMB_COM_WRITE_ANDX 0x2F
#define SMB_COM_TRANSACTION2 0x32
#define SMB_COM_TRANSACTION2_SECONDARY 0x33
#define SMB_COM_FIND_CLOSE2 0x34
#define SMB_COM_TREE_DISCONNECT 0x71
#define SMB_COM_NEGOTIATE 0x72
#define SMB_COM_SESSION_SETUP_ANDX 0x73
...
...
@@ -584,7 +585,7 @@ typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on tre
typedef
struct
smb_com_close_req
{
struct
smb_hdr
hdr
;
/* wct = 3 */
__u16
FileID
;
/* target file attributes */
__u16
FileID
;
__u32
LastWriteTime
;
/* should be zero */
__u16
ByteCount
;
/* 0 */
}
CLOSE_REQ
;
...
...
@@ -594,6 +595,12 @@ typedef struct smb_com_close_rsp {
__u16
ByteCount
;
/* bct = 0 */
}
CLOSE_RSP
;
typedef
struct
smb_com_findclose_req
{
struct
smb_hdr
hdr
;
/* wct = 1 */
__u16
FileID
;
__u16
ByteCount
;
/* 0 */
}
FINDCLOSE_REQ
;
/* OpenFlags */
#define REQ_OPLOCK 0x00000002
#define REQ_BATCHOPLOCK 0x00000004
...
...
@@ -1152,7 +1159,7 @@ typedef struct smb_com_transaction2_fnext_req {
__u16
InformationLevel
;
__u32
ResumeKey
;
__u16
SearchFlags
;
char
ResumeFileName
[
1
];
/* will be null string actually since we set bit 3 - resume from previous ending place */
char
ResumeFileName
[
1
];
}
TRANSACTION2_FNEXT_REQ
;
typedef
struct
smb_com_transaction2_fnext_rsp
{
...
...
fs/cifs/cifsproto.h
View file @
2dc51bdf
...
...
@@ -57,6 +57,8 @@ extern void header_assemble(struct smb_hdr *, char /* command */ ,
const
struct
cifsTconInfo
*
,
int
/* length of fixed section (word count) in two byte units */
);
struct
oplock_q_entry
*
AllocOplockQEntry
(
struct
file
*
,
struct
cifsTconInfo
*
);
void
DeleteOplockQEntry
(
struct
oplock_q_entry
*
);
extern
struct
timespec
cifs_NTtimeToUnix
(
u64
/* utc nanoseconds since 1601 */
);
extern
u64
cifs_UnixTimeToNT
(
struct
timespec
);
extern
void
RevUcode_to_Ucode
(
char
*
revUnicode
,
char
*
UnicodeName
);
...
...
@@ -104,9 +106,13 @@ extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
extern
int
CIFSFindNext
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
FILE_DIRECTORY_INFO
*
findData
,
T2_FNEXT_RSP_PARMS
*
findParms
,
const
__u16
searchHandle
,
const
__u32
resumeKey
,
const
__u16
searchHandle
,
char
*
resume_name
,
int
name_length
,
__u32
resume_key
,
int
*
UnicodeFlag
,
int
*
pUnixFlag
);
extern
int
CIFSFindClose
(
const
int
,
struct
cifsTconInfo
*
tcon
,
const
__u16
search_handle
);
extern
int
CIFSSMBQPathInfo
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
unsigned
char
*
searchName
,
FILE_ALL_INFO
*
findData
,
...
...
fs/cifs/cifssmb.c
View file @
2dc51bdf
...
...
@@ -1449,7 +1449,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
cpu_to_le16
(
ATTR_READONLY
|
ATTR_HIDDEN
|
ATTR_SYSTEM
|
ATTR_DIRECTORY
);
pSMB
->
SearchCount
=
cpu_to_le16
(
CIFS_MAX_MSGSIZE
/
sizeof
(
FILE_DIRECTORY_INFO
));
/* should this be shrunk even more ? */
pSMB
->
SearchFlags
=
cpu_to_le16
(
CIFS_SEARCH_CLOSE_AT_END
);
pSMB
->
SearchFlags
=
cpu_to_le16
(
CIFS_SEARCH_CLOSE_AT_END
|
CIFS_SEARCH_RETURN_RESUME
);
/* test for Unix extensions */
if
(
tcon
->
ses
->
capabilities
&
CAP_UNIX
)
{
...
...
@@ -1496,9 +1496,9 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
int
CIFSFindNext
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
FILE_DIRECTORY_INFO
*
findData
,
T2_FNEXT_RSP_PARMS
*
findParms
,
const
__u16
searchHandle
,
__u32
resumeK
ey
,
int
*
pUnicodeFlag
,
int
*
pUnixFlag
)
FILE_DIRECTORY_INFO
*
findData
,
T2_FNEXT_RSP_PARMS
*
findParms
,
const
__u16
searchHandle
,
char
*
resume_file_name
,
int
name_len
,
__u32
resume_k
ey
,
int
*
pUnicodeFlag
,
int
*
pUnixFlag
)
{
/* level 257 SMB_ */
TRANSACTION2_FNEXT_REQ
*
pSMB
=
NULL
;
...
...
@@ -1508,6 +1508,9 @@ CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
int
bytes_returned
;
cFYI
(
1
,
(
"In FindNext"
));
if
(
resume_file_name
==
NULL
)
{
return
-
EIO
;
}
rc
=
smb_init
(
SMB_COM_TRANSACTION2
,
15
,
tcon
,
(
void
**
)
&
pSMB
,
(
void
**
)
&
pSMBr
);
if
(
rc
)
...
...
@@ -1530,9 +1533,6 @@ CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
pSMB
->
SetupCount
=
1
;
pSMB
->
Reserved3
=
0
;
pSMB
->
SubCommand
=
cpu_to_le16
(
TRANS2_FIND_NEXT
);
pSMB
->
ByteCount
=
pSMB
->
TotalParameterCount
+
1
/* pad */
;
pSMB
->
TotalParameterCount
=
cpu_to_le16
(
pSMB
->
TotalParameterCount
);
pSMB
->
ParameterCount
=
pSMB
->
TotalParameterCount
;
pSMB
->
SearchHandle
=
searchHandle
;
/* always kept as le */
findParms
->
SearchCount
=
0
;
/* set to zero in case of error */
pSMB
->
SearchCount
=
...
...
@@ -1546,10 +1546,19 @@ CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
cpu_to_le16
(
SMB_FIND_FILE_DIRECTORY_INFO
);
*
pUnixFlag
=
FALSE
;
}
pSMB
->
ResumeKey
=
resume
Key
;
/* always kept as le */
pSMB
->
ResumeKey
=
resume
_key
;
pSMB
->
SearchFlags
=
cpu_to_le16
(
CIFS_SEARCH_CLOSE_AT_END
|
CIFS_SEARCH_CONTINUE_FROM_LAST
);
cpu_to_le16
(
CIFS_SEARCH_CLOSE_AT_END
|
CIFS_SEARCH_RETURN_RESUME
);
/* BB add check to make sure we do not cross end of smb */
if
(
name_len
<
CIFS_MAX_MSGSIZE
)
{
memcpy
(
pSMB
->
ResumeFileName
,
resume_file_name
,
name_len
);
pSMB
->
ByteCount
+=
name_len
;
}
pSMB
->
TotalParameterCount
+=
name_len
;
pSMB
->
ByteCount
=
pSMB
->
TotalParameterCount
+
1
/* pad */
;
pSMB
->
TotalParameterCount
=
cpu_to_le16
(
pSMB
->
TotalParameterCount
);
pSMB
->
ParameterCount
=
pSMB
->
TotalParameterCount
;
/* BB improve error handling here */
pSMB
->
hdr
.
smb_buf_length
+=
pSMB
->
ByteCount
;
pSMB
->
ByteCount
=
cpu_to_le16
(
pSMB
->
ByteCount
);
...
...
@@ -1585,6 +1594,33 @@ CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
return
rc
;
}
int
CIFSFindClose
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
__u16
searchHandle
)
{
int
rc
=
0
;
FINDCLOSE_REQ
*
pSMB
=
NULL
;
CLOSE_RSP
*
pSMBr
=
NULL
;
int
bytes_returned
;
cFYI
(
1
,
(
"In CIFSSMBFindClose"
));
rc
=
smb_init
(
SMB_COM_FIND_CLOSE2
,
1
,
tcon
,
(
void
**
)
&
pSMB
,
(
void
**
)
&
pSMBr
);
if
(
rc
)
return
rc
;
pSMB
->
FileID
=
searchHandle
;
pSMB
->
ByteCount
=
0
;
rc
=
SendReceive
(
xid
,
tcon
->
ses
,
(
struct
smb_hdr
*
)
pSMB
,
(
struct
smb_hdr
*
)
pSMBr
,
&
bytes_returned
,
0
);
if
(
rc
)
{
cERROR
(
1
,
(
"Send error in FindClose = %d"
,
rc
));
}
if
(
pSMB
)
buf_release
(
pSMB
);
return
rc
;
}
int
CIFSGetDFSRefer
(
const
int
xid
,
struct
cifsSesInfo
*
ses
,
const
unsigned
char
*
searchName
,
...
...
fs/cifs/connect.c
View file @
2dc51bdf
...
...
@@ -850,8 +850,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
init_waitqueue_head
(
&
srvTcp
->
response_q
);
INIT_LIST_HEAD
(
&
srvTcp
->
pending_mid_q
);
srvTcp
->
tcpStatus
=
CifsGood
;
kernel_thread
((
void
*
)
(
void
*
)
cifs_demultiplex_thread
,
srvTcp
,
kernel_thread
((
void
*
)(
void
*
)
cifs_demultiplex_thread
,
srvTcp
,
CLONE_FS
|
CLONE_FILES
|
CLONE_VM
);
}
}
...
...
fs/cifs/file.c
View file @
2dc51bdf
This diff is collapsed.
Click to expand it.
fs/cifs/inode.c
View file @
2dc51bdf
...
...
@@ -451,9 +451,9 @@ cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
pTcon
=
cifs_sb_source
->
tcon
;
if
(
pTcon
!=
cifs_sb_target
->
tcon
)
{
FreeXid
(
xid
);
return
-
EXDEV
;
/* BB actually could be allowed if same server, but
different share. Might eventually add support for this */
FreeXid
(
xid
);
}
fromName
=
build_path_from_dentry
(
source_direntry
);
...
...
@@ -500,7 +500,8 @@ cifs_revalidate(struct dentry *direntry)
if
(
time_before
(
jiffies
,
cifsInode
->
time
+
HZ
))
{
if
((
S_ISREG
(
direntry
->
d_inode
->
i_mode
)
==
0
)
||
(
direntry
->
d_inode
->
i_nlink
==
1
))
{
(
direntry
->
d_inode
->
i_nlink
==
1
)
||
(
lookupCacheEnabled
==
0
))
{
if
(
full_path
)
kfree
(
full_path
);
FreeXid
(
xid
);
...
...
@@ -508,7 +509,6 @@ cifs_revalidate(struct dentry *direntry)
}
else
{
cFYI
(
1
,(
"Have to revalidate file due to hardlinks"
));
}
}
if
(
cifs_sb
->
tcon
->
ses
->
capabilities
&
CAP_UNIX
)
...
...
fs/cifs/link.c
View file @
2dc51bdf
...
...
@@ -82,7 +82,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
int
rc
=
-
EACCES
;
int
xid
;
char
*
full_path
=
NULL
;
char
target_path
[
257
]
;
char
*
target_path
;
struct
cifs_sb_info
*
cifs_sb
;
struct
cifsTconInfo
*
pTcon
;
...
...
@@ -91,7 +91,11 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
cFYI
(
1
,
(
"Full path: %s inode = 0x%p"
,
full_path
,
inode
));
cifs_sb
=
CIFS_SB
(
inode
->
i_sb
);
pTcon
=
cifs_sb
->
tcon
;
target_path
=
kmalloc
(
PATH_MAX
,
GFP_KERNEL
);
if
(
target_path
==
NULL
)
{
FreeXid
(
xid
);
return
-
ENOMEM
;
}
/* can not call the following line due to EFAULT in vfs_readlink which is presumably expecting a user space buffer */
/* length = cifs_readlink(direntry,target_path, sizeof(target_path) - 1); */
...
...
@@ -99,7 +103,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
if
(
pTcon
->
ses
->
capabilities
&
CAP_UNIX
)
rc
=
CIFSSMBUnixQuerySymLink
(
xid
,
pTcon
,
full_path
,
target_path
,
sizeof
(
target_path
)
-
1
,
PATH_MAX
-
1
,
cifs_sb
->
local_nls
);
else
{
/* rc = CIFSSMBQueryReparseLinkInfo */
...
...
@@ -109,11 +113,13 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
/* BB Should we be using page symlink ops here? */
if
(
rc
==
0
)
{
target_path
[
256
]
=
0
;
target_path
[
PATH_MAX
-
1
]
=
0
;
rc
=
vfs_follow_link
(
nd
,
target_path
);
}
/* else EACCESS */
if
(
target_path
)
kfree
(
target_path
);
if
(
full_path
)
kfree
(
full_path
);
FreeXid
(
xid
);
...
...
@@ -180,7 +186,8 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
struct
cifs_sb_info
*
cifs_sb
;
struct
cifsTconInfo
*
pTcon
;
char
*
full_path
=
NULL
;
char
tmpbuffer
[
256
];
char
*
tmpbuffer
;
int
len
;
__u16
fid
;
xid
=
GetXid
();
...
...
@@ -190,12 +197,20 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
cFYI
(
1
,
(
"Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d"
,
full_path
,
inode
,
pBuffer
,
buflen
));
if
(
buflen
>
PATH_MAX
)
len
=
PATH_MAX
;
else
len
=
buflen
;
tmpbuffer
=
kmalloc
(
len
,
GFP_KERNEL
);
if
(
tmpbuffer
==
NULL
)
{
FreeXid
(
xid
);
return
-
ENOMEM
;
}
/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
if
(
cifs_sb
->
tcon
->
ses
->
capabilities
&
CAP_UNIX
)
rc
=
CIFSSMBUnixQuerySymLink
(
xid
,
pTcon
,
full_path
,
tmpbuffer
,
sizeof
(
tmpbuffer
)
-
1
,
len
-
1
,
cifs_sb
->
local_nls
);
else
{
rc
=
CIFSSMBOpen
(
xid
,
pTcon
,
full_path
,
FILE_OPEN
,
GENERIC_READ
,
...
...
@@ -203,7 +218,7 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
if
(
!
rc
)
{
rc
=
CIFSSMBQueryReparseLinkInfo
(
xid
,
pTcon
,
full_path
,
tmpbuffer
,
sizeof
(
tmpbuffer
)
-
1
,
len
-
1
,
fid
,
cifs_sb
->
local_nls
);
if
(
CIFSSMBClose
(
xid
,
pTcon
,
fid
))
{
...
...
@@ -216,15 +231,15 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
/* BB Should we be using page ops here? */
/* BB null terminate returned string in pBuffer? BB */
if
(
buflen
>
sizeof
(
tmpbuffer
))
buflen
=
sizeof
(
tmpbuffer
);
if
(
rc
==
0
)
{
rc
=
vfs_readlink
(
direntry
,
pBuffer
,
buf
len
,
tmpbuffer
);
rc
=
vfs_readlink
(
direntry
,
pBuffer
,
len
,
tmpbuffer
);
cFYI
(
1
,
(
"vfs_readlink called from cifs_readlink returned %d"
,
rc
));
}
if
(
tmpbuffer
)
kfree
(
tmpbuffer
);
if
(
full_path
)
kfree
(
full_path
);
FreeXid
(
xid
);
...
...
fs/cifs/misc.c
View file @
2dc51bdf
...
...
@@ -27,6 +27,7 @@
#include "cifs_debug.h"
extern
kmem_cache_t
*
cifs_req_cachep
;
extern
struct
task_struct
*
oplockThread
;
__u16
GlobalMid
;
/* multiplex id - rotating counter */
...
...
@@ -336,6 +337,7 @@ is_valid_oplock_break(struct smb_hdr *buf)
list_for_each
(
tmp1
,
&
tcon
->
openFileList
){
netfile
=
list_entry
(
tmp1
,
struct
cifsFileInfo
,
tlist
);
if
(
pSMB
->
Fid
==
netfile
->
netfid
)
{
struct
cifsInodeInfo
*
pCifsInode
;
/* BB Add following logic:
2) look up inode from tcon->openFileList->file->f_dentry->d_inode
3) flush dirty pages and cached byte range locks and mark inode
...
...
@@ -345,6 +347,15 @@ is_valid_oplock_break(struct smb_hdr *buf)
6) send oplock break response to server */
read_unlock
(
&
GlobalSMBSeslock
);
cFYI
(
1
,(
"Matching file id, processing oplock break"
));
pCifsInode
=
CIFS_I
(
netfile
->
pfile
->
f_dentry
->
d_inode
);
pCifsInode
->
clientCanCacheAll
=
FALSE
;
if
(
pSMB
->
OplockLevel
==
0
)
pCifsInode
->
clientCanCacheRead
=
FALSE
;
pCifsInode
->
oplockPending
=
TRUE
;
AllocOplockQEntry
(
netfile
->
pfile
,
tcon
);
cFYI
(
1
,(
"about to wake up oplock thd"
));
wake_up_process
(
oplockThread
);
return
TRUE
;
}
}
...
...
fs/cifs/transport.c
View file @
2dc51bdf
...
...
@@ -32,6 +32,7 @@
#include "cifs_debug.h"
extern
kmem_cache_t
*
cifs_mid_cachep
;
extern
kmem_cache_t
*
cifs_oplock_cachep
;
struct
mid_q_entry
*
AllocMidQEntry
(
struct
smb_hdr
*
smb_buffer
,
struct
cifsSesInfo
*
ses
)
...
...
@@ -95,6 +96,39 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
kmem_cache_free
(
cifs_mid_cachep
,
midEntry
);
}
struct
oplock_q_entry
*
AllocOplockQEntry
(
struct
file
*
file
,
struct
cifsTconInfo
*
tcon
)
{
struct
oplock_q_entry
*
temp
;
if
((
file
==
NULL
)
||
(
tcon
==
NULL
))
{
cERROR
(
1
,
(
"Null parms passed to AllocOplockQEntry"
));
return
NULL
;
}
temp
=
(
struct
oplock_q_entry
*
)
kmem_cache_alloc
(
cifs_oplock_cachep
,
SLAB_KERNEL
);
if
(
temp
==
NULL
)
return
temp
;
else
{
temp
->
file_to_flush
=
file
;
temp
->
tcon
=
tcon
;
write_lock
(
&
GlobalMid_Lock
);
list_add_tail
(
&
temp
->
qhead
,
&
GlobalOplock_Q
);
write_unlock
(
&
GlobalMid_Lock
);
}
return
temp
;
}
void
DeleteOplockQEntry
(
struct
oplock_q_entry
*
oplockEntry
)
{
/* BB add spinlock to protect midq for each session BB */
write_lock
(
&
GlobalMid_Lock
);
/* should we check if list empty first? */
list_del
(
&
oplockEntry
->
qhead
);
write_unlock
(
&
GlobalMid_Lock
);
kmem_cache_free
(
cifs_oplock_cachep
,
oplockEntry
);
}
int
smb_send
(
struct
socket
*
ssocket
,
struct
smb_hdr
*
smb_buffer
,
unsigned
int
smb_buf_length
,
struct
sockaddr
*
sin
)
...
...
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