Blame view

fs/cifs/inode.c 78.4 KB
929be906f   Steve French   cifs: use SPDX-Li...
1
  // SPDX-License-Identifier: LGPL-2.1
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
   *
f19159dc5   Steve French   [CIFS] Cleanup va...
4
   *   Copyright (C) International Business Machines  Corp., 2002,2010
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
   *   Author(s): Steve French (sfrench@us.ibm.com)
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
   */
  #include <linux/fs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
  #include <linux/stat.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
10
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
  #include <linux/pagemap.h>
4f73c7d34   Jeff Layton   cifs: fix potenti...
12
  #include <linux/freezer.h>
174cd4b1e   Ingo Molnar   sched/headers: Pr...
13
  #include <linux/sched/signal.h>
5dd43ce2f   Ingo Molnar   sched/wait: Split...
14
  #include <linux/wait_bit.h>
10c5db286   Christoph Hellwig   fs: move the fiem...
15
  #include <linux/fiemap.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
18
19
20
  #include <asm/div64.h>
  #include "cifsfs.h"
  #include "cifspdu.h"
  #include "cifsglob.h"
  #include "cifsproto.h"
6a5f6592a   Steve French   SMB311: Add suppo...
21
  #include "smb2proto.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
  #include "cifs_debug.h"
  #include "cifs_fs_sb.h"
2baa26825   Steve French   Remap reserved po...
24
  #include "cifs_unicode.h"
9451a9a52   Suresh Jayaraman   cifs: define inod...
25
  #include "fscache.h"
8401e9367   Ronnie Sahlberg   cifs: remove [gu]...
26
  #include "fs_context.h"
087f757b0   Steve French   cifs: add shutdow...
27
  #include "cifs_ioctl.h"
70eff55d2   Christoph Hellwig   [CIFS] factoring ...
28

01c64feac   David Howells   CIFS: Use d_autom...
29
  static void cifs_set_ops(struct inode *inode)
70eff55d2   Christoph Hellwig   [CIFS] factoring ...
30
31
32
33
34
35
36
37
38
39
40
  {
  	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;
8be7e6ba1   Pavel Shilovsky   CIFS: Implement c...
41
42
43
44
45
  		} 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;
70eff55d2   Christoph Hellwig   [CIFS] factoring ...
46
47
48
49
50
  		} 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;
  		}
70eff55d2   Christoph Hellwig   [CIFS] factoring ...
51
  		/* check if server can support readpages */
1f641d941   Jones Syue   cifs: improve rea...
52
  		if (cifs_sb_master_tcon(cifs_sb)->ses->server->max_read <
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
53
  				PAGE_SIZE + MAX_CIFS_HDR_SIZE)
70eff55d2   Christoph Hellwig   [CIFS] factoring ...
54
55
56
57
58
  			inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
  		else
  			inode->i_data.a_ops = &cifs_addr_ops;
  		break;
  	case S_IFDIR:
bc5b6e24a   Steve French   [CIFS] Fix build ...
59
  #ifdef CONFIG_CIFS_DFS_UPCALL
01c64feac   David Howells   CIFS: Use d_autom...
60
  		if (IS_AUTOMOUNT(inode)) {
7962670e6   Igor Mammedov   [CIFS] DFS patch...
61
62
  			inode->i_op = &cifs_dfs_referral_inode_operations;
  		} else {
bc5b6e24a   Steve French   [CIFS] Fix build ...
63
64
65
  #else /* NO DFS support, treat as a directory */
  		{
  #endif
7962670e6   Igor Mammedov   [CIFS] DFS patch...
66
67
68
  			inode->i_op = &cifs_dir_inode_ops;
  			inode->i_fop = &cifs_dir_ops;
  		}
70eff55d2   Christoph Hellwig   [CIFS] factoring ...
69
70
71
72
73
74
75
76
77
  		break;
  	case S_IFLNK:
  		inode->i_op = &cifs_symlink_inode_ops;
  		break;
  	default:
  		init_special_inode(inode, inode->i_mode, inode->i_rdev);
  		break;
  	}
  }
df2cf170c   Jeff Layton   cifs: overhaul ci...
78
79
80
81
82
83
84
  /* 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);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
85
86
87
  	cifs_dbg(FYI, "%s: revalidating inode %llu
  ",
  		 __func__, cifs_i->uniqueid);
df2cf170c   Jeff Layton   cifs: overhaul ci...
88
89
  
  	if (inode->i_state & I_NEW) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
90
91
92
  		cifs_dbg(FYI, "%s: inode %llu is new
  ",
  			 __func__, cifs_i->uniqueid);
df2cf170c   Jeff Layton   cifs: overhaul ci...
93
94
95
96
  		return;
  	}
  
  	/* don't bother with revalidation if we have an oplock */
18cceb6a7   Pavel Shilovsky   CIFS: Replace cli...
97
  	if (CIFS_CACHE_READ(cifs_i)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
98
99
100
  		cifs_dbg(FYI, "%s: inode %llu is oplocked
  ",
  			 __func__, cifs_i->uniqueid);
df2cf170c   Jeff Layton   cifs: overhaul ci...
101
102
103
104
  		return;
  	}
  
  	 /* revalidate if mtime or size have changed */
918c90098   Deepa Dinamani   fs: cifs: Delete ...
105
  	fattr->cf_mtime = timestamp_truncate(fattr->cf_mtime, inode);
95390201e   Arnd Bergmann   cifs: use timespe...
106
  	if (timespec64_equal(&inode->i_mtime, &fattr->cf_mtime) &&
df2cf170c   Jeff Layton   cifs: overhaul ci...
107
  	    cifs_i->server_eof == fattr->cf_eof) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
108
109
110
  		cifs_dbg(FYI, "%s: inode %llu is unchanged
  ",
  			 __func__, cifs_i->uniqueid);
df2cf170c   Jeff Layton   cifs: overhaul ci...
111
112
  		return;
  	}
f96637be0   Joe Perches   [CIFS] cifs: Rena...
113
114
115
  	cifs_dbg(FYI, "%s: invalidating inode %llu mapping
  ",
  		 __func__, cifs_i->uniqueid);
aff8d5ca7   Jeff Layton   cifs: convert boo...
116
  	set_bit(CIFS_INO_INVALID_MAPPING, &cifs_i->flags);
df2cf170c   Jeff Layton   cifs: overhaul ci...
117
  }
74d290da4   Jim McDonough   [CIFS] Provide sa...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
  /*
   * 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);
  }
cc0bad755   Jeff Layton   cifs: add new cif...
144
  /* populate an inode with info from a cifs_fattr struct */
4d66952a2   Al Viro   cifs: have cifs_f...
145
  int
cc0bad755   Jeff Layton   cifs: add new cif...
146
  cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
75f12983d   Christoph Hellwig   [CIFS] consolidat...
147
  {
cc0bad755   Jeff Layton   cifs: add new cif...
148
  	struct cifsInodeInfo *cifs_i = CIFS_I(inode);
0b8f18e35   Jeff Layton   cifs: convert cif...
149
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
cc0bad755   Jeff Layton   cifs: add new cif...
150

4d66952a2   Al Viro   cifs: have cifs_f...
151
152
153
154
155
  	if (!(inode->i_state & I_NEW) &&
  	    unlikely(inode_wrong_type(inode, fattr->cf_mode))) {
  		CIFS_I(inode)->time = 0; /* force reval */
  		return -ESTALE;
  	}
df2cf170c   Jeff Layton   cifs: overhaul ci...
156
  	cifs_revalidate_cache(inode, fattr);
b7ca69289   Steve French   CIFS: Protect i_n...
157
  	spin_lock(&inode->i_lock);
918c90098   Deepa Dinamani   fs: cifs: Delete ...
158
159
160
  	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);
9b9c5bea0   Steve French   cifs: do not retu...
161
  	/* we do not want atime to be less than mtime, it broke some apps */
69738cfdf   Deepa Dinamani   fs: cifs: Fix ati...
162
  	if (timespec64_compare(&fattr->cf_atime, &fattr->cf_mtime) < 0)
9b9c5bea0   Steve French   cifs: do not retu...
163
164
165
  		inode->i_atime = fattr->cf_mtime;
  	else
  		inode->i_atime = fattr->cf_atime;
95390201e   Arnd Bergmann   cifs: use timespe...
166
167
  	inode->i_mtime = fattr->cf_mtime;
  	inode->i_ctime = fattr->cf_ctime;
cc0bad755   Jeff Layton   cifs: add new cif...
168
  	inode->i_rdev = fattr->cf_rdev;
74d290da4   Jim McDonough   [CIFS] Provide sa...
169
  	cifs_nlink_fattr_to_inode(inode, fattr);
cc0bad755   Jeff Layton   cifs: add new cif...
170
171
  	inode->i_uid = fattr->cf_uid;
  	inode->i_gid = fattr->cf_gid;
0b8f18e35   Jeff Layton   cifs: convert cif...
172
173
174
175
  	/* 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;
cc0bad755   Jeff Layton   cifs: add new cif...
176
  	cifs_i->cifsAttrs = fattr->cf_cifsattrs;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
177

0b8f18e35   Jeff Layton   cifs: convert cif...
178
179
180
181
  	if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
  		cifs_i->time = 0;
  	else
  		cifs_i->time = jiffies;
aff8d5ca7   Jeff Layton   cifs: convert boo...
182
183
184
185
  	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);
cc0bad755   Jeff Layton   cifs: add new cif...
186

835a36ca4   Jeff Layton   cifs: set server_...
187
  	cifs_i->server_eof = fattr->cf_eof;
cc0bad755   Jeff Layton   cifs: add new cif...
188
189
190
191
  	/*
  	 * Can't safely change the file size here if the client is writing to
  	 * it due to potential races.
  	 */
cc0bad755   Jeff Layton   cifs: add new cif...
192
193
194
195
196
197
198
199
200
201
202
  	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);
01c64feac   David Howells   CIFS: Use d_autom...
203
204
  	if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL)
  		inode->i_flags |= S_AUTOMOUNT;
c2b93e069   Jeff Layton   cifs: only set op...
205
206
  	if (inode->i_state & I_NEW)
  		cifs_set_ops(inode);
4d66952a2   Al Viro   cifs: have cifs_f...
207
  	return 0;
cc0bad755   Jeff Layton   cifs: add new cif...
208
  }
4065c802d   Jeff Layton   cifs: fix noserve...
209
210
211
212
213
214
215
216
217
218
  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);
  }
cc0bad755   Jeff Layton   cifs: add new cif...
219
220
221
222
223
224
225
226
227
228
229
230
231
  /* 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);
6e70e26dc   Steve French   SMB3: handle new ...
232
  	/* old POSIX extensions don't get create time */
cc0bad755   Jeff Layton   cifs: add new cif...
233
  	fattr->cf_mode = le64_to_cpu(info->Permissions);
75f12983d   Christoph Hellwig   [CIFS] consolidat...
234
235
236
237
238
  
  	/*
  	 * Since we set the inode type below we need to mask off
  	 * to avoid strange results if bits set above.
  	 */
cc0bad755   Jeff Layton   cifs: add new cif...
239
  	fattr->cf_mode &= ~S_IFMT;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
240
241
  	switch (le32_to_cpu(info->Type)) {
  	case UNIX_FILE:
cc0bad755   Jeff Layton   cifs: add new cif...
242
243
  		fattr->cf_mode |= S_IFREG;
  		fattr->cf_dtype = DT_REG;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
244
245
  		break;
  	case UNIX_SYMLINK:
cc0bad755   Jeff Layton   cifs: add new cif...
246
247
  		fattr->cf_mode |= S_IFLNK;
  		fattr->cf_dtype = DT_LNK;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
248
249
  		break;
  	case UNIX_DIR:
cc0bad755   Jeff Layton   cifs: add new cif...
250
251
  		fattr->cf_mode |= S_IFDIR;
  		fattr->cf_dtype = DT_DIR;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
252
253
  		break;
  	case UNIX_CHARDEV:
cc0bad755   Jeff Layton   cifs: add new cif...
254
255
256
257
  		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);
75f12983d   Christoph Hellwig   [CIFS] consolidat...
258
259
  		break;
  	case UNIX_BLOCKDEV:
cc0bad755   Jeff Layton   cifs: add new cif...
260
261
262
263
  		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);
75f12983d   Christoph Hellwig   [CIFS] consolidat...
264
265
  		break;
  	case UNIX_FIFO:
cc0bad755   Jeff Layton   cifs: add new cif...
266
267
  		fattr->cf_mode |= S_IFIFO;
  		fattr->cf_dtype = DT_FIFO;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
268
269
  		break;
  	case UNIX_SOCKET:
cc0bad755   Jeff Layton   cifs: add new cif...
270
271
  		fattr->cf_mode |= S_IFSOCK;
  		fattr->cf_dtype = DT_SOCK;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
272
273
274
  		break;
  	default:
  		/* safest to call it a file if we do not know */
cc0bad755   Jeff Layton   cifs: add new cif...
275
276
  		fattr->cf_mode |= S_IFREG;
  		fattr->cf_dtype = DT_REG;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
277
278
  		cifs_dbg(FYI, "unknown type %d
  ", le32_to_cpu(info->Type));
75f12983d   Christoph Hellwig   [CIFS] consolidat...
279
280
  		break;
  	}
8401e9367   Ronnie Sahlberg   cifs: remove [gu]...
281
  	fattr->cf_uid = cifs_sb->ctx->linux_uid;
46bbc25f9   Eric W. Biederman   cifs: Override un...
282
283
  	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
  		u64 id = le64_to_cpu(info->Uid);
4a2c8cf56   Eric W. Biederman   cifs: Convert str...
284
285
286
287
288
  		if (id < ((uid_t)-1)) {
  			kuid_t uid = make_kuid(&init_user_ns, id);
  			if (uid_valid(uid))
  				fattr->cf_uid = uid;
  		}
46bbc25f9   Eric W. Biederman   cifs: Override un...
289
290
  	}
  	
8401e9367   Ronnie Sahlberg   cifs: remove [gu]...
291
  	fattr->cf_gid = cifs_sb->ctx->linux_gid;
46bbc25f9   Eric W. Biederman   cifs: Override un...
292
293
  	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
  		u64 id = le64_to_cpu(info->Gid);
4a2c8cf56   Eric W. Biederman   cifs: Convert str...
294
295
296
297
298
  		if (id < ((gid_t)-1)) {
  			kgid_t gid = make_kgid(&init_user_ns, id);
  			if (gid_valid(gid))
  				fattr->cf_gid = gid;
  		}
46bbc25f9   Eric W. Biederman   cifs: Override un...
299
  	}
75f12983d   Christoph Hellwig   [CIFS] consolidat...
300

cc0bad755   Jeff Layton   cifs: add new cif...
301
  	fattr->cf_nlink = le64_to_cpu(info->Nlinks);
75f12983d   Christoph Hellwig   [CIFS] consolidat...
302
  }
b9a3260f2   Steve French   [CIFS] Enable DFS...
303
  /*
cc0bad755   Jeff Layton   cifs: add new cif...
304
305
306
307
308
   * 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).
b9a3260f2   Steve French   [CIFS] Enable DFS...
309
   */
f1230c979   Steve French   [CIFS] fix sparse...
310
  static void
cc0bad755   Jeff Layton   cifs: add new cif...
311
  cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
0e4bbde94   Steve French   [CIFS] Enable DFS...
312
  {
cc0bad755   Jeff Layton   cifs: add new cif...
313
  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
0e4bbde94   Steve French   [CIFS] Enable DFS...
314

f96637be0   Joe Perches   [CIFS] cifs: Rena...
315
316
  	cifs_dbg(FYI, "creating fake fattr for DFS referral
  ");
cc0bad755   Jeff Layton   cifs: add new cif...
317
318
319
  
  	memset(fattr, 0, sizeof(*fattr));
  	fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
8401e9367   Ronnie Sahlberg   cifs: remove [gu]...
320
321
  	fattr->cf_uid = cifs_sb->ctx->linux_uid;
  	fattr->cf_gid = cifs_sb->ctx->linux_gid;
918c90098   Deepa Dinamani   fs: cifs: Delete ...
322
  	ktime_get_coarse_real_ts64(&fattr->cf_mtime);
e37fea58f   Deepa Dinamani   fs: cifs: replace...
323
  	fattr->cf_atime = fattr->cf_ctime = fattr->cf_mtime;
cc0bad755   Jeff Layton   cifs: add new cif...
324
  	fattr->cf_nlink = 2;
97aa495a8   Steve French   cifs: address tri...
325
  	fattr->cf_flags = CIFS_FATTR_DFS_REFERRAL;
0e4bbde94   Steve French   [CIFS] Enable DFS...
326
  }
4ad650445   Pavel Shilovsky   CIFS: Move guery ...
327
328
  static int
  cifs_get_file_info_unix(struct file *filp)
abab095d1   Jeff Layton   cifs: add cifs_re...
329
330
  {
  	int rc;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
331
  	unsigned int xid;
abab095d1   Jeff Layton   cifs: add cifs_re...
332
333
  	FILE_UNIX_BASIC_INFO find_data;
  	struct cifs_fattr fattr;
496ad9aa8   Al Viro   new helper: file_...
334
  	struct inode *inode = file_inode(filp);
abab095d1   Jeff Layton   cifs: add cifs_re...
335
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
c21dfb699   Joe Perches   fs/cifs: Remove u...
336
  	struct cifsFileInfo *cfile = filp->private_data;
96daf2b09   Steve French   [CIFS] Rename thr...
337
  	struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
abab095d1   Jeff Layton   cifs: add cifs_re...
338

6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
339
  	xid = get_xid();
4b4de76e3   Pavel Shilovsky   CIFS: Replace net...
340
  	rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data);
abab095d1   Jeff Layton   cifs: add cifs_re...
341
342
343
344
345
  	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;
e39df2416   Steve French   cifs: fix SMB1 er...
346
347
  	} else
  		goto cifs_gfiunix_out;
abab095d1   Jeff Layton   cifs: add cifs_re...
348

