[CIFS] Make CIFS statistics more accurate and add some stats that were
[linux-2.6-block.git] / fs / cifs / inode.c
CommitLineData
1da177e4
LT
1/*
2 * fs/cifs/inode.c
3 *
4 * Copyright (C) International Business Machines Corp., 2002,2005
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>
22#include <linux/buffer_head.h>
23#include <linux/stat.h>
24#include <linux/pagemap.h>
25#include <asm/div64.h>
26#include "cifsfs.h"
27#include "cifspdu.h"
28#include "cifsglob.h"
29#include "cifsproto.h"
30#include "cifs_debug.h"
31#include "cifs_fs_sb.h"
32
33int cifs_get_inode_info_unix(struct inode **pinode,
34 const unsigned char *search_path, struct super_block *sb, int xid)
35{
36 int rc = 0;
37 FILE_UNIX_BASIC_INFO findData;
38 struct cifsTconInfo *pTcon;
39 struct inode *inode;
40 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
41 char *tmp_path;
42
43 pTcon = cifs_sb->tcon;
44 cFYI(1, (" Getting info on %s ", search_path));
45 /* could have done a find first instead but this returns more info */
46 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
737b758c
SF
47 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
48 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
49/* dump_mem("\nUnixQPathInfo return data", &findData,
50 sizeof(findData)); */
51 if (rc) {
52 if (rc == -EREMOTE) {
53 tmp_path =
54 kmalloc(strnlen(pTcon->treeName,
55 MAX_TREE_SIZE + 1) +
56 strnlen(search_path, MAX_PATHCONF) + 1,
57 GFP_KERNEL);
58 if (tmp_path == NULL) {
59 return -ENOMEM;
60 }
61 /* have to skip first of the double backslash of
62 UNC name */
63 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
64 strncat(tmp_path, search_path, MAX_PATHCONF);
65 rc = connect_to_dfs_path(xid, pTcon->ses,
66 /* treename + */ tmp_path,
737b758c
SF
67 cifs_sb->local_nls,
68 cifs_sb->mnt_cifs_flags &
69 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
70 kfree(tmp_path);
71
72 /* BB fix up inode etc. */
73 } else if (rc) {
74 return rc;
75 }
76 } else {
77 struct cifsInodeInfo *cifsInfo;
78 __u32 type = le32_to_cpu(findData.Type);
79 __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
80 __u64 end_of_file = le64_to_cpu(findData.EndOfFile);
81
82 /* get new inode */
83 if (*pinode == NULL) {
84 *pinode = new_inode(sb);
d0d2f2df 85 if (*pinode == NULL)
1da177e4
LT
86 return -ENOMEM;
87 /* Is an i_ino of zero legal? */
88 /* Are there sanity checks we can use to ensure that
89 the server is really filling in that field? */
d0d2f2df 90 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
1da177e4
LT
91 (*pinode)->i_ino =
92 (unsigned long)findData.UniqueId;
93 } /* note ino incremented to unique num in new_inode */
94 insert_inode_hash(*pinode);
95 }
96
97 inode = *pinode;
98 cifsInfo = CIFS_I(inode);
99
100 cFYI(1, (" Old time %ld ", cifsInfo->time));
101 cifsInfo->time = jiffies;
102 cFYI(1, (" New time %ld ", cifsInfo->time));
103 /* this is ok to set on every inode revalidate */
104 atomic_set(&cifsInfo->inUse,1);
105
106 inode->i_atime =
107 cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
108 inode->i_mtime =
109 cifs_NTtimeToUnix(le64_to_cpu
110 (findData.LastModificationTime));
111 inode->i_ctime =
112 cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
113 inode->i_mode = le64_to_cpu(findData.Permissions);
114 if (type == UNIX_FILE) {
115 inode->i_mode |= S_IFREG;
116 } else if (type == UNIX_SYMLINK) {
117 inode->i_mode |= S_IFLNK;
118 } else if (type == UNIX_DIR) {
119 inode->i_mode |= S_IFDIR;
120 } else if (type == UNIX_CHARDEV) {
121 inode->i_mode |= S_IFCHR;
122 inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
123 le64_to_cpu(findData.DevMinor) & MINORMASK);
124 } else if (type == UNIX_BLOCKDEV) {
125 inode->i_mode |= S_IFBLK;
126 inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
127 le64_to_cpu(findData.DevMinor) & MINORMASK);
128 } else if (type == UNIX_FIFO) {
129 inode->i_mode |= S_IFIFO;
130 } else if (type == UNIX_SOCKET) {
131 inode->i_mode |= S_IFSOCK;
132 }
133 inode->i_uid = le64_to_cpu(findData.Uid);
134 inode->i_gid = le64_to_cpu(findData.Gid);
135 inode->i_nlink = le64_to_cpu(findData.Nlinks);
136
d0d2f2df 137 if (is_size_safe_to_change(cifsInfo)) {
1da177e4
LT
138 /* can not safely change the file size here if the
139 client is writing to it due to potential races */
140
141 i_size_write(inode, end_of_file);
142
143 /* blksize needs to be multiple of two. So safer to default to
144 blksize and blkbits set in superblock so 2**blkbits and blksize
145 will match rather than setting to:
146 (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
147
148 /* This seems incredibly stupid but it turns out that i_blocks
149 is not related to (i_size / i_blksize), instead 512 byte size
150 is required for calculating num blocks */
151
152 /* 512 bytes (2**9) is the fake blocksize that must be used */
153 /* for this calculation */
154 inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
155 }
156
157 if (num_of_bytes < end_of_file)
158 cFYI(1, ("allocation size less than end of file "));
159 cFYI(1,
160 ("Size %ld and blocks %ld",
161 (unsigned long) inode->i_size, inode->i_blocks));
162 if (S_ISREG(inode->i_mode)) {
163 cFYI(1, (" File inode "));
164 inode->i_op = &cifs_file_inode_ops;
d0d2f2df 165 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
1da177e4
LT
166 inode->i_fop = &cifs_file_direct_ops;
167 else
168 inode->i_fop = &cifs_file_ops;
c46fa8ac
SF
169 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
170 inode->i_fop->lock = NULL;
1da177e4
LT
171 inode->i_data.a_ops = &cifs_addr_ops;
172 } else if (S_ISDIR(inode->i_mode)) {
173 cFYI(1, (" Directory inode"));
174 inode->i_op = &cifs_dir_inode_ops;
175 inode->i_fop = &cifs_dir_ops;
176 } else if (S_ISLNK(inode->i_mode)) {
177 cFYI(1, (" Symbolic Link inode "));
178 inode->i_op = &cifs_symlink_inode_ops;
179 /* tmp_inode->i_fop = */ /* do not need to set to anything */
180 } else {
181 cFYI(1, (" Init special inode "));
182 init_special_inode(inode, inode->i_mode,
183 inode->i_rdev);
184 }
185 }
186 return rc;
187}
188
189int cifs_get_inode_info(struct inode **pinode,
190 const unsigned char *search_path, FILE_ALL_INFO *pfindData,
191 struct super_block *sb, int xid)
192{
193 int rc = 0;
194 struct cifsTconInfo *pTcon;
195 struct inode *inode;
196 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
197 char *tmp_path;
198 char *buf = NULL;
199
200 pTcon = cifs_sb->tcon;
201 cFYI(1,("Getting info on %s ", search_path));
202
d0d2f2df
SF
203 if ((pfindData == NULL) && (*pinode != NULL)) {
204 if (CIFS_I(*pinode)->clientCanCacheRead) {
1da177e4
LT
205 cFYI(1,("No need to revalidate cached inode sizes"));
206 return rc;
207 }
208 }
209
210 /* if file info not passed in then get it from server */
d0d2f2df 211 if (pfindData == NULL) {
1da177e4 212 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
d0d2f2df 213 if (buf == NULL)
1da177e4
LT
214 return -ENOMEM;
215 pfindData = (FILE_ALL_INFO *)buf;
216 /* could do find first instead but this returns more info */
217 rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
737b758c
SF
218 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
219 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
220 }
221 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
222 if (rc) {
223 if (rc == -EREMOTE) {
224 tmp_path =
225 kmalloc(strnlen
226 (pTcon->treeName,
227 MAX_TREE_SIZE + 1) +
228 strnlen(search_path, MAX_PATHCONF) + 1,
229 GFP_KERNEL);
230 if (tmp_path == NULL) {
231 kfree(buf);
232 return -ENOMEM;
233 }
234
235 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
236 strncat(tmp_path, search_path, MAX_PATHCONF);
237 rc = connect_to_dfs_path(xid, pTcon->ses,
238 /* treename + */ tmp_path,
737b758c
SF
239 cifs_sb->local_nls,
240 cifs_sb->mnt_cifs_flags &
241 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
242 kfree(tmp_path);
243 /* BB fix up inode etc. */
244 } else if (rc) {
245 kfree(buf);
246 return rc;
247 }
248 } else {
249 struct cifsInodeInfo *cifsInfo;
250 __u32 attr = le32_to_cpu(pfindData->Attributes);
251
252 /* get new inode */
253 if (*pinode == NULL) {
254 *pinode = new_inode(sb);
255 if (*pinode == NULL)
256 return -ENOMEM;
257 /* Is an i_ino of zero legal? Can we use that to check
258 if the server supports returning inode numbers? Are
259 there other sanity checks we can use to ensure that
260 the server is really filling in that field? */
261
262 /* We can not use the IndexNumber field by default from
263 Windows or Samba (in ALL_INFO buf) but we can request
264 it explicitly. It may not be unique presumably if
265 the server has multiple devices mounted under one
266 share */
267
268 /* There may be higher info levels that work but are
269 there Windows server or network appliances for which
270 IndexNumber field is not guaranteed unique? */
271
272#ifdef CONFIG_CIFS_EXPERIMENTAL
d0d2f2df 273 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
1da177e4
LT
274 int rc1 = 0;
275 __u64 inode_num;
276
277 rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
278 search_path, &inode_num,
737b758c
SF
279 cifs_sb->local_nls,
280 cifs_sb->mnt_cifs_flags &
281 CIFS_MOUNT_MAP_SPECIAL_CHR);
d0d2f2df 282 if (rc1) {
1da177e4
LT
283 cFYI(1,("GetSrvInodeNum rc %d", rc1));
284 /* BB EOPNOSUPP disable SERVER_INUM? */
285 } else /* do we need cast or hash to ino? */
286 (*pinode)->i_ino = inode_num;
287 } /* else ino incremented to unique num in new_inode*/
288#endif /* CIFS_EXPERIMENTAL */
289 insert_inode_hash(*pinode);
290 }
291 inode = *pinode;
292 cifsInfo = CIFS_I(inode);
293 cifsInfo->cifsAttrs = attr;
294 cFYI(1, (" Old time %ld ", cifsInfo->time));
295 cifsInfo->time = jiffies;
296 cFYI(1, (" New time %ld ", cifsInfo->time));
297
298 /* blksize needs to be multiple of two. So safer to default to
299 blksize and blkbits set in superblock so 2**blkbits and blksize
300 will match rather than setting to:
301 (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
302
303 /* Linux can not store file creation time unfortunately so we ignore it */
304 inode->i_atime =
305 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
306 inode->i_mtime =
307 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
308 inode->i_ctime =
309 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
310 cFYI(0, (" Attributes came in as 0x%x ", attr));
311
312 /* set default mode. will override for dirs below */
313 if (atomic_read(&cifsInfo->inUse) == 0)
314 /* new inode, can safely set these fields */
315 inode->i_mode = cifs_sb->mnt_file_mode;
316
317/* if (attr & ATTR_REPARSE) */
318 /* We no longer handle these as symlinks because we could not
319 follow them due to the absolute path with drive letter */
320 if (attr & ATTR_DIRECTORY) {
321 /* override default perms since we do not do byte range locking
322 on dirs */
323 inode->i_mode = cifs_sb->mnt_dir_mode;
324 inode->i_mode |= S_IFDIR;
eda3c029
SF
325 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
326 (cifsInfo->cifsAttrs & ATTR_SYSTEM) &&
327 /* No need to le64 convert size of zero */
328 (pfindData->EndOfFile == 0)) {
329 inode->i_mode = cifs_sb->mnt_file_mode;
330 inode->i_mode |= S_IFIFO;
331/* BB Finish for SFU style symlinks and devies */
332/* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
333 (cifsInfo->cifsAttrs & ATTR_SYSTEM) && ) */
334
1da177e4
LT
335 } else {
336 inode->i_mode |= S_IFREG;
337 /* treat the dos attribute of read-only as read-only
338 mode e.g. 555 */
339 if (cifsInfo->cifsAttrs & ATTR_READONLY)
340 inode->i_mode &= ~(S_IWUGO);
341 /* BB add code here -
342 validate if device or weird share or device type? */
343 }
344 if (is_size_safe_to_change(cifsInfo)) {
345 /* can not safely change the file size here if the
346 client is writing to it due to potential races */
347 i_size_write(inode,le64_to_cpu(pfindData->EndOfFile));
348
349 /* 512 bytes (2**9) is the fake blocksize that must be
350 used for this calculation */
351 inode->i_blocks = (512 - 1 + le64_to_cpu(
352 pfindData->AllocationSize)) >> 9;
353 }
354
355 inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
356
357 /* BB fill in uid and gid here? with help from winbind?
358 or retrieve from NTFS stream extended attribute */
359 if (atomic_read(&cifsInfo->inUse) == 0) {
360 inode->i_uid = cifs_sb->mnt_uid;
361 inode->i_gid = cifs_sb->mnt_gid;
362 /* set so we do not keep refreshing these fields with
363 bad data after user has changed them in memory */
364 atomic_set(&cifsInfo->inUse,1);
365 }
366
367 if (S_ISREG(inode->i_mode)) {
368 cFYI(1, (" File inode "));
369 inode->i_op = &cifs_file_inode_ops;
d0d2f2df 370 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
1da177e4
LT
371 inode->i_fop = &cifs_file_direct_ops;
372 else
373 inode->i_fop = &cifs_file_ops;
c46fa8ac
SF
374 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
375 inode->i_fop->lock = NULL;
1da177e4
LT
376 inode->i_data.a_ops = &cifs_addr_ops;
377 } else if (S_ISDIR(inode->i_mode)) {
378 cFYI(1, (" Directory inode "));
379 inode->i_op = &cifs_dir_inode_ops;
380 inode->i_fop = &cifs_dir_ops;
381 } else if (S_ISLNK(inode->i_mode)) {
382 cFYI(1, (" Symbolic Link inode "));
383 inode->i_op = &cifs_symlink_inode_ops;
384 } else {
385 init_special_inode(inode, inode->i_mode,
386 inode->i_rdev);
387 }
388 }
389 kfree(buf);
390 return rc;
391}
392
393/* gets root inode */
394void cifs_read_inode(struct inode *inode)
395{
396 int xid;
397 struct cifs_sb_info *cifs_sb;
398
399 cifs_sb = CIFS_SB(inode->i_sb);
400 xid = GetXid();
401 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
402 cifs_get_inode_info_unix(&inode, "", inode->i_sb,xid);
403 else
404 cifs_get_inode_info(&inode, "", NULL, inode->i_sb,xid);
405 /* can not call macro FreeXid here since in a void func */
406 _FreeXid(xid);
407}
408
409int cifs_unlink(struct inode *inode, struct dentry *direntry)
410{
411 int rc = 0;
412 int xid;
413 struct cifs_sb_info *cifs_sb;
414 struct cifsTconInfo *pTcon;
415 char *full_path = NULL;
416 struct cifsInodeInfo *cifsInode;
417 FILE_BASIC_INFO *pinfo_buf;
418
419 cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode));
420
421 xid = GetXid();
422
423 cifs_sb = CIFS_SB(inode->i_sb);
424 pTcon = cifs_sb->tcon;
425
426 /* Unlink can be called from rename so we can not grab the sem here
427 since we deadlock otherwise */
428/* down(&direntry->d_sb->s_vfs_rename_sem);*/
ac67055e 429 full_path = build_path_from_dentry(direntry, cifs_sb);
1da177e4
LT
430/* up(&direntry->d_sb->s_vfs_rename_sem);*/
431 if (full_path == NULL) {
432 FreeXid(xid);
433 return -ENOMEM;
434 }
737b758c
SF
435 rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
436 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
437
438 if (!rc) {
d0d2f2df 439 if (direntry->d_inode)
b2aeb9d5 440 direntry->d_inode->i_nlink--;
1da177e4
LT
441 } else if (rc == -ENOENT) {
442 d_drop(direntry);
443 } else if (rc == -ETXTBSY) {
444 int oplock = FALSE;
445 __u16 netfid;
446
447 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
448 CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
737b758c
SF
449 &netfid, &oplock, NULL, cifs_sb->local_nls,
450 cifs_sb->mnt_cifs_flags &
451 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
452 if (rc==0) {
453 CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,
737b758c
SF
454 cifs_sb->local_nls,
455 cifs_sb->mnt_cifs_flags &
456 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4 457 CIFSSMBClose(xid, pTcon, netfid);
d0d2f2df 458 if (direntry->d_inode)
b2aeb9d5 459 direntry->d_inode->i_nlink--;
1da177e4
LT
460 }
461 } else if (rc == -EACCES) {
462 /* try only if r/o attribute set in local lookup data? */
463 pinfo_buf = kmalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL);
464 if (pinfo_buf) {
465 memset(pinfo_buf, 0, sizeof(FILE_BASIC_INFO));
466 /* ATTRS set to normal clears r/o bit */
467 pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
468 if (!(pTcon->ses->flags & CIFS_SES_NT4))
469 rc = CIFSSMBSetTimes(xid, pTcon, full_path,
470 pinfo_buf,
737b758c
SF
471 cifs_sb->local_nls,
472 cifs_sb->mnt_cifs_flags &
473 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
474 else
475 rc = -EOPNOTSUPP;
476
477 if (rc == -EOPNOTSUPP) {
478 int oplock = FALSE;
479 __u16 netfid;
480 /* rc = CIFSSMBSetAttrLegacy(xid, pTcon,
481 full_path,
482 (__u16)ATTR_NORMAL,
483 cifs_sb->local_nls);
484 For some strange reason it seems that NT4 eats the
485 old setattr call without actually setting the
486 attributes so on to the third attempted workaround
487 */
488
489 /* BB could scan to see if we already have it open
490 and pass in pid of opener to function */
491 rc = CIFSSMBOpen(xid, pTcon, full_path,
492 FILE_OPEN, SYNCHRONIZE |
493 FILE_WRITE_ATTRIBUTES, 0,
494 &netfid, &oplock, NULL,
737b758c
SF
495 cifs_sb->local_nls,
496 cifs_sb->mnt_cifs_flags &
497 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
498 if (rc==0) {
499 rc = CIFSSMBSetFileTimes(xid, pTcon,
500 pinfo_buf,
501 netfid);
502 CIFSSMBClose(xid, pTcon, netfid);
503 }
504 }
505 kfree(pinfo_buf);
506 }
507 if (rc==0) {
737b758c
SF
508 rc = CIFSSMBDelFile(xid, pTcon, full_path,
509 cifs_sb->local_nls,
510 cifs_sb->mnt_cifs_flags &
511 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4 512 if (!rc) {
d0d2f2df 513 if (direntry->d_inode)
b2aeb9d5 514 direntry->d_inode->i_nlink--;
1da177e4
LT
515 } else if (rc == -ETXTBSY) {
516 int oplock = FALSE;
517 __u16 netfid;
518
519 rc = CIFSSMBOpen(xid, pTcon, full_path,
520 FILE_OPEN, DELETE,
521 CREATE_NOT_DIR |
522 CREATE_DELETE_ON_CLOSE,
523 &netfid, &oplock, NULL,
737b758c
SF
524 cifs_sb->local_nls,
525 cifs_sb->mnt_cifs_flags &
526 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
527 if (rc==0) {
528 CIFSSMBRenameOpenFile(xid, pTcon,
529 netfid, NULL,
737b758c
SF
530 cifs_sb->local_nls,
531 cifs_sb->mnt_cifs_flags &
532 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4 533 CIFSSMBClose(xid, pTcon, netfid);
d0d2f2df 534 if (direntry->d_inode)
b2aeb9d5 535 direntry->d_inode->i_nlink--;
1da177e4
LT
536 }
537 /* BB if rc = -ETXTBUSY goto the rename logic BB */
538 }
539 }
540 }
d0d2f2df 541 if (direntry->d_inode) {
b2aeb9d5
SF
542 cifsInode = CIFS_I(direntry->d_inode);
543 cifsInode->time = 0; /* will force revalidate to get info
544 when needed */
545 direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
546 }
547 inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
1da177e4
LT
548 cifsInode = CIFS_I(inode);
549 cifsInode->time = 0; /* force revalidate of dir as well */
550
551 kfree(full_path);
552 FreeXid(xid);
553 return rc;
554}
555
556int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
557{
558 int rc = 0;
559 int xid;
560 struct cifs_sb_info *cifs_sb;
561 struct cifsTconInfo *pTcon;
562 char *full_path = NULL;
563 struct inode *newinode = NULL;
564
565 cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode));
566
567 xid = GetXid();
568
569 cifs_sb = CIFS_SB(inode->i_sb);
570 pTcon = cifs_sb->tcon;
571
572 down(&inode->i_sb->s_vfs_rename_sem);
ac67055e 573 full_path = build_path_from_dentry(direntry, cifs_sb);
1da177e4
LT
574 up(&inode->i_sb->s_vfs_rename_sem);
575 if (full_path == NULL) {
576 FreeXid(xid);
577 return -ENOMEM;
578 }
579 /* BB add setting the equivalent of mode via CreateX w/ACLs */
737b758c
SF
580 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
581 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
582 if (rc) {
583 cFYI(1, ("cifs_mkdir returned 0x%x ", rc));
584 d_drop(direntry);
585 } else {
586 inode->i_nlink++;
587 if (pTcon->ses->capabilities & CAP_UNIX)
588 rc = cifs_get_inode_info_unix(&newinode, full_path,
589 inode->i_sb,xid);
590 else
591 rc = cifs_get_inode_info(&newinode, full_path, NULL,
592 inode->i_sb,xid);
593
594 direntry->d_op = &cifs_dentry_ops;
595 d_instantiate(direntry, newinode);
596 if (direntry->d_inode)
597 direntry->d_inode->i_nlink = 2;
598 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
d0d2f2df 599 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1da177e4
LT
600 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
601 mode,
602 (__u64)current->euid,
603 (__u64)current->egid,
604 0 /* dev_t */,
737b758c
SF
605 cifs_sb->local_nls,
606 cifs_sb->mnt_cifs_flags &
607 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
608 } else {
609 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
610 mode, (__u64)-1,
611 (__u64)-1, 0 /* dev_t */,
737b758c
SF
612 cifs_sb->local_nls,
613 cifs_sb->mnt_cifs_flags &
614 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
615 }
616 else {
617 /* BB to be implemented via Windows secrty descriptors
618 eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
619 -1, -1, local_nls); */
620 }
621 }
622 kfree(full_path);
623 FreeXid(xid);
624 return rc;
625}
626
627int cifs_rmdir(struct inode *inode, struct dentry *direntry)
628{
629 int rc = 0;
630 int xid;
631 struct cifs_sb_info *cifs_sb;
632 struct cifsTconInfo *pTcon;
633 char *full_path = NULL;
634 struct cifsInodeInfo *cifsInode;
635
636 cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode));
637
638 xid = GetXid();
639
640 cifs_sb = CIFS_SB(inode->i_sb);
641 pTcon = cifs_sb->tcon;
642
643 down(&inode->i_sb->s_vfs_rename_sem);
ac67055e 644 full_path = build_path_from_dentry(direntry, cifs_sb);
1da177e4
LT
645 up(&inode->i_sb->s_vfs_rename_sem);
646 if (full_path == NULL) {
647 FreeXid(xid);
648 return -ENOMEM;
649 }
650
737b758c
SF
651 rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
652 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
653
654 if (!rc) {
655 inode->i_nlink--;
656 i_size_write(direntry->d_inode,0);
657 direntry->d_inode->i_nlink = 0;
658 }
659
660 cifsInode = CIFS_I(direntry->d_inode);
661 cifsInode->time = 0; /* force revalidate to go get info when
662 needed */
663 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
664 current_fs_time(inode->i_sb);
665
666 kfree(full_path);
667 FreeXid(xid);
668 return rc;
669}
670
671int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
672 struct inode *target_inode, struct dentry *target_direntry)
673{
674 char *fromName;
675 char *toName;
676 struct cifs_sb_info *cifs_sb_source;
677 struct cifs_sb_info *cifs_sb_target;
678 struct cifsTconInfo *pTcon;
679 int xid;
680 int rc = 0;
681
682 xid = GetXid();
683
684 cifs_sb_target = CIFS_SB(target_inode->i_sb);
685 cifs_sb_source = CIFS_SB(source_inode->i_sb);
686 pTcon = cifs_sb_source->tcon;
687
688 if (pTcon != cifs_sb_target->tcon) {
689 FreeXid(xid);
690 return -EXDEV; /* BB actually could be allowed if same server,
691 but different share.
692 Might eventually add support for this */
693 }
694
695 /* we already have the rename sem so we do not need to grab it again
696 here to protect the path integrity */
ac67055e
JA
697 fromName = build_path_from_dentry(source_direntry, cifs_sb_source);
698 toName = build_path_from_dentry(target_direntry, cifs_sb_target);
1da177e4
LT
699 if ((fromName == NULL) || (toName == NULL)) {
700 rc = -ENOMEM;
701 goto cifs_rename_exit;
702 }
703
704 rc = CIFSSMBRename(xid, pTcon, fromName, toName,
737b758c
SF
705 cifs_sb_source->local_nls,
706 cifs_sb_source->mnt_cifs_flags &
707 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
708 if (rc == -EEXIST) {
709 /* check if they are the same file because rename of hardlinked
710 files is a noop */
711 FILE_UNIX_BASIC_INFO *info_buf_source;
712 FILE_UNIX_BASIC_INFO *info_buf_target;
713
714 info_buf_source =
715 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
716 if (info_buf_source != NULL) {
717 info_buf_target = info_buf_source + 1;
718 rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
737b758c
SF
719 info_buf_source, cifs_sb_source->local_nls,
720 cifs_sb_source->mnt_cifs_flags &
721 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
722 if (rc == 0) {
723 rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName,
724 info_buf_target,
737b758c
SF
725 cifs_sb_target->local_nls,
726 /* remap based on source sb */
727 cifs_sb_source->mnt_cifs_flags &
728 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
729 }
730 if ((rc == 0) &&
731 (info_buf_source->UniqueId ==
732 info_buf_target->UniqueId)) {
733 /* do not rename since the files are hardlinked which
734 is a noop */
735 } else {
736 /* we either can not tell the files are hardlinked
737 (as with Windows servers) or files are not
738 hardlinked so delete the target manually before
739 renaming to follow POSIX rather than Windows
740 semantics */
741 cifs_unlink(target_inode, target_direntry);
742 rc = CIFSSMBRename(xid, pTcon, fromName,
743 toName,
737b758c
SF
744 cifs_sb_source->local_nls,
745 cifs_sb_source->mnt_cifs_flags
746 & CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
747 }
748 kfree(info_buf_source);
749 } /* if we can not get memory just leave rc as EEXIST */
750 }
751
752 if (rc) {
753 cFYI(1, ("rename rc %d", rc));
754 }
755
756 if ((rc == -EIO) || (rc == -EEXIST)) {
757 int oplock = FALSE;
758 __u16 netfid;
759
760 /* BB FIXME Is Generic Read correct for rename? */
761 /* if renaming directory - we should not say CREATE_NOT_DIR,
762 need to test renaming open directory, also GENERIC_READ
763 might not right be right access to request */
764 rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
765 CREATE_NOT_DIR, &netfid, &oplock, NULL,
737b758c
SF
766 cifs_sb_source->local_nls,
767 cifs_sb_source->mnt_cifs_flags &
768 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
769 if (rc==0) {
770 CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
737b758c
SF
771 cifs_sb_source->local_nls,
772 cifs_sb_source->mnt_cifs_flags &
773 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
774 CIFSSMBClose(xid, pTcon, netfid);
775 }
776 }
777
778cifs_rename_exit:
779 kfree(fromName);
780 kfree(toName);
781 FreeXid(xid);
782 return rc;
783}
784
785int cifs_revalidate(struct dentry *direntry)
786{
787 int xid;
788 int rc = 0;
789 char *full_path;
790 struct cifs_sb_info *cifs_sb;
791 struct cifsInodeInfo *cifsInode;
792 loff_t local_size;
793 struct timespec local_mtime;
794 int invalidate_inode = FALSE;
795
796 if (direntry->d_inode == NULL)
797 return -ENOENT;
798
799 cifsInode = CIFS_I(direntry->d_inode);
800
801 if (cifsInode == NULL)
802 return -ENOENT;
803
804 /* no sense revalidating inode info on file that no one can write */
805 if (CIFS_I(direntry->d_inode)->clientCanCacheRead)
806 return rc;
807
808 xid = GetXid();
809
810 cifs_sb = CIFS_SB(direntry->d_sb);
811
812 /* can not safely grab the rename sem here if rename calls revalidate
813 since that would deadlock */
ac67055e 814 full_path = build_path_from_dentry(direntry, cifs_sb);
1da177e4
LT
815 if (full_path == NULL) {
816 FreeXid(xid);
817 return -ENOMEM;
818 }
819 cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
820 "jiffies %ld", full_path, direntry->d_inode,
821 direntry->d_inode->i_count.counter, direntry,
822 direntry->d_time, jiffies));
823
824 if (cifsInode->time == 0) {
825 /* was set to zero previously to force revalidate */
826 } else if (time_before(jiffies, cifsInode->time + HZ) &&
827 lookupCacheEnabled) {
828 if ((S_ISREG(direntry->d_inode->i_mode) == 0) ||
829 (direntry->d_inode->i_nlink == 1)) {
830 kfree(full_path);
831 FreeXid(xid);
832 return rc;
833 } else {
834 cFYI(1, ("Have to revalidate file due to hardlinks"));
835 }
836 }
837
838 /* save mtime and size */
839 local_mtime = direntry->d_inode->i_mtime;
840 local_size = direntry->d_inode->i_size;
841
842 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
843 rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
844 direntry->d_sb,xid);
845 if (rc) {
846 cFYI(1, ("error on getting revalidate info %d", rc));
847/* if (rc != -ENOENT)
848 rc = 0; */ /* BB should we cache info on
849 certain errors? */
850 }
851 } else {
852 rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
853 direntry->d_sb,xid);
854 if (rc) {
855 cFYI(1, ("error on getting revalidate info %d", rc));
856/* if (rc != -ENOENT)
857 rc = 0; */ /* BB should we cache info on
858 certain errors? */
859 }
860 }
861 /* should we remap certain errors, access denied?, to zero */
862
863 /* if not oplocked, we invalidate inode pages if mtime or file size
864 had changed on server */
865
866 if (timespec_equal(&local_mtime,&direntry->d_inode->i_mtime) &&
867 (local_size == direntry->d_inode->i_size)) {
868 cFYI(1, ("cifs_revalidate - inode unchanged"));
869 } else {
870 /* file may have changed on server */
871 if (cifsInode->clientCanCacheRead) {
872 /* no need to invalidate inode pages since we were the
873 only ones who could have modified the file and the
874 server copy is staler than ours */
875 } else {
876 invalidate_inode = TRUE;
877 }
878 }
879
880 /* can not grab this sem since kernel filesys locking documentation
881 indicates i_sem may be taken by the kernel on lookup and rename
882 which could deadlock if we grab the i_sem here as well */
883/* down(&direntry->d_inode->i_sem);*/
884 /* need to write out dirty pages here */
885 if (direntry->d_inode->i_mapping) {
886 /* do we need to lock inode until after invalidate completes
887 below? */
888 filemap_fdatawrite(direntry->d_inode->i_mapping);
889 }
890 if (invalidate_inode) {
891 if (direntry->d_inode->i_mapping)
892 filemap_fdatawait(direntry->d_inode->i_mapping);
893 /* may eventually have to do this for open files too */
894 if (list_empty(&(cifsInode->openFileList))) {
895 /* Has changed on server - flush read ahead pages */
896 cFYI(1, ("Invalidating read ahead data on "
897 "closed file"));
898 invalidate_remote_inode(direntry->d_inode);
899 }
900 }
901/* up(&direntry->d_inode->i_sem); */
902
903 kfree(full_path);
904 FreeXid(xid);
905 return rc;
906}
907
908int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
909 struct kstat *stat)
910{
911 int err = cifs_revalidate(dentry);
912 if (!err)
913 generic_fillattr(dentry->d_inode, stat);
914 return err;
915}
916
917static int cifs_truncate_page(struct address_space *mapping, loff_t from)
918{
919 pgoff_t index = from >> PAGE_CACHE_SHIFT;
920 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
921 struct page *page;
922 char *kaddr;
923 int rc = 0;
924
925 page = grab_cache_page(mapping, index);
926 if (!page)
927 return -ENOMEM;
928
929 kaddr = kmap_atomic(page, KM_USER0);
930 memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
931 flush_dcache_page(page);
932 kunmap_atomic(kaddr, KM_USER0);
933 unlock_page(page);
934 page_cache_release(page);
935 return rc;
936}
937
938int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
939{
940 int xid;
941 struct cifs_sb_info *cifs_sb;
942 struct cifsTconInfo *pTcon;
943 char *full_path = NULL;
944 int rc = -EACCES;
945 int found = FALSE;
946 struct cifsFileInfo *open_file = NULL;
947 FILE_BASIC_INFO time_buf;
948 int set_time = FALSE;
949 __u64 mode = 0xFFFFFFFFFFFFFFFFULL;
950 __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
951 __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
952 struct cifsInodeInfo *cifsInode;
953 struct list_head *tmp;
954
955 xid = GetXid();
956
957 cFYI(1, (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
958 direntry->d_name.name, attrs->ia_valid));
959 cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
960 pTcon = cifs_sb->tcon;
961
962 down(&direntry->d_sb->s_vfs_rename_sem);
ac67055e 963 full_path = build_path_from_dentry(direntry, cifs_sb);
1da177e4
LT
964 up(&direntry->d_sb->s_vfs_rename_sem);
965 if (full_path == NULL) {
966 FreeXid(xid);
967 return -ENOMEM;
968 }
969 cifsInode = CIFS_I(direntry->d_inode);
970
971 /* BB check if we need to refresh inode from server now ? BB */
972
973 /* need to flush data before changing file size on server */
974 filemap_fdatawrite(direntry->d_inode->i_mapping);
975 filemap_fdatawait(direntry->d_inode->i_mapping);
976
977 if (attrs->ia_valid & ATTR_SIZE) {
978 read_lock(&GlobalSMBSeslock);
979 /* To avoid spurious oplock breaks from server, in the case of
980 inodes that we already have open, avoid doing path based
981 setting of file size if we can do it by handle.
982 This keeps our caching token (oplock) and avoids timeouts
983 when the local oplock break takes longer to flush
984 writebehind data than the SMB timeout for the SetPathInfo
985 request would allow */
986 list_for_each(tmp, &cifsInode->openFileList) {
987 open_file = list_entry(tmp, struct cifsFileInfo,
988 flist);
989 /* We check if file is open for writing first */
990 if ((open_file->pfile) &&
991 ((open_file->pfile->f_flags & O_RDWR) ||
992 (open_file->pfile->f_flags & O_WRONLY))) {
993 if (open_file->invalidHandle == FALSE) {
994 /* we found a valid, writeable network
995 file handle to use to try to set the
996 file size */
997 __u16 nfid = open_file->netfid;
998 __u32 npid = open_file->pid;
999 read_unlock(&GlobalSMBSeslock);
1000 found = TRUE;
1001 rc = CIFSSMBSetFileSize(xid, pTcon,
1002 attrs->ia_size, nfid, npid,
1003 FALSE);
1004 cFYI(1, ("SetFileSize by handle "
1005 "(setattrs) rc = %d", rc));
1006 /* Do not need reopen and retry on
1007 EAGAIN since we will retry by
1008 pathname below */
1009
1010 /* now that we found one valid file
1011 handle no sense continuing to loop
1012 trying others, so break here */
1013 break;
1014 }
1015 }
1016 }
1017 if (found == FALSE)
1018 read_unlock(&GlobalSMBSeslock);
1019
1020 if (rc != 0) {
1021 /* Set file size by pathname rather than by handle
1022 either because no valid, writeable file handle for
1023 it was found or because there was an error setting
1024 it by handle */
1025 rc = CIFSSMBSetEOF(xid, pTcon, full_path,
1026 attrs->ia_size, FALSE,
737b758c
SF
1027 cifs_sb->local_nls,
1028 cifs_sb->mnt_cifs_flags &
1029 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
1030 cFYI(1, (" SetEOF by path (setattrs) rc = %d", rc));
1031 }
1032
1033 /* Server is ok setting allocation size implicitly - no need
1034 to call:
1035 CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE,
1036 cifs_sb->local_nls);
1037 */
1038
1039 if (rc == 0) {
1040 rc = vmtruncate(direntry->d_inode, attrs->ia_size);
1041 cifs_truncate_page(direntry->d_inode->i_mapping,
1042 direntry->d_inode->i_size);
1043 }
1044 }
1045 if (attrs->ia_valid & ATTR_UID) {
1046 cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid));
1047 uid = attrs->ia_uid;
1048 /* entry->uid = cpu_to_le16(attr->ia_uid); */
1049 }
1050 if (attrs->ia_valid & ATTR_GID) {
1051 cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid));
1052 gid = attrs->ia_gid;
1053 /* entry->gid = cpu_to_le16(attr->ia_gid); */
1054 }
1055
1056 time_buf.Attributes = 0;
1057 if (attrs->ia_valid & ATTR_MODE) {
1058 cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode));
1059 mode = attrs->ia_mode;
1060 /* entry->mode = cpu_to_le16(attr->ia_mode); */
1061 }
1062
1063 if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
1064 && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
1065 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
737b758c
SF
1066 0 /* dev_t */, cifs_sb->local_nls,
1067 cifs_sb->mnt_cifs_flags &
1068 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
1069 else if (attrs->ia_valid & ATTR_MODE) {
1070 if ((mode & S_IWUGO) == 0) /* not writeable */ {
1071 if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
1072 time_buf.Attributes =
1073 cpu_to_le32(cifsInode->cifsAttrs |
1074 ATTR_READONLY);
1075 } else if ((mode & S_IWUGO) == S_IWUGO) {
1076 if (cifsInode->cifsAttrs & ATTR_READONLY)
1077 time_buf.Attributes =
1078 cpu_to_le32(cifsInode->cifsAttrs &
1079 (~ATTR_READONLY));
1080 }
1081 /* BB to be implemented -
1082 via Windows security descriptors or streams */
1083 /* CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, uid, gid,
1084 cifs_sb->local_nls); */
1085 }
1086
1087 if (attrs->ia_valid & ATTR_ATIME) {
1088 set_time = TRUE;
1089 time_buf.LastAccessTime =
1090 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
1091 } else
1092 time_buf.LastAccessTime = 0;
1093
1094 if (attrs->ia_valid & ATTR_MTIME) {
1095 set_time = TRUE;
1096 time_buf.LastWriteTime =
1097 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1098 } else
1099 time_buf.LastWriteTime = 0;
1100
1101 if (attrs->ia_valid & ATTR_CTIME) {
1102 set_time = TRUE;
1103 cFYI(1, (" CIFS - CTIME changed ")); /* BB probably no need */
1104 time_buf.ChangeTime =
1105 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1106 } else
1107 time_buf.ChangeTime = 0;
1108
1109 if (set_time || time_buf.Attributes) {
1110 /* BB what if setting one attribute fails (such as size) but
1111 time setting works? */
1112 time_buf.CreationTime = 0; /* do not change */
1113 /* In the future we should experiment - try setting timestamps
1114 via Handle (SetFileInfo) instead of by path */
1115 if (!(pTcon->ses->flags & CIFS_SES_NT4))
1116 rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
737b758c
SF
1117 cifs_sb->local_nls,
1118 cifs_sb->mnt_cifs_flags &
1119 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
1120 else
1121 rc = -EOPNOTSUPP;
1122
1123 if (rc == -EOPNOTSUPP) {
1124 int oplock = FALSE;
1125 __u16 netfid;
1126
1127 cFYI(1, ("calling SetFileInfo since SetPathInfo for "
1128 "times not supported by this server"));
1129 /* BB we could scan to see if we already have it open
1130 and pass in pid of opener to function */
1131 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
1132 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1133 CREATE_NOT_DIR, &netfid, &oplock,
737b758c
SF
1134 NULL, cifs_sb->local_nls,
1135 cifs_sb->mnt_cifs_flags &
1136 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
1137 if (rc==0) {
1138 rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
1139 netfid);
1140 CIFSSMBClose(xid, pTcon, netfid);
1141 } else {
1142 /* BB For even older servers we could convert time_buf
1143 into old DOS style which uses two second
1144 granularity */
1145
1146 /* rc = CIFSSMBSetTimesLegacy(xid, pTcon, full_path,
1147 &time_buf, cifs_sb->local_nls); */
1148 }
1149 }
1150 }
1151
1152 /* do not need local check to inode_check_ok since the server does
1153 that */
1154 if (!rc)
1155 rc = inode_setattr(direntry->d_inode, attrs);
1156 kfree(full_path);
1157 FreeXid(xid);
1158 return rc;
1159}
1160
1161void cifs_delete_inode(struct inode *inode)
1162{
1163 cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode));
1164 /* may have to add back in if and when safe distributed caching of
1165 directories added e.g. via FindNotify */
1166}