Blame view

fs/cifs/inode.c 59.4 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
25
26
27
28
29
30
31
  #include <linux/pagemap.h>
  #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"
9451a9a52   Suresh Jayaraman   cifs: define inod...
32
  #include "fscache.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33

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

01c64feac   David Howells   CIFS: Use d_autom...
35
  static void cifs_set_ops(struct inode *inode)
70eff55d2   Christoph Hellwig   [CIFS] factoring ...
36
37
38
39
40
41
42
43
44
45
46
  {
  	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...
47
48
49
50
51
  		} 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 ...
52
53
54
55
56
  		} 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 ...
57
  		/* check if server can support readpages */
0d424ad0a   Jeff Layton   cifs: add cifs_sb...
58
  		if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf <
70eff55d2   Christoph Hellwig   [CIFS] factoring ...
59
60
61
62
63
64
  				PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
  			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 ...
65
  #ifdef CONFIG_CIFS_DFS_UPCALL
01c64feac   David Howells   CIFS: Use d_autom...
66
  		if (IS_AUTOMOUNT(inode)) {
7962670e6   Igor Mammedov   [CIFS] DFS patch...
67
68
  			inode->i_op = &cifs_dfs_referral_inode_operations;
  		} else {
bc5b6e24a   Steve French   [CIFS] Fix build ...
69
70
71
  #else /* NO DFS support, treat as a directory */
  		{
  #endif
7962670e6   Igor Mammedov   [CIFS] DFS patch...
72
73
74
  			inode->i_op = &cifs_dir_inode_ops;
  			inode->i_fop = &cifs_dir_ops;
  		}
70eff55d2   Christoph Hellwig   [CIFS] factoring ...
75
76
77
78
79
80
81
82
83
  		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...
84
85
86
87
88
89
90
  /* 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);
f19159dc5   Steve French   [CIFS] Cleanup va...
91
  	cFYI(1, "%s: revalidating inode %llu", __func__, cifs_i->uniqueid);
df2cf170c   Jeff Layton   cifs: overhaul ci...
92
93
  
  	if (inode->i_state & I_NEW) {
f19159dc5   Steve French   [CIFS] Cleanup va...
94
  		cFYI(1, "%s: inode %llu is new", __func__, cifs_i->uniqueid);
df2cf170c   Jeff Layton   cifs: overhaul ci...
95
96
97
98
99
  		return;
  	}
  
  	/* don't bother with revalidation if we have an oplock */
  	if (cifs_i->clientCanCacheRead) {
f19159dc5   Steve French   [CIFS] Cleanup va...
100
101
  		cFYI(1, "%s: inode %llu is oplocked", __func__,
  			 cifs_i->uniqueid);
df2cf170c   Jeff Layton   cifs: overhaul ci...
102
103
104
105
106
107
  		return;
  	}
  
  	 /* revalidate if mtime or size have changed */
  	if (timespec_equal(&inode->i_mtime, &fattr->cf_mtime) &&
  	    cifs_i->server_eof == fattr->cf_eof) {
f19159dc5   Steve French   [CIFS] Cleanup va...
108
109
  		cFYI(1, "%s: inode %llu is unchanged", __func__,
  			 cifs_i->uniqueid);
df2cf170c   Jeff Layton   cifs: overhaul ci...
110
111
  		return;
  	}
f19159dc5   Steve French   [CIFS] Cleanup va...
112
113
  	cFYI(1, "%s: invalidating inode %llu mapping", __func__,
  		 cifs_i->uniqueid);
df2cf170c   Jeff Layton   cifs: overhaul ci...
114
115
  	cifs_i->invalid_mapping = true;
  }
cc0bad755   Jeff Layton   cifs: add new cif...
116
117
118
  /* 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...
119
  {
cc0bad755   Jeff Layton   cifs: add new cif...
120
  	struct cifsInodeInfo *cifs_i = CIFS_I(inode);
0b8f18e35   Jeff Layton   cifs: convert cif...
121
122
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
  	unsigned long oldtime = cifs_i->time;
cc0bad755   Jeff Layton   cifs: add new cif...
123

df2cf170c   Jeff Layton   cifs: overhaul ci...
124
  	cifs_revalidate_cache(inode, fattr);
cc0bad755   Jeff Layton   cifs: add new cif...
125
126
127
  	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...
128
  	inode->i_rdev = fattr->cf_rdev;
bfe868486   Miklos Szeredi   filesystems: add ...
129
  	set_nlink(inode, fattr->cf_nlink);
cc0bad755   Jeff Layton   cifs: add new cif...
130
131
  	inode->i_uid = fattr->cf_uid;
  	inode->i_gid = fattr->cf_gid;
0b8f18e35   Jeff Layton   cifs: convert cif...
132
133
134
135
  	/* 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...
136
  	cifs_i->cifsAttrs = fattr->cf_cifsattrs;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
137

0b8f18e35   Jeff Layton   cifs: convert cif...
138
139
140
141
  	if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
  		cifs_i->time = 0;
  	else
  		cifs_i->time = jiffies;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
142
143
  	cFYI(1, "inode 0x%p old_time=%ld new_time=%ld", inode,
  		 oldtime, cifs_i->time);
0b8f18e35   Jeff Layton   cifs: convert cif...
144
145
  
  	cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING;
cc0bad755   Jeff Layton   cifs: add new cif...
146

835a36ca4   Jeff Layton   cifs: set server_...
147
  	cifs_i->server_eof = fattr->cf_eof;
cc0bad755   Jeff Layton   cifs: add new cif...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
  	/*
  	 * Can't safely change the file size here if the client is writing to
  	 * it due to potential races.
  	 */
  	spin_lock(&inode->i_lock);
  	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...
164
165
166
  	if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL)
  		inode->i_flags |= S_AUTOMOUNT;
  	cifs_set_ops(inode);
cc0bad755   Jeff Layton   cifs: add new cif...
167
  }
4065c802d   Jeff Layton   cifs: fix noserve...
168
169
170
171
172
173
174
175
176
177
  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...
178
179
180
181
182
183
184
185
186
187
188
189
190
191
  /* 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...
192
193
194
195
196
  
  	/*
  	 * 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...
197
  	fattr->cf_mode &= ~S_IFMT;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
198
199
  	switch (le32_to_cpu(info->Type)) {
  	case UNIX_FILE:
cc0bad755   Jeff Layton   cifs: add new cif...
200
201
  		fattr->cf_mode |= S_IFREG;
  		fattr->cf_dtype = DT_REG;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
202
203
  		break;
  	case UNIX_SYMLINK:
cc0bad755   Jeff Layton   cifs: add new cif...
204
205
  		fattr->cf_mode |= S_IFLNK;
  		fattr->cf_dtype = DT_LNK;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
206
207
  		break;
  	case UNIX_DIR:
cc0bad755   Jeff Layton   cifs: add new cif...
208
209
  		fattr->cf_mode |= S_IFDIR;
  		fattr->cf_dtype = DT_DIR;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
210
211
  		break;
  	case UNIX_CHARDEV:
cc0bad755   Jeff Layton   cifs: add new cif...
212
213
214
215
  		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...
216
217
  		break;
  	case UNIX_BLOCKDEV:
cc0bad755   Jeff Layton   cifs: add new cif...
218
219
220
221
  		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...
222
223
  		break;
  	case UNIX_FIFO:
cc0bad755   Jeff Layton   cifs: add new cif...
224
225
  		fattr->cf_mode |= S_IFIFO;
  		fattr->cf_dtype = DT_FIFO;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
226
227
  		break;
  	case UNIX_SOCKET:
cc0bad755   Jeff Layton   cifs: add new cif...
228
229
  		fattr->cf_mode |= S_IFSOCK;
  		fattr->cf_dtype = DT_SOCK;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
230
231
232
  		break;
  	default:
  		/* safest to call it a file if we do not know */
cc0bad755   Jeff Layton   cifs: add new cif...
233
234
  		fattr->cf_mode |= S_IFREG;
  		fattr->cf_dtype = DT_REG;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
235
  		cFYI(1, "unknown type %d", le32_to_cpu(info->Type));
75f12983d   Christoph Hellwig   [CIFS] consolidat...
236
237
  		break;
  	}
cc0bad755   Jeff Layton   cifs: add new cif...
238
239
  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
  		fattr->cf_uid = cifs_sb->mnt_uid;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
240
  	else
cc0bad755   Jeff Layton   cifs: add new cif...
241
  		fattr->cf_uid = le64_to_cpu(info->Uid);
75f12983d   Christoph Hellwig   [CIFS] consolidat...
242

cc0bad755   Jeff Layton   cifs: add new cif...
243
244
  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
  		fattr->cf_gid = cifs_sb->mnt_gid;
75f12983d   Christoph Hellwig   [CIFS] consolidat...
245
  	else
cc0bad755   Jeff Layton   cifs: add new cif...
246
  		fattr->cf_gid = le64_to_cpu(info->Gid);
75f12983d   Christoph Hellwig   [CIFS] consolidat...
247

cc0bad755   Jeff Layton   cifs: add new cif...
248
  	fattr->cf_nlink = le64_to_cpu(info->Nlinks);
75f12983d   Christoph Hellwig   [CIFS] consolidat...
249
  }
b9a3260f2   Steve French   [CIFS] Enable DFS...
250
  /*
cc0bad755   Jeff Layton   cifs: add new cif...
251
252
253
254
255
   * 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...
256
   */
f1230c979   Steve French   [CIFS] fix sparse...
257
  static void
cc0bad755   Jeff Layton   cifs: add new cif...
258
  cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
0e4bbde94   Steve French   [CIFS] Enable DFS...
259
  {
cc0bad755   Jeff Layton   cifs: add new cif...
260
  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
0e4bbde94   Steve French   [CIFS] Enable DFS...
261

b6b38f704   Joe Perches   [CIFS] Neaten cER...
262
  	cFYI(1, "creating fake fattr for DFS referral");
cc0bad755   Jeff Layton   cifs: add new cif...
263
264
265
266
267
268
269
270
271
272
  
  	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...
273
  }
abab095d1   Jeff Layton   cifs: add cifs_re...
274
275
276
277
278
279
280
281
  int cifs_get_file_info_unix(struct file *filp)
  {
  	int rc;
  	int xid;
  	FILE_UNIX_BASIC_INFO find_data;
  	struct cifs_fattr fattr;
  	struct inode *inode = filp->f_path.dentry->d_inode;
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
c21dfb699   Joe Perches   fs/cifs: Remove u...
282
  	struct cifsFileInfo *cfile = filp->private_data;
96daf2b09   Steve French   [CIFS] Rename thr...
283
  	struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
abab095d1   Jeff Layton   cifs: add cifs_re...
284
285
286
287
288
289
290
291
292
293
294
295
296
297
  
  	xid = GetXid();
  	rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data);
  	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);
  	FreeXid(xid);
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
298
  int cifs_get_inode_info_unix(struct inode **pinode,
cc0bad755   Jeff Layton   cifs: add new cif...
299
300
  			     const unsigned char *full_path,
  			     struct super_block *sb, int xid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
  {
cc0bad755   Jeff Layton   cifs: add new cif...
302
  	int rc;
0e4bbde94   Steve French   [CIFS] Enable DFS...
303
  	FILE_UNIX_BASIC_INFO find_data;
cc0bad755   Jeff Layton   cifs: add new cif...
304
  	struct cifs_fattr fattr;
96daf2b09   Steve French   [CIFS] Rename thr...
305
  	struct cifs_tcon *tcon;
7ffec3724   Jeff Layton   cifs: add refcoun...
306
  	struct tcon_link *tlink;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308

b6b38f704   Joe Perches   [CIFS] Neaten cER...
309
  	cFYI(1, "Getting info on %s", full_path);
7962670e6   Igor Mammedov   [CIFS] DFS patch...
310

7ffec3724   Jeff Layton   cifs: add refcoun...
311
312
313
314
  	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
315
  	/* could have done a find first instead but this returns more info */
cc0bad755   Jeff Layton   cifs: add new cif...
316
  	rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
737b758c9   Steve French   [PATCH] cifs: cha...
317
318
  				  cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
  					CIFS_MOUNT_MAP_SPECIAL_CHR);
7ffec3724   Jeff Layton   cifs: add refcoun...
319
  	cifs_put_tlink(tlink);
e911d0cc8   Jeff Layton   cifs: fix inode l...
320

cc0bad755   Jeff Layton   cifs: add new cif...
321
322
323
324
325
326
327
328
  	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
329

1b12b9c15   Stefan Metzmacher   cifs: use Minshal...
330
331
332
333
334
335
  	/* check for Minshall+French symlinks */
  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
  		int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
  		if (tmprc)
  			cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
  	}
0e4bbde94   Steve French   [CIFS] Enable DFS...
336
  	if (*pinode == NULL) {
cc0bad755   Jeff Layton   cifs: add new cif...
337
  		/* get new inode */
4065c802d   Jeff Layton   cifs: fix noserve...
338
  		cifs_fill_uniqueid(sb, &fattr);
cc0bad755   Jeff Layton   cifs: add new cif...
339
340
  		*pinode = cifs_iget(sb, &fattr);
  		if (!*pinode)
0e4bbde94   Steve French   [CIFS] Enable DFS...
341
  			rc = -ENOMEM;
cc0bad755   Jeff Layton   cifs: add new cif...
342
343
344
  	} else {
  		/* we already have inode, update it */
  		cifs_fattr_to_inode(*pinode, &fattr);
0e4bbde94   Steve French   [CIFS] Enable DFS...
345
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
348
  	return rc;
  }
