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