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
d7b7a72d
Commit
d7b7a72d
authored
May 19, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
ssh://master.kernel.org//home/hch/BK/xfs/linux-2.5/
into penguin.transmeta.com:/home/torvalds/v2.5/linux
parents
20d7d526
cc6bcfef
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
245 additions
and
55 deletions
+245
-55
fs/cifs/AUTHORS
fs/cifs/AUTHORS
+6
-0
fs/cifs/CHANGES
fs/cifs/CHANGES
+13
-0
fs/cifs/TODO
fs/cifs/TODO
+10
-2
fs/cifs/cifs_debug.c
fs/cifs/cifs_debug.c
+2
-2
fs/cifs/cifs_fs_sb.h
fs/cifs/cifs_fs_sb.h
+2
-2
fs/cifs/cifsfs.c
fs/cifs/cifsfs.c
+17
-10
fs/cifs/cifsglob.h
fs/cifs/cifsglob.h
+4
-3
fs/cifs/cifspdu.h
fs/cifs/cifspdu.h
+1
-0
fs/cifs/cifsproto.h
fs/cifs/cifsproto.h
+4
-2
fs/cifs/cifssmb.c
fs/cifs/cifssmb.c
+76
-3
fs/cifs/connect.c
fs/cifs/connect.c
+28
-8
fs/cifs/file.c
fs/cifs/file.c
+42
-11
fs/cifs/inode.c
fs/cifs/inode.c
+0
-9
fs/cifs/link.c
fs/cifs/link.c
+40
-3
No files found.
fs/cifs/AUTHORS
View file @
d7b7a72d
...
...
@@ -20,3 +20,9 @@ Patch Contributors
Zwane Mwaikambo
Andi Kleen
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.
fs/cifs/CHANGES
View file @
d7b7a72d
Version 0.77
------------
Fix display of NTFS DFS junctions to display as symlinks.
They are the network equivalent. Fix oops in
cifs_partialpagewrite caused by missing spinlock protection
of openfile linked list. Allow writebehind caching errors to
be returned to the application at file close.
Version 0.76
------------
Clean up options displayed in /proc/mounts by show_options to
be more consistent with other filesystems.
Version 0.75
------------
Fix delete of readonly file to Windows servers. Reflect
...
...
fs/cifs/TODO
View file @
d7b7a72d
...
...
@@ -18,6 +18,8 @@ c) multi-user mounts - multiplexed sessionsetups over single vc
d) Kerberos/SPNEGO session setup support - (started)
e) NTLMv2 authentication and MD5-HMAC signing SMB PDUs - (mostly implemented)
signing necessary for some Windows 2003 servers in domain
controller mode.
f) oplock support (ie safe CIFS distributed file caching) is not quite complete.
In addition Directory entry caching relies on a 1 second timer, rather than
...
...
@@ -52,7 +54,8 @@ file opens on top of each other by incrementing reference count rather
than resending (helps reduce server resource utilization and avoid
spurious oplock breaks).
KNOWN BUGS (updated March 7, 2003)
KNOWN BUGS (updated May 16, 2003)
====================================
1) existing symbolic links (Windows reparse points) are recognized but
can not be created remotely. They are implemented for Samba and those that
...
...
@@ -60,6 +63,11 @@ support the CIFS Unix extensions but Samba has a bug currently handling
symlink text beginning with slash
2) delete of file with read-only attribute set will fail (may be ok)
3) mount helper syntax not quite matching man page
4) follow_link and readdir code does not follow dfs junctions
but recognizes them
5) create of new files to FAT partitions on Windows servers can
succeed but still return access denied (appears to be Windows
not client problem). NTFS partitions do not have this problem.
Misc testing to do
=================
...
...
@@ -68,6 +76,6 @@ types.
2) Run dbench
3) Finish
FSX testing on SMP now that we workaround the Samba bug
3) Finish
high stress fsx testing on SMP clients
4) Additional performance testing and optimization
fs/cifs/cifs_debug.c
View file @
d7b7a72d
fs/cifs/cifs_fs_sb.h
View file @
d7b7a72d
fs/cifs/cifsfs.c
View file @
d7b7a72d
...
...
@@ -209,8 +209,8 @@ cifs_destroy_inode(struct inode *inode)
/*
* cifs_show_options() is for displaying mount options in /proc/mounts.
*
It tries to avoid showing settings that were not changed from their
*
defaults
.
*
Not all settable options are displayed but most of the important
*
ones are
.
*/
static
int
cifs_show_options
(
struct
seq_file
*
s
,
struct
vfsmount
*
m
)
...
...
@@ -219,14 +219,18 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
cifs_sb
=
CIFS_SB
(
m
->
mnt_sb
);
if
(
cifs_sb
)
if
(
cifs_sb
)
{
if
(
cifs_sb
->
tcon
)
{
seq_printf
(
s
,
", TARGET: %s "
,
cifs_sb
->
tcon
->
treeName
);
seq_printf
(
s
,
"FS TYPE: %s "
,
cifs_sb
->
tcon
->
nativeFileSystem
);
seq_printf
(
s
,
",unc=%s"
,
cifs_sb
->
tcon
->
treeName
);
if
(
cifs_sb
->
tcon
->
ses
->
userName
)
seq_printf
(
s
,
"
USER: %s
"
,
seq_printf
(
s
,
"
,username=%s
"
,
cifs_sb
->
tcon
->
ses
->
userName
);
if
(
cifs_sb
->
tcon
->
ses
->
domainName
)
seq_printf
(
s
,
",domain=%s"
,
cifs_sb
->
tcon
->
ses
->
domainName
);
}
seq_printf
(
s
,
",rsize=%d"
,
cifs_sb
->
rsize
);
seq_printf
(
s
,
",wsize=%d"
,
cifs_sb
->
wsize
);
}
return
0
;
}
...
...
@@ -423,6 +427,7 @@ cifs_destroy_mids(void)
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
;
...
...
@@ -438,9 +443,8 @@ static int cifs_oplock_thread(void * dummyarg)
/* BB add missing code */
cFYI
(
1
,(
"oplock thread woken up - flush inode"
));
/* BB remove */
write_lock
(
&
GlobalMid_Lock
);
list_for_each
(
tmp
,
&
GlobalOplock_Q
)
{
oplock_item
=
list_entry
(
tmp
,
struct
oplock_q_entry
,
list_for_each_safe
(
tmp
,
tmp1
,
&
GlobalOplock_Q
)
{
oplock_item
=
list_entry
(
tmp
,
struct
oplock_q_entry
,
qhead
);
if
(
oplock_item
)
{
pTcon
=
oplock_item
->
tcon
;
...
...
@@ -449,6 +453,9 @@ static int cifs_oplock_thread(void * dummyarg)
DeleteOplockQEntry
(
oplock_item
);
write_unlock
(
&
GlobalMid_Lock
);
rc
=
filemap_fdatawrite
(
pfile
->
f_dentry
->
d_inode
->
i_mapping
);
if
(
rc
)
CIFS_I
(
pfile
->
f_dentry
->
d_inode
)
->
write_behind_rc
=
rc
;
cFYI
(
1
,(
"Oplock flush file %p rc %d"
,
pfile
,
rc
));
/* send oplock break */
write_lock
(
&
GlobalMid_Lock
);
...
...
fs/cifs/cifsglob.h
View file @
d7b7a72d
...
...
@@ -221,6 +221,7 @@ struct cifsInodeInfo {
struct
list_head
lockList
;
/* BB add in lists for dirty pages - i.e. write caching info for oplock */
struct
list_head
openFileList
;
int
write_behind_rc
;
__u32
cifsAttrs
;
/* e.g. DOS archive bit, sparse, compressed, system */
atomic_t
inUse
;
/* num concurrent users (local openers cifs) of file*/
unsigned
long
time
;
/* jiffies of last update/check of inode */
...
...
fs/cifs/cifspdu.h
View file @
d7b7a72d
...
...
@@ -1263,6 +1263,7 @@ typedef struct dfs_referral_level_3 {
__u16
ServerType
;
/* 0x0001 = CIFS server */
__u16
ReferralFlags
;
/* or proximity - not clear which since always set to zero - SNIA spec says 0x01 means strip off PathConsumed chars before submitting RequestFileName to remote node */
__u16
TimeToLive
;
__u16
Proximity
;
__u16
DfsPathOffset
;
__u16
DfsAlternatePathOffset
;
__u16
NetworkAddressOffset
;
...
...
fs/cifs/cifsproto.h
View file @
d7b7a72d
...
...
@@ -127,13 +127,15 @@ extern int CIFSSMBUnixQPathInfo(const int xid,
extern
int
CIFSGetDFSRefer
(
const
int
xid
,
struct
cifsSesInfo
*
ses
,
const
unsigned
char
*
searchName
,
unsigned
char
**
targetUNCs
,
int
*
number_of_UNC_in_array
,
unsigned
int
*
number_of_UNC_in_array
,
const
struct
nls_table
*
nls_codepage
);
extern
int
connect_to_dfs_path
(
int
xid
,
struct
cifsSesInfo
*
pSesInfo
,
const
char
*
old_path
,
const
struct
nls_table
*
nls_codepage
);
extern
int
get_dfs_path
(
int
xid
,
struct
cifsSesInfo
*
pSesInfo
,
const
char
*
old_path
,
const
struct
nls_table
*
nls_codepage
,
unsigned
int
*
pnum_referrals
,
unsigned
char
**
preferrals
);
extern
int
CIFSSMBQFSInfo
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
struct
statfs
*
FSData
,
const
struct
nls_table
*
nls_codepage
);
...
...
fs/cifs/cifssmb.c
View file @
d7b7a72d
...
...
@@ -1625,15 +1625,18 @@ int
CIFSGetDFSRefer
(
const
int
xid
,
struct
cifsSesInfo
*
ses
,
const
unsigned
char
*
searchName
,
unsigned
char
**
targetUNCs
,
int
*
number_of_UNC_in_array
,
unsigned
int
*
number_of_UNC_in_array
,
const
struct
nls_table
*
nls_codepage
)
{
/* TRANS2_GET_DFS_REFERRAL */
TRANSACTION2_GET_DFS_REFER_REQ
*
pSMB
=
NULL
;
TRANSACTION2_GET_DFS_REFER_RSP
*
pSMBr
=
NULL
;
struct
dfs_referral_level_3
*
referrals
=
NULL
;
int
rc
=
0
;
int
bytes_returned
;
int
name_len
;
unsigned
int
i
;
char
*
temp
;
*
number_of_UNC_in_array
=
0
;
*
targetUNCs
=
NULL
;
...
...
@@ -1701,6 +1704,76 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
cFYI
(
1
,
(
"Send error in GetDFSRefer = %d"
,
rc
));
}
else
{
/* decode response */
/* BB Add logic to parse referrals here */
pSMBr
->
DataOffset
=
le16_to_cpu
(
pSMBr
->
DataOffset
);
pSMBr
->
DataCount
=
le16_to_cpu
(
pSMBr
->
DataCount
);
cFYI
(
1
,
(
"Decoding GetDFSRefer response. BCC: %d Offset %d"
,
pSMBr
->
ByteCount
,
pSMBr
->
DataOffset
));
if
((
pSMBr
->
ByteCount
<
17
)
||
(
pSMBr
->
DataOffset
>
512
))
/* BB also check enough total bytes returned */
rc
=
-
EIO
;
/* bad smb */
else
{
referrals
=
(
struct
dfs_referral_level_3
*
)
(
8
/* sizeof start of data block */
+
pSMBr
->
DataOffset
+
(
char
*
)
&
pSMBr
->
hdr
.
Protocol
);
cFYI
(
1
,(
"num_referrals: %d dfs flags: 0x%x ...
\n
for referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x"
,
pSMBr
->
NumberOfReferrals
,
pSMBr
->
DFSFlags
,
referrals
->
ReferralSize
,
referrals
->
ServerType
,
referrals
->
ReferralFlags
,
referrals
->
TimeToLive
));
/* BB This field is actually two bytes in from start of
data block so we could do safety check that DataBlock
begins at address of pSMBr->NumberOfReferrals */
*
number_of_UNC_in_array
=
le16_to_cpu
(
pSMBr
->
NumberOfReferrals
);
/* BB Fix below so can return more than one referral */
if
(
*
number_of_UNC_in_array
>
1
)
*
number_of_UNC_in_array
=
1
;
/* get the length of the strings describing refs */
name_len
=
0
;
for
(
i
=
0
;
i
<*
number_of_UNC_in_array
;
i
++
)
{
/* make sure that DfsPathOffset not past end */
referrals
->
DfsPathOffset
=
le16_to_cpu
(
referrals
->
DfsPathOffset
);
if
(
referrals
->
DfsPathOffset
>
pSMBr
->
DataCount
)
{
/* if invalid referral, stop here and do
not try to copy any more */
*
number_of_UNC_in_array
=
i
;
break
;
}
temp
=
((
char
*
)
referrals
)
+
referrals
->
DfsPathOffset
;
if
(
pSMBr
->
hdr
.
Flags2
&
SMBFLG2_UNICODE
)
{
name_len
+=
UniStrnlen
((
wchar_t
*
)
temp
,
pSMBr
->
DataCount
);
}
else
{
name_len
+=
strnlen
(
temp
,
pSMBr
->
DataCount
);
}
referrals
++
;
/* BB add check that referral pointer does not fall off end PDU */
}
/* BB add check for name_len bigger than bcc */
*
targetUNCs
=
kmalloc
(
name_len
+
1
+
(
*
number_of_UNC_in_array
),
GFP_KERNEL
);
/* copy the ref strings */
referrals
=
(
struct
dfs_referral_level_3
*
)
(
8
/* sizeof data hdr */
+
pSMBr
->
DataOffset
+
(
char
*
)
&
pSMBr
->
hdr
.
Protocol
);
for
(
i
=
0
;
i
<*
number_of_UNC_in_array
;
i
++
)
{
temp
=
((
char
*
)
referrals
)
+
referrals
->
DfsPathOffset
;
if
(
pSMBr
->
hdr
.
Flags2
&
SMBFLG2_UNICODE
)
{
cifs_strfromUCS_le
(
*
targetUNCs
,
(
wchar_t
*
)
temp
,
name_len
,
nls_codepage
);
}
else
{
strncpy
(
*
targetUNCs
,
temp
,
name_len
);
}
/* BB update target_uncs pointers */
referrals
++
;
}
temp
=
*
targetUNCs
;
temp
[
name_len
]
=
0
;
}
}
if
(
pSMB
)
buf_release
(
pSMB
);
...
...
fs/cifs/connect.c
View file @
d7b7a72d
...
...
@@ -571,11 +571,32 @@ find_unc(__u32 new_target_ip_addr, char *uncName, char *userName)
int
connect_to_dfs_path
(
int
xid
,
struct
cifsSesInfo
*
pSesInfo
,
const
char
*
old_path
,
const
struct
nls_table
*
nls_codepage
)
{
unsigned
char
*
referrals
=
NULL
;
unsigned
int
num_referrals
;
int
rc
=
0
;
rc
=
get_dfs_path
(
xid
,
pSesInfo
,
old_path
,
nls_codepage
,
&
num_referrals
,
&
referrals
);
/* BB Add in code to: if valid refrl, if not ip address contact
the helper that resolves tcp names, mount to it, try to
tcon to it unmount it if fail */
/* BB free memory for referrals string BB */
return
rc
;
}
int
get_dfs_path
(
int
xid
,
struct
cifsSesInfo
*
pSesInfo
,
const
char
*
old_path
,
const
struct
nls_table
*
nls_codepage
,
unsigned
int
*
pnum_referrals
,
unsigned
char
**
preferrals
)
{
char
*
temp_unc
;
int
rc
=
0
;
int
num_referrals
=
0
;
unsigned
char
*
referrals
=
NULL
;
*
pnum_referrals
=
0
;
if
(
pSesInfo
->
ipc_tid
==
0
)
{
temp_unc
=
kmalloc
(
2
/* for slashes */
+
...
...
@@ -594,11 +615,10 @@ connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
kfree
(
temp_unc
);
}
if
(
rc
==
0
)
rc
=
CIFSGetDFSRefer
(
xid
,
pSesInfo
,
old_path
,
&
referrals
,
&
num_referrals
,
nls_codepage
);
return
-
ENODEV
;
/* BB remove and add return code processing */
rc
=
CIFSGetDFSRefer
(
xid
,
pSesInfo
,
old_path
,
preferrals
,
pnum_referrals
,
nls_codepage
);
return
rc
;
}
int
setup_session
(
unsigned
int
xid
,
struct
cifsSesInfo
*
pSesInfo
,
struct
nls_table
*
nls_info
)
...
...
fs/cifs/file.c
View file @
d7b7a72d
...
...
@@ -110,10 +110,14 @@ cifs_open(struct inode *inode, struct file *file)
pCifsFile
->
netfid
=
netfid
;
pCifsFile
->
pid
=
current
->
pid
;
pCifsFile
->
pfile
=
file
;
/* needed for writepage */
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
)
list_add
(
&
pCifsFile
->
flist
,
&
pCifsInode
->
openFileList
);
write_unlock
(
&
GlobalSMBSeslock
);
write_unlock
(
&
file
->
f_owner
.
lock
);
if
(
file
->
f_flags
&
O_CREAT
)
{
/* time to set mode which we can not set earlier due
to problems creating new read-only files */
...
...
@@ -154,9 +158,11 @@ int reopen_files(struct cifsTconInfo * pTcon, struct nls_table * nlsinfo)
struct
cifsFileInfo
*
open_file
=
NULL
;
struct
file
*
file
=
NULL
;
struct
list_head
*
tmp
;
struct
list_head
*
tmp1
;
/* list all files open on tree connection */
list_for_each
(
tmp
,
&
pTcon
->
openFileList
)
{
read_lock
(
&
GlobalSMBSeslock
);
list_for_each_safe
(
tmp
,
tmp1
,
&
pTcon
->
openFileList
)
{
open_file
=
list_entry
(
tmp
,
struct
cifsFileInfo
,
flist
);
if
(
open_file
)
{
if
(
open_file
->
search_resume_name
)
{
...
...
@@ -166,7 +172,9 @@ int reopen_files(struct cifsTconInfo * pTcon, struct nls_table * nlsinfo)
kfree
(
open_file
);
if
(
file
)
{
file
->
private_data
=
NULL
;
read_unlock
(
&
GlobalSMBSeslock
);
rc
=
cifs_open
(
file
->
f_dentry
->
d_inode
,
file
);
read_lock
(
&
GlobalSMBSeslock
);
if
(
rc
)
{
cFYI
(
1
,(
"reconnecting file %s failed with %d"
,
file
->
f_dentry
->
d_name
.
name
,
rc
));
...
...
@@ -177,6 +185,7 @@ int reopen_files(struct cifsTconInfo * pTcon, struct nls_table * nlsinfo)
}
}
}
read_unlock
(
&
GlobalSMBSeslock
);
return
rc
;
}
...
...
@@ -195,9 +204,11 @@ cifs_close(struct inode *inode, struct file *file)
cifs_sb
=
CIFS_SB
(
inode
->
i_sb
);
pTcon
=
cifs_sb
->
tcon
;
if
(
pSMBFile
)
{
write_lock
(
&
file
->
f_owner
.
lock
);
if
(
pSMBFile
->
flist
.
next
)
list_del
(
&
pSMBFile
->
flist
);
list_del
(
&
pSMBFile
->
tlist
);
write_unlock
(
&
file
->
f_owner
.
lock
);
rc
=
CIFSSMBClose
(
xid
,
pTcon
,
pSMBFile
->
netfid
);
if
(
pSMBFile
->
search_resume_name
)
kfree
(
pSMBFile
->
search_resume_name
);
...
...
@@ -206,6 +217,8 @@ cifs_close(struct inode *inode, struct file *file)
}
else
rc
=
-
EBADF
;
if
((
rc
==
0
)
&&
CIFS_I
(
inode
)
->
write_behind_rc
)
rc
=
CIFS_I
(
inode
)
->
write_behind_rc
;
FreeXid
(
xid
);
return
rc
;
}
...
...
@@ -407,6 +420,7 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
struct
cifsInodeInfo
*
cifsInode
;
struct
cifsFileInfo
*
open_file
=
NULL
;
struct
list_head
*
tmp
;
struct
list_head
*
tmp1
;
int
xid
;
xid
=
GetXid
();
...
...
@@ -445,14 +459,17 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
cifsInode
=
CIFS_I
(
mapping
->
host
);
list_for_each
(
tmp
,
&
cifsInode
->
openFileList
)
{
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 */
if
((
open_file
->
pfile
)
&&
((
open_file
->
pfile
->
f_flags
&
O_RDWR
)
||
(
open_file
->
pfile
->
f_flags
&
O_WRONLY
)))
{
read_unlock
(
&
GlobalSMBSeslock
);
bytes_written
=
cifs_write
(
open_file
->
pfile
,
write_data
,
to
-
from
,
&
offset
);
read_lock
(
&
GlobalSMBSeslock
);
/* Does mm or vfs already set times? */
inode
->
i_atime
=
inode
->
i_mtime
=
CURRENT_TIME
;
if
((
bytes_written
>
0
)
&&
(
offset
))
{
...
...
@@ -462,6 +479,7 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
}
}
}
read_unlock
(
&
GlobalSMBSeslock
);
if
(
open_file
==
NULL
)
{
cFYI
(
1
,(
"No writeable filehandles for inode"
));
rc
=
-
EIO
;
...
...
@@ -548,7 +566,8 @@ cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
dentry
->
d_name
.
name
,
datasync
));
rc
=
filemap_fdatawrite
(
inode
->
i_mapping
);
if
(
rc
==
0
)
CIFS_I
(
inode
)
->
write_behind_rc
=
0
;
FreeXid
(
xid
);
return
rc
;
}
...
...
@@ -600,6 +619,9 @@ int cifs_flush(struct file *file)
/* filemapfdatawrite appears easier for the time being */
rc
=
filemap_fdatawrite
(
inode
->
i_mapping
);
if
(
rc
==
0
)
/* reset wb rc if we were able to write out dirty pages */
CIFS_I
(
inode
)
->
write_behind_rc
=
0
;
cFYI
(
1
,(
"Flush inode %p file %p rc %d"
,
inode
,
file
,
rc
));
return
rc
;
...
...
@@ -678,9 +700,13 @@ static void cifs_copy_cache_pages(struct address_space *mapping,
while
(
bytes_read
>
0
)
{
if
(
list_empty
(
pages
))
break
;
spin_lock
(
&
mapping
->
page_lock
);
page
=
list_entry
(
pages
->
prev
,
struct
page
,
list
);
list_del
(
&
page
->
list
);
spin_unlock
(
&
mapping
->
page_lock
);
if
(
add_to_page_cache
(
page
,
mapping
,
page
->
index
,
GFP_KERNEL
))
{
page_cache_release
(
page
);
cFYI
(
1
,(
"Add page cache failed"
));
...
...
@@ -739,12 +765,14 @@ cifs_readpages(struct file *file, struct address_space *mapping,
pagevec_init
(
&
lru_pvec
,
0
);
for
(
i
=
0
;
i
<
num_pages
;)
{
spin_lock
(
&
mapping
->
page_lock
);
if
(
list_empty
(
page_list
))
{
break
;
}
page
=
list_entry
(
page_list
->
prev
,
struct
page
,
list
);
offset
=
(
loff_t
)
page
->
index
<<
PAGE_CACHE_SHIFT
;
spin_unlock
(
&
mapping
->
page_lock
);
/* for reads over a certain size could initiate async read ahead */
cFYI
(
0
,(
"Read %d pages into cache at offset %ld "
,
...
...
@@ -762,12 +790,15 @@ cifs_readpages(struct file *file, struct address_space *mapping,
if
((
rc
<
0
)
||
(
smb_read_data
==
NULL
))
{
cFYI
(
1
,(
"Read error in readpages: %d"
,
rc
));
/* clean up remaing pages off list */
spin_lock
(
&
mapping
->
page_lock
);
while
(
!
list_empty
(
page_list
)
&&
(
i
<
num_pages
))
{
page
=
list_entry
(
page_list
->
prev
,
struct
page
,
list
);
list_del
(
&
page
->
list
);
}
spin_unlock
(
&
mapping
->
page_lock
);
break
;
}
else
if
(
bytes_read
>
0
){
}
else
if
(
bytes_read
>
0
)
{
pSMBr
=
(
struct
smb_com_read_rsp
*
)
smb_read_data
;
cifs_copy_cache_pages
(
mapping
,
page_list
,
bytes_read
,
smb_read_data
+
4
/* RFC1000 hdr */
+
...
...
fs/cifs/inode.c
View file @
d7b7a72d
...
...
@@ -53,10 +53,6 @@ cifs_get_inode_info_unix(struct inode **pinode,
/* dump_mem("\nUnixQPathInfo return data", &findData, sizeof(findData)); */
if
(
rc
)
{
if
(
rc
==
-
EREMOTE
)
{
/* rc = *//* CIFSGetDFSRefer(xid, pTcon->ses, search_path,
&referrals,
&num_referrals,
cifs_sb->local_nls); */
tmp_path
=
kmalloc
(
strnlen
(
pTcon
->
treeName
,
...
...
@@ -180,11 +176,6 @@ cifs_get_inode_info(struct inode **pinode,
/* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
if
(
rc
)
{
if
(
rc
==
-
EREMOTE
)
{
/* BB add call to new func rc = GetDFSReferral(); */
/* rc = *//* CIFSGetDFSRefer(xid, pTcon->ses, search_path,
&referrals,
&num_referrals,
cifs_sb->local_nls); */
tmp_path
=
kmalloc
(
strnlen
(
pTcon
->
treeName
,
...
...
fs/cifs/link.c
View file @
d7b7a72d
...
...
@@ -113,6 +113,9 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
/* BB Should we be using page symlink ops here? */
if
(
rc
==
0
)
{
/* BB Add special case check for Samba DFS symlinks */
target_path
[
PATH_MAX
-
1
]
=
0
;
rc
=
vfs_follow_link
(
nd
,
target_path
);
}
...
...
@@ -186,7 +189,10 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
struct
cifs_sb_info
*
cifs_sb
;
struct
cifsTconInfo
*
pTcon
;
char
*
full_path
=
NULL
;
char
*
tmp_path
=
NULL
;
char
*
tmpbuffer
;
unsigned
char
*
referrals
=
NULL
;
int
num_referrals
=
0
;
int
len
;
__u16
fid
;
...
...
@@ -206,6 +212,7 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
FreeXid
(
xid
);
return
-
ENOMEM
;
}
/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
if
(
cifs_sb
->
tcon
->
ses
->
capabilities
&
CAP_UNIX
)
rc
=
CIFSSMBUnixQuerySymLink
(
xid
,
pTcon
,
full_path
,
...
...
@@ -224,8 +231,36 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
if
(
CIFSSMBClose
(
xid
,
pTcon
,
fid
))
{
cFYI
(
1
,(
"Error closing junction point (open for ioctl)"
));
}
if
(
rc
==
-
EIO
)
{
/* Query if DFS Junction */
tmp_path
=
kmalloc
(
MAX_TREE_SIZE
+
MAX_PATHCONF
+
1
,
GFP_KERNEL
);
if
(
tmp_path
)
{
strncpy
(
tmp_path
,
pTcon
->
treeName
,
MAX_TREE_SIZE
);
strncat
(
tmp_path
,
full_path
,
MAX_PATHCONF
);
rc
=
get_dfs_path
(
xid
,
pTcon
->
ses
,
tmp_path
,
cifs_sb
->
local_nls
,
&
num_referrals
,
&
referrals
);
cFYI
(
1
,(
"Get DFS for %s rc = %d "
,
tmp_path
,
rc
));
if
((
num_referrals
==
0
)
&&
(
rc
==
0
))
rc
=
-
EACCES
;
else
{
cFYI
(
1
,(
"num referral: %d"
,
num_referrals
));
if
(
referrals
)
{
cFYI
(
1
,(
"referral string: %s "
,
referrals
));
strncpy
(
tmpbuffer
,
referrals
,
len
-
1
);
}
}
kfree
(
tmp_path
);
if
(
referrals
)
{
kfree
(
referrals
);
}
}
/* BB add code like else decode referrals then memcpy to
tmpbuffer and free referrals string array BB */
}
}
}
/* BB Anything else to do to handle recursive links? */
/* BB Should we be using page ops here? */
...
...
@@ -238,10 +273,12 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
rc
));
}
if
(
tmpbuffer
)
if
(
tmpbuffer
)
{
kfree
(
tmpbuffer
);
if
(
full_path
)
}
if
(
full_path
)
{
kfree
(
full_path
);
}
FreeXid
(
xid
);
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