0b8f18e35   Jeff Layton   cifs: convert cif...
349
350
351
  static int
  cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
  	      struct cifs_sb_info *cifs_sb, int xid)
d6e2f2a4c   Steve French   [CIFS] Recognize ...
352
353
  {
  	int rc;
4b18f2a9c   Steve French   [CIFS] convert us...
354
  	int oplock = 0;
d6e2f2a4c   Steve French   [CIFS] Recognize ...
355
  	__u16 netfid;
7ffec3724   Jeff Layton   cifs: add refcoun...
356
  	struct tcon_link *tlink;
96daf2b09   Steve French   [CIFS] Rename thr...
357
  	struct cifs_tcon *tcon;
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
358
  	struct cifs_io_parms io_parms;
86c96b4bb   Steve French   [CIFS] Fix mknod ...
359
  	char buf[24];
d6e2f2a4c   Steve French   [CIFS] Recognize ...
360
  	unsigned int bytes_read;
fb8c4b14d   Steve French   [CIFS] whitespace...
361
  	char *pbuf;
d6e2f2a4c   Steve French   [CIFS] Recognize ...
362
363
  
  	pbuf = buf;
0b8f18e35   Jeff Layton   cifs: convert cif...
364
365
366
367
368
  	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 ...
369
  		return 0;
0b8f18e35   Jeff Layton   cifs: convert cif...
370
371
372
  	} else if (fattr->cf_eof < 8) {
  		fattr->cf_mode |= S_IFREG;
  		fattr->cf_dtype = DT_REG;
d6e2f2a4c   Steve French   [CIFS] Recognize ...
373
374
  		return -EINVAL;	 /* EOPNOTSUPP? */
  	}
50c2f7538   Steve French   [CIFS] whitespace...
375

7ffec3724   Jeff Layton   cifs: add refcoun...
376
377
378
379
380
381
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
  	tcon = tlink_tcon(tlink);
  
  	rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ,
d6e2f2a4c   Steve French   [CIFS] Recognize ...
382
383
384
385
  			 CREATE_NOT_DIR, &netfid, &oplock, NULL,
  			 cifs_sb->local_nls,
  			 cifs_sb->mnt_cifs_flags &
  				CIFS_MOUNT_MAP_SPECIAL_CHR);
fb8c4b14d   Steve French   [CIFS] whitespace...
386
  	if (rc == 0) {
ec637e3ff   Steve French   [CIFS] Avoid extr...
387
  		int buf_type = CIFS_NO_BUFFER;
d6e2f2a4c   Steve French   [CIFS] Recognize ...
388
  			/* Read header */
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
389
390
391
392
393
394
395
  		io_parms.netfid = netfid;
  		io_parms.pid = current->tgid;
  		io_parms.tcon = tcon;
  		io_parms.offset = 0;
  		io_parms.length = 24;
  		rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf,
  				 &buf_type);
4523cc304   Steve French   [CIFS] UID/GID ov...
396
397
  		if ((rc == 0) && (bytes_read >= 8)) {
  			if (memcmp("IntxBLK", pbuf, 8) == 0) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
398
  				cFYI(1, "Block device");
0b8f18e35   Jeff Layton   cifs: convert cif...
399
400
  				fattr->cf_mode |= S_IFBLK;
  				fattr->cf_dtype = DT_BLK;
4523cc304   Steve French   [CIFS] UID/GID ov...
401
  				if (bytes_read == 24) {
86c96b4bb   Steve French   [CIFS] Fix mknod ...
402
403
404
405
406
  					/* 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));
0b8f18e35   Jeff Layton   cifs: convert cif...
407
  					fattr->cf_rdev = MKDEV(mjr, mnr);
86c96b4bb   Steve French   [CIFS] Fix mknod ...
408
  				}
4523cc304   Steve French   [CIFS] UID/GID ov...
409
  			} else if (memcmp("IntxCHR", pbuf, 8) == 0) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
410
  				cFYI(1, "Char device");
0b8f18e35   Jeff Layton   cifs: convert cif...
411
412
  				fattr->cf_mode |= S_IFCHR;
  				fattr->cf_dtype = DT_CHR;
4523cc304   Steve French   [CIFS] UID/GID ov...
413
  				if (bytes_read == 24) {
86c96b4bb   Steve French   [CIFS] Fix mknod ...
414
415
416
417
418
  					/* 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));
0b8f18e35   Jeff Layton   cifs: convert cif...
419
  					fattr->cf_rdev = MKDEV(mjr, mnr);
fb8c4b14d   Steve French   [CIFS] whitespace...
420
  				}
4523cc304   Steve French   [CIFS] UID/GID ov...
421
  			} else if (memcmp("IntxLNK", pbuf, 7) == 0) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
422
  				cFYI(1, "Symlink");
0b8f18e35   Jeff Layton   cifs: convert cif...
423
424
  				fattr->cf_mode |= S_IFLNK;
  				fattr->cf_dtype = DT_LNK;
86c96b4bb   Steve French   [CIFS] Fix mknod ...
425
  			} else {
0b8f18e35   Jeff Layton   cifs: convert cif...
426
427
  				fattr->cf_mode |= S_IFREG; /* file? */
  				fattr->cf_dtype = DT_REG;
fb8c4b14d   Steve French   [CIFS] whitespace...
428
  				rc = -EOPNOTSUPP;
86c96b4bb   Steve French   [CIFS] Fix mknod ...
429
  			}
3020a1f58   Steve French   [CIFS] Fix schedu...
430
  		} else {
0b8f18e35   Jeff Layton   cifs: convert cif...
431
432
  			fattr->cf_mode |= S_IFREG; /* then it is a file */
  			fattr->cf_dtype = DT_REG;
fb8c4b14d   Steve French   [CIFS] whitespace...
433
434
  			rc = -EOPNOTSUPP; /* or some unknown SFU type */
  		}
7ffec3724   Jeff Layton   cifs: add refcoun...
435
  		CIFSSMBClose(xid, tcon, netfid);
d6e2f2a4c   Steve French   [CIFS] Recognize ...
436
  	}
7ffec3724   Jeff Layton   cifs: add refcoun...
437
  	cifs_put_tlink(tlink);
d6e2f2a4c   Steve French   [CIFS] Recognize ...
438
  	return rc;
d6e2f2a4c   Steve French   [CIFS] Recognize ...
439
  }
9e294f1c4   Steve French   [CIFS] Recognize ...
440
  #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID)  /* SETFILEBITS valid bits */
0b8f18e35   Jeff Layton   cifs: convert cif...
441
442
443
444
445
446
447
  /*
   * 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,
  			 struct cifs_sb_info *cifs_sb, int xid)
9e294f1c4   Steve French   [CIFS] Recognize ...
448
  {
3020a1f58   Steve French   [CIFS] Fix schedu...
449
  #ifdef CONFIG_CIFS_XATTR
9e294f1c4   Steve French   [CIFS] Recognize ...
450
451
452
  	ssize_t rc;
  	char ea_value[4];
  	__u32 mode;
7ffec3724   Jeff Layton   cifs: add refcoun...
453
  	struct tcon_link *tlink;
96daf2b09   Steve French   [CIFS] Rename thr...
454
  	struct cifs_tcon *tcon;
7ffec3724   Jeff Layton   cifs: add refcoun...
455
456
457
458
459
  
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
  	tcon = tlink_tcon(tlink);
9e294f1c4   Steve French   [CIFS] Recognize ...
460

7ffec3724   Jeff Layton   cifs: add refcoun...
461
  	rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS",
0b8f18e35   Jeff Layton   cifs: convert cif...
462
463
464
  			    ea_value, 4 /* size of buf */, cifs_sb->local_nls,
  			    cifs_sb->mnt_cifs_flags &
  				CIFS_MOUNT_MAP_SPECIAL_CHR);
7ffec3724   Jeff Layton   cifs: add refcoun...
465
  	cifs_put_tlink(tlink);
4523cc304   Steve French   [CIFS] UID/GID ov...
466
  	if (rc < 0)
9e294f1c4   Steve French   [CIFS] Recognize ...
467
468
469
  		return (int)rc;
  	else if (rc > 3) {
  		mode = le32_to_cpu(*((__le32 *)ea_value));
0b8f18e35   Jeff Layton   cifs: convert cif...
470
  		fattr->cf_mode &= ~SFBITS_MASK;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
471
472
  		cFYI(1, "special bits 0%o org mode 0%o", mode,
  			 fattr->cf_mode);
0b8f18e35   Jeff Layton   cifs: convert cif...
473
  		fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
474
  		cFYI(1, "special mode bits 0%o", mode);
9e294f1c4   Steve French   [CIFS] Recognize ...
475
  	}
0b8f18e35   Jeff Layton   cifs: convert cif...
476
477
  
  	return 0;
3020a1f58   Steve French   [CIFS] Fix schedu...
478
479
480
  #else
  	return -EOPNOTSUPP;
  #endif
9e294f1c4   Steve French   [CIFS] Recognize ...
481
  }
0b8f18e35   Jeff Layton   cifs: convert cif...
482
  /* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
f1230c979   Steve French   [CIFS] fix sparse...
483
  static void
0b8f18e35   Jeff Layton   cifs: convert cif...
484
485
  cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
  		       struct cifs_sb_info *cifs_sb, bool adjust_tz)
b9a3260f2   Steve French   [CIFS] Enable DFS...
486
  {
96daf2b09   Steve French   [CIFS] Rename thr...
487
  	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
0d424ad0a   Jeff Layton   cifs: add cifs_sb...
488

0b8f18e35   Jeff Layton   cifs: convert cif...
489
490
491
492
493
494
495
496
497
498
499
500
501
502
  	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...
503
504
  		fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
  		fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
0b8f18e35   Jeff Layton   cifs: convert cif...
505
506
507
508
  	}
  
  	fattr->cf_eof = le64_to_cpu(info->EndOfFile);
  	fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
20054bd65   Jeff Layton   cifs: use Creatio...
509
  	fattr->cf_createtime = le64_to_cpu(info->CreationTime);
0b8f18e35   Jeff Layton   cifs: convert cif...
510
511
512
513
514
515
516
  
  	if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
  		fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
  		fattr->cf_dtype = DT_DIR;
  	} else {
  		fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
  		fattr->cf_dtype = DT_REG;
0b8f18e35   Jeff Layton   cifs: convert cif...
517

d0c280d26   Jeff Layton   cifs: when ATTR_R...
518
519
520
521
  		/* 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...
522
523
524
525
526
  
  	fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
  
  	fattr->cf_uid = cifs_sb->mnt_uid;
  	fattr->cf_gid = cifs_sb->mnt_gid;
b9a3260f2   Steve French   [CIFS] Enable DFS...
527
  }
abab095d1   Jeff Layton   cifs: add cifs_re...
528
529
530
531
532
533
534
535
  int cifs_get_file_info(struct file *filp)
  {
  	int rc;
  	int xid;
  	FILE_ALL_INFO find_data;
  	struct cifs_fattr fattr;
  	struct inode *inode = filp->f_path.dentry->d_inode;
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
c21dfb699   Joe Perches   fs/cifs: Remove u...
536
  	struct cifsFileInfo *cfile = filp->private_data;
96daf2b09   Steve French   [CIFS] Rename thr...
537
  	struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
abab095d1   Jeff Layton   cifs: add cifs_re...
538
539
540
  
  	xid = GetXid();
  	rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data);
42274bb22   Pavel Shilovsky   CIFS: Fix DFS han...
541
542
543
544
545
546
547
548
549
550
  	switch (rc) {
  	case 0:
  		cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false);
  		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...
551
552
  		/*
  		 * FIXME: legacy server -- fall back to path-based call?
ff215713e   Steve French   [CIFS] checkpatch...
553
554
555
  		 * for now, just skip revalidating and mark inode for
  		 * immediate reval.
  		 */
abab095d1   Jeff Layton   cifs: add cifs_re...
556
557
  		rc = 0;
  		CIFS_I(inode)->time = 0;
42274bb22   Pavel Shilovsky   CIFS: Fix DFS han...
558
  	default:
abab095d1   Jeff Layton   cifs: add cifs_re...
559
  		goto cgfi_exit;
42274bb22   Pavel Shilovsky   CIFS: Fix DFS han...
560
  	}
abab095d1   Jeff Layton   cifs: add cifs_re...
561
562
563
564
565
  
  	/*
  	 * don't bother with SFU junk here -- just mark inode as needing
  	 * revalidation.
  	 */
abab095d1   Jeff Layton   cifs: add cifs_re...
566
567
568
569
570
571
572
  	fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
  	fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
  	cifs_fattr_to_inode(inode, &fattr);
  cgfi_exit:
  	FreeXid(xid);
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573
  int cifs_get_inode_info(struct inode **pinode,
646dd5398   Steve French   [CIFS] Fix paths ...
574
  	const unsigned char *full_path, FILE_ALL_INFO *pfindData,
8b1327f6e   Steve French   [CIFS] file creat...
575
  	struct super_block *sb, int xid, const __u16 *pfid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
  {
0b8f18e35   Jeff Layton   cifs: convert cif...
577
  	int rc = 0, tmprc;
96daf2b09   Steve French   [CIFS] Rename thr...
578
  	struct cifs_tcon *pTcon;
7ffec3724   Jeff Layton   cifs: add refcoun...
579
  	struct tcon_link *tlink;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
581
  	char *buf = NULL;
5ade9deaa   Steve French   [CIFS] fix typo
582
  	bool adjustTZ = false;
0b8f18e35   Jeff Layton   cifs: convert cif...
583
  	struct cifs_fattr fattr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584

7ffec3724   Jeff Layton   cifs: add refcoun...
585
586
587
588
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
  	pTcon = tlink_tcon(tlink);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
589
  	cFYI(1, "Getting info on %s", full_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590

d0d2f2df6   Steve French   [CIFS] Update cif...
591
592
  	if ((pfindData == NULL) && (*pinode != NULL)) {
  		if (CIFS_I(*pinode)->clientCanCacheRead) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
593
  			cFYI(1, "No need to revalidate cached inode sizes");
7ffec3724   Jeff Layton   cifs: add refcoun...
594
  			goto cgii_exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595
596
597
598
  		}
  	}
  
  	/* if file info not passed in then get it from server */
d0d2f2df6   Steve French   [CIFS] Update cif...
599
  	if (pfindData == NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600
  		buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
7ffec3724   Jeff Layton   cifs: add refcoun...
601
602
603
604
  		if (buf == NULL) {
  			rc = -ENOMEM;
  			goto cgii_exit;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
  		pfindData = (FILE_ALL_INFO *)buf;
7962670e6   Igor Mammedov   [CIFS] DFS patch...
606

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
607
  		/* could do find first instead but this returns more info */
7962670e6   Igor Mammedov   [CIFS] DFS patch...
608
  		rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData,
acf1a1b10   Steve French   [CIFS] Level 1 QP...
609
  			      0 /* not legacy */,
6b8edfe0f   Steve French   [CIFS] Support fo...
610
  			      cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
737b758c9   Steve French   [PATCH] cifs: cha...
611
  				CIFS_MOUNT_MAP_SPECIAL_CHR);
6b8edfe0f   Steve French   [CIFS] Support fo...
612
613
614
  		/* BB optimize code so we do not make the above call
  		when server claims no NT SMB support and the above call
  		failed at least once - set flag in tcon or mount */
4523cc304   Steve French   [CIFS] UID/GID ov...
615
  		if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
7962670e6   Igor Mammedov   [CIFS] DFS patch...
616
  			rc = SMBQueryInformation(xid, pTcon, full_path,
fb8c4b14d   Steve French   [CIFS] whitespace...
617
  					pfindData, cifs_sb->local_nls,
6b8edfe0f   Steve French   [CIFS] Support fo...
618
619
  					cifs_sb->mnt_cifs_flags &
  					  CIFS_MOUNT_MAP_SPECIAL_CHR);
4b18f2a9c   Steve French   [CIFS] convert us...
620
  			adjustTZ = true;
6b8edfe0f   Steve French   [CIFS] Support fo...
621
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622
  	}
0b8f18e35   Jeff Layton   cifs: convert cif...
623
624
625
626
627
628
  
  	if (!rc) {
  		cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *) pfindData,
  				       cifs_sb, adjustTZ);
  	} else if (rc == -EREMOTE) {
  		cifs_create_dfs_fattr(&fattr, sb);
b9a3260f2   Steve French   [CIFS] Enable DFS...
629
  		rc = 0;
0b8f18e35   Jeff Layton   cifs: convert cif...
630
  	} else {
7962670e6   Igor Mammedov   [CIFS] DFS patch...
631
  		goto cgii_exit;
0b8f18e35   Jeff Layton   cifs: convert cif...
632
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
633

0b8f18e35   Jeff Layton   cifs: convert cif...
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
  	/*
  	 * 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?
  	 *
  	 * We can not use the IndexNumber field by default from Windows or
  	 * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA
  	 * CIFS spec claims that this value is unique within the scope of a
  	 * share, and the windows docs hint that it's actually unique
  	 * per-machine.
  	 *
  	 * There may be higher info levels that work but are there Windows
  	 * server or network appliances for which IndexNumber field is not
  	 * guaranteed unique?
  	 */
b9a3260f2   Steve French   [CIFS] Enable DFS...
651
  	if (*pinode == NULL) {
b9a3260f2   Steve French   [CIFS] Enable DFS...
652
653
  		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
  			int rc1 = 0;
b9a3260f2   Steve French   [CIFS] Enable DFS...
654
655
  
  			rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
0b8f18e35   Jeff Layton   cifs: convert cif...
656
  					full_path, &fattr.cf_uniqueid,
737b758c9   Steve French   [PATCH] cifs: cha...
657
658
659
  					cifs_sb->local_nls,
  					cifs_sb->mnt_cifs_flags &
  						CIFS_MOUNT_MAP_SPECIAL_CHR);
ec06aedd4   Jeff Layton   cifs: clean up ha...
660
  			if (rc1 || !fattr.cf_uniqueid) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
661
  				cFYI(1, "GetSrvInodeNum rc %d", rc1);
0b8f18e35   Jeff Layton   cifs: convert cif...
662
  				fattr.cf_uniqueid = iunique(sb, ROOT_I);
ec06aedd4   Jeff Layton   cifs: clean up ha...
663
  				cifs_autodisable_serverino(cifs_sb);
132ac7b77   Jeff Layton   cifs: refactor ne...
664
  			}
132ac7b77   Jeff Layton   cifs: refactor ne...
665
  		} else {
0b8f18e35   Jeff Layton   cifs: convert cif...
666
  			fattr.cf_uniqueid = iunique(sb, ROOT_I);
132ac7b77   Jeff Layton   cifs: refactor ne...
667
  		}
b9a3260f2   Steve French   [CIFS] Enable DFS...
668
  	} else {
0b8f18e35   Jeff Layton   cifs: convert cif...
669
  		fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid;
b9a3260f2   Steve French   [CIFS] Enable DFS...
670
  	}
0b8f18e35   Jeff Layton   cifs: convert cif...
671
672
673
674
675
  	/* 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)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
676
  			cFYI(1, "cifs_sfu_type failed: %d", tmprc);
b9a3260f2   Steve French   [CIFS] Enable DFS...
677
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678

79df1baee   Jeff Layton   cifs: fix use of ...
679
  #ifdef CONFIG_CIFS_ACL
b9a3260f2   Steve French   [CIFS] Enable DFS...
680
681
  	/* fill in 0777 bits from ACL */
  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
78415d2d3   Shirish Pargaonkar   cifs: Misc. clean...
682
683
684
685
686
687
688
  		rc = cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path,
  						pfid);
  		if (rc) {
  			cFYI(1, "%s: Getting ACL failed with error: %d",
  				__func__, rc);
  			goto cgii_exit;
  		}
b9a3260f2   Steve French   [CIFS] Enable DFS...
689
  	}
79df1baee   Jeff Layton   cifs: fix use of ...
690
  #endif /* CONFIG_CIFS_ACL */
b9a3260f2   Steve French   [CIFS] Enable DFS...
691

0b8f18e35   Jeff Layton   cifs: convert cif...
692
693
694
  	/* 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...
695

1b12b9c15   Stefan Metzmacher   cifs: use Minshal...
696
697
698
699
700
701
  	/* check for Minshall+French symlinks */
  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
  		tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
  		if (tmprc)
  			cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
  	}
0b8f18e35   Jeff Layton   cifs: convert cif...
702
703
704
705
706
707
708
  	if (!*pinode) {
  		*pinode = cifs_iget(sb, &fattr);
  		if (!*pinode)
  			rc = -ENOMEM;
  	} else {
  		cifs_fattr_to_inode(*pinode, &fattr);
  	}
b9a3260f2   Steve French   [CIFS] Enable DFS...
709

7962670e6   Igor Mammedov   [CIFS] DFS patch...
710
  cgii_exit:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
711
  	kfree(buf);
7ffec3724   Jeff Layton   cifs: add refcoun...
712
  	cifs_put_tlink(tlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
713
714
  	return rc;
  }
7f8ed420f   Steve French   [CIFS] CIFS suppo...
715
716
717
  static const struct inode_operations cifs_ipc_inode_ops = {
  	.lookup = cifs_lookup,
  };
f87d39d95   Steve French   [CIFS] Migrate fr...
718
  char *cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
96daf2b09   Steve French   [CIFS] Rename thr...
719
  			      struct cifs_tcon *tcon)
8be0ed44c   Steve French   [CIFS] Can not mo...
720
  {
f87d39d95   Steve French   [CIFS] Migrate fr...
721
  	int pplen = vol->prepath ? strlen(vol->prepath) : 0;
8be0ed44c   Steve French   [CIFS] Can not mo...
722
723
724
725
726
727
728
729
730
731
  	int dfsplen;
  	char *full_path = NULL;
  
  	/* if no prefix path, simply set path to the root of share to "" */
  	if (pplen == 0) {
  		full_path = kmalloc(1, GFP_KERNEL);
  		if (full_path)
  			full_path[0] = 0;
  		return full_path;
  	}
0d424ad0a   Jeff Layton   cifs: add cifs_sb...
732
733
  	if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
  		dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
8be0ed44c   Steve French   [CIFS] Can not mo...
734
735
736
737
738
739
  	else
  		dfsplen = 0;
  
  	full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL);
  	if (full_path == NULL)
  		return full_path;
f9e8c4500   Jeff Layton   cifs: convert pre...
740
  	if (dfsplen)
0d424ad0a   Jeff Layton   cifs: add cifs_sb...
741
  		strncpy(full_path, tcon->treeName, dfsplen);
f87d39d95   Steve French   [CIFS] Migrate fr...
742
  	strncpy(full_path + dfsplen, vol->prepath, pplen);
f9e8c4500   Jeff Layton   cifs: convert pre...
743
  	convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
8be0ed44c   Steve French   [CIFS] Can not mo...
744
745
746
  	full_path[dfsplen + pplen] = 0; /* add trailing null */
  	return full_path;
  }
cc0bad755   Jeff Layton   cifs: add new cif...
747
748
749
750
  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...
751
  	/* don't match inode with different uniqueid */
cc0bad755   Jeff Layton   cifs: add new cif...
752
753
  	if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
  		return 0;
20054bd65   Jeff Layton   cifs: use Creatio...
754
755
756
  	/* use createtime like an i_generation field */
  	if (CIFS_I(inode)->createtime != fattr->cf_createtime)
  		return 0;
f30b9c118   Jeff Layton   cifs: don't allow...
757
758
759
  	/* 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...
760
761
  	/* if it's not a directory or has no dentries, then flag it */
  	if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry))
3d6943803   Jeff Layton   cifs: guard again...
762
  		fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
3d6943803   Jeff Layton   cifs: guard again...
763

cc0bad755   Jeff Layton   cifs: add new cif...
764
765
766
767
768
769
770
771
772
  	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...
773
  	CIFS_I(inode)->createtime = fattr->cf_createtime;
cc0bad755   Jeff Layton   cifs: add new cif...
774
775
  	return 0;
  }
5acfec250   Jeff Layton   cifs: reduce fals...
776
777
778
779
780
781
782
783
784
  /*
   * 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...
785
  	spin_lock(&inode->i_lock);
5acfec250   Jeff Layton   cifs: reduce fals...
786
787
  	list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
  		if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
873feea09   Nick Piggin   fs: dcache per-in...
788
  			spin_unlock(&inode->i_lock);
5acfec250   Jeff Layton   cifs: reduce fals...
789
790
791
  			return true;
  		}
  	}
873feea09   Nick Piggin   fs: dcache per-in...
792
  	spin_unlock(&inode->i_lock);
5acfec250   Jeff Layton   cifs: reduce fals...
793
794
  	return false;
  }
cc0bad755   Jeff Layton   cifs: add new cif...
795
796
797
798
799
800
  /* 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...
801
  retry_iget5_locked:
b6b38f704   Joe Perches   [CIFS] Neaten cER...
802
  	cFYI(1, "looking for uniqueid=%llu", fattr->cf_uniqueid);
cc0bad755   Jeff Layton   cifs: add new cif...
803
804
805
806
807
  
  	/* 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...
808
  	if (inode) {
5acfec250   Jeff Layton   cifs: reduce fals...
809
  		/* was there a potentially problematic inode collision? */
3d6943803   Jeff Layton   cifs: guard again...
810
  		if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
3d6943803   Jeff Layton   cifs: guard again...
811
  			fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
5acfec250   Jeff Layton   cifs: reduce fals...
812
813
814
815
816
817
818
  
  			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...
819
  		}
cc0bad755   Jeff Layton   cifs: add new cif...
820
821
822
823
824
  		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;
522440ed5   Jeff Layton   cifs: set backing...
825
826
  			if (S_ISREG(inode->i_mode))
  				inode->i_data.backing_dev_info = sb->s_bdi;
0ccd48025   Steve French   [CIFS] Missing ifdef
827
  #ifdef CONFIG_CIFS_FSCACHE
9451a9a52   Suresh Jayaraman   cifs: define inod...
828
829
  			/* initialize per-inode cache cookie pointer */
  			CIFS_I(inode)->fscache = NULL;
0ccd48025   Steve French   [CIFS] Missing ifdef
830
  #endif
cc0bad755   Jeff Layton   cifs: add new cif...
831
832
833
834
835
836
  			unlock_new_inode(inode);
  		}
  	}
  
  	return inode;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
837
  /* gets root inode */
