Blame view

fs/cifs/inode.c 63 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   *   fs/cifs/inode.c
   *
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
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
   *   Author(s): Steve French (sfrench@us.ibm.com)
   *
   *   This library is free software; you can redistribute it and/or modify
   *   it under the terms of the GNU Lesser General Public License as published
   *   by the Free Software Foundation; either version 2.1 of the License, or
   *   (at your option) any later version.
   *
   *   This library is distributed in the hope that it will be useful,
   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
   *   the GNU Lesser General Public License for more details.
   *
   *   You should have received a copy of the GNU Lesser General Public License
   *   along with this library; if not, write to the Free Software
   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
   */
  #include <linux/fs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
  #include <linux/stat.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
23
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
  #include <linux/pagemap.h>
4f73c7d34   Jeff Layton   cifs: fix potenti...
25
  #include <linux/freezer.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
29
30
31
32
  #include <asm/div64.h>
  #include "cifsfs.h"
  #include "cifspdu.h"
  #include "cifsglob.h"
  #include "cifsproto.h"
  #include "cifs_debug.h"
  #include "cifs_fs_sb.h"
2baa26825   Steve French   Remap reserved po...
33
  #include "cifs_unicode.h"
9451a9a52   Suresh Jayaraman   cifs: define inod...
34
  #include "fscache.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35

70eff55d2   Christoph Hellwig   [CIFS] factoring ...
36

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

df2cf170c   Jeff Layton   cifs: overhaul ci...
158
  	cifs_revalidate_cache(inode, fattr);
b7ca69289   Steve French   CIFS: Protect i_n...
159
  	spin_lock(&inode->i_lock);
cc0bad755   Jeff Layton   cifs: add new cif...
160
161
162
  	inode->i_atime = fattr->cf_atime;
  	inode->i_mtime = fattr->cf_mtime;
  	inode->i_ctime = fattr->cf_ctime;
cc0bad755   Jeff Layton   cifs: add new cif...
163
  	inode->i_rdev = fattr->cf_rdev;
74d290da4   Jim McDonough   [CIFS] Provide sa...
164
  	cifs_nlink_fattr_to_inode(inode, fattr);
cc0bad755   Jeff Layton   cifs: add new cif...
165
166
  	inode->i_uid = fattr->cf_uid;
  	inode->i_gid = fattr->cf_gid;
0b8f18e35   Jeff Layton   cifs: convert cif...
167
168
169
170
  	/* 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...
171
  	cifs_i->cifsAttrs = fattr->cf_cifsattrs;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
172

0b8f18e35   Jeff Layton   cifs: convert cif...
173
174
175
176
  	if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
  		cifs_i->time = 0;
  	else
  		cifs_i->time = jiffies;
aff8d5ca7   Jeff Layton   cifs: convert boo...
177
178
179
180
  	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...
181

835a36ca4   Jeff Layton   cifs: set server_...
182
  	cifs_i->server_eof = fattr->cf_eof;
cc0bad755   Jeff Layton   cifs: add new cif...
183
184
185
186
  	/*
  	 * 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...
187
188
189
190
191
192
193
194
195
196
197
  	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...
198
199
  	if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL)
  		inode->i_flags |= S_AUTOMOUNT;
c2b93e069   Jeff Layton   cifs: only set op...
200
201
  	if (inode->i_state & I_NEW)
  		cifs_set_ops(inode);
cc0bad755   Jeff Layton   cifs: add new cif...
202
  }
4065c802d   Jeff Layton   cifs: fix noserve...
203
204
205
206
207
208
209
210
211
212
  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...
213
214
215
216
217
218
219
220
221
222
223
224
225
226
  /* 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);
  	fattr->cf_mode = le64_to_cpu(info->Permissions);
75f12983d   Christoph Hellwig   [CIFS] consolidat...
227
228
229
230
231
  
  	/*
  	 * 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...
232
  	fattr->cf_mode &= ~S_IFMT;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
233
234
  	switch (le32_to_cpu(info->Type)) {
  	case UNIX_FILE:
cc0bad755   Jeff Layton   cifs: add new cif...
235
236
  		fattr->cf_mode |= S_IFREG;
  		fattr->cf_dtype = DT_REG;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
237
238
  		break;
  	case UNIX_SYMLINK:
cc0bad755   Jeff Layton   cifs: add new cif...
239
240
  		fattr->cf_mode |= S_IFLNK;
  		fattr->cf_dtype = DT_LNK;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
241
242
  		break;
  	case UNIX_DIR:
cc0bad755   Jeff Layton   cifs: add new cif...
243
244
  		fattr->cf_mode |= S_IFDIR;
  		fattr->cf_dtype = DT_DIR;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
245
246
  		break;
  	case UNIX_CHARDEV:
cc0bad755   Jeff Layton   cifs: add new cif...
247
248
249
250
  		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...
251
252
  		break;
  	case UNIX_BLOCKDEV:
cc0bad755   Jeff Layton   cifs: add new cif...
253
254
255
256
  		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...
257
258
  		break;
  	case UNIX_FIFO:
cc0bad755   Jeff Layton   cifs: add new cif...
259
260
  		fattr->cf_mode |= S_IFIFO;
  		fattr->cf_dtype = DT_FIFO;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
261
262
  		break;
  	case UNIX_SOCKET:
cc0bad755   Jeff Layton   cifs: add new cif...
263
264
  		fattr->cf_mode |= S_IFSOCK;
  		fattr->cf_dtype = DT_SOCK;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
265
266
267
  		break;
  	default:
  		/* safest to call it a file if we do not know */
cc0bad755   Jeff Layton   cifs: add new cif...
268
269
  		fattr->cf_mode |= S_IFREG;
  		fattr->cf_dtype = DT_REG;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
270
271
  		cifs_dbg(FYI, "unknown type %d
  ", le32_to_cpu(info->Type));
75f12983d   Christoph Hellwig   [CIFS] consolidat...
272
273
  		break;
  	}
46bbc25f9   Eric W. Biederman   cifs: Override un...
274
275
276
  	fattr->cf_uid = cifs_sb->mnt_uid;
  	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
  		u64 id = le64_to_cpu(info->Uid);
4a2c8cf56   Eric W. Biederman   cifs: Convert str...
277
278
279
280
281
  		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...
282
283
284
285
286
  	}
  	
  	fattr->cf_gid = cifs_sb->mnt_gid;
  	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
  		u64 id = le64_to_cpu(info->Gid);
4a2c8cf56   Eric W. Biederman   cifs: Convert str...
287
288
289
290
291
  		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...
292
  	}
75f12983d   Christoph Hellwig   [CIFS] consolidat...
293

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

f96637be0   Joe Perches   [CIFS] cifs: Rena...
308
309
  	cifs_dbg(FYI, "creating fake fattr for DFS referral
  ");
cc0bad755   Jeff Layton   cifs: add new cif...
310
311
312
313
314
315
316
317
318
319
  
  	memset(fattr, 0, sizeof(*fattr));
  	fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
  	fattr->cf_uid = cifs_sb->mnt_uid;
  	fattr->cf_gid = cifs_sb->mnt_gid;
  	fattr->cf_atime = CURRENT_TIME;
  	fattr->cf_ctime = CURRENT_TIME;
  	fattr->cf_mtime = CURRENT_TIME;
  	fattr->cf_nlink = 2;
  	fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
0e4bbde94   Steve French   [CIFS] Enable DFS...
320
  }
4ad650445   Pavel Shilovsky   CIFS: Move guery ...
321
322
  static int
  cifs_get_file_info_unix(struct file *filp)
abab095d1   Jeff Layton   cifs: add cifs_re...
323
324
  {
  	int rc;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
325
  	unsigned int xid;
abab095d1   Jeff Layton   cifs: add cifs_re...
326
327
  	FILE_UNIX_BASIC_INFO find_data;
  	struct cifs_fattr fattr;
496ad9aa8   Al Viro   new helper: file_...
328
  	struct inode *inode = file_inode(filp);
abab095d1   Jeff Layton   cifs: add cifs_re...
329
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
c21dfb699   Joe Perches   fs/cifs: Remove u...
330
  	struct cifsFileInfo *cfile = filp->private_data;
96daf2b09   Steve French   [CIFS] Rename thr...
331
  	struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
abab095d1   Jeff Layton   cifs: add cifs_re...
332

6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
333
  	xid = get_xid();
4b4de76e3   Pavel Shilovsky   CIFS: Replace net...
334
  	rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data);
abab095d1   Jeff Layton   cifs: add cifs_re...
335
336
337
338
339
340
341
342
  	if (!rc) {
  		cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
  	} else if (rc == -EREMOTE) {
  		cifs_create_dfs_fattr(&fattr, inode->i_sb);
  		rc = 0;
  	}
  
  	cifs_fattr_to_inode(inode, &fattr);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
343
  	free_xid(xid);
abab095d1   Jeff Layton   cifs: add cifs_re...
344
345
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
  int cifs_get_inode_info_unix(struct inode **pinode,
cc0bad755   Jeff Layton   cifs: add new cif...
347
  			     const unsigned char *full_path,
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
348
  			     struct super_block *sb, unsigned int xid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
  {
cc0bad755   Jeff Layton   cifs: add new cif...
350
  	int rc;
0e4bbde94   Steve French   [CIFS] Enable DFS...
351
  	FILE_UNIX_BASIC_INFO find_data;
cc0bad755   Jeff Layton   cifs: add new cif...
352
  	struct cifs_fattr fattr;
96daf2b09   Steve French   [CIFS] Rename thr...
353
  	struct cifs_tcon *tcon;
7ffec3724   Jeff Layton   cifs: add refcoun...
354
  	struct tcon_link *tlink;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
355
  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356

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

7ffec3724   Jeff Layton   cifs: add refcoun...
360
361
362
363
  	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
364
  	/* could have done a find first instead but this returns more info */
cc0bad755   Jeff Layton   cifs: add new cif...
365
  	rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
bc8ebdc4f   Nakajima Akira   Fix that several ...
366
  				  cifs_sb->local_nls, cifs_remap(cifs_sb));
7ffec3724   Jeff Layton   cifs: add refcoun...
367
  	cifs_put_tlink(tlink);
e911d0cc8   Jeff Layton   cifs: fix inode l...
368

cc0bad755   Jeff Layton   cifs: add new cif...
369
370
371
372
373
374
375
376
  	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
377

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

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

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

d979f3b0a   Steve French   Add protocol spec...
543
544
545
546
547
548
549
550
  	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 */,
  			cifs_sb->local_nls,
2baa26825   Steve French   Remap reserved po...
551
  			cifs_remap(cifs_sb));
7ffec3724   Jeff Layton   cifs: add refcoun...
552
  	cifs_put_tlink(tlink);
4523cc304   Steve French   [CIFS] UID/GID ov...
553
  	if (rc < 0)
9e294f1c4   Steve French   [CIFS] Recognize ...
554
555
556
  		return (int)rc;
  	else if (rc > 3) {
  		mode = le32_to_cpu(*((__le32 *)ea_value));
0b8f18e35   Jeff Layton   cifs: convert cif...
557
  		fattr->cf_mode &= ~SFBITS_MASK;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
558
559
560
  		cifs_dbg(FYI, "special bits 0%o org mode 0%o
  ",
  			 mode, fattr->cf_mode);
0b8f18e35   Jeff Layton   cifs: convert cif...
561
  		fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
562
563
  		cifs_dbg(FYI, "special mode bits 0%o
  ", mode);
9e294f1c4   Steve French   [CIFS] Recognize ...
564
  	}
0b8f18e35   Jeff Layton   cifs: convert cif...
565
566
  
  	return 0;
3020a1f58   Steve French   [CIFS] Fix schedu...
567
568
569
  #else
  	return -EOPNOTSUPP;
  #endif
9e294f1c4   Steve French   [CIFS] Recognize ...
570
  }
0b8f18e35   Jeff Layton   cifs: convert cif...
571
  /* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
f1230c979   Steve French   [CIFS] fix sparse...
572
  static void
0b8f18e35   Jeff Layton   cifs: convert cif...
573
  cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
eb85d94bd   Pavel Shilovsky   CIFS: Fix symboli...
574
575
  		       struct cifs_sb_info *cifs_sb, bool adjust_tz,
  		       bool symlink)
b9a3260f2   Steve French   [CIFS] Enable DFS...
576
  {
96daf2b09   Steve French   [CIFS] Rename thr...
577
  	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
0d424ad0a   Jeff Layton   cifs: add cifs_sb...
578

0b8f18e35   Jeff Layton   cifs: convert cif...
579
580
581
582
583
584
585
586
587
588
589
590
591
592
  	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);
  	else
  		fattr->cf_atime = CURRENT_TIME;
  
  	fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
  	fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
  
  	if (adjust_tz) {
0d424ad0a   Jeff Layton   cifs: add cifs_sb...
593
594
  		fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
  		fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
0b8f18e35   Jeff Layton   cifs: convert cif...
595
596
597
598
  	}
  
  	fattr->cf_eof = le64_to_cpu(info->EndOfFile);
  	fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
20054bd65   Jeff Layton   cifs: use Creatio...
599
  	fattr->cf_createtime = le64_to_cpu(info->CreationTime);
0b8f18e35   Jeff Layton   cifs: convert cif...
600

74d290da4   Jim McDonough   [CIFS] Provide sa...
601
  	fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
eb85d94bd   Pavel Shilovsky   CIFS: Fix symboli...
602
603
604
605
606
  
  	if (symlink) {
  		fattr->cf_mode = S_IFLNK;
  		fattr->cf_dtype = DT_LNK;
  	} else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
0b8f18e35   Jeff Layton   cifs: convert cif...
607
608
  		fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
  		fattr->cf_dtype = DT_DIR;
6de2ce423   Pavel Shilovsky   CIFS: Fix mkdir/r...
609
610
611
612
  		/*
  		 * Server can return wrong NumberOfLinks value for directories
  		 * when Unix extensions are disabled - fake it.
  		 */
74d290da4   Jim McDonough   [CIFS] Provide sa...
613
614
  		if (!tcon->unix_ext)
  			fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
0b8f18e35   Jeff Layton   cifs: convert cif...
615
616
617
  	} else {
  		fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
  		fattr->cf_dtype = DT_REG;
0b8f18e35   Jeff Layton   cifs: convert cif...
618

d0c280d26   Jeff Layton   cifs: when ATTR_R...
619
620
621
  		/* 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...
622

74d290da4   Jim McDonough   [CIFS] Provide sa...
623
624
625
626
627
628
629
630
  		/*
  		 * 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) {
  			cifs_dbg(1, "bogus file nlink value %u
  ",
6658b9f70   Steve French   [CIFS] use sensib...
631
  				fattr->cf_nlink);
74d290da4   Jim McDonough   [CIFS] Provide sa...
632
  			fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
6658b9f70   Steve French   [CIFS] use sensib...
633
  		}
6de2ce423   Pavel Shilovsky   CIFS: Fix mkdir/r...
634
  	}
0b8f18e35   Jeff Layton   cifs: convert cif...
635
636
637
  
  	fattr->cf_uid = cifs_sb->mnt_uid;
  	fattr->cf_gid = cifs_sb->mnt_gid;
b9a3260f2   Steve French   [CIFS] Enable DFS...
638
  }
4ad650445   Pavel Shilovsky   CIFS: Move guery ...
639
640
  static int
  cifs_get_file_info(struct file *filp)
abab095d1   Jeff Layton   cifs: add cifs_re...
641
642
  {
  	int rc;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
643
  	unsigned int xid;
abab095d1   Jeff Layton   cifs: add cifs_re...
644
645
  	FILE_ALL_INFO find_data;
  	struct cifs_fattr fattr;
496ad9aa8   Al Viro   new helper: file_...
646
  	struct inode *inode = file_inode(filp);
abab095d1   Jeff Layton   cifs: add cifs_re...
647
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
c21dfb699   Joe Perches   fs/cifs: Remove u...
648
  	struct cifsFileInfo *cfile = filp->private_data;
96daf2b09   Steve French   [CIFS] Rename thr...
649
  	struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
4ad650445   Pavel Shilovsky   CIFS: Move guery ...
650
651
652
653
  	struct TCP_Server_Info *server = tcon->ses->server;
  
  	if (!server->ops->query_file_info)
  		return -ENOSYS;
abab095d1   Jeff Layton   cifs: add cifs_re...
654

6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
655
  	xid = get_xid();
4ad650445   Pavel Shilovsky   CIFS: Move guery ...
656
  	rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
42274bb22   Pavel Shilovsky   CIFS: Fix DFS han...
657
658
  	switch (rc) {
  	case 0:
eb85d94bd   Pavel Shilovsky   CIFS: Fix symboli...
659
660
  		cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false,
  				       false);
42274bb22   Pavel Shilovsky   CIFS: Fix DFS han...
661
662
663
664
665
666
667
  		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...
668
669
  		/*
  		 * FIXME: legacy server -- fall back to path-based call?
ff215713e   Steve French   [CIFS] checkpatch...
670
671
672
  		 * for now, just skip revalidating and mark inode for
  		 * immediate reval.
  		 */
abab095d1   Jeff Layton   cifs: add cifs_re...
673
674
  		rc = 0;
  		CIFS_I(inode)->time = 0;
42274bb22   Pavel Shilovsky   CIFS: Fix DFS han...
675
  	default:
abab095d1   Jeff Layton   cifs: add cifs_re...
676
  		goto cgfi_exit;
42274bb22   Pavel Shilovsky   CIFS: Fix DFS han...
677
  	}
abab095d1   Jeff Layton   cifs: add cifs_re...
678
679
680
681
682
  
  	/*
  	 * don't bother with SFU junk here -- just mark inode as needing
  	 * revalidation.
  	 */
abab095d1   Jeff Layton   cifs: add cifs_re...
683
684
685
686
  	fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
  	fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
  	cifs_fattr_to_inode(inode, &fattr);
  cgfi_exit:
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
687
  	free_xid(xid);
abab095d1   Jeff Layton   cifs: add cifs_re...
688
689
  	return rc;
  }
1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
690
691
692
  int
  cifs_get_inode_info(struct inode **inode, const char *full_path,
  		    FILE_ALL_INFO *data, struct super_block *sb, int xid,
42eacf9e5   Steve French   [CIFS] Fix cifsac...
693
  		    const struct cifs_fid *fid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694
  {
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
695
696
697
  	bool validinum = false;
  	__u16 srchflgs;
  	int rc = 0, tmprc = ENOSYS;
1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
698
699
  	struct cifs_tcon *tcon;
  	struct TCP_Server_Info *server;
7ffec3724   Jeff Layton   cifs: add refcoun...
700
  	struct tcon_link *tlink;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701
  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702
  	char *buf = NULL;
1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
703
  	bool adjust_tz = false;
0b8f18e35   Jeff Layton   cifs: convert cif...
704
  	struct cifs_fattr fattr;
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
705
  	struct cifs_search_info *srchinf = NULL;
eb85d94bd   Pavel Shilovsky   CIFS: Fix symboli...
706
  	bool symlink = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
707

7ffec3724   Jeff Layton   cifs: add refcoun...
708
709
710
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
711
712
  	tcon = tlink_tcon(tlink);
  	server = tcon->ses->server;
7ffec3724   Jeff Layton   cifs: add refcoun...
713

f96637be0   Joe Perches   [CIFS] cifs: Rena...
714
715
  	cifs_dbg(FYI, "Getting info on %s
  ", full_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716

1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
717
  	if ((data == NULL) && (*inode != NULL)) {
18cceb6a7   Pavel Shilovsky   CIFS: Replace cli...
718
  		if (CIFS_CACHE_READ(CIFS_I(*inode))) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
719
720
  			cifs_dbg(FYI, "No need to revalidate cached inode sizes
  ");
7ffec3724   Jeff Layton   cifs: add refcoun...
721
  			goto cgii_exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
723
  		}
  	}
1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
724
725
726
727
728
729
  	/* if inode info is not passed, get it from server */
  	if (data == NULL) {
  		if (!server->ops->query_path_info) {
  			rc = -ENOSYS;
  			goto cgii_exit;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
730
  		buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
7ffec3724   Jeff Layton   cifs: add refcoun...
731
732
733
734
  		if (buf == NULL) {
  			rc = -ENOMEM;
  			goto cgii_exit;
  		}
1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
735
736
  		data = (FILE_ALL_INFO *)buf;
  		rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path,
eb85d94bd   Pavel Shilovsky   CIFS: Fix symboli...
737
  						  data, &adjust_tz, &symlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
738
  	}
0b8f18e35   Jeff Layton   cifs: convert cif...
739
740
  
  	if (!rc) {
eb85d94bd   Pavel Shilovsky   CIFS: Fix symboli...
741
742
  		cifs_all_info_to_fattr(&fattr, data, cifs_sb, adjust_tz,
  				       symlink);
0b8f18e35   Jeff Layton   cifs: convert cif...
743
744
  	} else if (rc == -EREMOTE) {
  		cifs_create_dfs_fattr(&fattr, sb);
b9a3260f2   Steve French   [CIFS] Enable DFS...
745
  		rc = 0;
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
  	} else if (rc == -EACCES && backup_cred(cifs_sb)) {
  			srchinf = kzalloc(sizeof(struct cifs_search_info),
  						GFP_KERNEL);
  			if (srchinf == NULL) {
  				rc = -ENOMEM;
  				goto cgii_exit;
  			}
  
  			srchinf->endOfSearch = false;
  			srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
  
  			srchflgs = CIFS_SEARCH_CLOSE_ALWAYS |
  					CIFS_SEARCH_CLOSE_AT_END |
  					CIFS_SEARCH_BACKUP_SEARCH;
  
  			rc = CIFSFindFirst(xid, tcon, full_path,
  				cifs_sb, NULL, srchflgs, srchinf, false);
  			if (!rc) {
  				data =
  				(FILE_ALL_INFO *)srchinf->srch_entries_start;
  
  				cifs_dir_info_to_fattr(&fattr,
  				(FILE_DIRECTORY_INFO *)data, cifs_sb);
  				fattr.cf_uniqueid = le64_to_cpu(
  				((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
  				validinum = true;
  
  				cifs_buf_release(srchinf->ntwrk_buf_start);
  			}
  			kfree(srchinf);
4c5930e80   Steve French   Fix warning
776
777
  			if (rc)
  				goto cgii_exit;
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
778
  	} else
7962670e6   Igor Mammedov   [CIFS] DFS patch...
779
  		goto cgii_exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
780

0b8f18e35   Jeff Layton   cifs: convert cif...
781
782
783
784
785
786
  	/*
  	 * If an inode wasn't passed in, then get the inode number
  	 *
  	 * Is an i_ino of zero legal? Can we use that to check if the server
  	 * supports returning inode numbers?  Are there other sanity checks we
  	 * can use to ensure that the server is really filling in that field?
0b8f18e35   Jeff Layton   cifs: convert cif...
787
  	 */
1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
788
  	if (*inode == NULL) {
b9a3260f2   Steve French   [CIFS] Enable DFS...
789
  		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
790
791
792
793
794
795
  			if (validinum == false) {
  				if (server->ops->get_srv_inum)
  					tmprc = server->ops->get_srv_inum(xid,
  						tcon, cifs_sb, full_path,
  						&fattr.cf_uniqueid, data);
  				if (tmprc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
796
797
798
  					cifs_dbg(FYI, "GetSrvInodeNum rc %d
  ",
  						 tmprc);
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
799
800
801
  					fattr.cf_uniqueid = iunique(sb, ROOT_I);
  					cifs_autodisable_serverino(cifs_sb);
  				}
132ac7b77   Jeff Layton   cifs: refactor ne...
802
  			}
c052e2b42   Shirish Pargaonkar   cifs: obtain file...
803
  		} else
0b8f18e35   Jeff Layton   cifs: convert cif...
804
  			fattr.cf_uniqueid = iunique(sb, ROOT_I);
a108471b5   Ross Lagerwall   cifs: Check uniqu...
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
  	} else {
  		if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
  		    validinum == false && server->ops->get_srv_inum) {
  			/*
  			 * Pass a NULL tcon to ensure we don't make a round
  			 * trip to the server. This only works for SMB2+.
  			 */
  			tmprc = server->ops->get_srv_inum(xid,
  				NULL, cifs_sb, full_path,
  				&fattr.cf_uniqueid, data);
  			if (tmprc)
  				fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
  		} else
  			fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
  	}
b9a3260f2   Steve French   [CIFS] Enable DFS...
820

0b8f18e35   Jeff Layton   cifs: convert cif...
821
822
823
824
825
  	/* 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...
826
827
  			cifs_dbg(FYI, "cifs_sfu_type failed: %d
  ", tmprc);
b9a3260f2   Steve French   [CIFS] Enable DFS...
828
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
829

79df1baee   Jeff Layton   cifs: fix use of ...
830
  #ifdef CONFIG_CIFS_ACL
b9a3260f2   Steve French   [CIFS] Enable DFS...
831
832
  	/* fill in 0777 bits from ACL */
  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
833
  		rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
78415d2d3   Shirish Pargaonkar   cifs: Misc. clean...
834
  		if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
835
836
837
  			cifs_dbg(FYI, "%s: Getting ACL failed with error: %d
  ",
  				 __func__, rc);
78415d2d3   Shirish Pargaonkar   cifs: Misc. clean...
838
839
  			goto cgii_exit;
  		}
b9a3260f2   Steve French   [CIFS] Enable DFS...
840
  	}
79df1baee   Jeff Layton   cifs: fix use of ...
841
  #endif /* CONFIG_CIFS_ACL */
b9a3260f2   Steve French   [CIFS] Enable DFS...
842

0b8f18e35   Jeff Layton   cifs: convert cif...
843
844
845
  	/* 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...
846

1b12b9c15   Stefan Metzmacher   cifs: use Minshal...
847
848
  	/* check for Minshall+French symlinks */
  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
cb084b1a9   Sachin Prabhu   cifs: Rename MF s...
849
850
  		tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
  					 full_path);
1b12b9c15   Stefan Metzmacher   cifs: use Minshal...
851
  		if (tmprc)
cb084b1a9   Sachin Prabhu   cifs: Rename MF s...
852
853
  			cifs_dbg(FYI, "check_mf_symlink: %d
  ", tmprc);
1b12b9c15   Stefan Metzmacher   cifs: use Minshal...
854
  	}
1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
855
856
857
  	if (!*inode) {
  		*inode = cifs_iget(sb, &fattr);
  		if (!*inode)
0b8f18e35   Jeff Layton   cifs: convert cif...
858
859
  			rc = -ENOMEM;
  	} else {
7196ac113   Nakajima Akira   Fix to check Uniq...
860
  		/* we already have inode, update it */
a108471b5   Ross Lagerwall   cifs: Check uniqu...
861
862
863
864
865
866
  		/* if uniqueid is different, return error */
  		if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
  		    CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
  			rc = -ESTALE;
  			goto cgii_exit;
  		}
7196ac113   Nakajima Akira   Fix to check Uniq...
867
868
869
870
871
872
  		/* if filetype is different, return error */
  		if (unlikely(((*inode)->i_mode & S_IFMT) !=
  		    (fattr.cf_mode & S_IFMT))) {
  			rc = -ESTALE;
  			goto cgii_exit;
  		}
1208ef1f7   Pavel Shilovsky   CIFS: Move query ...
873
  		cifs_fattr_to_inode(*inode, &fattr);
0b8f18e35   Jeff Layton   cifs: convert cif...
874
  	}
b9a3260f2   Steve French   [CIFS] Enable DFS...
875

7962670e6   Igor Mammedov   [CIFS] DFS patch...
876
  cgii_exit:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
877
  	kfree(buf);
7ffec3724   Jeff Layton   cifs: add refcoun...
878
  	cifs_put_tlink(tlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879
880
  	return rc;
  }
7f8ed420f   Steve French   [CIFS] CIFS suppo...
881
882
883
  static const struct inode_operations cifs_ipc_inode_ops = {
  	.lookup = cifs_lookup,
  };
cc0bad755   Jeff Layton   cifs: add new cif...
884
885
886
887
  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...
888
  	/* don't match inode with different uniqueid */
cc0bad755   Jeff Layton   cifs: add new cif...
889
890
  	if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
  		return 0;
20054bd65   Jeff Layton   cifs: use Creatio...
891
892
893
  	/* use createtime like an i_generation field */
  	if (CIFS_I(inode)->createtime != fattr->cf_createtime)
  		return 0;
f30b9c118   Jeff Layton   cifs: don't allow...
894
895
896
  	/* don't match inode of different type */
  	if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
  		return 0;
5acfec250   Jeff Layton   cifs: reduce fals...
897
  	/* if it's not a directory or has no dentries, then flag it */
b3d9b7a3c   Al Viro   vfs: switch i_den...
898
  	if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
3d6943803   Jeff Layton   cifs: guard again...
899
  		fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
3d6943803   Jeff Layton   cifs: guard again...
900

cc0bad755   Jeff Layton   cifs: add new cif...
901
902
903
904
905
906
907
908
909
  	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...
910
  	CIFS_I(inode)->createtime = fattr->cf_createtime;
cc0bad755   Jeff Layton   cifs: add new cif...
911
912
  	return 0;
  }
5acfec250   Jeff Layton   cifs: reduce fals...
913
914
915
916
917
918
919
920
921
  /*
   * 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...
922
  	spin_lock(&inode->i_lock);
946e51f2b   Al Viro   move d_rcu from o...
923
  	hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
5acfec250   Jeff Layton   cifs: reduce fals...
924
  		if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
873feea09   Nick Piggin   fs: dcache per-in...
925
  			spin_unlock(&inode->i_lock);
5acfec250   Jeff Layton   cifs: reduce fals...
926
927
928
  			return true;
  		}
  	}
873feea09   Nick Piggin   fs: dcache per-in...
929
  	spin_unlock(&inode->i_lock);
5acfec250   Jeff Layton   cifs: reduce fals...
930
931
  	return false;
  }
cc0bad755   Jeff Layton   cifs: add new cif...
932
933
934
935
936
937
  /* 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...
938
  retry_iget5_locked:
f96637be0   Joe Perches   [CIFS] cifs: Rena...
939
940
  	cifs_dbg(FYI, "looking for uniqueid=%llu
  ", fattr->cf_uniqueid);
cc0bad755   Jeff Layton   cifs: add new cif...
941
942
943
944
945
  
  	/* 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...
946
  	if (inode) {
5acfec250   Jeff Layton   cifs: reduce fals...
947
  		/* was there a potentially problematic inode collision? */
3d6943803   Jeff Layton   cifs: guard again...
948
  		if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
3d6943803   Jeff Layton   cifs: guard again...
949
  			fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
5acfec250   Jeff Layton   cifs: reduce fals...
950
951
952
953
954
955
956
  
  			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...
957
  		}
cc0bad755   Jeff Layton   cifs: add new cif...
958
959
960
961
962
  		cifs_fattr_to_inode(inode, fattr);
  		if (sb->s_flags & MS_NOATIME)
  			inode->i_flags |= S_NOATIME | S_NOCMTIME;
  		if (inode->i_state & I_NEW) {
  			inode->i_ino = hash;
0ccd48025   Steve French   [CIFS] Missing ifdef
963
  #ifdef CONFIG_CIFS_FSCACHE
9451a9a52   Suresh Jayaraman   cifs: define inod...
964
965
  			/* initialize per-inode cache cookie pointer */
  			CIFS_I(inode)->fscache = NULL;
0ccd48025   Steve French   [CIFS] Missing ifdef
966
  #endif
cc0bad755   Jeff Layton   cifs: add new cif...
967
968
969
970
971
972
  			unlock_new_inode(inode);
  		}
  	}
  
  	return inode;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
973
  /* gets root inode */
9b6763e0a   Shirish Pargaonkar   cifs: Remove unus...
974
  struct inode *cifs_root_iget(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
975
  {
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
976
  	unsigned int xid;
0d424ad0a   Jeff Layton   cifs: add cifs_sb...
977
  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
cc0bad755   Jeff Layton   cifs: add new cif...
978
  	struct inode *inode = NULL;
ce634ab28   David Howells   iget: stop CIFS f...
979
  	long rc;
96daf2b09   Steve French   [CIFS] Rename thr...
980
  	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
a6b5058fa   Aurelien Aptel   fs/cifs: make sha...
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
  	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...
997

6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
998
  	xid = get_xid();
b5b374eab   Steve French   Workaround Mac se...
999
  	if (tcon->unix_ext) {
a6b5058fa   Aurelien Aptel   fs/cifs: make sha...
1000
  		rc = cifs_get_inode_info_unix(&inode, path, sb, xid);
b5b374eab   Steve French   Workaround Mac se...
1001
1002
1003
1004
1005
1006
  		/* some servers mistakenly claim POSIX support */
  		if (rc != -EOPNOTSUPP)
  			goto iget_no_retry;
  		cifs_dbg(VFS, "server does not support POSIX extensions");
  		tcon->unix_ext = false;
  	}
a6b5058fa   Aurelien Aptel   fs/cifs: make sha...
1007
1008
  	convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
  	rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
0b8f18e35   Jeff Layton   cifs: convert cif...
1009

b5b374eab   Steve French   Workaround Mac se...
1010
  iget_no_retry:
a7851ce73   Oskar Schirmer   cifs: fix another...
1011
1012
1013
1014
  	if (!inode) {
  		inode = ERR_PTR(rc);
  		goto out;
  	}
cc0bad755   Jeff Layton   cifs: add new cif...
1015

0ccd48025   Steve French   [CIFS] Missing ifdef
1016
  #ifdef CONFIG_CIFS_FSCACHE
d03382ce9   Suresh Jayaraman   cifs: define supe...
1017
  	/* populate tcon->resource_id */
0d424ad0a   Jeff Layton   cifs: add cifs_sb...
1018
  	tcon->resource_id = CIFS_I(inode)->uniqueid;
0ccd48025   Steve French   [CIFS] Missing ifdef
1019
  #endif
d03382ce9   Suresh Jayaraman   cifs: define supe...
1020

0d424ad0a   Jeff Layton   cifs: add cifs_sb...
1021
  	if (rc && tcon->ipc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1022
1023
  		cifs_dbg(FYI, "ipc connection - fake read inode
  ");
b7ca69289   Steve French   CIFS: Protect i_n...
1024
  		spin_lock(&inode->i_lock);
7f8ed420f   Steve French   [CIFS] CIFS suppo...
1025
  		inode->i_mode |= S_IFDIR;
bfe868486   Miklos Szeredi   filesystems: add ...
1026
  		set_nlink(inode, 2);
7f8ed420f   Steve French   [CIFS] CIFS suppo...
1027
1028
1029
1030
  		inode->i_op = &cifs_ipc_inode_ops;
  		inode->i_fop = &simple_dir_operations;
  		inode->i_uid = cifs_sb->mnt_uid;
  		inode->i_gid = cifs_sb->mnt_gid;
b7ca69289   Steve French   CIFS: Protect i_n...
1031
  		spin_unlock(&inode->i_lock);
ad661334b   Steve French   [CIFS] mount of I...
1032
  	} else if (rc) {
ce634ab28   David Howells   iget: stop CIFS f...
1033
  		iget_failed(inode);
a7851ce73   Oskar Schirmer   cifs: fix another...
1034
  		inode = ERR_PTR(rc);
7f8ed420f   Steve French   [CIFS] CIFS suppo...
1035
  	}
a7851ce73   Oskar Schirmer   cifs: fix another...
1036
  out:
a6b5058fa   Aurelien Aptel   fs/cifs: make sha...
1037
  	kfree(path);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1038
  	/* can not call macro free_xid here since in a void func
ce634ab28   David Howells   iget: stop CIFS f...
1039
1040
  	 * TODO: This is no longer true
  	 */
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1041
  	_free_xid(xid);
ce634ab28   David Howells   iget: stop CIFS f...
1042
  	return inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1043
  }
ed6875e0d   Pavel Shilovsky   CIFS: Move unlink...
1044
  int
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1045
  cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
ed6875e0d   Pavel Shilovsky   CIFS: Move unlink...
1046
  		   char *full_path, __u32 dosattr)
388e57b27   Steve French   [CIFS] use common...
1047
  {
388e57b27   Steve French   [CIFS] use common...
1048
  	bool set_time = false;
388e57b27   Steve French   [CIFS] use common...
1049
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
6bdf6dbd6   Pavel Shilovsky   CIFS: Move set_fi...
1050
  	struct TCP_Server_Info *server;
388e57b27   Steve French   [CIFS] use common...
1051
  	FILE_BASIC_INFO	info_buf;
1adcb7109   Steve French   [CIFS] add extra ...
1052
1053
  	if (attrs == NULL)
  		return -EINVAL;
6bdf6dbd6   Pavel Shilovsky   CIFS: Move set_fi...
1054
1055
1056
  	server = cifs_sb_master_tcon(cifs_sb)->ses->server;
  	if (!server->ops->set_file_info)
  		return -ENOSYS;
388e57b27   Steve French   [CIFS] use common...
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
  	if (attrs->ia_valid & ATTR_ATIME) {
  		set_time = true;
  		info_buf.LastAccessTime =
  			cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
  	} else
  		info_buf.LastAccessTime = 0;
  
  	if (attrs->ia_valid & ATTR_MTIME) {
  		set_time = true;
  		info_buf.LastWriteTime =
  		    cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
  	} 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...
1078
1079
  		cifs_dbg(FYI, "CIFS - CTIME changed
  ");
388e57b27   Steve French   [CIFS] use common...
1080
1081
1082
1083
1084
1085
1086
  		info_buf.ChangeTime =
  		    cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
  	} 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...
1087
  	return server->ops->set_file_info(inode, full_path, &info_buf, xid);
388e57b27   Steve French   [CIFS] use common...
1088
  }
a12a1ac7a   Jeff Layton   cifs: move rename...
1089
  /*
ed6875e0d   Pavel Shilovsky   CIFS: Move unlink...
1090
   * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
a12a1ac7a   Jeff Layton   cifs: move rename...
1091
1092
1093
   * and rename it to a random name that hopefully won't conflict with
   * anything else.
   */
ed6875e0d   Pavel Shilovsky   CIFS: Move unlink...
1094
1095
1096
  int
  cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
  			   const unsigned int xid)
