static int autofs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode) { struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); struct autofs_dirhash *dh = &sbi->dirhash; struct autofs_dir_ent *ent; struct inode *inode; ino_t ino; lock_kernel(); if (!autofs_oz_mode(sbi)) { unlock_kernel(); return -EACCES; } ent = autofs_hash_lookup(dh, &dentry->d_name); if (ent) { unlock_kernel(); return -EEXIST; } if (sbi->next_dir_ino < AUTOFS_FIRST_DIR_INO) { printk("autofs: Out of inode numbers -- what the heck did you do??\n"); unlock_kernel(); return -ENOSPC; } ino = sbi->next_dir_ino++; ent = kmalloc(sizeof(struct autofs_dir_ent), GFP_KERNEL); if (!ent) { unlock_kernel(); return -ENOSPC; } ent->name = kmalloc(dentry->d_name.len+1, GFP_KERNEL); if (!ent->name) { kfree(ent); unlock_kernel(); return -ENOSPC; } ent->hash = dentry->d_name.hash; memcpy(ent->name, dentry->d_name.name, 1+(ent->len = dentry->d_name.len)); ent->ino = ino; ent->dentry = dentry; autofs_hash_insert(dh,ent); inc_nlink(dir); inode = autofs_iget(dir->i_sb, ino); if (IS_ERR(inode)) { drop_nlink(dir); return PTR_ERR(inode); } d_instantiate(dentry, inode); unlock_kernel(); return 0; }
static int try_to_fill_dentry(struct dentry *dentry, struct super_block *sb, struct autofs_sb_info *sbi) { struct inode * inode; struct autofs_dir_ent *ent; int status = 0; if (!(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name))) { do { if (status && dentry->d_inode) { if (status != -ENOENT) printk("autofs warning: lookup failure on positive dentry, status = %d, name = %s\n", status, dentry->d_name.name); 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; } status = autofs_wait(sbi, &dentry->d_name); } while (!(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name))); } /* Abuse this field as a pointer to the directory entry, used to find the expire list pointers */ dentry->d_time = (unsigned long) ent; if (!dentry->d_inode) { inode = autofs_iget(sb, ent->ino); if (IS_ERR(inode)) { /* Failed, but leave pending for next time */ return 1; } dentry->d_inode = inode; } /* If this is a directory that isn't a mount point, bitch at the daemon and fix it in user space */ if (S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry)) { return !autofs_wait(sbi, &dentry->d_name); } /* We don't update the usages for the autofs daemon itself, this is necessary for recursive autofs mounts */ if (!autofs_oz_mode(sbi)) { autofs_update_usage(&sbi->dirhash,ent); } dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; return 1; }
static int autofs_root_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); struct autofs_dirhash *dh = &sbi->dirhash; struct autofs_dir_ent *ent; unsigned int n; int slsize; struct autofs_symlink *sl; struct inode *inode; DPRINTK(("autofs_root_symlink: %s <- ", symname)); autofs_say(dentry->d_name.name,dentry->d_name.len); lock_kernel(); if (!autofs_oz_mode(sbi)) { unlock_kernel(); return -EACCES; } if (autofs_hash_lookup(dh, &dentry->d_name)) { unlock_kernel(); return -EEXIST; } n = find_first_zero_bit(sbi->symlink_bitmap,AUTOFS_MAX_SYMLINKS); if (n >= AUTOFS_MAX_SYMLINKS) { unlock_kernel(); return -ENOSPC; } set_bit(n,sbi->symlink_bitmap); sl = &sbi->symlink[n]; sl->len = strlen(symname); sl->data = kmalloc(slsize = sl->len+1, GFP_KERNEL); if (!sl->data) { clear_bit(n,sbi->symlink_bitmap); unlock_kernel(); return -ENOSPC; } ent = kmalloc(sizeof(struct autofs_dir_ent), GFP_KERNEL); if (!ent) { kfree(sl->data); clear_bit(n,sbi->symlink_bitmap); unlock_kernel(); return -ENOSPC; } ent->name = kmalloc(dentry->d_name.len+1, GFP_KERNEL); if (!ent->name) { kfree(sl->data); kfree(ent); clear_bit(n,sbi->symlink_bitmap); unlock_kernel(); return -ENOSPC; } memcpy(sl->data,symname,slsize); sl->mtime = get_seconds(); ent->ino = AUTOFS_FIRST_SYMLINK + n; ent->hash = dentry->d_name.hash; memcpy(ent->name, dentry->d_name.name, 1+(ent->len = dentry->d_name.len)); ent->dentry = NULL; /* We don't keep the dentry for symlinks */ autofs_hash_insert(dh,ent); inode = autofs_iget(dir->i_sb, ent->ino); if (IS_ERR(inode)) return PTR_ERR(inode); d_instantiate(dentry, inode); unlock_kernel(); return 0; }
int autofs_fill_super(struct super_block *s, void *data, int silent) { struct inode * root_inode; struct dentry * root; struct file * pipe; int pipefd; struct autofs_sb_info *sbi; int minproto, maxproto; pid_t pgid; save_mount_options(s, data); sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) goto fail_unlock; DPRINTK(("autofs: starting up, sbi = %p\n",sbi)); s->s_fs_info = sbi; sbi->magic = AUTOFS_SBI_MAGIC; sbi->pipe = NULL; sbi->catatonic = 1; sbi->exp_timeout = 0; autofs_initialize_hash(&sbi->dirhash); sbi->queues = NULL; memset(sbi->symlink_bitmap, 0, sizeof(long)*AUTOFS_SYMLINK_BITMAP_LEN); sbi->next_dir_ino = AUTOFS_FIRST_DIR_INO; s->s_blocksize = 1024; s->s_blocksize_bits = 10; s->s_magic = AUTOFS_SUPER_MAGIC; s->s_op = &autofs_sops; s->s_time_gran = 1; sbi->sb = s; root_inode = autofs_iget(s, AUTOFS_ROOT_INO); if (IS_ERR(root_inode)) goto fail_free; root = d_alloc_root(root_inode); pipe = NULL; if (!root) goto fail_iput; /* Can this call block? - WTF cares? s is locked. */ if (parse_options(data, &pipefd, &root_inode->i_uid, &root_inode->i_gid, &pgid, &minproto, &maxproto)) { printk("autofs: called with bogus options\n"); goto fail_dput; } /* Couldn't this be tested earlier? */ if (minproto > AUTOFS_PROTO_VERSION || maxproto < AUTOFS_PROTO_VERSION) { printk("autofs: kernel does not match daemon version\n"); goto fail_dput; } DPRINTK(("autofs: pipe fd = %d, pgrp = %u\n", pipefd, pgid)); sbi->oz_pgrp = find_get_pid(pgid); if (!sbi->oz_pgrp) { printk("autofs: could not find process group %d\n", pgid); goto fail_dput; } pipe = fget(pipefd); if (!pipe) { printk("autofs: could not open pipe file descriptor\n"); goto fail_put_pid; } if (!pipe->f_op || !pipe->f_op->write) goto fail_fput; sbi->pipe = pipe; sbi->catatonic = 0; /* * Success! Install the root dentry now to indicate completion. */ s->s_root = root; return 0; fail_fput: printk("autofs: pipe file descriptor does not contain proper ops\n"); fput(pipe); fail_put_pid: put_pid(sbi->oz_pgrp); fail_dput: dput(root); goto fail_free; fail_iput: printk("autofs: get root dentry failed\n"); iput(root_inode); fail_free: kfree(sbi); s->s_fs_info = NULL; fail_unlock: return -EINVAL; }