dir.c 22.4 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4
/*
 *   fs/cifs/dir.c
 *
 *   vfs operations that deal with dentries
Steve French's avatar
Steve French committed
5
 *
6
 *   Copyright (C) International Business Machines  Corp., 2002,2009
Linus Torvalds's avatar
Linus Torvalds committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *   Author(s): Steve French (sfrench@us.ibm.com)
 *
 *   This library is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 *   the GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with this library; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/slab.h>
#include <linux/namei.h>
27
#include <linux/mount.h>
28
#include <linux/file.h>
Linus Torvalds's avatar
Linus Torvalds committed
29 30 31 32 33 34
#include "cifsfs.h"
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "cifs_debug.h"
#include "cifs_fs_sb.h"
35
#include "cifs_unicode.h"
Linus Torvalds's avatar
Linus Torvalds committed
36

37
static void
Linus Torvalds's avatar
Linus Torvalds committed
38 39
renew_parental_timestamps(struct dentry *direntry)
{
Steve French's avatar
Steve French committed
40 41
	/* BB check if there is a way to get the kernel to do this or if we
	   really need this */
Linus Torvalds's avatar
Linus Torvalds committed
42
	do {
Miklos Szeredi's avatar
Miklos Szeredi committed
43
		cifs_set_time(direntry, jiffies);
Linus Torvalds's avatar
Linus Torvalds committed
44
		direntry = direntry->d_parent;
Steve French's avatar
Steve French committed
45
	} while (!IS_ROOT(direntry));
Linus Torvalds's avatar
Linus Torvalds committed
46 47
}

48 49
char *
cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
50
			struct cifs_tcon *tcon, int add_treename)
51
{
52
	int pplen = vol->prepath ? strlen(vol->prepath) + 1 : 0;
53 54 55 56 57 58 59 60 61
	int dfsplen;
	char *full_path = NULL;

	/* if no prefix path, simply set path to the root of share to "" */
	if (pplen == 0) {
		full_path = kzalloc(1, GFP_KERNEL);
		return full_path;
	}

62
	if (add_treename)
63 64 65 66 67 68 69 70 71
		dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
	else
		dfsplen = 0;

	full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL);
	if (full_path == NULL)
		return full_path;

	if (dfsplen)
72
		memcpy(full_path, tcon->treeName, dfsplen);
73
	full_path[dfsplen] = CIFS_DIR_SEP(cifs_sb);
74
	memcpy(full_path + dfsplen + 1, vol->prepath, pplen);
75 76 77 78
	convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
	return full_path;
}

Linus Torvalds's avatar
Linus Torvalds committed
79 80 81
/* Note: caller must free return buffer */
char *
build_path_from_dentry(struct dentry *direntry)
82 83 84 85 86 87 88 89 90 91 92
{
	struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
	bool prefix = tcon->Flags & SMB_SHARE_IS_IN_DFS;

	return build_path_from_dentry_optional_prefix(direntry,
						      prefix);
}

char *
build_path_from_dentry_optional_prefix(struct dentry *direntry, bool prefix)
Linus Torvalds's avatar
Linus Torvalds committed
93 94
{
	struct dentry *temp;
95
	int namelen;
96
	int dfsplen;
97
	int pplen = 0;
Linus Torvalds's avatar
Linus Torvalds committed
98
	char *full_path;
99
	char dirsep;
100
	struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
101
	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
102
	unsigned seq;
Linus Torvalds's avatar
Linus Torvalds committed
103

104
	dirsep = CIFS_DIR_SEP(cifs_sb);
105
	if (prefix)
106
		dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
107 108
	else
		dfsplen = 0;
109 110 111 112

	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
		pplen = cifs_sb->prepath ? strlen(cifs_sb->prepath) + 1 : 0;

Linus Torvalds's avatar
Linus Torvalds committed
113
cifs_bp_rename_retry:
114
	namelen = dfsplen + pplen;
115 116
	seq = read_seqbegin(&rename_lock);
	rcu_read_lock();
Linus Torvalds's avatar
Linus Torvalds committed
117 118 119
	for (temp = direntry; !IS_ROOT(temp);) {
		namelen += (1 + temp->d_name.len);
		temp = temp->d_parent;
Steve French's avatar
Steve French committed
120
		if (temp == NULL) {
121
			cifs_dbg(VFS, "corrupt dentry\n");
122
			rcu_read_unlock();
Linus Torvalds's avatar
Linus Torvalds committed
123 124 125
			return NULL;
		}
	}
126
	rcu_read_unlock();
Linus Torvalds's avatar
Linus Torvalds committed
127 128

	full_path = kmalloc(namelen+1, GFP_KERNEL);
Steve French's avatar
Steve French committed
129
	if (full_path == NULL)
Linus Torvalds's avatar
Linus Torvalds committed
130 131
		return full_path;
	full_path[namelen] = 0;	/* trailing null */
132
	rcu_read_lock();
Linus Torvalds's avatar
Linus Torvalds committed
133
	for (temp = direntry; !IS_ROOT(temp);) {
134
		spin_lock(&temp->d_lock);
Linus Torvalds's avatar
Linus Torvalds committed
135 136
		namelen -= 1 + temp->d_name.len;
		if (namelen < 0) {
137
			spin_unlock(&temp->d_lock);
Linus Torvalds's avatar
Linus Torvalds committed
138 139
			break;
		} else {
140
			full_path[namelen] = dirsep;
Linus Torvalds's avatar
Linus Torvalds committed
141 142
			strncpy(full_path + namelen + 1, temp->d_name.name,
				temp->d_name.len);
143
			cifs_dbg(FYI, "name: %s\n", full_path + namelen);
Linus Torvalds's avatar
Linus Torvalds committed
144
		}
145
		spin_unlock(&temp->d_lock);
Linus Torvalds's avatar
Linus Torvalds committed
146
		temp = temp->d_parent;
Steve French's avatar
Steve French committed
147
		if (temp == NULL) {
148
			cifs_dbg(VFS, "corrupt dentry\n");
149
			rcu_read_unlock();
Linus Torvalds's avatar
Linus Torvalds committed
150 151 152 153
			kfree(full_path);
			return NULL;
		}
	}
154
	rcu_read_unlock();
155
	if (namelen != dfsplen + pplen || read_seqretry(&rename_lock, seq)) {
156 157
		cifs_dbg(FYI, "did not end path lookup where expected. namelen=%ddfsplen=%d\n",
			 namelen, dfsplen);
Steve French's avatar
Steve French committed
158
		/* presumably this is only possible if racing with a rename
Linus Torvalds's avatar
Linus Torvalds committed
159 160 161 162 163
		of one of the parent directories  (we can not lock the dentries
		above us to prevent this, but retrying should be harmless) */
		kfree(full_path);
		goto cifs_bp_rename_retry;
	}
164 165 166 167 168 169
	/* DIR_SEP already set for byte  0 / vs \ but not for
	   subsequent slashes in prepath which currently must
	   be entered the right way - not sure if there is an alternative
	   since the '\' is a valid posix character so we can not switch
	   those safely to '/' if any are found in the middle of the prepath */
	/* BB test paths to Windows with '/' in the midst of prepath */
170

171 172 173 174 175
	if (pplen) {
		int i;

		cifs_dbg(FYI, "using cifs_sb prepath <%s>\n", cifs_sb->prepath);
		memcpy(full_path+dfsplen+1, cifs_sb->prepath, pplen-1);
176
		full_path[dfsplen] = dirsep;
177 178 179 180 181
		for (i = 0; i < pplen-1; i++)
			if (full_path[dfsplen+1+i] == '/')
				full_path[dfsplen+1+i] = CIFS_DIR_SEP(cifs_sb);
	}

182
	if (dfsplen) {
183
		strncpy(full_path, tcon->treeName, dfsplen);
184 185 186 187 188 189 190 191
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
			int i;
			for (i = 0; i < dfsplen; i++) {
				if (full_path[i] == '\\')
					full_path[i] = '/';
			}
		}
	}
Linus Torvalds's avatar
Linus Torvalds committed
192 193 194
	return full_path;
}

195
/*
196
 * Don't allow path components longer than the server max.
197 198 199 200
 * Don't allow the separator character in a path component.
 * The VFS will not allow "/", but "\" is allowed by posix.
 */
static int
201
check_name(struct dentry *direntry, struct cifs_tcon *tcon)
202 203 204 205
{
	struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
	int i;

206 207
	if (unlikely(tcon->fsAttrInfo.MaxPathNameComponentLength &&
		     direntry->d_name.len >
208
		     le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength)))
209 210
		return -ENAMETOOLONG;