a12a1ac7a   Jeff Layton   cifs: move rename...
1097
1098
1099
  {
  	int oplock = 0;
  	int rc;
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1100
1101
  	struct cifs_fid fid;
  	struct cifs_open_parms oparms;
2b0143b5c   David Howells   VFS: normal files...
1102
  	struct inode *inode = d_inode(dentry);
a12a1ac7a   Jeff Layton   cifs: move rename...
1103
1104
  	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
1105
  	struct tcon_link *tlink;
96daf2b09   Steve French   [CIFS] Rename thr...
1106
  	struct cifs_tcon *tcon;
3270958b7   Steve French   [CIFS] undo chang...
1107
1108
  	__u32 dosattr, origattr;
  	FILE_BASIC_INFO *info_buf = NULL;
a12a1ac7a   Jeff Layton   cifs: move rename...
1109

7ffec3724   Jeff Layton   cifs: add refcoun...
1110
1111
1112
1113
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
  	tcon = tlink_tcon(tlink);
c483a9841   Sachin Prabhu   cifs: Check serve...
1114
1115
1116
1117
1118
1119
1120
1121
  	/*
  	 * 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...
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
  	oparms.tcon = tcon;
  	oparms.cifs_sb = cifs_sb;
  	oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
  	oparms.create_options = CREATE_NOT_DIR;
  	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...
1132
1133
  	if (rc != 0)
  		goto out;
3270958b7   Steve French   [CIFS] undo chang...
1134
1135
1136
1137
1138
  	origattr = cifsInode->cifsAttrs;
  	if (origattr == 0)
  		origattr |= ATTR_NORMAL;
  
  	dosattr = origattr & ~ATTR_READONLY;
a12a1ac7a   Jeff Layton   cifs: move rename...
1139
1140
1141
  	if (dosattr == 0)
  		dosattr |= ATTR_NORMAL;
  	dosattr |= ATTR_HIDDEN;
3270958b7   Steve French   [CIFS] undo chang...
1142
1143
1144
1145
1146
1147
1148
1149
  	/* 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...
1150
  		rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
3270958b7   Steve French   [CIFS] undo chang...
1151
1152
1153
  					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...
1154
  		if (!rc)
3270958b7   Steve French   [CIFS] undo chang...
1155
1156
1157
  			cifsInode->cifsAttrs = dosattr;
  		else
  			dosattr = origattr; /* since not able to change them */
a12a1ac7a   Jeff Layton   cifs: move rename...
1158
  	}
a12a1ac7a   Jeff Layton   cifs: move rename...
1159

dd1db2ded   Jeff Layton   cifs: don't use C...
1160
  	/* rename the file */
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1161
1162
  	rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
  				   cifs_sb->local_nls,
2baa26825   Steve French   Remap reserved po...
1163
  				   cifs_remap(cifs_sb));
3270958b7   Steve French   [CIFS] undo chang...
1164
  	if (rc != 0) {
47c78f4a7   Sachin Prabhu   cifs: map NT_STAT...
1165
  		rc = -EBUSY;
3270958b7   Steve French   [CIFS] undo chang...
1166
1167
  		goto undo_setattr;
  	}
6d22f0989   Jeff Layton   cifs: add functio...
1168

3270958b7   Steve French   [CIFS] undo chang...
1169
  	/* try to set DELETE_ON_CLOSE */
aff8d5ca7   Jeff Layton   cifs: convert boo...
1170
  	if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1171
  		rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
3270958b7   Steve French   [CIFS] undo chang...
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
  					       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...
1184
  			rc = -EBUSY;
3270958b7   Steve French   [CIFS] undo chang...
1185
1186
  			goto undo_rename;
  		}
aff8d5ca7   Jeff Layton   cifs: convert boo...
1187
  		set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
3270958b7   Steve French   [CIFS] undo chang...
1188
  	}
7ce86d5a9   Jeff Layton   cifs: work around...
1189

a12a1ac7a   Jeff Layton   cifs: move rename...
1190
  out_close:
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1191
  	CIFSSMBClose(xid, tcon, fid.netfid);
a12a1ac7a   Jeff Layton   cifs: move rename...
1192
  out:
3270958b7   Steve French   [CIFS] undo chang...
1193
  	kfree(info_buf);
7ffec3724   Jeff Layton   cifs: add refcoun...
1194
  	cifs_put_tlink(tlink);
a12a1ac7a   Jeff Layton   cifs: move rename...
1195
  	return rc;
3270958b7   Steve French   [CIFS] undo chang...
1196
1197
1198
1199
1200
1201
1202
  
  	/*
  	 * 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...
1203
  	CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
2baa26825   Steve French   Remap reserved po...
1204
  				cifs_sb->local_nls, cifs_remap(cifs_sb));
3270958b7   Steve French   [CIFS] undo chang...
1205
1206
1207
  undo_setattr:
  	if (dosattr != origattr) {
  		info_buf->Attributes = cpu_to_le32(origattr);
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1208
  		if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
3270958b7   Steve French   [CIFS] undo chang...
1209
1210
1211
1212
1213
  					current->tgid))
  			cifsInode->cifsAttrs = origattr;
  	}
  
  	goto out_close;
a12a1ac7a   Jeff Layton   cifs: move rename...
1214
  }
b7ca69289   Steve French   CIFS: Protect i_n...
1215
1216
1217
1218
1219
1220
1221
1222
1223
  /* 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_...
1224
1225
  
  /*
2b0143b5c   David Howells   VFS: normal files...
1226
   * If d_inode(dentry) is null (usually meaning the cached dentry
ff6945279   Steve French   [CIFS] Make cifs_...
1227
   * is a negative dentry) then we would attempt a standard SMB delete, but
af901ca18   André Goddard Rosa   tree-wide: fix as...
1228
1229
   * if that fails we can not attempt the fall back mechanisms on EACCESS
   * but will return the EACCESS to the caller. Note that the VFS does not call
ff6945279   Steve French   [CIFS] Make cifs_...
1230
1231
   * unlink on negative dentries currently.
   */
5f0319a79   Jeff Layton   cifs: clean up va...
1232
  int cifs_unlink(struct inode *dir, struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1233
1234
  {
  	int rc = 0;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1235
  	unsigned int xid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1236
  	char *full_path = NULL;
2b0143b5c   David Howells   VFS: normal files...
1237
  	struct inode *inode = d_inode(dentry);
ff6945279   Steve French   [CIFS] Make cifs_...
1238
  	struct cifsInodeInfo *cifs_inode;
5f0319a79   Jeff Layton   cifs: clean up va...
1239
1240
  	struct super_block *sb = dir->i_sb;
  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
1241
  	struct tcon_link *tlink;
96daf2b09   Steve French   [CIFS] Rename thr...
1242
  	struct cifs_tcon *tcon;
ed6875e0d   Pavel Shilovsky   CIFS: Move unlink...
1243
  	struct TCP_Server_Info *server;
6050247d8   Steve French   [CIFS] clean up ...
1244
1245
  	struct iattr *attrs = NULL;
  	__u32 dosattr = 0, origattr = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1246

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

7ffec3724   Jeff Layton   cifs: add refcoun...
1250
1251
1252
1253
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
  	tcon = tlink_tcon(tlink);
ed6875e0d   Pavel Shilovsky   CIFS: Move unlink...
1254
  	server = tcon->ses->server;
7ffec3724   Jeff Layton   cifs: add refcoun...
1255

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

5f0319a79   Jeff Layton   cifs: clean up va...
1258
1259
1260
  	/* Unlink can be called from rename so we can not take the
  	 * sb->s_vfs_rename_mutex here */
  	full_path = build_path_from_dentry(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1261
  	if (full_path == NULL) {
0f3bc09ee   Suresh Jayaraman   cifs: Fix incorre...
1262
  		rc = -ENOMEM;
7ffec3724   Jeff Layton   cifs: add refcoun...
1263
  		goto unlink_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1264
  	}
2d785a50a   Steve French   [CIFS] Add suppor...
1265

29e20f9c6   Pavel Shilovsky   CIFS: Make CAP_* ...
1266
1267
  	if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
  				le64_to_cpu(tcon->fsUnixInfo.Capability))) {
5f0319a79   Jeff Layton   cifs: clean up va...
1268
  		rc = CIFSPOSIXDelFile(xid, tcon, full_path,
2d785a50a   Steve French   [CIFS] Add suppor...
1269
  			SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
2baa26825   Steve French   Remap reserved po...
1270
  			cifs_remap(cifs_sb));
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1271
1272
  		cifs_dbg(FYI, "posix del rc %d
  ", rc);
2d785a50a   Steve French   [CIFS] Add suppor...
1273
1274
1275
  		if ((rc == 0) || (rc == -ENOENT))
  			goto psx_del_no_retry;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1276

6050247d8   Steve French   [CIFS] clean up ...
1277
  retry_std_delete:
ed6875e0d   Pavel Shilovsky   CIFS: Move unlink...
1278
1279
1280
1281
1282
1283
  	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 ...
1284

2d785a50a   Steve French   [CIFS] Add suppor...
1285
  psx_del_no_retry:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1286
  	if (!rc) {
5f0319a79   Jeff Layton   cifs: clean up va...
1287
  		if (inode)
b7ca69289   Steve French   CIFS: Protect i_n...
1288
  			cifs_drop_nlink(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1289
  	} else if (rc == -ENOENT) {
5f0319a79   Jeff Layton   cifs: clean up va...
1290
  		d_drop(dentry);
47c78f4a7   Sachin Prabhu   cifs: map NT_STAT...
1291
  	} else if (rc == -EBUSY) {
ed6875e0d   Pavel Shilovsky   CIFS: Move unlink...
1292
1293
1294
1295
1296
1297
  		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_...
1298
  	} else if ((rc == -EACCES) && (dosattr == 0) && inode) {
388e57b27   Steve French   [CIFS] use common...
1299
1300
1301
1302
  		attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
  		if (attrs == NULL) {
  			rc = -ENOMEM;
  			goto out_reval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1303
  		}
388e57b27   Steve French   [CIFS] use common...
1304
1305
  
  		/* try to reset dos attributes */
ff6945279   Steve French   [CIFS] Make cifs_...
1306
1307
  		cifs_inode = CIFS_I(inode);
  		origattr = cifs_inode->cifsAttrs;
6050247d8   Steve French   [CIFS] clean up ...
1308
1309
1310
  		if (origattr == 0)
  			origattr |= ATTR_NORMAL;
  		dosattr = origattr & ~ATTR_READONLY;
388e57b27   Steve French   [CIFS] use common...
1311
1312
1313
1314
1315
  		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...
1316
1317
  		if (rc != 0)
  			goto out_reval;
6050247d8   Steve French   [CIFS] clean up ...
1318
1319
  
  		goto retry_std_delete;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1320
  	}
6050247d8   Steve French   [CIFS] clean up ...
1321
1322
1323
1324
  
  	/* 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...
1325
  out_reval:
4523cc304   Steve French   [CIFS] UID/GID ov...
1326
  	if (inode) {
ff6945279   Steve French   [CIFS] Make cifs_...
1327
1328
  		cifs_inode = CIFS_I(inode);
  		cifs_inode->time = 0;	/* will force revalidate to get info
5f0319a79   Jeff Layton   cifs: clean up va...
1329
1330
  					   when needed */
  		inode->i_ctime = current_fs_time(sb);
06bcfedd0   Steve French   [CIFS] Fix typo i...
1331
  	}
5f0319a79   Jeff Layton   cifs: clean up va...
1332
  	dir->i_ctime = dir->i_mtime = current_fs_time(sb);
ff6945279   Steve French   [CIFS] Make cifs_...
1333
  	cifs_inode = CIFS_I(dir);
6050247d8   Steve French   [CIFS] clean up ...
1334
  	CIFS_I(dir)->time = 0;	/* force revalidate of dir as well */
7ffec3724   Jeff Layton   cifs: add refcoun...
1335
  unlink_out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1336
  	kfree(full_path);
6050247d8   Steve French   [CIFS] clean up ...
1337
  	kfree(attrs);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1338
  	free_xid(xid);
7ffec3724   Jeff Layton   cifs: add refcoun...
1339
  	cifs_put_tlink(tlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1340
1341
  	return rc;
  }
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1342
  static int
101b92d95   Jeff Layton   cifs: cleanups fo...
1343
  cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1344
1345
1346
1347
  		 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...
1348
  	struct inode *inode = NULL;
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1349
1350
  
  	if (tcon->unix_ext)
101b92d95   Jeff Layton   cifs: cleanups fo...
1351
  		rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1352
1353
  					      xid);
  	else
101b92d95   Jeff Layton   cifs: cleanups fo...
1354
1355
  		rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
  					 xid, NULL);
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1356
1357
  	if (rc)
  		return rc;
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1358
1359
  	/*
  	 * setting nlink not necessary except in cases where we failed to get it
101b92d95   Jeff Layton   cifs: cleanups fo...
1360
1361
  	 * 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...
1362
  	 */
101b92d95   Jeff Layton   cifs: cleanups fo...
1363
1364
  	if (inode->i_nlink < 2)
  		set_nlink(inode, 2);
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1365
1366
  	mode &= ~current_umask();
  	/* must turn on setgid bit if parent dir has it */
101b92d95   Jeff Layton   cifs: cleanups fo...
1367
  	if (parent->i_mode & S_ISGID)
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
  		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...
1379
  			args.uid = current_fsuid();
101b92d95   Jeff Layton   cifs: cleanups fo...
1380
  			if (parent->i_mode & S_ISGID)
49418b2c2   Eric W. Biederman   cifs: Modify stru...
1381
  				args.gid = parent->i_gid;
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1382
  			else
49418b2c2   Eric W. Biederman   cifs: Modify stru...
1383
  				args.gid = current_fsgid();
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1384
  		} else {
49418b2c2   Eric W. Biederman   cifs: Modify stru...
1385
1386
  			args.uid = INVALID_UID; /* no change */
  			args.gid = INVALID_GID; /* no change */
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1387
1388
1389
  		}
  		CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
  				       cifs_sb->local_nls,
