FreeBSD/Linux Kernel Cross Reference
sys/fs/smbfs/dir.c
1 /*
2 * dir.c
3 *
4 * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
5 * Copyright (C) 1997 by Volker Lendecke
6 *
7 * Please add a note about your changes to smbfs in the ChangeLog file.
8 */
9
10 #include <linux/sched.h>
11 #include <linux/errno.h>
12 #include <linux/kernel.h>
13 #include <linux/smp_lock.h>
14 #include <linux/ctype.h>
15
16 #include <linux/smb_fs.h>
17 #include <linux/smb_mount.h>
18 #include <linux/smbno.h>
19
20 #include "smb_debug.h"
21 #include "proto.h"
22
23 static int smb_readdir(struct file *, void *, filldir_t);
24 static int smb_dir_open(struct inode *, struct file *);
25
26 static struct dentry *smb_lookup(struct inode *, struct dentry *);
27 static int smb_create(struct inode *, struct dentry *, int);
28 static int smb_mkdir(struct inode *, struct dentry *, int);
29 static int smb_rmdir(struct inode *, struct dentry *);
30 static int smb_unlink(struct inode *, struct dentry *);
31 static int smb_rename(struct inode *, struct dentry *,
32 struct inode *, struct dentry *);
33
34 struct file_operations smb_dir_operations =
35 {
36 read: generic_read_dir,
37 readdir: smb_readdir,
38 ioctl: smb_ioctl,
39 open: smb_dir_open,
40 };
41
42 struct inode_operations smb_dir_inode_operations =
43 {
44 create: smb_create,
45 lookup: smb_lookup,
46 unlink: smb_unlink,
47 mkdir: smb_mkdir,
48 rmdir: smb_rmdir,
49 rename: smb_rename,
50 revalidate: smb_revalidate_inode,
51 setattr: smb_notify_change,
52 };
53
54 /*
55 * Read a directory, using filldir to fill the dirent memory.
56 * smb_proc_readdir does the actual reading from the smb server.
57 *
58 * The cache code is almost directly taken from ncpfs
59 */
60 static int
61 smb_readdir(struct file *filp, void *dirent, filldir_t filldir)
62 {
63 struct dentry *dentry = filp->f_dentry;
64 struct inode *dir = dentry->d_inode;
65 struct smb_sb_info *server = server_from_dentry(dentry);
66 union smb_dir_cache *cache = NULL;
67 struct smb_cache_control ctl;
68 struct page *page = NULL;
69 int result;
70
71 ctl.page = NULL;
72 ctl.cache = NULL;
73
74 VERBOSE("reading %s/%s, f_pos=%d\n",
75 DENTRY_PATH(dentry), (int) filp->f_pos);
76
77 result = 0;
78 switch ((unsigned int) filp->f_pos) {
79 case 0:
80 if (filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR) < 0)
81 goto out;
82 filp->f_pos = 1;
83 /* fallthrough */
84 case 1:
85 if (filldir(dirent, "..", 2, 1,
86 dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
87 goto out;
88 filp->f_pos = 2;
89 }
90
91 /*
92 * Make sure our inode is up-to-date.
93 */
94 result = smb_revalidate_inode(dentry);
95 if (result)
96 goto out;
97
98
99 page = grab_cache_page(&dir->i_data, 0);
100 if (!page)
101 goto read_really;
102
103 ctl.cache = cache = kmap(page);
104 ctl.head = cache->head;
105
106 if (!Page_Uptodate(page) || !ctl.head.eof) {
107 VERBOSE("%s/%s, page uptodate=%d, eof=%d\n",
108 DENTRY_PATH(dentry), Page_Uptodate(page),ctl.head.eof);
109 goto init_cache;
110 }
111
112 if (filp->f_pos == 2) {
113 if (jiffies - ctl.head.time >= SMB_MAX_AGE(server))
114 goto init_cache;
115
116 /*
117 * N.B. ncpfs checks mtime of dentry too here, we don't.
118 * 1. common smb servers do not update mtime on dir changes
119 * 2. it requires an extra smb request
120 * (revalidate has the same timeout as ctl.head.time)
121 *
122 * Instead smbfs invalidates its own cache on local changes
123 * and remote changes are not seen until timeout.
124 */
125 }
126
127 if (filp->f_pos > ctl.head.end)
128 goto finished;
129
130 ctl.fpos = filp->f_pos + (SMB_DIRCACHE_START - 2);
131 ctl.ofs = ctl.fpos / SMB_DIRCACHE_SIZE;
132 ctl.idx = ctl.fpos % SMB_DIRCACHE_SIZE;
133
134 for (;;) {
135 if (ctl.ofs != 0) {
136 ctl.page = find_lock_page(&dir->i_data, ctl.ofs);
137 if (!ctl.page)
138 goto invalid_cache;
139 ctl.cache = kmap(ctl.page);
140 if (!Page_Uptodate(ctl.page))
141 goto invalid_cache;
142 }
143 while (ctl.idx < SMB_DIRCACHE_SIZE) {
144 struct dentry *dent;
145 int res;
146
147 dent = smb_dget_fpos(ctl.cache->dentry[ctl.idx],
148 dentry, filp->f_pos);
149 if (!dent)
150 goto invalid_cache;
151
152 res = filldir(dirent, dent->d_name.name,
153 dent->d_name.len, filp->f_pos,
154 dent->d_inode->i_ino, DT_UNKNOWN);
155 dput(dent);
156 if (res)
157 goto finished;
158 filp->f_pos += 1;
159 ctl.idx += 1;
160 if (filp->f_pos > ctl.head.end)
161 goto finished;
162 }
163 if (ctl.page) {
164 kunmap(ctl.page);
165 SetPageUptodate(ctl.page);
166 UnlockPage(ctl.page);
167 page_cache_release(ctl.page);
168 ctl.page = NULL;
169 }
170 ctl.idx = 0;
171 ctl.ofs += 1;
172 }
173 invalid_cache:
174 if (ctl.page) {
175 kunmap(ctl.page);
176 UnlockPage(ctl.page);
177 page_cache_release(ctl.page);
178 ctl.page = NULL;
179 }
180 ctl.cache = cache;
181 init_cache:
182 smb_invalidate_dircache_entries(dentry);
183 ctl.head.time = jiffies;
184 ctl.head.eof = 0;
185 ctl.fpos = 2;
186 ctl.ofs = 0;
187 ctl.idx = SMB_DIRCACHE_START;
188 ctl.filled = 0;
189 ctl.valid = 1;
190 read_really:
191 result = smb_proc_readdir(filp, dirent, filldir, &ctl);
192 if (ctl.idx == -1)
193 goto invalid_cache; /* retry */
194 ctl.head.end = ctl.fpos - 1;
195 ctl.head.eof = ctl.valid;
196 finished:
197 if (page) {
198 cache->head = ctl.head;
199 kunmap(page);
200 SetPageUptodate(page);
201 UnlockPage(page);
202 page_cache_release(page);
203 }
204 if (ctl.page) {
205 kunmap(ctl.page);
206 SetPageUptodate(ctl.page);
207 UnlockPage(ctl.page);
208 page_cache_release(ctl.page);
209 }
210 out:
211 return result;
212 }
213
214 static int
215 smb_dir_open(struct inode *dir, struct file *file)
216 {
217 struct dentry *dentry = file->f_dentry;
218 struct smb_sb_info *server;
219 int error = 0;
220
221 VERBOSE("(%s/%s)\n", dentry->d_parent->d_name.name,
222 file->f_dentry->d_name.name);
223
224 /*
225 * Directory timestamps in the core protocol aren't updated
226 * when a file is added, so we give them a very short TTL.
227 */
228 lock_kernel();
229 server = server_from_dentry(dentry);
230 if (server->opt.protocol < SMB_PROTOCOL_LANMAN2) {
231 unsigned long age = jiffies - dir->u.smbfs_i.oldmtime;
232 if (age > 2*HZ)
233 smb_invalid_dir_cache(dir);
234 }
235
236 /*
237 * Note: in order to allow the smbmount process to open the
238 * mount point, we only revalidate if the connection is valid or
239 * if the process is trying to access something other than the root.
240 */
241 if (server->state == CONN_VALID || !IS_ROOT(dentry))
242 error = smb_revalidate_inode(dentry);
243 unlock_kernel();
244 return error;
245 }
246
247 /*
248 * Dentry operations routines
249 */
250 static int smb_lookup_validate(struct dentry *, int);
251 static int smb_hash_dentry(struct dentry *, struct qstr *);
252 static int smb_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
253 static int smb_delete_dentry(struct dentry *);
254
255 static struct dentry_operations smbfs_dentry_operations =
256 {
257 d_revalidate: smb_lookup_validate,
258 d_hash: smb_hash_dentry,
259 d_compare: smb_compare_dentry,
260 d_delete: smb_delete_dentry,
261 };
262
263 static struct dentry_operations smbfs_dentry_operations_case =
264 {
265 d_revalidate: smb_lookup_validate,
266 d_delete: smb_delete_dentry,
267 };
268
269
270 /*
271 * This is the callback when the dcache has a lookup hit.
272 */
273 static int
274 smb_lookup_validate(struct dentry * dentry, int flags)
275 {
276 struct smb_sb_info *server = server_from_dentry(dentry);
277 struct inode * inode = dentry->d_inode;
278 unsigned long age = jiffies - dentry->d_time;
279 int valid;
280
281 /*
282 * The default validation is based on dentry age:
283 * we believe in dentries for a few seconds. (But each
284 * successful server lookup renews the timestamp.)
285 */
286 valid = (age <= SMB_MAX_AGE(server));
287 #ifdef SMBFS_DEBUG_VERBOSE
288 if (!valid)
289 VERBOSE("%s/%s not valid, age=%lu\n",
290 DENTRY_PATH(dentry), age);
291 #endif
292
293 if (inode) {
294 lock_kernel();
295 if (is_bad_inode(inode)) {
296 PARANOIA("%s/%s has dud inode\n", DENTRY_PATH(dentry));
297 valid = 0;
298 } else if (!valid)
299 valid = (smb_revalidate_inode(dentry) == 0);
300 unlock_kernel();
301 } else {
302 /*
303 * What should we do for negative dentries?
304 */
305 }
306 return valid;
307 }
308
309 static int
310 smb_hash_dentry(struct dentry *dir, struct qstr *this)
311 {
312 unsigned long hash;
313 int i;
314
315 hash = init_name_hash();
316 for (i=0; i < this->len ; i++)
317 hash = partial_name_hash(tolower(this->name[i]), hash);
318 this->hash = end_name_hash(hash);
319
320 return 0;
321 }
322
323 static int
324 smb_compare_dentry(struct dentry *dir, struct qstr *a, struct qstr *b)
325 {
326 int i, result = 1;
327
328 if (a->len != b->len)
329 goto out;
330 for (i=0; i < a->len; i++) {
331 if (tolower(a->name[i]) != tolower(b->name[i]))
332 goto out;
333 }
334 result = 0;
335 out:
336 return result;
337 }
338
339 /*
340 * This is the callback from dput() when d_count is going to 0.
341 * We use this to unhash dentries with bad inodes.
342 */
343 static int
344 smb_delete_dentry(struct dentry * dentry)
345 {
346 if (dentry->d_inode) {
347 if (is_bad_inode(dentry->d_inode)) {
348 PARANOIA("bad inode, unhashing %s/%s\n",
349 DENTRY_PATH(dentry));
350 return 1;
351 }
352 } else {
353 /* N.B. Unhash negative dentries? */
354 }
355 return 0;
356 }
357
358 /*
359 * Initialize a new dentry
360 */
361 void
362 smb_new_dentry(struct dentry *dentry)
363 {
364 struct smb_sb_info *server = server_from_dentry(dentry);
365
366 if (server->mnt->flags & SMB_MOUNT_CASE)
367 dentry->d_op = &smbfs_dentry_operations_case;
368 else
369 dentry->d_op = &smbfs_dentry_operations;
370 dentry->d_time = jiffies;
371 }
372
373
374 /*
375 * Whenever a lookup succeeds, we know the parent directories
376 * are all valid, so we want to update the dentry timestamps.
377 * N.B. Move this to dcache?
378 */
379 void
380 smb_renew_times(struct dentry * dentry)
381 {
382 for (;;) {
383 dentry->d_time = jiffies;
384 if (IS_ROOT(dentry))
385 break;
386 dentry = dentry->d_parent;
387 }
388 }
389
390 static struct dentry *
391 smb_lookup(struct inode *dir, struct dentry *dentry)
392 {
393 struct smb_fattr finfo;
394 struct inode *inode;
395 int error;
396 struct smb_sb_info *server;
397
398 error = -ENAMETOOLONG;
399 if (dentry->d_name.len > SMB_MAXNAMELEN)
400 goto out;
401
402 error = smb_proc_getattr(dentry, &finfo);
403 #ifdef SMBFS_PARANOIA
404 if (error && error != -ENOENT)
405 PARANOIA("find %s/%s failed, error=%d\n",
406 DENTRY_PATH(dentry), error);
407 #endif
408
409 inode = NULL;
410 if (error == -ENOENT)
411 goto add_entry;
412 if (!error) {
413 error = -EACCES;
414 finfo.f_ino = iunique(dentry->d_sb, 2);
415 inode = smb_iget(dir->i_sb, &finfo);
416 if (inode) {
417 add_entry:
418 server = server_from_dentry(dentry);
419 if (server->mnt->flags & SMB_MOUNT_CASE)
420 dentry->d_op = &smbfs_dentry_operations_case;
421 else
422 dentry->d_op = &smbfs_dentry_operations;
423
424 d_add(dentry, inode);
425 smb_renew_times(dentry);
426 error = 0;
427 }
428 }
429 out:
430 return ERR_PTR(error);
431 }
432
433 /*
434 * This code is common to all routines creating a new inode.
435 */
436 static int
437 smb_instantiate(struct dentry *dentry, __u16 fileid, int have_id)
438 {
439 struct smb_sb_info *server = server_from_dentry(dentry);
440 struct inode *inode;
441 int error;
442 struct smb_fattr fattr;
443
444 VERBOSE("file %s/%s, fileid=%u\n", DENTRY_PATH(dentry), fileid);
445
446 error = smb_proc_getattr(dentry, &fattr);
447 if (error)
448 goto out_close;
449
450 smb_renew_times(dentry);
451 fattr.f_ino = iunique(dentry->d_sb, 2);
452 inode = smb_iget(dentry->d_sb, &fattr);
453 if (!inode)
454 goto out_no_inode;
455
456 if (have_id) {
457 inode->u.smbfs_i.fileid = fileid;
458 inode->u.smbfs_i.access = SMB_O_RDWR;
459 inode->u.smbfs_i.open = server->generation;
460 }
461 d_instantiate(dentry, inode);
462 out:
463 return error;
464
465 out_no_inode:
466 error = -EACCES;
467 out_close:
468 if (have_id) {
469 PARANOIA("%s/%s failed, error=%d, closing %u\n",
470 DENTRY_PATH(dentry), error, fileid);
471 smb_close_fileid(dentry, fileid);
472 }
473 goto out;
474 }
475
476 /* N.B. How should the mode argument be used? */
477 static int
478 smb_create(struct inode *dir, struct dentry *dentry, int mode)
479 {
480 __u16 fileid;
481 int error;
482
483 VERBOSE("creating %s/%s, mode=%d\n", DENTRY_PATH(dentry), mode);
484
485 smb_invalid_dir_cache(dir);
486 error = smb_proc_create(dentry, 0, CURRENT_TIME, &fileid);
487 if (!error) {
488 error = smb_instantiate(dentry, fileid, 1);
489 } else {
490 PARANOIA("%s/%s failed, error=%d\n",
491 DENTRY_PATH(dentry), error);
492 }
493 return error;
494 }
495
496 /* N.B. How should the mode argument be used? */
497 static int
498 smb_mkdir(struct inode *dir, struct dentry *dentry, int mode)
499 {
500 int error;
501
502 smb_invalid_dir_cache(dir);
503 error = smb_proc_mkdir(dentry);
504 if (!error) {
505 error = smb_instantiate(dentry, 0, 0);
506 }
507 return error;
508 }
509
510 static int
511 smb_rmdir(struct inode *dir, struct dentry *dentry)
512 {
513 struct inode *inode = dentry->d_inode;
514 int error;
515
516 /*
517 * Close the directory if it's open.
518 */
519 smb_close(inode);
520
521 /*
522 * Check that nobody else is using the directory..
523 */
524 error = -EBUSY;
525 if (!d_unhashed(dentry))
526 goto out;
527
528 smb_invalid_dir_cache(dir);
529 error = smb_proc_rmdir(dentry);
530
531 out:
532 return error;
533 }
534
535 static int
536 smb_unlink(struct inode *dir, struct dentry *dentry)
537 {
538 int error;
539
540 /*
541 * Close the file if it's open.
542 */
543 smb_close(dentry->d_inode);
544
545 smb_invalid_dir_cache(dir);
546 error = smb_proc_unlink(dentry);
547 if (!error)
548 smb_renew_times(dentry);
549 return error;
550 }
551
552 static int
553 smb_rename(struct inode *old_dir, struct dentry *old_dentry,
554 struct inode *new_dir, struct dentry *new_dentry)
555 {
556 int error;
557
558 /*
559 * Close any open files, and check whether to delete the
560 * target before attempting the rename.
561 */
562 if (old_dentry->d_inode)
563 smb_close(old_dentry->d_inode);
564 if (new_dentry->d_inode) {
565 smb_close(new_dentry->d_inode);
566 error = smb_proc_unlink(new_dentry);
567 if (error) {
568 VERBOSE("unlink %s/%s, error=%d\n",
569 DENTRY_PATH(new_dentry), error);
570 goto out;
571 }
572 /* FIXME */
573 d_delete(new_dentry);
574 }
575
576 smb_invalid_dir_cache(old_dir);
577 smb_invalid_dir_cache(new_dir);
578 error = smb_proc_mv(old_dentry, new_dentry);
579 if (!error) {
580 smb_renew_times(old_dentry);
581 smb_renew_times(new_dentry);
582 }
583 out:
584 return error;
585 }
Cache object: a7e60ca5295541bbc98ebae1336d2f1e
|