1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include <linux/fs.h>
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
32int cifs_get_inode_info_unix(struct inode **pinode,
33 const unsigned char *search_path, struct super_block *sb, int xid)
34{
35 int rc = 0;
36 FILE_UNIX_BASIC_INFO findData;
37 struct cifsTconInfo *pTcon;
38 struct inode *inode;
39 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
40 char *tmp_path;
41
42 pTcon = cifs_sb->tcon;
43 cFYI(1, ("Getting info on %s", search_path));
44
45 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
46 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
47 CIFS_MOUNT_MAP_SPECIAL_CHR);
48
49
50 if (rc) {
51 if (rc == -EREMOTE) {
52 tmp_path =
53 kmalloc(strnlen(pTcon->treeName,
54 MAX_TREE_SIZE + 1) +
55 strnlen(search_path, MAX_PATHCONF) + 1,
56 GFP_KERNEL);
57 if (tmp_path == NULL) {
58 return -ENOMEM;
59 }
60
61
62 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
63 strncat(tmp_path, search_path, MAX_PATHCONF);
64 rc = connect_to_dfs_path(xid, pTcon->ses,
65 tmp_path,
66 cifs_sb->local_nls,
67 cifs_sb->mnt_cifs_flags &
68 CIFS_MOUNT_MAP_SPECIAL_CHR);
69 kfree(tmp_path);
70
71
72 } else if (rc) {
73 return rc;
74 }
75 } else {
76 struct cifsInodeInfo *cifsInfo;
77 __u32 type = le32_to_cpu(findData.Type);
78 __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
79 __u64 end_of_file = le64_to_cpu(findData.EndOfFile);
80
81
82 if (*pinode == NULL) {
83 *pinode = new_inode(sb);
84 if (*pinode == NULL)
85 return -ENOMEM;
86
87
88
89 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
90 (*pinode)->i_ino =
91 (unsigned long)findData.UniqueId;
92 }
93 if (sb->s_flags & MS_NOATIME)
94 (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
95
96 insert_inode_hash(*pinode);
97 }
98
99 inode = *pinode;
100 cifsInfo = CIFS_I(inode);
101
102 cFYI(1, ("Old time %ld", cifsInfo->time));
103 cifsInfo->time = jiffies;
104 cFYI(1, ("New time %ld", cifsInfo->time));
105
106 atomic_set(&cifsInfo->inUse, 1);
107
108 inode->i_atime =
109 cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
110 inode->i_mtime =
111 cifs_NTtimeToUnix(le64_to_cpu
112 (findData.LastModificationTime));
113 inode->i_ctime =
114 cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
115 inode->i_mode = le64_to_cpu(findData.Permissions);
116
117
118 inode->i_mode &= ~S_IFMT;
119 if (type == UNIX_FILE) {
120 inode->i_mode |= S_IFREG;
121 } else if (type == UNIX_SYMLINK) {
122 inode->i_mode |= S_IFLNK;
123 } else if (type == UNIX_DIR) {
124 inode->i_mode |= S_IFDIR;
125 } else if (type == UNIX_CHARDEV) {
126 inode->i_mode |= S_IFCHR;
127 inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
128 le64_to_cpu(findData.DevMinor) & MINORMASK);
129 } else if (type == UNIX_BLOCKDEV) {
130 inode->i_mode |= S_IFBLK;
131 inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
132 le64_to_cpu(findData.DevMinor) & MINORMASK);
133 } else if (type == UNIX_FIFO) {
134 inode->i_mode |= S_IFIFO;
135 } else if (type == UNIX_SOCKET) {
136 inode->i_mode |= S_IFSOCK;
137 } else {
138
139 inode->i_mode |= S_IFREG;
140 cFYI(1, ("unknown type %d", type));
141 }
142
143 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
144 inode->i_uid = cifs_sb->mnt_uid;
145 else
146 inode->i_uid = le64_to_cpu(findData.Uid);
147
148 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
149 inode->i_gid = cifs_sb->mnt_gid;
150 else
151 inode->i_gid = le64_to_cpu(findData.Gid);
152
153 inode->i_nlink = le64_to_cpu(findData.Nlinks);
154
155 spin_lock(&inode->i_lock);
156 if (is_size_safe_to_change(cifsInfo, end_of_file)) {
157
158
159 i_size_write(inode, end_of_file);
160
161
162
163
164
165
166
167
168
169
170
171
172 inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
173 }
174 spin_unlock(&inode->i_lock);
175
176 if (num_of_bytes < end_of_file)
177 cFYI(1, ("allocation size less than end of file"));
178 cFYI(1, ("Size %ld and blocks %llu",
179 (unsigned long) inode->i_size,
180 (unsigned long long)inode->i_blocks));
181 if (S_ISREG(inode->i_mode)) {
182 cFYI(1, ("File inode"));
183 inode->i_op = &cifs_file_inode_ops;
184 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
185 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
186 inode->i_fop =
187 &cifs_file_direct_nobrl_ops;
188 else
189 inode->i_fop = &cifs_file_direct_ops;
190 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
191 inode->i_fop = &cifs_file_nobrl_ops;
192 else
193 inode->i_fop = &cifs_file_ops;
194
195
196 if (pTcon->ses->server->maxBuf <
197 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
198 inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
199 else
200 inode->i_data.a_ops = &cifs_addr_ops;
201 } else if (S_ISDIR(inode->i_mode)) {
202 cFYI(1, ("Directory inode"));
203 inode->i_op = &cifs_dir_inode_ops;
204 inode->i_fop = &cifs_dir_ops;
205 } else if (S_ISLNK(inode->i_mode)) {
206 cFYI(1, ("Symbolic Link inode"));
207 inode->i_op = &cifs_symlink_inode_ops;
208
209 } else {
210 cFYI(1, ("Init special inode"));
211 init_special_inode(inode, inode->i_mode,
212 inode->i_rdev);
213 }
214 }
215 return rc;
216}
217
218static int decode_sfu_inode(struct inode *inode, __u64 size,
219 const unsigned char *path,
220 struct cifs_sb_info *cifs_sb, int xid)
221{
222 int rc;
223 int oplock = FALSE;
224 __u16 netfid;
225 struct cifsTconInfo *pTcon = cifs_sb->tcon;
226 char buf[24];
227 unsigned int bytes_read;
228 char *pbuf;
229
230 pbuf = buf;
231
232 if (size == 0) {
233 inode->i_mode |= S_IFIFO;
234 return 0;
235 } else if (size < 8) {
236 return -EINVAL;
237 }
238
239 rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
240 CREATE_NOT_DIR, &netfid, &oplock, NULL,
241 cifs_sb->local_nls,
242 cifs_sb->mnt_cifs_flags &
243 CIFS_MOUNT_MAP_SPECIAL_CHR);
244 if (rc == 0) {
245 int buf_type = CIFS_NO_BUFFER;
246
247 rc = CIFSSMBRead(xid, pTcon,
248 netfid,
249 24 , 0 ,
250 &bytes_read, &pbuf, &buf_type);
251 if ((rc == 0) && (bytes_read >= 8)) {
252 if (memcmp("IntxBLK", pbuf, 8) == 0) {
253 cFYI(1, ("Block device"));
254 inode->i_mode |= S_IFBLK;
255 if (bytes_read == 24) {
256
257 __u64 mjr;
258 __u64 mnr;
259 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
260 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
261 inode->i_rdev = MKDEV(mjr, mnr);
262 }
263 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
264 cFYI(1, ("Char device"));
265 inode->i_mode |= S_IFCHR;
266 if (bytes_read == 24) {
267
268 __u64 mjr;
269 __u64 mnr;
270 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
271 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
272 inode->i_rdev = MKDEV(mjr, mnr);
273 }
274 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
275 cFYI(1, ("Symlink"));
276 inode->i_mode |= S_IFLNK;
277 } else {
278 inode->i_mode |= S_IFREG;
279 rc = -EOPNOTSUPP;
280 }
281 } else {
282 inode->i_mode |= S_IFREG;
283 rc = -EOPNOTSUPP;
284 }
285 CIFSSMBClose(xid, pTcon, netfid);
286 }
287 return rc;
288}
289
290#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID)
291
292static int get_sfu_mode(struct inode *inode,
293 const unsigned char *path,
294 struct cifs_sb_info *cifs_sb, int xid)
295{
296#ifdef CONFIG_CIFS_XATTR
297 ssize_t rc;
298 char ea_value[4];
299 __u32 mode;
300
301 rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS",
302 ea_value, 4 , cifs_sb->local_nls,
303 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
304 if (rc < 0)
305 return (int)rc;
306 else if (rc > 3) {
307 mode = le32_to_cpu(*((__le32 *)ea_value));
308 inode->i_mode &= ~SFBITS_MASK;
309 cFYI(1, ("special bits 0%o org mode 0%o", mode, inode->i_mode));
310 inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode;
311 cFYI(1, ("special mode bits 0%o", mode));
312 return 0;
313 } else {
314 return 0;
315 }
316#else
317 return -EOPNOTSUPP;
318#endif
319}
320
321int cifs_get_inode_info(struct inode **pinode,
322 const unsigned char *search_path, FILE_ALL_INFO *pfindData,
323 struct super_block *sb, int xid)
324{
325 int rc = 0;
326 struct cifsTconInfo *pTcon;
327 struct inode *inode;
328 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
329 char *tmp_path;
330 char *buf = NULL;
331 int adjustTZ = FALSE;
332
333 pTcon = cifs_sb->tcon;
334 cFYI(1, ("Getting info on %s", search_path));
335
336 if ((pfindData == NULL) && (*pinode != NULL)) {
337 if (CIFS_I(*pinode)->clientCanCacheRead) {
338 cFYI(1, ("No need to revalidate cached inode sizes"));
339 return rc;
340 }
341 }
342
343
344 if (pfindData == NULL) {
345 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
346 if (buf == NULL)
347 return -ENOMEM;
348 pfindData = (FILE_ALL_INFO *)buf;
349
350 rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
351 0 ,
352 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
353 CIFS_MOUNT_MAP_SPECIAL_CHR);
354
355
356
357 if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
358 rc = SMBQueryInformation(xid, pTcon, search_path,
359 pfindData, cifs_sb->local_nls,
360 cifs_sb->mnt_cifs_flags &
361 CIFS_MOUNT_MAP_SPECIAL_CHR);
362 adjustTZ = TRUE;
363 }
364 }
365
366 if (rc) {
367 if (rc == -EREMOTE) {
368 tmp_path =
369 kmalloc(strnlen
370 (pTcon->treeName,
371 MAX_TREE_SIZE + 1) +
372 strnlen(search_path, MAX_PATHCONF) + 1,
373 GFP_KERNEL);
374 if (tmp_path == NULL) {
375 kfree(buf);
376 return -ENOMEM;
377 }
378
379 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
380 strncat(tmp_path, search_path, MAX_PATHCONF);
381 rc = connect_to_dfs_path(xid, pTcon->ses,
382 tmp_path,
383 cifs_sb->local_nls,
384 cifs_sb->mnt_cifs_flags &
385 CIFS_MOUNT_MAP_SPECIAL_CHR);
386 kfree(tmp_path);
387
388 } else if (rc) {
389 kfree(buf);
390 return rc;
391 }
392 } else {
393 struct cifsInodeInfo *cifsInfo;
394 __u32 attr = le32_to_cpu(pfindData->Attributes);
395
396
397 if (*pinode == NULL) {
398 *pinode = new_inode(sb);
399 if (*pinode == NULL) {
400 kfree(buf);
401 return -ENOMEM;
402 }
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
419 int rc1 = 0;
420 __u64 inode_num;
421
422 rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
423 search_path, &inode_num,
424 cifs_sb->local_nls,
425 cifs_sb->mnt_cifs_flags &
426 CIFS_MOUNT_MAP_SPECIAL_CHR);
427 if (rc1) {
428 cFYI(1, ("GetSrvInodeNum rc %d", rc1));
429
430 } else
431 (*pinode)->i_ino = inode_num;
432 }
433 if (sb->s_flags & MS_NOATIME)
434 (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
435 insert_inode_hash(*pinode);
436 }
437 inode = *pinode;
438 cifsInfo = CIFS_I(inode);
439 cifsInfo->cifsAttrs = attr;
440 cFYI(1, ("Old time %ld", cifsInfo->time));
441 cifsInfo->time = jiffies;
442 cFYI(1, ("New time %ld", cifsInfo->time));
443
444
445
446
447
448
449
450 if (pfindData->LastAccessTime)
451 inode->i_atime = cifs_NTtimeToUnix
452 (le64_to_cpu(pfindData->LastAccessTime));
453 else
454 inode->i_atime = CURRENT_TIME;
455 inode->i_mtime =
456 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
457 inode->i_ctime =
458 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
459 cFYI(0, ("Attributes came in as 0x%x", attr));
460 if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
461 inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj;
462 inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj;
463 }
464
465
466 if (atomic_read(&cifsInfo->inUse) == 0)
467
468 inode->i_mode = cifs_sb->mnt_file_mode;
469 else
470
471
472 inode->i_mode &= ~S_IFMT;
473
474
475
476 if (attr & ATTR_DIRECTORY) {
477
478
479 inode->i_mode = cifs_sb->mnt_dir_mode;
480 inode->i_mode |= S_IFDIR;
481 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
482 (cifsInfo->cifsAttrs & ATTR_SYSTEM) &&
483
484 (pfindData->EndOfFile == 0)) {
485 inode->i_mode = cifs_sb->mnt_file_mode;
486 inode->i_mode |= S_IFIFO;
487
488 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
489 (cifsInfo->cifsAttrs & ATTR_SYSTEM)) {
490 if (decode_sfu_inode(inode,
491 le64_to_cpu(pfindData->EndOfFile),
492 search_path,
493 cifs_sb, xid)) {
494 cFYI(1, ("Unrecognized sfu inode type"));
495 }
496 cFYI(1, ("sfu mode 0%o", inode->i_mode));
497 } else {
498 inode->i_mode |= S_IFREG;
499
500
501 if (cifsInfo->cifsAttrs & ATTR_READONLY)
502 inode->i_mode &= ~(S_IWUGO);
503 else if ((inode->i_mode & S_IWUGO) == 0)
504
505
506
507 inode->i_mode |= (S_IWUGO &
508 cifs_sb->mnt_file_mode);
509
510
511 }
512
513 spin_lock(&inode->i_lock);
514 if (is_size_safe_to_change(cifsInfo, le64_to_cpu(pfindData->EndOfFile))) {
515
516
517 i_size_write(inode, le64_to_cpu(pfindData->EndOfFile));
518
519
520
521 inode->i_blocks = (512 - 1 + le64_to_cpu(
522 pfindData->AllocationSize)) >> 9;
523 }
524 spin_unlock(&inode->i_lock);
525
526 inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
527
528
529
530#ifdef CONFIG_CIFS_EXPERIMENTAL
531
532 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
533 cFYI(1, ("Getting mode bits from ACL"));
534 acl_to_uid_mode(inode, search_path);
535 }
536#endif
537 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
538
539 get_sfu_mode(inode, search_path, cifs_sb, xid);
540 } else if (atomic_read(&cifsInfo->inUse) == 0) {
541 inode->i_uid = cifs_sb->mnt_uid;
542 inode->i_gid = cifs_sb->mnt_gid;
543
544
545 atomic_set(&cifsInfo->inUse, 1);
546 }
547
548 if (S_ISREG(inode->i_mode)) {
549 cFYI(1, ("File inode"));
550 inode->i_op = &cifs_file_inode_ops;
551 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
552 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
553 inode->i_fop =
554 &cifs_file_direct_nobrl_ops;
555 else
556 inode->i_fop = &cifs_file_direct_ops;
557 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
558 inode->i_fop = &cifs_file_nobrl_ops;
559 else
560 inode->i_fop = &cifs_file_ops;
561
562 if (pTcon->ses->server->maxBuf <
563 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
564 inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
565 else
566 inode->i_data.a_ops = &cifs_addr_ops;
567 } else if (S_ISDIR(inode->i_mode)) {
568 cFYI(1, ("Directory inode"));
569 inode->i_op = &cifs_dir_inode_ops;
570 inode->i_fop = &cifs_dir_ops;
571 } else if (S_ISLNK(inode->i_mode)) {
572 cFYI(1, ("Symbolic Link inode"));
573 inode->i_op = &cifs_symlink_inode_ops;
574 } else {
575 init_special_inode(inode, inode->i_mode,
576 inode->i_rdev);
577 }
578 }
579 kfree(buf);
580 return rc;
581}
582
583static const struct inode_operations cifs_ipc_inode_ops = {
584 .lookup = cifs_lookup,
585};
586
587
588void cifs_read_inode(struct inode *inode)
589{
590 int xid, rc;
591 struct cifs_sb_info *cifs_sb;
592
593 cifs_sb = CIFS_SB(inode->i_sb);
594 xid = GetXid();
595
596 if (cifs_sb->tcon->unix_ext)
597 rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
598 else
599 rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);
600 if (rc && cifs_sb->tcon->ipc) {
601 cFYI(1, ("ipc connection - fake read inode"));
602 inode->i_mode |= S_IFDIR;
603 inode->i_nlink = 2;
604 inode->i_op = &cifs_ipc_inode_ops;
605 inode->i_fop = &simple_dir_operations;
606 inode->i_uid = cifs_sb->mnt_uid;
607 inode->i_gid = cifs_sb->mnt_gid;
608 }
609
610
611 _FreeXid(xid);
612}
613
614int cifs_unlink(struct inode *inode, struct dentry *direntry)
615{
616 int rc = 0;
617 int xid;
618 struct cifs_sb_info *cifs_sb;
619 struct cifsTconInfo *pTcon;
620 char *full_path = NULL;
621 struct cifsInodeInfo *cifsInode;
622 FILE_BASIC_INFO *pinfo_buf;
623
624 cFYI(1, ("cifs_unlink, inode = 0x%p", inode));
625
626 xid = GetXid();
627
628 if (inode)
629 cifs_sb = CIFS_SB(inode->i_sb);
630 else
631 cifs_sb = CIFS_SB(direntry->d_sb);
632 pTcon = cifs_sb->tcon;
633
634
635
636
637 full_path = build_path_from_dentry(direntry);
638
639 if (full_path == NULL) {
640 FreeXid(xid);
641 return -ENOMEM;
642 }
643
644 if ((pTcon->ses->capabilities & CAP_UNIX) &&
645 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
646 le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
647 rc = CIFSPOSIXDelFile(xid, pTcon, full_path,
648 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
649 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
650 cFYI(1, ("posix del rc %d", rc));
651 if ((rc == 0) || (rc == -ENOENT))
652 goto psx_del_no_retry;
653 }
654
655 rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
656 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
657psx_del_no_retry:
658 if (!rc) {
659 if (direntry->d_inode)
660 drop_nlink(direntry->d_inode);
661 } else if (rc == -ENOENT) {
662 d_drop(direntry);
663 } else if (rc == -ETXTBSY) {
664 int oplock = FALSE;
665 __u16 netfid;
666
667 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
668 CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
669 &netfid, &oplock, NULL, cifs_sb->local_nls,
670 cifs_sb->mnt_cifs_flags &
671 CIFS_MOUNT_MAP_SPECIAL_CHR);
672 if (rc == 0) {
673 CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,
674 cifs_sb->local_nls,
675 cifs_sb->mnt_cifs_flags &
676 CIFS_MOUNT_MAP_SPECIAL_CHR);
677 CIFSSMBClose(xid, pTcon, netfid);
678 if (direntry->d_inode)
679 drop_nlink(direntry->d_inode);
680 }
681 } else if (rc == -EACCES) {
682
683 pinfo_buf = kzalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL);
684 if (pinfo_buf) {
685
686 pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
687 if (!(pTcon->ses->flags & CIFS_SES_NT4))
688 rc = CIFSSMBSetTimes(xid, pTcon, full_path,
689 pinfo_buf,
690 cifs_sb->local_nls,
691 cifs_sb->mnt_cifs_flags &
692 CIFS_MOUNT_MAP_SPECIAL_CHR);
693 else
694 rc = -EOPNOTSUPP;
695
696 if (rc == -EOPNOTSUPP) {
697 int oplock = FALSE;
698 __u16 netfid;
699
700
701
702
703
704
705
706
707
708
709
710 rc = CIFSSMBOpen(xid, pTcon, full_path,
711 FILE_OPEN, SYNCHRONIZE |
712 FILE_WRITE_ATTRIBUTES, 0,
713 &netfid, &oplock, NULL,
714 cifs_sb->local_nls,
715 cifs_sb->mnt_cifs_flags &
716 CIFS_MOUNT_MAP_SPECIAL_CHR);
717 if (rc == 0) {
718 rc = CIFSSMBSetFileTimes(xid, pTcon,
719 pinfo_buf,
720 netfid);
721 CIFSSMBClose(xid, pTcon, netfid);
722 }
723 }
724 kfree(pinfo_buf);
725 }
726 if (rc == 0) {
727 rc = CIFSSMBDelFile(xid, pTcon, full_path,
728 cifs_sb->local_nls,
729 cifs_sb->mnt_cifs_flags &
730 CIFS_MOUNT_MAP_SPECIAL_CHR);
731 if (!rc) {
732 if (direntry->d_inode)
733 drop_nlink(direntry->d_inode);
734 } else if (rc == -ETXTBSY) {
735 int oplock = FALSE;
736 __u16 netfid;
737
738 rc = CIFSSMBOpen(xid, pTcon, full_path,
739 FILE_OPEN, DELETE,
740 CREATE_NOT_DIR |
741 CREATE_DELETE_ON_CLOSE,
742 &netfid, &oplock, NULL,
743 cifs_sb->local_nls,
744 cifs_sb->mnt_cifs_flags &
745 CIFS_MOUNT_MAP_SPECIAL_CHR);
746 if (rc == 0) {
747 CIFSSMBRenameOpenFile(xid, pTcon,
748 netfid, NULL,
749 cifs_sb->local_nls,
750 cifs_sb->mnt_cifs_flags &
751 CIFS_MOUNT_MAP_SPECIAL_CHR);
752 CIFSSMBClose(xid, pTcon, netfid);
753 if (direntry->d_inode)
754 drop_nlink(direntry->d_inode);
755 }
756
757 }
758 }
759 }
760 if (direntry->d_inode) {
761 cifsInode = CIFS_I(direntry->d_inode);
762 cifsInode->time = 0;
763
764 direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
765 }
766 if (inode) {
767 inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
768 cifsInode = CIFS_I(inode);
769 cifsInode->time = 0;
770 }
771
772 kfree(full_path);
773 FreeXid(xid);
774 return rc;
775}
776
777static void posix_fill_in_inode(struct inode *tmp_inode,
778 FILE_UNIX_BASIC_INFO *pData, int *pobject_type, int isNewInode)
779{
780 loff_t local_size;
781 struct timespec local_mtime;
782
783 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
784 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
785
786 __u32 type = le32_to_cpu(pData->Type);
787 __u64 num_of_bytes = le64_to_cpu(pData->NumOfBytes);
788 __u64 end_of_file = le64_to_cpu(pData->EndOfFile);
789 cifsInfo->time = jiffies;
790 atomic_inc(&cifsInfo->inUse);
791
792
793 local_mtime = tmp_inode->i_mtime;
794 local_size = tmp_inode->i_size;
795
796 tmp_inode->i_atime =
797 cifs_NTtimeToUnix(le64_to_cpu(pData->LastAccessTime));
798 tmp_inode->i_mtime =
799 cifs_NTtimeToUnix(le64_to_cpu(pData->LastModificationTime));
800 tmp_inode->i_ctime =
801 cifs_NTtimeToUnix(le64_to_cpu(pData->LastStatusChange));
802
803 tmp_inode->i_mode = le64_to_cpu(pData->Permissions);
804
805
806 tmp_inode->i_mode &= ~S_IFMT;
807 if (type == UNIX_FILE) {
808 *pobject_type = DT_REG;
809 tmp_inode->i_mode |= S_IFREG;
810 } else if (type == UNIX_SYMLINK) {
811 *pobject_type = DT_LNK;
812 tmp_inode->i_mode |= S_IFLNK;
813 } else if (type == UNIX_DIR) {
814 *pobject_type = DT_DIR;
815 tmp_inode->i_mode |= S_IFDIR;
816 } else if (type == UNIX_CHARDEV) {
817 *pobject_type = DT_CHR;
818 tmp_inode->i_mode |= S_IFCHR;
819 tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor),
820 le64_to_cpu(pData->DevMinor) & MINORMASK);
821 } else if (type == UNIX_BLOCKDEV) {
822 *pobject_type = DT_BLK;
823 tmp_inode->i_mode |= S_IFBLK;
824 tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor),
825 le64_to_cpu(pData->DevMinor) & MINORMASK);
826 } else if (type == UNIX_FIFO) {
827 *pobject_type = DT_FIFO;
828 tmp_inode->i_mode |= S_IFIFO;
829 } else if (type == UNIX_SOCKET) {
830 *pobject_type = DT_SOCK;
831 tmp_inode->i_mode |= S_IFSOCK;
832 } else {
833
834 *pobject_type = DT_REG;
835 tmp_inode->i_mode |= S_IFREG;
836 cFYI(1, ("unknown inode type %d", type));
837 }
838
839#ifdef CONFIG_CIFS_DEBUG2
840 cFYI(1, ("object type: %d", type));
841#endif
842 tmp_inode->i_uid = le64_to_cpu(pData->Uid);
843 tmp_inode->i_gid = le64_to_cpu(pData->Gid);
844 tmp_inode->i_nlink = le64_to_cpu(pData->Nlinks);
845
846 spin_lock(&tmp_inode->i_lock);
847 if (is_size_safe_to_change(cifsInfo, end_of_file)) {
848
849
850 i_size_write(tmp_inode, end_of_file);
851
852
853
854 tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
855 }
856 spin_unlock(&tmp_inode->i_lock);
857
858 if (S_ISREG(tmp_inode->i_mode)) {
859 cFYI(1, ("File inode"));
860 tmp_inode->i_op = &cifs_file_inode_ops;
861
862 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
863 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
864 tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
865 else
866 tmp_inode->i_fop = &cifs_file_direct_ops;
867
868 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
869 tmp_inode->i_fop = &cifs_file_nobrl_ops;
870 else
871 tmp_inode->i_fop = &cifs_file_ops;
872
873 if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
874 (cifs_sb->tcon->ses->server->maxBuf <
875 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
876 tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
877 else
878 tmp_inode->i_data.a_ops = &cifs_addr_ops;
879
880 if (isNewInode)
881 return;
882
883
884
885 if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
886 (local_size == tmp_inode->i_size)) {
887 cFYI(1, ("inode exists but unchanged"));
888 } else {
889
890 cFYI(1, ("invalidate inode, readdir detected change"));
891 invalidate_remote_inode(tmp_inode);
892 }
893 } else if (S_ISDIR(tmp_inode->i_mode)) {
894 cFYI(1, ("Directory inode"));
895 tmp_inode->i_op = &cifs_dir_inode_ops;
896 tmp_inode->i_fop = &cifs_dir_ops;
897 } else if (S_ISLNK(tmp_inode->i_mode)) {
898 cFYI(1, ("Symbolic Link inode"));
899 tmp_inode->i_op = &cifs_symlink_inode_ops;
900
901 } else {
902 cFYI(1, ("Special inode"));
903 init_special_inode(tmp_inode, tmp_inode->i_mode,
904 tmp_inode->i_rdev);
905 }
906}
907
908int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
909{
910 int rc = 0;
911 int xid;
912 struct cifs_sb_info *cifs_sb;
913 struct cifsTconInfo *pTcon;
914 char *full_path = NULL;
915 struct inode *newinode = NULL;
916
917 cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode));
918
919 xid = GetXid();
920
921 cifs_sb = CIFS_SB(inode->i_sb);
922 pTcon = cifs_sb->tcon;
923
924 full_path = build_path_from_dentry(direntry);
925 if (full_path == NULL) {
926 FreeXid(xid);
927 return -ENOMEM;
928 }
929
930 if ((pTcon->ses->capabilities & CAP_UNIX) &&
931 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
932 le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
933 u32 oplock = 0;
934 FILE_UNIX_BASIC_INFO * pInfo =
935 kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
936 if (pInfo == NULL) {
937 rc = -ENOMEM;
938 goto mkdir_out;
939 }
940
941 mode &= ~current->fs->umask;
942 rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
943 mode, NULL , pInfo, &oplock,
944 full_path, cifs_sb->local_nls,
945 cifs_sb->mnt_cifs_flags &
946 CIFS_MOUNT_MAP_SPECIAL_CHR);
947 if (rc == -EOPNOTSUPP) {
948 kfree(pInfo);
949 goto mkdir_retry_old;
950 } else if (rc) {
951 cFYI(1, ("posix mkdir returned 0x%x", rc));
952 d_drop(direntry);
953 } else {
954 int obj_type;
955 if (pInfo->Type == cpu_to_le32(-1)) {
956
957 kfree(pInfo);
958 goto mkdir_get_info;
959 }
960
961
962 inc_nlink(inode);
963 if (pTcon->nocase)
964 direntry->d_op = &cifs_ci_dentry_ops;
965 else
966 direntry->d_op = &cifs_dentry_ops;
967
968 newinode = new_inode(inode->i_sb);
969 if (newinode == NULL) {
970 kfree(pInfo);
971 goto mkdir_get_info;
972 }
973
974
975
976 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
977 newinode->i_ino =
978 (unsigned long)pInfo->UniqueId;
979 }
980 if (inode->i_sb->s_flags & MS_NOATIME)
981 newinode->i_flags |= S_NOATIME | S_NOCMTIME;
982 newinode->i_nlink = 2;
983
984 insert_inode_hash(newinode);
985 d_instantiate(direntry, newinode);
986
987
988
989 posix_fill_in_inode(direntry->d_inode,
990 pInfo, &obj_type, 1 );
991#ifdef CONFIG_CIFS_DEBUG2
992 cFYI(1, ("instantiated dentry %p %s to inode %p",
993 direntry, direntry->d_name.name, newinode));
994
995 if (newinode->i_nlink != 2)
996 cFYI(1, ("unexpected number of links %d",
997 newinode->i_nlink));
998#endif
999 }
1000 kfree(pInfo);
1001 goto mkdir_out;
1002 }
1003mkdir_retry_old:
1004
1005 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
1006 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1007 if (rc) {
1008 cFYI(1, ("cifs_mkdir returned 0x%x", rc));
1009 d_drop(direntry);
1010 } else {
1011mkdir_get_info:
1012 inc_nlink(inode);
1013 if (pTcon->unix_ext)
1014 rc = cifs_get_inode_info_unix(&newinode, full_path,
1015 inode->i_sb, xid);
1016 else
1017 rc = cifs_get_inode_info(&newinode, full_path, NULL,
1018 inode->i_sb, xid);
1019
1020 if (pTcon->nocase)
1021 direntry->d_op = &cifs_ci_dentry_ops;
1022 else
1023 direntry->d_op = &cifs_dentry_ops;
1024 d_instantiate(direntry, newinode);
1025
1026
1027 if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
1028 direntry->d_inode->i_nlink = 2;
1029 if (pTcon->unix_ext) {
1030 mode &= ~current->fs->umask;
1031 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1032 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
1033 mode,
1034 (__u64)current->fsuid,
1035 (__u64)current->fsgid,
1036 0 ,
1037 cifs_sb->local_nls,
1038 cifs_sb->mnt_cifs_flags &
1039 CIFS_MOUNT_MAP_SPECIAL_CHR);
1040 } else {
1041 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
1042 mode, (__u64)-1,
1043 (__u64)-1, 0 ,
1044 cifs_sb->local_nls,
1045 cifs_sb->mnt_cifs_flags &
1046 CIFS_MOUNT_MAP_SPECIAL_CHR);
1047 }
1048 } else {
1049
1050
1051
1052 if (direntry->d_inode) {
1053 direntry->d_inode->i_mode = mode;
1054 direntry->d_inode->i_mode |= S_IFDIR;
1055 if (cifs_sb->mnt_cifs_flags &
1056 CIFS_MOUNT_SET_UID) {
1057 direntry->d_inode->i_uid =
1058 current->fsuid;
1059 direntry->d_inode->i_gid =
1060 current->fsgid;
1061 }
1062 }
1063 }
1064 }
1065mkdir_out:
1066 kfree(full_path);
1067 FreeXid(xid);
1068 return rc;
1069}
1070
1071int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1072{
1073 int rc = 0;
1074 int xid;
1075 struct cifs_sb_info *cifs_sb;
1076 struct cifsTconInfo *pTcon;
1077 char *full_path = NULL;
1078 struct cifsInodeInfo *cifsInode;
1079
1080 cFYI(1, ("cifs_rmdir, inode = 0x%p", inode));
1081
1082 xid = GetXid();
1083
1084 cifs_sb = CIFS_SB(inode->i_sb);
1085 pTcon = cifs_sb->tcon;
1086
1087 full_path = build_path_from_dentry(direntry);
1088 if (full_path == NULL) {
1089 FreeXid(xid);
1090 return -ENOMEM;
1091 }
1092
1093 rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
1094 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1095
1096 if (!rc) {
1097 drop_nlink(inode);
1098 spin_lock(&direntry->d_inode->i_lock);
1099 i_size_write(direntry->d_inode, 0);
1100 clear_nlink(direntry->d_inode);
1101 spin_unlock(&direntry->d_inode->i_lock);
1102 }
1103
1104 cifsInode = CIFS_I(direntry->d_inode);
1105 cifsInode->time = 0;
1106
1107 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
1108 current_fs_time(inode->i_sb);
1109
1110 kfree(full_path);
1111 FreeXid(xid);
1112 return rc;
1113}
1114
1115int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
1116 struct inode *target_inode, struct dentry *target_direntry)
1117{
1118 char *fromName;
1119 char *toName;
1120 struct cifs_sb_info *cifs_sb_source;
1121 struct cifs_sb_info *cifs_sb_target;
1122 struct cifsTconInfo *pTcon;
1123 int xid;
1124 int rc = 0;
1125
1126 xid = GetXid();
1127
1128 cifs_sb_target = CIFS_SB(target_inode->i_sb);
1129 cifs_sb_source = CIFS_SB(source_inode->i_sb);
1130 pTcon = cifs_sb_source->tcon;
1131
1132 if (pTcon != cifs_sb_target->tcon) {
1133 FreeXid(xid);
1134 return -EXDEV;
1135
1136
1137 }
1138
1139
1140
1141 fromName = build_path_from_dentry(source_direntry);
1142 toName = build_path_from_dentry(target_direntry);
1143 if ((fromName == NULL) || (toName == NULL)) {
1144 rc = -ENOMEM;
1145 goto cifs_rename_exit;
1146 }
1147
1148 rc = CIFSSMBRename(xid, pTcon, fromName, toName,
1149 cifs_sb_source->local_nls,
1150 cifs_sb_source->mnt_cifs_flags &
1151 CIFS_MOUNT_MAP_SPECIAL_CHR);
1152 if (rc == -EEXIST) {
1153
1154
1155 FILE_UNIX_BASIC_INFO *info_buf_source;
1156 FILE_UNIX_BASIC_INFO *info_buf_target;
1157
1158 info_buf_source =
1159 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1160 if (info_buf_source != NULL) {
1161 info_buf_target = info_buf_source + 1;
1162 if (pTcon->unix_ext)
1163 rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
1164 info_buf_source,
1165 cifs_sb_source->local_nls,
1166 cifs_sb_source->mnt_cifs_flags &
1167 CIFS_MOUNT_MAP_SPECIAL_CHR);
1168
1169
1170 if (rc == 0) {
1171 rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName,
1172 info_buf_target,
1173 cifs_sb_target->local_nls,
1174
1175 cifs_sb_source->mnt_cifs_flags &
1176 CIFS_MOUNT_MAP_SPECIAL_CHR);
1177 }
1178 if ((rc == 0) &&
1179 (info_buf_source->UniqueId ==
1180 info_buf_target->UniqueId)) {
1181
1182
1183 } else {
1184
1185
1186
1187
1188
1189 cifs_unlink(target_inode, target_direntry);
1190 rc = CIFSSMBRename(xid, pTcon, fromName,
1191 toName,
1192 cifs_sb_source->local_nls,
1193 cifs_sb_source->mnt_cifs_flags
1194 & CIFS_MOUNT_MAP_SPECIAL_CHR);
1195 }
1196 kfree(info_buf_source);
1197 }
1198 }
1199
1200 if (rc) {
1201 cFYI(1, ("rename rc %d", rc));
1202 }
1203
1204 if ((rc == -EIO) || (rc == -EEXIST)) {
1205 int oplock = FALSE;
1206 __u16 netfid;
1207
1208
1209
1210
1211
1212 rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
1213 CREATE_NOT_DIR, &netfid, &oplock, NULL,
1214 cifs_sb_source->local_nls,
1215 cifs_sb_source->mnt_cifs_flags &
1216 CIFS_MOUNT_MAP_SPECIAL_CHR);
1217 if (rc == 0) {
1218 rc = CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
1219 cifs_sb_source->local_nls,
1220 cifs_sb_source->mnt_cifs_flags &
1221 CIFS_MOUNT_MAP_SPECIAL_CHR);
1222 CIFSSMBClose(xid, pTcon, netfid);
1223 }
1224 }
1225
1226cifs_rename_exit:
1227 kfree(fromName);
1228 kfree(toName);
1229 FreeXid(xid);
1230 return rc;
1231}
1232
1233int cifs_revalidate(struct dentry *direntry)
1234{
1235 int xid;
1236 int rc = 0, wbrc = 0;
1237 char *full_path;
1238 struct cifs_sb_info *cifs_sb;
1239 struct cifsInodeInfo *cifsInode;
1240 loff_t local_size;
1241 struct timespec local_mtime;
1242 int invalidate_inode = FALSE;
1243
1244 if (direntry->d_inode == NULL)
1245 return -ENOENT;
1246
1247 cifsInode = CIFS_I(direntry->d_inode);
1248
1249 if (cifsInode == NULL)
1250 return -ENOENT;
1251
1252
1253 if (CIFS_I(direntry->d_inode)->clientCanCacheRead)
1254 return rc;
1255
1256 xid = GetXid();
1257
1258 cifs_sb = CIFS_SB(direntry->d_sb);
1259
1260
1261
1262 full_path = build_path_from_dentry(direntry);
1263 if (full_path == NULL) {
1264 FreeXid(xid);
1265 return -ENOMEM;
1266 }
1267 cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
1268 "jiffies %ld", full_path, direntry->d_inode,
1269 direntry->d_inode->i_count.counter, direntry,
1270 direntry->d_time, jiffies));
1271
1272 if (cifsInode->time == 0) {
1273
1274 } else if (time_before(jiffies, cifsInode->time + HZ) &&
1275 lookupCacheEnabled) {
1276 if ((S_ISREG(direntry->d_inode->i_mode) == 0) ||
1277 (direntry->d_inode->i_nlink == 1)) {
1278 kfree(full_path);
1279 FreeXid(xid);
1280 return rc;
1281 } else {
1282 cFYI(1, ("Have to revalidate file due to hardlinks"));
1283 }
1284 }
1285
1286
1287 local_mtime = direntry->d_inode->i_mtime;
1288 local_size = direntry->d_inode->i_size;
1289
1290 if (cifs_sb->tcon->unix_ext) {
1291 rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
1292 direntry->d_sb, xid);
1293 if (rc) {
1294 cFYI(1, ("error on getting revalidate info %d", rc));
1295
1296
1297
1298 }
1299 } else {
1300 rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
1301 direntry->d_sb, xid);
1302 if (rc) {
1303 cFYI(1, ("error on getting revalidate info %d", rc));
1304
1305
1306
1307 }
1308 }
1309
1310
1311
1312
1313
1314 if (timespec_equal(&local_mtime, &direntry->d_inode->i_mtime) &&
1315 (local_size == direntry->d_inode->i_size)) {
1316 cFYI(1, ("cifs_revalidate - inode unchanged"));
1317 } else {
1318
1319 if (cifsInode->clientCanCacheRead) {
1320
1321
1322
1323 } else {
1324 invalidate_inode = TRUE;
1325 }
1326 }
1327
1328
1329
1330
1331
1332
1333 if (direntry->d_inode->i_mapping) {
1334
1335
1336 wbrc = filemap_fdatawrite(direntry->d_inode->i_mapping);
1337 if (wbrc)
1338 CIFS_I(direntry->d_inode)->write_behind_rc = wbrc;
1339 }
1340 if (invalidate_inode) {
1341
1342
1343
1344
1345 if (S_ISREG(direntry->d_inode->i_mode)) {
1346 if (direntry->d_inode->i_mapping)
1347 wbrc = filemap_fdatawait(direntry->d_inode->i_mapping);
1348 if (wbrc)
1349 CIFS_I(direntry->d_inode)->write_behind_rc = wbrc;
1350
1351 if (list_empty(&(cifsInode->openFileList))) {
1352
1353 cFYI(1, ("Invalidating read ahead data on "
1354 "closed file"));
1355 invalidate_remote_inode(direntry->d_inode);
1356 }
1357 }
1358 }
1359
1360
1361 kfree(full_path);
1362 FreeXid(xid);
1363 return rc;
1364}
1365
1366int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
1367 struct kstat *stat)
1368{
1369 int err = cifs_revalidate(dentry);
1370 if (!err) {
1371 generic_fillattr(dentry->d_inode, stat);
1372 stat->blksize = CIFS_MAX_MSGSIZE;
1373 }
1374 return err;
1375}
1376
1377static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1378{
1379 pgoff_t index = from >> PAGE_CACHE_SHIFT;
1380 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
1381 struct page *page;
1382 int rc = 0;
1383
1384 page = grab_cache_page(mapping, index);
1385 if (!page)
1386 return -ENOMEM;
1387
1388 zero_user_page(page, offset, PAGE_CACHE_SIZE - offset, KM_USER0);
1389 unlock_page(page);
1390 page_cache_release(page);
1391 return rc;
1392}
1393
1394static int cifs_vmtruncate(struct inode *inode, loff_t offset)
1395{
1396 struct address_space *mapping = inode->i_mapping;
1397 unsigned long limit;
1398
1399 spin_lock(&inode->i_lock);
1400 if (inode->i_size < offset)
1401 goto do_expand;
1402
1403
1404
1405
1406 if (IS_SWAPFILE(inode)) {
1407 spin_unlock(&inode->i_lock);
1408 goto out_busy;
1409 }
1410 i_size_write(inode, offset);
1411 spin_unlock(&inode->i_lock);
1412
1413
1414
1415
1416
1417
1418
1419
1420 unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
1421 truncate_inode_pages(mapping, offset);
1422 unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
1423 goto out_truncate;
1424
1425do_expand:
1426 limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
1427 if (limit != RLIM_INFINITY && offset > limit) {
1428 spin_unlock(&inode->i_lock);
1429 goto out_sig;
1430 }
1431 if (offset > inode->i_sb->s_maxbytes) {
1432 spin_unlock(&inode->i_lock);
1433 goto out_big;
1434 }
1435 i_size_write(inode, offset);
1436 spin_unlock(&inode->i_lock);
1437out_truncate:
1438 if (inode->i_op && inode->i_op->truncate)
1439 inode->i_op->truncate(inode);
1440 return 0;
1441out_sig:
1442 send_sig(SIGXFSZ, current, 0);
1443out_big:
1444 return -EFBIG;
1445out_busy:
1446 return -ETXTBSY;
1447}
1448
1449int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1450{
1451 int xid;
1452 struct cifs_sb_info *cifs_sb;
1453 struct cifsTconInfo *pTcon;
1454 char *full_path = NULL;
1455 int rc = -EACCES;
1456 struct cifsFileInfo *open_file = NULL;
1457 FILE_BASIC_INFO time_buf;
1458 int set_time = FALSE;
1459 int set_dosattr = FALSE;
1460 __u64 mode = 0xFFFFFFFFFFFFFFFFULL;
1461 __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
1462 __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
1463 struct cifsInodeInfo *cifsInode;
1464
1465 xid = GetXid();
1466
1467 cFYI(1, ("setattr on file %s attrs->iavalid 0x%x",
1468 direntry->d_name.name, attrs->ia_valid));
1469
1470 cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
1471 pTcon = cifs_sb->tcon;
1472
1473 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
1474
1475 rc = inode_change_ok(direntry->d_inode, attrs);
1476 if (rc < 0) {
1477 FreeXid(xid);
1478 return rc;
1479 } else
1480 rc = 0;
1481 }
1482
1483 full_path = build_path_from_dentry(direntry);
1484 if (full_path == NULL) {
1485 FreeXid(xid);
1486 return -ENOMEM;
1487 }
1488 cifsInode = CIFS_I(direntry->d_inode);
1489
1490
1491
1492 if (attrs->ia_valid & ATTR_SIZE) {
1493
1494
1495
1496
1497
1498
1499
1500 rc = filemap_write_and_wait(direntry->d_inode->i_mapping);
1501 if (rc != 0) {
1502 CIFS_I(direntry->d_inode)->write_behind_rc = rc;
1503 rc = 0;
1504 }
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514 open_file = find_writable_file(cifsInode);
1515 if (open_file) {
1516 __u16 nfid = open_file->netfid;
1517 __u32 npid = open_file->pid;
1518 rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
1519 nfid, npid, FALSE);
1520 atomic_dec(&open_file->wrtPending);
1521 cFYI(1, ("SetFSize for attrs rc = %d", rc));
1522 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1523 unsigned int bytes_written;
1524 rc = CIFSSMBWrite(xid, pTcon,
1525 nfid, 0, attrs->ia_size,
1526 &bytes_written, NULL, NULL,
1527 1 );
1528 cFYI(1, ("Wrt seteof rc %d", rc));
1529 }
1530 } else
1531 rc = -EINVAL;
1532
1533 if (rc != 0) {
1534
1535
1536
1537
1538 rc = CIFSSMBSetEOF(xid, pTcon, full_path,
1539 attrs->ia_size, FALSE,
1540 cifs_sb->local_nls,
1541 cifs_sb->mnt_cifs_flags &
1542 CIFS_MOUNT_MAP_SPECIAL_CHR);
1543 cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
1544 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1545 __u16 netfid;
1546 int oplock = FALSE;
1547
1548 rc = SMBLegacyOpen(xid, pTcon, full_path,
1549 FILE_OPEN,
1550 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1551 CREATE_NOT_DIR, &netfid, &oplock,
1552 NULL, cifs_sb->local_nls,
1553 cifs_sb->mnt_cifs_flags &
1554 CIFS_MOUNT_MAP_SPECIAL_CHR);
1555 if (rc == 0) {
1556 unsigned int bytes_written;
1557 rc = CIFSSMBWrite(xid, pTcon,
1558 netfid, 0,
1559 attrs->ia_size,
1560 &bytes_written, NULL,
1561 NULL, 1 );
1562 cFYI(1, ("wrt seteof rc %d", rc));
1563 CIFSSMBClose(xid, pTcon, netfid);
1564 }
1565
1566 }
1567 }
1568
1569
1570
1571
1572
1573
1574
1575 if (rc == 0) {
1576 rc = cifs_vmtruncate(direntry->d_inode, attrs->ia_size);
1577 cifs_truncate_page(direntry->d_inode->i_mapping,
1578 direntry->d_inode->i_size);
1579 } else
1580 goto cifs_setattr_exit;
1581 }
1582 if (attrs->ia_valid & ATTR_UID) {
1583 cFYI(1, ("UID changed to %d", attrs->ia_uid));
1584 uid = attrs->ia_uid;
1585 }
1586 if (attrs->ia_valid & ATTR_GID) {
1587 cFYI(1, ("GID changed to %d", attrs->ia_gid));
1588 gid = attrs->ia_gid;
1589 }
1590
1591 time_buf.Attributes = 0;
1592
1593
1594 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
1595 attrs->ia_valid &= ~ATTR_MODE;
1596
1597 if (attrs->ia_valid & ATTR_MODE) {
1598 cFYI(1, ("Mode changed to 0x%x", attrs->ia_mode));
1599 mode = attrs->ia_mode;
1600 }
1601
1602 if ((pTcon->unix_ext)
1603 && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
1604 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
1605 0 , cifs_sb->local_nls,
1606 cifs_sb->mnt_cifs_flags &
1607 CIFS_MOUNT_MAP_SPECIAL_CHR);
1608 else if (attrs->ia_valid & ATTR_MODE) {
1609 rc = 0;
1610 if ((mode & S_IWUGO) == 0) {
1611 if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
1612 set_dosattr = TRUE;
1613 time_buf.Attributes =
1614 cpu_to_le32(cifsInode->cifsAttrs |
1615 ATTR_READONLY);
1616 }
1617 } else if (cifsInode->cifsAttrs & ATTR_READONLY) {
1618
1619
1620
1621
1622 set_dosattr = TRUE;
1623 time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs &
1624 (~ATTR_READONLY));
1625
1626 if (time_buf.Attributes == 0)
1627 time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL);
1628 }
1629
1630
1631
1632
1633 }
1634
1635 if (attrs->ia_valid & ATTR_ATIME) {
1636 set_time = TRUE;
1637 time_buf.LastAccessTime =
1638 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
1639 } else
1640 time_buf.LastAccessTime = 0;
1641
1642 if (attrs->ia_valid & ATTR_MTIME) {
1643 set_time = TRUE;
1644 time_buf.LastWriteTime =
1645 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1646 } else
1647 time_buf.LastWriteTime = 0;
1648
1649
1650
1651
1652
1653 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
1654 set_time = TRUE;
1655
1656
1657
1658
1659 cFYI(1, ("CIFS - CTIME changed"));
1660 time_buf.ChangeTime =
1661 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1662 } else
1663 time_buf.ChangeTime = 0;
1664
1665 if (set_time || set_dosattr) {
1666 time_buf.CreationTime = 0;
1667
1668
1669 if (!(pTcon->ses->flags & CIFS_SES_NT4))
1670 rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
1671 cifs_sb->local_nls,
1672 cifs_sb->mnt_cifs_flags &
1673 CIFS_MOUNT_MAP_SPECIAL_CHR);
1674 else
1675 rc = -EOPNOTSUPP;
1676
1677 if (rc == -EOPNOTSUPP) {
1678 int oplock = FALSE;
1679 __u16 netfid;
1680
1681 cFYI(1, ("calling SetFileInfo since SetPathInfo for "
1682 "times not supported by this server"));
1683
1684
1685 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
1686 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1687 CREATE_NOT_DIR, &netfid, &oplock,
1688 NULL, cifs_sb->local_nls,
1689 cifs_sb->mnt_cifs_flags &
1690 CIFS_MOUNT_MAP_SPECIAL_CHR);
1691 if (rc == 0) {
1692 rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
1693 netfid);
1694 CIFSSMBClose(xid, pTcon, netfid);
1695 } else {
1696
1697
1698
1699
1700
1701
1702 }
1703 }
1704
1705
1706
1707
1708
1709 if ((rc) && (attrs->ia_valid &
1710 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
1711 rc = 0;
1712 }
1713
1714
1715
1716 if (!rc)
1717 rc = inode_setattr(direntry->d_inode, attrs);
1718cifs_setattr_exit:
1719 kfree(full_path);
1720 FreeXid(xid);
1721 return rc;
1722}
1723
1724#if 0
1725void cifs_delete_inode(struct inode *inode)
1726{
1727 cFYI(1, ("In cifs_delete_inode, inode = 0x%p", inode));
1728
1729
1730}
1731#endif
1732