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