aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-03-26 18:46:37 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-03-26 18:46:37 -0400
commit39f15003c7b268e4199d5ddce60a6944a74a14b7 (patch)
tree47d4513321aa16bcdc608619390f4f5dbf1d1e5e /fs
parent7676b8fd701beb47cc1b4cc291acaa07287ea69a (diff)
parentb363b3304bcf68c4541683b2eff70b29f0446a5b (diff)
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 memory overwrite when saving nativeFileSystem field during mount [CIFS] Rename compose_mount_options to cifs_compose_mount_options. [CIFS] work around bug in Samba server handling for posix open [CIFS] Use posix open on file open when server supports it cifs: fix buffer format byte on NT Rename/hardlink [CIFS] Add definitions for remoteably fsctl calls [CIFS] add extra null attr check [CIFS] fix build error [CIFS] reopen file via newer posix open protocol operation if available [CIFS] Add new nostrictsync cifs mount option to avoid slow SMB flush [CIFS] DFS no longer experimental [CIFS] Send SMB flush in cifs_fsync
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/CHANGES11
-rw-r--r--fs/cifs/Kconfig21
-rw-r--r--fs/cifs/README22
-rw-r--r--fs/cifs/cifs_debug.c2
-rw-r--r--fs/cifs/cifs_dfs_ref.c36
-rw-r--r--fs/cifs/cifs_fs_sb.h1
-rw-r--r--fs/cifs/cifsglob.h2
-rw-r--r--fs/cifs/cifspdu.h76
-rw-r--r--fs/cifs/cifsproto.h9
-rw-r--r--fs/cifs/cifssmb.c27
-rw-r--r--fs/cifs/connect.c9
-rw-r--r--fs/cifs/dir.c6
-rw-r--r--fs/cifs/file.c199
-rw-r--r--fs/cifs/inode.c3
-rw-r--r--fs/cifs/smbfsctl.h84
15 files changed, 397 insertions, 111 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 851388fafc73..65984006192c 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -6,7 +6,16 @@ the server to treat subsequent connections, especially those that
6are authenticated as guest, as reconnections, invalidating the earlier 6are authenticated as guest, as reconnections, invalidating the earlier
7user's smb session. This fix allows cifs to mount multiple times to the 7user's smb session. This fix allows cifs to mount multiple times to the
8same server with different userids without risking invalidating earlier 8same server with different userids without risking invalidating earlier
9established security contexts. 9established security contexts. fsync now sends SMB Flush operation
10to better ensure that we wait for server to write all of the data to
11server disk (not just write it over the network). Add new mount
12parameter to allow user to disable sending the (slow) SMB flush on
13fsync if desired (fsync still flushes all cached write data to the server).
14Posix file open support added (turned off after one attempt if server
15fails to support it properly, as with Samba server versions prior to 3.3.2)
16Fix "redzone overwritten" bug in cifs_put_tcon (CIFSTcon may allocate too
17little memory for the "nativeFileSystem" field returned by the server
18during mount).
10 19
11Version 1.56 20Version 1.56
12------------ 21------------
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig
index 341a98965bd0..6994a0f54f02 100644
--- a/fs/cifs/Kconfig
+++ b/fs/cifs/Kconfig
@@ -118,6 +118,18 @@ config CIFS_DEBUG2
118 option can be turned off unless you are debugging 118 option can be turned off unless you are debugging
119 cifs problems. If unsure, say N. 119 cifs problems. If unsure, say N.
120 120
121config CIFS_DFS_UPCALL
122 bool "DFS feature support"
123 depends on CIFS && KEYS
124 help
125 Distributed File System (DFS) support is used to access shares
126 transparently in an enterprise name space, even if the share
127 moves to a different server. This feature also enables
128 an upcall mechanism for CIFS which contacts userspace helper
129 utilities to provide server name resolution (host names to
130 IP addresses) which is needed for implicit mounts of DFS junction
131 points. If unsure, say N.
132
121config CIFS_EXPERIMENTAL 133config CIFS_EXPERIMENTAL
122 bool "CIFS Experimental Features (EXPERIMENTAL)" 134 bool "CIFS Experimental Features (EXPERIMENTAL)"
123 depends on CIFS && EXPERIMENTAL 135 depends on CIFS && EXPERIMENTAL
@@ -131,12 +143,3 @@ config CIFS_EXPERIMENTAL
131 (which is disabled by default). See the file fs/cifs/README 143 (which is disabled by default). See the file fs/cifs/README
132 for more details. If unsure, say N. 144 for more details. If unsure, say N.
133 145
134config CIFS_DFS_UPCALL
135 bool "DFS feature support (EXPERIMENTAL)"
136 depends on CIFS_EXPERIMENTAL
137 depends on KEYS
138 help
139 Enables an upcall mechanism for CIFS which contacts userspace
140 helper utilities to provide server name resolution (host names to
141 IP addresses) which is needed for implicit mounts of DFS junction
142 points. If unsure, say N.
diff --git a/fs/cifs/README b/fs/cifs/README
index da4515e3be20..07434181623b 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -472,6 +472,19 @@ A partial list of the supported mount options follows:
472 even if the cifs server would support posix advisory locks. 472 even if the cifs server would support posix advisory locks.
473 "forcemand" is accepted as a shorter form of this mount 473 "forcemand" is accepted as a shorter form of this mount
474 option. 474 option.
475 nostrictsync If this mount option is set, when an application does an
476 fsync call then the cifs client does not send an SMB Flush
477 to the server (to force the server to write all dirty data
478 for this file immediately to disk), although cifs still sends
479 all dirty (cached) file data to the server and waits for the
480 server to respond to the write. Since SMB Flush can be
481 very slow, and some servers may be reliable enough (to risk
482 delaying slightly flushing the data to disk on the server),
483 turning on this option may be useful to improve performance for
484 applications that fsync too much, at a small risk of server
485 crash. If this mount option is not set, by default cifs will
486 send an SMB flush request (and wait for a response) on every
487 fsync call.
475 nodfs Disable DFS (global name space support) even if the 488 nodfs Disable DFS (global name space support) even if the
476 server claims to support it. This can help work around 489 server claims to support it. This can help work around
477 a problem with parsing of DFS paths with Samba server 490 a problem with parsing of DFS paths with Samba server
@@ -692,13 +705,14 @@ require this helper. Note that NTLMv2 security (which does not require the
692cifs.upcall helper program), instead of using Kerberos, is sufficient for 705cifs.upcall helper program), instead of using Kerberos, is sufficient for
693some use cases. 706some use cases.
694 707
695Enabling DFS support (used to access shares transparently in an MS-DFS 708DFS support allows transparent redirection to shares in an MS-DFS name space.
696global name space) requires that CONFIG_CIFS_EXPERIMENTAL be enabled. In 709In addition, DFS support for target shares which are specified as UNC
697addition, DFS support for target shares which are specified as UNC
698names which begin with host names (rather than IP addresses) requires 710names which begin with host names (rather than IP addresses) requires
699a user space helper (such as cifs.upcall) to be present in order to 711a user space helper (such as cifs.upcall) to be present in order to
700translate host names to ip address, and the user space helper must also 712translate host names to ip address, and the user space helper must also
701be configured in the file /etc/request-key.conf 713be configured in the file /etc/request-key.conf. Samba, Windows servers and
714many NAS appliances support DFS as a way of constructing a global name
715space to ease network configuration and improve reliability.
702 716
703To use cifs Kerberos and DFS support, the Linux keyutils package should be 717To use cifs Kerberos and DFS support, the Linux keyutils package should be
704installed and something like the following lines should be added to the 718installed and something like the following lines should be added to the
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 490e34bbf27a..877e4d9a1159 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -340,6 +340,8 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v)
340 seq_printf(m, "\nWrites: %d Bytes: %lld", 340 seq_printf(m, "\nWrites: %d Bytes: %lld",
341 atomic_read(&tcon->num_writes), 341 atomic_read(&tcon->num_writes),
342 (long long)(tcon->bytes_written)); 342 (long long)(tcon->bytes_written));
343 seq_printf(m, "\nFlushes: %d",
344 atomic_read(&tcon->num_flushes));
343 seq_printf(m, "\nLocks: %d HardLinks: %d " 345 seq_printf(m, "\nLocks: %d HardLinks: %d "
344 "Symlinks: %d", 346 "Symlinks: %d",
345 atomic_read(&tcon->num_locks), 347 atomic_read(&tcon->num_locks),
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index 85c0a74d034d..5fdbf8a14472 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -104,9 +104,9 @@ static char *cifs_get_share_name(const char *node_name)
104 104
105 105
106/** 106/**
107 * compose_mount_options - creates mount options for refferral 107 * cifs_compose_mount_options - creates mount options for refferral
108 * @sb_mountdata: parent/root DFS mount options (template) 108 * @sb_mountdata: parent/root DFS mount options (template)
109 * @dentry: point where we are going to mount 109 * @fullpath: full path in UNC format
110 * @ref: server's referral 110 * @ref: server's referral
111 * @devname: pointer for saving device name 111 * @devname: pointer for saving device name
112 * 112 *
@@ -116,8 +116,8 @@ static char *cifs_get_share_name(const char *node_name)
116 * Returns: pointer to new mount options or ERR_PTR. 116 * Returns: pointer to new mount options or ERR_PTR.
117 * Caller is responcible for freeing retunrned value if it is not error. 117 * Caller is responcible for freeing retunrned value if it is not error.
118 */ 118 */
119static char *compose_mount_options(const char *sb_mountdata, 119char *cifs_compose_mount_options(const char *sb_mountdata,
120 struct dentry *dentry, 120 const char *fullpath,
121 const struct dfs_info3_param *ref, 121 const struct dfs_info3_param *ref,
122 char **devname) 122 char **devname)
123{ 123{
@@ -128,7 +128,6 @@ static char *compose_mount_options(const char *sb_mountdata,
128 char *srvIP = NULL; 128 char *srvIP = NULL;
129 char sep = ','; 129 char sep = ',';
130 int off, noff; 130 int off, noff;
131 char *fullpath;
132 131
133 if (sb_mountdata == NULL) 132 if (sb_mountdata == NULL)
134 return ERR_PTR(-EINVAL); 133 return ERR_PTR(-EINVAL);
@@ -202,17 +201,6 @@ static char *compose_mount_options(const char *sb_mountdata,
202 goto compose_mount_options_err; 201 goto compose_mount_options_err;
203 } 202 }
204 203
205 /*
206 * this function gives us a path with a double backslash prefix. We
207 * require a single backslash for DFS. Temporarily increment fullpath
208 * to put it in the proper form and decrement before freeing it.
209 */
210 fullpath = build_path_from_dentry(dentry);
211 if (!fullpath) {
212 rc = -ENOMEM;
213 goto compose_mount_options_err;
214 }
215 ++fullpath;
216 tkn_e = strchr(tkn_e + 1, '\\'); 204 tkn_e = strchr(tkn_e + 1, '\\');
217 if (tkn_e || (strlen(fullpath) - ref->path_consumed)) { 205 if (tkn_e || (strlen(fullpath) - ref->path_consumed)) {
218 strncat(mountdata, &sep, 1); 206 strncat(mountdata, &sep, 1);
@@ -221,8 +209,6 @@ static char *compose_mount_options(const char *sb_mountdata,
221 strcat(mountdata, tkn_e + 1); 209 strcat(mountdata, tkn_e + 1);
222 strcat(mountdata, fullpath + ref->path_consumed); 210 strcat(mountdata, fullpath + ref->path_consumed);
223 } 211 }
224 --fullpath;
225 kfree(fullpath);
226 212
227 /*cFYI(1,("%s: parent mountdata: %s", __func__,sb_mountdata));*/ 213 /*cFYI(1,("%s: parent mountdata: %s", __func__,sb_mountdata));*/
228 /*cFYI(1, ("%s: submount mountdata: %s", __func__, mountdata ));*/ 214 /*cFYI(1, ("%s: submount mountdata: %s", __func__, mountdata ));*/
@@ -245,10 +231,20 @@ static struct vfsmount *cifs_dfs_do_refmount(const struct vfsmount *mnt_parent,
245 struct vfsmount *mnt; 231 struct vfsmount *mnt;
246 char *mountdata; 232 char *mountdata;
247 char *devname = NULL; 233 char *devname = NULL;
234 char *fullpath;
248 235
249 cifs_sb = CIFS_SB(dentry->d_inode->i_sb); 236 cifs_sb = CIFS_SB(dentry->d_inode->i_sb);
250 mountdata = compose_mount_options(cifs_sb->mountdata, 237 /*
251 dentry, ref, &devname); 238 * this function gives us a path with a double backslash prefix. We
239 * require a single backslash for DFS.
240 */
241 fullpath = build_path_from_dentry(dentry);
242 if (!fullpath)
243 return ERR_PTR(-ENOMEM);
244
245 mountdata = cifs_compose_mount_options(cifs_sb->mountdata,
246 fullpath + 1, ref, &devname);
247 kfree(fullpath);
252 248
253 if (IS_ERR(mountdata)) 249 if (IS_ERR(mountdata))
254 return (struct vfsmount *)mountdata; 250 return (struct vfsmount *)mountdata;
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index c4c306f7b06f..4797787c6a44 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -32,6 +32,7 @@
32#define CIFS_MOUNT_OVERR_GID 0x800 /* override gid returned from server */ 32#define CIFS_MOUNT_OVERR_GID 0x800 /* override gid returned from server */
33#define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */ 33#define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */
34#define CIFS_MOUNT_NOPOSIXBRL 0x2000 /* mandatory not posix byte range lock */ 34#define CIFS_MOUNT_NOPOSIXBRL 0x2000 /* mandatory not posix byte range lock */
35#define CIFS_MOUNT_NOSSYNC 0x4000 /* don't do slow SMBflush on every sync*/
35 36
36struct cifs_sb_info { 37struct cifs_sb_info {
37 struct cifsTconInfo *tcon; /* primary mount */ 38 struct cifsTconInfo *tcon; /* primary mount */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index e004f6db5fc8..9fbf4dff5da6 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -254,6 +254,7 @@ struct cifsTconInfo {
254 atomic_t num_smbs_sent; 254 atomic_t num_smbs_sent;
255 atomic_t num_writes; 255 atomic_t num_writes;
256 atomic_t num_reads; 256 atomic_t num_reads;
257 atomic_t num_flushes;
257 atomic_t num_oplock_brks; 258 atomic_t num_oplock_brks;
258 atomic_t num_opens; 259 atomic_t num_opens;
259 atomic_t num_closes; 260 atomic_t num_closes;
@@ -298,6 +299,7 @@ struct cifsTconInfo {
298 bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol 299 bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol
299 for this mount even if server would support */ 300 for this mount even if server would support */
300 bool local_lease:1; /* check leases (only) on local system not remote */ 301 bool local_lease:1; /* check leases (only) on local system not remote */
302 bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */
301 bool need_reconnect:1; /* connection reset, tid now invalid */ 303 bool need_reconnect:1; /* connection reset, tid now invalid */
302 /* BB add field for back pointer to sb struct(s)? */ 304 /* BB add field for back pointer to sb struct(s)? */
303}; 305};
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index b4e2e9f0ee3d..b370489c8da5 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifspdu.h 2 * fs/cifs/cifspdu.h
3 * 3 *
4 * Copyright (c) International Business Machines Corp., 2002,2008 4 * Copyright (c) International Business Machines Corp., 2002,2009
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -23,6 +23,7 @@
23#define _CIFSPDU_H 23#define _CIFSPDU_H
24 24
25#include <net/sock.h> 25#include <net/sock.h>
26#include "smbfsctl.h"
26 27
27#ifdef CONFIG_CIFS_WEAK_PW_HASH 28#ifdef CONFIG_CIFS_WEAK_PW_HASH
28#define LANMAN_PROT 0 29#define LANMAN_PROT 0
@@ -34,15 +35,15 @@
34#define POSIX_PROT (CIFS_PROT+1) 35#define POSIX_PROT (CIFS_PROT+1)
35#define BAD_PROT 0xFFFF 36#define BAD_PROT 0xFFFF
36 37
37/* SMB command codes */ 38/* SMB command codes:
38/* 39 * Note some commands have minimal (wct=0,bcc=0), or uninteresting, responses
39 * Some commands have minimal (wct=0,bcc=0), or uninteresting, responses
40 * (ie which include no useful data other than the SMB error code itself). 40 * (ie which include no useful data other than the SMB error code itself).
41 * Knowing this helps avoid response buffer allocations and copy in some cases 41 * This can allow us to avoid response buffer allocations and copy in some cases
42 */ 42 */
43#define SMB_COM_CREATE_DIRECTORY 0x00 /* trivial response */ 43#define SMB_COM_CREATE_DIRECTORY 0x00 /* trivial response */
44#define SMB_COM_DELETE_DIRECTORY 0x01 /* trivial response */ 44#define SMB_COM_DELETE_DIRECTORY 0x01 /* trivial response */
45#define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */ 45#define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */
46#define SMB_COM_FLUSH 0x05 /* triv req/rsp */
46#define SMB_COM_DELETE 0x06 /* trivial response */ 47#define SMB_COM_DELETE 0x06 /* trivial response */
47#define SMB_COM_RENAME 0x07 /* trivial response */ 48#define SMB_COM_RENAME 0x07 /* trivial response */
48#define SMB_COM_QUERY_INFORMATION 0x08 /* aka getattr */ 49#define SMB_COM_QUERY_INFORMATION 0x08 /* aka getattr */
@@ -790,6 +791,12 @@ typedef struct smb_com_close_rsp {
790 __u16 ByteCount; /* bct = 0 */ 791 __u16 ByteCount; /* bct = 0 */
791} __attribute__((packed)) CLOSE_RSP; 792} __attribute__((packed)) CLOSE_RSP;
792 793
794typedef struct smb_com_flush_req {
795 struct smb_hdr hdr; /* wct = 1 */
796 __u16 FileID;
797 __u16 ByteCount; /* 0 */
798} __attribute__((packed)) FLUSH_REQ;
799
793typedef struct smb_com_findclose_req { 800typedef struct smb_com_findclose_req {
794 struct smb_hdr hdr; /* wct = 1 */ 801 struct smb_hdr hdr; /* wct = 1 */
795 __u16 FileID; 802 __u16 FileID;
@@ -1924,19 +1931,19 @@ typedef struct smb_com_transaction2_get_dfs_refer_req {
1924#define DFS_TYPE_ROOT 0x0001 1931#define DFS_TYPE_ROOT 0x0001
1925 1932
1926/* Referral Entry Flags */ 1933/* Referral Entry Flags */
1927#define DFS_NAME_LIST_REF 0x0200 1934#define DFS_NAME_LIST_REF 0x0200 /* set for domain or DC referral responses */
1935#define DFS_TARGET_SET_BOUNDARY 0x0400 /* only valid with version 4 dfs req */
1928 1936
1929typedef struct dfs_referral_level_3 { 1937typedef struct dfs_referral_level_3 { /* version 4 is same, + one flag bit */
1930 __le16 VersionNumber; 1938 __le16 VersionNumber; /* must be 3 or 4 */
1931 __le16 Size; 1939 __le16 Size;
1932 __le16 ServerType; /* 0x0001 = root targets; 0x0000 = link targets */ 1940 __le16 ServerType; /* 0x0001 = root targets; 0x0000 = link targets */
1933 __le16 ReferralEntryFlags; /* 0x0200 bit set only for domain 1941 __le16 ReferralEntryFlags;
1934 or DC referral responce */
1935 __le32 TimeToLive; 1942 __le32 TimeToLive;
1936 __le16 DfsPathOffset; 1943 __le16 DfsPathOffset;
1937 __le16 DfsAlternatePathOffset; 1944 __le16 DfsAlternatePathOffset;
1938 __le16 NetworkAddressOffset; /* offset of the link target */ 1945 __le16 NetworkAddressOffset; /* offset of the link target */
1939 __le16 ServiceSiteGuid; 1946 __u8 ServiceSiteGuid[16]; /* MBZ, ignored */
1940} __attribute__((packed)) REFERRAL3; 1947} __attribute__((packed)) REFERRAL3;
1941 1948
1942typedef struct smb_com_transaction_get_dfs_refer_rsp { 1949typedef struct smb_com_transaction_get_dfs_refer_rsp {
@@ -1946,48 +1953,15 @@ typedef struct smb_com_transaction_get_dfs_refer_rsp {
1946 __u8 Pad; 1953 __u8 Pad;
1947 __le16 PathConsumed; 1954 __le16 PathConsumed;
1948 __le16 NumberOfReferrals; 1955 __le16 NumberOfReferrals;
1949 __le16 DFSFlags; 1956 __le32 DFSFlags;
1950 __u16 Pad2;
1951 REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */ 1957 REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */
1952 /* followed by the strings pointed to by the referral structures */ 1958 /* followed by the strings pointed to by the referral structures */
1953} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_RSP; 1959} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_RSP;
1954 1960
1955/* DFS Flags */ 1961/* DFS Flags */
1956#define DFSREF_REFERRAL_SERVER 0x0001 1962#define DFSREF_REFERRAL_SERVER 0x00000001 /* all targets are DFS roots */
1957#define DFSREF_STORAGE_SERVER 0x0002 1963#define DFSREF_STORAGE_SERVER 0x00000002 /* no further ref requests needed */
1958 1964#define DFSREF_TARGET_FAILBACK 0x00000004 /* only for DFS referral version 4 */
1959/* IOCTL information */
1960/*
1961 * List of ioctl function codes that look to be of interest to remote clients
1962 * like this one. Need to do some experimentation to make sure they all work
1963 * remotely. Some of the following, such as the encryption/compression ones
1964 * would be invoked from tools via a specialized hook into the VFS rather
1965 * than via the standard vfs entry points
1966 */
1967#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
1968#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
1969#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008
1970#define FSCTL_LOCK_VOLUME 0x00090018
1971#define FSCTL_UNLOCK_VOLUME 0x0009001C
1972#define FSCTL_GET_COMPRESSION 0x0009003C
1973#define FSCTL_SET_COMPRESSION 0x0009C040
1974#define FSCTL_REQUEST_FILTER_OPLOCK 0x0009008C
1975#define FSCTL_FILESYS_GET_STATISTICS 0x00090090
1976#define FSCTL_SET_REPARSE_POINT 0x000900A4
1977#define FSCTL_GET_REPARSE_POINT 0x000900A8
1978#define FSCTL_DELETE_REPARSE_POINT 0x000900AC
1979#define FSCTL_SET_SPARSE 0x000900C4
1980#define FSCTL_SET_ZERO_DATA 0x000900C8
1981#define FSCTL_SET_ENCRYPTION 0x000900D7
1982#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB
1983#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF
1984#define FSCTL_READ_RAW_ENCRYPTED 0x000900E3
1985#define FSCTL_SIS_COPYFILE 0x00090100
1986#define FSCTL_SIS_LINK_FILES 0x0009C104
1987
1988#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003
1989#define IO_REPARSE_TAG_HSM 0xC0000004
1990#define IO_REPARSE_TAG_SIS 0x80000007
1991 1965
1992/* 1966/*
1993 ************************************************************************ 1967 ************************************************************************
@@ -2508,8 +2482,6 @@ struct data_blob {
2508 6) Use nanosecond timestamps throughout all time fields if 2482 6) Use nanosecond timestamps throughout all time fields if
2509 corresponding attribute flag is set 2483 corresponding attribute flag is set
2510 7) sendfile - handle based copy 2484 7) sendfile - handle based copy
2511 8) Direct i/o
2512 9) Misc fcntls?
2513 2485
2514 what about fixing 64 bit alignment 2486 what about fixing 64 bit alignment
2515 2487
@@ -2628,7 +2600,5 @@ typedef struct file_chattr_info {
2628 __le64 mode; /* list of actual attribute bits on this inode */ 2600 __le64 mode; /* list of actual attribute bits on this inode */
2629} __attribute__((packed)) FILE_CHATTR_INFO; /* ext attributes 2601} __attribute__((packed)) FILE_CHATTR_INFO; /* ext attributes
2630 (chattr, chflags) level 0x206 */ 2602 (chattr, chflags) level 0x206 */
2631 2603#endif /* POSIX */
2632#endif
2633
2634#endif /* _CIFSPDU_H */ 2604#endif /* _CIFSPDU_H */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 083dfc57c7a3..4167716d32f2 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -44,6 +44,9 @@ extern void _FreeXid(unsigned int);
44extern char *build_path_from_dentry(struct dentry *); 44extern char *build_path_from_dentry(struct dentry *);
45extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb); 45extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb);
46extern char *build_wildcard_path_from_dentry(struct dentry *direntry); 46extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
47extern char *cifs_compose_mount_options(const char *sb_mountdata,
48 const char *fullpath, const struct dfs_info3_param *ref,
49 char **devname);
47/* extern void renew_parental_timestamps(struct dentry *direntry);*/ 50/* extern void renew_parental_timestamps(struct dentry *direntry);*/
48extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, 51extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
49 struct smb_hdr * /* input */ , 52 struct smb_hdr * /* input */ ,
@@ -92,6 +95,9 @@ extern u64 cifs_UnixTimeToNT(struct timespec);
92extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time); 95extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
93extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time); 96extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time);
94 97
98extern int cifs_posix_open(char *full_path, struct inode **pinode,
99 struct super_block *sb, int mode, int oflags,
100 int *poplock, __u16 *pnetfid, int xid);
95extern void posix_fill_in_inode(struct inode *tmp_inode, 101extern void posix_fill_in_inode(struct inode *tmp_inode,
96 FILE_UNIX_BASIC_INFO *pData, int isNewInode); 102 FILE_UNIX_BASIC_INFO *pData, int isNewInode);
97extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum); 103extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum);
@@ -281,6 +287,9 @@ extern int CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon,
281extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, 287extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
282 const int smb_file_id); 288 const int smb_file_id);
283 289
290extern int CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon,
291 const int smb_file_id);
292
284extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, 293extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
285 const int netfid, unsigned int count, 294 const int netfid, unsigned int count,
286 const __u64 lseek, unsigned int *nbytes, char **buf, 295 const __u64 lseek, unsigned int *nbytes, char **buf,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 939e2f76b959..bc09c998631f 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1934,6 +1934,27 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1934} 1934}
1935 1935
1936int 1936int
1937CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1938{
1939 int rc = 0;
1940 FLUSH_REQ *pSMB = NULL;
1941 cFYI(1, ("In CIFSSMBFlush"));
1942
1943 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
1944 if (rc)
1945 return rc;
1946
1947 pSMB->FileID = (__u16) smb_file_id;
1948 pSMB->ByteCount = 0;
1949 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1950 cifs_stats_inc(&tcon->num_flushes);
1951 if (rc)
1952 cERROR(1, ("Send error in Flush = %d", rc));
1953
1954 return rc;
1955}
1956
1957int
1937CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, 1958CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1938 const char *fromName, const char *toName, 1959 const char *fromName, const char *toName,
1939 const struct nls_table *nls_codepage, int remap) 1960 const struct nls_table *nls_codepage, int remap)
@@ -2356,8 +2377,10 @@ winCreateHardLinkRetry:
2356 PATH_MAX, nls_codepage, remap); 2377 PATH_MAX, nls_codepage, remap);
2357 name_len++; /* trailing null */ 2378 name_len++; /* trailing null */
2358 name_len *= 2; 2379 name_len *= 2;
2359 pSMB->OldFileName[name_len] = 0; /* pad */ 2380
2360 pSMB->OldFileName[name_len + 1] = 0x04; 2381 /* protocol specifies ASCII buffer format (0x04) for unicode */
2382 pSMB->OldFileName[name_len] = 0x04;
2383 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2361 name_len2 = 2384 name_len2 =
2362 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], 2385 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2363 toName, PATH_MAX, nls_codepage, remap); 2386 toName, PATH_MAX, nls_codepage, remap);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index da0f4ffa0613..0de3b5615a22 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -95,6 +95,7 @@ struct smb_vol {
95 bool local_lease:1; /* check leases only on local system, not remote */ 95 bool local_lease:1; /* check leases only on local system, not remote */
96 bool noblocksnd:1; 96 bool noblocksnd:1;
97 bool noautotune:1; 97 bool noautotune:1;
98 bool nostrictsync:1; /* do not force expensive SMBflush on every sync */
98 unsigned int rsize; 99 unsigned int rsize;
99 unsigned int wsize; 100 unsigned int wsize;
100 unsigned int sockopt; 101 unsigned int sockopt;
@@ -1274,6 +1275,10 @@ cifs_parse_mount_options(char *options, const char *devname,
1274 vol->intr = 0; 1275 vol->intr = 0;
1275 } else if (strnicmp(data, "intr", 4) == 0) { 1276 } else if (strnicmp(data, "intr", 4) == 0) {
1276 vol->intr = 1; 1277 vol->intr = 1;
1278 } else if (strnicmp(data, "nostrictsync", 12) == 0) {
1279 vol->nostrictsync = 1;
1280 } else if (strnicmp(data, "strictsync", 10) == 0) {
1281 vol->nostrictsync = 0;
1277 } else if (strnicmp(data, "serverino", 7) == 0) { 1282 } else if (strnicmp(data, "serverino", 7) == 0) {
1278 vol->server_ino = 1; 1283 vol->server_ino = 1;
1279 } else if (strnicmp(data, "noserverino", 9) == 0) { 1284 } else if (strnicmp(data, "noserverino", 9) == 0) {
@@ -2160,6 +2165,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
2160 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; 2165 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
2161 if (pvolume_info->nobrl) 2166 if (pvolume_info->nobrl)
2162 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; 2167 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
2168 if (pvolume_info->nostrictsync)
2169 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
2163 if (pvolume_info->mand_lock) 2170 if (pvolume_info->mand_lock)
2164 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL; 2171 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
2165 if (pvolume_info->cifs_acl) 2172 if (pvolume_info->cifs_acl)
@@ -3667,7 +3674,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3667 BCC(smb_buffer_response)) { 3674 BCC(smb_buffer_response)) {
3668 kfree(tcon->nativeFileSystem); 3675 kfree(tcon->nativeFileSystem);
3669 tcon->nativeFileSystem = 3676 tcon->nativeFileSystem =
3670 kzalloc(length + 2, GFP_KERNEL); 3677 kzalloc(2*(length + 1), GFP_KERNEL);
3671 if (tcon->nativeFileSystem) 3678 if (tcon->nativeFileSystem)
3672 cifs_strfromUCS_le( 3679 cifs_strfromUCS_le(
3673 tcon->nativeFileSystem, 3680 tcon->nativeFileSystem,
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 89fb72832652..f9b6f68be976 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -129,7 +129,7 @@ cifs_bp_rename_retry:
129 return full_path; 129 return full_path;
130} 130}
131 131
132static int cifs_posix_open(char *full_path, struct inode **pinode, 132int cifs_posix_open(char *full_path, struct inode **pinode,
133 struct super_block *sb, int mode, int oflags, 133 struct super_block *sb, int mode, int oflags,
134 int *poplock, __u16 *pnetfid, int xid) 134 int *poplock, __u16 *pnetfid, int xid)
135{ 135{
@@ -187,7 +187,9 @@ static int cifs_posix_open(char *full_path, struct inode **pinode,
187 if (!pinode) 187 if (!pinode)
188 goto posix_open_ret; /* caller does not need info */ 188 goto posix_open_ret; /* caller does not need info */
189 189
190 *pinode = cifs_new_inode(sb, &presp_data->UniqueId); 190 if (*pinode == NULL)
191 *pinode = cifs_new_inode(sb, &presp_data->UniqueId);
192 /* else an inode was passed in. Update its info, don't create one */
191 193
192 /* We do not need to close the file if new_inode fails since 194 /* We do not need to close the file if new_inode fails since
193 the caller will retry qpathinfo as long as inode is null */ 195 the caller will retry qpathinfo as long as inode is null */
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 12bb656fbe75..81747acca4c4 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -78,8 +78,36 @@ static inline int cifs_convert_flags(unsigned int flags)
78 return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | 78 return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES |
79 FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA | 79 FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA |
80 FILE_READ_DATA); 80 FILE_READ_DATA);
81}
81 82
83static inline fmode_t cifs_posix_convert_flags(unsigned int flags)
84{
85 fmode_t posix_flags = 0;
82 86
87 if ((flags & O_ACCMODE) == O_RDONLY)
88 posix_flags = FMODE_READ;
89 else if ((flags & O_ACCMODE) == O_WRONLY)
90 posix_flags = FMODE_WRITE;
91 else if ((flags & O_ACCMODE) == O_RDWR) {
92 /* GENERIC_ALL is too much permission to request
93 can cause unnecessary access denied on create */
94 /* return GENERIC_ALL; */
95 posix_flags = FMODE_READ | FMODE_WRITE;
96 }
97 /* can not map O_CREAT or O_EXCL or O_TRUNC flags when
98 reopening a file. They had their effect on the original open */
99 if (flags & O_APPEND)
100 posix_flags |= (fmode_t)O_APPEND;
101 if (flags & O_SYNC)
102 posix_flags |= (fmode_t)O_SYNC;
103 if (flags & O_DIRECTORY)
104 posix_flags |= (fmode_t)O_DIRECTORY;
105 if (flags & O_NOFOLLOW)
106 posix_flags |= (fmode_t)O_NOFOLLOW;
107 if (flags & O_DIRECT)
108 posix_flags |= (fmode_t)O_DIRECT;
109
110 return posix_flags;
83} 111}
84 112
85static inline int cifs_get_disposition(unsigned int flags) 113static inline int cifs_get_disposition(unsigned int flags)
@@ -97,6 +125,80 @@ static inline int cifs_get_disposition(unsigned int flags)
97} 125}
98 126
99/* all arguments to this function must be checked for validity in caller */ 127/* all arguments to this function must be checked for validity in caller */
128static inline int cifs_posix_open_inode_helper(struct inode *inode,
129 struct file *file, struct cifsInodeInfo *pCifsInode,
130 struct cifsFileInfo *pCifsFile, int oplock, u16 netfid)
131{
132 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
133/* struct timespec temp; */ /* BB REMOVEME BB */
134
135 file->private_data = kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
136 if (file->private_data == NULL)
137 return -ENOMEM;
138 pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
139 write_lock(&GlobalSMBSeslock);
140 list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
141
142 pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
143 if (pCifsInode == NULL) {
144 write_unlock(&GlobalSMBSeslock);
145 return -EINVAL;
146 }
147
148 /* want handles we can use to read with first
149 in the list so we do not have to walk the
150 list to search for one in write_begin */
151 if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
152 list_add_tail(&pCifsFile->flist,
153 &pCifsInode->openFileList);
154 } else {
155 list_add(&pCifsFile->flist,
156 &pCifsInode->openFileList);
157 }
158
159 if (pCifsInode->clientCanCacheRead) {
160 /* we have the inode open somewhere else
161 no need to discard cache data */
162 goto psx_client_can_cache;
163 }
164
165 /* BB FIXME need to fix this check to move it earlier into posix_open
166 BB fIX following section BB FIXME */
167
168 /* if not oplocked, invalidate inode pages if mtime or file
169 size changed */
170/* temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
171 if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) &&
172 (file->f_path.dentry->d_inode->i_size ==
173 (loff_t)le64_to_cpu(buf->EndOfFile))) {
174 cFYI(1, ("inode unchanged on server"));
175 } else {
176 if (file->f_path.dentry->d_inode->i_mapping) {
177 rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping);
178 if (rc != 0)
179 CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc;
180 }
181 cFYI(1, ("invalidating remote inode since open detected it "
182 "changed"));
183 invalidate_remote_inode(file->f_path.dentry->d_inode);
184 } */
185
186psx_client_can_cache:
187 if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
188 pCifsInode->clientCanCacheAll = true;
189 pCifsInode->clientCanCacheRead = true;
190 cFYI(1, ("Exclusive Oplock granted on inode %p",
191 file->f_path.dentry->d_inode));
192 } else if ((oplock & 0xF) == OPLOCK_READ)
193 pCifsInode->clientCanCacheRead = true;
194
195 /* will have to change the unlock if we reenable the
196 filemap_fdatawrite (which does not seem necessary */
197 write_unlock(&GlobalSMBSeslock);
198 return 0;
199}
200
201/* all arguments to this function must be checked for validity in caller */
100static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, 202static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
101 struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile, 203 struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile,
102 struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf, 204 struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf,
@@ -167,7 +269,7 @@ int cifs_open(struct inode *inode, struct file *file)
167 int rc = -EACCES; 269 int rc = -EACCES;
168 int xid, oplock; 270 int xid, oplock;
169 struct cifs_sb_info *cifs_sb; 271 struct cifs_sb_info *cifs_sb;
170 struct cifsTconInfo *pTcon; 272 struct cifsTconInfo *tcon;
171 struct cifsFileInfo *pCifsFile; 273 struct cifsFileInfo *pCifsFile;
172 struct cifsInodeInfo *pCifsInode; 274 struct cifsInodeInfo *pCifsInode;
173 struct list_head *tmp; 275 struct list_head *tmp;
@@ -180,7 +282,7 @@ int cifs_open(struct inode *inode, struct file *file)
180 xid = GetXid(); 282 xid = GetXid();
181 283
182 cifs_sb = CIFS_SB(inode->i_sb); 284 cifs_sb = CIFS_SB(inode->i_sb);
183 pTcon = cifs_sb->tcon; 285 tcon = cifs_sb->tcon;
184 286
185 if (file->f_flags & O_CREAT) { 287 if (file->f_flags & O_CREAT) {
186 /* search inode for this file and fill in file->private_data */ 288 /* search inode for this file and fill in file->private_data */
@@ -220,6 +322,45 @@ int cifs_open(struct inode *inode, struct file *file)
220 322
221 cFYI(1, ("inode = 0x%p file flags are 0x%x for %s", 323 cFYI(1, ("inode = 0x%p file flags are 0x%x for %s",
222 inode, file->f_flags, full_path)); 324 inode, file->f_flags, full_path));
325
326 if (oplockEnabled)
327 oplock = REQ_OPLOCK;
328 else
329 oplock = 0;
330
331 if (!tcon->broken_posix_open && tcon->unix_ext &&
332 (tcon->ses->capabilities & CAP_UNIX) &&
333 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
334 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
335 int oflags = (int) cifs_posix_convert_flags(file->f_flags);
336 /* can not refresh inode info since size could be stale */
337 rc = cifs_posix_open(full_path, &inode, inode->i_sb,
338 cifs_sb->mnt_file_mode /* ignored */,
339 oflags, &oplock, &netfid, xid);
340 if (rc == 0) {
341 cFYI(1, ("posix open succeeded"));
342 /* no need for special case handling of setting mode
343 on read only files needed here */
344
345 cifs_posix_open_inode_helper(inode, file, pCifsInode,
346 pCifsFile, oplock, netfid);
347 goto out;
348 } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
349 if (tcon->ses->serverNOS)
350 cERROR(1, ("server %s of type %s returned"
351 " unexpected error on SMB posix open"
352 ", disabling posix open support."
353 " Check if server update available.",
354 tcon->ses->serverName,
355 tcon->ses->serverNOS));
356 tcon->broken_posix_open = true;
357 } else if ((rc != -EIO) && (rc != -EREMOTE) &&
358 (rc != -EOPNOTSUPP)) /* path not found or net err */
359 goto out;
360 /* else fallthrough to retry open the old way on network i/o
361 or DFS errors */
362 }
363
223 desiredAccess = cifs_convert_flags(file->f_flags); 364 desiredAccess = cifs_convert_flags(file->f_flags);
224 365
225/********************************************************************* 366/*********************************************************************
@@ -248,11 +389,6 @@ int cifs_open(struct inode *inode, struct file *file)
248 389
249 disposition = cifs_get_disposition(file->f_flags); 390 disposition = cifs_get_disposition(file->f_flags);
250 391
251 if (oplockEnabled)
252 oplock = REQ_OPLOCK;
253 else
254 oplock = 0;
255
256 /* BB pass O_SYNC flag through on file attributes .. BB */ 392 /* BB pass O_SYNC flag through on file attributes .. BB */
257 393
258 /* Also refresh inode by passing in file_info buf returned by SMBOpen 394 /* Also refresh inode by passing in file_info buf returned by SMBOpen
@@ -269,7 +405,7 @@ int cifs_open(struct inode *inode, struct file *file)
269 } 405 }
270 406
271 if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) 407 if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
272 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, 408 rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
273 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf, 409 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
274 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags 410 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
275 & CIFS_MOUNT_MAP_SPECIAL_CHR); 411 & CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -278,7 +414,7 @@ int cifs_open(struct inode *inode, struct file *file)
278 414
279 if (rc == -EIO) { 415 if (rc == -EIO) {
280 /* Old server, try legacy style OpenX */ 416 /* Old server, try legacy style OpenX */
281 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, 417 rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
282 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf, 418 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
283 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags 419 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
284 & CIFS_MOUNT_MAP_SPECIAL_CHR); 420 & CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -295,12 +431,12 @@ int cifs_open(struct inode *inode, struct file *file)
295 } 431 }
296 pCifsFile = cifs_init_private(file->private_data, inode, file, netfid); 432 pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
297 write_lock(&GlobalSMBSeslock); 433 write_lock(&GlobalSMBSeslock);
298 list_add(&pCifsFile->tlist, &pTcon->openFileList); 434 list_add(&pCifsFile->tlist, &tcon->openFileList);
299 435
300 pCifsInode = CIFS_I(file->f_path.dentry->d_inode); 436 pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
301 if (pCifsInode) { 437 if (pCifsInode) {
302 rc = cifs_open_inode_helper(inode, file, pCifsInode, 438 rc = cifs_open_inode_helper(inode, file, pCifsInode,
303 pCifsFile, pTcon, 439 pCifsFile, tcon,
304 &oplock, buf, full_path, xid); 440 &oplock, buf, full_path, xid);
305 } else { 441 } else {
306 write_unlock(&GlobalSMBSeslock); 442 write_unlock(&GlobalSMBSeslock);
@@ -309,7 +445,7 @@ int cifs_open(struct inode *inode, struct file *file)
309 if (oplock & CIFS_CREATE_ACTION) { 445 if (oplock & CIFS_CREATE_ACTION) {
310 /* time to set mode which we can not set earlier due to 446 /* time to set mode which we can not set earlier due to
311 problems creating new read-only files */ 447 problems creating new read-only files */
312 if (pTcon->unix_ext) { 448 if (tcon->unix_ext) {
313 struct cifs_unix_set_info_args args = { 449 struct cifs_unix_set_info_args args = {
314 .mode = inode->i_mode, 450 .mode = inode->i_mode,
315 .uid = NO_CHANGE_64, 451 .uid = NO_CHANGE_64,
@@ -319,7 +455,7 @@ int cifs_open(struct inode *inode, struct file *file)
319 .mtime = NO_CHANGE_64, 455 .mtime = NO_CHANGE_64,
320 .device = 0, 456 .device = 0,
321 }; 457 };
322 CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, 458 CIFSSMBUnixSetInfo(xid, tcon, full_path, &args,
323 cifs_sb->local_nls, 459 cifs_sb->local_nls,
324 cifs_sb->mnt_cifs_flags & 460 cifs_sb->mnt_cifs_flags &
325 CIFS_MOUNT_MAP_SPECIAL_CHR); 461 CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -349,7 +485,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
349 int rc = -EACCES; 485 int rc = -EACCES;
350 int xid, oplock; 486 int xid, oplock;
351 struct cifs_sb_info *cifs_sb; 487 struct cifs_sb_info *cifs_sb;
352 struct cifsTconInfo *pTcon; 488 struct cifsTconInfo *tcon;
353 struct cifsFileInfo *pCifsFile; 489 struct cifsFileInfo *pCifsFile;
354 struct cifsInodeInfo *pCifsInode; 490 struct cifsInodeInfo *pCifsInode;
355 struct inode *inode; 491 struct inode *inode;
@@ -387,7 +523,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
387 } 523 }
388 524
389 cifs_sb = CIFS_SB(inode->i_sb); 525 cifs_sb = CIFS_SB(inode->i_sb);
390 pTcon = cifs_sb->tcon; 526 tcon = cifs_sb->tcon;
391 527
392/* can not grab rename sem here because various ops, including 528/* can not grab rename sem here because various ops, including
393 those that already have the rename sem can end up causing writepage 529 those that already have the rename sem can end up causing writepage
@@ -404,20 +540,37 @@ reopen_error_exit:
404 540
405 cFYI(1, ("inode = 0x%p file flags 0x%x for %s", 541 cFYI(1, ("inode = 0x%p file flags 0x%x for %s",
406 inode, file->f_flags, full_path)); 542 inode, file->f_flags, full_path));
407 desiredAccess = cifs_convert_flags(file->f_flags);
408 543
409 if (oplockEnabled) 544 if (oplockEnabled)
410 oplock = REQ_OPLOCK; 545 oplock = REQ_OPLOCK;
411 else 546 else
412 oplock = 0; 547 oplock = 0;
413 548
549 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
550 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
551 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
552 int oflags = (int) cifs_posix_convert_flags(file->f_flags);
553 /* can not refresh inode info since size could be stale */
554 rc = cifs_posix_open(full_path, NULL, inode->i_sb,
555 cifs_sb->mnt_file_mode /* ignored */,
556 oflags, &oplock, &netfid, xid);
557 if (rc == 0) {
558 cFYI(1, ("posix reopen succeeded"));
559 goto reopen_success;
560 }
561 /* fallthrough to retry open the old way on errors, especially
562 in the reconnect path it is important to retry hard */
563 }
564
565 desiredAccess = cifs_convert_flags(file->f_flags);
566
414 /* Can not refresh inode by passing in file_info buf to be returned 567 /* Can not refresh inode by passing in file_info buf to be returned
415 by SMBOpen and then calling get_inode_info with returned buf 568 by SMBOpen and then calling get_inode_info with returned buf
416 since file might have write behind data that needs to be flushed 569 since file might have write behind data that needs to be flushed
417 and server version of file size can be stale. If we knew for sure 570 and server version of file size can be stale. If we knew for sure
418 that inode was not dirty locally we could do this */ 571 that inode was not dirty locally we could do this */
419 572
420 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, 573 rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess,
421 CREATE_NOT_DIR, &netfid, &oplock, NULL, 574 CREATE_NOT_DIR, &netfid, &oplock, NULL,
422 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 575 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
423 CIFS_MOUNT_MAP_SPECIAL_CHR); 576 CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -426,6 +579,7 @@ reopen_error_exit:
426 cFYI(1, ("cifs_open returned 0x%x", rc)); 579 cFYI(1, ("cifs_open returned 0x%x", rc));
427 cFYI(1, ("oplock: %d", oplock)); 580 cFYI(1, ("oplock: %d", oplock));
428 } else { 581 } else {
582reopen_success:
429 pCifsFile->netfid = netfid; 583 pCifsFile->netfid = netfid;
430 pCifsFile->invalidHandle = false; 584 pCifsFile->invalidHandle = false;
431 up(&pCifsFile->fh_sem); 585 up(&pCifsFile->fh_sem);
@@ -439,7 +593,7 @@ reopen_error_exit:
439 go to server to get inode info */ 593 go to server to get inode info */
440 pCifsInode->clientCanCacheAll = false; 594 pCifsInode->clientCanCacheAll = false;
441 pCifsInode->clientCanCacheRead = false; 595 pCifsInode->clientCanCacheRead = false;
442 if (pTcon->unix_ext) 596 if (tcon->unix_ext)
443 rc = cifs_get_inode_info_unix(&inode, 597 rc = cifs_get_inode_info_unix(&inode,
444 full_path, inode->i_sb, xid); 598 full_path, inode->i_sb, xid);
445 else 599 else
@@ -467,7 +621,6 @@ reopen_error_exit:
467 cifs_relock_file(pCifsFile); 621 cifs_relock_file(pCifsFile);
468 } 622 }
469 } 623 }
470
471 kfree(full_path); 624 kfree(full_path);
472 FreeXid(xid); 625 FreeXid(xid);
473 return rc; 626 return rc;
@@ -1523,6 +1676,9 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1523{ 1676{
1524 int xid; 1677 int xid;
1525 int rc = 0; 1678 int rc = 0;
1679 struct cifsTconInfo *tcon;
1680 struct cifsFileInfo *smbfile =
1681 (struct cifsFileInfo *)file->private_data;
1526 struct inode *inode = file->f_path.dentry->d_inode; 1682 struct inode *inode = file->f_path.dentry->d_inode;
1527 1683
1528 xid = GetXid(); 1684 xid = GetXid();
@@ -1534,7 +1690,12 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1534 if (rc == 0) { 1690 if (rc == 0) {
1535 rc = CIFS_I(inode)->write_behind_rc; 1691 rc = CIFS_I(inode)->write_behind_rc;
1536 CIFS_I(inode)->write_behind_rc = 0; 1692 CIFS_I(inode)->write_behind_rc = 0;
1693 tcon = CIFS_SB(inode->i_sb)->tcon;
1694 if (!rc && tcon && smbfile &&
1695 !(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
1696 rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
1537 } 1697 }
1698
1538 FreeXid(xid); 1699 FreeXid(xid);
1539 return rc; 1700 return rc;
1540} 1701}
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 4690a360c855..a8797cc60805 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -763,6 +763,9 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
763 struct cifsTconInfo *pTcon = cifs_sb->tcon; 763 struct cifsTconInfo *pTcon = cifs_sb->tcon;
764 FILE_BASIC_INFO info_buf; 764 FILE_BASIC_INFO info_buf;
765 765
766 if (attrs == NULL)
767 return -EINVAL;
768
766 if (attrs->ia_valid & ATTR_ATIME) { 769 if (attrs->ia_valid & ATTR_ATIME) {
767 set_time = true; 770 set_time = true;
768 info_buf.LastAccessTime = 771 info_buf.LastAccessTime =
diff --git a/fs/cifs/smbfsctl.h b/fs/cifs/smbfsctl.h
new file mode 100644
index 000000000000..7056b891e087
--- /dev/null
+++ b/fs/cifs/smbfsctl.h
@@ -0,0 +1,84 @@
1/*
2 * fs/cifs/smbfsctl.h: SMB, CIFS, SMB2 FSCTL definitions
3 *
4 * Copyright (c) International Business Machines Corp., 2002,2009
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22/* IOCTL information */
23/*
24 * List of ioctl/fsctl function codes that are or could be useful in the
25 * future to remote clients like cifs or SMB2 client. There is probably
26 * a slightly larger set of fsctls that NTFS local filesystem could handle,
27 * including the seven below that we do not have struct definitions for.
28 * Even with protocol definitions for most of these now available, we still
29 * need to do some experimentation to identify which are practical to do
30 * remotely. Some of the following, such as the encryption/compression ones
31 * could be invoked from tools via a specialized hook into the VFS rather
32 * than via the standard vfs entry points
33 */
34#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
35#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
36#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008
37#define FSCTL_LOCK_VOLUME 0x00090018
38#define FSCTL_UNLOCK_VOLUME 0x0009001C
39#define FSCTL_IS_PATHNAME_VALID 0x0009002C /* BB add struct */
40#define FSCTL_GET_COMPRESSION 0x0009003C /* BB add struct */
41#define FSCTL_SET_COMPRESSION 0x0009C040 /* BB add struct */
42#define FSCTL_QUERY_FAT_BPB 0x00090058 /* BB add struct */
43/* Verify the next FSCTL number, we had it as 0x00090090 before */
44#define FSCTL_FILESYSTEM_GET_STATS 0x00090060 /* BB add struct */
45#define FSCTL_GET_NTFS_VOLUME_DATA 0x00090064 /* BB add struct */
46#define FSCTL_GET_RETRIEVAL_POINTERS 0x00090073 /* BB add struct */
47#define FSCTL_IS_VOLUME_DIRTY 0x00090078 /* BB add struct */
48#define FSCTL_ALLOW_EXTENDED_DASD_IO 0x00090083 /* BB add struct */
49#define FSCTL_REQUEST_FILTER_OPLOCK 0x0009008C
50#define FSCTL_FIND_FILES_BY_SID 0x0009008F /* BB add struct */
51#define FSCTL_SET_OBJECT_ID 0x00090098 /* BB add struct */
52#define FSCTL_GET_OBJECT_ID 0x0009009C /* BB add struct */
53#define FSCTL_DELETE_OBJECT_ID 0x000900A0 /* BB add struct */
54#define FSCTL_SET_REPARSE_POINT 0x000900A4 /* BB add struct */
55#define FSCTL_GET_REPARSE_POINT 0x000900A8 /* BB add struct */
56#define FSCTL_DELETE_REPARSE_POINT 0x000900AC /* BB add struct */
57#define FSCTL_SET_OBJECT_ID_EXTENDED 0x000900BC /* BB add struct */
58#define FSCTL_CREATE_OR_GET_OBJECT_ID 0x000900C0 /* BB add struct */
59#define FSCTL_SET_SPARSE 0x000900C4 /* BB add struct */
60#define FSCTL_SET_ZERO_DATA 0x000900C8 /* BB add struct */
61#define FSCTL_SET_ENCRYPTION 0x000900D7 /* BB add struct */
62#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB /* BB add struct */
63#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF /* BB add struct */
64#define FSCTL_READ_RAW_ENCRYPTED 0x000900E3 /* BB add struct */
65#define FSCTL_READ_FILE_USN_DATA 0x000900EB /* BB add struct */
66#define FSCTL_WRITE_USN_CLOSE_RECORD 0x000900EF /* BB add struct */
67#define FSCTL_SIS_COPYFILE 0x00090100 /* BB add struct */
68#define FSCTL_RECALL_FILE 0x00090117 /* BB add struct */
69#define FSCTL_QUERY_SPARING_INFO 0x00090138 /* BB add struct */
70#define FSCTL_SET_ZERO_ON_DEALLOC 0x00090194 /* BB add struct */
71#define FSCTL_SET_SHORT_NAME_BEHAVIOR 0x000901B4 /* BB add struct */
72#define FSCTL_QUERY_ALLOCATED_RANGES 0x000940CF /* BB add struct */
73#define FSCTL_SET_DEFECT_MANAGEMENT 0x00098134 /* BB add struct */
74#define FSCTL_SIS_LINK_FILES 0x0009C104
75#define FSCTL_PIPE_PEEK 0x0011400C /* BB add struct */
76#define FSCTL_PIPE_TRANSCEIVE 0x0011C017 /* BB add struct */
77/* strange that the number for this op is not sequential with previous op */
78#define FSCTL_PIPE_WAIT 0x00110018 /* BB add struct */
79#define FSCTL_LMR_GET_LINK_TRACK_INF 0x001400E8 /* BB add struct */
80#define FSCTL_LMR_SET_LINK_TRACK_INF 0x001400EC /* BB add struct */
81
82#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003
83#define IO_REPARSE_TAG_HSM 0xC0000004
84#define IO_REPARSE_TAG_SIS 0x80000007