Blame view
fs/afs/dir.c
25.9 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/* dir.c: AFS filesystem directory handling * * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> |
1da177e4c Linux-2.6.12-rc2 |
15 |
#include <linux/fs.h> |
34286d666 fs: rcu-walk awar... |
16 |
#include <linux/namei.h> |
1da177e4c Linux-2.6.12-rc2 |
17 |
#include <linux/pagemap.h> |
00d3b7a45 [AFS]: Add securi... |
18 |
#include <linux/ctype.h> |
e8edc6e03 Detach sched.h fr... |
19 |
#include <linux/sched.h> |
1da177e4c Linux-2.6.12-rc2 |
20 |
#include "internal.h" |
260a98031 [AFS]: Add "direc... |
21 |
static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, |
00cd8dd3b stop passing name... |
22 |
unsigned int flags); |
1da177e4c Linux-2.6.12-rc2 |
23 |
static int afs_dir_open(struct inode *inode, struct file *file); |
1bbae9f81 [readdir] convert... |
24 |
static int afs_readdir(struct file *file, struct dir_context *ctx); |
0b728e191 stop passing name... |
25 |
static int afs_d_revalidate(struct dentry *dentry, unsigned int flags); |
fe15ce446 fs: change d_dele... |
26 |
static int afs_d_delete(const struct dentry *dentry); |
260a98031 [AFS]: Add "direc... |
27 |
static void afs_d_release(struct dentry *dentry); |
ac7576f4b vfs: make first a... |
28 |
static int afs_lookup_filldir(struct dir_context *ctx, const char *name, int nlen, |
afefdbb28 [PATCH] VFS: Make... |
29 |
loff_t fpos, u64 ino, unsigned dtype); |
4acdaf27e switch ->create()... |
30 |
static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
ebfc3b49a don't pass nameid... |
31 |
bool excl); |
18bb1db3e switch vfs_mkdir(... |
32 |
static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); |
260a98031 [AFS]: Add "direc... |
33 34 35 36 37 38 39 |
static int afs_rmdir(struct inode *dir, struct dentry *dentry); static int afs_unlink(struct inode *dir, struct dentry *dentry); static int afs_link(struct dentry *from, struct inode *dir, struct dentry *dentry); static int afs_symlink(struct inode *dir, struct dentry *dentry, const char *content); static int afs_rename(struct inode *old_dir, struct dentry *old_dentry, |
1cd66c93b fs: make remainin... |
40 41 |
struct inode *new_dir, struct dentry *new_dentry, unsigned int flags); |
1da177e4c Linux-2.6.12-rc2 |
42 |
|
4b6f5d20b [PATCH] Make most... |
43 |
const struct file_operations afs_dir_file_operations = { |
1da177e4c Linux-2.6.12-rc2 |
44 |
.open = afs_dir_open, |
00d3b7a45 [AFS]: Add securi... |
45 |
.release = afs_release, |
29884eff1 afs: switch to ->... |
46 |
.iterate_shared = afs_readdir, |
e8d6c5541 AFS: implement fi... |
47 |
.lock = afs_lock, |
3222a3e55 [PATCH] fix ->lls... |
48 |
.llseek = generic_file_llseek, |
1da177e4c Linux-2.6.12-rc2 |
49 |
}; |
754661f14 [PATCH] mark stru... |
50 |
const struct inode_operations afs_dir_inode_operations = { |
260a98031 [AFS]: Add "direc... |
51 52 53 54 55 56 57 |
.create = afs_create, .lookup = afs_lookup, .link = afs_link, .unlink = afs_unlink, .symlink = afs_symlink, .mkdir = afs_mkdir, .rmdir = afs_rmdir, |
2773bf00a fs: rename "renam... |
58 |
.rename = afs_rename, |
00d3b7a45 [AFS]: Add securi... |
59 |
.permission = afs_permission, |
416351f28 AFS: AFS fixups |
60 |
.getattr = afs_getattr, |
31143d5d5 AFS: implement ba... |
61 |
.setattr = afs_setattr, |
d3e3b7eac afs: Add metadata... |
62 |
.listxattr = afs_listxattr, |
1da177e4c Linux-2.6.12-rc2 |
63 |
}; |
d61dcce29 switch afs |
64 |
const struct dentry_operations afs_fs_dentry_operations = { |
1da177e4c Linux-2.6.12-rc2 |
65 66 |
.d_revalidate = afs_d_revalidate, .d_delete = afs_d_delete, |
260a98031 [AFS]: Add "direc... |
67 |
.d_release = afs_d_release, |
d18610b0c AFS: Use d_automo... |
68 |
.d_automount = afs_d_automount, |
1da177e4c Linux-2.6.12-rc2 |
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
}; #define AFS_DIR_HASHTBL_SIZE 128 #define AFS_DIR_DIRENT_SIZE 32 #define AFS_DIRENT_PER_BLOCK 64 union afs_dirent { struct { uint8_t valid; uint8_t unused[1]; __be16 hash_next; __be32 vnode; __be32 unique; uint8_t name[16]; uint8_t overflow[4]; /* if any char of the name (inc * NUL) reaches here, consume * the next dirent too */ } u; uint8_t extended_name[32]; }; /* AFS directory page header (one at the beginning of every 2048-byte chunk) */ struct afs_dir_pagehdr { __be16 npages; __be16 magic; #define AFS_DIR_MAGIC htons(1234) uint8_t nentries; uint8_t bitmap[8]; uint8_t pad[19]; }; /* directory block layout */ union afs_dir_block { struct afs_dir_pagehdr pagehdr; struct { struct afs_dir_pagehdr pagehdr; uint8_t alloc_ctrs[128]; /* dir hash table */ uint16_t hashtable[AFS_DIR_HASHTBL_SIZE]; } hdr; union afs_dirent dirents[AFS_DIRENT_PER_BLOCK]; }; /* layout on a linux VM page */ struct afs_dir_page { union afs_dir_block blocks[PAGE_SIZE / sizeof(union afs_dir_block)]; }; |
260a98031 [AFS]: Add "direc... |
119 |
struct afs_lookup_cookie { |
1bbae9f81 [readdir] convert... |
120 |
struct dir_context ctx; |
1da177e4c Linux-2.6.12-rc2 |
121 |
struct afs_fid fid; |
1bbae9f81 [readdir] convert... |
122 |
struct qstr name; |
1da177e4c Linux-2.6.12-rc2 |
123 124 |
int found; }; |
1da177e4c Linux-2.6.12-rc2 |
125 126 127 |
/* * check that a directory page is valid */ |
be5b82dbf make ext2_get_pag... |
128 |
static inline bool afs_dir_check_page(struct inode *dir, struct page *page) |
1da177e4c Linux-2.6.12-rc2 |
129 130 131 132 133 134 135 136 137 138 |
{ struct afs_dir_page *dbuf; loff_t latter; int tmp, qty; #if 0 /* check the page count */ qty = desc.size / sizeof(dbuf->blocks[0]); if (qty == 0) goto error; |
08e0e7c82 [AF_RXRPC]: Make ... |
139 |
if (page->index == 0 && qty != ntohs(dbuf->blocks[0].pagehdr.npages)) { |
1da177e4c Linux-2.6.12-rc2 |
140 141 |
printk("kAFS: %s(%lu): wrong number of dir blocks %d!=%hu ", |
530b64127 afs: replace rema... |
142 |
__func__, dir->i_ino, qty, |
08e0e7c82 [AF_RXRPC]: Make ... |
143 |
ntohs(dbuf->blocks[0].pagehdr.npages)); |
1da177e4c Linux-2.6.12-rc2 |
144 145 146 147 148 |
goto error; } #endif /* determine how many magic numbers there should be in this page */ |
54b21a799 [PATCH] fix possi... |
149 |
latter = dir->i_size - page_offset(page); |
1da177e4c Linux-2.6.12-rc2 |
150 151 152 153 154 155 156 157 158 159 160 161 |
if (latter >= PAGE_SIZE) qty = PAGE_SIZE; else qty = latter; qty /= sizeof(union afs_dir_block); /* check them */ dbuf = page_address(page); for (tmp = 0; tmp < qty; tmp++) { if (dbuf->blocks[tmp].pagehdr.magic != AFS_DIR_MAGIC) { printk("kAFS: %s(%lu): bad magic %d/%d is %04hx ", |
530b64127 afs: replace rema... |
162 |
__func__, dir->i_ino, tmp, qty, |
1da177e4c Linux-2.6.12-rc2 |
163 164 165 166 167 168 |
ntohs(dbuf->blocks[tmp].pagehdr.magic)); goto error; } } SetPageChecked(page); |
be5b82dbf make ext2_get_pag... |
169 |
return true; |
1da177e4c Linux-2.6.12-rc2 |
170 |
|
ec26815ad [AFS]: Clean up t... |
171 |
error: |
1da177e4c Linux-2.6.12-rc2 |
172 |
SetPageError(page); |
be5b82dbf make ext2_get_pag... |
173 |
return false; |
ec26815ad [AFS]: Clean up t... |
174 |
} |
1da177e4c Linux-2.6.12-rc2 |
175 |
|
1da177e4c Linux-2.6.12-rc2 |
176 177 178 179 180 181 |
/* * discard a page cached in the pagecache */ static inline void afs_dir_put_page(struct page *page) { kunmap(page); |
09cbfeaf1 mm, fs: get rid o... |
182 |
put_page(page); |
ec26815ad [AFS]: Clean up t... |
183 |
} |
1da177e4c Linux-2.6.12-rc2 |
184 |
|
1da177e4c Linux-2.6.12-rc2 |
185 186 187 |
/* * get a page into the pagecache */ |
00d3b7a45 [AFS]: Add securi... |
188 189 |
static struct page *afs_dir_get_page(struct inode *dir, unsigned long index, struct key *key) |
1da177e4c Linux-2.6.12-rc2 |
190 191 |
{ struct page *page; |
1da177e4c Linux-2.6.12-rc2 |
192 |
_enter("{%lu},%lu", dir->i_ino, index); |
f6d335c08 AFS: Don't put st... |
193 |
page = read_cache_page(dir->i_mapping, index, afs_page_filler, key); |
1da177e4c Linux-2.6.12-rc2 |
194 |
if (!IS_ERR(page)) { |
1da177e4c Linux-2.6.12-rc2 |
195 |
kmap(page); |
be5b82dbf make ext2_get_pag... |
196 197 198 199 |
if (unlikely(!PageChecked(page))) { if (PageError(page) || !afs_dir_check_page(dir, page)) goto fail; } |
1da177e4c Linux-2.6.12-rc2 |
200 201 |
} return page; |
ec26815ad [AFS]: Clean up t... |
202 |
fail: |
1da177e4c Linux-2.6.12-rc2 |
203 |
afs_dir_put_page(page); |
08e0e7c82 [AF_RXRPC]: Make ... |
204 |
_leave(" = -EIO"); |
1da177e4c Linux-2.6.12-rc2 |
205 |
return ERR_PTR(-EIO); |
ec26815ad [AFS]: Clean up t... |
206 |
} |
1da177e4c Linux-2.6.12-rc2 |
207 |
|
1da177e4c Linux-2.6.12-rc2 |
208 209 210 211 212 213 |
/* * open an AFS directory file */ static int afs_dir_open(struct inode *inode, struct file *file) { _enter("{%lu}", inode->i_ino); |
2ecd05ae6 [PATCH] fs/*: use... |
214 215 |
BUILD_BUG_ON(sizeof(union afs_dir_block) != 2048); BUILD_BUG_ON(sizeof(union afs_dirent) != 32); |
1da177e4c Linux-2.6.12-rc2 |
216 |
|
08e0e7c82 [AF_RXRPC]: Make ... |
217 |
if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(inode)->flags)) |
1da177e4c Linux-2.6.12-rc2 |
218 |
return -ENOENT; |
00d3b7a45 [AFS]: Add securi... |
219 |
return afs_open(inode, file); |
ec26815ad [AFS]: Clean up t... |
220 |
} |
1da177e4c Linux-2.6.12-rc2 |
221 |
|
1da177e4c Linux-2.6.12-rc2 |
222 223 224 |
/* * deal with one block in an AFS directory */ |
1bbae9f81 [readdir] convert... |
225 |
static int afs_dir_iterate_block(struct dir_context *ctx, |
1da177e4c Linux-2.6.12-rc2 |
226 |
union afs_dir_block *block, |
1bbae9f81 [readdir] convert... |
227 |
unsigned blkoff) |
1da177e4c Linux-2.6.12-rc2 |
228 229 230 231 |
{ union afs_dirent *dire; unsigned offset, next, curr; size_t nlen; |
1bbae9f81 [readdir] convert... |
232 |
int tmp; |
1da177e4c Linux-2.6.12-rc2 |
233 |
|
1bbae9f81 [readdir] convert... |
234 |
_enter("%u,%x,%p,,",(unsigned)ctx->pos,blkoff,block); |
1da177e4c Linux-2.6.12-rc2 |
235 |
|
1bbae9f81 [readdir] convert... |
236 |
curr = (ctx->pos - blkoff) / sizeof(union afs_dirent); |
1da177e4c Linux-2.6.12-rc2 |
237 238 239 240 241 242 243 244 245 246 247 |
/* walk through the block, an entry at a time */ for (offset = AFS_DIRENT_PER_BLOCK - block->pagehdr.nentries; offset < AFS_DIRENT_PER_BLOCK; offset = next ) { next = offset + 1; /* skip entries marked unused in the bitmap */ if (!(block->pagehdr.bitmap[offset / 8] & (1 << (offset % 8)))) { |
5b5e0928f lib/vsprintf.c: r... |
248 |
_debug("ENT[%zu.%u]: unused", |
1da177e4c Linux-2.6.12-rc2 |
249 250 |
blkoff / sizeof(union afs_dir_block), offset); if (offset >= curr) |
1bbae9f81 [readdir] convert... |
251 |
ctx->pos = blkoff + |
1da177e4c Linux-2.6.12-rc2 |
252 253 254 255 256 257 258 259 260 |
next * sizeof(union afs_dirent); continue; } /* got a valid entry */ dire = &block->dirents[offset]; nlen = strnlen(dire->u.name, sizeof(*block) - offset * sizeof(union afs_dirent)); |
5b5e0928f lib/vsprintf.c: r... |
261 |
_debug("ENT[%zu.%u]: %s %zu \"%s\"", |
1da177e4c Linux-2.6.12-rc2 |
262 263 264 265 266 267 268 |
blkoff / sizeof(union afs_dir_block), offset, (offset < curr ? "skip" : "fill"), nlen, dire->u.name); /* work out where the next possible entry is */ for (tmp = nlen; tmp > 15; tmp -= sizeof(union afs_dirent)) { if (next >= AFS_DIRENT_PER_BLOCK) { |
5b5e0928f lib/vsprintf.c: r... |
269 |
_debug("ENT[%zu.%u]:" |
1da177e4c Linux-2.6.12-rc2 |
270 |
" %u travelled beyond end dir block" |
5b5e0928f lib/vsprintf.c: r... |
271 |
" (len %u/%zu)", |
1da177e4c Linux-2.6.12-rc2 |
272 273 274 275 276 277 |
blkoff / sizeof(union afs_dir_block), offset, next, tmp, nlen); return -EIO; } if (!(block->pagehdr.bitmap[next / 8] & (1 << (next % 8)))) { |
5b5e0928f lib/vsprintf.c: r... |
278 279 |
_debug("ENT[%zu.%u]:" " %u unmarked extension (len %u/%zu)", |
1da177e4c Linux-2.6.12-rc2 |
280 281 282 283 |
blkoff / sizeof(union afs_dir_block), offset, next, tmp, nlen); return -EIO; } |
5b5e0928f lib/vsprintf.c: r... |
284 |
_debug("ENT[%zu.%u]: ext %u/%zu", |
1da177e4c Linux-2.6.12-rc2 |
285 286 287 288 289 290 291 292 293 294 |
blkoff / sizeof(union afs_dir_block), next, tmp, nlen); next++; } /* skip if starts before the current position */ if (offset < curr) continue; /* found the next entry */ |
1bbae9f81 [readdir] convert... |
295 |
if (!dir_emit(ctx, dire->u.name, nlen, |
1da177e4c Linux-2.6.12-rc2 |
296 |
ntohl(dire->u.vnode), |
1bbae9f81 [readdir] convert... |
297 298 |
ctx->actor == afs_lookup_filldir ? ntohl(dire->u.unique) : DT_UNKNOWN)) { |
1da177e4c Linux-2.6.12-rc2 |
299 300 301 |
_leave(" = 0 [full]"); return 0; } |
1bbae9f81 [readdir] convert... |
302 |
ctx->pos = blkoff + next * sizeof(union afs_dirent); |
1da177e4c Linux-2.6.12-rc2 |
303 304 305 306 |
} _leave(" = 1 [more]"); return 1; |
ec26815ad [AFS]: Clean up t... |
307 |
} |
1da177e4c Linux-2.6.12-rc2 |
308 |
|
1da177e4c Linux-2.6.12-rc2 |
309 |
/* |
08e0e7c82 [AF_RXRPC]: Make ... |
310 |
* iterate through the data blob that lists the contents of an AFS directory |
1da177e4c Linux-2.6.12-rc2 |
311 |
*/ |
1bbae9f81 [readdir] convert... |
312 313 |
static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx, struct key *key) |
1da177e4c Linux-2.6.12-rc2 |
314 |
{ |
08e0e7c82 [AF_RXRPC]: Make ... |
315 |
union afs_dir_block *dblock; |
1da177e4c Linux-2.6.12-rc2 |
316 317 318 319 |
struct afs_dir_page *dbuf; struct page *page; unsigned blkoff, limit; int ret; |
1bbae9f81 [readdir] convert... |
320 |
_enter("{%lu},%u,,", dir->i_ino, (unsigned)ctx->pos); |
1da177e4c Linux-2.6.12-rc2 |
321 |
|
08e0e7c82 [AF_RXRPC]: Make ... |
322 |
if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dir)->flags)) { |
1da177e4c Linux-2.6.12-rc2 |
323 324 325 326 327 |
_leave(" = -ESTALE"); return -ESTALE; } /* round the file position up to the next entry boundary */ |
1bbae9f81 [readdir] convert... |
328 329 |
ctx->pos += sizeof(union afs_dirent) - 1; ctx->pos &= ~(sizeof(union afs_dirent) - 1); |
1da177e4c Linux-2.6.12-rc2 |
330 331 332 |
/* walk through the blocks in sequence */ ret = 0; |
1bbae9f81 [readdir] convert... |
333 334 |
while (ctx->pos < dir->i_size) { blkoff = ctx->pos & ~(sizeof(union afs_dir_block) - 1); |
1da177e4c Linux-2.6.12-rc2 |
335 336 |
/* fetch the appropriate page from the directory */ |
00d3b7a45 [AFS]: Add securi... |
337 |
page = afs_dir_get_page(dir, blkoff / PAGE_SIZE, key); |
1da177e4c Linux-2.6.12-rc2 |
338 339 340 341 342 343 344 345 346 347 348 349 350 |
if (IS_ERR(page)) { ret = PTR_ERR(page); break; } limit = blkoff & ~(PAGE_SIZE - 1); dbuf = page_address(page); /* deal with the individual blocks stashed on this page */ do { dblock = &dbuf->blocks[(blkoff % PAGE_SIZE) / sizeof(union afs_dir_block)]; |
1bbae9f81 [readdir] convert... |
351 |
ret = afs_dir_iterate_block(ctx, dblock, blkoff); |
1da177e4c Linux-2.6.12-rc2 |
352 353 354 355 356 357 |
if (ret != 1) { afs_dir_put_page(page); goto out; } blkoff += sizeof(union afs_dir_block); |
1bbae9f81 [readdir] convert... |
358 |
} while (ctx->pos < dir->i_size && blkoff < limit); |
1da177e4c Linux-2.6.12-rc2 |
359 360 361 362 |
afs_dir_put_page(page); ret = 0; } |
ec26815ad [AFS]: Clean up t... |
363 |
out: |
1da177e4c Linux-2.6.12-rc2 |
364 365 |
_leave(" = %d", ret); return ret; |
ec26815ad [AFS]: Clean up t... |
366 |
} |
1da177e4c Linux-2.6.12-rc2 |
367 |
|
1da177e4c Linux-2.6.12-rc2 |
368 369 370 |
/* * read an AFS directory */ |
1bbae9f81 [readdir] convert... |
371 |
static int afs_readdir(struct file *file, struct dir_context *ctx) |
1da177e4c Linux-2.6.12-rc2 |
372 |
{ |
1bbae9f81 [readdir] convert... |
373 374 |
return afs_dir_iterate(file_inode(file), ctx, file->private_data); |
ec26815ad [AFS]: Clean up t... |
375 |
} |
1da177e4c Linux-2.6.12-rc2 |
376 |
|
1da177e4c Linux-2.6.12-rc2 |
377 378 379 380 381 |
/* * search the directory for a name * - if afs_dir_iterate_block() spots this function, it'll pass the FID * uniquifier through dtype */ |
ac7576f4b vfs: make first a... |
382 383 |
static int afs_lookup_filldir(struct dir_context *ctx, const char *name, int nlen, loff_t fpos, u64 ino, unsigned dtype) |
1da177e4c Linux-2.6.12-rc2 |
384 |
{ |
ac7576f4b vfs: make first a... |
385 386 |
struct afs_lookup_cookie *cookie = container_of(ctx, struct afs_lookup_cookie, ctx); |
1da177e4c Linux-2.6.12-rc2 |
387 |
|
1bbae9f81 [readdir] convert... |
388 389 |
_enter("{%s,%u},%s,%u,,%llu,%u", cookie->name.name, cookie->name.len, name, nlen, |
ba3e0e1ac [AFS]: Fix u64 pr... |
390 |
(unsigned long long) ino, dtype); |
1da177e4c Linux-2.6.12-rc2 |
391 |
|
08e0e7c82 [AF_RXRPC]: Make ... |
392 393 394 |
/* insanity checks first */ BUILD_BUG_ON(sizeof(union afs_dir_block) != 2048); BUILD_BUG_ON(sizeof(union afs_dirent) != 32); |
1bbae9f81 [readdir] convert... |
395 396 |
if (cookie->name.len != nlen || memcmp(cookie->name.name, name, nlen) != 0) { |
1da177e4c Linux-2.6.12-rc2 |
397 398 399 400 401 402 403 404 405 406 |
_leave(" = 0 [no]"); return 0; } cookie->fid.vnode = ino; cookie->fid.unique = dtype; cookie->found = 1; _leave(" = -1 [found]"); return -1; |
ec26815ad [AFS]: Clean up t... |
407 |
} |
1da177e4c Linux-2.6.12-rc2 |
408 |
|
1da177e4c Linux-2.6.12-rc2 |
409 |
/* |
08e0e7c82 [AF_RXRPC]: Make ... |
410 |
* do a lookup in a directory |
260a98031 [AFS]: Add "direc... |
411 |
* - just returns the FID the dentry name maps to if found |
1da177e4c Linux-2.6.12-rc2 |
412 |
*/ |
08e0e7c82 [AF_RXRPC]: Make ... |
413 |
static int afs_do_lookup(struct inode *dir, struct dentry *dentry, |
00d3b7a45 [AFS]: Add securi... |
414 |
struct afs_fid *fid, struct key *key) |
1da177e4c Linux-2.6.12-rc2 |
415 |
{ |
1bbae9f81 [readdir] convert... |
416 417 418 419 420 421 |
struct afs_super_info *as = dir->i_sb->s_fs_info; struct afs_lookup_cookie cookie = { .ctx.actor = afs_lookup_filldir, .name = dentry->d_name, .fid.vid = as->volume->vid }; |
1da177e4c Linux-2.6.12-rc2 |
422 |
int ret; |
a455589f1 assorted conversi... |
423 |
_enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry); |
1da177e4c Linux-2.6.12-rc2 |
424 |
|
1da177e4c Linux-2.6.12-rc2 |
425 |
/* search the directory */ |
1bbae9f81 [readdir] convert... |
426 |
ret = afs_dir_iterate(dir, &cookie.ctx, key); |
1da177e4c Linux-2.6.12-rc2 |
427 |
if (ret < 0) { |
08e0e7c82 [AF_RXRPC]: Make ... |
428 429 |
_leave(" = %d [iter]", ret); return ret; |
1da177e4c Linux-2.6.12-rc2 |
430 431 432 433 |
} ret = -ENOENT; if (!cookie.found) { |
08e0e7c82 [AF_RXRPC]: Make ... |
434 435 |
_leave(" = -ENOENT [not found]"); return -ENOENT; |
1da177e4c Linux-2.6.12-rc2 |
436 |
} |
08e0e7c82 [AF_RXRPC]: Make ... |
437 438 439 440 441 442 |
*fid = cookie.fid; _leave(" = 0 { vn=%u u=%u }", fid->vnode, fid->unique); return 0; } /* |
bec5eb614 AFS: Implement an... |
443 444 445 446 447 448 449 450 451 452 |
* Try to auto mount the mountpoint with pseudo directory, if the autocell * operation is setted. */ static struct inode *afs_try_auto_mntpt( int ret, struct dentry *dentry, struct inode *dir, struct key *key, struct afs_fid *fid) { const char *devname = dentry->d_name.name; struct afs_vnode *vnode = AFS_FS_I(dir); struct inode *inode; |
a455589f1 assorted conversi... |
453 454 |
_enter("%d, %p{%pd}, {%x:%u}, %p", ret, dentry, dentry, vnode->fid.vid, vnode->fid.vnode, key); |
bec5eb614 AFS: Implement an... |
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 |
if (ret != -ENOENT || !test_bit(AFS_VNODE_AUTOCELL, &vnode->flags)) goto out; inode = afs_iget_autocell(dir, devname, strlen(devname), key); if (IS_ERR(inode)) { ret = PTR_ERR(inode); goto out; } *fid = AFS_FS_I(inode)->fid; _leave("= %p", inode); return inode; out: _leave("= %d", ret); return ERR_PTR(ret); } /* |
08e0e7c82 [AF_RXRPC]: Make ... |
476 477 |
* look up an entry in a directory */ |
260a98031 [AFS]: Add "direc... |
478 |
static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, |
00cd8dd3b stop passing name... |
479 |
unsigned int flags) |
08e0e7c82 [AF_RXRPC]: Make ... |
480 481 482 483 |
{ struct afs_vnode *vnode; struct afs_fid fid; struct inode *inode; |
00d3b7a45 [AFS]: Add securi... |
484 |
struct key *key; |
08e0e7c82 [AF_RXRPC]: Make ... |
485 |
int ret; |
260a98031 [AFS]: Add "direc... |
486 |
vnode = AFS_FS_I(dir); |
a455589f1 assorted conversi... |
487 488 |
_enter("{%x:%u},%p{%pd},", vnode->fid.vid, vnode->fid.vnode, dentry, dentry); |
260a98031 [AFS]: Add "direc... |
489 |
|
2b0143b5c VFS: normal files... |
490 |
ASSERTCMP(d_inode(dentry), ==, NULL); |
08e0e7c82 [AF_RXRPC]: Make ... |
491 |
|
45222b9e0 AFS: implement st... |
492 |
if (dentry->d_name.len >= AFSNAMEMAX) { |
08e0e7c82 [AF_RXRPC]: Make ... |
493 494 495 |
_leave(" = -ENAMETOOLONG"); return ERR_PTR(-ENAMETOOLONG); } |
08e0e7c82 [AF_RXRPC]: Make ... |
496 497 498 499 |
if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { _leave(" = -ESTALE"); return ERR_PTR(-ESTALE); } |
00d3b7a45 [AFS]: Add securi... |
500 501 502 |
key = afs_request_key(vnode->volume->cell); if (IS_ERR(key)) { _leave(" = %ld [key]", PTR_ERR(key)); |
e231c2ee6 Convert ERR_PTR(P... |
503 |
return ERR_CAST(key); |
00d3b7a45 [AFS]: Add securi... |
504 |
} |
260a98031 [AFS]: Add "direc... |
505 506 507 508 509 510 |
ret = afs_validate(vnode, key); if (ret < 0) { key_put(key); _leave(" = %d [val]", ret); return ERR_PTR(ret); } |
00d3b7a45 [AFS]: Add securi... |
511 |
ret = afs_do_lookup(dir, dentry, &fid, key); |
1da177e4c Linux-2.6.12-rc2 |
512 |
if (ret < 0) { |
bec5eb614 AFS: Implement an... |
513 514 515 516 517 518 519 |
inode = afs_try_auto_mntpt(ret, dentry, dir, key, &fid); if (!IS_ERR(inode)) { key_put(key); goto success; } ret = PTR_ERR(inode); |
00d3b7a45 [AFS]: Add securi... |
520 |
key_put(key); |
260a98031 [AFS]: Add "direc... |
521 522 523 524 525 |
if (ret == -ENOENT) { d_add(dentry, NULL); _leave(" = NULL [negative]"); return NULL; } |
08e0e7c82 [AF_RXRPC]: Make ... |
526 |
_leave(" = %d [do]", ret); |
1da177e4c Linux-2.6.12-rc2 |
527 528 |
return ERR_PTR(ret); } |
260a98031 [AFS]: Add "direc... |
529 |
dentry->d_fsdata = (void *)(unsigned long) vnode->status.data_version; |
1da177e4c Linux-2.6.12-rc2 |
530 |
|
08e0e7c82 [AF_RXRPC]: Make ... |
531 |
/* instantiate the dentry */ |
260a98031 [AFS]: Add "direc... |
532 |
inode = afs_iget(dir->i_sb, key, &fid, NULL, NULL); |
00d3b7a45 [AFS]: Add securi... |
533 |
key_put(key); |
08e0e7c82 [AF_RXRPC]: Make ... |
534 535 |
if (IS_ERR(inode)) { _leave(" = %ld", PTR_ERR(inode)); |
e231c2ee6 Convert ERR_PTR(P... |
536 |
return ERR_CAST(inode); |
08e0e7c82 [AF_RXRPC]: Make ... |
537 |
} |
bec5eb614 AFS: Implement an... |
538 |
success: |
1da177e4c Linux-2.6.12-rc2 |
539 |
d_add(dentry, inode); |
d6e43f751 AFS: Use i_genera... |
540 |
_leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%u }", |
08e0e7c82 [AF_RXRPC]: Make ... |
541 542 |
fid.vnode, fid.unique, |
2b0143b5c VFS: normal files... |
543 544 |
d_inode(dentry)->i_ino, d_inode(dentry)->i_generation); |
1da177e4c Linux-2.6.12-rc2 |
545 546 |
return NULL; |
ec26815ad [AFS]: Clean up t... |
547 |
} |
1da177e4c Linux-2.6.12-rc2 |
548 |
|
1da177e4c Linux-2.6.12-rc2 |
549 550 551 552 |
/* * check that a dentry lookup hit has found a valid entry * - NOTE! the hit can be a negative hit too, so we can't assume we have an * inode |
1da177e4c Linux-2.6.12-rc2 |
553 |
*/ |
0b728e191 stop passing name... |
554 |
static int afs_d_revalidate(struct dentry *dentry, unsigned int flags) |
1da177e4c Linux-2.6.12-rc2 |
555 |
{ |
260a98031 [AFS]: Add "direc... |
556 |
struct afs_vnode *vnode, *dir; |
dd0d9a46f AFS: Fix compilat... |
557 |
struct afs_fid uninitialized_var(fid); |
1da177e4c Linux-2.6.12-rc2 |
558 |
struct dentry *parent; |
00d3b7a45 [AFS]: Add securi... |
559 |
struct key *key; |
260a98031 [AFS]: Add "direc... |
560 |
void *dir_version; |
1da177e4c Linux-2.6.12-rc2 |
561 |
int ret; |
0b728e191 stop passing name... |
562 |
if (flags & LOOKUP_RCU) |
34286d666 fs: rcu-walk awar... |
563 |
return -ECHILD; |
2b0143b5c VFS: normal files... |
564 |
vnode = AFS_FS_I(d_inode(dentry)); |
08e0e7c82 [AF_RXRPC]: Make ... |
565 |
|
2b0143b5c VFS: normal files... |
566 |
if (d_really_is_positive(dentry)) |
a455589f1 assorted conversi... |
567 568 |
_enter("{v={%x:%u} n=%pd fl=%lx},", vnode->fid.vid, vnode->fid.vnode, dentry, |
260a98031 [AFS]: Add "direc... |
569 570 |
vnode->flags); else |
a455589f1 assorted conversi... |
571 |
_enter("{neg n=%pd}", dentry); |
1da177e4c Linux-2.6.12-rc2 |
572 |
|
260a98031 [AFS]: Add "direc... |
573 |
key = afs_request_key(AFS_FS_S(dentry->d_sb)->volume->cell); |
00d3b7a45 [AFS]: Add securi... |
574 575 |
if (IS_ERR(key)) key = NULL; |
1da177e4c Linux-2.6.12-rc2 |
576 |
/* lock down the parent dentry so we can peer at it */ |
08e0e7c82 [AF_RXRPC]: Make ... |
577 |
parent = dget_parent(dentry); |
2b0143b5c VFS: normal files... |
578 |
dir = AFS_FS_I(d_inode(parent)); |
1da177e4c Linux-2.6.12-rc2 |
579 |
|
260a98031 [AFS]: Add "direc... |
580 581 582 583 584 |
/* validate the parent directory */ if (test_bit(AFS_VNODE_MODIFIED, &dir->flags)) afs_validate(dir, key); if (test_bit(AFS_VNODE_DELETED, &dir->flags)) { |
a455589f1 assorted conversi... |
585 |
_debug("%pd: parent dir deleted", dentry); |
1da177e4c Linux-2.6.12-rc2 |
586 587 |
goto out_bad; } |
260a98031 [AFS]: Add "direc... |
588 589 590 |
dir_version = (void *) (unsigned long) dir->status.data_version; if (dentry->d_fsdata == dir_version) goto out_valid; /* the dir contents are unchanged */ |
1da177e4c Linux-2.6.12-rc2 |
591 |
|
260a98031 [AFS]: Add "direc... |
592 593 594 595 596 597 598 |
_debug("dir modified"); /* search the directory for this vnode */ ret = afs_do_lookup(&dir->vfs_inode, dentry, &fid, key); switch (ret) { case 0: /* the filename maps to something */ |
2b0143b5c VFS: normal files... |
599 |
if (d_really_is_negative(dentry)) |
260a98031 [AFS]: Add "direc... |
600 |
goto out_bad; |
2b0143b5c VFS: normal files... |
601 |
if (is_bad_inode(d_inode(dentry))) { |
a455589f1 assorted conversi... |
602 603 604 |
printk("kAFS: afs_d_revalidate: %pd2 has bad inode ", dentry); |
1da177e4c Linux-2.6.12-rc2 |
605 606 |
goto out_bad; } |
1da177e4c Linux-2.6.12-rc2 |
607 608 |
/* if the vnode ID has changed, then the dirent points to a * different file */ |
08e0e7c82 [AF_RXRPC]: Make ... |
609 |
if (fid.vnode != vnode->fid.vnode) { |
a455589f1 assorted conversi... |
610 611 |
_debug("%pd: dirent changed [%u != %u]", dentry, fid.vnode, |
08e0e7c82 [AF_RXRPC]: Make ... |
612 |
vnode->fid.vnode); |
1da177e4c Linux-2.6.12-rc2 |
613 614 615 616 |
goto not_found; } /* if the vnode ID uniqifier has changed, then the file has |
260a98031 [AFS]: Add "direc... |
617 618 |
* been deleted and replaced, and the original vnode ID has * been reused */ |
08e0e7c82 [AF_RXRPC]: Make ... |
619 |
if (fid.unique != vnode->fid.unique) { |
a455589f1 assorted conversi... |
620 621 |
_debug("%pd: file deleted (uq %u -> %u I:%u)", dentry, fid.unique, |
7a224228e vfs: Add 64 bit i... |
622 |
vnode->fid.unique, |
2b0143b5c VFS: normal files... |
623 |
d_inode(dentry)->i_generation); |
08e0e7c82 [AF_RXRPC]: Make ... |
624 625 626 |
spin_lock(&vnode->lock); set_bit(AFS_VNODE_DELETED, &vnode->flags); spin_unlock(&vnode->lock); |
260a98031 [AFS]: Add "direc... |
627 |
goto not_found; |
1da177e4c Linux-2.6.12-rc2 |
628 |
} |
260a98031 [AFS]: Add "direc... |
629 |
goto out_valid; |
08e0e7c82 [AF_RXRPC]: Make ... |
630 |
|
260a98031 [AFS]: Add "direc... |
631 632 |
case -ENOENT: /* the filename is unknown */ |
a455589f1 assorted conversi... |
633 |
_debug("%pd: dirent not found", dentry); |
2b0143b5c VFS: normal files... |
634 |
if (d_really_is_positive(dentry)) |
260a98031 [AFS]: Add "direc... |
635 636 |
goto not_found; goto out_valid; |
1da177e4c Linux-2.6.12-rc2 |
637 |
|
260a98031 [AFS]: Add "direc... |
638 |
default: |
a455589f1 assorted conversi... |
639 640 |
_debug("failed to iterate dir %pd: %d", parent, ret); |
08e0e7c82 [AF_RXRPC]: Make ... |
641 642 |
goto out_bad; } |
ec26815ad [AFS]: Clean up t... |
643 |
out_valid: |
260a98031 [AFS]: Add "direc... |
644 |
dentry->d_fsdata = dir_version; |
1da177e4c Linux-2.6.12-rc2 |
645 |
dput(parent); |
00d3b7a45 [AFS]: Add securi... |
646 |
key_put(key); |
1da177e4c Linux-2.6.12-rc2 |
647 648 649 650 |
_leave(" = 1 [valid]"); return 1; /* the dirent, if it exists, now points to a different vnode */ |
ec26815ad [AFS]: Clean up t... |
651 |
not_found: |
1da177e4c Linux-2.6.12-rc2 |
652 653 654 |
spin_lock(&dentry->d_lock); dentry->d_flags |= DCACHE_NFSFS_RENAMED; spin_unlock(&dentry->d_lock); |
ec26815ad [AFS]: Clean up t... |
655 |
out_bad: |
a455589f1 assorted conversi... |
656 |
_debug("dropping dentry %pd2", dentry); |
1da177e4c Linux-2.6.12-rc2 |
657 |
dput(parent); |
00d3b7a45 [AFS]: Add securi... |
658 |
key_put(key); |
1da177e4c Linux-2.6.12-rc2 |
659 660 661 |
_leave(" = 0 [bad]"); return 0; |
ec26815ad [AFS]: Clean up t... |
662 |
} |
1da177e4c Linux-2.6.12-rc2 |
663 |
|
1da177e4c Linux-2.6.12-rc2 |
664 665 666 667 668 669 |
/* * allow the VFS to enquire as to whether a dentry should be unhashed (mustn't * sleep) * - called from dput() when d_count is going to 0. * - return 1 to request dentry be unhashed, 0 otherwise */ |
fe15ce446 fs: change d_dele... |
670 |
static int afs_d_delete(const struct dentry *dentry) |
1da177e4c Linux-2.6.12-rc2 |
671 |
{ |
a455589f1 assorted conversi... |
672 |
_enter("%pd", dentry); |
1da177e4c Linux-2.6.12-rc2 |
673 674 675 |
if (dentry->d_flags & DCACHE_NFSFS_RENAMED) goto zap; |
2b0143b5c VFS: normal files... |
676 677 678 |
if (d_really_is_positive(dentry) && (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(d_inode(dentry))->flags) || test_bit(AFS_VNODE_PSEUDODIR, &AFS_FS_I(d_inode(dentry))->flags))) |
bec5eb614 AFS: Implement an... |
679 |
goto zap; |
1da177e4c Linux-2.6.12-rc2 |
680 681 682 |
_leave(" = 0 [keep]"); return 0; |
ec26815ad [AFS]: Clean up t... |
683 |
zap: |
1da177e4c Linux-2.6.12-rc2 |
684 685 |
_leave(" = 1 [zap]"); return 1; |
ec26815ad [AFS]: Clean up t... |
686 |
} |
260a98031 [AFS]: Add "direc... |
687 688 689 690 691 692 |
/* * handle dentry release */ static void afs_d_release(struct dentry *dentry) { |
a455589f1 assorted conversi... |
693 |
_enter("%pd", dentry); |
260a98031 [AFS]: Add "direc... |
694 695 696 697 698 |
} /* * create a directory on an AFS filesystem */ |
18bb1db3e switch vfs_mkdir(... |
699 |
static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) |
260a98031 [AFS]: Add "direc... |
700 701 702 703 704 705 706 707 708 709 710 |
{ struct afs_file_status status; struct afs_callback cb; struct afs_server *server; struct afs_vnode *dvnode, *vnode; struct afs_fid fid; struct inode *inode; struct key *key; int ret; dvnode = AFS_FS_I(dir); |
a455589f1 assorted conversi... |
711 712 |
_enter("{%x:%u},{%pd},%ho", dvnode->fid.vid, dvnode->fid.vnode, dentry, mode); |
260a98031 [AFS]: Add "direc... |
713 |
|
260a98031 [AFS]: Add "direc... |
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 |
key = afs_request_key(dvnode->volume->cell); if (IS_ERR(key)) { ret = PTR_ERR(key); goto error; } mode |= S_IFDIR; ret = afs_vnode_create(dvnode, key, dentry->d_name.name, mode, &fid, &status, &cb, &server); if (ret < 0) goto mkdir_error; inode = afs_iget(dir->i_sb, key, &fid, &status, &cb); if (IS_ERR(inode)) { /* ENOMEM at a really inconvenient time - just abandon the new * directory on the server */ ret = PTR_ERR(inode); goto iget_error; } /* apply the status report we've got for the new vnode */ vnode = AFS_FS_I(inode); spin_lock(&vnode->lock); vnode->update_cnt++; spin_unlock(&vnode->lock); afs_vnode_finalise_status_update(vnode, server); afs_put_server(server); d_instantiate(dentry, inode); if (d_unhashed(dentry)) { _debug("not hashed"); d_rehash(dentry); } key_put(key); _leave(" = 0"); return 0; iget_error: afs_put_server(server); mkdir_error: key_put(key); error: d_drop(dentry); _leave(" = %d", ret); return ret; } /* * remove a directory from an AFS filesystem */ static int afs_rmdir(struct inode *dir, struct dentry *dentry) { struct afs_vnode *dvnode, *vnode; struct key *key; int ret; dvnode = AFS_FS_I(dir); |
a455589f1 assorted conversi... |
771 772 |
_enter("{%x:%u},{%pd}", dvnode->fid.vid, dvnode->fid.vnode, dentry); |
260a98031 [AFS]: Add "direc... |
773 |
|
260a98031 [AFS]: Add "direc... |
774 775 776 777 778 779 780 781 782 |
key = afs_request_key(dvnode->volume->cell); if (IS_ERR(key)) { ret = PTR_ERR(key); goto error; } ret = afs_vnode_remove(dvnode, key, dentry->d_name.name, true); if (ret < 0) goto rmdir_error; |
2b0143b5c VFS: normal files... |
783 784 |
if (d_really_is_positive(dentry)) { vnode = AFS_FS_I(d_inode(dentry)); |
260a98031 [AFS]: Add "direc... |
785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 |
clear_nlink(&vnode->vfs_inode); set_bit(AFS_VNODE_DELETED, &vnode->flags); afs_discard_callback_on_delete(vnode); } key_put(key); _leave(" = 0"); return 0; rmdir_error: key_put(key); error: _leave(" = %d", ret); return ret; } /* * remove a file from an AFS filesystem */ static int afs_unlink(struct inode *dir, struct dentry *dentry) { struct afs_vnode *dvnode, *vnode; struct key *key; int ret; dvnode = AFS_FS_I(dir); |
a455589f1 assorted conversi... |
811 812 |
_enter("{%x:%u},{%pd}", dvnode->fid.vid, dvnode->fid.vnode, dentry); |
260a98031 [AFS]: Add "direc... |
813 814 |
ret = -ENAMETOOLONG; |
45222b9e0 AFS: implement st... |
815 |
if (dentry->d_name.len >= AFSNAMEMAX) |
260a98031 [AFS]: Add "direc... |
816 817 818 819 820 821 822 |
goto error; key = afs_request_key(dvnode->volume->cell); if (IS_ERR(key)) { ret = PTR_ERR(key); goto error; } |
2b0143b5c VFS: normal files... |
823 824 |
if (d_really_is_positive(dentry)) { vnode = AFS_FS_I(d_inode(dentry)); |
260a98031 [AFS]: Add "direc... |
825 826 827 828 829 830 831 832 833 834 |
/* make sure we have a callback promise on the victim */ ret = afs_validate(vnode, key); if (ret < 0) goto error; } ret = afs_vnode_remove(dvnode, key, dentry->d_name.name, false); if (ret < 0) goto remove_error; |
2b0143b5c VFS: normal files... |
835 |
if (d_really_is_positive(dentry)) { |
260a98031 [AFS]: Add "direc... |
836 837 838 839 840 841 842 843 844 |
/* if the file wasn't deleted due to excess hard links, the * fileserver will break the callback promise on the file - if * it had one - before it returns to us, and if it was deleted, * it won't * * however, if we didn't have a callback promise outstanding, * or it was outstanding on a different server, then it won't * break it either... */ |
2b0143b5c VFS: normal files... |
845 |
vnode = AFS_FS_I(d_inode(dentry)); |
260a98031 [AFS]: Add "direc... |
846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 |
if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) _debug("AFS_VNODE_DELETED"); if (test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags)) _debug("AFS_VNODE_CB_BROKEN"); set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags); ret = afs_validate(vnode, key); _debug("nlink %d [val %d]", vnode->vfs_inode.i_nlink, ret); } key_put(key); _leave(" = 0"); return 0; remove_error: key_put(key); error: _leave(" = %d", ret); return ret; } /* * create a regular file on an AFS filesystem */ |
4acdaf27e switch ->create()... |
869 |
static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
ebfc3b49a don't pass nameid... |
870 |
bool excl) |
260a98031 [AFS]: Add "direc... |
871 872 873 874 875 876 877 878 879 880 881 |
{ struct afs_file_status status; struct afs_callback cb; struct afs_server *server; struct afs_vnode *dvnode, *vnode; struct afs_fid fid; struct inode *inode; struct key *key; int ret; dvnode = AFS_FS_I(dir); |
a455589f1 assorted conversi... |
882 883 |
_enter("{%x:%u},{%pd},%ho,", dvnode->fid.vid, dvnode->fid.vnode, dentry, mode); |
260a98031 [AFS]: Add "direc... |
884 |
|
260a98031 [AFS]: Add "direc... |
885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 |
key = afs_request_key(dvnode->volume->cell); if (IS_ERR(key)) { ret = PTR_ERR(key); goto error; } mode |= S_IFREG; ret = afs_vnode_create(dvnode, key, dentry->d_name.name, mode, &fid, &status, &cb, &server); if (ret < 0) goto create_error; inode = afs_iget(dir->i_sb, key, &fid, &status, &cb); if (IS_ERR(inode)) { /* ENOMEM at a really inconvenient time - just abandon the new * directory on the server */ ret = PTR_ERR(inode); goto iget_error; } /* apply the status report we've got for the new vnode */ vnode = AFS_FS_I(inode); spin_lock(&vnode->lock); vnode->update_cnt++; spin_unlock(&vnode->lock); afs_vnode_finalise_status_update(vnode, server); afs_put_server(server); d_instantiate(dentry, inode); if (d_unhashed(dentry)) { _debug("not hashed"); d_rehash(dentry); } key_put(key); _leave(" = 0"); return 0; iget_error: afs_put_server(server); create_error: key_put(key); error: d_drop(dentry); _leave(" = %d", ret); return ret; } /* * create a hard link between files in an AFS filesystem */ static int afs_link(struct dentry *from, struct inode *dir, struct dentry *dentry) { struct afs_vnode *dvnode, *vnode; struct key *key; int ret; |
2b0143b5c VFS: normal files... |
941 |
vnode = AFS_FS_I(d_inode(from)); |
260a98031 [AFS]: Add "direc... |
942 |
dvnode = AFS_FS_I(dir); |
a455589f1 assorted conversi... |
943 |
_enter("{%x:%u},{%x:%u},{%pd}", |
260a98031 [AFS]: Add "direc... |
944 945 |
vnode->fid.vid, vnode->fid.vnode, dvnode->fid.vid, dvnode->fid.vnode, |
a455589f1 assorted conversi... |
946 |
dentry); |
260a98031 [AFS]: Add "direc... |
947 |
|
260a98031 [AFS]: Add "direc... |
948 949 950 951 952 953 954 955 956 |
key = afs_request_key(dvnode->volume->cell); if (IS_ERR(key)) { ret = PTR_ERR(key); goto error; } ret = afs_vnode_link(dvnode, vnode, key, dentry->d_name.name); if (ret < 0) goto link_error; |
7de9c6ee3 new helper: ihold() |
957 |
ihold(&vnode->vfs_inode); |
260a98031 [AFS]: Add "direc... |
958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 |
d_instantiate(dentry, &vnode->vfs_inode); key_put(key); _leave(" = 0"); return 0; link_error: key_put(key); error: d_drop(dentry); _leave(" = %d", ret); return ret; } /* * create a symlink in an AFS filesystem */ static int afs_symlink(struct inode *dir, struct dentry *dentry, const char *content) { struct afs_file_status status; struct afs_server *server; struct afs_vnode *dvnode, *vnode; struct afs_fid fid; struct inode *inode; struct key *key; int ret; dvnode = AFS_FS_I(dir); |
a455589f1 assorted conversi... |
986 987 |
_enter("{%x:%u},{%pd},%s", dvnode->fid.vid, dvnode->fid.vnode, dentry, |
260a98031 [AFS]: Add "direc... |
988 |
content); |
260a98031 [AFS]: Add "direc... |
989 |
ret = -EINVAL; |
45222b9e0 AFS: implement st... |
990 |
if (strlen(content) >= AFSPATHMAX) |
260a98031 [AFS]: Add "direc... |
991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 |
goto error; key = afs_request_key(dvnode->volume->cell); if (IS_ERR(key)) { ret = PTR_ERR(key); goto error; } ret = afs_vnode_symlink(dvnode, key, dentry->d_name.name, content, &fid, &status, &server); if (ret < 0) goto create_error; inode = afs_iget(dir->i_sb, key, &fid, &status, NULL); if (IS_ERR(inode)) { /* ENOMEM at a really inconvenient time - just abandon the new * directory on the server */ ret = PTR_ERR(inode); goto iget_error; } /* apply the status report we've got for the new vnode */ vnode = AFS_FS_I(inode); spin_lock(&vnode->lock); vnode->update_cnt++; spin_unlock(&vnode->lock); afs_vnode_finalise_status_update(vnode, server); afs_put_server(server); d_instantiate(dentry, inode); if (d_unhashed(dentry)) { _debug("not hashed"); d_rehash(dentry); } key_put(key); _leave(" = 0"); return 0; iget_error: afs_put_server(server); create_error: key_put(key); error: d_drop(dentry); _leave(" = %d", ret); return ret; } /* * rename a file in an AFS filesystem and/or move it between directories */ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry, |
1cd66c93b fs: make remainin... |
1043 1044 |
struct inode *new_dir, struct dentry *new_dentry, unsigned int flags) |
260a98031 [AFS]: Add "direc... |
1045 1046 1047 1048 |
{ struct afs_vnode *orig_dvnode, *new_dvnode, *vnode; struct key *key; int ret; |
1cd66c93b fs: make remainin... |
1049 1050 |
if (flags) return -EINVAL; |
2b0143b5c VFS: normal files... |
1051 |
vnode = AFS_FS_I(d_inode(old_dentry)); |
260a98031 [AFS]: Add "direc... |
1052 1053 |
orig_dvnode = AFS_FS_I(old_dir); new_dvnode = AFS_FS_I(new_dir); |
a455589f1 assorted conversi... |
1054 |
_enter("{%x:%u},{%x:%u},{%x:%u},{%pd}", |
260a98031 [AFS]: Add "direc... |
1055 1056 1057 |
orig_dvnode->fid.vid, orig_dvnode->fid.vnode, vnode->fid.vid, vnode->fid.vnode, new_dvnode->fid.vid, new_dvnode->fid.vnode, |
a455589f1 assorted conversi... |
1058 |
new_dentry); |
260a98031 [AFS]: Add "direc... |
1059 |
|
260a98031 [AFS]: Add "direc... |
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 |
key = afs_request_key(orig_dvnode->volume->cell); if (IS_ERR(key)) { ret = PTR_ERR(key); goto error; } ret = afs_vnode_rename(orig_dvnode, new_dvnode, key, old_dentry->d_name.name, new_dentry->d_name.name); if (ret < 0) goto rename_error; key_put(key); _leave(" = 0"); return 0; rename_error: key_put(key); error: d_drop(new_dentry); _leave(" = %d", ret); return ret; } |