~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/afs/dir.c

Version: ~ [ linux-5.5-rc1 ] ~ [ linux-5.4.2 ] ~ [ linux-5.3.15 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.88 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.158 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.206 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.206 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.78 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp