inode.c 74.3 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 *   fs/cifs/inode.c
 *
4
 *   Copyright (C) International Business Machines  Corp., 2002,2010
L
Linus Torvalds 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *   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>
23
#include <linux/slab.h>
L
Linus Torvalds 已提交
24
#include <linux/pagemap.h>
25
#include <linux/freezer.h>
26
#include <linux/sched/signal.h>
27
#include <linux/wait_bit.h>
28
#include <linux/fiemap.h>
29

L
Linus Torvalds 已提交
30 31 32 33 34
#include <asm/div64.h>
#include "cifsfs.h"
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
35
#include "smb2proto.h"
L
Linus Torvalds 已提交
36 37
#include "cifs_debug.h"
#include "cifs_fs_sb.h"
38
#include "cifs_unicode.h"
39
#include "fscache.h"
L
Linus Torvalds 已提交
40

41

42
static void cifs_set_ops(struct inode *inode)
43 44 45 46 47 48 49 50 51 52 53
{
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);

	switch (inode->i_mode & S_IFMT) {
	case S_IFREG:
		inode->i_op = &cifs_file_inode_ops;
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
				inode->i_fop = &cifs_file_direct_nobrl_ops;
			else
				inode->i_fop = &cifs_file_direct_ops;
54 55 56 57 58
		} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
				inode->i_fop = &cifs_file_strict_nobrl_ops;
			else
				inode->i_fop = &cifs_file_strict_ops;
59 60 61 62 63 64 65
		} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
			inode->i_fop = &cifs_file_nobrl_ops;
		else { /* not direct, send byte range locks */
			inode->i_fop = &cifs_file_ops;
		}

		/* check if server can support readpages */
66
		if (cifs_sb_master_tcon(cifs_sb)->ses->server->max_read <
67
				PAGE_SIZE + MAX_CIFS_HDR_SIZE)
68 69 70 71 72
			inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
		else
			inode->i_data.a_ops = &cifs_addr_ops;
		break;
	case S_IFDIR:
S
Steve French 已提交
73
#ifdef CONFIG_CIFS_DFS_UPCALL
74
		if (IS_AUTOMOUNT(inode)) {
75 76
			inode->i_op = &cifs_dfs_referral_inode_operations;
		} else {
S
Steve French 已提交
77 78 79
#else /* NO DFS support, treat as a directory */
		{
#endif
80 81 82
			inode->i_op = &cifs_dir_inode_ops;
			inode->i_fop = &cifs_dir_ops;
		}
83 84 85 86 87 88 89 90 91 92
		break;
	case S_IFLNK:
		inode->i_op = &cifs_symlink_inode_ops;
		break;
	default:
		init_special_inode(inode, inode->i_mode, inode->i_rdev);
		break;
	}
}

93 94 95 96 97 98 99 100
/* check inode attributes against fattr. If they don't match, tag the
 * inode for cache invalidation
 */
static void
cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
{
	struct cifsInodeInfo *cifs_i = CIFS_I(inode);

101 102
	cifs_dbg(FYI, "%s: revalidating inode %llu\n",
		 __func__, cifs_i->uniqueid);
103 104

	if (inode->i_state & I_NEW) {
105 106
		cifs_dbg(FYI, "%s: inode %llu is new\n",
			 __func__, cifs_i->uniqueid);
107 108 109 110
		return;
	}

	/* don't bother with revalidation if we have an oplock */
111
	if (CIFS_CACHE_READ(cifs_i)) {
112 113
		cifs_dbg(FYI, "%s: inode %llu is oplocked\n",
			 __func__, cifs_i->uniqueid);
114 115 116 117
		return;
	}

	 /* revalidate if mtime or size have changed */
118
	fattr->cf_mtime = timestamp_truncate(fattr->cf_mtime, inode);
A
Arnd Bergmann 已提交
119
	if (timespec64_equal(&inode->i_mtime, &fattr->cf_mtime) &&
120
	    cifs_i->server_eof == fattr->cf_eof) {
121 122
		cifs_dbg(FYI, "%s: inode %llu is unchanged\n",
			 __func__, cifs_i->uniqueid);
123 124 125
		return;
	}

126 127
	cifs_dbg(FYI, "%s: invalidating inode %llu mapping\n",
		 __func__, cifs_i->uniqueid);
128
	set_bit(CIFS_INO_INVALID_MAPPING, &cifs_i->flags);
129 130
}

131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
/*
 * copy nlink to the inode, unless it wasn't provided.  Provide
 * sane values if we don't have an existing one and none was provided
 */
static void
cifs_nlink_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
{
	/*
	 * if we're in a situation where we can't trust what we
	 * got from the server (readdir, some non-unix cases)
	 * fake reasonable values
	 */
	if (fattr->cf_flags & CIFS_FATTR_UNKNOWN_NLINK) {
		/* only provide fake values on a new inode */
		if (inode->i_state & I_NEW) {
			if (fattr->cf_cifsattrs & ATTR_DIRECTORY)
				set_nlink(inode, 2);
			else
				set_nlink(inode, 1);
		}
		return;
	}

	/* we trust the server, so update it */
	set_nlink(inode, fattr->cf_nlink);
}

158 159 160
/* populate an inode with info from a cifs_fattr struct */
void
cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
161
{
162
	struct cifsInodeInfo *cifs_i = CIFS_I(inode);
163
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
164

165 166
	cifs_revalidate_cache(inode, fattr);

167
	spin_lock(&inode->i_lock);
168 169 170
	fattr->cf_mtime = timestamp_truncate(fattr->cf_mtime, inode);
	fattr->cf_atime = timestamp_truncate(fattr->cf_atime, inode);
	fattr->cf_ctime = timestamp_truncate(fattr->cf_ctime, inode);
171
	/* we do not want atime to be less than mtime, it broke some apps */
172
	if (timespec64_compare(&fattr->cf_atime, &fattr->cf_mtime) < 0)
173 174 175
		inode->i_atime = fattr->cf_mtime;
	else
		inode->i_atime = fattr->cf_atime;
A
Arnd Bergmann 已提交
176 177
	inode->i_mtime = fattr->cf_mtime;
	inode->i_ctime = fattr->cf_ctime;
178
	inode->i_rdev = fattr->cf_rdev;
179
	cifs_nlink_fattr_to_inode(inode, fattr);
180 181 182
	inode->i_uid = fattr->cf_uid;
	inode->i_gid = fattr->cf_gid;

183 184 185 186 187
	/* if dynperm is set, don't clobber existing mode */
	if (inode->i_state & I_NEW ||
	    !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
		inode->i_mode = fattr->cf_mode;

188
	cifs_i->cifsAttrs = fattr->cf_cifsattrs;
189

190 191 192 193 194
	if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
		cifs_i->time = 0;
	else
		cifs_i->time = jiffies;

195 196 197 198
	if (fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
		set_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
	else
		clear_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
199

200
	cifs_i->server_eof = fattr->cf_eof;
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
	/*
	 * Can't safely change the file size here if the client is writing to
	 * it due to potential races.
	 */
	if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
		i_size_write(inode, fattr->cf_eof);

		/*
		 * i_blocks is not related to (i_size / i_blksize),
		 * but instead 512 byte (2**9) size is required for
		 * calculating num blocks.
		 */
		inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
	}
	spin_unlock(&inode->i_lock);

217 218
	if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL)
		inode->i_flags |= S_AUTOMOUNT;
219 220
	if (inode->i_state & I_NEW)
		cifs_set_ops(inode);
221 222
}

223 224 225 226 227 228 229 230 231 232 233
void
cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
{
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);

	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
		return;

	fattr->cf_uniqueid = iunique(sb, ROOT_I);
}

234 235 236 237 238 239 240 241 242 243 244 245 246
/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
void
cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
			 struct cifs_sb_info *cifs_sb)
{
	memset(fattr, 0, sizeof(*fattr));
	fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
	fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
	fattr->cf_eof = le64_to_cpu(info->EndOfFile);

	fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
	fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
	fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
S
Steve French 已提交
247 248
	/* old POSIX extensions don't get create time */

249
	fattr->cf_mode = le64_to_cpu(info->Permissions);
250 251 252 253 254

	/*
	 * Since we set the inode type below we need to mask off
	 * to avoid strange results if bits set above.
	 */
255
	fattr->cf_mode &= ~S_IFMT;
256 257
	switch (le32_to_cpu(info->Type)) {
	case UNIX_FILE:
258 259
		fattr->cf_mode |= S_IFREG;
		fattr->cf_dtype = DT_REG;
260 261
		break;
	case UNIX_SYMLINK:
262 263
		fattr->cf_mode |= S_IFLNK;
		fattr->cf_dtype = DT_LNK;
264 265
		break;
	case UNIX_DIR:
266 267
		fattr->cf_mode |= S_IFDIR;
		fattr->cf_dtype = DT_DIR;
268 269
		break;
	case UNIX_CHARDEV:
270 271 272 273
		fattr->cf_mode |= S_IFCHR;
		fattr->cf_dtype = DT_CHR;
		fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
				       le64_to_cpu(info->DevMinor) & MINORMASK);
274 275
		break;
	case UNIX_BLOCKDEV:
276 277 278 279
		fattr->cf_mode |= S_IFBLK;
		fattr->cf_dtype = DT_BLK;
		fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
				       le64_to_cpu(info->DevMinor) & MINORMASK);
280 281
		break;
	case UNIX_FIFO:
282 283
		fattr->cf_mode |= S_IFIFO;
		fattr->cf_dtype = DT_FIFO;
284 285
		break;
	case UNIX_SOCKET:
286 287
		fattr->cf_mode |= S_IFSOCK;
		fattr->cf_dtype = DT_SOCK;
288 289 290
		break;
	default:
		/* safest to call it a file if we do not know */
291 292
		fattr->cf_mode |= S_IFREG;
		fattr->cf_dtype = DT_REG;
293
		cifs_dbg(FYI, "unknown type %d\n", le32_to_cpu(info->Type));
294 295 296
		break;
	}

297 298 299
	fattr->cf_uid = cifs_sb->mnt_uid;
	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
		u64 id = le64_to_cpu(info->Uid);
300 301 302 303 304
		if (id < ((uid_t)-1)) {
			kuid_t uid = make_kuid(&init_user_ns, id);
			if (uid_valid(uid))
				fattr->cf_uid = uid;
		}
305 306 307 308 309
	}
	
	fattr->cf_gid = cifs_sb->mnt_gid;
	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
		u64 id = le64_to_cpu(info->Gid);
310 311 312 313 314
		if (id < ((gid_t)-1)) {
			kgid_t gid = make_kgid(&init_user_ns, id);
			if (gid_valid(gid))
				fattr->cf_gid = gid;
		}
315
	}
316

317
	fattr->cf_nlink = le64_to_cpu(info->Nlinks);
318 319
}

320
/*
321 322 323 324 325
 * Fill a cifs_fattr struct with fake inode info.
 *
 * Needed to setup cifs_fattr data for the directory which is the
 * junction to the new submount (ie to setup the fake directory
 * which represents a DFS referral).
326
 */
S
Steve French 已提交
327
static void
328
cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
329
{
330
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
331

332
	cifs_dbg(FYI, "creating fake fattr for DFS referral\n");
333 334 335 336 337

	memset(fattr, 0, sizeof(*fattr));
	fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
	fattr->cf_uid = cifs_sb->mnt_uid;
	fattr->cf_gid = cifs_sb->mnt_gid;
338
	ktime_get_coarse_real_ts64(&fattr->cf_mtime);
339
	fattr->cf_atime = fattr->cf_ctime = fattr->cf_mtime;
340
	fattr->cf_nlink = 2;
341
	fattr->cf_flags = CIFS_FATTR_DFS_REFERRAL;
342 343
}

344 345
static int
cifs_get_file_info_unix(struct file *filp)
J
Jeff Layton 已提交
346 347
{
	int rc;
348
	unsigned int xid;
J
Jeff Layton 已提交
349 350
	FILE_UNIX_BASIC_INFO find_data;
	struct cifs_fattr fattr;
A
Al Viro 已提交
351
	struct inode *inode = file_inode(filp);
J
Jeff Layton 已提交
352
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
353
	struct cifsFileInfo *cfile = filp->private_data;
354
	struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
J
Jeff Layton 已提交
355

356
	xid = get_xid();
357
	rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data);
J
Jeff Layton 已提交
358 359 360 361 362 363 364 365
	if (!rc) {
		cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
	} else if (rc == -EREMOTE) {
		cifs_create_dfs_fattr(&fattr, inode->i_sb);
		rc = 0;
	}

	cifs_fattr_to_inode(inode, &fattr);
366
	free_xid(xid);
J
Jeff Layton 已提交
367 368 369
	return rc;
}

L
Linus Torvalds 已提交
370
int cifs_get_inode_info_unix(struct inode **pinode,
371
			     const unsigned char *full_path,
372
			     struct super_block *sb, unsigned int xid)