4d66952a2   Al Viro   cifs: have cifs_f...
349
  	rc = cifs_fattr_to_inode(inode, &fattr);
e39df2416   Steve French   cifs: fix SMB1 er...
350
351
  
  cifs_gfiunix_out:
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
352
  	free_xid(xid);
abab095d1   Jeff Layton   cifs: add cifs_re...
353
354
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
355
  int cifs_get_inode_info_unix(struct inode **pinode,
cc0bad755   Jeff Layton   cifs: add new cif...
356
  			     const unsigned char *full_path,
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
357
  			     struct super_block *sb, unsigned int xid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
  {
cc0bad755   Jeff Layton   cifs: add new cif...
359
  	int rc;
0e4bbde94   Steve French   [CIFS] Enable DFS...
360
  	FILE_UNIX_BASIC_INFO find_data;
cc0bad755   Jeff Layton   cifs: add new cif...
361
  	struct cifs_fattr fattr;
96daf2b09   Steve French   [CIFS] Rename thr...
362
  	struct cifs_tcon *tcon;
7ffec3724   Jeff Layton   cifs: add refcoun...
363
  	struct tcon_link *tlink;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365

f96637be0   Joe Perches   [CIFS] cifs: Rena...
366
367
  	cifs_dbg(FYI, "Getting info on %s
  ", full_path);
7962670e6   Igor Mammedov   [CIFS] DFS patch...
368

7ffec3724   Jeff Layton   cifs: add refcoun...
369
370
371
372
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
  	tcon = tlink_tcon(tlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
  	/* could have done a find first instead but this returns more info */
cc0bad755   Jeff Layton   cifs: add new cif...
374
  	rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
bc8ebdc4f   Nakajima Akira   Fix that several ...
375
  				  cifs_sb->local_nls, cifs_remap(cifs_sb));
7ffec3724   Jeff Layton   cifs: add refcoun...
376
  	cifs_put_tlink(tlink);
e911d0cc8   Jeff Layton   cifs: fix inode l...
377

cc0bad755   Jeff Layton   cifs: add new cif...
378
379
380
381
382
383
384
385
  	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;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386

1b12b9c15   Stefan Metzmacher   cifs: use Minshal...
387
388
  	/* check for Minshall+French symlinks */
  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
cb084b1a9   Sachin Prabhu   cifs: Rename MF s...
389
390
  		int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
  					     full_path);
1b12b9c15   Stefan Metzmacher   cifs: use Minshal...
391
  		if (tmprc)
cb084b1a9   Sachin Prabhu   cifs: Rename MF s...
392
393
  			cifs_dbg(FYI, "check_mf_symlink: %d
  ", tmprc);
1b12b9c15   Stefan Metzmacher   cifs: use Minshal...
394
  	}
0e4bbde94   Steve French   [CIFS] Enable DFS...
395
  	if (*pinode == NULL) {
cc0bad755   Jeff Layton   cifs: add new cif...
396
  		/* get new inode */
4065c802d   Jeff Layton   cifs: fix noserve...
397
  		cifs_fill_uniqueid(sb, &fattr);
cc0bad755   Jeff Layton   cifs: add new cif...
398
399
  		*pinode = cifs_iget(sb, &fattr);
  		if (!*pinode)
0e4bbde94   Steve French   [CIFS] Enable DFS...
400
  			rc = -ENOMEM;
cc0bad755   Jeff Layton   cifs: add new cif...
401
402
  	} else {
  		/* we already have inode, update it */
7196ac113   Nakajima Akira   Fix to check Uniq...
403
404
405
406
  
  		/* if uniqueid is different, return error */
  		if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
  		    CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
c82e5ac7f   Pavel Shilovsky   CIFS: Force reval...
407
  			CIFS_I(*pinode)->time = 0; /* force reval */
7196ac113   Nakajima Akira   Fix to check Uniq...
408
409
410
411
412
  			rc = -ESTALE;
  			goto cgiiu_exit;
  		}
  
  		/* if filetype is different, return error */
4d66952a2   Al Viro   cifs: have cifs_f...
413
  		rc = cifs_fattr_to_inode(*pinode, &fattr);
0e4bbde94   Steve French   [CIFS] Enable DFS...
414
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415

7196ac113   Nakajima Akira   Fix to check Uniq...
416
  cgiiu_exit:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
418
  	return rc;
  }
0b8f18e35   Jeff Layton   cifs: convert cif...
419
  static int
0360d605a   Pavel Shilovsky   CIFS: Remove extr...
420
  cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
421
  	      struct cifs_sb_info *cifs_sb, unsigned int xid)
d6e2f2a4c   Steve French   [CIFS] Recognize ...
422
423
  {
  	int rc;
db8b631d4   Steve French   Allow mknod and m...
424
  	__u32 oplock;
7ffec3724   Jeff Layton   cifs: add refcoun...
425
  	struct tcon_link *tlink;
96daf2b09   Steve French   [CIFS] Rename thr...
426
  	struct cifs_tcon *tcon;
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
427
428
  	struct cifs_fid fid;
  	struct cifs_open_parms oparms;
7c06514af   Aurelien Aptel   cifs: multichanne...
429
  	struct cifs_io_parms io_parms = {0};
86c96b4bb   Steve French   [CIFS] Fix mknod ...
430
  	char buf[24];
d6e2f2a4c   Steve French   [CIFS] Recognize ...
431
  	unsigned int bytes_read;
fb8c4b14d   Steve French   [CIFS] whitespace...
432
  	char *pbuf;
0360d605a   Pavel Shilovsky   CIFS: Remove extr...
433
  	int buf_type = CIFS_NO_BUFFER;
d6e2f2a4c   Steve French   [CIFS] Recognize ...
434
435
  
  	pbuf = buf;
0b8f18e35   Jeff Layton   cifs: convert cif...
436
437
438
439
440
  	fattr->cf_mode &= ~S_IFMT;
  
  	if (fattr->cf_eof == 0) {
  		fattr->cf_mode |= S_IFIFO;
  		fattr->cf_dtype = DT_FIFO;
d6e2f2a4c   Steve French   [CIFS] Recognize ...
441
  		return 0;
0b8f18e35   Jeff Layton   cifs: convert cif...
442
443
444
  	} else if (fattr->cf_eof < 8) {
  		fattr->cf_mode |= S_IFREG;
  		fattr->cf_dtype = DT_REG;
d6e2f2a4c   Steve French   [CIFS] Recognize ...
445
446
  		return -EINVAL;	 /* EOPNOTSUPP? */
  	}
50c2f7538   Steve French   [CIFS] whitespace...
447

7ffec3724   Jeff Layton   cifs: add refcoun...
448
449
450
451
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
  	tcon = tlink_tcon(tlink);
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
452
453
454
  	oparms.tcon = tcon;
  	oparms.cifs_sb = cifs_sb;
  	oparms.desired_access = GENERIC_READ;
0f060936e   Amir Goldstein   SMB3: Backup inte...
455
  	oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
456
457
458
459
  	oparms.disposition = FILE_OPEN;
  	oparms.path = path;
  	oparms.fid = &fid;
  	oparms.reconnect = false;
db8b631d4   Steve French   Allow mknod and m...
460
461
462
463
464
  	if (tcon->ses->server->oplocks)
  		oplock = REQ_OPLOCK;
  	else
  		oplock = 0;
  	rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
0360d605a   Pavel Shilovsky   CIFS: Remove extr...
465
  	if (rc) {
db8b631d4   Steve French   Allow mknod and m...
466
467
  		cifs_dbg(FYI, "check sfu type of %s, open rc = %d
  ", path, rc);
0360d605a   Pavel Shilovsky   CIFS: Remove extr...
468
469
470
471
472
  		cifs_put_tlink(tlink);
  		return rc;
  	}
  
  	/* Read header */
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
473
  	io_parms.netfid = fid.netfid;
0360d605a   Pavel Shilovsky   CIFS: Remove extr...
474
475
476
477
  	io_parms.pid = current->tgid;
  	io_parms.tcon = tcon;
  	io_parms.offset = 0;
  	io_parms.length = 24;
db8b631d4   Steve French   Allow mknod and m...
478
479
  	rc = tcon->ses->server->ops->sync_read(xid, &fid, &io_parms,
  					&bytes_read, &pbuf, &buf_type);
0360d605a   Pavel Shilovsky   CIFS: Remove extr...
480
481
482
483
484
485
486
487
488
489
490
491
492
  	if ((rc == 0) && (bytes_read >= 8)) {
  		if (memcmp("IntxBLK", pbuf, 8) == 0) {
  			cifs_dbg(FYI, "Block device
  ");
  			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);
86c96b4bb   Steve French   [CIFS] Fix mknod ...
493
  			}
0360d605a   Pavel Shilovsky   CIFS: Remove extr...
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
  		} else if (memcmp("IntxCHR", pbuf, 8) == 0) {
  			cifs_dbg(FYI, "Char device
  ");
  			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
  ");
  			fattr->cf_mode |= S_IFLNK;
  			fattr->cf_dtype = DT_LNK;
3020a1f58   Steve French   [CIFS] Fix schedu...
512
  		} else {
0360d605a   Pavel Shilovsky   CIFS: Remove extr...
513
  			fattr->cf_mode |= S_IFREG; /* file? */
0b8f18e35   Jeff Layton   cifs: convert cif...
514
  			fattr->cf_dtype = DT_REG;
0360d605a   Pavel Shilovsky   CIFS: Remove extr...
515
  			rc = -EOPNOTSUPP;
fb8c4b14d   Steve French   [CIFS] whitespace...
516
  		}
0360d605a   Pavel Shilovsky   CIFS: Remove extr...
517
518
519
520
  	} else {
  		fattr->cf_mode |= S_IFREG; /* then it is a file */
  		fattr->cf_dtype = DT_REG;
  		rc = -EOPNOTSUPP; /* or some unknown SFU type */
d6e2f2a4c   Steve French   [CIFS] Recognize ...
521
  	}
db8b631d4   Steve French   Allow mknod and m...
522
523
  
  	tcon->ses->server->ops->close(xid, tcon, &fid);
7ffec3724   Jeff Layton   cifs: add refcoun...
524
  	cifs_put_tlink(tlink);
d6e2f2a4c   Steve French   [CIFS] Recognize ...
525
  	return rc;
d6e2f2a4c   Steve French   [CIFS] Recognize ...
526
  }
9e294f1c4   Steve French   [CIFS] Recognize ...
527
  #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID)  /* SETFILEBITS valid bits */
0b8f18e35   Jeff Layton   cifs: convert cif...
528
529
530
531
532
533
  /*
   * 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,
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
534
  			 struct cifs_sb_info *cifs_sb, unsigned int xid)
9e294f1c4   Steve French   [CIFS] Recognize ...
535
  {
3020a1f58   Steve French   [CIFS] Fix schedu...
536
  #ifdef CONFIG_CIFS_XATTR
9e294f1c4   Steve French   [CIFS] Recognize ...
537
538
539
  	ssize_t rc;
  	char ea_value[4];
  	__u32 mode;
7ffec3724   Jeff Layton   cifs: add refcoun...
540
  	struct tcon_link *tlink;
96daf2b09   Steve French   [CIFS] Rename thr...
541
  	struct cifs_tcon *tcon;
7ffec3724   Jeff Layton   cifs: add refcoun...
542
543
544
545
546
  
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
  	tcon = tlink_tcon(tlink);
9e294f1c4   Steve French   [CIFS] Recognize ...
547

d979f3b0a   Steve French   Add protocol spec...
548
549
550
551
552
553
554
  	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 */,
67b4c889c   Steve French   [CIFS] Minor clea...
555
  			cifs_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
556
  	cifs_put_tlink(tlink);
4523cc304   Steve French   [CIFS] UID/GID ov...
557
  	if (rc < 0)
9e294f1c4   Steve French   [CIFS] Recognize ...
558
559
560
  		return (int)rc;
  	else if (rc > 3) {
  		mode = le32_to_cpu(*((__le32 *)ea_value));
0b8f18e35   Jeff Layton   cifs: convert cif...
561
  		fattr->cf_mode &= ~SFBITS_MASK;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
562
563
564
  		cifs_dbg(FYI, "special bits 0%o org mode 0%o
  ",
  			 mode, fattr->cf_mode);
0b8f18e35   Jeff Layton   cifs: convert cif...
565
  		fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
566
567
  		cifs_dbg(FYI, "special mode bits 0%o
  ", mode);
9e294f1c4   Steve French   [CIFS] Recognize ...
568
  	}
0b8f18e35   Jeff Layton   cifs: convert cif...
569
570
  
  	return 0;
3020a1f58   Steve French   [CIFS] Fix schedu...
571
572
573
  #else
  	return -EOPNOTSUPP;
  #endif
9e294f1c4   Steve French   [CIFS] Recognize ...
574
  }
6a5f6592a   Steve French   SMB311: Add suppo...
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
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
  /* 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 */
8401e9367   Ronnie Sahlberg   cifs: remove [gu]...
622
623
  	fattr->cf_uid = cifs_sb->ctx->linux_uid; /* TODO: map uid and gid from SID */
  	fattr->cf_gid = cifs_sb->ctx->linux_gid;
6a5f6592a   Steve French   SMB311: Add suppo...
624
625
626
627
628
  
  	cifs_dbg(FYI, "POSIX query info: mode 0x%x uniqueid 0x%llx nlink %d
  ",
  		fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink);
  }
0b8f18e35   Jeff Layton   cifs: convert cif...
629
  /* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
f1230c979   Steve French   [CIFS] fix sparse...
630
  static void
0b8f18e35   Jeff Layton   cifs: convert cif...
631
  cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
e37fea58f   Deepa Dinamani   fs: cifs: replace...
632
  		       struct super_block *sb, bool adjust_tz,
2e4564b31   Steve French   smb3: add support...
633
  		       bool symlink, u32 reparse_tag)
b9a3260f2   Steve French   [CIFS] Enable DFS...
634
  {
e37fea58f   Deepa Dinamani   fs: cifs: replace...
635
  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
96daf2b09   Steve French   [CIFS] Rename thr...
636
  	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
0d424ad0a   Jeff Layton   cifs: add cifs_sb...
637

0b8f18e35   Jeff Layton   cifs: convert cif...
638
639
640
641
642
643
644
  	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);
918c90098   Deepa Dinamani   fs: cifs: Delete ...
645
646
  	else
  		ktime_get_coarse_real_ts64(&fattr->cf_atime);
0b8f18e35   Jeff Layton   cifs: convert cif...
647
648
649
650
651
  
  	fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
  	fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
  
  	if (adjust_tz) {
0d424ad0a   Jeff Layton   cifs: add cifs_sb...
652
653
  		fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
  		fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
0b8f18e35   Jeff Layton   cifs: convert cif...
654
655
656
657
  	}
  
  	fattr->cf_eof = le64_to_cpu(info->EndOfFile);
  	fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
20054bd65   Jeff Layton   cifs: use Creatio...
658
  	fattr->cf_createtime = le64_to_cpu(info->CreationTime);
0b8f18e35   Jeff Layton   cifs: convert cif...
659

74d290da4   Jim McDonough   [CIFS] Provide sa...
660
  	fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
2e4564b31   Steve French   smb3: add support...
661
  	if (reparse_tag == IO_REPARSE_TAG_LX_SYMLINK) {
8401e9367   Ronnie Sahlberg   cifs: remove [gu]...
662
  		fattr->cf_mode |= S_IFLNK | cifs_sb->ctx->file_mode;
2e4564b31   Steve French   smb3: add support...
663
664
  		fattr->cf_dtype = DT_LNK;
  	} else if (reparse_tag == IO_REPARSE_TAG_LX_FIFO) {
8401e9367   Ronnie Sahlberg   cifs: remove [gu]...
665
  		fattr->cf_mode |= S_IFIFO | cifs_sb->ctx->file_mode;
2e4564b31   Steve French   smb3: add support...
666
667
  		fattr->cf_dtype = DT_FIFO;
  	} else if (reparse_tag == IO_REPARSE_TAG_AF_UNIX) {
8401e9367   Ronnie Sahlberg   cifs: remove [gu]...
668
  		fattr->cf_mode |= S_IFSOCK | cifs_sb->ctx->file_mode;
2e4564b31   Steve French   smb3: add support...
669
670
  		fattr->cf_dtype = DT_SOCK;
  	} else if (reparse_tag == IO_REPARSE_TAG_LX_CHR) {
8401e9367   Ronnie Sahlberg   cifs: remove [gu]...
671
  		fattr->cf_mode |= S_IFCHR | cifs_sb->ctx->file_mode;
2e4564b31   Steve French   smb3: add support...
672
673
  		fattr->cf_dtype = DT_CHR;
  	} else if (reparse_tag == IO_REPARSE_TAG_LX_BLK) {
8401e9367   Ronnie Sahlberg   cifs: remove [gu]...
674
  		fattr->cf_mode |= S_IFBLK | cifs_sb->ctx->file_mode;
2e4564b31   Steve French   smb3: add support...
675
676
  		fattr->cf_dtype = DT_BLK;
  	} else if (symlink) { /* TODO add more reparse tag checks */
eb85d94bd   Pavel Shilovsky   CIFS: Fix symboli...
677
678
679
  		fattr->cf_mode = S_IFLNK;
  		fattr->cf_dtype = DT_LNK;
  	} else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
8401e9367   Ronnie Sahlberg   cifs: remove [gu]...
680
  		fattr->cf_mode = S_IFDIR | cifs_sb->ctx->dir_mode;
0b8f18e35   Jeff Layton   cifs: convert cif...
681
  		fattr->cf_dtype = DT_DIR;
6de2ce423   Pavel Shilovsky   CIFS: Fix mkdir/r...
682
683
684
685
  		/*
  		 * Server can return wrong NumberOfLinks value for directories
  		 * when Unix extensions are disabled - fake it.
  		 */
74d290da4   Jim McDonough   [CIFS] Provide sa...
686
687
  		if (!tcon->unix_ext)
  			fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
0b8f18e35   Jeff Layton   cifs: convert cif...
688
  	} else {
8401e9367   Ronnie Sahlberg   cifs: remove [gu]...
689
  		fattr->cf_mode = S_IFREG | cifs_sb->ctx->file_mode;
0b8f18e35   Jeff Layton   cifs: convert cif...
690
  		fattr->cf_dtype = DT_REG;
0b8f18e35   Jeff Layton   cifs: convert cif...
691

d0c280d26   Jeff Layton   cifs: when ATTR_R...
692
693
694
  		/* clear write bits if ATTR_READONLY is set */
  		if (fattr->cf_cifsattrs & ATTR_READONLY)
  			fattr->cf_mode &= ~(S_IWUGO);
0b8f18e35   Jeff Layton   cifs: convert cif...
695

74d290da4   Jim McDonough   [CIFS] Provide sa...
696
697
698
699
700
701
  		/*
  		 * 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) {
fb4b5f134   Joe Perches   cifs: Use #define...
702
703
704
  			cifs_dbg(VFS, "bogus file nlink value %u
  ",
  				 fattr->cf_nlink);
74d290da4   Jim McDonough   [CIFS] Provide sa...
705
  			fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
6658b9f70   Steve French   [CIFS] use sensib...
706
  		}
6de2ce423   Pavel Shilovsky   CIFS: Fix mkdir/r...
707
  	}
0b8f18e35   Jeff Layton   cifs: convert cif...
708

8401e9367   Ronnie Sahlberg   cifs: remove [gu]...
709
710
  	fattr->cf_uid = cifs_sb->ctx->linux_uid;
  	fattr->cf_gid = cifs_sb->ctx->linux_gid;
b9a3260f2   Steve French   [CIFS] Enable DFS...
711
  }
4ad650445   Pavel Shilovsky   CIFS: Move guery ...
712
713
  static int
  cifs_get_file_info(struct file *filp)
abab095d1   Jeff Layton   cifs: add cifs_re...
714
715
  {
  	int rc;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
716
  	unsigned int xid;
abab095d1   Jeff Layton   cifs: add cifs_re...
717
718
  	FILE_ALL_INFO find_data;
  	struct cifs_fattr fattr;
496ad9aa8   Al Viro   new helper: file_...
719
  	struct inode *inode = file_inode(filp);
c21dfb699   Joe Perches   fs/cifs: Remove u...
720
  	struct cifsFileInfo *cfile = filp->private_data;
96daf2b09   Steve French   [CIFS] Rename thr...
721
  	struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
4ad650445   Pavel Shilovsky   CIFS: Move guery ...
722
723
724
725
  	struct TCP_Server_Info *server = tcon->ses->server;
  
  	if (!server->ops->query_file_info)
  		return -ENOSYS;
abab095d1   Jeff Layton   cifs: add cifs_re...
726

6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
727
  	xid = get_xid();
4ad650445   Pavel Shilovsky   CIFS: Move guery ...
728
  	rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
42274bb22   Pavel Shilovsky   CIFS: Fix DFS han...
729
730
  	switch (rc) {
  	case 0:
2e4564b31   Steve French   smb3: add support...
731
  		/* TODO: add support to query reparse tag */
e37fea58f   Deepa Dinamani   fs: cifs: replace...
732
  		cifs_all_info_to_fattr(&fattr, &find_data, inode->i_sb, false,
2e4564b31   Steve French   smb3: add support...
733
  				       false, 0 /* no reparse tag */);
42274bb22   Pavel Shilovsky   CIFS: Fix DFS han...
734
735
736
737
738
739
740
  		break;
  	case -EREMOTE:
  		cifs_create_dfs_fattr(&fattr, inode->i_sb);
  		rc = 0;
  		break;
  	case -EOPNOTSUPP:
  	case -EINVAL:
abab095d1   Jeff Layton   cifs: add cifs_re...
741
742
  		/*
  		 * FIXME: legacy server -- fall back to path-based call?
ff215713e   Steve French   [CIFS] checkpatch...
743
744
745
  		 * for now, just skip revalidating and mark inode for
  		 * immediate reval.
  		 */
abab095d1   Jeff Layton   cifs: add cifs_re...
746
747
  		rc = 0;
  		CIFS_I(inode)->time = 0;
21ac58f49   Gustavo A. R. Silva   cifs: Fix fall-th...
748
  		goto cgfi_exit;
42274bb22   Pavel Shilovsky   CIFS: Fix DFS han...
749
  	default:
abab095d1   Jeff Layton   cifs: add cifs_re...
750
  		goto cgfi_exit;
42274bb22   Pavel Shilovsky   CIFS: Fix DFS han...
751
  	}
abab095d1   Jeff Layton   cifs: add cifs_re...
752
753
754
755
756
  
  	/*
  	 * don't bother with SFU junk here -- just mark inode as needing
  	 * revalidation.
  	 */
abab095d1   Jeff Layton   cifs: add cifs_re...
757
758
  	fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
  	fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
4d66952a2   Al Viro   cifs: have cifs_f...
759
760
  	/* if filetype is different, return error */
  	rc = cifs_fattr_to_inode(inode, &fattr);
abab095d1   Jeff Layton   cifs: add cifs_re...
761
  cgfi_exit:
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
762
  	free_xid(xid);
abab095d1   Jeff Layton   cifs: add cifs_re...
763
764
  	return rc;
  }
7ea884c77   Steve French   smb3: Fix root di...
765
766
767
  /* Simple function to return a 64 bit hash of string.  Rarely called */
  static __u64 simple_hashstr(const char *str)
  {
3995bbf53   Geert Uytterhoeven   cifs: Use ULL suf...
768
  	const __u64 hash_mult =  1125899906842597ULL; /* a big enough prime */
7ea884c77   Steve French   smb3: Fix root di...
769
770
771
772
773
774
775
  	__u64 hash = 0;
  
  	while (*str)
  		hash = (hash + (__u64) *str++) * hash_mult;
  
  	return hash;
  }
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
776
777
778
779
  /**
   * cifs_backup_query_path_info - SMB1 fallback code to get ino
   *
   * Fallback code to get file metadata when we don't have access to
607dfc79c   Steve French   cifs: remove vari...
780
   * full_path (EACCES) and have backup creds.
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
781
   *
607dfc79c   Steve French   cifs: remove vari...
782
783
784
785
786
787
788
   * @xid:	transaction id used to identify original request in logs
   * @tcon:	information about the server share we have mounted
   * @sb:	the superblock stores info such as disk space available
   * @full_path:	name of the file we are getting the metadata for
   * @resp_buf:	will be set to cifs resp buf and needs to be freed with
   * 		cifs_buf_release() when done with @data
   * @data:	will be set to search info result buffer
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
789
790
791
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
   */
  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
  ");
  		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;
  }
1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
892
  int
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
893
894
895
896
  cifs_get_inode_info(struct inode **inode,
  		    const char *full_path,
  		    FILE_ALL_INFO *in_data,
  		    struct super_block *sb, int xid,
42eacf9e5   Steve French   [CIFS] Fix cifsac...
897
  		    const struct cifs_fid *fid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
898
  {
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
899

1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
900
901
  	struct cifs_tcon *tcon;
  	struct TCP_Server_Info *server;
7ffec3724   Jeff Layton   cifs: add refcoun...
902
  	struct tcon_link *tlink;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903
  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
904
  	bool adjust_tz = false;
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
905
  	struct cifs_fattr fattr = {0};
2e4564b31   Steve French   smb3: add support...
906
  	bool is_reparse_point = false;
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
907
908
909
910
911
  	FILE_ALL_INFO *data = in_data;
  	FILE_ALL_INFO *tmp_data = NULL;
  	void *smb1_backup_rsp_buf = NULL;
  	int rc = 0;
  	int tmprc = 0;
2e4564b31   Steve French   smb3: add support...
912
  	__u32 reparse_tag = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
913

7ffec3724   Jeff Layton   cifs: add refcoun...
914
915
916
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
917
918
  	tcon = tlink_tcon(tlink);
  	server = tcon->ses->server;
7ffec3724   Jeff Layton   cifs: add refcoun...
919

b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
920
921
922
  	/*
  	 * 1. Fetch file metadata if not provided (data)
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
923

b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
924
925
  	if (!data) {
  		if (is_inode_cache_good(*inode)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
926
927
  			cifs_dbg(FYI, "No need to revalidate cached inode sizes
  ");
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
928
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
929
  		}
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
930
931
  		tmp_data = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
  		if (!tmp_data) {
7ffec3724   Jeff Layton   cifs: add refcoun...
932
  			rc = -ENOMEM;
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
933
  			goto out;
7ffec3724   Jeff Layton   cifs: add refcoun...
934
  		}
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
935
  		rc = server->ops->query_path_info(xid, tcon, cifs_sb,
2e4564b31   Steve French   smb3: add support...
936
937
  						 full_path, tmp_data,
  						 &adjust_tz, &is_reparse_point);
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
938
  		data = tmp_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
939
  	}
0b8f18e35   Jeff Layton   cifs: convert cif...
940

b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
941
942
943
944
945
946
  	/*
  	 * 2. Convert it to internal cifs metadata (fattr)
  	 */
  
  	switch (rc) {
  	case 0:
2e4564b31   Steve French   smb3: add support...
947
948
949
950
951
952
953
954
955
956
957
958
959
960
  		/*
  		 * If the file is a reparse point, it is more complicated
  		 * since we have to check if its reparse tag matches a known
  		 * special file type e.g. symlink or fifo or char etc.
  		 */
  		if ((le32_to_cpu(data->Attributes) & ATTR_REPARSE) &&
  		    server->ops->query_reparse_tag) {
  			rc = server->ops->query_reparse_tag(xid, tcon, cifs_sb,
  						full_path, &reparse_tag);
  			cifs_dbg(FYI, "reparse tag 0x%x
  ", reparse_tag);
  		}
  		cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz,
  				       is_reparse_point, reparse_tag);
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
961
962
963
  		break;
  	case -EREMOTE:
  		/* DFS link, no metadata available on this server */
0b8f18e35   Jeff Layton   cifs: convert cif...
964
  		cifs_create_dfs_fattr(&fattr, sb);
b9a3260f2   Steve French   [CIFS] Enable DFS...
965
  		rc = 0;
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
966
967
  		break;
  	case -EACCES:
3b7960cac   Steve French   cifs: fallback to...
968
  		/*
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
969
970
971
972
973
974
  		 * 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
3b7960cac   Steve French   cifs: fallback to...
975
  		 */
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
  		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;
3b7960cac   Steve French   cifs: fallback to...
998
  		}
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
999
1000
1001
1002
1003
1004
  		break;
  	default:
  		cifs_dbg(FYI, "%s: unhandled err rc %d
  ", __func__, rc);
  		goto out;
  	}
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
1005

b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
1006
1007
1008
1009
1010
  	/*
  	 * 3. Get or update inode number (fattr.cf_uniqueid)
  	 */
  
  	cifs_set_fattr_ino(xid, tcon, sb, inode, full_path, data, &fattr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1011

0b8f18e35   Jeff Layton   cifs: convert cif...
1012
  	/*
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
1013
  	 * 4. Tweak fattr based on mount options
0b8f18e35   Jeff Layton   cifs: convert cif...
1014
  	 */
b9a3260f2   Steve French   [CIFS] Enable DFS...
1015

b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
1016
  handle_mnt_opt:
0b8f18e35   Jeff Layton   cifs: convert cif...
1017
1018
1019
1020
1021
  	/* 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)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1022
1023
  			cifs_dbg(FYI, "cifs_sfu_type failed: %d
  ", tmprc);
b9a3260f2   Steve French   [CIFS] Enable DFS...
1024
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1025

b9a3260f2   Steve French   [CIFS] Enable DFS...
1026
  	/* fill in 0777 bits from ACL */
e2f8fbfb8   Steve French   cifs: get mode bi...
1027
1028
1029
  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) {
  		rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, true,
  				       full_path, fid);
01ec372ce   Ronnie Sahlberg   cifs: fix DFS mou...
1030
1031
  		if (rc == -EREMOTE)
  			rc = 0;
e2f8fbfb8   Steve French   cifs: get mode bi...
1032
1033
1034
  		if (rc) {
  			cifs_dbg(FYI, "%s: Get mode from SID failed. rc=%d
  ",
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
1035
1036
  				 __func__, rc);
  			goto out;
e2f8fbfb8   Steve French   cifs: get mode bi...
1037
1038
1039
  		}
  	} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
  		rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, false,
68464b88c   Dan Carpenter via samba-technical   CIFS: fix a white...
1040
  				       full_path, fid);
01ec372ce   Ronnie Sahlberg   cifs: fix DFS mou...
1041
1042
  		if (rc == -EREMOTE)
  			rc = 0;
68464b88c   Dan Carpenter via samba-technical   CIFS: fix a white...
1043
  		if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1044
1045
1046
  			cifs_dbg(FYI, "%s: Getting ACL failed with error: %d
  ",
  				 __func__, rc);
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
1047
  			goto out;
78415d2d3   Shirish Pargaonkar   cifs: Misc. clean...
1048
  		}
b9a3260f2   Steve French   [CIFS] Enable DFS...
1049
  	}
b9a3260f2   Steve French   [CIFS] Enable DFS...
1050

0b8f18e35   Jeff Layton   cifs: convert cif...
1051
1052
1053
  	/* 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);
b9a3260f2   Steve French   [CIFS] Enable DFS...
1054

1b12b9c15   Stefan Metzmacher   cifs: use Minshal...
1055
1056
  	/* check for Minshall+French symlinks */
  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
cb084b1a9   Sachin Prabhu   cifs: Rename MF s...
1057
1058
  		tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
  					 full_path);
1b12b9c15   Stefan Metzmacher   cifs: use Minshal...
1059
  		if (tmprc)
cb084b1a9   Sachin Prabhu   cifs: Rename MF s...
1060
1061
  			cifs_dbg(FYI, "check_mf_symlink: %d
  ", tmprc);
1b12b9c15   Stefan Metzmacher   cifs: use Minshal...
1062
  	}
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
1063
1064
1065
  	/*
  	 * 5. Update inode with final fattr data
  	 */
1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
1066
1067
1068
  	if (!*inode) {
  		*inode = cifs_iget(sb, &fattr);
  		if (!*inode)
0b8f18e35   Jeff Layton   cifs: convert cif...
1069
1070
  			rc = -ENOMEM;
  	} else {
7196ac113   Nakajima Akira   Fix to check Uniq...
1071
  		/* we already have inode, update it */
a108471b5   Ross Lagerwall   cifs: Check uniqu...
1072
1073
1074
  		/* if uniqueid is different, return error */
  		if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
  		    CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
c82e5ac7f   Pavel Shilovsky   CIFS: Force reval...
1075
  			CIFS_I(*inode)->time = 0; /* force reval */
a108471b5   Ross Lagerwall   cifs: Check uniqu...
1076
  			rc = -ESTALE;
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
1077
  			goto out;
a108471b5   Ross Lagerwall   cifs: Check uniqu...
1078
  		}
7196ac113   Nakajima Akira   Fix to check Uniq...
1079
  		/* if filetype is different, return error */
4d66952a2   Al Viro   cifs: have cifs_f...
1080
  		rc = cifs_fattr_to_inode(*inode, &fattr);
0b8f18e35   Jeff Layton   cifs: convert cif...
1081
  	}
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
1082
1083
  out:
  	cifs_buf_release(smb1_backup_rsp_buf);
7ffec3724   Jeff Layton   cifs: add refcoun...
1084
  	cifs_put_tlink(tlink);
b8f7442bc   Aurelien Aptel   CIFS: refactor ci...
1085
  	kfree(tmp_data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1086
1087
  	return rc;
  }
6a5f6592a   Steve French   SMB311: Add suppo...
1088
1089
1090
1091
1092
1093
  int
  smb311_posix_get_inode_info(struct inode **inode,
  		    const char *full_path,
  		    struct super_block *sb, unsigned int xid)
  {
  	struct cifs_tcon *tcon;
6a5f6592a   Steve French   SMB311: Add suppo...
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
  	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);
6a5f6592a   Steve French   SMB311: Add suppo...
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
1151
1152
1153
1154
1155
  
  	/*
  	 * 1. Fetch file metadata
  	 */
  
  	if (is_inode_cache_good(*inode)) {
  		cifs_dbg(FYI, "No need to revalidate cached inode sizes
  ");
  		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
  ", __func__, rc);
  		goto out;
  	}
  
  
  	/*
a7a519a49   Steve French   smb3: Add debug m...
1156
  	 * 3. Tweak fattr based on mount options
6a5f6592a   Steve French   SMB311: Add suppo...
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
  	 */
  
  	/* 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
  ", tmprc);
  	}
  
  	/*
a7a519a49   Steve French   smb3: Add debug m...
1169
  	 * 4. Update inode with final fattr data
6a5f6592a   Steve French   SMB311: Add suppo...
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
  	 */
  
  	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 */
4d66952a2   Al Viro   cifs: have cifs_f...
1188
  		rc = cifs_fattr_to_inode(*inode, &fattr);
6a5f6592a   Steve French   SMB311: Add suppo...
1189
1190
1191
1192
1193
1194
  	}
  out:
  	cifs_put_tlink(tlink);
  	kfree(data);
  	return rc;
  }
7f8ed420f   Steve French   [CIFS] CIFS suppo...
1195
1196
1197
  static const struct inode_operations cifs_ipc_inode_ops = {
  	.lookup = cifs_lookup,
  };
cc0bad755   Jeff Layton   cifs: add new cif...
1198
1199
1200
1201
  static int
  cifs_find_inode(struct inode *inode, void *opaque)
  {
  	struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
f30b9c118   Jeff Layton   cifs: don't allow...
1202
  	/* don't match inode with different uniqueid */
cc0bad755   Jeff Layton   cifs: add new cif...
1203
1204
  	if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
  		return 0;
20054bd65   Jeff Layton   cifs: use Creatio...
1205
1206
1207
  	/* use createtime like an i_generation field */
  	if (CIFS_I(inode)->createtime != fattr->cf_createtime)
  		return 0;
f30b9c118   Jeff Layton   cifs: don't allow...
1208
  	/* don't match inode of different type */
6e3e2c436   Al Viro   new helper: inode...
1209
  	if (inode_wrong_type(inode, fattr->cf_mode))
f30b9c118   Jeff Layton   cifs: don't allow...
1210
  		return 0;
5acfec250   Jeff Layton   cifs: reduce fals...
1211
  	/* if it's not a directory or has no dentries, then flag it */
b3d9b7a3c   Al Viro   vfs: switch i_den...
1212
  	if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
3d6943803   Jeff Layton   cifs: guard again...
1213
  		fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
3d6943803   Jeff Layton   cifs: guard again...
1214

cc0bad755   Jeff Layton   cifs: add new cif...
1215
1216
1217
1218
1219
1220
1221
1222
1223
  	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;
20054bd65   Jeff Layton   cifs: use Creatio...
1224
  	CIFS_I(inode)->createtime = fattr->cf_createtime;
cc0bad755   Jeff Layton   cifs: add new cif...
1225
1226
  	return 0;
  }
5acfec250   Jeff Layton   cifs: reduce fals...
1227
1228
1229
1230
1231
1232
1233
1234
1235
  /*
   * 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;
873feea09   Nick Piggin   fs: dcache per-in...
1236
  	spin_lock(&inode->i_lock);
946e51f2b   Al Viro   move d_rcu from o...
1237
  	hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
5acfec250   Jeff Layton   cifs: reduce fals...
1238
  		if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
873feea09   Nick Piggin   fs: dcache per-in...
1239
  			spin_unlock(&inode->i_lock);
5acfec250   Jeff Layton   cifs: reduce fals...
1240
1241
1242
  			return true;
  		}
  	}
873feea09   Nick Piggin   fs: dcache per-in...
1243
  	spin_unlock(&inode->i_lock);
5acfec250   Jeff Layton   cifs: reduce fals...
1244
1245
  	return false;
  }
cc0bad755   Jeff Layton   cifs: add new cif...
1246
1247
1248
1249
1250
1251
  /* Given fattrs, get a corresponding inode */
  struct inode *
  cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
  {
  	unsigned long hash;
  	struct inode *inode;
3d6943803   Jeff Layton   cifs: guard again...
1252
  retry_iget5_locked:
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1253
1254
  	cifs_dbg(FYI, "looking for uniqueid=%llu
  ", fattr->cf_uniqueid);
cc0bad755   Jeff Layton   cifs: add new cif...
1255
1256
1257
1258
1259
  
  	/* 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);
cc0bad755   Jeff Layton   cifs: add new cif...
1260
  	if (inode) {
5acfec250   Jeff Layton   cifs: reduce fals...
1261
  		/* was there a potentially problematic inode collision? */
3d6943803   Jeff Layton   cifs: guard again...
1262
  		if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
3d6943803   Jeff Layton   cifs: guard again...
1263
  			fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
5acfec250   Jeff Layton   cifs: reduce fals...
1264
1265
1266
1267
1268
1269
1270
  
  			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;
  			}
3d6943803   Jeff Layton   cifs: guard again...
1271
  		}
4d66952a2   Al Viro   cifs: have cifs_f...
1272
  		/* can't fail - see cifs_find_inode() */
cc0bad755   Jeff Layton   cifs: add new cif...
1273
  		cifs_fattr_to_inode(inode, fattr);
1751e8a6c   Linus Torvalds   Rename superblock...
1274
  		if (sb->s_flags & SB_NOATIME)
cc0bad755   Jeff Layton   cifs: add new cif...
1275
1276
1277
  			inode->i_flags |= S_NOATIME | S_NOCMTIME;
  		if (inode->i_state & I_NEW) {
  			inode->i_ino = hash;
0ccd48025   Steve French   [CIFS] Missing ifdef
1278
  #ifdef CONFIG_CIFS_FSCACHE
9451a9a52   Suresh Jayaraman   cifs: define inod...
1279
1280
  			/* initialize per-inode cache cookie pointer */
  			CIFS_I(inode)->fscache = NULL;
0ccd48025   Steve French   [CIFS] Missing ifdef
1281
  #endif
cc0bad755   Jeff Layton   cifs: add new cif...
1282
1283
1284
1285
1286
1287
  			unlock_new_inode(inode);
  		}
  	}
  
  	return inode;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1288
  /* gets root inode */
9b6763e0a   Shirish Pargaonkar   cifs: Remove unus...
1289
  struct inode *cifs_root_iget(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1290
  {
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1291
  	unsigned int xid;
0d424ad0a   Jeff Layton   cifs: add cifs_sb...
1292
  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
cc0bad755   Jeff Layton   cifs: add new cif...
1293
  	struct inode *inode = NULL;
ce634ab28   David Howells   iget: stop CIFS f...
1294
  	long rc;
96daf2b09   Steve French   [CIFS] Rename thr...
1295
  	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
a6b5058fa   Aurelien Aptel   fs/cifs: make sha...
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
  	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);
  	}
ce634ab28   David Howells   iget: stop CIFS f...
1312

6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1313
  	xid = get_xid();
b5b374eab   Steve French   Workaround Mac se...
1314
  	if (tcon->unix_ext) {
a6b5058fa   Aurelien Aptel   fs/cifs: make sha...
1315
  		rc = cifs_get_inode_info_unix(&inode, path, sb, xid);
b5b374eab   Steve French   Workaround Mac se...
1316
1317
1318
  		/* some servers mistakenly claim POSIX support */
  		if (rc != -EOPNOTSUPP)
  			goto iget_no_retry;
a0a3036b8   Joe Perches   cifs: Standardize...
1319
1320
  		cifs_dbg(VFS, "server does not support POSIX extensions
  ");
b5b374eab   Steve French   Workaround Mac se...
1321
1322
  		tcon->unix_ext = false;
  	}
a6b5058fa   Aurelien Aptel   fs/cifs: make sha...
1323
  	convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
d313852d7   Steve French   smb311: add suppo...
1324
1325
1326
1327
  	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);
0b8f18e35   Jeff Layton   cifs: convert cif...
1328

b5b374eab   Steve French   Workaround Mac se...
1329
  iget_no_retry:
a7851ce73   Oskar Schirmer   cifs: fix another...
1330
1331
1332
1333
  	if (!inode) {
  		inode = ERR_PTR(rc);
  		goto out;
  	}
cc0bad755   Jeff Layton   cifs: add new cif...
1334

0ccd48025   Steve French   [CIFS] Missing ifdef
1335
  #ifdef CONFIG_CIFS_FSCACHE
d03382ce9   Suresh Jayaraman   cifs: define supe...
1336
  	/* populate tcon->resource_id */
0d424ad0a   Jeff Layton   cifs: add cifs_sb...
1337
  	tcon->resource_id = CIFS_I(inode)->uniqueid;
0ccd48025   Steve French   [CIFS] Missing ifdef
1338
  #endif
d03382ce9   Suresh Jayaraman   cifs: define supe...
1339

b327a717e   Aurelien Aptel   CIFS: make IPC a ...
1340
  	if (rc && tcon->pipe) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1341
1342
  		cifs_dbg(FYI, "ipc connection - fake read inode
  ");
b7ca69289   Steve French   CIFS: Protect i_n...
1343
  		spin_lock(&inode->i_lock);
7f8ed420f   Steve French   [CIFS] CIFS suppo...
1344
  		inode->i_mode |= S_IFDIR;
bfe868486   Miklos Szeredi   filesystems: add ...
1345
  		set_nlink(inode, 2);
7f8ed420f   Steve French   [CIFS] CIFS suppo...
1346
1347
  		inode->i_op = &cifs_ipc_inode_ops;
  		inode->i_fop = &simple_dir_operations;
8401e9367   Ronnie Sahlberg   cifs: remove [gu]...
1348
1349
  		inode->i_uid = cifs_sb->ctx->linux_uid;
  		inode->i_gid = cifs_sb->ctx->linux_gid;
b7ca69289   Steve French   CIFS: Protect i_n...
1350
  		spin_unlock(&inode->i_lock);
ad661334b   Steve French   [CIFS] mount of I...
1351
  	} else if (rc) {
ce634ab28   David Howells   iget: stop CIFS f...
1352
  		iget_failed(inode);
a7851ce73   Oskar Schirmer   cifs: fix another...
1353
  		inode = ERR_PTR(rc);
7f8ed420f   Steve French   [CIFS] CIFS suppo...
1354
  	}
a7851ce73   Oskar Schirmer   cifs: fix another...
1355
  out:
a6b5058fa   Aurelien Aptel   fs/cifs: make sha...
1356
  	kfree(path);
31cd106bb   Phillip Potter   fs: cifs: Replace...
1357
  	free_xid(xid);
ce634ab28   David Howells   iget: stop CIFS f...
1358
  	return inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1359
  }
ed6875e0d   Pavel Shilovsky   CIFS: Move unlink...
1360
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1361
  cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
f6f1f1790   Al Viro   cifs: constify pa...
1362
  		   const char *full_path, __u32 dosattr)
388e57b27   Steve French   [CIFS] use common...
1363
  {
388e57b27   Steve French   [CIFS] use common...
1364
  	bool set_time = false;
388e57b27   Steve French   [CIFS] use common...
1365
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
6bdf6dbd6   Pavel Shilovsky   CIFS: Move set_fi...
1366
  	struct TCP_Server_Info *server;
388e57b27   Steve French   [CIFS] use common...
1367
  	FILE_BASIC_INFO	info_buf;
1adcb7109   Steve French   [CIFS] add extra ...
1368
1369
  	if (attrs == NULL)
  		return -EINVAL;
6bdf6dbd6   Pavel Shilovsky   CIFS: Move set_fi...
1370
1371
1372
  	server = cifs_sb_master_tcon(cifs_sb)->ses->server;
  	if (!server->ops->set_file_info)
  		return -ENOSYS;
fd09b7d3b   Steve French   smb3: Do not send...
1373
  	info_buf.Pad = 0;
388e57b27   Steve French   [CIFS] use common...
1374
1375
1376
  	if (attrs->ia_valid & ATTR_ATIME) {
  		set_time = true;
  		info_buf.LastAccessTime =
95390201e   Arnd Bergmann   cifs: use timespe...
1377
  			cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
388e57b27   Steve French   [CIFS] use common...
1378
1379
1380
1381
1382
1383
  	} else
  		info_buf.LastAccessTime = 0;
  
  	if (attrs->ia_valid & ATTR_MTIME) {
  		set_time = true;
  		info_buf.LastWriteTime =
95390201e   Arnd Bergmann   cifs: use timespe...
1384
  		    cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
388e57b27   Steve French   [CIFS] use common...
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
  	} 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)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1395
1396
  		cifs_dbg(FYI, "CIFS - CTIME changed
  ");
388e57b27   Steve French   [CIFS] use common...
1397
  		info_buf.ChangeTime =
95390201e   Arnd Bergmann   cifs: use timespe...
1398
  		    cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
388e57b27   Steve French   [CIFS] use common...
1399
1400
1401
1402
1403
  	} else
  		info_buf.ChangeTime = 0;
  
  	info_buf.CreationTime = 0;	/* don't change */
  	info_buf.Attributes = cpu_to_le32(dosattr);
6bdf6dbd6   Pavel Shilovsky   CIFS: Move set_fi...
1404
  	return server->ops->set_file_info(inode, full_path, &info_buf, xid);
388e57b27   Steve French   [CIFS] use common...
1405
  }
a12a1ac7a   Jeff Layton   cifs: move rename...
1406
  /*
ed6875e0d   Pavel Shilovsky   CIFS: Move unlink...
1407
   * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
a12a1ac7a   Jeff Layton   cifs: move rename...
1408
1409
1410
   * and rename it to a random name that hopefully won't conflict with
   * anything else.
   */
ed6875e0d   Pavel Shilovsky   CIFS: Move unlink...
1411
1412
1413
  int
  cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
  			   const unsigned int xid)
a12a1ac7a   Jeff Layton   cifs: move rename...
1414
1415
1416
  {
  	int oplock = 0;
  	int rc;
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1417
1418
  	struct cifs_fid fid;
  	struct cifs_open_parms oparms;
2b0143b5c   David Howells   VFS: normal files...
1419
  	struct inode *inode = d_inode(dentry);
a12a1ac7a   Jeff Layton   cifs: move rename...
1420
1421
  	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
1422
  	struct tcon_link *tlink;
96daf2b09   Steve French   [CIFS] Rename thr...
1423
  	struct cifs_tcon *tcon;
3270958b7   Steve French   [CIFS] undo chang...
1424
1425
  	__u32 dosattr, origattr;
  	FILE_BASIC_INFO *info_buf = NULL;
a12a1ac7a   Jeff Layton   cifs: move rename...
1426

7ffec3724   Jeff Layton   cifs: add refcoun...
1427
1428
1429
1430
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
  	tcon = tlink_tcon(tlink);
c483a9841   Sachin Prabhu   cifs: Check serve...
1431
1432
1433
1434
1435
1436
1437
1438
  	/*
  	 * 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;
  	}
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1439
1440
1441
  	oparms.tcon = tcon;
  	oparms.cifs_sb = cifs_sb;
  	oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
0f060936e   Amir Goldstein   SMB3: Backup inte...
1442
  	oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1443
1444
1445
1446
1447
1448
  	oparms.disposition = FILE_OPEN;
  	oparms.path = full_path;
  	oparms.fid = &fid;
  	oparms.reconnect = false;
  
  	rc = CIFS_open(xid, &oparms, &oplock, NULL);
a12a1ac7a   Jeff Layton   cifs: move rename...
1449
1450
  	if (rc != 0)
  		goto out;
3270958b7   Steve French   [CIFS] undo chang...
1451
1452
1453
1454
1455
  	origattr = cifsInode->cifsAttrs;
  	if (origattr == 0)
  		origattr |= ATTR_NORMAL;
  
  	dosattr = origattr & ~ATTR_READONLY;
a12a1ac7a   Jeff Layton   cifs: move rename...
1456
1457
1458
  	if (dosattr == 0)
  		dosattr |= ATTR_NORMAL;
  	dosattr |= ATTR_HIDDEN;
3270958b7   Steve French   [CIFS] undo chang...
1459
1460
1461
1462
1463
1464
1465
1466
  	/* 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);
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1467
  		rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
3270958b7   Steve French   [CIFS] undo chang...
1468
1469
1470
  					current->tgid);
  		/* although we would like to mark the file hidden
   		   if that fails we will still try to rename it */
72d282dc5   Sachin Prabhu   cifs: Fix bug whe...
1471
  		if (!rc)
3270958b7   Steve French   [CIFS] undo chang...
1472
1473
1474
  			cifsInode->cifsAttrs = dosattr;
  		else
  			dosattr = origattr; /* since not able to change them */
a12a1ac7a   Jeff Layton   cifs: move rename...
1475
  	}
a12a1ac7a   Jeff Layton   cifs: move rename...
1476

dd1db2ded   Jeff Layton   cifs: don't use C...
1477
  	/* rename the file */
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1478
1479
  	rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
  				   cifs_sb->local_nls,
2baa26825   Steve French   Remap reserved po...
1480
  				   cifs_remap(cifs_sb));
3270958b7   Steve French   [CIFS] undo chang...
1481
  	if (rc != 0) {
47c78f4a7   Sachin Prabhu   cifs: map NT_STAT...
1482
  		rc = -EBUSY;
3270958b7   Steve French   [CIFS] undo chang...
1483
1484
  		goto undo_setattr;
  	}
6d22f0989   Jeff Layton   cifs: add functio...
1485

3270958b7   Steve French   [CIFS] undo chang...
1486
  	/* try to set DELETE_ON_CLOSE */
aff8d5ca7   Jeff Layton   cifs: convert boo...
1487
  	if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1488
  		rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
3270958b7   Steve French   [CIFS] undo chang...
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
  					       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) {
47c78f4a7   Sachin Prabhu   cifs: map NT_STAT...
1501
  			rc = -EBUSY;
3270958b7   Steve French   [CIFS] undo chang...
1502
1503
  			goto undo_rename;
  		}
aff8d5ca7   Jeff Layton   cifs: convert boo...
1504
  		set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
3270958b7   Steve French   [CIFS] undo chang...
1505
  	}
7ce86d5a9   Jeff Layton   cifs: work around...
1506

a12a1ac7a   Jeff Layton   cifs: move rename...
1507
  out_close:
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1508
  	CIFSSMBClose(xid, tcon, fid.netfid);
a12a1ac7a   Jeff Layton   cifs: move rename...
1509
  out:
3270958b7   Steve French   [CIFS] undo chang...
1510
  	kfree(info_buf);
7ffec3724   Jeff Layton   cifs: add refcoun...
1511
  	cifs_put_tlink(tlink);
a12a1ac7a   Jeff Layton   cifs: move rename...
1512
  	return rc;
3270958b7   Steve French   [CIFS] undo chang...
1513
1514
1515
1516
1517
1518
1519
  
  	/*
  	 * 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:
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1520
  	CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
2baa26825   Steve French   Remap reserved po...
1521
  				cifs_sb->local_nls, cifs_remap(cifs_sb));
3270958b7   Steve French   [CIFS] undo chang...
1522
1523
1524
  undo_setattr:
  	if (dosattr != origattr) {
  		info_buf->Attributes = cpu_to_le32(origattr);
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1525
  		if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
3270958b7   Steve French   [CIFS] undo chang...
1526
1527
1528
1529
1530
  					current->tgid))
  			cifsInode->cifsAttrs = origattr;
  	}
  
  	goto out_close;
a12a1ac7a   Jeff Layton   cifs: move rename...
1531
  }
b7ca69289   Steve French   CIFS: Protect i_n...
1532
1533
1534
1535
1536
1537
1538
1539
1540
  /* 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);
  }
ff6945279   Steve French   [CIFS] Make cifs_...
1541
1542
  
  /*
2b0143b5c   David Howells   VFS: normal files...
1543
   * If d_inode(dentry) is null (usually meaning the cached dentry
ff6945279   Steve French   [CIFS] Make cifs_...
1544
   * is a negative dentry) then we would attempt a standard SMB delete, but
413d61008   Colin Ian King   cifs: fix spellin...
1545
1546
   * 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
ff6945279   Steve French   [CIFS] Make cifs_...
1547
1548
   * unlink on negative dentries currently.
   */
5f0319a79   Jeff Layton   cifs: clean up va...
1549
  int cifs_unlink(struct inode *dir, struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1550
1551
  {
  	int rc = 0;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1552
  	unsigned int xid;
f6a9bc336   Al Viro   cifs: allocate bu...
1553
1554
  	const char *full_path;
  	void *page;
2b0143b5c   David Howells   VFS: normal files...
1555
  	struct inode *inode = d_inode(dentry);
ff6945279   Steve French   [CIFS] Make cifs_...
1556
  	struct cifsInodeInfo *cifs_inode;
5f0319a79   Jeff Layton   cifs: clean up va...
1557
1558
  	struct super_block *sb = dir->i_sb;
  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
1559
  	struct tcon_link *tlink;
96daf2b09   Steve French   [CIFS] Rename thr...
1560
  	struct cifs_tcon *tcon;
ed6875e0d   Pavel Shilovsky   CIFS: Move unlink...
1561
  	struct TCP_Server_Info *server;
6050247d8   Steve French   [CIFS] clean up ...
1562
1563
  	struct iattr *attrs = NULL;
  	__u32 dosattr = 0, origattr = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1564

f96637be0   Joe Perches   [CIFS] cifs: Rena...
1565
1566
  	cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p
  ", dir, dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1567

087f757b0   Steve French   cifs: add shutdow...
1568
1569
  	if (unlikely(cifs_forced_shutdown(cifs_sb)))
  		return -EIO;
7ffec3724   Jeff Layton   cifs: add refcoun...
1570
1571
1572
1573
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
  	tcon = tlink_tcon(tlink);
ed6875e0d   Pavel Shilovsky   CIFS: Move unlink...
1574
  	server = tcon->ses->server;
7ffec3724   Jeff Layton   cifs: add refcoun...
1575

6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1576
  	xid = get_xid();
f6a9bc336   Al Viro   cifs: allocate bu...
1577
  	page = alloc_dentry_path();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1578

82e9367c4   Steve French   smb3: Add new par...
1579
1580
1581
1582
  	if (tcon->nodelete) {
  		rc = -EACCES;
  		goto unlink_out;
  	}
5f0319a79   Jeff Layton   cifs: clean up va...
1583
1584
  	/* Unlink can be called from rename so we can not take the
  	 * sb->s_vfs_rename_mutex here */
f6a9bc336   Al Viro   cifs: allocate bu...
1585
1586
1587
  	full_path = build_path_from_dentry(dentry, page);
  	if (IS_ERR(full_path)) {
  		rc = PTR_ERR(full_path);
7ffec3724   Jeff Layton   cifs: add refcoun...
1588
  		goto unlink_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1589
  	}
2d785a50a   Steve French   [CIFS] Add suppor...
1590

e3fc06568   Rohith Surabattula   cifs: Deferred cl...
1591
  	cifs_close_deferred_file_under_dentry(tcon, full_path);
29e20f9c6   Pavel Shilovsky   CIFS: Make CAP_* ...
1592
1593
  	if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
  				le64_to_cpu(tcon->fsUnixInfo.Capability))) {
5f0319a79   Jeff Layton   cifs: clean up va...
1594
  		rc = CIFSPOSIXDelFile(xid, tcon, full_path,
2d785a50a   Steve French   [CIFS] Add suppor...
1595
  			SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
2baa26825   Steve French   Remap reserved po...
1596
  			cifs_remap(cifs_sb));
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1597
1598
  		cifs_dbg(FYI, "posix del rc %d
  ", rc);
2d785a50a   Steve French   [CIFS] Add suppor...
1599
1600
1601
  		if ((rc == 0) || (rc == -ENOENT))
  			goto psx_del_no_retry;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1602

6050247d8   Steve French   [CIFS] clean up ...
1603
  retry_std_delete:
ed6875e0d   Pavel Shilovsky   CIFS: Move unlink...
1604
1605
1606
1607
1608
1609
  	if (!server->ops->unlink) {
  		rc = -ENOSYS;
  		goto psx_del_no_retry;
  	}
  
  	rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
6050247d8   Steve French   [CIFS] clean up ...
1610

2d785a50a   Steve French   [CIFS] Add suppor...
1611
  psx_del_no_retry:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1612
  	if (!rc) {
5f0319a79   Jeff Layton   cifs: clean up va...
1613
  		if (inode)
b7ca69289   Steve French   CIFS: Protect i_n...
1614
  			cifs_drop_nlink(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1615
  	} else if (rc == -ENOENT) {
5f0319a79   Jeff Layton   cifs: clean up va...
1616
  		d_drop(dentry);
47c78f4a7   Sachin Prabhu   cifs: map NT_STAT...
1617
  	} else if (rc == -EBUSY) {
ed6875e0d   Pavel Shilovsky   CIFS: Move unlink...
1618
1619
1620
1621
1622
1623
  		if (server->ops->rename_pending_delete) {
  			rc = server->ops->rename_pending_delete(full_path,
  								dentry, xid);
  			if (rc == 0)
  				cifs_drop_nlink(inode);
  		}
ff6945279   Steve French   [CIFS] Make cifs_...
1624
  	} else if ((rc == -EACCES) && (dosattr == 0) && inode) {
388e57b27   Steve French   [CIFS] use common...
1625
1626
1627
1628
  		attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
  		if (attrs == NULL) {
  			rc = -ENOMEM;
  			goto out_reval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1629
  		}
388e57b27   Steve French   [CIFS] use common...
1630
1631
  
  		/* try to reset dos attributes */
ff6945279   Steve French   [CIFS] Make cifs_...
1632
1633
  		cifs_inode = CIFS_I(inode);
  		origattr = cifs_inode->cifsAttrs;
6050247d8   Steve French   [CIFS] clean up ...
1634
1635
1636
  		if (origattr == 0)
  			origattr |= ATTR_NORMAL;
  		dosattr = origattr & ~ATTR_READONLY;
388e57b27   Steve French   [CIFS] use common...
1637
1638
1639
1640
1641
  		if (dosattr == 0)
  			dosattr |= ATTR_NORMAL;
  		dosattr |= ATTR_HIDDEN;
  
  		rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
388e57b27   Steve French   [CIFS] use common...
1642
1643
  		if (rc != 0)
  			goto out_reval;
6050247d8   Steve French   [CIFS] clean up ...
1644
1645
  
  		goto retry_std_delete;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1646
  	}
6050247d8   Steve French   [CIFS] clean up ...
1647
1648
1649
1650
  
  	/* 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);
388e57b27   Steve French   [CIFS] use common...
1651
  out_reval:
4523cc304   Steve French   [CIFS] UID/GID ov...
1652
  	if (inode) {
ff6945279   Steve French   [CIFS] Make cifs_...
1653
1654
  		cifs_inode = CIFS_I(inode);
  		cifs_inode->time = 0;	/* will force revalidate to get info
5f0319a79   Jeff Layton   cifs: clean up va...
1655
  					   when needed */
e37fea58f   Deepa Dinamani   fs: cifs: replace...
1656
  		inode->i_ctime = current_time(inode);
06bcfedd0   Steve French   [CIFS] Fix typo i...
1657
  	}
e37fea58f   Deepa Dinamani   fs: cifs: replace...
1658
  	dir->i_ctime = dir->i_mtime = current_time(dir);
ff6945279   Steve French   [CIFS] Make cifs_...
1659
  	cifs_inode = CIFS_I(dir);
6050247d8   Steve French   [CIFS] clean up ...
1660
  	CIFS_I(dir)->time = 0;	/* force revalidate of dir as well */
7ffec3724   Jeff Layton   cifs: add refcoun...
1661
  unlink_out:
f6a9bc336   Al Viro   cifs: allocate bu...
1662
  	free_dentry_path(page);
6050247d8   Steve French   [CIFS] clean up ...
1663
  	kfree(attrs);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1664
  	free_xid(xid);
7ffec3724   Jeff Layton   cifs: add refcoun...
1665
  	cifs_put_tlink(tlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1666
1667
  	return rc;
  }
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1668
  static int
101b92d95   Jeff Layton   cifs: cleanups fo...
1669
  cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1670
1671
1672
1673
  		 const char *full_path, struct cifs_sb_info *cifs_sb,
  		 struct cifs_tcon *tcon, const unsigned int xid)
  {
  	int rc = 0;
101b92d95   Jeff Layton   cifs: cleanups fo...
1674
  	struct inode *inode = NULL;
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1675

d313852d7   Steve French   smb311: add suppo...
1676
1677
1678
  	if (tcon->posix_extensions)
  		rc = smb311_posix_get_inode_info(&inode, full_path, parent->i_sb, xid);
  	else if (tcon->unix_ext)
101b92d95   Jeff Layton   cifs: cleanups fo...
1679
  		rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1680
1681
  					      xid);
  	else
101b92d95   Jeff Layton   cifs: cleanups fo...
1682
1683
  		rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
  					 xid, NULL);
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1684
1685
  	if (rc)
  		return rc;
3bcb39b08   Al Viro   cifs: have ->mkdi...
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
  	if (!S_ISDIR(inode->i_mode)) {
  		/*
  		 * mkdir succeeded, but another client has managed to remove the
  		 * sucker and replace it with non-directory.  Return success,
  		 * but don't leave the child in dcache.
  		 */
  		 iput(inode);
  		 d_drop(dentry);
  		 return 0;
  	}
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1696
1697
  	/*
  	 * setting nlink not necessary except in cases where we failed to get it
101b92d95   Jeff Layton   cifs: cleanups fo...
1698
1699
  	 * 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.
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1700
  	 */
101b92d95   Jeff Layton   cifs: cleanups fo...
1701
1702
  	if (inode->i_nlink < 2)
  		set_nlink(inode, 2);
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1703
1704
  	mode &= ~current_umask();
  	/* must turn on setgid bit if parent dir has it */
101b92d95   Jeff Layton   cifs: cleanups fo...
1705
  	if (parent->i_mode & S_ISGID)
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
  		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) {
49418b2c2   Eric W. Biederman   cifs: Modify stru...
1717
  			args.uid = current_fsuid();
101b92d95   Jeff Layton   cifs: cleanups fo...
1718
  			if (parent->i_mode & S_ISGID)
49418b2c2   Eric W. Biederman   cifs: Modify stru...
1719
  				args.gid = parent->i_gid;
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1720
  			else
49418b2c2   Eric W. Biederman   cifs: Modify stru...
1721
  				args.gid = current_fsgid();
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1722
  		} else {
49418b2c2   Eric W. Biederman   cifs: Modify stru...
1723
1724
  			args.uid = INVALID_UID; /* no change */
  			args.gid = INVALID_GID; /* no change */
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1725
1726
1727
  		}
  		CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
  				       cifs_sb->local_nls,
2baa26825   Steve French   Remap reserved po...
1728
  				       cifs_remap(cifs_sb));
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1729
  	} else {
f436720e9   Pavel Shilovsky   CIFS: Separate pr...
1730
  		struct TCP_Server_Info *server = tcon->ses->server;
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1731
  		if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
f436720e9   Pavel Shilovsky   CIFS: Separate pr...
1732
  		    (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
101b92d95   Jeff Layton   cifs: cleanups fo...
1733
  			server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
f436720e9   Pavel Shilovsky   CIFS: Separate pr...
1734
  						   tcon, xid);
101b92d95   Jeff Layton   cifs: cleanups fo...
1735
1736
1737
1738
1739
1740
1741
1742
1743
  		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();
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1744
1745
  		}
  	}
101b92d95   Jeff Layton   cifs: cleanups fo...
1746
  	d_instantiate(dentry, inode);
3bcb39b08   Al Viro   cifs: have ->mkdi...
1747
  	return 0;
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
  }
  
  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,
2baa26825   Steve French   Remap reserved po...
1770
  			     cifs_sb->local_nls, cifs_remap(cifs_sb));
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1771
1772
1773
  	if (rc == -EOPNOTSUPP)
  		goto posix_mkdir_out;
  	else if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1774
1775
  		cifs_dbg(FYI, "posix mkdir returned 0x%x
  ", rc);
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
  		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
35c265e00   Al Viro   cifs: switch to u...
1797
1798
1799
  	cifs_dbg(FYI, "instantiated dentry %p %pd to inode %p
  ",
  		 dentry, dentry, newinode);
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1800
1801
  
  	if (newinode->i_nlink != 2)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1802
1803
1804
  		cifs_dbg(FYI, "unexpected number of links %d
  ",
  			 newinode->i_nlink);
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
  #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;
  }
549c72977   Christian Brauner   fs: make helpers ...
1815
1816
  int cifs_mkdir(struct user_namespace *mnt_userns, struct inode *inode,
  	       struct dentry *direntry, umode_t mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1817
  {
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1818
  	int rc = 0;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1819
  	unsigned int xid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1820
  	struct cifs_sb_info *cifs_sb;
7ffec3724   Jeff Layton   cifs: add refcoun...
1821
  	struct tcon_link *tlink;
29e20f9c6   Pavel Shilovsky   CIFS: Make CAP_* ...
1822
  	struct cifs_tcon *tcon;
f436720e9   Pavel Shilovsky   CIFS: Separate pr...
1823
  	struct TCP_Server_Info *server;
8e33cf20c   Al Viro   cifs: make build_...
1824
  	const char *full_path;
f6a9bc336   Al Viro   cifs: allocate bu...
1825
  	void *page;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1826

f52aa79df   Frank Sorenson   cifs: Fix mode ou...
1827
1828
  	cifs_dbg(FYI, "In cifs_mkdir, mode = %04ho inode = 0x%p
  ",
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1829
  		 mode, inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1830

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1831
  	cifs_sb = CIFS_SB(inode->i_sb);
087f757b0   Steve French   cifs: add shutdow...
1832
1833
  	if (unlikely(cifs_forced_shutdown(cifs_sb)))
  		return -EIO;
7ffec3724   Jeff Layton   cifs: add refcoun...
1834
1835
1836
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
29e20f9c6   Pavel Shilovsky   CIFS: Make CAP_* ...
1837
  	tcon = tlink_tcon(tlink);
7ffec3724   Jeff Layton   cifs: add refcoun...
1838

6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1839
  	xid = get_xid();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1840

f6a9bc336   Al Viro   cifs: allocate bu...
1841
1842
1843
1844
  	page = alloc_dentry_path();
  	full_path = build_path_from_dentry(direntry, page);
  	if (IS_ERR(full_path)) {
  		rc = PTR_ERR(full_path);
7ffec3724   Jeff Layton   cifs: add refcoun...
1845
  		goto mkdir_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1846
  	}
50c2f7538   Steve French   [CIFS] whitespace...
1847

bea851b8b   Steve French   smb3: Fix mode on...
1848
  	server = tcon->ses->server;
bea851b8b   Steve French   smb3: Fix mode on...
1849
1850
1851
1852
1853
1854
  	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;
  	}
bea851b8b   Steve French   smb3: Fix mode on...
1855

29e20f9c6   Pavel Shilovsky   CIFS: Make CAP_* ...
1856
1857
  	if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
  				le64_to_cpu(tcon->fsUnixInfo.Capability))) {
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1858
1859
1860
  		rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
  				      tcon, xid);
  		if (rc != -EOPNOTSUPP)
2dd29d313   Steve French   [CIFS] New CIFS P...
1861
  			goto mkdir_out;
fb8c4b14d   Steve French   [CIFS] whitespace...
1862
  	}
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1863

f436720e9   Pavel Shilovsky   CIFS: Separate pr...
1864
1865
1866
1867
  	if (!server->ops->mkdir) {
  		rc = -ENOSYS;
  		goto mkdir_out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1868
  	/* BB add setting the equivalent of mode via CreateX w/ACLs */
c3ca78e21   Steve French   smb3: pass mode b...
1869
  	rc = server->ops->mkdir(xid, inode, mode, tcon, full_path, cifs_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1870
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1871
1872
  		cifs_dbg(FYI, "cifs_mkdir returned 0x%x
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1873
  		d_drop(direntry);
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1874
  		goto mkdir_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1875
  	}
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1876

c3ca78e21   Steve French   smb3: pass mode b...
1877
  	/* TODO: skip this for smb2/smb3 */
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1878
1879
  	rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
  			      xid);
fb8c4b14d   Steve French   [CIFS] whitespace...
1880
  mkdir_out:
6de2ce423   Pavel Shilovsky   CIFS: Fix mkdir/r...
1881
1882
1883
1884
1885
  	/*
  	 * Force revalidate to get parent dir info when needed since cached
  	 * attributes are invalid now.
  	 */
  	CIFS_I(inode)->time = 0;
f6a9bc336   Al Viro   cifs: allocate bu...
1886
  	free_dentry_path(page);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1887
  	free_xid(xid);
7ffec3724   Jeff Layton   cifs: add refcoun...
1888
  	cifs_put_tlink(tlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1889
1890
1891
1892
1893
1894
  	return rc;
  }
  
  int cifs_rmdir(struct inode *inode, struct dentry *direntry)
  {
  	int rc = 0;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1895
  	unsigned int xid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1896
  	struct cifs_sb_info *cifs_sb;
7ffec3724   Jeff Layton   cifs: add refcoun...
1897
  	struct tcon_link *tlink;
f958ca5d8   Pavel Shilovsky   CIFS: Move rmdir ...
1898
1899
  	struct cifs_tcon *tcon;
  	struct TCP_Server_Info *server;
f6a9bc336   Al Viro   cifs: allocate bu...
1900
1901
  	const char *full_path;
  	void *page = alloc_dentry_path();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1902
  	struct cifsInodeInfo *cifsInode;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1903
1904
  	cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p
  ", inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1905

6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1906
  	xid = get_xid();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1907

f6a9bc336   Al Viro   cifs: allocate bu...
1908
1909
1910
  	full_path = build_path_from_dentry(direntry, page);
  	if (IS_ERR(full_path)) {
  		rc = PTR_ERR(full_path);
7ffec3724   Jeff Layton   cifs: add refcoun...
1911
  		goto rmdir_exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1912
  	}
7ffec3724   Jeff Layton   cifs: add refcoun...
1913
  	cifs_sb = CIFS_SB(inode->i_sb);
087f757b0   Steve French   cifs: add shutdow...
1914
1915
1916
1917
  	if (unlikely(cifs_forced_shutdown(cifs_sb))) {
  		rc = -EIO;
  		goto rmdir_exit;
  	}
7ffec3724   Jeff Layton   cifs: add refcoun...
1918
1919
1920
1921
1922
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink)) {
  		rc = PTR_ERR(tlink);
  		goto rmdir_exit;
  	}
