aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-03-26 13:29:40 -0400
committerIngo Molnar <mingo@elte.hu>2009-03-26 13:29:40 -0400
commit5a54bd1307471c1cd0521402fe65e2057edcab2f (patch)
tree25fb6a543db4ccc11b6d5662ed2e7facfce39ae7 /fs/cifs
parentf9f35677d81adb0feedcd6e0e661784805c8facd (diff)
parent8e0ee43bc2c3e19db56a4adaa9a9b04ce885cd84 (diff)
Merge commit 'v2.6.29' into core/header-fixes
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/CHANGES15
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsglob.h6
-rw-r--r--fs/cifs/cifsproto.h4
-rw-r--r--fs/cifs/cifssmb.c7
-rw-r--r--fs/cifs/connect.c51
-rw-r--r--fs/cifs/dir.c307
-rw-r--r--fs/cifs/inode.c104
-rw-r--r--fs/cifs/readdir.c58
-rw-r--r--fs/cifs/sess.c91
10 files changed, 458 insertions, 187 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 73ac7ebd1dfc..851388fafc73 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,13 @@
1Version 1.57
2------------
3Improve support for multiple security contexts to the same server. We
4used to use the same "vcnumber" for all connections which could cause
5the server to treat subsequent connections, especially those that
6are authenticated as guest, as reconnections, invalidating the earlier
7user's smb session. This fix allows cifs to mount multiple times to the
8same server with different userids without risking invalidating earlier
9established security contexts.
10
1Version 1.56 11Version 1.56
2------------ 12------------
3Add "forcemandatorylock" mount option to allow user to use mandatory 13Add "forcemandatorylock" mount option to allow user to use mandatory
@@ -7,7 +17,10 @@ specified and user does not have access to query information about the
7top of the share. Fix problem in 2.6.28 resolving DFS paths to 17top of the share. Fix problem in 2.6.28 resolving DFS paths to
8Samba servers (worked to Windows). Fix rmdir so that pending search 18Samba servers (worked to Windows). Fix rmdir so that pending search
9(readdir) requests do not get invalid results which include the now 19(readdir) requests do not get invalid results which include the now
10removed directory. 20removed directory. Fix oops in cifs_dfs_ref.c when prefixpath is not reachable
21when using DFS. Add better file create support to servers which support
22the CIFS POSIX protocol extensions (this adds support for new flags
23on create, and improves semantics for write of locked ranges).
11 24
12Version 1.55 25Version 1.55
13------------ 26------------
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 7ac481841f87..2b1d28a9ee28 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -100,5 +100,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
100extern const struct export_operations cifs_export_ops; 100extern const struct export_operations cifs_export_ops;
101#endif /* EXPERIMENTAL */ 101#endif /* EXPERIMENTAL */
102 102
103#define CIFS_VERSION "1.56" 103#define CIFS_VERSION "1.57"
104#endif /* _CIFSFS_H */ 104#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 94c1ca0ec953..e004f6db5fc8 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -164,9 +164,12 @@ struct TCP_Server_Info {
164 /* multiplexed reads or writes */ 164 /* multiplexed reads or writes */
165 unsigned int maxBuf; /* maxBuf specifies the maximum */ 165 unsigned int maxBuf; /* maxBuf specifies the maximum */
166 /* message size the server can send or receive for non-raw SMBs */ 166 /* message size the server can send or receive for non-raw SMBs */
167 unsigned int maxRw; /* maxRw specifies the maximum */ 167 unsigned int max_rw; /* maxRw specifies the maximum */
168 /* message size the server can send or receive for */ 168 /* message size the server can send or receive for */
169 /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ 169 /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
170 unsigned int max_vcs; /* maximum number of smb sessions, at least
171 those that can be specified uniquely with
172 vcnumbers */
170 char sessid[4]; /* unique token id for this session */ 173 char sessid[4]; /* unique token id for this session */
171 /* (returned on Negotiate */ 174 /* (returned on Negotiate */
172 int capabilities; /* allow selective disabling of caps by smb sess */ 175 int capabilities; /* allow selective disabling of caps by smb sess */
@@ -210,6 +213,7 @@ struct cifsSesInfo {
210 unsigned overrideSecFlg; /* if non-zero override global sec flags */ 213 unsigned overrideSecFlg; /* if non-zero override global sec flags */
211 __u16 ipc_tid; /* special tid for connection to IPC share */ 214 __u16 ipc_tid; /* special tid for connection to IPC share */
212 __u16 flags; 215 __u16 flags;
216 __u16 vcnum;
213 char *serverOS; /* name of operating system underlying server */ 217 char *serverOS; /* name of operating system underlying server */
214 char *serverNOS; /* name of network operating system of server */ 218 char *serverNOS; /* name of network operating system of server */
215 char *serverDomain; /* security realm of server */ 219 char *serverDomain; /* security realm of server */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 382ba6298809..083dfc57c7a3 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -42,6 +42,7 @@ extern void _FreeXid(unsigned int);
42#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid())); 42#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid()));
43#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));} 43#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));}
44extern char *build_path_from_dentry(struct dentry *); 44extern char *build_path_from_dentry(struct dentry *);
45extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb);
45extern char *build_wildcard_path_from_dentry(struct dentry *direntry); 46extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
46/* extern void renew_parental_timestamps(struct dentry *direntry);*/ 47/* extern void renew_parental_timestamps(struct dentry *direntry);*/
47extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, 48extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
@@ -91,6 +92,9 @@ extern u64 cifs_UnixTimeToNT(struct timespec);
91extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time); 92extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
92extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time); 93extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time);
93 94
95extern void posix_fill_in_inode(struct inode *tmp_inode,
96 FILE_UNIX_BASIC_INFO *pData, int isNewInode);
97extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum);
94extern int cifs_get_inode_info(struct inode **pinode, 98extern int cifs_get_inode_info(struct inode **pinode,
95 const unsigned char *search_path, 99 const unsigned char *search_path,
96 FILE_ALL_INFO *pfile_info, 100 FILE_ALL_INFO *pfile_info,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 552642a507c4..939e2f76b959 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -528,14 +528,15 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
528 server->maxReq = le16_to_cpu(rsp->MaxMpxCount); 528 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
529 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize), 529 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
530 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); 530 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
531 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
531 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey); 532 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
532 /* even though we do not use raw we might as well set this 533 /* even though we do not use raw we might as well set this
533 accurately, in case we ever find a need for it */ 534 accurately, in case we ever find a need for it */
534 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { 535 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
535 server->maxRw = 0xFF00; 536 server->max_rw = 0xFF00;
536 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE; 537 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
537 } else { 538 } else {
538 server->maxRw = 0;/* we do not need to use raw anyway */ 539 server->max_rw = 0;/* do not need to use raw anyway */
539 server->capabilities = CAP_MPX_MODE; 540 server->capabilities = CAP_MPX_MODE;
540 } 541 }
541 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone); 542 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
@@ -638,7 +639,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
638 /* probably no need to store and check maxvcs */ 639 /* probably no need to store and check maxvcs */
639 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize), 640 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
640 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); 641 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
641 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize); 642 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
642 cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf)); 643 cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf));
643 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); 644 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
644 server->capabilities = le32_to_cpu(pSMBr->Capabilities); 645 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 2209be943051..da0f4ffa0613 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -23,7 +23,6 @@
23#include <linux/string.h> 23#include <linux/string.h>
24#include <linux/list.h> 24#include <linux/list.h>
25#include <linux/wait.h> 25#include <linux/wait.h>
26#include <linux/ipv6.h>
27#include <linux/pagemap.h> 26#include <linux/pagemap.h>
28#include <linux/ctype.h> 27#include <linux/ctype.h>
29#include <linux/utsname.h> 28#include <linux/utsname.h>
@@ -35,6 +34,7 @@
35#include <linux/freezer.h> 34#include <linux/freezer.h>
36#include <asm/uaccess.h> 35#include <asm/uaccess.h>
37#include <asm/processor.h> 36#include <asm/processor.h>
37#include <net/ipv6.h>
38#include "cifspdu.h" 38#include "cifspdu.h"
39#include "cifsglob.h" 39#include "cifsglob.h"
40#include "cifsproto.h" 40#include "cifsproto.h"
@@ -1379,8 +1379,8 @@ cifs_find_tcp_session(struct sockaddr_storage *addr)
1379 server->addr.sockAddr.sin_addr.s_addr)) 1379 server->addr.sockAddr.sin_addr.s_addr))
1380 continue; 1380 continue;
1381 else if (addr->ss_family == AF_INET6 && 1381 else if (addr->ss_family == AF_INET6 &&
1382 memcmp(&server->addr.sockAddr6.sin6_addr, 1382 !ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr,
1383 &addr6->sin6_addr, sizeof(addr6->sin6_addr))) 1383 &addr6->sin6_addr))
1384 continue; 1384 continue;
1385 1385
1386 ++server->srv_count; 1386 ++server->srv_count;
@@ -2180,6 +2180,33 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
2180 "mount option supported")); 2180 "mount option supported"));
2181} 2181}
2182 2182
2183static int
2184is_path_accessible(int xid, struct cifsTconInfo *tcon,
2185 struct cifs_sb_info *cifs_sb, const char *full_path)
2186{
2187 int rc;
2188 __u64 inode_num;
2189 FILE_ALL_INFO *pfile_info;
2190
2191 rc = CIFSGetSrvInodeNumber(xid, tcon, full_path, &inode_num,
2192 cifs_sb->local_nls,
2193 cifs_sb->mnt_cifs_flags &
2194 CIFS_MOUNT_MAP_SPECIAL_CHR);
2195 if (rc != -EOPNOTSUPP)
2196 return rc;
2197
2198 pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
2199 if (pfile_info == NULL)
2200 return -ENOMEM;
2201
2202 rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info,
2203 0 /* not legacy */, cifs_sb->local_nls,
2204 cifs_sb->mnt_cifs_flags &
2205 CIFS_MOUNT_MAP_SPECIAL_CHR);
2206 kfree(pfile_info);
2207 return rc;
2208}
2209
2183int 2210int
2184cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, 2211cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2185 char *mount_data, const char *devname) 2212 char *mount_data, const char *devname)
@@ -2190,6 +2217,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2190 struct cifsSesInfo *pSesInfo = NULL; 2217 struct cifsSesInfo *pSesInfo = NULL;
2191 struct cifsTconInfo *tcon = NULL; 2218 struct cifsTconInfo *tcon = NULL;
2192 struct TCP_Server_Info *srvTcp = NULL; 2219 struct TCP_Server_Info *srvTcp = NULL;
2220 char *full_path;
2193 2221
2194 xid = GetXid(); 2222 xid = GetXid();
2195 2223
@@ -2426,6 +2454,23 @@ mount_fail_check:
2426 cifs_sb->rsize = min(cifs_sb->rsize, 2454 cifs_sb->rsize = min(cifs_sb->rsize,
2427 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); 2455 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
2428 2456
2457 if (!rc && cifs_sb->prepathlen) {
2458 /* build_path_to_root works only when we have a valid tcon */
2459 full_path = cifs_build_path_to_root(cifs_sb);
2460 if (full_path == NULL) {
2461 rc = -ENOMEM;
2462 goto mount_fail_check;
2463 }
2464 rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
2465 if (rc) {
2466 cERROR(1, ("Path %s in not accessible: %d",
2467 full_path, rc));
2468 kfree(full_path);
2469 goto mount_fail_check;
2470 }
2471 kfree(full_path);
2472 }
2473
2429 /* volume_info->password is freed above when existing session found 2474 /* volume_info->password is freed above when existing session found
2430 (in which case it is not needed anymore) but when new sesion is created 2475 (in which case it is not needed anymore) but when new sesion is created
2431 the password ptr is put in the new session structure (in which case the 2476 the password ptr is put in the new session structure (in which case the
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 964aad03c5ad..89fb72832652 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * vfs operations that deal with dentries 4 * vfs operations that deal with dentries
5 * 5 *
6 * Copyright (C) International Business Machines Corp., 2002,2008 6 * Copyright (C) International Business Machines Corp., 2002,2009
7 * Author(s): Steve French (sfrench@us.ibm.com) 7 * Author(s): Steve French (sfrench@us.ibm.com)
8 * 8 *
9 * This library is free software; you can redistribute it and/or modify 9 * This library is free software; you can redistribute it and/or modify
@@ -129,6 +129,78 @@ cifs_bp_rename_retry:
129 return full_path; 129 return full_path;
130} 130}
131 131
132static int cifs_posix_open(char *full_path, struct inode **pinode,
133 struct super_block *sb, int mode, int oflags,
134 int *poplock, __u16 *pnetfid, int xid)
135{
136 int rc;
137 __u32 oplock;
138 FILE_UNIX_BASIC_INFO *presp_data;
139 __u32 posix_flags = 0;
140 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
141
142 cFYI(1, ("posix open %s", full_path));
143
144 presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
145 if (presp_data == NULL)
146 return -ENOMEM;
147
148/* So far cifs posix extensions can only map the following flags.
149 There are other valid fmode oflags such as FMODE_LSEEK, FMODE_PREAD, but
150 so far we do not seem to need them, and we can treat them as local only */
151 if ((oflags & (FMODE_READ | FMODE_WRITE)) ==
152 (FMODE_READ | FMODE_WRITE))
153 posix_flags = SMB_O_RDWR;
154 else if (oflags & FMODE_READ)
155 posix_flags = SMB_O_RDONLY;
156 else if (oflags & FMODE_WRITE)
157 posix_flags = SMB_O_WRONLY;
158 if (oflags & O_CREAT)
159 posix_flags |= SMB_O_CREAT;
160 if (oflags & O_EXCL)
161 posix_flags |= SMB_O_EXCL;
162 if (oflags & O_TRUNC)
163 posix_flags |= SMB_O_TRUNC;
164 if (oflags & O_APPEND)
165 posix_flags |= SMB_O_APPEND;
166 if (oflags & O_SYNC)
167 posix_flags |= SMB_O_SYNC;
168 if (oflags & O_DIRECTORY)
169 posix_flags |= SMB_O_DIRECTORY;
170 if (oflags & O_NOFOLLOW)
171 posix_flags |= SMB_O_NOFOLLOW;
172 if (oflags & O_DIRECT)
173 posix_flags |= SMB_O_DIRECT;
174
175
176 rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
177 pnetfid, presp_data, &oplock, full_path,
178 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
179 CIFS_MOUNT_MAP_SPECIAL_CHR);
180 if (rc)
181 goto posix_open_ret;
182
183 if (presp_data->Type == cpu_to_le32(-1))
184 goto posix_open_ret; /* open ok, caller does qpathinfo */
185
186 /* get new inode and set it up */
187 if (!pinode)
188 goto posix_open_ret; /* caller does not need info */
189
190 *pinode = cifs_new_inode(sb, &presp_data->UniqueId);
191
192 /* We do not need to close the file if new_inode fails since
193 the caller will retry qpathinfo as long as inode is null */
194 if (*pinode == NULL)
195 goto posix_open_ret;
196
197 posix_fill_in_inode(*pinode, presp_data, 1);
198
199posix_open_ret:
200 kfree(presp_data);
201 return rc;
202}
203
132static void setup_cifs_dentry(struct cifsTconInfo *tcon, 204static void setup_cifs_dentry(struct cifsTconInfo *tcon,
133 struct dentry *direntry, 205 struct dentry *direntry,
134 struct inode *newinode) 206 struct inode *newinode)
@@ -150,7 +222,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
150 int xid; 222 int xid;
151 int create_options = CREATE_NOT_DIR; 223 int create_options = CREATE_NOT_DIR;
152 int oplock = 0; 224 int oplock = 0;
153 /* BB below access is too much for the mknod to request */ 225 int oflags;
226 /*
227 * BB below access is probably too much for mknod to request
228 * but we have to do query and setpathinfo so requesting
229 * less could fail (unless we want to request getatr and setatr
230 * permissions (only). At least for POSIX we do not have to
231 * request so much.
232 */
154 int desiredAccess = GENERIC_READ | GENERIC_WRITE; 233 int desiredAccess = GENERIC_READ | GENERIC_WRITE;
155 __u16 fileHandle; 234 __u16 fileHandle;
156 struct cifs_sb_info *cifs_sb; 235 struct cifs_sb_info *cifs_sb;
@@ -174,13 +253,43 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
174 } 253 }
175 254
176 mode &= ~current->fs->umask; 255 mode &= ~current->fs->umask;
256 if (oplockEnabled)
257 oplock = REQ_OPLOCK;
177 258
178 if (nd && (nd->flags & LOOKUP_OPEN)) { 259 if (nd && (nd->flags & LOOKUP_OPEN))
179 int oflags = nd->intent.open.flags; 260 oflags = nd->intent.open.flags;
261 else
262 oflags = FMODE_READ;
263
264 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
265 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
266 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
267 rc = cifs_posix_open(full_path, &newinode, inode->i_sb,
268 mode, oflags, &oplock, &fileHandle, xid);
269 /* EIO could indicate that (posix open) operation is not
270 supported, despite what server claimed in capability
271 negotation. EREMOTE indicates DFS junction, which is not
272 handled in posix open */
273
274 if ((rc == 0) && (newinode == NULL))
275 goto cifs_create_get_file_info; /* query inode info */
276 else if (rc == 0) /* success, no need to query */
277 goto cifs_create_set_dentry;
278 else if ((rc != -EIO) && (rc != -EREMOTE) &&
279 (rc != -EOPNOTSUPP)) /* path not found or net err */
280 goto cifs_create_out;
281 /* else fallthrough to retry, using older open call, this is
282 case where server does not support this SMB level, and
283 falsely claims capability (also get here for DFS case
284 which should be rare for path not covered on files) */
285 }
180 286
287 if (nd && (nd->flags & LOOKUP_OPEN)) {
288 /* if the file is going to stay open, then we
289 need to set the desired access properly */
181 desiredAccess = 0; 290 desiredAccess = 0;
182 if (oflags & FMODE_READ) 291 if (oflags & FMODE_READ)
183 desiredAccess |= GENERIC_READ; 292 desiredAccess |= GENERIC_READ; /* is this too little? */
184 if (oflags & FMODE_WRITE) { 293 if (oflags & FMODE_WRITE) {
185 desiredAccess |= GENERIC_WRITE; 294 desiredAccess |= GENERIC_WRITE;
186 if (!(oflags & FMODE_READ)) 295 if (!(oflags & FMODE_READ))
@@ -199,8 +308,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
199 308
200 /* BB add processing to set equivalent of mode - e.g. via CreateX with 309 /* BB add processing to set equivalent of mode - e.g. via CreateX with
201 ACLs */ 310 ACLs */
202 if (oplockEnabled)
203 oplock = REQ_OPLOCK;
204 311
205 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); 312 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
206 if (buf == NULL) { 313 if (buf == NULL) {
@@ -233,116 +340,112 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
233 } 340 }
234 if (rc) { 341 if (rc) {
235 cFYI(1, ("cifs_create returned 0x%x", rc)); 342 cFYI(1, ("cifs_create returned 0x%x", rc));
236 } else { 343 goto cifs_create_out;
237 /* If Open reported that we actually created a file 344 }
238 then we now have to set the mode if possible */ 345
239 if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) { 346 /* If Open reported that we actually created a file
240 struct cifs_unix_set_info_args args = { 347 then we now have to set the mode if possible */
348 if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
349 struct cifs_unix_set_info_args args = {
241 .mode = mode, 350 .mode = mode,
242 .ctime = NO_CHANGE_64, 351 .ctime = NO_CHANGE_64,
243 .atime = NO_CHANGE_64, 352 .atime = NO_CHANGE_64,
244 .mtime = NO_CHANGE_64, 353 .mtime = NO_CHANGE_64,
245 .device = 0, 354 .device = 0,
246 }; 355 };
247 356
248 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 357 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
249 args.uid = (__u64) current_fsuid(); 358 args.uid = (__u64) current_fsuid();
250 if (inode->i_mode & S_ISGID) 359 if (inode->i_mode & S_ISGID)
251 args.gid = (__u64) inode->i_gid; 360 args.gid = (__u64) inode->i_gid;
252 else 361 else
253 args.gid = (__u64) current_fsgid(); 362 args.gid = (__u64) current_fsgid();
254 } else {
255 args.uid = NO_CHANGE_64;
256 args.gid = NO_CHANGE_64;
257 }
258 CIFSSMBUnixSetInfo(xid, tcon, full_path, &args,
259 cifs_sb->local_nls,
260 cifs_sb->mnt_cifs_flags &
261 CIFS_MOUNT_MAP_SPECIAL_CHR);
262 } else { 363 } else {
263 /* BB implement mode setting via Windows security 364 args.uid = NO_CHANGE_64;
264 descriptors e.g. */ 365 args.gid = NO_CHANGE_64;
265 /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
266
267 /* Could set r/o dos attribute if mode & 0222 == 0 */
268 } 366 }
367 CIFSSMBUnixSetInfo(xid, tcon, full_path, &args,
368 cifs_sb->local_nls,
369 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
370 } else {
371 /* BB implement mode setting via Windows security
372 descriptors e.g. */
373 /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
269 374
270 /* server might mask mode so we have to query for it */ 375 /* Could set r/o dos attribute if mode & 0222 == 0 */
271 if (tcon->unix_ext) 376 }
272 rc = cifs_get_inode_info_unix(&newinode, full_path, 377
273 inode->i_sb, xid); 378cifs_create_get_file_info:
274 else { 379 /* server might mask mode so we have to query for it */
275 rc = cifs_get_inode_info(&newinode, full_path, 380 if (tcon->unix_ext)
276 buf, inode->i_sb, xid, 381 rc = cifs_get_inode_info_unix(&newinode, full_path,
277 &fileHandle); 382 inode->i_sb, xid);
278 if (newinode) { 383 else {
279 if (cifs_sb->mnt_cifs_flags & 384 rc = cifs_get_inode_info(&newinode, full_path, buf,
280 CIFS_MOUNT_DYNPERM) 385 inode->i_sb, xid, &fileHandle);
281 newinode->i_mode = mode; 386 if (newinode) {
282 if ((oplock & CIFS_CREATE_ACTION) && 387 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
283 (cifs_sb->mnt_cifs_flags & 388 newinode->i_mode = mode;
284 CIFS_MOUNT_SET_UID)) { 389 if ((oplock & CIFS_CREATE_ACTION) &&
285 newinode->i_uid = current_fsuid(); 390 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
286 if (inode->i_mode & S_ISGID) 391 newinode->i_uid = current_fsuid();
287 newinode->i_gid = 392 if (inode->i_mode & S_ISGID)
288 inode->i_gid; 393 newinode->i_gid = inode->i_gid;
289 else 394 else
290 newinode->i_gid = 395 newinode->i_gid = current_fsgid();
291 current_fsgid();
292 }
293 } 396 }
294 } 397 }
398 }
295 399
296 if (rc != 0) { 400cifs_create_set_dentry:
297 cFYI(1, ("Create worked, get_inode_info failed rc = %d", 401 if (rc == 0)
298 rc)); 402 setup_cifs_dentry(tcon, direntry, newinode);
299 } else 403 else
300 setup_cifs_dentry(tcon, direntry, newinode); 404 cFYI(1, ("Create worked, get_inode_info failed rc = %d", rc));
301 405
302 if ((nd == NULL /* nfsd case - nfs srv does not set nd */) || 406 /* nfsd case - nfs srv does not set nd */
303 (!(nd->flags & LOOKUP_OPEN))) { 407 if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
304 /* mknod case - do not leave file open */ 408 /* mknod case - do not leave file open */
305 CIFSSMBClose(xid, tcon, fileHandle); 409 CIFSSMBClose(xid, tcon, fileHandle);
306 } else if (newinode) { 410 } else if (newinode) {
307 struct cifsFileInfo *pCifsFile = 411 struct cifsFileInfo *pCifsFile =
308 kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); 412 kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
309 413
310 if (pCifsFile == NULL) 414 if (pCifsFile == NULL)
311 goto cifs_create_out; 415 goto cifs_create_out;
312 pCifsFile->netfid = fileHandle; 416 pCifsFile->netfid = fileHandle;
313 pCifsFile->pid = current->tgid; 417 pCifsFile->pid = current->tgid;
314 pCifsFile->pInode = newinode; 418 pCifsFile->pInode = newinode;
315 pCifsFile->invalidHandle = false; 419 pCifsFile->invalidHandle = false;
316 pCifsFile->closePend = false; 420 pCifsFile->closePend = false;
317 init_MUTEX(&pCifsFile->fh_sem); 421 init_MUTEX(&pCifsFile->fh_sem);
318 mutex_init(&pCifsFile->lock_mutex); 422 mutex_init(&pCifsFile->lock_mutex);
319 INIT_LIST_HEAD(&pCifsFile->llist); 423 INIT_LIST_HEAD(&pCifsFile->llist);
320 atomic_set(&pCifsFile->wrtPending, 0); 424 atomic_set(&pCifsFile->wrtPending, 0);
321 425
322 /* set the following in open now 426 /* set the following in open now
323 pCifsFile->pfile = file; */ 427 pCifsFile->pfile = file; */
324 write_lock(&GlobalSMBSeslock); 428 write_lock(&GlobalSMBSeslock);
325 list_add(&pCifsFile->tlist, &tcon->openFileList); 429 list_add(&pCifsFile->tlist, &tcon->openFileList);
326 pCifsInode = CIFS_I(newinode); 430 pCifsInode = CIFS_I(newinode);
327 if (pCifsInode) { 431 if (pCifsInode) {
328 /* if readable file instance put first in list*/ 432 /* if readable file instance put first in list*/
329 if (write_only) { 433 if (write_only) {
330 list_add_tail(&pCifsFile->flist, 434 list_add_tail(&pCifsFile->flist,
331 &pCifsInode->openFileList); 435 &pCifsInode->openFileList);
332 } else { 436 } else {
333 list_add(&pCifsFile->flist, 437 list_add(&pCifsFile->flist,
334 &pCifsInode->openFileList); 438 &pCifsInode->openFileList);
335 }
336 if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
337 pCifsInode->clientCanCacheAll = true;
338 pCifsInode->clientCanCacheRead = true;
339 cFYI(1, ("Exclusive Oplock inode %p",
340 newinode));
341 } else if ((oplock & 0xF) == OPLOCK_READ)
342 pCifsInode->clientCanCacheRead = true;
343 } 439 }
344 write_unlock(&GlobalSMBSeslock); 440 if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
441 pCifsInode->clientCanCacheAll = true;
442 pCifsInode->clientCanCacheRead = true;
443 cFYI(1, ("Exclusive Oplock inode %p",
444 newinode));
445 } else if ((oplock & 0xF) == OPLOCK_READ)
446 pCifsInode->clientCanCacheRead = true;
345 } 447 }
448 write_unlock(&GlobalSMBSeslock);
346 } 449 }
347cifs_create_out: 450cifs_create_out:
348 kfree(buf); 451 kfree(buf);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index bcf7b5184664..4690a360c855 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -199,6 +199,49 @@ static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat,
199 pfnd_dat->Gid = cpu_to_le64(pinode->i_gid); 199 pfnd_dat->Gid = cpu_to_le64(pinode->i_gid);
200} 200}
201 201
202/**
203 * cifs_new inode - create new inode, initialize, and hash it
204 * @sb - pointer to superblock
205 * @inum - if valid pointer and serverino is enabled, replace i_ino with val
206 *
207 * Create a new inode, initialize it for CIFS and hash it. Returns the new
208 * inode or NULL if one couldn't be allocated.
209 *
210 * If the share isn't mounted with "serverino" or inum is a NULL pointer then
211 * we'll just use the inode number assigned by new_inode(). Note that this can
212 * mean i_ino collisions since the i_ino assigned by new_inode is not
213 * guaranteed to be unique.
214 */
215struct inode *
216cifs_new_inode(struct super_block *sb, __u64 *inum)
217{
218 struct inode *inode;
219
220 inode = new_inode(sb);
221 if (inode == NULL)
222 return NULL;
223
224 /*
225 * BB: Is i_ino == 0 legal? Here, we assume that it is. If it isn't we
226 * stop passing inum as ptr. Are there sanity checks we can use to
227 * ensure that the server is really filling in that field? Also,
228 * if serverino is disabled, perhaps we should be using iunique()?
229 */
230 if (inum && (CIFS_SB(sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM))
231 inode->i_ino = (unsigned long) *inum;
232
233 /*
234 * must set this here instead of cifs_alloc_inode since VFS will
235 * clobber i_flags
236 */
237 if (sb->s_flags & MS_NOATIME)
238 inode->i_flags |= S_NOATIME | S_NOCMTIME;
239
240 insert_inode_hash(inode);
241
242 return inode;
243}
244
202int cifs_get_inode_info_unix(struct inode **pinode, 245int cifs_get_inode_info_unix(struct inode **pinode,
203 const unsigned char *full_path, struct super_block *sb, int xid) 246 const unsigned char *full_path, struct super_block *sb, int xid)
204{ 247{
@@ -233,22 +276,11 @@ int cifs_get_inode_info_unix(struct inode **pinode,
233 276
234 /* get new inode */ 277 /* get new inode */
235 if (*pinode == NULL) { 278 if (*pinode == NULL) {
236 *pinode = new_inode(sb); 279 *pinode = cifs_new_inode(sb, &find_data.UniqueId);
237 if (*pinode == NULL) { 280 if (*pinode == NULL) {
238 rc = -ENOMEM; 281 rc = -ENOMEM;
239 goto cgiiu_exit; 282 goto cgiiu_exit;
240 } 283 }
241 /* Is an i_ino of zero legal? */
242 /* note ino incremented to unique num in new_inode */
243 /* Are there sanity checks we can use to ensure that
244 the server is really filling in that field? */
245 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
246 (*pinode)->i_ino = (unsigned long)find_data.UniqueId;
247
248 if (sb->s_flags & MS_NOATIME)
249 (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
250
251 insert_inode_hash(*pinode);
252 } 284 }
253 285
254 inode = *pinode; 286 inode = *pinode;
@@ -465,11 +497,9 @@ int cifs_get_inode_info(struct inode **pinode,
465 497
466 /* get new inode */ 498 /* get new inode */
467 if (*pinode == NULL) { 499 if (*pinode == NULL) {
468 *pinode = new_inode(sb); 500 __u64 inode_num;
469 if (*pinode == NULL) { 501 __u64 *pinum = &inode_num;
470 rc = -ENOMEM; 502
471 goto cgii_exit;
472 }
473 /* Is an i_ino of zero legal? Can we use that to check 503 /* Is an i_ino of zero legal? Can we use that to check
474 if the server supports returning inode numbers? Are 504 if the server supports returning inode numbers? Are
475 there other sanity checks we can use to ensure that 505 there other sanity checks we can use to ensure that
@@ -486,22 +516,26 @@ int cifs_get_inode_info(struct inode **pinode,
486 516
487 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { 517 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
488 int rc1 = 0; 518 int rc1 = 0;
489 __u64 inode_num;
490 519
491 rc1 = CIFSGetSrvInodeNumber(xid, pTcon, 520 rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
492 full_path, &inode_num, 521 full_path, pinum,
493 cifs_sb->local_nls, 522 cifs_sb->local_nls,
494 cifs_sb->mnt_cifs_flags & 523 cifs_sb->mnt_cifs_flags &
495 CIFS_MOUNT_MAP_SPECIAL_CHR); 524 CIFS_MOUNT_MAP_SPECIAL_CHR);
496 if (rc1) { 525 if (rc1) {
497 cFYI(1, ("GetSrvInodeNum rc %d", rc1)); 526 cFYI(1, ("GetSrvInodeNum rc %d", rc1));
527 pinum = NULL;
498 /* BB EOPNOSUPP disable SERVER_INUM? */ 528 /* BB EOPNOSUPP disable SERVER_INUM? */
499 } else /* do we need cast or hash to ino? */ 529 }
500 (*pinode)->i_ino = inode_num; 530 } else {
501 } /* else ino incremented to unique num in new_inode*/ 531 pinum = NULL;
502 if (sb->s_flags & MS_NOATIME) 532 }
503 (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; 533
504 insert_inode_hash(*pinode); 534 *pinode = cifs_new_inode(sb, pinum);
535 if (*pinode == NULL) {
536 rc = -ENOMEM;
537 goto cgii_exit;
538 }
505 } 539 }
506 inode = *pinode; 540 inode = *pinode;
507 cifsInfo = CIFS_I(inode); 541 cifsInfo = CIFS_I(inode);
@@ -621,7 +655,7 @@ static const struct inode_operations cifs_ipc_inode_ops = {
621 .lookup = cifs_lookup, 655 .lookup = cifs_lookup,
622}; 656};
623 657
624static char *build_path_to_root(struct cifs_sb_info *cifs_sb) 658char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
625{ 659{
626 int pplen = cifs_sb->prepathlen; 660 int pplen = cifs_sb->prepathlen;
627 int dfsplen; 661 int dfsplen;
@@ -678,7 +712,7 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
678 return inode; 712 return inode;
679 713
680 cifs_sb = CIFS_SB(inode->i_sb); 714 cifs_sb = CIFS_SB(inode->i_sb);
681 full_path = build_path_to_root(cifs_sb); 715 full_path = cifs_build_path_to_root(cifs_sb);
682 if (full_path == NULL) 716 if (full_path == NULL)
683 return ERR_PTR(-ENOMEM); 717 return ERR_PTR(-ENOMEM);
684 718
@@ -1017,7 +1051,7 @@ out_reval:
1017 return rc; 1051 return rc;
1018} 1052}
1019 1053
1020static void posix_fill_in_inode(struct inode *tmp_inode, 1054void posix_fill_in_inode(struct inode *tmp_inode,
1021 FILE_UNIX_BASIC_INFO *pData, int isNewInode) 1055 FILE_UNIX_BASIC_INFO *pData, int isNewInode)
1022{ 1056{
1023 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); 1057 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
@@ -1114,24 +1148,14 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
1114 else 1148 else
1115 direntry->d_op = &cifs_dentry_ops; 1149 direntry->d_op = &cifs_dentry_ops;
1116 1150
1117 newinode = new_inode(inode->i_sb); 1151 newinode = cifs_new_inode(inode->i_sb,
1152 &pInfo->UniqueId);
1118 if (newinode == NULL) { 1153 if (newinode == NULL) {
1119 kfree(pInfo); 1154 kfree(pInfo);
1120 goto mkdir_get_info; 1155 goto mkdir_get_info;
1121 } 1156 }
1122 1157
1123 /* Is an i_ino of zero legal? */
1124 /* Are there sanity checks we can use to ensure that
1125 the server is really filling in that field? */
1126 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
1127 newinode->i_ino =
1128 (unsigned long)pInfo->UniqueId;
1129 } /* note ino incremented to unique num in new_inode */
1130 if (inode->i_sb->s_flags & MS_NOATIME)
1131 newinode->i_flags |= S_NOATIME | S_NOCMTIME;
1132 newinode->i_nlink = 2; 1158 newinode->i_nlink = 2;
1133
1134 insert_inode_hash(newinode);
1135 d_instantiate(direntry, newinode); 1159 d_instantiate(direntry, newinode);
1136 1160
1137 /* we already checked in POSIXCreate whether 1161 /* we already checked in POSIXCreate whether
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 9f51f9bf0292..c2c01ff4c32c 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -56,35 +56,34 @@ static inline void dump_cifs_file_struct(struct file *file, char *label)
56} 56}
57#endif /* DEBUG2 */ 57#endif /* DEBUG2 */
58 58
59/* Returns one if new inode created (which therefore needs to be hashed) */ 59/* Returns 1 if new inode created, 2 if both dentry and inode were */
60/* Might check in the future if inode number changed so we can rehash inode */ 60/* Might check in the future if inode number changed so we can rehash inode */
61static int construct_dentry(struct qstr *qstring, struct file *file, 61static int
62 struct inode **ptmp_inode, struct dentry **pnew_dentry) 62construct_dentry(struct qstr *qstring, struct file *file,
63 struct inode **ptmp_inode, struct dentry **pnew_dentry,
64 __u64 *inum)
63{ 65{
64 struct dentry *tmp_dentry; 66 struct dentry *tmp_dentry = NULL;
65 struct cifs_sb_info *cifs_sb; 67 struct super_block *sb = file->f_path.dentry->d_sb;
66 struct cifsTconInfo *pTcon;
67 int rc = 0; 68 int rc = 0;
68 69
69 cFYI(1, ("For %s", qstring->name)); 70 cFYI(1, ("For %s", qstring->name));
70 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
71 pTcon = cifs_sb->tcon;
72 71
73 qstring->hash = full_name_hash(qstring->name, qstring->len); 72 qstring->hash = full_name_hash(qstring->name, qstring->len);
74 tmp_dentry = d_lookup(file->f_path.dentry, qstring); 73 tmp_dentry = d_lookup(file->f_path.dentry, qstring);
75 if (tmp_dentry) { 74 if (tmp_dentry) {
75 /* BB: overwrite old name? i.e. tmp_dentry->d_name and
76 * tmp_dentry->d_name.len??
77 */
76 cFYI(0, ("existing dentry with inode 0x%p", 78 cFYI(0, ("existing dentry with inode 0x%p",
77 tmp_dentry->d_inode)); 79 tmp_dentry->d_inode));
78 *ptmp_inode = tmp_dentry->d_inode; 80 *ptmp_inode = tmp_dentry->d_inode;
79/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
80 if (*ptmp_inode == NULL) { 81 if (*ptmp_inode == NULL) {
81 *ptmp_inode = new_inode(file->f_path.dentry->d_sb); 82 *ptmp_inode = cifs_new_inode(sb, inum);
82 if (*ptmp_inode == NULL) 83 if (*ptmp_inode == NULL)
83 return rc; 84 return rc;
84 rc = 1; 85 rc = 1;
85 } 86 }
86 if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
87 (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;
88 } else { 87 } else {
89 tmp_dentry = d_alloc(file->f_path.dentry, qstring); 88 tmp_dentry = d_alloc(file->f_path.dentry, qstring);
90 if (tmp_dentry == NULL) { 89 if (tmp_dentry == NULL) {
@@ -93,15 +92,14 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
93 return rc; 92 return rc;
94 } 93 }
95 94
96 *ptmp_inode = new_inode(file->f_path.dentry->d_sb); 95 if (CIFS_SB(sb)->tcon->nocase)
97 if (pTcon->nocase)
98 tmp_dentry->d_op = &cifs_ci_dentry_ops; 96 tmp_dentry->d_op = &cifs_ci_dentry_ops;
99 else 97 else
100 tmp_dentry->d_op = &cifs_dentry_ops; 98 tmp_dentry->d_op = &cifs_dentry_ops;
99
100 *ptmp_inode = cifs_new_inode(sb, inum);
101 if (*ptmp_inode == NULL) 101 if (*ptmp_inode == NULL)
102 return rc; 102 return rc;
103 if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
104 (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;
105 rc = 2; 103 rc = 2;
106 } 104 }
107 105
@@ -822,7 +820,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
822/* inode num, inode type and filename returned */ 820/* inode num, inode type and filename returned */
823static int cifs_get_name_from_search_buf(struct qstr *pqst, 821static int cifs_get_name_from_search_buf(struct qstr *pqst,
824 char *current_entry, __u16 level, unsigned int unicode, 822 char *current_entry, __u16 level, unsigned int unicode,
825 struct cifs_sb_info *cifs_sb, int max_len, ino_t *pinum) 823 struct cifs_sb_info *cifs_sb, int max_len, __u64 *pinum)
826{ 824{
827 int rc = 0; 825 int rc = 0;
828 unsigned int len = 0; 826 unsigned int len = 0;
@@ -842,9 +840,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
842 len = strnlen(filename, PATH_MAX); 840 len = strnlen(filename, PATH_MAX);
843 } 841 }
844 842
845 /* BB fixme - hash low and high 32 bits if not 64 bit arch BB */ 843 *pinum = pFindData->UniqueId;
846 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
847 *pinum = pFindData->UniqueId;
848 } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { 844 } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
849 FILE_DIRECTORY_INFO *pFindData = 845 FILE_DIRECTORY_INFO *pFindData =
850 (FILE_DIRECTORY_INFO *)current_entry; 846 (FILE_DIRECTORY_INFO *)current_entry;
@@ -907,7 +903,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
907 struct qstr qstring; 903 struct qstr qstring;
908 struct cifsFileInfo *pCifsF; 904 struct cifsFileInfo *pCifsF;
909 unsigned int obj_type; 905 unsigned int obj_type;
910 ino_t inum; 906 __u64 inum;
911 struct cifs_sb_info *cifs_sb; 907 struct cifs_sb_info *cifs_sb;
912 struct inode *tmp_inode; 908 struct inode *tmp_inode;
913 struct dentry *tmp_dentry; 909 struct dentry *tmp_dentry;
@@ -940,20 +936,18 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
940 if (rc) 936 if (rc)
941 return rc; 937 return rc;
942 938
943 rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry); 939 /* only these two infolevels return valid inode numbers */
940 if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX ||
941 pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO)
942 rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry,
943 &inum);
944 else
945 rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry,
946 NULL);
947
944 if ((tmp_inode == NULL) || (tmp_dentry == NULL)) 948 if ((tmp_inode == NULL) || (tmp_dentry == NULL))
945 return -ENOMEM; 949 return -ENOMEM;
946 950
947 if (rc) {
948 /* inode created, we need to hash it with right inode number */
949 if (inum != 0) {
950 /* BB fixme - hash the 2 32 quantities bits together if
951 * necessary BB */
952 tmp_inode->i_ino = inum;
953 }
954 insert_inode_hash(tmp_inode);
955 }
956
957 /* we pass in rc below, indicating whether it is a new inode, 951 /* we pass in rc below, indicating whether it is a new inode,
958 so we can figure out whether to invalidate the inode cached 952 so we can figure out whether to invalidate the inode cached
959 data if the file has changed */ 953 data if the file has changed */
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 5f22de7b79a9..5c68b4282be9 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -34,15 +34,99 @@
34extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, 34extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
35 unsigned char *p24); 35 unsigned char *p24);
36 36
37/* Checks if this is the first smb session to be reconnected after
38 the socket has been reestablished (so we know whether to use vc 0).
39 Called while holding the cifs_tcp_ses_lock, so do not block */
40static bool is_first_ses_reconnect(struct cifsSesInfo *ses)
41{
42 struct list_head *tmp;
43 struct cifsSesInfo *tmp_ses;
44
45 list_for_each(tmp, &ses->server->smb_ses_list) {
46 tmp_ses = list_entry(tmp, struct cifsSesInfo,
47 smb_ses_list);
48 if (tmp_ses->need_reconnect == false)
49 return false;
50 }
51 /* could not find a session that was already connected,
52 this must be the first one we are reconnecting */
53 return true;
54}
55
56/*
57 * vc number 0 is treated specially by some servers, and should be the
58 * first one we request. After that we can use vcnumbers up to maxvcs,
59 * one for each smb session (some Windows versions set maxvcs incorrectly
60 * so maxvc=1 can be ignored). If we have too many vcs, we can reuse
61 * any vc but zero (some servers reset the connection on vcnum zero)
62 *
63 */
64static __le16 get_next_vcnum(struct cifsSesInfo *ses)
65{
66 __u16 vcnum = 0;
67 struct list_head *tmp;
68 struct cifsSesInfo *tmp_ses;
69 __u16 max_vcs = ses->server->max_vcs;
70 __u16 i;
71 int free_vc_found = 0;
72
73 /* Quoting the MS-SMB specification: "Windows-based SMB servers set this
74 field to one but do not enforce this limit, which allows an SMB client
75 to establish more virtual circuits than allowed by this value ... but
76 other server implementations can enforce this limit." */
77 if (max_vcs < 2)
78 max_vcs = 0xFFFF;
79
80 write_lock(&cifs_tcp_ses_lock);
81 if ((ses->need_reconnect) && is_first_ses_reconnect(ses))
82 goto get_vc_num_exit; /* vcnum will be zero */
83 for (i = ses->server->srv_count - 1; i < max_vcs; i++) {
84 if (i == 0) /* this is the only connection, use vc 0 */
85 break;
86
87 free_vc_found = 1;
88
89 list_for_each(tmp, &ses->server->smb_ses_list) {
90 tmp_ses = list_entry(tmp, struct cifsSesInfo,
91 smb_ses_list);
92 if (tmp_ses->vcnum == i) {
93 free_vc_found = 0;
94 break; /* found duplicate, try next vcnum */
95 }
96 }
97 if (free_vc_found)
98 break; /* we found a vcnumber that will work - use it */
99 }
100
101 if (i == 0)
102 vcnum = 0; /* for most common case, ie if one smb session, use
103 vc zero. Also for case when no free vcnum, zero
104 is safest to send (some clients only send zero) */
105 else if (free_vc_found == 0)
106 vcnum = 1; /* we can not reuse vc=0 safely, since some servers
107 reset all uids on that, but 1 is ok. */
108 else
109 vcnum = i;
110 ses->vcnum = vcnum;
111get_vc_num_exit:
112 write_unlock(&cifs_tcp_ses_lock);
113
114 return le16_to_cpu(vcnum);
115}
116
37static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) 117static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
38{ 118{
39 __u32 capabilities = 0; 119 __u32 capabilities = 0;
40 120
41 /* init fields common to all four types of SessSetup */ 121 /* init fields common to all four types of SessSetup */
42 /* note that header is initialized to zero in header_assemble */ 122 /* Note that offsets for first seven fields in req struct are same */
123 /* in CIFS Specs so does not matter which of 3 forms of struct */
124 /* that we use in next few lines */
125 /* Note that header is initialized to zero in header_assemble */
43 pSMB->req.AndXCommand = 0xFF; 126 pSMB->req.AndXCommand = 0xFF;
44 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); 127 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
45 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); 128 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
129 pSMB->req.VcNumber = get_next_vcnum(ses);
46 130
47 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ 131 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
48 132
@@ -71,7 +155,6 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
71 if (ses->capabilities & CAP_UNIX) 155 if (ses->capabilities & CAP_UNIX)
72 capabilities |= CAP_UNIX; 156 capabilities |= CAP_UNIX;
73 157
74 /* BB check whether to init vcnum BB */
75 return capabilities; 158 return capabilities;
76} 159}
77 160
@@ -228,7 +311,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
228 311
229 kfree(ses->serverOS); 312 kfree(ses->serverOS);
230 /* UTF-8 string will not grow more than four times as big as UCS-16 */ 313 /* UTF-8 string will not grow more than four times as big as UCS-16 */
231 ses->serverOS = kzalloc(4 * len, GFP_KERNEL); 314 ses->serverOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL);
232 if (ses->serverOS != NULL) 315 if (ses->serverOS != NULL)
233 cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp); 316 cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp);
234 data += 2 * (len + 1); 317 data += 2 * (len + 1);
@@ -241,7 +324,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
241 return rc; 324 return rc;
242 325
243 kfree(ses->serverNOS); 326 kfree(ses->serverNOS);
244 ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */ 327 ses->serverNOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL);
245 if (ses->serverNOS != NULL) { 328 if (ses->serverNOS != NULL) {
246 cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, 329 cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
247 nls_cp); 330 nls_cp);