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