L
Linus Torvalds 已提交
373
{
374
	int rc;
375
	FILE_UNIX_BASIC_INFO find_data;
376
	struct cifs_fattr fattr;
377
	struct cifs_tcon *tcon;
378
	struct tcon_link *tlink;
L
Linus Torvalds 已提交
379 380
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);

381
	cifs_dbg(FYI, "Getting info on %s\n", full_path);
382

383 384 385 386 387
	tlink = cifs_sb_tlink(cifs_sb);
	if (IS_ERR(tlink))
		return PTR_ERR(tlink);
	tcon = tlink_tcon(tlink);

L
Linus Torvalds 已提交
388
	/* could have done a find first instead but this returns more info */
389
	rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
390
				  cifs_sb->local_nls, cifs_remap(cifs_sb));
391
	cifs_put_tlink(tlink);
392

393 394 395 396 397 398 399 400
	if (!rc) {
		cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
	} else if (rc == -EREMOTE) {
		cifs_create_dfs_fattr(&fattr, sb);
		rc = 0;
	} else {
		return rc;
	}
L
Linus Torvalds 已提交
401

402 403
	/* check for Minshall+French symlinks */
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
404 405
		int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
					     full_path);
406
		if (tmprc)
407
			cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
408 409
	}

410
	if (*pinode == NULL) {
411
		/* get new inode */
412
		cifs_fill_uniqueid(sb, &fattr);
413 414
		*pinode = cifs_iget(sb, &fattr);
		if (!*pinode)
415
			rc = -ENOMEM;
416 417
	} else {
		/* we already have inode, update it */
418 419 420 421

		/* if uniqueid is different, return error */
		if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
		    CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
422
			CIFS_I(*pinode)->time = 0; /* force reval */
423 424 425 426 427 428 429
			rc = -ESTALE;
			goto cgiiu_exit;
		}

		/* if filetype is different, return error */
		if (unlikely(((*pinode)->i_mode & S_IFMT) !=
		    (fattr.cf_mode & S_IFMT))) {
430
			CIFS_I(*pinode)->time = 0; /* force reval */
431 432 433 434
			rc = -ESTALE;
			goto cgiiu_exit;
		}

435
		cifs_fattr_to_inode(*pinode, &fattr);
436
	}
L
Linus Torvalds 已提交
437

438
cgiiu_exit:
L
Linus Torvalds 已提交
439 440 441
	return rc;
}

442
static int
443
cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
444
	      struct cifs_sb_info *cifs_sb, unsigned int xid)
445 446
{
	int rc;
447
	__u32 oplock;
448
	struct tcon_link *tlink;
449
	struct cifs_tcon *tcon;
450 451
	struct cifs_fid fid;
	struct cifs_open_parms oparms;
452
	struct cifs_io_parms io_parms = {0};
453
	char buf[24];
454
	unsigned int bytes_read;
S
Steve French 已提交
455
	char *pbuf;
456
	int buf_type = CIFS_NO_BUFFER;
457 458 459

	pbuf = buf;

460 461 462 463 464
	fattr->cf_mode &= ~S_IFMT;

	if (fattr->cf_eof == 0) {
		fattr->cf_mode |= S_IFIFO;
		fattr->cf_dtype = DT_FIFO;
465
		return 0;
466 467 468
	} else if (fattr->cf_eof < 8) {
		fattr->cf_mode |= S_IFREG;
		fattr->cf_dtype = DT_REG;
469 470
		return -EINVAL;	 /* EOPNOTSUPP? */
	}
471

472 473 474 475 476
	tlink = cifs_sb_tlink(cifs_sb);
	if (IS_ERR(tlink))
		return PTR_ERR(tlink);
	tcon = tlink_tcon(tlink);

477 478 479
	oparms.tcon = tcon;
	oparms.cifs_sb = cifs_sb;
	oparms.desired_access = GENERIC_READ;
480
	oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
481 482 483 484 485
	oparms.disposition = FILE_OPEN;
	oparms.path = path;
	oparms.fid = &fid;
	oparms.reconnect = false;

486 487 488 489 490
	if (tcon->ses->server->oplocks)
		oplock = REQ_OPLOCK;
	else
		oplock = 0;
	rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
491
	if (rc) {
492
		cifs_dbg(FYI, "check sfu type of %s, open rc = %d\n", path, rc);
493 494 495 496 497
		cifs_put_tlink(tlink);
		return rc;
	}

	/* Read header */
498
	io_parms.netfid = fid.netfid;
499 500 501 502 503
	io_parms.pid = current->tgid;
	io_parms.tcon = tcon;
	io_parms.offset = 0;
	io_parms.length = 24;

504 505
	rc = tcon->ses->server->ops->sync_read(xid, &fid, &io_parms,
					&bytes_read, &pbuf, &buf_type);
506 507 508 509 510 511 512 513 514 515 516 517
	if ((rc == 0) && (bytes_read >= 8)) {
		if (memcmp("IntxBLK", pbuf, 8) == 0) {
			cifs_dbg(FYI, "Block device\n");
			fattr->cf_mode |= S_IFBLK;
			fattr->cf_dtype = DT_BLK;
			if (bytes_read == 24) {
				/* we have enough to decode dev num */
				__u64 mjr; /* major */
				__u64 mnr; /* minor */
				mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
				mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
				fattr->cf_rdev = MKDEV(mjr, mnr);
518
			}
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
		} else if (memcmp("IntxCHR", pbuf, 8) == 0) {
			cifs_dbg(FYI, "Char device\n");
			fattr->cf_mode |= S_IFCHR;
			fattr->cf_dtype = DT_CHR;
			if (bytes_read == 24) {
				/* we have enough to decode dev num */
				__u64 mjr; /* major */
				__u64 mnr; /* minor */
				mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
				mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
				fattr->cf_rdev = MKDEV(mjr, mnr);
			}
		} else if (memcmp("IntxLNK", pbuf, 7) == 0) {
			cifs_dbg(FYI, "Symlink\n");
			fattr->cf_mode |= S_IFLNK;
			fattr->cf_dtype = DT_LNK;
535
		} else {
536
			fattr->cf_mode |= S_IFREG; /* file? */
537
			fattr->cf_dtype = DT_REG;
538
			rc = -EOPNOTSUPP;
S
Steve French 已提交
539
		}
540 541 542 543
	} else {
		fattr->cf_mode |= S_IFREG; /* then it is a file */
		fattr->cf_dtype = DT_REG;
		rc = -EOPNOTSUPP; /* or some unknown SFU type */
544
	}
545 546

	tcon->ses->server->ops->close(xid, tcon, &fid);
547
	cifs_put_tlink(tlink);
548 549 550
	return rc;
}

551 552
#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID)  /* SETFILEBITS valid bits */

553 554 555 556 557 558
/*
 * Fetch mode bits as provided by SFU.
 *
 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
 */
static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
559
			 struct cifs_sb_info *cifs_sb, unsigned int xid)
560
{
561
#ifdef CONFIG_CIFS_XATTR
562 563 564
	ssize_t rc;
	char ea_value[4];
	__u32 mode;
565
	struct tcon_link *tlink;
566
	struct cifs_tcon *tcon;
567 568 569 570 571

	tlink = cifs_sb_tlink(cifs_sb);
	if (IS_ERR(tlink))
		return PTR_ERR(tlink);
	tcon = tlink_tcon(tlink);
572

573 574 575 576 577 578 579
	if (tcon->ses->server->ops->query_all_EAs == NULL) {
		cifs_put_tlink(tlink);
		return -EOPNOTSUPP;
	}

	rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path,
			"SETFILEBITS", ea_value, 4 /* size of buf */,
580
			cifs_sb);
581
	cifs_put_tlink(tlink);
582
	if (rc < 0)
583 584 585
		return (int)rc;
	else if (rc > 3) {
		mode = le32_to_cpu(*((__le32 *)ea_value));
586
		fattr->cf_mode &= ~SFBITS_MASK;
587 588
		cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
			 mode, fattr->cf_mode);
589
		fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
590
		cifs_dbg(FYI, "special mode bits 0%o\n", mode);
591
	}
592 593

	return 0;
594 595 596
#else
	return -EOPNOTSUPP;
#endif
597 598
}

599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654
/* Fill a cifs_fattr struct with info from POSIX info struct */
static void
smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct smb311_posix_qinfo *info,
			   struct super_block *sb, bool adjust_tz, bool symlink)
{
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);

	memset(fattr, 0, sizeof(*fattr));

	/* no fattr->flags to set */
	fattr->cf_cifsattrs = le32_to_cpu(info->DosAttributes);
	fattr->cf_uniqueid = le64_to_cpu(info->Inode);

	if (info->LastAccessTime)
		fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
	else
		ktime_get_coarse_real_ts64(&fattr->cf_atime);

	fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
	fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);

	if (adjust_tz) {
		fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
		fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
	}

	fattr->cf_eof = le64_to_cpu(info->EndOfFile);
	fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
	fattr->cf_createtime = le64_to_cpu(info->CreationTime);

	fattr->cf_nlink = le32_to_cpu(info->HardLinks);
	fattr->cf_mode = (umode_t) le32_to_cpu(info->Mode);
	/* The srv fs device id is overridden on network mount so setting rdev isn't needed here */
	/* fattr->cf_rdev = le32_to_cpu(info->DeviceId); */

	if (symlink) {
		fattr->cf_mode |= S_IFLNK;
		fattr->cf_dtype = DT_LNK;
	} else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
		fattr->cf_mode |= S_IFDIR;
		fattr->cf_dtype = DT_DIR;
	} else { /* file */
		fattr->cf_mode |= S_IFREG;
		fattr->cf_dtype = DT_REG;
	}
	/* else if reparse point ... TODO: add support for FIFO and blk dev; special file types */

	fattr->cf_uid = cifs_sb->mnt_uid; /* TODO: map uid and gid from SID */
	fattr->cf_gid = cifs_sb->mnt_gid;

	cifs_dbg(FYI, "POSIX query info: mode 0x%x uniqueid 0x%llx nlink %d\n",
		fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink);
}


655
/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
S
Steve French 已提交
656
static void
657
cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
658
		       struct super_block *sb, bool adjust_tz,
P
Pavel Shilovsky 已提交
659
		       bool symlink)
660
{
661
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
662
	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
663

664 665 666 667 668 669 670
	memset(fattr, 0, sizeof(*fattr));
	fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
	if (info->DeletePending)
		fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;

	if (info->LastAccessTime)
		fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
671 672
	else
		ktime_get_coarse_real_ts64(&fattr->cf_atime);
673 674 675 676 677

	fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
	fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);

	if (adjust_tz) {
678 679
		fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
		fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
680 681 682 683
	}

	fattr->cf_eof = le64_to_cpu(info->EndOfFile);
	fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
684
	fattr->cf_createtime = le64_to_cpu(info->CreationTime);
685

686
	fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
P
Pavel Shilovsky 已提交
687 688 689 690 691

	if (symlink) {
		fattr->cf_mode = S_IFLNK;
		fattr->cf_dtype = DT_LNK;
	} else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
692 693
		fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
		fattr->cf_dtype = DT_DIR;
694 695 696 697
		/*
		 * Server can return wrong NumberOfLinks value for directories
		 * when Unix extensions are disabled - fake it.
		 */
698 699
		if (!tcon->unix_ext)
			fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
700 701 702 703
	} else {
		fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
		fattr->cf_dtype = DT_REG;

704 705 706
		/* clear write bits if ATTR_READONLY is set */
		if (fattr->cf_cifsattrs & ATTR_READONLY)
			fattr->cf_mode &= ~(S_IWUGO);
707

708 709 710 711 712 713
		/*
		 * Don't accept zero nlink from non-unix servers unless
		 * delete is pending.  Instead mark it as unknown.
		 */
		if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
		    !info->DeletePending) {
J
Joe Perches 已提交
714 715
			cifs_dbg(VFS, "bogus file nlink value %u\n",
				 fattr->cf_nlink);
716
			fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
717
		}
718
	}
719 720 721

	fattr->cf_uid = cifs_sb->mnt_uid;
	fattr->cf_gid = cifs_sb->mnt_gid;
722 723
}