2baa26825   Steve French   Remap reserved po...
1390
  				       cifs_remap(cifs_sb));
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1391
  	} else {
f436720e9   Pavel Shilovsky   CIFS: Separate pr...
1392
  		struct TCP_Server_Info *server = tcon->ses->server;
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1393
  		if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
f436720e9   Pavel Shilovsky   CIFS: Separate pr...
1394
  		    (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
101b92d95   Jeff Layton   cifs: cleanups fo...
1395
  			server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
f436720e9   Pavel Shilovsky   CIFS: Separate pr...
1396
  						   tcon, xid);
101b92d95   Jeff Layton   cifs: cleanups fo...
1397
1398
1399
1400
1401
1402
1403
1404
1405
  		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...
1406
1407
  		}
  	}
101b92d95   Jeff Layton   cifs: cleanups fo...
1408
  	d_instantiate(dentry, inode);
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
  	return rc;
  }
  
  static int
  cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
  		 const char *full_path, struct cifs_sb_info *cifs_sb,
  		 struct cifs_tcon *tcon, const unsigned int xid)
  {
  	int rc = 0;
  	u32 oplock = 0;
  	FILE_UNIX_BASIC_INFO *info = NULL;
  	struct inode *newinode = NULL;
  	struct cifs_fattr fattr;
  
  	info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
  	if (info == NULL) {
  		rc = -ENOMEM;
  		goto posix_mkdir_out;
  	}
  
  	mode &= ~current_umask();
  	rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
  			     NULL /* netfid */, info, &oplock, full_path,
2baa26825   Steve French   Remap reserved po...
1432
  			     cifs_sb->local_nls, cifs_remap(cifs_sb));
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1433
1434
1435
  	if (rc == -EOPNOTSUPP)
  		goto posix_mkdir_out;
  	else if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1436
1437
  		cifs_dbg(FYI, "posix mkdir returned 0x%x
  ", rc);
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
  		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...
1459
1460
1461
  	cifs_dbg(FYI, "instantiated dentry %p %pd to inode %p
  ",
  		 dentry, dentry, newinode);
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1462
1463
  
  	if (newinode->i_nlink != 2)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1464
1465
1466
  		cifs_dbg(FYI, "unexpected number of links %d
  ",
  			 newinode->i_nlink);
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
  #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;
  }