211 212 213
	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
		for (i = 0; i < direntry->d_name.len; i++) {
			if (direntry->d_name.name[i] == '\\') {
214
				cifs_dbg(FYI, "Invalid file name\n");
215 216 217 218 219 220 221 222
				return -EINVAL;
			}
		}
	}
	return 0;
}


223
/* Inode operations in similar order to how they appear in Linux file fs.h */
Linus Torvalds's avatar
Linus Torvalds committed
224

225 226 227
static int
cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
	       struct tcon_link *tlink, unsigned oflags, umode_t mode,
Shirish Pargaonkar's avatar
Shirish Pargaonkar committed
228
	       __u32 *oplock, struct cifs_fid *fid)
Linus Torvalds's avatar
Linus Torvalds committed
229 230
{
	int rc = -ENOENT;
231
	int create_options = CREATE_NOT_DIR;
232
	int desired_access;
233 234
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
	struct cifs_tcon *tcon = tlink_tcon(tlink);
Linus Torvalds's avatar
Linus Torvalds committed
235
	char *full_path = NULL;
Steve French's avatar
Steve French committed
236
	FILE_ALL_INFO *buf = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
237
	struct inode *newinode = NULL;
238
	int disposition;
239
	struct TCP_Server_Info *server = tcon->ses->server;
240
	struct cifs_open_parms oparms;
Linus Torvalds's avatar
Linus Torvalds committed
241

242
	*oplock = 0;
243
	if (tcon->ses->server->oplocks)
244
		*oplock = REQ_OPLOCK;
245

246 247 248
	full_path = build_path_from_dentry(direntry);
	if (full_path == NULL) {
		rc = -ENOMEM;
249
		goto out;
250 251
	}

252
	if (tcon->unix_ext && cap_unix(tcon->ses) && !tcon->broken_posix_open &&
253 254
	    (CIFS_UNIX_POSIX_PATH_OPS_CAP &
			le64_to_cpu(tcon->fsUnixInfo.Capability))) {
255 256
		rc = cifs_posix_open(full_path, &newinode, inode->i_sb, mode,
				     oflags, oplock, &fid->netfid, xid);
257 258 259 260
		switch (rc) {
		case 0:
			if (newinode == NULL) {
				/* query inode info */
261
				goto cifs_create_get_file_info;
262 263
			}

264 265 266 267 268 269 270
			if (S_ISDIR(newinode->i_mode)) {
				CIFSSMBClose(xid, tcon, fid->netfid);
				iput(newinode);
				rc = -EISDIR;
				goto out;
			}

271 272 273 274 275 276 277 278
			if (!S_ISREG(newinode->i_mode)) {
				/*
				 * The server may allow us to open things like
				 * FIFOs, but the client isn't set up to deal
				 * with that. If it's not a regular file, just
				 * close it and proceed as if it were a normal
				 * lookup.
				 */
279
				CIFSSMBClose(xid, tcon, fid->netfid);
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
				goto cifs_create_get_file_info;
			}
			/* success, no need to query */
			goto cifs_create_set_dentry;

		case -ENOENT:
			goto cifs_create_get_file_info;

		case -EIO:
		case -EINVAL:
			/*
			 * EIO could indicate that (posix open) operation is not
			 * supported, despite what server claimed in capability
			 * negotiation.
			 *
			 * POSIX open in samba versions 3.3.1 and earlier could
			 * incorrectly fail with invalid parameter.
			 */
			tcon->broken_posix_open = true;
			break;

		case -EREMOTE:
		case -EOPNOTSUPP:
			/*
			 * EREMOTE indicates DFS junction, which is not handled
			 * in posix open.  If either that or op not supported
			 * returned, follow the normal lookup.
			 */
			break;
Miklos Szeredi's avatar
Miklos Szeredi committed
309

310 311 312 313 314 315 316 317 318
		default:
			goto out;
		}
		/*
		 * fallthrough to retry, using older open call, this is case
		 * where server does not support this SMB level, and falsely
		 * claims capability (also get here for DFS case which should be
		 * rare for path not covered on files)
		 */
Linus Torvalds's avatar
Linus Torvalds committed
319 320
	}

321
	desired_access = 0;
322
	if (OPEN_FMODE(oflags) & FMODE_READ)
323
		desired_access |= GENERIC_READ; /* is this too little? */
324
	if (OPEN_FMODE(oflags) & FMODE_WRITE)
325
		desired_access |= GENERIC_WRITE;
326 327 328 329 330 331 332 333 334

	disposition = FILE_OVERWRITE_IF;
	if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
		disposition = FILE_CREATE;
	else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
		disposition = FILE_OVERWRITE_IF;
	else if ((oflags & O_CREAT) == O_CREAT)
		disposition = FILE_OPEN_IF;
	else
335
		cifs_dbg(FYI, "Create flag not set in create function\n");
336

337 338 339 340 341 342 343 344 345
	/*
	 * BB add processing to set equivalent of mode - e.g. via CreateX with
	 * ACLs
	 */

	if (!server->ops->open) {
		rc = -ENOSYS;
		goto out;
	}
Linus Torvalds's avatar
Linus Torvalds committed
346

Steve French's avatar
Steve French committed
347 348
	buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
	if (buf == NULL) {
349
		rc = -ENOMEM;
350
		goto out;
Linus Torvalds's avatar
Linus Torvalds committed
351
	}
352 353 354 355 356

	/*
	 * if we're not using unix extensions, see if we need to set
	 * ATTR_READONLY on the create call
	 */
357
	if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
358 359
		create_options |= CREATE_OPTION_READONLY;

360 361 362
	if (backup_cred(cifs_sb))
		create_options |= CREATE_OPEN_BACKUP_INTENT;

363 364 365 366 367 368 369
	oparms.tcon = tcon;
	oparms.cifs_sb = cifs_sb;
	oparms.desired_access = desired_access;
	oparms.create_options = create_options;
	oparms.disposition = disposition;
	oparms.path = full_path;
	oparms.fid = fid;
370
	oparms.reconnect = false;
371
	oparms.mode = mode;
372
	rc = server->ops->open(xid, &oparms, oplock, buf);
Linus Torvalds's avatar
Linus Torvalds committed
373
	if (rc) {
374
		cifs_dbg(FYI, "cifs_create returned 0x%x\n", rc);
375
		goto out;
376 377
	}

378 379 380 381
	/*
	 * If Open reported that we actually created a file then we now have to
	 * set the mode if possible.
	 */
382
	if ((tcon->unix_ext) && (*oplock & CIFS_CREATE_ACTION)) {
383
		struct cifs_unix_set_info_args args = {
384 385 386 387 388
				.mode	= mode,
				.ctime	= NO_CHANGE_64,
				.atime	= NO_CHANGE_64,
				.mtime	= NO_CHANGE_64,
				.device	= 0,
389 390 391
		};

		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
392
			args.uid = current_fsuid();
393
			if (inode->i_mode & S_ISGID)
394
				args.gid = inode->i_gid;
395
			else
396
				args.gid = current_fsgid();
Steve French's avatar
Steve French committed
397
		} else {
398 399
			args.uid = INVALID_UID; /* no change */
			args.gid = INVALID_GID; /* no change */
Linus Torvalds's avatar
Linus Torvalds committed
400
		}
401 402
		CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid->netfid,
				       current->tgid);
