#
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_MD is not set
-CONFIG_BLK_DEV_RAM=y
+# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_BLK_DEV_XD is not set
# CONFIG_BLK_DEV_EZ is not set
{
int error;
struct file *file;
+ struct dentry *dentry;
+ struct inode *inode;
struct osf_dirent_callback buf;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
- return -EBADF;
- if (!file->f_op || !file->f_op->readdir)
- return -ENOTDIR;
- error = verify_area(VERIFY_WRITE, dirent, count);
- if (error)
- return error;
- if (basep) {
- error = verify_area(VERIFY_WRITE, basep, sizeof(long));
- if (error)
- return error;
- }
+ error = -EBADF;
+ if (fd >= NR_OPEN)
+ goto out;
+
+ file = current->files->fd[fd];
+ if (!file)
+ goto out;
+
+ dentry = file->f_dentry;
+ if (!dentry)
+ goto out;
+
+ inode = dentry->d_inode;
+ if (!inode)
+ goto out;
+
buf.dirent = dirent;
buf.basep = basep;
buf.count = count;
buf.error = 0;
- error = file->f_op->readdir(file->f_inode, file, &buf, osf_filldir);
+
+ error = -ENOTDIR;
+ if (!file->f_op || !file->f_op->readdir)
+ goto out;
+
+ error = file->f_op->readdir(inode, file, &buf, osf_filldir);
if (error < 0)
- return error;
+ goto out;
+
+ error = buf.error;
if (count == buf.count)
- return buf.error;
- return count - buf.count;
+ goto out;
+
+ error = count - buf.count;
+out:
+ return error;
}
/*
__kernel_fsid_t f_fsid;
} *osf_stat;
-static void linux_to_osf_statfs(struct statfs *linux_stat, struct osf_statfs *osf_stat)
+static int linux_to_osf_statfs(struct statfs *linux_stat, struct osf_statfs *osf_stat, unsigned long bufsiz)
{
- osf_stat->f_type = linux_stat->f_type;
- osf_stat->f_flags = 0; /* mount flags */
+ struct osf_statfs tmp_stat;
+
+ tmp_stat.f_type = linux_stat->f_type;
+ tmp_stat.f_flags = 0; /* mount flags */
/* Linux doesn't provide a "fundamental filesystem block size": */
- osf_stat->f_fsize = linux_stat->f_bsize;
- osf_stat->f_bsize = linux_stat->f_bsize;
- osf_stat->f_blocks = linux_stat->f_blocks;
- osf_stat->f_bfree = linux_stat->f_bfree;
- osf_stat->f_bavail = linux_stat->f_bavail;
- osf_stat->f_files = linux_stat->f_files;
- osf_stat->f_ffree = linux_stat->f_ffree;
- osf_stat->f_fsid = linux_stat->f_fsid;
+ tmp_stat.f_fsize = linux_stat->f_bsize;
+ tmp_stat.f_bsize = linux_stat->f_bsize;
+ tmp_stat.f_blocks = linux_stat->f_blocks;
+ tmp_stat.f_bfree = linux_stat->f_bfree;
+ tmp_stat.f_bavail = linux_stat->f_bavail;
+ tmp_stat.f_files = linux_stat->f_files;
+ tmp_stat.f_ffree = linux_stat->f_ffree;
+ tmp_stat.f_fsid = linux_stat->f_fsid;
+ if (bufsiz > sizeof(tmp_stat))
+ bufsiz = sizeof(tmp_stat);
+ return copy_to_user(osf_stat, &tmp_stat, bufsiz) ? -EFAULT : 0;
}
+static int do_osf_statfs(struct dentry * dentry, struct osf_statfs *buffer, unsigned long bufsiz)
+{
+ struct statfs linux_stat;
+ struct inode * inode = dentry->d_inode;
+ struct super_block * sb = inode->i_sb;
+ int error;
+
+ error = -ENOSYS;
+ if (sb->s_op->statfs) {
+ set_fs(KERNEL_DS);
+ error = sb->s_op->statfs(sb, &linux_stat, sizeof(linux_stat));
+ set_fs(USER_DS);
+ if (!error)
+ error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz);
+ }
+ return error;
+}
asmlinkage int osf_statfs(char *path, struct osf_statfs *buffer, unsigned long bufsiz)
{
- struct statfs linux_stat;
- struct inode *inode;
+ struct dentry *dentry;
int retval;
lock_kernel();
- if (bufsiz > sizeof(struct osf_statfs))
- bufsiz = sizeof(struct osf_statfs);
- retval = verify_area(VERIFY_WRITE, buffer, bufsiz);
- if (retval)
- goto out;
- retval = namei(path, &inode);
- if (retval)
- goto out;
- retval = -ENOSYS;
- if (!inode->i_sb->s_op->statfs) {
- iput(inode);
- goto out;
+ dentry = namei(path);
+ retval = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ retval = do_osf_statfs(dentry, buffer, bufsiz);
+ dput(dentry);
}
- inode->i_sb->s_op->statfs(inode->i_sb, &linux_stat, sizeof(linux_stat));
- linux_to_osf_statfs(&linux_stat, buffer);
- iput(inode);
- retval = 0;
-out:
unlock_kernel();
return retval;
}
asmlinkage int osf_fstatfs(unsigned long fd, struct osf_statfs *buffer, unsigned long bufsiz)
{
- struct statfs linux_stat;
struct file *file;
- struct inode *inode;
+ struct dentry *dentry;
int retval;
lock_kernel();
- retval = verify_area(VERIFY_WRITE, buffer, bufsiz);
- if (retval)
- goto out;
- if (bufsiz > sizeof(struct osf_statfs))
- bufsiz = sizeof(struct osf_statfs);
retval = -EBADF;
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
goto out;
- retval = -ENOENT;
- if (!(inode = file->f_inode))
- goto out;
- retval = -ENOSYS;
- if (!inode->i_sb->s_op->statfs)
- goto out;
- inode->i_sb->s_op->statfs(inode->i_sb, &linux_stat, sizeof(linux_stat));
- linux_to_osf_statfs(&linux_stat, buffer);
- retval = 0;
+ dentry = file->f_dentry;
+ if (dentry)
+ retval = do_osf_statfs(dentry, buffer, bufsiz);
out:
unlock_kernel();
return retval;
uid_t exroot;
};
-static int getdev(const char *name, int rdonly, struct inode **ino)
+static int getdev(const char *name, int rdonly, struct dentry **dp)
{
kdev_t dev;
+ struct dentry *dentry;
struct inode *inode;
struct file_operations *fops;
int retval;
- retval = namei(name, &inode);
- if (retval)
+ dentry = namei(name);
+ retval = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
return retval;
+
+ inode = dentry->d_inode;
if (!S_ISBLK(inode->i_mode)) {
- iput(inode);
+ dput(dentry);
return -ENOTBLK;
}
if (IS_NODEV(inode)) {
- iput(inode);
+ dput(dentry);
return -EACCES;
}
dev = inode->i_rdev;
if (MAJOR(dev) >= MAX_BLKDEV) {
- iput(inode);
+ dput(dentry);
return -ENXIO;
}
fops = get_blkfops(MAJOR(dev));
if (!fops) {
- iput(inode);
+ dput(dentry);
return -ENODEV;
}
if (fops->open) {
struct file dummy;
memset(&dummy, 0, sizeof(dummy));
- dummy.f_inode = inode;
+ dummy.f_dentry = dentry;
dummy.f_mode = rdonly ? 1 : 3;
retval = fops->open(inode, &dummy);
if (retval) {
- iput(inode);
+ dput(dentry);
return retval;
}
}
- *ino = inode;
+ *dp = dentry;
return 0;
}
-static void putdev(struct inode *inode)
+static void putdev(struct dentry *dentry)
{
struct file_operations *fops;
- fops = get_blkfops(MAJOR(inode->i_rdev));
+ fops = get_blkfops(MAJOR(dentry->d_inode->i_rdev));
if (fops->release)
- fops->release(inode, NULL);
+ fops->release(dentry->d_inode, NULL);
}
/*
static int osf_ufs_mount(char *dirname, struct ufs_args *args, int flags)
{
int retval;
- struct inode *inode;
+ struct dentry *dentry;
struct cdfs_args tmp;
retval = verify_area(VERIFY_READ, args, sizeof(*args));
if (retval)
return retval;
copy_from_user(&tmp, args, sizeof(tmp));
- retval = getdev(tmp.devname, 0, &inode);
+ retval = getdev(tmp.devname, 0, &dentry);
if (retval)
return retval;
- retval = do_mount(inode->i_rdev, tmp.devname, dirname, "ext2", flags, NULL);
+ retval = do_mount(dentry->d_inode->i_rdev, tmp.devname, dirname, "ext2", flags, NULL);
if (retval)
- putdev(inode);
- iput(inode);
+ putdev(dentry);
+ dput(dentry);
return retval;
}
static int osf_cdfs_mount(char *dirname, struct cdfs_args *args, int flags)
{
int retval;
- struct inode *inode;
+ struct dentry * dentry;
struct cdfs_args tmp;
retval = verify_area(VERIFY_READ, args, sizeof(*args));
if (retval)
return retval;
copy_from_user(&tmp, args, sizeof(tmp));
- retval = getdev(tmp.devname, 1, &inode);
+ retval = getdev(tmp.devname, 1, &dentry);
if (retval)
return retval;
- retval = do_mount(inode->i_rdev, tmp.devname, dirname, "iso9660", flags, NULL);
+ retval = do_mount(dentry->d_inode->i_rdev, tmp.devname, dirname, "iso9660", flags, NULL);
if (retval)
- putdev(inode);
- iput(inode);
+ putdev(dentry);
+ dput(dentry);
return retval;
}
char * filename;
lock_kernel();
- error = getname((char *) a0, &filename);
- if (error)
+ filename = getname((char *) a0);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
goto out;
error = do_execve(filename, (char **) a1, (char **) a2, ®s);
putname(filename);
unsigned long *r9_15)
{
long i;
- unsigned long sp, ra;
+ unsigned long ra;
unsigned int * pc;
+ unsigned long * sp;
if (regs->ps & 8)
return;
printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err);
- sp = (unsigned long) (regs+1);
+ sp = (unsigned long *) (regs+1);
__get_user(ra, (unsigned long *)sp);
printk("pc = [<%016lx>] ps = %04lx\n", regs->pc, regs->ps);
printk("rp = [<%016lx>] ra = [<%016lx>]\n", regs->r26, ra);
printk("r22= %016lx r23= %016lx\n", regs->r22, regs->r23);
printk("r24= %016lx r25= %016lx\n", regs->r24, regs->r25);
printk("r27= %016lx r28= %016lx\n", regs->r27, regs->r28);
- printk("gp = %016lx sp = %016lx\n", regs->gp, sp);
+ printk("gp = %016lx sp = %p\n", regs->gp, sp);
printk("Code:");
pc = (unsigned int *) regs->pc;
printk("%c%08x%c",i?' ':'<',insn,i?' ':'>');
}
printk("\n");
+ printk("Trace:");
+ while (0x1ff8 & (unsigned long) sp) {
+ extern unsigned long _stext, _etext;
+ unsigned long tmp = *sp;
+ sp++;
+ if (tmp < (unsigned long) &_stext)
+ continue;
+ if (tmp >= (unsigned long) &_etext)
+ continue;
+ printk(" [<%lx>]", tmp);
+ }
+ printk("\n");
+
do_exit(SIGSEGV);
}
bad_area:
up(&mm->mmap_sem);
+ if (user_mode(regs)) {
+ force_sig(SIGSEGV, tsk);
+ return;
+ }
+
/* Are we prepared to handle this fault as an exception? */
if ((fixup = search_exception_table(regs->pc)) != 0) {
unsigned long newpc;
return;
}
- if (user_mode(regs)) {
- printk("%s: memory violation at pc=%08lx ra=%08lx "
- "(bad address = %08lx)\n",
- tsk->comm, regs->pc, regs->r26, address);
- die_if_kernel("oops", regs, cause, (unsigned long*)regs - 16);
- force_sig(SIGSEGV, tsk);
- return;
- }
/*
* Oops. The kernel tried to access some bad page. We'll have to
* terminate things with extreme prejudice.
char * filename;
lock_kernel();
- error = getname((char *) regs.ebx, &filename);
- if (error)
+ filename = getname((char *) regs.ebx);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename)
goto out;
error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, ®s);
putname(filename);
bad_area:
up(&mm->mmap_sem);
- /* Are we prepared to handle this fault? */
+ /* User mode accesses just cause a SIGSEGV */
+ if (error_code & 4) {
+ tsk->tss.cr2 = address;
+ tsk->tss.error_code = error_code;
+ tsk->tss.trap_no = 14;
+ force_sig(SIGSEGV, tsk);
+ goto out;
+ }
+
+ /* Are we prepared to handle this kernel fault? */
if ((fixup = search_exception_table(regs->eip)) != 0) {
printk(KERN_DEBUG "%s: Exception at [<%lx>] (%lx)\n",
current->comm,
goto out;
}
- if (error_code & 4) {
- tsk->tss.cr2 = address;
- tsk->tss.error_code = error_code;
- tsk->tss.trap_no = 14;
- force_sig(SIGSEGV, tsk);
- goto out;
- }
/*
* Oops. The kernel tried to access some bad page. We'll have to
* terminate things with extreme prejudice.
* Read block 0 to test for gzipped kernel
*/
if (fp->f_op->llseek)
- fp->f_op->llseek(fp->f_inode, fp, start_block * BLOCK_SIZE, 0);
+ fp->f_op->llseek(fp->f_dentry->d_inode, fp, start_block * BLOCK_SIZE, 0);
fp->f_pos = start_block * BLOCK_SIZE;
- fp->f_op->read(fp->f_inode, fp, buf, size);
+ fp->f_op->read(fp->f_dentry->d_inode, fp, buf, size);
/*
* If it matches the gzip magic numbers, return -1
* Read block 1 to test for minix and ext2 superblock
*/
if (fp->f_op->llseek)
- fp->f_op->llseek(fp->f_inode, fp,
+ fp->f_op->llseek(fp->f_dentry->d_inode, fp,
(start_block+1) * BLOCK_SIZE, 0);
fp->f_pos = (start_block+1) * BLOCK_SIZE;
- fp->f_op->read(fp->f_inode, fp, buf, size);
+ fp->f_op->read(fp->f_dentry->d_inode, fp, buf, size);
/* Try minix */
if (minixsb->s_magic == MINIX_SUPER_MAGIC ||
done:
if (fp->f_op->llseek)
- fp->f_op->llseek(fp->f_inode, fp, start_block * BLOCK_SIZE, 0);
+ fp->f_op->llseek(fp->f_dentry->d_inode, fp, start_block * BLOCK_SIZE, 0);
fp->f_pos = start_block * BLOCK_SIZE;
if ((nblocks > 0) && blk_size[MAJOR(device)]) {
#endif
if (remap_page_range(vma->vm_start, offset, vma->vm_end - vma->vm_start, vma->vm_page_prot))
return -EAGAIN;
- vma->vm_inode = inode;
- atomic_inc(&inode->i_count);
+ vma->vm_dentry = dget(file->f_dentry);
return 0;
}
/* NOTE: not yet done after every sleep pending a thorough
check of the logic of this change. -- jlc */
/* don't stop on /dev/console */
- if (file->f_inode->i_rdev != CONSOLE_DEV &&
+ if (file->f_dentry->d_inode->i_rdev != CONSOLE_DEV &&
current->tty == tty) {
if (tty->pgrp <= 0)
printk("read_chan: tty->pgrp <= 0!\n");
int retval = 0;
/* Job control check -- must be done at start (POSIX.1 7.1.1.4). */
- if (L_TOSTOP(tty) && file->f_inode->i_rdev != CONSOLE_DEV) {
+ if (L_TOSTOP(tty) && file->f_dentry->d_inode->i_rdev != CONSOLE_DEV) {
retval = tty_check_change(tty);
if (retval)
return retval;
for (filp = inuse_filps; filp; filp = filp->f_next) {
if (filp->private_data != tty)
continue;
- if (!filp->f_inode)
+ if (!filp->f_dentry)
continue;
- if (filp->f_inode->i_rdev == CONSOLE_DEV)
+ if (!filp->f_dentry->d_inode)
+ continue;
+ if (filp->f_dentry->d_inode->i_rdev == CONSOLE_DEV)
continue;
if (filp->f_op != &tty_fops)
continue;
- tty_fasync(filp->f_inode, filp, 0);
+ tty_fasync(filp->f_dentry->d_inode, filp, 0);
filp->f_op = fops;
}
int idx;
tty = (struct tty_struct *)filp->private_data;
- if (tty_paranoia_check(tty, filp->f_inode->i_rdev, "release_dev"))
+ if (tty_paranoia_check(tty, filp->f_dentry->d_inode->i_rdev, "release_dev"))
return;
check_tty_count(tty, "release_dev");
- tty_fasync(filp->f_inode, filp, 0);
+ tty_fasync(filp->f_dentry->d_inode, filp, 0);
idx = MINOR(tty->device) - tty->driver.minor_start;
pty_master = (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
struct tty_struct * tty;
tty = (struct tty_struct *)filp->private_data;
- if (tty_paranoia_check(tty, filp->f_inode->i_rdev, "tty_poll"))
+ if (tty_paranoia_check(tty, filp->f_dentry->d_inode->i_rdev, "tty_poll"))
return 0;
if (tty->ldisc.poll)
/* Mask interrupts from the ethercard. */
outb_p(0x00, e8390_base + EN0_IMR);
+ synchronize_irq();
if (dev->interrupt) {
printk("%s: Tx request while isr active.\n",dev->name);
outb_p(ENISR_ALL, e8390_base + EN0_IMR);
static void autofs_put_inode(struct inode *inode)
{
- if (inode->i_nlink)
- return;
- inode->i_size = 0;
+ if (inode->i_nlink)
+ return;
+ inode->i_size = 0;
}
static void autofs_put_super(struct super_block *sb)
if ( !sbi->catatonic )
autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */
- lock_super(sb);
+ lock_super(sb);
autofs_hash_nuke(&sbi->dirhash);
for ( n = 0 ; n < AUTOFS_MAX_SYMLINKS ; n++ ) {
if ( test_bit(n, sbi->symlink_bitmap) )
kfree(sbi->symlink[n].data);
}
- sb->s_dev = 0;
+ sb->s_dev = 0;
kfree(sb->u.generic_sbp);
- unlock_super(sb);
+ unlock_super(sb);
DPRINTK(("autofs: shutting down\n"));
#endif
}
-static void autofs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
+static int autofs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
static void autofs_read_inode(struct inode *inode);
static void autofs_write_inode(struct inode *inode);
static struct super_operations autofs_sops = {
- autofs_read_inode,
- NULL,
- autofs_write_inode,
- autofs_put_inode,
- autofs_put_super,
- NULL,
- autofs_statfs,
- NULL
+ autofs_read_inode,
+ NULL,
+ autofs_write_inode,
+ autofs_put_inode,
+ autofs_put_super,
+ NULL,
+ autofs_statfs,
+ NULL
};
static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, pid_t *pgrp, int *minproto, int *maxproto)
{
- char *this_char, *value;
-
- *uid = current->uid;
- *gid = current->gid;
+ char *this_char, *value;
+
+ *uid = current->uid;
+ *gid = current->gid;
*pgrp = current->pgrp;
*minproto = *maxproto = AUTOFS_PROTO_VERSION;
- *pipefd = -1;
+ *pipefd = -1;
- if ( !options ) return 1;
- for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
- if ((value = strchr(this_char,'=')) != NULL)
- *value++ = 0;
- if (!strcmp(this_char,"fd")) {
- if (!value || !*value)
- return 1;
- *pipefd = simple_strtoul(value,&value,0);
- if (*value)
- return 1;
- }
- else if (!strcmp(this_char,"uid")) {
- if (!value || !*value)
- return 1;
- *uid = simple_strtoul(value,&value,0);
- if (*value)
- return 1;
- }
- else if (!strcmp(this_char,"gid")) {
- if (!value || !*value)
- return 1;
- *gid = simple_strtoul(value,&value,0);
- if (*value)
- return 1;
- }
- else if (!strcmp(this_char,"pgrp")) {
- if (!value || !*value)
- return 1;
- *pgrp = simple_strtoul(value,&value,0);
- if (*value)
- return 1;
- }
- else if (!strcmp(this_char,"minproto")) {
- if (!value || !*value)
- return 1;
- *minproto = simple_strtoul(value,&value,0);
- if (*value)
- return 1;
- }
- else if (!strcmp(this_char,"maxproto")) {
- if (!value || !*value)
- return 1;
- *maxproto = simple_strtoul(value,&value,0);
- if (*value)
- return 1;
- }
- else break;
- }
- return (*pipefd < 0);
+ if ( !options ) return 1;
+ for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
+ if ((value = strchr(this_char,'=')) != NULL)
+ *value++ = 0;
+ if (!strcmp(this_char,"fd")) {
+ if (!value || !*value)
+ return 1;
+ *pipefd = simple_strtoul(value,&value,0);
+ if (*value)
+ return 1;
+ }
+ else if (!strcmp(this_char,"uid")) {
+ if (!value || !*value)
+ return 1;
+ *uid = simple_strtoul(value,&value,0);
+ if (*value)
+ return 1;
+ }
+ else if (!strcmp(this_char,"gid")) {
+ if (!value || !*value)
+ return 1;
+ *gid = simple_strtoul(value,&value,0);
+ if (*value)
+ return 1;
+ }
+ else if (!strcmp(this_char,"pgrp")) {
+ if (!value || !*value)
+ return 1;
+ *pgrp = simple_strtoul(value,&value,0);
+ if (*value)
+ return 1;
+ }
+ else if (!strcmp(this_char,"minproto")) {
+ if (!value || !*value)
+ return 1;
+ *minproto = simple_strtoul(value,&value,0);
+ if (*value)
+ return 1;
+ }
+ else if (!strcmp(this_char,"maxproto")) {
+ if (!value || !*value)
+ return 1;
+ *maxproto = simple_strtoul(value,&value,0);
+ if (*value)
+ return 1;
+ }
+ else break;
+ }
+ return (*pipefd < 0);
}
struct super_block *autofs_read_super(struct super_block *s, void *data,
- int silent)
+ int silent)
{
- int pipefd;
+ int pipefd;
struct autofs_sb_info *sbi;
int minproto, maxproto;
MOD_INC_USE_COUNT;
- lock_super(s);
- sbi = (struct autofs_sb_info *) kmalloc(sizeof(struct autofs_sb_info), GFP_KERNEL);
+ lock_super(s);
+ sbi = (struct autofs_sb_info *) kmalloc(sizeof(struct autofs_sb_info), GFP_KERNEL);
if ( !sbi ) {
s->s_dev = 0;
MOD_DEC_USE_COUNT;
sbi->queues = NULL;
memset(sbi->symlink_bitmap, 0, sizeof(u32)*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;
- unlock_super(s);
- s->s_root = d_alloc_root(iget(s, AUTOFS_ROOT_INO), NULL);
- if (!s->s_root) {
- s->s_dev = 0;
+ s->s_blocksize = 1024;
+ s->s_blocksize_bits = 10;
+ s->s_magic = AUTOFS_SUPER_MAGIC;
+ s->s_op = &autofs_sops;
+ unlock_super(s);
+ s->s_root = d_alloc_root(iget(s, AUTOFS_ROOT_INO), NULL);
+ if (!s->s_root) {
+ s->s_dev = 0;
kfree(sbi);
- printk("autofs: get root inode failed\n");
+ printk("autofs: get root inode failed\n");
MOD_DEC_USE_COUNT;
- return NULL;
- }
+ return NULL;
+ }
- if ( parse_options(data,&pipefd,&s->s_root->d_inode->i_uid,&s->s_root->d_inode->i_gid,&sbi->oz_pgrp,&minproto,&maxproto) ) {
- d_delete(s->s_root);
- s->s_dev = 0;
+ if ( parse_options(data,&pipefd,&s->s_root->d_inode->i_uid,&s->s_root->d_inode->i_gid,&sbi->oz_pgrp,&minproto,&maxproto) ) {
+ d_delete(s->s_root);
+ s->s_dev = 0;
kfree(sbi);
- printk("autofs: called with bogus options\n");
+ printk("autofs: called with bogus options\n");
MOD_DEC_USE_COUNT;
- return NULL;
- }
+ return NULL;
+ }
if ( minproto > AUTOFS_PROTO_VERSION || maxproto < AUTOFS_PROTO_VERSION ) {
d_delete(s->s_root);
MOD_DEC_USE_COUNT;
return NULL;
}
- return s;
+ return s;
}
-static void autofs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int autofs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
{
- struct statfs tmp;
+ struct statfs tmp;
- tmp.f_type = AUTOFS_SUPER_MAGIC;
- tmp.f_bsize = 1024;
- tmp.f_blocks = 0;
- tmp.f_bfree = 0;
- tmp.f_bavail = 0;
- tmp.f_files = 0;
- tmp.f_ffree = 0;
- tmp.f_namelen = NAME_MAX;
- copy_to_user(buf, &tmp, bufsiz);
+ tmp.f_type = AUTOFS_SUPER_MAGIC;
+ tmp.f_bsize = 1024;
+ tmp.f_blocks = 0;
+ tmp.f_bfree = 0;
+ tmp.f_bavail = 0;
+ tmp.f_files = 0;
+ tmp.f_ffree = 0;
+ tmp.f_namelen = NAME_MAX;
+ return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
}
static void autofs_read_inode(struct inode *inode)
{
- ino_t ino = inode->i_ino;
+ ino_t ino = inode->i_ino;
unsigned int n;
- struct autofs_sb_info *sbi =
+ struct autofs_sb_info *sbi =
(struct autofs_sb_info *) inode->i_sb->u.generic_sbp;
- inode->i_op = NULL;
- inode->i_mode = 0;
- inode->i_nlink = 2;
- inode->i_size = 0;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
- inode->i_blocks = 0;
- inode->i_blksize = 1024;
+ inode->i_op = NULL;
+ inode->i_mode = 0;
+ inode->i_nlink = 2;
+ inode->i_size = 0;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ inode->i_blocks = 0;
+ inode->i_blksize = 1024;
- if ( ino == AUTOFS_ROOT_INO ) {
- inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
- inode->i_op = &autofs_root_inode_operations;
+ if ( ino == AUTOFS_ROOT_INO ) {
+ inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
+ inode->i_op = &autofs_root_inode_operations;
inode->i_uid = inode->i_gid = 0; /* Changed in read_super */
- return;
- }
+ return;
+ }
+
+ inode->i_uid = inode->i_sb->s_root->d_inode->i_uid;
+ inode->i_gid = inode->i_sb->s_root->d_inode->i_gid;
- inode->i_uid = inode->i_sb->s_root->d_inode->i_uid;
- inode->i_gid = inode->i_sb->s_root->d_inode->i_gid;
-
if ( ino >= AUTOFS_FIRST_SYMLINK && ino < AUTOFS_FIRST_DIR_INO ) {
/* Symlink inode - should be in symlink list */
struct autofs_symlink *sl;
static inline int
do_aout_core_dump(long signr, struct pt_regs * regs)
{
+ struct dentry * dentry = NULL;
struct inode * inode = NULL;
struct file file;
unsigned short fs;
#else
corefile[4] = '\0';
#endif
- if (open_namei(corefile,O_CREAT | 2 | O_TRUNC,0600,&inode)) {
- inode = NULL;
+ dentry = open_namei(corefile,O_CREAT | 2 | O_TRUNC, 0600);
+ if (IS_ERR(dentry)) {
+ dentry = NULL;
goto end_coredump;
}
+ inode = dentry->d_inode;
if (!S_ISREG(inode->i_mode))
goto end_coredump;
if (!inode->i_op || !inode->i_op->default_file_ops)
file.f_mode = 3;
file.f_flags = 0;
file.f_count = 1;
- file.f_inode = inode;
+ file.f_dentry = dentry;
file.f_pos = 0;
file.f_reada = 0;
file.f_op = inode->i_op->default_file_ops;
put_write_access(inode);
end_coredump:
set_fs(fs);
- iput(inode);
+ dput(dentry);
return has_dumped;
}
if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
N_TRSIZE(ex) || N_DRSIZE(ex) ||
- bprm->inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+ bprm->dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
return -ENOEXEC;
}
}
if (N_MAGIC(ex) == ZMAGIC && ex.a_text &&
- (fd_offset < bprm->inode->i_sb->s_blocksize)) {
+ (fd_offset < bprm->dentry->d_inode->i_sb->s_blocksize)) {
printk(KERN_NOTICE "N_TXTOFF < BLOCK_SIZE. Please convert binary.\n");
return -ENOEXEC;
}
error = do_mmap(NULL, N_TXTADDR(ex), ex.a_text,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE, 0);
- read_exec(bprm->inode, fd_offset, (char *) N_TXTADDR(ex),
+ read_exec(bprm->dentry, fd_offset, (char *) N_TXTADDR(ex),
ex.a_text, 0);
error = do_mmap(NULL, N_DATADDR(ex), ex.a_data,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE, 0);
- read_exec(bprm->inode, fd_offset + ex.a_text, (char *) N_DATADDR(ex),
+ read_exec(bprm->dentry, fd_offset + ex.a_text, (char *) N_DATADDR(ex),
ex.a_data, 0);
goto beyond_if;
}
ex.a_text+ex.a_data + PAGE_SIZE - 1,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE, 0);
- read_exec(bprm->inode, fd_offset, (char *) N_TXTADDR(ex),
+ read_exec(bprm->dentry, fd_offset, (char *) N_TXTADDR(ex),
ex.a_text+ex.a_data, 0);
#else
do_mmap(NULL, 0, ex.a_text+ex.a_data,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE, 0);
- read_exec(bprm->inode, 32, (char *) 0, ex.a_text+ex.a_data, 0);
+ read_exec(bprm->dentry, 32, (char *) 0, ex.a_text+ex.a_data, 0);
#endif
} else {
if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
(N_MAGIC(ex) != NMAGIC))
printk(KERN_NOTICE "executable not page aligned\n");
- fd = open_inode(bprm->inode, O_RDONLY);
+ fd = open_dentry(bprm->dentry, O_RDONLY);
if (fd < 0)
return fd;
do_mmap(NULL, 0, ex.a_text+ex.a_data,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE, 0);
- read_exec(bprm->inode, fd_offset,
+ read_exec(bprm->dentry, fd_offset,
(char *) N_TXTADDR(ex), ex.a_text+ex.a_data, 0);
goto beyond_if;
}
{
struct file * file;
struct exec ex;
- struct inode * inode;
+ struct dentry * dentry;
+ struct inode * inode;
unsigned int len;
unsigned int bss;
unsigned int start_addr;
unsigned long error;
file = current->files->fd[fd];
- inode = file->f_inode;
if (!file || !file->f_op)
return -EACCES;
+ dentry = file->f_dentry;
+ inode = dentry->d_inode;
+
/* Seek into the file */
if (file->f_op->llseek) {
if ((error = file->f_op->llseek(inode, file, 0, 0)) != 0)
an ELF header */
static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
- struct inode * interpreter_inode,
+ struct dentry * interpreter_dentry,
unsigned long *interp_load_addr)
{
struct file * file;
if ((interp_elf_ex->e_type != ET_EXEC &&
interp_elf_ex->e_type != ET_DYN) ||
!elf_check_arch(interp_elf_ex->e_machine) ||
- (!interpreter_inode->i_op ||
- !interpreter_inode->i_op->default_file_ops->mmap)){
+ (!interpreter_dentry->d_inode->i_op ||
+ !interpreter_dentry->d_inode->i_op->default_file_ops->mmap)){
return ~0UL;
}
return ~0UL;
}
- retval = read_exec(interpreter_inode, interp_elf_ex->e_phoff,
+ retval = read_exec(interpreter_dentry, interp_elf_ex->e_phoff,
(char *) elf_phdata,
sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, 1);
return retval;
}
- elf_exec_fileno = open_inode(interpreter_inode, O_RDONLY);
+ elf_exec_fileno = open_dentry(interpreter_dentry, O_RDONLY);
if (elf_exec_fileno < 0) {
kfree(elf_phdata);
return ~0UL;
}
static unsigned long load_aout_interp(struct exec * interp_ex,
- struct inode * interpreter_inode)
+ struct dentry * interpreter_dentry)
{
int retval;
unsigned long elf_entry;
do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE, 0);
- retval = read_exec(interpreter_inode, 32, (char *) 0,
+ retval = read_exec(interpreter_dentry, 32, (char *) 0,
interp_ex->a_text+interp_ex->a_data, 0);
} else if (N_MAGIC(*interp_ex) == ZMAGIC || N_MAGIC(*interp_ex) == QMAGIC) {
do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE, 0);
- retval = read_exec(interpreter_inode,
+ retval = read_exec(interpreter_dentry,
N_TXTOFF(*interp_ex) ,
(char *) N_TXTADDR(*interp_ex),
interp_ex->a_text+interp_ex->a_data, 0);
struct elfhdr interp_elf_ex;
struct file * file;
struct exec interp_ex;
- struct inode *interpreter_inode;
+ struct dentry *interpreter_dentry;
unsigned long load_addr;
int load_addr_set = 0;
unsigned int interpreter_type = INTERPRETER_NONE;
if ((elf_ex.e_type != ET_EXEC &&
elf_ex.e_type != ET_DYN) ||
(! elf_check_arch(elf_ex.e_machine)) ||
- (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops ||
- !bprm->inode->i_op->default_file_ops->mmap)){
+ (!bprm->dentry->d_inode->i_op || !bprm->dentry->d_inode->i_op->default_file_ops ||
+ !bprm->dentry->d_inode->i_op->default_file_ops->mmap)){
return -ENOEXEC;
}
return -ENOMEM;
}
- retval = read_exec(bprm->inode, elf_ex.e_phoff, (char *) elf_phdata,
+ retval = read_exec(bprm->dentry, elf_ex.e_phoff, (char *) elf_phdata,
elf_ex.e_phentsize * elf_ex.e_phnum, 1);
if (retval < 0) {
kfree (elf_phdata);
elf_bss = 0;
elf_brk = 0;
- elf_exec_fileno = open_inode(bprm->inode, O_RDONLY);
+ elf_exec_fileno = open_dentry(bprm->dentry, O_RDONLY);
if (elf_exec_fileno < 0) {
kfree (elf_phdata);
return -ENOMEM;
}
- retval = read_exec(bprm->inode,elf_ppnt->p_offset,
+ retval = read_exec(bprm->dentry,elf_ppnt->p_offset,
elf_interpreter,
elf_ppnt->p_filesz, 1);
/* If the program interpreter is one of these two,
if (retval >= 0) {
old_fs = get_fs(); /* This could probably be optimized */
set_fs(get_ds());
- retval = open_namei(elf_interpreter, 0, 0, &interpreter_inode);
+ interpreter_dentry = open_namei(elf_interpreter, 0, 0);
set_fs(old_fs);
+ if (IS_ERR(interpreter_dentry))
+ retval = PTR_ERR(interpreter_dentry);
}
if (retval >= 0)
- retval = read_exec(interpreter_inode,0,bprm->buf,128, 1);
+ retval = read_exec(interpreter_dentry,0,bprm->buf,128, 1);
if (retval >= 0) {
interp_ex = *((struct exec *) bprm->buf); /* exec-header */
if (elf_interpreter) {
if (interpreter_type & 1)
elf_entry = load_aout_interp(&interp_ex,
- interpreter_inode);
+ interpreter_dentry);
else if (interpreter_type & 2)
elf_entry = load_elf_interp(&interp_elf_ex,
- interpreter_inode,
+ interpreter_dentry,
&interp_load_addr);
- iput(interpreter_inode);
+ dput(interpreter_dentry);
kfree(elf_interpreter);
if (elf_entry == ~0UL) {
__MOD_INC_USE_COUNT(current->binfmt->module);
#ifndef VM_STACK_FLAGS
- current->executable = bprm->inode;
- atomic_inc(&bprm->inode->i_count);
+ current->executable = bprm->dentry;
+ atomic_inc(&bprm->dentry->i_count);
#endif
#ifdef LOW_ELF_STACK
current->start_stack = bprm->p = elf_stack - 4;
struct file * file;
struct elfhdr elf_ex;
struct elf_phdr *elf_phdata = NULL;
- struct inode * inode;
+ struct dentry * dentry;
+ struct inode * inode;
unsigned long len;
int elf_bss;
int retval;
len = 0;
file = current->files->fd[fd];
- inode = file->f_inode;
+ dentry = file->f_dentry;
+ inode = dentry->d_inode;
elf_bss = 0;
if (!file || !file->f_op)
if (elf_phdata == NULL)
return -ENOMEM;
- retval = read_exec(inode, elf_ex.e_phoff, (char *) elf_phdata,
+ retval = read_exec(dentry, elf_ex.e_phoff, (char *) elf_phdata,
sizeof(struct elf_phdr) * elf_ex.e_phnum, 1);
j = 0;
*/
static int dump_write(struct file *file, const void *addr, int nr)
{
- return file->f_op->write(file->f_inode, file, addr, nr) == nr;
+ return file->f_op->write(file->f_dentry->d_inode, file, addr, nr) == nr;
}
static int dump_seek(struct file *file, off_t off)
{
if (file->f_op->llseek) {
- if (file->f_op->llseek(file->f_inode, file, off, 0) != off)
+ if (file->f_op->llseek(file->f_dentry->d_inode, file, off, 0) != off)
return 0;
} else
file->f_pos = off;
{
int has_dumped = 0;
struct file file;
+ struct dentry *dentry;
struct inode *inode;
unsigned short fs;
char corefile[6+sizeof(current->comm)];
#else
corefile[4] = '\0';
#endif
- if (open_namei(corefile,O_CREAT | 2 | O_TRUNC,0600,&inode)) {
- inode = NULL;
+ dentry = open_namei(corefile, O_CREAT | 2 | O_TRUNC, 0600);
+ if (IS_ERR(dentry)) {
+ dentry = NULL;
goto end_coredump;
}
+ inode = dentry->d_inode;
if (!S_ISREG(inode->i_mode))
goto end_coredump;
if (!inode->i_op || !inode->i_op->default_file_ops)
file.f_mode = 3;
file.f_flags = 0;
file.f_count = 1;
- file.f_inode = inode;
+ file.f_dentry = dentry;
file.f_pos = 0;
file.f_reada = 0;
file.f_op = inode->i_op->default_file_ops;
end_coredump:
set_fs(fs);
- iput(inode);
+ dput(dentry);
#ifndef CONFIG_BINFMT_ELF
MOD_DEC_USE_COUNT;
#endif
static int do_load_em86(struct linux_binprm *bprm,struct pt_regs *regs)
{
char *interp, *i_name, *i_arg;
+ struct dentry * dentry;
int retval;
struct elfhdr elf_ex;
if ((elf_ex.e_type != ET_EXEC &&
elf_ex.e_type != ET_DYN) ||
(!((elf_ex.e_machine == EM_386) || (elf_ex.e_machine == EM_486))) ||
- (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops ||
- !bprm->inode->i_op->default_file_ops->mmap)){
+ (!bprm->dentry->d_inode->i_op || !bprm->dentry->d_inode->i_op->default_file_ops ||
+ !bprm->dentry->d_inode->i_op->default_file_ops->mmap)){
return -ENOEXEC;
}
bprm->sh_bang++; /* Well, the bang-shell is implicit... */
- iput(bprm->inode);
- bprm->dont_iput = 1;
+ dput(bprm->dentry);
+ bprm->dentry = NULL;
/* Unlike in the script case, we don't have to do any hairy
* parsing to find our interpreter... it's hardcoded!
* Note that we use open_namei() as the name is now in kernel
* space, and we don't need to copy it.
*/
- retval = open_namei(interp, 0, 0, &bprm->inode);
- if (retval)
- return retval;
- bprm->dont_iput=0;
- retval=prepare_binprm(bprm);
- if(retval<0)
+ dentry = open_namei(interp, 0, 0);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
+ bprm->dentry = dentry;
+
+ retval = prepare_binprm(bprm);
+ if (retval < 0)
return retval;
- return search_binary_handler(bprm,regs);
+
+ return search_binary_handler(bprm, regs);
}
static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs)
}
bprm->filename = iname; /* for binfmt_script */
- if ((retval = open_namei(iname, 0, 0, &bprm->inode, NULL)))
+ if ((retval = open_namei(iname, 0, 0, &bprm->inode)))
goto _ret;
bprm->dont_iput = 0;
static int do_load_script(struct linux_binprm *bprm,struct pt_regs *regs)
{
char *cp, *i_name, *i_name_start, *i_arg;
+ struct dentry * dentry;
char interp[128];
int retval;
+
if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') || (bprm->sh_bang))
return -ENOEXEC;
/*
*/
bprm->sh_bang++;
- iput(bprm->inode);
- bprm->dont_iput=1;
+ dput(bprm->dentry);
+ bprm->dentry = NULL;
bprm->buf[127] = '\0';
if ((cp = strchr(bprm->buf, '\n')) == NULL)
if (!bprm->p)
return -E2BIG;
/*
- * OK, now restart the process with the interpreter's inode.
+ * OK, now restart the process with the interpreter's dentry.
*/
- retval = open_namei(interp, 0, 0, &bprm->inode);
- if (retval)
- return retval;
- bprm->dont_iput=0;
- retval=prepare_binprm(bprm);
- if(retval<0)
+ dentry = open_namei(interp, 0, 0);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
+ bprm->dentry = dentry;
+ retval = prepare_binprm(bprm);
+ if (retval < 0)
return retval;
return search_binary_handler(bprm,regs);
}
asmlinkage int sys_fsync(unsigned int fd)
{
struct file * file;
+ struct dentry * dentry;
struct inode * inode;
- int err = 0;
+ int err;
lock_kernel();
- if (fd>=NR_OPEN || !(file=current->files->fd[fd]) || !(inode=file->f_inode))
- err = -EBADF;
- else if (!file->f_op || !file->f_op->fsync)
- err = -EINVAL;
- else if (file->f_op->fsync(inode,file))
- err = -EIO;
+ err = -EBADF;
+
+ if (fd >= NR_OPEN)
+ goto out;
+
+ file = current->files->fd[fd];
+ if (!file)
+ goto out;
+
+ dentry = file->f_dentry;
+ if (!dentry)
+ goto out;
+
+ inode = dentry->d_inode;
+ if (!inode)
+ goto out;
+
+ err = -EINVAL;
+ if (!file->f_op || !file->f_op->fsync)
+ goto out;
+
+ err = file->f_op->fsync(inode,file);
+
+out:
unlock_kernel();
return err;
}
asmlinkage int sys_fdatasync(unsigned int fd)
{
struct file * file;
+ struct dentry * dentry;
struct inode * inode;
- int err = -EBADF;
+ int err;
lock_kernel();
- if (fd>=NR_OPEN || !(file=current->files->fd[fd]) || !(inode=file->f_inode))
+ err = -EBADF;
+
+ if (fd >= NR_OPEN)
+ goto out;
+
+ file = current->files->fd[fd];
+ if (!file)
+ goto out;
+
+ dentry = file->f_dentry;
+ if (!dentry)
goto out;
+
+ inode = dentry->d_inode;
+ if (!inode)
+ goto out;
+
err = -EINVAL;
if (!file->f_op || !file->f_op->fsync)
goto out;
+
/* this needs further work, at the moment it is identical to fsync() */
- if (file->f_op->fsync(inode,file))
- err = -EIO;
- else
- err = 0;
+ err = file->f_op->fsync(inode,file);
+
out:
unlock_kernel();
return err;
static struct list_head dentry_hashtable[D_HASHSIZE];
static LIST_HEAD(dentry_unused);
-void dput(struct dentry *dentry)
-{
- if (dentry) {
- dentry->d_count--;
- if (dentry->d_count < 0) {
- printk("dentry->count = %d for %s\n",
- dentry->d_count, dentry->d_name.name);
- return;
- }
- if (!dentry->d_count) {
- list_del(&dentry->d_lru);
- list_add(&dentry->d_lru, &dentry_unused);
- }
- }
-}
-
void d_free(struct dentry *dentry)
{
kfree(dentry->d_name.name);
}
/*
- * Note! This tries to free the last entry on the dentry
- * LRU list. The dentries are put on the LRU list when
- * they are free'd, but that doesn't actually mean that
- * all LRU entries have d_count == 0 - it might have been
- * re-allocated. If so we delete it from the LRU list
- * here.
+ * dput()
*
- * Rationale:
- * - keep "dget()" extremely simple
- * - if there have been a lot of lookups in the LRU list
- * we want to make freeing more unlikely anyway, and
- * keeping used dentries on the LRU list in that case
- * will make the algorithm less likely to free an entry.
+ * This is complicated by the fact that we do not want to put
+ * dentries that are no longer on any hash chain on the unused
+ * list: we'd much rather just get rid of them immediately.
+ *
+ * However, that implies that we have to traverse the dentry
+ * tree upwards to the parents which might _also_ now be
+ * scheduled for deletion (it may have been only waiting for
+ * its last child to go away).
+ *
+ * This tail recursion is done by hand as we don't want to depend
+ * on the compiler to always get this right (gcc generally doesn't).
+ * Real recursion would eat up our stack space.
*/
-static inline struct dentry * free_one_dentry(struct dentry * dentry)
-{
- struct dentry * parent;
-
- list_del(&dentry->d_hash);
- parent = dentry->d_parent;
- if (parent != dentry)
- dput(parent);
- return dentry;
-}
-
-static inline struct dentry * try_free_one_dentry(struct dentry * dentry)
+void dput(struct dentry *dentry)
{
- struct inode * inode = dentry->d_inode;
-
- if (inode) {
- if (atomic_read(&inode->i_count) != 1) {
+ if (dentry) {
+ int count;
+repeat:
+ count = dentry->d_count-1;
+ if (count < 0) {
+ printk("Negative d_count (%d) for %s/%s\n",
+ count,
+ dentry->d_parent->d_name.name,
+ dentry->d_name.name);
+ *(int *)0 = 0;
+ }
+ dentry->d_count = count;
+ if (!count) {
+ list_del(&dentry->d_lru);
+ if (list_empty(&dentry->d_hash)) {
+ struct inode *inode = dentry->d_inode;
+ struct dentry * parent;
+ if (inode) {
+ list_del(&dentry->d_alias);
+ iput(inode);
+ }
+ parent = dentry->d_parent;
+ d_free(dentry);
+ if (dentry == parent)
+ return;
+ dentry = parent;
+ goto repeat;
+ }
list_add(&dentry->d_lru, &dentry_unused);
- return NULL;
}
- list_del(&dentry->d_alias);
- iput(inode);
- dentry->d_inode = NULL;
}
- return free_one_dentry(dentry);
}
-static struct dentry * try_free_dentries(void)
+/*
+ * Shrink the dcache. This is done when we need
+ * more memory, or simply when we need to unmount
+ * something (at which point we need to unuse
+ * all dentries).
+ *
+ * "priority" is a value between 0-6, 0 means that
+ * we should work really hard on releasing stuff..
+ */
+void shrink_dcache(int priority)
{
- struct list_head * tmp = dentry_unused.next;
+ int nr = 42; /* "random" number */
- if (tmp != &dentry_unused) {
- struct dentry * dentry;
+ nr <<= 6; nr >>= priority;
+ do {
+ struct dentry *dentry;
+ struct list_head *tmp = dentry_unused.prev;
+ if (tmp == &dentry_unused)
+ break;
list_del(tmp);
+ INIT_LIST_HEAD(tmp);
dentry = list_entry(tmp, struct dentry, d_lru);
- if (dentry->d_count == 0)
- return try_free_one_dentry(dentry);
- }
- return NULL;
+ if (!dentry->d_count) {
+ struct dentry * parent;
+
+ list_del(&dentry->d_hash);
+ if (dentry->d_inode) {
+ struct inode * inode = dentry->d_inode;
+
+ list_del(&dentry->d_alias);
+ dentry->d_inode = NULL;
+ iput(inode);
+ }
+ parent = dentry->d_parent;
+ d_free(dentry);
+ dput(parent);
+ }
+ } while (--nr);
}
#define NAME_ALLOC_LEN(len) ((len+16) & ~15)
struct dentry * d_alloc(struct dentry * parent, const struct qstr *name)
{
- int len;
char * str;
struct dentry *dentry;
- dentry = try_free_dentries();
- len = NAME_ALLOC_LEN(name->len);
- if (dentry) {
- str = (char *) dentry->d_name.name;
- if (len == NAME_ALLOC_LEN(dentry->d_name.len))
- goto right_size;
- kfree(dentry->d_name.name);
- } else {
- dentry = kmalloc(sizeof(struct dentry), GFP_KERNEL);
- if (!dentry)
- return NULL;
- }
- str = kmalloc(len, GFP_KERNEL);
+ dentry = kmalloc(sizeof(struct dentry), GFP_KERNEL);
+ if (!dentry)
+ return NULL;
+
+ str = kmalloc(NAME_ALLOC_LEN(name->len), GFP_KERNEL);
if (!str) {
kfree(dentry);
return NULL;
}
-right_size:
- len = name->len;
- memcpy(str, name->name, len);
- str[len] = 0;
+
+ memcpy(str, name->name, name->len);
+ str[name->len] = 0;
dentry->d_count = 0;
dentry->d_flags = 0;
}
/*
- * Remove the inode from the dentry.. This removes
- * it from the parent hashes but otherwise leaves it
- * around - it may be a "zombie", part of a path
- * that is still in use...
+ * When a file is deleted, we have two options:
+ * - turn this dentry into a negative dentry
+ * - unhash this dentry and free it.
*
- * "The Night of the Living Dead IV - the Dentry"
+ * Usually, we want to just turn this into
+ * a negative dentry, but if anybody else is
+ * currently using the dentry or the inode
+ * we can't do that and we fall back on removing
+ * it from the hash queues and waiting for
+ * it to be deleted later when it has no users
*/
void d_delete(struct dentry * dentry)
{
- list_del(&dentry->d_hash);
/*
- * Make the hash lists point to itself.. When we
- * later dput this, we want the list_del() there
- * to not do anything strange..
+ * Are we the only user?
*/
+ if (dentry->d_count == 1) {
+ struct inode * inode = dentry->d_inode;
+
+ dentry->d_inode = NULL;
+ list_del(&dentry->d_alias);
+ iput(inode);
+ return;
+ }
+
+ /*
+ * If not, just unhash us and wait for dput()
+ * to pick up the tab..
+ */
+ list_del(&dentry->d_hash);
INIT_LIST_HEAD(&dentry->d_hash);
+
}
void d_add(struct dentry * entry, struct inode * inode)
lock_dquot(dquot);
down(&dquot->dq_mnt->mnt_sem);
if (filp->f_op->llseek) {
- if (filp->f_op->llseek(filp->f_inode, filp,
+ if (filp->f_op->llseek(filp->f_dentry->d_inode, filp,
dqoff(dquot->dq_id), 0) != dqoff(dquot->dq_id)) {
up(&dquot->dq_mnt->mnt_sem);
unlock_dquot(dquot);
fs = get_fs();
set_fs(KERNEL_DS);
- if (filp->f_op->write(filp->f_inode, filp,
+ if (filp->f_op->write(filp->f_dentry->d_inode, filp,
(char *)&dquot->dq_dqb, sizeof(struct dqblk)) == sizeof(struct dqblk))
dquot->dq_flags &= ~DQ_MOD;
lock_dquot(dquot);
down(&dquot->dq_mnt->mnt_sem);
if (filp->f_op->llseek) {
- if (filp->f_op->llseek(filp->f_inode, filp,
+ if (filp->f_op->llseek(filp->f_dentry->d_inode, filp,
dqoff(dquot->dq_id), 0) != dqoff(dquot->dq_id)) {
up(&dquot->dq_mnt->mnt_sem);
unlock_dquot(dquot);
filp->f_pos = dqoff(dquot->dq_id);
fs = get_fs();
set_fs(KERNEL_DS);
- filp->f_op->read(filp->f_inode, filp, (char *)&dquot->dq_dqb, sizeof(struct dqblk));
+ filp->f_op->read(filp->f_dentry->d_inode, filp, (char *)&dquot->dq_dqb, sizeof(struct dqblk));
up(&dquot->dq_mnt->mnt_sem);
set_fs(fs);
if (dquot->dq_bhardlimit == 0 && dquot->dq_bsoftlimit == 0 &&
int quota_on(kdev_t dev, short type, char *path)
{
- struct file *filp = (struct file *)NULL;
+ struct file *filp = NULL;
+ struct dentry *dentry;
struct vfsmount *vfsmnt;
struct inode *inode;
struct dquot *dquot;
char *tmp;
int error;
- if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL)
- return(-ENODEV);
- if (vfsmnt->mnt_quotas[type] != (struct file *)NULL)
- return(-EBUSY);
- if ((error = getname(path, &tmp)) != 0)
- return(error);
- error = open_namei(tmp, O_RDWR, 0600, &inode);
+ vfsmnt = lookup_vfsmnt(dev);
+ if (vfsmnt == NULL)
+ return -ENODEV;
+
+ if (vfsmnt->mnt_quotas[type] != NULL)
+ return -EBUSY;
+
+ tmp = getname(path);
+ error = PTR_ERR(tmp);
+ if (IS_ERR(tmp))
+ return error;
+
+ dentry = open_namei(tmp, O_RDWR, 0600);
putname(tmp);
- if (error)
- return(error);
+
+ error = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
+ return error;
+ inode = dentry->d_inode;
+
if (!S_ISREG(inode->i_mode)) {
- iput(inode);
- return(-EACCES);
+ dput(dentry);
+ return -EACCES;
}
- if ((filp = get_empty_filp()) != (struct file *)NULL) {
+
+ filp = get_empty_filp();
+ if (filp != NULL) {
filp->f_mode = (O_RDWR + 1) & O_ACCMODE;
filp->f_flags = O_RDWR;
- filp->f_inode = inode;
+ filp->f_dentry = dentry;
filp->f_pos = 0;
filp->f_reada = 0;
filp->f_op = inode->i_op->default_file_ops;
if (filp->f_op->read || filp->f_op->write) {
- if ((error = get_write_access(inode)) == 0) {
+ error = get_write_access(inode);
+ if (!error) {
if (filp->f_op && filp->f_op->open)
error = filp->f_op->open(inode, filp);
- if (error == 0) {
+ if (!error) {
vfsmnt->mnt_quotas[type] = filp;
dquot = dqget(dev, 0, type);
vfsmnt->mnt_iexp[type] = (dquot) ? dquot->dq_itime : MAX_IQ_TIME;
dqput(dquot);
vfsmnt->mnt_sb->dq_op = &dquot_operations;
add_dquot_ref(dev, type);
- return(0);
+ return 0;
}
put_write_access(inode);
}
put_filp(filp);
} else
error = -EMFILE;
- iput(inode);
- return(error);
+ dput(dentry);
+ return error;
}
/*
asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
{
int cmds = 0, type = 0, flags = 0;
- struct inode *ino;
kdev_t dev;
int ret = -EINVAL;
}
ret = -EINVAL;
- if (special == (char *)NULL && (cmds == Q_SYNC || cmds == Q_GETSTATS))
- dev = 0;
- else {
- int error = namei(special, &ino);
- if(error)
+ dev = 0;
+ if (special != NULL || (cmds != Q_SYNC && cmds != Q_GETSTATS)) {
+ mode_t mode;
+ struct dentry * dentry;
+
+ dentry = namei(special);
+ if (IS_ERR(dentry))
goto out;
- dev = ino->i_rdev;
+
+ dev = dentry->d_inode->i_rdev;
+ mode = dentry->d_inode->i_mode;
+ dput(dentry);
+
ret = -ENOTBLK;
- if (!S_ISBLK(ino->i_mode)) {
- iput(ino);
+ if (!S_ISBLK(mode))
goto out;
- }
- iput(ino);
}
ret = -EINVAL;
}
#endif /* CONFIG_MODULES */
-int open_inode(struct inode * inode, int mode)
+int open_dentry(struct dentry * dentry, int mode)
{
int fd;
+ struct inode * inode = dentry->d_inode;
if (!inode->i_op || !inode->i_op->default_file_ops)
return -EINVAL;
fd = get_unused_fd();
if (fd >= 0) {
struct file * f = get_empty_filp();
+
if (!f) {
put_unused_fd(fd);
return -ENFILE;
}
f->f_flags = mode;
f->f_mode = (mode+1) & O_ACCMODE;
- f->f_inode = inode;
+ f->f_dentry = dentry;
f->f_pos = 0;
f->f_reada = 0;
f->f_op = inode->i_op->default_file_ops;
}
}
current->files->fd[fd] = f;
- atomic_inc(&inode->i_count);
+ dget(dentry);
}
return fd;
}
goto out;
file = current->files->fd[fd];
retval = -ENOEXEC;
- if (file && file->f_inode && file->f_op && file->f_op->read) {
+ if (file && file->f_dentry && file->f_op && file->f_op->read) {
for (fmt = formats ; fmt ; fmt = fmt->next) {
int (*fn)(int) = fmt->load_shlib;
if (!fn)
mpnt->vm_flags = VM_STACK_FLAGS;
mpnt->vm_ops = NULL;
mpnt->vm_offset = 0;
- mpnt->vm_inode = NULL;
+ mpnt->vm_dentry = NULL;
mpnt->vm_pte = 0;
insert_vm_struct(current->mm, mpnt);
current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
* that aren't on a block boundary, and for files on filesystems
* without bmap support.
*/
-int read_exec(struct inode *inode, unsigned long offset,
+int read_exec(struct dentry *dentry, unsigned long offset,
char * addr, unsigned long count, int to_kmem)
{
struct file file;
+ struct inode * inode = dentry->d_inode;
int result = -ENOEXEC;
if (!inode->i_op || !inode->i_op->default_file_ops)
file.f_mode = 1;
file.f_flags = 0;
file.f_count = 1;
- file.f_inode = inode;
+ file.f_dentry = dentry;
file.f_pos = 0;
file.f_reada = 0;
file.f_op = inode->i_op->default_file_ops;
flush_thread();
if (bprm->e_uid != current->euid || bprm->e_gid != current->egid ||
- permission(bprm->inode,MAY_READ))
+ permission(bprm->dentry->d_inode,MAY_READ))
current->dumpable = 0;
flush_old_signals(current->sig);
{
int mode;
int retval,id_change;
+ struct inode * inode = bprm->dentry->d_inode;
- mode = bprm->inode->i_mode;
+ mode = inode->i_mode;
if (!S_ISREG(mode)) /* must be regular file */
return -EACCES;
if (!(mode & 0111)) /* with at least _one_ execute bit set */
return -EACCES;
- if (IS_NOEXEC(bprm->inode)) /* FS mustn't be mounted noexec */
+ if (IS_NOEXEC(inode)) /* FS mustn't be mounted noexec */
return -EACCES;
- if (!bprm->inode->i_sb)
+ if (!inode->i_sb)
return -EACCES;
- if ((retval = permission(bprm->inode, MAY_EXEC)) != 0)
+ if ((retval = permission(inode, MAY_EXEC)) != 0)
return retval;
/* better not execute files which are being written to */
- if (bprm->inode->i_writecount > 0)
+ if (inode->i_writecount > 0)
return -ETXTBSY;
bprm->e_uid = current->euid;
/* Set-uid? */
if (mode & S_ISUID) {
- bprm->e_uid = bprm->inode->i_uid;
+ bprm->e_uid = inode->i_uid;
if (bprm->e_uid != current->euid)
id_change = 1;
}
* executable.
*/
if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
- bprm->e_gid = bprm->inode->i_gid;
+ bprm->e_gid = inode->i_gid;
if (!in_group_p(bprm->e_gid))
id_change = 1;
}
/* We can't suid-execute if we're sharing parts of the executable */
/* or if we're being traced (or if suid execs are not allowed) */
/* (current->mm->count > 1 is ok, as we'll get a new mm anyway) */
- if (IS_NOSUID(bprm->inode)
+ if (IS_NOSUID(inode)
|| (current->flags & PF_PTRACED)
|| (current->fs->count > 1)
|| (atomic_read(¤t->sig->count) > 1)
}
memset(bprm->buf,0,sizeof(bprm->buf));
- return read_exec(bprm->inode,0,bprm->buf,128,1);
+ return read_exec(bprm->dentry,0,bprm->buf,128,1);
}
void remove_arg_zero(struct linux_binprm *bprm)
(eh->fh.f_flags & 0x3000) == 0x3000)
{
char * dynloader[] = { "/sbin/loader" };
- iput(bprm->inode);
- bprm->dont_iput = 1;
+ struct dentry * dentry;
+
+ dput(bprm->dentry);
+ bprm->dentry = NULL;
remove_arg_zero(bprm);
bprm->p = copy_strings(1, dynloader, bprm->page, bprm->p, 2);
bprm->argc++;
bprm->loader = bprm->p;
- retval = open_namei(dynloader[0], 0, 0, &bprm->inode);
- if (retval)
+ dentry = open_namei(dynloader[0], 0, 0);
+ retval = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
return retval;
- bprm->dont_iput = 0;
+ bprm->dentry = dentry;
retval = prepare_binprm(bprm);
if (retval<0)
return retval;
continue;
retval = fn(bprm, regs);
if (retval >= 0) {
- if(!bprm->dont_iput)
- iput(bprm->inode);
- bprm->dont_iput=1;
+ if (bprm->dentry)
+ dput(bprm->dentry);
+ bprm->dentry = NULL;
current->did_exec = 1;
return retval;
}
if (retval != -ENOEXEC)
break;
- if (bprm->dont_iput) /* We don't have the inode anymore*/
+ if (!bprm->dentry) /* We don't have the dentry anymore */
return retval;
}
if (retval != -ENOEXEC) {
int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs)
{
struct linux_binprm bprm;
+ struct dentry * dentry;
int retval;
int i;
bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
bprm.page[i] = 0;
- retval = open_namei(filename, 0, 0, &bprm.inode);
- if (retval)
+
+ dentry = open_namei(filename, 0, 0);
+ retval = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
return retval;
+
+ bprm.dentry = dentry;
bprm.filename = filename;
bprm.sh_bang = 0;
bprm.java = 0;
bprm.loader = 0;
bprm.exec = 0;
- bprm.dont_iput = 0;
- if ((bprm.argc = count(argv)) < 0)
+ if ((bprm.argc = count(argv)) < 0) {
+ dput(dentry);
return bprm.argc;
- if ((bprm.envc = count(envp)) < 0)
+ }
+
+ if ((bprm.envc = count(envp)) < 0) {
+ dput(dentry);
return bprm.envc;
+ }
retval = prepare_binprm(&bprm);
- if(retval>=0) {
+ if (retval >= 0) {
bprm.p = copy_strings(1, &bprm.filename, bprm.page, bprm.p, 2);
bprm.exec = bprm.p;
bprm.p = copy_strings(bprm.envc,envp,bprm.page,bprm.p,0);
retval = -E2BIG;
}
- if(retval>=0)
+ if (retval >= 0)
retval = search_binary_handler(&bprm,regs);
- if(retval>=0)
+ if (retval >= 0)
/* execve success */
return retval;
/* Something went wrong, return the inode and free the argument pages*/
- if(!bprm.dont_iput)
- iput(bprm.inode);
+ if (bprm.dentry)
+ dput(bprm.dentry);
+
for (i=0 ; i<MAX_ARG_PAGES ; i++)
free_page(bprm.page[i]);
- return(retval);
+
+ return retval;
}
#endif
-void ext2_statfs (struct super_block * sb, struct statfs * buf, int bufsiz)
+int ext2_statfs (struct super_block * sb, struct statfs * buf, int bufsiz)
{
unsigned long overhead;
unsigned long overhead_per_group;
tmp.f_files = le32_to_cpu(sb->u.ext2_sb.s_es->s_inodes_count);
tmp.f_ffree = ext2_count_free_inodes (sb);
tmp.f_namelen = EXT2_NAME_LEN;
- copy_to_user(buf, &tmp, bufsiz);
+ return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
}
return ret;
}
+#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC)
+
+static int setfl(struct file * filp, unsigned long arg)
+{
+ struct inode * inode = filp->f_dentry->d_inode;
+
+ /*
+ * In the case of an append-only file, O_APPEND
+ * cannot be cleared
+ */
+ if (!(arg & O_APPEND) && IS_APPEND(inode))
+ return -EPERM;
+
+ /* Did FASYNC state change? */
+ if ((arg ^ filp->f_flags) & FASYNC) {
+ if (filp->f_op->fasync)
+ filp->f_op->fasync(inode, filp, (arg & FASYNC) != 0);
+ }
+
+ /* required for strict SunOS emulation */
+ if (O_NONBLOCK != O_NDELAY)
+ if (arg & O_NDELAY)
+ arg |= O_NONBLOCK;
+
+ filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK);
+ return 0;
+}
+
asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct file * filp;
err = filp->f_flags;
break;
case F_SETFL:
- /*
- * In the case of an append-only file, O_APPEND
- * cannot be cleared
- */
- err = -EPERM;
- if (IS_APPEND(filp->f_inode) && !(arg & O_APPEND))
- break;
- err = 0;
- if ((arg & FASYNC) && !(filp->f_flags & FASYNC) &&
- filp->f_op->fasync)
- filp->f_op->fasync(filp->f_inode, filp, 1);
- if (!(arg & FASYNC) && (filp->f_flags & FASYNC) &&
- filp->f_op->fasync)
- filp->f_op->fasync(filp->f_inode, filp, 0);
- /* required for strict SunOS emulation */
- if (O_NONBLOCK != O_NDELAY)
- if (arg & O_NDELAY)
- arg |= O_NONBLOCK;
- filp->f_flags &= ~(O_APPEND | O_NONBLOCK |
- O_NDELAY | FASYNC);
- filp->f_flags |= arg & (O_APPEND | O_NONBLOCK |
- O_NDELAY | FASYNC);
+ err = setfl(filp, arg);
break;
case F_GETLK:
err = fcntl_getlk(fd, (struct flock *) arg);
fasync_ok:
err = 0;
filp->f_owner = arg;
- if (S_ISSOCK (filp->f_inode->i_mode))
+ if (S_ISSOCK (filp->f_dentry->d_inode->i_mode))
err = sock_fcntl (filp, F_SETOWN, arg);
break;
default:
/* sockets need a few special fcntls. */
- if (S_ISSOCK (filp->f_inode->i_mode))
+ if (S_ISSOCK (filp->f_dentry->d_inode->i_mode))
err = sock_fcntl (filp, cmd, arg);
else
err = -EINVAL;
struct file *filp;
for (filp = inuse_filps; filp; filp = filp->f_next) {
- if (!filp->f_inode || filp->f_inode->i_dev != dev)
+ struct inode * inode;
+ if (!filp->f_dentry)
continue;
- if (filp->f_mode & FMODE_WRITE && filp->f_inode->i_sb->dq_op) {
- filp->f_inode->i_sb->dq_op->initialize(filp->f_inode, type);
- filp->f_inode->i_flags |= S_WRITE;
+ inode = filp->f_dentry->d_inode;
+ if (!inode || inode->i_dev != dev)
+ continue;
+ if (filp->f_mode & FMODE_WRITE && inode->i_sb->dq_op) {
+ inode->i_sb->dq_op->initialize(inode, type);
+ inode->i_flags |= S_WRITE;
}
}
}
struct file *filp;
for (filp = inuse_filps; filp; filp = filp->f_next) {
- if (!filp->f_inode || filp->f_inode->i_dev != dev)
+ struct inode * inode;
+ if (!filp->f_dentry)
+ continue;
+ inode = filp->f_dentry->d_inode;
+ if (!inode || inode->i_dev != dev)
continue;
- if (IS_WRITABLE(filp->f_inode)) {
- filp->f_inode->i_dquot[type] = NODQUOT;
- filp->f_inode->i_flags &= ~S_WRITE;
+ if (IS_WRITABLE(inode)) {
+ inode->i_dquot[type] = NODQUOT;
+ inode->i_flags &= ~S_WRITE;
}
}
}
{
int error;
int block;
+ struct inode * inode = filp->f_dentry->d_inode;
switch (cmd) {
case FIBMAP:
- if (filp->f_inode->i_op == NULL)
+ if (inode->i_op == NULL)
return -EBADF;
- if (filp->f_inode->i_op->bmap == NULL)
+ if (inode->i_op->bmap == NULL)
return -EINVAL;
if ((error = get_user(block, (int *) arg)) != 0)
return error;
- block = filp->f_inode->i_op->bmap(filp->f_inode,block);
+ block = inode->i_op->bmap(inode,block);
return put_user(block, (int *) arg);
case FIGETBSZ:
- if (filp->f_inode->i_sb == NULL)
+ if (inode->i_sb == NULL)
return -EBADF;
- return put_user(filp->f_inode->i_sb->s_blocksize,
- (int *) arg);
+ return put_user(inode->i_sb->s_blocksize, (int *) arg);
case FIONREAD:
- return put_user(filp->f_inode->i_size - filp->f_pos,
- (int *) arg);
+ return put_user(inode->i_size - filp->f_pos, (int *) arg);
}
if (filp->f_op && filp->f_op->ioctl)
- return filp->f_op->ioctl(filp->f_inode, filp, cmd, arg);
+ return filp->f_op->ioctl(inode, filp, cmd, arg);
return -ENOTTY;
}
break;
default:
- if (filp->f_inode && S_ISREG(filp->f_inode->i_mode))
+ if (filp->f_dentry && filp->f_dentry->d_inode && S_ISREG(filp->f_dentry->d_inode->i_mode))
error = file_ioctl(filp, cmd, arg);
else if (filp->f_op && filp->f_op->ioctl)
- error = filp->f_op->ioctl(filp->f_inode, filp, cmd, arg);
+ error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
else
error = -ENOTTY;
}
return NULL;
}
-void isofs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz)
+int isofs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz)
{
struct statfs tmp;
tmp.f_files = sb->u.isofs_sb.s_ninodes;
tmp.f_ffree = 0;
tmp.f_namelen = NAME_MAX;
- copy_to_user(buf, &tmp, bufsiz);
+ return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
}
int isofs_bmap(struct inode * inode,int block)
/* First, reclaim all locks that have been granted previously. */
do {
for (fl = file_lock_table; fl; fl = fl->fl_next) {
- inode = fl->fl_file->f_inode;
+ inode = fl->fl_file->f_dentry->d_inode;
if (inode->i_sb->s_magic == NFS_SUPER_MAGIC
&& nlm_cmp_addr(NFS_ADDR(inode), &host->h_addr)
&& fl->fl_u.nfs_fl.state != host->h_state
memset(argp, 0, sizeof(*argp));
argp->cookie = nlm_cookie++;
argp->state = nsm_local_state;
- lock->fh = *NFS_FH(fl->fl_file->f_inode);
+ lock->fh = *NFS_FH(fl->fl_file->f_dentry->d_inode);
lock->caller = system_utsname.nodename;
lock->oh.data = req->a_owner;
lock->oh.len = sprintf(req->a_owner, "%d@%s",
int error;
dprintk("lockd: nlmsvc_lock(%04x/%ld, ty=%d, pi=%d, %ld-%ld, bl=%d)\n",
- file->f_file.f_inode->i_dev,
- file->f_file.f_inode->i_ino,
+ file->f_file.f_dentry->d_inode->i_dev,
+ file->f_file.f_dentry->d_inode->i_ino,
lock->fl.fl_type, lock->fl.fl_pid,
lock->fl.fl_start,
lock->fl.fl_end,
struct file_lock *fl;
dprintk("lockd: nlmsvc_testlock(%04x/%ld, ty=%d, %ld-%ld)\n",
- file->f_file.f_inode->i_dev,
- file->f_file.f_inode->i_ino,
+ file->f_file.f_dentry->d_inode->i_dev,
+ file->f_file.f_dentry->d_inode->i_ino,
lock->fl.fl_type,
lock->fl.fl_start,
lock->fl.fl_end);
int error;
dprintk("lockd: nlmsvc_unlock(%04x/%ld, pi=%d, %ld-%ld)\n",
- file->f_file.f_inode->i_dev,
- file->f_file.f_inode->i_ino,
+ file->f_file.f_dentry->d_inode->i_dev,
+ file->f_file.f_dentry->d_inode->i_ino,
lock->fl.fl_pid,
lock->fl.fl_start,
lock->fl.fl_end);
struct nlm_block *block;
dprintk("lockd: nlmsvc_cancel(%04x/%ld, pi=%d, %ld-%ld)\n",
- file->f_file.f_inode->i_dev,
- file->f_file.f_inode->i_ino,
+ file->f_file.f_dentry->d_inode->i_dev,
+ file->f_file.f_dentry->d_inode->i_ino,
lock->fl.fl_pid,
lock->fl.fl_start,
lock->fl.fl_end);
{
struct flock flock;
struct file *filp;
+ struct dentry *dentry;
+ struct inode *inode;
struct file_lock *fl,file_lock;
int error;
if ((fd >= NR_OPEN) || !(filp = current->files->fd[fd]))
- return (-EBADF);
+ return -EBADF;
if (copy_from_user(&flock, l, sizeof(flock)))
- return (-EFAULT);
+ return -EFAULT;
if ((flock.l_type != F_RDLCK) && (flock.l_type != F_WRLCK))
- return (-EINVAL);
+ return -EINVAL;
- if (!filp->f_inode || !posix_make_lock(filp, &file_lock, &flock))
- return (-EINVAL);
+ dentry = filp->f_dentry;
+ if (!dentry)
+ return -EINVAL;
+
+ inode = dentry->d_inode;
+ if (!inode)
+ return -EINVAL;
+
+ if (!posix_make_lock(filp, &file_lock, &flock))
+ return -EINVAL;
if (filp->f_op->lock) {
- error = filp->f_op->lock(filp->f_inode, filp,
- F_GETLK, &file_lock);
+ error = filp->f_op->lock(inode, filp, F_GETLK, &file_lock);
if (error < 0)
- return (error);
+ return error;
fl = &file_lock;
} else {
fl = posix_test_lock(filp, &file_lock);
struct file *filp;
struct file_lock file_lock;
struct flock flock;
+ struct dentry * dentry;
struct inode *inode;
int error;
*/
if ((fd >= NR_OPEN) || !(filp = current->files->fd[fd]))
- return (-EBADF);
-
- if (!(inode = filp->f_inode))
- return (-EINVAL);
+ return -EBADF;
+
+ if (!(dentry = filp->f_dentry))
+ return -EINVAL;
+
+ if (!(inode = dentry->d_inode))
+ return -EINVAL;
/* Don't allow mandatory locks on files that may be memory mapped
* and shared.
}
if (filp->f_op->lock != NULL) {
- error = filp->f_op->lock(filp->f_inode, filp, cmd, &file_lock);
+ error = filp->f_op->lock(inode, filp, cmd, &file_lock);
if (error < 0)
return (error);
}
{
struct file_lock file_lock, *fl;
struct file_lock **before;
+ struct inode * inode;
/* For POSIX locks we free all locks on this file for the given task.
* For FLOCK we only free locks on this *open* file if it is the last
* close on that file.
*/
- before = &filp->f_inode->i_flock;
+ inode = filp->f_dentry->d_inode;
+ before = &inode->i_flock;
while ((fl = *before) != NULL) {
if (((fl->fl_flags & FL_POSIX) && (fl->fl_owner == task)) ||
locks_delete_lock(before, 0);
if (filp->f_op->lock) {
file_lock.fl_type = F_UNLCK;
- filp->f_op->lock(filp->f_inode, filp,
- F_SETLK, &file_lock);
+ filp->f_op->lock(inode, filp, F_SETLK, &file_lock);
/* List may have changed: */
- before = &filp->f_inode->i_flock;
+ before = &inode->i_flock;
}
} else {
before = &fl->fl_next;
{
struct file_lock *cfl;
- for (cfl = filp->f_inode->i_flock; cfl; cfl = cfl->fl_next) {
+ for (cfl = filp->f_dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
if (!(cfl->fl_flags & FL_POSIX))
continue;
if (posix_locks_conflict(cfl, fl))
start = filp->f_pos;
break;
case 2: /*SEEK_END*/
- start = filp->f_inode->i_size;
+ start = filp->f_dentry->d_inode->i_size;
break;
default:
return (0);
{
memset(fl, 0, sizeof(*fl));
- if (!filp->f_inode) /* just in case */
+ if (!filp->f_dentry) /* just in case */
return (0);
switch (cmd & ~LOCK_NB) {
struct file_lock *fl;
struct file_lock *new_fl;
struct file_lock **before;
+ struct inode * inode = filp->f_dentry->d_inode;
int change = 0;
- before = &filp->f_inode->i_flock;
+ before = &inode->i_flock;
while (((fl = *before) != NULL) && (fl->fl_flags & FL_FLOCK)) {
if (caller->fl_file == fl->fl_file) {
if (caller->fl_type == fl->fl_type)
if ((new_fl = locks_alloc_lock(caller)) == NULL)
return (-ENOLCK);
repeat:
- for (fl = filp->f_inode->i_flock; (fl != NULL) && (fl->fl_flags & FL_FLOCK);
+ for (fl = inode->i_flock; (fl != NULL) && (fl->fl_flags & FL_FLOCK);
fl = fl->fl_next) {
if (!flock_locks_conflict(new_fl, fl))
continue;
}
goto repeat;
}
- locks_insert_lock(&filp->f_inode->i_flock, new_fl);
+ locks_insert_lock(&inode->i_flock, new_fl);
return (0);
}
struct file_lock *left = NULL;
struct file_lock *right = NULL;
struct file_lock **before;
+ struct inode * inode = filp->f_dentry->d_inode;
int added = 0;
if (caller->fl_type != F_UNLCK) {
repeat:
- for (fl = filp->f_inode->i_flock; fl != NULL; fl = fl->fl_next) {
+ for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
if (!(fl->fl_flags & FL_POSIX))
continue;
if (!posix_locks_conflict(caller, fl))
/* Find the first old lock with the same owner as the new lock.
*/
- before = &filp->f_inode->i_flock;
+ before = &inode->i_flock;
/* First skip locks owned by other processes.
*/
char *p = temp;
struct inode *inode;
- inode = fl->fl_file->f_inode;
+ inode = fl->fl_file->f_dentry->d_inode;
p += sprintf(p, "%d:%s ", id, pfx);
if (fl->fl_flags & FL_POSIX) {
return retval;
}
-int getname(const char * filename, char **result)
+char * getname(const char * filename)
{
- char *tmp;
- int retval;
+ char *tmp, *result;
+ result = ERR_PTR(-ENOMEM);
tmp = get_page();
- if (!tmp)
- return -ENOMEM;
- retval = do_getname(filename, tmp);
- if (retval < 0)
- putname(tmp);
- else
- *result = tmp;
- return retval;
+ if (tmp) {
+ int retval = do_getname(filename, tmp);
+
+ result = tmp;
+ if (retval < 0) {
+ putname(tmp);
+ result = ERR_PTR(retval);
+ }
+ }
+ return result;
}
/*
result = d_lookup(parent, name);
if (result) {
d_free(new);
+ iput(inode);
} else {
d_add(new, inode);
result = new;
*/
if (parent->d_count <= 1) {
printk("lookup of %s success in %s, but parent count is %d\n",
- dentry->d_name, parent->d_name, parent->d_count);
+ dentry->d_name.name, parent->d_name.name, parent->d_count);
}
}
return dentry;
* namei exists in two versions: namei/lnamei. The only difference is
* that namei follows links, while lnamei does not.
*/
-int __namei(const char *pathname, struct inode **res_inode, int follow_link)
+struct dentry * __namei(const char *pathname, int follow_link)
{
- int error;
- char * name;
-
- error = getname(pathname, &name);
- if (!error) {
- struct dentry * dentry;
+ char *name;
+ struct dentry *dentry;
+ name = getname(pathname);
+ dentry = (struct dentry *) name;
+ if (!IS_ERR(name)) {
dentry = lookup_dentry(name, NULL, follow_link);
putname(name);
- error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
- error = -ENOENT;
- if (dentry) {
- struct inode *inode = dentry->d_inode;
- if (inode) {
- atomic_inc(&inode->i_count);
- *res_inode = inode;
- error = 0;
- }
+ if (!dentry->d_inode) {
dput(dentry);
+ dentry = ERR_PTR(-ENOENT);
}
}
}
- return error;
+ return dentry;
}
static inline struct inode *get_parent(struct dentry *dentry)
* which is a lot more logical, and also allows the "no perm" needed
* for symlinks (where the permissions are checked later).
*/
-int open_namei(const char * pathname, int flag, int mode, struct inode ** res_inode)
+struct dentry * open_namei(const char * pathname, int flag, int mode)
{
- int error;
- int acc_mode;
+ int acc_mode, error;
struct inode *inode;
struct dentry *dentry;
dentry = lookup_dentry(pathname, NULL, 1);
if (IS_ERR(dentry))
- return PTR_ERR(dentry);
+ return dentry;
acc_mode = ACC_MODE(flag);
if (flag & O_CREAT) {
if (inode->i_sb && inode->i_sb->dq_op)
inode->i_sb->dq_op->initialize(inode, -1);
- *res_inode = inode;
- atomic_inc(&inode->i_count);
- error = 0;
+ return dentry;
exit:
dput(dentry);
- return error;
+ return ERR_PTR(error);
}
-int do_mknod(const char * filename, int mode, dev_t dev)
+struct dentry * do_mknod(const char * filename, int mode, dev_t dev)
{
int error;
struct inode *dir;
- struct dentry *dentry;
+ struct dentry *dentry, *retval;
mode &= ~current->fs->umask;
dentry = lookup_dentry(filename, NULL, 1);
-
- error = PTR_ERR(dentry);
if (IS_ERR(dentry))
- goto exit;
+ return dentry;
dir = lock_parent(dentry);
- error = -EEXIST;
+ retval = ERR_PTR(-EEXIST);
if (dentry->d_inode)
goto exit_lock;
- error = -EROFS;
+ retval = ERR_PTR(-EROFS);
if (IS_RDONLY(dir))
goto exit_lock;
error = permission(dir,MAY_WRITE | MAY_EXEC);
+ retval = ERR_PTR(error);
if (error)
goto exit_lock;
- error = -EPERM;
+ retval = ERR_PTR(-EPERM);
if (!dir->i_op || !dir->i_op->mknod)
goto exit_lock;
if (dir->i_sb && dir->i_sb->dq_op)
dir->i_sb->dq_op->initialize(dir, -1);
error = dir->i_op->mknod(dir, dentry, mode, dev);
+ retval = ERR_PTR(error);
+ if (!error)
+ retval = dget(dentry);
exit_lock:
up(&dir->i_sem);
iput(dir);
dput(dentry);
-exit:
- return error;
+ return retval;
}
asmlinkage int sys_mknod(const char * filename, int mode, dev_t dev)
default:
goto out;
}
- error = getname(filename,&tmp);
- if (!error) {
- error = do_mknod(tmp,mode,dev);
+ tmp = getname(filename);
+ error = PTR_ERR(tmp);
+ if (!IS_ERR(tmp)) {
+ struct dentry * dentry = do_mknod(tmp,mode,dev);
putname(tmp);
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ dput(dentry);
+ error = 0;
+ }
}
out:
unlock_kernel();
char * tmp;
lock_kernel();
- error = getname(pathname,&tmp);
- if (!error) {
+ tmp = getname(pathname);
+ error = PTR_ERR(tmp);
+ if (!IS_ERR(tmp)) {
error = do_mkdir(tmp,mode);
putname(tmp);
}
char * tmp;
lock_kernel();
- error = getname(pathname,&tmp);
- if (!error) {
+ tmp = getname(pathname);
+ error = PTR_ERR(tmp);
+ if (!IS_ERR(tmp)) {
error = do_rmdir(tmp);
putname(tmp);
}
char * tmp;
lock_kernel();
- error = getname(pathname,&tmp);
- if (!error) {
+ tmp = getname(pathname);
+ error = PTR_ERR(tmp);
+ if (!IS_ERR(tmp)) {
error = do_unlink(tmp);
putname(tmp);
}
asmlinkage int sys_symlink(const char * oldname, const char * newname)
{
int error;
- char * from, * to;
+ char * from;
lock_kernel();
- error = getname(oldname,&from);
- if (!error) {
- error = getname(newname,&to);
- if (!error) {
+ from = getname(oldname);
+ error = PTR_ERR(from);
+ if (!IS_ERR(from)) {
+ char * to;
+ to = getname(newname);
+ error = PTR_ERR(to);
+ if (!IS_ERR(to)) {
error = do_symlink(from,to);
putname(to);
}
asmlinkage int sys_link(const char * oldname, const char * newname)
{
int error;
- char * from, * to;
+ char * from;
lock_kernel();
- error = getname(oldname,&from);
- if (!error) {
- error = getname(newname,&to);
- if (!error) {
+ from = getname(oldname);
+ error = PTR_ERR(from);
+ if (!IS_ERR(from)) {
+ char * to;
+ to = getname(newname);
+ error = PTR_ERR(to);
+ if (!IS_ERR(to)) {
error = do_link(from,to);
putname(to);
}
asmlinkage int sys_rename(const char * oldname, const char * newname)
{
int error;
- char * from, * to;
+ char * from;
lock_kernel();
- error = getname(oldname,&from);
- if (!error) {
- error = getname(newname,&to);
- if (!error) {
+ from = getname(oldname);
+ error = PTR_ERR(from);
+ if (!IS_ERR(from)) {
+ char * to;
+ to = getname(newname);
+ error = PTR_ERR(to);
+ if (!IS_ERR(to)) {
error = do_rename(from,to);
putname(to);
}
int status;
dprintk("NFS: nfs_lock(f=%4x/%ld, t=%x, fl=%x, r=%ld:%ld)\n",
- filp->f_inode->i_dev, filp->f_inode->i_ino,
+ filp->f_dentry->d_inode->i_dev, filp->f_dentry->d_inode->i_ino,
fl->fl_type, fl->fl_flags,
fl->fl_start, fl->fl_end);
- if (!(inode = filp->f_inode))
+ if (!(inode = filp->f_dentry->d_inode))
return -EINVAL;
/* No mandatory locks over NFS */
static void nfs_put_inode(struct inode *);
static void nfs_put_super(struct super_block *);
static void nfs_read_inode(struct inode *);
-static void nfs_statfs(struct super_block *, struct statfs *, int bufsiz);
+static int nfs_statfs(struct super_block *, struct statfs *, int bufsiz);
static struct super_operations nfs_sops = {
nfs_read_inode, /* read inode */
return NULL;
}
-static void
+static int
nfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
{
int error;
tmp.f_files = 0;
tmp.f_ffree = 0;
tmp.f_namelen = NAME_MAX;
- copy_to_user(buf, &tmp, bufsiz);
+ return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
}
/*
asmlinkage int sys_statfs(const char * path, struct statfs * buf)
{
- struct inode * inode;
+ struct dentry * dentry;
int error;
lock_kernel();
- error = verify_area(VERIFY_WRITE, buf, sizeof(struct statfs));
- if (error)
- goto out;
- error = namei(path, &inode);
- if (error)
- goto out;
- error = -ENOSYS;
- if (!inode->i_sb->s_op->statfs) {
- iput(inode);
- goto out;
+ dentry = namei(path);
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ struct inode * inode = dentry->d_inode;
+
+ error = -ENOSYS;
+ if (inode->i_sb->s_op->statfs)
+ error = inode->i_sb->s_op->statfs(inode->i_sb, buf, sizeof(struct statfs));
+
+ dput(dentry);
}
- inode->i_sb->s_op->statfs(inode->i_sb, buf, sizeof(struct statfs));
- iput(inode);
- error = 0;
-out:
unlock_kernel();
return error;
}
asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf)
{
struct inode * inode;
+ struct dentry * dentry;
struct file * file;
int error;
goto out;
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
error = -EBADF;
- else if (!(inode = file->f_inode))
+ else if (!(dentry = file->f_dentry))
+ error = -ENOENT;
+ else if (!(inode = dentry->d_inode))
error = -ENOENT;
else if (!inode->i_sb)
error = -ENODEV;
asmlinkage int sys_truncate(const char * path, unsigned long length)
{
+ struct dentry * dentry;
struct inode * inode;
int error;
lock_kernel();
- error = namei(path, &inode);
- if (error)
+ dentry = namei(path);
+
+ error = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
goto out;
+ inode = dentry->d_inode;
error = -EACCES;
if (S_ISDIR(inode->i_mode))
- goto iput_and_out;
+ goto dput_and_out;
error = permission(inode,MAY_WRITE);
if (error)
- goto iput_and_out;
+ goto dput_and_out;
error = -EROFS;
if (IS_RDONLY(inode))
- goto iput_and_out;
+ goto dput_and_out;
error = -EPERM;
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
- goto iput_and_out;
+ goto dput_and_out;
error = get_write_access(inode);
if (error)
- goto iput_and_out;
+ goto dput_and_out;
error = locks_verify_area(FLOCK_VERIFY_WRITE, inode, NULL,
length < inode->i_size ? length : inode->i_size,
error = do_truncate(inode, length);
}
put_write_access(inode);
-iput_and_out:
- iput(inode);
+dput_and_out:
+ dput(dentry);
out:
unlock_kernel();
return error;
asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length)
{
struct inode * inode;
+ struct dentry *dentry;
struct file * file;
int error;
lock_kernel();
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
error = -EBADF;
- else if (!(inode = file->f_inode))
+ else if (!(dentry = file->f_dentry))
+ error = -ENOENT;
+ else if (!(inode = dentry->d_inode))
error = -ENOENT;
else if (S_ISDIR(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
error = -EACCES;
asmlinkage int sys_utime(char * filename, struct utimbuf * times)
{
int error;
+ struct dentry * dentry;
struct inode * inode;
struct iattr newattrs;
lock_kernel();
- /* Hmm, should I always follow symlinks or not ? */
- error = namei(filename, &inode);
- if (error)
+ dentry = namei(filename);
+
+ error = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
goto out;
+ inode = dentry->d_inode;
+
error = -EROFS;
if (IS_RDONLY(inode))
- goto iput_and_out;
+ goto dput_and_out;
/* Don't worry, the checks are done in inode_change_ok() */
newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
if (!error)
error = get_user(newattrs.ia_mtime, ×->modtime);
if (error)
- goto iput_and_out;
+ goto dput_and_out;
newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
} else {
if (current->fsuid != inode->i_uid &&
(error = permission(inode,MAY_WRITE)) != 0)
- goto iput_and_out;
+ goto dput_and_out;
}
error = notify_change(inode, &newattrs);
-iput_and_out:
- iput(inode);
+dput_and_out:
+ dput(dentry);
out:
unlock_kernel();
return error;
asmlinkage int sys_utimes(char * filename, struct timeval * utimes)
{
int error;
+ struct dentry * dentry;
struct inode * inode;
struct iattr newattrs;
lock_kernel();
- error = namei(filename, &inode);
- if (error)
+ dentry = namei(filename);
+
+ error = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
goto out;
+ inode = dentry->d_inode;
+
error = -EROFS;
if (IS_RDONLY(inode))
- goto iput_and_out;
+ goto dput_and_out;
+
/* Don't worry, the checks are done in inode_change_ok() */
newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
if (utimes) {
struct timeval times[2];
error = -EFAULT;
if (copy_from_user(×, utimes, sizeof(times)))
- goto iput_and_out;
+ goto dput_and_out;
newattrs.ia_atime = times[0].tv_sec;
newattrs.ia_mtime = times[1].tv_sec;
newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
} else {
if ((error = permission(inode,MAY_WRITE)) != 0)
- goto iput_and_out;
+ goto dput_and_out;
}
error = notify_change(inode, &newattrs);
-iput_and_out:
- iput(inode);
+dput_and_out:
+ dput(dentry);
out:
unlock_kernel();
return error;
*/
asmlinkage int sys_access(const char * filename, int mode)
{
- struct inode * inode;
+ struct dentry * dentry;
int old_fsuid, old_fsgid;
int res = -EINVAL;
old_fsgid = current->fsgid;
current->fsuid = current->uid;
current->fsgid = current->gid;
- res = namei(filename, &inode);
- if (!res) {
- res = permission(inode, mode);
- iput(inode);
+
+ dentry = namei(filename);
+ res = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ res = permission(dentry->d_inode, mode);
+ dput(dentry);
}
+
current->fsuid = old_fsuid;
current->fsgid = old_fsgid;
out:
asmlinkage int sys_fchdir(unsigned int fd)
{
struct file *file;
+ struct dentry *dentry;
struct inode *inode;
int error;
goto out;
error = -ENOENT;
- if (!(inode = file->f_inode))
+ if (!(dentry = file->f_dentry))
+ goto out;
+ if (!(inode = dentry->d_inode))
goto out;
error = -ENOTDIR;
goto out;
{
- struct dentry *dentry, *tmp;
+ struct dentry *tmp;
- dentry = dget(i_dentry(inode));
tmp = current->fs->pwd;
- current->fs->pwd = dentry;
+ current->fs->pwd = dget(dentry);
dput(tmp);
}
out:
asmlinkage int sys_fchmod(unsigned int fd, mode_t mode)
{
struct inode * inode;
+ struct dentry * dentry;
struct file * file;
struct iattr newattrs;
int err = -EBADF;
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
goto out;
err = -ENOENT;
- if (!(inode = file->f_inode))
+ if (!(dentry = file->f_dentry))
+ goto out;
+ if (!(inode = dentry->d_inode))
goto out;
err = -EROFS;
if (IS_RDONLY(inode))
asmlinkage int sys_chmod(const char * filename, mode_t mode)
{
+ struct dentry * dentry;
struct inode * inode;
int error;
struct iattr newattrs;
lock_kernel();
- /* I'm not sure whether to use NAM_FOLLOW_TRAILSLASH instead,
- * because permissions on symlinks now can never be changed,
- * but on the other hand they are never needed.
- */
- error = namei(filename, &inode);
- if (error)
+ dentry = namei(filename);
+
+ error = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
goto out;
+ inode = dentry->d_inode;
+
error = -EROFS;
if (IS_RDONLY(inode))
- goto iput_and_out;
+ goto dput_and_out;
+
error = -EPERM;
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
- goto iput_and_out;
+ goto dput_and_out;
+
if (mode == (mode_t) -1)
mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
error = notify_change(inode, &newattrs);
-iput_and_out:
- iput(inode);
+
+dput_and_out:
+ dput(dentry);
out:
unlock_kernel();
return error;
asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
{
struct inode * inode;
+ struct dentry * dentry;
struct file * file;
struct iattr newattrs;
int error = -EBADF;
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
goto out;
error = -ENOENT;
- if (!(inode = file->f_inode))
+ if (!(dentry = file->f_dentry))
+ goto out;
+ if (!(inode = dentry->d_inode))
goto out;
error = -EROFS;
if (IS_RDONLY(inode))
asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
{
+ struct dentry * dentry;
struct inode * inode;
int error;
struct iattr newattrs;
lock_kernel();
- error = namei(filename, &inode);
- if (error)
+ dentry = namei(filename);
+
+ error = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
goto out;
+ inode = dentry->d_inode;
+
error = -EROFS;
if (IS_RDONLY(inode))
- goto iput_and_out;
+ goto dput_and_out;
+
error = -EPERM;
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
- goto iput_and_out;
+ goto dput_and_out;
+
if (user == (uid_t) -1)
user = inode->i_uid;
if (group == (gid_t) -1)
inode->i_sb->dq_op->initialize(inode, -1);
error = -EDQUOT;
if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0))
- goto iput_and_out;
+ goto dput_and_out;
error = notify_change(inode, &newattrs);
if (error)
inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
} else
error = notify_change(inode, &newattrs);
-iput_and_out:
- iput(inode);
+dput_and_out:
+ dput(dentry);
out:
unlock_kernel();
return(error);
static int do_open(const char * filename,int flags,int mode, int fd)
{
struct inode * inode;
+ struct dentry * dentry;
struct file * f;
int flag,error;
flag++;
if (flag & O_TRUNC)
flag |= 2;
- error = open_namei(filename,flag,mode,&inode);
- if (error)
+ dentry = open_namei(filename,flag,mode);
+ error = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
goto cleanup_file;
+ inode = dentry->d_inode;
if (f->f_mode & FMODE_WRITE) {
error = get_write_access(inode);
if (error)
- goto cleanup_inode;
+ goto cleanup_dentry;
}
- f->f_inode = inode;
+ f->f_dentry = dentry;
f->f_pos = 0;
f->f_reada = 0;
f->f_op = NULL;
cleanup_all:
if (f->f_mode & FMODE_WRITE)
put_write_access(inode);
-cleanup_inode:
- iput(inode);
+cleanup_dentry:
+ dput(dentry);
cleanup_file:
put_filp(f);
return error;
int fd, error;
lock_kernel();
- fd = get_unused_fd();
- if (fd < 0) {
- error = fd;
+ error = get_unused_fd();
+ if (error < 0)
goto out;
- }
- error = getname(filename, &tmp);
- if (!error) {
- error = do_open(tmp,flags,mode, fd);
+
+ fd = error;
+ tmp = getname(filename);
+ error = PTR_ERR(tmp);
+ if (!IS_ERR(tmp)) {
+ error = do_open(tmp,flags,mode,fd);
putname(tmp);
if (!error) {
error = fd;
#endif
-int __fput(struct file *filp, struct inode *inode)
+int __fput(struct file *filp)
{
int error = 0;
+ struct dentry * dentry = filp->f_dentry;
+ struct inode * inode = dentry->d_inode;
if (filp->f_op && filp->f_op->release)
error = filp->f_op->release(inode,filp);
- filp->f_inode = NULL;
+ filp->f_dentry = NULL;
if (filp->f_mode & FMODE_WRITE)
put_write_access(inode);
- iput(inode);
+ dput(dentry);
return error;
}
int close_fp(struct file *filp)
{
+ struct dentry *dentry;
struct inode *inode;
if (filp->f_count == 0) {
printk("VFS: Close: file count is 0\n");
return 0;
}
- inode = filp->f_inode;
+ dentry = filp->f_dentry;
+ inode = dentry->d_inode;
if (inode)
locks_remove_locks(current, filp);
- return fput(filp, inode);
+ return fput(filp);
}
asmlinkage int sys_close(unsigned int fd)
static unsigned int pipe_poll(struct file * filp, poll_table * wait)
{
unsigned int mask;
- struct inode * inode = filp->f_inode;
+ struct inode * inode = filp->f_dentry->d_inode;
poll_wait(&PIPE_WAIT(*inode), wait);
mask = POLLIN | POLLRDNORM;
static unsigned int fifo_poll(struct file * filp, poll_table * wait)
{
unsigned int mask;
- struct inode * inode = filp->f_inode;
+ struct inode * inode = filp->f_dentry->d_inode;
poll_wait(&PIPE_WAIT(*inode), wait);
mask = POLLIN | POLLRDNORM;
static unsigned int connect_poll(struct file * filp, poll_table * wait)
{
- struct inode * inode = filp->f_inode;
+ struct inode * inode = filp->f_dentry->d_inode;
poll_wait(&PIPE_WAIT(*inode), wait);
if (!PIPE_EMPTY(*inode)) {
goto close_f12_inode_i;
j = error;
- f1->f_inode = f2->f_inode = inode;
+ f1->f_dentry = f2->f_dentry = d_alloc_root(inode, NULL);
/* read file */
f1->f_pos = f2->f_pos = 0;
close_f12_inode_i:
put_unused_fd(i);
close_f12_inode:
- atomic_dec(&inode->i_count);
iput(inode);
close_f12:
put_filp(f2);
for (vma = mm->mmap; vma; vma = vma->vm_next) {
unsigned long len = (vma->vm_end - vma->vm_start) >> 10;
- if (!vma->vm_inode) {
+ if (!vma->vm_dentry) {
data += len;
if (vma->vm_flags & VM_GROWSDOWN)
stack += len;
*cp++ = flags & VM_MAYSHARE ? 's' : 'p';
*cp++ = 0;
- if (map->vm_inode != NULL) {
- dev = map->vm_inode->i_dev;
- ino = map->vm_inode->i_ino;
- } else {
- dev = 0;
- ino = 0;
+ dev = 0;
+ ino = 0;
+ if (map->vm_dentry != NULL) {
+ dev = map->vm_dentry->d_inode->i_dev;
+ ino = map->vm_dentry->d_inode->i_ino;
}
len = sprintf(line,
if (fd >= NR_OPEN ||
!p->files ||
!p->files->fd[fd] ||
- !p->files->fd[fd]->f_inode)
+ !p->files->fd[fd]->f_dentry)
return -ENOENT;
ino = (pid << 16) + (PROC_PID_FD_DIR << 8) + fd;
for (fd -= 2 ; fd < NR_OPEN; fd++, filp->f_pos++) {
if (!p->files)
break;
- if (!p->files->fd[fd] || !p->files->fd[fd]->f_inode)
+ if (!p->files->fd[fd] || !p->files->fd[fd]->f_dentry)
continue;
j = NUMBUF;
return s;
}
-void proc_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+int proc_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
{
struct statfs tmp;
tmp.f_files = 0;
tmp.f_ffree = 0;
tmp.f_namelen = NAME_MAX;
- copy_to_user(buf, &tmp, bufsiz);
+ return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
}
void proc_read_inode(struct inode * inode)
vma = p->mm->mmap;
while (vma) {
if (vma->vm_flags & VM_EXECUTABLE)
- return dget(i_dentry(vma->vm_inode));
+ return dget(vma->vm_dentry);
vma = vma->vm_next;
}
break;
if (!p->files->fd[ino])
break;
- if (!p->files->fd[ino]->f_inode)
+ if (!p->files->fd[ino]->f_dentry)
break;
- result = dget(i_dentry(p->files->fd[ino]->f_inode));
+ result = dget(p->files->fd[ino]->f_dentry);
break;
}
}
{
long retval;
struct file * file;
+ struct dentry * dentry;
struct inode * inode;
lock_kernel();
retval = -EBADF;
if (fd >= NR_OPEN ||
!(file = current->files->fd[fd]) ||
- !(inode = file->f_inode))
+ !(dentry = file->f_dentry) ||
+ !(inode = dentry->d_inode))
goto bad;
retval = -EINVAL;
if (origin > 2)
{
long retval;
struct file * file;
+ struct dentry * dentry;
struct inode * inode;
long long offset;
retval = -EBADF;
if (fd >= NR_OPEN ||
!(file = current->files->fd[fd]) ||
- !(inode = file->f_inode))
+ !(dentry = file->f_dentry) ||
+ !(inode = dentry->d_inode))
goto bad;
retval = -EINVAL;
if (origin > 2)
{
int error;
struct file * file;
+ struct dentry * dentry;
struct inode * inode;
long (*read)(struct inode *, struct file *, char *, unsigned long);
file = fget(fd);
if (!file)
goto bad_file;
- inode = file->f_inode;
+ dentry = file->f_dentry;
+ if (!dentry)
+ goto bad_file;
+ inode = dentry->d_inode;
if (!inode)
goto out;
error = -EBADF;
goto out;
error = read(inode,file,buf,count);
out:
- fput(file, inode);
+ fput(file);
bad_file:
unlock_kernel();
return error;
{
int error;
struct file * file;
+ struct dentry * dentry;
struct inode * inode;
long (*write)(struct inode *, struct file *, const char *, unsigned long);
file = fget(fd);
if (!file)
goto bad_file;
- inode = file->f_inode;
+ dentry = file->f_dentry;
+ if (!dentry)
+ goto out;
+ inode = dentry->d_inode;
if (!inode)
goto out;
if (!(file->f_mode & 2))
error = write(inode,file,buf,count);
up(&inode->i_sem);
out:
- fput(file, inode);
+ fput(file);
bad_file:
unlock_kernel();
return error;
asmlinkage long sys_readv(unsigned long fd, const struct iovec * vector, unsigned long count)
{
struct file * file;
+ struct dentry * dentry;
struct inode * inode;
- long err = -EBADF;
+ long err;
lock_kernel();
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]) || !(inode=file->f_inode))
+ err = -EBADF;
+ if (fd >= NR_OPEN)
+ goto out;
+
+ file = current->files->fd[fd];
+ if (!file)
goto out;
+
if (!(file->f_mode & 1))
goto out;
+
+ dentry = file->f_dentry;
+ if (!dentry)
+ goto out;
+
+ inode = dentry->d_inode;
+ if (!inode)
+ goto out;
+
err = do_readv_writev(VERIFY_WRITE, inode, file, vector, count);
out:
unlock_kernel();
asmlinkage long sys_writev(unsigned long fd, const struct iovec * vector, unsigned long count)
{
- int error = -EBADF;
+ long error;
struct file * file;
+ struct dentry * dentry;
struct inode * inode;
lock_kernel();
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]) || !(inode=file->f_inode))
+ error = -EBADF;
+
+ if (fd >= NR_OPEN)
+ goto out;
+
+ file = current->files->fd[fd];
+ if (!file)
goto out;
+
if (!(file->f_mode & 2))
goto out;
+
+ dentry = file->f_dentry;
+ if (!dentry)
+ goto out;
+
+ inode = dentry->d_inode;
+ if (!inode)
+ goto out;
+
down(&inode->i_sem);
error = do_readv_writev(VERIFY_READ, inode, file, vector, count);
up(&inode->i_sem);
asmlinkage int old_readdir(unsigned int fd, void * dirent, unsigned int count)
{
- int error = -EBADF;
+ int error;
struct file * file;
+ struct dentry * dentry;
+ struct inode * inode;
struct readdir_callback buf;
lock_kernel();
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ error = -EBADF;
+ if (fd >= NR_OPEN)
goto out;
- error = -ENOTDIR;
- if (!file->f_op || !file->f_op->readdir)
+
+ file = current->files->fd[fd];
+ if (!file)
goto out;
- error = verify_area(VERIFY_WRITE, dirent, sizeof(struct old_linux_dirent));
- if (error)
+
+ dentry = file->f_dentry;
+ if (!dentry)
+ goto out;
+
+ inode = dentry->d_inode;
+ if (!inode)
goto out;
+
buf.count = 0;
buf.dirent = dirent;
- error = file->f_op->readdir(file->f_inode, file, &buf, fillonedir);
+
+ error = -ENOTDIR;
+ if (!file->f_op || !file->f_op->readdir)
+ goto out;
+
+ error = file->f_op->readdir(inode, file, &buf, fillonedir);
if (error < 0)
goto out;
error = buf.count;
asmlinkage int sys_getdents(unsigned int fd, void * dirent, unsigned int count)
{
struct file * file;
+ struct dentry * dentry;
+ struct inode * inode;
struct linux_dirent * lastdirent;
struct getdents_callback buf;
- int error = -EBADF;
+ int error;
lock_kernel();
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ error = -EBADF;
+ if (fd >= NR_OPEN)
goto out;
- error = -ENOTDIR;
- if (!file->f_op || !file->f_op->readdir)
+
+ file = current->files->fd[fd];
+ if (!file)
goto out;
- error = verify_area(VERIFY_WRITE, dirent, count);
- if (error)
+
+ dentry = file->f_dentry;
+ if (!dentry)
+ goto out;
+
+ inode = dentry->d_inode;
+ if (!inode)
goto out;
+
buf.current_dir = (struct linux_dirent *) dirent;
buf.previous = NULL;
buf.count = count;
buf.error = 0;
- error = file->f_op->readdir(file->f_inode, file, &buf, filldir);
+
+ error = -ENOTDIR;
+ if (!file->f_op || !file->f_op->readdir)
+ goto out;
+
+ error = file->f_op->readdir(inode, file, &buf, filldir);
if (error < 0)
goto out;
lastdirent = buf.previous;
- if (!lastdirent) {
- error = buf.error;
- } else {
+ error = buf.error;
+ if (lastdirent) {
put_user(file->f_pos, &lastdirent->d_off);
error = count - buf.count;
}
return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
}
+
#if !defined(__alpha__) && !defined(__sparc__)
/*
* For backward compatibility? Maybe this should be moved
*/
asmlinkage int sys_stat(char * filename, struct __old_kernel_stat * statbuf)
{
- struct inode * inode;
+ struct dentry * dentry;
int error;
lock_kernel();
- error = namei(filename, &inode);
- if (error)
- goto out;
- if ((error = do_revalidate(inode)) == 0)
- error = cp_old_stat(inode,statbuf);
- iput(inode);
-out:
+ dentry = namei(filename);
+
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ struct inode * inode = dentry->d_inode;
+ error = do_revalidate(inode);
+ if (!error)
+ error = cp_old_stat(inode, statbuf);
+
+ dput(dentry);
+ }
unlock_kernel();
return error;
}
asmlinkage int sys_newstat(char * filename, struct stat * statbuf)
{
- struct inode * inode;
+ struct dentry * dentry;
int error;
lock_kernel();
- error = namei(filename, &inode);
- if (error)
- goto out;
- if ((error = do_revalidate(inode)) == 0)
- error = cp_new_stat(inode,statbuf);
- iput(inode);
-out:
+ dentry = namei(filename);
+
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ struct inode * inode = dentry->d_inode;
+ error = do_revalidate(inode);
+ if (!error)
+ error = cp_new_stat(inode,statbuf);
+
+ dput(dentry);
+ }
unlock_kernel();
return error;
}
*/
asmlinkage int sys_lstat(char * filename, struct __old_kernel_stat * statbuf)
{
- struct inode * inode;
+ struct dentry * dentry;
int error;
lock_kernel();
- error = lnamei(filename, &inode);
- if (error)
- goto out;
- if ((error = do_revalidate(inode)) == 0)
- error = cp_old_stat(inode,statbuf);
- iput(inode);
-out:
+ dentry = lnamei(filename);
+
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ struct inode * inode = dentry->d_inode;
+ error = do_revalidate(inode);
+ if (!error)
+ error = cp_old_stat(inode, statbuf);
+
+ dput(dentry);
+ }
unlock_kernel();
return error;
}
asmlinkage int sys_newlstat(char * filename, struct stat * statbuf)
{
- struct inode * inode;
+ struct dentry * dentry;
int error;
lock_kernel();
- error = lnamei(filename, &inode);
- if (error)
- goto out;
- if ((error = do_revalidate(inode)) == 0)
- error = cp_new_stat(inode,statbuf);
- iput(inode);
-out:
+ dentry = lnamei(filename);
+
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ struct inode * inode = dentry->d_inode;
+ error = do_revalidate(inode);
+ if (!error)
+ error = cp_new_stat(inode,statbuf);
+
+ dput(dentry);
+ }
unlock_kernel();
return error;
}
asmlinkage int sys_fstat(unsigned int fd, struct __old_kernel_stat * statbuf)
{
struct file * f;
- struct inode * inode;
- int ret = -EBADF;
+ int err = -EBADF;
lock_kernel();
- if (fd >= NR_OPEN || !(f=current->files->fd[fd]) || !(inode=f->f_inode))
- goto out;
- if ((ret = do_revalidate(inode)) == 0)
- ret = cp_old_stat(inode,statbuf);
-out:
+ if (fd < NR_OPEN && (f = current->files->fd[fd]) != NULL) {
+ struct dentry * dentry = f->f_dentry;
+ struct inode * inode = dentry->d_inode;
+
+ err = do_revalidate(inode);
+ if (!err)
+ err = cp_old_stat(inode,statbuf);
+ }
unlock_kernel();
- return ret;
+ return err;
}
#endif
asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf)
{
struct file * f;
- struct inode * inode;
int err = -EBADF;
lock_kernel();
- if (fd >= NR_OPEN || !(f=current->files->fd[fd]) || !(inode=f->f_inode))
- goto out;
- if ((err = do_revalidate(inode)) == 0)
- err = cp_new_stat(inode,statbuf);
-out:
+ if (fd < NR_OPEN && (f = current->files->fd[fd]) != NULL) {
+ struct dentry * dentry = f->f_dentry;
+ struct inode * inode = dentry->d_inode;
+
+ err = do_revalidate(inode);
+ if (!err)
+ err = cp_new_stat(inode,statbuf);
+ }
unlock_kernel();
return err;
}
asmlinkage int sys_readlink(const char * path, char * buf, int bufsiz)
{
- struct inode * inode;
+ struct dentry * dentry;
int error;
if (bufsiz <= 0)
return -EINVAL;
lock_kernel();
- error = lnamei(path, &inode);
- if (error)
- goto out;
- error = -EINVAL;
- if (!inode->i_op || !inode->i_op->readlink ||
- !S_ISLNK(inode->i_mode) || (error = do_revalidate(inode)) < 0) {
- iput(inode);
- goto out;
+ dentry = lnamei(path);
+
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ struct inode * inode = dentry->d_inode;
+
+ error = -EINVAL;
+ if (inode->i_op && inode->i_op->readlink && !(error = do_revalidate(inode))) {
+ UPDATE_ATIME(inode);
+ error = inode->i_op->readlink(inode,buf,bufsiz);
+ }
+ dput(dentry);
}
- UPDATE_ATIME(inode);
- error = inode->i_op->readlink(inode,buf,bufsiz);
- iput(inode);
-out:
unlock_kernel();
return error;
}
lptr->mnt_dev = dev;
sema_init(&lptr->mnt_sem, 1);
- if (dev_name && !getname(dev_name, &tmp)) {
+ if (dev_name && !IS_ERR(tmp = getname(dev_name))) {
if ((lptr->mnt_devname =
(char *) kmalloc(strlen(tmp)+1, GFP_KERNEL)) != (char *)NULL)
strcpy(lptr->mnt_devname, tmp);
putname(tmp);
}
- if (dir_name && !getname(dir_name, &tmp)) {
+ if (dir_name && !IS_ERR(tmp = getname(dir_name))) {
if ((lptr->mnt_dirname =
(char *) kmalloc(strlen(tmp)+1, GFP_KERNEL)) != (char *)NULL)
strcpy(lptr->mnt_dirname, tmp);
char * name;
int err, index;
- err = getname(__name, &name);
- if (err)
+ name = getname(__name);
+ err = PTR_ERR(name);
+ if (IS_ERR(name))
return err;
+
index = 0;
for (tmp = file_systems ; tmp ; tmp = tmp->next) {
if (strcmp(tmp->name, name) == 0) {
asmlinkage int sys_umount(char * name)
{
+ struct dentry * dentry;
struct inode * inode;
kdev_t dev;
struct inode * dummy_inode = NULL;
- int retval = -EPERM;
+ int retval;
- lock_kernel();
if (!suser())
+ return -EPERM;
+
+ lock_kernel();
+ dentry = namei(name);
+ retval = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
goto out;
- retval = namei(name, &inode);
+
+ inode = dentry->d_inode;
if (S_ISBLK(inode->i_mode)) {
dev = inode->i_rdev;
retval = -EACCES;
if (IS_NODEV(inode)) {
- iput(inode);
+ dput(dentry);
goto out;
}
} else {
retval = -EINVAL;
if (!inode->i_sb || inode != inode->i_sb->s_root->d_inode) {
- iput(inode);
+ dput(dentry);
goto out;
}
dev = inode->i_sb->s_dev;
- iput(inode);
+ dput(dentry);
inode = dummy_inode = get_empty_inode();
inode->i_rdev = dev;
}
retval = -ENXIO;
if (MAJOR(dev) >= MAX_BLKDEV) {
- iput(inode);
+ dput(dentry);
goto out;
}
retval = do_umount(dev,0);
put_unnamed_dev(dev);
}
}
- iput(inode);
+ dput(dentry);
if (!retval)
fsync_dev(dev);
out:
static int do_remount(const char *dir,int flags,char *data)
{
- struct inode *dir_i;
+ struct dentry *dentry;
int retval;
- retval = namei(dir, &dir_i);
- if (retval)
- return retval;
- if (dir_i != dir_i->i_sb->s_root->d_inode) {
- iput(dir_i);
- return -EINVAL;
+ dentry = namei(dir);
+ retval = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ struct super_block * sb = dentry->d_inode->i_sb;
+
+ retval = -EINVAL;
+ if (dentry == sb->s_root)
+ retval = do_remount_sb(sb, flags, data);
+ dput(dentry);
}
- retval = do_remount_sb(dir_i->i_sb, flags, data);
- iput(dir_i);
return retval;
}
unsigned long new_flags, void * data)
{
struct file_system_type * fstype;
- struct inode * inode;
+ struct dentry * dentry = NULL;
+ struct inode * inode = NULL;
struct file_operations * fops;
kdev_t dev;
int retval = -EPERM;
goto out;
t = fstype->name;
fops = NULL;
- if ((fstype->fs_flags & FS_REQUIRES_DEV)) {
- retval = namei(dev_name, &inode);
- if (retval)
+ if (fstype->fs_flags & FS_REQUIRES_DEV) {
+ dentry = namei(dev_name);
+ retval = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
goto out;
+
+ inode = dentry->d_inode;
retval = -ENOTBLK;
- if (!S_ISBLK(inode->i_mode)) {
- iput(inode);
- goto out;
- }
+ if (!S_ISBLK(inode->i_mode))
+ goto dput_and_out;
+
retval = -EACCES;
- if (IS_NODEV(inode)) {
- iput(inode);
- goto out;
- }
+ if (IS_NODEV(inode))
+ goto dput_and_out;
+
dev = inode->i_rdev;
retval = -ENXIO;
- if (MAJOR(dev) >= MAX_BLKDEV) {
- iput(inode);
- goto out;
- }
+ if (MAJOR(dev) >= MAX_BLKDEV)
+ goto dput_and_out;
+
fops = get_blkfops(MAJOR(dev));
retval = -ENOTBLK;
- if (!fops) {
- iput(inode);
- goto out;
- }
+ if (!fops)
+ goto dput_and_out;
+
if (fops->open) {
struct file dummy; /* allows read-write or read-only flag */
memset(&dummy, 0, sizeof(dummy));
- dummy.f_inode = inode;
+ dummy.f_dentry = dentry;
dummy.f_mode = (new_flags & MS_RDONLY) ? 1 : 3;
retval = fops->open(inode, &dummy);
- if (retval) {
- iput(inode);
- goto out;
- }
+ if (retval)
+ goto dput_and_out;
}
} else {
retval = -EMFILE;
if (!(dev = get_unnamed_dev()))
goto out;
- inode = NULL;
}
+
page = 0;
if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL) {
flags = new_flags & ~MS_MGC_MSK;
retval = copy_mount_options(data, &page);
if (retval < 0) {
put_unnamed_dev(dev);
- iput(inode);
- goto out;
+ goto dput_and_out;
}
}
retval = do_mount(dev,dev_name,dir_name,t,flags,(void *) page);
fops->release(inode, NULL);
put_unnamed_dev(dev);
}
- iput(inode);
+dput_and_out:
+ dput(dentry);
out:
unlock_kernel();
return retval;
memset(&filp, 0, sizeof(filp));
d_inode = get_empty_inode();
d_inode->i_rdev = ROOT_DEV;
- filp.f_inode = d_inode;
+ filp.f_dentry = NULL;
if ( root_mountflags & MS_RDONLY)
filp.f_mode = 1; /* read only */
else
unsigned long p;
int sh_bang;
int java; /* Java binary, prevent recursive invocation */
- struct inode * inode;
+ struct dentry * dentry;
int e_uid, e_gid;
int argc, envc;
char * filename; /* Name of binary */
unsigned long loader, exec;
- int dont_iput; /* binfmt handler has put inode */
};
/*
extern int register_binfmt(struct linux_binfmt *);
extern int unregister_binfmt(struct linux_binfmt *);
-extern int read_exec(struct inode *inode, unsigned long offset,
+extern int read_exec(struct dentry *, unsigned long offset,
char * addr, unsigned long count, int to_kmem);
-extern int open_inode(struct inode * inode, int mode);
+extern int open_dentry(struct dentry *, int mode);
extern int init_elf_binfmt(void);
extern int init_elf32_binfmt(void);
extern void d_delete(struct dentry *);
-/* Note that all these routines must be called with vfs_lock() held */
-
-/* get inode, if necessary retrieve it with iget() */
-extern struct inode * d_inode(struct dentry ** changing_entry);
-
/* allocate/de-allocate */
extern void d_free(struct dentry *);
extern struct dentry * d_alloc(struct dentry * parent, const struct qstr *name);
+extern void shrink_dcache(int);
/* only used at mount-time */
extern struct dentry * d_alloc_root(struct inode * root_inode, struct dentry * old_root);
extern int ext2_remount (struct super_block *, int *, char *);
extern struct super_block * ext2_read_super (struct super_block *,void *,int);
extern int init_ext2_fs(void);
-extern void ext2_statfs (struct super_block *, struct statfs *, int);
+extern int ext2_statfs (struct super_block *, struct statfs *, int);
/* truncate.c */
extern void ext2_truncate (struct inode *);
return file;
}
-extern int __fput(struct file *, struct inode *);
+extern int __fput(struct file *);
extern void insert_file_free(struct file *file);
/* It does not matter which list it is on. */
*file->f_pprev = file->f_next;
}
-extern inline int fput(struct file *file, struct inode *inode)
+extern inline int fput(struct file *file)
{
int count = file->f_count-1;
int error = 0;
if (!count) {
- error = __fput(file, inode);
+ error = __fput(file);
file->f_count = 0;
remove_filp(file);
insert_file_free(file);
struct file {
struct file *f_next, **f_pprev;
- struct inode *f_inode;
+ struct dentry *f_dentry;
struct file_operations *f_op;
mode_t f_mode;
loff_t f_pos;
void (*put_inode) (struct inode *);
void (*put_super) (struct super_block *);
void (*write_super) (struct super_block *);
- void (*statfs) (struct super_block *, struct statfs *, int);
+ int (*statfs) (struct super_block *, struct statfs *, int);
int (*remount_fs) (struct super_block *, int *, char *);
};
extern void kill_fasync(struct fasync_struct *fa, int sig);
-extern int getname(const char * filename, char **result);
+extern char * getname(const char * filename);
extern void putname(char * name);
extern int do_truncate(struct inode *, unsigned long);
extern int register_blkdev(unsigned int, const char *, struct file_operations *);
extern int permission(struct inode * inode,int mask);
extern int get_write_access(struct inode *inode);
extern void put_write_access(struct inode *inode);
-extern int open_namei(const char * pathname, int flag, int mode, struct inode ** res_inode);
-extern int do_mknod(const char * filename, int mode, dev_t dev);
+extern struct dentry * open_namei(const char * pathname, int flag, int mode);
+extern struct dentry * do_mknod(const char * filename, int mode, dev_t dev);
extern int do_pipe(int *);
/*
#define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000))
extern struct dentry * lookup_dentry(const char *, struct dentry *, int);
-extern int __namei(const char *, struct inode **, int);
+extern struct dentry * __namei(const char *, int);
-#define namei(pathname, inode_p) __namei(pathname, inode_p, 1)
-#define lnamei(pathname, inode_p) __namei(pathname, inode_p, 0)
+#define namei(pathname) __namei(pathname, 1)
+#define lnamei(pathname) __namei(pathname, 0)
#include <asm/semaphore.h>
extern int init_iso9660_fs(void);
extern void isofs_read_inode(struct inode *);
extern void isofs_put_inode(struct inode *);
-extern void isofs_statfs(struct super_block *, struct statfs *, int);
+extern int isofs_statfs(struct super_block *, struct statfs *, int);
extern int isofs_lseek(struct inode *, struct file *, off_t, int);
extern int isofs_read(struct inode *, struct file *, char *, int);
prev->next = next;
}
+static inline int list_empty(struct list_head *head)
+{
+ return head->next == head;
+}
+
+/*
+ * Splice in "list" into "head"
+ */
+static inline void list_splice(struct list_head *list, struct list_head *head)
+{
+ struct list_head *first = list->next;
+
+ if (first != list) {
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+ }
+}
+
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
extern __inline__ struct inode *
nlmsvc_file_inode(struct nlm_file *file)
{
- return file->f_file.f_inode;
+ return file->f_file.f_dentry->d_inode;
}
/*
struct vm_operations_struct * vm_ops;
unsigned long vm_offset;
- struct inode * vm_inode;
+ struct dentry * vm_dentry;
unsigned long vm_pte; /* shared mem */
};
extern struct super_block *proc_read_super(struct super_block *,void *,int);
extern int init_proc_fs(void);
extern struct inode * proc_get_inode(struct super_block *, int, struct proc_dir_entry *);
-extern void proc_statfs(struct super_block *, struct statfs *, int);
+extern int proc_statfs(struct super_block *, struct statfs *, int);
extern void proc_read_inode(struct inode *);
extern void proc_write_inode(struct inode *);
struct swap_info_struct {
unsigned int flags;
kdev_t swap_device;
- char *swap_filename;
- struct inode * swap_file;
+ struct dentry * swap_file;
unsigned char * swap_map;
unsigned char * swap_lockmap;
unsigned int lowest_bit;
shmd->vm_flags = VM_SHM | VM_MAYSHARE | VM_SHARED
| VM_MAYREAD | VM_MAYEXEC | VM_READ | VM_EXEC
| ((shmflg & SHM_RDONLY) ? 0 : VM_MAYWRITE | VM_WRITE);
- shmd->vm_inode = NULL;
+ shmd->vm_dentry = NULL;
shmd->vm_offset = 0;
shmd->vm_ops = &shm_vm_ops;
flush_cache_mm(current->mm);
pprev = &mm->mmap;
for (mpnt = current->mm->mmap ; mpnt ; mpnt = mpnt->vm_next) {
- struct inode *inode;
+ struct dentry *dentry;
tmp = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
if (!tmp) {
tmp->vm_flags &= ~VM_LOCKED;
tmp->vm_mm = mm;
tmp->vm_next = NULL;
- inode = tmp->vm_inode;
- if (inode) {
- atomic_inc(&inode->i_count);
+ dentry = tmp->vm_dentry;
+ if (dentry) {
+ dentry->d_count++;
if (tmp->vm_flags & VM_DENYWRITE)
- inode->i_writecount--;
+ dentry->d_inode->i_writecount--;
/* insert tmp into the share list, just after mpnt */
if((tmp->vm_next_share = mpnt->vm_next_share) != NULL)
EXPORT_SYMBOL(copy_strings);
EXPORT_SYMBOL(do_execve);
EXPORT_SYMBOL(flush_old_exec);
-EXPORT_SYMBOL(open_inode);
+EXPORT_SYMBOL(open_dentry);
EXPORT_SYMBOL(read_exec);
/* Miscellaneous access points */
fs = get_fs();
set_fs(KERNEL_DS);
- acct_file.f_op->write(acct_file.f_inode, &acct_file,
+ acct_file.f_op->write(acct_file.f_dentry->d_inode, &acct_file,
(char *)&ac, sizeof(struct acct));
set_fs(fs);
}
asmlinkage int sys_acct(const char *name)
{
- struct inode *inode = (struct inode *)0;
- char *tmp;
int error = -EPERM;
lock_kernel();
if (name == (char *)0) {
if (acct_active) {
if (acct_file.f_op->release)
- acct_file.f_op->release(acct_file.f_inode, &acct_file);
+ acct_file.f_op->release(acct_file.f_dentry->d_inode, &acct_file);
- if (acct_file.f_inode != (struct inode *) 0)
- iput(acct_file.f_inode);
+ if (acct_file.f_dentry != NULL)
+ dput(acct_file.f_dentry);
acct_active = 0;
}
} else {
error = -EBUSY;
if (!acct_active) {
- if ((error = getname(name, &tmp)) != 0)
+ struct dentry *dentry;
+ struct inode *inode;
+ char *tmp;
+
+ tmp = getname(name);
+ error = PTR_ERR(tmp);
+ if (IS_ERR(tmp))
goto out;
- error = open_namei(tmp, O_RDWR, 0600, &inode);
+ dentry = open_namei(tmp, O_RDWR, 0600);
putname(tmp);
- if (error)
+
+ error = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
goto out;
+ inode = dentry->d_inode;
error = -EACCES;
if (!S_ISREG(inode->i_mode)) {
- iput(inode);
+ dput(dentry);
goto out;
}
error = -EIO;
if (!inode->i_op || !inode->i_op->default_file_ops ||
!inode->i_op->default_file_ops->write) {
- iput(inode);
+ dput(dentry);
goto out;
}
acct_file.f_mode = 3;
acct_file.f_flags = 0;
acct_file.f_count = 1;
- acct_file.f_inode = inode;
+ acct_file.f_dentry = dentry;
acct_file.f_pos = inode->i_size;
acct_file.f_reada = 0;
acct_file.f_op = inode->i_op->default_file_ops;
- if(acct_file.f_op->open)
- if(acct_file.f_op->open(acct_file.f_inode, &acct_file)) {
- iput(inode);
+ if(acct_file.f_op->open) {
+ error = acct_file.f_op->open(inode, &acct_file);
+ if (error) {
+ dput(dentry);
goto out;
}
+ }
acct_active = 1;
error = 0;
{
unsigned long offset;
struct page * page, **hash;
- struct inode * inode = area->vm_inode;
+ struct inode * inode = area->vm_dentry->d_inode;
unsigned long old_page, new_page;
new_page = 0;
{
int result;
struct file file;
+ struct dentry * dentry;
struct inode * inode;
struct buffer_head * bh;
return 0;
}
- inode = vma->vm_inode;
+ dentry = vma->vm_dentry;
+ inode = dentry->d_inode;
file.f_op = inode->i_op->default_file_ops;
if (!file.f_op->write)
return -EIO;
file.f_mode = 3;
file.f_flags = 0;
file.f_count = 1;
- file.f_inode = inode;
+ file.f_dentry = dentry;
file.f_pos = offset;
file.f_reada = 0;
if (!inode->i_op || !inode->i_op->readpage)
return -ENOEXEC;
UPDATE_ATIME(inode);
- vma->vm_inode = inode;
- atomic_inc(&inode->i_count);
+ vma->vm_dentry = dget(file->f_dentry);
vma->vm_ops = ops;
return 0;
}
static int msync_interval(struct vm_area_struct * vma,
unsigned long start, unsigned long end, int flags)
{
- if (!vma->vm_inode)
+ if (!vma->vm_dentry)
return 0;
if (vma->vm_ops->sync) {
int error;
if (error)
return error;
if (flags & MS_SYNC)
- return file_fsync(vma->vm_inode, NULL);
+ return file_fsync(vma->vm_dentry->d_inode, NULL);
return 0;
}
return 0;
n->vm_end = end;
vma->vm_offset += vma->vm_start - n->vm_start;
n->vm_flags = newflags;
- if (n->vm_inode)
- atomic_inc(&n->vm_inode->i_count);
+ n->vm_dentry = dget(vma->vm_dentry);
if (n->vm_ops && n->vm_ops->open)
n->vm_ops->open(n);
insert_vm_struct(current->mm, n);
n->vm_start = start;
n->vm_offset += n->vm_start - vma->vm_start;
n->vm_flags = newflags;
- if (n->vm_inode)
- atomic_inc(&n->vm_inode->i_count);
+ n->vm_dentry = dget(vma->vm_dentry);
if (n->vm_ops && n->vm_ops->open)
n->vm_ops->open(n);
insert_vm_struct(current->mm, n);
vma->vm_offset += vma->vm_start - left->vm_start;
right->vm_offset += right->vm_start - left->vm_start;
vma->vm_flags = newflags;
- if (vma->vm_inode)
- atomic_add(2, &vma->vm_inode->i_count);
+ if (vma->vm_dentry)
+ vma->vm_dentry->d_count += 2;
+
if (vma->vm_ops && vma->vm_ops->open) {
vma->vm_ops->open(left);
vma->vm_ops->open(right);
/* Remove one vm structure from the inode's i_mmap ring. */
static inline void remove_shared_vm_struct(struct vm_area_struct *vma)
{
- struct inode * inode = vma->vm_inode;
+ struct dentry * dentry = vma->vm_dentry;
- if (inode) {
+ if (dentry) {
if (vma->vm_flags & VM_DENYWRITE)
- inode->i_writecount++;
+ dentry->d_inode->i_writecount++;
if(vma->vm_next_share)
vma->vm_next_share->vm_pprev_share = vma->vm_pprev_share;
*vma->vm_pprev_share = vma->vm_next_share;
return -EACCES;
/* make sure there are no mandatory locks on the file. */
- if (locks_verify_locked(file->f_inode))
+ if (locks_verify_locked(file->f_dentry->d_inode))
return -EAGAIN;
/* fall through */
case MAP_PRIVATE:
vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
vma->vm_ops = NULL;
vma->vm_offset = off;
- vma->vm_inode = NULL;
+ vma->vm_dentry = NULL;
vma->vm_pte = 0;
do_munmap(addr, len); /* Clear old maps */
if (file) {
int error = 0;
if (vma->vm_flags & VM_DENYWRITE) {
- if (file->f_inode->i_writecount > 0)
+ if (file->f_dentry->d_inode->i_writecount > 0)
error = -ETXTBSY;
else {
/* f_op->mmap might possibly sleep
* might). In any case, this takes care of any
* race that this might cause.
*/
- file->f_inode->i_writecount--;
+ file->f_dentry->d_inode->i_writecount--;
correct_wcount = 1;
}
}
if (!error)
- error = file->f_op->mmap(file->f_inode, file, vma);
+ error = file->f_op->mmap(file->f_dentry->d_inode, file, vma);
if (error) {
if (correct_wcount)
- file->f_inode->i_writecount++;
+ file->f_dentry->d_inode->i_writecount++;
kmem_cache_free(vm_area_cachep, vma);
return error;
}
flags = vma->vm_flags;
insert_vm_struct(mm, vma);
if (correct_wcount)
- file->f_inode->i_writecount++;
+ file->f_dentry->d_inode->i_writecount++;
merge_segments(mm, vma->vm_start, vma->vm_end);
addr = vma->vm_start;
if (addr == area->vm_start && end == area->vm_end) {
if (area->vm_ops && area->vm_ops->close)
area->vm_ops->close(area);
- if (area->vm_inode)
- iput(area->vm_inode);
+ if (area->vm_dentry)
+ dput(area->vm_dentry);
return;
}
if (!mpnt)
return;
- *mpnt = *area;
- mpnt->vm_offset += (end - area->vm_start);
+ mpnt->vm_mm = area->vm_mm;
mpnt->vm_start = end;
- if (mpnt->vm_inode)
- atomic_inc(&mpnt->vm_inode->i_count);
+ mpnt->vm_end = area->vm_end;
+ mpnt->vm_page_prot = area->vm_page_prot;
+ mpnt->vm_flags = area->vm_flags;
+ mpnt->vm_ops = area->vm_ops;
+ mpnt->vm_offset += (end - area->vm_start);
+ mpnt->vm_dentry = dget(area->vm_dentry);
if (mpnt->vm_ops && mpnt->vm_ops->open)
mpnt->vm_ops->open(mpnt);
area->vm_end = addr; /* Truncate area */
}
remove_shared_vm_struct(mpnt);
zap_page_range(mm, start, size);
- if (mpnt->vm_inode)
- iput(mpnt->vm_inode);
+ if (mpnt->vm_dentry)
+ dput(mpnt->vm_dentry);
kmem_cache_free(vm_area_cachep, mpnt);
mpnt = next;
}
void insert_vm_struct(struct mm_struct *mm, struct vm_area_struct *vmp)
{
struct vm_area_struct **pprev = &mm->mmap;
- struct inode * inode;
+ struct dentry * dentry;
/* Find where to link it in. */
while(*pprev && (*pprev)->vm_start <= vmp->vm_start)
*pprev = vmp;
vmp->vm_pprev = pprev;
- inode = vmp->vm_inode;
- if (inode) {
+ dentry = vmp->vm_dentry;
+ if (dentry) {
+ struct inode * inode = dentry->d_inode;
if (vmp->vm_flags & VM_DENYWRITE)
inode->i_writecount--;
for ( ; mpnt && prev->vm_start < end_addr ; prev = mpnt, mpnt = next) {
next = mpnt->vm_next;
- /* To share, we must have the same inode, operations.. */
- if ((mpnt->vm_inode != prev->vm_inode) ||
+ /* To share, we must have the same dentry, operations.. */
+ if ((mpnt->vm_dentry != prev->vm_dentry)||
(mpnt->vm_pte != prev->vm_pte) ||
(mpnt->vm_ops != prev->vm_ops) ||
(mpnt->vm_flags != prev->vm_flags) ||
(prev->vm_end != mpnt->vm_start))
continue;
- /* and if we have an inode, the offsets must be contiguous.. */
- if ((mpnt->vm_inode != NULL) || (mpnt->vm_flags & VM_SHM)) {
+ /*
+ * If we have a dentry or it's a shared memory area
+ * the offsets must be contiguous..
+ */
+ if ((mpnt->vm_dentry != NULL) || (mpnt->vm_flags & VM_SHM)) {
unsigned long off = prev->vm_offset+prev->vm_end-prev->vm_start;
if (off != mpnt->vm_offset)
continue;
mpnt->vm_ops->close(mpnt);
}
remove_shared_vm_struct(mpnt);
- if (mpnt->vm_inode)
- atomic_dec(&mpnt->vm_inode->i_count);
+ if (mpnt->vm_dentry)
+ dput(mpnt->vm_dentry);
kmem_cache_free(vm_area_cachep, mpnt);
mpnt = prev;
}
vma->vm_offset += vma->vm_start - n->vm_start;
n->vm_flags = newflags;
n->vm_page_prot = prot;
- if (n->vm_inode)
- atomic_inc(&n->vm_inode->i_count);
+ n->vm_dentry = dget(n->vm_dentry);
if (n->vm_ops && n->vm_ops->open)
n->vm_ops->open(n);
insert_vm_struct(current->mm, n);
n->vm_offset += n->vm_start - vma->vm_start;
n->vm_flags = newflags;
n->vm_page_prot = prot;
- if (n->vm_inode)
- atomic_inc(&n->vm_inode->i_count);
+ n->vm_dentry = dget(n->vm_dentry);
if (n->vm_ops && n->vm_ops->open)
n->vm_ops->open(n);
insert_vm_struct(current->mm, n);
right->vm_offset += right->vm_start - left->vm_start;
vma->vm_flags = newflags;
vma->vm_page_prot = prot;
- if (vma->vm_inode)
- atomic_add(2, &vma->vm_inode->i_count);
+ if (vma->vm_dentry)
+ vma->vm_dentry->d_count += 2;
if (vma->vm_ops && vma->vm_ops->open) {
vma->vm_ops->open(left);
vma->vm_ops->open(right);
new_vma->vm_start = new_addr;
new_vma->vm_end = new_addr+new_len;
new_vma->vm_offset = vma->vm_offset + (addr - vma->vm_start);
- if (new_vma->vm_inode)
- atomic_inc(&new_vma->vm_inode->i_count);
+ new_vma->vm_dentry = dget(vma->vm_dentry);
if (new_vma->vm_ops && new_vma->vm_ops->open)
new_vma->vm_ops->open(new_vma);
insert_vm_struct(current->mm, new_vma);
return;
wait_on_page(page);
} else if (p->swap_file) {
- struct inode *swapf = p->swap_file;
+ struct inode *swapf = p->swap_file->d_inode;
unsigned int zones[PAGE_SIZE/512];
int i;
if (swapf->i_op->bmap == NULL
asmlinkage int sys_swapoff(const char * specialfile)
{
struct swap_info_struct * p = NULL;
- struct inode * inode;
+ struct dentry * dentry;
struct file filp;
int i, type, prev;
int err = -EPERM;
lock_kernel();
if (!suser())
goto out;
- err = namei(specialfile, &inode);
- if (err)
+
+ dentry = namei(specialfile);
+ err = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
goto out;
+
prev = -1;
for (type = swap_list.head; type >= 0; type = swap_info[type].next) {
p = swap_info + type;
if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) {
if (p->swap_file) {
- if (p->swap_file == inode)
+ if (p->swap_file == dentry)
break;
} else {
- if (S_ISBLK(inode->i_mode)
- && (p->swap_device == inode->i_rdev))
+ if (S_ISBLK(dentry->d_inode->i_mode)
+ && (p->swap_device == dentry->d_inode->i_rdev))
break;
}
}
}
err = -EINVAL;
if (type < 0){
- iput(inode);
+ dput(dentry);
goto out;
}
if (prev < 0) {
p->flags = SWP_USED;
err = try_to_unuse(type);
if (err) {
- iput(inode);
+ dput(dentry);
/* re-insert swap space back into swap_list */
for (prev = -1, i = swap_list.head; i >= 0; prev = i, i = swap_info[i].next)
if (p->prio >= swap_info[i].prio)
}
if(p->swap_device){
memset(&filp, 0, sizeof(filp));
- filp.f_inode = inode;
+ filp.f_dentry = dentry;
filp.f_mode = 3; /* read write */
/* open it again to get fops */
- if( !blkdev_open(inode, &filp) &&
+ if( !blkdev_open(dentry->d_inode, &filp) &&
filp.f_op && filp.f_op->release){
- filp.f_op->release(inode,&filp);
- filp.f_op->release(inode,&filp);
+ filp.f_op->release(dentry->d_inode,&filp);
+ filp.f_op->release(dentry->d_inode,&filp);
}
}
- iput(inode);
+ dput(dentry);
nr_swap_pages -= p->pages;
- iput(p->swap_file);
- if (p->swap_filename)
- kfree(p->swap_filename);
+ dput(p->swap_file);
p->swap_file = NULL;
p->swap_device = 0;
vfree(p->swap_map);
len += sprintf(buf, "Filename\t\t\tType\t\tSize\tUsed\tPriority\n");
for (i = 0 ; i < nr_swapfiles ; i++, ptr++)
if (ptr->flags & SWP_USED) {
- if (ptr->swap_filename)
- len += sprintf(buf + len, "%-31s ", ptr->swap_filename);
- else
- len += sprintf(buf + len, "(null)\t\t\t");
+ len += sprintf(buf + len, "%-31s ", ptr->swap_file->d_name.name);
+
if (ptr->swap_file)
len += sprintf(buf + len, "file\t\t");
else
asmlinkage int sys_swapon(const char * specialfile, int swap_flags)
{
struct swap_info_struct * p;
- struct inode * swap_inode;
+ struct dentry * swap_dentry;
unsigned int type;
int i, j, prev;
int error = -EPERM;
- char *tmp;
struct file filp;
static int least_priority = 0;
if (type >= nr_swapfiles)
nr_swapfiles = type+1;
p->flags = SWP_USED;
- p->swap_filename = NULL;
p->swap_file = NULL;
p->swap_device = 0;
p->swap_map = NULL;
} else {
p->prio = --least_priority;
}
- error = namei(specialfile, &swap_inode);
- if (error)
+ swap_dentry = namei(specialfile);
+ error = PTR_ERR(swap_dentry);
+ if (IS_ERR(swap_dentry))
goto bad_swap_2;
- p->swap_file = swap_inode;
+
+ p->swap_file = swap_dentry;
error = -EINVAL;
- if (S_ISBLK(swap_inode->i_mode)) {
- p->swap_device = swap_inode->i_rdev;
+ if (S_ISBLK(swap_dentry->d_inode->i_mode)) {
+ p->swap_device = swap_dentry->d_inode->i_rdev;
set_blocksize(p->swap_device, PAGE_SIZE);
- filp.f_inode = swap_inode;
+ filp.f_dentry = swap_dentry;
filp.f_mode = 3; /* read write */
- error = blkdev_open(swap_inode, &filp);
- p->swap_file = NULL;
- iput(swap_inode);
- if(error)
+ error = blkdev_open(swap_dentry->d_inode, &filp);
+ if (error)
goto bad_swap_2;
error = -ENODEV;
if (!p->swap_device ||
if (p->swap_device == swap_info[i].swap_device)
goto bad_swap;
}
- } else if (!S_ISREG(swap_inode->i_mode))
+ } else if (!S_ISREG(swap_dentry->d_inode->i_mode))
goto bad_swap;
p->swap_lockmap = (unsigned char *) get_free_page(GFP_USER);
if (!p->swap_lockmap) {
prev = i;
}
p->next = i;
- if (!getname(specialfile, &tmp)) {
- if ((p->swap_filename =
- (char *) kmalloc(strlen(tmp)+1, GFP_KERNEL)) != (char *)NULL)
- strcpy(p->swap_filename, tmp);
- putname(tmp);
- }
if (prev < 0) {
swap_list.head = swap_list.next = p - swap_info;
} else {
goto out;
bad_swap:
if(filp.f_op && filp.f_op->release)
- filp.f_op->release(filp.f_inode,&filp);
+ filp.f_op->release(filp.f_dentry->d_inode,&filp);
bad_swap_2:
free_page((long) p->swap_lockmap);
vfree(p->swap_map);
- iput(p->swap_file);
+ dput(p->swap_file);
p->swap_device = 0;
p->swap_file = NULL;
p->swap_map = NULL;
if (shm_swap(i, dma))
return 1;
state = 3;
+ case 3:
+ shrink_dcache(i);
+ state = 4;
default:
if (swap_out(i, dma, wait))
return 1;
if (acc_fd < 0 || acc_fd >= NR_OPEN ||
(file=current->files->fd[acc_fd])==NULL)
return -EBADF;
- if (!file->f_inode || !file->f_inode->i_sock)
+ if (!file->f_dentry->d_inode || !file->f_dentry->d_inode->i_sock)
return -ENOTSOCK;
- p->sock = &file->f_inode->u.socket_i;
+ p->sock = &file->f_dentry->d_inode->u.socket_i;
if (p->sock->state != SS_UNCONNECTED)
return -EINVAL;
}
static unsigned int netlink_poll(struct file *file, poll_table * wait)
{
unsigned int mask;
- unsigned int minor = MINOR(file->f_inode->i_rdev);
+ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
poll_wait(&read_space_wait[minor], wait);
mask = POLLOUT | POLLWRNORM;
file->f_op = &socket_file_ops;
file->f_mode = 3;
file->f_flags = O_RDWR;
- file->f_inode = inode;
- if (inode)
- atomic_inc(&inode->i_count);
+ file->f_dentry = d_alloc_root(inode, NULL);
file->f_pos = 0;
}
return fd;
return NULL;
}
- inode = file->f_inode;
+ inode = file->f_dentry->d_inode;
if (!inode || !inode->i_sock || !socki_lookup(inode))
{
*err = -ENOTSOCK;
- fput(file,inode);
+ fput(file);
return NULL;
}
extern __inline__ void sockfd_put(struct socket *sock)
{
- fput(sock->file,sock->inode);
+ fput(sock->file);
}
/*
{
struct socket *sock;
- sock = socki_lookup(file->f_inode);
+ sock = socki_lookup(file->f_dentry->d_inode);
/*
* We can't return errors to poll, so it's either yes or no.
{
struct socket *sock;
- sock = socki_lookup (filp->f_inode);
+ sock = socki_lookup (filp->f_dentry->d_inode);
if (sock && sock->ops && sock->ops->fcntl)
return sock->ops->fcntl(sock, cmd, arg);
return(-EINVAL);
static unix_socket *unix_find_other(struct sockaddr_un *sunname, int len,
int type, unsigned hash, int *error)
{
- unsigned long old_fs;
- int err;
- struct inode *inode;
unix_socket *u;
if (sunname->sun_path[0])
{
- old_fs=get_fs();
- set_fs(get_ds());
- err = open_namei(sunname->sun_path, 2, S_IFSOCK, &inode);
- set_fs(old_fs);
- if(err<0)
- {
- *error=err;
+ struct dentry *dentry;
+ dentry = open_namei(sunname->sun_path, 2, S_IFSOCK);
+ if (IS_ERR(dentry)) {
+ *error = PTR_ERR(dentry);
return NULL;
}
- u=unix_find_socket_byinode(inode);
- iput(inode);
+ u=unix_find_socket_byinode(dentry->d_inode);
+ dput(dentry);
if (u && u->type != type)
{
*error=-EPROTOTYPE;
{
struct sock *sk = sock->sk;
struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
- struct inode * inode;
- int old_fs;
+ struct dentry * dentry;
+ struct inode * inode = NULL;
int err;
unsigned hash;
struct unix_address *addr;
addr->hash = UNIX_HASH_SIZE;
sk->protinfo.af_unix.addr = addr;
- old_fs=get_fs();
- set_fs(get_ds());
- err=do_mknod(sunaddr->sun_path, S_IFSOCK|S_IRWXUGO, 0);
- if (!err)
- err=open_namei(sunaddr->sun_path, 2, S_IFSOCK, &inode);
-
- set_fs(old_fs);
-
+ dentry = do_mknod(sunaddr->sun_path, S_IFSOCK|S_IRWXUGO, 0);
+ err = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ inode = dentry->d_inode;
+ atomic_inc(&inode->i_count);
+ dput(dentry);
+ err = 0;
+ }
+
if(err<0)
{
unix_release_addr(addr);
extern inline unix_socket *unix_get_socket(struct file *filp)
{
unix_socket * u_sock = NULL;
- struct inode *inode = filp->f_inode;
+ struct inode *inode = filp->f_dentry->d_inode;
/*
* Socket ?