Commit 9468482b authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  [CIFS] on reconnect to Samba - reset the unix capabilities
  [CIFS] Allow update of EOF on remote extend of file
  [CIFS] POSIX CIFS Extensions (continued) - POSIX Open
  [CIFS] Additional POSIX CIFS Extensions infolevels
parents 551a10c7 8af18971
...@@ -1864,20 +1864,14 @@ config CIFS ...@@ -1864,20 +1864,14 @@ config CIFS
file servers such as Windows 2000 (including Windows 2003, NT 4 file servers such as Windows 2000 (including Windows 2003, NT 4
and Windows XP) as well by Samba (which provides excellent CIFS and Windows XP) as well by Samba (which provides excellent CIFS
server support for Linux and many other operating systems). Limited server support for Linux and many other operating systems). Limited
support for Windows ME and similar servers is provided as well. support for OS/2 and Windows ME and similar servers is provided as well.
You must use the smbfs client filesystem to access older SMB servers
such as OS/2 and DOS.
The intent of the cifs module is to provide an advanced The intent of the cifs module is to provide an advanced
network file system client for mounting to CIFS compliant servers, network file system client for mounting to CIFS compliant servers,
including support for dfs (hierarchical name space), secure per-user including support for dfs (hierarchical name space), secure per-user
session establishment, safe distributed caching (oplock), optional session establishment, safe distributed caching (oplock), optional
packet signing, Unicode and other internationalization improvements, packet signing, Unicode and other internationalization improvements.
and optional Winbind (nsswitch) integration. You do not need to enable If you need to mount to Samba or Windows from this machine, say Y.
cifs if running only a (Samba) server. It is possible to enable both
smbfs and cifs (e.g. if you are using CIFS for accessing Windows 2003
and Samba 3 servers, and smbfs for accessing old servers). If you need
to mount to Samba or Windows from this machine, say Y.
config CIFS_STATS config CIFS_STATS
bool "CIFS statistics" bool "CIFS statistics"
...@@ -1970,14 +1964,13 @@ config CIFS_EXPERIMENTAL ...@@ -1970,14 +1964,13 @@ config CIFS_EXPERIMENTAL
depends on CIFS && EXPERIMENTAL depends on CIFS && EXPERIMENTAL
help help
Enables cifs features under testing. These features are Enables cifs features under testing. These features are
experimental and currently include support for writepages experimental and currently include DFS support and directory
(multipage writebehind performance improvements) and directory change notification ie fcntl(F_DNOTIFY), as well as the upcall
change notification ie fcntl(F_DNOTIFY) as well as some security mechanism which will be used for Kerberos session negotiation
improvements. Some also depend on setting at runtime the and uid remapping. Some of these features also may depend on
pseudo-file /proc/fs/cifs/Experimental (which is disabled by setting a value of 1 to the pseudo-file /proc/fs/cifs/Experimental
default). See the file fs/cifs/README for more details. (which is disabled by default). See the file fs/cifs/README
for more details. If unsure, say N.
If unsure, say N.
config CIFS_UPCALL config CIFS_UPCALL
bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
......
Version 1.47 Version 1.47
------------ ------------
Fix oops in list_del during mount caused by unaligned string. Fix oops in list_del during mount caused by unaligned string.
Fix file corruption which could occur on some large file
copies caused by writepages page i/o completion bug.
Seek to SEEK_END forces check for update of file size for non-cached Seek to SEEK_END forces check for update of file size for non-cached
files. files. Allow file size to be updated on remote extend of locally open,
non-cached file. Fix reconnect to newer Samba servers (or other servers
which support the CIFS Unix/POSIX extensions) so that we again tell the
server the Unix/POSIX cifs capabilities which we support (SetFSInfo).
Add experimental support for new POSIX Open/Mkdir (which returns
stat information on the open, and allows setting the mode).
Version 1.46 Version 1.46
------------ ------------
......
...@@ -128,3 +128,11 @@ negotiated size) and send larger write sizes to modern servers. ...@@ -128,3 +128,11 @@ negotiated size) and send larger write sizes to modern servers.
4) More exhaustively test against less common servers. More testing 4) More exhaustively test against less common servers. More testing
against Windows 9x, Windows ME servers. 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
...@@ -100,5 +100,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); ...@@ -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 ssize_t cifs_listxattr(struct dentry *, char *, size_t);
extern int cifs_ioctl (struct inode * inode, struct file * filep, extern int cifs_ioctl (struct inode * inode, struct file * filep,
unsigned int command, unsigned long arg); unsigned int command, unsigned long arg);
#define CIFS_VERSION "1.47" #define CIFS_VERSION "1.48"
#endif /* _CIFSFS_H */ #endif /* _CIFSFS_H */
/* /*
* fs/cifs/cifspdu.h * fs/cifs/cifspdu.h
* *
* Copyright (c) International Business Machines Corp., 2002,2005 * Copyright (c) International Business Machines Corp., 2002,2007
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
...@@ -544,7 +544,8 @@ typedef union smb_com_session_setup_andx { ...@@ -544,7 +544,8 @@ typedef union smb_com_session_setup_andx {
/* unsigned char * NativeOS; */ /* unsigned char * NativeOS; */
/* unsigned char * NativeLanMan; */ /* unsigned char * NativeLanMan; */
/* unsigned char * PrimaryDomain; */ /* unsigned char * PrimaryDomain; */
} __attribute__((packed)) resp; /* NTLM response with or without extended sec*/ } __attribute__((packed)) resp; /* NTLM response
(with or without extended sec) */
struct { /* request format */ struct { /* request format */
struct smb_hdr hdr; /* wct = 10 */ struct smb_hdr hdr; /* wct = 10 */
...@@ -795,6 +796,8 @@ typedef struct smb_com_openx_rsp { ...@@ -795,6 +796,8 @@ typedef struct smb_com_openx_rsp {
__u16 ByteCount; __u16 ByteCount;
} __attribute__((packed)) OPENX_RSP; } __attribute__((packed)) OPENX_RSP;
/* For encoding of POSIX Open Request - see trans2 function 0x209 data struct */
/* Legacy write request for older servers */ /* Legacy write request for older servers */
typedef struct smb_com_writex_req { typedef struct smb_com_writex_req {
struct smb_hdr hdr; /* wct = 12 */ struct smb_hdr hdr; /* wct = 12 */
...@@ -1352,11 +1355,13 @@ struct smb_t2_rsp { ...@@ -1352,11 +1355,13 @@ struct smb_t2_rsp {
#define SMB_QUERY_FILE_UNIX_BASIC 0x200 #define SMB_QUERY_FILE_UNIX_BASIC 0x200
#define SMB_QUERY_FILE_UNIX_LINK 0x201 #define SMB_QUERY_FILE_UNIX_LINK 0x201
#define SMB_QUERY_POSIX_ACL 0x204 #define SMB_QUERY_POSIX_ACL 0x204
#define SMB_QUERY_XATTR 0x205 #define SMB_QUERY_XATTR 0x205 /* e.g. system EA name space */
#define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */ #define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */
#define SMB_QUERY_POSIX_PERMISSION 0x207 #define SMB_QUERY_POSIX_PERMISSION 0x207
#define SMB_QUERY_POSIX_LOCK 0x208 #define SMB_QUERY_POSIX_LOCK 0x208
/* #define SMB_POSIX_OPEN 0x209 */ /* #define SMB_POSIX_OPEN 0x209 */
/* #define SMB_POSIX_UNLINK 0x20a */
#define SMB_QUERY_FILE__UNIX_INFO2 0x20b
#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee #define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee
#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0 #define SMB_QUERY_FILE_ACCESS_INFO 0x3f0
#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */ #define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */
...@@ -1377,8 +1382,10 @@ struct smb_t2_rsp { ...@@ -1377,8 +1382,10 @@ struct smb_t2_rsp {
#define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */ #define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */
#define SMB_SET_POSIX_LOCK 0x208 #define SMB_SET_POSIX_LOCK 0x208
#define SMB_POSIX_OPEN 0x209 #define SMB_POSIX_OPEN 0x209
#define SMB_POSIX_UNLINK 0x20a
#define SMB_SET_FILE_UNIX_INFO2
#define SMB_SET_FILE_BASIC_INFO2 0x3ec #define SMB_SET_FILE_BASIC_INFO2 0x3ec
#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */ #define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo too */
#define SMB_FILE_ALL_INFO2 0x3fa #define SMB_FILE_ALL_INFO2 0x3fa
#define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb #define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb
#define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc #define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc
...@@ -1428,7 +1435,7 @@ typedef struct smb_com_transaction2_qpi_rsp { ...@@ -1428,7 +1435,7 @@ typedef struct smb_com_transaction2_qpi_rsp {
struct smb_hdr hdr; /* wct = 10 + SetupCount */ struct smb_hdr hdr; /* wct = 10 + SetupCount */
struct trans2_resp t2; struct trans2_resp t2;
__u16 ByteCount; __u16 ByteCount;
__u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ __u16 Reserved2; /* parameter word is present for infolevels > 100 */
} __attribute__((packed)) TRANSACTION2_QPI_RSP; } __attribute__((packed)) TRANSACTION2_QPI_RSP;
typedef struct smb_com_transaction2_spi_req { typedef struct smb_com_transaction2_spi_req {
...@@ -1461,7 +1468,7 @@ typedef struct smb_com_transaction2_spi_rsp { ...@@ -1461,7 +1468,7 @@ typedef struct smb_com_transaction2_spi_rsp {
struct smb_hdr hdr; /* wct = 10 + SetupCount */ struct smb_hdr hdr; /* wct = 10 + SetupCount */
struct trans2_resp t2; struct trans2_resp t2;
__u16 ByteCount; __u16 ByteCount;
__u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ __u16 Reserved2; /* parameter word is present for infolevels > 100 */
} __attribute__((packed)) TRANSACTION2_SPI_RSP; } __attribute__((packed)) TRANSACTION2_SPI_RSP;
struct set_file_rename { struct set_file_rename {
...@@ -1627,6 +1634,7 @@ typedef struct smb_com_transaction2_fnext_rsp_parms { ...@@ -1627,6 +1634,7 @@ typedef struct smb_com_transaction2_fnext_rsp_parms {
#define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105 #define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105
#define SMB_QUERY_CIFS_UNIX_INFO 0x200 #define SMB_QUERY_CIFS_UNIX_INFO 0x200
#define SMB_QUERY_POSIX_FS_INFO 0x201 #define SMB_QUERY_POSIX_FS_INFO 0x201
#define SMB_QUERY_POSIX_WHO_AM_I 0x202
#define SMB_QUERY_LABEL_INFO 0x3ea #define SMB_QUERY_LABEL_INFO 0x3ea
#define SMB_QUERY_FS_QUOTA_INFO 0x3ee #define SMB_QUERY_FS_QUOTA_INFO 0x3ee
#define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef #define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef
...@@ -1659,9 +1667,21 @@ typedef struct smb_com_transaction_qfsi_rsp { ...@@ -1659,9 +1667,21 @@ typedef struct smb_com_transaction_qfsi_rsp {
struct smb_hdr hdr; /* wct = 10 + SetupCount */ struct smb_hdr hdr; /* wct = 10 + SetupCount */
struct trans2_resp t2; struct trans2_resp t2;
__u16 ByteCount; __u16 ByteCount;
__u8 Pad; /* may be three bytes *//* followed by data area */ __u8 Pad; /* may be three bytes? *//* followed by data area */
} __attribute__((packed)) TRANSACTION2_QFSI_RSP; } __attribute__((packed)) TRANSACTION2_QFSI_RSP;
typedef struct whoami_rsp_data { /* Query level 0x202 */
__u32 flags; /* 0 = Authenticated user 1 = GUEST */
__u32 mask; /* which flags bits server understands ie 0x0001 */
__u64 unix_user_id;
__u64 unix_user_gid;
__u32 number_of_supplementary_gids; /* may be zero */
__u32 number_of_sids; /* may be zero */
__u32 length_of_sid_array; /* in bytes - may be zero */
__u32 pad; /* reserved - MBZ */
/* __u64 gid_array[0]; */ /* may be empty */
/* __u8 * psid_list */ /* may be empty */
} __attribute__((packed)) WHOAMI_RSP_DATA;
/* SETFSInfo Levels */ /* SETFSInfo Levels */
#define SMB_SET_CIFS_UNIX_INFO 0x200 #define SMB_SET_CIFS_UNIX_INFO 0x200
...@@ -1858,8 +1878,11 @@ typedef struct { ...@@ -1858,8 +1878,11 @@ typedef struct {
#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */ #define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */
#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */ #define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */
#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Allow POSIX path chars */ #define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Allow POSIX path chars */
#define CIFS_UNIX_POSIX_PATH_OPS_CAP 0x00000020 /* Allow new POSIX path based
calls including posix open
and posix unlink */
#ifdef CONFIG_CIFS_POSIX #ifdef CONFIG_CIFS_POSIX
#define CIFS_UNIX_CAP_MASK 0x0000001b #define CIFS_UNIX_CAP_MASK 0x0000003b
#else #else
#define CIFS_UNIX_CAP_MASK 0x00000013 #define CIFS_UNIX_CAP_MASK 0x00000013
#endif /* CONFIG_CIFS_POSIX */ #endif /* CONFIG_CIFS_POSIX */
...@@ -2075,6 +2098,19 @@ struct cifs_posix_acl { /* access conrol list (ACL) */ ...@@ -2075,6 +2098,19 @@ struct cifs_posix_acl { /* access conrol list (ACL) */
/* end of POSIX ACL definitions */ /* end of POSIX ACL definitions */
typedef struct {
__u32 OpenFlags; /* same as NT CreateX */
__u32 PosixOpenFlags;
__u32 Mode;
__u16 Level; /* reply level requested (see QPathInfo levels) */
__u16 Pad; /* reserved - MBZ */
} __attribute__((packed)) OPEN_PSX_REQ; /* level 0x209 SetPathInfo data */
typedef struct {
/* reply varies based on requested level */
} __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */
struct file_internal_info { struct file_internal_info {
__u64 UniqueId; /* inode number */ __u64 UniqueId; /* inode number */
} __attribute__((packed)); /* level 0x3ee */ } __attribute__((packed)); /* level 0x3ee */
...@@ -2238,7 +2274,8 @@ struct data_blob { ...@@ -2238,7 +2274,8 @@ struct data_blob {
1) PosixCreateX - to set and return the mode, inode#, device info and 1) PosixCreateX - to set and return the mode, inode#, device info and
perhaps add a CreateDevice - to create Pipes and other special .inodes perhaps add a CreateDevice - to create Pipes and other special .inodes
Also note POSIX open flags Also note POSIX open flags
2) Close - to return the last write time to do cache across close more safely 2) Close - to return the last write time to do cache across close
more safely
3) FindFirst return unique inode number - what about resume key, two 3) FindFirst return unique inode number - what about resume key, two
forms short (matches readdir) and full (enough info to cache inodes) forms short (matches readdir) and full (enough info to cache inodes)
4) Mkdir - set mode 4) Mkdir - set mode
...@@ -2273,7 +2310,8 @@ struct data_blob { ...@@ -2273,7 +2310,8 @@ struct data_blob {
TRANSACTION2 (18 cases) TRANSACTION2 (18 cases)
SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2 SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2
(BB verify that never need to set allocation size) (BB verify that never need to set allocation size)
SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via Unix ext?) SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via
Unix ext?)
COPY (note support for copy across directories) - FUTURE, OPTIONAL COPY (note support for copy across directories) - FUTURE, OPTIONAL
setting/getting OS/2 EAs - FUTURE (BB can this handle setting/getting OS/2 EAs - FUTURE (BB can this handle
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/nls.h> #include <linux/nls.h>
struct statfs; struct statfs;
struct smb_vol;
/* /*
***************************************************************** *****************************************************************
...@@ -57,7 +58,7 @@ extern int SendReceiveBlockingLock(const unsigned int /* xid */ , ...@@ -57,7 +58,7 @@ extern int SendReceiveBlockingLock(const unsigned int /* xid */ ,
int * /* bytes returned */); int * /* bytes returned */);
extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length); extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length);
extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *); extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *);
extern int is_size_safe_to_change(struct cifsInodeInfo *); extern int is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *); extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *);
extern unsigned int smbCalcSize(struct smb_hdr *ptr); extern unsigned int smbCalcSize(struct smb_hdr *ptr);
extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
...@@ -147,6 +148,8 @@ extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, ...@@ -147,6 +148,8 @@ extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
unsigned int *pnum_referrals, unsigned int *pnum_referrals,
unsigned char ** preferrals, unsigned char ** preferrals,
int remap); int remap);
extern void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
struct super_block * sb, struct smb_vol * vol);
extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
struct kstatfs *FSData); struct kstatfs *FSData);
extern int SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, extern int SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon,
......
...@@ -158,9 +158,15 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, ...@@ -158,9 +158,15 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
nls_codepage); nls_codepage);
if(!rc && (tcon->tidStatus == CifsNeedReconnect)) { if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
mark_open_files_invalid(tcon); mark_open_files_invalid(tcon);
rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon rc = CIFSTCon(0, tcon->ses, tcon->treeName,
, nls_codepage); tcon, nls_codepage);
up(&tcon->ses->sesSem); up(&tcon->ses->sesSem);
/* tell server which Unix caps we support */
if (tcon->ses->capabilities & CAP_UNIX)
reset_cifs_unix_caps(0 /* no xid */,
tcon,
NULL /* we do not know sb */,
NULL /* no vol info */);
/* BB FIXME add code to check if wsize needs /* BB FIXME add code to check if wsize needs
update due to negotiated smb buffer size update due to negotiated smb buffer size
shrinking */ shrinking */
...@@ -298,6 +304,12 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, ...@@ -298,6 +304,12 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
rc = CIFSTCon(0, tcon->ses, tcon->treeName, rc = CIFSTCon(0, tcon->ses, tcon->treeName,
tcon, nls_codepage); tcon, nls_codepage);
up(&tcon->ses->sesSem); up(&tcon->ses->sesSem);
/* tell server which Unix caps we support */
if (tcon->ses->capabilities & CAP_UNIX)
reset_cifs_unix_caps(0 /* no xid */,
tcon,
NULL /* do not know sb */,
NULL /* no vol info */);
/* BB FIXME add code to check if wsize needs /* BB FIXME add code to check if wsize needs
update due to negotiated smb buffer size update due to negotiated smb buffer size
shrinking */ shrinking */
......
...@@ -1613,6 +1613,76 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) ...@@ -1613,6 +1613,76 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
return rc; return rc;
} }
void reset_cifs_unix_caps(int xid, struct cifsTconInfo * tcon,
struct super_block * sb, struct smb_vol * vol_info)
{
/* if we are reconnecting then should we check to see if
* any requested capabilities changed locally e.g. via
* remount but we can not do much about it here
* if they have (even if we could detect it by the following)
* Perhaps we could add a backpointer to array of sb from tcon
* or if we change to make all sb to same share the same
* sb as NFS - then we only have one backpointer to sb.
* What if we wanted to mount the server share twice once with
* and once without posixacls or posix paths? */
__u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
/* check for reconnect case in which we do not
want to change the mount behavior if we can avoid it */
if(vol_info == NULL) {
/* turn off POSIX ACL and PATHNAMES if not set
originally at mount time */
if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0)
cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
}
cap &= CIFS_UNIX_CAP_MASK;
if(vol_info && vol_info->no_psx_acl)
cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
else if(CIFS_UNIX_POSIX_ACL_CAP & cap) {
cFYI(1,("negotiated posix acl support"));
if(sb)
sb->s_flags |= MS_POSIXACL;
}
if(vol_info && vol_info->posix_paths == 0)
cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
cFYI(1,("negotiate posix pathnames"));
if(sb)
CIFS_SB(sb)->mnt_cifs_flags |=
CIFS_MOUNT_POSIX_PATHS;
}
cFYI(1,("Negotiate caps 0x%x",(int)cap));
#ifdef CONFIG_CIFS_DEBUG2
if(cap & CIFS_UNIX_FCNTL_CAP)
cFYI(1,("FCNTL cap"));
if(cap & CIFS_UNIX_EXTATTR_CAP)
cFYI(1,("EXTATTR cap"));
if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
cFYI(1,("POSIX path cap"));
if(cap & CIFS_UNIX_XATTR_CAP)
cFYI(1,("XATTR cap"));
if(cap & CIFS_UNIX_POSIX_ACL_CAP)
cFYI(1,("POSIX ACL cap"));
#endif /* CIFS_DEBUG2 */
if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
cFYI(1,("setting capabilities failed"));
}
}
}
int int
cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
char *mount_data, const char *devname) char *mount_data, const char *devname)
...@@ -1928,9 +1998,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -1928,9 +1998,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
if (tcon == NULL) if (tcon == NULL)
rc = -ENOMEM; rc = -ENOMEM;
else { else {
/* check for null share name ie connect to dfs root */ /* check for null share name ie connecting to
* dfs root */
/* BB check if this works for exactly length three strings */ /* BB check if this works for exactly length
* three strings */
if ((strchr(volume_info.UNC + 3, '\\') == NULL) if ((strchr(volume_info.UNC + 3, '\\') == NULL)
&& (strchr(volume_info.UNC + 3, '/') == && (strchr(volume_info.UNC + 3, '/') ==
NULL)) { NULL)) {
...@@ -1942,6 +2014,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -1942,6 +2014,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
FreeXid(xid); FreeXid(xid);
return -ENODEV; return -ENODEV;
} else { } else {
/* BB Do we need to wrap sesSem around
* this TCon call and Unix SetFS as
* we do on SessSetup and reconnect? */
rc = CIFSTCon(xid, pSesInfo, rc = CIFSTCon(xid, pSesInfo,
volume_info.UNC, volume_info.UNC,
tcon, cifs_sb->local_nls); tcon, cifs_sb->local_nls);
...@@ -1962,6 +2037,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -1962,6 +2037,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */ sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
} }
/* BB FIXME fix time_gran to be larger for LANMAN sessions */
sb->s_time_gran = 100; sb->s_time_gran = 100;
/* on error free sesinfo and tcon struct if needed */ /* on error free sesinfo and tcon struct if needed */
...@@ -2007,44 +2083,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -2007,44 +2083,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
CIFSSMBQFSDeviceInfo(xid, tcon); CIFSSMBQFSDeviceInfo(xid, tcon);
CIFSSMBQFSAttributeInfo(xid, tcon); CIFSSMBQFSAttributeInfo(xid, tcon);
if (tcon->ses->capabilities & CAP_UNIX) { /* tell server which Unix caps we support */
if(!CIFSSMBQFSUnixInfo(xid, tcon)) { if (tcon->ses->capabilities & CAP_UNIX)
__u64 cap = reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
le64_to_cpu(tcon->fsUnixInfo.Capability);
cap &= CIFS_UNIX_CAP_MASK;
if(volume_info.no_psx_acl)
cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
else if(CIFS_UNIX_POSIX_ACL_CAP & cap) {
cFYI(1,("negotiated posix acl support"));
sb->s_flags |= MS_POSIXACL;
}
if(volume_info.posix_paths == 0)
cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
cFYI(1,("negotiate posix pathnames"));
cifs_sb->mnt_cifs_flags |=
CIFS_MOUNT_POSIX_PATHS;
}
cFYI(1,("Negotiate caps 0x%x",(int)cap));
#ifdef CONFIG_CIFS_DEBUG2
if(cap & CIFS_UNIX_FCNTL_CAP)
cFYI(1,("FCNTL cap"));
if(cap & CIFS_UNIX_EXTATTR_CAP)
cFYI(1,("EXTATTR cap"));
if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
cFYI(1,("POSIX path cap"));
if(cap & CIFS_UNIX_XATTR_CAP)
cFYI(1,("XATTR cap"));
if(cap & CIFS_UNIX_POSIX_ACL_CAP)
cFYI(1,("POSIX ACL cap"));
#endif /* CIFS_DEBUG2 */
if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
cFYI(1,("setting capabilities failed"));
}
}
}
if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X)) if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
cifs_sb->wsize = min(cifs_sb->wsize, cifs_sb->wsize = min(cifs_sb->wsize,
(tcon->ses->server->maxBuf - (tcon->ses->server->maxBuf -
......
...@@ -1954,7 +1954,7 @@ static int cifs_readpage(struct file *file, struct page *page) ...@@ -1954,7 +1954,7 @@ static int cifs_readpage(struct file *file, struct page *page)
refreshing the inode only on increases in the file size refreshing the inode only on increases in the file size
but this is tricky to do without racing with writebehind but this is tricky to do without racing with writebehind
page caching in the current Linux kernel design */ page caching in the current Linux kernel design */
int is_size_safe_to_change(struct cifsInodeInfo *cifsInode) int is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
{ {
struct cifsFileInfo *open_file = NULL; struct cifsFileInfo *open_file = NULL;
...@@ -1976,6 +1976,9 @@ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode) ...@@ -1976,6 +1976,9 @@ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
return 1; return 1;
} }
if(i_size_read(&cifsInode->vfs_inode) < end_of_file)
return 1;
return 0; return 0;
} else } else
return 1; return 1;
......
...@@ -140,7 +140,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, ...@@ -140,7 +140,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
inode->i_gid = le64_to_cpu(findData.Gid); inode->i_gid = le64_to_cpu(findData.Gid);
inode->i_nlink = le64_to_cpu(findData.Nlinks); inode->i_nlink = le64_to_cpu(findData.Nlinks);
if (is_size_safe_to_change(cifsInfo)) { if (is_size_safe_to_change(cifsInfo, end_of_file)) {
/* can not safely change the file size here if the /* can not safely change the file size here if the
client is writing to it due to potential races */ client is writing to it due to potential races */
...@@ -491,8 +491,8 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -491,8 +491,8 @@ int cifs_get_inode_info(struct inode **pinode,
/* BB add code here - /* BB add code here -
validate if device or weird share or device type? */ validate if device or weird share or device type? */
} }
if (is_size_safe_to_change(cifsInfo)) { if (is_size_safe_to_change(cifsInfo, le64_to_cpu(pfindData->EndOfFile))) {
/* can not safely change the file size here if the /* can not safely shrink the file size here if the
client is writing to it due to potential races */ client is writing to it due to potential races */
i_size_write(inode,le64_to_cpu(pfindData->EndOfFile)); i_size_write(inode,le64_to_cpu(pfindData->EndOfFile));
......
...@@ -222,7 +222,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, ...@@ -222,7 +222,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
atomic_set(&cifsInfo->inUse, 1); atomic_set(&cifsInfo->inUse, 1);
} }
if (is_size_safe_to_change(cifsInfo)) { if (is_size_safe_to_change(cifsInfo, end_of_file)) {
/* can not safely change the file size here if the /* can not safely change the file size here if the
client is writing to it due to potential races */ client is writing to it due to potential races */
i_size_write(tmp_inode, end_of_file); i_size_write(tmp_inode, end_of_file);
...@@ -351,10 +351,10 @@ static void unix_fill_in_inode(struct inode *tmp_inode, ...@@ -351,10 +351,10 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks); tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
if (is_size_safe_to_change(cifsInfo)) { if (is_size_safe_to_change(cifsInfo, end_of_file)) {
/* can not safely change the file size here if the /* can not safely change the file size here if the
client is writing to it due to potential races */ client is writing to it due to potential races */
i_size_write(tmp_inode,end_of_file); i_size_write(tmp_inode, end_of_file);
/* 512 bytes (2**9) is the fake blocksize that must be used */ /* 512 bytes (2**9) is the fake blocksize that must be used */
/* for this calculation, not the real blocksize */ /* for this calculation, not the real blocksize */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment