• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/fs/cifs/
1/*
2 *   fs/cifs/dir.c
3 *
4 *   vfs operations that deal with dentries
5 *
6 *   Copyright (C) International Business Machines  Corp., 2002,2009
7 *   Author(s): Steve French (sfrench@us.ibm.com)
8 *
9 *   This library is free software; you can redistribute it and/or modify
10 *   it under the terms of the GNU Lesser General Public License as published
11 *   by the Free Software Foundation; either version 2.1 of the License, or
12 *   (at your option) any later version.
13 *
14 *   This library is distributed in the hope that it will be useful,
15 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17 *   the GNU Lesser General Public License for more details.
18 *
19 *   You should have received a copy of the GNU Lesser General Public License
20 *   along with this library; if not, write to the Free Software
21 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#include <linux/fs.h>
24#include <linux/stat.h>
25#include <linux/slab.h>
26#include <linux/namei.h>
27#include <linux/mount.h>
28#include <linux/file.h>
29#include "cifsfs.h"
30#include "cifspdu.h"
31#include "cifsglob.h"
32#include "cifsproto.h"
33#include "cifs_debug.h"
34#include "cifs_fs_sb.h"
35
36static void
37renew_parental_timestamps(struct dentry *direntry)
38{
39	/* BB check if there is a way to get the kernel to do this or if we
40	   really need this */
41	do {
42		direntry->d_time = jiffies;
43		direntry = direntry->d_parent;
44	} while (!IS_ROOT(direntry));
45}
46
47/* Note: caller must free return buffer */
48char *
49build_path_from_dentry(struct dentry *direntry)
50{
51	struct dentry *temp;
52	int namelen;
53	int pplen;
54	int dfsplen;
55	char *full_path;
56	char dirsep;
57	struct cifs_sb_info *cifs_sb;
58
59	if (direntry == NULL)
60		return NULL;  /* not much we can do if dentry is freed and
61		we need to reopen the file after it was closed implicitly
62		when the server crashed */
63
64	cifs_sb = CIFS_SB(direntry->d_sb);
65	dirsep = CIFS_DIR_SEP(cifs_sb);
66	pplen = cifs_sb->prepathlen;
67	if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
68		dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
69	else
70		dfsplen = 0;
71cifs_bp_rename_retry:
72	namelen = pplen + dfsplen;
73	for (temp = direntry; !IS_ROOT(temp);) {
74		namelen += (1 + temp->d_name.len);
75		temp = temp->d_parent;
76		if (temp == NULL) {
77			cERROR(1, "corrupt dentry");
78			return NULL;
79		}
80	}
81
82	full_path = kmalloc(namelen+1, GFP_KERNEL);
83	if (full_path == NULL)
84		return full_path;
85	full_path[namelen] = 0;	/* trailing null */
86	for (temp = direntry; !IS_ROOT(temp);) {
87		namelen -= 1 + temp->d_name.len;
88		if (namelen < 0) {
89			break;
90		} else {
91			full_path[namelen] = dirsep;
92			strncpy(full_path + namelen + 1, temp->d_name.name,
93				temp->d_name.len);
94			cFYI(0, "name: %s", full_path + namelen);
95		}
96		temp = temp->d_parent;
97		if (temp == NULL) {
98			cERROR(1, "corrupt dentry");
99			kfree(full_path);
100			return NULL;
101		}
102	}
103	if (namelen != pplen + dfsplen) {
104		cERROR(1, "did not end path lookup where expected namelen is %d",
105			namelen);
106		/* presumably this is only possible if racing with a rename
107		of one of the parent directories  (we can not lock the dentries
108		above us to prevent this, but retrying should be harmless) */
109		kfree(full_path);
110		goto cifs_bp_rename_retry;
111	}
112	/* DIR_SEP already set for byte  0 / vs \ but not for
113	   subsequent slashes in prepath which currently must
114	   be entered the right way - not sure if there is an alternative
115	   since the '\' is a valid posix character so we can not switch
116	   those safely to '/' if any are found in the middle of the prepath */
117	/* BB test paths to Windows with '/' in the midst of prepath */
118
119	if (dfsplen) {
120		strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
121		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
122			int i;
123			for (i = 0; i < dfsplen; i++) {
124				if (full_path[i] == '\\')
125					full_path[i] = '/';
126			}
127		}
128	}
129	strncpy(full_path + dfsplen, CIFS_SB(direntry->d_sb)->prepath, pplen);
130	return full_path;
131}
132
133struct cifsFileInfo *
134cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
135		  struct file *file, struct vfsmount *mnt, unsigned int oflags,
136		  __u32 oplock)
137{
138	struct cifsFileInfo *pCifsFile;
139	struct cifsInodeInfo *pCifsInode;
140	struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
141
142	pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
143	if (pCifsFile == NULL)
144		return pCifsFile;
145
146	pCifsFile->netfid = fileHandle;
147	pCifsFile->pid = current->tgid;
148	pCifsFile->pInode = igrab(newinode);
149	pCifsFile->mnt = mnt;
150	pCifsFile->pfile = file;
151	pCifsFile->invalidHandle = false;
152	pCifsFile->closePend = false;
153	mutex_init(&pCifsFile->fh_mutex);
154	mutex_init(&pCifsFile->lock_mutex);
155	INIT_LIST_HEAD(&pCifsFile->llist);
156	atomic_set(&pCifsFile->count, 1);
157	INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break);
158
159	write_lock(&GlobalSMBSeslock);
160	list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
161	pCifsInode = CIFS_I(newinode);
162	if (pCifsInode) {
163		/* if readable file instance put first in list*/
164		if (oflags & FMODE_READ)
165			list_add(&pCifsFile->flist, &pCifsInode->openFileList);
166		else
167			list_add_tail(&pCifsFile->flist,
168				      &pCifsInode->openFileList);
169
170		if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
171			pCifsInode->clientCanCacheAll = true;
172			pCifsInode->clientCanCacheRead = true;
173			cFYI(1, "Exclusive Oplock inode %p", newinode);
174		} else if ((oplock & 0xF) == OPLOCK_READ)
175				pCifsInode->clientCanCacheRead = true;
176	}
177	write_unlock(&GlobalSMBSeslock);
178
179	file->private_data = pCifsFile;
180
181	return pCifsFile;
182}
183
184int cifs_posix_open(char *full_path, struct inode **pinode,
185			struct super_block *sb, int mode, int oflags,
186			__u32 *poplock, __u16 *pnetfid, int xid)
187{
188	int rc;
189	FILE_UNIX_BASIC_INFO *presp_data;
190	__u32 posix_flags = 0;
191	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
192	struct cifs_fattr fattr;
193
194	cFYI(1, "posix open %s", full_path);
195
196	presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
197	if (presp_data == NULL)
198		return -ENOMEM;
199
200/* So far cifs posix extensions can only map the following flags.
201   There are other valid fmode oflags such as FMODE_LSEEK, FMODE_PREAD, but
202   so far we do not seem to need them, and we can treat them as local only */
203	if ((oflags & (FMODE_READ | FMODE_WRITE)) ==
204		(FMODE_READ | FMODE_WRITE))
205		posix_flags = SMB_O_RDWR;
206	else if (oflags & FMODE_READ)
207		posix_flags = SMB_O_RDONLY;
208	else if (oflags & FMODE_WRITE)
209		posix_flags = SMB_O_WRONLY;
210	if (oflags & O_CREAT)
211		posix_flags |= SMB_O_CREAT;
212	if (oflags & O_EXCL)
213		posix_flags |= SMB_O_EXCL;
214	if (oflags & O_TRUNC)
215		posix_flags |= SMB_O_TRUNC;
216	/* be safe and imply O_SYNC for O_DSYNC */
217	if (oflags & O_DSYNC)
218		posix_flags |= SMB_O_SYNC;
219	if (oflags & O_DIRECTORY)
220		posix_flags |= SMB_O_DIRECTORY;
221	if (oflags & O_NOFOLLOW)
222		posix_flags |= SMB_O_NOFOLLOW;
223	if (oflags & O_DIRECT)
224		posix_flags |= SMB_O_DIRECT;
225
226	mode &= ~current_umask();
227	rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
228			pnetfid, presp_data, poplock, full_path,
229			cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
230					CIFS_MOUNT_MAP_SPECIAL_CHR);
231	if (rc)
232		goto posix_open_ret;
233
234	if (presp_data->Type == cpu_to_le32(-1))
235		goto posix_open_ret; /* open ok, caller does qpathinfo */
236
237	if (!pinode)
238		goto posix_open_ret; /* caller does not need info */
239
240	cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
241
242	/* get new inode and set it up */
243	if (*pinode == NULL) {
244		cifs_fill_uniqueid(sb, &fattr);
245		*pinode = cifs_iget(sb, &fattr);
246		if (!*pinode) {
247			rc = -ENOMEM;
248			goto posix_open_ret;
249		}
250	} else {
251		cifs_fattr_to_inode(*pinode, &fattr);
252	}
253
254posix_open_ret:
255	kfree(presp_data);
256	return rc;
257}
258
259static void setup_cifs_dentry(struct cifsTconInfo *tcon,
260			      struct dentry *direntry,
261			      struct inode *newinode)
262{
263	if (tcon->nocase)
264		direntry->d_op = &cifs_ci_dentry_ops;
265	else
266		direntry->d_op = &cifs_dentry_ops;
267	d_instantiate(direntry, newinode);
268}
269
270/* Inode operations in similar order to how they appear in Linux file fs.h */
271
272int
273cifs_create(struct inode *inode, struct dentry *direntry, int mode,
274		struct nameidata *nd)
275{
276	int rc = -ENOENT;
277	int xid;
278	int create_options = CREATE_NOT_DIR;
279	__u32 oplock = 0;
280	int oflags;
281	/*
282	 * BB below access is probably too much for mknod to request
283	 *    but we have to do query and setpathinfo so requesting
284	 *    less could fail (unless we want to request getatr and setatr
285	 *    permissions (only).  At least for POSIX we do not have to
286	 *    request so much.
287	 */
288	int desiredAccess = GENERIC_READ | GENERIC_WRITE;
289	__u16 fileHandle;
290	struct cifs_sb_info *cifs_sb;
291	struct cifsTconInfo *tcon;
292	char *full_path = NULL;
293	FILE_ALL_INFO *buf = NULL;
294	struct inode *newinode = NULL;
295	int disposition = FILE_OVERWRITE_IF;
296
297	xid = GetXid();
298
299	cifs_sb = CIFS_SB(inode->i_sb);
300	tcon = cifs_sb->tcon;
301
302	full_path = build_path_from_dentry(direntry);
303	if (full_path == NULL) {
304		rc = -ENOMEM;
305		goto cifs_create_out;
306	}
307
308	if (oplockEnabled)
309		oplock = REQ_OPLOCK;
310
311	if (nd && (nd->flags & LOOKUP_OPEN))
312		oflags = nd->intent.open.flags;
313	else
314		oflags = FMODE_READ | SMB_O_CREAT;
315
316	if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
317	    (CIFS_UNIX_POSIX_PATH_OPS_CAP &
318			le64_to_cpu(tcon->fsUnixInfo.Capability))) {
319		rc = cifs_posix_open(full_path, &newinode,
320			inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
321		/* EIO could indicate that (posix open) operation is not
322		   supported, despite what server claimed in capability
323		   negotation.  EREMOTE indicates DFS junction, which is not
324		   handled in posix open */
325
326		if (rc == 0) {
327			if (newinode == NULL) /* query inode info */
328				goto cifs_create_get_file_info;
329			else /* success, no need to query */
330				goto cifs_create_set_dentry;
331		} else if ((rc != -EIO) && (rc != -EREMOTE) &&
332			 (rc != -EOPNOTSUPP) && (rc != -EINVAL))
333			goto cifs_create_out;
334		/* else fallthrough to retry, using older open call, this is
335		   case where server does not support this SMB level, and
336		   falsely claims capability (also get here for DFS case
337		   which should be rare for path not covered on files) */
338	}
339
340	if (nd && (nd->flags & LOOKUP_OPEN)) {
341		/* if the file is going to stay open, then we
342		   need to set the desired access properly */
343		desiredAccess = 0;
344		if (oflags & FMODE_READ)
345			desiredAccess |= GENERIC_READ; /* is this too little? */
346		if (oflags & FMODE_WRITE)
347			desiredAccess |= GENERIC_WRITE;
348
349		if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
350			disposition = FILE_CREATE;
351		else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
352			disposition = FILE_OVERWRITE_IF;
353		else if ((oflags & O_CREAT) == O_CREAT)
354			disposition = FILE_OPEN_IF;
355		else
356			cFYI(1, "Create flag not set in create function");
357	}
358
359	/* BB add processing to set equivalent of mode - e.g. via CreateX with
360	   ACLs */
361
362	buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
363	if (buf == NULL) {
364		rc = -ENOMEM;
365		goto cifs_create_out;
366	}
367
368	/*
369	 * if we're not using unix extensions, see if we need to set
370	 * ATTR_READONLY on the create call
371	 */
372	if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
373		create_options |= CREATE_OPTION_READONLY;
374
375	if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
376		rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
377			 desiredAccess, create_options,
378			 &fileHandle, &oplock, buf, cifs_sb->local_nls,
379			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
380	else
381		rc = -EIO; /* no NT SMB support fall into legacy open below */
382
383	if (rc == -EIO) {
384		/* old server, retry the open legacy style */
385		rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
386			desiredAccess, create_options,
387			&fileHandle, &oplock, buf, cifs_sb->local_nls,
388			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
389	}
390	if (rc) {
391		cFYI(1, "cifs_create returned 0x%x", rc);
392		goto cifs_create_out;
393	}
394
395	/* If Open reported that we actually created a file
396	   then we now have to set the mode if possible */
397	if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
398		struct cifs_unix_set_info_args args = {
399				.mode	= mode,
400				.ctime	= NO_CHANGE_64,
401				.atime	= NO_CHANGE_64,
402				.mtime	= NO_CHANGE_64,
403				.device	= 0,
404		};
405
406		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
407			args.uid = (__u64) current_fsuid();
408			if (inode->i_mode & S_ISGID)
409				args.gid = (__u64) inode->i_gid;
410			else
411				args.gid = (__u64) current_fsgid();
412		} else {
413			args.uid = NO_CHANGE_64;
414			args.gid = NO_CHANGE_64;
415		}
416		CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
417					cifs_sb->local_nls,
418					cifs_sb->mnt_cifs_flags &
419						CIFS_MOUNT_MAP_SPECIAL_CHR);
420	} else {
421		/* BB implement mode setting via Windows security
422		   descriptors e.g. */
423		/* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
424
425		/* Could set r/o dos attribute if mode & 0222 == 0 */
426	}
427
428cifs_create_get_file_info:
429	/* server might mask mode so we have to query for it */
430	if (tcon->unix_ext)
431		rc = cifs_get_inode_info_unix(&newinode, full_path,
432					      inode->i_sb, xid);
433	else {
434		rc = cifs_get_inode_info(&newinode, full_path, buf,
435					 inode->i_sb, xid, &fileHandle);
436		if (newinode) {
437			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
438				newinode->i_mode = mode;
439			if ((oplock & CIFS_CREATE_ACTION) &&
440			    (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
441				newinode->i_uid = current_fsuid();
442				if (inode->i_mode & S_ISGID)
443					newinode->i_gid = inode->i_gid;
444				else
445					newinode->i_gid = current_fsgid();
446			}
447		}
448	}
449
450cifs_create_set_dentry:
451	if (rc == 0)
452		setup_cifs_dentry(tcon, direntry, newinode);
453	else
454		cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
455
456	if (newinode && nd && (nd->flags & LOOKUP_OPEN)) {
457		struct cifsFileInfo *pfile_info;
458		struct file *filp;
459
460		filp = lookup_instantiate_filp(nd, direntry, generic_file_open);
461		if (IS_ERR(filp)) {
462			rc = PTR_ERR(filp);
463			CIFSSMBClose(xid, tcon, fileHandle);
464			goto cifs_create_out;
465		}
466
467		pfile_info = cifs_new_fileinfo(newinode, fileHandle, filp,
468					       nd->path.mnt, oflags, oplock);
469		if (pfile_info == NULL) {
470			fput(filp);
471			CIFSSMBClose(xid, tcon, fileHandle);
472			rc = -ENOMEM;
473		}
474	} else {
475		CIFSSMBClose(xid, tcon, fileHandle);
476	}
477
478cifs_create_out:
479	kfree(buf);
480	kfree(full_path);
481	FreeXid(xid);
482	return rc;
483}
484
485int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
486		dev_t device_number)
487{
488	int rc = -EPERM;
489	int xid;
490	struct cifs_sb_info *cifs_sb;
491	struct cifsTconInfo *pTcon;
492	char *full_path = NULL;
493	struct inode *newinode = NULL;
494	int oplock = 0;
495	u16 fileHandle;
496	FILE_ALL_INFO *buf = NULL;
497	unsigned int bytes_written;
498	struct win_dev *pdev;
499
500	if (!old_valid_dev(device_number))
501		return -EINVAL;
502
503	xid = GetXid();
504
505	cifs_sb = CIFS_SB(inode->i_sb);
506	pTcon = cifs_sb->tcon;
507
508	full_path = build_path_from_dentry(direntry);
509	if (full_path == NULL) {
510		rc = -ENOMEM;
511		goto mknod_out;
512	}
513
514	if (pTcon->unix_ext) {
515		struct cifs_unix_set_info_args args = {
516			.mode	= mode & ~current_umask(),
517			.ctime	= NO_CHANGE_64,
518			.atime	= NO_CHANGE_64,
519			.mtime	= NO_CHANGE_64,
520			.device	= device_number,
521		};
522		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
523			args.uid = (__u64) current_fsuid();
524			args.gid = (__u64) current_fsgid();
525		} else {
526			args.uid = NO_CHANGE_64;
527			args.gid = NO_CHANGE_64;
528		}
529		rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
530					    cifs_sb->local_nls,
531					    cifs_sb->mnt_cifs_flags &
532						CIFS_MOUNT_MAP_SPECIAL_CHR);
533		if (rc)
534			goto mknod_out;
535
536		rc = cifs_get_inode_info_unix(&newinode, full_path,
537						inode->i_sb, xid);
538		if (pTcon->nocase)
539			direntry->d_op = &cifs_ci_dentry_ops;
540		else
541			direntry->d_op = &cifs_dentry_ops;
542
543		if (rc == 0)
544			d_instantiate(direntry, newinode);
545		goto mknod_out;
546	}
547
548	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
549		goto mknod_out;
550
551
552	cFYI(1, "sfu compat create special file");
553
554	buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
555	if (buf == NULL) {
556		kfree(full_path);
557		rc = -ENOMEM;
558		FreeXid(xid);
559		return rc;
560	}
561
562	rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE,
563			 GENERIC_WRITE, CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
564			 &fileHandle, &oplock, buf, cifs_sb->local_nls,
565			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
566	if (rc)
567		goto mknod_out;
568
569	/* BB Do not bother to decode buf since no local inode yet to put
570	 * timestamps in, but we can reuse it safely */
571
572	pdev = (struct win_dev *)buf;
573	if (S_ISCHR(mode)) {
574		memcpy(pdev->type, "IntxCHR", 8);
575		pdev->major =
576		      cpu_to_le64(MAJOR(device_number));
577		pdev->minor =
578		      cpu_to_le64(MINOR(device_number));
579		rc = CIFSSMBWrite(xid, pTcon,
580			fileHandle,
581			sizeof(struct win_dev),
582			0, &bytes_written, (char *)pdev,
583			NULL, 0);
584	} else if (S_ISBLK(mode)) {
585		memcpy(pdev->type, "IntxBLK", 8);
586		pdev->major =
587		      cpu_to_le64(MAJOR(device_number));
588		pdev->minor =
589		      cpu_to_le64(MINOR(device_number));
590		rc = CIFSSMBWrite(xid, pTcon,
591			fileHandle,
592			sizeof(struct win_dev),
593			0, &bytes_written, (char *)pdev,
594			NULL, 0);
595	} /* else if (S_ISFIFO) */
596	CIFSSMBClose(xid, pTcon, fileHandle);
597	d_drop(direntry);
598
599
600mknod_out:
601	kfree(full_path);
602	kfree(buf);
603	FreeXid(xid);
604	return rc;
605}
606
607struct dentry *
608cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
609	    struct nameidata *nd)
610{
611	int xid;
612	int rc = 0; /* to get around spurious gcc warning, set to zero here */
613	__u32 oplock = 0;
614	__u16 fileHandle = 0;
615	bool posix_open = false;
616	struct cifs_sb_info *cifs_sb;
617	struct cifsTconInfo *pTcon;
618	struct cifsFileInfo *cfile;
619	struct inode *newInode = NULL;
620	char *full_path = NULL;
621	struct file *filp;
622
623	xid = GetXid();
624
625	cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
626	      parent_dir_inode, direntry->d_name.name, direntry);
627
628	/* check whether path exists */
629
630	cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
631	pTcon = cifs_sb->tcon;
632
633	/*
634	 * Don't allow the separator character in a path component.
635	 * The VFS will not allow "/", but "\" is allowed by posix.
636	 */
637	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
638		int i;
639		for (i = 0; i < direntry->d_name.len; i++)
640			if (direntry->d_name.name[i] == '\\') {
641				cFYI(1, "Invalid file name");
642				FreeXid(xid);
643				return ERR_PTR(-EINVAL);
644			}
645	}
646
647	/*
648	 * O_EXCL: optimize away the lookup, but don't hash the dentry. Let
649	 * the VFS handle the create.
650	 */
651	if (nd && (nd->flags & LOOKUP_EXCL)) {
652		d_instantiate(direntry, NULL);
653		return NULL;
654	}
655
656	/* can not grab the rename sem here since it would
657	deadlock in the cases (beginning of sys_rename itself)
658	in which we already have the sb rename sem */
659	full_path = build_path_from_dentry(direntry);
660	if (full_path == NULL) {
661		FreeXid(xid);
662		return ERR_PTR(-ENOMEM);
663	}
664
665	if (direntry->d_inode != NULL) {
666		cFYI(1, "non-NULL inode in lookup");
667	} else {
668		cFYI(1, "NULL inode in lookup");
669	}
670	cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode);
671
672	/* Posix open is only called (at lookup time) for file create now.
673	 * For opens (rather than creates), because we do not know if it
674	 * is a file or directory yet, and current Samba no longer allows
675	 * us to do posix open on dirs, we could end up wasting an open call
676	 * on what turns out to be a dir. For file opens, we wait to call posix
677	 * open till cifs_open.  It could be added here (lookup) in the future
678	 * but the performance tradeoff of the extra network request when EISDIR
679	 * or EACCES is returned would have to be weighed against the 50%
680	 * reduction in network traffic in the other paths.
681	 */
682	if (pTcon->unix_ext) {
683		if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
684		     (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
685		     (nd->intent.open.flags & O_CREAT)) {
686			rc = cifs_posix_open(full_path, &newInode,
687					parent_dir_inode->i_sb,
688					nd->intent.open.create_mode,
689					nd->intent.open.flags, &oplock,
690					&fileHandle, xid);
691			/*
692			 * The check below works around a bug in POSIX
693			 * open in samba versions 3.3.1 and earlier where
694			 * open could incorrectly fail with invalid parameter.
695			 * If either that or op not supported returned, follow
696			 * the normal lookup.
697			 */
698			if ((rc == 0) || (rc == -ENOENT))
699				posix_open = true;
700			else if ((rc == -EINVAL) || (rc != -EOPNOTSUPP))
701				pTcon->broken_posix_open = true;
702		}
703		if (!posix_open)
704			rc = cifs_get_inode_info_unix(&newInode, full_path,
705						parent_dir_inode->i_sb, xid);
706	} else
707		rc = cifs_get_inode_info(&newInode, full_path, NULL,
708				parent_dir_inode->i_sb, xid, NULL);
709
710	if ((rc == 0) && (newInode != NULL)) {
711		if (pTcon->nocase)
712			direntry->d_op = &cifs_ci_dentry_ops;
713		else
714			direntry->d_op = &cifs_dentry_ops;
715		d_add(direntry, newInode);
716		if (posix_open) {
717			filp = lookup_instantiate_filp(nd, direntry,
718						       generic_file_open);
719			if (IS_ERR(filp)) {
720				rc = PTR_ERR(filp);
721				CIFSSMBClose(xid, pTcon, fileHandle);
722				goto lookup_out;
723			}
724
725			cfile = cifs_new_fileinfo(newInode, fileHandle, filp,
726						  nd->path.mnt,
727						  nd->intent.open.flags,
728						  oplock);
729			if (cfile == NULL) {
730				fput(filp);
731				CIFSSMBClose(xid, pTcon, fileHandle);
732				rc = -ENOMEM;
733				goto lookup_out;
734			}
735		}
736		/* since paths are not looked up by component - the parent
737		   directories are presumed to be good here */
738		renew_parental_timestamps(direntry);
739
740	} else if (rc == -ENOENT) {
741		rc = 0;
742		direntry->d_time = jiffies;
743		if (pTcon->nocase)
744			direntry->d_op = &cifs_ci_dentry_ops;
745		else
746			direntry->d_op = &cifs_dentry_ops;
747		d_add(direntry, NULL);
748	/*	if it was once a directory (but how can we tell?) we could do
749		shrink_dcache_parent(direntry); */
750	} else if (rc != -EACCES) {
751		cERROR(1, "Unexpected lookup error %d", rc);
752		/* We special case check for Access Denied - since that
753		is a common return code */
754	}
755
756lookup_out:
757	kfree(full_path);
758	FreeXid(xid);
759	return ERR_PTR(rc);
760}
761
762static int
763cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
764{
765	int isValid = 1;
766
767	if (direntry->d_inode) {
768		if (cifs_revalidate_dentry(direntry))
769			return 0;
770	} else {
771		cFYI(1, "neg dentry 0x%p name = %s",
772			 direntry, direntry->d_name.name);
773		if (time_after(jiffies, direntry->d_time + HZ) ||
774			!lookupCacheEnabled) {
775			d_drop(direntry);
776			isValid = 0;
777		}
778	}
779
780	return isValid;
781}
782
783/* static int cifs_d_delete(struct dentry *direntry)
784{
785	int rc = 0;
786
787	cFYI(1, "In cifs d_delete, name = %s", direntry->d_name.name);
788
789	return rc;
790}     */
791
792const struct dentry_operations cifs_dentry_ops = {
793	.d_revalidate = cifs_d_revalidate,
794/* d_delete:       cifs_d_delete,      */ /* not needed except for debugging */
795};
796
797static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
798{
799	struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
800	unsigned long hash;
801	int i;
802
803	hash = init_name_hash();
804	for (i = 0; i < q->len; i++)
805		hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
806					 hash);
807	q->hash = end_name_hash(hash);
808
809	return 0;
810}
811
812static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
813			   struct qstr *b)
814{
815	struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
816
817	if ((a->len == b->len) &&
818	    (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) {
819		/*
820		 * To preserve case, don't let an existing negative dentry's
821		 * case take precedence.  If a is not a negative dentry, this
822		 * should have no side effects
823		 */
824		memcpy((void *)a->name, b->name, a->len);
825		return 0;
826	}
827	return 1;
828}
829
830const struct dentry_operations cifs_ci_dentry_ops = {
831	.d_revalidate = cifs_d_revalidate,
832	.d_hash = cifs_ci_hash,
833	.d_compare = cifs_ci_compare,
834};
835