9b6763e0a   Shirish Pargaonkar   cifs: Remove unus...
838
  struct inode *cifs_root_iget(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839
  {
ce634ab28   David Howells   iget: stop CIFS f...
840
  	int xid;
0d424ad0a   Jeff Layton   cifs: add cifs_sb...
841
  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
cc0bad755   Jeff Layton   cifs: add new cif...
842
  	struct inode *inode = NULL;
ce634ab28   David Howells   iget: stop CIFS f...
843
  	long rc;
96daf2b09   Steve French   [CIFS] Rename thr...
844
  	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
ce634ab28   David Howells   iget: stop CIFS f...
845

8be0ed44c   Steve French   [CIFS] Can not mo...
846
  	xid = GetXid();
0d424ad0a   Jeff Layton   cifs: add cifs_sb...
847
  	if (tcon->unix_ext)
f87d39d95   Steve French   [CIFS] Migrate fr...
848
  		rc = cifs_get_inode_info_unix(&inode, "", sb, xid);
0b8f18e35   Jeff Layton   cifs: convert cif...
849
  	else
f87d39d95   Steve French   [CIFS] Migrate fr...
850
  		rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL);
0b8f18e35   Jeff Layton   cifs: convert cif...
851

a7851ce73   Oskar Schirmer   cifs: fix another...
852
853
854
855
  	if (!inode) {
  		inode = ERR_PTR(rc);
  		goto out;
  	}
cc0bad755   Jeff Layton   cifs: add new cif...
856

0ccd48025   Steve French   [CIFS] Missing ifdef
857
  #ifdef CONFIG_CIFS_FSCACHE
d03382ce9   Suresh Jayaraman   cifs: define supe...
858
  	/* populate tcon->resource_id */
0d424ad0a   Jeff Layton   cifs: add cifs_sb...
859
  	tcon->resource_id = CIFS_I(inode)->uniqueid;
0ccd48025   Steve French   [CIFS] Missing ifdef
860
  #endif
d03382ce9   Suresh Jayaraman   cifs: define supe...
861

0d424ad0a   Jeff Layton   cifs: add cifs_sb...
862
  	if (rc && tcon->ipc) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
863
  		cFYI(1, "ipc connection - fake read inode");
7f8ed420f   Steve French   [CIFS] CIFS suppo...
864
  		inode->i_mode |= S_IFDIR;
bfe868486   Miklos Szeredi   filesystems: add ...
865
  		set_nlink(inode, 2);
7f8ed420f   Steve French   [CIFS] CIFS suppo...
866
867
868
869
  		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;
ad661334b   Steve French   [CIFS] mount of I...
870
  	} else if (rc) {
ce634ab28   David Howells   iget: stop CIFS f...
871
  		iget_failed(inode);
a7851ce73   Oskar Schirmer   cifs: fix another...
872
  		inode = ERR_PTR(rc);
7f8ed420f   Steve French   [CIFS] CIFS suppo...
873
  	}
a7851ce73   Oskar Schirmer   cifs: fix another...
874
  out:
ce634ab28   David Howells   iget: stop CIFS f...
875
876
877
  	/* can not call macro FreeXid here since in a void func
  	 * TODO: This is no longer true
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
878
  	_FreeXid(xid);
ce634ab28   David Howells   iget: stop CIFS f...
879
  	return inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
880
  }
388e57b27   Steve French   [CIFS] use common...
881
882
883
884
885
886
887
888
889
890
891
892
  static int
  cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
  		    char *full_path, __u32 dosattr)
  {
  	int rc;
  	int oplock = 0;
  	__u16 netfid;
  	__u32 netpid;
  	bool set_time = false;
  	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...
893
  	struct tcon_link *tlink = NULL;
96daf2b09   Steve French   [CIFS] Rename thr...
894
  	struct cifs_tcon *pTcon;
388e57b27   Steve French   [CIFS] use common...
895
  	FILE_BASIC_INFO	info_buf;
1adcb7109   Steve French   [CIFS] add extra ...
896
897
  	if (attrs == NULL)
  		return -EINVAL;
388e57b27   Steve French   [CIFS] use common...
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
  	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)) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
919
  		cFYI(1, "CIFS - CTIME changed");
388e57b27   Steve French   [CIFS] use common...
920
921
922
923
924
925
926
927
928
929
930
  		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);
  
  	/*
  	 * If the file is already open for write, just use that fileid
  	 */
6508d904e   Jeff Layton   cifs: have find_r...
931
  	open_file = find_writable_file(cifsInode, true);
388e57b27   Steve French   [CIFS] use common...
932
933
934
  	if (open_file) {
  		netfid = open_file->netfid;
  		netpid = open_file->pid;
13cfb7334   Jeff Layton   cifs: have cifsFi...
935
  		pTcon = tlink_tcon(open_file->tlink);
388e57b27   Steve French   [CIFS] use common...
936
937
  		goto set_via_filehandle;
  	}
7ffec3724   Jeff Layton   cifs: add refcoun...
938
939
940
941
942
943
944
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink)) {
  		rc = PTR_ERR(tlink);
  		tlink = NULL;
  		goto out;
  	}
  	pTcon = tlink_tcon(tlink);
ba00ba64c   Jeff Layton   cifs: make variou...
945

388e57b27   Steve French   [CIFS] use common...
946
947
948
949
950
951
952
953
954
  	/*
  	 * NT4 apparently returns success on this call, but it doesn't
  	 * really work.
  	 */
  	if (!(pTcon->ses->flags & CIFS_SES_NT4)) {
  		rc = CIFSSMBSetPathInfo(xid, pTcon, full_path,
  				     &info_buf, cifs_sb->local_nls,
  				     cifs_sb->mnt_cifs_flags &
  					CIFS_MOUNT_MAP_SPECIAL_CHR);
6b37faa17   Jeff Layton   [CIFS] fix some s...
955
956
957
958
  		if (rc == 0) {
  			cifsInode->cifsAttrs = dosattr;
  			goto out;
  		} else if (rc != -EOPNOTSUPP && rc != -EINVAL)
388e57b27   Steve French   [CIFS] use common...
959
960
  			goto out;
  	}
b6b38f704   Joe Perches   [CIFS] Neaten cER...
961
962
  	cFYI(1, "calling SetFileInfo since SetPathInfo for "
  		 "times not supported by this server");
388e57b27   Steve French   [CIFS] use common...
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
  	rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
  			 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
  			 CREATE_NOT_DIR, &netfid, &oplock,
  			 NULL, cifs_sb->local_nls,
  			 cifs_sb->mnt_cifs_flags &
  				CIFS_MOUNT_MAP_SPECIAL_CHR);
  
  	if (rc != 0) {
  		if (rc == -EIO)
  			rc = -EINVAL;
  		goto out;
  	}
  
  	netpid = current->tgid;
  
  set_via_filehandle:
  	rc = CIFSSMBSetFileInfo(xid, pTcon, &info_buf, netfid, netpid);
d388908ec   Steve French   [CIFS] update DOS...
980
981
  	if (!rc)
  		cifsInode->cifsAttrs = dosattr;
388e57b27   Steve French   [CIFS] use common...
982
983
984
  	if (open_file == NULL)
  		CIFSSMBClose(xid, pTcon, netfid);
  	else
6ab409b53   Dave Kleikamp   cifs: Replace wrt...
985
  		cifsFileInfo_put(open_file);
388e57b27   Steve French   [CIFS] use common...
986
  out:
7ffec3724   Jeff Layton   cifs: add refcoun...
987
988
  	if (tlink != NULL)
  		cifs_put_tlink(tlink);
388e57b27   Steve French   [CIFS] use common...
989
990
  	return rc;
  }
a12a1ac7a   Jeff Layton   cifs: move rename...
991
992
993
994
995
996
  /*
   * open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
   * and rename it to a random name that hopefully won't conflict with
   * anything else.
   */
  static int
3270958b7   Steve French   [CIFS] undo chang...
997
  cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid)
a12a1ac7a   Jeff Layton   cifs: move rename...
998
999
1000
1001
  {
  	int oplock = 0;
  	int rc;
  	__u16 netfid;
3270958b7   Steve French   [CIFS] undo chang...
1002
  	struct inode *inode = dentry->d_inode;
a12a1ac7a   Jeff Layton   cifs: move rename...
1003
1004
  	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
1005
  	struct tcon_link *tlink;
96daf2b09   Steve French   [CIFS] Rename thr...
1006
  	struct cifs_tcon *tcon;
3270958b7   Steve French   [CIFS] undo chang...
1007
1008
  	__u32 dosattr, origattr;
  	FILE_BASIC_INFO *info_buf = NULL;
a12a1ac7a   Jeff Layton   cifs: move rename...
1009

7ffec3724   Jeff Layton   cifs: add refcoun...
1010
1011
1012
1013
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
  	tcon = tlink_tcon(tlink);
a12a1ac7a   Jeff Layton   cifs: move rename...
1014
  	rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
dd1db2ded   Jeff Layton   cifs: don't use C...
1015
  			 DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
a12a1ac7a   Jeff Layton   cifs: move rename...
1016
1017
1018
1019
  			 &netfid, &oplock, NULL, cifs_sb->local_nls,
  			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
  	if (rc != 0)
  		goto out;
3270958b7   Steve French   [CIFS] undo chang...
1020
1021
1022
1023
1024
  	origattr = cifsInode->cifsAttrs;
  	if (origattr == 0)
  		origattr |= ATTR_NORMAL;
  
  	dosattr = origattr & ~ATTR_READONLY;
a12a1ac7a   Jeff Layton   cifs: move rename...
1025
1026
1027
  	if (dosattr == 0)
  		dosattr |= ATTR_NORMAL;
  	dosattr |= ATTR_HIDDEN;
3270958b7   Steve French   [CIFS] undo chang...
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
  	/* 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);
  		rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
  					current->tgid);
  		/* although we would like to mark the file hidden
   		   if that fails we will still try to rename it */
413460980   Steve French   [CIFS] fix build ...
1040
  		if (rc != 0)
3270958b7   Steve French   [CIFS] undo chang...
1041
1042
1043
  			cifsInode->cifsAttrs = dosattr;
  		else
  			dosattr = origattr; /* since not able to change them */
a12a1ac7a   Jeff Layton   cifs: move rename...
1044
  	}
a12a1ac7a   Jeff Layton   cifs: move rename...
1045

dd1db2ded   Jeff Layton   cifs: don't use C...
1046
1047
  	/* rename the file */
  	rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls,
a12a1ac7a   Jeff Layton   cifs: move rename...
1048
1049
  				   cifs_sb->mnt_cifs_flags &
  					    CIFS_MOUNT_MAP_SPECIAL_CHR);
3270958b7   Steve French   [CIFS] undo chang...
1050
1051
1052
1053
  	if (rc != 0) {
  		rc = -ETXTBSY;
  		goto undo_setattr;
  	}
6d22f0989   Jeff Layton   cifs: add functio...
1054

3270958b7   Steve French   [CIFS] undo chang...
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
  	/* try to set DELETE_ON_CLOSE */
  	if (!cifsInode->delete_pending) {
  		rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid,
  					       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) {
  			rc = -ETXTBSY;
  			goto undo_rename;
  		}
  		cifsInode->delete_pending = true;
  	}
7ce86d5a9   Jeff Layton   cifs: work around...
1075

a12a1ac7a   Jeff Layton   cifs: move rename...
1076
1077
1078
  out_close:
  	CIFSSMBClose(xid, tcon, netfid);
  out:
3270958b7   Steve French   [CIFS] undo chang...
1079
  	kfree(info_buf);
7ffec3724   Jeff Layton   cifs: add refcoun...
1080
  	cifs_put_tlink(tlink);
a12a1ac7a   Jeff Layton   cifs: move rename...
1081
  	return rc;
3270958b7   Steve French   [CIFS] undo chang...
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
  
  	/*
  	 * 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:
  	CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name,
  				cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
  					    CIFS_MOUNT_MAP_SPECIAL_CHR);
  undo_setattr:
  	if (dosattr != origattr) {
  		info_buf->Attributes = cpu_to_le32(origattr);
  		if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
  					current->tgid))
  			cifsInode->cifsAttrs = origattr;
  	}
  
  	goto out_close;
a12a1ac7a   Jeff Layton   cifs: move rename...
1101
  }
ff6945279   Steve French   [CIFS] Make cifs_...
1102
1103
1104
1105
  
  /*
   * If dentry->d_inode is null (usually meaning the cached dentry
   * is a negative dentry) then we would attempt a standard SMB delete, but
af901ca18   André Goddard Rosa   tree-wide: fix as...
1106
1107
   * 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_...
1108
1109
   * unlink on negative dentries currently.
   */
