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
This commit is contained in:
commit
9468482bd4
11 changed files with 203 additions and 97 deletions
29
fs/Kconfig
29
fs/Kconfig
|
@ -1864,20 +1864,14 @@ config CIFS
|
|||
file servers such as Windows 2000 (including Windows 2003, NT 4
|
||||
and Windows XP) as well by Samba (which provides excellent CIFS
|
||||
server support for Linux and many other operating systems). Limited
|
||||
support for 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.
|
||||
support for OS/2 and Windows ME and similar servers is provided as well.
|
||||
|
||||
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
|
||||
session establishment, safe distributed caching (oplock), optional
|
||||
packet signing, Unicode and other internationalization improvements,
|
||||
and optional Winbind (nsswitch) integration. You do not need to enable
|
||||
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.
|
||||
packet signing, Unicode and other internationalization improvements.
|
||||
If you need to mount to Samba or Windows from this machine, say Y.
|
||||
|
||||
config CIFS_STATS
|
||||
bool "CIFS statistics"
|
||||
|
@ -1970,14 +1964,13 @@ config CIFS_EXPERIMENTAL
|
|||
depends on CIFS && EXPERIMENTAL
|
||||
help
|
||||
Enables cifs features under testing. These features are
|
||||
experimental and currently include support for writepages
|
||||
(multipage writebehind performance improvements) and directory
|
||||
change notification ie fcntl(F_DNOTIFY) as well as some security
|
||||
improvements. Some also depend on setting at runtime the
|
||||
pseudo-file /proc/fs/cifs/Experimental (which is disabled by
|
||||
default). See the file fs/cifs/README for more details.
|
||||
|
||||
If unsure, say N.
|
||||
experimental and currently include DFS support and directory
|
||||
change notification ie fcntl(F_DNOTIFY), as well as the upcall
|
||||
mechanism which will be used for Kerberos session negotiation
|
||||
and uid remapping. Some of these features also may depend on
|
||||
setting a value of 1 to the pseudo-file /proc/fs/cifs/Experimental
|
||||
(which is disabled by default). See the file fs/cifs/README
|
||||
for more details. If unsure, say N.
|
||||
|
||||
config CIFS_UPCALL
|
||||
bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
Version 1.47
|
||||
------------
|
||||
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
|
||||
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
|
||||
------------
|
||||
|
|
|
@ -128,3 +128,11 @@ 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
|
||||
|
|
|
@ -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.47"
|
||||
#define CIFS_VERSION "1.48"
|
||||
#endif /* _CIFSFS_H */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* 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)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
|
@ -544,7 +544,8 @@ typedef union smb_com_session_setup_andx {
|
|||
/* unsigned char * NativeOS; */
|
||||
/* unsigned char * NativeLanMan; */
|
||||
/* 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 smb_hdr hdr; /* wct = 10 */
|
||||
|
@ -795,6 +796,8 @@ typedef struct smb_com_openx_rsp {
|
|||
__u16 ByteCount;
|
||||
} __attribute__((packed)) OPENX_RSP;
|
||||
|
||||
/* For encoding of POSIX Open Request - see trans2 function 0x209 data struct */
|
||||
|
||||
/* Legacy write request for older servers */
|
||||
typedef struct smb_com_writex_req {
|
||||
struct smb_hdr hdr; /* wct = 12 */
|
||||
|
@ -1352,11 +1355,13 @@ struct smb_t2_rsp {
|
|||
#define SMB_QUERY_FILE_UNIX_BASIC 0x200
|
||||
#define SMB_QUERY_FILE_UNIX_LINK 0x201
|
||||
#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_POSIX_PERMISSION 0x207
|
||||
#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_ACCESS_INFO 0x3f0
|
||||
#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */
|
||||
|
@ -1377,8 +1382,10 @@ struct smb_t2_rsp {
|
|||
#define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */
|
||||
#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_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_SET_FILE_ALLOCATION_INFO2 0x3fb
|
||||
#define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc
|
||||
|
@ -1428,7 +1435,7 @@ typedef struct smb_com_transaction2_qpi_rsp {
|
|||
struct smb_hdr hdr; /* wct = 10 + SetupCount */
|
||||
struct trans2_resp t2;
|
||||
__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;
|
||||
|
||||
typedef struct smb_com_transaction2_spi_req {
|
||||
|
@ -1461,7 +1468,7 @@ typedef struct smb_com_transaction2_spi_rsp {
|
|||
struct smb_hdr hdr; /* wct = 10 + SetupCount */
|
||||
struct trans2_resp t2;
|
||||
__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;
|
||||
|
||||
struct set_file_rename {
|
||||
|
@ -1627,6 +1634,7 @@ typedef struct smb_com_transaction2_fnext_rsp_parms {
|
|||
#define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105
|
||||
#define SMB_QUERY_CIFS_UNIX_INFO 0x200
|
||||
#define SMB_QUERY_POSIX_FS_INFO 0x201
|
||||
#define SMB_QUERY_POSIX_WHO_AM_I 0x202
|
||||
#define SMB_QUERY_LABEL_INFO 0x3ea
|
||||
#define SMB_QUERY_FS_QUOTA_INFO 0x3ee
|
||||
#define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef
|
||||
|
@ -1659,9 +1667,21 @@ typedef struct smb_com_transaction_qfsi_rsp {
|
|||
struct smb_hdr hdr; /* wct = 10 + SetupCount */
|
||||
struct trans2_resp t2;
|
||||
__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;
|
||||
|
||||
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 */
|
||||
#define SMB_SET_CIFS_UNIX_INFO 0x200
|
||||
|
@ -1858,8 +1878,11 @@ typedef struct {
|
|||
#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */
|
||||
#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */
|
||||
#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
|
||||
#define CIFS_UNIX_CAP_MASK 0x0000001b
|
||||
#define CIFS_UNIX_CAP_MASK 0x0000003b
|
||||
#else
|
||||
#define CIFS_UNIX_CAP_MASK 0x00000013
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
|
@ -1946,7 +1969,7 @@ typedef struct { /* data block encoding of response to level 263 QPathInfo */
|
|||
__le32 AlignmentRequirement;
|
||||
__le32 FileNameLength;
|
||||
char FileName[1];
|
||||
} __attribute__((packed)) FILE_ALL_INFO; /* level 0x107 QPathInfo */
|
||||
} __attribute__((packed)) FILE_ALL_INFO; /* level 0x107 QPathInfo */
|
||||
|
||||
/* defines for enumerating possible values of the Unix type field below */
|
||||
#define UNIX_FILE 0
|
||||
|
@ -1970,11 +1993,11 @@ typedef struct {
|
|||
__u64 UniqueId;
|
||||
__le64 Permissions;
|
||||
__le64 Nlinks;
|
||||
} __attribute__((packed)) FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */
|
||||
} __attribute__((packed)) FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */
|
||||
|
||||
typedef struct {
|
||||
char LinkDest[1];
|
||||
} __attribute__((packed)) FILE_UNIX_LINK_INFO; /* level 0x201 QPathInfo */
|
||||
} __attribute__((packed)) FILE_UNIX_LINK_INFO; /* level 0x201 QPathInfo */
|
||||
|
||||
/* The following three structures are needed only for
|
||||
setting time to NT4 and some older servers via
|
||||
|
@ -2011,7 +2034,7 @@ typedef struct {
|
|||
__le64 ChangeTime;
|
||||
__le32 Attributes;
|
||||
__u32 Pad;
|
||||
} __attribute__((packed)) FILE_BASIC_INFO; /* size info, level 0x101 */
|
||||
} __attribute__((packed)) FILE_BASIC_INFO; /* size info, level 0x101 */
|
||||
|
||||
struct file_allocation_info {
|
||||
__le64 AllocationSize; /* Note old Samba srvr rounds this up too much */
|
||||
|
@ -2020,7 +2043,7 @@ struct file_allocation_info {
|
|||
|
||||
struct file_end_of_file_info {
|
||||
__le64 FileSize; /* offset to end of file */
|
||||
} __attribute__((packed)); /* size info, level 0x104 for set, 0x106 for query */
|
||||
} __attribute__((packed)); /* size info, level 0x104 for set, 0x106 for query */
|
||||
|
||||
struct file_alt_name_info {
|
||||
__u8 alt_name[1];
|
||||
|
@ -2075,6 +2098,19 @@ struct cifs_posix_acl { /* access conrol list (ACL) */
|
|||
|
||||
/* 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 {
|
||||
__u64 UniqueId; /* inode number */
|
||||
} __attribute__((packed)); /* level 0x3ee */
|
||||
|
@ -2238,7 +2274,8 @@ struct data_blob {
|
|||
1) PosixCreateX - to set and return the mode, inode#, device info and
|
||||
perhaps add a CreateDevice - to create Pipes and other special .inodes
|
||||
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
|
||||
forms short (matches readdir) and full (enough info to cache inodes)
|
||||
4) Mkdir - set mode
|
||||
|
@ -2273,7 +2310,8 @@ struct data_blob {
|
|||
TRANSACTION2 (18 cases)
|
||||
SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2
|
||||
(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
|
||||
setting/getting OS/2 EAs - FUTURE (BB can this handle
|
||||
|
@ -2293,13 +2331,13 @@ struct data_blob {
|
|||
T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields
|
||||
Actually need QUERY_FILE_UNIX_INFO since has inode num
|
||||
BB what about a) blksize/blkbits/blocks
|
||||
b) i_version
|
||||
c) i_rdev
|
||||
d) notify mask?
|
||||
e) generation
|
||||
f) size_seqcount
|
||||
b) i_version
|
||||
c) i_rdev
|
||||
d) notify mask?
|
||||
e) generation
|
||||
f) size_seqcount
|
||||
T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
|
||||
TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended
|
||||
TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended
|
||||
T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
|
||||
|
||||
|
||||
|
@ -2338,7 +2376,7 @@ typedef struct file_xattr_info {
|
|||
__u32 xattr_value_len;
|
||||
char xattr_name[0];
|
||||
/* followed by xattr_value[xattr_value_len], no pad */
|
||||
} __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute, info level 0x205 */
|
||||
} __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute, info level 0x205 */
|
||||
|
||||
|
||||
/* flags for chattr command */
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/nls.h>
|
||||
|
||||
struct statfs;
|
||||
struct smb_vol;
|
||||
|
||||
/*
|
||||
*****************************************************************
|
||||
|
@ -57,7 +58,7 @@ extern int SendReceiveBlockingLock(const unsigned int /* xid */ ,
|
|||
int * /* bytes returned */);
|
||||
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_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 unsigned int smbCalcSize(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,
|
|||
unsigned int *pnum_referrals,
|
||||
unsigned char ** preferrals,
|
||||
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,
|
||||
struct kstatfs *FSData);
|
||||
extern int SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon,
|
||||
|
|
|
@ -158,9 +158,15 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
|
|||
nls_codepage);
|
||||
if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
|
||||
mark_open_files_invalid(tcon);
|
||||
rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
|
||||
, nls_codepage);
|
||||
rc = CIFSTCon(0, tcon->ses, tcon->treeName,
|
||||
tcon, nls_codepage);
|
||||
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
|
||||
update due to negotiated smb buffer size
|
||||
shrinking */
|
||||
|
@ -298,6 +304,12 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
|
|||
rc = CIFSTCon(0, tcon->ses, tcon->treeName,
|
||||
tcon, nls_codepage);
|
||||
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
|
||||
update due to negotiated smb buffer size
|
||||
shrinking */
|
||||
|
|
|
@ -1613,6 +1613,76 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
|
|||
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
|
||||
cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||
char *mount_data, const char *devname)
|
||||
|
@ -1928,20 +1998,25 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|||
if (tcon == NULL)
|
||||
rc = -ENOMEM;
|
||||
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)
|
||||
&& (strchr(volume_info.UNC + 3, '/') ==
|
||||
NULL)) {
|
||||
rc = connect_to_dfs_path(xid, pSesInfo,
|
||||
"", cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
"", cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
kfree(volume_info.UNC);
|
||||
FreeXid(xid);
|
||||
return -ENODEV;
|
||||
} 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,
|
||||
volume_info.UNC,
|
||||
tcon, cifs_sb->local_nls);
|
||||
|
@ -1962,6 +2037,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|||
sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
|
||||
}
|
||||
|
||||
/* BB FIXME fix time_gran to be larger for LANMAN sessions */
|
||||
sb->s_time_gran = 100;
|
||||
|
||||
/* on error free sesinfo and tcon struct if needed */
|
||||
|
@ -2006,45 +2082,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|||
/* do not care if following two calls succeed - informational */
|
||||
CIFSSMBQFSDeviceInfo(xid, tcon);
|
||||
CIFSSMBQFSAttributeInfo(xid, tcon);
|
||||
|
||||
if (tcon->ses->capabilities & CAP_UNIX) {
|
||||
if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
|
||||
__u64 cap =
|
||||
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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* tell server which Unix caps we support */
|
||||
if (tcon->ses->capabilities & CAP_UNIX)
|
||||
reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
|
||||
|
||||
if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
|
||||
cifs_sb->wsize = min(cifs_sb->wsize,
|
||||
(tcon->ses->server->maxBuf -
|
||||
|
|
|
@ -1954,7 +1954,7 @@ static int cifs_readpage(struct file *file, struct page *page)
|
|||
refreshing the inode only on increases in the file size
|
||||
but this is tricky to do without racing with writebehind
|
||||
page caching in the current Linux kernel design */
|
||||
int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
|
||||
int is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
|
||||
{
|
||||
struct cifsFileInfo *open_file = NULL;
|
||||
|
||||
|
@ -1976,6 +1976,9 @@ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if(i_size_read(&cifsInode->vfs_inode) < end_of_file)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
|
|
|
@ -140,7 +140,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
|||
inode->i_gid = le64_to_cpu(findData.Gid);
|
||||
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
|
||||
client is writing to it due to potential races */
|
||||
|
||||
|
@ -491,8 +491,8 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||
/* BB add code here -
|
||||
validate if device or weird share or device type? */
|
||||
}
|
||||
if (is_size_safe_to_change(cifsInfo)) {
|
||||
/* can not safely change the file size here if the
|
||||
if (is_size_safe_to_change(cifsInfo, le64_to_cpu(pfindData->EndOfFile))) {
|
||||
/* can not safely shrink the file size here if the
|
||||
client is writing to it due to potential races */
|
||||
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,
|
|||
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
|
||||
client is writing to it due to potential races */
|
||||
i_size_write(tmp_inode, end_of_file);
|
||||
|
@ -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_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
|
||||
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 */
|
||||
/* for this calculation, not the real blocksize */
|
||||
|
|
Loading…
Reference in a new issue