724 725
static int
cifs_get_file_info(struct file *filp)
J
Jeff Layton 已提交
726 727
{
	int rc;
728
	unsigned int xid;
J
Jeff Layton 已提交
729 730
	FILE_ALL_INFO find_data;
	struct cifs_fattr fattr;
A
Al Viro 已提交
731
	struct inode *inode = file_inode(filp);
732
	struct cifsFileInfo *cfile = filp->private_data;
733
	struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
734 735 736 737
	struct TCP_Server_Info *server = tcon->ses->server;

	if (!server->ops->query_file_info)
		return -ENOSYS;
J
Jeff Layton 已提交
738

739
	xid = get_xid();
740
	rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
741 742
	switch (rc) {
	case 0:
743
		cifs_all_info_to_fattr(&fattr, &find_data, inode->i_sb, false,
P
Pavel Shilovsky 已提交
744
				       false);
745 746 747 748 749 750 751
		break;
	case -EREMOTE:
		cifs_create_dfs_fattr(&fattr, inode->i_sb);
		rc = 0;
		break;
	case -EOPNOTSUPP:
	case -EINVAL:
J
Jeff Layton 已提交
752 753
		/*
		 * FIXME: legacy server -- fall back to path-based call?
S
Steve French 已提交
754 755 756
		 * for now, just skip revalidating and mark inode for
		 * immediate reval.
		 */
J
Jeff Layton 已提交
757 758
		rc = 0;
		CIFS_I(inode)->time = 0;
759
	default:
J
Jeff Layton 已提交
760
		goto cgfi_exit;
761
	}
J
Jeff Layton 已提交
762 763 764 765 766 767 768 769 770

	/*
	 * don't bother with SFU junk here -- just mark inode as needing
	 * revalidation.
	 */
	fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
	fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
	cifs_fattr_to_inode(inode, &fattr);
cgfi_exit:
771
	free_xid(xid);
J
Jeff Layton 已提交
772 773 774
	return rc;
}

775 776 777
/* Simple function to return a 64 bit hash of string.  Rarely called */
static __u64 simple_hashstr(const char *str)
{
778
	const __u64 hash_mult =  1125899906842597ULL; /* a big enough prime */
779 780 781 782 783 784 785 786
	__u64 hash = 0;

	while (*str)
		hash = (hash + (__u64) *str++) * hash_mult;

	return hash;
}

787 788 789 790
/**
 * cifs_backup_query_path_info - SMB1 fallback code to get ino
 *
 * Fallback code to get file metadata when we don't have access to
791
 * @full_path (EACCES) and have backup creds.
792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 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 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898
 *
 * @data will be set to search info result buffer
 * @resp_buf will be set to cifs resp buf and needs to be freed with
 * cifs_buf_release() when done with @data.
 */
static int
cifs_backup_query_path_info(int xid,
			    struct cifs_tcon *tcon,
			    struct super_block *sb,
			    const char *full_path,
			    void **resp_buf,
			    FILE_ALL_INFO **data)
{
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
	struct cifs_search_info info = {0};
	u16 flags;
	int rc;

	*resp_buf = NULL;
	info.endOfSearch = false;
	if (tcon->unix_ext)
		info.info_level = SMB_FIND_FILE_UNIX;
	else if ((tcon->ses->capabilities &
		  tcon->ses->server->vals->cap_nt_find) == 0)
		info.info_level = SMB_FIND_FILE_INFO_STANDARD;
	else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
		info.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
	else /* no srvino useful for fallback to some netapp */
		info.info_level = SMB_FIND_FILE_DIRECTORY_INFO;

	flags = CIFS_SEARCH_CLOSE_ALWAYS |
		CIFS_SEARCH_CLOSE_AT_END |
		CIFS_SEARCH_BACKUP_SEARCH;

	rc = CIFSFindFirst(xid, tcon, full_path,
			   cifs_sb, NULL, flags, &info, false);
	if (rc)
		return rc;

	*resp_buf = (void *)info.ntwrk_buf_start;
	*data = (FILE_ALL_INFO *)info.srch_entries_start;
	return 0;
}

static void
cifs_set_fattr_ino(int xid,
		   struct cifs_tcon *tcon,
		   struct super_block *sb,
		   struct inode **inode,
		   const char *full_path,
		   FILE_ALL_INFO *data,
		   struct cifs_fattr *fattr)
{
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
	struct TCP_Server_Info *server = tcon->ses->server;
	int rc;

	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
		if (*inode)
			fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
		else
			fattr->cf_uniqueid = iunique(sb, ROOT_I);
		return;
	}

	/*
	 * If we have an inode pass a NULL tcon to ensure we don't
	 * make a round trip to the server. This only works for SMB2+.
	 */
	rc = server->ops->get_srv_inum(xid,
				       *inode ? NULL : tcon,
				       cifs_sb, full_path,
				       &fattr->cf_uniqueid,
				       data);
	if (rc) {
		/*
		 * If that fails reuse existing ino or generate one
		 * and disable server ones
		 */
		if (*inode)
			fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
		else {
			fattr->cf_uniqueid = iunique(sb, ROOT_I);
			cifs_autodisable_serverino(cifs_sb);
		}
		return;
	}

	/* If no errors, check for zero root inode (invalid) */
	if (fattr->cf_uniqueid == 0 && strlen(full_path) == 0) {
		cifs_dbg(FYI, "Invalid (0) inodenum\n");
		if (*inode) {
			/* reuse */
			fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
		} else {
			/* make an ino by hashing the UNC */
			fattr->cf_flags |= CIFS_FATTR_FAKE_ROOT_INO;
			fattr->cf_uniqueid = simple_hashstr(tcon->treeName);
		}
	}
}

static inline bool is_inode_cache_good(struct inode *ino)
{
	return ino && CIFS_CACHE_READ(CIFS_I(ino)) && CIFS_I(ino)->time != 0;
}

899
int
900 901 902 903
cifs_get_inode_info(struct inode **inode,
		    const char *full_path,
		    FILE_ALL_INFO *in_data,
		    struct super_block *sb, int xid,
904
		    const struct cifs_fid *fid)
L
Linus Torvalds 已提交
905
{
906

907 908
	struct cifs_tcon *tcon;
	struct TCP_Server_Info *server;
909
	struct tcon_link *tlink;
L
Linus Torvalds 已提交
910
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
911
	bool adjust_tz = false;
912
	struct cifs_fattr fattr = {0};
P
Pavel Shilovsky 已提交
913
	bool symlink = false;
914 915 916 917 918
	FILE_ALL_INFO *data = in_data;
	FILE_ALL_INFO *tmp_data = NULL;
	void *smb1_backup_rsp_buf = NULL;
	int rc = 0;
	int tmprc = 0;
L
Linus Torvalds 已提交
919

920 921 922
	tlink = cifs_sb_tlink(cifs_sb);
	if (IS_ERR(tlink))
		return PTR_ERR(tlink);
923 924
	tcon = tlink_tcon(tlink);
	server = tcon->ses->server;
925

926 927 928
	/*
	 * 1. Fetch file metadata if not provided (data)
	 */
L
Linus Torvalds 已提交
929

930 931
	if (!data) {
		if (is_inode_cache_good(*inode)) {
932
			cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
933
			goto out;
L
Linus Torvalds 已提交
934
		}
935 936
		tmp_data = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
		if (!tmp_data) {
937
			rc = -ENOMEM;
938
			goto out;
939
		}
940 941 942 943
		rc = server->ops->query_path_info(xid, tcon, cifs_sb,
						  full_path, tmp_data,
						  &adjust_tz, &symlink);
		data = tmp_data;
L
Linus Torvalds 已提交
944
	}
945

946 947 948 949 950 951 952 953 954 955
	/*
	 * 2. Convert it to internal cifs metadata (fattr)
	 */

	switch (rc) {
	case 0:
		cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz, symlink);
		break;
	case -EREMOTE:
		/* DFS link, no metadata available on this server */
956
		cifs_create_dfs_fattr(&fattr, sb);
957
		rc = 0;
958 959
		break;
	case -EACCES:
960
		/*
961 962 963 964 965 966
		 * perm errors, try again with backup flags if possible
		 *
		 * For SMB2 and later the backup intent flag
		 * is already sent if needed on open and there
		 * is no path based FindFirst operation to use
		 * to retry with
967
		 */
968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989
		if (backup_cred(cifs_sb) && is_smb1_server(server)) {
			/* for easier reading */
			FILE_DIRECTORY_INFO *fdi;
			SEARCH_ID_FULL_DIR_INFO *si;

			rc = cifs_backup_query_path_info(xid, tcon, sb,
							 full_path,
							 &smb1_backup_rsp_buf,
							 &data);
			if (rc)
				goto out;

			fdi = (FILE_DIRECTORY_INFO *)data;
			si = (SEARCH_ID_FULL_DIR_INFO *)data;

			cifs_dir_info_to_fattr(&fattr, fdi, cifs_sb);
			fattr.cf_uniqueid = le64_to_cpu(si->UniqueId);
			/* uniqueid set, skip get inum step */
			goto handle_mnt_opt;
		} else {
			/* nothing we can do, bail out */
			goto out;
990
		}
991 992 993 994 995
		break;
	default:
		cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc);
		goto out;
	}
996

997 998 999 1000 1001
	/*
	 * 3. Get or update inode number (fattr.cf_uniqueid)
	 */

	cifs_set_fattr_ino(xid, tcon, sb, inode, full_path, data, &fattr);
L
Linus Torvalds 已提交
1002

1003
	/*
1004
	 * 4. Tweak fattr based on mount options
1005
	 */
1006

1007
handle_mnt_opt:
1008 1009 1010 1011 1012
	/* query for SFU type info if supported and needed */
	if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
	    cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
		tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
		if (tmprc)
1013
			cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
1014
	}
L
Linus Torvalds 已提交
1015

1016
	/* fill in 0777 bits from ACL */
1017 1018 1019 1020 1021
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) {
		rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, true,
				       full_path, fid);
		if (rc) {
			cifs_dbg(FYI, "%s: Get mode from SID failed. rc=%d\n",
1022 1023
				 __func__, rc);
			goto out;
1024 1025 1026
		}
	} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
		rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, false,
1027 1028
				       full_path, fid);
		if (rc) {
1029 1030
			cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
				 __func__, rc);
1031
			goto out;
1032
		}
1033 1034
	}

1035 1036 1037
	/* fill in remaining high mode bits e.g. SUID, VTX */
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
		cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
1038

1039 1040
	/* check for Minshall+French symlinks */
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
1041 1042
		tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
					 full_path);
1043
		if (tmprc)
1044
			cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
1045 1046
	}

1047 1048 1049 1050
	/*
	 * 5. Update inode with final fattr data
	 */

1051 1052 1053
	if (!*inode) {
		*inode = cifs_iget(sb, &fattr);
		if (!*inode)
1054 1055
			rc = -ENOMEM;
	} else {
1056 1057
		/* we already have inode, update it */

1058 1059 1060
		/* if uniqueid is different, return error */
		if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
		    CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
1061
			CIFS_I(*inode)->time = 0; /* force reval */
1062
			rc = -ESTALE;
1063
			goto out;
1064 1065
		}

1066 1067 1068
		/* if filetype is different, return error */
		if (unlikely(((*inode)->i_mode & S_IFMT) !=
		    (fattr.cf_mode & S_IFMT))) {
1069
			CIFS_I(*inode)->time = 0; /* force reval */
1070
			rc = -ESTALE;
1071
			goto out;
1072 1073
		}

1074
		cifs_fattr_to_inode(*inode, &fattr);
1075
	}
1076 1077
out:
	cifs_buf_release(smb1_backup_rsp_buf);
1078
	cifs_put_tlink(tlink);
1079
	kfree(tmp_data);
L
Linus Torvalds 已提交
1080 1081 1082
	return rc;
}

1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150
int
smb311_posix_get_inode_info(struct inode **inode,
		    const char *full_path,
		    struct super_block *sb, unsigned int xid)
{
	struct cifs_tcon *tcon;
	struct TCP_Server_Info *server;
	struct tcon_link *tlink;
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
	bool adjust_tz = false;
	struct cifs_fattr fattr = {0};
	bool symlink = false;
	struct smb311_posix_qinfo *data = NULL;
	int rc = 0;
	int tmprc = 0;

	tlink = cifs_sb_tlink(cifs_sb);
	if (IS_ERR(tlink))
		return PTR_ERR(tlink);
	tcon = tlink_tcon(tlink);
	server = tcon->ses->server;

	/*
	 * 1. Fetch file metadata
	 */

	if (is_inode_cache_good(*inode)) {
		cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
		goto out;
	}
	data = kmalloc(sizeof(struct smb311_posix_qinfo), GFP_KERNEL);
	if (!data) {
		rc = -ENOMEM;
		goto out;
	}

	rc = smb311_posix_query_path_info(xid, tcon, cifs_sb,
						  full_path, data,
						  &adjust_tz, &symlink);

	/*
	 * 2. Convert it to internal cifs metadata (fattr)
	 */

