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