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
22 #define SMBFS_MAX_AGE 5*HZ
23
24 static int smb_readdir(struct file *, void *, filldir_t);
25 static int smb_dir_open(struct inode *, struct file *);
26
27 static struct dentry *smb_lookup(struct inode *, struct dentry *);
28 static int smb_create(struct inode *, struct dentry *, int);
29 static int smb_mkdir(struct inode *, struct dentry *, int);
30 static int smb_rmdir(struct inode *, struct dentry *);
31 static int smb_unlink(struct inode *, struct dentry *);
32 static int smb_rename(struct inode *, struct dentry *,
33 struct inode *, struct dentry *);
34
35 struct file_operations smb_dir_operations =
36 {
37 read: generic_read_dir,
38 readdir: smb_readdir,
39 ioctl: smb_ioctl,
40 open: smb_dir_open,
41 };
42
43 struct inode_operations smb_dir_inode_operations =
44 {
45 create: smb_create,
46 lookup: smb_lookup,
47 unlink: smb_unlink,
48 mkdir: smb_mkdir,
49 rmdir: smb_rmdir,
50 rename: smb_rename,
51 revalidate: smb_revalidate_inode,
52 setattr: smb_notify_change,
53 };
54
55 static int
56 smb_readdir(struct file *filp, void *dirent, filldir_t filldir)
57 {
58 struct dentry *dentry = filp->f_dentry;
59 struct inode *dir = dentry->d_inode;
60 struct cache_head *cachep;
61 int result;
62
63 VERBOSE("reading %s/%s, f_pos=%d\n",
64 DENTRY_PATH(dentry), (int) filp->f_pos);
65
66 result = 0;
67 switch ((unsigned int) filp->f_pos)
68 {
69 case 0:
70 if (filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR) < 0)
71 goto out;
72 filp->f_pos = 1;
73 case 1:
74 if (filldir(dirent, "..", 2, 1,
75 dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
76 goto out;
77 filp->f_pos = 2;
78 }
79
80 /*
81 * Make sure our inode is up-to-date.
82 */
83 result = smb_revalidate_inode(dentry);
84 if (result)
85 goto out;
86 /*
87 * Get the cache pointer ...
88 */
89 result = -EIO;
90 cachep = smb_get_dircache(dentry);
91 if (!cachep)
92 goto out;
93
94 /*
95 * Make sure the cache is up-to-date.
96 *
97 * To detect changes on the server we refill on each "new" access.
98 *
99 * Directory mtime would be nice to use for finding changes,
100 * unfortunately some servers (NT4) doesn't update on local changes.
101 */
102 if (!cachep->valid || filp->f_pos == 2)
103 {
104 result = smb_refill_dircache(cachep, dentry);
105 if (result)
106 goto out_free;
107 }
108
109 result = 0;
110
111 while (1)
112 {
113 struct cache_dirent this_dirent, *entry = &this_dirent;
114
115 if (!smb_find_in_cache(cachep, filp->f_pos, entry))
116 break;
117 /*
118 * Check whether to look up the inode number.
119 */
120 if (!entry->ino) {
121 struct qstr qname;
122 /* N.B. Make cache_dirent name a qstr! */
123 qname.name = entry->name;
124 qname.len = entry->len;
125 entry->ino = find_inode_number(dentry, &qname);
126 if (!entry->ino)
127 entry->ino = iunique(dentry->d_sb, 2);
128 }
129
130 if (filldir(dirent, entry->name, entry->len,
131 filp->f_pos, entry->ino, DT_UNKNOWN) < 0)
132 break;
133 filp->f_pos += 1;
134 }
135
136 /*
137 * Release the dircache.
138 */
139 out_free:
140 smb_free_dircache(cachep);
141 out:
142 return result;
143 }
144
145 /*
146 * Note: in order to allow the smbmount process to open the
147 * mount point, we don't revalidate if conn_pid is NULL.
148 */
149 static int
150 smb_dir_open(struct inode *dir, struct file *file)
151 {
152 struct dentry *dentry = file->f_dentry;
153 struct smb_sb_info *server;
154 int error = 0;
155
156 VERBOSE("(%s/%s)\n", dentry->d_parent->d_name.name,
157 file->f_dentry->d_name.name);
158
159 /*
160 * Directory timestamps in the core protocol aren't updated
161 * when a file is added, so we give them a very short TTL.
162 */
163 lock_kernel();
164 server = server_from_dentry(dentry);
165 if (server->opt.protocol < SMB_PROTOCOL_LANMAN2)
166 {
167 unsigned long age = jiffies - dir->u.smbfs_i.oldmtime;
168 if (age > 2*HZ)
169 smb_invalid_dir_cache(dir);
170 }
171
172 if (server->conn_pid)
173 error = smb_revalidate_inode(dentry);
174 unlock_kernel();
175 return error;
176 }
177
178 /*
179 * Dentry operations routines
180 */
181 static int smb_lookup_validate(struct dentry *, int);
182 static int smb_hash_dentry(struct dentry *, struct qstr *);
183 static int smb_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
184 static int smb_delete_dentry(struct dentry *);
185
186 static struct dentry_operations smbfs_dentry_operations =
187 {
188 d_revalidate: smb_lookup_validate,
189 d_hash: smb_hash_dentry,
190 d_compare: smb_compare_dentry,
191 d_delete: smb_delete_dentry,
192 };
193
194 static struct dentry_operations smbfs_dentry_operations_case =
195 {
196 d_revalidate: smb_lookup_validate,
197 d_delete: smb_delete_dentry,
198 };
199
200
201 /*
202 * This is the callback when the dcache has a lookup hit.
203 */
204 static int
205 smb_lookup_validate(struct dentry * dentry, int flags)
206 {
207 struct inode * inode = dentry->d_inode;
208 unsigned long age = jiffies - dentry->d_time;
209 int valid;
210
211 /*
212 * The default validation is based on dentry age:
213 * we believe in dentries for 5 seconds. (But each
214 * successful server lookup renews the timestamp.)
215 */
216 valid = (age <= SMBFS_MAX_AGE);
217 #ifdef SMBFS_DEBUG_VERBOSE
218 if (!valid)
219 VERBOSE("%s/%s not valid, age=%lu\n",
220 DENTRY_PATH(dentry), age);
221 #endif
222
223 if (inode) {
224 lock_kernel();
225 if (is_bad_inode(inode)) {
226 PARANOIA("%s/%s has dud inode\n", DENTRY_PATH(dentry));
227 valid = 0;
228 } else if (!valid)
229 valid = (smb_revalidate_inode(dentry) == 0);
230 unlock_kernel();
231 } else {
232 /*
233 * What should we do for negative dentries?
234 */
235 }
236 return valid;
237 }
238
239 static int
240 smb_hash_dentry(struct dentry *dir, struct qstr *this)
241 {
242 unsigned long hash;
243 int i;
244
245 hash = init_name_hash();
246 for (i=0; i < this->len ; i++)
247 hash = partial_name_hash(tolower(this->name[i]), hash);
248 this->hash = end_name_hash(hash);
249
250 return 0;
251 }
252
253 static int
254 smb_compare_dentry(struct dentry *dir, struct qstr *a, struct qstr *b)
255 {
256 int i, result = 1;
257
258 if (a->len != b->len)
259 goto out;
260 for (i=0; i < a->len; i++) {
261 if (tolower(a->name[i]) != tolower(b->name[i]))
262 goto out;
263 }
264 result = 0;
265 out:
266 return result;
267 }
268
269 /*
270 * This is the callback from dput() when d_count is going to 0.
271 * We use this to unhash dentries with bad inodes.
272 */
273 static int
274 smb_delete_dentry(struct dentry * dentry)
275 {
276 if (dentry->d_inode) {
277 if (is_bad_inode(dentry->d_inode)) {
278 PARANOIA("bad inode, unhashing %s/%s\n",
279 DENTRY_PATH(dentry));
280 return 1;
281 }
282 } else {
283 /* N.B. Unhash negative dentries? */
284 }
285 return 0;
286 }
287
288 /*
289 * Whenever a lookup succeeds, we know the parent directories
290 * are all valid, so we want to update the dentry timestamps.
291 * N.B. Move this to dcache?
292 */
293 void
294 smb_renew_times(struct dentry * dentry)
295 {
296 for (;;) {
297 dentry->d_time = jiffies;
298 if (IS_ROOT(dentry))
299 break;
300 dentry = dentry->d_parent;
301 }
302 }
303
304 static struct dentry *
305 smb_lookup(struct inode *dir, struct dentry *dentry)
306 {
307 struct smb_fattr finfo;
308 struct inode *inode;
309 int error;
310 struct smb_sb_info *server;
311
312 error = -ENAMETOOLONG;
313 if (dentry->d_name.len > SMB_MAXNAMELEN)
314 goto out;
315
316 error = smb_proc_getattr(dentry, &finfo);
317 #ifdef SMBFS_PARANOIA
318 if (error && error != -ENOENT)
319 PARANOIA("find %s/%s failed, error=%d\n",
320 DENTRY_PATH(dentry), error);
321 #endif
322
323 inode = NULL;
324 if (error == -ENOENT)
325 goto add_entry;
326 if (!error) {
327 error = -EACCES;
328 finfo.f_ino = iunique(dentry->d_sb, 2);
329 inode = smb_iget(dir->i_sb, &finfo);
330 if (inode) {
331 add_entry:
332 server = server_from_dentry(dentry);
333 if (server->mnt->flags & SMB_MOUNT_CASE)
334 dentry->d_op = &smbfs_dentry_operations_case;
335 else
336 dentry->d_op = &smbfs_dentry_operations;
337
338 d_add(dentry, inode);
339 smb_renew_times(dentry);
340 error = 0;
341 }
342 }
343 out:
344 return ERR_PTR(error);
345 }
346
347 /*
348 * This code is common to all routines creating a new inode.
349 */
350 static int
351 smb_instantiate(struct dentry *dentry, __u16 fileid, int have_id)
352 {
353 struct smb_sb_info *server = server_from_dentry(dentry);
354 struct inode *inode;
355 int error;
356 struct smb_fattr fattr;
357
358 VERBOSE("file %s/%s, fileid=%u\n", DENTRY_PATH(dentry), fileid);
359
360 error = smb_proc_getattr(dentry, &fattr);
361 if (error)
362 goto out_close;
363
364 smb_renew_times(dentry);
365 fattr.f_ino = iunique(dentry->d_sb, 2);
366 inode = smb_iget(dentry->d_sb, &fattr);
367 if (!inode)
368 goto out_no_inode;
369
370 if (have_id)
371 {
372 inode->u.smbfs_i.fileid = fileid;
373 inode->u.smbfs_i.access = SMB_O_RDWR;
374 inode->u.smbfs_i.open = server->generation;
375 }
376 d_instantiate(dentry, inode);
377 out:
378 return error;
379
380 out_no_inode:
381 error = -EACCES;
382 out_close:
383 if (have_id)
384 {
385 PARANOIA("%s/%s failed, error=%d, closing %u\n",
386 DENTRY_PATH(dentry), error, fileid);
387 smb_close_fileid(dentry, fileid);
388 }
389 goto out;
390 }
391
392 /* N.B. How should the mode argument be used? */
393 static int
394 smb_create(struct inode *dir, struct dentry *dentry, int mode)
395 {
396 __u16 fileid;
397 int error;
398
399 VERBOSE("creating %s/%s, mode=%d\n", DENTRY_PATH(dentry), mode);
400
401 smb_invalid_dir_cache(dir);
402 error = smb_proc_create(dentry, 0, CURRENT_TIME, &fileid);
403 if (!error) {
404 error = smb_instantiate(dentry, fileid, 1);
405 } else {
406 PARANOIA("%s/%s failed, error=%d\n",
407 DENTRY_PATH(dentry), error);
408 }
409 return error;
410 }
411
412 /* N.B. How should the mode argument be used? */
413 static int
414 smb_mkdir(struct inode *dir, struct dentry *dentry, int mode)
415 {
416 int error;
417
418 smb_invalid_dir_cache(dir);
419 error = smb_proc_mkdir(dentry);
420 if (!error) {
421 error = smb_instantiate(dentry, 0, 0);
422 }
423 return error;
424 }
425
426 static int
427 smb_rmdir(struct inode *dir, struct dentry *dentry)
428 {
429 struct inode *inode = dentry->d_inode;
430 int error;
431
432 /*
433 * Close the directory if it's open.
434 */
435 smb_close(inode);
436
437 /*
438 * Check that nobody else is using the directory..
439 */
440 error = -EBUSY;
441 if (!d_unhashed(dentry))
442 goto out;
443
444 error = smb_proc_rmdir(dentry);
445
446 out:
447 return error;
448 }
449
450 static int
451 smb_unlink(struct inode *dir, struct dentry *dentry)
452 {
453 int error;
454
455 /*
456 * Close the file if it's open.
457 */
458 smb_close(dentry->d_inode);
459
460 error = smb_proc_unlink(dentry);
461 if (!error)
462 smb_renew_times(dentry);
463 return error;
464 }
465
466 static int
467 smb_rename(struct inode *old_dir, struct dentry *old_dentry,
468 struct inode *new_dir, struct dentry *new_dentry)
469 {
470 int error;
471
472 /*
473 * Close any open files, and check whether to delete the
474 * target before attempting the rename.
475 */
476 if (old_dentry->d_inode)
477 smb_close(old_dentry->d_inode);
478 if (new_dentry->d_inode)
479 {
480 smb_close(new_dentry->d_inode);
481 error = smb_proc_unlink(new_dentry);
482 if (error)
483 {
484 VERBOSE("unlink %s/%s, error=%d\n",
485 DENTRY_PATH(new_dentry), error);
486 goto out;
487 }
488 /* FIXME */
489 d_delete(new_dentry);
490 }
491
492 smb_invalid_dir_cache(old_dir);
493 smb_invalid_dir_cache(new_dir);
494 error = smb_proc_mv(old_dentry, new_dentry);
495 if (!error)
496 {
497 smb_renew_times(old_dentry);
498 smb_renew_times(new_dentry);
499 }
500 out:
501 return error;
502 }
503
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.