Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/fs/cifs/dir.c
15109 views
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 ([email protected])
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 <linux/mount.h>
28
#include <linux/file.h>
29
#include "cifsfs.h"
30
#include "cifspdu.h"
31
#include "cifsglob.h"
32
#include "cifsproto.h"
33
#include "cifs_debug.h"
34
#include "cifs_fs_sb.h"
35
36
static void
37
renew_parental_timestamps(struct dentry *direntry)
38
{
39
/* BB check if there is a way to get the kernel to do this or if we
40
really need this */
41
do {
42
direntry->d_time = jiffies;
43
direntry = direntry->d_parent;
44
} while (!IS_ROOT(direntry));
45
}
46
47
/* Note: caller must free return buffer */
48
char *
49
build_path_from_dentry(struct dentry *direntry)
50
{
51
struct dentry *temp;
52
int namelen;
53
int dfsplen;
54
char *full_path;
55
char dirsep;
56
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
57
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
58
unsigned seq;
59
60
if (direntry == NULL)
61
return NULL; /* not much we can do if dentry is freed and
62
we need to reopen the file after it was closed implicitly
63
when the server crashed */
64
65
dirsep = CIFS_DIR_SEP(cifs_sb);
66
if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
67
dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
68
else
69
dfsplen = 0;
70
cifs_bp_rename_retry:
71
namelen = dfsplen;
72
seq = read_seqbegin(&rename_lock);
73
rcu_read_lock();
74
for (temp = direntry; !IS_ROOT(temp);) {
75
namelen += (1 + temp->d_name.len);
76
temp = temp->d_parent;
77
if (temp == NULL) {
78
cERROR(1, "corrupt dentry");
79
rcu_read_unlock();
80
return NULL;
81
}
82
}
83
rcu_read_unlock();
84
85
full_path = kmalloc(namelen+1, GFP_KERNEL);
86
if (full_path == NULL)
87
return full_path;
88
full_path[namelen] = 0; /* trailing null */
89
rcu_read_lock();
90
for (temp = direntry; !IS_ROOT(temp);) {
91
spin_lock(&temp->d_lock);
92
namelen -= 1 + temp->d_name.len;
93
if (namelen < 0) {
94
spin_unlock(&temp->d_lock);
95
break;
96
} else {
97
full_path[namelen] = dirsep;
98
strncpy(full_path + namelen + 1, temp->d_name.name,
99
temp->d_name.len);
100
cFYI(0, "name: %s", full_path + namelen);
101
}
102
spin_unlock(&temp->d_lock);
103
temp = temp->d_parent;
104
if (temp == NULL) {
105
cERROR(1, "corrupt dentry");
106
rcu_read_unlock();
107
kfree(full_path);
108
return NULL;
109
}
110
}
111
rcu_read_unlock();
112
if (namelen != dfsplen || read_seqretry(&rename_lock, seq)) {
113
cERROR(1, "did not end path lookup where expected namelen is %d",
114
namelen);
115
/* presumably this is only possible if racing with a rename
116
of one of the parent directories (we can not lock the dentries
117
above us to prevent this, but retrying should be harmless) */
118
kfree(full_path);
119
goto cifs_bp_rename_retry;
120
}
121
/* DIR_SEP already set for byte 0 / vs \ but not for
122
subsequent slashes in prepath which currently must
123
be entered the right way - not sure if there is an alternative
124
since the '\' is a valid posix character so we can not switch
125
those safely to '/' if any are found in the middle of the prepath */
126
/* BB test paths to Windows with '/' in the midst of prepath */
127
128
if (dfsplen) {
129
strncpy(full_path, tcon->treeName, dfsplen);
130
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
131
int i;
132
for (i = 0; i < dfsplen; i++) {
133
if (full_path[i] == '\\')
134
full_path[i] = '/';
135
}
136
}
137
}
138
return full_path;
139
}
140
141
/* Inode operations in similar order to how they appear in Linux file fs.h */
142
143
int
144
cifs_create(struct inode *inode, struct dentry *direntry, int mode,
145
struct nameidata *nd)
146
{
147
int rc = -ENOENT;
148
int xid;
149
int create_options = CREATE_NOT_DIR;
150
__u32 oplock = 0;
151
int oflags;
152
/*
153
* BB below access is probably too much for mknod to request
154
* but we have to do query and setpathinfo so requesting
155
* less could fail (unless we want to request getatr and setatr
156
* permissions (only). At least for POSIX we do not have to
157
* request so much.
158
*/
159
int desiredAccess = GENERIC_READ | GENERIC_WRITE;
160
__u16 fileHandle;
161
struct cifs_sb_info *cifs_sb;
162
struct tcon_link *tlink;
163
struct cifs_tcon *tcon;
164
char *full_path = NULL;
165
FILE_ALL_INFO *buf = NULL;
166
struct inode *newinode = NULL;
167
int disposition = FILE_OVERWRITE_IF;
168
169
xid = GetXid();
170
171
cifs_sb = CIFS_SB(inode->i_sb);
172
tlink = cifs_sb_tlink(cifs_sb);
173
if (IS_ERR(tlink)) {
174
FreeXid(xid);
175
return PTR_ERR(tlink);
176
}
177
tcon = tlink_tcon(tlink);
178
179
if (oplockEnabled)
180
oplock = REQ_OPLOCK;
181
182
if (nd && (nd->flags & LOOKUP_OPEN))
183
oflags = nd->intent.open.file->f_flags;
184
else
185
oflags = O_RDONLY | O_CREAT;
186
187
full_path = build_path_from_dentry(direntry);
188
if (full_path == NULL) {
189
rc = -ENOMEM;
190
goto cifs_create_out;
191
}
192
193
if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
194
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
195
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
196
rc = cifs_posix_open(full_path, &newinode,
197
inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
198
/* EIO could indicate that (posix open) operation is not
199
supported, despite what server claimed in capability
200
negotiation. EREMOTE indicates DFS junction, which is not
201
handled in posix open */
202
203
if (rc == 0) {
204
if (newinode == NULL) /* query inode info */
205
goto cifs_create_get_file_info;
206
else /* success, no need to query */
207
goto cifs_create_set_dentry;
208
} else if ((rc != -EIO) && (rc != -EREMOTE) &&
209
(rc != -EOPNOTSUPP) && (rc != -EINVAL))
210
goto cifs_create_out;
211
/* else fallthrough to retry, using older open call, this is
212
case where server does not support this SMB level, and
213
falsely claims capability (also get here for DFS case
214
which should be rare for path not covered on files) */
215
}
216
217
if (nd && (nd->flags & LOOKUP_OPEN)) {
218
/* if the file is going to stay open, then we
219
need to set the desired access properly */
220
desiredAccess = 0;
221
if (OPEN_FMODE(oflags) & FMODE_READ)
222
desiredAccess |= GENERIC_READ; /* is this too little? */
223
if (OPEN_FMODE(oflags) & FMODE_WRITE)
224
desiredAccess |= GENERIC_WRITE;
225
226
if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
227
disposition = FILE_CREATE;
228
else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
229
disposition = FILE_OVERWRITE_IF;
230
else if ((oflags & O_CREAT) == O_CREAT)
231
disposition = FILE_OPEN_IF;
232
else
233
cFYI(1, "Create flag not set in create function");
234
}
235
236
/* BB add processing to set equivalent of mode - e.g. via CreateX with
237
ACLs */
238
239
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
240
if (buf == NULL) {
241
rc = -ENOMEM;
242
goto cifs_create_out;
243
}
244
245
/*
246
* if we're not using unix extensions, see if we need to set
247
* ATTR_READONLY on the create call
248
*/
249
if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
250
create_options |= CREATE_OPTION_READONLY;
251
252
if (tcon->ses->capabilities & CAP_NT_SMBS)
253
rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
254
desiredAccess, create_options,
255
&fileHandle, &oplock, buf, cifs_sb->local_nls,
256
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
257
else
258
rc = -EIO; /* no NT SMB support fall into legacy open below */
259
260
if (rc == -EIO) {
261
/* old server, retry the open legacy style */
262
rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
263
desiredAccess, create_options,
264
&fileHandle, &oplock, buf, cifs_sb->local_nls,
265
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
266
}
267
if (rc) {
268
cFYI(1, "cifs_create returned 0x%x", rc);
269
goto cifs_create_out;
270
}
271
272
/* If Open reported that we actually created a file
273
then we now have to set the mode if possible */
274
if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
275
struct cifs_unix_set_info_args args = {
276
.mode = mode,
277
.ctime = NO_CHANGE_64,
278
.atime = NO_CHANGE_64,
279
.mtime = NO_CHANGE_64,
280
.device = 0,
281
};
282
283
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
284
args.uid = (__u64) current_fsuid();
285
if (inode->i_mode & S_ISGID)
286
args.gid = (__u64) inode->i_gid;
287
else
288
args.gid = (__u64) current_fsgid();
289
} else {
290
args.uid = NO_CHANGE_64;
291
args.gid = NO_CHANGE_64;
292
}
293
CIFSSMBUnixSetFileInfo(xid, tcon, &args, fileHandle,
294
current->tgid);
295
} else {
296
/* BB implement mode setting via Windows security
297
descriptors e.g. */
298
/* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
299
300
/* Could set r/o dos attribute if mode & 0222 == 0 */
301
}
302
303
cifs_create_get_file_info:
304
/* server might mask mode so we have to query for it */
305
if (tcon->unix_ext)
306
rc = cifs_get_inode_info_unix(&newinode, full_path,
307
inode->i_sb, xid);
308
else {
309
rc = cifs_get_inode_info(&newinode, full_path, buf,
310
inode->i_sb, xid, &fileHandle);
311
if (newinode) {
312
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
313
newinode->i_mode = mode;
314
if ((oplock & CIFS_CREATE_ACTION) &&
315
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
316
newinode->i_uid = current_fsuid();
317
if (inode->i_mode & S_ISGID)
318
newinode->i_gid = inode->i_gid;
319
else
320
newinode->i_gid = current_fsgid();
321
}
322
}
323
}
324
325
cifs_create_set_dentry:
326
if (rc == 0)
327
d_instantiate(direntry, newinode);
328
else
329
cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
330
331
if (newinode && nd && (nd->flags & LOOKUP_OPEN)) {
332
struct cifsFileInfo *pfile_info;
333
struct file *filp;
334
335
filp = lookup_instantiate_filp(nd, direntry, generic_file_open);
336
if (IS_ERR(filp)) {
337
rc = PTR_ERR(filp);
338
CIFSSMBClose(xid, tcon, fileHandle);
339
goto cifs_create_out;
340
}
341
342
pfile_info = cifs_new_fileinfo(fileHandle, filp, tlink, oplock);
343
if (pfile_info == NULL) {
344
fput(filp);
345
CIFSSMBClose(xid, tcon, fileHandle);
346
rc = -ENOMEM;
347
}
348
} else {
349
CIFSSMBClose(xid, tcon, fileHandle);
350
}
351
352
cifs_create_out:
353
kfree(buf);
354
kfree(full_path);
355
cifs_put_tlink(tlink);
356
FreeXid(xid);
357
return rc;
358
}
359
360
int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
361
dev_t device_number)
362
{
363
int rc = -EPERM;
364
int xid;
365
struct cifs_sb_info *cifs_sb;
366
struct tcon_link *tlink;
367
struct cifs_tcon *pTcon;
368
struct cifs_io_parms io_parms;
369
char *full_path = NULL;
370
struct inode *newinode = NULL;
371
int oplock = 0;
372
u16 fileHandle;
373
FILE_ALL_INFO *buf = NULL;
374
unsigned int bytes_written;
375
struct win_dev *pdev;
376
377
if (!old_valid_dev(device_number))
378
return -EINVAL;
379
380
cifs_sb = CIFS_SB(inode->i_sb);
381
tlink = cifs_sb_tlink(cifs_sb);
382
if (IS_ERR(tlink))
383
return PTR_ERR(tlink);
384
385
pTcon = tlink_tcon(tlink);
386
387
xid = GetXid();
388
389
full_path = build_path_from_dentry(direntry);
390
if (full_path == NULL) {
391
rc = -ENOMEM;
392
goto mknod_out;
393
}
394
395
if (pTcon->unix_ext) {
396
struct cifs_unix_set_info_args args = {
397
.mode = mode & ~current_umask(),
398
.ctime = NO_CHANGE_64,
399
.atime = NO_CHANGE_64,
400
.mtime = NO_CHANGE_64,
401
.device = device_number,
402
};
403
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
404
args.uid = (__u64) current_fsuid();
405
args.gid = (__u64) current_fsgid();
406
} else {
407
args.uid = NO_CHANGE_64;
408
args.gid = NO_CHANGE_64;
409
}
410
rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
411
cifs_sb->local_nls,
412
cifs_sb->mnt_cifs_flags &
413
CIFS_MOUNT_MAP_SPECIAL_CHR);
414
if (rc)
415
goto mknod_out;
416
417
rc = cifs_get_inode_info_unix(&newinode, full_path,
418
inode->i_sb, xid);
419
420
if (rc == 0)
421
d_instantiate(direntry, newinode);
422
goto mknod_out;
423
}
424
425
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
426
goto mknod_out;
427
428
429
cFYI(1, "sfu compat create special file");
430
431
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
432
if (buf == NULL) {
433
kfree(full_path);
434
rc = -ENOMEM;
435
FreeXid(xid);
436
return rc;
437
}
438
439
/* FIXME: would WRITE_OWNER | WRITE_DAC be better? */
440
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE,
441
GENERIC_WRITE, CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
442
&fileHandle, &oplock, buf, cifs_sb->local_nls,
443
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
444
if (rc)
445
goto mknod_out;
446
447
/* BB Do not bother to decode buf since no local inode yet to put
448
* timestamps in, but we can reuse it safely */
449
450
pdev = (struct win_dev *)buf;
451
io_parms.netfid = fileHandle;
452
io_parms.pid = current->tgid;
453
io_parms.tcon = pTcon;
454
io_parms.offset = 0;
455
io_parms.length = sizeof(struct win_dev);
456
if (S_ISCHR(mode)) {
457
memcpy(pdev->type, "IntxCHR", 8);
458
pdev->major =
459
cpu_to_le64(MAJOR(device_number));
460
pdev->minor =
461
cpu_to_le64(MINOR(device_number));
462
rc = CIFSSMBWrite(xid, &io_parms,
463
&bytes_written, (char *)pdev,
464
NULL, 0);
465
} else if (S_ISBLK(mode)) {
466
memcpy(pdev->type, "IntxBLK", 8);
467
pdev->major =
468
cpu_to_le64(MAJOR(device_number));
469
pdev->minor =
470
cpu_to_le64(MINOR(device_number));
471
rc = CIFSSMBWrite(xid, &io_parms,
472
&bytes_written, (char *)pdev,
473
NULL, 0);
474
} /* else if (S_ISFIFO) */
475
CIFSSMBClose(xid, pTcon, fileHandle);
476
d_drop(direntry);
477
478
/* FIXME: add code here to set EAs */
479
480
mknod_out:
481
kfree(full_path);
482
kfree(buf);
483
FreeXid(xid);
484
cifs_put_tlink(tlink);
485
return rc;
486
}
487
488
struct dentry *
489
cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
490
struct nameidata *nd)
491
{
492
int xid;
493
int rc = 0; /* to get around spurious gcc warning, set to zero here */
494
__u32 oplock = 0;
495
__u16 fileHandle = 0;
496
bool posix_open = false;
497
struct cifs_sb_info *cifs_sb;
498
struct tcon_link *tlink;
499
struct cifs_tcon *pTcon;
500
struct cifsFileInfo *cfile;
501
struct inode *newInode = NULL;
502
char *full_path = NULL;
503
struct file *filp;
504
505
xid = GetXid();
506
507
cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
508
parent_dir_inode, direntry->d_name.name, direntry);
509
510
/* check whether path exists */
511
512
cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
513
tlink = cifs_sb_tlink(cifs_sb);
514
if (IS_ERR(tlink)) {
515
FreeXid(xid);
516
return (struct dentry *)tlink;
517
}
518
pTcon = tlink_tcon(tlink);
519
520
/*
521
* Don't allow the separator character in a path component.
522
* The VFS will not allow "/", but "\" is allowed by posix.
523
*/
524
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
525
int i;
526
for (i = 0; i < direntry->d_name.len; i++)
527
if (direntry->d_name.name[i] == '\\') {
528
cFYI(1, "Invalid file name");
529
rc = -EINVAL;
530
goto lookup_out;
531
}
532
}
533
534
/*
535
* O_EXCL: optimize away the lookup, but don't hash the dentry. Let
536
* the VFS handle the create.
537
*/
538
if (nd && (nd->flags & LOOKUP_EXCL)) {
539
d_instantiate(direntry, NULL);
540
rc = 0;
541
goto lookup_out;
542
}
543
544
/* can not grab the rename sem here since it would
545
deadlock in the cases (beginning of sys_rename itself)
546
in which we already have the sb rename sem */
547
full_path = build_path_from_dentry(direntry);
548
if (full_path == NULL) {
549
rc = -ENOMEM;
550
goto lookup_out;
551
}
552
553
if (direntry->d_inode != NULL) {
554
cFYI(1, "non-NULL inode in lookup");
555
} else {
556
cFYI(1, "NULL inode in lookup");
557
}
558
cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode);
559
560
/* Posix open is only called (at lookup time) for file create now.
561
* For opens (rather than creates), because we do not know if it
562
* is a file or directory yet, and current Samba no longer allows
563
* us to do posix open on dirs, we could end up wasting an open call
564
* on what turns out to be a dir. For file opens, we wait to call posix
565
* open till cifs_open. It could be added here (lookup) in the future
566
* but the performance tradeoff of the extra network request when EISDIR
567
* or EACCES is returned would have to be weighed against the 50%
568
* reduction in network traffic in the other paths.
569
*/
570
if (pTcon->unix_ext) {
571
if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
572
(nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
573
(nd->intent.open.file->f_flags & O_CREAT)) {
574
rc = cifs_posix_open(full_path, &newInode,
575
parent_dir_inode->i_sb,
576
nd->intent.open.create_mode,
577
nd->intent.open.file->f_flags, &oplock,
578
&fileHandle, xid);
579
/*
580
* The check below works around a bug in POSIX
581
* open in samba versions 3.3.1 and earlier where
582
* open could incorrectly fail with invalid parameter.
583
* If either that or op not supported returned, follow
584
* the normal lookup.
585
*/
586
if ((rc == 0) || (rc == -ENOENT))
587
posix_open = true;
588
else if ((rc == -EINVAL) || (rc != -EOPNOTSUPP))
589
pTcon->broken_posix_open = true;
590
}
591
if (!posix_open)
592
rc = cifs_get_inode_info_unix(&newInode, full_path,
593
parent_dir_inode->i_sb, xid);
594
} else
595
rc = cifs_get_inode_info(&newInode, full_path, NULL,
596
parent_dir_inode->i_sb, xid, NULL);
597
598
if ((rc == 0) && (newInode != NULL)) {
599
d_add(direntry, newInode);
600
if (posix_open) {
601
filp = lookup_instantiate_filp(nd, direntry,
602
generic_file_open);
603
if (IS_ERR(filp)) {
604
rc = PTR_ERR(filp);
605
CIFSSMBClose(xid, pTcon, fileHandle);
606
goto lookup_out;
607
}
608
609
cfile = cifs_new_fileinfo(fileHandle, filp, tlink,
610
oplock);
611
if (cfile == NULL) {
612
fput(filp);
613
CIFSSMBClose(xid, pTcon, fileHandle);
614
rc = -ENOMEM;
615
goto lookup_out;
616
}
617
}
618
/* since paths are not looked up by component - the parent
619
directories are presumed to be good here */
620
renew_parental_timestamps(direntry);
621
622
} else if (rc == -ENOENT) {
623
rc = 0;
624
direntry->d_time = jiffies;
625
d_add(direntry, NULL);
626
/* if it was once a directory (but how can we tell?) we could do
627
shrink_dcache_parent(direntry); */
628
} else if (rc != -EACCES) {
629
cERROR(1, "Unexpected lookup error %d", rc);
630
/* We special case check for Access Denied - since that
631
is a common return code */
632
}
633
634
lookup_out:
635
kfree(full_path);
636
cifs_put_tlink(tlink);
637
FreeXid(xid);
638
return ERR_PTR(rc);
639
}
640
641
static int
642
cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
643
{
644
if (nd->flags & LOOKUP_RCU)
645
return -ECHILD;
646
647
if (direntry->d_inode) {
648
if (cifs_revalidate_dentry(direntry))
649
return 0;
650
else
651
return 1;
652
}
653
654
/*
655
* This may be nfsd (or something), anyway, we can't see the
656
* intent of this. So, since this can be for creation, drop it.
657
*/
658
if (!nd)
659
return 0;
660
661
/*
662
* Drop the negative dentry, in order to make sure to use the
663
* case sensitive name which is specified by user if this is
664
* for creation.
665
*/
666
if (!(nd->flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))) {
667
if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
668
return 0;
669
}
670
671
if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled)
672
return 0;
673
674
return 1;
675
}
676
677
/* static int cifs_d_delete(struct dentry *direntry)
678
{
679
int rc = 0;
680
681
cFYI(1, "In cifs d_delete, name = %s", direntry->d_name.name);
682
683
return rc;
684
} */
685
686
const struct dentry_operations cifs_dentry_ops = {
687
.d_revalidate = cifs_d_revalidate,
688
.d_automount = cifs_dfs_d_automount,
689
/* d_delete: cifs_d_delete, */ /* not needed except for debugging */
690
};
691
692
static int cifs_ci_hash(const struct dentry *dentry, const struct inode *inode,
693
struct qstr *q)
694
{
695
struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls;
696
unsigned long hash;
697
int i;
698
699
hash = init_name_hash();
700
for (i = 0; i < q->len; i++)
701
hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
702
hash);
703
q->hash = end_name_hash(hash);
704
705
return 0;
706
}
707
708
static int cifs_ci_compare(const struct dentry *parent,
709
const struct inode *pinode,
710
const struct dentry *dentry, const struct inode *inode,
711
unsigned int len, const char *str, const struct qstr *name)
712
{
713
struct nls_table *codepage = CIFS_SB(pinode->i_sb)->local_nls;
714
715
if ((name->len == len) &&
716
(nls_strnicmp(codepage, name->name, str, len) == 0))
717
return 0;
718
return 1;
719
}
720
721
const struct dentry_operations cifs_ci_dentry_ops = {
722
.d_revalidate = cifs_d_revalidate,
723
.d_hash = cifs_ci_hash,
724
.d_compare = cifs_ci_compare,
725
.d_automount = cifs_dfs_d_automount,
726
};
727
728