Ejemplo n.º 1
0
static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentry)
{
    struct autofs_sb_info *sbi;
    int oz_mode;

    DPRINTK(("autofs_root_lookup: name = "));
    autofs_say(dentry->d_name.name,dentry->d_name.len);

    if (dentry->d_name.len > NAME_MAX)
        return ERR_PTR(-ENAMETOOLONG);/* File name too long to exist */

    sbi = autofs_sbi(dir->i_sb);

    oz_mode = autofs_oz_mode(sbi);
    DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n",
             current->pid, current->pgrp, sbi->catatonic, oz_mode));

    /*
     * Mark the dentry incomplete, but add it. This is needed so
     * that the VFS layer knows about the dentry, and we can count
     * on catching any lookups through the revalidate.
     *
     * Let all the hard work be done by the revalidate function that
     * needs to be able to do this anyway..
     *
     * We need to do this before we release the directory semaphore.
     */
    dentry->d_op = &autofs_dentry_operations;
    dentry->d_flags |= DCACHE_AUTOFS_PENDING;
    d_add(dentry, NULL);

    up(&dir->i_sem);
    autofs_revalidate(dentry, 0);
    down(&dir->i_sem);

    /*
     * If we are still pending, check if we had to handle
     * a signal. If so we can force a restart..
     */
    if (dentry->d_flags & DCACHE_AUTOFS_PENDING) {
        if (signal_pending(current))
            return ERR_PTR(-ERESTARTNOINTR);
    }

    /*
     * If this dentry is unhashed, then we shouldn't honour this
     * lookup even if the dentry is positive.  Returning ENOENT here
     * doesn't do the right thing for all system calls, but it should
     * be OK for the operations we permit from an autofs.
     */
    if ( dentry->d_inode && d_unhashed(dentry) )
        return ERR_PTR(-ENOENT);

    return NULL;
}
Ejemplo n.º 2
0
static void autofs_notify_daemon(struct autofs_sb_info *sbi, struct autofs_wait_queue *wq)
{
	struct autofs_packet_missing pkt;

	DPRINTK(("autofs_wait: wait id = 0x%08lx, name = ", wq->wait_queue_token));
	autofs_say(wq->name,wq->len);

	memset(&pkt,0,sizeof pkt); /* For security reasons */

	pkt.hdr.proto_version = AUTOFS_PROTO_VERSION;
	pkt.hdr.type = autofs_ptype_missing;
	pkt.wait_queue_token = wq->wait_queue_token;
	pkt.len = wq->len;
        memcpy(pkt.name, wq->name, pkt.len);
	pkt.name[pkt.len] = '\0';

	if ( autofs_write(sbi->pipe,&pkt,sizeof(struct autofs_packet_missing)) )
		autofs_catatonic_mode(sbi);
}
Ejemplo n.º 3
0
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;
}