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
29fa971b
Commit
29fa971b
authored
Aug 06, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://cifs.bkbits.net/linux-2.5cifs
into home.osdl.org:/home/torvalds/v2.5/linux
parents
a58eef7f
e8aea2e4
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
359 additions
and
142 deletions
+359
-142
fs/cifs/AUTHORS
fs/cifs/AUTHORS
+2
-1
fs/cifs/CHANGES
fs/cifs/CHANGES
+22
-0
fs/cifs/README
fs/cifs/README
+5
-1
fs/cifs/cifsfs.c
fs/cifs/cifsfs.c
+47
-24
fs/cifs/cifsglob.h
fs/cifs/cifsglob.h
+3
-1
fs/cifs/cifspdu.h
fs/cifs/cifspdu.h
+6
-0
fs/cifs/cifsproto.h
fs/cifs/cifsproto.h
+4
-3
fs/cifs/cifssmb.c
fs/cifs/cifssmb.c
+19
-6
fs/cifs/connect.c
fs/cifs/connect.c
+1
-1
fs/cifs/dir.c
fs/cifs/dir.c
+74
-33
fs/cifs/file.c
fs/cifs/file.c
+80
-17
fs/cifs/inode.c
fs/cifs/inode.c
+67
-38
fs/cifs/link.c
fs/cifs/link.c
+2
-2
fs/cifs/misc.c
fs/cifs/misc.c
+4
-2
fs/cifs/ntlmssp.h
fs/cifs/ntlmssp.h
+13
-8
fs/cifs/transport.c
fs/cifs/transport.c
+10
-5
No files found.
fs/cifs/AUTHORS
View file @
29fa971b
...
...
@@ -19,10 +19,11 @@ Patch Contributors
------------------
Zwane Mwaikambo
Andi Kleen
Amrut Joshi
Test case and Bug Report contributors
-------------------------------------
Thanks to those in the community who have submitted detailed bug reports
and debug of problems they have found: Jochen Dolze, David Blaine,
Rene Scharfe, Martin Josefsson and others.
Rene Scharfe, Martin Josefsson
, Alexander Wild
and others.
fs/cifs/CHANGES
View file @
29fa971b
Version 0.87
------------
Fix oops on big endian readdir. Set blksize to be even power of two (2**blkbits) to fix
allocation size miscalculation. After oplock token lost do not read through
cache.
Version 0.86
------------
Fix oops on empty file readahead. Fix for file size handling for locally cached files.
Version 0.85
------------
Fix oops in mkdir when server fails to return inode info. Fix oops in reopen_files
during auto reconnection to server after server recovered from failure.
Version 0.84
------------
Finish support for Linux 2.5 open/create changes, which removes the
redundant NTCreate/QPathInfo/close that was sent during file create.
Enable oplock by default. Enable packet signing by default (needed to
access many recent Windows servers)
Version 0.83
------------
Fix oops when mounting to long server names caused by inverted parms to kmalloc.
...
...
fs/cifs/README
View file @
29fa971b
...
...
@@ -150,7 +150,10 @@ Configuration pseudo-files:
point and if the uids user/password mapping
information is available. (default is 0)
PacketSigningEnabled If set to one, cifs packet signing is enabled
(default 0)
and will be used if the server requires
it. If set to two, cifs packet signing is
required even if the server considers packet
signing optional. (default 1)
cifsFYI If set to one, additional debug information is
logged to the system error log. (default 0)
ExtendedSecurity If set to one, SPNEGO session establishment
...
...
@@ -166,6 +169,7 @@ Configuration pseudo-files:
for one second improving performance of lookups
(default 1)
OplockEnabled If set to one, safe distributed caching enabled.
(default 1)
These experimental features and tracing can be enabled by changing flags in /proc/fs/cifs
(after the cifs module has been installed or built into the kernel, e.g. insmod cifs).
...
...
fs/cifs/cifsfs.c
View file @
29fa971b
...
...
@@ -47,12 +47,12 @@ extern struct file_system_type cifs_fs_type;
int
cifsFYI
=
0
;
int
cifsERROR
=
1
;
int
traceSMB
=
0
;
unsigned
int
oplockEnabled
=
0
;
unsigned
int
oplockEnabled
=
1
;
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
sign_CIFS_PDUs
=
1
;
unsigned
int
CIFSMaximumBufferSize
=
CIFS_MAX_MSGSIZE
;
struct
task_struct
*
oplockThread
=
NULL
;
...
...
@@ -90,10 +90,10 @@ cifs_read_super(struct super_block *sb, void *data,
sb
->
s_magic
=
CIFS_MAGIC_NUMBER
;
sb
->
s_op
=
&
cifs_super_ops
;
if
(
cifs_sb
->
tcon
->
ses
->
server
->
maxBuf
>
MAX_CIFS_HDR_SIZE
+
512
)
sb
->
s_blocksize
=
cifs_sb
->
tcon
->
ses
->
server
->
maxBuf
-
MAX_CIFS_HDR_SIZE
;
else
sb
->
s_blocksize
=
CIFSMaximumBufferSize
;
/*
if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE;
*/
sb
->
s_blocksize
=
CIFS_MAX_MSGSIZE
;
sb
->
s_blocksize_bits
=
14
;
/* default 2**14 = CIFS_MAX_MSGSIZE */
inode
=
iget
(
sb
,
ROOT_I
);
...
...
@@ -201,10 +201,14 @@ cifs_alloc_inode(struct super_block *sb)
cifs_inode
->
cifsAttrs
=
0x20
;
/* default */
atomic_set
(
&
cifs_inode
->
inUse
,
0
);
cifs_inode
->
time
=
0
;
if
(
oplockEnabled
)
{
cifs_inode
->
clientCanCacheRead
=
1
;
cifs_inode
->
clientCanCacheAll
=
1
;
}
/* Until the file is open and we have gotten oplock
info back from the server, can not assume caching of
file data or metadata */
cifs_inode
->
clientCanCacheRead
=
FALSE
;
cifs_inode
->
clientCanCacheAll
=
FALSE
;
cifs_inode
->
vfs_inode
.
i_blksize
=
CIFS_MAX_MSGSIZE
;
cifs_inode
->
vfs_inode
.
i_blkbits
=
14
;
/* 2**14 = CIFS_MAX_MSGSIZE */
INIT_LIST_HEAD
(
&
cifs_inode
->
openFileList
);
return
&
cifs_inode
->
vfs_inode
;
}
...
...
@@ -281,6 +285,27 @@ cifs_get_sb(struct file_system_type *fs_type,
return
sb
;
}
ssize_t
cifs_read_wrapper
(
struct
file
*
file
,
char
*
read_data
,
size_t
read_size
,
loff_t
*
poffset
)
{
if
(
CIFS_I
(
file
->
f_dentry
->
d_inode
)
->
clientCanCacheRead
)
return
generic_file_read
(
file
,
read_data
,
read_size
,
poffset
);
else
return
cifs_read
(
file
,
read_data
,
read_size
,
poffset
);
}
ssize_t
cifs_write_wrapper
(
struct
file
*
file
,
const
char
*
write_data
,
size_t
write_size
,
loff_t
*
poffset
)
{
if
(
CIFS_I
(
file
->
f_dentry
->
d_inode
)
->
clientCanCacheAll
)
/* check caching for write */
return
generic_file_write
(
file
,
write_data
,
write_size
,
poffset
);
else
return
cifs_write
(
file
,
write_data
,
write_size
,
poffset
);
}
static
struct
file_system_type
cifs_fs_type
=
{
.
owner
=
THIS_MODULE
,
.
name
=
"cifs"
,
...
...
@@ -439,8 +464,9 @@ static int cifs_oplock_thread(void * dummyarg)
struct
list_head
*
tmp
;
struct
list_head
*
tmp1
;
struct
oplock_q_entry
*
oplock_item
;
struct
file
*
pfile
;
struct
cifsTconInfo
*
pTcon
;
struct
inode
*
inode
;
__u16
netfid
;
int
rc
;
daemonize
(
"cifsoplockd"
);
...
...
@@ -457,23 +483,20 @@ static int cifs_oplock_thread(void * dummyarg)
qhead
);
if
(
oplock_item
)
{
pTcon
=
oplock_item
->
tcon
;
pfile
=
oplock_item
->
file_to_flush
;
cFYI
(
1
,(
"process item on queue"
));
/* BB remove */
inode
=
oplock_item
->
pinode
;
netfid
=
oplock_item
->
netfid
;
DeleteOplockQEntry
(
oplock_item
);
write_unlock
(
&
GlobalMid_Lock
);
rc
=
filemap_fdatawrite
(
pfile
->
f_dentry
->
d_
inode
->
i_mapping
);
rc
=
filemap_fdatawrite
(
inode
->
i_mapping
);
if
(
rc
)
CIFS_I
(
pfile
->
f_dentry
->
d_
inode
)
->
write_behind_rc
CIFS_I
(
inode
)
->
write_behind_rc
=
rc
;
cFYI
(
1
,(
"Oplock flush file %p rc %d"
,
pfile
,
rc
));
if
(
pfile
->
private_data
)
{
rc
=
CIFSSMBLock
(
0
,
pTcon
,
((
struct
cifsFileInfo
*
)
pfile
->
private_data
)
->
netfid
,
0
/* len */
,
0
/* offset */
,
0
,
0
,
LOCKING_ANDX_OPLOCK_RELEASE
,
0
/* wait flag */
);
cFYI
(
1
,(
"Oplock release rc = %d "
,
rc
));
}
cFYI
(
1
,(
"Oplock flush inode %p rc %d"
,
inode
,
rc
));
rc
=
CIFSSMBLock
(
0
,
pTcon
,
netfid
,
0
/* len */
,
0
/* offset */
,
0
,
0
,
LOCKING_ANDX_OPLOCK_RELEASE
,
0
/* wait flag */
);
cFYI
(
1
,(
"Oplock release rc = %d "
,
rc
));
write_lock
(
&
GlobalMid_Lock
);
}
else
break
;
...
...
fs/cifs/cifsglob.h
View file @
29fa971b
...
...
@@ -208,6 +208,7 @@ struct cifsFileInfo {
/* BB add lock scope info here if needed */
;
/* lock scope id (0 if none) */
struct
file
*
pfile
;
/* needed for writepage */
struct
inode
*
pInode
;
/* needed for oplock break */
int
endOfSearch
:
1
;
/* we have reached end of search */
int
closePend
:
1
;
/* file is marked to close */
int
emptyDir
:
1
;
...
...
@@ -263,8 +264,9 @@ struct mid_q_entry {
struct
oplock_q_entry
{
struct
list_head
qhead
;
struct
file
*
file_to_flush
;
struct
inode
*
pinode
;
struct
cifsTconInfo
*
tcon
;
__u16
netfid
;
};
#define MID_FREE 0
...
...
fs/cifs/cifspdu.h
View file @
29fa971b
...
...
@@ -633,6 +633,12 @@ typedef struct smb_com_open_req { /* also handles create */
char
fileName
[
1
];
}
OPEN_REQ
;
/* open response: oplock levels */
#define OPLOCK_NONE 0
#define OPLOCK_EXCLUSIVE 1
#define OPLOCK_BATCH 2
#define OPLOCK_READ 3
/* level 2 oplock */
typedef
struct
smb_com_open_rsp
{
struct
smb_hdr
hdr
;
/* wct = 34 BB */
__u8
AndXCommand
;
...
...
fs/cifs/cifsproto.h
View file @
29fa971b
...
...
@@ -57,7 +57,7 @@ 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
*
);
struct
oplock_q_entry
*
AllocOplockQEntry
(
struct
inode
*
,
u16
,
struct
cifsTconInfo
*
);
void
DeleteOplockQEntry
(
struct
oplock_q_entry
*
);
extern
struct
timespec
cifs_NTtimeToUnix
(
u64
/* utc nanoseconds since 1601 */
);
extern
u64
cifs_UnixTimeToNT
(
struct
timespec
);
...
...
@@ -68,7 +68,8 @@ extern void RevUcode_to_Ucode_with_Len(char *revUnicode, char *UnicodeName,
extern
void
Ucode_to_RevUcode_with_Len
(
char
*
Unicode
,
char
*
revUnicodeName
,
int
Len
);
extern
int
cifs_get_inode_info
(
struct
inode
**
pinode
,
const
unsigned
char
*
search_path
,
const
unsigned
char
*
search_path
,
FILE_ALL_INFO
*
pfile_info
,
struct
super_block
*
sb
);
extern
int
cifs_get_inode_info_unix
(
struct
inode
**
pinode
,
const
unsigned
char
*
search_path
,
...
...
@@ -195,7 +196,7 @@ extern int CIFSSMBQueryReparseLinkInfo(const int xid,
extern
int
CIFSSMBOpen
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
char
*
fileName
,
const
int
disposition
,
const
int
access_flags
,
const
int
omode
,
__u16
*
netfid
,
int
*
pOplock
,
__u16
*
netfid
,
int
*
pOplock
,
FILE_ALL_INFO
*
,
const
struct
nls_table
*
nls_codepage
);
extern
int
CIFSSMBClose
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
int
smb_file_id
);
...
...
fs/cifs/cifssmb.c
View file @
29fa971b
...
...
@@ -179,7 +179,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
cERROR
(
1
,
(
"Server requires /proc/fs/cifs/PacketSigningEnabled"
));
server
->
secMode
&=
~
(
SECMODE_SIGN_ENABLED
|
SECMODE_SIGN_REQUIRED
);
}
else
if
(
sign_CIFS_PDUs
==
1
)
{
if
((
server
->
secMode
&
SECMODE_SIGN_REQUIRED
)
==
0
)
server
->
secMode
&=
~
(
SECMODE_SIGN_ENABLED
|
SECMODE_SIGN_REQUIRED
);
}
}
if
(
pSMB
)
buf_release
(
pSMB
);
...
...
@@ -419,7 +423,8 @@ int
CIFSSMBOpen
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
char
*
fileName
,
const
int
openDisposition
,
const
int
access_flags
,
const
int
create_options
,
__u16
*
netfid
,
int
*
pOplock
,
const
struct
nls_table
*
nls_codepage
)
int
*
pOplock
,
FILE_ALL_INFO
*
pfile_info
,
const
struct
nls_table
*
nls_codepage
)
{
int
rc
=
-
EACCES
;
OPEN_REQ
*
pSMB
=
NULL
;
...
...
@@ -476,16 +481,23 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
pSMB
->
hdr
.
smb_buf_length
+=
pSMB
->
ByteCount
;
pSMB
->
ByteCount
=
cpu_to_le16
(
pSMB
->
ByteCount
);
/* long_op set to 1 to allow for oplock break timeouts */
rc
=
SendReceive
(
xid
,
tcon
->
ses
,
(
struct
smb_hdr
*
)
pSMB
,
(
struct
smb_hdr
*
)
pSMBr
,
&
bytes_returned
,
0
);
(
struct
smb_hdr
*
)
pSMBr
,
&
bytes_returned
,
1
);
if
(
rc
)
{
cFYI
(
1
,
(
"Error in Open = %d"
,
rc
));
}
else
{
*
pOplock
=
pSMBr
->
OplockLevel
;
/* one byte no need to le_to_cpu */
*
netfid
=
pSMBr
->
Fid
;
/* cifs fid stays in le */
/* Do we care about the CreateAction in any cases? */
/* BB add code to update inode file sizes from create response */
if
(
pfile_info
)
{
memcpy
((
char
*
)
pfile_info
,(
char
*
)
&
pSMBr
->
CreationTime
,
36
/* CreationTime to Attributes */
);
/* the file_info buf is endian converted by caller */
pfile_info
->
AllocationSize
=
pSMBr
->
AllocationSize
;
pfile_info
->
EndOfFile
=
pSMBr
->
EndOfFile
;
pfile_info
->
NumberOfLinks
=
cpu_to_le32
(
1
);
}
}
if
(
pSMB
)
buf_release
(
pSMB
);
...
...
@@ -1231,11 +1243,12 @@ CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
/* BB also check enough total bytes returned */
if
((
pSMBr
->
ByteCount
<
40
)
||
(
pSMBr
->
DataOffset
>
512
))
rc
=
-
EIO
;
/* bad smb */
else
{
else
if
(
pFindData
)
{
memcpy
((
char
*
)
pFindData
,
(
char
*
)
&
pSMBr
->
hdr
.
Protocol
+
pSMBr
->
DataOffset
,
sizeof
(
FILE_ALL_INFO
));
}
}
else
rc
=
-
ENOMEM
;
}
if
(
pSMB
)
buf_release
(
pSMB
);
...
...
fs/cifs/connect.c
View file @
29fa971b
...
...
@@ -251,7 +251,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
/* iov.iov_base = smb_buffer+total_read;
iov.iov_len = pdu_length-total_read; */
length
=
sock_recvmsg
(
csocket
,
&
smb_msg
,
pdu_length
-
total_read
,
0
);
pdu_length
-
total_read
,
0
);
/* cERROR(1,("For iovlen %d Length received: %d with total read %d",
iov.iov_len, length,total_read)); */
if
(
length
==
0
)
{
...
...
fs/cifs/dir.c
View file @
29fa971b
...
...
@@ -125,13 +125,16 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
{
int
rc
=
-
ENOENT
;
int
xid
;
int
oplock
=
REQ_OPLOCK
;
int
oplock
=
0
;
int
desiredAccess
=
GENERIC_ALL
;
__u16
fileHandle
;
struct
cifs_sb_info
*
cifs_sb
;
struct
cifsTconInfo
*
pTcon
;
char
*
full_path
=
NULL
;
FILE_ALL_INFO
*
buf
=
NULL
;
struct
inode
*
newinode
=
NULL
;
struct
cifsFileInfo
*
pCifsFile
=
NULL
;
struct
cifsInodeInfo
*
pCifsInode
;
xid
=
GetXid
();
...
...
@@ -140,10 +143,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
full_path
=
build_path_from_dentry
(
direntry
);
if
(
nd
)
{
cFYI
(
1
,(
"In create
nd flags = 0x%x for %s"
,
nd
->
flags
,
full_path
));
cFYI
(
1
,(
"Intent flags: 0x%x"
,
nd
->
intent
.
open
.
flags
));
cFYI
(
1
,(
"In create
for inode %p dentry->inode %p nd flags = 0x%x for %s"
,
inode
,
direntry
->
d_inode
,
nd
->
flags
,
full_path
));
if
((
nd
->
intent
.
open
.
flags
&
O_ACCMODE
)
==
O_RDONLY
)
desiredAccess
=
GENERIC_READ
;
else
if
((
nd
->
intent
.
open
.
flags
&
O_ACCMODE
)
==
O_WRONLY
)
...
...
@@ -152,42 +154,93 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
desiredAccess
=
GENERIC_ALL
;
}
/* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */
if
(
oplockEnabled
)
oplock
=
REQ_OPLOCK
;
/* BB add processing for setting the equivalent of mode - e.g. via CreateX with ACLs */
buf
=
kmalloc
(
sizeof
(
FILE_ALL_INFO
),
GFP_KERNEL
);
rc
=
CIFSSMBOpen
(
xid
,
pTcon
,
full_path
,
FILE_OVERWRITE_IF
,
desiredAccess
,
CREATE_NOT_DIR
,
&
fileHandle
,
&
oplock
,
cifs_sb
->
local_nls
);
&
fileHandle
,
&
oplock
,
buf
,
cifs_sb
->
local_nls
);
if
(
rc
)
{
cFYI
(
1
,
(
"cifs_create returned 0x%x "
,
rc
));
}
else
{
/* BB for case of overwriting existing file can we use the inode that was
passed in rather than creating new one?? */
if
(
pTcon
->
ses
->
capabilities
&
CAP_UNIX
)
rc
=
cifs_get_inode_info_unix
(
&
newinode
,
full_path
,
inode
->
i_sb
);
else
rc
=
cifs_get_inode_info
(
&
newinode
,
full_path
,
inode
->
i_sb
);
buf
,
inode
->
i_sb
);
if
(
rc
!=
0
)
{
cFYI
(
1
,(
"Create worked but get_inode_info failed with rc = %d"
,
rc
));
/* close handle */
}
else
{
direntry
->
d_op
=
&
cifs_dentry_ops
;
d_instantiate
(
direntry
,
newinode
);
}
/* BB check oplock state before deciding to call following */
/* if(*oplock)
save off handle in inode and dontdoclose */
CIFSSMBClose
(
xid
,
pTcon
,
fileHandle
);
/* BB In the future chain close with the NTCreateX to narrow window */
if
(
newinode
)
newinode
->
i_mode
=
mode
;
}
if
((
nd
->
flags
&
LOOKUP_OPEN
)
==
FALSE
)
{
/* mknod case - do not leave file open */
CIFSSMBClose
(
xid
,
pTcon
,
fileHandle
);
if
(
newinode
)
newinode
->
i_mode
=
mode
;
if
(
cifs_sb
->
tcon
->
ses
->
capabilities
&
CAP_UNIX
)
CIFSSMBUnixSetPerms
(
xid
,
pTcon
,
full_path
,
mode
,
(
__u64
)
-
1
,
(
__u64
)
-
1
,
0
/* dev */
,
cifs_sb
->
local_nls
);
else
{
/* BB implement via Windows security descriptors */
/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
/* in the meantime could set r/o dos attribute when perms are eg:
mode & 0222 == 0 */
}
}
else
if
(
newinode
)
{
newinode
->
i_mode
=
mode
;
pCifsFile
=
(
struct
cifsFileInfo
*
)
kmalloc
(
sizeof
(
struct
cifsFileInfo
),
GFP_KERNEL
);
if
(
pCifsFile
)
{
memset
((
char
*
)
pCifsFile
,
0
,
sizeof
(
struct
cifsFileInfo
));
pCifsFile
->
netfid
=
fileHandle
;
pCifsFile
->
pid
=
current
->
pid
;
pCifsFile
->
pInode
=
newinode
;
/* pCifsFile->pfile = file; */
/* put in at open time */
write_lock
(
&
GlobalSMBSeslock
);
list_add
(
&
pCifsFile
->
tlist
,
&
pTcon
->
openFileList
);
pCifsInode
=
CIFS_I
(
newinode
);
if
(
pCifsInode
)
{
list_add
(
&
pCifsFile
->
flist
,
&
pCifsInode
->
openFileList
);
if
(
oplock
==
OPLOCK_EXCLUSIVE
)
{
pCifsInode
->
clientCanCacheAll
=
TRUE
;
pCifsInode
->
clientCanCacheRead
=
TRUE
;
cFYI
(
1
,(
"Exclusive Oplock granted on inode %p"
,
newinode
));
}
else
if
(
oplock
==
OPLOCK_READ
)
pCifsInode
->
clientCanCacheRead
=
TRUE
;
}
write_unlock
(
&
GlobalSMBSeslock
);
if
(
cifs_sb
->
tcon
->
ses
->
capabilities
&
CAP_UNIX
)
CIFSSMBUnixSetPerms
(
xid
,
pTcon
,
full_path
,
inode
->
i_mode
,
(
__u64
)
-
1
,
(
__u64
)
-
1
,
0
/* dev */
,
cifs_sb
->
local_nls
);
else
{
/* BB implement via Windows security descriptors */
/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
/* in the meantime could set r/o dos attribute when perms are eg:
mode & 0222 == 0 */
}
}
}
}
if
(
buf
)
kfree
(
buf
);
if
(
full_path
)
kfree
(
full_path
);
kfree
(
full_path
);
FreeXid
(
xid
);
return
rc
;
...
...
@@ -261,17 +314,11 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
cFYI
(
1
,
(
" Full path: %s inode = 0x%p"
,
full_path
,
direntry
->
d_inode
));
if
(
nd
)
{
/* BB remove begin */
cFYI
(
1
,(
"In lookup nd flags = 0x%x"
,
nd
->
flags
));
cFYI
(
1
,(
"Intent flags: 0x%x"
,
nd
->
intent
.
open
.
flags
));
}
/* BB remove end BB */
if
(
pTcon
->
ses
->
capabilities
&
CAP_UNIX
)
rc
=
cifs_get_inode_info_unix
(
&
newInode
,
full_path
,
parent_dir_inode
->
i_sb
);
else
rc
=
cifs_get_inode_info
(
&
newInode
,
full_path
,
rc
=
cifs_get_inode_info
(
&
newInode
,
full_path
,
NULL
,
parent_dir_inode
->
i_sb
);
if
((
rc
==
0
)
&&
(
newInode
!=
NULL
))
{
...
...
@@ -328,12 +375,6 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
/* lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */
if
(
nd
)
{
/* BB remove begin */
cFYI
(
1
,(
"In d_revalidate nd flags = 0x%x"
,
nd
->
flags
));
cFYI
(
1
,(
"Intent flags: 0x%x"
,
nd
->
intent
.
open
.
flags
));
}
/* BB remove end BB */
if
(
direntry
->
d_inode
)
{
if
(
cifs_revalidate
(
direntry
))
{
/* unlock_kernel(); */
...
...
fs/cifs/file.c
View file @
29fa971b
...
...
@@ -45,16 +45,41 @@ cifs_open(struct inode *inode, struct file *file)
struct
cifsTconInfo
*
pTcon
;
struct
cifsFileInfo
*
pCifsFile
;
struct
cifsInodeInfo
*
pCifsInode
;
struct
list_head
*
tmp
;
char
*
full_path
=
NULL
;
int
desiredAccess
=
0x20197
;
int
disposition
=
FILE_OPEN
;
__u16
netfid
;
FILE_ALL_INFO
*
buf
=
NULL
;
xid
=
GetXid
();
cifs_sb
=
CIFS_SB
(
inode
->
i_sb
);
pTcon
=
cifs_sb
->
tcon
;
if
(
file
->
f_flags
&
O_CREAT
)
{
/* search inode for this file and fill in file->private_data = */
pCifsInode
=
CIFS_I
(
file
->
f_dentry
->
d_inode
);
read_lock
(
&
GlobalSMBSeslock
);
list_for_each
(
tmp
,
&
pCifsInode
->
openFileList
)
{
pCifsFile
=
list_entry
(
tmp
,
struct
cifsFileInfo
,
flist
);
if
((
pCifsFile
->
pfile
==
NULL
)
&&
(
pCifsFile
->
pid
=
current
->
pid
)){
/* set mode ?? */
pCifsFile
->
pfile
=
file
;
/* needed for writepage */
file
->
private_data
=
pCifsFile
;
break
;
}
}
read_unlock
(
&
GlobalSMBSeslock
);
if
(
file
->
private_data
!=
NULL
)
{
rc
=
0
;
FreeXid
(
xid
);
return
rc
;
}
else
{
cERROR
(
1
,(
"could not find file instance for new file %p "
,
file
));
}
}
full_path
=
build_path_from_dentry
(
file
->
f_dentry
);
cFYI
(
1
,
(
" inode = 0x%p file flags are %x for %s"
,
inode
,
file
->
f_flags
,
full_path
));
...
...
@@ -86,20 +111,22 @@ cifs_open(struct inode *inode, struct file *file)
if
(
file
->
f_flags
&
O_CREAT
)
disposition
=
FILE_OVERWRITE
;
/* BB first check if file has batch oplock (or oplock ?) */
/* BB finish adding in oplock support BB */
if
(
oplockEnabled
)
oplock
=
REQ_OPLOCK
;
else
oplock
=
FALSE
;
/* BB pass O_SYNC flag through on file attributes .. BB */
/* Also refresh inode by passing in file_info buf returned by SMBOpen
and calling get_inode_info with returned buf (at least
helps non-Unix server case */
buf
=
kmalloc
(
sizeof
(
FILE_ALL_INFO
),
GFP_KERNEL
);
rc
=
CIFSSMBOpen
(
xid
,
pTcon
,
full_path
,
disposition
,
desiredAccess
,
CREATE_NOT_DIR
,
&
netfid
,
&
oplock
,
cifs_sb
->
local_nls
);
CREATE_NOT_DIR
,
&
netfid
,
&
oplock
,
buf
,
cifs_sb
->
local_nls
);
if
(
rc
)
{
cFYI
(
1
,
(
"cifs_open returned 0x%x "
,
rc
));
cFYI
(
1
,
(
"oplock: %d "
,
oplock
));
cFYI
(
1
,
(
"oplock: %d "
,
oplock
));
}
else
{
file
->
private_data
=
kmalloc
(
sizeof
(
struct
cifsFileInfo
),
GFP_KERNEL
);
...
...
@@ -110,12 +137,27 @@ cifs_open(struct inode *inode, struct file *file)
pCifsFile
->
netfid
=
netfid
;
pCifsFile
->
pid
=
current
->
pid
;
pCifsFile
->
pfile
=
file
;
/* needed for writepage */
pCifsFile
->
pInode
=
inode
;
write_lock
(
&
file
->
f_owner
.
lock
);
write_lock
(
&
GlobalSMBSeslock
);
list_add
(
&
pCifsFile
->
tlist
,
&
pTcon
->
openFileList
);
pCifsInode
=
CIFS_I
(
file
->
f_dentry
->
d_inode
);
if
(
pCifsInode
->
openFileList
.
next
)
if
(
pCifsInode
)
{
if
(
pTcon
->
ses
->
capabilities
&
CAP_UNIX
)
rc
=
cifs_get_inode_info_unix
(
&
file
->
f_dentry
->
d_inode
,
full_path
,
inode
->
i_sb
);
else
rc
=
cifs_get_inode_info
(
&
file
->
f_dentry
->
d_inode
,
full_path
,
buf
,
inode
->
i_sb
);
list_add
(
&
pCifsFile
->
flist
,
&
pCifsInode
->
openFileList
);
if
(
oplock
==
OPLOCK_EXCLUSIVE
)
{
pCifsInode
->
clientCanCacheAll
=
TRUE
;
pCifsInode
->
clientCanCacheRead
=
TRUE
;
cFYI
(
1
,(
"Exclusive Oplock granted on inode %p"
,
file
->
f_dentry
->
d_inode
));
}
else
if
(
oplock
==
OPLOCK_READ
)
pCifsInode
->
clientCanCacheRead
=
TRUE
;
}
write_unlock
(
&
GlobalSMBSeslock
);
write_unlock
(
&
file
->
f_owner
.
lock
);
if
(
file
->
f_flags
&
O_CREAT
)
{
...
...
@@ -136,6 +178,8 @@ cifs_open(struct inode *inode, struct file *file)
}
}
if
(
buf
)
kfree
(
buf
);
if
(
full_path
)
kfree
(
full_path
);
FreeXid
(
xid
);
...
...
@@ -164,12 +208,14 @@ int reopen_files(struct cifsTconInfo * pTcon, struct nls_table * nlsinfo)
/* list all files open on tree connection */
read_lock
(
&
GlobalSMBSeslock
);
list_for_each_safe
(
tmp
,
tmp1
,
&
pTcon
->
openFileList
)
{
open_file
=
list_entry
(
tmp
,
struct
cifsFileInfo
,
f
list
);
open_file
=
list_entry
(
tmp
,
struct
cifsFileInfo
,
t
list
);
if
(
open_file
)
{
if
(
open_file
->
search_resume_name
)
{
kfree
(
open_file
->
search_resume_name
);
}
file
=
open_file
->
pfile
;
list_del
(
&
open_file
->
flist
);
list_del
(
&
open_file
->
tlist
);
kfree
(
open_file
);
if
(
file
)
{
file
->
private_data
=
NULL
;
...
...
@@ -206,8 +252,7 @@ cifs_close(struct inode *inode, struct file *file)
pTcon
=
cifs_sb
->
tcon
;
if
(
pSMBFile
)
{
write_lock
(
&
file
->
f_owner
.
lock
);
if
(
pSMBFile
->
flist
.
next
)
list_del
(
&
pSMBFile
->
flist
);
list_del
(
&
pSMBFile
->
flist
);
list_del
(
&
pSMBFile
->
tlist
);
write_unlock
(
&
file
->
f_owner
.
lock
);
rc
=
CIFSSMBClose
(
xid
,
pTcon
,
pSMBFile
->
netfid
);
...
...
@@ -218,6 +263,13 @@ cifs_close(struct inode *inode, struct file *file)
}
else
rc
=
-
EBADF
;
if
(
list_empty
(
&
(
CIFS_I
(
inode
)
->
openFileList
)))
{
cFYI
(
1
,(
"closing last open instance for inode %p"
,
inode
));
/* if the file is not open we do not know if we can cache
info on this inode, much less write behind and read ahead */
CIFS_I
(
inode
)
->
clientCanCacheRead
=
FALSE
;
CIFS_I
(
inode
)
->
clientCanCacheAll
=
FALSE
;
}
if
((
rc
==
0
)
&&
CIFS_I
(
inode
)
->
write_behind_rc
)
rc
=
CIFS_I
(
inode
)
->
write_behind_rc
;
FreeXid
(
xid
);
...
...
@@ -462,8 +514,8 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
cifsInode
=
CIFS_I
(
mapping
->
host
);
read_lock
(
&
GlobalSMBSeslock
);
list_for_each_safe
(
tmp
,
tmp1
,
&
cifsInode
->
openFileList
)
{
open_file
=
list_entry
(
tmp
,
struct
cifsFileInfo
,
flist
);
/* We could
check if file is open for writing first */
open_file
=
list_entry
(
tmp
,
struct
cifsFileInfo
,
flist
);
/* We
check if file is open for writing first */
if
((
open_file
->
pfile
)
&&
((
open_file
->
pfile
->
f_flags
&
O_RDWR
)
||
(
open_file
->
pfile
->
f_flags
&
O_WRONLY
)))
{
...
...
@@ -810,7 +862,13 @@ cifs_readpages(struct file *file, struct address_space *mapping,
break
;
}
}
else
{
cFYI
(
1
,(
"No bytes read"
));
cFYI
(
1
,(
"No bytes read cleaning remaining pages off readahead list"
));
/* BB turn off caching and do new lookup on file size at server? */
while
(
!
list_empty
(
page_list
)
&&
(
i
<
num_pages
))
{
page
=
list_entry
(
page_list
->
prev
,
struct
page
,
list
);
list_del
(
&
page
->
list
);
}
break
;
}
if
(
smb_read_data
)
{
...
...
@@ -927,7 +985,7 @@ fill_in_inode(struct inode *tmp_inode,
/* can not fill in nlink here as in qpathinfo version and Unx search */
tmp_inode
->
i_size
=
pfindData
->
EndOfFile
;
tmp_inode
->
i_blocks
=
do_div
(
pfindData
->
AllocationSize
,
tmp_inode
->
i_blksize
)
;
(
tmp_inode
->
i_blksize
-
1
+
pfindData
->
AllocationSize
)
>>
tmp_inode
->
i_blkbits
;
if
(
pfindData
->
AllocationSize
<
pfindData
->
EndOfFile
)
cFYI
(
1
,
(
"Possible sparse file: allocation size less than end of file "
));
cFYI
(
1
,
...
...
@@ -1001,7 +1059,8 @@ unix_fill_in_inode(struct inode *tmp_inode,
pfindData
->
EndOfFile
=
le64_to_cpu
(
pfindData
->
EndOfFile
);
tmp_inode
->
i_size
=
pfindData
->
EndOfFile
;
tmp_inode
->
i_blocks
=
do_div
(
pfindData
->
NumOfBytes
,
tmp_inode
->
i_blksize
);
(
tmp_inode
->
i_blksize
-
1
+
pfindData
->
NumOfBytes
)
>>
tmp_inode
->
i_blkbits
;
if
(
S_ISREG
(
tmp_inode
->
i_mode
))
{
cFYI
(
1
,
(
" File inode "
));
tmp_inode
->
i_op
=
&
cifs_file_inode_ops
;
...
...
@@ -1040,6 +1099,10 @@ construct_dentry(struct qstr *qstring, struct file *file,
cFYI
(
0
,
(
" existing dentry with inode 0x%p"
,
tmp_dentry
->
d_inode
));
*
ptmp_inode
=
tmp_dentry
->
d_inode
;
/* BB overwrite the old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len ?? */
if
(
*
ptmp_inode
==
NULL
)
{
*
ptmp_inode
=
new_inode
(
file
->
f_dentry
->
d_sb
);
d_instantiate
(
tmp_dentry
,
*
ptmp_inode
);
}
}
else
{
tmp_dentry
=
d_alloc
(
file
->
f_dentry
,
qstring
);
*
ptmp_inode
=
new_inode
(
file
->
f_dentry
->
d_sb
);
...
...
@@ -1193,7 +1256,7 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
renew_parental_timestamps
(
file
->
f_dentry
);
lastFindData
=
(
FILE_DIRECTORY_INFO
*
)
((
char
*
)
pfindData
+
le32_to_cpu
(
findParms
.
LastNameOffset
)
);
findParms
.
LastNameOffset
);
if
((
char
*
)
lastFindData
>
(
char
*
)
pfindData
+
bufsize
)
{
cFYI
(
1
,(
"last search entry past end of packet"
));
rc
=
-
EIO
;
...
...
@@ -1248,7 +1311,7 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
pfindDataUnix
->
FileName
,
cifsFile
->
resume_name_length
);
}
for
(
i
=
2
;
i
<
findParms
.
SearchCount
+
2
;
i
++
)
{
for
(
i
=
2
;
i
<
(
unsigned
int
)
findParms
.
SearchCount
+
2
;
i
++
)
{
if
(
UnixSearch
==
FALSE
)
{
pfindData
->
FileNameLength
=
le32_to_cpu
(
pfindData
->
FileNameLength
);
...
...
@@ -1353,7 +1416,7 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
/* BB save off resume key, key name and name length */
lastFindData
=
(
FILE_DIRECTORY_INFO
*
)
((
char
*
)
pfindData
+
le32_to_cpu
(
findNextParms
.
LastNameOffset
)
);
+
findNextParms
.
LastNameOffset
);
if
((
char
*
)
lastFindData
>
(
char
*
)
pfindData
+
bufsize
)
{
cFYI
(
1
,(
"last search entry past end of packet"
));
rc
=
-
EIO
;
...
...
fs/cifs/inode.c
View file @
29fa971b
...
...
@@ -43,6 +43,9 @@ cifs_get_inode_info_unix(struct inode **pinode,
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
sb
);
char
*
tmp_path
;
/* BB add caching check so we do not go to server to overwrite inode info to cached file
where the local file sizes are correct and the server info is stale BB */
xid
=
GetXid
();
pTcon
=
cifs_sb
->
tcon
;
...
...
@@ -123,9 +126,13 @@ cifs_get_inode_info_unix(struct inode **pinode,
findData
.
NumOfBytes
=
le64_to_cpu
(
findData
.
NumOfBytes
);
findData
.
EndOfFile
=
le64_to_cpu
(
findData
.
EndOfFile
);
inode
->
i_size
=
findData
.
EndOfFile
;
inode
->
i_blksize
=
(
pTcon
->
ses
->
server
->
maxBuf
-
MAX_CIFS_HDR_SIZE
)
&
0xFFFFFE00
;
inode
->
i_blocks
=
do_div
(
findData
.
NumOfBytes
,
inode
->
i_blksize
);
/* blksize needs to be multiple of two. So safer to default to blksize
and blkbits set in superblock so 2**blkbits and blksize will match */
/* inode->i_blksize =
(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
inode
->
i_blocks
=
(
inode
->
i_blksize
-
1
+
findData
.
NumOfBytes
)
>>
inode
->
i_blkbits
;
if
(
findData
.
NumOfBytes
<
findData
.
EndOfFile
)
cFYI
(
1
,
(
"Server inconsistency Error: it says allocation size less than end of file "
));
cFYI
(
1
,
...
...
@@ -155,24 +162,38 @@ cifs_get_inode_info_unix(struct inode **pinode,
}
int
cifs_get_inode_info
(
struct
inode
**
pinode
,
const
unsigned
char
*
search_path
,
struct
super_block
*
sb
)
cifs_get_inode_info
(
struct
inode
**
pinode
,
const
unsigned
char
*
search_path
,
FILE_ALL_INFO
*
pfindData
,
struct
super_block
*
sb
)
{
int
xid
;
int
rc
=
0
;
FILE_ALL_INFO
findData
;
struct
cifsTconInfo
*
pTcon
;
struct
inode
*
inode
;
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
sb
);
char
*
tmp_path
;
char
*
buf
=
NULL
;
xid
=
GetXid
();
pTcon
=
cifs_sb
->
tcon
;
cFYI
(
1
,
(
" Getting info on %s "
,
search_path
));
/* we could have done a find first instead but this returns more info */
rc
=
CIFSSMBQPathInfo
(
xid
,
pTcon
,
search_path
,
&
findData
,
cFYI
(
1
,(
"Getting info on %s "
,
search_path
));
if
((
pfindData
==
NULL
)
&&
(
*
pinode
!=
NULL
))
{
if
(
CIFS_I
(
*
pinode
)
->
clientCanCacheRead
)
{
cFYI
(
1
,(
"No need to revalidate inode sizes on cached file "
));
FreeXid
(
xid
);
return
rc
;
}
}
/* if file info not passed in then get it from server */
if
(
pfindData
==
NULL
)
{
buf
=
kmalloc
(
sizeof
(
FILE_ALL_INFO
),
GFP_KERNEL
);
pfindData
=
(
FILE_ALL_INFO
*
)
buf
;
/* could do find first instead but this returns more info */
rc
=
CIFSSMBQPathInfo
(
xid
,
pTcon
,
search_path
,
pfindData
,
cifs_sb
->
local_nls
);
}
/* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
if
(
rc
)
{
if
(
rc
==
-
EREMOTE
)
{
...
...
@@ -183,8 +204,10 @@ cifs_get_inode_info(struct inode **pinode,
strnlen
(
search_path
,
MAX_PATHCONF
)
+
1
,
GFP_KERNEL
);
if
(
tmp_path
==
NULL
)
{
FreeXid
(
xid
);
return
-
ENOMEM
;
if
(
buf
)
kfree
(
buf
);
FreeXid
(
xid
);
return
-
ENOMEM
;
}
strncpy
(
tmp_path
,
pTcon
->
treeName
,
MAX_TREE_SIZE
);
...
...
@@ -195,8 +218,10 @@ cifs_get_inode_info(struct inode **pinode,
kfree
(
tmp_path
);
/* BB fix up inode etc. */
}
else
if
(
rc
)
{
FreeXid
(
xid
);
return
rc
;
if
(
buf
)
kfree
(
buf
);
FreeXid
(
xid
);
return
rc
;
}
}
else
{
struct
cifsInodeInfo
*
cifsInfo
;
...
...
@@ -208,32 +233,35 @@ cifs_get_inode_info(struct inode **pinode,
inode
=
*
pinode
;
cifsInfo
=
CIFS_I
(
inode
);
findData
.
Attributes
=
le32_to_cpu
(
findData
.
Attributes
);
cifsInfo
->
cifsAttrs
=
findData
.
Attributes
;
pfindData
->
Attributes
=
le32_to_cpu
(
pfindData
->
Attributes
);
cifsInfo
->
cifsAttrs
=
pfindData
->
Attributes
;
cFYI
(
1
,
(
" Old time %ld "
,
cifsInfo
->
time
));
cifsInfo
->
time
=
jiffies
;
cFYI
(
1
,
(
" New time %ld "
,
cifsInfo
->
time
));
atomic_inc
(
&
cifsInfo
->
inUse
);
/* inc on every refresh of inode */
inode
->
i_blksize
=
(
pTcon
->
ses
->
server
->
maxBuf
-
MAX_CIFS_HDR_SIZE
)
&
0xFFFFFE00
;
/* blksize needs to be multiple of two. So safer to default to blksize
and blkbits set in superblock so 2**blkbits and blksize will match */
/* inode->i_blksize =
(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
/* Linux can not store file creation time unfortunately so we ignore it */
inode
->
i_atime
=
cifs_NTtimeToUnix
(
le64_to_cpu
(
findData
.
LastAccessTime
));
cifs_NTtimeToUnix
(
le64_to_cpu
(
pfindData
->
LastAccessTime
));
inode
->
i_mtime
=
cifs_NTtimeToUnix
(
le64_to_cpu
(
findData
.
LastWriteTime
));
cifs_NTtimeToUnix
(
le64_to_cpu
(
pfindData
->
LastWriteTime
));
inode
->
i_ctime
=
cifs_NTtimeToUnix
(
le64_to_cpu
(
findData
.
ChangeTime
));
cifs_NTtimeToUnix
(
le64_to_cpu
(
pfindData
->
ChangeTime
));
cFYI
(
0
,
(
" Attributes came in as 0x%x "
,
findData
.
Attributes
));
(
" Attributes came in as 0x%x "
,
pfindData
->
Attributes
));
/* set default mode. will override for dirs below */
inode
->
i_mode
=
cifs_sb
->
mnt_file_mode
;
if
(
findData
.
Attributes
&
ATTR_REPARSE
)
{
if
(
pfindData
->
Attributes
&
ATTR_REPARSE
)
{
/* Can IFLNK be set as it basically is on windows with IFREG or IFDIR? */
inode
->
i_mode
|=
S_IFLNK
;
}
else
if
(
findData
.
Attributes
&
ATTR_DIRECTORY
)
{
}
else
if
(
pfindData
->
Attributes
&
ATTR_DIRECTORY
)
{
/* override default perms since we do not do byte range locking on dirs */
inode
->
i_mode
=
cifs_sb
->
mnt_dir_mode
;
inode
->
i_mode
|=
S_IFDIR
;
...
...
@@ -244,14 +272,12 @@ cifs_get_inode_info(struct inode **pinode,
inode
->
i_mode
&=
~
(
S_IWUGO
);
/* BB add code here - validate if device or weird share or device type? */
}
inode
->
i_size
=
le64_to_cpu
(
findData
.
EndOfFile
);
findData
.
AllocationSize
=
le64_to_cpu
(
findData
.
AllocationSize
);
inode
->
i_size
=
le64_to_cpu
(
pfindData
->
EndOfFile
);
pfindData
->
AllocationSize
=
le64_to_cpu
(
pfindData
->
AllocationSize
);
inode
->
i_blocks
=
do_div
(
findData
.
AllocationSize
,
inode
->
i_blksize
);
cFYI
(
1
,
(
" Size %ld and blocks %ld "
,
(
unsigned
long
)
inode
->
i_size
,
inode
->
i_blocks
));
inode
->
i_nlink
=
le32_to_cpu
(
findData
.
NumberOfLinks
);
(
inode
->
i_blksize
-
1
+
pfindData
->
AllocationSize
)
>>
inode
->
i_blkbits
;
inode
->
i_nlink
=
le32_to_cpu
(
pfindData
->
NumberOfLinks
);
/* BB fill in uid and gid here? with help from winbind?
or retrieve from NTFS stream extended attribute */
...
...
@@ -275,6 +301,8 @@ cifs_get_inode_info(struct inode **pinode,
kdev_t_to_nr
(
inode
->
i_rdev
));
}
}
if
(
buf
)
kfree
(
buf
);
FreeXid
(
xid
);
return
rc
;
}
...
...
@@ -290,7 +318,7 @@ cifs_read_inode(struct inode *inode)
if
(
cifs_sb
->
tcon
->
ses
->
capabilities
&
CAP_UNIX
)
cifs_get_inode_info_unix
(
&
inode
,
""
,
inode
->
i_sb
);
else
cifs_get_inode_info
(
&
inode
,
""
,
inode
->
i_sb
);
cifs_get_inode_info
(
&
inode
,
""
,
NULL
,
inode
->
i_sb
);
}
int
...
...
@@ -323,7 +351,7 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
rc
=
CIFSSMBOpen
(
xid
,
pTcon
,
full_path
,
FILE_OPEN
,
DELETE
,
CREATE_NOT_DIR
|
CREATE_DELETE_ON_CLOSE
,
&
netfid
,
&
oplock
,
cifs_sb
->
local_nls
);
&
netfid
,
&
oplock
,
NULL
,
cifs_sb
->
local_nls
);
if
(
rc
==
0
)
{
CIFSSMBClose
(
xid
,
pTcon
,
netfid
);
/* BB In the future chain close with the NTCreateX to narrow window */
...
...
@@ -387,12 +415,13 @@ cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
rc
=
cifs_get_inode_info_unix
(
&
newinode
,
full_path
,
inode
->
i_sb
);
else
rc
=
cifs_get_inode_info
(
&
newinode
,
full_path
,
rc
=
cifs_get_inode_info
(
&
newinode
,
full_path
,
NULL
,
inode
->
i_sb
);
direntry
->
d_op
=
&
cifs_dentry_ops
;
d_instantiate
(
direntry
,
newinode
);
direntry
->
d_inode
->
i_nlink
=
2
;
if
(
direntry
->
d_inode
)
direntry
->
d_inode
->
i_nlink
=
2
;
if
(
cifs_sb
->
tcon
->
ses
->
capabilities
&
CAP_UNIX
)
CIFSSMBUnixSetPerms
(
xid
,
pTcon
,
full_path
,
mode
,
(
__u64
)
-
1
,
...
...
@@ -511,13 +540,13 @@ cifs_revalidate(struct dentry *direntry)
direntry
->
d_inode
->
i_count
.
counter
,
direntry
,
direntry
->
d_time
,
jiffies
));
cifsInode
=
CIFS_I
(
direntry
->
d_inode
);
/* BB add check - do not need to revalidate oplocked files */
if
(
time_before
(
jiffies
,
cifsInode
->
time
+
HZ
))
{
if
(
time_before
(
jiffies
,
cifsInode
->
time
+
HZ
)
&&
lookupCacheEnabled
)
{
if
((
S_ISREG
(
direntry
->
d_inode
->
i_mode
)
==
0
)
||
(
direntry
->
d_inode
->
i_nlink
==
1
)
||
(
lookupCacheEnabled
==
0
))
{
(
direntry
->
d_inode
->
i_nlink
==
1
))
{
if
(
full_path
)
kfree
(
full_path
);
FreeXid
(
xid
);
...
...
@@ -531,7 +560,7 @@ cifs_revalidate(struct dentry *direntry)
cifs_get_inode_info_unix
(
&
direntry
->
d_inode
,
full_path
,
direntry
->
d_sb
);
else
cifs_get_inode_info
(
&
direntry
->
d_inode
,
full_path
,
cifs_get_inode_info
(
&
direntry
->
d_inode
,
full_path
,
NULL
,
direntry
->
d_sb
);
/* BB if not oplocked, invalidate inode pages if mtime has changed */
...
...
fs/cifs/link.c
View file @
29fa971b
...
...
@@ -160,7 +160,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
rc
=
cifs_get_inode_info_unix
(
&
newinode
,
full_path
,
inode
->
i_sb
);
else
rc
=
cifs_get_inode_info
(
&
newinode
,
full_path
,
rc
=
cifs_get_inode_info
(
&
newinode
,
full_path
,
NULL
,
inode
->
i_sb
);
if
(
rc
!=
0
)
{
...
...
@@ -221,7 +221,7 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
cifs_sb
->
local_nls
);
else
{
rc
=
CIFSSMBOpen
(
xid
,
pTcon
,
full_path
,
FILE_OPEN
,
GENERIC_READ
,
OPEN_REPARSE_POINT
,
&
fid
,
&
oplock
,
cifs_sb
->
local_nls
);
OPEN_REPARSE_POINT
,
&
fid
,
&
oplock
,
NULL
,
cifs_sb
->
local_nls
);
if
(
!
rc
)
{
rc
=
CIFSSMBQueryReparseLinkInfo
(
xid
,
pTcon
,
full_path
,
tmpbuffer
,
...
...
fs/cifs/misc.c
View file @
29fa971b
...
...
@@ -55,6 +55,8 @@ void
_FreeXid
(
unsigned
int
xid
)
{
write_lock
(
&
GlobalMid_Lock
);
/* if(GlobalTotalActiveXid == 0)
BUG(); */
GlobalTotalActiveXid
--
;
write_unlock
(
&
GlobalMid_Lock
);
}
...
...
@@ -390,12 +392,12 @@ is_valid_oplock_break(struct smb_hdr *buf)
read_unlock
(
&
GlobalSMBSeslock
);
cFYI
(
1
,(
"Matching file id, processing oplock break"
));
pCifsInode
=
CIFS_I
(
netfile
->
p
file
->
f_dentry
->
d_i
node
);
CIFS_I
(
netfile
->
p
I
node
);
pCifsInode
->
clientCanCacheAll
=
FALSE
;
if
(
pSMB
->
OplockLevel
==
0
)
pCifsInode
->
clientCanCacheRead
=
FALSE
;
pCifsInode
->
oplockPending
=
TRUE
;
AllocOplockQEntry
(
netfile
->
p
file
,
tcon
);
AllocOplockQEntry
(
netfile
->
p
Inode
,
netfile
->
netfid
,
tcon
);
cFYI
(
1
,(
"about to wake up oplock thd"
));
wake_up_process
(
oplockThread
);
return
TRUE
;
...
...
fs/cifs/ntlmssp.h
View file @
29fa971b
...
...
@@ -27,26 +27,31 @@
#define NtLmChallenge 2
#define NtLmAuthenticate 3
#define UnknownMessage 8
/* Negotiate Flags */
#define NTLMSSP_NEGOTIATE_UNICODE 0x01 // Text strings are in unicode
#define NTLMSSP_NEGOTIATE_OEM 0x02 // Text strings are in OEM
#define NTLMSSP_REQUEST_TARGET 0x04 // Server return its auth realm
#define NTLMSSP_NEGOTIATE_SIGN 0x0010 // Request signature capability
#define NTLMSSP_NEGOTIATE_SEAL 0x0020 // Request confidentiality
#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 // Use LM session key for sign/seal
#define NTLMSSP_NEGOTIATE_NTLM 0x0200 // NTLM authentication
#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 // client/server on same machine
#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 // Sign for all security levels
#define NTLMSSP_NEGOTIATE_NTLMV2 0x80000
#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
#define NTLMSSP_NEGOTIATE_NTLMV2 0x80000
#define NTLMSSP_REQUEST_INIT_RESP 0x100000
#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000
#define NTLMSSP_REQUEST_NOT_NT_KEY 0x400000
#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000
#define NTLMSSP_NEGOTIATE_128 0x20000000
#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
/* server only negotiate flags */
#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
/* NEGOTIATE_DOMAIN 0x1000 ? */
#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
/* NEGOTIATE_WORKSTATION 0x2000 ? */
#define NTLMSSP_NEGOTIATE_56 0x80000000
/* Although typedefs are not commonly used for structure definitions */
/* in the Linux kernel, in this particular case they are useful */
...
...
@@ -62,7 +67,7 @@ typedef struct _SECURITY_BUFFER {
typedef
struct
_NEGOTIATE_MESSAGE
{
__u8
Signature
[
sizeof
(
NTLMSSP_SIGNATURE
)];
__u32
MessageType
;
__u32
MessageType
;
/* 1 */
__u32
NegotiateFlags
;
SECURITY_BUFFER
DomainName
;
/* RFC 1001 style and ASCII */
SECURITY_BUFFER
WorkstationName
;
/* RFC 1001 and ASCII */
...
...
@@ -72,7 +77,7 @@ typedef struct _NEGOTIATE_MESSAGE {
typedef
struct
_CHALLENGE_MESSAGE
{
__u8
Signature
[
sizeof
(
NTLMSSP_SIGNATURE
)];
__u32
MessageType
;
__u32
MessageType
;
/* 2 */
SECURITY_BUFFER
TargetName
;
__u32
NegotiateFlags
;
__u8
Challenge
[
CIFS_CRYPTO_KEY_SIZE
];
...
...
@@ -82,7 +87,7 @@ typedef struct _CHALLENGE_MESSAGE {
typedef
struct
_AUTHENTICATE_MESSAGE
{
__u8
Signature
[
sizeof
(
NTLMSSP_SIGNATURE
)];
__u32
MessageType
;
__u32
MessageType
;
/* 3 */
SECURITY_BUFFER
LmChallengeResponse
;
SECURITY_BUFFER
NtChallengeResponse
;
SECURITY_BUFFER
DomainName
;
...
...
fs/cifs/transport.c
View file @
29fa971b
...
...
@@ -101,10 +101,10 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
}
struct
oplock_q_entry
*
AllocOplockQEntry
(
struct
file
*
file
,
struct
cifsTconInfo
*
tcon
)
AllocOplockQEntry
(
struct
inode
*
pinode
,
__u16
fid
,
struct
cifsTconInfo
*
tcon
)
{
struct
oplock_q_entry
*
temp
;
if
((
file
==
NULL
)
||
(
tcon
==
NULL
))
{
if
((
pinode
==
NULL
)
||
(
tcon
==
NULL
))
{
cERROR
(
1
,
(
"Null parms passed to AllocOplockQEntry"
));
return
NULL
;
}
...
...
@@ -113,8 +113,9 @@ AllocOplockQEntry(struct file * file, struct cifsTconInfo * tcon)
if
(
temp
==
NULL
)
return
temp
;
else
{
temp
->
file_to_flush
=
fil
e
;
temp
->
pinode
=
pinod
e
;
temp
->
tcon
=
tcon
;
temp
->
netfid
=
fid
;
write_lock
(
&
GlobalMid_Lock
);
list_add_tail
(
&
temp
->
qhead
,
&
GlobalOplock_Q
);
write_unlock
(
&
GlobalMid_Lock
);
...
...
@@ -215,7 +216,8 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
if
(
long_op
>
1
)
/* writes past end of file can take looooong time */
timeout
=
300
*
HZ
;
else
if
(
long_op
==
1
)
timeout
=
60
*
HZ
;
timeout
=
45
*
HZ
;
/* should be greater than
servers oplock break timeout (about 43 seconds) */
else
timeout
=
15
*
HZ
;
/* wait for 15 seconds or until woken up due to response arriving or
...
...
@@ -234,6 +236,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
receive_len
=
be32_to_cpu
(
midQ
->
resp_buf
->
smb_buf_length
);
else
{
cFYI
(
1
,(
"No response buffer"
));
DeleteMidQEntry
(
midQ
);
return
-
EIO
;
}
...
...
@@ -286,8 +289,10 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
4
/* do not count RFC1001 header */
+
(
2
*
out_buf
->
WordCount
)
+
2
/* bcc */
)
BCC
(
out_buf
)
=
le16_to_cpu
(
BCC
(
out_buf
));
}
else
}
else
{
rc
=
-
EIO
;
cFYI
(
1
,(
"Bad MID state? "
));
}
}
cifs_no_response_exit:
DeleteMidQEntry
(
midQ
);
/* BB what if process is killed?
...
...
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