5f0319a79   Jeff Layton   cifs: clean up va...
1110
  int cifs_unlink(struct inode *dir, struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1111
1112
1113
  {
  	int rc = 0;
  	int xid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1114
  	char *full_path = NULL;
5f0319a79   Jeff Layton   cifs: clean up va...
1115
  	struct inode *inode = dentry->d_inode;
ff6945279   Steve French   [CIFS] Make cifs_...
1116
  	struct cifsInodeInfo *cifs_inode;
5f0319a79   Jeff Layton   cifs: clean up va...
1117
1118
  	struct super_block *sb = dir->i_sb;
  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
1119
  	struct tcon_link *tlink;
96daf2b09   Steve French   [CIFS] Rename thr...
1120
  	struct cifs_tcon *tcon;
6050247d8   Steve French   [CIFS] clean up ...
1121
1122
  	struct iattr *attrs = NULL;
  	__u32 dosattr = 0, origattr = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1123

b6b38f704   Joe Perches   [CIFS] Neaten cER...
1124
  	cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1125

7ffec3724   Jeff Layton   cifs: add refcoun...
1126
1127
1128
1129
  	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
1130
  	xid = GetXid();
5f0319a79   Jeff Layton   cifs: clean up va...
1131
1132
1133
  	/* 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
1134
  	if (full_path == NULL) {
0f3bc09ee   Suresh Jayaraman   cifs: Fix incorre...
1135
  		rc = -ENOMEM;
7ffec3724   Jeff Layton   cifs: add refcoun...
1136
  		goto unlink_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1137
  	}
2d785a50a   Steve French   [CIFS] Add suppor...
1138

5f0319a79   Jeff Layton   cifs: clean up va...
1139
  	if ((tcon->ses->capabilities & CAP_UNIX) &&
2d785a50a   Steve French   [CIFS] Add suppor...
1140
  		(CIFS_UNIX_POSIX_PATH_OPS_CAP &
5f0319a79   Jeff Layton   cifs: clean up va...
1141
1142
  			le64_to_cpu(tcon->fsUnixInfo.Capability))) {
  		rc = CIFSPOSIXDelFile(xid, tcon, full_path,
2d785a50a   Steve French   [CIFS] Add suppor...
1143
  			SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
737b758c9   Steve French   [PATCH] cifs: cha...
1144
  			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1145
  		cFYI(1, "posix del rc %d", rc);
2d785a50a   Steve French   [CIFS] Add suppor...
1146
1147
1148
  		if ((rc == 0) || (rc == -ENOENT))
  			goto psx_del_no_retry;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1149

6050247d8   Steve French   [CIFS] clean up ...
1150
  retry_std_delete:
5f0319a79   Jeff Layton   cifs: clean up va...
1151
  	rc = CIFSSMBDelFile(xid, tcon, full_path, cifs_sb->local_nls,
2d785a50a   Steve French   [CIFS] Add suppor...
1152
  			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
6050247d8   Steve French   [CIFS] clean up ...
1153

2d785a50a   Steve French   [CIFS] Add suppor...
1154
  psx_del_no_retry:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1155
  	if (!rc) {
5f0319a79   Jeff Layton   cifs: clean up va...
1156
1157
  		if (inode)
  			drop_nlink(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1158
  	} else if (rc == -ENOENT) {
5f0319a79   Jeff Layton   cifs: clean up va...
1159
  		d_drop(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1160
  	} else if (rc == -ETXTBSY) {
3270958b7   Steve French   [CIFS] undo chang...
1161
  		rc = cifs_rename_pending_delete(full_path, dentry, xid);
a12a1ac7a   Jeff Layton   cifs: move rename...
1162
1163
  		if (rc == 0)
  			drop_nlink(inode);
ff6945279   Steve French   [CIFS] Make cifs_...
1164
  	} else if ((rc == -EACCES) && (dosattr == 0) && inode) {
388e57b27   Steve French   [CIFS] use common...
1165
1166
1167
1168
  		attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
  		if (attrs == NULL) {
  			rc = -ENOMEM;
  			goto out_reval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1169
  		}
388e57b27   Steve French   [CIFS] use common...
1170
1171
  
  		/* try to reset dos attributes */
ff6945279   Steve French   [CIFS] Make cifs_...
1172
1173
  		cifs_inode = CIFS_I(inode);
  		origattr = cifs_inode->cifsAttrs;
6050247d8   Steve French   [CIFS] clean up ...
1174
1175
1176
  		if (origattr == 0)
  			origattr |= ATTR_NORMAL;
  		dosattr = origattr & ~ATTR_READONLY;
388e57b27   Steve French   [CIFS] use common...
1177
1178
1179
1180
1181
  		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...
1182
1183
  		if (rc != 0)
  			goto out_reval;
6050247d8   Steve French   [CIFS] clean up ...
1184
1185
  
  		goto retry_std_delete;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1186
  	}
6050247d8   Steve French   [CIFS] clean up ...
1187
1188
1189
1190
  
  	/* 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...
1191
  out_reval:
4523cc304   Steve French   [CIFS] UID/GID ov...
1192
  	if (inode) {
ff6945279   Steve French   [CIFS] Make cifs_...
1193
1194
  		cifs_inode = CIFS_I(inode);
  		cifs_inode->time = 0;	/* will force revalidate to get info
5f0319a79   Jeff Layton   cifs: clean up va...
1195
1196
  					   when needed */
  		inode->i_ctime = current_fs_time(sb);
06bcfedd0   Steve French   [CIFS] Fix typo i...
1197
  	}
5f0319a79   Jeff Layton   cifs: clean up va...
1198
  	dir->i_ctime = dir->i_mtime = current_fs_time(sb);
ff6945279   Steve French   [CIFS] Make cifs_...
1199
  	cifs_inode = CIFS_I(dir);
6050247d8   Steve French   [CIFS] clean up ...
1200
  	CIFS_I(dir)->time = 0;	/* force revalidate of dir as well */
7ffec3724   Jeff Layton   cifs: add refcoun...
1201
  unlink_out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1202
  	kfree(full_path);