f958ca5d8   Pavel Shilovsky   CIFS: Move rmdir ...
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;
  	}
7ffec3724   Jeff Layton   cifs: add refcoun...
1931

82e9367c4   Steve French   smb3: Add new par...
1932
1933
1934
1935
1936
  	if (tcon->nodelete) {
  		rc = -EACCES;
  		cifs_put_tlink(tlink);
  		goto rmdir_exit;
  	}
f958ca5d8   Pavel Shilovsky   CIFS: Move rmdir ...
1937
  	rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
1938
  	cifs_put_tlink(tlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1939
1940
  
  	if (!rc) {
2b0143b5c   David Howells   VFS: normal files...
1941
1942
1943
1944
  		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);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1945
  	}
2b0143b5c   David Howells   VFS: normal files...
1946
  	cifsInode = CIFS_I(d_inode(direntry));
6de2ce423   Pavel Shilovsky   CIFS: Fix mkdir/r...
1947
1948
  	/* force revalidate to go get info when needed */
  	cifsInode->time = 0;
42c245447   Steve French   [CIFS] revalidate...
1949
1950
  
  	cifsInode = CIFS_I(inode);
6de2ce423   Pavel Shilovsky   CIFS: Fix mkdir/r...
1951
1952
1953
1954
1955
  	/*
  	 * Force revalidate to get parent dir info when needed since cached
  	 * attributes are invalid now.
  	 */
  	cifsInode->time = 0;
42c245447   Steve French   [CIFS] revalidate...
1956

2b0143b5c   David Howells   VFS: normal files...
1957
  	d_inode(direntry)->i_ctime = inode->i_ctime = inode->i_mtime =
e37fea58f   Deepa Dinamani   fs: cifs: replace...
1958
  		current_time(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1959

7ffec3724   Jeff Layton   cifs: add refcoun...
1960
  rmdir_exit:
f6a9bc336   Al Viro   cifs: allocate bu...
1961
  	free_dentry_path(page);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1962
  	free_xid(xid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1963
1964
  	return rc;
  }
ee2fd967f   Steve French   [CIFS] fix busy-...
1965
  static int
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1966
1967
1968
  cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
  	       const char *from_path, struct dentry *to_dentry,
  	       const char *to_path)
ee2fd967f   Steve French   [CIFS] fix busy-...
1969
1970
  {
  	struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
1971
  	struct tcon_link *tlink;
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1972
1973
  	struct cifs_tcon *tcon;
  	struct TCP_Server_Info *server;
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1974
1975
  	struct cifs_fid fid;
  	struct cifs_open_parms oparms;
ee2fd967f   Steve French   [CIFS] fix busy-...
1976
  	int oplock, rc;
7ffec3724   Jeff Layton   cifs: add refcoun...
1977
1978
1979
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1980
1981
1982
1983
1984
  	tcon = tlink_tcon(tlink);
  	server = tcon->ses->server;
  
  	if (!server->ops->rename)
  		return -ENOSYS;
7ffec3724   Jeff Layton   cifs: add refcoun...
1985

ee2fd967f   Steve French   [CIFS] fix busy-...
1986
  	/* try path-based rename first */
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1987
  	rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
ee2fd967f   Steve French   [CIFS] fix busy-...
1988
1989
  
  	/*
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1990
1991
  	 * Don't bother with rename by filehandle unless file is busy and
  	 * source. Note that cross directory moves do not work with
ee2fd967f   Steve French   [CIFS] fix busy-...
1992
1993
  	 * rename by filehandle to various Windows servers.
  	 */
47c78f4a7   Sachin Prabhu   cifs: map NT_STAT...
1994
  	if (rc == 0 || rc != -EBUSY)
7ffec3724   Jeff Layton   cifs: add refcoun...
1995
  		goto do_rename_exit;
ee2fd967f   Steve French   [CIFS] fix busy-...
1996

652727bbe   Frank Sorenson   cifs: do not atte...
1997
1998
1999
  	/* Don't fall back to using SMB on SMB 2+ mount */
  	if (server->vals->protocol_id != 0)
  		goto do_rename_exit;
ed0e3ace5   Jeff Layton   cifs: don't attem...
2000
2001
  	/* open-file renames don't work across directories */
  	if (to_dentry->d_parent != from_dentry->d_parent)
7ffec3724   Jeff Layton   cifs: add refcoun...
2002
  		goto do_rename_exit;
ed0e3ace5   Jeff Layton   cifs: don't attem...
2003

d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
2004
2005
  	oparms.tcon = tcon;
  	oparms.cifs_sb = cifs_sb;
ee2fd967f   Steve French   [CIFS] fix busy-...
2006
  	/* open the file to be renamed -- we need DELETE perms */
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
2007
  	oparms.desired_access = DELETE;
0f060936e   Amir Goldstein   SMB3: Backup inte...
2008
  	oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
2009
2010
2011
2012
2013
2014
  	oparms.disposition = FILE_OPEN;
  	oparms.path = from_path;
  	oparms.fid = &fid;
  	oparms.reconnect = false;
  
  	rc = CIFS_open(xid, &oparms, &oplock, NULL);
ee2fd967f   Steve French   [CIFS] fix busy-...
2015
  	if (rc == 0) {
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
2016
  		rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
ee2fd967f   Steve French   [CIFS] fix busy-...
2017
  				(const char *) to_dentry->d_name.name,
2baa26825   Steve French   Remap reserved po...
2018
  				cifs_sb->local_nls, cifs_remap(cifs_sb));
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
2019
  		CIFSSMBClose(xid, tcon, fid.netfid);
ee2fd967f   Steve French   [CIFS] fix busy-...
2020
  	}
7ffec3724   Jeff Layton   cifs: add refcoun...
2021
  do_rename_exit:
c7e9f78f7   Steve French   cifs: do d_move i...
2022
2023
  	if (rc == 0)
  		d_move(from_dentry, to_dentry);
7ffec3724   Jeff Layton   cifs: add refcoun...
2024
  	cifs_put_tlink(tlink);
ee2fd967f   Steve French   [CIFS] fix busy-...
2025
2026
  	return rc;
  }
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
2027
  int
549c72977   Christian Brauner   fs: make helpers ...
2028
2029
2030
  cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
  	     struct dentry *source_dentry, struct inode *target_dir,
  	     struct dentry *target_dentry, unsigned int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2031
  {
f6a9bc336   Al Viro   cifs: allocate bu...
2032
2033
  	const char *from_name, *to_name;
  	void *page1, *page2;
639e7a913   Jeff Layton   cifs: eliminate r...
2034
  	struct cifs_sb_info *cifs_sb;
7ffec3724   Jeff Layton   cifs: add refcoun...
2035
  	struct tcon_link *tlink;
96daf2b09   Steve French   [CIFS] Rename thr...
2036
  	struct cifs_tcon *tcon;
ee2fd967f   Steve French   [CIFS] fix busy-...
2037
2038
  	FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
  	FILE_UNIX_BASIC_INFO *info_buf_target;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2039
2040
  	unsigned int xid;
  	int rc, tmprc;
41535701d   Rohith Surabattula   cifs: Handle race...
2041
  	int retry_count = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2042

7c33d5972   Miklos Szeredi   cifs: support REN...
2043
2044
  	if (flags & ~RENAME_NOREPLACE)
  		return -EINVAL;
639e7a913   Jeff Layton   cifs: eliminate r...
2045
  	cifs_sb = CIFS_SB(source_dir->i_sb);
087f757b0   Steve French   cifs: add shutdow...
2046
2047
  	if (unlikely(cifs_forced_shutdown(cifs_sb)))
  		return -EIO;
7ffec3724   Jeff Layton   cifs: add refcoun...
2048
2049
2050
2051
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
  	tcon = tlink_tcon(tlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2052

f6a9bc336   Al Viro   cifs: allocate bu...
2053
2054
  	page1 = alloc_dentry_path();
  	page2 = alloc_dentry_path();
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2055
  	xid = get_xid();
ee2fd967f   Steve French   [CIFS] fix busy-...
2056

f6a9bc336   Al Viro   cifs: allocate bu...
2057
2058
2059
  	from_name = build_path_from_dentry(source_dentry, page1);
  	if (IS_ERR(from_name)) {
  		rc = PTR_ERR(from_name);
ee2fd967f   Steve French   [CIFS] fix busy-...
2060
2061
  		goto cifs_rename_exit;
  	}
f6a9bc336   Al Viro   cifs: allocate bu...
2062
2063
2064
  	to_name = build_path_from_dentry(target_dentry, page2);
  	if (IS_ERR(to_name)) {
  		rc = PTR_ERR(to_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2065
2066
  		goto cifs_rename_exit;
  	}
e3fc06568   Rohith Surabattula   cifs: Deferred cl...
2067
  	cifs_close_deferred_file_under_dentry(tcon, from_name);
41535701d   Rohith Surabattula   cifs: Handle race...
2068
  	if (d_inode(target_dentry) != NULL)
e3fc06568   Rohith Surabattula   cifs: Deferred cl...
2069
  		cifs_close_deferred_file_under_dentry(tcon, to_name);
41535701d   Rohith Surabattula   cifs: Handle race...
2070

8ceb98437   Pavel Shilovsky   CIFS: Move rename...
2071
2072
  	rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
  			    to_name);
ee2fd967f   Steve French   [CIFS] fix busy-...
2073

41535701d   Rohith Surabattula   cifs: Handle race...
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
  	if (rc == -EACCES) {
  		while (retry_count < 3) {
  			cifs_close_all_deferred_files(tcon);
  			rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
  					    to_name);
  			if (rc != -EACCES)
  				break;
  			retry_count++;
  		}
  	}
7c33d5972   Miklos Szeredi   cifs: support REN...
2084
2085
2086
2087
2088
  	/*
  	 * No-replace is the natural behavior for CIFS, so skip unlink hacks.
  	 */
  	if (flags & RENAME_NOREPLACE)
  		goto cifs_rename_exit;
14121bdcc   Jeff Layton   cifs: make cifs_r...
2089
2090
  	if (rc == -EEXIST && tcon->unix_ext) {
  		/*
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
2091
2092
  		 * Are src and dst hardlinks of same inode? We can only tell
  		 * with unix extensions enabled.
14121bdcc   Jeff Layton   cifs: make cifs_r...
2093
2094
  		 */
  		info_buf_source =
6da2ec560   Kees Cook   treewide: kmalloc...
2095
  			kmalloc_array(2, sizeof(FILE_UNIX_BASIC_INFO),
14121bdcc   Jeff Layton   cifs: make cifs_r...
2096
2097
2098
2099
2100
2101
2102
  					GFP_KERNEL);
  		if (info_buf_source == NULL) {
  			rc = -ENOMEM;
  			goto cifs_rename_exit;
  		}
  
  		info_buf_target = info_buf_source + 1;
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
2103
2104
2105
  		tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
  					     info_buf_source,
  					     cifs_sb->local_nls,
2baa26825   Steve French   Remap reserved po...
2106
  					     cifs_remap(cifs_sb));
8d281efb6   Jeff Layton   cifs: fix unlinki...
2107
  		if (tmprc != 0)
14121bdcc   Jeff Layton   cifs: make cifs_r...
2108
  			goto unlink_target;
ee2fd967f   Steve French   [CIFS] fix busy-...
2109

8ceb98437   Pavel Shilovsky   CIFS: Move rename...
2110
2111
2112
  		tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
  					     info_buf_target,
  					     cifs_sb->local_nls,
2baa26825   Steve French   Remap reserved po...
2113
  					     cifs_remap(cifs_sb));
14121bdcc   Jeff Layton   cifs: make cifs_r...
2114

8d281efb6   Jeff Layton   cifs: fix unlinki...
2115
  		if (tmprc == 0 && (info_buf_source->UniqueId ==
ae6884a9d   Jeff Layton   cifs: fix renamin...
2116
  				   info_buf_target->UniqueId)) {
14121bdcc   Jeff Layton   cifs: make cifs_r...
2117
  			/* same file, POSIX says that this is a noop */
ae6884a9d   Jeff Layton   cifs: fix renamin...
2118
  			rc = 0;
14121bdcc   Jeff Layton   cifs: make cifs_r...
2119
  			goto cifs_rename_exit;
ae6884a9d   Jeff Layton   cifs: fix renamin...
2120
  		}
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
2121
2122
2123
2124
2125
  	}
  	/*
  	 * else ... BB we could add the same check for Windows by
  	 * checking the UniqueId via FILE_INTERNAL_INFO
  	 */
14121bdcc   Jeff Layton   cifs: make cifs_r...
2126

ee2fd967f   Steve French   [CIFS] fix busy-...
2127
  unlink_target:
0e6705182   Steve French   Revert "cifs: Fix...
2128
2129
  	/* Try unlinking the target dentry if it's not negative */
  	if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
a07d32205   Pavel Shilovsky   CIFS: Fix directo...
2130
2131
2132
2133
  		if (d_is_dir(target_dentry))
  			tmprc = cifs_rmdir(target_dir, target_dentry);
  		else
  			tmprc = cifs_unlink(target_dir, target_dentry);
14121bdcc   Jeff Layton   cifs: make cifs_r...
2134
2135
  		if (tmprc)
  			goto cifs_rename_exit;
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
2136
2137
  		rc = cifs_do_rename(xid, source_dentry, from_name,
  				    target_dentry, to_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2138
  	}
b46799a8f   Pavel Shilovsky   CIFS: Fix wrong d...
2139
2140
2141
2142
  	/* 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 =
e37fea58f   Deepa Dinamani   fs: cifs: replace...
2143
  		target_dir->i_mtime = current_time(source_dir);
b46799a8f   Pavel Shilovsky   CIFS: Fix wrong d...
2144

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2145
  cifs_rename_exit:
ee2fd967f   Steve French   [CIFS] fix busy-...
2146
  	kfree(info_buf_source);
f6a9bc336   Al Viro   cifs: allocate bu...
2147
2148
  	free_dentry_path(page2);
  	free_dentry_path(page1);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2149
  	free_xid(xid);
7ffec3724   Jeff Layton   cifs: add refcoun...
2150
  	cifs_put_tlink(tlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2151
2152
  	return rc;
  }
df2cf170c   Jeff Layton   cifs: overhaul ci...
2153
  static bool
ed8561fa1   Ronnie Sahlberg   cifs: pass the de...
2154
  cifs_dentry_needs_reval(struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2155
  {
ed8561fa1   Ronnie Sahlberg   cifs: pass the de...
2156
  	struct inode *inode = d_inode(dentry);
df2cf170c   Jeff Layton   cifs: overhaul ci...
2157
  	struct cifsInodeInfo *cifs_i = CIFS_I(inode);
6d20e8406   Suresh Jayaraman   cifs: add attribu...
2158
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
f6d2353a5   Ronnie Sahlberg   cifs: check the t...
2159
2160
  	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
  	struct cached_fid *cfid = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2161

57c55cd7c   Ronnie Sahlberg   cifs: invalidate ...
2162
2163
  	if (cifs_i->time == 0)
  		return true;
18cceb6a7   Pavel Shilovsky   CIFS: Replace cli...
2164
  	if (CIFS_CACHE_READ(cifs_i))
df2cf170c   Jeff Layton   cifs: overhaul ci...
2165
  		return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2166

df2cf170c   Jeff Layton   cifs: overhaul ci...
2167
2168
  	if (!lookupCacheEnabled)
  		return true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2169

f6d2353a5   Ronnie Sahlberg   cifs: check the t...
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
  	if (!open_cached_dir_by_dentry(tcon, dentry->d_parent, &cfid)) {
  		mutex_lock(&cfid->fid_mutex);
  		if (cfid->time && cifs_i->time > cfid->time) {
  			mutex_unlock(&cfid->fid_mutex);
  			close_cached_dir(cfid);
  			return false;
  		}
  		mutex_unlock(&cfid->fid_mutex);
  		close_cached_dir(cfid);
  	}
ddaf6d4a9   Steve French   cifs: convert rev...
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
  	/*
  	 * depending on inode type, check if attribute caching disabled for
  	 * files or directories
  	 */
  	if (S_ISDIR(inode->i_mode)) {
  		if (!cifs_sb->ctx->acdirmax)
  			return true;
  		if (!time_in_range(jiffies, cifs_i->time,
  				   cifs_i->time + cifs_sb->ctx->acdirmax))
  			return true;
  	} else { /* file */
578046461   Steve French   cifs: Add new par...
2191
  		if (!cifs_sb->ctx->acregmax)
ddaf6d4a9   Steve French   cifs: convert rev...
2192
2193
  			return true;
  		if (!time_in_range(jiffies, cifs_i->time,
578046461   Steve French   cifs: Add new par...
2194
  				   cifs_i->time + cifs_sb->ctx->acregmax))
ddaf6d4a9   Steve French   cifs: convert rev...
2195
2196
  			return true;
  	}
df2cf170c   Jeff Layton   cifs: overhaul ci...
2197

db19272ed   Jeff Layton   cifs: always reva...
2198
  	/* hardlinked files w/ noserverino get "special" treatment */
6d20e8406   Suresh Jayaraman   cifs: add attribu...
2199
  	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
db19272ed   Jeff Layton   cifs: always reva...
2200
2201
  	    S_ISREG(inode->i_mode) && inode->i_nlink != 1)
  		return true;
