diff options
Diffstat (limited to 'fs/afs/dir.c')
-rw-r--r-- | fs/afs/dir.c | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index b42d5cc1d6d2..0d38c09bd55e 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
@@ -477,6 +477,40 @@ static int afs_do_lookup(struct inode *dir, struct dentry *dentry, | |||
477 | } | 477 | } |
478 | 478 | ||
479 | /* | 479 | /* |
480 | * Try to auto mount the mountpoint with pseudo directory, if the autocell | ||
481 | * operation is setted. | ||
482 | */ | ||
483 | static struct inode *afs_try_auto_mntpt( | ||
484 | int ret, struct dentry *dentry, struct inode *dir, struct key *key, | ||
485 | struct afs_fid *fid) | ||
486 | { | ||
487 | const char *devname = dentry->d_name.name; | ||
488 | struct afs_vnode *vnode = AFS_FS_I(dir); | ||
489 | struct inode *inode; | ||
490 | |||
491 | _enter("%d, %p{%s}, {%x:%u}, %p", | ||
492 | ret, dentry, devname, vnode->fid.vid, vnode->fid.vnode, key); | ||
493 | |||
494 | if (ret != -ENOENT || | ||
495 | !test_bit(AFS_VNODE_AUTOCELL, &vnode->flags)) | ||
496 | goto out; | ||
497 | |||
498 | inode = afs_iget_autocell(dir, devname, strlen(devname), key); | ||
499 | if (IS_ERR(inode)) { | ||
500 | ret = PTR_ERR(inode); | ||
501 | goto out; | ||
502 | } | ||
503 | |||
504 | *fid = AFS_FS_I(inode)->fid; | ||
505 | _leave("= %p", inode); | ||
506 | return inode; | ||
507 | |||
508 | out: | ||
509 | _leave("= %d", ret); | ||
510 | return ERR_PTR(ret); | ||
511 | } | ||
512 | |||
513 | /* | ||
480 | * look up an entry in a directory | 514 | * look up an entry in a directory |
481 | */ | 515 | */ |
482 | static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, | 516 | static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, |
@@ -520,6 +554,13 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, | |||
520 | 554 | ||
521 | ret = afs_do_lookup(dir, dentry, &fid, key); | 555 | ret = afs_do_lookup(dir, dentry, &fid, key); |
522 | if (ret < 0) { | 556 | if (ret < 0) { |
557 | inode = afs_try_auto_mntpt(ret, dentry, dir, key, &fid); | ||
558 | if (!IS_ERR(inode)) { | ||
559 | key_put(key); | ||
560 | goto success; | ||
561 | } | ||
562 | |||
563 | ret = PTR_ERR(inode); | ||
523 | key_put(key); | 564 | key_put(key); |
524 | if (ret == -ENOENT) { | 565 | if (ret == -ENOENT) { |
525 | d_add(dentry, NULL); | 566 | d_add(dentry, NULL); |
@@ -539,6 +580,7 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, | |||
539 | return ERR_CAST(inode); | 580 | return ERR_CAST(inode); |
540 | } | 581 | } |
541 | 582 | ||
583 | success: | ||
542 | dentry->d_op = &afs_fs_dentry_operations; | 584 | dentry->d_op = &afs_fs_dentry_operations; |
543 | 585 | ||
544 | d_add(dentry, inode); | 586 | d_add(dentry, inode); |
@@ -696,8 +738,9 @@ static int afs_d_delete(struct dentry *dentry) | |||
696 | goto zap; | 738 | goto zap; |
697 | 739 | ||
698 | if (dentry->d_inode && | 740 | if (dentry->d_inode && |
699 | test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dentry->d_inode)->flags)) | 741 | (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dentry->d_inode)->flags) || |
700 | goto zap; | 742 | test_bit(AFS_VNODE_PSEUDODIR, &AFS_FS_I(dentry->d_inode)->flags))) |
743 | goto zap; | ||
701 | 744 | ||
702 | _leave(" = 0 [keep]"); | 745 | _leave(" = 0 [keep]"); |
703 | return 0; | 746 | return 0; |