Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/fs/coda/dir.c
26295 views
1
// SPDX-License-Identifier: GPL-2.0
2
3
/*
4
* Directory operations for Coda filesystem
5
* Original version: (C) 1996 P. Braam and M. Callahan
6
* Rewritten for Linux 2.1. (C) 1997 Carnegie Mellon University
7
*
8
* Carnegie Mellon encourages users to contribute improvements to
9
* the Coda project. Contact Peter Braam ([email protected]).
10
*/
11
12
#include <linux/types.h>
13
#include <linux/kernel.h>
14
#include <linux/time.h>
15
#include <linux/fs.h>
16
#include <linux/slab.h>
17
#include <linux/file.h>
18
#include <linux/stat.h>
19
#include <linux/errno.h>
20
#include <linux/string.h>
21
#include <linux/spinlock.h>
22
#include <linux/namei.h>
23
#include <linux/uaccess.h>
24
25
#include <linux/coda.h>
26
#include "coda_psdev.h"
27
#include "coda_linux.h"
28
#include "coda_cache.h"
29
30
#include "coda_int.h"
31
32
/* same as fs/bad_inode.c */
33
static int coda_return_EIO(void)
34
{
35
return -EIO;
36
}
37
#define CODA_EIO_ERROR ((void *) (coda_return_EIO))
38
39
/* inode operations for directories */
40
/* access routines: lookup, readlink, permission */
41
static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, unsigned int flags)
42
{
43
struct super_block *sb = dir->i_sb;
44
const char *name = entry->d_name.name;
45
size_t length = entry->d_name.len;
46
struct inode *inode;
47
int type = 0;
48
49
if (length > CODA_MAXNAMLEN) {
50
pr_err("name too long: lookup, %s %zu\n",
51
coda_i2s(dir), length);
52
return ERR_PTR(-ENAMETOOLONG);
53
}
54
55
/* control object, create inode on the fly */
56
if (is_root_inode(dir) && coda_iscontrol(name, length)) {
57
inode = coda_cnode_makectl(sb);
58
type = CODA_NOCACHE;
59
} else {
60
struct CodaFid fid = { { 0, } };
61
int error = venus_lookup(sb, coda_i2f(dir), name, length,
62
&type, &fid);
63
inode = !error ? coda_cnode_make(&fid, sb) : ERR_PTR(error);
64
}
65
66
if (!IS_ERR(inode) && (type & CODA_NOCACHE))
67
coda_flag_inode(inode, C_VATTR | C_PURGE);
68
69
if (inode == ERR_PTR(-ENOENT))
70
inode = NULL;
71
72
return d_splice_alias(inode, entry);
73
}
74
75
76
int coda_permission(struct mnt_idmap *idmap, struct inode *inode,
77
int mask)
78
{
79
int error;
80
81
if (mask & MAY_NOT_BLOCK)
82
return -ECHILD;
83
84
mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
85
86
if (!mask)
87
return 0;
88
89
if ((mask & MAY_EXEC) && !execute_ok(inode))
90
return -EACCES;
91
92
if (coda_cache_check(inode, mask))
93
return 0;
94
95
error = venus_access(inode->i_sb, coda_i2f(inode), mask);
96
97
if (!error)
98
coda_cache_enter(inode, mask);
99
100
return error;
101
}
102
103
104
static inline void coda_dir_update_mtime(struct inode *dir)
105
{
106
#ifdef REQUERY_VENUS_FOR_MTIME
107
/* invalidate the directory cnode's attributes so we refetch the
108
* attributes from venus next time the inode is referenced */
109
coda_flag_inode(dir, C_VATTR);
110
#else
111
/* optimistically we can also act as if our nose bleeds. The
112
* granularity of the mtime is coarse anyways so we might actually be
113
* right most of the time. Note: we only do this for directories. */
114
inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
115
#endif
116
}
117
118
/* we have to wrap inc_nlink/drop_nlink because sometimes userspace uses a
119
* trick to fool GNU find's optimizations. If we can't be sure of the link
120
* (because of volume mount points) we set i_nlink to 1 which forces find
121
* to consider every child as a possible directory. We should also never
122
* see an increment or decrement for deleted directories where i_nlink == 0 */
123
static inline void coda_dir_inc_nlink(struct inode *dir)
124
{
125
if (dir->i_nlink >= 2)
126
inc_nlink(dir);
127
}
128
129
static inline void coda_dir_drop_nlink(struct inode *dir)
130
{
131
if (dir->i_nlink > 2)
132
drop_nlink(dir);
133
}
134
135
/* creation routines: create, mknod, mkdir, link, symlink */
136
static int coda_create(struct mnt_idmap *idmap, struct inode *dir,
137
struct dentry *de, umode_t mode, bool excl)
138
{
139
int error;
140
const char *name=de->d_name.name;
141
int length=de->d_name.len;
142
struct inode *inode;
143
struct CodaFid newfid;
144
struct coda_vattr attrs;
145
146
if (is_root_inode(dir) && coda_iscontrol(name, length))
147
return -EPERM;
148
149
error = venus_create(dir->i_sb, coda_i2f(dir), name, length,
150
0, mode, &newfid, &attrs);
151
if (error)
152
goto err_out;
153
154
inode = coda_iget(dir->i_sb, &newfid, &attrs);
155
if (IS_ERR(inode)) {
156
error = PTR_ERR(inode);
157
goto err_out;
158
}
159
160
/* invalidate the directory cnode's attributes */
161
coda_dir_update_mtime(dir);
162
d_instantiate(de, inode);
163
return 0;
164
err_out:
165
d_drop(de);
166
return error;
167
}
168
169
static struct dentry *coda_mkdir(struct mnt_idmap *idmap, struct inode *dir,
170
struct dentry *de, umode_t mode)
171
{
172
struct inode *inode;
173
struct coda_vattr attrs;
174
const char *name = de->d_name.name;
175
int len = de->d_name.len;
176
int error;
177
struct CodaFid newfid;
178
179
if (is_root_inode(dir) && coda_iscontrol(name, len))
180
return ERR_PTR(-EPERM);
181
182
attrs.va_mode = mode;
183
error = venus_mkdir(dir->i_sb, coda_i2f(dir),
184
name, len, &newfid, &attrs);
185
if (error)
186
goto err_out;
187
188
inode = coda_iget(dir->i_sb, &newfid, &attrs);
189
if (IS_ERR(inode)) {
190
error = PTR_ERR(inode);
191
goto err_out;
192
}
193
194
/* invalidate the directory cnode's attributes */
195
coda_dir_inc_nlink(dir);
196
coda_dir_update_mtime(dir);
197
d_instantiate(de, inode);
198
return NULL;
199
err_out:
200
d_drop(de);
201
return ERR_PTR(error);
202
}
203
204
/* try to make de an entry in dir_inodde linked to source_de */
205
static int coda_link(struct dentry *source_de, struct inode *dir_inode,
206
struct dentry *de)
207
{
208
struct inode *inode = d_inode(source_de);
209
const char * name = de->d_name.name;
210
int len = de->d_name.len;
211
int error;
212
213
if (is_root_inode(dir_inode) && coda_iscontrol(name, len))
214
return -EPERM;
215
216
error = venus_link(dir_inode->i_sb, coda_i2f(inode),
217
coda_i2f(dir_inode), (const char *)name, len);
218
if (error) {
219
d_drop(de);
220
return error;
221
}
222
223
coda_dir_update_mtime(dir_inode);
224
ihold(inode);
225
d_instantiate(de, inode);
226
inc_nlink(inode);
227
return 0;
228
}
229
230
231
static int coda_symlink(struct mnt_idmap *idmap,
232
struct inode *dir_inode, struct dentry *de,
233
const char *symname)
234
{
235
const char *name = de->d_name.name;
236
int len = de->d_name.len;
237
int symlen;
238
int error;
239
240
if (is_root_inode(dir_inode) && coda_iscontrol(name, len))
241
return -EPERM;
242
243
symlen = strlen(symname);
244
if (symlen > CODA_MAXPATHLEN)
245
return -ENAMETOOLONG;
246
247
/*
248
* This entry is now negative. Since we do not create
249
* an inode for the entry we have to drop it.
250
*/
251
d_drop(de);
252
error = venus_symlink(dir_inode->i_sb, coda_i2f(dir_inode), name, len,
253
symname, symlen);
254
255
/* mtime is no good anymore */
256
if (!error)
257
coda_dir_update_mtime(dir_inode);
258
259
return error;
260
}
261
262
/* destruction routines: unlink, rmdir */
263
static int coda_unlink(struct inode *dir, struct dentry *de)
264
{
265
int error;
266
const char *name = de->d_name.name;
267
int len = de->d_name.len;
268
269
error = venus_remove(dir->i_sb, coda_i2f(dir), name, len);
270
if (error)
271
return error;
272
273
coda_dir_update_mtime(dir);
274
drop_nlink(d_inode(de));
275
return 0;
276
}
277
278
static int coda_rmdir(struct inode *dir, struct dentry *de)
279
{
280
const char *name = de->d_name.name;
281
int len = de->d_name.len;
282
int error;
283
284
error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);
285
if (!error) {
286
/* VFS may delete the child */
287
if (d_really_is_positive(de))
288
clear_nlink(d_inode(de));
289
290
/* fix the link count of the parent */
291
coda_dir_drop_nlink(dir);
292
coda_dir_update_mtime(dir);
293
}
294
return error;
295
}
296
297
/* rename */
298
static int coda_rename(struct mnt_idmap *idmap, struct inode *old_dir,
299
struct dentry *old_dentry, struct inode *new_dir,
300
struct dentry *new_dentry, unsigned int flags)
301
{
302
const char *old_name = old_dentry->d_name.name;
303
const char *new_name = new_dentry->d_name.name;
304
int old_length = old_dentry->d_name.len;
305
int new_length = new_dentry->d_name.len;
306
int error;
307
308
if (flags)
309
return -EINVAL;
310
311
error = venus_rename(old_dir->i_sb, coda_i2f(old_dir),
312
coda_i2f(new_dir), old_length, new_length,
313
(const char *) old_name, (const char *)new_name);
314
if (!error) {
315
if (d_really_is_positive(new_dentry)) {
316
if (d_is_dir(new_dentry)) {
317
coda_dir_drop_nlink(old_dir);
318
coda_dir_inc_nlink(new_dir);
319
}
320
coda_flag_inode(d_inode(new_dentry), C_VATTR);
321
}
322
coda_dir_update_mtime(old_dir);
323
coda_dir_update_mtime(new_dir);
324
}
325
return error;
326
}
327
328
static inline unsigned int CDT2DT(unsigned char cdt)
329
{
330
unsigned int dt;
331
332
switch(cdt) {
333
case CDT_UNKNOWN: dt = DT_UNKNOWN; break;
334
case CDT_FIFO: dt = DT_FIFO; break;
335
case CDT_CHR: dt = DT_CHR; break;
336
case CDT_DIR: dt = DT_DIR; break;
337
case CDT_BLK: dt = DT_BLK; break;
338
case CDT_REG: dt = DT_REG; break;
339
case CDT_LNK: dt = DT_LNK; break;
340
case CDT_SOCK: dt = DT_SOCK; break;
341
case CDT_WHT: dt = DT_WHT; break;
342
default: dt = DT_UNKNOWN; break;
343
}
344
return dt;
345
}
346
347
/* support routines */
348
static int coda_venus_readdir(struct file *coda_file, struct dir_context *ctx)
349
{
350
struct coda_file_info *cfi;
351
struct coda_inode_info *cii;
352
struct file *host_file;
353
struct venus_dirent *vdir;
354
unsigned long vdir_size = offsetof(struct venus_dirent, d_name);
355
unsigned int type;
356
struct qstr name;
357
ino_t ino;
358
int ret;
359
360
cfi = coda_ftoc(coda_file);
361
host_file = cfi->cfi_container;
362
363
cii = ITOC(file_inode(coda_file));
364
365
vdir = kmalloc(sizeof(*vdir), GFP_KERNEL);
366
if (!vdir) return -ENOMEM;
367
368
if (!dir_emit_dots(coda_file, ctx))
369
goto out;
370
371
while (1) {
372
loff_t pos = ctx->pos - 2;
373
374
/* read entries from the directory file */
375
ret = kernel_read(host_file, vdir, sizeof(*vdir), &pos);
376
if (ret < 0) {
377
pr_err("%s: read dir %s failed %d\n",
378
__func__, coda_f2s(&cii->c_fid), ret);
379
break;
380
}
381
if (ret == 0) break; /* end of directory file reached */
382
383
/* catch truncated reads */
384
if (ret < vdir_size || ret < vdir_size + vdir->d_namlen) {
385
pr_err("%s: short read on %s\n",
386
__func__, coda_f2s(&cii->c_fid));
387
ret = -EBADF;
388
break;
389
}
390
/* validate whether the directory file actually makes sense */
391
if (vdir->d_reclen < vdir_size + vdir->d_namlen) {
392
pr_err("%s: invalid dir %s\n",
393
__func__, coda_f2s(&cii->c_fid));
394
ret = -EBADF;
395
break;
396
}
397
398
name.len = vdir->d_namlen;
399
name.name = vdir->d_name;
400
401
/* Make sure we skip '.' and '..', we already got those */
402
if (name.name[0] == '.' && (name.len == 1 ||
403
(name.name[1] == '.' && name.len == 2)))
404
vdir->d_fileno = name.len = 0;
405
406
/* skip null entries */
407
if (vdir->d_fileno && name.len) {
408
ino = vdir->d_fileno;
409
type = CDT2DT(vdir->d_type);
410
if (!dir_emit(ctx, name.name, name.len, ino, type))
411
break;
412
}
413
/* we'll always have progress because d_reclen is unsigned and
414
* we've already established it is non-zero. */
415
ctx->pos += vdir->d_reclen;
416
}
417
out:
418
kfree(vdir);
419
return 0;
420
}
421
422
/* file operations for directories */
423
static int coda_readdir(struct file *coda_file, struct dir_context *ctx)
424
{
425
struct coda_file_info *cfi;
426
struct file *host_file;
427
int ret;
428
429
cfi = coda_ftoc(coda_file);
430
host_file = cfi->cfi_container;
431
432
ret = iterate_dir(host_file, ctx);
433
if (ret != -ENOTDIR)
434
return ret;
435
/* Venus: we must read Venus dirents from a file */
436
return coda_venus_readdir(coda_file, ctx);
437
}
438
439
/* called when a cache lookup succeeds */
440
static int coda_dentry_revalidate(struct inode *dir, const struct qstr *name,
441
struct dentry *de, unsigned int flags)
442
{
443
struct inode *inode;
444
struct coda_inode_info *cii;
445
446
if (flags & LOOKUP_RCU)
447
return -ECHILD;
448
449
inode = d_inode(de);
450
if (!inode || is_root_inode(inode))
451
goto out;
452
if (is_bad_inode(inode))
453
goto bad;
454
455
cii = ITOC(d_inode(de));
456
if (!(cii->c_flags & (C_PURGE | C_FLUSH)))
457
goto out;
458
459
shrink_dcache_parent(de);
460
461
/* propagate for a flush */
462
if (cii->c_flags & C_FLUSH)
463
coda_flag_inode_children(inode, C_FLUSH);
464
465
if (d_count(de) > 1)
466
/* pretend it's valid, but don't change the flags */
467
goto out;
468
469
/* clear the flags. */
470
spin_lock(&cii->c_lock);
471
cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
472
spin_unlock(&cii->c_lock);
473
bad:
474
return 0;
475
out:
476
return 1;
477
}
478
479
/*
480
* This is the callback from dput() when d_count is going to 0.
481
* We use this to unhash dentries with bad inodes.
482
*/
483
static int coda_dentry_delete(const struct dentry * dentry)
484
{
485
struct inode *inode;
486
struct coda_inode_info *cii;
487
488
if (d_really_is_negative(dentry))
489
return 0;
490
491
inode = d_inode(dentry);
492
if (!inode || is_bad_inode(inode))
493
return 1;
494
495
cii = ITOC(inode);
496
if (cii->c_flags & C_PURGE)
497
return 1;
498
499
return 0;
500
}
501
502
503
504
/*
505
* This is called when we want to check if the inode has
506
* changed on the server. Coda makes this easy since the
507
* cache manager Venus issues a downcall to the kernel when this
508
* happens
509
*/
510
int coda_revalidate_inode(struct inode *inode)
511
{
512
struct coda_vattr attr;
513
int error;
514
int old_mode;
515
ino_t old_ino;
516
struct coda_inode_info *cii = ITOC(inode);
517
518
if (!cii->c_flags)
519
return 0;
520
521
if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {
522
error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
523
if (error)
524
return -EIO;
525
526
/* this inode may be lost if:
527
- it's ino changed
528
- type changes must be permitted for repair and
529
missing mount points.
530
*/
531
old_mode = inode->i_mode;
532
old_ino = inode->i_ino;
533
coda_vattr_to_iattr(inode, &attr);
534
535
if ((old_mode & S_IFMT) != (inode->i_mode & S_IFMT)) {
536
pr_warn("inode %ld, fid %s changed type!\n",
537
inode->i_ino, coda_f2s(&(cii->c_fid)));
538
}
539
540
/* the following can happen when a local fid is replaced
541
with a global one, here we lose and declare the inode bad */
542
if (inode->i_ino != old_ino)
543
return -EIO;
544
545
coda_flag_inode_children(inode, C_FLUSH);
546
547
spin_lock(&cii->c_lock);
548
cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
549
spin_unlock(&cii->c_lock);
550
}
551
return 0;
552
}
553
554
const struct dentry_operations coda_dentry_operations = {
555
.d_revalidate = coda_dentry_revalidate,
556
.d_delete = coda_dentry_delete,
557
};
558
559
const struct inode_operations coda_dir_inode_operations = {
560
.create = coda_create,
561
.lookup = coda_lookup,
562
.link = coda_link,
563
.unlink = coda_unlink,
564
.symlink = coda_symlink,
565
.mkdir = coda_mkdir,
566
.rmdir = coda_rmdir,
567
.mknod = CODA_EIO_ERROR,
568
.rename = coda_rename,
569
.permission = coda_permission,
570
.getattr = coda_getattr,
571
.setattr = coda_setattr,
572
};
573
574
WRAP_DIR_ITER(coda_readdir) // FIXME!
575
const struct file_operations coda_dir_operations = {
576
.llseek = generic_file_llseek,
577
.read = generic_read_dir,
578
.iterate_shared = shared_coda_readdir,
579
.open = coda_open,
580
.release = coda_release,
581
.fsync = coda_fsync,
582
};
583
584