	switch (rc) {
	case 0:
		smb311_posix_info_to_fattr(&fattr, data, sb, adjust_tz, symlink);
		break;
	case -EREMOTE:
		/* DFS link, no metadata available on this server */
		cifs_create_dfs_fattr(&fattr, sb);
		rc = 0;
		break;
	case -EACCES:
		/*
		 * For SMB2 and later the backup intent flag
		 * is already sent if needed on open and there
		 * is no path based FindFirst operation to use
		 * to retry with so nothing we can do, bail out
		 */
		goto out;
	default:
		cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc);
		goto out;
	}


	/*
1151
	 * 3. Tweak fattr based on mount options
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162
	 */

	/* check for Minshall+French symlinks */
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
		tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
					 full_path);
		if (tmprc)
			cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
	}

	/*
1163
	 * 4. Update inode with final fattr data
1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197
	 */

	if (!*inode) {
		*inode = cifs_iget(sb, &fattr);
		if (!*inode)
			rc = -ENOMEM;
	} else {
		/* we already have inode, update it */

		/* if uniqueid is different, return error */
		if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
		    CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
			CIFS_I(*inode)->time = 0; /* force reval */
			rc = -ESTALE;
			goto out;
		}

		/* if filetype is different, return error */
		if (unlikely(((*inode)->i_mode & S_IFMT) !=
		    (fattr.cf_mode & S_IFMT))) {
			CIFS_I(*inode)->time = 0; /* force reval */
			rc = -ESTALE;
			goto out;
		}

		cifs_fattr_to_inode(*inode, &fattr);
	}
out:
	cifs_put_tlink(tlink);
	kfree(data);
	return rc;
}


1198 1199 1200 1201
static const struct inode_operations cifs_ipc_inode_ops = {
	.lookup = cifs_lookup,
};

1202 1203 1204 1205 1206
static int
cifs_find_inode(struct inode *inode, void *opaque)
{
	struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;

1207
	/* don't match inode with different uniqueid */
1208 1209 1210
	if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
		return 0;

1211 1212 1213 1214
	/* use createtime like an i_generation field */
	if (CIFS_I(inode)->createtime != fattr->cf_createtime)
		return 0;

1215 1216 1217 1218
	/* don't match inode of different type */
	if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
		return 0;

1219
	/* if it's not a directory or has no dentries, then flag it */
A
Al Viro 已提交
1220
	if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
1221 1222
		fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;

1223 1224 1225 1226 1227 1228 1229 1230 1231
	return 1;
}

static int
cifs_init_inode(struct inode *inode, void *opaque)
{
	struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;

	CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
1232
	CIFS_I(inode)->createtime = fattr->cf_createtime;
1233 1234 1235
	return 0;
}

1236 1237 1238 1239 1240 1241 1242 1243 1244 1245
/*
 * walk dentry list for an inode and report whether it has aliases that
 * are hashed. We use this to determine if a directory inode can actually
 * be used.
 */
static bool
inode_has_hashed_dentries(struct inode *inode)
{
	struct dentry *dentry;

1246
	spin_lock(&inode->i_lock);
1247
	hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
1248
		if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
1249
			spin_unlock(&inode->i_lock);
1250 1251 1252
			return true;
		}
	}
1253
	spin_unlock(&inode->i_lock);
1254 1255 1256
	return false;
}

1257 1258 1259 1260 1261 1262 1263
/* Given fattrs, get a corresponding inode */
struct inode *
cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
{
	unsigned long hash;
	struct inode *inode;

1264
retry_iget5_locked:
1265
	cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
1266 1267 1268 1269 1270 1271

	/* hash down to 32-bits on 32-bit arch */
	hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);

	inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
	if (inode) {
1272
		/* was there a potentially problematic inode collision? */
1273 1274
		if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
			fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
1275 1276 1277 1278 1279 1280 1281

			if (inode_has_hashed_dentries(inode)) {
				cifs_autodisable_serverino(CIFS_SB(sb));
				iput(inode);
				fattr->cf_uniqueid = iunique(sb, ROOT_I);
				goto retry_iget5_locked;
			}
1282 1283
		}

1284
		cifs_fattr_to_inode(inode, fattr);
1285
		if (sb->s_flags & SB_NOATIME)
1286 1287 1288
			inode->i_flags |= S_NOATIME | S_NOCMTIME;
		if (inode->i_state & I_NEW) {
			inode->i_ino = hash;
S
Steve French 已提交
1289
#ifdef CONFIG_CIFS_FSCACHE
1290 1291
			/* initialize per-inode cache cookie pointer */
			CIFS_I(inode)->fscache = NULL;
S
Steve French 已提交
1292
#endif
1293 1294 1295 1296 1297 1298 1299
			unlock_new_inode(inode);
		}
	}

	return inode;
}

L
Linus Torvalds 已提交
1300
/* gets root inode */
1301
struct inode *cifs_root_iget(struct super_block *sb)
L
Linus Torvalds 已提交
1302
{
1303
	unsigned int xid;
1304
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1305
	struct inode *inode = NULL;
1306
	long rc;
1307
	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323
	char *path = NULL;
	int len;

	if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
	    && cifs_sb->prepath) {
		len = strlen(cifs_sb->prepath);
		path = kzalloc(len + 2 /* leading sep + null */, GFP_KERNEL);
		if (path == NULL)
			return ERR_PTR(-ENOMEM);
		path[0] = '/';
		memcpy(path+1, cifs_sb->prepath, len);
	} else {
		path = kstrdup("", GFP_KERNEL);
		if (path == NULL)
			return ERR_PTR(-ENOMEM);
	}
1324

1325
	xid = get_xid();
S
Steve French 已提交
1326
	if (tcon->unix_ext) {
1327
		rc = cifs_get_inode_info_unix(&inode, path, sb, xid);
S
Steve French 已提交
1328 1329 1330
		/* some servers mistakenly claim POSIX support */
		if (rc != -EOPNOTSUPP)
			goto iget_no_retry;
J
Joe Perches 已提交
1331
		cifs_dbg(VFS, "server does not support POSIX extensions\n");
S
Steve French 已提交
1332 1333 1334
		tcon->unix_ext = false;
	}

1335
	convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
1336 1337 1338 1339
	if (tcon->posix_extensions)
		rc = smb311_posix_get_inode_info(&inode, path, sb, xid);
	else
		rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
1340

S
Steve French 已提交
1341
iget_no_retry:
1342 1343 1344 1345
	if (!inode) {
		inode = ERR_PTR(rc);
		goto out;
	}
1346

S
Steve French 已提交
1347
#ifdef CONFIG_CIFS_FSCACHE
1348
	/* populate tcon->resource_id */
1349
	tcon->resource_id = CIFS_I(inode)->uniqueid;
S
Steve French 已提交
1350
#endif
1351

A
Aurelien Aptel 已提交
1352
	if (rc && tcon->pipe) {
1353
		cifs_dbg(FYI, "ipc connection - fake read inode\n");
1354
		spin_lock(&inode->i_lock);
1355
		inode->i_mode |= S_IFDIR;
M
Miklos Szeredi 已提交
1356
		set_nlink(inode, 2);
1357 1358 1359 1360
		inode->i_op = &cifs_ipc_inode_ops;
		inode->i_fop = &simple_dir_operations;
		inode->i_uid = cifs_sb->mnt_uid;
		inode->i_gid = cifs_sb->mnt_gid;
1361
		spin_unlock(&inode->i_lock);
1362
	} else if (rc) {
1363
		iget_failed(inode);
1364
		inode = ERR_PTR(rc);
1365 1366
	}

1367
out:
1368
	kfree(path);
1369
	free_xid(xid);
1370
	return inode;
L
Linus Torvalds 已提交
1371 1372
}

1373
int
1374
cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
1375
		   char *full_path, __u32 dosattr)
1376 1377 1378
{
	bool set_time = false;
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1379
	struct TCP_Server_Info *server;
1380 1381
	FILE_BASIC_INFO	info_buf;

S
Steve French 已提交
1382 1383 1384
	if (attrs == NULL)
		return -EINVAL;

1385 1386 1387 1388
	server = cifs_sb_master_tcon(cifs_sb)->ses->server;
	if (!server->ops->set_file_info)
		return -ENOSYS;

1389 1390
	info_buf.Pad = 0;

1391 1392 1393
	if (attrs->ia_valid & ATTR_ATIME) {
		set_time = true;
		info_buf.LastAccessTime =
A
Arnd Bergmann 已提交
1394
			cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
1395 1396 1397 1398 1399 1400
	} else
		info_buf.LastAccessTime = 0;

	if (attrs->ia_valid & ATTR_MTIME) {
		set_time = true;
		info_buf.LastWriteTime =
A
Arnd Bergmann 已提交
1401
		    cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1402 1403 1404 1405 1406 1407 1408 1409 1410 1411
	} else
		info_buf.LastWriteTime = 0;

	/*
	 * Samba throws this field away, but windows may actually use it.
	 * Do not set ctime unless other time stamps are changed explicitly
	 * (i.e. by utimes()) since we would then have a mix of client and
	 * server times.
	 */
	if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
1412
		cifs_dbg(FYI, "CIFS - CTIME changed\n");
1413
		info_buf.ChangeTime =
A
Arnd Bergmann 已提交
1414
		    cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1415 1416 1417 1418 1419 1420
	} else
		info_buf.ChangeTime = 0;

	info_buf.CreationTime = 0;	/* don't change */
	info_buf.Attributes = cpu_to_le32(dosattr);

1421
	return server->ops->set_file_info(inode, full_path, &info_buf, xid);
1422 1423
}

1424
/*
1425
 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
1426 1427 1428
 * and rename it to a random name that hopefully won't conflict with
 * anything else.
 */
1429 1430 1431
int
cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
			   const unsigned int xid)
1432 1433 1434
{
	int oplock = 0;
	int rc;
1435 1436
	struct cifs_fid fid;
	struct cifs_open_parms oparms;
1437
	struct inode *inode = d_inode(dentry);
1438 1439
	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1440
	struct tcon_link *tlink;
1441
	struct cifs_tcon *tcon;
1442 1443
	__u32 dosattr, origattr;
	FILE_BASIC_INFO *info_buf = NULL;
1444

1445 1446 1447 1448 1449
	tlink = cifs_sb_tlink(cifs_sb);
	if (IS_ERR(tlink))
		return PTR_ERR(tlink);
	tcon = tlink_tcon(tlink);

1450 1451 1452 1453 1454 1455 1456 1457 1458
	/*
	 * We cannot rename the file if the server doesn't support
	 * CAP_INFOLEVEL_PASSTHRU
	 */
	if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
		rc = -EBUSY;
		goto out;
	}

1459 1460 1461
	oparms.tcon = tcon;
	oparms.cifs_sb = cifs_sb;
	oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
1462
	oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
1463 1464 1465 1466 1467 1468
	oparms.disposition = FILE_OPEN;
	oparms.path = full_path;
	oparms.fid = &fid;
	oparms.reconnect = false;

	rc = CIFS_open(xid, &oparms, &oplock, NULL);
1469 1470 1471
	if (rc != 0)
		goto out;

1472 1473 1474 1475 1476
	origattr = cifsInode->cifsAttrs;
	if (origattr == 0)
		origattr |= ATTR_NORMAL;

	dosattr = origattr & ~ATTR_READONLY;
1477 1478 1479 1480
	if (dosattr == 0)
		dosattr |= ATTR_NORMAL;
	dosattr |= ATTR_HIDDEN;

1481 1482 1483 1484 1485 1486 1487 1488
	/* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
	if (dosattr != origattr) {
		info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
		if (info_buf == NULL) {
			rc = -ENOMEM;
			goto out_close;
		}
		info_buf->Attributes = cpu_to_le32(dosattr);
1489
		rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
1490 1491 1492
					current->tgid);
		/* although we would like to mark the file hidden
 		   if that fails we will still try to rename it */
1493
		if (!rc)
1494 1495 1496
			cifsInode->cifsAttrs = dosattr;
		else
			dosattr = origattr; /* since not able to change them */
1497 1498
	}

1499
	/* rename the file */
1500 1501
	rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
				   cifs_sb->local_nls,
1502
				   cifs_remap(cifs_sb));
1503
	if (rc != 0) {
1504
		rc = -EBUSY;
1505 1506
		goto undo_setattr;
	}
1507

1508
	/* try to set DELETE_ON_CLOSE */
1509
	if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
1510
		rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522
					       current->tgid);
		/*
		 * some samba versions return -ENOENT when we try to set the
		 * file disposition here. Likely a samba bug, but work around
		 * it for now. This means that some cifsXXX files may hang
		 * around after they shouldn't.
		 *
		 * BB: remove this hack after more servers have the fix
		 */
		if (rc == -ENOENT)
			rc = 0;
		else if (rc != 0) {
1523
			rc = -EBUSY;
1524 1525
			goto undo_rename;
		}
1526
		set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
1527
	}
1528

1529
out_close:
1530
	CIFSSMBClose(xid, tcon, fid.netfid);
1531
out:
1532
	kfree(info_buf);
1533
	cifs_put_tlink(tlink);
1534
	return rc;
1535 1536 1537 1538 1539 1540 1541

	/*
	 * reset everything back to the original state. Don't bother
	 * dealing with errors here since we can't do anything about
	 * them anyway.
	 */