403
	} else {
404 405 406 407
		/*
		 * BB implement mode setting via Windows security
		 * descriptors e.g.
		 */
408 409 410 411
		/* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/

		/* Could set r/o dos attribute if mode & 0222 == 0 */
	}
Linus Torvalds's avatar
Linus Torvalds committed
412

413 414 415
cifs_create_get_file_info:
	/* server might mask mode so we have to query for it */
	if (tcon->unix_ext)
416 417
		rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb,
					      xid);
418
	else {
419
		rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb,
420
					 xid, fid);
421
		if (newinode) {
Pavel Shilovsky's avatar
Pavel Shilovsky committed
422 423
			if (server->ops->set_lease_key)
				server->ops->set_lease_key(newinode, fid);
424 425
			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
				newinode->i_mode = mode;
426
			if ((*oplock & CIFS_CREATE_ACTION) &&
427 428 429 430 431 432
			    (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
				newinode->i_uid = current_fsuid();
				if (inode->i_mode & S_ISGID)
					newinode->i_gid = inode->i_gid;
				else
					newinode->i_gid = current_fsgid();
433
			}
Linus Torvalds's avatar
Linus Torvalds committed
434
		}
435
	}
Linus Torvalds's avatar
Linus Torvalds committed
436

437
cifs_create_set_dentry:
438
	if (rc != 0) {
439 440
		cifs_dbg(FYI, "Create worked, get_inode_info failed rc = %d\n",
			 rc);
441
		goto out_err;
442
	}
