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
nexedi
linux
Commits
a63a10fe
Commit
a63a10fe
authored
Jun 15, 2004
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://cifs.bkbits.net/linux-2.5cifs
into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents
71279d2b
81a50e44
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
370 additions
and
101 deletions
+370
-101
fs/cifs/CHANGES
fs/cifs/CHANGES
+8
-0
fs/cifs/README
fs/cifs/README
+7
-4
fs/cifs/TODO
fs/cifs/TODO
+1
-15
fs/cifs/cifs_debug.c
fs/cifs/cifs_debug.c
+15
-15
fs/cifs/cifsfs.c
fs/cifs/cifsfs.c
+2
-2
fs/cifs/cifsfs.h
fs/cifs/cifsfs.h
+2
-2
fs/cifs/cifspdu.h
fs/cifs/cifspdu.h
+8
-4
fs/cifs/cifsproto.h
fs/cifs/cifsproto.h
+4
-0
fs/cifs/cifssmb.c
fs/cifs/cifssmb.c
+100
-0
fs/cifs/connect.c
fs/cifs/connect.c
+9
-8
fs/cifs/file.c
fs/cifs/file.c
+102
-29
fs/cifs/inode.c
fs/cifs/inode.c
+51
-11
fs/cifs/link.c
fs/cifs/link.c
+1
-1
fs/cifs/transport.c
fs/cifs/transport.c
+20
-1
fs/cifs/xattr.c
fs/cifs/xattr.c
+40
-9
No files found.
fs/cifs/CHANGES
View file @
a63a10fe
Version 1.18
------------
Do not rename hardlinked files (since that should be a noop). Flush
cached write behind data when reopening a file after session abend,
except when already in write. Grab per socket sem during reconnect
to avoid oops in sendmsg if overlapping with reconnect.
Version 1.17
------------
Update number of blocks in file so du command is happier (in Linux a fake
...
...
fs/cifs/README
View file @
a63a10fe
...
...
@@ -97,7 +97,9 @@ Linux:
case sensitive = yes
delete readonly = yes
ea support = yes
Note that ea support is required for supporting Linux xattrs.
Some administrators also change the "map archive" and the "create mask"
parameters from their default values. Creating special devices (mknod) remotely
may require specifying a mkdev function to Samba. For more information on these
...
...
@@ -268,11 +270,12 @@ Misc /proc/fs/cifs Flags and Debug Info
=======================================
Informational pseudo-files:
DebugData Displays information about active CIFS sessions
as well as per share statistics (if CONFIG_CIFS_STATS
is enabled in the kernel configuration).
and shares.
SimultaneousOps Counter which holds maximum number of
simultaneous outstanding SMB/CIFS requests.
Stats Lists summary resource usage information
Stats Lists summary resource usage information as well as per
share statistics, if CONFIG_CIFS_STATS in enabled
in the kernel configuration.
Configuration pseudo-files:
MultiuserMount If set to one, more than one CIFS session to
...
...
fs/cifs/TODO
View file @
a63a10fe
...
...
@@ -80,27 +80,13 @@ symlink text beginning with slash
but recognizes them
3) create of new files to FAT partitions on Windows servers can
succeed but still return access denied (appears to be Windows
not
client problem) and has not been reproduced recently.
server not cifs
client problem) and has not been reproduced recently.
NTFS partitions do not have this problem.
4) debug connectation lock test case 10 which fails against
Samba (may be unmappable due to POSIX to Windows lock model
differences but worth investigating). Also debug Samba to
see why lock test case 7 takes longer to complete to Samba
than to Windows.
5) prepare_write does not initialize pages properly when partial
page writes begin in the middle of a page (pages can get zeroed).
6) Write caching done incorrectly when files are only opened
with write permission by the application.
7) Rename of files that are hardlinked does not work correctly e.g.
ln source target
mv source target
This should be no op since files are linked but in cifs it causes
the source file to go away. This may require implementation of
the cifs POSIX extensions (Unix Extensions version 2) for
it to be done correctly since Samba is failing the rename,
(rather than ignoring it) so the client not knowing they
are linked proceeds to delete the target and then retry the
move which succeeds this time (but the source is gone).
Misc testing to do
==================
...
...
fs/cifs/cifs_debug.c
View file @
a63a10fe
...
...
@@ -190,26 +190,26 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
struct
cifsTconInfo
*
tcon
;
length
=
sprintf
(
buf
,
"
Currently Allocated structures
\n
CIFS Sessions
: %d
\n
"
,
"
Resources in use
\n
CIFS Session
: %d
\n
"
,
sesInfoAllocCount
.
counter
);
buf
+=
length
;
item_length
=
sprintf
(
buf
,
"Share
s
(unique mount targets): %d
\n
"
,
sprintf
(
buf
,
"Share (unique mount targets): %d
\n
"
,
tconInfoAllocCount
.
counter
);
length
+=
item_length
;
buf
+=
item_length
;
item_length
=
sprintf
(
buf
,
"
Allocated SMB Request/Response Buffers
: %d
\n
"
,
sprintf
(
buf
,
"
SMB Request/Response Buffer
: %d
\n
"
,
bufAllocCount
.
counter
);
length
+=
item_length
;
buf
+=
item_length
;
item_length
=
sprintf
(
buf
,
"
Active Operations (MIDs in use
): %d
\n
"
,
sprintf
(
buf
,
"
Operations (MIDs
): %d
\n
"
,
midCount
.
counter
);
length
+=
item_length
;
buf
+=
item_length
;
item_length
=
sprintf
(
buf
,
"
%d sessions and %d shares reconnected after failure
\n
"
,
"
\n
%d session %d share reconnects
\n
"
,
tcpSesReconnectCount
.
counter
,
tconInfoReconnectCount
.
counter
);
length
+=
item_length
;
buf
+=
item_length
;
...
...
@@ -400,7 +400,7 @@ cifsFYI_read(char *page, char **start, off_t off, int count,
return
len
;
}
static
int
cifsFYI_write
(
struct
file
*
file
,
const
char
*
buffer
,
cifsFYI_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
char
c
;
...
...
@@ -439,7 +439,7 @@ oplockEnabled_read(char *page, char **start, off_t off,
return
len
;
}
static
int
oplockEnabled_write
(
struct
file
*
file
,
const
char
*
buffer
,
oplockEnabled_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
char
c
;
...
...
@@ -479,7 +479,7 @@ quotaEnabled_read(char *page, char **start, off_t off,
return
len
;
}
static
int
quotaEnabled_write
(
struct
file
*
file
,
const
char
*
buffer
,
quotaEnabled_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
char
c
;
...
...
@@ -519,7 +519,7 @@ linuxExtensionsEnabled_read(char *page, char **start, off_t off,
return
len
;
}
static
int
linuxExtensionsEnabled_write
(
struct
file
*
file
,
const
char
*
buffer
,
linuxExtensionsEnabled_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
char
c
;
...
...
@@ -559,7 +559,7 @@ lookupFlag_read(char *page, char **start, off_t off,
return
len
;
}
static
int
lookupFlag_write
(
struct
file
*
file
,
const
char
*
buffer
,
lookupFlag_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
char
c
;
...
...
@@ -597,7 +597,7 @@ traceSMB_read(char *page, char **start, off_t off, int count,
return
len
;
}
static
int
traceSMB_write
(
struct
file
*
file
,
const
char
*
buffer
,
traceSMB_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
char
c
;
...
...
@@ -636,7 +636,7 @@ multiuser_mount_read(char *page, char **start, off_t off,
return
len
;
}
static
int
multiuser_mount_write
(
struct
file
*
file
,
const
char
*
buffer
,
multiuser_mount_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
char
c
;
...
...
@@ -675,7 +675,7 @@ extended_security_read(char *page, char **start, off_t off,
return
len
;
}
static
int
extended_security_write
(
struct
file
*
file
,
const
char
*
buffer
,
extended_security_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
char
c
;
...
...
@@ -714,7 +714,7 @@ ntlmv2_enabled_read(char *page, char **start, off_t off,
return
len
;
}
static
int
ntlmv2_enabled_write
(
struct
file
*
file
,
const
char
*
buffer
,
ntlmv2_enabled_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
char
c
;
...
...
@@ -753,7 +753,7 @@ packet_signing_enabled_read(char *page, char **start, off_t off,
return
len
;
}
static
int
packet_signing_enabled_write
(
struct
file
*
file
,
const
char
*
buffer
,
packet_signing_enabled_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
char
c
;
...
...
fs/cifs/cifsfs.c
View file @
a63a10fe
...
...
@@ -426,7 +426,7 @@ cifs_get_sb(struct file_system_type *fs_type,
}
static
ssize_t
cifs_read_wrapper
(
struct
file
*
file
,
char
*
read_data
,
size_t
read_size
,
cifs_read_wrapper
(
struct
file
*
file
,
char
__user
*
read_data
,
size_t
read_size
,
loff_t
*
poffset
)
{
if
(
file
==
NULL
)
...
...
@@ -455,7 +455,7 @@ cifs_read_wrapper(struct file * file, char *read_data, size_t read_size,
}
static
ssize_t
cifs_write_wrapper
(
struct
file
*
file
,
const
char
*
write_data
,
cifs_write_wrapper
(
struct
file
*
file
,
const
char
__user
*
write_data
,
size_t
write_size
,
loff_t
*
poffset
)
{
ssize_t
written
;
...
...
fs/cifs/cifsfs.h
View file @
a63a10fe
...
...
@@ -85,7 +85,7 @@ extern struct dentry_operations cifs_dentry_ops;
/* Functions related to symlinks */
extern
int
cifs_follow_link
(
struct
dentry
*
direntry
,
struct
nameidata
*
nd
);
extern
int
cifs_readlink
(
struct
dentry
*
direntry
,
char
*
buffer
,
int
buflen
);
extern
int
cifs_readlink
(
struct
dentry
*
direntry
,
char
__user
*
buffer
,
int
buflen
);
extern
int
cifs_symlink
(
struct
inode
*
inode
,
struct
dentry
*
direntry
,
const
char
*
symname
);
extern
int
cifs_removexattr
(
struct
dentry
*
,
const
char
*
);
...
...
@@ -93,5 +93,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t
,
int
);
extern
ssize_t
cifs_getxattr
(
struct
dentry
*
,
const
char
*
,
void
*
,
size_t
);
extern
ssize_t
cifs_listxattr
(
struct
dentry
*
,
char
*
,
size_t
);
#define CIFS_VERSION "1.1
7
"
#define CIFS_VERSION "1.1
8
"
#endif
/* _CIFSFS_H */
fs/cifs/cifspdu.h
View file @
a63a10fe
...
...
@@ -1046,9 +1046,12 @@ typedef union smb_com_transaction2 {
/* PathInfo/FileInfo infolevels */
#define SMB_INFO_STANDARD 1
#define SMB_INFO_QUERY_EAS_FROM_LIST 3
#define SMB_INFO_QUERY_ALL_EAS 4
#define SMB_INFO_IS_NAME_VALID 6
#define SMB_QUERY_FILE_BASIC_INFO 0x101
#define SMB_QUERY_FILE_STANDARD_INFO 0x102
#define SMB_QUERY_FILE_EA_INFO 0x103
#define SMB_QUERY_FILE_NAME_INFO 0x104
#define SMB_QUERY_FILE_ALLOCATION_INFO 0x105
#define SMB_QUERY_FILE_END_OF_FILEINFO 0x106
...
...
@@ -1687,16 +1690,17 @@ struct gealist {
};
struct
fea
{
unsigned
char
fEA
;
unsigned
char
cbName
;
unsigned
short
cbValue
;
unsigned
char
EA_flags
;
__u8
name_len
;
__u16
value_len
;
char
szName
[
1
];
/* optionally followed by value */
};
/* flags for _FEA.fEA */
#define FEA_NEEDEA 0x80
/* need EA bit */
struct
fealist
{
unsigned
long
cbList
;
__u32
list_len
;
struct
fea
list
[
1
];
};
...
...
fs/cifs/cifsproto.h
View file @
a63a10fe
...
...
@@ -247,4 +247,8 @@ extern int CIFSSMBCopy(int xid,
extern
int
CIFSSMBNotify
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
int
notify_subdirs
,
const
__u16
netfid
,
__u32
filter
,
const
struct
nls_table
*
nls_codepage
);
extern
int
CIFSSMBQAllEAs
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
unsigned
char
*
searchName
,
char
*
EAData
,
size_t
size
,
const
struct
nls_table
*
nls_codepage
);
#endif
/* _CIFSPROTO_H */
fs/cifs/cifssmb.c
View file @
a63a10fe
...
...
@@ -1596,6 +1596,8 @@ CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
}
else
{
/* decode response */
pSMBr
->
DataOffset
=
le16_to_cpu
(
pSMBr
->
DataOffset
);
/* BB also check enough total bytes returned */
/* BB we need to improve the validity checking
of these trans2 responses */
if
((
pSMBr
->
ByteCount
<
40
)
||
(
pSMBr
->
DataOffset
>
512
))
rc
=
-
EIO
;
/* bad smb */
else
if
(
pFindData
){
...
...
@@ -2879,3 +2881,101 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
goto NotifyRetry; */
return
rc
;
}
#ifdef CONFIG_CIFS_XATTR
int
CIFSSMBQAllEAs
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
unsigned
char
*
searchName
,
char
*
EAData
,
size_t
size
,
const
struct
nls_table
*
nls_codepage
)
{
/* BB assumes one setup word */
TRANSACTION2_QPI_REQ
*
pSMB
=
NULL
;
TRANSACTION2_QPI_RSP
*
pSMBr
=
NULL
;
int
rc
=
0
;
int
bytes_returned
;
int
name_len
;
cFYI
(
1
,
(
"In Query All EAs path %s"
,
searchName
));
QAllEAsRetry:
rc
=
smb_init
(
SMB_COM_TRANSACTION2
,
15
,
tcon
,
(
void
**
)
&
pSMB
,
(
void
**
)
&
pSMBr
);
if
(
rc
)
return
rc
;
if
(
pSMB
->
hdr
.
Flags2
&
SMBFLG2_UNICODE
)
{
name_len
=
cifs_strtoUCS
((
wchar_t
*
)
pSMB
->
FileName
,
searchName
,
530
/* find define for this maxpathcomponent */
,
nls_codepage
);
name_len
++
;
/* trailing null */
name_len
*=
2
;
}
else
{
/* BB improve the check for buffer overruns BB */
name_len
=
strnlen
(
searchName
,
530
);
name_len
++
;
/* trailing null */
strncpy
(
pSMB
->
FileName
,
searchName
,
name_len
);
}
pSMB
->
TotalParameterCount
=
2
/* level */
+
4
/* reserved */
+
name_len
/* includes null */
;
pSMB
->
TotalDataCount
=
0
;
pSMB
->
MaxParameterCount
=
cpu_to_le16
(
2
);
pSMB
->
MaxDataCount
=
cpu_to_le16
(
4000
);
/* BB find exact max SMB PDU from sess structure BB */
pSMB
->
MaxSetupCount
=
0
;
pSMB
->
Reserved
=
0
;
pSMB
->
Flags
=
0
;
pSMB
->
Timeout
=
0
;
pSMB
->
Reserved2
=
0
;
pSMB
->
ParameterOffset
=
cpu_to_le16
(
offsetof
(
struct
smb_com_transaction2_qpi_req
,
InformationLevel
)
-
4
);
pSMB
->
DataCount
=
0
;
pSMB
->
DataOffset
=
0
;
pSMB
->
SetupCount
=
1
;
pSMB
->
Reserved3
=
0
;
pSMB
->
SubCommand
=
cpu_to_le16
(
TRANS2_QUERY_PATH_INFORMATION
);
pSMB
->
ByteCount
=
pSMB
->
TotalParameterCount
+
1
/* pad */
;
pSMB
->
TotalParameterCount
=
cpu_to_le16
(
pSMB
->
TotalParameterCount
);
pSMB
->
ParameterCount
=
pSMB
->
TotalParameterCount
;
pSMB
->
InformationLevel
=
cpu_to_le16
(
SMB_INFO_QUERY_ALL_EAS
);
pSMB
->
Reserved4
=
0
;
pSMB
->
hdr
.
smb_buf_length
+=
pSMB
->
ByteCount
;
pSMB
->
ByteCount
=
cpu_to_le16
(
pSMB
->
ByteCount
);
rc
=
SendReceive
(
xid
,
tcon
->
ses
,
(
struct
smb_hdr
*
)
pSMB
,
(
struct
smb_hdr
*
)
pSMBr
,
&
bytes_returned
,
0
);
if
(
rc
)
{
cFYI
(
1
,
(
"Send error in QueryAllEAs = %d"
,
rc
));
}
else
{
/* decode response */
pSMBr
->
DataOffset
=
le16_to_cpu
(
pSMBr
->
DataOffset
);
/* BB also check enough total bytes returned */
/* BB we need to improve the validity checking
of these trans2 responses */
if
((
pSMBr
->
ByteCount
<
4
)
||
(
pSMBr
->
DataOffset
>
512
))
rc
=
-
EIO
;
/* bad smb */
/* else if (pFindData){
memcpy((char *) pFindData,
(char *) &pSMBr->hdr.Protocol +
pSMBr->DataOffset, kl);
}*/
else
{
/* check that length of list is not more than bcc */
/* check that each entry does not go beyond length
of list */
/* check that each element of each entry does not
go beyond end of list */
struct
fealist
*
ea_response_data
;
rc
=
0
;
/* validate_trans2_offsets() */
/* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
ea_response_data
=
(
struct
fealist
*
)
(((
char
*
)
&
pSMBr
->
hdr
.
Protocol
)
+
pSMBr
->
DataOffset
);
cFYI
(
1
,(
"ea length %d"
,
ea_response_data
->
list_len
));
}
}
if
(
pSMB
)
cifs_buf_release
(
pSMB
);
if
(
rc
==
-
EAGAIN
)
goto
QAllEAsRetry
;
return
rc
;
}
#endif
fs/cifs/connect.c
View file @
a63a10fe
...
...
@@ -128,7 +128,8 @@ cifs_reconnect(struct TCP_Server_Info *server)
}
}
read_unlock
(
&
GlobalSMBSeslock
);
/* do not want to be sending data on a socket we are freeing */
down
(
&
server
->
tcpSem
);
if
(
server
->
ssocket
)
{
cFYI
(
1
,(
"State: 0x%x Flags: 0x%lx"
,
server
->
ssocket
->
state
,
server
->
ssocket
->
flags
));
...
...
@@ -154,7 +155,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
}
}
spin_unlock
(
&
GlobalMid_Lock
);
up
(
&
server
->
tcpSem
);
while
((
server
->
tcpStatus
!=
CifsExiting
)
&&
(
server
->
tcpStatus
!=
CifsGood
))
{
...
...
@@ -279,7 +280,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
length
=
sock_recvmsg
(
csocket
,
&
smb_msg
,
4
,
0
);
cFYI
(
0
,(
"Received 4 byte keep alive packet"
));
}
else
if
(
temp
[
0
]
==
(
char
)
RFC1002_POSITIVE_SESSION_RESPONSE
)
{
iov
.
iov_base
=
smb_buffer
;
iov
.
iov_base
=
smb_buffer
;
iov
.
iov_len
=
4
;
length
=
sock_recvmsg
(
csocket
,
&
smb_msg
,
4
,
0
);
cFYI
(
1
,(
"Good RFC 1002 session rsp"
));
...
...
@@ -1559,7 +1560,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr
+=
pSMBr
->
resp
.
SecurityBlobLength
;
if
(
smb_buffer
->
Flags2
&
=
SMBFLG2_UNICODE
)
{
if
(
smb_buffer
->
Flags2
&
SMBFLG2_UNICODE
)
{
if
((
long
)
(
bcc_ptr
)
%
2
)
{
remaining_words
=
(
BCC
(
smb_buffer_response
)
...
...
@@ -1812,7 +1813,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
pSMBr
->
resp
.
SecurityBlobLength
));
}
if
(
smb_buffer
->
Flags2
&
=
SMBFLG2_UNICODE
)
{
if
(
smb_buffer
->
Flags2
&
SMBFLG2_UNICODE
)
{
if
((
long
)
(
bcc_ptr
)
%
2
)
{
remaining_words
=
(
BCC
(
smb_buffer_response
)
...
...
@@ -2123,7 +2124,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
ses
->
server
->
secMode
|=
SECMODE_SIGN_ENABLED
;
if
(
smb_buffer
->
Flags2
&
=
SMBFLG2_UNICODE
)
{
if
(
smb_buffer
->
Flags2
&
SMBFLG2_UNICODE
)
{
if
((
long
)
(
bcc_ptr
)
%
2
)
{
remaining_words
=
(
BCC
(
smb_buffer_response
)
...
...
@@ -2519,7 +2520,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
cFYI
(
1
,
(
"NTLMSSP response to Authenticate "
));
if
(
smb_buffer
->
Flags2
&
=
SMBFLG2_UNICODE
)
{
if
(
smb_buffer
->
Flags2
&
SMBFLG2_UNICODE
)
{
if
((
long
)
(
bcc_ptr
)
%
2
)
{
remaining_words
=
(
BCC
(
smb_buffer_response
)
...
...
@@ -2718,7 +2719,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
/* skip service field (NB: this field is always ASCII) */
bcc_ptr
+=
length
+
1
;
strncpy
(
tcon
->
treeName
,
tree
,
MAX_TREE_SIZE
);
if
(
smb_buffer
->
Flags2
&
=
SMBFLG2_UNICODE
)
{
if
(
smb_buffer
->
Flags2
&
SMBFLG2_UNICODE
)
{
length
=
UniStrnlen
((
wchar_t
*
)
bcc_ptr
,
512
);
if
(((
long
)
bcc_ptr
+
(
2
*
length
))
-
(
long
)
pByteArea
(
smb_buffer_response
)
<=
...
...
fs/cifs/file.c
View file @
a63a10fe
...
...
@@ -143,6 +143,10 @@ cifs_open(struct inode *inode, struct file *file)
/* 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 */
/* BB we can not do this if this is the second open of a file
and the first handle has writebehind data, we might be
able to simply do a filemap_fdatawrite/filemap_fdatawait first */
buf
=
kmalloc
(
sizeof
(
FILE_ALL_INFO
),
GFP_KERNEL
);
if
(
buf
==
0
)
{
if
(
full_path
)
...
...
@@ -263,7 +267,7 @@ static int cifs_relock_file(struct cifsFileInfo * cifsFile)
return
rc
;
}
static
int
cifs_reopen_file
(
struct
inode
*
inode
,
struct
file
*
file
)
static
int
cifs_reopen_file
(
struct
inode
*
inode
,
struct
file
*
file
,
int
can_flush
)
{
int
rc
=
-
EACCES
;
int
xid
,
oplock
;
...
...
@@ -275,7 +279,6 @@ static int cifs_reopen_file(struct inode *inode, struct file *file)
int
desiredAccess
=
0x20197
;
int
disposition
=
FILE_OPEN
;
__u16
netfid
;
FILE_ALL_INFO
*
buf
=
NULL
;
if
(
inode
==
NULL
)
return
-
EBADF
;
...
...
@@ -328,21 +331,23 @@ and we can never tell if the caller already has the rename_sem */
else
oplock
=
FALSE
;
/* BB pass O_SYNC flag through on file attributes .. BB */
/* Can not refresh inode by passing in file_info buf to be returned
by SMBOpen and then calling get_inode_info with returned buf
since file might have write behind data that needs to be flushed
and server version of file size can be stale. If we
knew for sure that inode was not dirty locally we could do this */
/* 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
);
/* buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
if(buf==0) {
up(&pCifsFile->fh_sem);
if (full_path)
kfree(full_path);
FreeXid(xid);
return -ENOMEM;
}
}
*/
rc
=
CIFSSMBOpen
(
xid
,
pTcon
,
full_path
,
disposition
,
desiredAccess
,
CREATE_NOT_DIR
,
&
netfid
,
&
oplock
,
buf
,
cifs_sb
->
local_nls
);
CREATE_NOT_DIR
,
&
netfid
,
&
oplock
,
NULL
,
cifs_sb
->
local_nls
);
if
(
rc
)
{
up
(
&
pCifsFile
->
fh_sem
);
cFYI
(
1
,
(
"cifs_open returned 0x%x "
,
rc
));
...
...
@@ -353,13 +358,25 @@ and we can never tell if the caller already has the rename_sem */
up
(
&
pCifsFile
->
fh_sem
);
pCifsInode
=
CIFS_I
(
inode
);
if
(
pCifsInode
)
{
if
(
pTcon
->
ses
->
capabilities
&
CAP_UNIX
)
rc
=
cifs_get_inode_info_unix
(
&
inode
,
if
(
can_flush
)
{
filemap_fdatawrite
(
inode
->
i_mapping
);
filemap_fdatawait
(
inode
->
i_mapping
);
/* temporarily disable caching while we
go to server to get inode info */
pCifsInode
->
clientCanCacheAll
=
FALSE
;
pCifsInode
->
clientCanCacheRead
=
FALSE
;
if
(
pTcon
->
ses
->
capabilities
&
CAP_UNIX
)
rc
=
cifs_get_inode_info_unix
(
&
inode
,
full_path
,
inode
->
i_sb
);
else
rc
=
cifs_get_inode_info
(
&
inode
,
full_path
,
buf
,
inode
->
i_sb
);
else
rc
=
cifs_get_inode_info
(
&
inode
,
full_path
,
NULL
,
inode
->
i_sb
);
}
/* else we are writing out data to server already
and could deadlock if we tried to flush data, and
since we do not know if we have data that would
invalidate the current end of file on the server
we can not go to the server to get the new
inod info */
if
((
oplock
&
0xF
)
==
OPLOCK_EXCLUSIVE
)
{
pCifsInode
->
clientCanCacheAll
=
TRUE
;
pCifsInode
->
clientCanCacheRead
=
TRUE
;
...
...
@@ -375,8 +392,6 @@ and we can never tell if the caller already has the rename_sem */
}
}
if
(
buf
)
kfree
(
buf
);
if
(
full_path
)
kfree
(
full_path
);
FreeXid
(
xid
);
...
...
@@ -612,7 +627,11 @@ cifs_write(struct file * file, const char *write_data,
FreeXid
(
xid
);
return
total_written
;
}
rc
=
cifs_reopen_file
(
file
->
f_dentry
->
d_inode
,
file
);
/* we could deadlock if we called
filemap_fdatawait from here so tell
reopen_file not to flush data to server now */
rc
=
cifs_reopen_file
(
file
->
f_dentry
->
d_inode
,
file
,
FALSE
);
if
(
rc
!=
0
)
break
;
}
...
...
@@ -829,7 +848,7 @@ cifs_commit_write(struct file *file, struct page *page, unsigned offset,
cFYI(1,(" SetEOF (commit write) rc = %d",rc));
}*/
}
if
(
!
PageUptodate
(
page
))
{
if
(
!
PageUptodate
(
page
))
{
position
=
((
loff_t
)
page
->
index
<<
PAGE_CACHE_SHIFT
)
+
offset
;
/* can not rely on (or let) writepage write this data */
if
(
to
<
offset
)
{
...
...
@@ -968,7 +987,8 @@ cifs_read(struct file * file, char *read_data, size_t read_size,
rc
=
-
EAGAIN
;
while
(
rc
==
-
EAGAIN
)
{
if
((
open_file
->
invalidHandle
)
&&
(
!
open_file
->
closePend
))
{
rc
=
cifs_reopen_file
(
file
->
f_dentry
->
d_inode
,
file
);
rc
=
cifs_reopen_file
(
file
->
f_dentry
->
d_inode
,
file
,
TRUE
);
if
(
rc
!=
0
)
break
;
}
...
...
@@ -1123,7 +1143,8 @@ cifs_readpages(struct file *file, struct address_space *mapping,
rc
=
-
EAGAIN
;
while
(
rc
==
-
EAGAIN
)
{
if
((
open_file
->
invalidHandle
)
&&
(
!
open_file
->
closePend
))
{
rc
=
cifs_reopen_file
(
file
->
f_dentry
->
d_inode
,
file
);
rc
=
cifs_reopen_file
(
file
->
f_dentry
->
d_inode
,
file
,
TRUE
);
if
(
rc
!=
0
)
break
;
}
...
...
@@ -1263,6 +1284,49 @@ cifs_readpage(struct file *file, struct page *page)
return
rc
;
}
/* We do not want to update the file size from server for inodes
open for write - to avoid races with writepage extending
the file - in the future we could consider allowing
refreshing the inode only on increases in the file size
but this is tricky to do without racing with writebehind
page caching in the current Linux kernel design */
int
is_size_safe_to_change
(
struct
cifsInodeInfo
*
cifsInode
)
{
struct
list_head
*
tmp
;
struct
list_head
*
tmp1
;
struct
cifsFileInfo
*
open_file
=
NULL
;
int
rc
=
TRUE
;
if
(
cifsInode
==
NULL
)
return
rc
;
read_lock
(
&
GlobalSMBSeslock
);
list_for_each_safe
(
tmp
,
tmp1
,
&
cifsInode
->
openFileList
)
{
open_file
=
list_entry
(
tmp
,
struct
cifsFileInfo
,
flist
);
if
(
open_file
==
NULL
)
break
;
if
(
open_file
->
closePend
)
continue
;
/* We check if file is open for writing,
BB we could supplement this with a check to see if file size
changes have been flushed to server - ie inode metadata dirty */
if
((
open_file
->
pfile
)
&&
((
open_file
->
pfile
->
f_flags
&
O_RDWR
)
||
(
open_file
->
pfile
->
f_flags
&
O_WRONLY
)))
{
rc
=
FALSE
;
break
;
}
if
(
tmp
->
next
==
NULL
)
{
cFYI
(
1
,(
"File instance %p removed"
,
tmp
));
break
;
}
}
read_unlock
(
&
GlobalSMBSeslock
);
return
rc
;
}
void
fill_in_inode
(
struct
inode
*
tmp_inode
,
FILE_DIRECTORY_INFO
*
pfindData
,
int
*
pobject_type
)
...
...
@@ -1322,11 +1386,15 @@ fill_in_inode(struct inode *tmp_inode,
atomic_set
(
&
cifsInfo
->
inUse
,
1
);
}
i_size_write
(
tmp_inode
,
pfindData
->
EndOfFile
);
if
(
is_size_safe_to_change
(
cifsInfo
))
{
/* can not safely change the file size here if the
client is writing to it due to potential races */
i_size_write
(
tmp_inode
,
pfindData
->
EndOfFile
);
/* 512 bytes (2**9) is the fake blocksize that must be used */
/* for this calculation, even though the reported blocksize is larger */
tmp_inode
->
i_blocks
=
(
512
-
1
+
pfindData
->
AllocationSize
)
>>
9
;
tmp_inode
->
i_blocks
=
(
512
-
1
+
pfindData
->
AllocationSize
)
>>
9
;
}
if
(
pfindData
->
AllocationSize
<
pfindData
->
EndOfFile
)
cFYI
(
1
,
(
"Possible sparse file: allocation size less than end of file "
));
...
...
@@ -1398,12 +1466,17 @@ unix_fill_in_inode(struct inode *tmp_inode,
tmp_inode
->
i_nlink
=
le64_to_cpu
(
pfindData
->
Nlinks
);
pfindData
->
NumOfBytes
=
le64_to_cpu
(
pfindData
->
NumOfBytes
);
pfindData
->
EndOfFile
=
le64_to_cpu
(
pfindData
->
EndOfFile
);
i_size_write
(
tmp_inode
,
pfindData
->
EndOfFile
);
if
(
is_size_safe_to_change
(
cifsInfo
))
{
/* can not safely change the file size here if the
client is writing to it due to potential races */
pfindData
->
EndOfFile
=
le64_to_cpu
(
pfindData
->
EndOfFile
);
i_size_write
(
tmp_inode
,
pfindData
->
EndOfFile
);
/* 512 bytes (2**9) is the fake blocksize that must be used */
/* for this calculation, not the real blocksize */
tmp_inode
->
i_blocks
=
(
512
-
1
+
pfindData
->
NumOfBytes
)
>>
9
;
tmp_inode
->
i_blocks
=
(
512
-
1
+
pfindData
->
NumOfBytes
)
>>
9
;
}
if
(
S_ISREG
(
tmp_inode
->
i_mode
))
{
cFYI
(
1
,
(
"File inode"
));
...
...
@@ -1547,9 +1620,9 @@ cifs_filldir_unix(struct qstr *pqstring,
pqstring
->
len
=
strnlen
(
pUnixFindData
->
FileName
,
MAX_PATHCONF
);
construct_dentry
(
pqstring
,
file
,
&
tmp_inode
,
&
tmp_dentry
);
if
((
tmp_inode
==
NULL
)
||
(
tmp_dentry
==
NULL
))
{
return
-
ENOMEM
;
}
if
((
tmp_inode
==
NULL
)
||
(
tmp_dentry
==
NULL
))
{
return
-
ENOMEM
;
}
unix_fill_in_inode
(
tmp_inode
,
pUnixFindData
,
&
object_type
);
rc
=
filldir
(
direntry
,
pUnixFindData
->
FileName
,
pqstring
->
len
,
...
...
fs/cifs/inode.c
View file @
a63a10fe
...
...
@@ -30,6 +30,8 @@
#include "cifs_debug.h"
#include "cifs_fs_sb.h"
extern
int
is_size_safe_to_change
(
struct
cifsInodeInfo
*
);
int
cifs_get_inode_info_unix
(
struct
inode
**
pinode
,
const
unsigned
char
*
search_path
,
...
...
@@ -43,9 +45,6 @@ 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
;
...
...
@@ -125,7 +124,12 @@ cifs_get_inode_info_unix(struct inode **pinode,
inode
->
i_nlink
=
le64_to_cpu
(
findData
.
Nlinks
);
findData
.
NumOfBytes
=
le64_to_cpu
(
findData
.
NumOfBytes
);
findData
.
EndOfFile
=
le64_to_cpu
(
findData
.
EndOfFile
);
i_size_write
(
inode
,
findData
.
EndOfFile
);
if
(
is_size_safe_to_change
(
cifsInfo
))
{
/* can not safely change the file size here if the
client is writing to it due to potential races */
i_size_write
(
inode
,
findData
.
EndOfFile
);
/* 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 =
...
...
@@ -141,7 +145,8 @@ cifs_get_inode_info_unix(struct inode **pinode,
/* 512 bytes (2**9) is the fake blocksize that must be used */
/* for this calculation */
inode
->
i_blocks
=
(
512
-
1
+
findData
.
NumOfBytes
)
>>
9
;
inode
->
i_blocks
=
(
512
-
1
+
findData
.
NumOfBytes
)
>>
9
;
}
if
(
findData
.
NumOfBytes
<
findData
.
EndOfFile
)
cFYI
(
1
,
(
"Server inconsistency Error: it says allocation size less than end of file "
));
...
...
@@ -283,12 +288,18 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
inode
->
i_mode
&=
~
(
S_IWUGO
);
/* BB add code here - validate if device or weird share or device type? */
}
i_size_write
(
inode
,
le64_to_cpu
(
pfindData
->
EndOfFile
));
pfindData
->
AllocationSize
=
le64_to_cpu
(
pfindData
->
AllocationSize
);
if
(
is_size_safe_to_change
(
cifsInfo
))
{
/* can not safely change the file size here if the
client is writing to it due to potential races */
i_size_write
(
inode
,
le64_to_cpu
(
pfindData
->
EndOfFile
));
/* 512 bytes (2**9) is the fake blocksize that must be used */
/* for this calculation */
inode
->
i_blocks
=
(
512
-
1
+
pfindData
->
AllocationSize
)
>>
9
;
inode
->
i_blocks
=
(
512
-
1
+
pfindData
->
AllocationSize
)
>>
9
;
}
pfindData
->
AllocationSize
=
le64_to_cpu
(
pfindData
->
AllocationSize
);
inode
->
i_nlink
=
le32_to_cpu
(
pfindData
->
NumberOfLinks
);
...
...
@@ -568,9 +579,38 @@ cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
rc
=
CIFSSMBRename
(
xid
,
pTcon
,
fromName
,
toName
,
cifs_sb_source
->
local_nls
);
if
(
rc
==
-
EEXIST
)
{
cifs_unlink
(
target_inode
,
target_direntry
);
rc
=
CIFSSMBRename
(
xid
,
pTcon
,
fromName
,
toName
,
cifs_sb_source
->
local_nls
);
/* check if they are the same file
because rename of hardlinked files is a noop */
FILE_UNIX_BASIC_INFO
*
info_buf_source
;
FILE_UNIX_BASIC_INFO
*
info_buf_target
;
info_buf_source
=
kmalloc
(
2
*
sizeof
(
FILE_UNIX_BASIC_INFO
),
GFP_KERNEL
);
if
(
info_buf_source
!=
NULL
)
{
info_buf_target
=
info_buf_source
+
1
;
rc
=
CIFSSMBUnixQPathInfo
(
xid
,
pTcon
,
fromName
,
info_buf_source
,
cifs_sb_source
->
local_nls
);
if
(
rc
==
0
)
{
rc
=
CIFSSMBUnixQPathInfo
(
xid
,
pTcon
,
toName
,
info_buf_target
,
cifs_sb_target
->
local_nls
);
}
if
((
rc
==
0
)
&&
(
info_buf_source
->
UniqueId
==
info_buf_target
->
UniqueId
))
{
/* do not rename since the files are hardlinked
which is a noop */
}
else
{
/* we either can not tell the files are hardlinked
(as with Windows servers) or files are not hardlinked
so delete the target manually before renaming to
follow POSIX rather than Windows semantics */
cifs_unlink
(
target_inode
,
target_direntry
);
rc
=
CIFSSMBRename
(
xid
,
pTcon
,
fromName
,
toName
,
cifs_sb_source
->
local_nls
);
}
kfree
(
info_buf_source
);
}
/* if we can not get memory just leave rc as EEXIST */
}
if
((
rc
==
-
EIO
)
||
(
rc
==
-
EEXIST
))
{
...
...
fs/cifs/link.c
View file @
a63a10fe
...
...
@@ -210,7 +210,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
}
int
cifs_readlink
(
struct
dentry
*
direntry
,
char
*
pBuffer
,
int
buflen
)
cifs_readlink
(
struct
dentry
*
direntry
,
char
__user
*
pBuffer
,
int
buflen
)
{
struct
inode
*
inode
=
direntry
->
d_inode
;
int
rc
=
-
EACCES
;
...
...
fs/cifs/transport.c
View file @
a63a10fe
...
...
@@ -120,6 +120,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
unsigned
int
smb_buf_length
,
struct
sockaddr
*
sin
)
{
int
rc
=
0
;
int
i
=
0
;
struct
msghdr
smb_msg
;
struct
iovec
iov
;
mm_segment_t
temp_fs
;
...
...
@@ -151,6 +152,14 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
while
(
iov
.
iov_len
>
0
)
{
rc
=
sock_sendmsg
(
ssocket
,
&
smb_msg
,
smb_buf_length
+
4
);
if
((
rc
==
-
ENOSPC
)
||
(
rc
==
-
EAGAIN
))
{
i
++
;
if
(
i
>
60
)
{
cERROR
(
1
,
(
"sends on sock %p stuck for 30 seconds"
,
ssocket
));
rc
=
-
EAGAIN
;
break
;
}
set_current_state
(
TASK_INTERRUPTIBLE
);
schedule_timeout
(
HZ
/
2
);
continue
;
...
...
@@ -259,7 +268,17 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
midQ
->
midState
=
MID_REQUEST_SUBMITTED
;
rc
=
smb_send
(
ses
->
server
->
ssocket
,
in_buf
,
in_buf
->
smb_buf_length
,
(
struct
sockaddr
*
)
&
(
ses
->
server
->
addr
.
sockAddr
));
up
(
&
ses
->
server
->
tcpSem
);
if
(
rc
<
0
)
{
DeleteMidQEntry
(
midQ
);
up
(
&
ses
->
server
->
tcpSem
);
/* If not lock req, update # of requests on wire to server */
if
(
long_op
<
3
)
{
atomic_dec
(
&
ses
->
server
->
inFlight
);
wake_up
(
&
ses
->
server
->
request_q
);
}
return
rc
;
}
else
up
(
&
ses
->
server
->
tcpSem
);
if
(
long_op
==
-
1
)
goto
cifs_no_response_exit
;
else
if
(
long_op
==
2
)
/* writes past end of file can take looooong time */
...
...
fs/cifs/xattr.c
View file @
a63a10fe
...
...
@@ -20,37 +20,68 @@
*/
#include <linux/fs.h>
#include "cifsfs.h"
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "cifs_debug.h"
int
cifs_removexattr
(
struct
dentry
*
direntry
,
const
char
*
name
)
{
int
rc
=
-
EOPNOTSUPP
;
return
rc
;
int
rc
=
-
EOPNOTSUPP
;
return
rc
;
}
int
cifs_setxattr
(
struct
dentry
*
direntry
,
const
char
*
name
,
const
void
*
value
,
size_t
size
,
int
flags
)
{
int
rc
=
-
EOPNOTSUPP
;
return
rc
;
int
rc
=
-
EOPNOTSUPP
;
return
rc
;
}
ssize_t
cifs_getxattr
(
struct
dentry
*
direntry
,
const
char
*
name
,
void
*
value
,
size_t
size
)
{
ssize_t
rc
=
-
EOPNOTSUPP
;
return
rc
;
ssize_t
rc
=
-
EOPNOTSUPP
;
return
rc
;
}
ssize_t
cifs_listxattr
(
struct
dentry
*
direntry
,
char
*
ea_data
,
size_t
ea_size
)
{
ssize_t
rc
=
-
EOPNOTSUPP
;
ssize_t
rc
=
-
EOPNOTSUPP
;
#ifdef CONFIG_CIFS_XATTR
int
xid
;
struct
cifs_sb_info
*
cifs_sb
;
struct
cifsTconInfo
*
pTcon
;
struct
super_block
*
sb
;
char
*
full_path
;
if
(
direntry
==
NULL
)
return
-
EIO
;
if
(
direntry
->
d_inode
==
NULL
)
return
-
EIO
;
sb
=
direntry
->
d_inode
->
i_sb
;
if
(
sb
==
NULL
)
return
-
EIO
;
xid
=
GetXid
();
cifs_sb
=
CIFS_SB
(
sb
);
pTcon
=
cifs_sb
->
tcon
;
down
(
&
sb
->
s_vfs_rename_sem
);
full_path
=
build_path_from_dentry
(
direntry
);
up
(
&
sb
->
s_vfs_rename_sem
);
if
(
full_path
==
NULL
)
{
FreeXid
(
xid
);
return
-
ENOMEM
;
}
/* return dosattributes as pseudo xattr */
/* return alt name if available as pseudo attr */
/* if proc/fs/cifs/streamstoxattr is set then
search server for EAs or streams to
returns as xattrs */
return
rc
;
rc
=
CIFSSMBQAllEAs
(
xid
,
pTcon
,
full_path
,
ea_data
,
ea_size
,
cifs_sb
->
local_nls
);
FreeXid
(
xid
);
#endif
return
rc
;
}
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