undo_rename:
1542
	CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
1543
				cifs_sb->local_nls, cifs_remap(cifs_sb));
1544 1545 1546
undo_setattr:
	if (dosattr != origattr) {
		info_buf->Attributes = cpu_to_le32(origattr);
1547
		if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
1548 1549 1550 1551 1552
					current->tgid))
			cifsInode->cifsAttrs = origattr;
	}

	goto out_close;
1553 1554
}

1555 1556 1557 1558 1559 1560 1561 1562 1563
/* copied from fs/nfs/dir.c with small changes */
static void
cifs_drop_nlink(struct inode *inode)
{
	spin_lock(&inode->i_lock);
	if (inode->i_nlink > 0)
		drop_nlink(inode);
	spin_unlock(&inode->i_lock);
}
1564 1565

/*
1566
 * If d_inode(dentry) is null (usually meaning the cached dentry
1567
 * is a negative dentry) then we would attempt a standard SMB delete, but
1568 1569
 * if that fails we can not attempt the fall back mechanisms on EACCES
 * but will return the EACCES to the caller. Note that the VFS does not call
1570 1571
 * unlink on negative dentries currently.
 */
1572
int cifs_unlink(struct inode *dir, struct dentry *dentry)
L
Linus Torvalds 已提交
1573 1574
{
	int rc = 0;
1575
	unsigned int xid;
L
Linus Torvalds 已提交
1576
	char *full_path = NULL;
1577
	struct inode *inode = d_inode(dentry);
1578
	struct cifsInodeInfo *cifs_inode;
1579 1580
	struct super_block *sb = dir->i_sb;
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1581
	struct tcon_link *tlink;
1582
	struct cifs_tcon *tcon;
1583
	struct TCP_Server_Info *server;
1584 1585
	struct iattr *attrs = NULL;
	__u32 dosattr = 0, origattr = 0;
L
Linus Torvalds 已提交
1586

1587
	cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
L
Linus Torvalds 已提交
1588

1589 1590 1591 1592
	tlink = cifs_sb_tlink(cifs_sb);
	if (IS_ERR(tlink))
		return PTR_ERR(tlink);
	tcon = tlink_tcon(tlink);
1593
	server = tcon->ses->server;
1594

1595
	xid = get_xid();
L
Linus Torvalds 已提交
1596

S
Steve French 已提交
1597 1598 1599 1600 1601
	if (tcon->nodelete) {
		rc = -EACCES;
		goto unlink_out;
	}

1602 1603 1604
	/* Unlink can be called from rename so we can not take the
	 * sb->s_vfs_rename_mutex here */
	full_path = build_path_from_dentry(dentry);
L
Linus Torvalds 已提交
1605
	if (full_path == NULL) {
1606
		rc = -ENOMEM;
1607
		goto unlink_out;
L
Linus Torvalds 已提交
1608
	}
1609

1610 1611
	if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
				le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1612
		rc = CIFSPOSIXDelFile(xid, tcon, full_path,
1613
			SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
1614
			cifs_remap(cifs_sb));
1615
		cifs_dbg(FYI, "posix del rc %d\n", rc);
1616 1617 1618
		if ((rc == 0) || (rc == -ENOENT))
			goto psx_del_no_retry;
	}
L
Linus Torvalds 已提交
1619

1620
retry_std_delete:
1621 1622 1623 1624 1625 1626
	if (!server->ops->unlink) {
		rc = -ENOSYS;
		goto psx_del_no_retry;
	}

	rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
1627

1628
psx_del_no_retry:
L
Linus Torvalds 已提交
1629
	if (!rc) {
1630
		if (inode)
1631
			cifs_drop_nlink(inode);
L
Linus Torvalds 已提交
1632
	} else if (rc == -ENOENT) {
1633
		d_drop(dentry);
1634
	} else if (rc == -EBUSY) {
1635 1636 1637 1638 1639 1640
		if (server->ops->rename_pending_delete) {
			rc = server->ops->rename_pending_delete(full_path,
								dentry, xid);
			if (rc == 0)
				cifs_drop_nlink(inode);
		}
1641
	} else if ((rc == -EACCES) && (dosattr == 0) && inode) {
1642 1643 1644 1645
		attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
		if (attrs == NULL) {
			rc = -ENOMEM;
			goto out_reval;
L
Linus Torvalds 已提交
1646
		}
1647 1648

		/* try to reset dos attributes */
1649 1650
		cifs_inode = CIFS_I(inode);
		origattr = cifs_inode->cifsAttrs;
1651 1652 1653
		if (origattr == 0)
			origattr |= ATTR_NORMAL;
		dosattr = origattr & ~ATTR_READONLY;
1654 1655 1656 1657 1658 1659 1660
		if (dosattr == 0)
			dosattr |= ATTR_NORMAL;
		dosattr |= ATTR_HIDDEN;

		rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
		if (rc != 0)
			goto out_reval;
1661 1662

		goto retry_std_delete;
L
Linus Torvalds 已提交
1663
	}
1664 1665 1666 1667 1668

	/* undo the setattr if we errored out and it's needed */
	if (rc != 0 && dosattr != 0)
		cifs_set_file_info(inode, attrs, xid, full_path, origattr);

1669
out_reval:
1670
	if (inode) {
1671 1672
		cifs_inode = CIFS_I(inode);
		cifs_inode->time = 0;	/* will force revalidate to get info
1673
					   when needed */
1674
		inode->i_ctime = current_time(inode);
1675
	}
1676
	dir->i_ctime = dir->i_mtime = current_time(dir);
1677
	cifs_inode = CIFS_I(dir);
1678
	CIFS_I(dir)->time = 0;	/* force revalidate of dir as well */
1679
unlink_out:
L
Linus Torvalds 已提交
1680
	kfree(full_path);
1681
	kfree(attrs);
1682
	free_xid(xid);
1683
	cifs_put_tlink(tlink);
L
Linus Torvalds 已提交
1684 1685 1686
	return rc;
}

P
Pavel Shilovsky 已提交
1687
static int
1688
cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
P
Pavel Shilovsky 已提交
1689 1690 1691 1692
		 const char *full_path, struct cifs_sb_info *cifs_sb,
		 struct cifs_tcon *tcon, const unsigned int xid)
{
	int rc = 0;
1693
	struct inode *inode = NULL;
P
Pavel Shilovsky 已提交
1694

1695 1696 1697
	if (tcon->posix_extensions)
		rc = smb311_posix_get_inode_info(&inode, full_path, parent->i_sb, xid);
	else if (tcon->unix_ext)
1698
		rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
P
Pavel Shilovsky 已提交
1699 1700
					      xid);
	else
1701 1702 1703
		rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
					 xid, NULL);

P
Pavel Shilovsky 已提交
1704 1705 1706 1707 1708
	if (rc)
		return rc;

	/*
	 * setting nlink not necessary except in cases where we failed to get it
1709 1710
	 * from the server or was set bogus. Also, since this is a brand new
	 * inode, no need to grab the i_lock before setting the i_nlink.
P
Pavel Shilovsky 已提交
1711
	 */
1712 1713
	if (inode->i_nlink < 2)
		set_nlink(inode, 2);
P
Pavel Shilovsky 已提交
1714 1715
	mode &= ~current_umask();
	/* must turn on setgid bit if parent dir has it */
1716
	if (parent->i_mode & S_ISGID)
P
Pavel Shilovsky 已提交
1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727
		mode |= S_ISGID;

	if (tcon->unix_ext) {
		struct cifs_unix_set_info_args args = {
			.mode	= mode,
			.ctime	= NO_CHANGE_64,
			.atime	= NO_CHANGE_64,
			.mtime	= NO_CHANGE_64,
			.device	= 0,
		};
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1728
			args.uid = current_fsuid();
1729
			if (parent->i_mode & S_ISGID)
1730
				args.gid = parent->i_gid;
P
Pavel Shilovsky 已提交
1731
			else
1732
				args.gid = current_fsgid();
P
Pavel Shilovsky 已提交
1733
		} else {
1734 1735
			args.uid = INVALID_UID; /* no change */
			args.gid = INVALID_GID; /* no change */
P
Pavel Shilovsky 已提交
1736 1737 1738
		}
		CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
				       cifs_sb->local_nls,
1739
				       cifs_remap(cifs_sb));
P
Pavel Shilovsky 已提交
1740
	} else {
1741
		struct TCP_Server_Info *server = tcon->ses->server;
P
Pavel Shilovsky 已提交
1742
		if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
1743
		    (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
1744
			server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
1745
						   tcon, xid);
1746 1747 1748 1749 1750 1751 1752 1753 1754
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
			inode->i_mode = (mode | S_IFDIR);

		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
			inode->i_uid = current_fsuid();
			if (inode->i_mode & S_ISGID)
				inode->i_gid = parent->i_gid;
			else
				inode->i_gid = current_fsgid();
P
Pavel Shilovsky 已提交
1755 1756
		}
	}
1757
	d_instantiate(dentry, inode);
P
Pavel Shilovsky 已提交
1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780
	return rc;
}

static int
cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
		 const char *full_path, struct cifs_sb_info *cifs_sb,
		 struct cifs_tcon *tcon, const unsigned int xid)
{
	int rc = 0;
	u32 oplock = 0;
	FILE_UNIX_BASIC_INFO *info = NULL;
	struct inode *newinode = NULL;
	struct cifs_fattr fattr;

	info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
	if (info == NULL) {
		rc = -ENOMEM;
		goto posix_mkdir_out;
	}

	mode &= ~current_umask();
	rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
			     NULL /* netfid */, info, &oplock, full_path,
1781
			     cifs_sb->local_nls, cifs_remap(cifs_sb));
P
Pavel Shilovsky 已提交
1782 1783 1784
	if (rc == -EOPNOTSUPP)
		goto posix_mkdir_out;
	else if (rc) {
1785
		cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
P
Pavel Shilovsky 已提交
1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806
		d_drop(dentry);
		goto posix_mkdir_out;
	}

	if (info->Type == cpu_to_le32(-1))
		/* no return info, go query for it */
		goto posix_mkdir_get_info;
	/*
	 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
	 * need to set uid/gid.
	 */

	cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
	cifs_fill_uniqueid(inode->i_sb, &fattr);
	newinode = cifs_iget(inode->i_sb, &fattr);
	if (!newinode)
		goto posix_mkdir_get_info;

	d_instantiate(dentry, newinode);

#ifdef CONFIG_CIFS_DEBUG2
A
Al Viro 已提交
1807 1808
	cifs_dbg(FYI, "instantiated dentry %p %pd to inode %p\n",
		 dentry, dentry, newinode);
P
Pavel Shilovsky 已提交
1809 1810

	if (newinode->i_nlink != 2)
1811 1812
		cifs_dbg(FYI, "unexpected number of links %d\n",
			 newinode->i_nlink);
P
Pavel Shilovsky 已提交
1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823
#endif

posix_mkdir_out:
	kfree(info);
	return rc;
posix_mkdir_get_info:
	rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
			      xid);
	goto posix_mkdir_out;
}

1824
int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
L
Linus Torvalds 已提交
1825
{
P
Pavel Shilovsky 已提交
1826
	int rc = 0;
1827
	unsigned int xid;
L
Linus Torvalds 已提交
1828
	struct cifs_sb_info *cifs_sb;
1829
	struct tcon_link *tlink;
1830
	struct cifs_tcon *tcon;
1831
	struct TCP_Server_Info *server;
P
Pavel Shilovsky 已提交
1832
	char *full_path;
L
Linus Torvalds 已提交
1833

1834
	cifs_dbg(FYI, "In cifs_mkdir, mode = %04ho inode = 0x%p\n",
1835
		 mode, inode);
L
Linus Torvalds 已提交
1836 1837

	cifs_sb = CIFS_SB(inode->i_sb);
1838 1839 1840
	tlink = cifs_sb_tlink(cifs_sb);
	if (IS_ERR(tlink))
		return PTR_ERR(tlink);
1841
	tcon = tlink_tcon(tlink);
1842

1843
	xid = get_xid();
L
Linus Torvalds 已提交
1844

1845
	full_path = build_path_from_dentry(direntry);
L
Linus Torvalds 已提交
1846
	if (full_path == NULL) {
1847
		rc = -ENOMEM;
1848
		goto mkdir_out;
L
Linus Torvalds 已提交
1849
	}
1850

1851 1852 1853 1854 1855 1856 1857 1858 1859
	server = tcon->ses->server;

	if ((server->ops->posix_mkdir) && (tcon->posix_extensions)) {
		rc = server->ops->posix_mkdir(xid, inode, mode, tcon, full_path,
					      cifs_sb);
		d_drop(direntry); /* for time being always refresh inode info */
		goto mkdir_out;
	}

1860 1861
	if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
				le64_to_cpu(tcon->fsUnixInfo.Capability))) {
P
Pavel Shilovsky 已提交
1862 1863 1864
		rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
				      tcon, xid);
		if (rc != -EOPNOTSUPP)