443 444 445 446

	if (S_ISDIR(newinode->i_mode)) {
		rc = -EISDIR;
		goto out_err;
447
	}
448

449 450
	d_drop(direntry);
	d_add(direntry, newinode);
451

452 453 454 455
out:
	kfree(buf);
	kfree(full_path);
	return rc;
456 457 458 459 460 461 462

out_err:
	if (server->ops->close)
		server->ops->close(xid, tcon, fid);
	if (newinode)
		iput(newinode);
	goto out;
463
}
464

Al Viro's avatar
Al Viro committed
465
int
466
cifs_atomic_open(struct inode *inode, struct dentry *direntry,
467
		 struct file *file, unsigned oflags, umode_t mode)
468 469
{
	int rc;
470
	unsigned int xid;
471 472
	struct tcon_link *tlink;
	struct cifs_tcon *tcon;
473
	struct TCP_Server_Info *server;
474
	struct cifs_fid fid;
475
	struct cifs_pending_open open;
476
	__u32 oplock;
477
	struct cifsFileInfo *file_info;
478

479 480
	/*
	 * Posix open is only called (at lookup time) for file create now. For
481 482 483 484 485 486 487 488 489 490
	 * opens (rather than creates), because we do not know if it is a file
	 * or directory yet, and current Samba no longer allows us to do posix
	 * open on dirs, we could end up wasting an open call on what turns out
	 * to be a dir. For file opens, we wait to call posix open till
	 * cifs_open.  It could be added to atomic_open in the future but the
	 * performance tradeoff of the extra network request when EISDIR or
	 * EACCES is returned would have to be weighed against the 50% reduction
	 * in network traffic in the other paths.
	 */
	if (!(oflags & O_CREAT)) {
491 492 493 494 495 496
		struct dentry *res;

		/*
		 * Check for hashed negative dentry. We have already revalidated
		 * the dentry and it is fine. No need to perform another lookup.
		 */
497
		if (!d_in_lookup(direntry))
498 499 500
			return -ENOENT;

		res = cifs_lookup(inode, direntry, 0);
501
		if (IS_ERR(res))
Al Viro's avatar
Al Viro committed
502
			return PTR_ERR(res);
503

Al Viro's avatar
Al Viro committed
504
		return finish_no_open(file, res);
505 506
	}

507
	xid = get_xid();
508

Al Viro's avatar
Al Viro committed
509 510
	cifs_dbg(FYI, "parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
		 inode, direntry, direntry);
511 512

	tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
513 514
	if (IS_ERR(tlink)) {
		rc = PTR_ERR(tlink);
515
		goto out_free_xid;
516
	}
517 518

	tcon = tlink_tcon(tlink);
519 520 521

	rc = check_name(direntry, tcon);
	if (rc)
522
		goto out;
523

524
	server = tcon->ses->server;
525

Pavel Shilovsky's avatar
Pavel Shilovsky committed
526 527 528
	if (server->ops->new_lease_key)
		server->ops->new_lease_key(&fid);

529 530
	cifs_add_pending_open(&fid, tlink, &open);

531
	rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
Shirish Pargaonkar's avatar
Shirish Pargaonkar committed
532
			    &oplock, &fid);
533

534 535
	if (rc) {
		cifs_del_pending_open(&open);
536
		goto out;
537
	}
538

Shirish Pargaonkar's avatar
Shirish Pargaonkar committed
539
	if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
540
		file->f_mode |= FMODE_CREATED;
Shirish Pargaonkar's avatar
Shirish Pargaonkar committed
541

542
	rc = finish_open(file, direntry, generic_file_open);
Al Viro's avatar
Al Viro committed
543
	if (rc) {
544 545
		if (server->ops->close)
			server->ops->close(xid, tcon, &fid);
546
		cifs_del_pending_open(&open);
547
		goto out;
Steve French's avatar
Steve French committed
548
	}
549

550 551 552 553 554 555 556 557
	if (file->f_flags & O_DIRECT &&
	    CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
		if (CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
			file->f_op = &cifs_file_direct_nobrl_ops;
		else
			file->f_op = &cifs_file_direct_ops;
		}

558 559
	file_info = cifs_new_fileinfo(&fid, file, tlink, oplock);
	if (file_info == NULL) {
560 561
		if (server->ops->close)
			server->ops->close(xid, tcon, &fid);
562
		cifs_del_pending_open(&open);
563
		fput(file);
Al Viro's avatar
Al Viro committed
564
		rc = -ENOMEM;
565 566 567 568
	}

out:
	cifs_put_tlink(tlink);
569 570
out_free_xid:
	free_xid(xid);
Al Viro's avatar
Al Viro committed
571
	return rc;
572 573 574
}