df2cf170c   Jeff Layton   cifs: overhaul ci...
2202
2203
  	return false;
  }
523fb8c86   Suresh Jayaraman   cifs: trivial com...
2204
2205
2206
  /*
   * Zap the cache. Called when invalid_mapping flag is set.
   */
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2207
  int
df2cf170c   Jeff Layton   cifs: overhaul ci...
2208
2209
  cifs_invalidate_mapping(struct inode *inode)
  {
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2210
  	int rc = 0;
df2cf170c   Jeff Layton   cifs: overhaul ci...
2211

df2cf170c   Jeff Layton   cifs: overhaul ci...
2212
  	if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
257fb1f15   Pavel Shilovsky   CIFS: Use invalid...
2213
  		rc = invalidate_inode_pages2(inode->i_mapping);
4f73c7d34   Jeff Layton   cifs: fix potenti...
2214
  		if (rc)
a0a3036b8   Joe Perches   cifs: Standardize...
2215
2216
  			cifs_dbg(VFS, "%s: Could not invalidate inode %p
  ",
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2217
  				 __func__, inode);
df2cf170c   Jeff Layton   cifs: overhaul ci...
2218
  	}
257fb1f15   Pavel Shilovsky   CIFS: Use invalid...
2219

9451a9a52   Suresh Jayaraman   cifs: define inod...
2220
  	cifs_fscache_reset_inode_cookie(inode);
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2221
  	return rc;
df2cf170c   Jeff Layton   cifs: overhaul ci...
2222
  }
4f73c7d34   Jeff Layton   cifs: fix potenti...
2223
2224
  /**
   * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
607dfc79c   Steve French   cifs: remove vari...
2225
2226
2227
   *
   * @key:	currently unused
   * @mode:	the task state to sleep in
4f73c7d34   Jeff Layton   cifs: fix potenti...
2228
2229
   */
  static int
dfd01f026   Peter Zijlstra   sched/wait: Fix t...
2230
  cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
4f73c7d34   Jeff Layton   cifs: fix potenti...
2231
  {
4f73c7d34   Jeff Layton   cifs: fix potenti...
2232
  	freezable_schedule_unsafe();
dfd01f026   Peter Zijlstra   sched/wait: Fix t...
2233
2234
  	if (signal_pending_state(mode, current))
  		return -ERESTARTSYS;
4f73c7d34   Jeff Layton   cifs: fix potenti...
2235
2236
  	return 0;
  }
e284e53fd   Jeff Layton   cifs: new helper ...
2237
2238
2239
  int
  cifs_revalidate_mapping(struct inode *inode)
  {
4f73c7d34   Jeff Layton   cifs: fix potenti...
2240
2241
  	int rc;
  	unsigned long *flags = &CIFS_I(inode)->flags;
18d04062f   Shyam Prasad N   cifs: enable fsca...
2242
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
4f73c7d34   Jeff Layton   cifs: fix potenti...
2243

4e8aea30f   Steve French   smb3: enable swap...
2244
2245
2246
  	/* swapfiles are not supposed to be shared */
  	if (IS_SWAPFILE(inode))
  		return 0;
743162013   NeilBrown   sched: Remove pro...
2247
2248
  	rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
  				     TASK_KILLABLE);
4f73c7d34   Jeff Layton   cifs: fix potenti...
2249
2250
2251
2252
  	if (rc)
  		return rc;
  
  	if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
18d04062f   Shyam Prasad N   cifs: enable fsca...
2253
2254
2255
  		/* for cache=singleclient, do not invalidate */
  		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE)
  			goto skip_invalidate;
4f73c7d34   Jeff Layton   cifs: fix potenti...
2256
2257
2258
2259
  		rc = cifs_invalidate_mapping(inode);
  		if (rc)
  			set_bit(CIFS_INO_INVALID_MAPPING, flags);
  	}
18d04062f   Shyam Prasad N   cifs: enable fsca...
2260
  skip_invalidate:
4f73c7d34   Jeff Layton   cifs: fix potenti...
2261
  	clear_bit_unlock(CIFS_INO_LOCK, flags);
b1cce8032   Linus Torvalds   Merge branch 'for...
2262
  	smp_mb__after_atomic();
4f73c7d34   Jeff Layton   cifs: fix potenti...
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
  	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);
e284e53fd   Jeff Layton   cifs: new helper ...
2273
  }
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2274
  int cifs_revalidate_file_attr(struct file *filp)
abab095d1   Jeff Layton   cifs: add cifs_re...
2275
2276
  {
  	int rc = 0;
ed8561fa1   Ronnie Sahlberg   cifs: pass the de...
2277
  	struct dentry *dentry = file_dentry(filp);
ba00ba64c   Jeff Layton   cifs: make variou...
2278
  	struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
abab095d1   Jeff Layton   cifs: add cifs_re...
2279

ed8561fa1   Ronnie Sahlberg   cifs: pass the de...
2280
  	if (!cifs_dentry_needs_reval(dentry))
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2281
  		return rc;
abab095d1   Jeff Layton   cifs: add cifs_re...
2282

13cfb7334   Jeff Layton   cifs: have cifsFi...
2283
  	if (tlink_tcon(cfile->tlink)->unix_ext)
abab095d1   Jeff Layton   cifs: add cifs_re...
2284
2285
2286
  		rc = cifs_get_file_info_unix(filp);
  	else
  		rc = cifs_get_file_info(filp);
abab095d1   Jeff Layton   cifs: add cifs_re...
2287
2288
  	return rc;
  }
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2289
  int cifs_revalidate_dentry_attr(struct dentry *dentry)
df2cf170c   Jeff Layton   cifs: overhaul ci...
2290
  {
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2291
  	unsigned int xid;
df2cf170c   Jeff Layton   cifs: overhaul ci...
2292
  	int rc = 0;
2b0143b5c   David Howells   VFS: normal files...
2293
  	struct inode *inode = d_inode(dentry);
df2cf170c   Jeff Layton   cifs: overhaul ci...
2294
  	struct super_block *sb = dentry->d_sb;
f6a9bc336   Al Viro   cifs: allocate bu...
2295
2296
  	const char *full_path;
  	void *page;
fc513fac5   Ronnie Sahlberg   cifs: don't leak ...
2297
  	int count = 0;
df2cf170c   Jeff Layton   cifs: overhaul ci...
2298
2299
2300
  
  	if (inode == NULL)
  		return -ENOENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2301

ed8561fa1   Ronnie Sahlberg   cifs: pass the de...
2302
  	if (!cifs_dentry_needs_reval(dentry))
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2303
  		return rc;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2304
  	xid = get_xid();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2305

f6a9bc336   Al Viro   cifs: allocate bu...
2306
2307
2308
2309
  	page = alloc_dentry_path();
  	full_path = build_path_from_dentry(dentry, page);
  	if (IS_ERR(full_path)) {
  		rc = PTR_ERR(full_path);
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2310
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2311
  	}
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2312
2313
2314
  	cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld
  ",
  		 full_path, inode, inode->i_count.counter,
a00be0e31   Miklos Szeredi   cifs: don't use -...
2315
  		 dentry, cifs_get_time(dentry), jiffies);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2316

fc513fac5   Ronnie Sahlberg   cifs: don't leak ...
2317
  again:
6a5f6592a   Steve French   SMB311: Add suppo...
2318
2319
2320
  	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)
df2cf170c   Jeff Layton   cifs: overhaul ci...
2321
2322
2323
2324
  		rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
  	else
  		rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
  					 xid, NULL);
fc513fac5   Ronnie Sahlberg   cifs: don't leak ...
2325
2326
  	if (rc == -EAGAIN && count++ < 10)
  		goto again;
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2327
  out:
f6a9bc336   Al Viro   cifs: allocate bu...
2328
  	free_dentry_path(page);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2329
  	free_xid(xid);
fc513fac5   Ronnie Sahlberg   cifs: don't leak ...
2330

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2331
2332
  	return rc;
  }
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2333
2334
2335
  int cifs_revalidate_file(struct file *filp)
  {
  	int rc;
496ad9aa8   Al Viro   new helper: file_...
2336
  	struct inode *inode = file_inode(filp);
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2337
2338
2339
2340
  
  	rc = cifs_revalidate_file_attr(filp);
  	if (rc)
  		return rc;
e284e53fd   Jeff Layton   cifs: new helper ...
2341
  	return cifs_revalidate_mapping(inode);
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2342
2343
2344
2345
2346
2347
  }
  
  /* revalidate a dentry's inode attributes */
  int cifs_revalidate_dentry(struct dentry *dentry)
  {
  	int rc;
2b0143b5c   David Howells   VFS: normal files...
2348
  	struct inode *inode = d_inode(dentry);
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2349
2350
2351
2352
  
  	rc = cifs_revalidate_dentry_attr(dentry);
  	if (rc)
  		return rc;
e284e53fd   Jeff Layton   cifs: new helper ...
2353
  	return cifs_revalidate_mapping(inode);
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2354
  }
549c72977   Christian Brauner   fs: make helpers ...
2355
2356
  int cifs_getattr(struct user_namespace *mnt_userns, const struct path *path,
  		 struct kstat *stat, u32 request_mask, unsigned int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2357
  {
a528d35e8   David Howells   statx: Add a syst...
2358
  	struct dentry *dentry = path->dentry;
3aa1c8c29   Jeff Layton   cifs: on multiuse...
2359
  	struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
96daf2b09   Steve French   [CIFS] Rename thr...
2360
  	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
2b0143b5c   David Howells   VFS: normal files...
2361
  	struct inode *inode = d_inode(dentry);
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2362
  	int rc;
3aa1c8c29   Jeff Layton   cifs: on multiuse...
2363

087f757b0   Steve French   cifs: add shutdow...
2364
2365
  	if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb))))
  		return -EIO;
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2366
2367
2368
2369
  	/*
  	 * We need to be sure that all dirty pages are written and the server
  	 * has actual ctime, mtime and file length.
  	 */
65af8f016   Steve French   cifs: fix allocat...
2370
  	if ((request_mask & (STATX_CTIME | STATX_MTIME | STATX_SIZE | STATX_BLOCKS)) &&
ffdec8d64   Steve French   cifs: do not igno...
2371
2372
  	    !CIFS_CACHE_READ(CIFS_I(inode)) &&
  	    inode->i_mapping && inode->i_mapping->nrpages != 0) {
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2373
  		rc = filemap_fdatawait(inode->i_mapping);
156ecb2d8   Steve French   [CIFS] Fix to pro...
2374
2375
2376
2377
  		if (rc) {
  			mapping_set_error(inode->i_mapping, rc);
  			return rc;
  		}
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2378
  	}
1c456013e   Jeff Layton   cifs: on multiuse...
2379

ffdec8d64   Steve French   cifs: do not igno...
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
  	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;
  	}
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2394

0d56a4518   Christian Brauner   stat: handle idma...
2395
  	generic_fillattr(&init_user_ns, inode, stat);
522aa3b57   Ronnie Sahlberg   cifs: move [brw]s...
2396
  	stat->blksize = cifs_sb->ctx->bsize;
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2397
  	stat->ino = CIFS_I(inode)->uniqueid;
6e70e26dc   Steve French   SMB3: handle new ...
2398
2399
2400
  	/* old CIFS Unix Extensions doesn't return create time */
  	if (CIFS_I(inode)->createtime) {
  		stat->result_mask |= STATX_BTIME;
95390201e   Arnd Bergmann   cifs: use timespe...
2401
2402
  		stat->btime =
  		      cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime));
6e70e26dc   Steve French   SMB3: handle new ...
2403
2404
2405
2406
2407
2408
2409
  	}
  
  	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;
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2410
  	/*
d3d1fce11   Jeff Layton   cifs: don't overr...
2411
2412
2413
  	 * 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.
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2414
2415
  	 */
  	if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
d3d1fce11   Jeff Layton   cifs: don't overr...
2416
  	    !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
2417
2418
2419
2420
2421
  	    !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();
5fe14c851   Steve French   [CIFS] Explicitly...
2422
  	}
39946886f   Dan Carpenter   cifs: potential u...
2423
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2424
  }
2f3ebaba1   Ronnie Sahlberg   cifs: add fiemap ...
2425
2426
2427
2428
2429
2430
2431
2432
2433
  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;
087f757b0   Steve French   cifs: add shutdow...
2434
2435
  	if (unlikely(cifs_forced_shutdown(cifs_sb)))
  		return -EIO;
2f3ebaba1   Ronnie Sahlberg   cifs: add fiemap ...
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
  	/*
  	 * 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;
  }
8bd0d7014   Ronnie Sahlberg   cifs: add support...
2462
  int cifs_truncate_page(struct address_space *mapping, loff_t from)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2463
  {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2464
2465
  	pgoff_t index = from >> PAGE_SHIFT;
  	unsigned offset = from & (PAGE_SIZE - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2466
  	struct page *page;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2467
2468
2469
2470
2471
  	int rc = 0;
  
  	page = grab_cache_page(mapping, index);
  	if (!page)
  		return -ENOMEM;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2472
  	zero_user_segment(page, offset, PAGE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2473
  	unlock_page(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2474
  	put_page(page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2475
2476
  	return rc;
  }
8bd0d7014   Ronnie Sahlberg   cifs: add support...
2477
  void cifs_setsize(struct inode *inode, loff_t offset)
3677db10a   Steve French   [CIFS] Fix lockin...
2478
  {
57c55cd7c   Ronnie Sahlberg   cifs: invalidate ...
2479
  	struct cifsInodeInfo *cifs_i = CIFS_I(inode);
ba6a46a03   Steve French   [CIFS] small piec...
2480
  	spin_lock(&inode->i_lock);
3677db10a   Steve French   [CIFS] Fix lockin...
2481
  	i_size_write(inode, offset);
ba6a46a03   Steve French   [CIFS] small piec...
2482
  	spin_unlock(&inode->i_lock);
1b9474635   Christoph Hellwig   cifs: truncate fa...
2483

57c55cd7c   Ronnie Sahlberg   cifs: invalidate ...
2484
2485
  	/* Cached inode must be refreshed on truncate */
  	cifs_i->time = 0;
7caef2676   Kirill A. Shutemov   truncate: drop 'o...
2486
  	truncate_pagecache(inode, offset);
3677db10a   Steve French   [CIFS] Fix lockin...
2487
  }
8efdbde64   Jeff Layton   [CIFS] break ATTR...
2488
2489
  static int
  cifs_set_file_size(struct inode *inode, struct iattr *attrs,
f6f1f1790   Al Viro   cifs: constify pa...
2490
  		   unsigned int xid, const char *full_path)
