forked from Minki/linux
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: [CIFS] Fix typo in cifs readme from previous commit [CIFS] Make sec=none force an anonymous mount [CIFS] Change semaphore to mutex for cifs lock_sem [CIFS] Fix oops in reset_cifs_unix_caps on reconnect [CIFS] UID/GID override on CIFS mounts to Samba [CIFS] prefixpath mounts to servers supporting posix paths used wrong slash [CIFS] Update cifs version to 1.49 [CIFS] Replace kmalloc/memset combination with kzalloc [CIFS] Add IPv6 support [CIFS] New CIFS POSIX mkdir performance improvement (part 2) [CIFS] New CIFS POSIX mkdir performance improvement [CIFS] Add write perm for usr to file on windows should remove r/o dos attr [CIFS] Remove unnecessary parm to cifs_reopen_file [CIFS] Switch cifsd to kthread_run from kernel_thread [CIFS] Remove unnecessary checks
This commit is contained in:
commit
b7405e1643
@ -1,4 +1,16 @@
|
||||
Verison 1.48
|
||||
Version 1.49
|
||||
------------
|
||||
IPv6 support. Enable ipv6 addresses to be passed on mount (put the ipv6
|
||||
address after the "ip=" mount option, at least until mount.cifs is fixed to
|
||||
handle DNS host to ipv6 name translation). Accept override of uid or gid
|
||||
on mount even when Unix Extensions are negotiated (it used to be ignored
|
||||
when Unix Extensions were ignored). This allows users to override the
|
||||
default uid and gid for files when they are certain that the uids or
|
||||
gids on the server do not match those of the client. Make "sec=none"
|
||||
mount override username (so that null user connection is attempted)
|
||||
to match what documentation said.
|
||||
|
||||
Version 1.48
|
||||
------------
|
||||
Fix mtime bouncing around from local idea of last write times to remote time.
|
||||
Fix hang (in i_size_read) when simultaneous size update of same remote file
|
||||
@ -9,7 +21,13 @@ from read-only back to read-write, reflect this change in default file mode
|
||||
(we had been leaving a file's mode read-only until the inode were reloaded).
|
||||
Allow setting of attribute back to ATTR_NORMAL (removing readonly dos attribute
|
||||
when archive dos attribute not set and we are changing mode back to writeable
|
||||
on server which does not support the Unix Extensions).
|
||||
on server which does not support the Unix Extensions). Remove read only dos
|
||||
attribute on chmod when adding any write permission (ie on any of
|
||||
user/group/other (not all of user/group/other ie 0222) when
|
||||
mounted to windows. Add support for POSIX MkDir (slight performance
|
||||
enhancement and eliminates the network race between the mkdir and set
|
||||
path info of the mode).
|
||||
|
||||
|
||||
Version 1.47
|
||||
------------
|
||||
|
@ -257,13 +257,19 @@ A partial list of the supported mount options follows:
|
||||
mount.
|
||||
domain Set the SMB/CIFS workgroup name prepended to the
|
||||
username during CIFS session establishment
|
||||
uid If CIFS Unix extensions are not supported by the server
|
||||
this overrides the default uid for inodes. For mounts to
|
||||
servers which do support the CIFS Unix extensions, such
|
||||
as a properly configured Samba server, the server provides
|
||||
the uid, gid and mode. For servers which do not support
|
||||
the Unix extensions, the default uid (and gid) returned on
|
||||
lookup of existing files is the uid (gid) of the person
|
||||
uid Set the default uid for inodes. For mounts to servers
|
||||
which do support the CIFS Unix extensions, such as a
|
||||
properly configured Samba server, the server provides
|
||||
the uid, gid and mode so this parameter should not be
|
||||
specified unless the server and clients uid and gid
|
||||
numbering differ. If the server and client are in the
|
||||
same domain (e.g. running winbind or nss_ldap) and
|
||||
the server supports the Unix Extensions then the uid
|
||||
and gid can be retrieved from the server (and uid
|
||||
and gid would not have to be specifed on the mount.
|
||||
For servers which do not support the CIFS Unix
|
||||
extensions, the default uid (and gid) returned on lookup
|
||||
of existing files will be the uid (gid) of the person
|
||||
who executed the mount (root, except when mount.cifs
|
||||
is configured setuid for user mounts) unless the "uid="
|
||||
(gid) mount option is specified. For the uid (gid) of newly
|
||||
@ -281,8 +287,7 @@ A partial list of the supported mount options follows:
|
||||
the client. Note that the mount.cifs helper must be
|
||||
at version 1.10 or higher to support specifying the uid
|
||||
(or gid) in non-numberic form.
|
||||
gid If CIFS Unix extensions are not supported by the server
|
||||
this overrides the default gid for inodes.
|
||||
gid Set the default gid for inodes (similar to above).
|
||||
file_mode If CIFS Unix extensions are not supported by the server
|
||||
this overrides the default mode for file inodes.
|
||||
dir_mode If CIFS Unix extensions are not supported by the server
|
||||
@ -467,7 +472,7 @@ including:
|
||||
-V print mount.cifs version
|
||||
-? display simple usage information
|
||||
|
||||
With recent 2.6 kernel versions of modutils, the version of the cifs kernel
|
||||
With most 2.6 kernel versions of modutils, the version of the cifs kernel
|
||||
module can be displayed via modinfo.
|
||||
|
||||
Misc /proc/fs/cifs Flags and Debug Info
|
||||
@ -516,8 +521,22 @@ SecurityFlags Flags which control security negotiation and
|
||||
must use plaintext passwords 0x20020
|
||||
(reserved for future packet encryption) 0x00040
|
||||
|
||||
cifsFYI If set to one, additional debug information is
|
||||
logged to the system error log. (default 0)
|
||||
cifsFYI If set to non-zero value, additional debug information
|
||||
will be logged to the system error log. This field
|
||||
contains three flags controlling different classes of
|
||||
debugging entries. The maximum value it can be set
|
||||
to is 7 which enables all debugging points (default 0).
|
||||
Some debugging statements are not compiled into the
|
||||
cifs kernel unless CONFIG_CIFS_DEBUG2 is enabled in the
|
||||
kernel configuration. cifsFYI may be set to one or
|
||||
nore of the following flags (7 sets them all):
|
||||
|
||||
log cifs informational messages 0x01
|
||||
log return codes from cifs entry points 0x02
|
||||
log slow responses (ie which take longer than 1 second)
|
||||
CONFIG_CIFS_STATS2 must be enabled in .config 0x04
|
||||
|
||||
|
||||
traceSMB If set to one, debug information is logged to the
|
||||
system error log with the start of smb requests
|
||||
and responses (default 0)
|
||||
|
69
fs/cifs/TODO
69
fs/cifs/TODO
@ -1,4 +1,4 @@
|
||||
Version 1.39 November 30, 2005
|
||||
Version 1.49 April 26, 2007
|
||||
|
||||
A Partial List of Missing Features
|
||||
==================================
|
||||
@ -18,7 +18,7 @@ better)
|
||||
|
||||
d) Kerberos/SPNEGO session setup support - (started)
|
||||
|
||||
e) NTLMv2 authentication (mostly implemented - double check
|
||||
e) More testing of NTLMv2 authentication (mostly implemented - double check
|
||||
that NTLMv2 signing works, also need to cleanup now unneeded SessSetup code in
|
||||
fs/cifs/connect.c)
|
||||
|
||||
@ -27,55 +27,44 @@ used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM
|
||||
and raw NTLMSSP already. This is important when enabling
|
||||
extended security and mounting to Windows 2003 Servers
|
||||
|
||||
f) Directory entry caching relies on a 1 second timer, rather than
|
||||
g) Directory entry caching relies on a 1 second timer, rather than
|
||||
using FindNotify or equivalent. - (started)
|
||||
|
||||
g) A few byte range testcases fail due to POSIX vs. Windows/CIFS
|
||||
style byte range lock differences. Save byte range locks so
|
||||
reconnect can replay them.
|
||||
|
||||
h) Support unlock all (unlock 0,MAX_OFFSET)
|
||||
by unlocking all known byte range locks that we locked on the file.
|
||||
|
||||
i) quota support (needs minor kernel change since quota calls
|
||||
h) quota support (needs minor kernel change since quota calls
|
||||
to make it to network filesystems or deviceless filesystems)
|
||||
|
||||
j) investigate sync behavior (including syncpage) and check
|
||||
i) investigate sync behavior (including syncpage) and check
|
||||
for proper behavior of intr/nointr
|
||||
|
||||
k) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
|
||||
j) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
|
||||
extra copy in/out of the socket buffers in some cases.
|
||||
|
||||
l) finish support for IPv6. This is mostly complete but
|
||||
needs a simple conversion of ipv6 to sin6_addr from the
|
||||
address in string representation.
|
||||
|
||||
m) Better optimize open (and pathbased setfilesize) to reduce the
|
||||
k) Better optimize open (and pathbased setfilesize) to reduce the
|
||||
oplock breaks coming from windows srv. Piggyback identical file
|
||||
opens on top of each other by incrementing reference count rather
|
||||
than resending (helps reduce server resource utilization and avoid
|
||||
spurious oplock breaks).
|
||||
|
||||
o) Improve performance of readpages by sending more than one read
|
||||
l) Improve performance of readpages by sending more than one read
|
||||
at a time when 8 pages or more are requested. In conjuntion
|
||||
add support for async_cifs_readpages.
|
||||
|
||||
p) Add support for storing symlink info to Windows servers
|
||||
m) Add support for storing symlink info to Windows servers
|
||||
in the Extended Attribute format their SFU clients would recognize.
|
||||
|
||||
q) Finish fcntl D_NOTIFY support so kde and gnome file list windows
|
||||
n) Finish fcntl D_NOTIFY support so kde and gnome file list windows
|
||||
will autorefresh (partially complete by Asser). Needs minor kernel
|
||||
vfs change to support removing D_NOTIFY on a file.
|
||||
|
||||
r) Add GUI tool to configure /proc/fs/cifs settings and for display of
|
||||
o) Add GUI tool to configure /proc/fs/cifs settings and for display of
|
||||
the CIFS statistics (started)
|
||||
|
||||
s) implement support for security and trusted categories of xattrs
|
||||
p) implement support for security and trusted categories of xattrs
|
||||
(requires minor protocol extension) to enable better support for SELINUX
|
||||
|
||||
t) Implement O_DIRECT flag on open (already supported on mount)
|
||||
q) Implement O_DIRECT flag on open (already supported on mount)
|
||||
|
||||
u) Create UID mapping facility so server UIDs can be mapped on a per
|
||||
r) Create UID mapping facility so server UIDs can be mapped on a per
|
||||
mount or a per server basis to client UIDs or nobody if no mapping
|
||||
exists. This is helpful when Unix extensions are negotiated to
|
||||
allow better permission checking when UIDs differ on the server
|
||||
@ -83,19 +72,26 @@ and client. Add new protocol request to the CIFS protocol
|
||||
standard for asking the server for the corresponding name of a
|
||||
particular uid.
|
||||
|
||||
v) Add support for CIFS Unix and also the newer POSIX extensions to the
|
||||
s) Add support for CIFS Unix and also the newer POSIX extensions to the
|
||||
server side for Samba 4.
|
||||
|
||||
w) Finish up the dos time conversion routines needed to return old server
|
||||
time to the client (default time, of now or time 0 is used now for these
|
||||
very old servers)
|
||||
|
||||
x) In support for OS/2 (LANMAN 1.2 and LANMAN2.1 based SMB servers)
|
||||
t) In support for OS/2 (LANMAN 1.2 and LANMAN2.1 based SMB servers)
|
||||
need to add ability to set time to server (utimes command)
|
||||
|
||||
y) Finish testing of Windows 9x/Windows ME server support (started).
|
||||
u) DOS attrs - returned as pseudo-xattr in Samba format (check VFAT and NTFS for this too)
|
||||
|
||||
KNOWN BUGS (updated February 26, 2007)
|
||||
v) mount check for unmatched uids
|
||||
|
||||
w) Add mount option for Linux extension disable per mount, and partial
|
||||
disable per mount (uid off, symlink/fifo/mknod on but what about posix acls?)
|
||||
|
||||
x) Fix Samba 3 server to handle Linux kernel aio so dbench with lots of
|
||||
processes can proceed better in parallel (on the server)
|
||||
|
||||
y) Fix Samba 3 to handle reads/writes over 127K (and remove the cifs mount
|
||||
restriction of wsize max being 127K)
|
||||
|
||||
KNOWN BUGS (updated April 24, 2007)
|
||||
====================================
|
||||
See http://bugzilla.samba.org - search on product "CifsVFS" for
|
||||
current bug list.
|
||||
@ -127,10 +123,3 @@ negotiated size) and send larger write sizes to modern servers.
|
||||
4) More exhaustively test against less common servers. More testing
|
||||
against Windows 9x, Windows ME servers.
|
||||
|
||||
DOS attrs - returned as pseudo-xattr in Samba format (check VFAT and NTFS for this too)
|
||||
|
||||
mount check for unmatched uids - and uid override
|
||||
|
||||
Add mount option for Linux extension disable per mount, and partial disable per mount (uid off, symlink/fifo/mknod on but what about posix acls?)
|
||||
|
||||
Free threads at umount --force that are stuck on the sesSem
|
||||
|
@ -22,12 +22,14 @@
|
||||
#define CIFS_MOUNT_SET_UID 2 /* set current->euid in create etc. */
|
||||
#define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */
|
||||
#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */
|
||||
#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */
|
||||
#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */
|
||||
#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */
|
||||
#define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */
|
||||
#define CIFS_MOUNT_NO_BRL 0x100 /* No sending byte range locks to srv */
|
||||
#define CIFS_MOUNT_CIFS_ACL 0x200 /* send ACL requests to non-POSIX srv */
|
||||
#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */
|
||||
#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */
|
||||
#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible*/
|
||||
#define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */
|
||||
#define CIFS_MOUNT_NO_BRL 0x100 /* No sending byte range locks to srv */
|
||||
#define CIFS_MOUNT_CIFS_ACL 0x200 /* send ACL requests to non-POSIX srv */
|
||||
#define CIFS_MOUNT_OVERR_UID 0x400 /* override uid returned from server */
|
||||
#define CIFS_MOUNT_OVERR_GID 0x800 /* override gid returned from server */
|
||||
|
||||
struct cifs_sb_info {
|
||||
struct cifsTconInfo *tcon; /* primary mount */
|
||||
|
@ -74,8 +74,8 @@ cifs_strtoUCS(__le16 * to, const char *from, int len,
|
||||
charlen = codepage->char2uni(from, len, &wchar_to[i]);
|
||||
if (charlen < 1) {
|
||||
cERROR(1,
|
||||
("cifs_strtoUCS: char2uni returned %d",
|
||||
charlen));
|
||||
("strtoUCS: char2uni of %d returned %d",
|
||||
(int)*from, charlen));
|
||||
/* A question mark */
|
||||
to[i] = cpu_to_le16(0x003f);
|
||||
charlen = 1;
|
||||
|
@ -100,7 +100,7 @@ cifs_read_super(struct super_block *sb, void *data,
|
||||
sb->s_flags |= MS_NODIRATIME | MS_NOATIME;
|
||||
sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
|
||||
cifs_sb = CIFS_SB(sb);
|
||||
if(cifs_sb == NULL)
|
||||
if (cifs_sb == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = cifs_mount(sb, cifs_sb, data, devname);
|
||||
@ -115,10 +115,10 @@ cifs_read_super(struct super_block *sb, void *data,
|
||||
sb->s_magic = CIFS_MAGIC_NUMBER;
|
||||
sb->s_op = &cifs_super_ops;
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
if(experimEnabled != 0)
|
||||
if (experimEnabled != 0)
|
||||
sb->s_export_op = &cifs_export_ops;
|
||||
#endif /* EXPERIMENTAL */
|
||||
/* if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
|
||||
/* 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; */
|
||||
#ifdef CONFIG_CIFS_QUOTA
|
||||
sb->s_qcop = &cifs_quotactl_ops;
|
||||
@ -147,8 +147,8 @@ out_no_root:
|
||||
iput(inode);
|
||||
|
||||
out_mount_failed:
|
||||
if(cifs_sb) {
|
||||
if(cifs_sb->local_nls)
|
||||
if (cifs_sb) {
|
||||
if (cifs_sb->local_nls)
|
||||
unload_nls(cifs_sb->local_nls);
|
||||
kfree(cifs_sb);
|
||||
}
|
||||
@ -163,7 +163,7 @@ cifs_put_super(struct super_block *sb)
|
||||
|
||||
cFYI(1, ("In cifs_put_super"));
|
||||
cifs_sb = CIFS_SB(sb);
|
||||
if(cifs_sb == NULL) {
|
||||
if (cifs_sb == NULL) {
|
||||
cFYI(1,("Empty cifs superblock info passed to unmount"));
|
||||
return;
|
||||
}
|
||||
@ -208,14 +208,14 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||
|
||||
/* Only need to call the old QFSInfo if failed
|
||||
on newer one */
|
||||
if(rc)
|
||||
if(pTcon->ses->capabilities & CAP_NT_SMBS)
|
||||
if (rc)
|
||||
if (pTcon->ses->capabilities & CAP_NT_SMBS)
|
||||
rc = CIFSSMBQFSInfo(xid, pTcon, buf); /* not supported by OS2 */
|
||||
|
||||
/* Some old Windows servers also do not support level 103, retry with
|
||||
older level one if old server failed the previous call or we
|
||||
bypassed it because we detected that this was an older LANMAN sess */
|
||||
if(rc)
|
||||
if (rc)
|
||||
rc = SMBOldQFSInfo(xid, pTcon, buf);
|
||||
/*
|
||||
int f_type;
|
||||
@ -301,11 +301,19 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
|
||||
if (cifs_sb->tcon->ses->userName)
|
||||
seq_printf(s, ",username=%s",
|
||||
cifs_sb->tcon->ses->userName);
|
||||
if(cifs_sb->tcon->ses->domainName)
|
||||
if (cifs_sb->tcon->ses->domainName)
|
||||
seq_printf(s, ",domain=%s",
|
||||
cifs_sb->tcon->ses->domainName);
|
||||
}
|
||||
}
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
|
||||
seq_printf(s, ",posixpaths");
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
|
||||
!(cifs_sb->tcon->ses->capabilities & CAP_UNIX))
|
||||
seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
|
||||
!(cifs_sb->tcon->ses->capabilities & CAP_UNIX))
|
||||
seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
|
||||
seq_printf(s, ",rsize=%d",cifs_sb->rsize);
|
||||
seq_printf(s, ",wsize=%d",cifs_sb->wsize);
|
||||
}
|
||||
@ -321,14 +329,14 @@ int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct cifsTconInfo *pTcon;
|
||||
|
||||
if(cifs_sb)
|
||||
if (cifs_sb)
|
||||
pTcon = cifs_sb->tcon;
|
||||
else
|
||||
return -EIO;
|
||||
|
||||
|
||||
xid = GetXid();
|
||||
if(pTcon) {
|
||||
if (pTcon) {
|
||||
cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
|
||||
} else {
|
||||
return -EIO;
|
||||
@ -346,13 +354,13 @@ int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct cifsTconInfo *pTcon;
|
||||
|
||||
if(cifs_sb)
|
||||
if (cifs_sb)
|
||||
pTcon = cifs_sb->tcon;
|
||||
else
|
||||
return -EIO;
|
||||
|
||||
xid = GetXid();
|
||||
if(pTcon) {
|
||||
if (pTcon) {
|
||||
cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
|
||||
} else {
|
||||
rc = -EIO;
|
||||
@ -369,13 +377,13 @@ int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct cifsTconInfo *pTcon;
|
||||
|
||||
if(cifs_sb)
|
||||
if (cifs_sb)
|
||||
pTcon = cifs_sb->tcon;
|
||||
else
|
||||
return -EIO;
|
||||
|
||||
xid = GetXid();
|
||||
if(pTcon) {
|
||||
if (pTcon) {
|
||||
cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation));
|
||||
} else {
|
||||
rc = -EIO;
|
||||
@ -392,13 +400,13 @@ int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats)
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct cifsTconInfo *pTcon;
|
||||
|
||||
if(cifs_sb) {
|
||||
if (cifs_sb) {
|
||||
pTcon = cifs_sb->tcon;
|
||||
} else {
|
||||
return -EIO;
|
||||
}
|
||||
xid = GetXid();
|
||||
if(pTcon) {
|
||||
if (pTcon) {
|
||||
cFYI(1,("pqstats %p",qstats));
|
||||
} else {
|
||||
rc = -EIO;
|
||||
@ -424,11 +432,11 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
|
||||
if (!(flags & MNT_FORCE))
|
||||
return;
|
||||
cifs_sb = CIFS_SB(vfsmnt->mnt_sb);
|
||||
if(cifs_sb == NULL)
|
||||
if (cifs_sb == NULL)
|
||||
return;
|
||||
|
||||
tcon = cifs_sb->tcon;
|
||||
if(tcon == NULL)
|
||||
if (tcon == NULL)
|
||||
return;
|
||||
down(&tcon->tconSem);
|
||||
if (atomic_read(&tcon->useCount) == 1)
|
||||
@ -437,7 +445,7 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
|
||||
|
||||
/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
|
||||
/* cancel_notify_requests(tcon); */
|
||||
if(tcon->ses && tcon->ses->server)
|
||||
if (tcon->ses && tcon->ses->server)
|
||||
{
|
||||
cFYI(1,("wake up tasks now - umount begin not complete"));
|
||||
wake_up_all(&tcon->ses->server->request_q);
|
||||
@ -529,8 +537,7 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
|
||||
/* some applications poll for the file length in this strange
|
||||
way so we must seek to end on non-oplocked files by
|
||||
setting the revalidate time to zero */
|
||||
if(file->f_path.dentry->d_inode)
|
||||
CIFS_I(file->f_path.dentry->d_inode)->time = 0;
|
||||
CIFS_I(file->f_path.dentry->d_inode)->time = 0;
|
||||
|
||||
retval = cifs_revalidate(file->f_path.dentry);
|
||||
if (retval < 0)
|
||||
@ -724,7 +731,7 @@ cifs_destroy_inodecache(void)
|
||||
static int
|
||||
cifs_init_request_bufs(void)
|
||||
{
|
||||
if(CIFSMaxBufSize < 8192) {
|
||||
if (CIFSMaxBufSize < 8192) {
|
||||
/* Buffer size can not be smaller than 2 * PATH_MAX since maximum
|
||||
Unicode path name has to fit in any SMB/CIFS path based frames */
|
||||
CIFSMaxBufSize = 8192;
|
||||
@ -741,7 +748,7 @@ cifs_init_request_bufs(void)
|
||||
if (cifs_req_cachep == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
if(cifs_min_rcv < 1)
|
||||
if (cifs_min_rcv < 1)
|
||||
cifs_min_rcv = 1;
|
||||
else if (cifs_min_rcv > 64) {
|
||||
cifs_min_rcv = 64;
|
||||
@ -751,7 +758,7 @@ cifs_init_request_bufs(void)
|
||||
cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv,
|
||||
cifs_req_cachep);
|
||||
|
||||
if(cifs_req_poolp == NULL) {
|
||||
if (cifs_req_poolp == NULL) {
|
||||
kmem_cache_destroy(cifs_req_cachep);
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -772,7 +779,7 @@ cifs_init_request_bufs(void)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if(cifs_min_small < 2)
|
||||
if (cifs_min_small < 2)
|
||||
cifs_min_small = 2;
|
||||
else if (cifs_min_small > 256) {
|
||||
cifs_min_small = 256;
|
||||
@ -782,7 +789,7 @@ cifs_init_request_bufs(void)
|
||||
cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small,
|
||||
cifs_sm_req_cachep);
|
||||
|
||||
if(cifs_sm_req_poolp == NULL) {
|
||||
if (cifs_sm_req_poolp == NULL) {
|
||||
mempool_destroy(cifs_req_poolp);
|
||||
kmem_cache_destroy(cifs_req_cachep);
|
||||
kmem_cache_destroy(cifs_sm_req_cachep);
|
||||
@ -812,7 +819,7 @@ cifs_init_mids(void)
|
||||
|
||||
/* 3 is a reasonable minimum number of simultaneous operations */
|
||||
cifs_mid_poolp = mempool_create_slab_pool(3, cifs_mid_cachep);
|
||||
if(cifs_mid_poolp == NULL) {
|
||||
if (cifs_mid_poolp == NULL) {
|
||||
kmem_cache_destroy(cifs_mid_cachep);
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -850,14 +857,14 @@ static int cifs_oplock_thread(void * dummyarg)
|
||||
continue;
|
||||
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
if(list_empty(&GlobalOplock_Q)) {
|
||||
if (list_empty(&GlobalOplock_Q)) {
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(39*HZ);
|
||||
} else {
|
||||
oplock_item = list_entry(GlobalOplock_Q.next,
|
||||
struct oplock_q_entry, qhead);
|
||||
if(oplock_item) {
|
||||
if (oplock_item) {
|
||||
cFYI(1,("found oplock item to write out"));
|
||||
pTcon = oplock_item->tcon;
|
||||
inode = oplock_item->pinode;
|
||||
@ -871,7 +878,7 @@ static int cifs_oplock_thread(void * dummyarg)
|
||||
/* mutex_lock(&inode->i_mutex);*/
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
rc = filemap_fdatawrite(inode->i_mapping);
|
||||
if(CIFS_I(inode)->clientCanCacheRead == 0) {
|
||||
if (CIFS_I(inode)->clientCanCacheRead == 0) {
|
||||
filemap_fdatawait(inode->i_mapping);
|
||||
invalidate_remote_inode(inode);
|
||||
}
|
||||
@ -888,7 +895,7 @@ static int cifs_oplock_thread(void * dummyarg)
|
||||
not bother sending an oplock release if session
|
||||
to server still is disconnected since oplock
|
||||
already released by the server in that case */
|
||||
if(pTcon->tidStatus != CifsNeedReconnect) {
|
||||
if (pTcon->tidStatus != CifsNeedReconnect) {
|
||||
rc = CIFSSMBLock(0, pTcon, netfid,
|
||||
0 /* len */ , 0 /* offset */, 0,
|
||||
0, LOCKING_ANDX_OPLOCK_RELEASE,
|
||||
@ -922,7 +929,7 @@ static int cifs_dnotify_thread(void * dummyarg)
|
||||
list_for_each(tmp, &GlobalSMBSessionList) {
|
||||
ses = list_entry(tmp, struct cifsSesInfo,
|
||||
cifsSessionList);
|
||||
if(ses && ses->server &&
|
||||
if (ses && ses->server &&
|
||||
atomic_read(&ses->server->inFlight))
|
||||
wake_up_all(&ses->server->response_q);
|
||||
}
|
||||
@ -971,10 +978,10 @@ init_cifs(void)
|
||||
rwlock_init(&GlobalSMBSeslock);
|
||||
spin_lock_init(&GlobalMid_Lock);
|
||||
|
||||
if(cifs_max_pending < 2) {
|
||||
if (cifs_max_pending < 2) {
|
||||
cifs_max_pending = 2;
|
||||
cFYI(1,("cifs_max_pending set to min of 2"));
|
||||
} else if(cifs_max_pending > 256) {
|
||||
} else if (cifs_max_pending > 256) {
|
||||
cifs_max_pending = 256;
|
||||
cFYI(1,("cifs_max_pending set to max of 256"));
|
||||
}
|
||||
|
@ -100,5 +100,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
|
||||
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
|
||||
extern int cifs_ioctl (struct inode * inode, struct file * filep,
|
||||
unsigned int command, unsigned long arg);
|
||||
#define CIFS_VERSION "1.48"
|
||||
#define CIFS_VERSION "1.49"
|
||||
#endif /* _CIFSFS_H */
|
||||
|
@ -311,7 +311,7 @@ struct cifsFileInfo {
|
||||
/* lock scope id (0 if none) */
|
||||
struct file * pfile; /* needed for writepage */
|
||||
struct inode * pInode; /* needed for oplock break */
|
||||
struct semaphore lock_sem;
|
||||
struct mutex lock_mutex;
|
||||
struct list_head llist; /* list of byte range locks we have. */
|
||||
unsigned closePend:1; /* file is marked to close */
|
||||
unsigned invalidHandle:1; /* file closed via session abend */
|
||||
|
@ -1388,7 +1388,7 @@ struct smb_t2_rsp {
|
||||
#define SMB_SET_POSIX_LOCK 0x208
|
||||
#define SMB_POSIX_OPEN 0x209
|
||||
#define SMB_POSIX_UNLINK 0x20a
|
||||
#define SMB_SET_FILE_UNIX_INFO2
|
||||
#define SMB_SET_FILE_UNIX_INFO2 0x20b
|
||||
#define SMB_SET_FILE_BASIC_INFO2 0x3ec
|
||||
#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo too */
|
||||
#define SMB_FILE_ALL_INFO2 0x3fa
|
||||
@ -2109,22 +2109,40 @@ struct cifs_posix_acl { /* access conrol list (ACL) */
|
||||
|
||||
/* end of POSIX ACL definitions */
|
||||
|
||||
/* POSIX Open Flags */
|
||||
#define SMB_O_RDONLY 0x1
|
||||
#define SMB_O_WRONLY 0x2
|
||||
#define SMB_O_RDWR 0x4
|
||||
#define SMB_O_CREAT 0x10
|
||||
#define SMB_O_EXCL 0x20
|
||||
#define SMB_O_TRUNC 0x40
|
||||
#define SMB_O_APPEND 0x80
|
||||
#define SMB_O_SYNC 0x100
|
||||
#define SMB_O_DIRECTORY 0x200
|
||||
#define SMB_O_NOFOLLOW 0x400
|
||||
#define SMB_O_DIRECT 0x800
|
||||
|
||||
typedef struct {
|
||||
__u32 OpenFlags; /* same as NT CreateX */
|
||||
__u32 PosixOpenFlags;
|
||||
__u32 Mode;
|
||||
__u16 Level; /* reply level requested (see QPathInfo levels) */
|
||||
__u16 Pad; /* reserved - MBZ */
|
||||
__le32 OpenFlags; /* same as NT CreateX */
|
||||
__le32 PosixOpenFlags;
|
||||
__le64 Permissions;
|
||||
__le16 Level; /* reply level requested (see QPathInfo levels) */
|
||||
} __attribute__((packed)) OPEN_PSX_REQ; /* level 0x209 SetPathInfo data */
|
||||
|
||||
typedef struct {
|
||||
/* reply varies based on requested level */
|
||||
__le16 OplockFlags;
|
||||
__u16 Fid;
|
||||
__le32 CreateAction;
|
||||
__le16 ReturnedLevel;
|
||||
__le16 Pad;
|
||||
/* struct following varies based on requested level */
|
||||
} __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */
|
||||
|
||||
|
||||
struct file_internal_info {
|
||||
__u64 UniqueId; /* inode number */
|
||||
} __attribute__((packed)); /* level 0x3ee */
|
||||
|
||||
struct file_mode_info {
|
||||
__le32 Mode;
|
||||
} __attribute__((packed)); /* level 0x3f8 */
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* fs/cifs/cifsproto.h
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2002,2006
|
||||
* Copyright (c) International Business Machines Corp., 2002,2007
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
@ -244,6 +244,11 @@ extern int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
|
||||
const int access_flags, const int omode,
|
||||
__u16 * netfid, int *pOplock, FILE_ALL_INFO *,
|
||||
const struct nls_table *nls_codepage, int remap);
|
||||
extern int CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon,
|
||||
u32 posix_flags, __u64 mode, __u16 * netfid,
|
||||
FILE_UNIX_BASIC_INFO *pRetData,
|
||||
__u32 *pOplock, const char *name,
|
||||
const struct nls_table *nls_codepage, int remap);
|
||||
extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
|
||||
const int smb_file_id);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* fs/cifs/cifssmb.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002,2006
|
||||
* Copyright (C) International Business Machines Corp., 2002,2007
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
*
|
||||
* Contains the routines for constructing the SMB PDUs themselves
|
||||
@ -24,8 +24,8 @@
|
||||
/* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
|
||||
/* These are mostly routines that operate on a pathname, or on a tree id */
|
||||
/* (mounted volume), but there are eight handle based routines which must be */
|
||||
/* treated slightly different for reconnection purposes since we never want */
|
||||
/* to reuse a stale file handle and the caller knows the file handle */
|
||||
/* treated slightly differently for reconnection purposes since we never */
|
||||
/* want to reuse a stale file handle and only the caller knows the file info */
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kernel.h>
|
||||
@ -913,6 +913,130 @@ MkDirRetry:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
|
||||
__u64 mode, __u16 * netfid, FILE_UNIX_BASIC_INFO *pRetData,
|
||||
__u32 *pOplock, const char *name,
|
||||
const struct nls_table *nls_codepage, int remap)
|
||||
{
|
||||
TRANSACTION2_SPI_REQ *pSMB = NULL;
|
||||
TRANSACTION2_SPI_RSP *pSMBr = NULL;
|
||||
int name_len;
|
||||
int rc = 0;
|
||||
int bytes_returned = 0;
|
||||
char *data_offset;
|
||||
__u16 params, param_offset, offset, byte_count, count;
|
||||
OPEN_PSX_REQ * pdata;
|
||||
OPEN_PSX_RSP * psx_rsp;
|
||||
|
||||
cFYI(1, ("In POSIX Create"));
|
||||
PsxCreat:
|
||||
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
|
||||
(void **) &pSMBr);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifsConvertToUCS((__le16 *) pSMB->FileName, name,
|
||||
PATH_MAX, nls_codepage, remap);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else { /* BB improve the check for buffer overruns BB */
|
||||
name_len = strnlen(name, PATH_MAX);
|
||||
name_len++; /* trailing null */
|
||||
strncpy(pSMB->FileName, name, name_len);
|
||||
}
|
||||
|
||||
params = 6 + name_len;
|
||||
count = sizeof(OPEN_PSX_REQ);
|
||||
pSMB->MaxParameterCount = cpu_to_le16(2);
|
||||
pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
|
||||
pSMB->MaxSetupCount = 0;
|
||||
pSMB->Reserved = 0;
|
||||
pSMB->Flags = 0;
|
||||
pSMB->Timeout = 0;
|
||||
pSMB->Reserved2 = 0;
|
||||
param_offset = offsetof(struct smb_com_transaction2_spi_req,
|
||||
InformationLevel) - 4;
|
||||
offset = param_offset + params;
|
||||
data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
|
||||
pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
|
||||
pdata->Level = SMB_QUERY_FILE_UNIX_BASIC;
|
||||
pdata->Permissions = cpu_to_le64(mode);
|
||||
pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
|
||||
pdata->OpenFlags = cpu_to_le32(*pOplock);
|
||||
pSMB->ParameterOffset = cpu_to_le16(param_offset);
|
||||
pSMB->DataOffset = cpu_to_le16(offset);
|
||||
pSMB->SetupCount = 1;
|
||||
pSMB->Reserved3 = 0;
|
||||
pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
|
||||
byte_count = 3 /* pad */ + params + count;
|
||||
|
||||
pSMB->DataCount = cpu_to_le16(count);
|
||||
pSMB->ParameterCount = cpu_to_le16(params);
|
||||
pSMB->TotalDataCount = pSMB->DataCount;
|
||||
pSMB->TotalParameterCount = pSMB->ParameterCount;
|
||||
pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
|
||||
pSMB->Reserved4 = 0;
|
||||
pSMB->hdr.smb_buf_length += byte_count;
|
||||
pSMB->ByteCount = cpu_to_le16(byte_count);
|
||||
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
|
||||
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
|
||||
if (rc) {
|
||||
cFYI(1, ("Posix create returned %d", rc));
|
||||
goto psx_create_err;
|
||||
}
|
||||
|
||||
cFYI(1,("copying inode info"));
|
||||
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
|
||||
|
||||
if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
|
||||
rc = -EIO; /* bad smb */
|
||||
goto psx_create_err;
|
||||
}
|
||||
|
||||
/* copy return information to pRetData */
|
||||
psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
|
||||
+ le16_to_cpu(pSMBr->t2.DataOffset));
|
||||
|
||||
*pOplock = le16_to_cpu(psx_rsp->OplockFlags);
|
||||
if(netfid)
|
||||
*netfid = psx_rsp->Fid; /* cifs fid stays in le */
|
||||
/* Let caller know file was created so we can set the mode. */
|
||||
/* Do we care about the CreateAction in any other cases? */
|
||||
if(cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
|
||||
*pOplock |= CIFS_CREATE_ACTION;
|
||||
/* check to make sure response data is there */
|
||||
if(psx_rsp->ReturnedLevel != SMB_QUERY_FILE_UNIX_BASIC) {
|
||||
pRetData->Type = -1; /* unknown */
|
||||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
cFYI(1,("unknown type"));
|
||||
#endif
|
||||
} else {
|
||||
if(pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
|
||||
+ sizeof(FILE_UNIX_BASIC_INFO)) {
|
||||
cERROR(1,("Open response data too small"));
|
||||
pRetData->Type = -1;
|
||||
goto psx_create_err;
|
||||
}
|
||||
memcpy((char *) pRetData,
|
||||
(char *)psx_rsp + sizeof(OPEN_PSX_RSP),
|
||||
sizeof (FILE_UNIX_BASIC_INFO));
|
||||
}
|
||||
|
||||
|
||||
psx_create_err:
|
||||
cifs_buf_release(pSMB);
|
||||
|
||||
cifs_stats_inc(&tcon->num_mkdirs);
|
||||
|
||||
if (rc == -EAGAIN)
|
||||
goto PsxCreat;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static __u16 convert_disposition(int disposition)
|
||||
{
|
||||
__u16 ofun = 0;
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <linux/mempool.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/pagevec.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <asm/uaccess.h>
|
||||
@ -74,6 +75,8 @@ struct smb_vol {
|
||||
unsigned retry:1;
|
||||
unsigned intr:1;
|
||||
unsigned setuids:1;
|
||||
unsigned override_uid:1;
|
||||
unsigned override_gid:1;
|
||||
unsigned noperm:1;
|
||||
unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
|
||||
unsigned cifs_acl:1;
|
||||
@ -120,7 +123,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
||||
struct mid_q_entry * mid_entry;
|
||||
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
if(server->tcpStatus == CifsExiting) {
|
||||
if( kthread_should_stop() ) {
|
||||
/* the demux thread will exit normally
|
||||
next time through the loop */
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
@ -182,7 +185,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
up(&server->tcpSem);
|
||||
|
||||
while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
|
||||
while ( (!kthread_should_stop()) && (server->tcpStatus != CifsGood))
|
||||
{
|
||||
try_to_freeze();
|
||||
if(server->protocolType == IPV6) {
|
||||
@ -199,7 +202,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
||||
} else {
|
||||
atomic_inc(&tcpSesReconnectCount);
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
if(server->tcpStatus != CifsExiting)
|
||||
if( !kthread_should_stop() )
|
||||
server->tcpStatus = CifsGood;
|
||||
server->sequence_number = 0;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
@ -345,7 +348,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
int isMultiRsp;
|
||||
int reconnect;
|
||||
|
||||
daemonize("cifsd");
|
||||
allow_signal(SIGKILL);
|
||||
current->flags |= PF_MEMALLOC;
|
||||
server->tsk = current; /* save process info to wake at shutdown */
|
||||
@ -361,7 +363,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
GFP_KERNEL);
|
||||
}
|
||||
|
||||
while (server->tcpStatus != CifsExiting) {
|
||||
while (!kthread_should_stop()) {
|
||||
if (try_to_freeze())
|
||||
continue;
|
||||
if (bigbuf == NULL) {
|
||||
@ -400,7 +402,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
kernel_recvmsg(csocket, &smb_msg,
|
||||
&iov, 1, 4, 0 /* BB see socket.h flags */);
|
||||
|
||||
if (server->tcpStatus == CifsExiting) {
|
||||
if ( kthread_should_stop() ) {
|
||||
break;
|
||||
} else if (server->tcpStatus == CifsNeedReconnect) {
|
||||
cFYI(1, ("Reconnect after server stopped responding"));
|
||||
@ -524,7 +526,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
total_read += length) {
|
||||
length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
|
||||
pdu_length - total_read, 0);
|
||||
if((server->tcpStatus == CifsExiting) ||
|
||||
if( kthread_should_stop() ||
|
||||
(length == -EINTR)) {
|
||||
/* then will exit */
|
||||
reconnect = 2;
|
||||
@ -757,7 +759,6 @@ multi_t2_fnd:
|
||||
GFP_KERNEL);
|
||||
}
|
||||
|
||||
complete_and_exit(&cifsd_complete, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -973,7 +974,7 @@ 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)
|
||||
if (vol->UNC == NULL)
|
||||
return 1;
|
||||
strcpy(vol->UNC,value);
|
||||
if (strncmp(vol->UNC, "//", 2) == 0) {
|
||||
@ -1010,12 +1011,12 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||
return 1; /* needs_arg; */
|
||||
}
|
||||
if ((temp_len = strnlen(value, 1024)) < 1024) {
|
||||
if(value[0] != '/')
|
||||
if (value[0] != '/')
|
||||
temp_len++; /* missing leading slash */
|
||||
vol->prepath = kmalloc(temp_len+1,GFP_KERNEL);
|
||||
if(vol->prepath == NULL)
|
||||
if (vol->prepath == NULL)
|
||||
return 1;
|
||||
if(value[0] != '/') {
|
||||
if (value[0] != '/') {
|
||||
vol->prepath[0] = '/';
|
||||
strcpy(vol->prepath+1,value);
|
||||
} else
|
||||
@ -1031,7 +1032,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||
return 1; /* needs_arg; */
|
||||
}
|
||||
if (strnlen(value, 65) < 65) {
|
||||
if(strnicmp(value,"default",7))
|
||||
if (strnicmp(value,"default",7))
|
||||
vol->iocharset = value;
|
||||
/* if iocharset not set load_nls_default used by caller */
|
||||
cFYI(1, ("iocharset set to %s",value));
|
||||
@ -1043,11 +1044,13 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||
if (value && *value) {
|
||||
vol->linux_uid =
|
||||
simple_strtoul(value, &value, 0);
|
||||
vol->override_uid = 1;
|
||||
}
|
||||
} else if (strnicmp(data, "gid", 3) == 0) {
|
||||
if (value && *value) {
|
||||
vol->linux_gid =
|
||||
simple_strtoul(value, &value, 0);
|
||||
vol->override_gid = 1;
|
||||
}
|
||||
} else if (strnicmp(data, "file_mode", 4) == 0) {
|
||||
if (value && *value) {
|
||||
@ -1102,7 +1105,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||
}
|
||||
/* The string has 16th byte zero still from
|
||||
set at top of the function */
|
||||
if((i==15) && (value[i] != 0))
|
||||
if ((i==15) && (value[i] != 0))
|
||||
printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n");
|
||||
}
|
||||
} else if (strnicmp(data, "servern", 7) == 0) {
|
||||
@ -1126,7 +1129,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||
}
|
||||
/* The string has 16th byte zero still from
|
||||
set at top of the function */
|
||||
if((i==15) && (value[i] != 0))
|
||||
if ((i==15) && (value[i] != 0))
|
||||
printk(KERN_WARNING "CIFS: server netbiosname longer than 15 truncated.\n");
|
||||
}
|
||||
} else if (strnicmp(data, "credentials", 4) == 0) {
|
||||
@ -1233,13 +1236,13 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||
printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
|
||||
}
|
||||
if (vol->UNC == NULL) {
|
||||
if(devname == NULL) {
|
||||
if (devname == NULL) {
|
||||
printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
|
||||
return 1;
|
||||
}
|
||||
if ((temp_len = strnlen(devname, 300)) < 300) {
|
||||
vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
|
||||
if(vol->UNC == NULL)
|
||||
if (vol->UNC == NULL)
|
||||
return 1;
|
||||
strcpy(vol->UNC,devname);
|
||||
if (strncmp(vol->UNC, "//", 2) == 0) {
|
||||
@ -1663,7 +1666,13 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo * tcon,
|
||||
CIFS_SB(sb)->mnt_cifs_flags |=
|
||||
CIFS_MOUNT_POSIX_PATHS;
|
||||
}
|
||||
|
||||
|
||||
/* We might be setting the path sep back to a different
|
||||
form if we are reconnecting and the server switched its
|
||||
posix path capability for this share */
|
||||
if(sb && (CIFS_SB(sb)->prepathlen > 0))
|
||||
CIFS_SB(sb)->prepath[0] = CIFS_DIR_SEP(CIFS_SB(sb));
|
||||
|
||||
cFYI(1,("Negotiate caps 0x%x",(int)cap));
|
||||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
if(cap & CIFS_UNIX_FCNTL_CAP)
|
||||
@ -1712,12 +1721,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (volume_info.username) {
|
||||
if (volume_info.nullauth) {
|
||||
cFYI(1,("null user"));
|
||||
volume_info.username = NULL;
|
||||
} else if (volume_info.username) {
|
||||
/* BB fixme parse for domain name here */
|
||||
cFYI(1, ("Username: %s ", volume_info.username));
|
||||
|
||||
} else if (volume_info.nullauth) {
|
||||
cFYI(1,("null user"));
|
||||
} else {
|
||||
cifserror("No username specified");
|
||||
/* In userspace mount helper we can get user name from alternate
|
||||
@ -1791,11 +1800,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||
existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
|
||||
NULL /* no ipv6 addr */,
|
||||
volume_info.username, &srvTcp);
|
||||
else if(address_type == AF_INET6)
|
||||
else if(address_type == AF_INET6) {
|
||||
cFYI(1,("looking for ipv6 address"));
|
||||
existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
|
||||
&sin_server6.sin6_addr,
|
||||
volume_info.username, &srvTcp);
|
||||
else {
|
||||
} else {
|
||||
kfree(volume_info.UNC);
|
||||
kfree(volume_info.password);
|
||||
kfree(volume_info.prepath);
|
||||
@ -1807,17 +1817,23 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||
if (srvTcp) {
|
||||
cFYI(1, ("Existing tcp session with server found"));
|
||||
} else { /* create socket */
|
||||
if(volume_info.port)
|
||||
if (volume_info.port)
|
||||
sin_server.sin_port = htons(volume_info.port);
|
||||
else
|
||||
sin_server.sin_port = 0;
|
||||
rc = ipv4_connect(&sin_server,&csocket,
|
||||
if (address_type == AF_INET6) {
|
||||
cFYI(1,("attempting ipv6 connect"));
|
||||
/* BB should we allow ipv6 on port 139? */
|
||||
/* other OS never observed in Wild doing 139 with v6 */
|
||||
rc = ipv6_connect(&sin_server6,&csocket);
|
||||
} else
|
||||
rc = ipv4_connect(&sin_server,&csocket,
|
||||
volume_info.source_rfc1001_name,
|
||||
volume_info.target_rfc1001_name);
|
||||
if (rc < 0) {
|
||||
cERROR(1,
|
||||
("Error connecting to IPv4 socket. Aborting operation"));
|
||||
if(csocket != NULL)
|
||||
("Error connecting to IPv4 socket. Aborting operation"));
|
||||
if (csocket != NULL)
|
||||
sock_release(csocket);
|
||||
kfree(volume_info.UNC);
|
||||
kfree(volume_info.password);
|
||||
@ -1850,10 +1866,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||
so no need to spinlock this init of tcpStatus */
|
||||
srvTcp->tcpStatus = CifsNew;
|
||||
init_MUTEX(&srvTcp->tcpSem);
|
||||
rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
|
||||
CLONE_FS | CLONE_FILES | CLONE_VM);
|
||||
if(rc < 0) {
|
||||
rc = -ENOMEM;
|
||||
srvTcp->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread, srvTcp, "cifsd");
|
||||
if ( IS_ERR(srvTcp->tsk) ) {
|
||||
rc = PTR_ERR(srvTcp->tsk);
|
||||
cERROR(1,("error %d create cifsd thread", rc));
|
||||
srvTcp->tsk = NULL;
|
||||
sock_release(csocket);
|
||||
kfree(volume_info.UNC);
|
||||
kfree(volume_info.password);
|
||||
@ -1896,7 +1913,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||
int len = strlen(volume_info.domainname);
|
||||
pSesInfo->domainName =
|
||||
kmalloc(len + 1, GFP_KERNEL);
|
||||
if(pSesInfo->domainName)
|
||||
if (pSesInfo->domainName)
|
||||
strcpy(pSesInfo->domainName,
|
||||
volume_info.domainname);
|
||||
}
|
||||
@ -1906,7 +1923,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||
/* BB FIXME need to pass vol->secFlgs BB */
|
||||
rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
|
||||
up(&pSesInfo->sesSem);
|
||||
if(!rc)
|
||||
if (!rc)
|
||||
atomic_inc(&srvTcp->socketUseCount);
|
||||
} else
|
||||
kfree(volume_info.password);
|
||||
@ -1914,7 +1931,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||
|
||||
/* search for existing tcon to this server share */
|
||||
if (!rc) {
|
||||
if(volume_info.rsize > CIFSMaxBufSize) {
|
||||
if (volume_info.rsize > CIFSMaxBufSize) {
|
||||
cERROR(1,("rsize %d too large, using MaxBufSize",
|
||||
volume_info.rsize));
|
||||
cifs_sb->rsize = CIFSMaxBufSize;
|
||||
@ -1923,11 +1940,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||
else /* default */
|
||||
cifs_sb->rsize = CIFSMaxBufSize;
|
||||
|
||||
if(volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
|
||||
if (volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
|
||||
cERROR(1,("wsize %d too large using 4096 instead",
|
||||
volume_info.wsize));
|
||||
cifs_sb->wsize = 4096;
|
||||
} else if(volume_info.wsize)
|
||||
} else if (volume_info.wsize)
|
||||
cifs_sb->wsize = volume_info.wsize;
|
||||
else
|
||||
cifs_sb->wsize =
|
||||
@ -1940,14 +1957,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||
conjunction with 52K kvec constraint on arch with 4K
|
||||
page size */
|
||||
|
||||
if(cifs_sb->rsize < 2048) {
|
||||
if (cifs_sb->rsize < 2048) {
|
||||
cifs_sb->rsize = 2048;
|
||||
/* Windows ME may prefer this */
|
||||
cFYI(1,("readsize set to minimum 2048"));
|
||||
}
|
||||
/* calculate prepath */
|
||||
cifs_sb->prepath = volume_info.prepath;
|
||||
if(cifs_sb->prepath) {
|
||||
if (cifs_sb->prepath) {
|
||||
cifs_sb->prepathlen = strlen(cifs_sb->prepath);
|
||||
cifs_sb->prepath[0] = CIFS_DIR_SEP(cifs_sb);
|
||||
volume_info.prepath = NULL;
|
||||
@ -1960,24 +1977,27 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||
cFYI(1,("file mode: 0x%x dir mode: 0x%x",
|
||||
cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
|
||||
|
||||
if(volume_info.noperm)
|
||||
if (volume_info.noperm)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
|
||||
if(volume_info.setuids)
|
||||
if (volume_info.setuids)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
|
||||
if(volume_info.server_ino)
|
||||
if (volume_info.server_ino)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
|
||||
if(volume_info.remap)
|
||||
if (volume_info.remap)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
|
||||
if(volume_info.no_xattr)
|
||||
if (volume_info.no_xattr)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
|
||||
if(volume_info.sfu_emul)
|
||||
if (volume_info.sfu_emul)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
|
||||
if(volume_info.nobrl)
|
||||
if (volume_info.nobrl)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
|
||||
if(volume_info.cifs_acl)
|
||||
if (volume_info.cifs_acl)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
|
||||
|
||||
if(volume_info.direct_io) {
|
||||
if (volume_info.override_uid)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
|
||||
if (volume_info.override_gid)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
|
||||
if (volume_info.direct_io) {
|
||||
cFYI(1,("mounting share using direct i/o"));
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
|
||||
}
|
||||
@ -2030,7 +2050,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||
}
|
||||
}
|
||||
}
|
||||
if(pSesInfo) {
|
||||
if (pSesInfo) {
|
||||
if (pSesInfo->capabilities & CAP_LARGE_FILES) {
|
||||
sb->s_maxbytes = (u64) 1 << 63;
|
||||
} else
|
||||
@ -2044,13 +2064,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||
if (rc) {
|
||||
/* if session setup failed, use count is zero but
|
||||
we still need to free cifsd thread */
|
||||
if(atomic_read(&srvTcp->socketUseCount) == 0) {
|
||||
if (atomic_read(&srvTcp->socketUseCount) == 0) {
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
srvTcp->tcpStatus = CifsExiting;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
if(srvTcp->tsk) {
|
||||
if (srvTcp->tsk) {
|
||||
send_sig(SIGKILL,srvTcp->tsk,1);
|
||||
wait_for_completion(&cifsd_complete);
|
||||
kthread_stop(srvTcp->tsk);
|
||||
}
|
||||
}
|
||||
/* If find_unc succeeded then rc == 0 so we can not end */
|
||||
@ -2063,10 +2083,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||
int temp_rc;
|
||||
temp_rc = CIFSSMBLogoff(xid, pSesInfo);
|
||||
/* if the socketUseCount is now zero */
|
||||
if((temp_rc == -ESHUTDOWN) &&
|
||||
(pSesInfo->server->tsk)) {
|
||||
if ((temp_rc == -ESHUTDOWN) &&
|
||||
(pSesInfo->server) && (pSesInfo->server->tsk)) {
|
||||
send_sig(SIGKILL,pSesInfo->server->tsk,1);
|
||||
wait_for_completion(&cifsd_complete);
|
||||
kthread_stop(pSesInfo->server->tsk);
|
||||
}
|
||||
} else
|
||||
cFYI(1, ("No session or bad tcon"));
|
||||
@ -2127,7 +2147,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||
__u16 count;
|
||||
|
||||
cFYI(1, ("In sesssetup"));
|
||||
if(ses == NULL)
|
||||
if (ses == NULL)
|
||||
return -EINVAL;
|
||||
user = ses->userName;
|
||||
domain = ses->domainName;
|
||||
@ -2182,7 +2202,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||
*bcc_ptr = 0;
|
||||
bcc_ptr++;
|
||||
}
|
||||
if(user == NULL)
|
||||
if (user == NULL)
|
||||
bytes_returned = 0; /* skip null user */
|
||||
else
|
||||
bytes_returned =
|
||||
@ -2216,7 +2236,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||
bcc_ptr += 2 * bytes_returned;
|
||||
bcc_ptr += 2;
|
||||
} else {
|
||||
if(user != NULL) {
|
||||
if (user != NULL) {
|
||||
strncpy(bcc_ptr, user, 200);
|
||||
bcc_ptr += strnlen(user, 200);
|
||||
}
|
||||
@ -3316,7 +3336,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
|
||||
cFYI(1,("Waking up socket by sending it signal"));
|
||||
if(cifsd_task) {
|
||||
send_sig(SIGKILL,cifsd_task,1);
|
||||
wait_for_completion(&cifsd_complete);
|
||||
kthread_stop(cifsd_task);
|
||||
}
|
||||
rc = 0;
|
||||
} /* else - we have an smb session
|
||||
|
@ -274,7 +274,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||
pCifsFile->invalidHandle = FALSE;
|
||||
pCifsFile->closePend = FALSE;
|
||||
init_MUTEX(&pCifsFile->fh_sem);
|
||||
init_MUTEX(&pCifsFile->lock_sem);
|
||||
mutex_init(&pCifsFile->lock_mutex);
|
||||
INIT_LIST_HEAD(&pCifsFile->llist);
|
||||
atomic_set(&pCifsFile->wrtPending,0);
|
||||
|
||||
|
129
fs/cifs/file.c
129
fs/cifs/file.c
@ -48,7 +48,7 @@ static inline struct cifsFileInfo *cifs_init_private(
|
||||
private_data->netfid = netfid;
|
||||
private_data->pid = current->tgid;
|
||||
init_MUTEX(&private_data->fh_sem);
|
||||
init_MUTEX(&private_data->lock_sem);
|
||||
mutex_init(&private_data->lock_mutex);
|
||||
INIT_LIST_HEAD(&private_data->llist);
|
||||
private_data->pfile = file; /* needed for writepage */
|
||||
private_data->pInode = inode;
|
||||
@ -338,8 +338,7 @@ static int cifs_relock_file(struct cifsFileInfo *cifsFile)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cifs_reopen_file(struct inode *inode, struct file *file,
|
||||
int can_flush)
|
||||
static int cifs_reopen_file(struct file *file, int can_flush)
|
||||
{
|
||||
int rc = -EACCES;
|
||||
int xid, oplock;
|
||||
@ -347,13 +346,12 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
|
||||
struct cifsTconInfo *pTcon;
|
||||
struct cifsFileInfo *pCifsFile;
|
||||
struct cifsInodeInfo *pCifsInode;
|
||||
struct inode * inode;
|
||||
char *full_path = NULL;
|
||||
int desiredAccess;
|
||||
int disposition = FILE_OPEN;
|
||||
__u16 netfid;
|
||||
|
||||
if (inode == NULL)
|
||||
return -EBADF;
|
||||
if (file->private_data) {
|
||||
pCifsFile = (struct cifsFileInfo *)file->private_data;
|
||||
} else
|
||||
@ -368,25 +366,37 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
|
||||
}
|
||||
|
||||
if (file->f_path.dentry == NULL) {
|
||||
up(&pCifsFile->fh_sem);
|
||||
cFYI(1, ("failed file reopen, no valid name if dentry freed"));
|
||||
FreeXid(xid);
|
||||
return -EBADF;
|
||||
cERROR(1, ("no valid name if dentry freed"));
|
||||
dump_stack();
|
||||
rc = -EBADF;
|
||||
goto reopen_error_exit;
|
||||
}
|
||||
|
||||
inode = file->f_path.dentry->d_inode;
|
||||
if(inode == NULL) {
|
||||
cERROR(1, ("inode not valid"));
|
||||
dump_stack();
|
||||
rc = -EBADF;
|
||||
goto reopen_error_exit;
|
||||
}
|
||||
|
||||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
pTcon = cifs_sb->tcon;
|
||||
|
||||
/* can not grab rename sem here because various ops, including
|
||||
those that already have the rename sem can end up causing writepage
|
||||
to get called and if the server was down that means we end up here,
|
||||
and we can never tell if the caller already has the rename_sem */
|
||||
full_path = build_path_from_dentry(file->f_path.dentry);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
reopen_error_exit:
|
||||
up(&pCifsFile->fh_sem);
|
||||
FreeXid(xid);
|
||||
return -ENOMEM;
|
||||
return rc;
|
||||
}
|
||||
|
||||
cFYI(1, (" inode = 0x%p file flags are 0x%x for %s",
|
||||
cFYI(1, ("inode = 0x%p file flags 0x%x for %s",
|
||||
inode, file->f_flags,full_path));
|
||||
desiredAccess = cifs_convert_flags(file->f_flags);
|
||||
|
||||
@ -401,13 +411,6 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
|
||||
and server version of file size can be stale. If we knew for sure
|
||||
that inode was not dirty locally we could do this */
|
||||
|
||||
/* buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
|
||||
if (buf == 0) {
|
||||
up(&pCifsFile->fh_sem);
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
return -ENOMEM;
|
||||
} */
|
||||
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
|
||||
CREATE_NOT_DIR, &netfid, &oplock, NULL,
|
||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||
@ -508,12 +511,12 @@ int cifs_close(struct inode *inode, struct file *file)
|
||||
|
||||
/* Delete any outstanding lock records.
|
||||
We'll lose them when the file is closed anyway. */
|
||||
down(&pSMBFile->lock_sem);
|
||||
mutex_lock(&pSMBFile->lock_mutex);
|
||||
list_for_each_entry_safe(li, tmp, &pSMBFile->llist, llist) {
|
||||
list_del(&li->llist);
|
||||
kfree(li);
|
||||
}
|
||||
up(&pSMBFile->lock_sem);
|
||||
mutex_unlock(&pSMBFile->lock_mutex);
|
||||
|
||||
write_lock(&GlobalSMBSeslock);
|
||||
list_del(&pSMBFile->flist);
|
||||
@ -598,9 +601,9 @@ static int store_file_lock(struct cifsFileInfo *fid, __u64 len,
|
||||
li->offset = offset;
|
||||
li->length = len;
|
||||
li->type = lockType;
|
||||
down(&fid->lock_sem);
|
||||
mutex_lock(&fid->lock_mutex);
|
||||
list_add(&li->llist, &fid->llist);
|
||||
up(&fid->lock_sem);
|
||||
mutex_unlock(&fid->lock_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -757,7 +760,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
|
||||
struct cifsLockInfo *li, *tmp;
|
||||
|
||||
rc = 0;
|
||||
down(&fid->lock_sem);
|
||||
mutex_lock(&fid->lock_mutex);
|
||||
list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
|
||||
if (pfLock->fl_start <= li->offset &&
|
||||
length >= li->length) {
|
||||
@ -771,7 +774,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
|
||||
kfree(li);
|
||||
}
|
||||
}
|
||||
up(&fid->lock_sem);
|
||||
mutex_unlock(&fid->lock_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -792,12 +795,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
|
||||
int xid, long_op;
|
||||
struct cifsFileInfo *open_file;
|
||||
|
||||
if (file->f_path.dentry == NULL)
|
||||
return -EBADF;
|
||||
|
||||
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
||||
if (cifs_sb == NULL)
|
||||
return -EBADF;
|
||||
|
||||
pTcon = cifs_sb->tcon;
|
||||
|
||||
@ -807,14 +805,9 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
|
||||
|
||||
if (file->private_data == NULL)
|
||||
return -EBADF;
|
||||
else
|
||||
open_file = (struct cifsFileInfo *) file->private_data;
|
||||
open_file = (struct cifsFileInfo *) file->private_data;
|
||||
|
||||
xid = GetXid();
|
||||
if (file->f_path.dentry->d_inode == NULL) {
|
||||
FreeXid(xid);
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
if (*poffset > file->f_path.dentry->d_inode->i_size)
|
||||
long_op = 2; /* writes past end of file can take a long time */
|
||||
@ -841,17 +834,11 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
|
||||
return -EBADF;
|
||||
}
|
||||
if (open_file->invalidHandle) {
|
||||
if ((file->f_path.dentry == NULL) ||
|
||||
(file->f_path.dentry->d_inode == NULL)) {
|
||||
FreeXid(xid);
|
||||
return total_written;
|
||||
}
|
||||
/* 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_path.dentry->d_inode,
|
||||
file, FALSE);
|
||||
rc = cifs_reopen_file(file, FALSE);
|
||||
if (rc != 0)
|
||||
break;
|
||||
}
|
||||
@ -908,12 +895,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
|
||||
int xid, long_op;
|
||||
struct cifsFileInfo *open_file;
|
||||
|
||||
if (file->f_path.dentry == NULL)
|
||||
return -EBADF;
|
||||
|
||||
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
||||
if (cifs_sb == NULL)
|
||||
return -EBADF;
|
||||
|
||||
pTcon = cifs_sb->tcon;
|
||||
|
||||
@ -922,14 +904,9 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
|
||||
|
||||
if (file->private_data == NULL)
|
||||
return -EBADF;
|
||||
else
|
||||
open_file = (struct cifsFileInfo *)file->private_data;
|
||||
open_file = (struct cifsFileInfo *)file->private_data;
|
||||
|
||||
xid = GetXid();
|
||||
if (file->f_path.dentry->d_inode == NULL) {
|
||||
FreeXid(xid);
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
if (*poffset > file->f_path.dentry->d_inode->i_size)
|
||||
long_op = 2; /* writes past end of file can take a long time */
|
||||
@ -957,17 +934,11 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
|
||||
return -EBADF;
|
||||
}
|
||||
if (open_file->invalidHandle) {
|
||||
if ((file->f_path.dentry == NULL) ||
|
||||
(file->f_path.dentry->d_inode == NULL)) {
|
||||
FreeXid(xid);
|
||||
return total_written;
|
||||
}
|
||||
/* 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_path.dentry->d_inode,
|
||||
file, FALSE);
|
||||
rc = cifs_reopen_file(file, FALSE);
|
||||
if (rc != 0)
|
||||
break;
|
||||
}
|
||||
@ -1056,8 +1027,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
|
||||
read_unlock(&GlobalSMBSeslock);
|
||||
if((open_file->invalidHandle) &&
|
||||
(!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) {
|
||||
rc = cifs_reopen_file(&cifs_inode->vfs_inode,
|
||||
open_file->pfile, FALSE);
|
||||
rc = cifs_reopen_file(open_file->pfile, FALSE);
|
||||
/* if it fails, try another handle - might be */
|
||||
/* dangerous to hold up writepages with retry */
|
||||
if(rc) {
|
||||
@ -1404,32 +1374,6 @@ static int cifs_commit_write(struct file *file, struct page *page,
|
||||
spin_lock(&inode->i_lock);
|
||||
if (position > inode->i_size) {
|
||||
i_size_write(inode, position);
|
||||
/* if (file->private_data == NULL) {
|
||||
rc = -EBADF;
|
||||
} else {
|
||||
open_file = (struct cifsFileInfo *)file->private_data;
|
||||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
rc = -EAGAIN;
|
||||
while (rc == -EAGAIN) {
|
||||
if ((open_file->invalidHandle) &&
|
||||
(!open_file->closePend)) {
|
||||
rc = cifs_reopen_file(
|
||||
file->f_path.dentry->d_inode, file);
|
||||
if (rc != 0)
|
||||
break;
|
||||
}
|
||||
if (!open_file->closePend) {
|
||||
rc = CIFSSMBSetFileSize(xid,
|
||||
cifs_sb->tcon, position,
|
||||
open_file->netfid,
|
||||
open_file->pid, FALSE);
|
||||
} else {
|
||||
rc = -EBADF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cFYI(1, (" SetEOF (commit write) rc = %d", rc));
|
||||
} */
|
||||
}
|
||||
spin_unlock(&inode->i_lock);
|
||||
if (!PageUptodate(page)) {
|
||||
@ -1573,8 +1517,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
|
||||
int buf_type = CIFS_NO_BUFFER;
|
||||
if ((open_file->invalidHandle) &&
|
||||
(!open_file->closePend)) {
|
||||
rc = cifs_reopen_file(file->f_path.dentry->d_inode,
|
||||
file, TRUE);
|
||||
rc = cifs_reopen_file(file, TRUE);
|
||||
if (rc != 0)
|
||||
break;
|
||||
}
|
||||
@ -1660,8 +1603,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
|
||||
while (rc == -EAGAIN) {
|
||||
if ((open_file->invalidHandle) &&
|
||||
(!open_file->closePend)) {
|
||||
rc = cifs_reopen_file(file->f_path.dentry->d_inode,
|
||||
file, TRUE);
|
||||
rc = cifs_reopen_file(file, TRUE);
|
||||
if (rc != 0)
|
||||
break;
|
||||
}
|
||||
@ -1817,8 +1759,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
||||
while (rc == -EAGAIN) {
|
||||
if ((open_file->invalidHandle) &&
|
||||
(!open_file->closePend)) {
|
||||
rc = cifs_reopen_file(file->f_path.dentry->d_inode,
|
||||
file, TRUE);
|
||||
rc = cifs_reopen_file(file, TRUE);
|
||||
if (rc != 0)
|
||||
break;
|
||||
}
|
||||
|
282
fs/cifs/inode.c
282
fs/cifs/inode.c
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* fs/cifs/inode.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002,2005
|
||||
* Copyright (C) International Business Machines Corp., 2002,2007
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
@ -90,7 +90,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
(*pinode)->i_ino =
|
||||
(unsigned long)findData.UniqueId;
|
||||
} /* note ino incremented to unique num in new_inode */
|
||||
if(sb->s_flags & MS_NOATIME)
|
||||
if (sb->s_flags & MS_NOATIME)
|
||||
(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
|
||||
|
||||
insert_inode_hash(*pinode);
|
||||
@ -139,8 +139,17 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
inode->i_mode |= S_IFREG;
|
||||
cFYI(1,("unknown type %d",type));
|
||||
}
|
||||
inode->i_uid = le64_to_cpu(findData.Uid);
|
||||
inode->i_gid = le64_to_cpu(findData.Gid);
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
|
||||
inode->i_uid = cifs_sb->mnt_uid;
|
||||
else
|
||||
inode->i_uid = le64_to_cpu(findData.Uid);
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
|
||||
inode->i_gid = cifs_sb->mnt_gid;
|
||||
else
|
||||
inode->i_gid = le64_to_cpu(findData.Gid);
|
||||
|
||||
inode->i_nlink = le64_to_cpu(findData.Nlinks);
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
@ -178,13 +187,13 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
&cifs_file_direct_nobrl_ops;
|
||||
else
|
||||
inode->i_fop = &cifs_file_direct_ops;
|
||||
} else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
inode->i_fop = &cifs_file_nobrl_ops;
|
||||
else /* not direct, send byte range locks */
|
||||
inode->i_fop = &cifs_file_ops;
|
||||
|
||||
/* check if server can support readpages */
|
||||
if(pTcon->ses->server->maxBuf <
|
||||
if (pTcon->ses->server->maxBuf <
|
||||
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
|
||||
inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
|
||||
else
|
||||
@ -220,7 +229,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
|
||||
|
||||
pbuf = buf;
|
||||
|
||||
if(size == 0) {
|
||||
if (size == 0) {
|
||||
inode->i_mode |= S_IFIFO;
|
||||
return 0;
|
||||
} else if (size < 8) {
|
||||
@ -239,11 +248,11 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
|
||||
netfid,
|
||||
24 /* length */, 0 /* offset */,
|
||||
&bytes_read, &pbuf, &buf_type);
|
||||
if((rc == 0) && (bytes_read >= 8)) {
|
||||
if(memcmp("IntxBLK", pbuf, 8) == 0) {
|
||||
if ((rc == 0) && (bytes_read >= 8)) {
|
||||
if (memcmp("IntxBLK", pbuf, 8) == 0) {
|
||||
cFYI(1,("Block device"));
|
||||
inode->i_mode |= S_IFBLK;
|
||||
if(bytes_read == 24) {
|
||||
if (bytes_read == 24) {
|
||||
/* we have enough to decode dev num */
|
||||
__u64 mjr; /* major */
|
||||
__u64 mnr; /* minor */
|
||||
@ -251,10 +260,10 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
|
||||
mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
|
||||
inode->i_rdev = MKDEV(mjr, mnr);
|
||||
}
|
||||
} else if(memcmp("IntxCHR", pbuf, 8) == 0) {
|
||||
} else if (memcmp("IntxCHR", pbuf, 8) == 0) {
|
||||
cFYI(1,("Char device"));
|
||||
inode->i_mode |= S_IFCHR;
|
||||
if(bytes_read == 24) {
|
||||
if (bytes_read == 24) {
|
||||
/* we have enough to decode dev num */
|
||||
__u64 mjr; /* major */
|
||||
__u64 mnr; /* minor */
|
||||
@ -262,7 +271,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
|
||||
mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
|
||||
inode->i_rdev = MKDEV(mjr, mnr);
|
||||
}
|
||||
} else if(memcmp("IntxLNK", pbuf, 7) == 0) {
|
||||
} else if (memcmp("IntxLNK", pbuf, 7) == 0) {
|
||||
cFYI(1,("Symlink"));
|
||||
inode->i_mode |= S_IFLNK;
|
||||
} else {
|
||||
@ -293,7 +302,7 @@ static int get_sfu_uid_mode(struct inode * inode,
|
||||
rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS",
|
||||
ea_value, 4 /* size of buf */, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if(rc < 0)
|
||||
if (rc < 0)
|
||||
return (int)rc;
|
||||
else if (rc > 3) {
|
||||
mode = le32_to_cpu(*((__le32 *)ea_value));
|
||||
@ -348,7 +357,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
/* BB optimize code so we do not make the above call
|
||||
when server claims no NT SMB support and the above call
|
||||
failed at least once - set flag in tcon or mount */
|
||||
if((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
|
||||
if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
|
||||
rc = SMBQueryInformation(xid, pTcon, search_path,
|
||||
pfindData, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
@ -425,7 +434,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
} else /* do we need cast or hash to ino? */
|
||||
(*pinode)->i_ino = inode_num;
|
||||
} /* else ino incremented to unique num in new_inode*/
|
||||
if(sb->s_flags & MS_NOATIME)
|
||||
if (sb->s_flags & MS_NOATIME)
|
||||
(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
|
||||
insert_inode_hash(*pinode);
|
||||
}
|
||||
@ -442,7 +451,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
|
||||
|
||||
/* Linux can not store file creation time so ignore it */
|
||||
if(pfindData->LastAccessTime)
|
||||
if (pfindData->LastAccessTime)
|
||||
inode->i_atime = cifs_NTtimeToUnix
|
||||
(le64_to_cpu(pfindData->LastAccessTime));
|
||||
else /* do not need to use current_fs_time - time not stored */
|
||||
@ -452,7 +461,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
inode->i_ctime =
|
||||
cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
|
||||
cFYI(0, ("Attributes came in as 0x%x", attr));
|
||||
if(adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
|
||||
if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
|
||||
inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj;
|
||||
inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj;
|
||||
}
|
||||
@ -521,8 +530,10 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
|
||||
/* BB fill in uid and gid here? with help from winbind?
|
||||
or retrieve from NTFS stream extended attribute */
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
||||
/* fill in uid, gid, mode from server ACL */
|
||||
/* BB FIXME this should also take into account the
|
||||
* default uid specified on mount if present */
|
||||
get_sfu_uid_mode(inode, search_path, cifs_sb, xid);
|
||||
} else if (atomic_read(&cifsInfo->inUse) == 0) {
|
||||
inode->i_uid = cifs_sb->mnt_uid;
|
||||
@ -541,12 +552,12 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
&cifs_file_direct_nobrl_ops;
|
||||
else
|
||||
inode->i_fop = &cifs_file_direct_ops;
|
||||
} else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
inode->i_fop = &cifs_file_nobrl_ops;
|
||||
else /* not direct, send byte range locks */
|
||||
inode->i_fop = &cifs_file_ops;
|
||||
|
||||
if(pTcon->ses->server->maxBuf <
|
||||
if (pTcon->ses->server->maxBuf <
|
||||
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
|
||||
inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
|
||||
else
|
||||
@ -597,7 +608,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
||||
|
||||
xid = GetXid();
|
||||
|
||||
if(inode)
|
||||
if (inode)
|
||||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
else
|
||||
cifs_sb = CIFS_SB(direntry->d_sb);
|
||||
@ -723,7 +734,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
||||
when needed */
|
||||
direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
|
||||
}
|
||||
if(inode) {
|
||||
if (inode) {
|
||||
inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
|
||||
cifsInode = CIFS_I(inode);
|
||||
cifsInode->time = 0; /* force revalidate of dir as well */
|
||||
@ -734,6 +745,136 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void posix_fill_in_inode(struct inode *tmp_inode,
|
||||
FILE_UNIX_BASIC_INFO *pData, int *pobject_type, int isNewInode)
|
||||
{
|
||||
loff_t local_size;
|
||||
struct timespec local_mtime;
|
||||
|
||||
struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
|
||||
|
||||
__u32 type = le32_to_cpu(pData->Type);
|
||||
__u64 num_of_bytes = le64_to_cpu(pData->NumOfBytes);
|
||||
__u64 end_of_file = le64_to_cpu(pData->EndOfFile);
|
||||
cifsInfo->time = jiffies;
|
||||
atomic_inc(&cifsInfo->inUse);
|
||||
|
||||
/* save mtime and size */
|
||||
local_mtime = tmp_inode->i_mtime;
|
||||
local_size = tmp_inode->i_size;
|
||||
|
||||
tmp_inode->i_atime =
|
||||
cifs_NTtimeToUnix(le64_to_cpu(pData->LastAccessTime));
|
||||
tmp_inode->i_mtime =
|
||||
cifs_NTtimeToUnix(le64_to_cpu(pData->LastModificationTime));
|
||||
tmp_inode->i_ctime =
|
||||
cifs_NTtimeToUnix(le64_to_cpu(pData->LastStatusChange));
|
||||
|
||||
tmp_inode->i_mode = le64_to_cpu(pData->Permissions);
|
||||
/* since we set the inode type below we need to mask off type
|
||||
to avoid strange results if bits above were corrupt */
|
||||
tmp_inode->i_mode &= ~S_IFMT;
|
||||
if (type == UNIX_FILE) {
|
||||
*pobject_type = DT_REG;
|
||||
tmp_inode->i_mode |= S_IFREG;
|
||||
} else if (type == UNIX_SYMLINK) {
|
||||
*pobject_type = DT_LNK;
|
||||
tmp_inode->i_mode |= S_IFLNK;
|
||||
} else if (type == UNIX_DIR) {
|
||||
*pobject_type = DT_DIR;
|
||||
tmp_inode->i_mode |= S_IFDIR;
|
||||
} else if (type == UNIX_CHARDEV) {
|
||||
*pobject_type = DT_CHR;
|
||||
tmp_inode->i_mode |= S_IFCHR;
|
||||
tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor),
|
||||
le64_to_cpu(pData->DevMinor) & MINORMASK);
|
||||
} else if (type == UNIX_BLOCKDEV) {
|
||||
*pobject_type = DT_BLK;
|
||||
tmp_inode->i_mode |= S_IFBLK;
|
||||
tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor),
|
||||
le64_to_cpu(pData->DevMinor) & MINORMASK);
|
||||
} else if (type == UNIX_FIFO) {
|
||||
*pobject_type = DT_FIFO;
|
||||
tmp_inode->i_mode |= S_IFIFO;
|
||||
} else if (type == UNIX_SOCKET) {
|
||||
*pobject_type = DT_SOCK;
|
||||
tmp_inode->i_mode |= S_IFSOCK;
|
||||
} else {
|
||||
/* safest to just call it a file */
|
||||
*pobject_type = DT_REG;
|
||||
tmp_inode->i_mode |= S_IFREG;
|
||||
cFYI(1,("unknown inode type %d",type));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
cFYI(1,("object type: %d", type));
|
||||
#endif
|
||||
tmp_inode->i_uid = le64_to_cpu(pData->Uid);
|
||||
tmp_inode->i_gid = le64_to_cpu(pData->Gid);
|
||||
tmp_inode->i_nlink = le64_to_cpu(pData->Nlinks);
|
||||
|
||||
spin_lock(&tmp_inode->i_lock);
|
||||
if (is_size_safe_to_change(cifsInfo, end_of_file)) {
|
||||
/* can not safely change the file size here if the
|
||||
client is writing to it due to potential races */
|
||||
i_size_write(tmp_inode, end_of_file);
|
||||
|
||||
/* 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 + num_of_bytes) >> 9;
|
||||
}
|
||||
spin_unlock(&tmp_inode->i_lock);
|
||||
|
||||
if (S_ISREG(tmp_inode->i_mode)) {
|
||||
cFYI(1, ("File inode"));
|
||||
tmp_inode->i_op = &cifs_file_inode_ops;
|
||||
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
|
||||
else
|
||||
tmp_inode->i_fop = &cifs_file_direct_ops;
|
||||
|
||||
} else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
tmp_inode->i_fop = &cifs_file_nobrl_ops;
|
||||
else
|
||||
tmp_inode->i_fop = &cifs_file_ops;
|
||||
|
||||
if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
|
||||
(cifs_sb->tcon->ses->server->maxBuf <
|
||||
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
|
||||
tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
|
||||
else
|
||||
tmp_inode->i_data.a_ops = &cifs_addr_ops;
|
||||
|
||||
if(isNewInode)
|
||||
return; /* No sense invalidating pages for new inode since we
|
||||
have not started caching readahead file data yet */
|
||||
|
||||
if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
|
||||
(local_size == tmp_inode->i_size)) {
|
||||
cFYI(1, ("inode exists but unchanged"));
|
||||
} else {
|
||||
/* file may have changed on server */
|
||||
cFYI(1, ("invalidate inode, readdir detected change"));
|
||||
invalidate_remote_inode(tmp_inode);
|
||||
}
|
||||
} else if (S_ISDIR(tmp_inode->i_mode)) {
|
||||
cFYI(1, ("Directory inode"));
|
||||
tmp_inode->i_op = &cifs_dir_inode_ops;
|
||||
tmp_inode->i_fop = &cifs_dir_ops;
|
||||
} else if (S_ISLNK(tmp_inode->i_mode)) {
|
||||
cFYI(1, ("Symbolic Link inode"));
|
||||
tmp_inode->i_op = &cifs_symlink_inode_ops;
|
||||
/* tmp_inode->i_fop = *//* do not need to set to anything */
|
||||
} else {
|
||||
cFYI(1, ("Special inode"));
|
||||
init_special_inode(tmp_inode, tmp_inode->i_mode,
|
||||
tmp_inode->i_rdev);
|
||||
}
|
||||
}
|
||||
|
||||
int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||
{
|
||||
int rc = 0;
|
||||
@ -755,6 +896,71 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||
FreeXid(xid);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if((pTcon->ses->capabilities & CAP_UNIX) &&
|
||||
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||
le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
|
||||
u32 oplock = 0;
|
||||
FILE_UNIX_BASIC_INFO * pInfo =
|
||||
kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
|
||||
if(pInfo == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto mkdir_out;
|
||||
}
|
||||
|
||||
rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
|
||||
mode, NULL /* netfid */, pInfo, &oplock,
|
||||
full_path, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc) {
|
||||
cFYI(1, ("posix mkdir returned 0x%x", rc));
|
||||
d_drop(direntry);
|
||||
} else {
|
||||
int obj_type;
|
||||
if (pInfo->Type == -1) /* no return info - go query */
|
||||
goto mkdir_get_info;
|
||||
/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need to set uid/gid */
|
||||
inc_nlink(inode);
|
||||
if (pTcon->nocase)
|
||||
direntry->d_op = &cifs_ci_dentry_ops;
|
||||
else
|
||||
direntry->d_op = &cifs_dentry_ops;
|
||||
|
||||
newinode = new_inode(inode->i_sb);
|
||||
if (newinode == NULL)
|
||||
goto mkdir_get_info;
|
||||
/* Is an i_ino of zero legal? */
|
||||
/* Are there sanity checks we can use to ensure that
|
||||
the server is really filling in that field? */
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
||||
newinode->i_ino =
|
||||
(unsigned long)pInfo->UniqueId;
|
||||
} /* note ino incremented to unique num in new_inode */
|
||||
if(inode->i_sb->s_flags & MS_NOATIME)
|
||||
newinode->i_flags |= S_NOATIME | S_NOCMTIME;
|
||||
newinode->i_nlink = 2;
|
||||
|
||||
insert_inode_hash(newinode);
|
||||
d_instantiate(direntry, newinode);
|
||||
|
||||
/* we already checked in POSIXCreate whether
|
||||
frame was long enough */
|
||||
posix_fill_in_inode(direntry->d_inode,
|
||||
pInfo, &obj_type, 1 /* NewInode */);
|
||||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
cFYI(1,("instantiated dentry %p %s to inode %p",
|
||||
direntry, direntry->d_name.name, newinode));
|
||||
|
||||
if(newinode->i_nlink != 2)
|
||||
cFYI(1,("unexpected number of links %d",
|
||||
newinode->i_nlink));
|
||||
#endif
|
||||
}
|
||||
kfree(pInfo);
|
||||
goto mkdir_out;
|
||||
}
|
||||
|
||||
/* BB add setting the equivalent of mode via CreateX w/ACLs */
|
||||
rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
@ -762,6 +968,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||
cFYI(1, ("cifs_mkdir returned 0x%x", rc));
|
||||
d_drop(direntry);
|
||||
} else {
|
||||
mkdir_get_info:
|
||||
inc_nlink(inode);
|
||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
||||
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
||||
@ -775,8 +982,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||
else
|
||||
direntry->d_op = &cifs_dentry_ops;
|
||||
d_instantiate(direntry, newinode);
|
||||
if (direntry->d_inode)
|
||||
direntry->d_inode->i_nlink = 2;
|
||||
/* setting nlink not necessary except in cases where we
|
||||
* failed to get it from the server or was set bogus */
|
||||
if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
|
||||
direntry->d_inode->i_nlink = 2;
|
||||
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
||||
@ -812,6 +1021,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||
}
|
||||
}
|
||||
}
|
||||
mkdir_out:
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
return rc;
|
||||
@ -1339,17 +1549,17 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||
cpu_to_le32(cifsInode->cifsAttrs |
|
||||
ATTR_READONLY);
|
||||
}
|
||||
} else if ((mode & S_IWUGO) == S_IWUGO) {
|
||||
if (cifsInode->cifsAttrs & ATTR_READONLY) {
|
||||
set_dosattr = TRUE;
|
||||
time_buf.Attributes =
|
||||
cpu_to_le32(cifsInode->cifsAttrs &
|
||||
(~ATTR_READONLY));
|
||||
/* Windows ignores set to zero */
|
||||
if(time_buf.Attributes == 0)
|
||||
time_buf.Attributes |=
|
||||
cpu_to_le32(ATTR_NORMAL);
|
||||
}
|
||||
} else if (cifsInode->cifsAttrs & ATTR_READONLY) {
|
||||
/* If file is readonly on server, we would
|
||||
not be able to write to it - so if any write
|
||||
bit is enabled for user or group or other we
|
||||
need to at least try to remove r/o dos attr */
|
||||
set_dosattr = TRUE;
|
||||
time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs &
|
||||
(~ATTR_READONLY));
|
||||
/* Windows ignores set to zero */
|
||||
if(time_buf.Attributes == 0)
|
||||
time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL);
|
||||
}
|
||||
/* BB to be implemented -
|
||||
via Windows security descriptors or streams */
|
||||
|
@ -30,6 +30,9 @@
|
||||
#include <linux/fs.h>
|
||||
#include <asm/div64.h>
|
||||
#include <asm/byteorder.h>
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
#include <linux/inet.h>
|
||||
#endif
|
||||
#include "cifsfs.h"
|
||||
#include "cifspdu.h"
|
||||
#include "cifsglob.h"
|
||||
@ -129,11 +132,27 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
|
||||
/* Convert string containing dotted ip address to binary form */
|
||||
/* returns 0 if invalid address */
|
||||
|
||||
/* BB add address family, change rc to status flag and return union or for ipv6 */
|
||||
/* will need parent to call something like inet_pton to convert ipv6 address BB */
|
||||
int
|
||||
cifs_inet_pton(int address_family, char *cp,void *dst)
|
||||
{
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
int ret = 0;
|
||||
|
||||
/* calculate length by finding first slash or NULL */
|
||||
/* BB Should we convert '/' slash to '\' here since it seems already done
|
||||
before this */
|
||||
if( address_family == AF_INET ){
|
||||
ret = in4_pton(cp, -1 /* len */, dst , '\\', NULL);
|
||||
} else if( address_family == AF_INET6 ){
|
||||
ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL);
|
||||
}
|
||||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
cFYI(1,("address conversion returned %d for %s", ret, cp));
|
||||
#endif
|
||||
if (ret > 0)
|
||||
ret = 1;
|
||||
return ret;
|
||||
#else
|
||||
int value;
|
||||
int digit;
|
||||
int i;
|
||||
@ -192,6 +211,7 @@ cifs_inet_pton(int address_family, char *cp,void *dst)
|
||||
|
||||
*((__be32 *)dst) = *((__be32 *) bytes) | htonl(value);
|
||||
return 1; /* success */
|
||||
#endif /* EXPERIMENTAL */
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -37,19 +37,19 @@ static void dump_cifs_file_struct(struct file *file, char *label)
|
||||
{
|
||||
struct cifsFileInfo * cf;
|
||||
|
||||
if(file) {
|
||||
if (file) {
|
||||
cf = file->private_data;
|
||||
if(cf == NULL) {
|
||||
if (cf == NULL) {
|
||||
cFYI(1,("empty cifs private file data"));
|
||||
return;
|
||||
}
|
||||
if(cf->invalidHandle) {
|
||||
if (cf->invalidHandle) {
|
||||
cFYI(1,("invalid handle"));
|
||||
}
|
||||
if(cf->srch_inf.endOfSearch) {
|
||||
if (cf->srch_inf.endOfSearch) {
|
||||
cFYI(1,("end of search"));
|
||||
}
|
||||
if(cf->srch_inf.emptyDir) {
|
||||
if (cf->srch_inf.emptyDir) {
|
||||
cFYI(1,("empty dir"));
|
||||
}
|
||||
|
||||
@ -77,17 +77,17 @@ static int 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 old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
|
||||
if(*ptmp_inode == NULL) {
|
||||
if (*ptmp_inode == NULL) {
|
||||
*ptmp_inode = new_inode(file->f_path.dentry->d_sb);
|
||||
if(*ptmp_inode == NULL)
|
||||
if (*ptmp_inode == NULL)
|
||||
return rc;
|
||||
rc = 1;
|
||||
}
|
||||
if(file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
|
||||
if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
|
||||
(*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;
|
||||
} else {
|
||||
tmp_dentry = d_alloc(file->f_path.dentry, qstring);
|
||||
if(tmp_dentry == NULL) {
|
||||
if (tmp_dentry == NULL) {
|
||||
cERROR(1,("Failed allocating dentry"));
|
||||
*ptmp_inode = NULL;
|
||||
return rc;
|
||||
@ -98,9 +98,9 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
|
||||
tmp_dentry->d_op = &cifs_ci_dentry_ops;
|
||||
else
|
||||
tmp_dentry->d_op = &cifs_dentry_ops;
|
||||
if(*ptmp_inode == NULL)
|
||||
if (*ptmp_inode == NULL)
|
||||
return rc;
|
||||
if(file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
|
||||
if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
|
||||
(*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;
|
||||
rc = 2;
|
||||
}
|
||||
@ -112,7 +112,7 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
|
||||
|
||||
static void AdjustForTZ(struct cifsTconInfo * tcon, struct inode * inode)
|
||||
{
|
||||
if((tcon) && (tcon->ses) && (tcon->ses->server)) {
|
||||
if ((tcon) && (tcon->ses) && (tcon->ses->server)) {
|
||||
inode->i_ctime.tv_sec += tcon->ses->server->timeAdj;
|
||||
inode->i_mtime.tv_sec += tcon->ses->server->timeAdj;
|
||||
inode->i_atime.tv_sec += tcon->ses->server->timeAdj;
|
||||
@ -137,7 +137,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
|
||||
local_mtime = tmp_inode->i_mtime;
|
||||
local_size = tmp_inode->i_size;
|
||||
|
||||
if(new_buf_type) {
|
||||
if (new_buf_type) {
|
||||
FILE_DIRECTORY_INFO *pfindData = (FILE_DIRECTORY_INFO *)buf;
|
||||
|
||||
attr = le32_to_cpu(pfindData->ExtFileAttributes);
|
||||
@ -193,7 +193,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
|
||||
if (attr & ATTR_DIRECTORY) {
|
||||
*pobject_type = DT_DIR;
|
||||
/* override default perms since we do not lock dirs */
|
||||
if(atomic_read(&cifsInfo->inUse) == 0) {
|
||||
if (atomic_read(&cifsInfo->inUse) == 0) {
|
||||
tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
|
||||
}
|
||||
tmp_inode->i_mode |= S_IFDIR;
|
||||
@ -250,25 +250,25 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
|
||||
if (S_ISREG(tmp_inode->i_mode)) {
|
||||
cFYI(1, ("File inode"));
|
||||
tmp_inode->i_op = &cifs_file_inode_ops;
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
|
||||
else
|
||||
tmp_inode->i_fop = &cifs_file_direct_ops;
|
||||
|
||||
} else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
tmp_inode->i_fop = &cifs_file_nobrl_ops;
|
||||
else
|
||||
tmp_inode->i_fop = &cifs_file_ops;
|
||||
|
||||
if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
|
||||
if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
|
||||
(cifs_sb->tcon->ses->server->maxBuf <
|
||||
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
|
||||
tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
|
||||
else
|
||||
tmp_inode->i_data.a_ops = &cifs_addr_ops;
|
||||
|
||||
if(isNewInode)
|
||||
if (isNewInode)
|
||||
return; /* No sense invalidating pages for new inode
|
||||
since have not started caching readahead file
|
||||
data yet */
|
||||
@ -357,8 +357,14 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
|
||||
cFYI(1,("unknown inode type %d",type));
|
||||
}
|
||||
|
||||
tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
|
||||
tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
|
||||
tmp_inode->i_uid = cifs_sb->mnt_uid;
|
||||
else
|
||||
tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
|
||||
tmp_inode->i_gid = cifs_sb->mnt_gid;
|
||||
else
|
||||
tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
|
||||
tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
|
||||
|
||||
spin_lock(&tmp_inode->i_lock);
|
||||
@ -377,25 +383,24 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
|
||||
cFYI(1, ("File inode"));
|
||||
tmp_inode->i_op = &cifs_file_inode_ops;
|
||||
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
|
||||
else
|
||||
tmp_inode->i_fop = &cifs_file_direct_ops;
|
||||
|
||||
} else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
tmp_inode->i_fop = &cifs_file_nobrl_ops;
|
||||
else
|
||||
tmp_inode->i_fop = &cifs_file_ops;
|
||||
|
||||
if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
|
||||
if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
|
||||
(cifs_sb->tcon->ses->server->maxBuf <
|
||||
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
|
||||
tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
|
||||
else
|
||||
tmp_inode->i_data.a_ops = &cifs_addr_ops;
|
||||
|
||||
if(isNewInode)
|
||||
if (isNewInode)
|
||||
return; /* No sense invalidating pages for new inode since we
|
||||
have not started caching readahead file data yet */
|
||||
|
||||
@ -430,34 +435,28 @@ static int initiate_cifs_search(const int xid, struct file *file)
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifsTconInfo *pTcon;
|
||||
|
||||
if(file->private_data == NULL) {
|
||||
if (file->private_data == NULL) {
|
||||
file->private_data =
|
||||
kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
|
||||
kzalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
|
||||
}
|
||||
|
||||
if(file->private_data == NULL) {
|
||||
if (file->private_data == NULL)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
memset(file->private_data,0,sizeof(struct cifsFileInfo));
|
||||
}
|
||||
cifsFile = file->private_data;
|
||||
cifsFile->invalidHandle = TRUE;
|
||||
cifsFile->srch_inf.endOfSearch = FALSE;
|
||||
|
||||
if(file->f_path.dentry == NULL)
|
||||
return -ENOENT;
|
||||
|
||||
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
||||
if(cifs_sb == NULL)
|
||||
if (cifs_sb == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
pTcon = cifs_sb->tcon;
|
||||
if(pTcon == NULL)
|
||||
if (pTcon == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
full_path = build_path_from_dentry(file->f_path.dentry);
|
||||
|
||||
if(full_path == NULL) {
|
||||
if (full_path == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -480,9 +479,9 @@ ffirst_retry:
|
||||
&cifsFile->netfid, &cifsFile->srch_inf,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
|
||||
if(rc == 0)
|
||||
if (rc == 0)
|
||||
cifsFile->invalidHandle = FALSE;
|
||||
if((rc == -EOPNOTSUPP) &&
|
||||
if ((rc == -EOPNOTSUPP) &&
|
||||
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
|
||||
goto ffirst_retry;
|
||||
@ -498,7 +497,7 @@ static int cifs_unicode_bytelen(char *str)
|
||||
__le16 * ustr = (__le16 *)str;
|
||||
|
||||
for(len=0;len <= PATH_MAX;len++) {
|
||||
if(ustr[len] == 0)
|
||||
if (ustr[len] == 0)
|
||||
return len << 1;
|
||||
}
|
||||
cFYI(1,("Unicode string longer than PATH_MAX found"));
|
||||
@ -510,7 +509,7 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
|
||||
char * new_entry;
|
||||
FILE_DIRECTORY_INFO * pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
|
||||
|
||||
if(level == SMB_FIND_FILE_INFO_STANDARD) {
|
||||
if (level == SMB_FIND_FILE_INFO_STANDARD) {
|
||||
FIND_FILE_STANDARD_INFO * pfData;
|
||||
pfData = (FIND_FILE_STANDARD_INFO *)pDirInfo;
|
||||
|
||||
@ -520,12 +519,12 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
|
||||
new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
|
||||
cFYI(1,("new entry %p old entry %p",new_entry,old_entry));
|
||||
/* validate that new_entry is not past end of SMB */
|
||||
if(new_entry >= end_of_smb) {
|
||||
if (new_entry >= end_of_smb) {
|
||||
cERROR(1,
|
||||
("search entry %p began after end of SMB %p old entry %p",
|
||||
new_entry, end_of_smb, old_entry));
|
||||
return NULL;
|
||||
} else if(((level == SMB_FIND_FILE_INFO_STANDARD) &&
|
||||
} else if (((level == SMB_FIND_FILE_INFO_STANDARD) &&
|
||||
(new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb)) ||
|
||||
((level != SMB_FIND_FILE_INFO_STANDARD) &&
|
||||
(new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) {
|
||||
@ -546,39 +545,39 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
|
||||
char * filename = NULL;
|
||||
int len = 0;
|
||||
|
||||
if(cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
|
||||
if (cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
|
||||
FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
if(cfile->srch_inf.unicode) {
|
||||
if (cfile->srch_inf.unicode) {
|
||||
len = cifs_unicode_bytelen(filename);
|
||||
} else {
|
||||
/* BB should we make this strnlen of PATH_MAX? */
|
||||
len = strnlen(filename, 5);
|
||||
}
|
||||
} else if(cfile->srch_inf.info_level == SMB_FIND_FILE_DIRECTORY_INFO) {
|
||||
} else if (cfile->srch_inf.info_level == SMB_FIND_FILE_DIRECTORY_INFO) {
|
||||
FILE_DIRECTORY_INFO * pFindData =
|
||||
(FILE_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
} else if(cfile->srch_inf.info_level ==
|
||||
} else if (cfile->srch_inf.info_level ==
|
||||
SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
|
||||
FILE_FULL_DIRECTORY_INFO * pFindData =
|
||||
(FILE_FULL_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
} else if(cfile->srch_inf.info_level ==
|
||||
} else if (cfile->srch_inf.info_level ==
|
||||
SMB_FIND_FILE_ID_FULL_DIR_INFO) {
|
||||
SEARCH_ID_FULL_DIR_INFO * pFindData =
|
||||
(SEARCH_ID_FULL_DIR_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
} else if(cfile->srch_inf.info_level ==
|
||||
} else if (cfile->srch_inf.info_level ==
|
||||
SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
|
||||
FILE_BOTH_DIRECTORY_INFO * pFindData =
|
||||
(FILE_BOTH_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
} else if(cfile->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) {
|
||||
} else if (cfile->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) {
|
||||
FIND_FILE_STANDARD_INFO * pFindData =
|
||||
(FIND_FILE_STANDARD_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
@ -587,25 +586,25 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
|
||||
cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level));
|
||||
}
|
||||
|
||||
if(filename) {
|
||||
if(cfile->srch_inf.unicode) {
|
||||
if (filename) {
|
||||
if (cfile->srch_inf.unicode) {
|
||||
__le16 *ufilename = (__le16 *)filename;
|
||||
if(len == 2) {
|
||||
if (len == 2) {
|
||||
/* check for . */
|
||||
if(ufilename[0] == UNICODE_DOT)
|
||||
if (ufilename[0] == UNICODE_DOT)
|
||||
rc = 1;
|
||||
} else if(len == 4) {
|
||||
} else if (len == 4) {
|
||||
/* check for .. */
|
||||
if((ufilename[0] == UNICODE_DOT)
|
||||
if ((ufilename[0] == UNICODE_DOT)
|
||||
&&(ufilename[1] == UNICODE_DOT))
|
||||
rc = 2;
|
||||
}
|
||||
} else /* ASCII */ {
|
||||
if(len == 1) {
|
||||
if(filename[0] == '.')
|
||||
if (len == 1) {
|
||||
if (filename[0] == '.')
|
||||
rc = 1;
|
||||
} else if(len == 2) {
|
||||
if((filename[0] == '.') && (filename[1] == '.'))
|
||||
} else if (len == 2) {
|
||||
if((filename[0] == '.') && (filename[1] == '.'))
|
||||
rc = 2;
|
||||
}
|
||||
}
|
||||
@ -618,20 +617,10 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
|
||||
whether we can use the cached search results from the previous search */
|
||||
static int is_dir_changed(struct file * file)
|
||||
{
|
||||
struct inode * inode;
|
||||
struct cifsInodeInfo *cifsInfo;
|
||||
struct inode *inode = file->f_path.dentry->d_inode;
|
||||
struct cifsInodeInfo *cifsInfo = CIFS_I(inode);
|
||||
|
||||
if(file->f_path.dentry == NULL)
|
||||
return 0;
|
||||
|
||||
inode = file->f_path.dentry->d_inode;
|
||||
|
||||
if(inode == NULL)
|
||||
return 0;
|
||||
|
||||
cifsInfo = CIFS_I(inode);
|
||||
|
||||
if(cifsInfo->time == 0)
|
||||
if (cifsInfo->time == 0)
|
||||
return 1; /* directory was changed, perhaps due to unlink */
|
||||
else
|
||||
return 0;
|
||||
@ -654,7 +643,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
|
||||
struct cifsFileInfo * cifsFile = file->private_data;
|
||||
/* check if index in the buffer */
|
||||
|
||||
if((cifsFile == NULL) || (ppCurrentEntry == NULL) ||
|
||||
if ((cifsFile == NULL) || (ppCurrentEntry == NULL) ||
|
||||
(num_to_ret == NULL))
|
||||
return -ENOENT;
|
||||
|
||||
@ -672,7 +661,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
|
||||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
dump_cifs_file_struct(file, "In fce ");
|
||||
#endif
|
||||
if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) &&
|
||||
if (((index_to_find < cifsFile->srch_inf.index_of_last_entry) &&
|
||||
is_dir_changed(file)) ||
|
||||
(index_to_find < first_entry_in_buffer)) {
|
||||
/* close and restart search */
|
||||
@ -681,9 +670,9 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
|
||||
CIFSFindClose(xid, pTcon, cifsFile->netfid);
|
||||
kfree(cifsFile->search_resume_name);
|
||||
cifsFile->search_resume_name = NULL;
|
||||
if(cifsFile->srch_inf.ntwrk_buf_start) {
|
||||
if (cifsFile->srch_inf.ntwrk_buf_start) {
|
||||
cFYI(1,("freeing SMB ff cache buf on search rewind"));
|
||||
if(cifsFile->srch_inf.smallBuf)
|
||||
if (cifsFile->srch_inf.smallBuf)
|
||||
cifs_small_buf_release(cifsFile->srch_inf.
|
||||
ntwrk_buf_start);
|
||||
else
|
||||
@ -691,7 +680,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
|
||||
ntwrk_buf_start);
|
||||
}
|
||||
rc = initiate_cifs_search(xid,file);
|
||||
if(rc) {
|
||||
if (rc) {
|
||||
cFYI(1,("error %d reinitiating a search on rewind",rc));
|
||||
return rc;
|
||||
}
|
||||
@ -702,10 +691,10 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
|
||||
cFYI(1,("calling findnext2"));
|
||||
rc = CIFSFindNext(xid,pTcon,cifsFile->netfid,
|
||||
&cifsFile->srch_inf);
|
||||
if(rc)
|
||||
if (rc)
|
||||
return -ENOENT;
|
||||
}
|
||||
if(index_to_find < cifsFile->srch_inf.index_of_last_entry) {
|
||||
if (index_to_find < cifsFile->srch_inf.index_of_last_entry) {
|
||||
/* we found the buffer that contains the entry */
|
||||
/* scan and find it */
|
||||
int i;
|
||||
@ -851,9 +840,6 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
|
||||
if((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
|
||||
return -ENOENT;
|
||||
|
||||
if(file->f_path.dentry == NULL)
|
||||
return -ENOENT;
|
||||
|
||||
rc = cifs_entry_is_dot(pfindEntry,pCifsF);
|
||||
/* skip . and .. since we added them first */
|
||||
if(rc != 0)
|
||||
@ -997,11 +983,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
||||
|
||||
xid = GetXid();
|
||||
|
||||
if(file->f_path.dentry == NULL) {
|
||||
FreeXid(xid);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
||||
pTcon = cifs_sb->tcon;
|
||||
if(pTcon == NULL)
|
||||
|
Loading…
Reference in New Issue
Block a user