int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
Al Viro's avatar
Al Viro committed
575
		bool excl)
576 577
{
	int rc;
578
	unsigned int xid = get_xid();
579 580 581 582 583 584 585 586 587
	/*
	 * BB below access is probably too much for mknod to request
	 *    but we have to do query and setpathinfo so requesting
	 *    less could fail (unless we want to request getatr and setatr
	 *    permissions (only).  At least for POSIX we do not have to
	 *    request so much.
	 */
	unsigned oflags = O_EXCL | O_CREAT | O_RDWR;
	struct tcon_link *tlink;
588 589 590
	struct cifs_tcon *tcon;
	struct TCP_Server_Info *server;
	struct cifs_fid fid;
591 592
	__u32 oplock;

Al Viro's avatar
Al Viro committed
593 594
	cifs_dbg(FYI, "cifs_create parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
		 inode, direntry, direntry);
595 596 597 598

	tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
	rc = PTR_ERR(tlink);
	if (IS_ERR(tlink))
599
		goto out_free_xid;
600

601 602
	tcon = tlink_tcon(tlink);
	server = tcon->ses->server;
Pavel Shilovsky's avatar
Pavel Shilovsky committed
603 604 605 606 607

	if (server->ops->new_lease_key)
		server->ops->new_lease_key(&fid);

	rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
Shirish Pargaonkar's avatar
Shirish Pargaonkar committed
608
			    &oplock, &fid);
609 610
	if (!rc && server->ops->close)
		server->ops->close(xid, tcon, &fid);
611

612
	cifs_put_tlink(tlink);
613 614
out_free_xid:
	free_xid(xid);
Linus Torvalds's avatar
Linus Torvalds committed
615 616 617
	return rc;
}

Al Viro's avatar
Al Viro committed
618
int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
Steve French's avatar
Steve French committed
619
		dev_t device_number)
Linus Torvalds's avatar
Linus Torvalds committed
620 621
{
	int rc = -EPERM;
622
	unsigned int xid;
Linus Torvalds's avatar
Linus Torvalds committed
623
	struct cifs_sb_info *cifs_sb;
624
	struct tcon_link *tlink;
Pavel Shilovsky's avatar
Pavel Shilovsky committed
625
	struct cifs_tcon *tcon;
Linus Torvalds's avatar
Linus Torvalds committed
626 627 628 629 630 631
	char *full_path = NULL;

	if (!old_valid_dev(device_number))
		return -EINVAL;

	cifs_sb = CIFS_SB(inode->i_sb);
632 633 634 635
	tlink = cifs_sb_tlink(cifs_sb);
	if (IS_ERR(tlink))
		return PTR_ERR(tlink);

Pavel Shilovsky's avatar
Pavel Shilovsky committed
636
	tcon = tlink_tcon(tlink);
637

638
	xid = get_xid();
Linus Torvalds's avatar
Linus Torvalds committed
639 640

	full_path = build_path_from_dentry(direntry);
641
	if (full_path == NULL) {
Linus Torvalds's avatar
Linus Torvalds committed
642
		rc = -ENOMEM;
643 644 645
		goto mknod_out;
	}

646 647 648
	rc = tcon->ses->server->ops->make_node(xid, inode, direntry, tcon,
					       full_path, mode,
					       device_number);
649 650

mknod_out:
651
	kfree(full_path);
652
	free_xid(xid);
653
	cifs_put_tlink(tlink);
Linus Torvalds's avatar
Linus Torvalds committed
654 655 656 657
	return rc;
}

struct dentry *
Steve French's avatar
Steve French committed
658
cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
Al Viro's avatar
Al Viro committed
659
	    unsigned int flags)