18bb1db3e   Al Viro   switch vfs_mkdir(...
1477
  int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1478
  {
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1479
  	int rc = 0;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1480
  	unsigned int xid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1481
  	struct cifs_sb_info *cifs_sb;
7ffec3724   Jeff Layton   cifs: add refcoun...
1482
  	struct tcon_link *tlink;
29e20f9c6   Pavel Shilovsky   CIFS: Make CAP_* ...
1483
  	struct cifs_tcon *tcon;
f436720e9   Pavel Shilovsky   CIFS: Separate pr...
1484
  	struct TCP_Server_Info *server;
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1485
  	char *full_path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1486

f96637be0   Joe Perches   [CIFS] cifs: Rena...
1487
1488
1489
  	cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p
  ",
  		 mode, inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1490

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1491
  	cifs_sb = CIFS_SB(inode->i_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
1492
1493
1494
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
29e20f9c6   Pavel Shilovsky   CIFS: Make CAP_* ...
1495
  	tcon = tlink_tcon(tlink);
7ffec3724   Jeff Layton   cifs: add refcoun...
1496

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

7f57356b7   Steve French   [CIFS] Remove cif...
1499
  	full_path = build_path_from_dentry(direntry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1500
  	if (full_path == NULL) {
0f3bc09ee   Suresh Jayaraman   cifs: Fix incorre...
1501
  		rc = -ENOMEM;
7ffec3724   Jeff Layton   cifs: add refcoun...
1502
  		goto mkdir_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1503
  	}
50c2f7538   Steve French   [CIFS] whitespace...
1504

29e20f9c6   Pavel Shilovsky   CIFS: Make CAP_* ...
1505
1506
  	if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
  				le64_to_cpu(tcon->fsUnixInfo.Capability))) {
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1507
1508
1509
  		rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
  				      tcon, xid);
  		if (rc != -EOPNOTSUPP)
2dd29d313   Steve French   [CIFS] New CIFS P...
1510
  			goto mkdir_out;
fb8c4b14d   Steve French   [CIFS] whitespace...
1511
  	}
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1512

f436720e9   Pavel Shilovsky   CIFS: Separate pr...
1513
1514
1515
1516
1517
1518
  	server = tcon->ses->server;
  
  	if (!server->ops->mkdir) {
  		rc = -ENOSYS;
  		goto mkdir_out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1519
  	/* BB add setting the equivalent of mode via CreateX w/ACLs */
f436720e9   Pavel Shilovsky   CIFS: Separate pr...
1520
  	rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1521
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1522
1523
  		cifs_dbg(FYI, "cifs_mkdir returned 0x%x
  ", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1524
  		d_drop(direntry);
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1525
  		goto mkdir_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1526
  	}
ff691e969   Pavel Shilovsky   CIFS: Simplify ci...
1527
1528
1529
  
  	rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
  			      xid);
fb8c4b14d   Steve French   [CIFS] whitespace...
1530
  mkdir_out:
6de2ce423   Pavel Shilovsky   CIFS: Fix mkdir/r...
1531
1532
1533
1534
1535
  	/*
  	 * Force revalidate to get parent dir info when needed since cached
  	 * attributes are invalid now.
  	 */
  	CIFS_I(inode)->time = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1536
  	kfree(full_path);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1537
  	free_xid(xid);
7ffec3724   Jeff Layton   cifs: add refcoun...
1538
  	cifs_put_tlink(tlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1539
1540
1541
1542
1543
1544
  	return rc;
  }
  
  int cifs_rmdir(struct inode *inode, struct dentry *direntry)
  {
  	int rc = 0;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1545
  	unsigned int xid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1546
  	struct cifs_sb_info *cifs_sb;
7ffec3724   Jeff Layton   cifs: add refcoun...
1547
  	struct tcon_link *tlink;
f958ca5d8   Pavel Shilovsky   CIFS: Move rmdir ...
1548
1549
  	struct cifs_tcon *tcon;
  	struct TCP_Server_Info *server;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1550
1551
  	char *full_path = NULL;
  	struct cifsInodeInfo *cifsInode;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1552
1553
  	cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p
  ", inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1554

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

7f57356b7   Steve French   [CIFS] Remove cif...
1557
  	full_path = build_path_from_dentry(direntry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1558
  	if (full_path == NULL) {
0f3bc09ee   Suresh Jayaraman   cifs: Fix incorre...
1559
  		rc = -ENOMEM;
7ffec3724   Jeff Layton   cifs: add refcoun...
1560
  		goto rmdir_exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1561
  	}
7ffec3724   Jeff Layton   cifs: add refcoun...
1562
1563
1564
1565
1566
1567
  	cifs_sb = CIFS_SB(inode->i_sb);
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink)) {
  		rc = PTR_ERR(tlink);
  		goto rmdir_exit;
  	}
f958ca5d8   Pavel Shilovsky   CIFS: Move rmdir ...
1568
1569
1570
1571
1572
1573
1574
1575
  	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...
1576

f958ca5d8   Pavel Shilovsky   CIFS: Move rmdir ...
1577
  	rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
1578
  	cifs_put_tlink(tlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1579
1580
  
  	if (!rc) {
2b0143b5c   David Howells   VFS: normal files...
1581
1582
1583
1584
  		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
1585
  	}
2b0143b5c   David Howells   VFS: normal files...
1586
  	cifsInode = CIFS_I(d_inode(direntry));
6de2ce423   Pavel Shilovsky   CIFS: Fix mkdir/r...
1587
1588
  	/* force revalidate to go get info when needed */
  	cifsInode->time = 0;
42c245447   Steve French   [CIFS] revalidate...
1589
1590
  
  	cifsInode = CIFS_I(inode);
6de2ce423   Pavel Shilovsky   CIFS: Fix mkdir/r...
1591
1592
1593
1594
1595
  	/*
  	 * Force revalidate to get parent dir info when needed since cached
  	 * attributes are invalid now.
  	 */
  	cifsInode->time = 0;
42c245447   Steve French   [CIFS] revalidate...
1596

2b0143b5c   David Howells   VFS: normal files...
1597
  	d_inode(direntry)->i_ctime = inode->i_ctime = inode->i_mtime =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1598
  		current_fs_time(inode->i_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
1599
  rmdir_exit:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1600
  	kfree(full_path);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1601
  	free_xid(xid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1602
1603
  	return rc;
  }
ee2fd967f   Steve French   [CIFS] fix busy-...
1604
  static int
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1605
1606
1607
  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-...
1608
1609
  {
  	struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
1610
  	struct tcon_link *tlink;
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1611
1612
  	struct cifs_tcon *tcon;
  	struct TCP_Server_Info *server;
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1613
1614
  	struct cifs_fid fid;
  	struct cifs_open_parms oparms;
ee2fd967f   Steve French   [CIFS] fix busy-...
1615
  	int oplock, rc;
7ffec3724   Jeff Layton   cifs: add refcoun...
1616
1617
1618
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1619
1620
1621
1622
1623
  	tcon = tlink_tcon(tlink);
  	server = tcon->ses->server;
  
  	if (!server->ops->rename)
  		return -ENOSYS;
7ffec3724   Jeff Layton   cifs: add refcoun...
1624

ee2fd967f   Steve French   [CIFS] fix busy-...
1625
  	/* try path-based rename first */
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1626
  	rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
ee2fd967f   Steve French   [CIFS] fix busy-...
1627
1628
  
  	/*
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1629
1630
  	 * 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-...
1631
1632
  	 * rename by filehandle to various Windows servers.
  	 */
47c78f4a7   Sachin Prabhu   cifs: map NT_STAT...
1633
  	if (rc == 0 || rc != -EBUSY)
7ffec3724   Jeff Layton   cifs: add refcoun...
1634
  		goto do_rename_exit;
ee2fd967f   Steve French   [CIFS] fix busy-...
1635

ed0e3ace5   Jeff Layton   cifs: don't attem...
1636
1637
  	/* open-file renames don't work across directories */
  	if (to_dentry->d_parent != from_dentry->d_parent)
7ffec3724   Jeff Layton   cifs: add refcoun...
1638
  		goto do_rename_exit;
ed0e3ace5   Jeff Layton   cifs: don't attem...
1639

d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1640
1641
  	oparms.tcon = tcon;
  	oparms.cifs_sb = cifs_sb;
ee2fd967f   Steve French   [CIFS] fix busy-...
1642
  	/* open the file to be renamed -- we need DELETE perms */
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1643
1644
1645
1646
1647
1648
1649
1650
  	oparms.desired_access = DELETE;
  	oparms.create_options = CREATE_NOT_DIR;
  	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-...
1651
  	if (rc == 0) {
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1652
  		rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
ee2fd967f   Steve French   [CIFS] fix busy-...
1653
  				(const char *) to_dentry->d_name.name,
2baa26825   Steve French   Remap reserved po...
1654
  				cifs_sb->local_nls, cifs_remap(cifs_sb));
d81b8a40e   Pavel Shilovsky   CIFS: Cleanup cif...
1655
  		CIFSSMBClose(xid, tcon, fid.netfid);
ee2fd967f   Steve French   [CIFS] fix busy-...
1656
  	}
7ffec3724   Jeff Layton   cifs: add refcoun...
1657
1658
  do_rename_exit:
  	cifs_put_tlink(tlink);
ee2fd967f   Steve French   [CIFS] fix busy-...
1659
1660
  	return rc;
  }
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1661
  int
7c33d5972   Miklos Szeredi   cifs: support REN...
1662
1663
1664
  cifs_rename2(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
1665
  {
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1666
1667
  	char *from_name = NULL;
  	char *to_name = NULL;
639e7a913   Jeff Layton   cifs: eliminate r...
1668
  	struct cifs_sb_info *cifs_sb;
7ffec3724   Jeff Layton   cifs: add refcoun...
1669
  	struct tcon_link *tlink;
96daf2b09   Steve French   [CIFS] Rename thr...
1670
  	struct cifs_tcon *tcon;
ee2fd967f   Steve French   [CIFS] fix busy-...
1671
1672
  	FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
  	FILE_UNIX_BASIC_INFO *info_buf_target;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1673
1674
  	unsigned int xid;
  	int rc, tmprc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1675

7c33d5972   Miklos Szeredi   cifs: support REN...
1676
1677
  	if (flags & ~RENAME_NOREPLACE)
  		return -EINVAL;
639e7a913   Jeff Layton   cifs: eliminate r...
1678
  	cifs_sb = CIFS_SB(source_dir->i_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
1679
1680
1681
1682
  	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
1683

6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1684
  	xid = get_xid();
ee2fd967f   Steve French   [CIFS] fix busy-...
1685
1686
  
  	/*
ee2fd967f   Steve French   [CIFS] fix busy-...
1687
1688
1689
  	 * we already have the rename sem so we do not need to
  	 * grab it again here to protect the path integrity
  	 */
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1690
1691
  	from_name = build_path_from_dentry(source_dentry);
  	if (from_name == NULL) {
ee2fd967f   Steve French   [CIFS] fix busy-...
1692
1693
1694
  		rc = -ENOMEM;
  		goto cifs_rename_exit;
  	}
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1695
1696
  	to_name = build_path_from_dentry(target_dentry);
  	if (to_name == NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1697
1698
1699
  		rc = -ENOMEM;
  		goto cifs_rename_exit;
  	}
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1700
1701
  	rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
  			    to_name);
ee2fd967f   Steve French   [CIFS] fix busy-...
1702

7c33d5972   Miklos Szeredi   cifs: support REN...
1703
1704
1705
1706
1707
  	/*
  	 * 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...
1708
1709
  	if (rc == -EEXIST && tcon->unix_ext) {
  		/*
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1710
1711
  		 * Are src and dst hardlinks of same inode? We can only tell
  		 * with unix extensions enabled.
14121bdcc   Jeff Layton   cifs: make cifs_r...
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
  		 */
  		info_buf_source =
  			kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
  					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...
1722
1723
1724
  		tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
  					     info_buf_source,
  					     cifs_sb->local_nls,
2baa26825   Steve French   Remap reserved po...
1725
  					     cifs_remap(cifs_sb));
8d281efb6   Jeff Layton   cifs: fix unlinki...
1726
  		if (tmprc != 0)
14121bdcc   Jeff Layton   cifs: make cifs_r...
1727
  			goto unlink_target;
ee2fd967f   Steve French   [CIFS] fix busy-...
1728

8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1729
1730
1731
  		tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
  					     info_buf_target,
  					     cifs_sb->local_nls,
2baa26825   Steve French   Remap reserved po...
1732
  					     cifs_remap(cifs_sb));
14121bdcc   Jeff Layton   cifs: make cifs_r...
1733

8d281efb6   Jeff Layton   cifs: fix unlinki...
1734
  		if (tmprc == 0 && (info_buf_source->UniqueId ==
ae6884a9d   Jeff Layton   cifs: fix renamin...
1735
  				   info_buf_target->UniqueId)) {
14121bdcc   Jeff Layton   cifs: make cifs_r...
1736
  			/* same file, POSIX says that this is a noop */
ae6884a9d   Jeff Layton   cifs: fix renamin...
1737
  			rc = 0;
14121bdcc   Jeff Layton   cifs: make cifs_r...
1738
  			goto cifs_rename_exit;
ae6884a9d   Jeff Layton   cifs: fix renamin...
1739
  		}
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1740
1741
1742
1743
1744
  	}
  	/*
  	 * 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...
1745

ee2fd967f   Steve French   [CIFS] fix busy-...
1746
  unlink_target:
fc6f39433   Jeff Layton   cifs: when renami...
1747
  	/* Try unlinking the target dentry if it's not negative */
2b0143b5c   David Howells   VFS: normal files...
1748
  	if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
a07d32205   Pavel Shilovsky   CIFS: Fix directo...
1749
1750
1751
1752
  		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...
1753
1754
  		if (tmprc)
  			goto cifs_rename_exit;
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1755
1756
  		rc = cifs_do_rename(xid, source_dentry, from_name,
  				    target_dentry, to_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1757
  	}
b46799a8f   Pavel Shilovsky   CIFS: Fix wrong d...
1758
1759
1760
1761
1762
  	/* 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 =
  		target_dir->i_mtime = current_fs_time(source_dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1763
  cifs_rename_exit:
ee2fd967f   Steve French   [CIFS] fix busy-...
1764
  	kfree(info_buf_source);
8ceb98437   Pavel Shilovsky   CIFS: Move rename...
1765
1766
  	kfree(from_name);
  	kfree(to_name);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1767
  	free_xid(xid);
7ffec3724   Jeff Layton   cifs: add refcoun...
1768
  	cifs_put_tlink(tlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1769
1770
  	return rc;
  }
df2cf170c   Jeff Layton   cifs: overhaul ci...
1771
1772
  static bool
  cifs_inode_needs_reval(struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1773
  {
df2cf170c   Jeff Layton   cifs: overhaul ci...
1774
  	struct cifsInodeInfo *cifs_i = CIFS_I(inode);
6d20e8406   Suresh Jayaraman   cifs: add attribu...
1775
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1776

18cceb6a7   Pavel Shilovsky   CIFS: Replace cli...
1777
  	if (CIFS_CACHE_READ(cifs_i))
df2cf170c   Jeff Layton   cifs: overhaul ci...
1778
  		return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1779

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

df2cf170c   Jeff Layton   cifs: overhaul ci...
1783
1784
  	if (cifs_i->time == 0)
  		return true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1785

a87c9ad95   Jeff Layton   cifs: fix actimeo...
1786
1787
  	if (!cifs_sb->actimeo)
  		return true;
6d20e8406   Suresh Jayaraman   cifs: add attribu...
1788
1789
  	if (!time_in_range(jiffies, cifs_i->time,
  				cifs_i->time + cifs_sb->actimeo))
df2cf170c   Jeff Layton   cifs: overhaul ci...
1790
  		return true;
db19272ed   Jeff Layton   cifs: always reva...
1791
  	/* hardlinked files w/ noserverino get "special" treatment */
6d20e8406   Suresh Jayaraman   cifs: add attribu...
1792
  	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
db19272ed   Jeff Layton   cifs: always reva...
1793
1794
  	    S_ISREG(inode->i_mode) && inode->i_nlink != 1)
  		return true;
df2cf170c   Jeff Layton   cifs: overhaul ci...
1795
1796
  	return false;
  }
523fb8c86   Suresh Jayaraman   cifs: trivial com...
1797
1798
1799
  /*
   * Zap the cache. Called when invalid_mapping flag is set.
   */
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1800
  int
df2cf170c   Jeff Layton   cifs: overhaul ci...
1801
1802
  cifs_invalidate_mapping(struct inode *inode)
  {
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1803
  	int rc = 0;
df2cf170c   Jeff Layton   cifs: overhaul ci...
1804

df2cf170c   Jeff Layton   cifs: overhaul ci...
1805
  	if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
257fb1f15   Pavel Shilovsky   CIFS: Use invalid...
1806
  		rc = invalidate_inode_pages2(inode->i_mapping);
4f73c7d34   Jeff Layton   cifs: fix potenti...
1807
  		if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1808
1809
1810
  			cifs_dbg(VFS, "%s: could not invalidate inode %p
  ",
  				 __func__, inode);
df2cf170c   Jeff Layton   cifs: overhaul ci...
1811
  	}
257fb1f15   Pavel Shilovsky   CIFS: Use invalid...
1812

9451a9a52   Suresh Jayaraman   cifs: define inod...
1813
  	cifs_fscache_reset_inode_cookie(inode);
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1814
  	return rc;
df2cf170c   Jeff Layton   cifs: overhaul ci...
1815
  }
4f73c7d34   Jeff Layton   cifs: fix potenti...
1816
1817
1818
1819
1820
  /**
   * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
   * @word: long word containing the bit lock
   */
  static int
dfd01f026   Peter Zijlstra   sched/wait: Fix t...
1821
  cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
