oprofile: introduce module_param oprofile.cpu_type
[deliverable/linux.git] / fs / cifs / dir.c
1 /*
2 * fs/cifs/dir.c
3 *
4 * vfs operations that deal with dentries
5 *
6 * Copyright (C) International Business Machines Corp., 2002,2009
7 * Author(s): Steve French (sfrench@us.ibm.com)
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23 #include <linux/fs.h>
24 #include <linux/stat.h>
25 #include <linux/slab.h>
26 #include <linux/namei.h>
27 #include "cifsfs.h"
28 #include "cifspdu.h"
29 #include "cifsglob.h"
30 #include "cifsproto.h"
31 #include "cifs_debug.h"
32 #include "cifs_fs_sb.h"
33
34 static void
35 renew_parental_timestamps(struct dentry *direntry)
36 {
37 /* BB check if there is a way to get the kernel to do this or if we
38 really need this */
39 do {
40 direntry->d_time = jiffies;
41 direntry = direntry->d_parent;
42 } while (!IS_ROOT(direntry));
43 }
44
45 /* Note: caller must free return buffer */
46 char *
47 build_path_from_dentry(struct dentry *direntry)
48 {
49 struct dentry *temp;
50 int namelen;
51 int pplen;
52 int dfsplen;
53 char *full_path;
54 char dirsep;
55 struct cifs_sb_info *cifs_sb;
56
57 if (direntry == NULL)
58 return NULL; /* not much we can do if dentry is freed and
59 we need to reopen the file after it was closed implicitly
60 when the server crashed */
61
62 cifs_sb = CIFS_SB(direntry->d_sb);
63 dirsep = CIFS_DIR_SEP(cifs_sb);
64 pplen = cifs_sb->prepathlen;
65 if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
66 dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
67 else
68 dfsplen = 0;
69 cifs_bp_rename_retry:
70 namelen = pplen + dfsplen;
71 for (temp = direntry; !IS_ROOT(temp);) {
72 namelen += (1 + temp->d_name.len);
73 temp = temp->d_parent;
74 if (temp == NULL) {
75 cERROR(1, ("corrupt dentry"));
76 return NULL;
77 }
78 }
79
80 full_path = kmalloc(namelen+1, GFP_KERNEL);
81 if (full_path == NULL)
82 return full_path;
83 full_path[namelen] = 0; /* trailing null */
84 for (temp = direntry; !IS_ROOT(temp);) {
85 namelen -= 1 + temp->d_name.len;
86 if (namelen < 0) {
87 break;
88 } else {
89 full_path[namelen] = dirsep;
90 strncpy(full_path + namelen + 1, temp->d_name.name,
91 temp->d_name.len);
92 cFYI(0, ("name: %s", full_path + namelen));
93 }
94 temp = temp->d_parent;
95 if (temp == NULL) {
96 cERROR(1, ("corrupt dentry"));
97 kfree(full_path);
98 return NULL;
99 }
100 }
101 if (namelen != pplen + dfsplen) {
102 cERROR(1,
103 ("did not end path lookup where expected namelen is %d",
104 namelen));
105 /* presumably this is only possible if racing with a rename
106 of one of the parent directories (we can not lock the dentries
107 above us to prevent this, but retrying should be harmless) */
108 kfree(full_path);
109 goto cifs_bp_rename_retry;
110 }
111 /* DIR_SEP already set for byte 0 / vs \ but not for
112 subsequent slashes in prepath which currently must
113 be entered the right way - not sure if there is an alternative
114 since the '\' is a valid posix character so we can not switch
115 those safely to '/' if any are found in the middle of the prepath */
116 /* BB test paths to Windows with '/' in the midst of prepath */
117
118 if (dfsplen) {
119 strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
120 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
121 int i;
122 for (i = 0; i < dfsplen; i++) {
123 if (full_path[i] == '\\')
124 full_path[i] = '/';
125 }
126 }
127 }
128 strncpy(full_path + dfsplen, CIFS_SB(direntry->d_sb)->prepath, pplen);
129 return full_path;
130 }
131
132 static void
133 cifs_fill_fileinfo(struct inode *newinode, __u16 fileHandle,
134 struct cifsTconInfo *tcon, bool write_only)
135 {
136 int oplock = 0;
137 struct cifsFileInfo *pCifsFile;
138 struct cifsInodeInfo *pCifsInode;
139
140 pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
141
142 if (pCifsFile == NULL)
143 return;
144
145 if (oplockEnabled)
146 oplock = REQ_OPLOCK;
147
148 pCifsFile->netfid = fileHandle;
149 pCifsFile->pid = current->tgid;
150 pCifsFile->pInode = newinode;
151 pCifsFile->invalidHandle = false;
152 pCifsFile->closePend = false;
153 mutex_init(&pCifsFile->fh_mutex);
154 mutex_init(&pCifsFile->lock_mutex);
155 INIT_LIST_HEAD(&pCifsFile->llist);
156 atomic_set(&pCifsFile->wrtPending, 0);
157
158 /* set the following in open now
159 pCifsFile->pfile = file; */
160 write_lock(&GlobalSMBSeslock);
161 list_add(&pCifsFile->tlist, &tcon->openFileList);
162 pCifsInode = CIFS_I(newinode);
163 if (pCifsInode) {
164 /* if readable file instance put first in list*/
165 if (write_only)
166 list_add_tail(&pCifsFile->flist,
167 &pCifsInode->openFileList);
168 else
169 list_add(&pCifsFile->flist, &pCifsInode->openFileList);
170
171 if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
172 pCifsInode->clientCanCacheAll = true;
173 pCifsInode->clientCanCacheRead = true;
174 cFYI(1, ("Exclusive Oplock inode %p", newinode));
175 } else if ((oplock & 0xF) == OPLOCK_READ)
176 pCifsInode->clientCanCacheRead = true;
177 }
178 write_unlock(&GlobalSMBSeslock);
179 }
180
181 int cifs_posix_open(char *full_path, struct inode **pinode,
182 struct super_block *sb, int mode, int oflags,
183 int *poplock, __u16 *pnetfid, int xid)
184 {
185 int rc;
186 __u32 oplock;
187 bool write_only = false;
188 FILE_UNIX_BASIC_INFO *presp_data;
189 __u32 posix_flags = 0;
190 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
191
192 cFYI(1, ("posix open %s", full_path));
193
194 presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
195 if (presp_data == NULL)
196 return -ENOMEM;
197
198 /* So far cifs posix extensions can only map the following flags.
199 There are other valid fmode oflags such as FMODE_LSEEK, FMODE_PREAD, but
200 so far we do not seem to need them, and we can treat them as local only */
201 if ((oflags & (FMODE_READ | FMODE_WRITE)) ==
202 (FMODE_READ | FMODE_WRITE))
203 posix_flags = SMB_O_RDWR;
204 else if (oflags & FMODE_READ)
205 posix_flags = SMB_O_RDONLY;
206 else if (oflags & FMODE_WRITE)
207 posix_flags = SMB_O_WRONLY;
208 if (oflags & O_CREAT)
209 posix_flags |= SMB_O_CREAT;
210 if (oflags & O_EXCL)
211 posix_flags |= SMB_O_EXCL;
212 if (oflags & O_TRUNC)
213 posix_flags |= SMB_O_TRUNC;
214 if (oflags & O_APPEND)
215 posix_flags |= SMB_O_APPEND;
216 if (oflags & O_SYNC)
217 posix_flags |= SMB_O_SYNC;
218 if (oflags & O_DIRECTORY)
219 posix_flags |= SMB_O_DIRECTORY;
220 if (oflags & O_NOFOLLOW)
221 posix_flags |= SMB_O_NOFOLLOW;
222 if (oflags & O_DIRECT)
223 posix_flags |= SMB_O_DIRECT;
224
225 if (!(oflags & FMODE_READ))
226 write_only = true;
227
228 rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
229 pnetfid, presp_data, &oplock, full_path,
230 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
231 CIFS_MOUNT_MAP_SPECIAL_CHR);
232 if (rc)
233 goto posix_open_ret;
234
235 if (presp_data->Type == cpu_to_le32(-1))
236 goto posix_open_ret; /* open ok, caller does qpathinfo */
237
238 /* get new inode and set it up */
239 if (!pinode)
240 goto posix_open_ret; /* caller does not need info */
241
242 if (*pinode == NULL) {
243 __u64 unique_id = le64_to_cpu(presp_data->UniqueId);
244 *pinode = cifs_new_inode(sb, &unique_id);
245 }
246 /* else an inode was passed in. Update its info, don't create one */
247
248 /* We do not need to close the file if new_inode fails since
249 the caller will retry qpathinfo as long as inode is null */
250 if (*pinode == NULL)
251 goto posix_open_ret;
252
253 posix_fill_in_inode(*pinode, presp_data, 1);
254
255 cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only);
256
257 posix_open_ret:
258 kfree(presp_data);
259 return rc;
260 }
261
262 static void setup_cifs_dentry(struct cifsTconInfo *tcon,
263 struct dentry *direntry,
264 struct inode *newinode)
265 {
266 if (tcon->nocase)
267 direntry->d_op = &cifs_ci_dentry_ops;
268 else
269 direntry->d_op = &cifs_dentry_ops;
270 d_instantiate(direntry, newinode);
271 }
272
273 /* Inode operations in similar order to how they appear in Linux file fs.h */
274
275 int
276 cifs_create(struct inode *inode, struct dentry *direntry, int mode,
277 struct nameidata *nd)
278 {
279 int rc = -ENOENT;
280 int xid;
281 int create_options = CREATE_NOT_DIR;
282 int oplock = 0;
283 int oflags;
284 /*
285 * BB below access is probably too much for mknod to request
286 * but we have to do query and setpathinfo so requesting
287 * less could fail (unless we want to request getatr and setatr
288 * permissions (only). At least for POSIX we do not have to
289 * request so much.
290 */
291 int desiredAccess = GENERIC_READ | GENERIC_WRITE;
292 __u16 fileHandle;
293 struct cifs_sb_info *cifs_sb;
294 struct cifsTconInfo *tcon;
295 char *full_path = NULL;
296 FILE_ALL_INFO *buf = NULL;
297 struct inode *newinode = NULL;
298 int disposition = FILE_OVERWRITE_IF;
299 bool write_only = false;
300
301 xid = GetXid();
302
303 cifs_sb = CIFS_SB(inode->i_sb);
304 tcon = cifs_sb->tcon;
305
306 full_path = build_path_from_dentry(direntry);
307 if (full_path == NULL) {
308 FreeXid(xid);
309 return -ENOMEM;
310 }
311
312 mode &= ~current_umask();
313 if (oplockEnabled)
314 oplock = REQ_OPLOCK;
315
316 if (nd && (nd->flags & LOOKUP_OPEN))
317 oflags = nd->intent.open.flags;
318 else
319 oflags = FMODE_READ;
320
321 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
322 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
323 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
324 rc = cifs_posix_open(full_path, &newinode, inode->i_sb,
325 mode, oflags, &oplock, &fileHandle, xid);
326 /* EIO could indicate that (posix open) operation is not
327 supported, despite what server claimed in capability
328 negotation. EREMOTE indicates DFS junction, which is not
329 handled in posix open */
330
331 if ((rc == 0) && (newinode == NULL))
332 goto cifs_create_get_file_info; /* query inode info */
333 else if (rc == 0) /* success, no need to query */
334 goto cifs_create_set_dentry;
335 else if ((rc != -EIO) && (rc != -EREMOTE) &&
336 (rc != -EOPNOTSUPP)) /* path not found or net err */
337 goto cifs_create_out;
338 /* else fallthrough to retry, using older open call, this is
339 case where server does not support this SMB level, and
340 falsely claims capability (also get here for DFS case
341 which should be rare for path not covered on files) */
342 }
343
344 if (nd && (nd->flags & LOOKUP_OPEN)) {
345 /* if the file is going to stay open, then we
346 need to set the desired access properly */
347 desiredAccess = 0;
348 if (oflags & FMODE_READ)
349 desiredAccess |= GENERIC_READ; /* is this too little? */
350 if (oflags & FMODE_WRITE) {
351 desiredAccess |= GENERIC_WRITE;
352 if (!(oflags & FMODE_READ))
353 write_only = true;
354 }
355
356 if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
357 disposition = FILE_CREATE;
358 else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
359 disposition = FILE_OVERWRITE_IF;
360 else if ((oflags & O_CREAT) == O_CREAT)
361 disposition = FILE_OPEN_IF;
362 else
363 cFYI(1, ("Create flag not set in create function"));
364 }
365
366 /* BB add processing to set equivalent of mode - e.g. via CreateX with
367 ACLs */
368
369 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
370 if (buf == NULL) {
371 kfree(full_path);
372 FreeXid(xid);
373 return -ENOMEM;
374 }
375
376 /*
377 * if we're not using unix extensions, see if we need to set
378 * ATTR_READONLY on the create call
379 */
380 if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
381 create_options |= CREATE_OPTION_READONLY;
382
383 if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
384 rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
385 desiredAccess, create_options,
386 &fileHandle, &oplock, buf, cifs_sb->local_nls,
387 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
388 else
389 rc = -EIO; /* no NT SMB support fall into legacy open below */
390
391 if (rc == -EIO) {
392 /* old server, retry the open legacy style */
393 rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
394 desiredAccess, create_options,
395 &fileHandle, &oplock, buf, cifs_sb->local_nls,
396 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
397 }
398 if (rc) {
399 cFYI(1, ("cifs_create returned 0x%x", rc));
400 goto cifs_create_out;
401 }
402
403 /* If Open reported that we actually created a file
404 then we now have to set the mode if possible */
405 if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
406 struct cifs_unix_set_info_args args = {
407 .mode = mode,
408 .ctime = NO_CHANGE_64,
409 .atime = NO_CHANGE_64,
410 .mtime = NO_CHANGE_64,
411 .device = 0,
412 };
413
414 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
415 args.uid = (__u64) current_fsuid();
416 if (inode->i_mode & S_ISGID)
417 args.gid = (__u64) inode->i_gid;
418 else
419 args.gid = (__u64) current_fsgid();
420 } else {
421 args.uid = NO_CHANGE_64;
422 args.gid = NO_CHANGE_64;
423 }
424 CIFSSMBUnixSetInfo(xid, tcon, full_path, &args,
425 cifs_sb->local_nls,
426 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
427 } else {
428 /* BB implement mode setting via Windows security
429 descriptors e.g. */
430 /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
431
432 /* Could set r/o dos attribute if mode & 0222 == 0 */
433 }
434
435 cifs_create_get_file_info:
436 /* server might mask mode so we have to query for it */
437 if (tcon->unix_ext)
438 rc = cifs_get_inode_info_unix(&newinode, full_path,
439 inode->i_sb, xid);
440 else {
441 rc = cifs_get_inode_info(&newinode, full_path, buf,
442 inode->i_sb, xid, &fileHandle);
443 if (newinode) {
444 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
445 newinode->i_mode = mode;
446 if ((oplock & CIFS_CREATE_ACTION) &&
447 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
448 newinode->i_uid = current_fsuid();
449 if (inode->i_mode & S_ISGID)
450 newinode->i_gid = inode->i_gid;
451 else
452 newinode->i_gid = current_fsgid();
453 }
454 }
455 }
456
457 cifs_create_set_dentry:
458 if (rc == 0)
459 setup_cifs_dentry(tcon, direntry, newinode);
460 else
461 cFYI(1, ("Create worked, get_inode_info failed rc = %d", rc));
462
463 /* nfsd case - nfs srv does not set nd */
464 if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
465 /* mknod case - do not leave file open */
466 CIFSSMBClose(xid, tcon, fileHandle);
467 } else if (newinode) {
468 cifs_fill_fileinfo(newinode, fileHandle,
469 cifs_sb->tcon, write_only);
470 }
471 cifs_create_out:
472 kfree(buf);
473 kfree(full_path);
474 FreeXid(xid);
475 return rc;
476 }
477
478 int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
479 dev_t device_number)
480 {
481 int rc = -EPERM;
482 int xid;
483 struct cifs_sb_info *cifs_sb;
484 struct cifsTconInfo *pTcon;
485 char *full_path = NULL;
486 struct inode *newinode = NULL;
487
488 if (!old_valid_dev(device_number))
489 return -EINVAL;
490
491 xid = GetXid();
492
493 cifs_sb = CIFS_SB(inode->i_sb);
494 pTcon = cifs_sb->tcon;
495
496 full_path = build_path_from_dentry(direntry);
497 if (full_path == NULL)
498 rc = -ENOMEM;
499 else if (pTcon->unix_ext) {
500 struct cifs_unix_set_info_args args = {
501 .mode = mode & ~current_umask(),
502 .ctime = NO_CHANGE_64,
503 .atime = NO_CHANGE_64,
504 .mtime = NO_CHANGE_64,
505 .device = device_number,
506 };
507 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
508 args.uid = (__u64) current_fsuid();
509 args.gid = (__u64) current_fsgid();
510 } else {
511 args.uid = NO_CHANGE_64;
512 args.gid = NO_CHANGE_64;
513 }
514 rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path,
515 &args, cifs_sb->local_nls,
516 cifs_sb->mnt_cifs_flags &
517 CIFS_MOUNT_MAP_SPECIAL_CHR);
518
519 if (!rc) {
520 rc = cifs_get_inode_info_unix(&newinode, full_path,
521 inode->i_sb, xid);
522 if (pTcon->nocase)
523 direntry->d_op = &cifs_ci_dentry_ops;
524 else
525 direntry->d_op = &cifs_dentry_ops;
526 if (rc == 0)
527 d_instantiate(direntry, newinode);
528 }
529 } else {
530 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
531 int oplock = 0;
532 u16 fileHandle;
533 FILE_ALL_INFO *buf;
534
535 cFYI(1, ("sfu compat create special file"));
536
537 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
538 if (buf == NULL) {
539 kfree(full_path);
540 FreeXid(xid);
541 return -ENOMEM;
542 }
543
544 rc = CIFSSMBOpen(xid, pTcon, full_path,
545 FILE_CREATE, /* fail if exists */
546 GENERIC_WRITE /* BB would
547 WRITE_OWNER | WRITE_DAC be better? */,
548 /* Create a file and set the
549 file attribute to SYSTEM */
550 CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
551 &fileHandle, &oplock, buf,
552 cifs_sb->local_nls,
553 cifs_sb->mnt_cifs_flags &
554 CIFS_MOUNT_MAP_SPECIAL_CHR);
555
556 /* BB FIXME - add handling for backlevel servers
557 which need legacy open and check for all
558 calls to SMBOpen for fallback to SMBLeagcyOpen */
559 if (!rc) {
560 /* BB Do not bother to decode buf since no
561 local inode yet to put timestamps in,
562 but we can reuse it safely */
563 unsigned int bytes_written;
564 struct win_dev *pdev;
565 pdev = (struct win_dev *)buf;
566 if (S_ISCHR(mode)) {
567 memcpy(pdev->type, "IntxCHR", 8);
568 pdev->major =
569 cpu_to_le64(MAJOR(device_number));
570 pdev->minor =
571 cpu_to_le64(MINOR(device_number));
572 rc = CIFSSMBWrite(xid, pTcon,
573 fileHandle,
574 sizeof(struct win_dev),
575 0, &bytes_written, (char *)pdev,
576 NULL, 0);
577 } else if (S_ISBLK(mode)) {
578 memcpy(pdev->type, "IntxBLK", 8);
579 pdev->major =
580 cpu_to_le64(MAJOR(device_number));
581 pdev->minor =
582 cpu_to_le64(MINOR(device_number));
583 rc = CIFSSMBWrite(xid, pTcon,
584 fileHandle,
585 sizeof(struct win_dev),
586 0, &bytes_written, (char *)pdev,
587 NULL, 0);
588 } /* else if(S_ISFIFO */
589 CIFSSMBClose(xid, pTcon, fileHandle);
590 d_drop(direntry);
591 }
592 kfree(buf);
593 /* add code here to set EAs */
594 }
595 }
596
597 kfree(full_path);
598 FreeXid(xid);
599 return rc;
600 }
601
602 struct dentry *
603 cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
604 struct nameidata *nd)
605 {
606 int xid;
607 int rc = 0; /* to get around spurious gcc warning, set to zero here */
608 int oplock = 0;
609 int mode;
610 __u16 fileHandle = 0;
611 bool posix_open = false;
612 struct cifs_sb_info *cifs_sb;
613 struct cifsTconInfo *pTcon;
614 struct inode *newInode = NULL;
615 char *full_path = NULL;
616 struct file *filp;
617
618 xid = GetXid();
619
620 cFYI(1, ("parent inode = 0x%p name is: %s and dentry = 0x%p",
621 parent_dir_inode, direntry->d_name.name, direntry));
622
623 /* check whether path exists */
624
625 cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
626 pTcon = cifs_sb->tcon;
627
628 /*
629 * Don't allow the separator character in a path component.
630 * The VFS will not allow "/", but "\" is allowed by posix.
631 */
632 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
633 int i;
634 for (i = 0; i < direntry->d_name.len; i++)
635 if (direntry->d_name.name[i] == '\\') {
636 cFYI(1, ("Invalid file name"));
637 FreeXid(xid);
638 return ERR_PTR(-EINVAL);
639 }
640 }
641
642 /* can not grab the rename sem here since it would
643 deadlock in the cases (beginning of sys_rename itself)
644 in which we already have the sb rename sem */
645 full_path = build_path_from_dentry(direntry);
646 if (full_path == NULL) {
647 FreeXid(xid);
648 return ERR_PTR(-ENOMEM);
649 }
650
651 if (direntry->d_inode != NULL) {
652 cFYI(1, ("non-NULL inode in lookup"));
653 } else {
654 cFYI(1, ("NULL inode in lookup"));
655 }
656 cFYI(1, ("Full path: %s inode = 0x%p", full_path, direntry->d_inode));
657
658 if (pTcon->unix_ext) {
659 if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
660 (nd->flags & LOOKUP_OPEN)) {
661 if (!((nd->intent.open.flags & O_CREAT) &&
662 (nd->intent.open.flags & O_EXCL))) {
663 mode = nd->intent.open.create_mode &
664 ~current_umask();
665 rc = cifs_posix_open(full_path, &newInode,
666 parent_dir_inode->i_sb, mode,
667 nd->intent.open.flags, &oplock,
668 &fileHandle, xid);
669 /*
670 * This code works around a bug in
671 * samba posix open in samba versions 3.3.1
672 * and earlier where create works
673 * but open fails with invalid parameter.
674 * If either of these error codes are
675 * returned, follow the normal lookup.
676 * Otherwise, the error during posix open
677 * is handled.
678 */
679 if ((rc != -EINVAL) && (rc != -EOPNOTSUPP))
680 posix_open = true;
681 }
682 }
683 if (!posix_open)
684 rc = cifs_get_inode_info_unix(&newInode, full_path,
685 parent_dir_inode->i_sb, xid);
686 } else
687 rc = cifs_get_inode_info(&newInode, full_path, NULL,
688 parent_dir_inode->i_sb, xid, NULL);
689
690 if ((rc == 0) && (newInode != NULL)) {
691 if (pTcon->nocase)
692 direntry->d_op = &cifs_ci_dentry_ops;
693 else
694 direntry->d_op = &cifs_dentry_ops;
695 d_add(direntry, newInode);
696 if (posix_open)
697 filp = lookup_instantiate_filp(nd, direntry, NULL);
698 /* since paths are not looked up by component - the parent
699 directories are presumed to be good here */
700 renew_parental_timestamps(direntry);
701
702 } else if (rc == -ENOENT) {
703 rc = 0;
704 direntry->d_time = jiffies;
705 if (pTcon->nocase)
706 direntry->d_op = &cifs_ci_dentry_ops;
707 else
708 direntry->d_op = &cifs_dentry_ops;
709 d_add(direntry, NULL);
710 /* if it was once a directory (but how can we tell?) we could do
711 shrink_dcache_parent(direntry); */
712 } else if (rc != -EACCES) {
713 cERROR(1, ("Unexpected lookup error %d", rc));
714 /* We special case check for Access Denied - since that
715 is a common return code */
716 }
717
718 kfree(full_path);
719 FreeXid(xid);
720 return ERR_PTR(rc);
721 }
722
723 static int
724 cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
725 {
726 int isValid = 1;
727
728 if (direntry->d_inode) {
729 if (cifs_revalidate(direntry))
730 return 0;
731 } else {
732 cFYI(1, ("neg dentry 0x%p name = %s",
733 direntry, direntry->d_name.name));
734 if (time_after(jiffies, direntry->d_time + HZ) ||
735 !lookupCacheEnabled) {
736 d_drop(direntry);
737 isValid = 0;
738 }
739 }
740
741 return isValid;
742 }
743
744 /* static int cifs_d_delete(struct dentry *direntry)
745 {
746 int rc = 0;
747
748 cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name));
749
750 return rc;
751 } */
752
753 const struct dentry_operations cifs_dentry_ops = {
754 .d_revalidate = cifs_d_revalidate,
755 /* d_delete: cifs_d_delete, */ /* not needed except for debugging */
756 };
757
758 static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
759 {
760 struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
761 unsigned long hash;
762 int i;
763
764 hash = init_name_hash();
765 for (i = 0; i < q->len; i++)
766 hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
767 hash);
768 q->hash = end_name_hash(hash);
769
770 return 0;
771 }
772
773 static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
774 struct qstr *b)
775 {
776 struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
777
778 if ((a->len == b->len) &&
779 (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) {
780 /*
781 * To preserve case, don't let an existing negative dentry's
782 * case take precedence. If a is not a negative dentry, this
783 * should have no side effects
784 */
785 memcpy((void *)a->name, b->name, a->len);
786 return 0;
787 }
788 return 1;
789 }
790
791 const struct dentry_operations cifs_ci_dentry_ops = {
792 .d_revalidate = cifs_d_revalidate,
793 .d_hash = cifs_ci_hash,
794 .d_compare = cifs_ci_compare,
795 };
This page took 0.078609 seconds and 5 git commands to generate.