Linus Torvalds's avatar
Linus Torvalds committed
660
{
661
	unsigned int xid;
Linus Torvalds's avatar
Linus Torvalds committed
662 663
	int rc = 0; /* to get around spurious gcc warning, set to zero here */
	struct cifs_sb_info *cifs_sb;
664
	struct tcon_link *tlink;
665
	struct cifs_tcon *pTcon;
Linus Torvalds's avatar
Linus Torvalds committed
666 667 668
	struct inode *newInode = NULL;
	char *full_path = NULL;

669
	xid = get_xid();
Linus Torvalds's avatar
Linus Torvalds committed
670

Al Viro's avatar
Al Viro committed
671 672
	cifs_dbg(FYI, "parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
		 parent_dir_inode, direntry, direntry);
Linus Torvalds's avatar
Linus Torvalds committed
673 674 675 676

	/* check whether path exists */

	cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
677 678
	tlink = cifs_sb_tlink(cifs_sb);
	if (IS_ERR(tlink)) {
679
		free_xid(xid);
680
		return ERR_CAST(tlink);
681 682
	}
	pTcon = tlink_tcon(tlink);
Linus Torvalds's avatar
Linus Torvalds committed
683

684
	rc = check_name(direntry, pTcon);
685 686 687 688 689
	if (unlikely(rc)) {
		cifs_put_tlink(tlink);
		free_xid(xid);
		return ERR_PTR(rc);
	}
690

Linus Torvalds's avatar
Linus Torvalds committed
691 692 693 694
	/* can not grab the rename sem here since it would
	deadlock in the cases (beginning of sys_rename itself)
	in which we already have the sb rename sem */
	full_path = build_path_from_dentry(direntry);
Steve French's avatar
Steve French committed
695
	if (full_path == NULL) {
696 697 698
		cifs_put_tlink(tlink);
		free_xid(xid);
		return ERR_PTR(-ENOMEM);
Linus Torvalds's avatar
Linus Torvalds committed
699 700
	}

701
	if (d_really_is_positive(direntry)) {
702
		cifs_dbg(FYI, "non-NULL inode in lookup\n");
Linus Torvalds's avatar
Linus Torvalds committed
703
	} else {
704
		cifs_dbg(FYI, "NULL inode in lookup\n");
Linus Torvalds's avatar
Linus Torvalds committed
705
	}
706
	cifs_dbg(FYI, "Full path: %s inode = 0x%p\n",
707
		 full_path, d_inode(direntry));
Linus Torvalds's avatar
Linus Torvalds committed
708

709
	if (pTcon->unix_ext) {
710 711 712
		rc = cifs_get_inode_info_unix(&newInode, full_path,
					      parent_dir_inode->i_sb, xid);
	} else {
Linus Torvalds's avatar
Linus Torvalds committed
713
		rc = cifs_get_inode_info(&newInode, full_path, NULL,
714
				parent_dir_inode->i_sb, xid, NULL);
715
	}
Linus Torvalds's avatar
Linus Torvalds committed
716

717
	if (rc == 0) {
Steve French's avatar
Steve French committed
718
		/* since paths are not looked up by component - the parent
719
		   directories are presumed to be good here */
Linus Torvalds's avatar
Linus Torvalds committed
720 721
		renew_parental_timestamps(direntry);
	} else if (rc == -ENOENT) {
Miklos Szeredi's avatar
Miklos Szeredi committed
722
		cifs_set_time(direntry, jiffies);
723 724 725 726 727 728 729 730
		newInode = NULL;
	} else {
		if (rc != -EACCES) {
			cifs_dbg(FYI, "Unexpected lookup error %d\n", rc);
			/* We special case check for Access Denied - since that
			is a common return code */
		}
		newInode = ERR_PTR(rc);
Linus Torvalds's avatar
Linus Torvalds committed
731
	}
732
	kfree(full_path);
733
	cifs_put_tlink(tlink);
734
	free_xid(xid);
735
	return d_splice_alias(newInode, direntry);
Linus Torvalds's avatar
Linus Torvalds committed
736 737 738
}

static int
739
cifs_d_revalidate(struct dentry *direntry, unsigned int flags)
Linus Torvalds's avatar
Linus Torvalds committed
740
{
741
	if (flags & LOOKUP_RCU)
742 743
		return -ECHILD;

744
	if (d_really_is_positive(direntry)) {
745
		if (cifs_revalidate_dentry(direntry))
Linus Torvalds's avatar
Linus Torvalds committed
746
			return 0;
747 748
		else {
			/*
749 750 751 752 753
			 * If the inode wasn't known to be a dfs entry when
			 * the dentry was instantiated, such as when created
			 * via ->readdir(), it needs to be set now since the
			 * attributes will have been updated by
			 * cifs_revalidate_dentry().
754
			 */
755
			if (IS_AUTOMOUNT(d_inode(direntry)) &&
756 757 758 759 760 761
			   !(direntry->d_flags & DCACHE_NEED_AUTOMOUNT)) {
				spin_lock(&direntry->d_lock);
				direntry->d_flags |= DCACHE_NEED_AUTOMOUNT;
				spin_unlock(&direntry->d_lock);
			}

762
			return 1;
763
		}
Linus Torvalds's avatar
Linus Torvalds committed
764 765
	}

766 767 768 769
	/*
	 * This may be nfsd (or something), anyway, we can't see the
	 * intent of this. So, since this can be for creation, drop it.
	 */
770
	if (!flags)
771 772 773 774 775 776 777
		return 0;

	/*
	 * Drop the negative dentry, in order to make sure to use the
	 * case sensitive name which is specified by user if this is
	 * for creation.
	 */
778
	if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
779
		return 0;
780

Miklos Szeredi's avatar
Miklos Szeredi committed
781
	if (time_after(jiffies, cifs_get_time(direntry) + HZ) || !lookupCacheEnabled)
782 783 784
		return 0;

	return 1;
Linus Torvalds's avatar
Linus Torvalds committed
785 786 787 788 789 790
}

/* static int cifs_d_delete(struct dentry *direntry)
{
	int rc = 0;

Al Viro's avatar
Al Viro committed
791
	cifs_dbg(FYI, "In cifs d_delete, name = %pd\n", direntry);
Linus Torvalds's avatar
Linus Torvalds committed
792 793 794 795

	return rc;
}     */

Al Viro's avatar
Al Viro committed
796
const struct dentry_operations cifs_dentry_ops = {
Linus Torvalds's avatar
Linus Torvalds committed
797
	.d_revalidate = cifs_d_revalidate,
798
	.d_automount = cifs_dfs_d_automount,
Steve French's avatar
Steve French committed
799
/* d_delete:       cifs_d_delete,      */ /* not needed except for debugging */
Linus Torvalds's avatar
Linus Torvalds committed
800
};
801

802
static int cifs_ci_hash(const struct dentry *dentry, struct qstr *q)
803
{
Nick Piggin's avatar
Nick Piggin committed
804
	struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls;
805
	unsigned long hash;
806 807
	wchar_t c;
	int i, charlen;
808

809
	hash = init_name_hash(dentry);
810 811 812 813 814 815 816
	for (i = 0; i < q->len; i += charlen) {
		charlen = codepage->char2uni(&q->name[i], q->len - i, &c);
		/* error out if we can't convert the character */
		if (unlikely(charlen < 0))
			return charlen;
		hash = partial_name_hash(cifs_toupper(c), hash);
	}
817 818 819 820 821
	q->hash = end_name_hash(hash);

	return 0;
}

822
static int cifs_ci_compare(const struct dentry *dentry,
823
		unsigned int len, const char *str, const struct qstr *name)
824
{
825
	struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls;
826 827
	wchar_t c1, c2;
	int i, l1, l2;
828

829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866
	/*
	 * We make the assumption here that uppercase characters in the local
	 * codepage are always the same length as their lowercase counterparts.
	 *
	 * If that's ever not the case, then this will fail to match it.
	 */
	if (name->len != len)
		return 1;

	for (i = 0; i < len; i += l1) {
		/* Convert characters in both strings to UTF-16. */
		l1 = codepage->char2uni(&str[i], len - i, &c1);
		l2 = codepage->char2uni(&name->name[i], name->len - i, &c2);

		/*
		 * If we can't convert either character, just declare it to
		 * be 1 byte long and compare the original byte.
		 */
		if (unlikely(l1 < 0 && l2 < 0)) {
			if (str[i] != name->name[i])
				return 1;
			l1 = 1;
			continue;
		}

		/*
		 * Here, we again ass|u|me that upper/lowercase versions of
		 * a character are the same length in the local NLS.
		 */
		if (l1 != l2)
			return 1;

		/* Now compare uppercase versions of these characters */
		if (cifs_toupper(c1) != cifs_toupper(c2))
			return 1;
	}

	return 0;
867 868
}

Al Viro's avatar
Al Viro committed
869
const struct dentry_operations cifs_ci_dentry_ops = {
870 871 872
	.d_revalidate = cifs_d_revalidate,
	.d_hash = cifs_ci_hash,
	.d_compare = cifs_ci_compare,
873
	.d_automount = cifs_dfs_d_automount,
874
};