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; }
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); }
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; }