6050247d8   Steve French   [CIFS] clean up ...
1203
  	kfree(attrs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1204
  	FreeXid(xid);
7ffec3724   Jeff Layton   cifs: add refcoun...
1205
  	cifs_put_tlink(tlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1206
1207
  	return rc;
  }
18bb1db3e   Al Viro   switch vfs_mkdir(...
1208
  int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1209
  {
6b37faa17   Jeff Layton   [CIFS] fix some s...
1210
  	int rc = 0, tmprc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1211
1212
  	int xid;
  	struct cifs_sb_info *cifs_sb;
7ffec3724   Jeff Layton   cifs: add refcoun...
1213
  	struct tcon_link *tlink;
96daf2b09   Steve French   [CIFS] Rename thr...
1214
  	struct cifs_tcon *pTcon;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1215
1216
  	char *full_path = NULL;
  	struct inode *newinode = NULL;
cc0bad755   Jeff Layton   cifs: add new cif...
1217
  	struct cifs_fattr fattr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1218

18bb1db3e   Al Viro   switch vfs_mkdir(...
1219
  	cFYI(1, "In cifs_mkdir, mode = 0x%hx inode = 0x%p", mode, inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1220

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1221
  	cifs_sb = CIFS_SB(inode->i_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
1222
1223
1224
1225
1226
1227
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
  	pTcon = tlink_tcon(tlink);
  
  	xid = GetXid();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1228

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

fb8c4b14d   Steve French   [CIFS] whitespace...
1235
1236
  	if ((pTcon->ses->capabilities & CAP_UNIX) &&
  		(CIFS_UNIX_POSIX_PATH_OPS_CAP &
2dd29d313   Steve French   [CIFS] New CIFS P...
1237
1238
  			le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
  		u32 oplock = 0;
f6d099821   Steve French   [CIFS] fix checkp...
1239
  		FILE_UNIX_BASIC_INFO *pInfo =
2dd29d313   Steve French   [CIFS] New CIFS P...
1240
  			kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
fb8c4b14d   Steve French   [CIFS] whitespace...
1241
  		if (pInfo == NULL) {
2dd29d313   Steve French   [CIFS] New CIFS P...
1242
1243
1244
  			rc = -ENOMEM;
  			goto mkdir_out;
  		}
50c2f7538   Steve French   [CIFS] whitespace...
1245

ce3b0f8d5   Al Viro   New helper - curr...
1246
  		mode &= ~current_umask();
2dd29d313   Steve French   [CIFS] New CIFS P...
1247
1248
  		rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
  				mode, NULL /* netfid */, pInfo, &oplock,
fb8c4b14d   Steve French   [CIFS] whitespace...
1249
1250
  				full_path, cifs_sb->local_nls,
  				cifs_sb->mnt_cifs_flags &
2dd29d313   Steve French   [CIFS] New CIFS P...
1251
  					CIFS_MOUNT_MAP_SPECIAL_CHR);
c45d707f6   Steve French   [CIFS] Fallback t...
1252
1253
1254
1255
  		if (rc == -EOPNOTSUPP) {
  			kfree(pInfo);
  			goto mkdir_retry_old;
  		} else if (rc) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1256
  			cFYI(1, "posix mkdir returned 0x%x", rc);
2dd29d313   Steve French   [CIFS] New CIFS P...
1257
1258
  			d_drop(direntry);
  		} else {
8f2376adf   Cyril Gorcunov   [CIFS] Fix endian...
1259
1260
  			if (pInfo->Type == cpu_to_le32(-1)) {
  				/* no return info, go query for it */
5a07cdf86   Steve French   [CIFS] fix small ...
1261
  				kfree(pInfo);
fb8c4b14d   Steve French   [CIFS] whitespace...
1262
  				goto mkdir_get_info;
5a07cdf86   Steve French   [CIFS] fix small ...
1263
  			}
fb8c4b14d   Steve French   [CIFS] whitespace...
1264
1265
  /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
  	to set uid/gid */
2dd29d313   Steve French   [CIFS] New CIFS P...
1266
  			inc_nlink(inode);
cbac3cba6   Steve French   [CIFS] New CIFS P...
1267

cc0bad755   Jeff Layton   cifs: add new cif...
1268
  			cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb);
4065c802d   Jeff Layton   cifs: fix noserve...
1269
  			cifs_fill_uniqueid(inode->i_sb, &fattr);
cc0bad755   Jeff Layton   cifs: add new cif...
1270
1271
  			newinode = cifs_iget(inode->i_sb, &fattr);
  			if (!newinode) {
5a07cdf86   Steve French   [CIFS] fix small ...
1272
  				kfree(pInfo);
cbac3cba6   Steve French   [CIFS] New CIFS P...
1273
  				goto mkdir_get_info;
5a07cdf86   Steve French   [CIFS] fix small ...
1274
  			}
6b37faa17   Jeff Layton   [CIFS] fix some s...
1275

2dd29d313   Steve French   [CIFS] New CIFS P...
1276
  			d_instantiate(direntry, newinode);
cbac3cba6   Steve French   [CIFS] New CIFS P...
1277

cbac3cba6   Steve French   [CIFS] New CIFS P...
1278
  #ifdef CONFIG_CIFS_DEBUG2
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1279
1280
  			cFYI(1, "instantiated dentry %p %s to inode %p",
  				direntry, direntry->d_name.name, newinode);
cbac3cba6   Steve French   [CIFS] New CIFS P...
1281

fb8c4b14d   Steve French   [CIFS] whitespace...
1282
  			if (newinode->i_nlink != 2)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1283
1284
  				cFYI(1, "unexpected number of links %d",
  					newinode->i_nlink);
cbac3cba6   Steve French   [CIFS] New CIFS P...
1285
  #endif
2dd29d313   Steve French   [CIFS] New CIFS P...
1286
1287
1288
  		}
  		kfree(pInfo);
  		goto mkdir_out;
fb8c4b14d   Steve French   [CIFS] whitespace...
1289
  	}
c45d707f6   Steve French   [CIFS] Fallback t...
1290
  mkdir_retry_old:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1291
  	/* BB add setting the equivalent of mode via CreateX w/ACLs */
737b758c9   Steve French   [PATCH] cifs: cha...
1292
1293
  	rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
  			  cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1294
  	if (rc) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1295
  		cFYI(1, "cifs_mkdir returned 0x%x", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1296
1297
  		d_drop(direntry);
  	} else {
fb8c4b14d   Steve French   [CIFS] whitespace...
1298
  mkdir_get_info:
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
1299
  		inc_nlink(inode);
c18c842b1   Steve French   [CIFS] Allow disa...
1300
  		if (pTcon->unix_ext)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1301
  			rc = cifs_get_inode_info_unix(&newinode, full_path,
fb8c4b14d   Steve French   [CIFS] whitespace...
1302
  						      inode->i_sb, xid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1303
1304
  		else
  			rc = cifs_get_inode_info(&newinode, full_path, NULL,
8b1327f6e   Steve French   [CIFS] file creat...
1305
  						 inode->i_sb, xid, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1306

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1307
  		d_instantiate(direntry, newinode);
2dd29d313   Steve French   [CIFS] New CIFS P...
1308
  		 /* setting nlink not necessary except in cases where we
fb8c4b14d   Steve French   [CIFS] whitespace...
1309
  		  * failed to get it from the server or was set bogus */
2dd29d313   Steve French   [CIFS] New CIFS P...
1310
  		if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
bfe868486   Miklos Szeredi   filesystems: add ...
1311
  			set_nlink(direntry->d_inode, 2);
950899109   Jeff Layton   [CIFS] cifs_mkdir...
1312

ce3b0f8d5   Al Viro   New helper - curr...
1313
  		mode &= ~current_umask();
950899109   Jeff Layton   [CIFS] cifs_mkdir...
1314
1315
1316
  		/* must turn on setgid bit if parent dir has it */
  		if (inode->i_mode & S_ISGID)
  			mode |= S_ISGID;
c18c842b1   Steve French   [CIFS] Allow disa...
1317
  		if (pTcon->unix_ext) {
4e1e7fb9e   Jeff Layton   bundle up Unix SE...
1318
1319
1320
1321
1322
1323
1324
  			struct cifs_unix_set_info_args args = {
  				.mode	= mode,
  				.ctime	= NO_CHANGE_64,
  				.atime	= NO_CHANGE_64,
  				.mtime	= NO_CHANGE_64,
  				.device	= 0,
  			};
d0d2f2df6   Steve French   [CIFS] Update cif...
1325
  			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
a001e5b55   David Howells   CRED: Wrap task c...
1326
  				args.uid = (__u64)current_fsuid();
950899109   Jeff Layton   [CIFS] cifs_mkdir...
1327
1328
1329
  				if (inode->i_mode & S_ISGID)
  					args.gid = (__u64)inode->i_gid;
  				else
a001e5b55   David Howells   CRED: Wrap task c...
1330
  					args.gid = (__u64)current_fsgid();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1331
  			} else {
4e1e7fb9e   Jeff Layton   bundle up Unix SE...
1332
1333
  				args.uid = NO_CHANGE_64;
  				args.gid = NO_CHANGE_64;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1334
  			}
01ea95e3b   Jeff Layton   cifs: rename CIFS...
1335
1336
1337
1338
  			CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
  					       cifs_sb->local_nls,
  					       cifs_sb->mnt_cifs_flags &
  						CIFS_MOUNT_MAP_SPECIAL_CHR);
3ce53fc4c   Steve French   [CIFS] CIFS shoul...
1339
  		} else {
67750fb9e   Jeff Layton   [CIFS] when not u...
1340
1341
1342
  			if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
  			    (mode & S_IWUGO) == 0) {
  				FILE_BASIC_INFO pInfo;
6b37faa17   Jeff Layton   [CIFS] fix some s...
1343
1344
  				struct cifsInodeInfo *cifsInode;
  				u32 dosattrs;
67750fb9e   Jeff Layton   [CIFS] when not u...
1345
  				memset(&pInfo, 0, sizeof(pInfo));
6b37faa17   Jeff Layton   [CIFS] fix some s...
1346
1347
1348
1349
1350
1351
  				cifsInode = CIFS_I(newinode);
  				dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
  				pInfo.Attributes = cpu_to_le32(dosattrs);
  				tmprc = CIFSSMBSetPathInfo(xid, pTcon,
  						full_path, &pInfo,
  						cifs_sb->local_nls,
67750fb9e   Jeff Layton   [CIFS] when not u...
1352
1353
  						cifs_sb->mnt_cifs_flags &
  						CIFS_MOUNT_MAP_SPECIAL_CHR);
6b37faa17   Jeff Layton   [CIFS] fix some s...
1354
1355
  				if (tmprc == 0)
  					cifsInode->cifsAttrs = dosattrs;
67750fb9e   Jeff Layton   [CIFS] when not u...
1356
  			}
fb8c4b14d   Steve French   [CIFS] whitespace...
1357
  			if (direntry->d_inode) {
b0fd30d3e   Jeff Layton   when creating new...
1358
1359
1360
1361
  				if (cifs_sb->mnt_cifs_flags &
  				     CIFS_MOUNT_DYNPERM)
  					direntry->d_inode->i_mode =
  						(mode | S_IFDIR);
4e94a105e   Steve French   [CIFS] remove tra...
1362

fb8c4b14d   Steve French   [CIFS] whitespace...
1363
  				if (cifs_sb->mnt_cifs_flags &
6473a559c   Steve French   [CIFS] Fix missin...
1364
  				     CIFS_MOUNT_SET_UID) {
fb8c4b14d   Steve French   [CIFS] whitespace...
1365
  					direntry->d_inode->i_uid =
a001e5b55   David Howells   CRED: Wrap task c...
1366
  						current_fsuid();
950899109   Jeff Layton   [CIFS] cifs_mkdir...
1367
1368
1369
1370
1371
  					if (inode->i_mode & S_ISGID)
  						direntry->d_inode->i_gid =
  							inode->i_gid;
  					else
  						direntry->d_inode->i_gid =
a001e5b55   David Howells   CRED: Wrap task c...
1372
  							current_fsgid();
6473a559c   Steve French   [CIFS] Fix missin...
1373
1374
  				}
  			}
2a138ebb0   Steve French   [CIFS] Missing pa...
1375
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1376
  	}
fb8c4b14d   Steve French   [CIFS] whitespace...
1377
  mkdir_out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1378
1379
  	kfree(full_path);
  	FreeXid(xid);
7ffec3724   Jeff Layton   cifs: add refcoun...
1380
  	cifs_put_tlink(tlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1381
1382
1383
1384
1385
1386
1387
1388
  	return rc;
  }
  
  int cifs_rmdir(struct inode *inode, struct dentry *direntry)
  {
  	int rc = 0;
  	int xid;
  	struct cifs_sb_info *cifs_sb;
7ffec3724   Jeff Layton   cifs: add refcoun...
1389
  	struct tcon_link *tlink;
96daf2b09   Steve French   [CIFS] Rename thr...
1390
  	struct cifs_tcon *pTcon;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1391
1392
  	char *full_path = NULL;
  	struct cifsInodeInfo *cifsInode;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1393
  	cFYI(1, "cifs_rmdir, inode = 0x%p", inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1394
1395
  
  	xid = GetXid();
7f57356b7   Steve French   [CIFS] Remove cif...
1396
  	full_path = build_path_from_dentry(direntry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1397
  	if (full_path == NULL) {
0f3bc09ee   Suresh Jayaraman   cifs: Fix incorre...
1398
  		rc = -ENOMEM;
7ffec3724   Jeff Layton   cifs: add refcoun...
1399
  		goto rmdir_exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1400
  	}
7ffec3724   Jeff Layton   cifs: add refcoun...
1401
1402
1403
1404
1405
1406
1407
  	cifs_sb = CIFS_SB(inode->i_sb);
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink)) {
  		rc = PTR_ERR(tlink);
  		goto rmdir_exit;
  	}
  	pTcon = tlink_tcon(tlink);
737b758c9   Steve French   [PATCH] cifs: cha...
1408
1409
  	rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
  			  cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
7ffec3724   Jeff Layton   cifs: add refcoun...
1410
  	cifs_put_tlink(tlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1411
1412
  
  	if (!rc) {
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
1413
  		drop_nlink(inode);
3677db10a   Steve French   [CIFS] Fix lockin...
1414
  		spin_lock(&direntry->d_inode->i_lock);
fb8c4b14d   Steve French   [CIFS] whitespace...
1415
  		i_size_write(direntry->d_inode, 0);
ce71ec368   Dave Hansen   [PATCH] r/o bind ...
1416
  		clear_nlink(direntry->d_inode);
3677db10a   Steve French   [CIFS] Fix lockin...
1417
  		spin_unlock(&direntry->d_inode->i_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1418
1419
1420
1421
1422
  	}
  
  	cifsInode = CIFS_I(direntry->d_inode);
  	cifsInode->time = 0;	/* force revalidate to go get info when
  				   needed */
42c245447   Steve French   [CIFS] revalidate...
1423
1424
1425
1426
  
  	cifsInode = CIFS_I(inode);
  	cifsInode->time = 0;	/* force revalidate to get parent dir info
  				   since cached search results now invalid */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1427
1428
  	direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
  		current_fs_time(inode->i_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
1429
  rmdir_exit:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1430
1431
1432
1433
  	kfree(full_path);
  	FreeXid(xid);
  	return rc;
  }
ee2fd967f   Steve French   [CIFS] fix busy-...
1434
1435
1436
1437
1438
  static int
  cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
  		struct dentry *to_dentry, const char *toPath)
  {
  	struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
1439
  	struct tcon_link *tlink;
96daf2b09   Steve French   [CIFS] Rename thr...
1440
  	struct cifs_tcon *pTcon;
ee2fd967f   Steve French   [CIFS] fix busy-...
1441
1442
  	__u16 srcfid;
  	int oplock, rc;
7ffec3724   Jeff Layton   cifs: add refcoun...
1443
1444
1445
1446
  	tlink = cifs_sb_tlink(cifs_sb);
  	if (IS_ERR(tlink))
  		return PTR_ERR(tlink);
  	pTcon = tlink_tcon(tlink);
ee2fd967f   Steve French   [CIFS] fix busy-...
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
  	/* try path-based rename first */
  	rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls,
  			   cifs_sb->mnt_cifs_flags &
  				CIFS_MOUNT_MAP_SPECIAL_CHR);
  
  	/*
  	 * don't bother with rename by filehandle unless file is busy and
  	 * source Note that cross directory moves do not work with
  	 * rename by filehandle to various Windows servers.
  	 */
  	if (rc == 0 || rc != -ETXTBSY)
7ffec3724   Jeff Layton   cifs: add refcoun...
1458
  		goto do_rename_exit;
ee2fd967f   Steve French   [CIFS] fix busy-...
1459

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

ee2fd967f   Steve French   [CIFS] fix busy-...
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
  	/* open the file to be renamed -- we need DELETE perms */
  	rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE,
  			 CREATE_NOT_DIR, &srcfid, &oplock, NULL,
  			 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
  				CIFS_MOUNT_MAP_SPECIAL_CHR);
  
  	if (rc == 0) {
  		rc = CIFSSMBRenameOpenFile(xid, pTcon, srcfid,
  				(const char *) to_dentry->d_name.name,
  				cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
  					CIFS_MOUNT_MAP_SPECIAL_CHR);
  
  		CIFSSMBClose(xid, pTcon, srcfid);
  	}
7ffec3724   Jeff Layton   cifs: add refcoun...
1478
1479
  do_rename_exit:
  	cifs_put_tlink(tlink);
ee2fd967f   Steve French   [CIFS] fix busy-...
1480
1481
  	return rc;
  }
14121bdcc   Jeff Layton   cifs: make cifs_r...
1482
1483
  int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
  	struct inode *target_dir, struct dentry *target_dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1484
  {
ee2fd967f   Steve French   [CIFS] fix busy-...
1485
1486
  	char *fromName = NULL;
  	char *toName = NULL;
639e7a913   Jeff Layton   cifs: eliminate r...
1487
  	struct cifs_sb_info *cifs_sb;
7ffec3724   Jeff Layton   cifs: add refcoun...
1488
  	struct tcon_link *tlink;
96daf2b09   Steve French   [CIFS] Rename thr...
1489
  	struct cifs_tcon *tcon;
ee2fd967f   Steve French   [CIFS] fix busy-...
1490
1491
  	FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
  	FILE_UNIX_BASIC_INFO *info_buf_target;
8d281efb6   Jeff Layton   cifs: fix unlinki...
1492
  	int xid, rc, tmprc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1493

639e7a913   Jeff Layton   cifs: eliminate r...
1494
  	cifs_sb = CIFS_SB(source_dir->i_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
1495
1496
1497
1498
  	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
1499

ee2fd967f   Steve French   [CIFS] fix busy-...
1500
1501
1502
  	xid = GetXid();
  
  	/*
ee2fd967f   Steve French   [CIFS] fix busy-...
1503
1504
1505
  	 * we already have the rename sem so we do not need to
  	 * grab it again here to protect the path integrity
  	 */
14121bdcc   Jeff Layton   cifs: make cifs_r...
1506
  	fromName = build_path_from_dentry(source_dentry);
ee2fd967f   Steve French   [CIFS] fix busy-...
1507
1508
1509
1510
  	if (fromName == NULL) {
  		rc = -ENOMEM;
  		goto cifs_rename_exit;
  	}
14121bdcc   Jeff Layton   cifs: make cifs_r...
1511
  	toName = build_path_from_dentry(target_dentry);
ee2fd967f   Steve French   [CIFS] fix busy-...
1512
  	if (toName == NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1513
1514
1515
  		rc = -ENOMEM;
  		goto cifs_rename_exit;
  	}
14121bdcc   Jeff Layton   cifs: make cifs_r...
1516
1517
  	rc = cifs_do_rename(xid, source_dentry, fromName,
  			    target_dentry, toName);
ee2fd967f   Steve French   [CIFS] fix busy-...
1518

14121bdcc   Jeff Layton   cifs: make cifs_r...
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
  	if (rc == -EEXIST && tcon->unix_ext) {
  		/*
  		 * Are src and dst hardlinks of same inode? We can
  		 * only tell with unix extensions enabled
  		 */
  		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;
8d281efb6   Jeff Layton   cifs: fix unlinki...
1533
  		tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName,
14121bdcc   Jeff Layton   cifs: make cifs_r...
1534
  					info_buf_source,
639e7a913   Jeff Layton   cifs: eliminate r...
1535
1536
  					cifs_sb->local_nls,
  					cifs_sb->mnt_cifs_flags &
14121bdcc   Jeff Layton   cifs: make cifs_r...
1537
  					CIFS_MOUNT_MAP_SPECIAL_CHR);
8d281efb6   Jeff Layton   cifs: fix unlinki...
1538
  		if (tmprc != 0)
14121bdcc   Jeff Layton   cifs: make cifs_r...
1539
  			goto unlink_target;
ee2fd967f   Steve French   [CIFS] fix busy-...
1540

639e7a913   Jeff Layton   cifs: eliminate r...
1541
1542
1543
1544
  		tmprc = CIFSSMBUnixQPathInfo(xid, tcon, toName,
  					info_buf_target,
  					cifs_sb->local_nls,
  					cifs_sb->mnt_cifs_flags &
14121bdcc   Jeff Layton   cifs: make cifs_r...
1545
  					CIFS_MOUNT_MAP_SPECIAL_CHR);
8d281efb6   Jeff Layton   cifs: fix unlinki...
1546
  		if (tmprc == 0 && (info_buf_source->UniqueId ==
ae6884a9d   Jeff Layton   cifs: fix renamin...
1547
  				   info_buf_target->UniqueId)) {
14121bdcc   Jeff Layton   cifs: make cifs_r...
1548
  			/* same file, POSIX says that this is a noop */
ae6884a9d   Jeff Layton   cifs: fix renamin...
1549
  			rc = 0;
14121bdcc   Jeff Layton   cifs: make cifs_r...
1550
  			goto cifs_rename_exit;
ae6884a9d   Jeff Layton   cifs: fix renamin...
1551
  		}
14121bdcc   Jeff Layton   cifs: make cifs_r...
1552
  	} /* else ... BB we could add the same check for Windows by
ee2fd967f   Steve French   [CIFS] fix busy-...
1553
  		     checking the UniqueId via FILE_INTERNAL_INFO */
14121bdcc   Jeff Layton   cifs: make cifs_r...
1554

ee2fd967f   Steve French   [CIFS] fix busy-...
1555
  unlink_target:
fc6f39433   Jeff Layton   cifs: when renami...
1556
1557
  	/* Try unlinking the target dentry if it's not negative */
  	if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
8d281efb6   Jeff Layton   cifs: fix unlinki...
1558
  		tmprc = cifs_unlink(target_dir, target_dentry);
14121bdcc   Jeff Layton   cifs: make cifs_r...
1559
1560
  		if (tmprc)
  			goto cifs_rename_exit;
14121bdcc   Jeff Layton   cifs: make cifs_r...
1561
1562
  		rc = cifs_do_rename(xid, source_dentry, fromName,
  				    target_dentry, toName);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1563
1564
1565
  	}
  
  cifs_rename_exit:
ee2fd967f   Steve French   [CIFS] fix busy-...
1566
  	kfree(info_buf_source);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1567
1568
1569
  	kfree(fromName);
  	kfree(toName);
  	FreeXid(xid);
7ffec3724   Jeff Layton   cifs: add refcoun...
1570
  	cifs_put_tlink(tlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1571
1572
  	return rc;
  }
df2cf170c   Jeff Layton   cifs: overhaul ci...
1573
1574
  static bool
  cifs_inode_needs_reval(struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1575
  {
df2cf170c   Jeff Layton   cifs: overhaul ci...
1576
  	struct cifsInodeInfo *cifs_i = CIFS_I(inode);
6d20e8406   Suresh Jayaraman   cifs: add attribu...
1577
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1578

df2cf170c   Jeff Layton   cifs: overhaul ci...
1579
1580
  	if (cifs_i->clientCanCacheRead)
  		return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1581

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

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

6d20e8406   Suresh Jayaraman   cifs: add attribu...
1588
1589
  	if (!time_in_range(jiffies, cifs_i->time,
  				cifs_i->time + cifs_sb->actimeo))
df2cf170c   Jeff Layton   cifs: overhaul ci...
1590
  		return true;
db19272ed   Jeff Layton   cifs: always reva...
1591
  	/* hardlinked files w/ noserverino get "special" treatment */
6d20e8406   Suresh Jayaraman   cifs: add attribu...
1592
  	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
db19272ed   Jeff Layton   cifs: always reva...
1593
1594
  	    S_ISREG(inode->i_mode) && inode->i_nlink != 1)
  		return true;
df2cf170c   Jeff Layton   cifs: overhaul ci...
1595
1596
  	return false;
  }
523fb8c86   Suresh Jayaraman   cifs: trivial com...
1597
1598
1599
  /*
   * Zap the cache. Called when invalid_mapping flag is set.
   */
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1600
  int
df2cf170c   Jeff Layton   cifs: overhaul ci...
1601
1602
  cifs_invalidate_mapping(struct inode *inode)
  {
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1603
  	int rc = 0;
df2cf170c   Jeff Layton   cifs: overhaul ci...
1604
1605
1606
  	struct cifsInodeInfo *cifs_i = CIFS_I(inode);
  
  	cifs_i->invalid_mapping = false;
df2cf170c   Jeff Layton   cifs: overhaul ci...
1607
  	if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
257fb1f15   Pavel Shilovsky   CIFS: Use invalid...
1608
1609
1610
1611
1612
1613
  		rc = invalidate_inode_pages2(inode->i_mapping);
  		if (rc) {
  			cERROR(1, "%s: could not invalidate inode %p", __func__,
  			       inode);
  			cifs_i->invalid_mapping = true;
  		}
df2cf170c   Jeff Layton   cifs: overhaul ci...
1614
  	}
257fb1f15   Pavel Shilovsky   CIFS: Use invalid...
1615

9451a9a52   Suresh Jayaraman   cifs: define inod...
1616
  	cifs_fscache_reset_inode_cookie(inode);
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1617
  	return rc;
df2cf170c   Jeff Layton   cifs: overhaul ci...
1618
  }
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1619
  int cifs_revalidate_file_attr(struct file *filp)
abab095d1   Jeff Layton   cifs: add cifs_re...
1620
1621
1622
  {
  	int rc = 0;
  	struct inode *inode = filp->f_path.dentry->d_inode;
ba00ba64c   Jeff Layton   cifs: make variou...
1623
  	struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
abab095d1   Jeff Layton   cifs: add cifs_re...
1624
1625
  
  	if (!cifs_inode_needs_reval(inode))
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1626
  		return rc;
abab095d1   Jeff Layton   cifs: add cifs_re...
1627

13cfb7334   Jeff Layton   cifs: have cifsFi...
1628
  	if (tlink_tcon(cfile->tlink)->unix_ext)
abab095d1   Jeff Layton   cifs: add cifs_re...
1629
1630
1631
  		rc = cifs_get_file_info_unix(filp);
  	else
  		rc = cifs_get_file_info(filp);
abab095d1   Jeff Layton   cifs: add cifs_re...
1632
1633
  	return rc;
  }
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1634
  int cifs_revalidate_dentry_attr(struct dentry *dentry)
df2cf170c   Jeff Layton   cifs: overhaul ci...
1635
1636
1637
  {
  	int xid;
  	int rc = 0;
df2cf170c   Jeff Layton   cifs: overhaul ci...
1638
1639
  	struct inode *inode = dentry->d_inode;
  	struct super_block *sb = dentry->d_sb;
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1640
  	char *full_path = NULL;
df2cf170c   Jeff Layton   cifs: overhaul ci...
1641
1642
1643
  
  	if (inode == NULL)
  		return -ENOENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1644

df2cf170c   Jeff Layton   cifs: overhaul ci...
1645
  	if (!cifs_inode_needs_reval(inode))
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1646
1647
1648
  		return rc;
  
  	xid = GetXid();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1649
1650
1651
  
  	/* can not safely grab the rename sem here if rename calls revalidate
  	   since that would deadlock */
df2cf170c   Jeff Layton   cifs: overhaul ci...
1652
  	full_path = build_path_from_dentry(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1653
  	if (full_path == NULL) {
0f3bc09ee   Suresh Jayaraman   cifs: Fix incorre...
1654
  		rc = -ENOMEM;
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1655
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1656
  	}
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1657
1658
  	cFYI(1, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time "
  		 "%ld jiffies %ld", full_path, inode, inode->i_count.counter,
f19159dc5   Steve French   [CIFS] Cleanup va...
1659
  		 dentry, dentry->d_time, jiffies);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1660

0d424ad0a   Jeff Layton   cifs: add cifs_sb...
1661
  	if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
df2cf170c   Jeff Layton   cifs: overhaul ci...
1662
1663
1664
1665
  		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
1666

6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1667
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1668
1669
1670
1671
  	kfree(full_path);
  	FreeXid(xid);
  	return rc;
  }
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
  int cifs_revalidate_file(struct file *filp)
  {
  	int rc;
  	struct inode *inode = filp->f_path.dentry->d_inode;
  
  	rc = cifs_revalidate_file_attr(filp);
  	if (rc)
  		return rc;
  
  	if (CIFS_I(inode)->invalid_mapping)
  		rc = cifs_invalidate_mapping(inode);
  	return rc;
  }
  
  /* revalidate a dentry's inode attributes */
  int cifs_revalidate_dentry(struct dentry *dentry)
  {
  	int rc;
  	struct inode *inode = dentry->d_inode;
  
  	rc = cifs_revalidate_dentry_attr(dentry);
  	if (rc)
  		return rc;
  
  	if (CIFS_I(inode)->invalid_mapping)
  		rc = cifs_invalidate_mapping(inode);
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1700
  int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
1c456013e   Jeff Layton   cifs: on multiuse...
1701
  		 struct kstat *stat)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1702
  {
3aa1c8c29   Jeff Layton   cifs: on multiuse...
1703
  	struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
96daf2b09   Steve French   [CIFS] Rename thr...
1704
  	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1705
1706
  	struct inode *inode = dentry->d_inode;
  	int rc;
3aa1c8c29   Jeff Layton   cifs: on multiuse...
1707

6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1708
1709
1710
1711
1712
1713
1714
  	/*
  	 * We need to be sure that all dirty pages are written and the server
  	 * has actual ctime, mtime and file length.
  	 */
  	if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping &&
  	    inode->i_mapping->nrpages != 0) {
  		rc = filemap_fdatawait(inode->i_mapping);
156ecb2d8   Steve French   [CIFS] Fix to pro...
1715
1716
1717
1718
  		if (rc) {
  			mapping_set_error(inode->i_mapping, rc);
  			return rc;
  		}
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1719
  	}
1c456013e   Jeff Layton   cifs: on multiuse...
1720

6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
  	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;
  
  	/*
  	 * If on a multiuser mount without unix extensions, and the admin hasn't
  	 * overridden them, set the ownership to the fsuid/fsgid of the current
  	 * process.
  	 */
  	if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
  	    !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...
1740
  	}
6feb9891d   Pavel Shilovsky   CIFS: Simplify in...
1741
  	return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1742
1743
1744
1745
1746
1747
1748
  }
  
  static int cifs_truncate_page(struct address_space *mapping, loff_t from)
  {
  	pgoff_t index = from >> PAGE_CACHE_SHIFT;
  	unsigned offset = from & (PAGE_CACHE_SIZE - 1);
  	struct page *page;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1749
1750
1751
1752
1753
  	int rc = 0;
  
  	page = grab_cache_page(mapping, index);
  	if (!page)
  		return -ENOMEM;
eebd2aa35   Christoph Lameter   Pagecache zeroing...
1754
  	zero_user_segment(page, offset, PAGE_CACHE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1755
1756
1757
1758
  	unlock_page(page);
  	page_cache_release(page);
  	return rc;
  }
1b9474635   Christoph Hellwig   cifs: truncate fa...
1759
  static void cifs_setsize(struct inode *inode, loff_t offset)
3677db10a   Steve French   [CIFS] Fix lockin...
1760
  {
c08d3b0e3   npiggin@suse.de   truncate: use new...
1761
  	loff_t oldsize;
3677db10a   Steve French   [CIFS] Fix lockin...
1762

ba6a46a03   Steve French   [CIFS] small piec...
1763
  	spin_lock(&inode->i_lock);
c08d3b0e3   npiggin@suse.de   truncate: use new...
1764
  	oldsize = inode->i_size;
3677db10a   Steve French   [CIFS] Fix lockin...
1765
  	i_size_write(inode, offset);
ba6a46a03   Steve French   [CIFS] small piec...
1766
  	spin_unlock(&inode->i_lock);
1b9474635   Christoph Hellwig   cifs: truncate fa...
1767

c08d3b0e3   npiggin@suse.de   truncate: use new...
1768
  	truncate_pagecache(inode, oldsize, offset);
3677db10a   Steve French   [CIFS] Fix lockin...
1769
  }
8efdbde64   Jeff Layton   [CIFS] break ATTR...
1770
1771
1772
1773
1774
1775
1776
1777
  static int
  cifs_set_file_size(struct inode *inode, struct iattr *attrs,
  		   int xid, char *full_path)
  {
  	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...
1778
  	struct tcon_link *tlink = NULL;
96daf2b09   Steve French   [CIFS] Rename thr...
1779
  	struct cifs_tcon *pTcon = NULL;
fa2989f44   Pavel Shilovsky   CIFS: Use pid sav...
1780
  	struct cifs_io_parms io_parms;
8efdbde64   Jeff Layton   [CIFS] break ATTR...
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
  
  	/*
  	 * 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...
1791
  	open_file = find_writable_file(cifsInode, true);
8efdbde64   Jeff Layton   [CIFS] break ATTR...
1792
1793
1794
  	if (open_file) {
  		__u16 nfid = open_file->netfid;
  		__u32 npid = open_file->pid;
13cfb7334   Jeff Layton   cifs: have cifsFi...
1795
  		pTcon = tlink_tcon(open_file->tlink);
8efdbde64   Jeff Layton   [CIFS] break ATTR...
1796
1797
  		rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid,
  					npid, false);
6ab409b53   Dave Kleikamp   cifs: Replace wrt...
1798
  		cifsFileInfo_put(open_file);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1799
  		cFYI(1, "SetFSize for attrs rc = %d", rc);
8efdbde64   Jeff Layton   [CIFS] break ATTR...
1800
1801
  		if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
  			unsigned int bytes_written;
fa2989f44   Pavel Shilovsky   CIFS: Use pid sav...
1802
1803
1804
1805
1806
1807
1808
1809
  
  			io_parms.netfid = nfid;
  			io_parms.pid = npid;
  			io_parms.tcon = pTcon;
  			io_parms.offset = 0;
  			io_parms.length = attrs->ia_size;
  			rc = CIFSSMBWrite(xid, &io_parms, &bytes_written,
  					  NULL, NULL, 1);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1810
  			cFYI(1, "Wrt seteof rc %d", rc);
8efdbde64   Jeff Layton   [CIFS] break ATTR...
1811
1812
1813
1814
1815
  		}
  	} else
  		rc = -EINVAL;
  
  	if (rc != 0) {
7ffec3724   Jeff Layton   cifs: add refcoun...
1816
1817
1818
1819
1820
1821
  		if (pTcon == NULL) {
  			tlink = cifs_sb_tlink(cifs_sb);
  			if (IS_ERR(tlink))
  				return PTR_ERR(tlink);
  			pTcon = tlink_tcon(tlink);
  		}
ba00ba64c   Jeff Layton   cifs: make variou...
1822

8efdbde64   Jeff Layton   [CIFS] break ATTR...
1823
1824
1825
1826
1827
1828
1829
1830
  		/* 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 */
  		rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,
  				   false, cifs_sb->local_nls,
  				   cifs_sb->mnt_cifs_flags &
  					CIFS_MOUNT_MAP_SPECIAL_CHR);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1831
  		cFYI(1, "SetEOF by path (setattrs) rc = %d", rc);
8efdbde64   Jeff Layton   [CIFS] break ATTR...
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
  		if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
  			__u16 netfid;
  			int oplock = 0;
  
  			rc = SMBLegacyOpen(xid, pTcon, full_path,
  				FILE_OPEN, GENERIC_WRITE,
  				CREATE_NOT_DIR, &netfid, &oplock, NULL,
  				cifs_sb->local_nls,
  				cifs_sb->mnt_cifs_flags &
  					CIFS_MOUNT_MAP_SPECIAL_CHR);
  			if (rc == 0) {
  				unsigned int bytes_written;
fa2989f44   Pavel Shilovsky   CIFS: Use pid sav...
1844
1845
1846
1847
1848
1849
1850
1851
1852
  
  				io_parms.netfid = netfid;
  				io_parms.pid = current->tgid;
  				io_parms.tcon = pTcon;
  				io_parms.offset = 0;
  				io_parms.length = attrs->ia_size;
  				rc = CIFSSMBWrite(xid, &io_parms,
  						  &bytes_written,
  						  NULL, NULL,  1);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1853
  				cFYI(1, "wrt seteof rc %d", rc);
8efdbde64   Jeff Layton   [CIFS] break ATTR...
1854
1855
1856
  				CIFSSMBClose(xid, pTcon, netfid);
  			}
  		}
7ffec3724   Jeff Layton   cifs: add refcoun...
1857
1858
  		if (tlink)
  			cifs_put_tlink(tlink);
8efdbde64   Jeff Layton   [CIFS] break ATTR...
1859
1860
1861
  	}
  
  	if (rc == 0) {
fbec9ab95   Jeff Layton   cifs: vary timeou...
1862
  		cifsInode->server_eof = attrs->ia_size;
1b9474635   Christoph Hellwig   cifs: truncate fa...
1863
  		cifs_setsize(inode, attrs->ia_size);
8efdbde64   Jeff Layton   [CIFS] break ATTR...
1864
1865
1866
1867
1868
  		cifs_truncate_page(inode->i_mapping, inode->i_size);
  	}
  
  	return rc;
  }
