cifs: add a CIFSSMBUnixQFileInfo function
[deliverable/linux.git] / fs / cifs / inode.c
CommitLineData
1da177e4
LT
1/*
2 * fs/cifs/inode.c
3 *
8be0ed44 4 * Copyright (C) International Business Machines Corp., 2002,2008
1da177e4
LT
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <linux/fs.h>
1da177e4
LT
22#include <linux/stat.h>
23#include <linux/pagemap.h>
24#include <asm/div64.h>
25#include "cifsfs.h"
26#include "cifspdu.h"
27#include "cifsglob.h"
28#include "cifsproto.h"
29#include "cifs_debug.h"
30#include "cifs_fs_sb.h"
31
70eff55d 32
7962670e 33static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral)
70eff55d
CH
34{
35 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
36
37 switch (inode->i_mode & S_IFMT) {
38 case S_IFREG:
39 inode->i_op = &cifs_file_inode_ops;
40 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
41 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
42 inode->i_fop = &cifs_file_direct_nobrl_ops;
43 else
44 inode->i_fop = &cifs_file_direct_ops;
45 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
46 inode->i_fop = &cifs_file_nobrl_ops;
47 else { /* not direct, send byte range locks */
48 inode->i_fop = &cifs_file_ops;
49 }
50
51
52 /* check if server can support readpages */
53 if (cifs_sb->tcon->ses->server->maxBuf <
54 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
55 inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
56 else
57 inode->i_data.a_ops = &cifs_addr_ops;
58 break;
59 case S_IFDIR:
bc5b6e24 60#ifdef CONFIG_CIFS_DFS_UPCALL
7962670e
IM
61 if (is_dfs_referral) {
62 inode->i_op = &cifs_dfs_referral_inode_operations;
63 } else {
bc5b6e24
SF
64#else /* NO DFS support, treat as a directory */
65 {
66#endif
7962670e
IM
67 inode->i_op = &cifs_dir_inode_ops;
68 inode->i_fop = &cifs_dir_ops;
69 }
70eff55d
CH
70 break;
71 case S_IFLNK:
72 inode->i_op = &cifs_symlink_inode_ops;
73 break;
74 default:
75 init_special_inode(inode, inode->i_mode, inode->i_rdev);
76 break;
77 }
78}
79
df2cf170
JL
80/* check inode attributes against fattr. If they don't match, tag the
81 * inode for cache invalidation
82 */
83static void
84cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
85{
86 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
87
88 cFYI(1, ("%s: revalidating inode %llu", __func__, cifs_i->uniqueid));
89
90 if (inode->i_state & I_NEW) {
91 cFYI(1, ("%s: inode %llu is new", __func__, cifs_i->uniqueid));
92 return;
93 }
94
95 /* don't bother with revalidation if we have an oplock */
96 if (cifs_i->clientCanCacheRead) {
97 cFYI(1, ("%s: inode %llu is oplocked", __func__,
98 cifs_i->uniqueid));
99 return;
100 }
101
102 /* revalidate if mtime or size have changed */
103 if (timespec_equal(&inode->i_mtime, &fattr->cf_mtime) &&
104 cifs_i->server_eof == fattr->cf_eof) {
105 cFYI(1, ("%s: inode %llu is unchanged", __func__,
106 cifs_i->uniqueid));
107 return;
108 }
109
110 cFYI(1, ("%s: invalidating inode %llu mapping", __func__,
111 cifs_i->uniqueid));
112 cifs_i->invalid_mapping = true;
113}
114
cc0bad75
JL
115/* populate an inode with info from a cifs_fattr struct */
116void
117cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
75f12983 118{
cc0bad75 119 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
0b8f18e3
JL
120 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
121 unsigned long oldtime = cifs_i->time;
cc0bad75 122
df2cf170
JL
123 cifs_revalidate_cache(inode, fattr);
124
cc0bad75
JL
125 inode->i_atime = fattr->cf_atime;
126 inode->i_mtime = fattr->cf_mtime;
127 inode->i_ctime = fattr->cf_ctime;
cc0bad75
JL
128 inode->i_rdev = fattr->cf_rdev;
129 inode->i_nlink = fattr->cf_nlink;
130 inode->i_uid = fattr->cf_uid;
131 inode->i_gid = fattr->cf_gid;
132
0b8f18e3
JL
133 /* if dynperm is set, don't clobber existing mode */
134 if (inode->i_state & I_NEW ||
135 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
136 inode->i_mode = fattr->cf_mode;
137
cc0bad75
JL
138 cifs_i->cifsAttrs = fattr->cf_cifsattrs;
139 cifs_i->uniqueid = fattr->cf_uniqueid;
75f12983 140
0b8f18e3
JL
141 if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
142 cifs_i->time = 0;
143 else
144 cifs_i->time = jiffies;
145
cc0bad75 146 cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode,
0b8f18e3
JL
147 oldtime, cifs_i->time));
148
149 cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING;
cc0bad75 150
835a36ca 151 cifs_i->server_eof = fattr->cf_eof;
cc0bad75
JL
152 /*
153 * Can't safely change the file size here if the client is writing to
154 * it due to potential races.
155 */
156 spin_lock(&inode->i_lock);
157 if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
158 i_size_write(inode, fattr->cf_eof);
159
160 /*
161 * i_blocks is not related to (i_size / i_blksize),
162 * but instead 512 byte (2**9) size is required for
163 * calculating num blocks.
164 */
165 inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
166 }
167 spin_unlock(&inode->i_lock);
168
169 cifs_set_ops(inode, fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL);
170}
171
172/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
173void
174cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
175 struct cifs_sb_info *cifs_sb)
176{
177 memset(fattr, 0, sizeof(*fattr));
178 fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
179 fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
180 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
181
182 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
183 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
184 fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
185 fattr->cf_mode = le64_to_cpu(info->Permissions);
75f12983
CH
186
187 /*
188 * Since we set the inode type below we need to mask off
189 * to avoid strange results if bits set above.
190 */
cc0bad75 191 fattr->cf_mode &= ~S_IFMT;
75f12983
CH
192 switch (le32_to_cpu(info->Type)) {
193 case UNIX_FILE:
cc0bad75
JL
194 fattr->cf_mode |= S_IFREG;
195 fattr->cf_dtype = DT_REG;
75f12983
CH
196 break;
197 case UNIX_SYMLINK:
cc0bad75
JL
198 fattr->cf_mode |= S_IFLNK;
199 fattr->cf_dtype = DT_LNK;
75f12983
CH
200 break;
201 case UNIX_DIR:
cc0bad75
JL
202 fattr->cf_mode |= S_IFDIR;
203 fattr->cf_dtype = DT_DIR;
75f12983
CH
204 break;
205 case UNIX_CHARDEV:
cc0bad75
JL
206 fattr->cf_mode |= S_IFCHR;
207 fattr->cf_dtype = DT_CHR;
208 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
209 le64_to_cpu(info->DevMinor) & MINORMASK);
75f12983
CH
210 break;
211 case UNIX_BLOCKDEV:
cc0bad75
JL
212 fattr->cf_mode |= S_IFBLK;
213 fattr->cf_dtype = DT_BLK;
214 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
215 le64_to_cpu(info->DevMinor) & MINORMASK);
75f12983
CH
216 break;
217 case UNIX_FIFO:
cc0bad75
JL
218 fattr->cf_mode |= S_IFIFO;
219 fattr->cf_dtype = DT_FIFO;
75f12983
CH
220 break;
221 case UNIX_SOCKET:
cc0bad75
JL
222 fattr->cf_mode |= S_IFSOCK;
223 fattr->cf_dtype = DT_SOCK;
75f12983
CH
224 break;
225 default:
226 /* safest to call it a file if we do not know */
cc0bad75
JL
227 fattr->cf_mode |= S_IFREG;
228 fattr->cf_dtype = DT_REG;
75f12983
CH
229 cFYI(1, ("unknown type %d", le32_to_cpu(info->Type)));
230 break;
231 }
232
cc0bad75
JL
233 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
234 fattr->cf_uid = cifs_sb->mnt_uid;
75f12983 235 else
cc0bad75 236 fattr->cf_uid = le64_to_cpu(info->Uid);
75f12983 237
cc0bad75
JL
238 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
239 fattr->cf_gid = cifs_sb->mnt_gid;
75f12983 240 else
cc0bad75 241 fattr->cf_gid = le64_to_cpu(info->Gid);
75f12983 242
cc0bad75 243 fattr->cf_nlink = le64_to_cpu(info->Nlinks);
75f12983
CH
244}
245
b9a3260f 246/*
cc0bad75
JL
247 * Fill a cifs_fattr struct with fake inode info.
248 *
249 * Needed to setup cifs_fattr data for the directory which is the
250 * junction to the new submount (ie to setup the fake directory
251 * which represents a DFS referral).
b9a3260f 252 */
f1230c97 253static void
cc0bad75 254cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
0e4bbde9 255{
cc0bad75 256 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
0e4bbde9 257
cc0bad75
JL
258 cFYI(1, ("creating fake fattr for DFS referral"));
259
260 memset(fattr, 0, sizeof(*fattr));
261 fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
262 fattr->cf_uid = cifs_sb->mnt_uid;
263 fattr->cf_gid = cifs_sb->mnt_gid;
264 fattr->cf_atime = CURRENT_TIME;
265 fattr->cf_ctime = CURRENT_TIME;
266 fattr->cf_mtime = CURRENT_TIME;
267 fattr->cf_nlink = 2;
268 fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
0e4bbde9
SF
269}
270
1da177e4 271int cifs_get_inode_info_unix(struct inode **pinode,
cc0bad75
JL
272 const unsigned char *full_path,
273 struct super_block *sb, int xid)
1da177e4 274{
cc0bad75 275 int rc;
0e4bbde9 276 FILE_UNIX_BASIC_INFO find_data;
cc0bad75
JL
277 struct cifs_fattr fattr;
278 struct cifsTconInfo *tcon;
1da177e4 279 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1da177e4 280
cc0bad75 281 tcon = cifs_sb->tcon;
646dd539 282 cFYI(1, ("Getting info on %s", full_path));
7962670e 283
1da177e4 284 /* could have done a find first instead but this returns more info */
cc0bad75 285 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
737b758c
SF
286 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
287 CIFS_MOUNT_MAP_SPECIAL_CHR);
e911d0cc 288
cc0bad75
JL
289 if (!rc) {
290 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
291 } else if (rc == -EREMOTE) {
292 cifs_create_dfs_fattr(&fattr, sb);
293 rc = 0;
294 } else {
295 return rc;
296 }
1da177e4 297
0e4bbde9 298 if (*pinode == NULL) {
cc0bad75
JL
299 /* get new inode */
300 *pinode = cifs_iget(sb, &fattr);
301 if (!*pinode)
0e4bbde9 302 rc = -ENOMEM;
cc0bad75
JL
303 } else {
304 /* we already have inode, update it */
305 cifs_fattr_to_inode(*pinode, &fattr);
0e4bbde9 306 }
1da177e4 307
1da177e4
LT
308 return rc;
309}
310
0b8f18e3
JL
311static int
312cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
313 struct cifs_sb_info *cifs_sb, int xid)
d6e2f2a4
SF
314{
315 int rc;
4b18f2a9 316 int oplock = 0;
d6e2f2a4
SF
317 __u16 netfid;
318 struct cifsTconInfo *pTcon = cifs_sb->tcon;
86c96b4b 319 char buf[24];
d6e2f2a4 320 unsigned int bytes_read;
fb8c4b14 321 char *pbuf;
d6e2f2a4
SF
322
323 pbuf = buf;
324
0b8f18e3
JL
325 fattr->cf_mode &= ~S_IFMT;
326
327 if (fattr->cf_eof == 0) {
328 fattr->cf_mode |= S_IFIFO;
329 fattr->cf_dtype = DT_FIFO;
d6e2f2a4 330 return 0;
0b8f18e3
JL
331 } else if (fattr->cf_eof < 8) {
332 fattr->cf_mode |= S_IFREG;
333 fattr->cf_dtype = DT_REG;
d6e2f2a4
SF
334 return -EINVAL; /* EOPNOTSUPP? */
335 }
50c2f753 336
d6e2f2a4
SF
337 rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
338 CREATE_NOT_DIR, &netfid, &oplock, NULL,
339 cifs_sb->local_nls,
340 cifs_sb->mnt_cifs_flags &
341 CIFS_MOUNT_MAP_SPECIAL_CHR);
fb8c4b14 342 if (rc == 0) {
ec637e3f 343 int buf_type = CIFS_NO_BUFFER;
d6e2f2a4 344 /* Read header */
0b8f18e3 345 rc = CIFSSMBRead(xid, pTcon, netfid,
86c96b4b 346 24 /* length */, 0 /* offset */,
ec637e3f 347 &bytes_read, &pbuf, &buf_type);
4523cc30
SF
348 if ((rc == 0) && (bytes_read >= 8)) {
349 if (memcmp("IntxBLK", pbuf, 8) == 0) {
fb8c4b14 350 cFYI(1, ("Block device"));
0b8f18e3
JL
351 fattr->cf_mode |= S_IFBLK;
352 fattr->cf_dtype = DT_BLK;
4523cc30 353 if (bytes_read == 24) {
86c96b4b
SF
354 /* we have enough to decode dev num */
355 __u64 mjr; /* major */
356 __u64 mnr; /* minor */
357 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
358 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
0b8f18e3 359 fattr->cf_rdev = MKDEV(mjr, mnr);
86c96b4b 360 }
4523cc30 361 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
fb8c4b14 362 cFYI(1, ("Char device"));
0b8f18e3
JL
363 fattr->cf_mode |= S_IFCHR;
364 fattr->cf_dtype = DT_CHR;
4523cc30 365 if (bytes_read == 24) {
86c96b4b
SF
366 /* we have enough to decode dev num */
367 __u64 mjr; /* major */
368 __u64 mnr; /* minor */
369 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
370 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
0b8f18e3 371 fattr->cf_rdev = MKDEV(mjr, mnr);
fb8c4b14 372 }
4523cc30 373 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
fb8c4b14 374 cFYI(1, ("Symlink"));
0b8f18e3
JL
375 fattr->cf_mode |= S_IFLNK;
376 fattr->cf_dtype = DT_LNK;
86c96b4b 377 } else {
0b8f18e3
JL
378 fattr->cf_mode |= S_IFREG; /* file? */
379 fattr->cf_dtype = DT_REG;
fb8c4b14 380 rc = -EOPNOTSUPP;
86c96b4b 381 }
3020a1f5 382 } else {
0b8f18e3
JL
383 fattr->cf_mode |= S_IFREG; /* then it is a file */
384 fattr->cf_dtype = DT_REG;
fb8c4b14
SF
385 rc = -EOPNOTSUPP; /* or some unknown SFU type */
386 }
d6e2f2a4 387 CIFSSMBClose(xid, pTcon, netfid);
d6e2f2a4
SF
388 }
389 return rc;
d6e2f2a4
SF
390}
391
9e294f1c
SF
392#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
393
0b8f18e3
JL
394/*
395 * Fetch mode bits as provided by SFU.
396 *
397 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
398 */
399static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
400 struct cifs_sb_info *cifs_sb, int xid)
9e294f1c 401{
3020a1f5 402#ifdef CONFIG_CIFS_XATTR
9e294f1c
SF
403 ssize_t rc;
404 char ea_value[4];
405 __u32 mode;
406
31c0519f 407 rc = CIFSSMBQAllEAs(xid, cifs_sb->tcon, path, "SETFILEBITS",
0b8f18e3
JL
408 ea_value, 4 /* size of buf */, cifs_sb->local_nls,
409 cifs_sb->mnt_cifs_flags &
410 CIFS_MOUNT_MAP_SPECIAL_CHR);
4523cc30 411 if (rc < 0)
9e294f1c
SF
412 return (int)rc;
413 else if (rc > 3) {
414 mode = le32_to_cpu(*((__le32 *)ea_value));
0b8f18e3
JL
415 fattr->cf_mode &= ~SFBITS_MASK;
416 cFYI(1, ("special bits 0%o org mode 0%o", mode,
417 fattr->cf_mode));
418 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
fb8c4b14 419 cFYI(1, ("special mode bits 0%o", mode));
9e294f1c 420 }
0b8f18e3
JL
421
422 return 0;
3020a1f5
SF
423#else
424 return -EOPNOTSUPP;
425#endif
9e294f1c
SF
426}
427
0b8f18e3 428/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
f1230c97 429static void
0b8f18e3
JL
430cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
431 struct cifs_sb_info *cifs_sb, bool adjust_tz)
b9a3260f 432{
0b8f18e3
JL
433 memset(fattr, 0, sizeof(*fattr));
434 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
435 if (info->DeletePending)
436 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
437
438 if (info->LastAccessTime)
439 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
440 else
441 fattr->cf_atime = CURRENT_TIME;
442
443 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
444 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
445
446 if (adjust_tz) {
447 fattr->cf_ctime.tv_sec += cifs_sb->tcon->ses->server->timeAdj;
448 fattr->cf_mtime.tv_sec += cifs_sb->tcon->ses->server->timeAdj;
449 }
450
451 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
452 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
453
454 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
455 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
456 fattr->cf_dtype = DT_DIR;
457 } else {
458 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
459 fattr->cf_dtype = DT_REG;
0b8f18e3 460
d0c280d2
JL
461 /* clear write bits if ATTR_READONLY is set */
462 if (fattr->cf_cifsattrs & ATTR_READONLY)
463 fattr->cf_mode &= ~(S_IWUGO);
464 }
0b8f18e3
JL
465
466 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
467
468 fattr->cf_uid = cifs_sb->mnt_uid;
469 fattr->cf_gid = cifs_sb->mnt_gid;
b9a3260f
SF
470}
471
1da177e4 472int cifs_get_inode_info(struct inode **pinode,
646dd539 473 const unsigned char *full_path, FILE_ALL_INFO *pfindData,
8b1327f6 474 struct super_block *sb, int xid, const __u16 *pfid)
1da177e4 475{
0b8f18e3 476 int rc = 0, tmprc;
1da177e4 477 struct cifsTconInfo *pTcon;
1da177e4 478 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1da177e4 479 char *buf = NULL;
5ade9dea 480 bool adjustTZ = false;
0b8f18e3 481 struct cifs_fattr fattr;
1da177e4
LT
482
483 pTcon = cifs_sb->tcon;
646dd539 484 cFYI(1, ("Getting info on %s", full_path));
1da177e4 485
d0d2f2df
SF
486 if ((pfindData == NULL) && (*pinode != NULL)) {
487 if (CIFS_I(*pinode)->clientCanCacheRead) {
fb8c4b14 488 cFYI(1, ("No need to revalidate cached inode sizes"));
1da177e4
LT
489 return rc;
490 }
491 }
492
493 /* if file info not passed in then get it from server */
d0d2f2df 494 if (pfindData == NULL) {
1da177e4 495 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
d0d2f2df 496 if (buf == NULL)
1da177e4
LT
497 return -ENOMEM;
498 pfindData = (FILE_ALL_INFO *)buf;
7962670e 499
1da177e4 500 /* could do find first instead but this returns more info */
7962670e 501 rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData,
acf1a1b1 502 0 /* not legacy */,
6b8edfe0 503 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
737b758c 504 CIFS_MOUNT_MAP_SPECIAL_CHR);
6b8edfe0
SF
505 /* BB optimize code so we do not make the above call
506 when server claims no NT SMB support and the above call
507 failed at least once - set flag in tcon or mount */
4523cc30 508 if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
7962670e 509 rc = SMBQueryInformation(xid, pTcon, full_path,
fb8c4b14 510 pfindData, cifs_sb->local_nls,
6b8edfe0
SF
511 cifs_sb->mnt_cifs_flags &
512 CIFS_MOUNT_MAP_SPECIAL_CHR);
4b18f2a9 513 adjustTZ = true;
6b8edfe0 514 }
1da177e4 515 }
0b8f18e3
JL
516
517 if (!rc) {
518 cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *) pfindData,
519 cifs_sb, adjustTZ);
520 } else if (rc == -EREMOTE) {
521 cifs_create_dfs_fattr(&fattr, sb);
b9a3260f 522 rc = 0;
0b8f18e3 523 } else {
7962670e 524 goto cgii_exit;
0b8f18e3 525 }
1da177e4 526
0b8f18e3
JL
527 /*
528 * If an inode wasn't passed in, then get the inode number
529 *
530 * Is an i_ino of zero legal? Can we use that to check if the server
531 * supports returning inode numbers? Are there other sanity checks we
532 * can use to ensure that the server is really filling in that field?
533 *
534 * We can not use the IndexNumber field by default from Windows or
535 * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA
536 * CIFS spec claims that this value is unique within the scope of a
537 * share, and the windows docs hint that it's actually unique
538 * per-machine.
539 *
540 * There may be higher info levels that work but are there Windows
541 * server or network appliances for which IndexNumber field is not
542 * guaranteed unique?
543 */
b9a3260f 544 if (*pinode == NULL) {
b9a3260f
SF
545 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
546 int rc1 = 0;
b9a3260f
SF
547
548 rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
0b8f18e3 549 full_path, &fattr.cf_uniqueid,
737b758c
SF
550 cifs_sb->local_nls,
551 cifs_sb->mnt_cifs_flags &
552 CIFS_MOUNT_MAP_SPECIAL_CHR);
ec06aedd 553 if (rc1 || !fattr.cf_uniqueid) {
0b8f18e3
JL
554 cFYI(1, ("GetSrvInodeNum rc %d", rc1));
555 fattr.cf_uniqueid = iunique(sb, ROOT_I);
ec06aedd 556 cifs_autodisable_serverino(cifs_sb);
132ac7b7 557 }
132ac7b7 558 } else {
0b8f18e3 559 fattr.cf_uniqueid = iunique(sb, ROOT_I);
132ac7b7 560 }
b9a3260f 561 } else {
0b8f18e3 562 fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid;
b9a3260f
SF
563 }
564
0b8f18e3
JL
565 /* query for SFU type info if supported and needed */
566 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
567 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
568 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
569 if (tmprc)
570 cFYI(1, ("cifs_sfu_type failed: %d", tmprc));
b9a3260f 571 }
1da177e4 572
4879b448 573#ifdef CONFIG_CIFS_EXPERIMENTAL
b9a3260f
SF
574 /* fill in 0777 bits from ACL */
575 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
576 cFYI(1, ("Getting mode bits from ACL"));
0b8f18e3 577 cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid);
b9a3260f 578 }
4879b448 579#endif
b9a3260f 580
0b8f18e3
JL
581 /* fill in remaining high mode bits e.g. SUID, VTX */
582 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
583 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
b9a3260f 584
0b8f18e3
JL
585 if (!*pinode) {
586 *pinode = cifs_iget(sb, &fattr);
587 if (!*pinode)
588 rc = -ENOMEM;
589 } else {
590 cifs_fattr_to_inode(*pinode, &fattr);
591 }
b9a3260f 592
7962670e 593cgii_exit:
1da177e4
LT
594 kfree(buf);
595 return rc;
596}
597
7f8ed420
SF
598static const struct inode_operations cifs_ipc_inode_ops = {
599 .lookup = cifs_lookup,
600};
601
e4cce94c 602char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
8be0ed44
SF
603{
604 int pplen = cifs_sb->prepathlen;
605 int dfsplen;
606 char *full_path = NULL;
607
608 /* if no prefix path, simply set path to the root of share to "" */
609 if (pplen == 0) {
610 full_path = kmalloc(1, GFP_KERNEL);
611 if (full_path)
612 full_path[0] = 0;
613 return full_path;
614 }
615
616 if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
617 dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
618 else
619 dfsplen = 0;
620
621 full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL);
622 if (full_path == NULL)
623 return full_path;
624
625 if (dfsplen) {
626 strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
627 /* switch slash direction in prepath depending on whether
628 * windows or posix style path names
629 */
630 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
631 int i;
632 for (i = 0; i < dfsplen; i++) {
633 if (full_path[i] == '\\')
634 full_path[i] = '/';
635 }
636 }
637 }
638 strncpy(full_path + dfsplen, cifs_sb->prepath, pplen);
639 full_path[dfsplen + pplen] = 0; /* add trailing null */
640 return full_path;
641}
642
cc0bad75
JL
643static int
644cifs_find_inode(struct inode *inode, void *opaque)
645{
646 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
647
648 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
649 return 0;
650
651 return 1;
652}
653
654static int
655cifs_init_inode(struct inode *inode, void *opaque)
656{
657 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
658
659 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
660 return 0;
661}
662
663/* Given fattrs, get a corresponding inode */
664struct inode *
665cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
666{
667 unsigned long hash;
668 struct inode *inode;
669
670 cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid));
671
672 /* hash down to 32-bits on 32-bit arch */
673 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
674
675 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
676
677 /* we have fattrs in hand, update the inode */
678 if (inode) {
679 cifs_fattr_to_inode(inode, fattr);
680 if (sb->s_flags & MS_NOATIME)
681 inode->i_flags |= S_NOATIME | S_NOCMTIME;
682 if (inode->i_state & I_NEW) {
683 inode->i_ino = hash;
684 unlock_new_inode(inode);
685 }
686 }
687
688 return inode;
689}
690
1da177e4 691/* gets root inode */
bd433d4c 692struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
1da177e4 693{
ce634ab2 694 int xid;
1da177e4 695 struct cifs_sb_info *cifs_sb;
cc0bad75 696 struct inode *inode = NULL;
ce634ab2 697 long rc;
8be0ed44 698 char *full_path;
ce634ab2 699
cc0bad75 700 cifs_sb = CIFS_SB(sb);
e4cce94c 701 full_path = cifs_build_path_to_root(cifs_sb);
8be0ed44
SF
702 if (full_path == NULL)
703 return ERR_PTR(-ENOMEM);
c18c842b 704
8be0ed44 705 xid = GetXid();
0b8f18e3 706 if (cifs_sb->tcon->unix_ext)
cc0bad75 707 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
0b8f18e3
JL
708 else
709 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
8be0ed44 710 xid, NULL);
0b8f18e3
JL
711
712 if (!inode)
713 return ERR_PTR(-ENOMEM);
cc0bad75 714
7f8ed420
SF
715 if (rc && cifs_sb->tcon->ipc) {
716 cFYI(1, ("ipc connection - fake read inode"));
717 inode->i_mode |= S_IFDIR;
718 inode->i_nlink = 2;
719 inode->i_op = &cifs_ipc_inode_ops;
720 inode->i_fop = &simple_dir_operations;
721 inode->i_uid = cifs_sb->mnt_uid;
722 inode->i_gid = cifs_sb->mnt_gid;
ad661334 723 } else if (rc) {
8be0ed44 724 kfree(full_path);
ce634ab2
DH
725 _FreeXid(xid);
726 iget_failed(inode);
727 return ERR_PTR(rc);
7f8ed420
SF
728 }
729
ce634ab2 730
8be0ed44 731 kfree(full_path);
ce634ab2
DH
732 /* can not call macro FreeXid here since in a void func
733 * TODO: This is no longer true
734 */
1da177e4 735 _FreeXid(xid);
ce634ab2 736 return inode;
1da177e4
LT
737}
738
388e57b2
SF
739static int
740cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
741 char *full_path, __u32 dosattr)
742{
743 int rc;
744 int oplock = 0;
745 __u16 netfid;
746 __u32 netpid;
747 bool set_time = false;
748 struct cifsFileInfo *open_file;
749 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
750 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
751 struct cifsTconInfo *pTcon = cifs_sb->tcon;
752 FILE_BASIC_INFO info_buf;
753
1adcb710
SF
754 if (attrs == NULL)
755 return -EINVAL;
756
388e57b2
SF
757 if (attrs->ia_valid & ATTR_ATIME) {
758 set_time = true;
759 info_buf.LastAccessTime =
760 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
761 } else
762 info_buf.LastAccessTime = 0;
763
764 if (attrs->ia_valid & ATTR_MTIME) {
765 set_time = true;
766 info_buf.LastWriteTime =
767 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
768 } else
769 info_buf.LastWriteTime = 0;
770
771 /*
772 * Samba throws this field away, but windows may actually use it.
773 * Do not set ctime unless other time stamps are changed explicitly
774 * (i.e. by utimes()) since we would then have a mix of client and
775 * server times.
776 */
777 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
778 cFYI(1, ("CIFS - CTIME changed"));
779 info_buf.ChangeTime =
780 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
781 } else
782 info_buf.ChangeTime = 0;
783
784 info_buf.CreationTime = 0; /* don't change */
785 info_buf.Attributes = cpu_to_le32(dosattr);
786
787 /*
788 * If the file is already open for write, just use that fileid
789 */
790 open_file = find_writable_file(cifsInode);
791 if (open_file) {
792 netfid = open_file->netfid;
793 netpid = open_file->pid;
794 goto set_via_filehandle;
795 }
796
797 /*
798 * NT4 apparently returns success on this call, but it doesn't
799 * really work.
800 */
801 if (!(pTcon->ses->flags & CIFS_SES_NT4)) {
802 rc = CIFSSMBSetPathInfo(xid, pTcon, full_path,
803 &info_buf, cifs_sb->local_nls,
804 cifs_sb->mnt_cifs_flags &
805 CIFS_MOUNT_MAP_SPECIAL_CHR);
6b37faa1
JL
806 if (rc == 0) {
807 cifsInode->cifsAttrs = dosattr;
808 goto out;
809 } else if (rc != -EOPNOTSUPP && rc != -EINVAL)
388e57b2
SF
810 goto out;
811 }
812
813 cFYI(1, ("calling SetFileInfo since SetPathInfo for "
814 "times not supported by this server"));
815 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
816 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
817 CREATE_NOT_DIR, &netfid, &oplock,
818 NULL, cifs_sb->local_nls,
819 cifs_sb->mnt_cifs_flags &
820 CIFS_MOUNT_MAP_SPECIAL_CHR);
821
822 if (rc != 0) {
823 if (rc == -EIO)
824 rc = -EINVAL;
825 goto out;
826 }
827
828 netpid = current->tgid;
829
830set_via_filehandle:
831 rc = CIFSSMBSetFileInfo(xid, pTcon, &info_buf, netfid, netpid);
d388908e
SF
832 if (!rc)
833 cifsInode->cifsAttrs = dosattr;
834
388e57b2
SF
835 if (open_file == NULL)
836 CIFSSMBClose(xid, pTcon, netfid);
837 else
6ab409b5 838 cifsFileInfo_put(open_file);
388e57b2
SF
839out:
840 return rc;
841}
842
a12a1ac7
JL
843/*
844 * open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
845 * and rename it to a random name that hopefully won't conflict with
846 * anything else.
847 */
848static int
3270958b 849cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid)
a12a1ac7
JL
850{
851 int oplock = 0;
852 int rc;
853 __u16 netfid;
3270958b 854 struct inode *inode = dentry->d_inode;
a12a1ac7
JL
855 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
856 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
857 struct cifsTconInfo *tcon = cifs_sb->tcon;
3270958b
SF
858 __u32 dosattr, origattr;
859 FILE_BASIC_INFO *info_buf = NULL;
a12a1ac7
JL
860
861 rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
dd1db2de 862 DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
a12a1ac7
JL
863 &netfid, &oplock, NULL, cifs_sb->local_nls,
864 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
865 if (rc != 0)
866 goto out;
867
3270958b
SF
868 origattr = cifsInode->cifsAttrs;
869 if (origattr == 0)
870 origattr |= ATTR_NORMAL;
871
872 dosattr = origattr & ~ATTR_READONLY;
a12a1ac7
JL
873 if (dosattr == 0)
874 dosattr |= ATTR_NORMAL;
875 dosattr |= ATTR_HIDDEN;
876
3270958b
SF
877 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
878 if (dosattr != origattr) {
879 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
880 if (info_buf == NULL) {
881 rc = -ENOMEM;
882 goto out_close;
883 }
884 info_buf->Attributes = cpu_to_le32(dosattr);
885 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
886 current->tgid);
887 /* although we would like to mark the file hidden
888 if that fails we will still try to rename it */
41346098 889 if (rc != 0)
3270958b
SF
890 cifsInode->cifsAttrs = dosattr;
891 else
892 dosattr = origattr; /* since not able to change them */
a12a1ac7 893 }
a12a1ac7 894
dd1db2de
JL
895 /* rename the file */
896 rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls,
a12a1ac7
JL
897 cifs_sb->mnt_cifs_flags &
898 CIFS_MOUNT_MAP_SPECIAL_CHR);
3270958b
SF
899 if (rc != 0) {
900 rc = -ETXTBSY;
901 goto undo_setattr;
902 }
6d22f098 903
3270958b
SF
904 /* try to set DELETE_ON_CLOSE */
905 if (!cifsInode->delete_pending) {
906 rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid,
907 current->tgid);
908 /*
909 * some samba versions return -ENOENT when we try to set the
910 * file disposition here. Likely a samba bug, but work around
911 * it for now. This means that some cifsXXX files may hang
912 * around after they shouldn't.
913 *
914 * BB: remove this hack after more servers have the fix
915 */
916 if (rc == -ENOENT)
917 rc = 0;
918 else if (rc != 0) {
919 rc = -ETXTBSY;
920 goto undo_rename;
921 }
922 cifsInode->delete_pending = true;
923 }
7ce86d5a 924
a12a1ac7
JL
925out_close:
926 CIFSSMBClose(xid, tcon, netfid);
927out:
3270958b 928 kfree(info_buf);
a12a1ac7 929 return rc;
3270958b
SF
930
931 /*
932 * reset everything back to the original state. Don't bother
933 * dealing with errors here since we can't do anything about
934 * them anyway.
935 */
936undo_rename:
937 CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name,
938 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
939 CIFS_MOUNT_MAP_SPECIAL_CHR);
940undo_setattr:
941 if (dosattr != origattr) {
942 info_buf->Attributes = cpu_to_le32(origattr);
943 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
944 current->tgid))
945 cifsInode->cifsAttrs = origattr;
946 }
947
948 goto out_close;
a12a1ac7
JL
949}
950
ff694527
SF
951
952/*
953 * If dentry->d_inode is null (usually meaning the cached dentry
954 * is a negative dentry) then we would attempt a standard SMB delete, but
af901ca1
AGR
955 * if that fails we can not attempt the fall back mechanisms on EACCESS
956 * but will return the EACCESS to the caller. Note that the VFS does not call
ff694527
SF
957 * unlink on negative dentries currently.
958 */
5f0319a7 959int cifs_unlink(struct inode *dir, struct dentry *dentry)
1da177e4
LT
960{
961 int rc = 0;
962 int xid;
1da177e4 963 char *full_path = NULL;
5f0319a7 964 struct inode *inode = dentry->d_inode;
ff694527 965 struct cifsInodeInfo *cifs_inode;
5f0319a7
JL
966 struct super_block *sb = dir->i_sb;
967 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
968 struct cifsTconInfo *tcon = cifs_sb->tcon;
6050247d
SF
969 struct iattr *attrs = NULL;
970 __u32 dosattr = 0, origattr = 0;
1da177e4 971
5f0319a7 972 cFYI(1, ("cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry));
1da177e4
LT
973
974 xid = GetXid();
975
5f0319a7
JL
976 /* Unlink can be called from rename so we can not take the
977 * sb->s_vfs_rename_mutex here */
978 full_path = build_path_from_dentry(dentry);
1da177e4 979 if (full_path == NULL) {
0f3bc09e 980 rc = -ENOMEM;
1da177e4 981 FreeXid(xid);
0f3bc09e 982 return rc;
1da177e4 983 }
2d785a50 984
5f0319a7 985 if ((tcon->ses->capabilities & CAP_UNIX) &&
2d785a50 986 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
5f0319a7
JL
987 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
988 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
2d785a50 989 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
737b758c 990 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
2d785a50
SF
991 cFYI(1, ("posix del rc %d", rc));
992 if ((rc == 0) || (rc == -ENOENT))
993 goto psx_del_no_retry;
994 }
1da177e4 995
6050247d 996retry_std_delete:
5f0319a7 997 rc = CIFSSMBDelFile(xid, tcon, full_path, cifs_sb->local_nls,
2d785a50 998 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
6050247d 999
2d785a50 1000psx_del_no_retry:
1da177e4 1001 if (!rc) {
5f0319a7
JL
1002 if (inode)
1003 drop_nlink(inode);
1da177e4 1004 } else if (rc == -ENOENT) {
5f0319a7 1005 d_drop(dentry);
1da177e4 1006 } else if (rc == -ETXTBSY) {
3270958b 1007 rc = cifs_rename_pending_delete(full_path, dentry, xid);
a12a1ac7
JL
1008 if (rc == 0)
1009 drop_nlink(inode);
ff694527 1010 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
388e57b2
SF
1011 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1012 if (attrs == NULL) {
1013 rc = -ENOMEM;
1014 goto out_reval;
1da177e4 1015 }
388e57b2
SF
1016
1017 /* try to reset dos attributes */
ff694527
SF
1018 cifs_inode = CIFS_I(inode);
1019 origattr = cifs_inode->cifsAttrs;
6050247d
SF
1020 if (origattr == 0)
1021 origattr |= ATTR_NORMAL;
1022 dosattr = origattr & ~ATTR_READONLY;
388e57b2
SF
1023 if (dosattr == 0)
1024 dosattr |= ATTR_NORMAL;
1025 dosattr |= ATTR_HIDDEN;
1026
1027 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
388e57b2
SF
1028 if (rc != 0)
1029 goto out_reval;
6050247d
SF
1030
1031 goto retry_std_delete;
1da177e4 1032 }
6050247d
SF
1033
1034 /* undo the setattr if we errored out and it's needed */
1035 if (rc != 0 && dosattr != 0)
1036 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1037
388e57b2 1038out_reval:
4523cc30 1039 if (inode) {
ff694527
SF
1040 cifs_inode = CIFS_I(inode);
1041 cifs_inode->time = 0; /* will force revalidate to get info
5f0319a7
JL
1042 when needed */
1043 inode->i_ctime = current_fs_time(sb);
06bcfedd 1044 }
5f0319a7 1045 dir->i_ctime = dir->i_mtime = current_fs_time(sb);
ff694527 1046 cifs_inode = CIFS_I(dir);
6050247d 1047 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
1da177e4
LT
1048
1049 kfree(full_path);
6050247d 1050 kfree(attrs);
1da177e4
LT
1051 FreeXid(xid);
1052 return rc;
1053}
1054
1055int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
1056{
6b37faa1 1057 int rc = 0, tmprc;
1da177e4
LT
1058 int xid;
1059 struct cifs_sb_info *cifs_sb;
1060 struct cifsTconInfo *pTcon;
1061 char *full_path = NULL;
1062 struct inode *newinode = NULL;
cc0bad75 1063 struct cifs_fattr fattr;
1da177e4 1064
6473a559 1065 cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode));
1da177e4
LT
1066
1067 xid = GetXid();
1068
1069 cifs_sb = CIFS_SB(inode->i_sb);
1070 pTcon = cifs_sb->tcon;
1071
7f57356b 1072 full_path = build_path_from_dentry(direntry);
1da177e4 1073 if (full_path == NULL) {
0f3bc09e 1074 rc = -ENOMEM;
1da177e4 1075 FreeXid(xid);
0f3bc09e 1076 return rc;
1da177e4 1077 }
50c2f753 1078
fb8c4b14
SF
1079 if ((pTcon->ses->capabilities & CAP_UNIX) &&
1080 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
2dd29d31
SF
1081 le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
1082 u32 oplock = 0;
f6d09982 1083 FILE_UNIX_BASIC_INFO *pInfo =
2dd29d31 1084 kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
fb8c4b14 1085 if (pInfo == NULL) {
2dd29d31
SF
1086 rc = -ENOMEM;
1087 goto mkdir_out;
1088 }
50c2f753 1089
ce3b0f8d 1090 mode &= ~current_umask();
2dd29d31
SF
1091 rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
1092 mode, NULL /* netfid */, pInfo, &oplock,
fb8c4b14
SF
1093 full_path, cifs_sb->local_nls,
1094 cifs_sb->mnt_cifs_flags &
2dd29d31 1095 CIFS_MOUNT_MAP_SPECIAL_CHR);
c45d707f
SF
1096 if (rc == -EOPNOTSUPP) {
1097 kfree(pInfo);
1098 goto mkdir_retry_old;
1099 } else if (rc) {
2dd29d31
SF
1100 cFYI(1, ("posix mkdir returned 0x%x", rc));
1101 d_drop(direntry);
1102 } else {
8f2376ad
CG
1103 if (pInfo->Type == cpu_to_le32(-1)) {
1104 /* no return info, go query for it */
5a07cdf8 1105 kfree(pInfo);
fb8c4b14 1106 goto mkdir_get_info;
5a07cdf8 1107 }
fb8c4b14
SF
1108/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
1109 to set uid/gid */
2dd29d31
SF
1110 inc_nlink(inode);
1111 if (pTcon->nocase)
1112 direntry->d_op = &cifs_ci_dentry_ops;
1113 else
1114 direntry->d_op = &cifs_dentry_ops;
cbac3cba 1115
cc0bad75
JL
1116 cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb);
1117 newinode = cifs_iget(inode->i_sb, &fattr);
1118 if (!newinode) {
5a07cdf8 1119 kfree(pInfo);
cbac3cba 1120 goto mkdir_get_info;
5a07cdf8 1121 }
6b37faa1 1122
2dd29d31 1123 d_instantiate(direntry, newinode);
cbac3cba 1124
cbac3cba 1125#ifdef CONFIG_CIFS_DEBUG2
fb8c4b14 1126 cFYI(1, ("instantiated dentry %p %s to inode %p",
cbac3cba
SF
1127 direntry, direntry->d_name.name, newinode));
1128
fb8c4b14
SF
1129 if (newinode->i_nlink != 2)
1130 cFYI(1, ("unexpected number of links %d",
cbac3cba
SF
1131 newinode->i_nlink));
1132#endif
2dd29d31
SF
1133 }
1134 kfree(pInfo);
1135 goto mkdir_out;
fb8c4b14 1136 }
c45d707f 1137mkdir_retry_old:
1da177e4 1138 /* BB add setting the equivalent of mode via CreateX w/ACLs */
737b758c
SF
1139 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
1140 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4 1141 if (rc) {
26a21b98 1142 cFYI(1, ("cifs_mkdir returned 0x%x", rc));
1da177e4
LT
1143 d_drop(direntry);
1144 } else {
fb8c4b14 1145mkdir_get_info:
d8c76e6f 1146 inc_nlink(inode);
c18c842b 1147 if (pTcon->unix_ext)
1da177e4 1148 rc = cifs_get_inode_info_unix(&newinode, full_path,
fb8c4b14 1149 inode->i_sb, xid);
1da177e4
LT
1150 else
1151 rc = cifs_get_inode_info(&newinode, full_path, NULL,
8b1327f6 1152 inode->i_sb, xid, NULL);
1da177e4 1153
b92327fe
SF
1154 if (pTcon->nocase)
1155 direntry->d_op = &cifs_ci_dentry_ops;
1156 else
1157 direntry->d_op = &cifs_dentry_ops;
1da177e4 1158 d_instantiate(direntry, newinode);
2dd29d31 1159 /* setting nlink not necessary except in cases where we
fb8c4b14 1160 * failed to get it from the server or was set bogus */
2dd29d31 1161 if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
fb8c4b14 1162 direntry->d_inode->i_nlink = 2;
95089910 1163
ce3b0f8d 1164 mode &= ~current_umask();
95089910
JL
1165 /* must turn on setgid bit if parent dir has it */
1166 if (inode->i_mode & S_ISGID)
1167 mode |= S_ISGID;
1168
c18c842b 1169 if (pTcon->unix_ext) {
4e1e7fb9
JL
1170 struct cifs_unix_set_info_args args = {
1171 .mode = mode,
1172 .ctime = NO_CHANGE_64,
1173 .atime = NO_CHANGE_64,
1174 .mtime = NO_CHANGE_64,
1175 .device = 0,
1176 };
d0d2f2df 1177 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
a001e5b5 1178 args.uid = (__u64)current_fsuid();
95089910
JL
1179 if (inode->i_mode & S_ISGID)
1180 args.gid = (__u64)inode->i_gid;
1181 else
a001e5b5 1182 args.gid = (__u64)current_fsgid();
1da177e4 1183 } else {
4e1e7fb9
JL
1184 args.uid = NO_CHANGE_64;
1185 args.gid = NO_CHANGE_64;
1da177e4 1186 }
01ea95e3
JL
1187 CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
1188 cifs_sb->local_nls,
1189 cifs_sb->mnt_cifs_flags &
1190 CIFS_MOUNT_MAP_SPECIAL_CHR);
3ce53fc4 1191 } else {
67750fb9
JL
1192 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
1193 (mode & S_IWUGO) == 0) {
1194 FILE_BASIC_INFO pInfo;
6b37faa1
JL
1195 struct cifsInodeInfo *cifsInode;
1196 u32 dosattrs;
1197
67750fb9 1198 memset(&pInfo, 0, sizeof(pInfo));
6b37faa1
JL
1199 cifsInode = CIFS_I(newinode);
1200 dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
1201 pInfo.Attributes = cpu_to_le32(dosattrs);
1202 tmprc = CIFSSMBSetPathInfo(xid, pTcon,
1203 full_path, &pInfo,
1204 cifs_sb->local_nls,
67750fb9
JL
1205 cifs_sb->mnt_cifs_flags &
1206 CIFS_MOUNT_MAP_SPECIAL_CHR);
6b37faa1
JL
1207 if (tmprc == 0)
1208 cifsInode->cifsAttrs = dosattrs;
67750fb9 1209 }
fb8c4b14 1210 if (direntry->d_inode) {
b0fd30d3
JL
1211 if (cifs_sb->mnt_cifs_flags &
1212 CIFS_MOUNT_DYNPERM)
1213 direntry->d_inode->i_mode =
1214 (mode | S_IFDIR);
4e94a105 1215
fb8c4b14 1216 if (cifs_sb->mnt_cifs_flags &
6473a559 1217 CIFS_MOUNT_SET_UID) {
fb8c4b14 1218 direntry->d_inode->i_uid =
a001e5b5 1219 current_fsuid();
95089910
JL
1220 if (inode->i_mode & S_ISGID)
1221 direntry->d_inode->i_gid =
1222 inode->i_gid;
1223 else
1224 direntry->d_inode->i_gid =
a001e5b5 1225 current_fsgid();
6473a559
SF
1226 }
1227 }
2a138ebb 1228 }
1da177e4 1229 }
fb8c4b14 1230mkdir_out:
1da177e4
LT
1231 kfree(full_path);
1232 FreeXid(xid);
1233 return rc;
1234}
1235
1236int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1237{
1238 int rc = 0;
1239 int xid;
1240 struct cifs_sb_info *cifs_sb;
1241 struct cifsTconInfo *pTcon;
1242 char *full_path = NULL;
1243 struct cifsInodeInfo *cifsInode;
1244
26a21b98 1245 cFYI(1, ("cifs_rmdir, inode = 0x%p", inode));
1da177e4
LT
1246
1247 xid = GetXid();
1248
1249 cifs_sb = CIFS_SB(inode->i_sb);
1250 pTcon = cifs_sb->tcon;
1251
7f57356b 1252 full_path = build_path_from_dentry(direntry);
1da177e4 1253 if (full_path == NULL) {
0f3bc09e 1254 rc = -ENOMEM;
1da177e4 1255 FreeXid(xid);
0f3bc09e 1256 return rc;
1da177e4
LT
1257 }
1258
737b758c
SF
1259 rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
1260 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
1261
1262 if (!rc) {
9a53c3a7 1263 drop_nlink(inode);
3677db10 1264 spin_lock(&direntry->d_inode->i_lock);
fb8c4b14 1265 i_size_write(direntry->d_inode, 0);
ce71ec36 1266 clear_nlink(direntry->d_inode);
3677db10 1267 spin_unlock(&direntry->d_inode->i_lock);
1da177e4
LT
1268 }
1269
1270 cifsInode = CIFS_I(direntry->d_inode);
1271 cifsInode->time = 0; /* force revalidate to go get info when
1272 needed */
42c24544
SF
1273
1274 cifsInode = CIFS_I(inode);
1275 cifsInode->time = 0; /* force revalidate to get parent dir info
1276 since cached search results now invalid */
1277
1da177e4
LT
1278 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
1279 current_fs_time(inode->i_sb);
1280
1281 kfree(full_path);
1282 FreeXid(xid);
1283 return rc;
1284}
1285
ee2fd967
SF
1286static int
1287cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
1288 struct dentry *to_dentry, const char *toPath)
1289{
1290 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
1291 struct cifsTconInfo *pTcon = cifs_sb->tcon;
1292 __u16 srcfid;
1293 int oplock, rc;
1294
1295 /* try path-based rename first */
1296 rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls,
1297 cifs_sb->mnt_cifs_flags &
1298 CIFS_MOUNT_MAP_SPECIAL_CHR);
1299
1300 /*
1301 * don't bother with rename by filehandle unless file is busy and
1302 * source Note that cross directory moves do not work with
1303 * rename by filehandle to various Windows servers.
1304 */
1305 if (rc == 0 || rc != -ETXTBSY)
1306 return rc;
1307
1308 /* open the file to be renamed -- we need DELETE perms */
1309 rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE,
1310 CREATE_NOT_DIR, &srcfid, &oplock, NULL,
1311 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1312 CIFS_MOUNT_MAP_SPECIAL_CHR);
1313
1314 if (rc == 0) {
1315 rc = CIFSSMBRenameOpenFile(xid, pTcon, srcfid,
1316 (const char *) to_dentry->d_name.name,
1317 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1318 CIFS_MOUNT_MAP_SPECIAL_CHR);
1319
1320 CIFSSMBClose(xid, pTcon, srcfid);
1321 }
1322
1323 return rc;
1324}
1325
14121bdc
JL
1326int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
1327 struct inode *target_dir, struct dentry *target_dentry)
1da177e4 1328{
ee2fd967
SF
1329 char *fromName = NULL;
1330 char *toName = NULL;
1da177e4
LT
1331 struct cifs_sb_info *cifs_sb_source;
1332 struct cifs_sb_info *cifs_sb_target;
14121bdc 1333 struct cifsTconInfo *tcon;
ee2fd967
SF
1334 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1335 FILE_UNIX_BASIC_INFO *info_buf_target;
8d281efb 1336 int xid, rc, tmprc;
1da177e4 1337
14121bdc
JL
1338 cifs_sb_target = CIFS_SB(target_dir->i_sb);
1339 cifs_sb_source = CIFS_SB(source_dir->i_sb);
1340 tcon = cifs_sb_source->tcon;
1da177e4 1341
ee2fd967
SF
1342 xid = GetXid();
1343
1344 /*
1345 * BB: this might be allowed if same server, but different share.
1346 * Consider adding support for this
1347 */
14121bdc 1348 if (tcon != cifs_sb_target->tcon) {
ee2fd967
SF
1349 rc = -EXDEV;
1350 goto cifs_rename_exit;
1da177e4
LT
1351 }
1352
ee2fd967
SF
1353 /*
1354 * we already have the rename sem so we do not need to
1355 * grab it again here to protect the path integrity
1356 */
14121bdc 1357 fromName = build_path_from_dentry(source_dentry);
ee2fd967
SF
1358 if (fromName == NULL) {
1359 rc = -ENOMEM;
1360 goto cifs_rename_exit;
1361 }
1362
14121bdc 1363 toName = build_path_from_dentry(target_dentry);
ee2fd967 1364 if (toName == NULL) {
1da177e4
LT
1365 rc = -ENOMEM;
1366 goto cifs_rename_exit;
1367 }
1368
14121bdc
JL
1369 rc = cifs_do_rename(xid, source_dentry, fromName,
1370 target_dentry, toName);
ee2fd967 1371
14121bdc
JL
1372 if (rc == -EEXIST && tcon->unix_ext) {
1373 /*
1374 * Are src and dst hardlinks of same inode? We can
1375 * only tell with unix extensions enabled
1376 */
1377 info_buf_source =
1378 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
1379 GFP_KERNEL);
1380 if (info_buf_source == NULL) {
1381 rc = -ENOMEM;
1382 goto cifs_rename_exit;
1383 }
1384
1385 info_buf_target = info_buf_source + 1;
8d281efb 1386 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName,
14121bdc
JL
1387 info_buf_source,
1388 cifs_sb_source->local_nls,
1389 cifs_sb_source->mnt_cifs_flags &
1390 CIFS_MOUNT_MAP_SPECIAL_CHR);
8d281efb 1391 if (tmprc != 0)
14121bdc 1392 goto unlink_target;
ee2fd967 1393
8d281efb 1394 tmprc = CIFSSMBUnixQPathInfo(xid, tcon,
14121bdc
JL
1395 toName, info_buf_target,
1396 cifs_sb_target->local_nls,
1397 /* remap based on source sb */
1398 cifs_sb_source->mnt_cifs_flags &
1399 CIFS_MOUNT_MAP_SPECIAL_CHR);
1400
8d281efb 1401 if (tmprc == 0 && (info_buf_source->UniqueId ==
ae6884a9 1402 info_buf_target->UniqueId)) {
14121bdc 1403 /* same file, POSIX says that this is a noop */
ae6884a9 1404 rc = 0;
14121bdc 1405 goto cifs_rename_exit;
ae6884a9 1406 }
14121bdc 1407 } /* else ... BB we could add the same check for Windows by
ee2fd967 1408 checking the UniqueId via FILE_INTERNAL_INFO */
14121bdc 1409
ee2fd967 1410unlink_target:
fc6f3943
JL
1411 /* Try unlinking the target dentry if it's not negative */
1412 if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
8d281efb 1413 tmprc = cifs_unlink(target_dir, target_dentry);
14121bdc
JL
1414 if (tmprc)
1415 goto cifs_rename_exit;
1416
14121bdc
JL
1417 rc = cifs_do_rename(xid, source_dentry, fromName,
1418 target_dentry, toName);
1da177e4
LT
1419 }
1420
1421cifs_rename_exit:
ee2fd967 1422 kfree(info_buf_source);
1da177e4
LT
1423 kfree(fromName);
1424 kfree(toName);
1425 FreeXid(xid);
1426 return rc;
1427}
1428
df2cf170
JL
1429static bool
1430cifs_inode_needs_reval(struct inode *inode)
1da177e4 1431{
df2cf170 1432 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
1da177e4 1433
df2cf170
JL
1434 if (cifs_i->clientCanCacheRead)
1435 return false;
1da177e4 1436
df2cf170
JL
1437 if (!lookupCacheEnabled)
1438 return true;
1da177e4 1439
df2cf170
JL
1440 if (cifs_i->time == 0)
1441 return true;
1da177e4 1442
df2cf170
JL
1443 /* FIXME: the actimeo should be tunable */
1444 if (time_after_eq(jiffies, cifs_i->time + HZ))
1445 return true;
1446
1447 return false;
1448}
1449
1450/* check invalid_mapping flag and zap the cache if it's set */
1451static void
1452cifs_invalidate_mapping(struct inode *inode)
1453{
1454 int rc;
1455 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
1456
1457 cifs_i->invalid_mapping = false;
1458
1459 /* write back any cached data */
1460 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
1461 rc = filemap_write_and_wait(inode->i_mapping);
1462 if (rc)
1463 cifs_i->write_behind_rc = rc;
1464 }
1465 invalidate_remote_inode(inode);
1466}
1467
1468/* revalidate a dentry's inode attributes */
1469int cifs_revalidate_dentry(struct dentry *dentry)
1470{
1471 int xid;
1472 int rc = 0;
1473 char *full_path = NULL;
1474 struct inode *inode = dentry->d_inode;
1475 struct super_block *sb = dentry->d_sb;
1476
1477 if (inode == NULL)
1478 return -ENOENT;
1da177e4
LT
1479
1480 xid = GetXid();
1481
df2cf170
JL
1482 if (!cifs_inode_needs_reval(inode))
1483 goto check_inval;
1da177e4
LT
1484
1485 /* can not safely grab the rename sem here if rename calls revalidate
1486 since that would deadlock */
df2cf170 1487 full_path = build_path_from_dentry(dentry);
1da177e4 1488 if (full_path == NULL) {
0f3bc09e 1489 rc = -ENOMEM;
df2cf170 1490 goto check_inval;
1da177e4
LT
1491 }
1492
df2cf170
JL
1493 cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
1494 "jiffies %ld", full_path, inode, inode->i_count.counter,
1495 dentry, dentry->d_time, jiffies));
1da177e4 1496
df2cf170
JL
1497 if (CIFS_SB(sb)->tcon->unix_ext)
1498 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
1499 else
1500 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
1501 xid, NULL);
1da177e4 1502
df2cf170
JL
1503check_inval:
1504 if (CIFS_I(inode)->invalid_mapping)
1505 cifs_invalidate_mapping(inode);
50c2f753 1506
1da177e4
LT
1507 kfree(full_path);
1508 FreeXid(xid);
1509 return rc;
1510}
1511
1512int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
1513 struct kstat *stat)
1514{
df2cf170 1515 int err = cifs_revalidate_dentry(dentry);
5fe14c85 1516 if (!err) {
1da177e4 1517 generic_fillattr(dentry->d_inode, stat);
5fe14c85 1518 stat->blksize = CIFS_MAX_MSGSIZE;
cc0bad75 1519 stat->ino = CIFS_I(dentry->d_inode)->uniqueid;
5fe14c85 1520 }
1da177e4
LT
1521 return err;
1522}
1523
1524static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1525{
1526 pgoff_t index = from >> PAGE_CACHE_SHIFT;
1527 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
1528 struct page *page;
1da177e4
LT
1529 int rc = 0;
1530
1531 page = grab_cache_page(mapping, index);
1532 if (!page)
1533 return -ENOMEM;
1534
eebd2aa3 1535 zero_user_segment(page, offset, PAGE_CACHE_SIZE);
1da177e4
LT
1536 unlock_page(page);
1537 page_cache_release(page);
1538 return rc;
1539}
1540
fb8c4b14 1541static int cifs_vmtruncate(struct inode *inode, loff_t offset)
3677db10 1542{
c08d3b0e 1543 loff_t oldsize;
1544 int err;
3677db10 1545
ba6a46a0 1546 spin_lock(&inode->i_lock);
c08d3b0e 1547 err = inode_newsize_ok(inode, offset);
1548 if (err) {
ba6a46a0 1549 spin_unlock(&inode->i_lock);
c08d3b0e 1550 goto out;
ba6a46a0 1551 }
c08d3b0e 1552
1553 oldsize = inode->i_size;
3677db10 1554 i_size_write(inode, offset);
ba6a46a0 1555 spin_unlock(&inode->i_lock);
c08d3b0e 1556 truncate_pagecache(inode, oldsize, offset);
acfa4380 1557 if (inode->i_op->truncate)
3677db10 1558 inode->i_op->truncate(inode);
c08d3b0e 1559out:
1560 return err;
3677db10
SF
1561}
1562
8efdbde6
JL
1563static int
1564cifs_set_file_size(struct inode *inode, struct iattr *attrs,
1565 int xid, char *full_path)
1566{
1567 int rc;
1568 struct cifsFileInfo *open_file;
1569 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1570 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1571 struct cifsTconInfo *pTcon = cifs_sb->tcon;
1572
1573 /*
1574 * To avoid spurious oplock breaks from server, in the case of
1575 * inodes that we already have open, avoid doing path based
1576 * setting of file size if we can do it by handle.
1577 * This keeps our caching token (oplock) and avoids timeouts
1578 * when the local oplock break takes longer to flush
1579 * writebehind data than the SMB timeout for the SetPathInfo
1580 * request would allow
1581 */
1582 open_file = find_writable_file(cifsInode);
1583 if (open_file) {
1584 __u16 nfid = open_file->netfid;
1585 __u32 npid = open_file->pid;
1586 rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid,
1587 npid, false);
6ab409b5 1588 cifsFileInfo_put(open_file);
8efdbde6
JL
1589 cFYI(1, ("SetFSize for attrs rc = %d", rc));
1590 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1591 unsigned int bytes_written;
1592 rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size,
1593 &bytes_written, NULL, NULL, 1);
1594 cFYI(1, ("Wrt seteof rc %d", rc));
1595 }
1596 } else
1597 rc = -EINVAL;
1598
1599 if (rc != 0) {
1600 /* Set file size by pathname rather than by handle
1601 either because no valid, writeable file handle for
1602 it was found or because there was an error setting
1603 it by handle */
1604 rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,
1605 false, cifs_sb->local_nls,
1606 cifs_sb->mnt_cifs_flags &
1607 CIFS_MOUNT_MAP_SPECIAL_CHR);
1608 cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
1609 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1610 __u16 netfid;
1611 int oplock = 0;
1612
1613 rc = SMBLegacyOpen(xid, pTcon, full_path,
1614 FILE_OPEN, GENERIC_WRITE,
1615 CREATE_NOT_DIR, &netfid, &oplock, NULL,
1616 cifs_sb->local_nls,
1617 cifs_sb->mnt_cifs_flags &
1618 CIFS_MOUNT_MAP_SPECIAL_CHR);
1619 if (rc == 0) {
1620 unsigned int bytes_written;
1621 rc = CIFSSMBWrite(xid, pTcon, netfid, 0,
1622 attrs->ia_size,
1623 &bytes_written, NULL,
1624 NULL, 1);
1625 cFYI(1, ("wrt seteof rc %d", rc));
1626 CIFSSMBClose(xid, pTcon, netfid);
1627 }
1628 }
1629 }
1630
1631 if (rc == 0) {
fbec9ab9 1632 cifsInode->server_eof = attrs->ia_size;
8efdbde6
JL
1633 rc = cifs_vmtruncate(inode, attrs->ia_size);
1634 cifs_truncate_page(inode->i_mapping, inode->i_size);
1635 }
1636
1637 return rc;
1638}
1639
3fe5c1dd
JL
1640static int
1641cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1642{
1643 int rc;
1644 int xid;
1645 char *full_path = NULL;
1646 struct inode *inode = direntry->d_inode;
1647 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1648 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1649 struct cifsTconInfo *pTcon = cifs_sb->tcon;
1650 struct cifs_unix_set_info_args *args = NULL;
3bbeeb3c 1651 struct cifsFileInfo *open_file;
3fe5c1dd
JL
1652
1653 cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x",
1654 direntry->d_name.name, attrs->ia_valid));
1655
1656 xid = GetXid();
1657
1658 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
1659 /* check if we have permission to change attrs */
1660 rc = inode_change_ok(inode, attrs);
1661 if (rc < 0)
1662 goto out;
1663 else
1664 rc = 0;
1665 }
1666
1667 full_path = build_path_from_dentry(direntry);
1668 if (full_path == NULL) {
1669 rc = -ENOMEM;
1670 goto out;
1671 }
1672
0f4d634c
JL
1673 /*
1674 * Attempt to flush data before changing attributes. We need to do
1675 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
1676 * ownership or mode then we may also need to do this. Here, we take
1677 * the safe way out and just do the flush on all setattr requests. If
1678 * the flush returns error, store it to report later and continue.
1679 *
1680 * BB: This should be smarter. Why bother flushing pages that
1681 * will be truncated anyway? Also, should we error out here if
1682 * the flush returns error?
1683 */
1684 rc = filemap_write_and_wait(inode->i_mapping);
1685 if (rc != 0) {
1686 cifsInode->write_behind_rc = rc;
1687 rc = 0;
3fe5c1dd
JL
1688 }
1689
1690 if (attrs->ia_valid & ATTR_SIZE) {
1691 rc = cifs_set_file_size(inode, attrs, xid, full_path);
1692 if (rc != 0)
1693 goto out;
1694 }
1695
1696 /* skip mode change if it's just for clearing setuid/setgid */
1697 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
1698 attrs->ia_valid &= ~ATTR_MODE;
1699
1700 args = kmalloc(sizeof(*args), GFP_KERNEL);
1701 if (args == NULL) {
1702 rc = -ENOMEM;
1703 goto out;
1704 }
1705
1706 /* set up the struct */
1707 if (attrs->ia_valid & ATTR_MODE)
1708 args->mode = attrs->ia_mode;
1709 else
1710 args->mode = NO_CHANGE_64;
1711
1712 if (attrs->ia_valid & ATTR_UID)
1713 args->uid = attrs->ia_uid;
1714 else
1715 args->uid = NO_CHANGE_64;
1716
1717 if (attrs->ia_valid & ATTR_GID)
1718 args->gid = attrs->ia_gid;
1719 else
1720 args->gid = NO_CHANGE_64;
1721
1722 if (attrs->ia_valid & ATTR_ATIME)
1723 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
1724 else
1725 args->atime = NO_CHANGE_64;
1726
1727 if (attrs->ia_valid & ATTR_MTIME)
1728 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
1729 else
1730 args->mtime = NO_CHANGE_64;
1731
1732 if (attrs->ia_valid & ATTR_CTIME)
1733 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
1734 else
1735 args->ctime = NO_CHANGE_64;
1736
1737 args->device = 0;
3bbeeb3c
JL
1738 open_file = find_writable_file(cifsInode);
1739 if (open_file) {
1740 u16 nfid = open_file->netfid;
1741 u32 npid = open_file->pid;
1742 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
6ab409b5 1743 cifsFileInfo_put(open_file);
3bbeeb3c
JL
1744 } else {
1745 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
01ea95e3
JL
1746 cifs_sb->local_nls,
1747 cifs_sb->mnt_cifs_flags &
1748 CIFS_MOUNT_MAP_SPECIAL_CHR);
3bbeeb3c 1749 }
3fe5c1dd 1750
ccd4bb1b 1751 if (!rc) {
3fe5c1dd 1752 rc = inode_setattr(inode, attrs);
ccd4bb1b
SF
1753
1754 /* force revalidate when any of these times are set since some
1755 of the fs types (eg ext3, fat) do not have fine enough
1756 time granularity to match protocol, and we do not have a
1757 a way (yet) to query the server fs's time granularity (and
1758 whether it rounds times down).
1759 */
1760 if (!rc && (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME)))
1761 cifsInode->time = 0;
1762 }
3fe5c1dd
JL
1763out:
1764 kfree(args);
1765 kfree(full_path);
1766 FreeXid(xid);
1767 return rc;
1768}
1769
0510eeb7
JL
1770static int
1771cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
1da177e4
LT
1772{
1773 int xid;
3fe5c1dd
JL
1774 struct inode *inode = direntry->d_inode;
1775 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
3fe5c1dd 1776 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1da177e4
LT
1777 char *full_path = NULL;
1778 int rc = -EACCES;
feb3e20c 1779 __u32 dosattr = 0;
4e1e7fb9 1780 __u64 mode = NO_CHANGE_64;
3fe5c1dd 1781
1da177e4
LT
1782 xid = GetXid();
1783
3979877e 1784 cFYI(1, ("setattr on file %s attrs->iavalid 0x%x",
1da177e4 1785 direntry->d_name.name, attrs->ia_valid));
6473a559 1786
2a138ebb 1787 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
6473a559 1788 /* check if we have permission to change attrs */
02eadeff 1789 rc = inode_change_ok(inode, attrs);
fb8c4b14 1790 if (rc < 0) {
6473a559
SF
1791 FreeXid(xid);
1792 return rc;
1793 } else
1794 rc = 0;
1795 }
50c2f753 1796
7f57356b 1797 full_path = build_path_from_dentry(direntry);
1da177e4 1798 if (full_path == NULL) {
0f3bc09e 1799 rc = -ENOMEM;
1da177e4 1800 FreeXid(xid);
0f3bc09e 1801 return rc;
1da177e4 1802 }
1da177e4 1803
0f4d634c
JL
1804 /*
1805 * Attempt to flush data before changing attributes. We need to do
1806 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
1807 * ownership or mode then we may also need to do this. Here, we take
1808 * the safe way out and just do the flush on all setattr requests. If
1809 * the flush returns error, store it to report later and continue.
1810 *
1811 * BB: This should be smarter. Why bother flushing pages that
1812 * will be truncated anyway? Also, should we error out here if
1813 * the flush returns error?
1814 */
1815 rc = filemap_write_and_wait(inode->i_mapping);
1816 if (rc != 0) {
1817 cifsInode->write_behind_rc = rc;
1818 rc = 0;
50531444 1819 }
cea21805 1820
50531444 1821 if (attrs->ia_valid & ATTR_SIZE) {
8efdbde6
JL
1822 rc = cifs_set_file_size(inode, attrs, xid, full_path);
1823 if (rc != 0)
e30dcf3a 1824 goto cifs_setattr_exit;
1da177e4 1825 }
4ca691a8
JL
1826
1827 /*
1828 * Without unix extensions we can't send ownership changes to the
1829 * server, so silently ignore them. This is consistent with how
1830 * local DOS/Windows filesystems behave (VFAT, NTFS, etc). With
1831 * CIFSACL support + proper Windows to Unix idmapping, we may be
1832 * able to support this in the future.
1833 */
3fe5c1dd 1834 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
4ca691a8 1835 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
1da177e4 1836
d32c4f26
JL
1837 /* skip mode change if it's just for clearing setuid/setgid */
1838 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
1839 attrs->ia_valid &= ~ATTR_MODE;
1840
1da177e4 1841 if (attrs->ia_valid & ATTR_MODE) {
5132861a 1842 cFYI(1, ("Mode changed to 0%o", attrs->ia_mode));
1da177e4 1843 mode = attrs->ia_mode;
1da177e4
LT
1844 }
1845
3fe5c1dd 1846 if (attrs->ia_valid & ATTR_MODE) {
cdbce9c8 1847 rc = 0;
97837582
SF
1848#ifdef CONFIG_CIFS_EXPERIMENTAL
1849 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
02eadeff 1850 rc = mode_to_acl(inode, full_path, mode);
5132861a 1851 else
97837582 1852#endif
5132861a
JL
1853 if (((mode & S_IWUGO) == 0) &&
1854 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
feb3e20c
JL
1855
1856 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
1857
5132861a
JL
1858 /* fix up mode if we're not using dynperm */
1859 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
1860 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
1861 } else if ((mode & S_IWUGO) &&
1862 (cifsInode->cifsAttrs & ATTR_READONLY)) {
feb3e20c
JL
1863
1864 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
1865 /* Attributes of 0 are ignored */
1866 if (dosattr == 0)
1867 dosattr |= ATTR_NORMAL;
5132861a
JL
1868
1869 /* reset local inode permissions to normal */
1870 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
1871 attrs->ia_mode &= ~(S_IALLUGO);
1872 if (S_ISDIR(inode->i_mode))
1873 attrs->ia_mode |=
1874 cifs_sb->mnt_dir_mode;
1875 else
1876 attrs->ia_mode |=
1877 cifs_sb->mnt_file_mode;
1878 }
1879 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
1880 /* ignore mode change - ATTR_READONLY hasn't changed */
1881 attrs->ia_valid &= ~ATTR_MODE;
1da177e4 1882 }
1da177e4
LT
1883 }
1884
feb3e20c
JL
1885 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
1886 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
1887 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
1888 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
1da177e4 1889
e30dcf3a
SF
1890 /* Even if error on time set, no sense failing the call if
1891 the server would set the time to a reasonable value anyway,
1892 and this check ensures that we are not being called from
1893 sys_utimes in which case we ought to fail the call back to
1894 the user when the server rejects the call */
fb8c4b14 1895 if ((rc) && (attrs->ia_valid &
feb3e20c 1896 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
e30dcf3a 1897 rc = 0;
1da177e4
LT
1898 }
1899
1900 /* do not need local check to inode_check_ok since the server does
1901 that */
1902 if (!rc)
02eadeff 1903 rc = inode_setattr(inode, attrs);
e30dcf3a 1904cifs_setattr_exit:
1da177e4
LT
1905 kfree(full_path);
1906 FreeXid(xid);
1907 return rc;
1908}
1909
0510eeb7
JL
1910int
1911cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1912{
1913 struct inode *inode = direntry->d_inode;
1914 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1915 struct cifsTconInfo *pTcon = cifs_sb->tcon;
1916
1917 if (pTcon->unix_ext)
1918 return cifs_setattr_unix(direntry, attrs);
1919
1920 return cifs_setattr_nounix(direntry, attrs);
1921
1922 /* BB: add cifs_setattr_legacy for really old servers */
1923}
1924
99ee4dbd 1925#if 0
1da177e4
LT
1926void cifs_delete_inode(struct inode *inode)
1927{
26a21b98 1928 cFYI(1, ("In cifs_delete_inode, inode = 0x%p", inode));
1da177e4
LT
1929 /* may have to add back in if and when safe distributed caching of
1930 directories added e.g. via FindNotify */
1931}
99ee4dbd 1932#endif
This page took 0.400631 seconds and 5 git commands to generate.