1865
			goto mkdir_out;
S
Steve French 已提交
1866
	}
P
Pavel Shilovsky 已提交
1867

1868 1869 1870 1871 1872
	if (!server->ops->mkdir) {
		rc = -ENOSYS;
		goto mkdir_out;
	}

L
Linus Torvalds 已提交
1873
	/* BB add setting the equivalent of mode via CreateX w/ACLs */
1874
	rc = server->ops->mkdir(xid, inode, mode, tcon, full_path, cifs_sb);
L
Linus Torvalds 已提交
1875
	if (rc) {
1876
		cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
L
Linus Torvalds 已提交
1877
		d_drop(direntry);
P
Pavel Shilovsky 已提交
1878
		goto mkdir_out;
L
Linus Torvalds 已提交
1879
	}
P
Pavel Shilovsky 已提交
1880

1881
	/* TODO: skip this for smb2/smb3 */
P
Pavel Shilovsky 已提交
1882 1883
	rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
			      xid);
S
Steve French 已提交
1884
mkdir_out:
1885 1886 1887 1888 1889
	/*
	 * Force revalidate to get parent dir info when needed since cached
	 * attributes are invalid now.
	 */
	CIFS_I(inode)->time = 0;
L
Linus Torvalds 已提交
1890
	kfree(full_path);
1891
	free_xid(xid);
1892
	cifs_put_tlink(tlink);
L
Linus Torvalds 已提交
1893 1894 1895 1896 1897 1898
	return rc;
}

int cifs_rmdir(struct inode *inode, struct dentry *direntry)
{
	int rc = 0;
1899
	unsigned int xid;
L
Linus Torvalds 已提交
1900
	struct cifs_sb_info *cifs_sb;
1901
	struct tcon_link *tlink;
1902 1903
	struct cifs_tcon *tcon;
	struct TCP_Server_Info *server;
L
Linus Torvalds 已提交
1904 1905 1906
	char *full_path = NULL;
	struct cifsInodeInfo *cifsInode;

1907
	cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
L
Linus Torvalds 已提交
1908

1909
	xid = get_xid();
L
Linus Torvalds 已提交
1910

1911
	full_path = build_path_from_dentry(direntry);
L
Linus Torvalds 已提交
1912
	if (full_path == NULL) {
1913
		rc = -ENOMEM;
1914
		goto rmdir_exit;
L
Linus Torvalds 已提交
1915 1916
	}

1917 1918 1919 1920 1921 1922
	cifs_sb = CIFS_SB(inode->i_sb);
	tlink = cifs_sb_tlink(cifs_sb);
	if (IS_ERR(tlink)) {
		rc = PTR_ERR(tlink);
		goto rmdir_exit;
	}
1923 1924 1925 1926 1927 1928 1929 1930
	tcon = tlink_tcon(tlink);
	server = tcon->ses->server;

	if (!server->ops->rmdir) {
		rc = -ENOSYS;
		cifs_put_tlink(tlink);
		goto rmdir_exit;
	}
1931

S
Steve French 已提交
1932 1933 1934 1935 1936 1937
	if (tcon->nodelete) {
		rc = -EACCES;
		cifs_put_tlink(tlink);
		goto rmdir_exit;
	}

1938
	rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
1939
	cifs_put_tlink(tlink);
L
Linus Torvalds 已提交
1940 1941

	if (!rc) {
1942 1943 1944 1945
		spin_lock(&d_inode(direntry)->i_lock);
		i_size_write(d_inode(direntry), 0);
		clear_nlink(d_inode(direntry));
		spin_unlock(&d_inode(direntry)->i_lock);
L
Linus Torvalds 已提交
1946 1947
	}

1948
	cifsInode = CIFS_I(d_inode(direntry));
1949 1950
	/* force revalidate to go get info when needed */
	cifsInode->time = 0;
1951 1952

	cifsInode = CIFS_I(inode);
1953 1954 1955 1956 1957
	/*
	 * Force revalidate to get parent dir info when needed since cached
	 * attributes are invalid now.
	 */
	cifsInode->time = 0;
1958

1959
	d_inode(direntry)->i_ctime = inode->i_ctime = inode->i_mtime =
1960
		current_time(inode);
L
Linus Torvalds 已提交
1961

1962
rmdir_exit:
L
Linus Torvalds 已提交
1963
	kfree(full_path);
1964
	free_xid(xid);
L
Linus Torvalds 已提交
1965 1966 1967
	return rc;
}

1968
static int
1969 1970 1971
cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
	       const char *from_path, struct dentry *to_dentry,
	       const char *to_path)
1972 1973
{
	struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
1974
	struct tcon_link *tlink;
1975 1976
	struct cifs_tcon *tcon;
	struct TCP_Server_Info *server;
1977 1978
	struct cifs_fid fid;
	struct cifs_open_parms oparms;
1979 1980
	int oplock, rc;

1981 1982 1983
	tlink = cifs_sb_tlink(cifs_sb);
	if (IS_ERR(tlink))
		return PTR_ERR(tlink);
1984 1985 1986 1987 1988
	tcon = tlink_tcon(tlink);
	server = tcon->ses->server;

	if (!server->ops->rename)
		return -ENOSYS;
1989

1990
	/* try path-based rename first */
1991
	rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
1992 1993

	/*
1994 1995
	 * Don't bother with rename by filehandle unless file is busy and
	 * source. Note that cross directory moves do not work with
1996 1997
	 * rename by filehandle to various Windows servers.
	 */
1998
	if (rc == 0 || rc != -EBUSY)
1999
		goto do_rename_exit;
2000

2001 2002 2003 2004
	/* Don't fall back to using SMB on SMB 2+ mount */
	if (server->vals->protocol_id != 0)
		goto do_rename_exit;

2005 2006
	/* open-file renames don't work across directories */
	if (to_dentry->d_parent != from_dentry->d_parent)
2007
		goto do_rename_exit;
2008

2009 2010
	oparms.tcon = tcon;
	oparms.cifs_sb = cifs_sb;
2011
	/* open the file to be renamed -- we need DELETE perms */
2012
	oparms.desired_access = DELETE;
2013
	oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
2014 2015 2016 2017 2018 2019
	oparms.disposition = FILE_OPEN;
	oparms.path = from_path;
	oparms.fid = &fid;
	oparms.reconnect = false;

	rc = CIFS_open(xid, &oparms, &oplock, NULL);
2020
	if (rc == 0) {
2021
		rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
2022
				(const char *) to_dentry->d_name.name,
2023
				cifs_sb->local_nls, cifs_remap(cifs_sb));
2024
		CIFSSMBClose(xid, tcon, fid.netfid);
2025
	}
2026
do_rename_exit:
S
Steve French 已提交
2027 2028
	if (rc == 0)
		d_move(from_dentry, to_dentry);
2029
	cifs_put_tlink(tlink);
2030 2031 2032
	return rc;
}

2033
int
M
Miklos Szeredi 已提交
2034 2035 2036
cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
	     struct inode *target_dir, struct dentry *target_dentry,
	     unsigned int flags)
L
Linus Torvalds 已提交
2037
{
2038 2039
	char *from_name = NULL;
	char *to_name = NULL;
2040
	struct cifs_sb_info *cifs_sb;
2041
	struct tcon_link *tlink;
2042
	struct cifs_tcon *tcon;
2043 2044
	FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
	FILE_UNIX_BASIC_INFO *info_buf_target;
2045 2046
	unsigned int xid;
	int rc, tmprc;
L
Linus Torvalds 已提交
2047

M
Miklos Szeredi 已提交
2048 2049 2050
	if (flags & ~RENAME_NOREPLACE)
		return -EINVAL;

2051
	cifs_sb = CIFS_SB(source_dir->i_sb);
2052 2053 2054 2055
	tlink = cifs_sb_tlink(cifs_sb);
	if (IS_ERR(tlink))
		return PTR_ERR(tlink);
	tcon = tlink_tcon(tlink);
L
Linus Torvalds 已提交
2056

2057
	xid = get_xid();
2058 2059 2060 2061 2062

	/*
	 * we already have the rename sem so we do not need to
	 * grab it again here to protect the path integrity
	 */
2063 2064
	from_name = build_path_from_dentry(source_dentry);
	if (from_name == NULL) {
2065 2066 2067 2068
		rc = -ENOMEM;
		goto cifs_rename_exit;
	}

2069 2070
	to_name = build_path_from_dentry(target_dentry);
	if (to_name == NULL) {
L
Linus Torvalds 已提交
2071 2072 2073 2074
		rc = -ENOMEM;
		goto cifs_rename_exit;
	}

2075 2076
	rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
			    to_name);
2077

M
Miklos Szeredi 已提交
2078 2079 2080 2081 2082 2083
	/*
	 * No-replace is the natural behavior for CIFS, so skip unlink hacks.
	 */
	if (flags & RENAME_NOREPLACE)
		goto cifs_rename_exit;

2084 2085
	if (rc == -EEXIST && tcon->unix_ext) {
		/*
2086 2087
		 * Are src and dst hardlinks of same inode? We can only tell
		 * with unix extensions enabled.
2088 2089
		 */
		info_buf_source =
2090
			kmalloc_array(2, sizeof(FILE_UNIX_BASIC_INFO),
2091 2092 2093 2094 2095 2096 2097
					GFP_KERNEL);
		if (info_buf_source == NULL) {
			rc = -ENOMEM;
			goto cifs_rename_exit;
		}

		info_buf_target = info_buf_source + 1;
2098 2099 2100
		tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
					     info_buf_source,
					     cifs_sb->local_nls,
2101
					     cifs_remap(cifs_sb));
2102
		if (tmprc != 0)
2103
			goto unlink_target;
2104

2105 2106 2107
		tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
					     info_buf_target,
					     cifs_sb->local_nls,
2108
					     cifs_remap(cifs_sb));
2109

2110
		if (tmprc == 0 && (info_buf_source->UniqueId ==
2111
				   info_buf_target->UniqueId)) {
2112
			/* same file, POSIX says that this is a noop */
2113
			rc = 0;
2114
			goto cifs_rename_exit;
2115
		}
2116 2117 2118 2119 2120
	}
	/*
	 * else ... BB we could add the same check for Windows by
	 * checking the UniqueId via FILE_INTERNAL_INFO
	 */
2121

2122
unlink_target:
2123
	/* Try unlinking the target dentry if it's not negative */
2124
	if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
2125 2126 2127 2128
		if (d_is_dir(target_dentry))
			tmprc = cifs_rmdir(target_dir, target_dentry);
		else
			tmprc = cifs_unlink(target_dir, target_dentry);
2129 2130
		if (tmprc)
			goto cifs_rename_exit;
2131 2132
		rc = cifs_do_rename(xid, source_dentry, from_name,
				    target_dentry, to_name);
L
Linus Torvalds 已提交
2133 2134
	}

2135 2136 2137 2138
	/* force revalidate to go get info when needed */
	CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;

	source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
2139
		target_dir->i_mtime = current_time(source_dir);
2140

L
Linus Torvalds 已提交
2141
cifs_rename_exit:
2142
	kfree(info_buf_source);
2143 2144
	kfree(from_name);
	kfree(to_name);
2145
	free_xid(xid);
2146
	cifs_put_tlink(tlink);
L
Linus Torvalds 已提交
2147 2148 2149
	return rc;
}

2150 2151
static bool
cifs_inode_needs_reval(struct inode *inode)
L
Linus Torvalds 已提交
2152
{
2153
	struct cifsInodeInfo *cifs_i = CIFS_I(inode);
2154
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
L
Linus Torvalds 已提交
2155

2156 2157 2158
	if (cifs_i->time == 0)
		return true;

2159
	if (CIFS_CACHE_READ(cifs_i))
2160
		return false;
L
Linus Torvalds 已提交
2161

2162 2163
	if (!lookupCacheEnabled)
		return true;
L
Linus Torvalds 已提交
2164

2165 2166 2167
	if (!cifs_sb->actimeo)
		return true;

2168 2169
	if (!time_in_range(jiffies, cifs_i->time,
				cifs_i->time + cifs_sb->actimeo))
2170 2171
		return true;

2172
	/* hardlinked files w/ noserverino get "special" treatment */
2173
	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
2174 2175 2176
	    S_ISREG(inode->i_mode) && inode->i_nlink != 1)
		return true;

2177 2178 2179
	return false;
}

2180 2181 2182
/*
 * Zap the cache. Called when invalid_mapping flag is set.
 */
2183
int
2184 2185
cifs_invalidate_mapping(struct inode *inode)
{
2186
	int rc = 0;
2187 2188

	if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
2189
		rc = invalidate_inode_pages2(inode->i_mapping);
2190
		if (rc)
J
Joe Perches 已提交
2191
			cifs_dbg(VFS, "%s: Could not invalidate inode %p\n",
2192
				 __func__, inode);
2193
	}