3fe5c1dd0   Jeff Layton   spin off cifs_set...
1869
1870
1871
1872
1873
1874
1875
1876
1877
  static int
  cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
  {
  	int rc;
  	int xid;
  	char *full_path = NULL;
  	struct inode *inode = direntry->d_inode;
  	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
7ffec3724   Jeff Layton   cifs: add refcoun...
1878
  	struct tcon_link *tlink;
96daf2b09   Steve French   [CIFS] Rename thr...
1879
  	struct cifs_tcon *pTcon;
3fe5c1dd0   Jeff Layton   spin off cifs_set...
1880
  	struct cifs_unix_set_info_args *args = NULL;
3bbeeb3c9   Jeff Layton   cifs: add and use...
1881
  	struct cifsFileInfo *open_file;
3fe5c1dd0   Jeff Layton   spin off cifs_set...
1882

b6b38f704   Joe Perches   [CIFS] Neaten cER...
1883
1884
  	cFYI(1, "setattr_unix on file %s attrs->ia_valid=0x%x",
  		 direntry->d_name.name, attrs->ia_valid);
3fe5c1dd0   Jeff Layton   spin off cifs_set...
1885
1886
  
  	xid = GetXid();
db78b877f   Christoph Hellwig   always call inode...
1887
1888
1889
1890
1891
1892
  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
  		attrs->ia_valid |= ATTR_FORCE;
  
  	rc = inode_change_ok(inode, attrs);
  	if (rc < 0)
  		goto out;
3fe5c1dd0   Jeff Layton   spin off cifs_set...
1893
1894
1895
1896
1897
1898
  
  	full_path = build_path_from_dentry(direntry);
  	if (full_path == NULL) {
  		rc = -ENOMEM;
  		goto out;
  	}
0f4d634c5   Jeff Layton   cifs: flush data ...
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
  	/*
  	 * 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...
1911
1912
  	mapping_set_error(inode->i_mapping, rc);
  	rc = 0;
3fe5c1dd0   Jeff Layton   spin off cifs_set...
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
  
  	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
  		args->uid = NO_CHANGE_64;
  
  	if (attrs->ia_valid & ATTR_GID)
  		args->gid = attrs->ia_gid;
  	else
  		args->gid = NO_CHANGE_64;
  
  	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...
1962
  	open_file = find_writable_file(cifsInode, true);
3bbeeb3c9   Jeff Layton   cifs: add and use...
1963
1964
1965
  	if (open_file) {
  		u16 nfid = open_file->netfid;
  		u32 npid = open_file->pid;
13cfb7334   Jeff Layton   cifs: have cifsFi...
1966
  		pTcon = tlink_tcon(open_file->tlink);
3bbeeb3c9   Jeff Layton   cifs: add and use...
1967
  		rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
6ab409b53   Dave Kleikamp   cifs: Replace wrt...
1968
  		cifsFileInfo_put(open_file);
3bbeeb3c9   Jeff Layton   cifs: add and use...
1969
  	} else {
7ffec3724   Jeff Layton   cifs: add refcoun...
1970
1971
1972
1973
1974
1975
  		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...
1976
  		rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
01ea95e3b   Jeff Layton   cifs: rename CIFS...
1977
1978
1979
  				    cifs_sb->local_nls,
  				    cifs_sb->mnt_cifs_flags &
  					CIFS_MOUNT_MAP_SPECIAL_CHR);
7ffec3724   Jeff Layton   cifs: add refcoun...
1980
  		cifs_put_tlink(tlink);
3bbeeb3c9   Jeff Layton   cifs: add and use...
1981
  	}
3fe5c1dd0   Jeff Layton   spin off cifs_set...
1982

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

1025774ce   Christoph Hellwig   remove inode_setattr
1986
  	if ((attrs->ia_valid & ATTR_SIZE) &&
1b9474635   Christoph Hellwig   cifs: truncate fa...
1987
1988
  	    attrs->ia_size != i_size_read(inode))
  		truncate_setsize(inode, attrs->ia_size);
1025774ce   Christoph Hellwig   remove inode_setattr
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
  
  	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...
2001
2002
2003
2004
2005
2006
  out:
  	kfree(args);
  	kfree(full_path);
  	FreeXid(xid);
  	return rc;
  }
0510eeb73   Jeff Layton   turn cifs_setattr...
2007
2008
  static int
  cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2009
2010
  {
  	int xid;
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
2011
2012
  	uid_t uid = NO_CHANGE_32;
  	gid_t gid = NO_CHANGE_32;
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2013
2014
  	struct inode *inode = direntry->d_inode;
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2015
  	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2016
2017
  	char *full_path = NULL;
  	int rc = -EACCES;
feb3e20ce   Jeff Layton   move file time an...
2018
  	__u32 dosattr = 0;
4e1e7fb9e   Jeff Layton   bundle up Unix SE...
2019
  	__u64 mode = NO_CHANGE_64;
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2020

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2021
  	xid = GetXid();
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2022
2023
  	cFYI(1, "setattr on file %s attrs->iavalid 0x%x",
  		 direntry->d_name.name, attrs->ia_valid);
6473a559c   Steve French   [CIFS] Fix missin...
2024

db78b877f   Christoph Hellwig   always call inode...
2025
2026
2027
2028
2029
2030
2031
  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
  		attrs->ia_valid |= ATTR_FORCE;
  
  	rc = inode_change_ok(inode, attrs);
  	if (rc < 0) {
  		FreeXid(xid);
  		return rc;
6473a559c   Steve French   [CIFS] Fix missin...
2032
  	}
50c2f7538   Steve French   [CIFS] whitespace...
2033

7f57356b7   Steve French   [CIFS] Remove cif...
2034
  	full_path = build_path_from_dentry(direntry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2035
  	if (full_path == NULL) {
0f3bc09ee   Suresh Jayaraman   cifs: Fix incorre...
2036
  		rc = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2037
  		FreeXid(xid);
0f3bc09ee   Suresh Jayaraman   cifs: Fix incorre...
2038
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2039
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2040

0f4d634c5   Jeff Layton   cifs: flush data ...
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
  	/*
  	 * 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...
2053
2054
  	mapping_set_error(inode->i_mapping, rc);
  	rc = 0;
cea218054   Jeff Layton   [CIFS] Fix potent...
2055

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

a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
  	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) {
  		if (uid != NO_CHANGE_32 || gid != NO_CHANGE_32) {
  			rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
  							uid, gid);
  			if (rc) {
  				cFYI(1, "%s: Setting id failed with error: %d",
  					__func__, rc);
  				goto cifs_setattr_exit;
  			}
  		}
  	} else
  #endif /* CONFIG_CIFS_ACL */
3fe5c1dd0   Jeff Layton   spin off cifs_set...
2081
  	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
4ca691a89   Jeff Layton   silently ignore o...
2082
  		attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2083

d32c4f262   Jeff Layton   CIFS: ignore mode...
2084
2085
2086
  	/* 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
2087
  	if (attrs->ia_valid & ATTR_MODE) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2088
  		mode = attrs->ia_mode;
cdbce9c87   Steve French   [CIFS] Fix setatt...
2089
  		rc = 0;
79df1baee   Jeff Layton   cifs: fix use of ...
2090
  #ifdef CONFIG_CIFS_ACL
78415d2d3   Shirish Pargaonkar   cifs: Misc. clean...
2091
  		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
a5ff37696   Shirish Pargaonkar   cifs: Call id to ...
2092
2093
  			rc = id_mode_to_cifs_acl(inode, full_path, mode,
  						NO_CHANGE_32, NO_CHANGE_32);
78415d2d3   Shirish Pargaonkar   cifs: Misc. clean...
2094
2095
2096
2097
2098
2099
  			if (rc) {
  				cFYI(1, "%s: Setting ACL failed with error: %d",
  					__func__, rc);
  				goto cifs_setattr_exit;
  			}
  		} else
79df1baee   Jeff Layton   cifs: fix use of ...
2100
  #endif /* CONFIG_CIFS_ACL */
5132861a7   Jeff Layton   disable most mode...
2101
2102
  		if (((mode & S_IWUGO) == 0) &&
  		    (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
feb3e20ce   Jeff Layton   move file time an...
2103
2104
  
  			dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
5132861a7   Jeff Layton   disable most mode...
2105
2106
2107
2108
2109
  			/* 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...
2110
2111
2112
2113
2114
  
  			dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
  			/* Attributes of 0 are ignored */
  			if (dosattr == 0)
  				dosattr |= ATTR_NORMAL;
5132861a7   Jeff Layton   disable most mode...
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
  
  			/* 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
2129
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2130
  	}
feb3e20ce   Jeff Layton   move file time an...
2131
2132
2133
2134
  	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
2135

e30dcf3a1   Steve French   [CIFS] Add suppor...
2136
2137
2138
2139
2140
  		/* 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...
2141
  		if ((rc) && (attrs->ia_valid &
feb3e20ce   Jeff Layton   move file time an...
2142
  				(ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
e30dcf3a1   Steve French   [CIFS] Add suppor...
2143
  			rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2144
2145
2146
2147
  	}
  
  	/* do not need local check to inode_check_ok since the server does
  	   that */
1025774ce   Christoph Hellwig   remove inode_setattr
2148
2149
2150
2151
  	if (rc)
  		goto cifs_setattr_exit;
  
  	if ((attrs->ia_valid & ATTR_SIZE) &&
1b9474635   Christoph Hellwig   cifs: truncate fa...
2152
2153
  	    attrs->ia_size != i_size_read(inode))
  		truncate_setsize(inode, attrs->ia_size);
1025774ce   Christoph Hellwig   remove inode_setattr
2154
2155
2156
  
  	setattr_copy(inode, attrs);
  	mark_inode_dirty(inode);
1025774ce   Christoph Hellwig   remove inode_setattr
2157

e30dcf3a1   Steve French   [CIFS] Add suppor...
2158
  cifs_setattr_exit:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2159
2160
2161
2162
  	kfree(full_path);
  	FreeXid(xid);
  	return rc;
  }
0510eeb73   Jeff Layton   turn cifs_setattr...
2163
2164
2165
2166
2167
  int
  cifs_setattr(struct dentry *direntry, struct iattr *attrs)
  {
  	struct inode *inode = direntry->d_inode;
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
96daf2b09   Steve French   [CIFS] Rename thr...
2168
  	struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
0510eeb73   Jeff Layton   turn cifs_setattr...
2169
2170
2171
2172
2173
2174
2175
2176
  
  	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...
2177
  #if 0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2178
2179
  void cifs_delete_inode(struct inode *inode)
  {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2180
  	cFYI(1, "In cifs_delete_inode, inode = 0x%p", inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2181
2182
2183
  	/* 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...
2184
  #endif