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
754d4c9b
Commit
754d4c9b
authored
Jun 08, 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
b8611623
ce0025eb
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
376 additions
and
112 deletions
+376
-112
fs/cifs/AUTHORS
fs/cifs/AUTHORS
+4
-1
fs/cifs/CHANGES
fs/cifs/CHANGES
+9
-0
fs/cifs/cifs_debug.c
fs/cifs/cifs_debug.c
+63
-33
fs/cifs/cifsfs.h
fs/cifs/cifsfs.h
+1
-1
fs/cifs/cifspdu.h
fs/cifs/cifspdu.h
+37
-17
fs/cifs/cifsproto.h
fs/cifs/cifsproto.h
+3
-0
fs/cifs/cifssmb.c
fs/cifs/cifssmb.c
+54
-3
fs/cifs/connect.c
fs/cifs/connect.c
+43
-11
fs/cifs/dir.c
fs/cifs/dir.c
+16
-5
fs/cifs/fcntl.c
fs/cifs/fcntl.c
+17
-1
fs/cifs/file.c
fs/cifs/file.c
+113
-35
fs/cifs/inode.c
fs/cifs/inode.c
+16
-4
fs/cifs/transport.c
fs/cifs/transport.c
+0
-1
No files found.
fs/cifs/AUTHORS
View file @
754d4c9b
...
...
@@ -23,6 +23,7 @@ Amrut Joshi
Shobhit Dayal
Sergey Vlasov
Richard Hughes
Yury Umanets
Test case and Bug Report contributors
-------------------------------------
...
...
@@ -30,5 +31,7 @@ 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, Alexander Wild, Anthony Liguori,
Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
Kieron Briggs and others.
Olaf Kirch,
Kieron Briggs and others.
And thanks to the IBM LTC and Power test teams and SuSE testers for
finding multiple bugs during excellent stress test runs.
fs/cifs/CHANGES
View file @
754d4c9b
Version 1.17
------------
Update number of blocks in file so du command is happier (in Linux a fake
blocksize of 512 is required for calculating number of blocks in inode).
Fix prepare write of partial pages to read in data from server if possible.
Fix race on tcpStatus field between unmount and reconnection code, causing
cifsd process sometimes to hang around forever. Improve out of memory
checks in cifs_filldir
Version 1.16
------------
Fix incorrect file size in file handle based setattr on big endian hardware.
...
...
fs/cifs/cifs_debug.c
View file @
754d4c9b
...
...
@@ -142,30 +142,10 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
sprintf
(
buf
,
" type: %d "
,
tcon
->
fsDevInfo
.
DeviceType
);
buf
+=
length
;
if
(
tcon
->
tidStatus
==
CifsNeedReconnect
)
if
(
tcon
->
tidStatus
==
CifsNeedReconnect
)
{
buf
+=
sprintf
(
buf
,
"
\t
DISCONNECTED "
);
#ifdef CONFIG_CIFS_STATS
length
=
sprintf
(
buf
,
"
\n
SMBs: %d Oplock Breaks: %d"
,
atomic_read
(
&
tcon
->
num_smbs_sent
),
atomic_read
(
&
tcon
->
num_oplock_brks
));
buf
+=
length
;
length
=
sprintf
(
buf
,
"
\n
Reads: %d Bytes %lld"
,
atomic_read
(
&
tcon
->
num_reads
),
(
long
long
)(
tcon
->
bytes_read
));
buf
+=
length
;
length
=
sprintf
(
buf
,
"
\n
Writes: %d Bytes: %lld"
,
atomic_read
(
&
tcon
->
num_writes
),
(
long
long
)(
tcon
->
bytes_written
));
buf
+=
length
;
length
=
sprintf
(
buf
,
"
\n
Opens: %d Deletes: %d
\n
Mkdirs: %d Rmdirs: %d"
,
atomic_read
(
&
tcon
->
num_opens
),
atomic_read
(
&
tcon
->
num_deletes
),
atomic_read
(
&
tcon
->
num_mkdirs
),
atomic_read
(
&
tcon
->
num_rmdirs
));
buf
+=
length
;
#endif
length
+=
14
;
}
}
read_unlock
(
&
GlobalSMBSeslock
);
...
...
@@ -200,32 +180,80 @@ cifs_total_xid_read(char *buf, char **beginBuffer, off_t offset,
return
length
;
}
#ifdef CONFIG_CIFS_STATS
int
cifs_stats_read
(
char
*
buf
,
char
**
beginBuffer
,
off_t
offset
,
int
length
,
int
*
eof
,
void
*
data
)
{
int
item_length
;
length
=
sprintf
(
buf
,
"Currently Allocated structures
\n
CIFS Sessions: %d
\n
"
,
sesInfoAllocCount
.
counter
);
int
item_length
,
i
;
struct
list_head
*
tmp
;
struct
cifsTconInfo
*
tcon
;
length
=
sprintf
(
buf
,
"Currently Allocated structures
\n
CIFS Sessions: %d
\n
"
,
sesInfoAllocCount
.
counter
);
buf
+=
length
;
item_length
=
sprintf
(
buf
,
"Shares (unique mount targets): %d
\n
"
,
tconInfoAllocCount
.
counter
);
sprintf
(
buf
,
"Shares (unique mount targets): %d
\n
"
,
tconInfoAllocCount
.
counter
);
length
+=
item_length
;
buf
+=
item_length
;
item_length
=
sprintf
(
buf
,
"Allocated SMB Request and Response Buffers: %d
\n
"
,
bufAllocCount
.
counter
);
sprintf
(
buf
,
"Allocated SMB Request/Response Buffers: %d
\n
"
,
bufAllocCount
.
counter
);
length
+=
item_length
;
buf
+=
item_length
;
item_length
=
sprintf
(
buf
,
"Active Operations (MIDs in use): %d
\n
"
,
midCount
.
counter
);
sprintf
(
buf
,
"Active Operations (MIDs in use): %d
\n
"
,
midCount
.
counter
);
length
+=
item_length
;
buf
+=
item_length
;
item_length
=
sprintf
(
buf
,
"%d sessions and %d shares reconnected after failure
\n
"
,
tcpSesReconnectCount
.
counter
,
tconInfoReconnectCount
.
counter
);
item_length
=
sprintf
(
buf
,
"%d sessions and %d shares reconnected after failure
\n
"
,
tcpSesReconnectCount
.
counter
,
tconInfoReconnectCount
.
counter
);
length
+=
item_length
;
buf
+=
item_length
;
i
=
0
;
read_lock
(
&
GlobalSMBSeslock
);
list_for_each
(
tmp
,
&
GlobalTreeConnectionList
)
{
i
++
;
tcon
=
list_entry
(
tmp
,
struct
cifsTconInfo
,
cifsConnectionList
);
item_length
=
sprintf
(
buf
,
"
\n
%d) %s"
,
i
,
tcon
->
treeName
);
buf
+=
item_length
;
length
+=
item_length
;
if
(
tcon
->
tidStatus
==
CifsNeedReconnect
)
{
buf
+=
sprintf
(
buf
,
"
\t
DISCONNECTED "
);
length
+=
14
;
}
item_length
=
sprintf
(
buf
,
"
\n
SMBs: %d Oplock Breaks: %d"
,
atomic_read
(
&
tcon
->
num_smbs_sent
),
atomic_read
(
&
tcon
->
num_oplock_brks
));
buf
+=
item_length
;
length
+=
item_length
;
item_length
=
sprintf
(
buf
,
"
\n
Reads: %d Bytes %lld"
,
atomic_read
(
&
tcon
->
num_reads
),
(
long
long
)(
tcon
->
bytes_read
));
buf
+=
item_length
;
item_length
=
sprintf
(
buf
,
"
\n
Writes: %d Bytes: %lld"
,
atomic_read
(
&
tcon
->
num_writes
),
(
long
long
)(
tcon
->
bytes_written
));
buf
+=
item_length
;
item_length
=
sprintf
(
buf
,
"
\n
Opens: %d Deletes: %d
\n
Mkdirs: %d Rmdirs: %d"
,
atomic_read
(
&
tcon
->
num_opens
),
atomic_read
(
&
tcon
->
num_deletes
),
atomic_read
(
&
tcon
->
num_mkdirs
),
atomic_read
(
&
tcon
->
num_rmdirs
));
buf
+=
item_length
;
length
+=
item_length
;
}
read_unlock
(
&
GlobalSMBSeslock
);
return
length
;
}
#endif
struct
proc_dir_entry
*
proc_fs_cifs
;
read_proc_t
cifs_txanchor_read
;
...
...
@@ -265,10 +293,10 @@ cifs_proc_init(void)
create_proc_read_entry
(
"SimultaneousOps"
,
0
,
proc_fs_cifs
,
cifs_total_xid_read
,
0
);
#ifdef CONFIG_CIFS_STATS
create_proc_read_entry
(
"Stats"
,
0
,
proc_fs_cifs
,
cifs_stats_read
,
0
);
#endif
pde
=
create_proc_read_entry
(
"cifsFYI"
,
0
,
proc_fs_cifs
,
cifsFYI_read
,
0
);
if
(
pde
)
...
...
@@ -336,7 +364,9 @@ cifs_proc_clean(void)
remove_proc_entry
(
"cifsFYI"
,
proc_fs_cifs
);
remove_proc_entry
(
"traceSMB"
,
proc_fs_cifs
);
remove_proc_entry
(
"SimultaneousOps"
,
proc_fs_cifs
);
#ifdef CONFIG_CIFS_STATS
remove_proc_entry
(
"Stats"
,
proc_fs_cifs
);
#endif
remove_proc_entry
(
"MultiuserMount"
,
proc_fs_cifs
);
remove_proc_entry
(
"OplockEnabled"
,
proc_fs_cifs
);
remove_proc_entry
(
"NTLMV2Enabled"
,
proc_fs_cifs
);
...
...
fs/cifs/cifsfs.h
View file @
754d4c9b
...
...
@@ -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
6
"
#define CIFS_VERSION "1.1
7
"
#endif
/* _CIFSFS_H */
fs/cifs/cifspdu.h
View file @
754d4c9b
...
...
@@ -862,6 +862,10 @@ typedef struct smb_com_create_directory_rsp {
__u16
ByteCount
;
/* bct = 0 */
}
CREATE_DIRECTORY_RSP
;
/***************************************************/
/* NT Transact structure defintions follow */
/* Currently only ioctl and notify are implemented */
/***************************************************/
typedef
struct
smb_com_transaction_ioctl_req
{
struct
smb_hdr
hdr
;
/* wct = 23 */
__u8
MaxSetupCount
;
...
...
@@ -921,12 +925,28 @@ typedef struct smb_com_transaction_change_notify_req {
__u32
CompletionFilter
;
/* operation to monitor */
__u16
Fid
;
__u8
WatchTree
;
/* 1 = Monitor subdirectories */
__u8
Reserved2
;
__u16
ByteCount
;
__u8
Pad
[
3
];
__u8
Data
[
1
];
/* __u8 Pad[3];*/
/* __u8 Data[1];*/
}
TRANSACT_CHANGE_NOTIFY_REQ
;
/* Completion Filter flags */
typedef
struct
smb_com_transaction_change_notify_rsp
{
struct
smb_hdr
hdr
;
/* wct = 18 */
__u8
Reserved
[
3
];
__u32
TotalParameterCount
;
__u32
TotalDataCount
;
__u32
ParameterCount
;
__u32
ParameterOffset
;
__u32
ParameterDisplacement
;
__u32
DataCount
;
__u32
DataOffset
;
__u32
DataDisplacement
;
__u8
SetupCount
;
/* 0 */
__u16
ByteCount
;
/* __u8 Pad[3]; */
}
TRANSACT_CHANGE_NOTIFY_RSP
;
/* Completion Filter flags for Notify */
#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
#define FILE_NOTIFY_CHANGE_NAME 0x00000003
...
...
fs/cifs/cifsproto.h
View file @
754d4c9b
...
...
@@ -244,4 +244,7 @@ extern int CIFSSMBCopy(int xid,
const
__u16
target_tid
,
const
char
*
toName
,
const
int
flags
,
const
struct
nls_table
*
nls_codepage
);
extern
int
CIFSSMBNotify
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
int
notify_subdirs
,
const
__u16
netfid
,
__u32
filter
,
const
struct
nls_table
*
nls_codepage
);
#endif
/* _CIFSPROTO_H */
fs/cifs/cifssmb.c
View file @
754d4c9b
...
...
@@ -383,8 +383,11 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
smb_buffer_response
,
&
length
,
0
);
if
(
ses
->
server
)
{
atomic_dec
(
&
ses
->
server
->
socketUseCount
);
if
(
atomic_read
(
&
ses
->
server
->
socketUseCount
)
==
0
)
if
(
atomic_read
(
&
ses
->
server
->
socketUseCount
)
==
0
)
{
spin_lock
(
&
GlobalMid_Lock
);
ses
->
server
->
tcpStatus
=
CifsExiting
;
spin_unlock
(
&
GlobalMid_Lock
);
}
}
if
(
pSMB
)
cifs_buf_release
(
pSMB
);
...
...
@@ -1464,9 +1467,9 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
pSMB
->
TotalParameterCount
=
0
;
pSMB
->
TotalDataCount
=
0
;
pSMB
->
MaxParameterCount
=
cpu_to_le
16
(
2
);
pSMB
->
MaxParameterCount
=
cpu_to_le
32
(
2
);
/* BB find exact data count max from sess structure BB */
pSMB
->
MaxDataCount
=
cpu_to_le
16
(
4000
);
pSMB
->
MaxDataCount
=
cpu_to_le
32
(
4000
);
pSMB
->
MaxSetupCount
=
4
;
pSMB
->
Reserved
=
0
;
pSMB
->
ParameterOffset
=
0
;
...
...
@@ -2828,3 +2831,51 @@ CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
goto
setPermsRetry
;
return
rc
;
}
int
CIFSSMBNotify
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
int
notify_subdirs
,
const
__u16
netfid
,
__u32
filter
,
const
struct
nls_table
*
nls_codepage
)
{
int
rc
=
0
;
struct
smb_com_transaction_change_notify_req
*
pSMB
=
NULL
;
struct
smb_com_transaction_change_notify_rsp
*
pSMBr
=
NULL
;
int
bytes_returned
;
cFYI
(
1
,
(
"In CIFSSMBNotify for file handle %d"
,(
int
)
netfid
));
rc
=
smb_init
(
SMB_COM_NT_TRANSACT
,
23
,
tcon
,
(
void
**
)
&
pSMB
,
(
void
**
)
&
pSMBr
);
if
(
rc
)
return
rc
;
pSMB
->
TotalParameterCount
=
0
;
pSMB
->
TotalDataCount
=
0
;
pSMB
->
MaxParameterCount
=
cpu_to_le32
(
2
);
/* BB find exact data count max from sess structure BB */
pSMB
->
MaxDataCount
=
0
;
/* same in little endian or be */
pSMB
->
MaxSetupCount
=
4
;
pSMB
->
Reserved
=
0
;
pSMB
->
ParameterOffset
=
0
;
pSMB
->
DataCount
=
0
;
pSMB
->
DataOffset
=
0
;
pSMB
->
SetupCount
=
4
;
/* single byte does not need le conversion */
pSMB
->
SubCommand
=
cpu_to_le16
(
NT_TRANSACT_NOTIFY_CHANGE
);
pSMB
->
ParameterCount
=
pSMB
->
TotalParameterCount
;
if
(
notify_subdirs
)
pSMB
->
WatchTree
=
1
;
/* one byte - no le conversion needed */
pSMB
->
Reserved2
=
0
;
pSMB
->
CompletionFilter
=
cpu_to_le32
(
filter
);
pSMB
->
Fid
=
netfid
;
/* file handle always le */
pSMB
->
ByteCount
=
0
;
pSMB
->
hdr
.
smb_buf_length
+=
pSMB
->
ByteCount
;
rc
=
SendReceive
(
xid
,
tcon
->
ses
,
(
struct
smb_hdr
*
)
pSMB
,
(
struct
smb_hdr
*
)
pSMBr
,
&
bytes_returned
,
0
);
if
(
rc
)
{
cFYI
(
1
,
(
"Error in Notify = %d"
,
rc
));
}
if
(
pSMB
)
cifs_buf_release
(
pSMB
);
/* if (rc == -EAGAIN)
goto NotifyRetry; */
return
rc
;
}
fs/cifs/connect.c
View file @
754d4c9b
...
...
@@ -95,9 +95,15 @@ cifs_reconnect(struct TCP_Server_Info *server)
struct
cifsTconInfo
*
tcon
;
struct
mid_q_entry
*
mid_entry
;
if
(
server
->
tcpStatus
==
CifsExiting
)
spin_lock
(
&
GlobalMid_Lock
);
if
(
server
->
tcpStatus
==
CifsExiting
)
{
/* the demux thread will exit normally
next time through the loop */
spin_unlock
(
&
GlobalMid_Lock
);
return
rc
;
}
else
server
->
tcpStatus
=
CifsNeedReconnect
;
spin_unlock
(
&
GlobalMid_Lock
);
server
->
maxBuf
=
0
;
cFYI
(
1
,
(
"Reconnecting tcp session "
));
...
...
@@ -164,7 +170,10 @@ cifs_reconnect(struct TCP_Server_Info *server)
schedule_timeout
(
3
*
HZ
);
}
else
{
atomic_inc
(
&
tcpSesReconnectCount
);
spin_lock
(
&
GlobalMid_Lock
);
if
(
server
->
tcpStatus
!=
CifsExiting
)
server
->
tcpStatus
=
CifsGood
;
spin_unlock
(
&
GlobalMid_Lock
);
atomic_set
(
&
server
->
inFlight
,
0
);
wake_up
(
&
server
->
response_q
);
}
...
...
@@ -243,12 +252,14 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
/* some servers kill tcp session rather than returning
smb negprot error in which case reconnecting here is
not going to help - return error to mount */
spin_lock
(
&
GlobalMid_Lock
);
server
->
tcpStatus
=
CifsExiting
;
spin_unlock
(
&
GlobalMid_Lock
);
wake_up
(
&
server
->
response_q
);
break
;
}
cFYI
(
1
,(
"Reconnecting after unexpected
rcvmsg error "
));
cFYI
(
1
,(
"Reconnecting after unexpected
peek error %d"
,
length
));
cifs_reconnect
(
server
);
csocket
=
server
->
ssocket
;
wake_up
(
&
server
->
response_q
);
...
...
@@ -280,7 +291,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
/* if nack on negprot (rather than
ret of smb negprot error) reconnecting
not going to help, ret error to mount */
spin_lock
(
&
GlobalMid_Lock
);
server
->
tcpStatus
=
CifsExiting
;
spin_unlock
(
&
GlobalMid_Lock
);
/* wake up thread doing negprot */
wake_up
(
&
server
->
response_q
);
break
;
...
...
@@ -391,7 +404,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
}
}
}
spin_lock
(
&
GlobalMid_Lock
);
server
->
tcpStatus
=
CifsExiting
;
spin_unlock
(
&
GlobalMid_Lock
);
atomic_set
(
&
server
->
inFlight
,
0
);
/* Although there should not be any requests blocked on
this queue it can not hurt to be paranoid and try to wake up requests
...
...
@@ -595,6 +610,8 @@ cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol
}
if
((
temp_len
=
strnlen
(
value
,
300
))
<
300
)
{
vol
->
UNC
=
kmalloc
(
temp_len
+
1
,
GFP_KERNEL
);
if
(
vol
->
UNC
==
NULL
)
return
1
;
strcpy
(
vol
->
UNC
,
value
);
if
(
strncmp
(
vol
->
UNC
,
"//"
,
2
)
==
0
)
{
vol
->
UNC
[
0
]
=
'\\'
;
...
...
@@ -742,6 +759,8 @@ cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol
}
if
((
temp_len
=
strnlen
(
devname
,
300
))
<
300
)
{
vol
->
UNC
=
kmalloc
(
temp_len
+
1
,
GFP_KERNEL
);
if
(
vol
->
UNC
==
NULL
)
return
1
;
strcpy
(
vol
->
UNC
,
devname
);
if
(
strncmp
(
vol
->
UNC
,
"//"
,
2
)
==
0
)
{
vol
->
UNC
[
0
]
=
'\\'
;
...
...
@@ -1226,6 +1245,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
init_waitqueue_head
(
&
srvTcp
->
response_q
);
init_waitqueue_head
(
&
srvTcp
->
request_q
);
INIT_LIST_HEAD
(
&
srvTcp
->
pending_mid_q
);
/* at this point we are the only ones with the pointer
to the struct since the kernel thread not created yet
so no need to spinlock this init of tcpStatus */
srvTcp
->
tcpStatus
=
CifsNew
;
init_MUTEX
(
&
srvTcp
->
tcpSem
);
kernel_thread
((
void
*
)(
void
*
)
cifs_demultiplex_thread
,
srvTcp
,
...
...
@@ -1342,8 +1364,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
/* on error free sesinfo and tcon struct if needed */
if
(
rc
)
{
if
(
atomic_read
(
&
srvTcp
->
socketUseCount
)
==
0
)
if
(
atomic_read
(
&
srvTcp
->
socketUseCount
)
==
0
)
{
spin_lock
(
&
GlobalMid_Lock
);
srvTcp
->
tcpStatus
=
CifsExiting
;
spin_unlock
(
&
GlobalMid_Lock
);
}
/* If find_unc succeeded then rc == 0 so we can not end */
if
(
tcon
)
/* up here accidently freeing someone elses tcon struct */
tconInfoFree
(
tcon
);
...
...
@@ -2799,8 +2824,15 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
if
(
rc
==
-
EAGAIN
)
rc
=
-
EHOSTDOWN
;
}
if
(
rc
==
0
)
if
(
rc
==
0
)
{
spin_lock
(
&
GlobalMid_Lock
);
if
(
pSesInfo
->
server
->
tcpStatus
!=
CifsExiting
)
pSesInfo
->
server
->
tcpStatus
=
CifsGood
;
else
rc
=
-
EHOSTDOWN
;
spin_unlock
(
&
GlobalMid_Lock
);
}
}
if
(
!
rc
)
{
pSesInfo
->
capabilities
=
pSesInfo
->
server
->
capabilities
;
...
...
fs/cifs/dir.c
View file @
754d4c9b
...
...
@@ -159,6 +159,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
struct
cifsFileInfo
*
pCifsFile
=
NULL
;
struct
cifsInodeInfo
*
pCifsInode
;
int
disposition
=
FILE_OVERWRITE_IF
;
int
write_only
=
FALSE
;
xid
=
GetXid
();
...
...
@@ -176,9 +177,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
if
(
nd
)
{
if
((
nd
->
intent
.
open
.
flags
&
O_ACCMODE
)
==
O_RDONLY
)
desiredAccess
=
GENERIC_READ
;
else
if
((
nd
->
intent
.
open
.
flags
&
O_ACCMODE
)
==
O_WRONLY
)
else
if
((
nd
->
intent
.
open
.
flags
&
O_ACCMODE
)
==
O_WRONLY
)
{
desiredAccess
=
GENERIC_WRITE
;
else
if
((
nd
->
intent
.
open
.
flags
&
O_ACCMODE
)
==
O_RDWR
)
{
write_only
=
TRUE
;
}
else
if
((
nd
->
intent
.
open
.
flags
&
O_ACCMODE
)
==
O_RDWR
)
{
/* GENERIC_ALL is too much permission to request */
/* can cause unnecessary access denied on create */
/* desiredAccess = GENERIC_ALL; */
...
...
@@ -262,16 +264,25 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
pCifsFile
->
invalidHandle
=
FALSE
;
pCifsFile
->
closePend
=
FALSE
;
init_MUTEX
(
&
pCifsFile
->
fh_sem
);
/* pCifsFile->pfile = file; */
/* put in at open time */
/* put the following in at open now */
/* pCifsFile->pfile = file; */
write_lock
(
&
GlobalSMBSeslock
);
list_add
(
&
pCifsFile
->
tlist
,
&
pTcon
->
openFileList
);
pCifsInode
=
CIFS_I
(
newinode
);
if
(
pCifsInode
)
{
list_add
(
&
pCifsFile
->
flist
,
&
pCifsInode
->
openFileList
);
/* if readable file instance put first in list*/
if
(
write_only
==
TRUE
)
{
list_add_tail
(
&
pCifsFile
->
flist
,
&
pCifsInode
->
openFileList
);
}
else
{
list_add
(
&
pCifsFile
->
flist
,
&
pCifsInode
->
openFileList
);
}
if
((
oplock
&
0xF
)
==
OPLOCK_EXCLUSIVE
)
{
pCifsInode
->
clientCanCacheAll
=
TRUE
;
pCifsInode
->
clientCanCacheRead
=
TRUE
;
cFYI
(
1
,(
"Exclusive Oplock granted on inode %p"
,
newinode
));
cFYI
(
1
,(
"Exclusive Oplock granted on inode %p"
,
newinode
));
}
else
if
((
oplock
&
0xF
)
==
OPLOCK_READ
)
pCifsInode
->
clientCanCacheRead
=
TRUE
;
}
...
...
fs/cifs/fcntl.c
View file @
754d4c9b
...
...
@@ -32,9 +32,12 @@ int cifs_directory_notify(unsigned long arg, struct file * file)
{
int
xid
;
int
rc
=
-
EINVAL
;
int
oplock
=
FALSE
;
struct
cifs_sb_info
*
cifs_sb
;
struct
cifsTconInfo
*
pTcon
;
char
*
full_path
=
NULL
;
__u32
filter
=
FILE_NOTIFY_CHANGE_NAME
|
FILE_NOTIFY_CHANGE_ATTRIBUTES
;
__u16
netfid
;
xid
=
GetXid
();
cifs_sb
=
CIFS_SB
(
file
->
f_dentry
->
d_sb
);
...
...
@@ -48,7 +51,20 @@ int cifs_directory_notify(unsigned long arg, struct file * file)
rc
=
-
ENOMEM
;
}
else
{
cFYI
(
1
,(
"cifs dir notify on file %s"
,
full_path
));
/* CIFSSMBNotify(xid, pTcon, full_path, cifs_sb->local_nls);*/
rc
=
CIFSSMBOpen
(
xid
,
pTcon
,
full_path
,
FILE_OPEN
,
GENERIC_READ
|
SYNCHRONIZE
,
0
/* create options */
,
&
netfid
,
&
oplock
,
NULL
,
cifs_sb
->
local_nls
);
/* BB fixme - add this handle to a notify handle list */
if
(
rc
)
{
cFYI
(
1
,(
"Could not open directory for notify"
));
}
else
{
rc
=
CIFSSMBNotify
(
xid
,
pTcon
,
1
/* subdirs */
,
netfid
,
filter
,
cifs_sb
->
local_nls
);
/* BB add code to close file eventually (at unmount
it would close automatically but may be a way
to do it easily when inode freed or when
notify info is cleared/changed */
}
}
FreeXid
(
xid
);
...
...
fs/cifs/file.c
View file @
754d4c9b
...
...
@@ -173,7 +173,14 @@ cifs_open(struct inode *inode, struct file *file)
list_add
(
&
pCifsFile
->
tlist
,
&
pTcon
->
openFileList
);
pCifsInode
=
CIFS_I
(
file
->
f_dentry
->
d_inode
);
if
(
pCifsInode
)
{
/* want handles we can use to read with first */
/* in the list so we do not have to walk the */
/* list to search for one in prepare_write */
if
((
file
->
f_flags
&
O_ACCMODE
)
==
O_WRONLY
)
{
list_add_tail
(
&
pCifsFile
->
flist
,
&
pCifsInode
->
openFileList
);
}
else
{
list_add
(
&
pCifsFile
->
flist
,
&
pCifsInode
->
openFileList
);
}
write_unlock
(
&
GlobalSMBSeslock
);
write_unlock
(
&
file
->
f_owner
.
lock
);
if
(
pCifsInode
->
clientCanCacheRead
)
{
...
...
@@ -701,6 +708,7 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
cifsInode
=
CIFS_I
(
mapping
->
host
);
read_lock
(
&
GlobalSMBSeslock
);
/* BB we should start at the end */
list_for_each_safe
(
tmp
,
tmp1
,
&
cifsInode
->
openFileList
)
{
open_file
=
list_entry
(
tmp
,
struct
cifsFileInfo
,
flist
);
if
(
open_file
->
closePend
)
...
...
@@ -770,6 +778,9 @@ cifs_writepage(struct page* page, struct writeback_control *wbc)
xid
=
GetXid
();
/* BB add check for wbc flags */
page_cache_get
(
page
);
if
(
!
PageUptodate
(
page
))
{
cFYI
(
1
,(
"ppw - page not up to date"
));
}
rc
=
cifs_partialpagewrite
(
page
,
0
,
PAGE_CACHE_SIZE
);
SetPageUptodate
(
page
);
/* BB add check for error and Clearuptodate? */
...
...
@@ -787,8 +798,7 @@ cifs_commit_write(struct file *file, struct page *page, unsigned offset,
int
rc
=
0
;
struct
inode
*
inode
=
page
->
mapping
->
host
;
loff_t
position
=
((
loff_t
)
page
->
index
<<
PAGE_CACHE_SHIFT
)
+
to
;
/* struct cifsFileInfo *open_file;
struct cifs_sb_info *cifs_sb; */
char
*
page_data
;
xid
=
GetXid
();
cFYI
(
1
,(
"commit write for page %p up to position %lld for %d"
,
page
,
position
,
to
));
...
...
@@ -819,7 +829,31 @@ cifs_commit_write(struct file *file, struct page *page, unsigned offset,
cFYI(1,(" SetEOF (commit write) rc = %d",rc));
}*/
}
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
)
{
cFYI
(
1
,(
"Illegal offsets, can not copy from %d to %d"
,
offset
,
to
));
FreeXid
(
xid
);
return
rc
;
}
/* this is probably better than directly calling
partialpage_write since in this function
the file handle is known which we might as well
leverage */
/* BB check if anything else missing out of ppw */
/* such as updating last write time */
page_data
=
kmap
(
page
);
rc
=
cifs_write
(
file
,
page_data
+
offset
,
to
-
offset
,
&
position
);
if
(
rc
>
0
)
rc
=
0
;
/* else if rc < 0 should we set writebehind rc? */
kunmap
(
page
);
}
else
{
set_page_dirty
(
page
);
}
FreeXid
(
xid
);
return
rc
;
...
...
@@ -924,6 +958,10 @@ cifs_read(struct file * file, char *read_data, size_t read_size,
}
open_file
=
(
struct
cifsFileInfo
*
)
file
->
private_data
;
if
((
file
->
f_flags
&
O_ACCMODE
)
==
O_WRONLY
)
{
cFYI
(
1
,(
"attempting read on write only file instance"
));
}
for
(
total_read
=
0
,
current_offset
=
read_data
;
read_size
>
total_read
;
total_read
+=
bytes_read
,
current_offset
+=
bytes_read
)
{
current_read_size
=
min_t
(
const
int
,
read_size
-
total_read
,
cifs_sb
->
rsize
);
...
...
@@ -1169,28 +1207,16 @@ cifs_readpages(struct file *file, struct address_space *mapping,
return
rc
;
}
static
int
cifs_readpage
(
struct
file
*
file
,
struct
page
*
page
)
static
int
cifs_readpage_worker
(
struct
file
*
file
,
struct
page
*
page
,
loff_t
*
poffset
)
{
loff_t
offset
=
(
loff_t
)
page
->
index
<<
PAGE_CACHE_SHIFT
;
char
*
read_data
;
int
rc
=
-
EACCES
;
int
xid
;
xid
=
GetXid
();
if
(
file
->
private_data
==
NULL
)
{
FreeXid
(
xid
);
return
-
EBADF
;
}
cFYI
(
0
,(
"readpage %p at offset %d 0x%x
\n
"
,
page
,(
int
)
offset
,(
int
)
offset
));
int
rc
;
page_cache_get
(
page
);
read_data
=
kmap
(
page
);
/* for reads over a certain size could initiate async read ahead */
rc
=
cifs_read
(
file
,
read_data
,
PAGE_CACHE_SIZE
,
&
offset
);
rc
=
cifs_read
(
file
,
read_data
,
PAGE_CACHE_SIZE
,
p
offset
);
if
(
rc
<
0
)
goto
io_error
;
...
...
@@ -1209,9 +1235,30 @@ cifs_readpage(struct file *file, struct page *page)
io_error:
kunmap
(
page
);
page_cache_release
(
page
);
return
rc
;
}
static
int
cifs_readpage
(
struct
file
*
file
,
struct
page
*
page
)
{
loff_t
offset
=
(
loff_t
)
page
->
index
<<
PAGE_CACHE_SHIFT
;
int
rc
=
-
EACCES
;
int
xid
;
xid
=
GetXid
();
if
(
file
->
private_data
==
NULL
)
{
FreeXid
(
xid
);
return
-
EBADF
;
}
cFYI
(
1
,(
"readpage %p at offset %d 0x%x
\n
"
,
page
,(
int
)
offset
,(
int
)
offset
));
rc
=
cifs_readpage_worker
(
file
,
page
,
&
offset
);
unlock_page
(
page
);
page_cache_release
(
page
);
FreeXid
(
xid
);
return
rc
;
}
...
...
@@ -1276,8 +1323,11 @@ fill_in_inode(struct inode *tmp_inode,
}
i_size_write
(
tmp_inode
,
pfindData
->
EndOfFile
);
tmp_inode
->
i_blocks
=
(
tmp_inode
->
i_blksize
-
1
+
pfindData
->
AllocationSize
)
>>
tmp_inode
->
i_blkbits
;
/* 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
;
if
(
pfindData
->
AllocationSize
<
pfindData
->
EndOfFile
)
cFYI
(
1
,
(
"Possible sparse file: allocation size less than end of file "
));
cFYI
(
1
,
...
...
@@ -1350,8 +1400,10 @@ unix_fill_in_inode(struct inode *tmp_inode,
pfindData
->
NumOfBytes
=
le64_to_cpu
(
pfindData
->
NumOfBytes
);
pfindData
->
EndOfFile
=
le64_to_cpu
(
pfindData
->
EndOfFile
);
i_size_write
(
tmp_inode
,
pfindData
->
EndOfFile
);
tmp_inode
->
i_blocks
=
(
tmp_inode
->
i_blksize
-
1
+
pfindData
->
NumOfBytes
)
>>
tmp_inode
->
i_blkbits
;
/* 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
;
if
(
S_ISREG
(
tmp_inode
->
i_mode
))
{
cFYI
(
1
,
(
"File inode"
));
...
...
@@ -1393,12 +1445,15 @@ construct_dentry(struct qstr *qstring, struct file *file,
/* 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
);
if
(
*
ptmp_inode
==
NULL
)
return
;
d_instantiate
(
tmp_dentry
,
*
ptmp_inode
);
}
}
else
{
tmp_dentry
=
d_alloc
(
file
->
f_dentry
,
qstring
);
if
(
tmp_dentry
==
NULL
)
{
cERROR
(
1
,(
"Failed allocating dentry"
));
*
ptmp_inode
=
NULL
;
return
;
}
...
...
@@ -1406,6 +1461,8 @@ construct_dentry(struct qstr *qstring, struct file *file,
tmp_dentry
->
d_op
=
&
cifs_dentry_ops
;
cFYI
(
0
,
(
" instantiate dentry 0x%p with inode 0x%p "
,
tmp_dentry
,
*
ptmp_inode
));
if
(
*
ptmp_inode
==
NULL
)
return
;
d_instantiate
(
tmp_dentry
,
*
ptmp_inode
);
d_rehash
(
tmp_dentry
);
}
...
...
@@ -1462,7 +1519,9 @@ cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData,
pqstring
->
len
=
pfindData
->
FileNameLength
;
construct_dentry
(
pqstring
,
file
,
&
tmp_inode
,
&
tmp_dentry
);
if
((
tmp_inode
==
NULL
)
||
(
tmp_dentry
==
NULL
))
{
return
-
ENOMEM
;
}
fill_in_inode
(
tmp_inode
,
pfindData
,
&
object_type
);
rc
=
filldir
(
direntry
,
pfindData
->
FileName
,
pqstring
->
len
,
file
->
f_pos
,
tmp_inode
->
i_ino
,
object_type
);
...
...
@@ -1488,6 +1547,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
;
}
unix_fill_in_inode
(
tmp_inode
,
pUnixFindData
,
&
object_type
);
rc
=
filldir
(
direntry
,
pUnixFindData
->
FileName
,
pqstring
->
len
,
...
...
@@ -1950,17 +2012,34 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
int
cifs_prepare_write
(
struct
file
*
file
,
struct
page
*
page
,
unsigned
from
,
unsigned
to
)
{
int
rc
=
0
;
loff_t
offset
=
(
loff_t
)
page
->
index
<<
PAGE_CACHE_SHIFT
;
cFYI
(
1
,(
"prepare write for page %p from %d to %d"
,
page
,
from
,
to
));
if
(
!
PageUptodate
(
page
))
{
if
(
to
-
from
!=
PAGE_CACHE_SIZE
)
{
/*
if (to - from != PAGE_CACHE_SIZE) {
void *kaddr = kmap_atomic(page, KM_USER0);
memset(kaddr, 0, from);
memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
flush_dcache_page(page);
kunmap_atomic(kaddr, KM_USER0);
}
} */
/* If we are writing a full page it will be up to date,
no need to read from the server */
if
((
to
==
PAGE_CACHE_SIZE
)
&&
(
from
==
0
))
SetPageUptodate
(
page
);
/* might as well read a page, it is fast enough */
if
((
file
->
f_flags
&
O_ACCMODE
)
!=
O_WRONLY
)
{
rc
=
cifs_readpage_worker
(
file
,
page
,
&
offset
);
}
else
{
/* should we try using another
file handle if there is one - how would we lock it
to prevent close of that handle racing with this read? */
/* In any case this will be written out by commit_write */
}
}
/* BB should we pass any errors back? e.g. if we do not have read access to the file */
return
0
;
}
...
...
@@ -1969,8 +2048,7 @@ struct address_space_operations cifs_addr_ops = {
.
readpage
=
cifs_readpage
,
.
readpages
=
cifs_readpages
,
.
writepage
=
cifs_writepage
,
.
prepare_write
=
simple_prepare_write
,
/* BB fixme BB */
/* .prepare_write = cifs_prepare_write, */
/* BB removeme BB */
.
prepare_write
=
cifs_prepare_write
,
.
commit_write
=
cifs_commit_write
,
/* .sync_page = cifs_sync_page, */
/*.direct_IO = */
...
...
fs/cifs/inode.c
View file @
754d4c9b
...
...
@@ -130,8 +130,18 @@ cifs_get_inode_info_unix(struct inode **pinode,
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
;
/* This seems incredibly stupid but it turns out that
i_blocks is not related to (i_size / i_blksize), instead a
size of 512 is required to be used for calculating num blocks */
/* inode->i_blocks =
(inode->i_blksize - 1 + findData.NumOfBytes) >> inode->i_blkbits;*/
/* 512 bytes (2**9) is the fake blocksize that must be used */
/* for this calculation */
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 "
));
...
...
@@ -275,8 +285,10 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
}
i_size_write
(
inode
,
le64_to_cpu
(
pfindData
->
EndOfFile
));
pfindData
->
AllocationSize
=
le64_to_cpu
(
pfindData
->
AllocationSize
);
inode
->
i_blocks
=
(
inode
->
i_blksize
-
1
+
pfindData
->
AllocationSize
)
>>
inode
->
i_blkbits
;
/* 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_nlink
=
le32_to_cpu
(
pfindData
->
NumberOfLinks
);
...
...
fs/cifs/transport.c
View file @
754d4c9b
...
...
@@ -126,7 +126,6 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
if
(
ssocket
==
NULL
)
return
-
ENOTSOCK
;
/* BB eventually add reconnect code here */
/* ssocket->sk->allocation = GFP_BUFFER; *//* BB is this spurious? */
iov
.
iov_base
=
smb_buffer
;
iov
.
iov_len
=
smb_buf_length
+
4
;
...
...
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