2194

2195
	cifs_fscache_reset_inode_cookie(inode);
2196
	return rc;
2197 2198
}

2199 2200 2201 2202 2203
/**
 * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
 * @word: long word containing the bit lock
 */
static int
2204
cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
2205 2206
{
	freezable_schedule_unsafe();
2207 2208
	if (signal_pending_state(mode, current))
		return -ERESTARTSYS;
2209 2210 2211
	return 0;
}

2212 2213 2214
int
cifs_revalidate_mapping(struct inode *inode)
{
2215 2216 2217
	int rc;
	unsigned long *flags = &CIFS_I(inode)->flags;

S
Steve French 已提交
2218 2219 2220 2221
	/* swapfiles are not supposed to be shared */
	if (IS_SWAPFILE(inode))
		return 0;

2222 2223
	rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
				     TASK_KILLABLE);
2224 2225 2226 2227 2228 2229 2230 2231 2232 2233
	if (rc)
		return rc;

	if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
		rc = cifs_invalidate_mapping(inode);
		if (rc)
			set_bit(CIFS_INO_INVALID_MAPPING, flags);
	}

	clear_bit_unlock(CIFS_INO_LOCK, flags);
2234
	smp_mb__after_atomic();
2235 2236 2237 2238 2239 2240 2241 2242 2243 2244
	wake_up_bit(flags, CIFS_INO_LOCK);

	return rc;
}

int
cifs_zap_mapping(struct inode *inode)
{
	set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
	return cifs_revalidate_mapping(inode);
2245 2246
}

2247
int cifs_revalidate_file_attr(struct file *filp)
J
Jeff Layton 已提交
2248 2249
{
	int rc = 0;
A
Al Viro 已提交
2250
	struct inode *inode = file_inode(filp);
2251
	struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
J
Jeff Layton 已提交
2252 2253

	if (!cifs_inode_needs_reval(inode))
2254
		return rc;
J
Jeff Layton 已提交
2255

2256
	if (tlink_tcon(cfile->tlink)->unix_ext)
J
Jeff Layton 已提交
2257 2258 2259 2260 2261 2262 2263
		rc = cifs_get_file_info_unix(filp);
	else
		rc = cifs_get_file_info(filp);

	return rc;
}

2264
int cifs_revalidate_dentry_attr(struct dentry *dentry)
2265
{
2266
	unsigned int xid;
2267
	int rc = 0;
2268
	struct inode *inode = d_inode(dentry);
2269
	struct super_block *sb = dentry->d_sb;
2270
	char *full_path = NULL;
2271
	int count = 0;
2272 2273 2274

	if (inode == NULL)
		return -ENOENT;
L
Linus Torvalds 已提交
2275

2276
	if (!cifs_inode_needs_reval(inode))
2277 2278
		return rc;

2279
	xid = get_xid();
L
Linus Torvalds 已提交
2280 2281 2282

	/* can not safely grab the rename sem here if rename calls revalidate
	   since that would deadlock */
2283
	full_path = build_path_from_dentry(dentry);
L
Linus Torvalds 已提交
2284
	if (full_path == NULL) {
2285
		rc = -ENOMEM;
2286
		goto out;
L
Linus Torvalds 已提交
2287 2288
	}

2289 2290
	cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
		 full_path, inode, inode->i_count.counter,
M
Miklos Szeredi 已提交
2291
		 dentry, cifs_get_time(dentry), jiffies);
L
Linus Torvalds 已提交
2292

2293
again:
2294 2295 2296
	if (cifs_sb_master_tcon(CIFS_SB(sb))->posix_extensions)
		rc = smb311_posix_get_inode_info(&inode, full_path, sb, xid);
	else if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
2297 2298 2299 2300
		rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
	else
		rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
					 xid, NULL);
2301 2302
	if (rc == -EAGAIN && count++ < 10)
		goto again;
2303
out:
L
Linus Torvalds 已提交
2304
	kfree(full_path);
2305
	free_xid(xid);
2306

L
Linus Torvalds 已提交
2307 2308 2309
	return rc;
}

2310 2311 2312
int cifs_revalidate_file(struct file *filp)
{
	int rc;
A
Al Viro 已提交
2313
	struct inode *inode = file_inode(filp);
2314 2315 2316 2317 2318

	rc = cifs_revalidate_file_attr(filp);
	if (rc)
		return rc;

2319
	return cifs_revalidate_mapping(inode);
2320 2321 2322 2323 2324 2325
}

/* revalidate a dentry's inode attributes */
int cifs_revalidate_dentry(struct dentry *dentry)
{
	int rc;
2326
	struct inode *inode = d_inode(dentry);
2327 2328 2329 2330 2331

	rc = cifs_revalidate_dentry_attr(dentry);
	if (rc)
		return rc;

2332
	return cifs_revalidate_mapping(inode);
2333 2334
}

2335 2336
int cifs_getattr(const struct path *path, struct kstat *stat,
		 u32 request_mask, unsigned int flags)
L
Linus Torvalds 已提交
2337
{
2338
	struct dentry *dentry = path->dentry;
2339
	struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
2340
	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
2341
	struct inode *inode = d_inode(dentry);
2342
	int rc;
2343

2344 2345 2346 2347
	/*
	 * We need to be sure that all dirty pages are written and the server
	 * has actual ctime, mtime and file length.
	 */
2348 2349 2350
	if ((request_mask & (STATX_CTIME | STATX_MTIME | STATX_SIZE)) &&
	    !CIFS_CACHE_READ(CIFS_I(inode)) &&
	    inode->i_mapping && inode->i_mapping->nrpages != 0) {
2351
		rc = filemap_fdatawait(inode->i_mapping);
2352 2353 2354 2355
		if (rc) {
			mapping_set_error(inode->i_mapping, rc);
			return rc;
		}
2356
	}
2357

2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371
	if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_FORCE_SYNC)
		CIFS_I(inode)->time = 0; /* force revalidate */

	/*
	 * If the caller doesn't require syncing, only sync if
	 * necessary (e.g. due to earlier truncate or setattr
	 * invalidating the cached metadata)
	 */
	if (((flags & AT_STATX_SYNC_TYPE) != AT_STATX_DONT_SYNC) ||
	    (CIFS_I(inode)->time == 0)) {
		rc = cifs_revalidate_dentry_attr(dentry);
		if (rc)
			return rc;
	}
2372 2373

	generic_fillattr(inode, stat);
2374
	stat->blksize = cifs_sb->bsize;
2375 2376
	stat->ino = CIFS_I(inode)->uniqueid;

S
Steve French 已提交
2377 2378 2379
	/* old CIFS Unix Extensions doesn't return create time */
	if (CIFS_I(inode)->createtime) {
		stat->result_mask |= STATX_BTIME;
A
Arnd Bergmann 已提交
2380 2381
		stat->btime =
		      cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime));
S
Steve French 已提交
2382 2383 2384 2385 2386 2387 2388 2389
	}

	stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED);
	if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_COMPRESSED)
		stat->attributes |= STATX_ATTR_COMPRESSED;
	if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_ENCRYPTED)
		stat->attributes |= STATX_ATTR_ENCRYPTED;

2390
	/*
2391 2392 2393
	 * If on a multiuser mount without unix extensions or cifsacl being
	 * enabled, and the admin hasn't overridden them, set the ownership
	 * to the fsuid/fsgid of the current process.
2394 2395
	 */
	if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
2396
	    !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
2397 2398 2399 2400 2401
	    !tcon->unix_ext) {
		if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
			stat->uid = current_fsuid();
		if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
			stat->gid = current_fsgid();
S
Steve French 已提交
2402
	}
2403
	return 0;
L
Linus Torvalds 已提交
2404 2405
}

R
Ronnie Sahlberg 已提交
2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442
int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start,
		u64 len)
{
	struct cifsInodeInfo *cifs_i = CIFS_I(inode);
	struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_i->vfs_inode.i_sb);
	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
	struct TCP_Server_Info *server = tcon->ses->server;
	struct cifsFileInfo *cfile;
	int rc;

	/*
	 * We need to be sure that all dirty pages are written as they
	 * might fill holes on the server.
	 */
	if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
	    inode->i_mapping->nrpages != 0) {
		rc = filemap_fdatawait(inode->i_mapping);
		if (rc) {
			mapping_set_error(inode->i_mapping, rc);
			return rc;
		}
	}

	cfile = find_readable_file(cifs_i, false);
	if (cfile == NULL)
		return -EINVAL;

	if (server->ops->fiemap) {
		rc = server->ops->fiemap(tcon, cfile, fei, start, len);
		cifsFileInfo_put(cfile);
		return rc;
	}

	cifsFileInfo_put(cfile);
	return -ENOTSUPP;
}

2443
int cifs_truncate_page(struct address_space *mapping, loff_t from)
L
Linus Torvalds 已提交
2444
{
2445 2446
	pgoff_t index = from >> PAGE_SHIFT;
	unsigned offset = from & (PAGE_SIZE - 1);
L
Linus Torvalds 已提交
2447 2448 2449 2450 2451 2452 2453
	struct page *page;
	int rc = 0;

	page = grab_cache_page(mapping, index);
	if (!page)
		return -ENOMEM;

2454
	zero_user_segment(page, offset, PAGE_SIZE);
L
Linus Torvalds 已提交
2455
	unlock_page(page);
2456
	put_page(page);
L
Linus Torvalds 已提交
2457 2458 2459
	return rc;
}

2460
void cifs_setsize(struct inode *inode, loff_t offset)
2461
{
2462 2463
	struct cifsInodeInfo *cifs_i = CIFS_I(inode);

2464
	spin_lock(&inode->i_lock);
2465
	i_size_write(inode, offset);
2466
	spin_unlock(&inode->i_lock);
C
Christoph Hellwig 已提交
2467

2468 2469
	/* Cached inode must be refreshed on truncate */
	cifs_i->time = 0;
2470
	truncate_pagecache(inode, offset);
2471 2472
}

2473 2474
static int
cifs_set_file_size(struct inode *inode, struct iattr *attrs,
2475
		   unsigned int xid, char *full_path)
2476 2477 2478 2479 2480
{
	int rc;
	struct cifsFileInfo *open_file;
	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
2481
	struct tcon_link *tlink = NULL;
2482 2483
	struct cifs_tcon *tcon = NULL;
	struct TCP_Server_Info *server;
2484 2485 2486 2487 2488 2489 2490 2491 2492 2493

	/*
	 * To avoid spurious oplock breaks from server, in the case of
	 * inodes that we already have open, avoid doing path based
	 * setting of file size if we can do it by handle.
	 * This keeps our caching token (oplock) and avoids timeouts
	 * when the local oplock break takes longer to flush
	 * writebehind data than the SMB timeout for the SetPathInfo
	 * request would allow
	 */
2494
	open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
2495
	if (open_file) {
2496 2497 2498 2499 2500 2501 2502
		tcon = tlink_tcon(open_file->tlink);
		server = tcon->ses->server;
		if (server->ops->set_file_size)
			rc = server->ops->set_file_size(xid, tcon, open_file,
							attrs->ia_size, false);
		else
			rc = -ENOSYS;
2503
		cifsFileInfo_put(open_file);
2504
		cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
2505 2506 2507
	} else
		rc = -EINVAL;

2508 2509 2510 2511 2512 2513 2514 2515 2516 2517
	if (!rc)
		goto set_size_out;

	if (tcon == NULL) {
		tlink = cifs_sb_tlink(cifs_sb);
		if (IS_ERR(tlink))
			return PTR_ERR(tlink);
		tcon = tlink_tcon(tlink);
		server = tcon->ses->server;
	}
2518

2519 2520 2521 2522 2523 2524 2525 2526 2527 2528
	/*
	 * Set file size by pathname rather than by handle either because no
	 * valid, writeable file handle for it was found or because there was
	 * an error setting it by handle.
	 */
	if (server->ops->set_path_size)
		rc = server->ops->set_path_size(xid, tcon, full_path,
						attrs->ia_size, cifs_sb, false);
	else
		rc = -ENOSYS;
2529
	cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
2530 2531 2532

	if (tlink)
		cifs_put_tlink(tlink);
2533

2534
set_size_out:
2535
	if (rc == 0) {
2536
		cifsInode->server_eof = attrs->ia_size;
C
Christoph Hellwig 已提交
2537
		cifs_setsize(inode, attrs->ia_size);
2538 2539 2540 2541 2542 2543
		cifs_truncate_page(inode->i_mapping, inode->i_size);
	}

	return rc;
}