8efdbde64   Jeff Layton   [CIFS] break ATTR...
2491
2492
2493
2494
2495
  {
  	int rc;
  	struct cifsFileInfo *open_file;
  	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
2496
  	struct tcon_link *tlink = NULL;
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
2497
2498
  	struct cifs_tcon *tcon = NULL;
  	struct TCP_Server_Info *server;
8efdbde64   Jeff Layton   [CIFS] break ATTR...
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
  
  	/*
  	 * 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
  	 */
86f740f2a   Aurelien Aptel   cifs: fix rename(...
2509
  	open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
8efdbde64   Jeff Layton   [CIFS] break ATTR...
2510
  	if (open_file) {
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
2511
2512
2513
2514
2515
2516
2517
  		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;
6ab409b53   Dave Kleikamp   cifs: Replace wrt...
2518
  		cifsFileInfo_put(open_file);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2519
2520
  		cifs_dbg(FYI, "SetFSize for attrs rc = %d
  ", rc);
8efdbde64   Jeff Layton   [CIFS] break ATTR...
2521
2522
  	} else
  		rc = -EINVAL;
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
  	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;
  	}
ba00ba64c   Jeff Layton   cifs: make variou...
2533

d14334181   Pavel Shilovsky   CIFS: Move set_fi...
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
  	/*
  	 * 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;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2544
2545
  	cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d
  ", rc);
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
2546

d14334181   Pavel Shilovsky   CIFS: Move set_fi...
2547
2548
  	if (tlink)
  		cifs_put_tlink(tlink);
8efdbde64   Jeff Layton   [CIFS] break ATTR...
2549

d14334181   Pavel Shilovsky   CIFS: Move set_fi...
2550
  set_size_out:
8efdbde64   Jeff Layton   [CIFS] break ATTR...
2551
  	if (rc == 0) {
fbec9ab95   Jeff Layton   cifs: vary timeou...
2552
  		cifsInode->server_eof = attrs->ia_size;
1b9474635   Christoph Hellwig   cifs: truncate fa...
2553
  		cifs_setsize(inode, attrs->ia_size);
65af8f016   Steve French   cifs: fix allocat...
2554
2555
2556
2557
2558
2559
2560
2561
  		/*
  		 * i_blocks is not related to (i_size / i_blksize), but instead
  		 * 512 byte (2**9) size is required for calculating num blocks.
  		 * Until we can query the server for actual allocation size,
  		 * this is best estimate we have for blocks allocated for a file
  		 * Number of blocks must be rounded up so size 1 is not 0 blocks
  		 */
  		inode->i_blocks = (512 - 1 + attrs->ia_size) >> 9;
5618303d8   Zhang Xiaoxu   cifs: update ctim...
2562
2563
2564
2565
2566
2567
2568
2569
  
  		/*
  		 * The man page of truncate says if the size changed,
  		 * then the st_ctime and st_mtime fields for the file
  		 * are updated.
  		 */
  		attrs->ia_ctime = attrs->ia_mtime = current_time(inode);
  		attrs->ia_valid |= ATTR_CTIME | ATTR_MTIME;
8efdbde64   Jeff Layton   [CIFS] break ATTR...
2570
2571
2572
2573
2574
  		cifs_truncate_page(inode->i_mapping, inode->i_size);
  	}
  
  	return rc;
  }
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2575
2576
2577
2578
  static int
  cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
  {
  	int rc;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2579
  	unsigned int xid;
f6a9bc336   Al Viro   cifs: allocate bu...
2580
2581
  	const char *full_path;
  	void *page = alloc_dentry_path();
2b0143b5c   David Howells   VFS: normal files...
2582
  	struct inode *inode = d_inode(direntry);
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2583
2584
  	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
2585
  	struct tcon_link *tlink;
96daf2b09   Steve French   [CIFS] Rename thr...
2586
  	struct cifs_tcon *pTcon;
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2587
  	struct cifs_unix_set_info_args *args = NULL;
3bbeeb3c9   Jeff Layton   cifs: add and use...
2588
  	struct cifsFileInfo *open_file;
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2589

35c265e00   Al Viro   cifs: switch to u...
2590
2591
2592
  	cifs_dbg(FYI, "setattr_unix on file %pd attrs->ia_valid=0x%x
  ",
  		 direntry, attrs->ia_valid);
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2593

6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2594
  	xid = get_xid();
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2595

db78b877f   Christoph Hellwig   always call inode...
2596
2597
  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
  		attrs->ia_valid |= ATTR_FORCE;
2f221d6f7   Christian Brauner   attr: handle idma...
2598
  	rc = setattr_prepare(&init_user_ns, direntry, attrs);
db78b877f   Christoph Hellwig   always call inode...
2599
2600
  	if (rc < 0)
  		goto out;
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2601

f6a9bc336   Al Viro   cifs: allocate bu...
2602
2603
2604
  	full_path = build_path_from_dentry(direntry, page);
  	if (IS_ERR(full_path)) {
  		rc = PTR_ERR(full_path);
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2605
2606
  		goto out;
  	}
0f4d634c5   Jeff Layton   cifs: flush data ...
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
  	/*
  	 * 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);
9a66396f1   Pavel Shilovsky   CIFS: Fix error p...
2619
2620
2621
2622
  	if (is_interrupt_error(rc)) {
  		rc = -ERESTARTSYS;
  		goto out;
  	}
eb4b756b1   Jeff Layton   cifs: eliminate c...
2623
2624
  	mapping_set_error(inode->i_mapping, rc);
  	rc = 0;
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
  
  	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
49418b2c2   Eric W. Biederman   cifs: Modify stru...
2651
  		args->uid = INVALID_UID; /* no change */
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2652
2653
2654
2655
  
  	if (attrs->ia_valid & ATTR_GID)
  		args->gid = attrs->ia_gid;
  	else
49418b2c2   Eric W. Biederman   cifs: Modify stru...
2656
  		args->gid = INVALID_GID; /* no change */
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2657
2658
  
  	if (attrs->ia_valid & ATTR_ATIME)
95390201e   Arnd Bergmann   cifs: use timespe...
2659
  		args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2660
2661
2662
2663
  	else
  		args->atime = NO_CHANGE_64;
  
  	if (attrs->ia_valid & ATTR_MTIME)
95390201e   Arnd Bergmann   cifs: use timespe...
2664
  		args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2665
2666
2667
2668
  	else
  		args->mtime = NO_CHANGE_64;
  
  	if (attrs->ia_valid & ATTR_CTIME)
95390201e   Arnd Bergmann   cifs: use timespe...
2669
  		args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2670
2671
2672
2673
  	else
  		args->ctime = NO_CHANGE_64;
  
  	args->device = 0;
86f740f2a   Aurelien Aptel   cifs: fix rename(...
2674
  	open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
3bbeeb3c9   Jeff Layton   cifs: add and use...
2675
  	if (open_file) {
4b4de76e3   Pavel Shilovsky   CIFS: Replace net...
2676
  		u16 nfid = open_file->fid.netfid;
3bbeeb3c9   Jeff Layton   cifs: add and use...
2677
  		u32 npid = open_file->pid;
13cfb7334   Jeff Layton   cifs: have cifsFi...
2678
  		pTcon = tlink_tcon(open_file->tlink);
3bbeeb3c9   Jeff Layton   cifs: add and use...
2679
  		rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
6ab409b53   Dave Kleikamp   cifs: Replace wrt...
2680
  		cifsFileInfo_put(open_file);
3bbeeb3c9   Jeff Layton   cifs: add and use...
2681
  	} else {
7ffec3724   Jeff Layton   cifs: add refcoun...
2682
2683
2684
2685
2686
2687
  		tlink = cifs_sb_tlink(cifs_sb);
  		if (IS_ERR(tlink)) {
  			rc = PTR_ERR(tlink);
  			goto out;
  		}
  		pTcon = tlink_tcon(tlink);
3bbeeb3c9   Jeff Layton   cifs: add and use...
2688
  		rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
01ea95e3b   Jeff Layton   cifs: rename CIFS...
2689
  				    cifs_sb->local_nls,
bc8ebdc4f   Nakajima Akira   Fix that several ...
2690
  				    cifs_remap(cifs_sb));
7ffec3724   Jeff Layton   cifs: add refcoun...
2691
  		cifs_put_tlink(tlink);
3bbeeb3c9   Jeff Layton   cifs: add and use...
2692
  	}
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2693

1025774ce   Christoph Hellwig   remove inode_setattr
2694
2695
  	if (rc)
  		goto out;
ccd4bb1be   Steve French   [CIFS] Don't cach...
2696

1025774ce   Christoph Hellwig   remove inode_setattr
2697
  	if ((attrs->ia_valid & ATTR_SIZE) &&
1b9474635   Christoph Hellwig   cifs: truncate fa...
2698
2699
  	    attrs->ia_size != i_size_read(inode))
  		truncate_setsize(inode, attrs->ia_size);
1025774ce   Christoph Hellwig   remove inode_setattr
2700

2f221d6f7   Christian Brauner   attr: handle idma...
2701
  	setattr_copy(&init_user_ns, inode, attrs);
1025774ce   Christoph Hellwig   remove inode_setattr
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
  	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;
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2712
2713
  out:
  	kfree(args);
f6a9bc336   Al Viro   cifs: allocate bu...
2714
  	free_dentry_path(page);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2715
  	free_xid(xid);
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2716
2717
  	return rc;
  }
0510eeb73   Jeff Layton   turn cifs_setattr...
2718
2719
  static int
  cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2720
  {
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2721
  	unsigned int xid;
8abf2775d   Eric W. Biederman   cifs: Use kuids a...
2722
2723
  	kuid_t uid = INVALID_UID;
  	kgid_t gid = INVALID_GID;
2b0143b5c   David Howells   VFS: normal files...
2724
  	struct inode *inode = d_inode(direntry);
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2725
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2726
  	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
aa081859b   Ronnie Sahlberg   cifs: flush befor...
2727
2728
  	struct cifsFileInfo *wfile;
  	struct cifs_tcon *tcon;
f6a9bc336   Al Viro   cifs: allocate bu...
2729
2730
  	const char *full_path;
  	void *page = alloc_dentry_path();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2731
  	int rc = -EACCES;
feb3e20ce   Jeff Layton   move file time an...
2732
  	__u32 dosattr = 0;
4e1e7fb9e   Jeff Layton   bundle up Unix SE...
2733
  	__u64 mode = NO_CHANGE_64;
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2734

6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2735
  	xid = get_xid();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2736

63d614a60   Colin Ian King   cifs: fix typo in...
2737
2738
  	cifs_dbg(FYI, "setattr on file %pd attrs->ia_valid 0x%x
  ",
35c265e00   Al Viro   cifs: switch to u...
2739
  		 direntry, attrs->ia_valid);
6473a559c   Steve French   [CIFS] Fix missin...
2740

db78b877f   Christoph Hellwig   always call inode...
2741
2742
  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
  		attrs->ia_valid |= ATTR_FORCE;
2f221d6f7   Christian Brauner   attr: handle idma...
2743
  	rc = setattr_prepare(&init_user_ns, direntry, attrs);
f6a9bc336   Al Viro   cifs: allocate bu...
2744
2745
  	if (rc < 0)
  		goto cifs_setattr_exit;
50c2f7538   Steve French   [CIFS] whitespace...
2746

f6a9bc336   Al Viro   cifs: allocate bu...
2747
2748
2749
2750
  	full_path = build_path_from_dentry(direntry, page);
  	if (IS_ERR(full_path)) {
  		rc = PTR_ERR(full_path);
  		goto cifs_setattr_exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2751
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2752

0f4d634c5   Jeff Layton   cifs: flush data ...
2753
2754
  	/*
  	 * Attempt to flush data before changing attributes. We need to do
cf5371ae4   Steve French   smb3: fix perform...
2755
2756
  	 * this for ATTR_SIZE and ATTR_MTIME.  If the flush of the data
  	 * returns error, store it to report later and continue.
0f4d634c5   Jeff Layton   cifs: flush data ...
2757
2758
2759
  	 *
  	 * BB: This should be smarter. Why bother flushing pages that
  	 * will be truncated anyway? Also, should we error out here if
cf5371ae4   Steve French   smb3: fix perform...
2760
  	 * the flush returns error? Do we need to check for ATTR_MTIME_SET flag?
0f4d634c5   Jeff Layton   cifs: flush data ...
2761
  	 */
cf5371ae4   Steve French   smb3: fix perform...
2762
2763
2764
2765
2766
2767
2768
  	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);
9a66396f1   Pavel Shilovsky   CIFS: Fix error p...
2769
  	}
eb4b756b1   Jeff Layton   cifs: eliminate c...
2770
  	rc = 0;
cea218054   Jeff Layton   [CIFS] Fix potent...
2771

cf5371ae4   Steve French   smb3: fix perform...
2772
2773
  	if ((attrs->ia_valid & ATTR_MTIME) &&
  	    !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
86f740f2a   Aurelien Aptel   cifs: fix rename(...
2774
  		rc = cifs_get_writable_file(cifsInode, FIND_WR_ANY, &wfile);
aa081859b   Ronnie Sahlberg   cifs: flush befor...
2775
2776
2777
2778
2779
  		if (!rc) {
  			tcon = tlink_tcon(wfile->tlink);
  			rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid);
  			cifsFileInfo_put(wfile);
  			if (rc)
783bf7b8b   Chuhong Yuan   cifs: Fix missed ...
2780
  				goto cifs_setattr_exit;
aa081859b   Ronnie Sahlberg   cifs: flush befor...
2781
  		} else if (rc != -EBADF)
783bf7b8b   Chuhong Yuan   cifs: Fix missed ...
2782
  			goto cifs_setattr_exit;
aa081859b   Ronnie Sahlberg   cifs: flush befor...
2783
2784
2785
  		else
  			rc = 0;
  	}
50531444f   Steve French   [CIFS] Fix mtime ...
2786
  	if (attrs->ia_valid & ATTR_SIZE) {
8efdbde64   Jeff Layton   [CIFS] break ATTR...
2787
2788
  		rc = cifs_set_file_size(inode, attrs, xid, full_path);
  		if (rc != 0)
e30dcf3a1   Steve French   [CIFS] Add suppor...
2789
  			goto cifs_setattr_exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2790
  	}
4ca691a89   Jeff Layton   silently ignore o...
2791

a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
2792
2793
2794
2795
2796
  	if (attrs->ia_valid & ATTR_UID)
  		uid = attrs->ia_uid;
  
  	if (attrs->ia_valid & ATTR_GID)
  		gid = attrs->ia_gid;
22442179a   Steve French   cifs: allow chmod...
2797
2798
  	if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
  	    (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
8abf2775d   Eric W. Biederman   cifs: Use kuids a...
2799
  		if (uid_valid(uid) || gid_valid(gid)) {
0f22053e8   Shyam Prasad N   cifs: Fix unix pe...
2800
2801
  			mode = NO_CHANGE_64;
  			rc = id_mode_to_cifs_acl(inode, full_path, &mode,
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
2802
2803
  							uid, gid);
  			if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2804
2805
2806
  				cifs_dbg(FYI, "%s: Setting id failed with error: %d
  ",
  					 __func__, rc);
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
2807
2808
2809
2810
  				goto cifs_setattr_exit;
  			}
  		}
  	} else
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2811
  	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
4ca691a89   Jeff Layton   silently ignore o...
2812
  		attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2813

d32c4f262   Jeff Layton   CIFS: ignore mode...
2814
2815
2816
  	/* 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;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2817
  	if (attrs->ia_valid & ATTR_MODE) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2818
  		mode = attrs->ia_mode;
cdbce9c87   Steve French   [CIFS] Fix setatt...
2819
  		rc = 0;
22442179a   Steve French   cifs: allow chmod...
2820
2821
  		if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
  		    (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
0f22053e8   Shyam Prasad N   cifs: Fix unix pe...
2822
  			rc = id_mode_to_cifs_acl(inode, full_path, &mode,
8abf2775d   Eric W. Biederman   cifs: Use kuids a...
2823
  						INVALID_UID, INVALID_GID);
78415d2d3   Shirish Pargaonkar   cifs: Misc. clean...
2824
  			if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2825
2826
2827
  				cifs_dbg(FYI, "%s: Setting ACL failed with error: %d
  ",
  					 __func__, rc);
78415d2d3   Shirish Pargaonkar   cifs: Misc. clean...
2828
2829
  				goto cifs_setattr_exit;
  			}
0f22053e8   Shyam Prasad N   cifs: Fix unix pe...
2830
2831
2832
2833
2834
2835
2836
  
  			/*
  			 * In case of CIFS_MOUNT_CIFS_ACL, we cannot support all modes.
  			 * Pick up the actual mode bits that were set.
  			 */
  			if (mode != attrs->ia_mode)
  				attrs->ia_mode = mode;
78415d2d3   Shirish Pargaonkar   cifs: Misc. clean...
2837
  		} else
5132861a7   Jeff Layton   disable most mode...
2838
2839
  		if (((mode & S_IWUGO) == 0) &&
  		    (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
feb3e20ce   Jeff Layton   move file time an...
2840
2841
  
  			dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
5132861a7   Jeff Layton   disable most mode...
2842
2843
2844
2845
2846
  			/* 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)) {
feb3e20ce   Jeff Layton   move file time an...
2847
2848
2849
2850
2851
  
  			dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
  			/* Attributes of 0 are ignored */
  			if (dosattr == 0)
  				dosattr |= ATTR_NORMAL;
5132861a7   Jeff Layton   disable most mode...
2852
2853
2854
2855
2856
2857
  
  			/* 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 |=
8401e9367   Ronnie Sahlberg   cifs: remove [gu]...
2858
  						cifs_sb->ctx->dir_mode;
5132861a7   Jeff Layton   disable most mode...
2859
2860
  				else
  					attrs->ia_mode |=
8401e9367   Ronnie Sahlberg   cifs: remove [gu]...
2861
  						cifs_sb->ctx->file_mode;
5132861a7   Jeff Layton   disable most mode...
2862
2863
2864
2865
  			}
  		} else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
  			/* ignore mode change - ATTR_READONLY hasn't changed */
  			attrs->ia_valid &= ~ATTR_MODE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2866
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2867
  	}
feb3e20ce   Jeff Layton   move file time an...
2868
2869
2870
2871
  	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 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2872

e30dcf3a1   Steve French   [CIFS] Add suppor...
2873
2874
2875
2876
2877
  		/* 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 */
fb8c4b14d   Steve French   [CIFS] whitespace...
2878
  		if ((rc) && (attrs->ia_valid &
feb3e20ce   Jeff Layton   move file time an...
2879
  				(ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
e30dcf3a1   Steve French   [CIFS] Add suppor...
2880
  			rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2881
2882
2883
2884
  	}
  
  	/* do not need local check to inode_check_ok since the server does
  	   that */
1025774ce   Christoph Hellwig   remove inode_setattr
2885
2886
2887
2888
  	if (rc)
  		goto cifs_setattr_exit;
  
  	if ((attrs->ia_valid & ATTR_SIZE) &&
1b9474635   Christoph Hellwig   cifs: truncate fa...
2889
2890
  	    attrs->ia_size != i_size_read(inode))
  		truncate_setsize(inode, attrs->ia_size);
1025774ce   Christoph Hellwig   remove inode_setattr
2891

2f221d6f7   Christian Brauner   attr: handle idma...
2892
  	setattr_copy(&init_user_ns, inode, attrs);
1025774ce   Christoph Hellwig   remove inode_setattr
2893
  	mark_inode_dirty(inode);
1025774ce   Christoph Hellwig   remove inode_setattr
2894

e30dcf3a1   Steve French   [CIFS] Add suppor...
2895
  cifs_setattr_exit:
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2896
  	free_xid(xid);
f6a9bc336   Al Viro   cifs: allocate bu...
2897
  	free_dentry_path(page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2898
2899
  	return rc;
  }
0510eeb73   Jeff Layton   turn cifs_setattr...
2900
  int
549c72977   Christian Brauner   fs: make helpers ...
2901
2902
  cifs_setattr(struct user_namespace *mnt_userns, struct dentry *direntry,
  	     struct iattr *attrs)
0510eeb73   Jeff Layton   turn cifs_setattr...
2903
  {
fc64005c9   Al Viro   don't bother with...
2904
  	struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
96daf2b09   Steve French   [CIFS] Rename thr...
2905
  	struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
c6cc4c5a7   Ronnie Sahlberg   cifs: handle -EIN...
2906
  	int rc, retries = 0;
0510eeb73   Jeff Layton   turn cifs_setattr...
2907

087f757b0   Steve French   cifs: add shutdow...
2908
2909
  	if (unlikely(cifs_forced_shutdown(cifs_sb)))
  		return -EIO;
c6cc4c5a7   Ronnie Sahlberg   cifs: handle -EIN...
2910
2911
2912
2913
2914
2915
2916
  	do {
  		if (pTcon->unix_ext)
  			rc = cifs_setattr_unix(direntry, attrs);
  		else
  			rc = cifs_setattr_nounix(direntry, attrs);
  		retries++;
  	} while (is_retryable_error(rc) && retries < 2);
0510eeb73   Jeff Layton   turn cifs_setattr...
2917
2918
  
  	/* BB: add cifs_setattr_legacy for really old servers */
c6cc4c5a7   Ronnie Sahlberg   cifs: handle -EIN...
2919
  	return rc;
0510eeb73   Jeff Layton   turn cifs_setattr...
2920
  }