4f73c7d34   Jeff Layton   cifs: fix potenti...
1822
  {
4f73c7d34   Jeff Layton   cifs: fix potenti...
1823
  	freezable_schedule_unsafe();
dfd01f026   Peter Zijlstra   sched/wait: Fix t...
1824
1825
  	if (signal_pending_state(mode, current))
  		return -ERESTARTSYS;
4f73c7d34   Jeff Layton   cifs: fix potenti...
1826
1827
  	return 0;
  }
e284e53fd   Jeff Layton   cifs: new helper ...
1828
1829
1830
  int
  cifs_revalidate_mapping(struct inode *inode)
  {
4f73c7d34   Jeff Layton   cifs: fix potenti...
1831
1832
  	int rc;
  	unsigned long *flags = &CIFS_I(inode)->flags;
743162013   NeilBrown   sched: Remove pro...
1833
1834
  	rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
  				     TASK_KILLABLE);
4f73c7d34   Jeff Layton   cifs: fix potenti...
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
  	if (rc)
  		return rc;
  
  	if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
  		rc = cifs_invalidate_mapping(inode);
  		if (rc)
  			set_bit(CIFS_INO_INVALID_MAPPING, flags);
  	}
  
  	clear_bit_unlock(CIFS_INO_LOCK, flags);
b1cce8032   Linus Torvalds   Merge branch 'for...
1845
  	smp_mb__after_atomic();
4f73c7d34   Jeff Layton   cifs: fix potenti...
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
  	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 ...
1856
  }
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1857
  int cifs_revalidate_file_attr(struct file *filp)
abab095d1   Jeff Layton   cifs: add cifs_re...
1858
1859
  {
  	int rc = 0;
496ad9aa8   Al Viro   new helper: file_...
1860
  	struct inode *inode = file_inode(filp);
ba00ba64c   Jeff Layton   cifs: make variou...
1861
  	struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
abab095d1   Jeff Layton   cifs: add cifs_re...
1862
1863
  
  	if (!cifs_inode_needs_reval(inode))
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1864
  		return rc;
abab095d1   Jeff Layton   cifs: add cifs_re...
1865

13cfb7334   Jeff Layton   cifs: have cifsFi...
1866
  	if (tlink_tcon(cfile->tlink)->unix_ext)
abab095d1   Jeff Layton   cifs: add cifs_re...
1867
1868
1869
  		rc = cifs_get_file_info_unix(filp);
  	else
  		rc = cifs_get_file_info(filp);
abab095d1   Jeff Layton   cifs: add cifs_re...
1870
1871
  	return rc;
  }
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1872
  int cifs_revalidate_dentry_attr(struct dentry *dentry)
df2cf170c   Jeff Layton   cifs: overhaul ci...
1873
  {
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1874
  	unsigned int xid;
df2cf170c   Jeff Layton   cifs: overhaul ci...
1875
  	int rc = 0;
2b0143b5c   David Howells   VFS: normal files...
1876
  	struct inode *inode = d_inode(dentry);
df2cf170c   Jeff Layton   cifs: overhaul ci...
1877
  	struct super_block *sb = dentry->d_sb;
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1878
  	char *full_path = NULL;
df2cf170c   Jeff Layton   cifs: overhaul ci...
1879
1880
1881
  
  	if (inode == NULL)
  		return -ENOENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1882

df2cf170c   Jeff Layton   cifs: overhaul ci...
1883
  	if (!cifs_inode_needs_reval(inode))
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1884
  		return rc;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1885
  	xid = get_xid();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1886
1887
1888
  
  	/* can not safely grab the rename sem here if rename calls revalidate
  	   since that would deadlock */
df2cf170c   Jeff Layton   cifs: overhaul ci...
1889
  	full_path = build_path_from_dentry(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1890
  	if (full_path == NULL) {
0f3bc09ee   Suresh Jayaraman   cifs: Fix incorre...
1891
  		rc = -ENOMEM;
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1892
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1893
  	}
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1894
1895
1896
  	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 -...
1897
  		 dentry, cifs_get_time(dentry), jiffies);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1898

0d424ad0a   Jeff Layton   cifs: add cifs_sb...
1899
  	if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
df2cf170c   Jeff Layton   cifs: overhaul ci...
1900
1901
1902
1903
  		rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
  	else
  		rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
  					 xid, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1904

6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1905
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1906
  	kfree(full_path);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
1907
  	free_xid(xid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1908
1909
  	return rc;
  }
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1910
1911
1912
  int cifs_revalidate_file(struct file *filp)
  {
  	int rc;
496ad9aa8   Al Viro   new helper: file_...
1913
  	struct inode *inode = file_inode(filp);
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1914
1915
1916
1917
  
  	rc = cifs_revalidate_file_attr(filp);
  	if (rc)
  		return rc;
e284e53fd   Jeff Layton   cifs: new helper ...
1918
  	return cifs_revalidate_mapping(inode);
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1919
1920
1921
1922
1923
1924
  }
  
  /* revalidate a dentry's inode attributes */
  int cifs_revalidate_dentry(struct dentry *dentry)
  {
  	int rc;
2b0143b5c   David Howells   VFS: normal files...
1925
  	struct inode *inode = d_inode(dentry);
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1926
1927
1928
1929
  
  	rc = cifs_revalidate_dentry_attr(dentry);
  	if (rc)
  		return rc;
e284e53fd   Jeff Layton   cifs: new helper ...
1930
  	return cifs_revalidate_mapping(inode);
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1931
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1932
  int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
1c456013e   Jeff Layton   cifs: on multiuse...
1933
  		 struct kstat *stat)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1934
  {
3aa1c8c29   Jeff Layton   cifs: on multiuse...
1935
  	struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
96daf2b09   Steve French   [CIFS] Rename thr...
1936
  	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
2b0143b5c   David Howells   VFS: normal files...
1937
  	struct inode *inode = d_inode(dentry);
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1938
  	int rc;
3aa1c8c29   Jeff Layton   cifs: on multiuse...
1939

6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1940
1941
1942
1943
  	/*
  	 * We need to be sure that all dirty pages are written and the server
  	 * has actual ctime, mtime and file length.
  	 */
18cceb6a7   Pavel Shilovsky   CIFS: Replace cli...
1944
  	if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1945
1946
  	    inode->i_mapping->nrpages != 0) {
  		rc = filemap_fdatawait(inode->i_mapping);
156ecb2d8   Steve French   [CIFS] Fix to pro...
1947
1948
1949
1950
  		if (rc) {
  			mapping_set_error(inode->i_mapping, rc);
  			return rc;
  		}
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1951
  	}
1c456013e   Jeff Layton   cifs: on multiuse...
1952

6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1953
1954
1955
1956
1957
1958
1959
1960
1961
  	rc = cifs_revalidate_dentry_attr(dentry);
  	if (rc)
  		return rc;
  
  	generic_fillattr(inode, stat);
  	stat->blksize = CIFS_MAX_MSGSIZE;
  	stat->ino = CIFS_I(inode)->uniqueid;
  
  	/*
d3d1fce11   Jeff Layton   cifs: don't overr...
1962
1963
1964
  	 * 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...
1965
1966
  	 */
  	if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
d3d1fce11   Jeff Layton   cifs: don't overr...
1967
  	    !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1968
1969
1970
1971
1972
  	    !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...
1973
  	}
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1974
  	return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1975