2544 2545 2546 2547
static int
cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
{
	int rc;
2548
	unsigned int xid;
2549
	char *full_path = NULL;
2550
	struct inode *inode = d_inode(direntry);
2551 2552
	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
2553
	struct tcon_link *tlink;
2554
	struct cifs_tcon *pTcon;
2555
	struct cifs_unix_set_info_args *args = NULL;
2556
	struct cifsFileInfo *open_file;
2557

A
Al Viro 已提交
2558 2559
	cifs_dbg(FYI, "setattr_unix on file %pd attrs->ia_valid=0x%x\n",
		 direntry, attrs->ia_valid);
2560

2561
	xid = get_xid();
2562

2563 2564 2565
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
		attrs->ia_valid |= ATTR_FORCE;

2566
	rc = setattr_prepare(direntry, attrs);
2567 2568
	if (rc < 0)
		goto out;
2569 2570 2571 2572 2573 2574 2575

	full_path = build_path_from_dentry(direntry);
	if (full_path == NULL) {
		rc = -ENOMEM;
		goto out;
	}

J
Jeff Layton 已提交
2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587
	/*
	 * Attempt to flush data before changing attributes. We need to do
	 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
	 * ownership or mode then we may also need to do this. Here, we take
	 * the safe way out and just do the flush on all setattr requests. If
	 * the flush returns error, store it to report later and continue.
	 *
	 * BB: This should be smarter. Why bother flushing pages that
	 * will be truncated anyway? Also, should we error out here if
	 * the flush returns error?
	 */
	rc = filemap_write_and_wait(inode->i_mapping);
2588 2589 2590 2591 2592
	if (is_interrupt_error(rc)) {
		rc = -ERESTARTSYS;
		goto out;
	}

2593 2594
	mapping_set_error(inode->i_mapping, rc);
	rc = 0;
2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620

	if (attrs->ia_valid & ATTR_SIZE) {
		rc = cifs_set_file_size(inode, attrs, xid, full_path);
		if (rc != 0)
			goto out;
	}

	/* skip mode change if it's just for clearing setuid/setgid */
	if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
		attrs->ia_valid &= ~ATTR_MODE;

	args = kmalloc(sizeof(*args), GFP_KERNEL);
	if (args == NULL) {
		rc = -ENOMEM;
		goto out;
	}

	/* set up the struct */
	if (attrs->ia_valid & ATTR_MODE)
		args->mode = attrs->ia_mode;
	else
		args->mode = NO_CHANGE_64;

	if (attrs->ia_valid & ATTR_UID)
		args->uid = attrs->ia_uid;
	else
2621
		args->uid = INVALID_UID; /* no change */
2622 2623 2624 2625

	if (attrs->ia_valid & ATTR_GID)
		args->gid = attrs->ia_gid;
	else
2626
		args->gid = INVALID_GID; /* no change */
2627 2628

	if (attrs->ia_valid & ATTR_ATIME)
A
Arnd Bergmann 已提交
2629
		args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
2630 2631 2632 2633
	else
		args->atime = NO_CHANGE_64;

	if (attrs->ia_valid & ATTR_MTIME)
A
Arnd Bergmann 已提交
2634
		args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
2635 2636 2637 2638
	else
		args->mtime = NO_CHANGE_64;

	if (attrs->ia_valid & ATTR_CTIME)
A
Arnd Bergmann 已提交
2639
		args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
2640 2641 2642 2643
	else
		args->ctime = NO_CHANGE_64;

	args->device = 0;
2644
	open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
2645
	if (open_file) {
2646
		u16 nfid = open_file->fid.netfid;
2647
		u32 npid = open_file->pid;
2648
		pTcon = tlink_tcon(open_file->tlink);
2649
		rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
2650
		cifsFileInfo_put(open_file);
2651
	} else {
2652 2653 2654 2655 2656 2657
		tlink = cifs_sb_tlink(cifs_sb);
		if (IS_ERR(tlink)) {
			rc = PTR_ERR(tlink);
			goto out;
		}
		pTcon = tlink_tcon(tlink);
2658
		rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
2659
				    cifs_sb->local_nls,
2660
				    cifs_remap(cifs_sb));
2661
		cifs_put_tlink(tlink);
2662
	}
2663

C
Christoph Hellwig 已提交
2664 2665
	if (rc)
		goto out;
2666

C
Christoph Hellwig 已提交
2667
	if ((attrs->ia_valid & ATTR_SIZE) &&
C
Christoph Hellwig 已提交
2668 2669
	    attrs->ia_size != i_size_read(inode))
		truncate_setsize(inode, attrs->ia_size);
C
Christoph Hellwig 已提交
2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681

	setattr_copy(inode, attrs);
	mark_inode_dirty(inode);

	/* force revalidate when any of these times are set since some
	   of the fs types (eg ext3, fat) do not have fine enough
	   time granularity to match protocol, and we do not have a
	   a way (yet) to query the server fs's time granularity (and
	   whether it rounds times down).
	*/
	if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
		cifsInode->time = 0;
2682 2683 2684
out:
	kfree(args);
	kfree(full_path);
2685
	free_xid(xid);
2686 2687 2688
	return rc;
}

2689 2690
static int
cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
L
Linus Torvalds 已提交
2691
{
2692
	unsigned int xid;
2693 2694
	kuid_t uid = INVALID_UID;
	kgid_t gid = INVALID_GID;
2695
	struct inode *inode = d_inode(direntry);
2696 2697
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2698 2699
	struct cifsFileInfo *wfile;
	struct cifs_tcon *tcon;
L
Linus Torvalds 已提交
2700 2701
	char *full_path = NULL;
	int rc = -EACCES;
2702
	__u32 dosattr = 0;
2703
	__u64 mode = NO_CHANGE_64;
2704

2705
	xid = get_xid();
L
Linus Torvalds 已提交
2706

2707
	cifs_dbg(FYI, "setattr on file %pd attrs->ia_valid 0x%x\n",
A
Al Viro 已提交
2708
		 direntry, attrs->ia_valid);
2709

2710 2711 2712
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
		attrs->ia_valid |= ATTR_FORCE;

2713
	rc = setattr_prepare(direntry, attrs);
2714
	if (rc < 0) {
2715
		free_xid(xid);
2716
		return rc;
2717
	}
2718

2719
	full_path = build_path_from_dentry(direntry);
L
Linus Torvalds 已提交
2720
	if (full_path == NULL) {
2721
		rc = -ENOMEM;
2722
		free_xid(xid);
2723
		return rc;
L
Linus Torvalds 已提交
2724 2725
	}

J
Jeff Layton 已提交
2726 2727
	/*
	 * Attempt to flush data before changing attributes. We need to do
2728 2729
	 * this for ATTR_SIZE and ATTR_MTIME.  If the flush of the data
	 * returns error, store it to report later and continue.
J
Jeff Layton 已提交
2730 2731 2732
	 *
	 * BB: This should be smarter. Why bother flushing pages that
	 * will be truncated anyway? Also, should we error out here if
2733
	 * the flush returns error? Do we need to check for ATTR_MTIME_SET flag?
J
Jeff Layton 已提交
2734
	 */
2735 2736 2737 2738 2739 2740 2741
	if (attrs->ia_valid & (ATTR_MTIME | ATTR_SIZE | ATTR_CTIME)) {
		rc = filemap_write_and_wait(inode->i_mapping);
		if (is_interrupt_error(rc)) {
			rc = -ERESTARTSYS;
			goto cifs_setattr_exit;
		}
		mapping_set_error(inode->i_mapping, rc);
2742 2743
	}

2744
	rc = 0;
2745

2746 2747
	if ((attrs->ia_valid & ATTR_MTIME) &&
	    !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
2748
		rc = cifs_get_writable_file(cifsInode, FIND_WR_ANY, &wfile);
2749 2750 2751 2752 2753
		if (!rc) {
			tcon = tlink_tcon(wfile->tlink);
			rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid);
			cifsFileInfo_put(wfile);
			if (rc)
C
Chuhong Yuan 已提交
2754
				goto cifs_setattr_exit;
2755
		} else if (rc != -EBADF)
C
Chuhong Yuan 已提交
2756
			goto cifs_setattr_exit;
2757 2758 2759 2760
		else
			rc = 0;
	}

2761
	if (attrs->ia_valid & ATTR_SIZE) {
2762 2763
		rc = cifs_set_file_size(inode, attrs, xid, full_path);
		if (rc != 0)
2764
			goto cifs_setattr_exit;
L
Linus Torvalds 已提交
2765
	}
2766

2767 2768 2769 2770 2771 2772
	if (attrs->ia_valid & ATTR_UID)
		uid = attrs->ia_uid;

	if (attrs->ia_valid & ATTR_GID)
		gid = attrs->ia_gid;

2773 2774
	if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
	    (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
2775
		if (uid_valid(uid) || gid_valid(gid)) {
2776 2777 2778
			rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
							uid, gid);
			if (rc) {
2779 2780
				cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
					 __func__, rc);
2781 2782 2783 2784
				goto cifs_setattr_exit;
			}
		}
	} else
2785
	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
2786
		attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
L
Linus Torvalds 已提交
2787

2788 2789 2790 2791
	/* skip mode change if it's just for clearing setuid/setgid */
	if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
		attrs->ia_valid &= ~ATTR_MODE;

L
Linus Torvalds 已提交
2792 2793
	if (attrs->ia_valid & ATTR_MODE) {
		mode = attrs->ia_mode;
2794
		rc = 0;
2795 2796
		if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
		    (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
2797
			rc = id_mode_to_cifs_acl(inode, full_path, mode,
2798
						INVALID_UID, INVALID_GID);
2799
			if (rc) {
2800 2801
				cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
					 __func__, rc);
2802 2803 2804
				goto cifs_setattr_exit;
			}
		} else
2805 2806
		if (((mode & S_IWUGO) == 0) &&
		    (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
2807 2808 2809

			dosattr = cifsInode->cifsAttrs | ATTR_READONLY;

2810 2811 2812 2813 2814
			/* fix up mode if we're not using dynperm */
			if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
				attrs->ia_mode = inode->i_mode & ~S_IWUGO;
		} else if ((mode & S_IWUGO) &&
			   (cifsInode->cifsAttrs & ATTR_READONLY)) {
2815 2816 2817 2818 2819

			dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
			/* Attributes of 0 are ignored */
			if (dosattr == 0)
				dosattr |= ATTR_NORMAL;
2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833

			/* reset local inode permissions to normal */
			if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
				attrs->ia_mode &= ~(S_IALLUGO);
				if (S_ISDIR(inode->i_mode))
					attrs->ia_mode |=
						cifs_sb->mnt_dir_mode;
				else
					attrs->ia_mode |=
						cifs_sb->mnt_file_mode;
			}
		} else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
			/* ignore mode change - ATTR_READONLY hasn't changed */
			attrs->ia_valid &= ~ATTR_MODE;
L
Linus Torvalds 已提交
2834 2835 2836
		}
	}

2837 2838 2839 2840
	if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
	    ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
		rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
		/* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
L
Linus Torvalds 已提交
2841

2842 2843 2844 2845 2846
		/* Even if error on time set, no sense failing the call if
		the server would set the time to a reasonable value anyway,
		and this check ensures that we are not being called from
		sys_utimes in which case we ought to fail the call back to
		the user when the server rejects the call */
S
Steve French 已提交
2847
		if ((rc) && (attrs->ia_valid &
2848
				(ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
2849
			rc = 0;
L
Linus Torvalds 已提交
2850 2851 2852 2853
	}

	/* do not need local check to inode_check_ok since the server does
	   that */
C
Christoph Hellwig 已提交
2854 2855 2856 2857
	if (rc)
		goto cifs_setattr_exit;

	if ((attrs->ia_valid & ATTR_SIZE) &&
C
Christoph Hellwig 已提交
2858 2859
	    attrs->ia_size != i_size_read(inode))
		truncate_setsize(inode, attrs->ia_size);
C
Christoph Hellwig 已提交
2860 2861 2862 2863

	setattr_copy(inode, attrs);
	mark_inode_dirty(inode);

2864
cifs_setattr_exit:
L
Linus Torvalds 已提交
2865
	kfree(full_path);
2866
	free_xid(xid);
L
Linus Torvalds 已提交
2867 2868 2869
	return rc;
}

2870 2871 2872
int
cifs_setattr(struct dentry *direntry, struct iattr *attrs)
{
2873
	struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
2874
	struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
2875 2876 2877 2878 2879 2880 2881 2882 2883

	if (pTcon->unix_ext)
		return cifs_setattr_unix(direntry, attrs);

	return cifs_setattr_nounix(direntry, attrs);

	/* BB: add cifs_setattr_legacy for really old servers */
}

2884
#if 0
L
Linus Torvalds 已提交
2885 2886
void cifs_delete_inode(struct inode *inode)
{
2887
	cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
L
Linus Torvalds 已提交
2888 2889 2890
	/* may have to add back in if and when safe distributed caching of
	   directories added e.g. via FindNotify */
}
2891
#endif