static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd) { struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); if (!autofs4_oz_mode(sbi)) autofs4_update_usage(dentry); return 1; }
/* * Revalidate is called on every cache lookup. Some of those * cache lookups may actually happen while the dentry is not * yet completely filled in, and revalidate has to delay such * lookups.. */ static int autofs4_root_revalidate(struct dentry * dentry, int flags) { struct inode * dir = dentry->d_parent->d_inode; struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); struct autofs_info *ino; int oz_mode = autofs4_oz_mode(sbi); /* Pending dentry */ if (autofs4_ispending(dentry)) { if (autofs4_oz_mode(sbi)) return 1; else return try_to_fill_dentry(dentry, dir->i_sb, sbi); } /* Negative dentry.. invalidate if "old" */ if (dentry->d_inode == NULL) return (dentry->d_time - jiffies <= AUTOFS_NEGATIVE_TIMEOUT); ino = autofs4_dentry_ino(dentry); /* Check for a non-mountpoint directory with no contents */ spin_lock(&dcache_lock); if (S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { DPRINTK(("autofs_root_revalidate: dentry=%p %.*s, emptydir\n", dentry, dentry->d_name.len, dentry->d_name.name)); spin_unlock(&dcache_lock); if (oz_mode) return 1; else return try_to_fill_dentry(dentry, dir->i_sb, sbi); } spin_unlock(&dcache_lock); /* Update the usage list */ if (!oz_mode) autofs4_update_usage(dentry); return 1; }
static int try_to_fill_dentry(struct dentry *dentry, struct super_block *sb, struct autofs_sb_info *sbi) { struct autofs_info *de_info = autofs4_dentry_ino(dentry); int status = 0; /* Block on any pending expiry here; invalidate the dentry when expiration is done to trigger mount request with a new dentry */ if (de_info && (de_info->flags & AUTOFS_INF_EXPIRING)) { DPRINTK(("try_to_fill_entry: waiting for expire %p name=%.*s, flags&PENDING=%s de_info=%p de_info->flags=%x\n", dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_flags & DCACHE_AUTOFS_PENDING?"t":"f", de_info, de_info?de_info->flags:0)); status = autofs4_wait(sbi, &dentry->d_name, NFY_NONE); DPRINTK(("try_to_fill_entry: expire done status=%d\n", status)); return 0; } DPRINTK(("try_to_fill_entry: dentry=%p %.*s ino=%p\n", dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode)); /* Wait for a pending mount, triggering one if there isn't one already */ while(dentry->d_inode == NULL) { DPRINTK(("try_to_fill_entry: waiting for mount name=%.*s, de_info=%p de_info->flags=%x\n", dentry->d_name.len, dentry->d_name.name, de_info, de_info?de_info->flags:0)); status = autofs4_wait(sbi, &dentry->d_name, NFY_MOUNT); DPRINTK(("try_to_fill_entry: mount done status=%d\n", status)); if (status && dentry->d_inode) return 0; /* Try to get the kernel to invalidate this dentry */ /* Turn this into a real negative dentry? */ if (status == -ENOENT) { dentry->d_time = jiffies + AUTOFS_NEGATIVE_TIMEOUT; dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; return 1; } else if (status) { /* Return a negative dentry, but leave it "pending" */ return 1; } } /* If this is an unused directory that isn't a mount point, bitch at the daemon and fix it in user space */ spin_lock(&dcache_lock); if (S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { DPRINTK(("try_to_fill_entry: mounting existing dir\n")); spin_unlock(&dcache_lock); return autofs4_wait(sbi, &dentry->d_name, NFY_MOUNT) == 0; } spin_unlock(&dcache_lock); /* We don't update the usages for the autofs daemon itself, this is necessary for recursive autofs mounts */ if (!autofs4_oz_mode(sbi)) autofs4_update_usage(dentry); dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; return 1; }
static int try_to_fill_dentry(struct dentry *dentry, struct super_block *sb, struct autofs_sb_info *sbi, int flags) { struct autofs_info *de_info = autofs4_dentry_ino(dentry); int status = 0; /* Block on any pending expiry here; invalidate the dentry when expiration is done to trigger mount request with a new dentry */ if (de_info && (de_info->flags & AUTOFS_INF_EXPIRING)) { DPRINTK("waiting for expire %p name=%.*s", dentry, dentry->d_name.len, dentry->d_name.name); status = autofs4_wait(sbi, dentry, NFY_NONE); DPRINTK("expire done status=%d", status); return 0; } DPRINTK("dentry=%p %.*s ino=%p", dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode); /* Wait for a pending mount, triggering one if there isn't one already */ if (dentry->d_inode == NULL) { DPRINTK("waiting for mount name=%.*s", dentry->d_name.len, dentry->d_name.name); status = autofs4_wait(sbi, dentry, NFY_MOUNT); DPRINTK("mount done status=%d", status); if (status && dentry->d_inode) return 0; /* Try to get the kernel to invalidate this dentry */ /* Turn this into a real negative dentry? */ if (status == -ENOENT) { dentry->d_time = jiffies + AUTOFS_NEGATIVE_TIMEOUT; spin_lock(&dentry->d_lock); dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; spin_unlock(&dentry->d_lock); return 1; } else if (status) { /* Return a negative dentry, but leave it "pending" */ return 1; } /* Trigger mount for path component or follow link */ } else if (flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY) || current->link_count) { DPRINTK("waiting for mount name=%.*s", dentry->d_name.len, dentry->d_name.name); spin_lock(&dentry->d_lock); dentry->d_flags |= DCACHE_AUTOFS_PENDING; spin_unlock(&dentry->d_lock); status = autofs4_wait(sbi, dentry, NFY_MOUNT); DPRINTK("mount done status=%d", status); if (status) { spin_lock(&dentry->d_lock); dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; spin_unlock(&dentry->d_lock); return 0; } } /* We don't update the usages for the autofs daemon itself, this is necessary for recursive autofs mounts */ if (!autofs4_oz_mode(sbi)) autofs4_update_usage(dentry); spin_lock(&dentry->d_lock); dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; spin_unlock(&dentry->d_lock); return 1; }