aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2010-08-26 13:22:27 -0400
committerJ. Bruce Fields <bfields@redhat.com>2010-08-26 13:22:27 -0400
commitf632265d0ffb5acf331252d98c64939849d96bb2 (patch)
tree31187d9a726bf1ca6ca12e26ad8e7c609eaf4d8b /fs/cifs
parent7d94784293096c0a46897acdb83be5abd9278ece (diff)
parentda5cabf80e2433131bf0ed8993abc0f7ea618c73 (diff)
Merge commit 'v2.6.36-rc1' into HEAD
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/Kconfig27
-rw-r--r--fs/cifs/Makefile2
-rw-r--r--fs/cifs/README15
-rw-r--r--fs/cifs/cache.c331
-rw-r--r--fs/cifs/cifs_debug.c25
-rw-r--r--fs/cifs/cifs_dfs_ref.c33
-rw-r--r--fs/cifs/cifs_fs_sb.h1
-rw-r--r--fs/cifs/cifs_spnego.c7
-rw-r--r--fs/cifs/cifsfs.c50
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsglob.h48
-rw-r--r--fs/cifs/cifsproto.h5
-rw-r--r--fs/cifs/connect.c181
-rw-r--r--fs/cifs/dir.c84
-rw-r--r--fs/cifs/dns_resolve.c166
-rw-r--r--fs/cifs/dns_resolve.h2
-rw-r--r--fs/cifs/file.c203
-rw-r--r--fs/cifs/fscache.c236
-rw-r--r--fs/cifs/fscache.h136
-rw-r--r--fs/cifs/inode.c153
-rw-r--r--fs/cifs/ioctl.c3
-rw-r--r--fs/cifs/misc.c20
-rw-r--r--fs/cifs/netmisc.c63
-rw-r--r--fs/cifs/readdir.c5
-rw-r--r--fs/cifs/sess.c10
-rw-r--r--fs/cifs/smberr.h1
26 files changed, 1334 insertions, 475 deletions
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig
index 80f352596807..917b7d449bb2 100644
--- a/fs/cifs/Kconfig
+++ b/fs/cifs/Kconfig
@@ -2,7 +2,6 @@ config CIFS
2 tristate "CIFS support (advanced network filesystem, SMBFS successor)" 2 tristate "CIFS support (advanced network filesystem, SMBFS successor)"
3 depends on INET 3 depends on INET
4 select NLS 4 select NLS
5 select SLOW_WORK
6 help 5 help
7 This is the client VFS module for the Common Internet File System 6 This is the client VFS module for the Common Internet File System
8 (CIFS) protocol which is the successor to the Server Message Block 7 (CIFS) protocol which is the successor to the Server Message Block
@@ -71,14 +70,14 @@ config CIFS_WEAK_PW_HASH
71 If unsure, say N. 70 If unsure, say N.
72 71
73config CIFS_UPCALL 72config CIFS_UPCALL
74 bool "Kerberos/SPNEGO advanced session setup" 73 bool "Kerberos/SPNEGO advanced session setup"
75 depends on CIFS && KEYS 74 depends on CIFS && KEYS
76 help 75 select DNS_RESOLVER
77 Enables an upcall mechanism for CIFS which accesses 76 help
78 userspace helper utilities to provide SPNEGO packaged (RFC 4178) 77 Enables an upcall mechanism for CIFS which accesses userspace helper
79 Kerberos tickets which are needed to mount to certain secure servers 78 utilities to provide SPNEGO packaged (RFC 4178) Kerberos tickets
80 (for which more secure Kerberos authentication is required). If 79 which are needed to mount to certain secure servers (for which more
81 unsure, say N. 80 secure Kerberos authentication is required). If unsure, say N.
82 81
83config CIFS_XATTR 82config CIFS_XATTR
84 bool "CIFS extended attributes" 83 bool "CIFS extended attributes"
@@ -122,6 +121,7 @@ config CIFS_DEBUG2
122config CIFS_DFS_UPCALL 121config CIFS_DFS_UPCALL
123 bool "DFS feature support" 122 bool "DFS feature support"
124 depends on CIFS && KEYS 123 depends on CIFS && KEYS
124 select DNS_RESOLVER
125 help 125 help
126 Distributed File System (DFS) support is used to access shares 126 Distributed File System (DFS) support is used to access shares
127 transparently in an enterprise name space, even if the share 127 transparently in an enterprise name space, even if the share
@@ -131,6 +131,15 @@ config CIFS_DFS_UPCALL
131 IP addresses) which is needed for implicit mounts of DFS junction 131 IP addresses) which is needed for implicit mounts of DFS junction
132 points. If unsure, say N. 132 points. If unsure, say N.
133 133
134config CIFS_FSCACHE
135 bool "Provide CIFS client caching support (EXPERIMENTAL)"
136 depends on EXPERIMENTAL
137 depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y
138 help
139 Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data
140 to be cached locally on disk through the general filesystem cache
141 manager. If unsure, say N.
142
134config CIFS_EXPERIMENTAL 143config CIFS_EXPERIMENTAL
135 bool "CIFS Experimental Features (EXPERIMENTAL)" 144 bool "CIFS Experimental Features (EXPERIMENTAL)"
136 depends on CIFS && EXPERIMENTAL 145 depends on CIFS && EXPERIMENTAL
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index 9948c0030e86..adefa60a9bdc 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -11,3 +11,5 @@ cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \
11cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o 11cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o
12 12
13cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o 13cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
14
15cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o
diff --git a/fs/cifs/README b/fs/cifs/README
index a727b7cb075f..7099a526f775 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -301,6 +301,16 @@ A partial list of the supported mount options follows:
301 gid Set the default gid for inodes (similar to above). 301 gid Set the default gid for inodes (similar to above).
302 file_mode If CIFS Unix extensions are not supported by the server 302 file_mode If CIFS Unix extensions are not supported by the server
303 this overrides the default mode for file inodes. 303 this overrides the default mode for file inodes.
304 fsc Enable local disk caching using FS-Cache (off by default). This
305 option could be useful to improve performance on a slow link,
306 heavily loaded server and/or network where reading from the
307 disk is faster than reading from the server (over the network).
308 This could also impact scalability positively as the
309 number of calls to the server are reduced. However, local
310 caching is not suitable for all workloads for e.g. read-once
311 type workloads. So, you need to consider carefully your
312 workload/scenario before using this option. Currently, local
313 disk caching is functional for CIFS files opened as read-only.
304 dir_mode If CIFS Unix extensions are not supported by the server 314 dir_mode If CIFS Unix extensions are not supported by the server
305 this overrides the default mode for directory inodes. 315 this overrides the default mode for directory inodes.
306 port attempt to contact the server on this tcp port, before 316 port attempt to contact the server on this tcp port, before
@@ -568,8 +578,9 @@ module can be displayed via modinfo.
568Misc /proc/fs/cifs Flags and Debug Info 578Misc /proc/fs/cifs Flags and Debug Info
569======================================= 579=======================================
570Informational pseudo-files: 580Informational pseudo-files:
571DebugData Displays information about active CIFS sessions 581DebugData Displays information about active CIFS sessions and
572 and shares, as well as the cifs.ko version. 582 shares, features enabled as well as the cifs.ko
583 version.
573Stats Lists summary resource usage information as well as per 584Stats Lists summary resource usage information as well as per
574 share statistics, if CONFIG_CIFS_STATS in enabled 585 share statistics, if CONFIG_CIFS_STATS in enabled
575 in the kernel configuration. 586 in the kernel configuration.
diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c
new file mode 100644
index 000000000000..224d7bbd1fcc
--- /dev/null
+++ b/fs/cifs/cache.c
@@ -0,0 +1,331 @@
1/*
2 * fs/cifs/cache.c - CIFS filesystem cache index structure definitions
3 *
4 * Copyright (c) 2010 Novell, Inc.
5 * Authors(s): Suresh Jayaraman (sjayaraman@suse.de>
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#include "fscache.h"
22#include "cifs_debug.h"
23
24/*
25 * CIFS filesystem definition for FS-Cache
26 */
27struct fscache_netfs cifs_fscache_netfs = {
28 .name = "cifs",
29 .version = 0,
30};
31
32/*
33 * Register CIFS for caching with FS-Cache
34 */
35int cifs_fscache_register(void)
36{
37 return fscache_register_netfs(&cifs_fscache_netfs);
38}
39
40/*
41 * Unregister CIFS for caching
42 */
43void cifs_fscache_unregister(void)
44{
45 fscache_unregister_netfs(&cifs_fscache_netfs);
46}
47
48/*
49 * Key layout of CIFS server cache index object
50 */
51struct cifs_server_key {
52 uint16_t family; /* address family */
53 uint16_t port; /* IP port */
54 union {
55 struct in_addr ipv4_addr;
56 struct in6_addr ipv6_addr;
57 } addr[0];
58};
59
60/*
61 * Server object keyed by {IPaddress,port,family} tuple
62 */
63static uint16_t cifs_server_get_key(const void *cookie_netfs_data,
64 void *buffer, uint16_t maxbuf)
65{
66 const struct TCP_Server_Info *server = cookie_netfs_data;
67 const struct sockaddr *sa = (struct sockaddr *) &server->addr.sockAddr;
68 struct cifs_server_key *key = buffer;
69 uint16_t key_len = sizeof(struct cifs_server_key);
70
71 memset(key, 0, key_len);
72
73 /*
74 * Should not be a problem as sin_family/sin6_family overlays
75 * sa_family field
76 */
77 switch (sa->sa_family) {
78 case AF_INET:
79 key->family = server->addr.sockAddr.sin_family;
80 key->port = server->addr.sockAddr.sin_port;
81 key->addr[0].ipv4_addr = server->addr.sockAddr.sin_addr;
82 key_len += sizeof(key->addr[0].ipv4_addr);
83 break;
84
85 case AF_INET6:
86 key->family = server->addr.sockAddr6.sin6_family;
87 key->port = server->addr.sockAddr6.sin6_port;
88 key->addr[0].ipv6_addr = server->addr.sockAddr6.sin6_addr;
89 key_len += sizeof(key->addr[0].ipv6_addr);
90 break;
91
92 default:
93 cERROR(1, "CIFS: Unknown network family '%d'", sa->sa_family);
94 key_len = 0;
95 break;
96 }
97
98 return key_len;
99}
100
101/*
102 * Server object for FS-Cache
103 */
104const struct fscache_cookie_def cifs_fscache_server_index_def = {
105 .name = "CIFS.server",
106 .type = FSCACHE_COOKIE_TYPE_INDEX,
107 .get_key = cifs_server_get_key,
108};
109
110/*
111 * Auxiliary data attached to CIFS superblock within the cache
112 */
113struct cifs_fscache_super_auxdata {
114 u64 resource_id; /* unique server resource id */
115};
116
117static char *extract_sharename(const char *treename)
118{
119 const char *src;
120 char *delim, *dst;
121 int len;
122
123 /* skip double chars at the beginning */
124 src = treename + 2;
125
126 /* share name is always preceded by '\\' now */
127 delim = strchr(src, '\\');
128 if (!delim)
129 return ERR_PTR(-EINVAL);
130 delim++;
131 len = strlen(delim);
132
133 /* caller has to free the memory */
134 dst = kstrndup(delim, len, GFP_KERNEL);
135 if (!dst)
136 return ERR_PTR(-ENOMEM);
137
138 return dst;
139}
140
141/*
142 * Superblock object currently keyed by share name
143 */
144static uint16_t cifs_super_get_key(const void *cookie_netfs_data, void *buffer,
145 uint16_t maxbuf)
146{
147 const struct cifsTconInfo *tcon = cookie_netfs_data;
148 char *sharename;
149 uint16_t len;
150
151 sharename = extract_sharename(tcon->treeName);
152 if (IS_ERR(sharename)) {
153 cFYI(1, "CIFS: couldn't extract sharename\n");
154 sharename = NULL;
155 return 0;
156 }
157
158 len = strlen(sharename);
159 if (len > maxbuf)
160 return 0;
161
162 memcpy(buffer, sharename, len);
163
164 kfree(sharename);
165
166 return len;
167}
168
169static uint16_t
170cifs_fscache_super_get_aux(const void *cookie_netfs_data, void *buffer,
171 uint16_t maxbuf)
172{
173 struct cifs_fscache_super_auxdata auxdata;
174 const struct cifsTconInfo *tcon = cookie_netfs_data;
175
176 memset(&auxdata, 0, sizeof(auxdata));
177 auxdata.resource_id = tcon->resource_id;
178
179 if (maxbuf > sizeof(auxdata))
180 maxbuf = sizeof(auxdata);
181
182 memcpy(buffer, &auxdata, maxbuf);
183
184 return maxbuf;
185}
186
187static enum
188fscache_checkaux cifs_fscache_super_check_aux(void *cookie_netfs_data,
189 const void *data,
190 uint16_t datalen)
191{
192 struct cifs_fscache_super_auxdata auxdata;
193 const struct cifsTconInfo *tcon = cookie_netfs_data;
194
195 if (datalen != sizeof(auxdata))
196 return FSCACHE_CHECKAUX_OBSOLETE;
197
198 memset(&auxdata, 0, sizeof(auxdata));
199 auxdata.resource_id = tcon->resource_id;
200
201 if (memcmp(data, &auxdata, datalen) != 0)
202 return FSCACHE_CHECKAUX_OBSOLETE;
203
204 return FSCACHE_CHECKAUX_OKAY;
205}
206
207/*
208 * Superblock object for FS-Cache
209 */
210const struct fscache_cookie_def cifs_fscache_super_index_def = {
211 .name = "CIFS.super",
212 .type = FSCACHE_COOKIE_TYPE_INDEX,
213 .get_key = cifs_super_get_key,
214 .get_aux = cifs_fscache_super_get_aux,
215 .check_aux = cifs_fscache_super_check_aux,
216};
217
218/*
219 * Auxiliary data attached to CIFS inode within the cache
220 */
221struct cifs_fscache_inode_auxdata {
222 struct timespec last_write_time;
223 struct timespec last_change_time;
224 u64 eof;
225};
226
227static uint16_t cifs_fscache_inode_get_key(const void *cookie_netfs_data,
228 void *buffer, uint16_t maxbuf)
229{
230 const struct cifsInodeInfo *cifsi = cookie_netfs_data;
231 uint16_t keylen;
232
233 /* use the UniqueId as the key */
234 keylen = sizeof(cifsi->uniqueid);
235 if (keylen > maxbuf)
236 keylen = 0;
237 else
238 memcpy(buffer, &cifsi->uniqueid, keylen);
239
240 return keylen;
241}
242
243static void
244cifs_fscache_inode_get_attr(const void *cookie_netfs_data, uint64_t *size)
245{
246 const struct cifsInodeInfo *cifsi = cookie_netfs_data;
247
248 *size = cifsi->vfs_inode.i_size;
249}
250
251static uint16_t
252cifs_fscache_inode_get_aux(const void *cookie_netfs_data, void *buffer,
253 uint16_t maxbuf)
254{
255 struct cifs_fscache_inode_auxdata auxdata;
256 const struct cifsInodeInfo *cifsi = cookie_netfs_data;
257
258 memset(&auxdata, 0, sizeof(auxdata));
259 auxdata.eof = cifsi->server_eof;
260 auxdata.last_write_time = cifsi->vfs_inode.i_mtime;
261 auxdata.last_change_time = cifsi->vfs_inode.i_ctime;
262
263 if (maxbuf > sizeof(auxdata))
264 maxbuf = sizeof(auxdata);
265
266 memcpy(buffer, &auxdata, maxbuf);
267
268 return maxbuf;
269}
270
271static enum
272fscache_checkaux cifs_fscache_inode_check_aux(void *cookie_netfs_data,
273 const void *data,
274 uint16_t datalen)
275{
276 struct cifs_fscache_inode_auxdata auxdata;
277 struct cifsInodeInfo *cifsi = cookie_netfs_data;
278
279 if (datalen != sizeof(auxdata))
280 return FSCACHE_CHECKAUX_OBSOLETE;
281
282 memset(&auxdata, 0, sizeof(auxdata));
283 auxdata.eof = cifsi->server_eof;
284 auxdata.last_write_time = cifsi->vfs_inode.i_mtime;
285 auxdata.last_change_time = cifsi->vfs_inode.i_ctime;
286
287 if (memcmp(data, &auxdata, datalen) != 0)
288 return FSCACHE_CHECKAUX_OBSOLETE;
289
290 return FSCACHE_CHECKAUX_OKAY;
291}
292
293static void cifs_fscache_inode_now_uncached(void *cookie_netfs_data)
294{
295 struct cifsInodeInfo *cifsi = cookie_netfs_data;
296 struct pagevec pvec;
297 pgoff_t first;
298 int loop, nr_pages;
299
300 pagevec_init(&pvec, 0);
301 first = 0;
302
303 cFYI(1, "cifs inode 0x%p now uncached", cifsi);
304
305 for (;;) {
306 nr_pages = pagevec_lookup(&pvec,
307 cifsi->vfs_inode.i_mapping, first,
308 PAGEVEC_SIZE - pagevec_count(&pvec));
309 if (!nr_pages)
310 break;
311
312 for (loop = 0; loop < nr_pages; loop++)
313 ClearPageFsCache(pvec.pages[loop]);
314
315 first = pvec.pages[nr_pages - 1]->index + 1;
316
317 pvec.nr = nr_pages;
318 pagevec_release(&pvec);
319 cond_resched();
320 }
321}
322
323const struct fscache_cookie_def cifs_fscache_inode_object_def = {
324 .name = "CIFS.uniqueid",
325 .type = FSCACHE_COOKIE_TYPE_DATAFILE,
326 .get_key = cifs_fscache_inode_get_key,
327 .get_attr = cifs_fscache_inode_get_attr,
328 .get_aux = cifs_fscache_inode_get_aux,
329 .check_aux = cifs_fscache_inode_check_aux,
330 .now_uncached = cifs_fscache_inode_now_uncached,
331};
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 4fce6e61b34e..eb1ba493489f 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -119,6 +119,31 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
119 "Display Internal CIFS Data Structures for Debugging\n" 119 "Display Internal CIFS Data Structures for Debugging\n"
120 "---------------------------------------------------\n"); 120 "---------------------------------------------------\n");
121 seq_printf(m, "CIFS Version %s\n", CIFS_VERSION); 121 seq_printf(m, "CIFS Version %s\n", CIFS_VERSION);
122 seq_printf(m, "Features: ");
123#ifdef CONFIG_CIFS_DFS_UPCALL
124 seq_printf(m, "dfs");
125 seq_putc(m, ' ');
126#endif
127#ifdef CONFIG_CIFS_FSCACHE
128 seq_printf(m, "fscache");
129 seq_putc(m, ' ');
130#endif
131#ifdef CONFIG_CIFS_WEAK_PW_HASH
132 seq_printf(m, "lanman");
133 seq_putc(m, ' ');
134#endif
135#ifdef CONFIG_CIFS_POSIX
136 seq_printf(m, "posix");
137 seq_putc(m, ' ');
138#endif
139#ifdef CONFIG_CIFS_UPCALL
140 seq_printf(m, "spnego");
141 seq_putc(m, ' ');
142#endif
143#ifdef CONFIG_CIFS_XATTR
144 seq_printf(m, "xattr");
145#endif
146 seq_putc(m, '\n');
122 seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid); 147 seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid);
123 seq_printf(m, "Servers:"); 148 seq_printf(m, "Servers:");
124 149
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index ac19a6f3dae0..d6ced7aa23cf 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -141,7 +141,7 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
141 } 141 }
142 142
143 rc = dns_resolve_server_name_to_ip(*devname, &srvIP); 143 rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
144 if (rc != 0) { 144 if (rc < 0) {
145 cERROR(1, "%s: Failed to resolve server part of %s to IP: %d", 145 cERROR(1, "%s: Failed to resolve server part of %s to IP: %d",
146 __func__, *devname, rc); 146 __func__, *devname, rc);
147 goto compose_mount_options_err; 147 goto compose_mount_options_err;
@@ -150,8 +150,7 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
150 * assuming that we have 'unc=' and 'ip=' in 150 * assuming that we have 'unc=' and 'ip=' in
151 * the original sb_mountdata 151 * the original sb_mountdata
152 */ 152 */
153 md_len = strlen(sb_mountdata) + strlen(srvIP) + 153 md_len = strlen(sb_mountdata) + rc + strlen(ref->node_name) + 12;
154 strlen(ref->node_name) + 12;
155 mountdata = kzalloc(md_len+1, GFP_KERNEL); 154 mountdata = kzalloc(md_len+1, GFP_KERNEL);
156 if (mountdata == NULL) { 155 if (mountdata == NULL) {
157 rc = -ENOMEM; 156 rc = -ENOMEM;
@@ -230,28 +229,22 @@ compose_mount_options_err:
230 goto compose_mount_options_out; 229 goto compose_mount_options_out;
231} 230}
232 231
233 232/**
234static struct vfsmount *cifs_dfs_do_refmount(const struct vfsmount *mnt_parent, 233 * cifs_dfs_do_refmount - mounts specified path using provided refferal
235 struct dentry *dentry, const struct dfs_info3_param *ref) 234 * @cifs_sb: parent/root superblock
235 * @fullpath: full path in UNC format
236 * @ref: server's referral
237 */
238static struct vfsmount *cifs_dfs_do_refmount(struct cifs_sb_info *cifs_sb,
239 const char *fullpath, const struct dfs_info3_param *ref)
236{ 240{
237 struct cifs_sb_info *cifs_sb;
238 struct vfsmount *mnt; 241 struct vfsmount *mnt;
239 char *mountdata; 242 char *mountdata;
240 char *devname = NULL; 243 char *devname = NULL;
241 char *fullpath;
242
243 cifs_sb = CIFS_SB(dentry->d_inode->i_sb);
244 /*
245 * this function gives us a path with a double backslash prefix. We
246 * require a single backslash for DFS.
247 */
248 fullpath = build_path_from_dentry(dentry);
249 if (!fullpath)
250 return ERR_PTR(-ENOMEM);
251 244
245 /* strip first '\' from fullpath */
252 mountdata = cifs_compose_mount_options(cifs_sb->mountdata, 246 mountdata = cifs_compose_mount_options(cifs_sb->mountdata,
253 fullpath + 1, ref, &devname); 247 fullpath + 1, ref, &devname);
254 kfree(fullpath);
255 248
256 if (IS_ERR(mountdata)) 249 if (IS_ERR(mountdata))
257 return (struct vfsmount *)mountdata; 250 return (struct vfsmount *)mountdata;
@@ -357,8 +350,8 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
357 rc = -EINVAL; 350 rc = -EINVAL;
358 goto out_err; 351 goto out_err;
359 } 352 }
360 mnt = cifs_dfs_do_refmount(nd->path.mnt, 353 mnt = cifs_dfs_do_refmount(cifs_sb,
361 nd->path.dentry, referrals + i); 354 full_path, referrals + i);
362 cFYI(1, "%s: cifs_dfs_do_refmount:%s , mnt:%p", __func__, 355 cFYI(1, "%s: cifs_dfs_do_refmount:%s , mnt:%p", __func__,
363 referrals[i].node_name, mnt); 356 referrals[i].node_name, mnt);
364 357
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 246a167cb913..9e771450c3b8 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -35,6 +35,7 @@
35#define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */ 35#define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */
36#define CIFS_MOUNT_NOPOSIXBRL 0x2000 /* mandatory not posix byte range lock */ 36#define CIFS_MOUNT_NOPOSIXBRL 0x2000 /* mandatory not posix byte range lock */
37#define CIFS_MOUNT_NOSSYNC 0x4000 /* don't do slow SMBflush on every sync*/ 37#define CIFS_MOUNT_NOSSYNC 0x4000 /* don't do slow SMBflush on every sync*/
38#define CIFS_MOUNT_FSCACHE 0x8000 /* local caching enabled */
38 39
39struct cifs_sb_info { 40struct cifs_sb_info {
40 struct cifsTconInfo *tcon; /* primary mount */ 41 struct cifsTconInfo *tcon; /* primary mount */
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
index 379bd7d9c05f..87044906cd1f 100644
--- a/fs/cifs/cifs_spnego.c
+++ b/fs/cifs/cifs_spnego.c
@@ -84,6 +84,9 @@ struct key_type cifs_spnego_key_type = {
84/* strlen of ";uid=0x" */ 84/* strlen of ";uid=0x" */
85#define UID_KEY_LEN 7 85#define UID_KEY_LEN 7
86 86
87/* strlen of ";creduid=0x" */
88#define CREDUID_KEY_LEN 11
89
87/* strlen of ";user=" */ 90/* strlen of ";user=" */
88#define USER_KEY_LEN 6 91#define USER_KEY_LEN 6
89 92
@@ -107,6 +110,7 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
107 IP_KEY_LEN + INET6_ADDRSTRLEN + 110 IP_KEY_LEN + INET6_ADDRSTRLEN +
108 MAX_MECH_STR_LEN + 111 MAX_MECH_STR_LEN +
109 UID_KEY_LEN + (sizeof(uid_t) * 2) + 112 UID_KEY_LEN + (sizeof(uid_t) * 2) +
113 CREDUID_KEY_LEN + (sizeof(uid_t) * 2) +
110 USER_KEY_LEN + strlen(sesInfo->userName) + 114 USER_KEY_LEN + strlen(sesInfo->userName) +
111 PID_KEY_LEN + (sizeof(pid_t) * 2) + 1; 115 PID_KEY_LEN + (sizeof(pid_t) * 2) + 1;
112 116
@@ -144,6 +148,9 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
144 sprintf(dp, ";uid=0x%x", sesInfo->linux_uid); 148 sprintf(dp, ";uid=0x%x", sesInfo->linux_uid);
145 149
146 dp = description + strlen(description); 150 dp = description + strlen(description);
151 sprintf(dp, ";creduid=0x%x", sesInfo->cred_uid);
152
153 dp = description + strlen(description);
147 sprintf(dp, ";user=%s", sesInfo->userName); 154 sprintf(dp, ";user=%s", sesInfo->userName);
148 155
149 dp = description + strlen(description); 156 dp = description + strlen(description);
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 78c02eb4cb1f..b7431afdd76d 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -45,8 +45,8 @@
45#include "cifs_fs_sb.h" 45#include "cifs_fs_sb.h"
46#include <linux/mm.h> 46#include <linux/mm.h>
47#include <linux/key-type.h> 47#include <linux/key-type.h>
48#include "dns_resolve.h"
49#include "cifs_spnego.h" 48#include "cifs_spnego.h"
49#include "fscache.h"
50#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */ 50#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
51 51
52int cifsFYI = 0; 52int cifsFYI = 0;
@@ -329,6 +329,14 @@ cifs_destroy_inode(struct inode *inode)
329} 329}
330 330
331static void 331static void
332cifs_evict_inode(struct inode *inode)
333{
334 truncate_inode_pages(&inode->i_data, 0);
335 end_writeback(inode);
336 cifs_fscache_release_inode_cookie(inode);
337}
338
339static void
332cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) 340cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
333{ 341{
334 seq_printf(s, ",addr="); 342 seq_printf(s, ",addr=");
@@ -473,14 +481,24 @@ static int cifs_remount(struct super_block *sb, int *flags, char *data)
473 return 0; 481 return 0;
474} 482}
475 483
484static int cifs_drop_inode(struct inode *inode)
485{
486 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
487
488 /* no serverino => unconditional eviction */
489 return !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) ||
490 generic_drop_inode(inode);
491}
492
476static const struct super_operations cifs_super_ops = { 493static const struct super_operations cifs_super_ops = {
477 .put_super = cifs_put_super, 494 .put_super = cifs_put_super,
478 .statfs = cifs_statfs, 495 .statfs = cifs_statfs,
479 .alloc_inode = cifs_alloc_inode, 496 .alloc_inode = cifs_alloc_inode,
480 .destroy_inode = cifs_destroy_inode, 497 .destroy_inode = cifs_destroy_inode,
481/* .drop_inode = generic_delete_inode, 498 .drop_inode = cifs_drop_inode,
482 .delete_inode = cifs_delete_inode, */ /* Do not need above two 499 .evict_inode = cifs_evict_inode,
483 functions unless later we add lazy close of inodes or unless the 500/* .delete_inode = cifs_delete_inode, */ /* Do not need above
501 function unless later we add lazy close of inodes or unless the
484 kernel forgets to call us with the same number of releases (closes) 502 kernel forgets to call us with the same number of releases (closes)
485 as opens */ 503 as opens */
486 .show_options = cifs_show_options, 504 .show_options = cifs_show_options,
@@ -892,6 +910,10 @@ init_cifs(void)
892 cFYI(1, "cifs_max_pending set to max of 256"); 910 cFYI(1, "cifs_max_pending set to max of 256");
893 } 911 }
894 912
913 rc = cifs_fscache_register();
914 if (rc)
915 goto out;
916
895 rc = cifs_init_inodecache(); 917 rc = cifs_init_inodecache();
896 if (rc) 918 if (rc)
897 goto out_clean_proc; 919 goto out_clean_proc;
@@ -912,27 +934,13 @@ init_cifs(void)
912 if (rc) 934 if (rc)
913 goto out_unregister_filesystem; 935 goto out_unregister_filesystem;
914#endif 936#endif
915#ifdef CONFIG_CIFS_DFS_UPCALL
916 rc = register_key_type(&key_type_dns_resolver);
917 if (rc)
918 goto out_unregister_key_type;
919#endif
920 rc = slow_work_register_user(THIS_MODULE);
921 if (rc)
922 goto out_unregister_resolver_key;
923 937
924 return 0; 938 return 0;
925 939
926 out_unregister_resolver_key:
927#ifdef CONFIG_CIFS_DFS_UPCALL
928 unregister_key_type(&key_type_dns_resolver);
929 out_unregister_key_type:
930#endif
931#ifdef CONFIG_CIFS_UPCALL 940#ifdef CONFIG_CIFS_UPCALL
932 unregister_key_type(&cifs_spnego_key_type);
933 out_unregister_filesystem: 941 out_unregister_filesystem:
934#endif
935 unregister_filesystem(&cifs_fs_type); 942 unregister_filesystem(&cifs_fs_type);
943#endif
936 out_destroy_request_bufs: 944 out_destroy_request_bufs:
937 cifs_destroy_request_bufs(); 945 cifs_destroy_request_bufs();
938 out_destroy_mids: 946 out_destroy_mids:
@@ -941,6 +949,8 @@ init_cifs(void)
941 cifs_destroy_inodecache(); 949 cifs_destroy_inodecache();
942 out_clean_proc: 950 out_clean_proc:
943 cifs_proc_clean(); 951 cifs_proc_clean();
952 cifs_fscache_unregister();
953 out:
944 return rc; 954 return rc;
945} 955}
946 956
@@ -949,9 +959,9 @@ exit_cifs(void)
949{ 959{
950 cFYI(DBG2, "exit_cifs"); 960 cFYI(DBG2, "exit_cifs");
951 cifs_proc_clean(); 961 cifs_proc_clean();
962 cifs_fscache_unregister();
952#ifdef CONFIG_CIFS_DFS_UPCALL 963#ifdef CONFIG_CIFS_DFS_UPCALL
953 cifs_dfs_release_automount_timer(); 964 cifs_dfs_release_automount_timer();
954 unregister_key_type(&key_type_dns_resolver);
955#endif 965#endif
956#ifdef CONFIG_CIFS_UPCALL 966#ifdef CONFIG_CIFS_UPCALL
957 unregister_key_type(&cifs_spnego_key_type); 967 unregister_key_type(&cifs_spnego_key_type);
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index a7eb65c84b1c..d82f5fb4761e 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -114,5 +114,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
114extern const struct export_operations cifs_export_ops; 114extern const struct export_operations cifs_export_ops;
115#endif /* EXPERIMENTAL */ 115#endif /* EXPERIMENTAL */
116 116
117#define CIFS_VERSION "1.64" 117#define CIFS_VERSION "1.65"
118#endif /* _CIFSFS_H */ 118#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index a88479ceaad5..0cdfb8c32ac6 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -16,10 +16,13 @@
16 * the GNU Lesser General Public License for more details. 16 * the GNU Lesser General Public License for more details.
17 * 17 *
18 */ 18 */
19#ifndef _CIFS_GLOB_H
20#define _CIFS_GLOB_H
21
19#include <linux/in.h> 22#include <linux/in.h>
20#include <linux/in6.h> 23#include <linux/in6.h>
21#include <linux/slab.h> 24#include <linux/slab.h>
22#include <linux/slow-work.h> 25#include <linux/workqueue.h>
23#include "cifs_fs_sb.h" 26#include "cifs_fs_sb.h"
24#include "cifsacl.h" 27#include "cifsacl.h"
25/* 28/*
@@ -34,7 +37,7 @@
34#define MAX_SHARE_SIZE 64 /* used to be 20, this should still be enough */ 37#define MAX_SHARE_SIZE 64 /* used to be 20, this should still be enough */
35#define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null 38#define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null
36 termination then *2 for unicode versions */ 39 termination then *2 for unicode versions */
37#define MAX_PASSWORD_SIZE 16 40#define MAX_PASSWORD_SIZE 512 /* max for windows seems to be 256 wide chars */
38 41
39#define CIFS_MIN_RCV_POOL 4 42#define CIFS_MIN_RCV_POOL 4
40 43
@@ -80,8 +83,7 @@ enum statusEnum {
80}; 83};
81 84
82enum securityEnum { 85enum securityEnum {
83 PLAINTXT = 0, /* Legacy with Plaintext passwords */ 86 LANMAN = 0, /* Legacy LANMAN auth */
84 LANMAN, /* Legacy LANMAN auth */
85 NTLM, /* Legacy NTLM012 auth with NTLM hash */ 87 NTLM, /* Legacy NTLM012 auth with NTLM hash */
86 NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ 88 NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
87 RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */ 89 RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */
@@ -142,7 +144,6 @@ struct TCP_Server_Info {
142 struct list_head pending_mid_q; 144 struct list_head pending_mid_q;
143 void *Server_NlsInfo; /* BB - placeholder for future NLS info */ 145 void *Server_NlsInfo; /* BB - placeholder for future NLS info */
144 unsigned short server_codepage; /* codepage for the server */ 146 unsigned short server_codepage; /* codepage for the server */
145 unsigned long ip_address; /* IP addr for the server if known */
146 enum protocolEnum protocolType; 147 enum protocolEnum protocolType;
147 char versionMajor; 148 char versionMajor;
148 char versionMinor; 149 char versionMinor;
@@ -190,19 +191,9 @@ struct TCP_Server_Info {
190 bool sec_mskerberos; /* supports legacy MS Kerberos */ 191 bool sec_mskerberos; /* supports legacy MS Kerberos */
191 bool sec_kerberosu2u; /* supports U2U Kerberos */ 192 bool sec_kerberosu2u; /* supports U2U Kerberos */
192 bool sec_ntlmssp; /* supports NTLMSSP */ 193 bool sec_ntlmssp; /* supports NTLMSSP */
193}; 194#ifdef CONFIG_CIFS_FSCACHE
194 195 struct fscache_cookie *fscache; /* client index cache cookie */
195/* 196#endif
196 * The following is our shortcut to user information. We surface the uid,
197 * and name. We always get the password on the fly in case it
198 * has changed. We also hang a list of sessions owned by this user off here.
199 */
200struct cifsUidInfo {
201 struct list_head userList;
202 struct list_head sessionList; /* SMB sessions for this user */
203 uid_t linux_uid;
204 char user[MAX_USERNAME_SIZE + 1]; /* ascii name of user */
205 /* BB may need ptr or callback for PAM or WinBind info */
206}; 197};
207 198
208/* 199/*
@@ -212,9 +203,6 @@ struct cifsSesInfo {
212 struct list_head smb_ses_list; 203 struct list_head smb_ses_list;
213 struct list_head tcon_list; 204 struct list_head tcon_list;
214 struct mutex session_mutex; 205 struct mutex session_mutex;
215#if 0
216 struct cifsUidInfo *uidInfo; /* pointer to user info */
217#endif
218 struct TCP_Server_Info *server; /* pointer to server info */ 206 struct TCP_Server_Info *server; /* pointer to server info */
219 int ses_count; /* reference counter */ 207 int ses_count; /* reference counter */
220 enum statusEnum status; 208 enum statusEnum status;
@@ -226,7 +214,8 @@ struct cifsSesInfo {
226 char *serverNOS; /* name of network operating system of server */ 214 char *serverNOS; /* name of network operating system of server */
227 char *serverDomain; /* security realm of server */ 215 char *serverDomain; /* security realm of server */
228 int Suid; /* remote smb uid */ 216 int Suid; /* remote smb uid */
229 uid_t linux_uid; /* local Linux uid */ 217 uid_t linux_uid; /* overriding owner of files on the mount */
218 uid_t cred_uid; /* owner of credentials */
230 int capabilities; 219 int capabilities;
231 char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for 220 char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
232 TCP names - will ipv6 and sctp addresses fit? */ 221 TCP names - will ipv6 and sctp addresses fit? */
@@ -311,6 +300,10 @@ struct cifsTconInfo {
311 bool local_lease:1; /* check leases (only) on local system not remote */ 300 bool local_lease:1; /* check leases (only) on local system not remote */
312 bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */ 301 bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */
313 bool need_reconnect:1; /* connection reset, tid now invalid */ 302 bool need_reconnect:1; /* connection reset, tid now invalid */
303#ifdef CONFIG_CIFS_FSCACHE
304 u64 resource_id; /* server resource id */
305 struct fscache_cookie *fscache; /* cookie for share */
306#endif
314 /* BB add field for back pointer to sb struct(s)? */ 307 /* BB add field for back pointer to sb struct(s)? */
315}; 308};
316 309
@@ -363,7 +356,7 @@ struct cifsFileInfo {
363 atomic_t count; /* reference count */ 356 atomic_t count; /* reference count */
364 struct mutex fh_mutex; /* prevents reopen race after dead ses*/ 357 struct mutex fh_mutex; /* prevents reopen race after dead ses*/
365 struct cifs_search_info srch_inf; 358 struct cifs_search_info srch_inf;
366 struct slow_work oplock_break; /* slow_work job for oplock breaks */ 359 struct work_struct oplock_break; /* work for oplock breaks */
367}; 360};
368 361
369/* Take a reference on the file private data */ 362/* Take a reference on the file private data */
@@ -398,6 +391,9 @@ struct cifsInodeInfo {
398 bool invalid_mapping:1; /* pagecache is invalid */ 391 bool invalid_mapping:1; /* pagecache is invalid */
399 u64 server_eof; /* current file size on server */ 392 u64 server_eof; /* current file size on server */
400 u64 uniqueid; /* server inode number */ 393 u64 uniqueid; /* server inode number */
394#ifdef CONFIG_CIFS_FSCACHE
395 struct fscache_cookie *fscache;
396#endif
401 struct inode vfs_inode; 397 struct inode vfs_inode;
402}; 398};
403 399
@@ -732,4 +728,10 @@ GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */
732GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */ 728GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */
733GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ 729GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/
734 730
731void cifs_oplock_break(struct work_struct *work);
732void cifs_oplock_break_get(struct cifsFileInfo *cfile);
733void cifs_oplock_break_put(struct cifsFileInfo *cfile);
734
735extern const struct slow_work_ops cifs_oplock_break_ops; 735extern const struct slow_work_ops cifs_oplock_break_ops;
736
737#endif /* _CIFS_GLOB_H */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index fb1657e0fdb8..1f5450814087 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -86,7 +86,9 @@ extern unsigned int smbCalcSize(struct smb_hdr *ptr);
86extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); 86extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
87extern int decode_negTokenInit(unsigned char *security_blob, int length, 87extern int decode_negTokenInit(unsigned char *security_blob, int length,
88 struct TCP_Server_Info *server); 88 struct TCP_Server_Info *server);
89extern int cifs_convert_address(char *src, void *dst); 89extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len);
90extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len,
91 unsigned short int port);
90extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); 92extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr);
91extern void header_assemble(struct smb_hdr *, char /* command */ , 93extern void header_assemble(struct smb_hdr *, char /* command */ ,
92 const struct cifsTconInfo *, int /* length of 94 const struct cifsTconInfo *, int /* length of
@@ -106,7 +108,6 @@ extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode,
106 __u16 fileHandle, struct file *file, 108 __u16 fileHandle, struct file *file,
107 struct vfsmount *mnt, unsigned int oflags); 109 struct vfsmount *mnt, unsigned int oflags);
108extern int cifs_posix_open(char *full_path, struct inode **pinode, 110extern int cifs_posix_open(char *full_path, struct inode **pinode,
109 struct vfsmount *mnt,
110 struct super_block *sb, 111 struct super_block *sb,
111 int mode, int oflags, 112 int mode, int oflags,
112 __u32 *poplock, __u16 *pnetfid, int xid); 113 __u32 *poplock, __u16 *pnetfid, int xid);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 2208f06e4c45..95c2ea67edfb 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -48,6 +48,7 @@
48#include "nterr.h" 48#include "nterr.h"
49#include "rfc1002pdu.h" 49#include "rfc1002pdu.h"
50#include "cn_cifs.h" 50#include "cn_cifs.h"
51#include "fscache.h"
51 52
52#define CIFS_PORT 445 53#define CIFS_PORT 445
53#define RFC1001_PORT 139 54#define RFC1001_PORT 139
@@ -66,6 +67,7 @@ struct smb_vol {
66 char *iocharset; /* local code page for mapping to and from Unicode */ 67 char *iocharset; /* local code page for mapping to and from Unicode */
67 char source_rfc1001_name[16]; /* netbios name of client */ 68 char source_rfc1001_name[16]; /* netbios name of client */
68 char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */ 69 char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */
70 uid_t cred_uid;
69 uid_t linux_uid; 71 uid_t linux_uid;
70 gid_t linux_gid; 72 gid_t linux_gid;
71 mode_t file_mode; 73 mode_t file_mode;
@@ -97,6 +99,7 @@ struct smb_vol {
97 bool noblocksnd:1; 99 bool noblocksnd:1;
98 bool noautotune:1; 100 bool noautotune:1;
99 bool nostrictsync:1; /* do not force expensive SMBflush on every sync */ 101 bool nostrictsync:1; /* do not force expensive SMBflush on every sync */
102 bool fsc:1; /* enable fscache */
100 unsigned int rsize; 103 unsigned int rsize;
101 unsigned int wsize; 104 unsigned int wsize;
102 bool sockopt_tcp_nodelay:1; 105 bool sockopt_tcp_nodelay:1;
@@ -830,7 +833,8 @@ cifs_parse_mount_options(char *options, const char *devname,
830 /* null target name indicates to use *SMBSERVR default called name 833 /* null target name indicates to use *SMBSERVR default called name
831 if we end up sending RFC1001 session initialize */ 834 if we end up sending RFC1001 session initialize */
832 vol->target_rfc1001_name[0] = 0; 835 vol->target_rfc1001_name[0] = 0;
833 vol->linux_uid = current_uid(); /* use current_euid() instead? */ 836 vol->cred_uid = current_uid();
837 vol->linux_uid = current_uid();
834 vol->linux_gid = current_gid(); 838 vol->linux_gid = current_gid();
835 839
836 /* default to only allowing write access to owner of the mount */ 840 /* default to only allowing write access to owner of the mount */
@@ -1257,6 +1261,12 @@ cifs_parse_mount_options(char *options, const char *devname,
1257 } else if ((strnicmp(data, "nocase", 6) == 0) || 1261 } else if ((strnicmp(data, "nocase", 6) == 0) ||
1258 (strnicmp(data, "ignorecase", 10) == 0)) { 1262 (strnicmp(data, "ignorecase", 10) == 0)) {
1259 vol->nocase = 1; 1263 vol->nocase = 1;
1264 } else if (strnicmp(data, "mand", 4) == 0) {
1265 /* ignore */
1266 } else if (strnicmp(data, "nomand", 6) == 0) {
1267 /* ignore */
1268 } else if (strnicmp(data, "_netdev", 7) == 0) {
1269 /* ignore */
1260 } else if (strnicmp(data, "brl", 3) == 0) { 1270 } else if (strnicmp(data, "brl", 3) == 0) {
1261 vol->nobrl = 0; 1271 vol->nobrl = 0;
1262 } else if ((strnicmp(data, "nobrl", 5) == 0) || 1272 } else if ((strnicmp(data, "nobrl", 5) == 0) ||
@@ -1331,6 +1341,8 @@ cifs_parse_mount_options(char *options, const char *devname,
1331 printk(KERN_WARNING "CIFS: Mount option noac not " 1341 printk(KERN_WARNING "CIFS: Mount option noac not "
1332 "supported. Instead set " 1342 "supported. Instead set "
1333 "/proc/fs/cifs/LookupCacheEnabled to 0\n"); 1343 "/proc/fs/cifs/LookupCacheEnabled to 0\n");
1344 } else if (strnicmp(data, "fsc", 3) == 0) {
1345 vol->fsc = true;
1334 } else 1346 } else
1335 printk(KERN_WARNING "CIFS: Unknown mount option %s\n", 1347 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
1336 data); 1348 data);
@@ -1380,18 +1392,92 @@ cifs_parse_mount_options(char *options, const char *devname,
1380 return 0; 1392 return 0;
1381} 1393}
1382 1394
1395static bool
1396match_address(struct TCP_Server_Info *server, struct sockaddr *addr)
1397{
1398 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
1399 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
1400
1401 switch (addr->sa_family) {
1402 case AF_INET:
1403 if (addr4->sin_addr.s_addr !=
1404 server->addr.sockAddr.sin_addr.s_addr)
1405 return false;
1406 if (addr4->sin_port &&
1407 addr4->sin_port != server->addr.sockAddr.sin_port)
1408 return false;
1409 break;
1410 case AF_INET6:
1411 if (!ipv6_addr_equal(&addr6->sin6_addr,
1412 &server->addr.sockAddr6.sin6_addr))
1413 return false;
1414 if (addr6->sin6_scope_id !=
1415 server->addr.sockAddr6.sin6_scope_id)
1416 return false;
1417 if (addr6->sin6_port &&
1418 addr6->sin6_port != server->addr.sockAddr6.sin6_port)
1419 return false;
1420 break;
1421 }
1422
1423 return true;
1424}
1425
1426static bool
1427match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
1428{
1429 unsigned int secFlags;
1430
1431 if (vol->secFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
1432 secFlags = vol->secFlg;
1433 else
1434 secFlags = global_secflags | vol->secFlg;
1435
1436 switch (server->secType) {
1437 case LANMAN:
1438 if (!(secFlags & (CIFSSEC_MAY_LANMAN|CIFSSEC_MAY_PLNTXT)))
1439 return false;
1440 break;
1441 case NTLMv2:
1442 if (!(secFlags & CIFSSEC_MAY_NTLMV2))
1443 return false;
1444 break;
1445 case NTLM:
1446 if (!(secFlags & CIFSSEC_MAY_NTLM))
1447 return false;
1448 break;
1449 case Kerberos:
1450 if (!(secFlags & CIFSSEC_MAY_KRB5))
1451 return false;
1452 break;
1453 case RawNTLMSSP:
1454 if (!(secFlags & CIFSSEC_MAY_NTLMSSP))
1455 return false;
1456 break;
1457 default:
1458 /* shouldn't happen */
1459 return false;
1460 }
1461
1462 /* now check if signing mode is acceptible */
1463 if ((secFlags & CIFSSEC_MAY_SIGN) == 0 &&
1464 (server->secMode & SECMODE_SIGN_REQUIRED))
1465 return false;
1466 else if (((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) &&
1467 (server->secMode &
1468 (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)) == 0)
1469 return false;
1470
1471 return true;
1472}
1473
1383static struct TCP_Server_Info * 1474static struct TCP_Server_Info *
1384cifs_find_tcp_session(struct sockaddr_storage *addr, unsigned short int port) 1475cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol)
1385{ 1476{
1386 struct list_head *tmp;
1387 struct TCP_Server_Info *server; 1477 struct TCP_Server_Info *server;
1388 struct sockaddr_in *addr4 = (struct sockaddr_in *) addr;
1389 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) addr;
1390 1478
1391 write_lock(&cifs_tcp_ses_lock); 1479 write_lock(&cifs_tcp_ses_lock);
1392 list_for_each(tmp, &cifs_tcp_ses_list) { 1480 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
1393 server = list_entry(tmp, struct TCP_Server_Info,
1394 tcp_ses_list);
1395 /* 1481 /*
1396 * the demux thread can exit on its own while still in CifsNew 1482 * the demux thread can exit on its own while still in CifsNew
1397 * so don't accept any sockets in that state. Since the 1483 * so don't accept any sockets in that state. Since the
@@ -1401,37 +1487,11 @@ cifs_find_tcp_session(struct sockaddr_storage *addr, unsigned short int port)
1401 if (server->tcpStatus == CifsNew) 1487 if (server->tcpStatus == CifsNew)
1402 continue; 1488 continue;
1403 1489
1404 switch (addr->ss_family) { 1490 if (!match_address(server, addr))
1405 case AF_INET: 1491 continue;
1406 if (addr4->sin_addr.s_addr ==
1407 server->addr.sockAddr.sin_addr.s_addr) {
1408 addr4->sin_port = htons(port);
1409 /* user overrode default port? */
1410 if (addr4->sin_port) {
1411 if (addr4->sin_port !=
1412 server->addr.sockAddr.sin_port)
1413 continue;
1414 }
1415 break;
1416 } else
1417 continue;
1418 1492
1419 case AF_INET6: 1493 if (!match_security(server, vol))
1420 if (ipv6_addr_equal(&addr6->sin6_addr, 1494 continue;
1421 &server->addr.sockAddr6.sin6_addr) &&
1422 (addr6->sin6_scope_id ==
1423 server->addr.sockAddr6.sin6_scope_id)) {
1424 addr6->sin6_port = htons(port);
1425 /* user overrode default port? */
1426 if (addr6->sin6_port) {
1427 if (addr6->sin6_port !=
1428 server->addr.sockAddr6.sin6_port)
1429 continue;
1430 }
1431 break;
1432 } else
1433 continue;
1434 }
1435 1495
1436 ++server->srv_count; 1496 ++server->srv_count;
1437 write_unlock(&cifs_tcp_ses_lock); 1497 write_unlock(&cifs_tcp_ses_lock);
@@ -1460,6 +1520,8 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
1460 server->tcpStatus = CifsExiting; 1520 server->tcpStatus = CifsExiting;
1461 spin_unlock(&GlobalMid_Lock); 1521 spin_unlock(&GlobalMid_Lock);
1462 1522
1523 cifs_fscache_release_client_cookie(server);
1524
1463 task = xchg(&server->tsk, NULL); 1525 task = xchg(&server->tsk, NULL);
1464 if (task) 1526 if (task)
1465 force_sig(SIGKILL, task); 1527 force_sig(SIGKILL, task);
@@ -1479,7 +1541,10 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
1479 cFYI(1, "UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip); 1541 cFYI(1, "UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip);
1480 1542
1481 if (volume_info->UNCip && volume_info->UNC) { 1543 if (volume_info->UNCip && volume_info->UNC) {
1482 rc = cifs_convert_address(volume_info->UNCip, &addr); 1544 rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
1545 volume_info->UNCip,
1546 strlen(volume_info->UNCip),
1547 volume_info->port);
1483 if (!rc) { 1548 if (!rc) {
1484 /* we failed translating address */ 1549 /* we failed translating address */
1485 rc = -EINVAL; 1550 rc = -EINVAL;
@@ -1499,7 +1564,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
1499 } 1564 }
1500 1565
1501 /* see if we already have a matching tcp_ses */ 1566 /* see if we already have a matching tcp_ses */
1502 tcp_ses = cifs_find_tcp_session(&addr, volume_info->port); 1567 tcp_ses = cifs_find_tcp_session((struct sockaddr *)&addr, volume_info);
1503 if (tcp_ses) 1568 if (tcp_ses)
1504 return tcp_ses; 1569 return tcp_ses;
1505 1570
@@ -1543,12 +1608,10 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
1543 cFYI(1, "attempting ipv6 connect"); 1608 cFYI(1, "attempting ipv6 connect");
1544 /* BB should we allow ipv6 on port 139? */ 1609 /* BB should we allow ipv6 on port 139? */
1545 /* other OS never observed in Wild doing 139 with v6 */ 1610 /* other OS never observed in Wild doing 139 with v6 */
1546 sin_server6->sin6_port = htons(volume_info->port);
1547 memcpy(&tcp_ses->addr.sockAddr6, sin_server6, 1611 memcpy(&tcp_ses->addr.sockAddr6, sin_server6,
1548 sizeof(struct sockaddr_in6)); 1612 sizeof(struct sockaddr_in6));
1549 rc = ipv6_connect(tcp_ses); 1613 rc = ipv6_connect(tcp_ses);
1550 } else { 1614 } else {
1551 sin_server->sin_port = htons(volume_info->port);
1552 memcpy(&tcp_ses->addr.sockAddr, sin_server, 1615 memcpy(&tcp_ses->addr.sockAddr, sin_server,
1553 sizeof(struct sockaddr_in)); 1616 sizeof(struct sockaddr_in));
1554 rc = ipv4_connect(tcp_ses); 1617 rc = ipv4_connect(tcp_ses);
@@ -1577,6 +1640,8 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
1577 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list); 1640 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
1578 write_unlock(&cifs_tcp_ses_lock); 1641 write_unlock(&cifs_tcp_ses_lock);
1579 1642
1643 cifs_fscache_get_client_cookie(tcp_ses);
1644
1580 return tcp_ses; 1645 return tcp_ses;
1581 1646
1582out_err: 1647out_err:
@@ -1591,17 +1656,27 @@ out_err:
1591} 1656}
1592 1657
1593static struct cifsSesInfo * 1658static struct cifsSesInfo *
1594cifs_find_smb_ses(struct TCP_Server_Info *server, char *username) 1659cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
1595{ 1660{
1596 struct list_head *tmp;
1597 struct cifsSesInfo *ses; 1661 struct cifsSesInfo *ses;
1598 1662
1599 write_lock(&cifs_tcp_ses_lock); 1663 write_lock(&cifs_tcp_ses_lock);
1600 list_for_each(tmp, &server->smb_ses_list) { 1664 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
1601 ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list); 1665 switch (server->secType) {
1602 if (strncmp(ses->userName, username, MAX_USERNAME_SIZE)) 1666 case Kerberos:
1603 continue; 1667 if (vol->cred_uid != ses->cred_uid)
1604 1668 continue;
1669 break;
1670 default:
1671 /* anything else takes username/password */
1672 if (strncmp(ses->userName, vol->username,
1673 MAX_USERNAME_SIZE))
1674 continue;
1675 if (strlen(vol->username) != 0 &&
1676 strncmp(ses->password, vol->password,
1677 MAX_PASSWORD_SIZE))
1678 continue;
1679 }
1605 ++ses->ses_count; 1680 ++ses->ses_count;
1606 write_unlock(&cifs_tcp_ses_lock); 1681 write_unlock(&cifs_tcp_ses_lock);
1607 return ses; 1682 return ses;
@@ -1643,7 +1718,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
1643 1718
1644 xid = GetXid(); 1719 xid = GetXid();
1645 1720
1646 ses = cifs_find_smb_ses(server, volume_info->username); 1721 ses = cifs_find_smb_ses(server, volume_info);
1647 if (ses) { 1722 if (ses) {
1648 cFYI(1, "Existing smb sess found (status=%d)", ses->status); 1723 cFYI(1, "Existing smb sess found (status=%d)", ses->status);
1649 1724
@@ -1706,6 +1781,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
1706 if (ses->domainName) 1781 if (ses->domainName)
1707 strcpy(ses->domainName, volume_info->domainname); 1782 strcpy(ses->domainName, volume_info->domainname);
1708 } 1783 }
1784 ses->cred_uid = volume_info->cred_uid;
1709 ses->linux_uid = volume_info->linux_uid; 1785 ses->linux_uid = volume_info->linux_uid;
1710 ses->overrideSecFlg = volume_info->secFlg; 1786 ses->overrideSecFlg = volume_info->secFlg;
1711 1787
@@ -1773,6 +1849,7 @@ cifs_put_tcon(struct cifsTconInfo *tcon)
1773 CIFSSMBTDis(xid, tcon); 1849 CIFSSMBTDis(xid, tcon);
1774 _FreeXid(xid); 1850 _FreeXid(xid);
1775 1851
1852 cifs_fscache_release_super_cookie(tcon);
1776 tconInfoFree(tcon); 1853 tconInfoFree(tcon);
1777 cifs_put_smb_ses(ses); 1854 cifs_put_smb_ses(ses);
1778} 1855}
@@ -1843,6 +1920,8 @@ cifs_get_tcon(struct cifsSesInfo *ses, struct smb_vol *volume_info)
1843 list_add(&tcon->tcon_list, &ses->tcon_list); 1920 list_add(&tcon->tcon_list, &ses->tcon_list);
1844 write_unlock(&cifs_tcp_ses_lock); 1921 write_unlock(&cifs_tcp_ses_lock);
1845 1922
1923 cifs_fscache_get_super_cookie(tcon);
1924
1846 return tcon; 1925 return tcon;
1847 1926
1848out_fail: 1927out_fail:
@@ -2397,6 +2476,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
2397 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID; 2476 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
2398 if (pvolume_info->dynperm) 2477 if (pvolume_info->dynperm)
2399 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM; 2478 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
2479 if (pvolume_info->fsc)
2480 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
2400 if (pvolume_info->direct_io) { 2481 if (pvolume_info->direct_io) {
2401 cFYI(1, "mounting share using direct i/o"); 2482 cFYI(1, "mounting share using direct i/o");
2402 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; 2483 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 391816b461ca..578d88c5b46e 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -25,6 +25,7 @@
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/namei.h> 26#include <linux/namei.h>
27#include <linux/mount.h> 27#include <linux/mount.h>
28#include <linux/file.h>
28#include "cifsfs.h" 29#include "cifsfs.h"
29#include "cifspdu.h" 30#include "cifspdu.h"
30#include "cifsglob.h" 31#include "cifsglob.h"
@@ -129,12 +130,6 @@ cifs_bp_rename_retry:
129 return full_path; 130 return full_path;
130} 131}
131 132
132/*
133 * When called with struct file pointer set to NULL, there is no way we could
134 * update file->private_data, but getting it stuck on openFileList provides a
135 * way to access it from cifs_fill_filedata and thereby set file->private_data
136 * from cifs_open.
137 */
138struct cifsFileInfo * 133struct cifsFileInfo *
139cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, 134cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
140 struct file *file, struct vfsmount *mnt, unsigned int oflags) 135 struct file *file, struct vfsmount *mnt, unsigned int oflags)
@@ -162,7 +157,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
162 mutex_init(&pCifsFile->lock_mutex); 157 mutex_init(&pCifsFile->lock_mutex);
163 INIT_LIST_HEAD(&pCifsFile->llist); 158 INIT_LIST_HEAD(&pCifsFile->llist);
164 atomic_set(&pCifsFile->count, 1); 159 atomic_set(&pCifsFile->count, 1);
165 slow_work_init(&pCifsFile->oplock_break, &cifs_oplock_break_ops); 160 INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break);
166 161
167 write_lock(&GlobalSMBSeslock); 162 write_lock(&GlobalSMBSeslock);
168 list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList); 163 list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
@@ -184,12 +179,13 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
184 } 179 }
185 write_unlock(&GlobalSMBSeslock); 180 write_unlock(&GlobalSMBSeslock);
186 181
182 file->private_data = pCifsFile;
183
187 return pCifsFile; 184 return pCifsFile;
188} 185}
189 186
190int cifs_posix_open(char *full_path, struct inode **pinode, 187int cifs_posix_open(char *full_path, struct inode **pinode,
191 struct vfsmount *mnt, struct super_block *sb, 188 struct super_block *sb, int mode, int oflags,
192 int mode, int oflags,
193 __u32 *poplock, __u16 *pnetfid, int xid) 189 __u32 *poplock, __u16 *pnetfid, int xid)
194{ 190{
195 int rc; 191 int rc;
@@ -258,19 +254,6 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
258 cifs_fattr_to_inode(*pinode, &fattr); 254 cifs_fattr_to_inode(*pinode, &fattr);
259 } 255 }
260 256
261 /*
262 * cifs_fill_filedata() takes care of setting cifsFileInfo pointer to
263 * file->private_data.
264 */
265 if (mnt) {
266 struct cifsFileInfo *pfile_info;
267
268 pfile_info = cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt,
269 oflags);
270 if (pfile_info == NULL)
271 rc = -ENOMEM;
272 }
273
274posix_open_ret: 257posix_open_ret:
275 kfree(presp_data); 258 kfree(presp_data);
276 return rc; 259 return rc;
@@ -298,7 +281,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
298 int create_options = CREATE_NOT_DIR; 281 int create_options = CREATE_NOT_DIR;
299 __u32 oplock = 0; 282 __u32 oplock = 0;
300 int oflags; 283 int oflags;
301 bool posix_create = false;
302 /* 284 /*
303 * BB below access is probably too much for mknod to request 285 * BB below access is probably too much for mknod to request
304 * but we have to do query and setpathinfo so requesting 286 * but we have to do query and setpathinfo so requesting
@@ -339,7 +321,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
339 (CIFS_UNIX_POSIX_PATH_OPS_CAP & 321 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
340 le64_to_cpu(tcon->fsUnixInfo.Capability))) { 322 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
341 rc = cifs_posix_open(full_path, &newinode, 323 rc = cifs_posix_open(full_path, &newinode,
342 nd ? nd->path.mnt : NULL,
343 inode->i_sb, mode, oflags, &oplock, &fileHandle, xid); 324 inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
344 /* EIO could indicate that (posix open) operation is not 325 /* EIO could indicate that (posix open) operation is not
345 supported, despite what server claimed in capability 326 supported, despite what server claimed in capability
@@ -347,7 +328,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
347 handled in posix open */ 328 handled in posix open */
348 329
349 if (rc == 0) { 330 if (rc == 0) {
350 posix_create = true;
351 if (newinode == NULL) /* query inode info */ 331 if (newinode == NULL) /* query inode info */
352 goto cifs_create_get_file_info; 332 goto cifs_create_get_file_info;
353 else /* success, no need to query */ 333 else /* success, no need to query */
@@ -478,21 +458,28 @@ cifs_create_set_dentry:
478 else 458 else
479 cFYI(1, "Create worked, get_inode_info failed rc = %d", rc); 459 cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
480 460
481 /* nfsd case - nfs srv does not set nd */ 461 if (newinode && nd && (nd->flags & LOOKUP_OPEN)) {
482 if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
483 /* mknod case - do not leave file open */
484 CIFSSMBClose(xid, tcon, fileHandle);
485 } else if (!(posix_create) && (newinode)) {
486 struct cifsFileInfo *pfile_info; 462 struct cifsFileInfo *pfile_info;
487 /* 463 struct file *filp;
488 * cifs_fill_filedata() takes care of setting cifsFileInfo 464
489 * pointer to file->private_data. 465 filp = lookup_instantiate_filp(nd, direntry, generic_file_open);
490 */ 466 if (IS_ERR(filp)) {
491 pfile_info = cifs_new_fileinfo(newinode, fileHandle, NULL, 467 rc = PTR_ERR(filp);
468 CIFSSMBClose(xid, tcon, fileHandle);
469 goto cifs_create_out;
470 }
471
472 pfile_info = cifs_new_fileinfo(newinode, fileHandle, filp,
492 nd->path.mnt, oflags); 473 nd->path.mnt, oflags);
493 if (pfile_info == NULL) 474 if (pfile_info == NULL) {
475 fput(filp);
476 CIFSSMBClose(xid, tcon, fileHandle);
494 rc = -ENOMEM; 477 rc = -ENOMEM;
478 }
479 } else {
480 CIFSSMBClose(xid, tcon, fileHandle);
495 } 481 }
482
496cifs_create_out: 483cifs_create_out:
497 kfree(buf); 484 kfree(buf);
498 kfree(full_path); 485 kfree(full_path);
@@ -636,6 +623,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
636 bool posix_open = false; 623 bool posix_open = false;
637 struct cifs_sb_info *cifs_sb; 624 struct cifs_sb_info *cifs_sb;
638 struct cifsTconInfo *pTcon; 625 struct cifsTconInfo *pTcon;
626 struct cifsFileInfo *cfile;
639 struct inode *newInode = NULL; 627 struct inode *newInode = NULL;
640 char *full_path = NULL; 628 char *full_path = NULL;
641 struct file *filp; 629 struct file *filp;
@@ -703,7 +691,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
703 if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) && 691 if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
704 (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && 692 (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
705 (nd->intent.open.flags & O_CREAT)) { 693 (nd->intent.open.flags & O_CREAT)) {
706 rc = cifs_posix_open(full_path, &newInode, nd->path.mnt, 694 rc = cifs_posix_open(full_path, &newInode,
707 parent_dir_inode->i_sb, 695 parent_dir_inode->i_sb,
708 nd->intent.open.create_mode, 696 nd->intent.open.create_mode,
709 nd->intent.open.flags, &oplock, 697 nd->intent.open.flags, &oplock,
@@ -733,8 +721,25 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
733 else 721 else
734 direntry->d_op = &cifs_dentry_ops; 722 direntry->d_op = &cifs_dentry_ops;
735 d_add(direntry, newInode); 723 d_add(direntry, newInode);
736 if (posix_open) 724 if (posix_open) {
737 filp = lookup_instantiate_filp(nd, direntry, NULL); 725 filp = lookup_instantiate_filp(nd, direntry,
726 generic_file_open);
727 if (IS_ERR(filp)) {
728 rc = PTR_ERR(filp);
729 CIFSSMBClose(xid, pTcon, fileHandle);
730 goto lookup_out;
731 }
732
733 cfile = cifs_new_fileinfo(newInode, fileHandle, filp,
734 nd->path.mnt,
735 nd->intent.open.flags);
736 if (cfile == NULL) {
737 fput(filp);
738 CIFSSMBClose(xid, pTcon, fileHandle);
739 rc = -ENOMEM;
740 goto lookup_out;
741 }
742 }
738 /* since paths are not looked up by component - the parent 743 /* since paths are not looked up by component - the parent
739 directories are presumed to be good here */ 744 directories are presumed to be good here */
740 renew_parental_timestamps(direntry); 745 renew_parental_timestamps(direntry);
@@ -755,6 +760,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
755 is a common return code */ 760 is a common return code */
756 } 761 }
757 762
763lookup_out:
758 kfree(full_path); 764 kfree(full_path);
759 FreeXid(xid); 765 FreeXid(xid);
760 return ERR_PTR(rc); 766 return ERR_PTR(rc);
diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c
index 4db2c5e7283f..0eb87026cad3 100644
--- a/fs/cifs/dns_resolve.c
+++ b/fs/cifs/dns_resolve.c
@@ -4,6 +4,8 @@
4 * Copyright (c) 2007 Igor Mammedov 4 * Copyright (c) 2007 Igor Mammedov
5 * Author(s): Igor Mammedov (niallain@gmail.com) 5 * Author(s): Igor Mammedov (niallain@gmail.com)
6 * Steve French (sfrench@us.ibm.com) 6 * Steve French (sfrench@us.ibm.com)
7 * Wang Lei (wang840925@gmail.com)
8 * David Howells (dhowells@redhat.com)
7 * 9 *
8 * Contains the CIFS DFS upcall routines used for hostname to 10 * Contains the CIFS DFS upcall routines used for hostname to
9 * IP address translation. 11 * IP address translation.
@@ -24,145 +26,73 @@
24 */ 26 */
25 27
26#include <linux/slab.h> 28#include <linux/slab.h>
27#include <keys/user-type.h> 29#include <linux/dns_resolver.h>
28#include "dns_resolve.h" 30#include "dns_resolve.h"
29#include "cifsglob.h" 31#include "cifsglob.h"
30#include "cifsproto.h" 32#include "cifsproto.h"
31#include "cifs_debug.h" 33#include "cifs_debug.h"
32 34
33/* Checks if supplied name is IP address 35/**
34 * returns: 36 * dns_resolve_server_name_to_ip - Resolve UNC server name to ip address.
35 * 1 - name is IP 37 * @unc: UNC path specifying the server
36 * 0 - name is not IP 38 * @ip_addr: Where to return the IP address.
37 */ 39 *
38static int 40 * The IP address will be returned in string form, and the caller is
39is_ip(char *name) 41 * responsible for freeing it.
40{ 42 *
41 struct sockaddr_storage ss; 43 * Returns length of result on success, -ve on error.
42
43 return cifs_convert_address(name, &ss);
44}
45
46static int
47dns_resolver_instantiate(struct key *key, const void *data,
48 size_t datalen)
49{
50 int rc = 0;
51 char *ip;
52
53 ip = kmalloc(datalen + 1, GFP_KERNEL);
54 if (!ip)
55 return -ENOMEM;
56
57 memcpy(ip, data, datalen);
58 ip[datalen] = '\0';
59
60 /* make sure this looks like an address */
61 if (!is_ip(ip)) {
62 kfree(ip);
63 return -EINVAL;
64 }
65
66 key->type_data.x[0] = datalen;
67 key->payload.data = ip;
68
69 return rc;
70}
71
72static void
73dns_resolver_destroy(struct key *key)
74{
75 kfree(key->payload.data);
76}
77
78struct key_type key_type_dns_resolver = {
79 .name = "dns_resolver",
80 .def_datalen = sizeof(struct in_addr),
81 .describe = user_describe,
82 .instantiate = dns_resolver_instantiate,
83 .destroy = dns_resolver_destroy,
84 .match = user_match,
85};
86
87/* Resolves server name to ip address.
88 * input:
89 * unc - server UNC
90 * output:
91 * *ip_addr - pointer to server ip, caller responcible for freeing it.
92 * return 0 on success
93 */ 44 */
94int 45int
95dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) 46dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
96{ 47{
97 int rc = -EAGAIN; 48 struct sockaddr_storage ss;
98 struct key *rkey = ERR_PTR(-EAGAIN); 49 const char *hostname, *sep;
99 char *name; 50 char *name;
100 char *data = NULL; 51 int len, rc;
101 int len;
102 52
103 if (!ip_addr || !unc) 53 if (!ip_addr || !unc)
104 return -EINVAL; 54 return -EINVAL;
105 55
106 /* search for server name delimiter */
107 len = strlen(unc); 56 len = strlen(unc);
108 if (len < 3) { 57 if (len < 3) {
109 cFYI(1, "%s: unc is too short: %s", __func__, unc); 58 cFYI(1, "%s: unc is too short: %s", __func__, unc);
110 return -EINVAL; 59 return -EINVAL;
111 } 60 }
61
62 /* Discount leading slashes for cifs */
112 len -= 2; 63 len -= 2;
113 name = memchr(unc+2, '\\', len); 64 hostname = unc + 2;
114 if (!name) { 65
66 /* Search for server name delimiter */
67 sep = memchr(hostname, '\\', len);
68 if (sep)
69 len = sep - unc;
70 else
115 cFYI(1, "%s: probably server name is whole unc: %s", 71 cFYI(1, "%s: probably server name is whole unc: %s",
116 __func__, unc); 72 __func__, unc);
117 } else { 73
118 len = (name - unc) - 2/* leading // */; 74 /* Try to interpret hostname as an IPv4 or IPv6 address */
119 } 75 rc = cifs_convert_address((struct sockaddr *)&ss, hostname, len);
76 if (rc > 0)
77 goto name_is_IP_address;
78
79 /* Perform the upcall */
80 rc = dns_query(NULL, hostname, len, NULL, ip_addr, NULL);
81 if (rc < 0)
82 cERROR(1, "%s: unable to resolve: %*.*s",
83 __func__, len, len, hostname);
84 else
85 cFYI(1, "%s: resolved: %*.*s to %s",
86 __func__, len, len, hostname, *ip_addr);
87 return rc;
120 88
121 name = kmalloc(len+1, GFP_KERNEL); 89name_is_IP_address:
122 if (!name) { 90 name = kmalloc(len + 1, GFP_KERNEL);
123 rc = -ENOMEM; 91 if (!name)
124 return rc; 92 return -ENOMEM;
125 } 93 memcpy(name, hostname, len);
126 memcpy(name, unc+2, len);
127 name[len] = 0; 94 name[len] = 0;
128 95 cFYI(1, "%s: unc is IP, skipping dns upcall: %s", __func__, name);
129 if (is_ip(name)) { 96 *ip_addr = name;
130 cFYI(1, "%s: it is IP, skipping dns upcall: %s", 97 return 0;
131 __func__, name);
132 data = name;
133 goto skip_upcall;
134 }
135
136 rkey = request_key(&key_type_dns_resolver, name, "");
137 if (!IS_ERR(rkey)) {
138 len = rkey->type_data.x[0];
139 data = rkey->payload.data;
140 } else {
141 cERROR(1, "%s: unable to resolve: %s", __func__, name);
142 goto out;
143 }
144
145skip_upcall:
146 if (data) {
147 *ip_addr = kmalloc(len + 1, GFP_KERNEL);
148 if (*ip_addr) {
149 memcpy(*ip_addr, data, len + 1);
150 if (!IS_ERR(rkey))
151 cFYI(1, "%s: resolved: %s to %s", __func__,
152 name,
153 *ip_addr
154 );
155 rc = 0;
156 } else {
157 rc = -ENOMEM;
158 }
159 if (!IS_ERR(rkey))
160 key_put(rkey);
161 }
162
163out:
164 kfree(name);
165 return rc;
166} 98}
167
168
diff --git a/fs/cifs/dns_resolve.h b/fs/cifs/dns_resolve.h
index 966e9288930b..d3f5d27f4d06 100644
--- a/fs/cifs/dns_resolve.h
+++ b/fs/cifs/dns_resolve.h
@@ -24,8 +24,6 @@
24#define _DNS_RESOLVE_H 24#define _DNS_RESOLVE_H
25 25
26#ifdef __KERNEL__ 26#ifdef __KERNEL__
27#include <linux/key-type.h>
28extern struct key_type key_type_dns_resolver;
29extern int dns_resolve_server_name_to_ip(const char *unc, char **ip_addr); 27extern int dns_resolve_server_name_to_ip(const char *unc, char **ip_addr);
30#endif /* KERNEL */ 28#endif /* KERNEL */
31 29
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index f1ff785b2292..db11fdef0e92 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -40,6 +40,7 @@
40#include "cifs_unicode.h" 40#include "cifs_unicode.h"
41#include "cifs_debug.h" 41#include "cifs_debug.h"
42#include "cifs_fs_sb.h" 42#include "cifs_fs_sb.h"
43#include "fscache.h"
43 44
44static inline int cifs_convert_flags(unsigned int flags) 45static inline int cifs_convert_flags(unsigned int flags)
45{ 46{
@@ -162,44 +163,12 @@ psx_client_can_cache:
162 return 0; 163 return 0;
163} 164}
164 165
165static struct cifsFileInfo *
166cifs_fill_filedata(struct file *file)
167{
168 struct list_head *tmp;
169 struct cifsFileInfo *pCifsFile = NULL;
170 struct cifsInodeInfo *pCifsInode = NULL;
171
172 /* search inode for this file and fill in file->private_data */
173 pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
174 read_lock(&GlobalSMBSeslock);
175 list_for_each(tmp, &pCifsInode->openFileList) {
176 pCifsFile = list_entry(tmp, struct cifsFileInfo, flist);
177 if ((pCifsFile->pfile == NULL) &&
178 (pCifsFile->pid == current->tgid)) {
179 /* mode set in cifs_create */
180
181 /* needed for writepage */
182 pCifsFile->pfile = file;
183 file->private_data = pCifsFile;
184 break;
185 }
186 }
187 read_unlock(&GlobalSMBSeslock);
188
189 if (file->private_data != NULL) {
190 return pCifsFile;
191 } else if ((file->f_flags & O_CREAT) && (file->f_flags & O_EXCL))
192 cERROR(1, "could not find file instance for "
193 "new file %p", file);
194 return NULL;
195}
196
197/* all arguments to this function must be checked for validity in caller */ 166/* all arguments to this function must be checked for validity in caller */
198static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, 167static inline int cifs_open_inode_helper(struct inode *inode,
199 struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile,
200 struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf, 168 struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf,
201 char *full_path, int xid) 169 char *full_path, int xid)
202{ 170{
171 struct cifsInodeInfo *pCifsInode = CIFS_I(inode);
203 struct timespec temp; 172 struct timespec temp;
204 int rc; 173 int rc;
205 174
@@ -213,36 +182,35 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
213 /* if not oplocked, invalidate inode pages if mtime or file 182 /* if not oplocked, invalidate inode pages if mtime or file
214 size changed */ 183 size changed */
215 temp = cifs_NTtimeToUnix(buf->LastWriteTime); 184 temp = cifs_NTtimeToUnix(buf->LastWriteTime);
216 if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) && 185 if (timespec_equal(&inode->i_mtime, &temp) &&
217 (file->f_path.dentry->d_inode->i_size == 186 (inode->i_size ==
218 (loff_t)le64_to_cpu(buf->EndOfFile))) { 187 (loff_t)le64_to_cpu(buf->EndOfFile))) {
219 cFYI(1, "inode unchanged on server"); 188 cFYI(1, "inode unchanged on server");
220 } else { 189 } else {
221 if (file->f_path.dentry->d_inode->i_mapping) { 190 if (inode->i_mapping) {
222 /* BB no need to lock inode until after invalidate 191 /* BB no need to lock inode until after invalidate
223 since namei code should already have it locked? */ 192 since namei code should already have it locked? */
224 rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping); 193 rc = filemap_write_and_wait(inode->i_mapping);
225 if (rc != 0) 194 if (rc != 0)
226 CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc; 195 pCifsInode->write_behind_rc = rc;
227 } 196 }
228 cFYI(1, "invalidating remote inode since open detected it " 197 cFYI(1, "invalidating remote inode since open detected it "
229 "changed"); 198 "changed");
230 invalidate_remote_inode(file->f_path.dentry->d_inode); 199 invalidate_remote_inode(inode);
231 } 200 }
232 201
233client_can_cache: 202client_can_cache:
234 if (pTcon->unix_ext) 203 if (pTcon->unix_ext)
235 rc = cifs_get_inode_info_unix(&file->f_path.dentry->d_inode, 204 rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
236 full_path, inode->i_sb, xid); 205 xid);
237 else 206 else
238 rc = cifs_get_inode_info(&file->f_path.dentry->d_inode, 207 rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
239 full_path, buf, inode->i_sb, xid, NULL); 208 xid, NULL);
240 209
241 if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) { 210 if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) {
242 pCifsInode->clientCanCacheAll = true; 211 pCifsInode->clientCanCacheAll = true;
243 pCifsInode->clientCanCacheRead = true; 212 pCifsInode->clientCanCacheRead = true;
244 cFYI(1, "Exclusive Oplock granted on inode %p", 213 cFYI(1, "Exclusive Oplock granted on inode %p", inode);
245 file->f_path.dentry->d_inode);
246 } else if ((*oplock & 0xF) == OPLOCK_READ) 214 } else if ((*oplock & 0xF) == OPLOCK_READ)
247 pCifsInode->clientCanCacheRead = true; 215 pCifsInode->clientCanCacheRead = true;
248 216
@@ -256,7 +224,7 @@ int cifs_open(struct inode *inode, struct file *file)
256 __u32 oplock; 224 __u32 oplock;
257 struct cifs_sb_info *cifs_sb; 225 struct cifs_sb_info *cifs_sb;
258 struct cifsTconInfo *tcon; 226 struct cifsTconInfo *tcon;
259 struct cifsFileInfo *pCifsFile; 227 struct cifsFileInfo *pCifsFile = NULL;
260 struct cifsInodeInfo *pCifsInode; 228 struct cifsInodeInfo *pCifsInode;
261 char *full_path = NULL; 229 char *full_path = NULL;
262 int desiredAccess; 230 int desiredAccess;
@@ -270,12 +238,6 @@ int cifs_open(struct inode *inode, struct file *file)
270 tcon = cifs_sb->tcon; 238 tcon = cifs_sb->tcon;
271 239
272 pCifsInode = CIFS_I(file->f_path.dentry->d_inode); 240 pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
273 pCifsFile = cifs_fill_filedata(file);
274 if (pCifsFile) {
275 rc = 0;
276 FreeXid(xid);
277 return rc;
278 }
279 241
280 full_path = build_path_from_dentry(file->f_path.dentry); 242 full_path = build_path_from_dentry(file->f_path.dentry);
281 if (full_path == NULL) { 243 if (full_path == NULL) {
@@ -299,8 +261,7 @@ int cifs_open(struct inode *inode, struct file *file)
299 int oflags = (int) cifs_posix_convert_flags(file->f_flags); 261 int oflags = (int) cifs_posix_convert_flags(file->f_flags);
300 oflags |= SMB_O_CREAT; 262 oflags |= SMB_O_CREAT;
301 /* can not refresh inode info since size could be stale */ 263 /* can not refresh inode info since size could be stale */
302 rc = cifs_posix_open(full_path, &inode, file->f_path.mnt, 264 rc = cifs_posix_open(full_path, &inode, inode->i_sb,
303 inode->i_sb,
304 cifs_sb->mnt_file_mode /* ignored */, 265 cifs_sb->mnt_file_mode /* ignored */,
305 oflags, &oplock, &netfid, xid); 266 oflags, &oplock, &netfid, xid);
306 if (rc == 0) { 267 if (rc == 0) {
@@ -308,9 +269,23 @@ int cifs_open(struct inode *inode, struct file *file)
308 /* no need for special case handling of setting mode 269 /* no need for special case handling of setting mode
309 on read only files needed here */ 270 on read only files needed here */
310 271
311 pCifsFile = cifs_fill_filedata(file); 272 rc = cifs_posix_open_inode_helper(inode, file,
312 cifs_posix_open_inode_helper(inode, file, pCifsInode, 273 pCifsInode, oplock, netfid);
313 oplock, netfid); 274 if (rc != 0) {
275 CIFSSMBClose(xid, tcon, netfid);
276 goto out;
277 }
278
279 pCifsFile = cifs_new_fileinfo(inode, netfid, file,
280 file->f_path.mnt,
281 oflags);
282 if (pCifsFile == NULL) {
283 CIFSSMBClose(xid, tcon, netfid);
284 rc = -ENOMEM;
285 }
286
287 cifs_fscache_set_inode_cookie(inode, file);
288
314 goto out; 289 goto out;
315 } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { 290 } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
316 if (tcon->ses->serverNOS) 291 if (tcon->ses->serverNOS)
@@ -391,16 +366,18 @@ int cifs_open(struct inode *inode, struct file *file)
391 goto out; 366 goto out;
392 } 367 }
393 368
369 rc = cifs_open_inode_helper(inode, tcon, &oplock, buf, full_path, xid);
370 if (rc != 0)
371 goto out;
372
394 pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt, 373 pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt,
395 file->f_flags); 374 file->f_flags);
396 file->private_data = pCifsFile; 375 if (pCifsFile == NULL) {
397 if (file->private_data == NULL) {
398 rc = -ENOMEM; 376 rc = -ENOMEM;
399 goto out; 377 goto out;
400 } 378 }
401 379
402 rc = cifs_open_inode_helper(inode, file, pCifsInode, pCifsFile, tcon, 380 cifs_fscache_set_inode_cookie(inode, file);
403 &oplock, buf, full_path, xid);
404 381
405 if (oplock & CIFS_CREATE_ACTION) { 382 if (oplock & CIFS_CREATE_ACTION) {
406 /* time to set mode which we can not set earlier due to 383 /* time to set mode which we can not set earlier due to
@@ -456,7 +433,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
456 __u16 netfid; 433 __u16 netfid;
457 434
458 if (file->private_data) 435 if (file->private_data)
459 pCifsFile = (struct cifsFileInfo *)file->private_data; 436 pCifsFile = file->private_data;
460 else 437 else
461 return -EBADF; 438 return -EBADF;
462 439
@@ -513,8 +490,7 @@ reopen_error_exit:
513 le64_to_cpu(tcon->fsUnixInfo.Capability))) { 490 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
514 int oflags = (int) cifs_posix_convert_flags(file->f_flags); 491 int oflags = (int) cifs_posix_convert_flags(file->f_flags);
515 /* can not refresh inode info since size could be stale */ 492 /* can not refresh inode info since size could be stale */
516 rc = cifs_posix_open(full_path, NULL, file->f_path.mnt, 493 rc = cifs_posix_open(full_path, NULL, inode->i_sb,
517 inode->i_sb,
518 cifs_sb->mnt_file_mode /* ignored */, 494 cifs_sb->mnt_file_mode /* ignored */,
519 oflags, &oplock, &netfid, xid); 495 oflags, &oplock, &netfid, xid);
520 if (rc == 0) { 496 if (rc == 0) {
@@ -595,8 +571,7 @@ int cifs_close(struct inode *inode, struct file *file)
595 int xid, timeout; 571 int xid, timeout;
596 struct cifs_sb_info *cifs_sb; 572 struct cifs_sb_info *cifs_sb;
597 struct cifsTconInfo *pTcon; 573 struct cifsTconInfo *pTcon;
598 struct cifsFileInfo *pSMBFile = 574 struct cifsFileInfo *pSMBFile = file->private_data;
599 (struct cifsFileInfo *)file->private_data;
600 575
601 xid = GetXid(); 576 xid = GetXid();
602 577
@@ -671,8 +646,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
671{ 646{
672 int rc = 0; 647 int rc = 0;
673 int xid; 648 int xid;
674 struct cifsFileInfo *pCFileStruct = 649 struct cifsFileInfo *pCFileStruct = file->private_data;
675 (struct cifsFileInfo *)file->private_data;
676 char *ptmp; 650 char *ptmp;
677 651
678 cFYI(1, "Closedir inode = 0x%p", inode); 652 cFYI(1, "Closedir inode = 0x%p", inode);
@@ -893,8 +867,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
893 length, pfLock, 867 length, pfLock,
894 posix_lock_type, wait_flag); 868 posix_lock_type, wait_flag);
895 } else { 869 } else {
896 struct cifsFileInfo *fid = 870 struct cifsFileInfo *fid = file->private_data;
897 (struct cifsFileInfo *)file->private_data;
898 871
899 if (numLock) { 872 if (numLock) {
900 rc = CIFSSMBLock(xid, tcon, netfid, length, 873 rc = CIFSSMBLock(xid, tcon, netfid, length,
@@ -995,7 +968,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
995 968
996 if (file->private_data == NULL) 969 if (file->private_data == NULL)
997 return -EBADF; 970 return -EBADF;
998 open_file = (struct cifsFileInfo *) file->private_data; 971 open_file = file->private_data;
999 972
1000 rc = generic_write_checks(file, poffset, &write_size, 0); 973 rc = generic_write_checks(file, poffset, &write_size, 0);
1001 if (rc) 974 if (rc)
@@ -1097,7 +1070,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
1097 1070
1098 if (file->private_data == NULL) 1071 if (file->private_data == NULL)
1099 return -EBADF; 1072 return -EBADF;
1100 open_file = (struct cifsFileInfo *)file->private_data; 1073 open_file = file->private_data;
1101 1074
1102 xid = GetXid(); 1075 xid = GetXid();
1103 1076
@@ -1681,8 +1654,7 @@ int cifs_fsync(struct file *file, int datasync)
1681 int xid; 1654 int xid;
1682 int rc = 0; 1655 int rc = 0;
1683 struct cifsTconInfo *tcon; 1656 struct cifsTconInfo *tcon;
1684 struct cifsFileInfo *smbfile = 1657 struct cifsFileInfo *smbfile = file->private_data;
1685 (struct cifsFileInfo *)file->private_data;
1686 struct inode *inode = file->f_path.dentry->d_inode; 1658 struct inode *inode = file->f_path.dentry->d_inode;
1687 1659
1688 xid = GetXid(); 1660 xid = GetXid();
@@ -1786,7 +1758,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
1786 FreeXid(xid); 1758 FreeXid(xid);
1787 return rc; 1759 return rc;
1788 } 1760 }
1789 open_file = (struct cifsFileInfo *)file->private_data; 1761 open_file = file->private_data;
1790 1762
1791 if ((file->f_flags & O_ACCMODE) == O_WRONLY) 1763 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
1792 cFYI(1, "attempting read on write only file instance"); 1764 cFYI(1, "attempting read on write only file instance");
@@ -1867,7 +1839,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1867 FreeXid(xid); 1839 FreeXid(xid);
1868 return rc; 1840 return rc;
1869 } 1841 }
1870 open_file = (struct cifsFileInfo *)file->private_data; 1842 open_file = file->private_data;
1871 1843
1872 if ((file->f_flags & O_ACCMODE) == O_WRONLY) 1844 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
1873 cFYI(1, "attempting read on write only file instance"); 1845 cFYI(1, "attempting read on write only file instance");
@@ -1952,6 +1924,7 @@ static void cifs_copy_cache_pages(struct address_space *mapping,
1952 bytes_read -= PAGE_CACHE_SIZE; 1924 bytes_read -= PAGE_CACHE_SIZE;
1953 continue; 1925 continue;
1954 } 1926 }
1927 page_cache_release(page);
1955 1928
1956 target = kmap_atomic(page, KM_USER0); 1929 target = kmap_atomic(page, KM_USER0);
1957 1930
@@ -1971,6 +1944,9 @@ static void cifs_copy_cache_pages(struct address_space *mapping,
1971 SetPageUptodate(page); 1944 SetPageUptodate(page);
1972 unlock_page(page); 1945 unlock_page(page);
1973 data += PAGE_CACHE_SIZE; 1946 data += PAGE_CACHE_SIZE;
1947
1948 /* add page to FS-Cache */
1949 cifs_readpage_to_fscache(mapping->host, page);
1974 } 1950 }
1975 return; 1951 return;
1976} 1952}
@@ -1997,10 +1973,19 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1997 FreeXid(xid); 1973 FreeXid(xid);
1998 return rc; 1974 return rc;
1999 } 1975 }
2000 open_file = (struct cifsFileInfo *)file->private_data; 1976 open_file = file->private_data;
2001 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 1977 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
2002 pTcon = cifs_sb->tcon; 1978 pTcon = cifs_sb->tcon;
2003 1979
1980 /*
1981 * Reads as many pages as possible from fscache. Returns -ENOBUFS
1982 * immediately if the cookie is negative
1983 */
1984 rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list,
1985 &num_pages);
1986 if (rc == 0)
1987 goto read_complete;
1988
2004 cFYI(DBG2, "rpages: num pages %d", num_pages); 1989 cFYI(DBG2, "rpages: num pages %d", num_pages);
2005 for (i = 0; i < num_pages; ) { 1990 for (i = 0; i < num_pages; ) {
2006 unsigned contig_pages; 1991 unsigned contig_pages;
@@ -2111,6 +2096,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
2111 smb_read_data = NULL; 2096 smb_read_data = NULL;
2112 } 2097 }
2113 2098
2099read_complete:
2114 FreeXid(xid); 2100 FreeXid(xid);
2115 return rc; 2101 return rc;
2116} 2102}
@@ -2121,6 +2107,11 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
2121 char *read_data; 2107 char *read_data;
2122 int rc; 2108 int rc;
2123 2109
2110 /* Is the page cached? */
2111 rc = cifs_readpage_from_fscache(file->f_path.dentry->d_inode, page);
2112 if (rc == 0)
2113 goto read_complete;
2114
2124 page_cache_get(page); 2115 page_cache_get(page);
2125 read_data = kmap(page); 2116 read_data = kmap(page);
2126 /* for reads over a certain size could initiate async read ahead */ 2117 /* for reads over a certain size could initiate async read ahead */
@@ -2140,11 +2131,17 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
2140 2131
2141 flush_dcache_page(page); 2132 flush_dcache_page(page);
2142 SetPageUptodate(page); 2133 SetPageUptodate(page);
2134
2135 /* send this page to the cache */
2136 cifs_readpage_to_fscache(file->f_path.dentry->d_inode, page);
2137
2143 rc = 0; 2138 rc = 0;
2144 2139
2145io_error: 2140io_error:
2146 kunmap(page); 2141 kunmap(page);
2147 page_cache_release(page); 2142 page_cache_release(page);
2143
2144read_complete:
2148 return rc; 2145 return rc;
2149} 2146}
2150 2147
@@ -2294,8 +2291,23 @@ out:
2294 return rc; 2291 return rc;
2295} 2292}
2296 2293
2297static void 2294static int cifs_release_page(struct page *page, gfp_t gfp)
2298cifs_oplock_break(struct slow_work *work) 2295{
2296 if (PagePrivate(page))
2297 return 0;
2298
2299 return cifs_fscache_release_page(page, gfp);
2300}
2301
2302static void cifs_invalidate_page(struct page *page, unsigned long offset)
2303{
2304 struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host);
2305
2306 if (offset == 0)
2307 cifs_fscache_invalidate_page(page, &cifsi->vfs_inode);
2308}
2309
2310void cifs_oplock_break(struct work_struct *work)
2299{ 2311{
2300 struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, 2312 struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
2301 oplock_break); 2313 oplock_break);
@@ -2332,33 +2344,30 @@ cifs_oplock_break(struct slow_work *work)
2332 LOCKING_ANDX_OPLOCK_RELEASE, false); 2344 LOCKING_ANDX_OPLOCK_RELEASE, false);
2333 cFYI(1, "Oplock release rc = %d", rc); 2345 cFYI(1, "Oplock release rc = %d", rc);
2334 } 2346 }
2347
2348 /*
2349 * We might have kicked in before is_valid_oplock_break()
2350 * finished grabbing reference for us. Make sure it's done by
2351 * waiting for GlobalSMSSeslock.
2352 */
2353 write_lock(&GlobalSMBSeslock);
2354 write_unlock(&GlobalSMBSeslock);
2355
2356 cifs_oplock_break_put(cfile);
2335} 2357}
2336 2358
2337static int 2359void cifs_oplock_break_get(struct cifsFileInfo *cfile)
2338cifs_oplock_break_get(struct slow_work *work)
2339{ 2360{
2340 struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
2341 oplock_break);
2342 mntget(cfile->mnt); 2361 mntget(cfile->mnt);
2343 cifsFileInfo_get(cfile); 2362 cifsFileInfo_get(cfile);
2344 return 0;
2345} 2363}
2346 2364
2347static void 2365void cifs_oplock_break_put(struct cifsFileInfo *cfile)
2348cifs_oplock_break_put(struct slow_work *work)
2349{ 2366{
2350 struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
2351 oplock_break);
2352 mntput(cfile->mnt); 2367 mntput(cfile->mnt);
2353 cifsFileInfo_put(cfile); 2368 cifsFileInfo_put(cfile);
2354} 2369}
2355 2370
2356const struct slow_work_ops cifs_oplock_break_ops = {
2357 .get_ref = cifs_oplock_break_get,
2358 .put_ref = cifs_oplock_break_put,
2359 .execute = cifs_oplock_break,
2360};
2361
2362const struct address_space_operations cifs_addr_ops = { 2371const struct address_space_operations cifs_addr_ops = {
2363 .readpage = cifs_readpage, 2372 .readpage = cifs_readpage,
2364 .readpages = cifs_readpages, 2373 .readpages = cifs_readpages,
@@ -2367,6 +2376,8 @@ const struct address_space_operations cifs_addr_ops = {
2367 .write_begin = cifs_write_begin, 2376 .write_begin = cifs_write_begin,
2368 .write_end = cifs_write_end, 2377 .write_end = cifs_write_end,
2369 .set_page_dirty = __set_page_dirty_nobuffers, 2378 .set_page_dirty = __set_page_dirty_nobuffers,
2379 .releasepage = cifs_release_page,
2380 .invalidatepage = cifs_invalidate_page,
2370 /* .sync_page = cifs_sync_page, */ 2381 /* .sync_page = cifs_sync_page, */
2371 /* .direct_IO = */ 2382 /* .direct_IO = */
2372}; 2383};
@@ -2383,6 +2394,8 @@ const struct address_space_operations cifs_addr_ops_smallbuf = {
2383 .write_begin = cifs_write_begin, 2394 .write_begin = cifs_write_begin,
2384 .write_end = cifs_write_end, 2395 .write_end = cifs_write_end,
2385 .set_page_dirty = __set_page_dirty_nobuffers, 2396 .set_page_dirty = __set_page_dirty_nobuffers,
2397 .releasepage = cifs_release_page,
2398 .invalidatepage = cifs_invalidate_page,
2386 /* .sync_page = cifs_sync_page, */ 2399 /* .sync_page = cifs_sync_page, */
2387 /* .direct_IO = */ 2400 /* .direct_IO = */
2388}; 2401};
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c
new file mode 100644
index 000000000000..9f3f5c4be161
--- /dev/null
+++ b/fs/cifs/fscache.c
@@ -0,0 +1,236 @@
1/*
2 * fs/cifs/fscache.c - CIFS filesystem cache interface
3 *
4 * Copyright (c) 2010 Novell, Inc.
5 * Author(s): Suresh Jayaraman (sjayaraman@suse.de>
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#include "fscache.h"
22#include "cifsglob.h"
23#include "cifs_debug.h"
24#include "cifs_fs_sb.h"
25
26void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server)
27{
28 server->fscache =
29 fscache_acquire_cookie(cifs_fscache_netfs.primary_index,
30 &cifs_fscache_server_index_def, server);
31 cFYI(1, "CIFS: get client cookie (0x%p/0x%p)", server,
32 server->fscache);
33}
34
35void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server)
36{
37 cFYI(1, "CIFS: release client cookie (0x%p/0x%p)", server,
38 server->fscache);
39 fscache_relinquish_cookie(server->fscache, 0);
40 server->fscache = NULL;
41}
42
43void cifs_fscache_get_super_cookie(struct cifsTconInfo *tcon)
44{
45 struct TCP_Server_Info *server = tcon->ses->server;
46
47 tcon->fscache =
48 fscache_acquire_cookie(server->fscache,
49 &cifs_fscache_super_index_def, tcon);
50 cFYI(1, "CIFS: get superblock cookie (0x%p/0x%p)",
51 server->fscache, tcon->fscache);
52}
53
54void cifs_fscache_release_super_cookie(struct cifsTconInfo *tcon)
55{
56 cFYI(1, "CIFS: releasing superblock cookie (0x%p)", tcon->fscache);
57 fscache_relinquish_cookie(tcon->fscache, 0);
58 tcon->fscache = NULL;
59}
60
61static void cifs_fscache_enable_inode_cookie(struct inode *inode)
62{
63 struct cifsInodeInfo *cifsi = CIFS_I(inode);
64 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
65
66 if (cifsi->fscache)
67 return;
68
69 cifsi->fscache = fscache_acquire_cookie(cifs_sb->tcon->fscache,
70 &cifs_fscache_inode_object_def,
71 cifsi);
72 cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)",
73 cifs_sb->tcon->fscache, cifsi->fscache);
74}
75
76void cifs_fscache_release_inode_cookie(struct inode *inode)
77{
78 struct cifsInodeInfo *cifsi = CIFS_I(inode);
79
80 if (cifsi->fscache) {
81 cFYI(1, "CIFS releasing inode cookie (0x%p)",
82 cifsi->fscache);
83 fscache_relinquish_cookie(cifsi->fscache, 0);
84 cifsi->fscache = NULL;
85 }
86}
87
88static void cifs_fscache_disable_inode_cookie(struct inode *inode)
89{
90 struct cifsInodeInfo *cifsi = CIFS_I(inode);
91
92 if (cifsi->fscache) {
93 cFYI(1, "CIFS disabling inode cookie (0x%p)",
94 cifsi->fscache);
95 fscache_relinquish_cookie(cifsi->fscache, 1);
96 cifsi->fscache = NULL;
97 }
98}
99
100void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
101{
102 if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
103 cifs_fscache_disable_inode_cookie(inode);
104 else {
105 cifs_fscache_enable_inode_cookie(inode);
106 cFYI(1, "CIFS: fscache inode cookie set");
107 }
108}
109
110void cifs_fscache_reset_inode_cookie(struct inode *inode)
111{
112 struct cifsInodeInfo *cifsi = CIFS_I(inode);
113 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
114 struct fscache_cookie *old = cifsi->fscache;
115
116 if (cifsi->fscache) {
117 /* retire the current fscache cache and get a new one */
118 fscache_relinquish_cookie(cifsi->fscache, 1);
119
120 cifsi->fscache = fscache_acquire_cookie(cifs_sb->tcon->fscache,
121 &cifs_fscache_inode_object_def,
122 cifsi);
123 cFYI(1, "CIFS: new cookie 0x%p oldcookie 0x%p",
124 cifsi->fscache, old);
125 }
126}
127
128int cifs_fscache_release_page(struct page *page, gfp_t gfp)
129{
130 if (PageFsCache(page)) {
131 struct inode *inode = page->mapping->host;
132 struct cifsInodeInfo *cifsi = CIFS_I(inode);
133
134 cFYI(1, "CIFS: fscache release page (0x%p/0x%p)",
135 page, cifsi->fscache);
136 if (!fscache_maybe_release_page(cifsi->fscache, page, gfp))
137 return 0;
138 }
139
140 return 1;
141}
142
143static void cifs_readpage_from_fscache_complete(struct page *page, void *ctx,
144 int error)
145{
146 cFYI(1, "CFS: readpage_from_fscache_complete (0x%p/%d)",
147 page, error);
148 if (!error)
149 SetPageUptodate(page);
150 unlock_page(page);
151}
152
153/*
154 * Retrieve a page from FS-Cache
155 */
156int __cifs_readpage_from_fscache(struct inode *inode, struct page *page)
157{
158 int ret;
159
160 cFYI(1, "CIFS: readpage_from_fscache(fsc:%p, p:%p, i:0x%p",
161 CIFS_I(inode)->fscache, page, inode);
162 ret = fscache_read_or_alloc_page(CIFS_I(inode)->fscache, page,
163 cifs_readpage_from_fscache_complete,
164 NULL,
165 GFP_KERNEL);
166 switch (ret) {
167
168 case 0: /* page found in fscache, read submitted */
169 cFYI(1, "CIFS: readpage_from_fscache: submitted");
170 return ret;
171 case -ENOBUFS: /* page won't be cached */
172 case -ENODATA: /* page not in cache */
173 cFYI(1, "CIFS: readpage_from_fscache %d", ret);
174 return 1;
175
176 default:
177 cERROR(1, "unknown error ret = %d", ret);
178 }
179 return ret;
180}
181
182/*
183 * Retrieve a set of pages from FS-Cache
184 */
185int __cifs_readpages_from_fscache(struct inode *inode,
186 struct address_space *mapping,
187 struct list_head *pages,
188 unsigned *nr_pages)
189{
190 int ret;
191
192 cFYI(1, "CIFS: __cifs_readpages_from_fscache (0x%p/%u/0x%p)",
193 CIFS_I(inode)->fscache, *nr_pages, inode);
194 ret = fscache_read_or_alloc_pages(CIFS_I(inode)->fscache, mapping,
195 pages, nr_pages,
196 cifs_readpage_from_fscache_complete,
197 NULL,
198 mapping_gfp_mask(mapping));
199 switch (ret) {
200 case 0: /* read submitted to the cache for all pages */
201 cFYI(1, "CIFS: readpages_from_fscache: submitted");
202 return ret;
203
204 case -ENOBUFS: /* some pages are not cached and can't be */
205 case -ENODATA: /* some pages are not cached */
206 cFYI(1, "CIFS: readpages_from_fscache: no page");
207 return 1;
208
209 default:
210 cFYI(1, "unknown error ret = %d", ret);
211 }
212
213 return ret;
214}
215
216void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
217{
218 int ret;
219
220 cFYI(1, "CIFS: readpage_to_fscache(fsc: %p, p: %p, i: %p",
221 CIFS_I(inode)->fscache, page, inode);
222 ret = fscache_write_page(CIFS_I(inode)->fscache, page, GFP_KERNEL);
223 if (ret != 0)
224 fscache_uncache_page(CIFS_I(inode)->fscache, page);
225}
226
227void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
228{
229 struct cifsInodeInfo *cifsi = CIFS_I(inode);
230 struct fscache_cookie *cookie = cifsi->fscache;
231
232 cFYI(1, "CIFS: fscache invalidatepage (0x%p/0x%p)", page, cookie);
233 fscache_wait_on_page_write(cookie, page);
234 fscache_uncache_page(cookie, page);
235}
236
diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h
new file mode 100644
index 000000000000..31b88ec2341e
--- /dev/null
+++ b/fs/cifs/fscache.h
@@ -0,0 +1,136 @@
1/*
2 * fs/cifs/fscache.h - CIFS filesystem cache interface definitions
3 *
4 * Copyright (c) 2010 Novell, Inc.
5 * Authors(s): Suresh Jayaraman (sjayaraman@suse.de>
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#ifndef _CIFS_FSCACHE_H
22#define _CIFS_FSCACHE_H
23
24#include <linux/fscache.h>
25
26#include "cifsglob.h"
27
28#ifdef CONFIG_CIFS_FSCACHE
29
30extern struct fscache_netfs cifs_fscache_netfs;
31extern const struct fscache_cookie_def cifs_fscache_server_index_def;
32extern const struct fscache_cookie_def cifs_fscache_super_index_def;
33extern const struct fscache_cookie_def cifs_fscache_inode_object_def;
34
35extern int cifs_fscache_register(void);
36extern void cifs_fscache_unregister(void);
37
38/*
39 * fscache.c
40 */
41extern void cifs_fscache_get_client_cookie(struct TCP_Server_Info *);
42extern void cifs_fscache_release_client_cookie(struct TCP_Server_Info *);
43extern void cifs_fscache_get_super_cookie(struct cifsTconInfo *);
44extern void cifs_fscache_release_super_cookie(struct cifsTconInfo *);
45
46extern void cifs_fscache_release_inode_cookie(struct inode *);
47extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *);
48extern void cifs_fscache_reset_inode_cookie(struct inode *);
49
50extern void __cifs_fscache_invalidate_page(struct page *, struct inode *);
51extern int cifs_fscache_release_page(struct page *page, gfp_t gfp);
52extern int __cifs_readpage_from_fscache(struct inode *, struct page *);
53extern int __cifs_readpages_from_fscache(struct inode *,
54 struct address_space *,
55 struct list_head *,
56 unsigned *);
57
58extern void __cifs_readpage_to_fscache(struct inode *, struct page *);
59
60static inline void cifs_fscache_invalidate_page(struct page *page,
61 struct inode *inode)
62{
63 if (PageFsCache(page))
64 __cifs_fscache_invalidate_page(page, inode);
65}
66
67static inline int cifs_readpage_from_fscache(struct inode *inode,
68 struct page *page)
69{
70 if (CIFS_I(inode)->fscache)
71 return __cifs_readpage_from_fscache(inode, page);
72
73 return -ENOBUFS;
74}
75
76static inline int cifs_readpages_from_fscache(struct inode *inode,
77 struct address_space *mapping,
78 struct list_head *pages,
79 unsigned *nr_pages)
80{
81 if (CIFS_I(inode)->fscache)
82 return __cifs_readpages_from_fscache(inode, mapping, pages,
83 nr_pages);
84 return -ENOBUFS;
85}
86
87static inline void cifs_readpage_to_fscache(struct inode *inode,
88 struct page *page)
89{
90 if (PageFsCache(page))
91 __cifs_readpage_to_fscache(inode, page);
92}
93
94#else /* CONFIG_CIFS_FSCACHE */
95static inline int cifs_fscache_register(void) { return 0; }
96static inline void cifs_fscache_unregister(void) {}
97
98static inline void
99cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) {}
100static inline void
101cifs_fscache_release_client_cookie(struct TCP_Server_Info *server) {}
102static inline void cifs_fscache_get_super_cookie(struct cifsTconInfo *tcon) {}
103static inline void
104cifs_fscache_release_super_cookie(struct cifsTconInfo *tcon) {}
105
106static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {}
107static inline void cifs_fscache_set_inode_cookie(struct inode *inode,
108 struct file *filp) {}
109static inline void cifs_fscache_reset_inode_cookie(struct inode *inode) {}
110static inline int cifs_fscache_release_page(struct page *page, gfp_t gfp)
111{
112 return 1; /* May release page */
113}
114
115static inline void cifs_fscache_invalidate_page(struct page *page,
116 struct inode *inode) {}
117static inline int
118cifs_readpage_from_fscache(struct inode *inode, struct page *page)
119{
120 return -ENOBUFS;
121}
122
123static inline int cifs_readpages_from_fscache(struct inode *inode,
124 struct address_space *mapping,
125 struct list_head *pages,
126 unsigned *nr_pages)
127{
128 return -ENOBUFS;
129}
130
131static inline void cifs_readpage_to_fscache(struct inode *inode,
132 struct page *page) {}
133
134#endif /* CONFIG_CIFS_FSCACHE */
135
136#endif /* _CIFS_FSCACHE_H */
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 62b324f26a56..4bc47e5b5f29 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -29,6 +29,7 @@
29#include "cifsproto.h" 29#include "cifsproto.h"
30#include "cifs_debug.h" 30#include "cifs_debug.h"
31#include "cifs_fs_sb.h" 31#include "cifs_fs_sb.h"
32#include "fscache.h"
32 33
33 34
34static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) 35static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral)
@@ -288,7 +289,7 @@ int cifs_get_file_info_unix(struct file *filp)
288 struct inode *inode = filp->f_path.dentry->d_inode; 289 struct inode *inode = filp->f_path.dentry->d_inode;
289 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 290 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
290 struct cifsTconInfo *tcon = cifs_sb->tcon; 291 struct cifsTconInfo *tcon = cifs_sb->tcon;
291 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; 292 struct cifsFileInfo *cfile = filp->private_data;
292 293
293 xid = GetXid(); 294 xid = GetXid();
294 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data); 295 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data);
@@ -515,7 +516,7 @@ int cifs_get_file_info(struct file *filp)
515 struct inode *inode = filp->f_path.dentry->d_inode; 516 struct inode *inode = filp->f_path.dentry->d_inode;
516 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 517 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
517 struct cifsTconInfo *tcon = cifs_sb->tcon; 518 struct cifsTconInfo *tcon = cifs_sb->tcon;
518 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; 519 struct cifsFileInfo *cfile = filp->private_data;
519 520
520 xid = GetXid(); 521 xid = GetXid();
521 rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); 522 rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data);
@@ -723,18 +724,17 @@ cifs_find_inode(struct inode *inode, void *opaque)
723{ 724{
724 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; 725 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
725 726
727 /* don't match inode with different uniqueid */
726 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) 728 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
727 return 0; 729 return 0;
728 730
729 /* 731 /* don't match inode of different type */
730 * uh oh -- it's a directory. We can't use it since hardlinked dirs are 732 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
731 * verboten. Disable serverino and return it as if it were found, the 733 return 0;
732 * caller can discard it, generate a uniqueid and retry the find 734
733 */ 735 /* if it's not a directory or has no dentries, then flag it */
734 if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry)) { 736 if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry))
735 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION; 737 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
736 cifs_autodisable_serverino(CIFS_SB(inode->i_sb));
737 }
738 738
739 return 1; 739 return 1;
740} 740}
@@ -748,6 +748,27 @@ cifs_init_inode(struct inode *inode, void *opaque)
748 return 0; 748 return 0;
749} 749}
750 750
751/*
752 * walk dentry list for an inode and report whether it has aliases that
753 * are hashed. We use this to determine if a directory inode can actually
754 * be used.
755 */
756static bool
757inode_has_hashed_dentries(struct inode *inode)
758{
759 struct dentry *dentry;
760
761 spin_lock(&dcache_lock);
762 list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
763 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
764 spin_unlock(&dcache_lock);
765 return true;
766 }
767 }
768 spin_unlock(&dcache_lock);
769 return false;
770}
771
751/* Given fattrs, get a corresponding inode */ 772/* Given fattrs, get a corresponding inode */
752struct inode * 773struct inode *
753cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) 774cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
@@ -763,12 +784,16 @@ retry_iget5_locked:
763 784
764 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); 785 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
765 if (inode) { 786 if (inode) {
766 /* was there a problematic inode number collision? */ 787 /* was there a potentially problematic inode collision? */
767 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) { 788 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
768 iput(inode);
769 fattr->cf_uniqueid = iunique(sb, ROOT_I);
770 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION; 789 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
771 goto retry_iget5_locked; 790
791 if (inode_has_hashed_dentries(inode)) {
792 cifs_autodisable_serverino(CIFS_SB(sb));
793 iput(inode);
794 fattr->cf_uniqueid = iunique(sb, ROOT_I);
795 goto retry_iget5_locked;
796 }
772 } 797 }
773 798
774 cifs_fattr_to_inode(inode, fattr); 799 cifs_fattr_to_inode(inode, fattr);
@@ -776,6 +801,10 @@ retry_iget5_locked:
776 inode->i_flags |= S_NOATIME | S_NOCMTIME; 801 inode->i_flags |= S_NOATIME | S_NOCMTIME;
777 if (inode->i_state & I_NEW) { 802 if (inode->i_state & I_NEW) {
778 inode->i_ino = hash; 803 inode->i_ino = hash;
804#ifdef CONFIG_CIFS_FSCACHE
805 /* initialize per-inode cache cookie pointer */
806 CIFS_I(inode)->fscache = NULL;
807#endif
779 unlock_new_inode(inode); 808 unlock_new_inode(inode);
780 } 809 }
781 } 810 }
@@ -807,6 +836,11 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
807 if (!inode) 836 if (!inode)
808 return ERR_PTR(-ENOMEM); 837 return ERR_PTR(-ENOMEM);
809 838
839#ifdef CONFIG_CIFS_FSCACHE
840 /* populate tcon->resource_id */
841 cifs_sb->tcon->resource_id = CIFS_I(inode)->uniqueid;
842#endif
843
810 if (rc && cifs_sb->tcon->ipc) { 844 if (rc && cifs_sb->tcon->ipc) {
811 cFYI(1, "ipc connection - fake read inode"); 845 cFYI(1, "ipc connection - fake read inode");
812 inode->i_mode |= S_IFDIR; 846 inode->i_mode |= S_IFDIR;
@@ -1401,6 +1435,10 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
1401 if (rc == 0 || rc != -ETXTBSY) 1435 if (rc == 0 || rc != -ETXTBSY)
1402 return rc; 1436 return rc;
1403 1437
1438 /* open-file renames don't work across directories */
1439 if (to_dentry->d_parent != from_dentry->d_parent)
1440 return rc;
1441
1404 /* open the file to be renamed -- we need DELETE perms */ 1442 /* open the file to be renamed -- we need DELETE perms */
1405 rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE, 1443 rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE,
1406 CREATE_NOT_DIR, &srcfid, &oplock, NULL, 1444 CREATE_NOT_DIR, &srcfid, &oplock, NULL,
@@ -1564,6 +1602,7 @@ cifs_invalidate_mapping(struct inode *inode)
1564 cifs_i->write_behind_rc = rc; 1602 cifs_i->write_behind_rc = rc;
1565 } 1603 }
1566 invalidate_remote_inode(inode); 1604 invalidate_remote_inode(inode);
1605 cifs_fscache_reset_inode_cookie(inode);
1567} 1606}
1568 1607
1569int cifs_revalidate_file(struct file *filp) 1608int cifs_revalidate_file(struct file *filp)
@@ -1659,26 +1698,16 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1659 return rc; 1698 return rc;
1660} 1699}
1661 1700
1662static int cifs_vmtruncate(struct inode *inode, loff_t offset) 1701static void cifs_setsize(struct inode *inode, loff_t offset)
1663{ 1702{
1664 loff_t oldsize; 1703 loff_t oldsize;
1665 int err;
1666 1704
1667 spin_lock(&inode->i_lock); 1705 spin_lock(&inode->i_lock);
1668 err = inode_newsize_ok(inode, offset);
1669 if (err) {
1670 spin_unlock(&inode->i_lock);
1671 goto out;
1672 }
1673
1674 oldsize = inode->i_size; 1706 oldsize = inode->i_size;
1675 i_size_write(inode, offset); 1707 i_size_write(inode, offset);
1676 spin_unlock(&inode->i_lock); 1708 spin_unlock(&inode->i_lock);
1709
1677 truncate_pagecache(inode, oldsize, offset); 1710 truncate_pagecache(inode, oldsize, offset);
1678 if (inode->i_op->truncate)
1679 inode->i_op->truncate(inode);
1680out:
1681 return err;
1682} 1711}
1683 1712
1684static int 1713static int
@@ -1751,7 +1780,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
1751 1780
1752 if (rc == 0) { 1781 if (rc == 0) {
1753 cifsInode->server_eof = attrs->ia_size; 1782 cifsInode->server_eof = attrs->ia_size;
1754 rc = cifs_vmtruncate(inode, attrs->ia_size); 1783 cifs_setsize(inode, attrs->ia_size);
1755 cifs_truncate_page(inode->i_mapping, inode->i_size); 1784 cifs_truncate_page(inode->i_mapping, inode->i_size);
1756 } 1785 }
1757 1786
@@ -1776,14 +1805,12 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1776 1805
1777 xid = GetXid(); 1806 xid = GetXid();
1778 1807
1779 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { 1808 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
1780 /* check if we have permission to change attrs */ 1809 attrs->ia_valid |= ATTR_FORCE;
1781 rc = inode_change_ok(inode, attrs); 1810
1782 if (rc < 0) 1811 rc = inode_change_ok(inode, attrs);
1783 goto out; 1812 if (rc < 0)
1784 else 1813 goto out;
1785 rc = 0;
1786 }
1787 1814
1788 full_path = build_path_from_dentry(direntry); 1815 full_path = build_path_from_dentry(direntry);
1789 if (full_path == NULL) { 1816 if (full_path == NULL) {
@@ -1869,18 +1896,24 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1869 CIFS_MOUNT_MAP_SPECIAL_CHR); 1896 CIFS_MOUNT_MAP_SPECIAL_CHR);
1870 } 1897 }
1871 1898
1872 if (!rc) { 1899 if (rc)
1873 rc = inode_setattr(inode, attrs); 1900 goto out;
1874 1901
1875 /* force revalidate when any of these times are set since some 1902 if ((attrs->ia_valid & ATTR_SIZE) &&
1876 of the fs types (eg ext3, fat) do not have fine enough 1903 attrs->ia_size != i_size_read(inode))
1877 time granularity to match protocol, and we do not have a 1904 truncate_setsize(inode, attrs->ia_size);
1878 a way (yet) to query the server fs's time granularity (and 1905
1879 whether it rounds times down). 1906 setattr_copy(inode, attrs);
1880 */ 1907 mark_inode_dirty(inode);
1881 if (!rc && (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))) 1908
1882 cifsInode->time = 0; 1909 /* force revalidate when any of these times are set since some
1883 } 1910 of the fs types (eg ext3, fat) do not have fine enough
1911 time granularity to match protocol, and we do not have a
1912 a way (yet) to query the server fs's time granularity (and
1913 whether it rounds times down).
1914 */
1915 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
1916 cifsInode->time = 0;
1884out: 1917out:
1885 kfree(args); 1918 kfree(args);
1886 kfree(full_path); 1919 kfree(full_path);
@@ -1905,14 +1938,13 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
1905 cFYI(1, "setattr on file %s attrs->iavalid 0x%x", 1938 cFYI(1, "setattr on file %s attrs->iavalid 0x%x",
1906 direntry->d_name.name, attrs->ia_valid); 1939 direntry->d_name.name, attrs->ia_valid);
1907 1940
1908 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { 1941 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
1909 /* check if we have permission to change attrs */ 1942 attrs->ia_valid |= ATTR_FORCE;
1910 rc = inode_change_ok(inode, attrs); 1943
1911 if (rc < 0) { 1944 rc = inode_change_ok(inode, attrs);
1912 FreeXid(xid); 1945 if (rc < 0) {
1913 return rc; 1946 FreeXid(xid);
1914 } else 1947 return rc;
1915 rc = 0;
1916 } 1948 }
1917 1949
1918 full_path = build_path_from_dentry(direntry); 1950 full_path = build_path_from_dentry(direntry);
@@ -2020,8 +2052,17 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
2020 2052
2021 /* do not need local check to inode_check_ok since the server does 2053 /* do not need local check to inode_check_ok since the server does
2022 that */ 2054 that */
2023 if (!rc) 2055 if (rc)
2024 rc = inode_setattr(inode, attrs); 2056 goto cifs_setattr_exit;
2057
2058 if ((attrs->ia_valid & ATTR_SIZE) &&
2059 attrs->ia_size != i_size_read(inode))
2060 truncate_setsize(inode, attrs->ia_size);
2061
2062 setattr_copy(inode, attrs);
2063 mark_inode_dirty(inode);
2064 return 0;
2065
2025cifs_setattr_exit: 2066cifs_setattr_exit:
2026 kfree(full_path); 2067 kfree(full_path);
2027 FreeXid(xid); 2068 FreeXid(xid);
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index 505926f1ee6b..9d38a71c8e14 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -41,8 +41,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
41 __u64 ExtAttrMask = 0; 41 __u64 ExtAttrMask = 0;
42 __u64 caps; 42 __u64 caps;
43 struct cifsTconInfo *tcon; 43 struct cifsTconInfo *tcon;
44 struct cifsFileInfo *pSMBFile = 44 struct cifsFileInfo *pSMBFile = filep->private_data;
45 (struct cifsFileInfo *)filep->private_data;
46#endif /* CONFIG_CIFS_POSIX */ 45#endif /* CONFIG_CIFS_POSIX */
47 46
48 xid = GetXid(); 47 xid = GetXid();
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 1394aa37f26c..3ccadc1326d6 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -498,7 +498,6 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
498 struct cifsTconInfo *tcon; 498 struct cifsTconInfo *tcon;
499 struct cifsInodeInfo *pCifsInode; 499 struct cifsInodeInfo *pCifsInode;
500 struct cifsFileInfo *netfile; 500 struct cifsFileInfo *netfile;
501 int rc;
502 501
503 cFYI(1, "Checking for oplock break or dnotify response"); 502 cFYI(1, "Checking for oplock break or dnotify response");
504 if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) && 503 if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
@@ -583,13 +582,18 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
583 pCifsInode->clientCanCacheAll = false; 582 pCifsInode->clientCanCacheAll = false;
584 if (pSMB->OplockLevel == 0) 583 if (pSMB->OplockLevel == 0)
585 pCifsInode->clientCanCacheRead = false; 584 pCifsInode->clientCanCacheRead = false;
586 rc = slow_work_enqueue(&netfile->oplock_break); 585
587 if (rc) { 586 /*
588 cERROR(1, "failed to enqueue oplock " 587 * cifs_oplock_break_put() can't be called
589 "break: %d\n", rc); 588 * from here. Get reference after queueing
590 } else { 589 * succeeded. cifs_oplock_break() will
591 netfile->oplock_break_cancelled = false; 590 * synchronize using GlobalSMSSeslock.
592 } 591 */
592 if (queue_work(system_nrt_wq,
593 &netfile->oplock_break))
594 cifs_oplock_break_get(netfile);
595 netfile->oplock_break_cancelled = false;
596
593 read_unlock(&GlobalSMBSeslock); 597 read_unlock(&GlobalSMBSeslock);
594 read_unlock(&cifs_tcp_ses_lock); 598 read_unlock(&cifs_tcp_ses_lock);
595 return true; 599 return true;
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index d35d52889cb5..f97851119e6c 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -61,6 +61,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
61 {ERRremcd, -EACCES}, 61 {ERRremcd, -EACCES},
62 {ERRdiffdevice, -EXDEV}, 62 {ERRdiffdevice, -EXDEV},
63 {ERRnofiles, -ENOENT}, 63 {ERRnofiles, -ENOENT},
64 {ERRwriteprot, -EROFS},
64 {ERRbadshare, -ETXTBSY}, 65 {ERRbadshare, -ETXTBSY},
65 {ERRlock, -EACCES}, 66 {ERRlock, -EACCES},
66 {ERRunsup, -EINVAL}, 67 {ERRunsup, -EINVAL},
@@ -139,17 +140,18 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
139 * Returns 0 on failure. 140 * Returns 0 on failure.
140 */ 141 */
141static int 142static int
142cifs_inet_pton(const int address_family, const char *cp, void *dst) 143cifs_inet_pton(const int address_family, const char *cp, int len, void *dst)
143{ 144{
144 int ret = 0; 145 int ret = 0;
145 146
146 /* calculate length by finding first slash or NULL */ 147 /* calculate length by finding first slash or NULL */
147 if (address_family == AF_INET) 148 if (address_family == AF_INET)
148 ret = in4_pton(cp, -1 /* len */, dst, '\\', NULL); 149 ret = in4_pton(cp, len, dst, '\\', NULL);
149 else if (address_family == AF_INET6) 150 else if (address_family == AF_INET6)
150 ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL); 151 ret = in6_pton(cp, len, dst , '\\', NULL);
151 152
152 cFYI(DBG2, "address conversion returned %d for %s", ret, cp); 153 cFYI(DBG2, "address conversion returned %d for %*.*s",
154 ret, len, len, cp);
153 if (ret > 0) 155 if (ret > 0)
154 ret = 1; 156 ret = 1;
155 return ret; 157 return ret;
@@ -164,43 +166,66 @@ cifs_inet_pton(const int address_family, const char *cp, void *dst)
164 * Returns 0 on failure. 166 * Returns 0 on failure.
165 */ 167 */
166int 168int
167cifs_convert_address(char *src, void *dst) 169cifs_convert_address(struct sockaddr *dst, const char *src, int len)
168{ 170{
169 int rc; 171 int rc, alen, slen;
170 char *pct, *endp; 172 const char *pct;
173 char *endp, scope_id[13];
171 struct sockaddr_in *s4 = (struct sockaddr_in *) dst; 174 struct sockaddr_in *s4 = (struct sockaddr_in *) dst;
172 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst; 175 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst;
173 176
174 /* IPv4 address */ 177 /* IPv4 address */
175 if (cifs_inet_pton(AF_INET, src, &s4->sin_addr.s_addr)) { 178 if (cifs_inet_pton(AF_INET, src, len, &s4->sin_addr.s_addr)) {
176 s4->sin_family = AF_INET; 179 s4->sin_family = AF_INET;
177 return 1; 180 return 1;
178 } 181 }
179 182
180 /* temporarily terminate string */ 183 /* attempt to exclude the scope ID from the address part */
181 pct = strchr(src, '%'); 184 pct = memchr(src, '%', len);
182 if (pct) 185 alen = pct ? pct - src : len;
183 *pct = '\0';
184
185 rc = cifs_inet_pton(AF_INET6, src, &s6->sin6_addr.s6_addr);
186
187 /* repair temp termination (if any) and make pct point to scopeid */
188 if (pct)
189 *pct++ = '%';
190 186
187 rc = cifs_inet_pton(AF_INET6, src, alen, &s6->sin6_addr.s6_addr);
191 if (!rc) 188 if (!rc)
192 return rc; 189 return rc;
193 190
194 s6->sin6_family = AF_INET6; 191 s6->sin6_family = AF_INET6;
195 if (pct) { 192 if (pct) {
193 /* grab the scope ID */
194 slen = len - (alen + 1);
195 if (slen <= 0 || slen > 12)
196 return 0;
197 memcpy(scope_id, pct + 1, slen);
198 scope_id[slen] = '\0';
199
196 s6->sin6_scope_id = (u32) simple_strtoul(pct, &endp, 0); 200 s6->sin6_scope_id = (u32) simple_strtoul(pct, &endp, 0);
197 if (!*pct || *endp) 201 if (endp != scope_id + slen)
198 return 0; 202 return 0;
199 } 203 }
200 204
201 return rc; 205 return rc;
202} 206}
203 207
208int
209cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len,
210 const unsigned short int port)
211{
212 if (!cifs_convert_address(dst, src, len))
213 return 0;
214
215 switch (dst->sa_family) {
216 case AF_INET:
217 ((struct sockaddr_in *)dst)->sin_port = htons(port);
218 break;
219 case AF_INET6:
220 ((struct sockaddr_in6 *)dst)->sin6_port = htons(port);
221 break;
222 default:
223 return 0;
224 }
225
226 return 1;
227}
228
204/***************************************************************************** 229/*****************************************************************************
205convert a NT status code to a dos class/code 230convert a NT status code to a dos class/code
206 *****************************************************************************/ 231 *****************************************************************************/
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index daf1753af674..d5e591fab475 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -847,6 +847,11 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
847 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; 847 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
848 848
849 tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); 849 tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
850 if (tmp_buf == NULL) {
851 rc = -ENOMEM;
852 break;
853 }
854
850 for (i = 0; (i < num_to_fill) && (rc == 0); i++) { 855 for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
851 if (current_entry == NULL) { 856 if (current_entry == NULL) {
852 /* evaluate whether this case is an error */ 857 /* evaluate whether this case is an error */
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 7707389bdf2c..0a57cb7db5dd 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -730,15 +730,7 @@ ssetup_ntlmssp_authenticate:
730 730
731 /* calculate session key */ 731 /* calculate session key */
732 setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); 732 setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
733 if (first_time) /* should this be moved into common code 733 /* FIXME: calculate MAC key */
734 with similar ntlmv2 path? */
735 /* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
736 response BB FIXME, v2_sess_key); */
737
738 /* copy session key */
739
740 /* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
741 bcc_ptr += LM2_SESS_KEY_SIZE; */
742 memcpy(bcc_ptr, (char *)v2_sess_key, 734 memcpy(bcc_ptr, (char *)v2_sess_key,
743 sizeof(struct ntlmv2_resp)); 735 sizeof(struct ntlmv2_resp));
744 bcc_ptr += sizeof(struct ntlmv2_resp); 736 bcc_ptr += sizeof(struct ntlmv2_resp);
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h
index c5084d27db7c..7f16cb825fe5 100644
--- a/fs/cifs/smberr.h
+++ b/fs/cifs/smberr.h
@@ -76,6 +76,7 @@
76#define ERRnofiles 18 /* A File Search command can find no 76#define ERRnofiles 18 /* A File Search command can find no
77 more files matching the specified 77 more files matching the specified
78 criteria. */ 78 criteria. */
79#define ERRwriteprot 19 /* media is write protected */
79#define ERRgeneral 31 80#define ERRgeneral 31
80#define ERRbadshare 32 /* The sharing mode specified for an 81#define ERRbadshare 32 /* The sharing mode specified for an
81 Open conflicts with existing FIDs on 82 Open conflicts with existing FIDs on