1976
1977
1978
  }
  
  static int cifs_truncate_page(struct address_space *mapping, loff_t from)
  {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1979
1980
  	pgoff_t index = from >> PAGE_SHIFT;
  	unsigned offset = from & (PAGE_SIZE - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1981
  	struct page *page;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1982
1983
1984
1985
1986
  	int rc = 0;
  
  	page = grab_cache_page(mapping, index);
  	if (!page)
  		return -ENOMEM;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1987
  	zero_user_segment(page, offset, PAGE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1988
  	unlock_page(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1989
  	put_page(page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1990
1991
  	return rc;
  }
1b9474635   Christoph Hellwig   cifs: truncate fa...
1992
  static void cifs_setsize(struct inode *inode, loff_t offset)
3677db10a   Steve French   [CIFS] Fix lockin...
1993
  {
ba6a46a03   Steve French   [CIFS] small piec...
1994
  	spin_lock(&inode->i_lock);
3677db10a   Steve French   [CIFS] Fix lockin...
1995
  	i_size_write(inode, offset);
ba6a46a03   Steve French   [CIFS] small piec...
1996
  	spin_unlock(&inode->i_lock);
1b9474635   Christoph Hellwig   cifs: truncate fa...
1997

7caef2676   Kirill A. Shutemov   truncate: drop 'o...
1998
  	truncate_pagecache(inode, offset);
3677db10a   Steve French   [CIFS] Fix lockin...
1999
  }
8efdbde64   Jeff Layton   [CIFS] break ATTR...
2000
2001
  static int
  cifs_set_file_size(struct inode *inode, struct iattr *attrs,
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2002
  		   unsigned int xid, char *full_path)
8efdbde64   Jeff Layton   [CIFS] break ATTR...
2003
2004
2005
2006
2007
  {
  	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...
2008
  	struct tcon_link *tlink = NULL;
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
2009
2010
  	struct cifs_tcon *tcon = NULL;
  	struct TCP_Server_Info *server;
8efdbde64   Jeff Layton   [CIFS] break ATTR...
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
  
  	/*
  	 * 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
  	 */
6508d904e   Jeff Layton   cifs: have find_r...
2021
  	open_file = find_writable_file(cifsInode, true);
8efdbde64   Jeff Layton   [CIFS] break ATTR...
2022
  	if (open_file) {
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
2023
2024
2025
2026
2027
2028
2029
  		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...
2030
  		cifsFileInfo_put(open_file);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2031
2032
  		cifs_dbg(FYI, "SetFSize for attrs rc = %d
  ", rc);
8efdbde64   Jeff Layton   [CIFS] break ATTR...
2033
2034
  	} else
  		rc = -EINVAL;
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
  	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...
2045

d14334181   Pavel Shilovsky   CIFS: Move set_fi...
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
  	/*
  	 * 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...
2056
2057
  	cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d
  ", rc);
d14334181   Pavel Shilovsky   CIFS: Move set_fi...
2058

d14334181   Pavel Shilovsky   CIFS: Move set_fi...
2059
2060
  	if (tlink)
  		cifs_put_tlink(tlink);
8efdbde64   Jeff Layton   [CIFS] break ATTR...
2061

d14334181   Pavel Shilovsky   CIFS: Move set_fi...
2062
  set_size_out:
8efdbde64   Jeff Layton   [CIFS] break ATTR...
2063
  	if (rc == 0) {
fbec9ab95   Jeff Layton   cifs: vary timeou...
2064
  		cifsInode->server_eof = attrs->ia_size;
1b9474635   Christoph Hellwig   cifs: truncate fa...
2065
  		cifs_setsize(inode, attrs->ia_size);
8efdbde64   Jeff Layton   [CIFS] break ATTR...
2066
2067
2068
2069
2070
  		cifs_truncate_page(inode->i_mapping, inode->i_size);
  	}
  
  	return rc;
  }
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2071
2072
2073
2074
  static int
  cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
  {
  	int rc;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2075
  	unsigned int xid;
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2076
  	char *full_path = NULL;
2b0143b5c   David Howells   VFS: normal files...
2077
  	struct inode *inode = d_inode(direntry);
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2078
2079
  	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
2080
  	struct tcon_link *tlink;
96daf2b09   Steve French   [CIFS] Rename thr...
2081
  	struct cifs_tcon *pTcon;
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2082
  	struct cifs_unix_set_info_args *args = NULL;
3bbeeb3c9   Jeff Layton   cifs: add and use...
2083
  	struct cifsFileInfo *open_file;
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2084

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

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

db78b877f   Christoph Hellwig   always call inode...
2091
2092
  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
  		attrs->ia_valid |= ATTR_FORCE;
31051c85b   Jan Kara   fs: Give dentry t...
2093
  	rc = setattr_prepare(direntry, attrs);
db78b877f   Christoph Hellwig   always call inode...
2094
2095
  	if (rc < 0)
  		goto out;
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2096
2097
2098
2099
2100
2101
  
  	full_path = build_path_from_dentry(direntry);
  	if (full_path == NULL) {
  		rc = -ENOMEM;
  		goto out;
  	}
0f4d634c5   Jeff Layton   cifs: flush data ...
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
  	/*
  	 * 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);
eb4b756b1   Jeff Layton   cifs: eliminate c...
2114
2115
  	mapping_set_error(inode->i_mapping, rc);
  	rc = 0;
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
  
  	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...
2142
  		args->uid = INVALID_UID; /* no change */
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2143
2144
2145
2146
  
  	if (attrs->ia_valid & ATTR_GID)
  		args->gid = attrs->ia_gid;
  	else
49418b2c2   Eric W. Biederman   cifs: Modify stru...
2147
  		args->gid = INVALID_GID; /* no change */
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
  
  	if (attrs->ia_valid & ATTR_ATIME)
  		args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
  	else
  		args->atime = NO_CHANGE_64;
  
  	if (attrs->ia_valid & ATTR_MTIME)
  		args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
  	else
  		args->mtime = NO_CHANGE_64;
  
  	if (attrs->ia_valid & ATTR_CTIME)
  		args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
  	else
  		args->ctime = NO_CHANGE_64;
  
  	args->device = 0;
6508d904e   Jeff Layton   cifs: have find_r...
2165
  	open_file = find_writable_file(cifsInode, true);
3bbeeb3c9   Jeff Layton   cifs: add and use...
2166
  	if (open_file) {
4b4de76e3   Pavel Shilovsky   CIFS: Replace net...
2167
  		u16 nfid = open_file->fid.netfid;
3bbeeb3c9   Jeff Layton   cifs: add and use...
2168
  		u32 npid = open_file->pid;
13cfb7334   Jeff Layton   cifs: have cifsFi...
2169
  		pTcon = tlink_tcon(open_file->tlink);
3bbeeb3c9   Jeff Layton   cifs: add and use...
2170
  		rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
6ab409b53   Dave Kleikamp   cifs: Replace wrt...
2171
  		cifsFileInfo_put(open_file);
3bbeeb3c9   Jeff Layton   cifs: add and use...
2172
  	} else {
7ffec3724   Jeff Layton   cifs: add refcoun...
2173
2174
2175
2176
2177
2178
  		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...
2179
  		rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
01ea95e3b   Jeff Layton   cifs: rename CIFS...
2180
  				    cifs_sb->local_nls,
bc8ebdc4f   Nakajima Akira   Fix that several ...
2181
  				    cifs_remap(cifs_sb));
7ffec3724   Jeff Layton   cifs: add refcoun...
2182
  		cifs_put_tlink(tlink);
3bbeeb3c9   Jeff Layton   cifs: add and use...
2183
  	}
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2184

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

1025774ce   Christoph Hellwig   remove inode_setattr
2188
  	if ((attrs->ia_valid & ATTR_SIZE) &&
1b9474635   Christoph Hellwig   cifs: truncate fa...
2189
2190
  	    attrs->ia_size != i_size_read(inode))
  		truncate_setsize(inode, attrs->ia_size);
1025774ce   Christoph Hellwig   remove inode_setattr
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
  
  	setattr_copy(inode, attrs);
  	mark_inode_dirty(inode);
  
  	/* force revalidate when any of these times are set since some
  	   of the fs types (eg ext3, fat) do not have fine enough
  	   time granularity to match protocol, and we do not have a
  	   a way (yet) to query the server fs's time granularity (and
  	   whether it rounds times down).
  	*/
  	if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
  		cifsInode->time = 0;
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2203
2204
2205
  out:
  	kfree(args);
  	kfree(full_path);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2206
  	free_xid(xid);
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2207
2208
  	return rc;
  }
0510eeb73   Jeff Layton   turn cifs_setattr...
2209
2210
  static int
  cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2211
  {
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2212
  	unsigned int xid;
8abf2775d   Eric W. Biederman   cifs: Use kuids a...
2213
2214
  	kuid_t uid = INVALID_UID;
  	kgid_t gid = INVALID_GID;
2b0143b5c   David Howells   VFS: normal files...
2215
  	struct inode *inode = d_inode(direntry);
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2216
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2217
  	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2218
2219
  	char *full_path = NULL;
  	int rc = -EACCES;
feb3e20ce   Jeff Layton   move file time an...
2220
  	__u32 dosattr = 0;
4e1e7fb9e   Jeff Layton   bundle up Unix SE...
2221
  	__u64 mode = NO_CHANGE_64;
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2222

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

35c265e00   Al Viro   cifs: switch to u...
2225
2226
2227
  	cifs_dbg(FYI, "setattr on file %pd attrs->iavalid 0x%x
  ",
  		 direntry, attrs->ia_valid);
6473a559c   Steve French   [CIFS] Fix missin...
2228

db78b877f   Christoph Hellwig   always call inode...
2229
2230
  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
  		attrs->ia_valid |= ATTR_FORCE;
31051c85b   Jan Kara   fs: Give dentry t...
2231
  	rc = setattr_prepare(direntry, attrs);
db78b877f   Christoph Hellwig   always call inode...
2232
  	if (rc < 0) {
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2233
  		free_xid(xid);
db78b877f   Christoph Hellwig   always call inode...
2234
  		return rc;
6473a559c   Steve French   [CIFS] Fix missin...
2235
  	}
50c2f7538   Steve French   [CIFS] whitespace...
2236

7f57356b7   Steve French   [CIFS] Remove cif...
2237
  	full_path = build_path_from_dentry(direntry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2238
  	if (full_path == NULL) {
0f3bc09ee   Suresh Jayaraman   cifs: Fix incorre...
2239
  		rc = -ENOMEM;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2240
  		free_xid(xid);
0f3bc09ee   Suresh Jayaraman   cifs: Fix incorre...
2241
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2242
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2243

0f4d634c5   Jeff Layton   cifs: flush data ...
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
  	/*
  	 * 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);
eb4b756b1   Jeff Layton   cifs: eliminate c...
2256
2257
  	mapping_set_error(inode->i_mapping, rc);
  	rc = 0;
cea218054   Jeff Layton   [CIFS] Fix potent...
2258

50531444f   Steve French   [CIFS] Fix mtime ...
2259
  	if (attrs->ia_valid & ATTR_SIZE) {
8efdbde64   Jeff Layton   [CIFS] break ATTR...
2260
2261
  		rc = cifs_set_file_size(inode, attrs, xid, full_path);
  		if (rc != 0)
e30dcf3a1   Steve French   [CIFS] Add suppor...
2262
  			goto cifs_setattr_exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2263
  	}
4ca691a89   Jeff Layton   silently ignore o...
2264

a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
2265
2266
2267
2268
2269
2270
2271
2272
  	if (attrs->ia_valid & ATTR_UID)
  		uid = attrs->ia_uid;
  
  	if (attrs->ia_valid & ATTR_GID)
  		gid = attrs->ia_gid;
  
  #ifdef CONFIG_CIFS_ACL
  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
8abf2775d   Eric W. Biederman   cifs: Use kuids a...
2273
  		if (uid_valid(uid) || gid_valid(gid)) {
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
2274
2275
2276
  			rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
  							uid, gid);
  			if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2277
2278
2279
  				cifs_dbg(FYI, "%s: Setting id failed with error: %d
  ",
  					 __func__, rc);
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
2280
2281
2282
2283
2284
  				goto cifs_setattr_exit;
  			}
  		}
  	} else
  #endif /* CONFIG_CIFS_ACL */
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2285
  	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
4ca691a89   Jeff Layton   silently ignore o...
2286
  		attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2287

d32c4f262   Jeff Layton   CIFS: ignore mode...
2288
2289
2290
  	/* 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
2291
  	if (attrs->ia_valid & ATTR_MODE) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2292
  		mode = attrs->ia_mode;
cdbce9c87   Steve French   [CIFS] Fix setatt...
2293
  		rc = 0;
79df1baee   Jeff Layton   cifs: fix use of ...
2294
  #ifdef CONFIG_CIFS_ACL
78415d2d3   Shirish Pargaonkar   cifs: Misc. clean...
2295
  		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
2296
  			rc = id_mode_to_cifs_acl(inode, full_path, mode,
8abf2775d   Eric W. Biederman   cifs: Use kuids a...
2297
  						INVALID_UID, INVALID_GID);
78415d2d3   Shirish Pargaonkar   cifs: Misc. clean...
2298
  			if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2299
2300
2301
  				cifs_dbg(FYI, "%s: Setting ACL failed with error: %d
  ",
  					 __func__, rc);
78415d2d3   Shirish Pargaonkar   cifs: Misc. clean...
2302
2303
2304
  				goto cifs_setattr_exit;
  			}
  		} else
79df1baee   Jeff Layton   cifs: fix use of ...
2305
  #endif /* CONFIG_CIFS_ACL */
5132861a7   Jeff Layton   disable most mode...
2306
2307
  		if (((mode & S_IWUGO) == 0) &&
  		    (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
feb3e20ce   Jeff Layton   move file time an...
2308
2309
  
  			dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
5132861a7   Jeff Layton   disable most mode...
2310
2311
2312
2313
2314
  			/* 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...
2315
2316
2317
2318
2319
  
  			dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
  			/* Attributes of 0 are ignored */
  			if (dosattr == 0)
  				dosattr |= ATTR_NORMAL;
5132861a7   Jeff Layton   disable most mode...
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
  
  			/* reset local inode permissions to normal */
  			if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
  				attrs->ia_mode &= ~(S_IALLUGO);
  				if (S_ISDIR(inode->i_mode))
  					attrs->ia_mode |=
  						cifs_sb->mnt_dir_mode;
  				else
  					attrs->ia_mode |=
  						cifs_sb->mnt_file_mode;
  			}
  		} else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
  			/* ignore mode change - ATTR_READONLY hasn't changed */
  			attrs->ia_valid &= ~ATTR_MODE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2334
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2335
  	}
feb3e20ce   Jeff Layton   move file time an...
2336
2337
2338
2339
  	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
2340

e30dcf3a1   Steve French   [CIFS] Add suppor...
2341
2342
2343
2344
2345
  		/* 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...
2346
  		if ((rc) && (attrs->ia_valid &
feb3e20ce   Jeff Layton   move file time an...
2347
  				(ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
e30dcf3a1   Steve French   [CIFS] Add suppor...
2348
  			rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2349
2350
2351
2352
  	}
  
  	/* do not need local check to inode_check_ok since the server does
  	   that */
1025774ce   Christoph Hellwig   remove inode_setattr
2353
2354
2355
2356
  	if (rc)
  		goto cifs_setattr_exit;
  
  	if ((attrs->ia_valid & ATTR_SIZE) &&
1b9474635   Christoph Hellwig   cifs: truncate fa...
2357
2358
  	    attrs->ia_size != i_size_read(inode))
  		truncate_setsize(inode, attrs->ia_size);
1025774ce   Christoph Hellwig   remove inode_setattr
2359
2360
2361
  
  	setattr_copy(inode, attrs);
  	mark_inode_dirty(inode);
1025774ce   Christoph Hellwig   remove inode_setattr
2362

e30dcf3a1   Steve French   [CIFS] Add suppor...
2363
  cifs_setattr_exit:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2364
  	kfree(full_path);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2365
  	free_xid(xid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2366
2367
  	return rc;
  }
0510eeb73   Jeff Layton   turn cifs_setattr...
2368
2369
2370
  int
  cifs_setattr(struct dentry *direntry, struct iattr *attrs)
  {
fc64005c9   Al Viro   don't bother with...
2371
  	struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
96daf2b09   Steve French   [CIFS] Rename thr...
2372
  	struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
0510eeb73   Jeff Layton   turn cifs_setattr...
2373
2374
2375
2376
2377
2378
2379
2380
  
  	if (pTcon->unix_ext)
  		return cifs_setattr_unix(direntry, attrs);
  
  	return cifs_setattr_nounix(direntry, attrs);
  
  	/* BB: add cifs_setattr_legacy for really old servers */
  }
99ee4dbd7   Steve French   [CIFS] Remove som...
2381
  #if 0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2382
2383
  void cifs_delete_inode(struct inode *inode)
  {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2384
2385
  	cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p
  ", inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2386
2387
2388
  	/* may have to add back in if and when safe distributed caching of
  	   directories added e.g. via FindNotify */
  }
99ee4dbd7   Steve French   [CIFS] Remove som...
2389
  #endif