long cause, struct pt_regs *regs)
{
struct vm_area_struct * vma;
- struct task_struct *tsk = current;
- struct mm_struct *mm = tsk->mm;
+ struct mm_struct *mm = current->mm;
unsigned fixup;
down(&mm->mmap_sem);
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
}
- handle_mm_fault(tsk, vma, address, cause > 0);
+ handle_mm_fault(current, vma, address, cause > 0);
up(&mm->mmap_sem);
return;
up(&mm->mmap_sem);
if (user_mode(regs)) {
- force_sig(SIGSEGV, tsk);
+ force_sig(SIGSEGV, current);
return;
}
if ((fixup = search_exception_table(regs->pc)) != 0) {
unsigned long newpc;
newpc = fixup_exception(dpf_reg, fixup, regs->pc);
- printk("Taking exception at [<%lx>] (%lx)\n", regs->pc, newpc);
+ printk("%s: Exception at [<%lx>] (%lx)\n", current->comm, regs->pc, newpc);
regs->pc = newpc;
return;
}
lock_kernel();
filename = getname((char *) regs.ebx);
error = PTR_ERR(filename);
- if (IS_ERR(filename)
+ if (IS_ERR(filename))
goto out;
error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, ®s);
putname(filename);
/* 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,
+ tsk->comm,
regs->eip,
fixup);
regs->eip = fixup;
return -EBADF;
if (lo->lo_inode)
return -EBUSY;
- inode = file->f_inode;
+ inode = file->f_dentry->d_inode;
if (!inode) {
printk("loop_set_fd: NULL inode?!?\n");
return -EINVAL;
*/
__initfunc(static void rd_load_image(kdev_t device,int offset))
{
- struct inode inode, out_inode;
+ struct inode inode, out_inode;
struct file infile, outfile;
+ struct dentry in_dentry, out_dentry;
unsigned short fs;
kdev_t ram_device;
int nblocks, i;
memset(&infile, 0, sizeof(infile));
memset(&inode, 0, sizeof(inode));
+ memset(&in_dentry, 0, sizeof(in_dentry));
inode.i_rdev = device;
infile.f_mode = 1; /* read only */
- infile.f_inode = &inode;
+ infile.f_dentry = &in_dentry;
+ in_dentry.d_inode = &inode;
memset(&outfile, 0, sizeof(outfile));
memset(&out_inode, 0, sizeof(out_inode));
+ memset(&out_dentry, 0, sizeof(out_dentry));
out_inode.i_rdev = ram_device;
outfile.f_mode = 3; /* read/write */
- outfile.f_inode = &out_inode;
+ outfile.f_dentry = &out_dentry;
+ out_dentry.d_inode = &out_inode;
if (blkdev_open(&inode, &infile) != 0) return;
if (blkdev_open(&out_inode, &outfile) != 0) return;
printk(KERN_NOTICE "RAMDISK: Loading %d blocks into ram disk... ", nblocks);
for (i=0; i < nblocks; i++) {
- infile.f_op->read(infile.f_inode, &infile, buf,
+ infile.f_op->read(infile.f_dentry->d_inode, &infile, buf,
BLOCK_SIZE);
- outfile.f_op->write(outfile.f_inode, &outfile, buf,
+ outfile.f_op->write(outfile.f_dentry->d_inode, &outfile, buf,
BLOCK_SIZE);
if (!(i % 16)) {
printk("%c\b", rotator[rotate & 0x3]);
{
if (exit_code) return -1;
- insize = crd_infp->f_op->read(crd_infp->f_inode, crd_infp,
+ insize = crd_infp->f_op->read(crd_infp->f_dentry->d_inode, crd_infp,
inbuf, INBUFSIZ);
if (insize == 0) return -1;
unsigned n;
uch *in, ch;
- crd_outfp->f_op->write(crd_outfp->f_inode, crd_outfp, window,
+ crd_outfp->f_op->write(crd_outfp->f_dentry->d_inode, crd_outfp, window,
outcnt);
in = window;
for (n = 0; n < outcnt; n++) {
static unsigned int sg_poll(struct file *file, poll_table * wait)
{
- int dev = MINOR(file->f_inode->i_rdev);
+ int dev = MINOR(file->f_dentry->d_inode->i_rdev);
struct scsi_generic *device = &scsi_generics[dev];
unsigned int mask = 0;
struct inode *inode;
int ret = 0;
- inode = file->f_inode;
+ inode = file->f_dentry->d_inode;
if (sound_select (inode, file, SEL_IN, wait))
ret |= POLLIN;
vma->vm_page_prot))
return -EAGAIN;
- vma->vm_inode = inode;
- atomic_inc(&inode->i_count);
+ vma->vm_dentry = dget(file->f_dentry);
dmap->mapping_flags |= DMA_MAP_MAPPED;
sbi->pipe = fget(pipefd);
if ( !sbi->pipe || !sbi->pipe->f_op || !sbi->pipe->f_op->write ) {
if ( sbi->pipe ) {
- fput(sbi->pipe, sbi->pipe->f_inode);
+ fput(sbi->pipe);
printk("autofs: pipe file descriptor does not contain proper ops\n");
} else {
printk("autofs: could not open pipe file descriptor\n");
wake_up(&wq->queue);
wq = nwq;
}
- fput(sbi->pipe, sbi->pipe->f_inode); /* Close the pipe */
+ fput(sbi->pipe); /* Close the pipe */
}
static int autofs_write(struct file *file, const void *addr, int bytes)
old_signal = current->signal;
- while ( bytes && (written = file->f_op->write(file->f_inode,file,data,bytes)) > 0 ) {
+ while ( bytes && (written = file->f_op->write(file->f_dentry->d_inode,file,data,bytes)) > 0 ) {
data += written;
bytes -= written;
}
__MOD_INC_USE_COUNT(current->binfmt->module);
#ifndef VM_STACK_FLAGS
- current->executable = bprm->dentry;
- atomic_inc(&bprm->dentry->i_count);
+ current->executable = dget(bprm->dentry);
#endif
#ifdef LOW_ELF_STACK
current->start_stack = bprm->p = elf_stack - 4;
char *i_name;
int len;
int retval;
+ struct dentry * dentry;
unsigned char *ucp = (unsigned char *) bprm->buf;
+
if ((ucp[0] != 0xca) || (ucp[1] != 0xfe) || (ucp[2] != 0xba) || (ucp[3] != 0xbe))
return -ENOEXEC;
bprm->java = 1;
- iput(bprm->inode);
- bprm->dont_iput=1;
+ dput(bprm->dentry);
+ bprm->dentry = NULL;
/*
* Set args: [0] the name of the java interpreter
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.
*/
bprm->filename = binfmt_java_interpreter;
- retval = open_namei(binfmt_java_interpreter, 0, 0, &bprm->inode);
- if (retval)
+ dentry = open_namei(binfmt_java_interpreter, 0, 0);
+ retval = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
return retval;
- bprm->dont_iput=0;
- retval=prepare_binprm(bprm);
- if(retval<0)
+
+ bprm->dentry = dentry;
+ retval = prepare_binprm(bprm);
+ if (retval < 0)
return retval;
return search_binary_handler(bprm,regs);
static int do_load_applet(struct linux_binprm *bprm,struct pt_regs *regs)
{
char *i_name;
+ struct dentry * dentry;
int retval;
+
if (strncmp (bprm->buf, "<!--applet", 10))
return -ENOEXEC;
- iput(bprm->inode);
- bprm->dont_iput=1;
+ dput(bprm->dentry);
+ bprm->dentry = NULL;
/*
* Set args: [0] the name of the appletviewer
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.
*/
bprm->filename = binfmt_java_appletviewer;
- retval = open_namei(binfmt_java_appletviewer, 0, 0, &bprm->inode);
- if (retval)
+ dentry = open_namei(binfmt_java_appletviewer, 0, 0);
+ retval = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
return retval;
- bprm->dont_iput=0;
- retval=prepare_binprm(bprm);
- if(retval<0)
+
+ bprm->dentry = dentry;
+ retval = prepare_binprm(bprm);
+ if (retval < 0)
return retval;
return search_binary_handler(bprm,regs);
static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
{
struct binfmt_entry *fmt;
+ struct dentry * dentry;
char iname[128];
char *iname_addr = iname, *p;
int retval, fmt_flags = 0;
goto _ret;
}
- iput(bprm->inode);
- bprm->dont_iput = 1;
+ dput(bprm->dentry);
+ bprm->dentry = NULL;
/* Build args for interpreter */
if ((fmt_flags & ENTRY_STRIP_EXT) &&
}
bprm->filename = iname; /* for binfmt_script */
- if ((retval = open_namei(iname, 0, 0, &bprm->inode)))
+ dentry = open_namei(iname, 0, 0);
+ retval = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
goto _ret;
- bprm->dont_iput = 0;
+ bprm->dentry = dentry;
- if ((retval = prepare_binprm(bprm)) >= 0)
+ retval = prepare_binprm(bprm);
+ if (retval >= 0)
retval = search_binary_handler(bprm, regs);
_ret:
return retval;
if (root_inode) {
res = d_alloc(NULL, &(const struct qstr) { "/", 1, 0 });
res->d_parent = res;
- res->d_count = 2;
+ res->d_count = 1;
d_instantiate(res, root_inode);
}
return res;
printk(KERN_DEBUG "VFS: Disk change detected on device %s\n",
kdevname(dev));
- for (i=0 ; i<NR_SUPER ; i++)
- if (super_blocks[i].s_dev == dev)
- put_super(super_blocks[i].s_dev);
+
invalidate_inodes(dev);
invalidate_buffers(dev);
int fs_may_umount(kdev_t dev, struct dentry * root)
{
- return 0;
+ shrink_dcache();
+ return root->d_count == 1;
}
int fs_may_remount_ro(kdev_t dev)
}
/* Internal lookup() using the new generic dcache. */
-static inline struct dentry * cached_lookup(struct dentry * parent, struct qstr * name)
+static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name)
{
struct dentry * dentry = d_lookup(parent, name);
if (name->name[1] != '.')
break;
- if (parent != current->fs->root) {
+ if (parent != current->fs->root)
parent = parent->d_covers->d_parent;
- }
/* fallthrough */
case 1:
- result = dget(parent);
- break;
+ result = parent;
}
}
return result;
}
-static inline int is_reserved(struct dentry *dentry)
-{
- if (dentry->d_name.name[0] == '.') {
- switch (dentry->d_name.len) {
- case 2:
- if (dentry->d_name.name[1] != '.')
- break;
- /* fallthrough */
- case 1:
- return 1;
- }
- }
- return 0;
-}
-
/* In difference to the former version, lookup() no longer eats the dir. */
static struct dentry * lookup(struct dentry * dir, struct qstr * name)
{
err = permission(dir->d_inode, MAY_EXEC);
result = ERR_PTR(err);
if (err)
- goto done;
+ goto done_error;
result = reserved_lookup(dir, name);
if (result)
- goto done;
+ goto done_noerror;
result = cached_lookup(dir, name);
if (result)
- goto done;
+ goto done_noerror;
result = real_lookup(dir, name);
- if (!result)
- result = ERR_PTR(-ENOTDIR);
-done:
- if (!IS_ERR(result))
- result = dget(result->d_mounts);
+ if (!IS_ERR(result)) {
+done_noerror:
+ result = dget(result->d_mounts);
+ }
+done_error:
return result;
}
{
struct inode * inode = dentry->d_inode;
- if (inode->i_op && inode->i_op->follow_link) {
+ if (inode && inode->i_op && inode->i_op->follow_link) {
struct dentry *result;
/* This eats the base */
base = dget(current->fs->pwd);
}
- if (*name == '\0')
+ if (!*name)
return base;
/* At this point we know we have a real path component. */
int len;
unsigned long hash;
struct qstr this;
- char c, trailing;
+ char c, follow;
+ dentry = ERR_PTR(-ENOENT);
+ if (!base->d_inode)
+ break;
this.name = name;
hash = init_name_hash();
- for (len = 0; (c = *name++) && (c != '/') ; len++)
+ len = 0;
+ c = *name;
+ do {
+ len++; name++;
hash = partial_name_hash(c, hash);
+ c = *name;
+ } while (c && (c != '/'));
this.len = len;
this.hash = end_name_hash(hash);
/* remove trailing slashes? */
- trailing = c;
+ follow = follow_link;
if (c) {
- while ((c = *name) == '/')
- name++;
+ follow |= c;
+ do {
+ c = *++name;
+ } while (c == '/');
}
dentry = lookup(base, &this);
if (IS_ERR(dentry))
break;
- if (!dentry->d_inode)
- break;
- /* Last component? */
- if (!c) {
- if (!trailing && !follow_link)
- break;
- return do_follow_link(base, dentry);
- }
+ if (!follow)
+ break;
base = do_follow_link(base, dentry);
+ if (c)
+ continue;
+
+ return base;
}
dput(base);
return dentry;
static inline struct inode *get_parent(struct dentry *dentry)
{
- struct inode *dir = dentry->d_parent->d_inode;
-
- atomic_inc(&dir->i_count);
- return dir;
+ return dentry->d_parent->d_inode;
}
static inline struct inode *lock_parent(struct dentry *dentry)
{
struct inode *dir = dentry->d_parent->d_inode;
- atomic_inc(&dir->i_count);
down(&dir->i_sem);
return dir;
}
acc_mode = 0;
}
up(&dir->i_sem);
- iput(dir);
if (error)
goto exit;
}
exit_lock:
up(&dir->i_sem);
- iput(dir);
dput(dentry);
return retval;
}
exit_lock:
up(&dir->i_sem);
- iput(dir);
dput(dentry);
exit:
return error;
exit_lock:
up(&dir->i_sem);
- iput(dir);
dput(dentry);
exit:
return error;
exit_lock:
up(&dir->i_sem);
- iput(dir);
dput(dentry);
exit:
return error;
exit_lock:
up(&dir->i_sem);
- iput(dir);
dput(dentry);
exit:
return error;
exit_lock:
up(&dir->i_sem);
- iput(dir);
dput(new_dentry);
exit_old:
dput(old_dentry);
}
}
+static inline int is_reserved(struct dentry *dentry)
+{
+ if (dentry->d_name.name[0] == '.') {
+ switch (dentry->d_name.len) {
+ case 2:
+ if (dentry->d_name.name[1] != '.')
+ break;
+ /* fallthrough */
+ case 1:
+ return 1;
+ }
+ }
+ return 0;
+}
+
static inline int do_rename(const char * oldname, const char * newname)
{
int error;
exit_lock:
up(&new_dir->i_sem);
up(&old_dir->i_sem);
- iput(old_dir);
- iput(new_dir);
dput(new_dentry);
exit_old:
dput(old_dentry);
goto close_f12_inode_i;
j = error;
- f1->f_dentry = f2->f_dentry = d_alloc_root(inode, NULL);
+ f1->f_dentry = f2->f_dentry = dget(d_alloc_root(inode, NULL));
/* read file */
f1->f_pos = f2->f_pos = 0;
return NULL;
}
-void put_super(kdev_t dev)
-{
- struct super_block * sb;
-
- if (dev == ROOT_DEV) {
- printk("VFS: Root device %s: prepare for armageddon\n",
- kdevname(dev));
- return;
- }
- if (!(sb = get_super(dev)))
- return;
- if (sb->s_root != sb->s_root->d_mounts) {
- printk("VFS: Mounted device %s - tssk, tssk\n",
- kdevname(dev));
- return;
- }
- if (sb->s_op && sb->s_op->put_super)
- sb->s_op->put_super(sb);
-}
-
asmlinkage int sys_ustat(dev_t dev, struct ustat * ubuf)
{
struct super_block *s;
{
struct dentry * covers = dentry->d_covers;
- if (covers == dentry) {
- printk("VFS: unmount - covers == dentry?\n");
- return;
+ if (covers != dentry) {
+ covers->d_mounts = covers;
+ dentry->d_covers = dentry;
+ dput(covers);
+ dput(dentry);
}
- covers->d_mounts = covers;
- dentry->d_covers = dentry;
- dput(covers);
- dput(dentry);
}
static void d_mount(struct dentry *covers, struct dentry *dentry)
printk("VFS: mount - already mounted\n");
return;
}
- covers->d_mounts = dget(dentry);
- dentry->d_covers = dget(covers);
+ covers->d_mounts = dentry;
+ dentry->d_covers = covers;
}
static int do_umount(kdev_t dev,int unmount_root)
struct super_block * sb;
int retval;
+ sb = get_super(dev);
+ if (!sb)
+ return -ENOENT;
+
+ if (!sb->s_root)
+ return -ENOENT;
+
if (dev==ROOT_DEV && !unmount_root) {
/*
* Special case for "unmounting" root. We just try to remount
* it readonly, and sync() the device.
*/
- if (!(sb=get_super(dev)))
- return -ENOENT;
if (!(sb->s_flags & MS_RDONLY)) {
/*
* Make sure all quotas are turned off on this device we need to mount
}
return 0;
}
- sb=get_super(dev);
- if (!sb)
- return -ENOENT;
/*
* Before checking if the filesystem is still busy make sure the kernel
if (!fs_may_umount(dev, sb->s_root))
return -EBUSY;
- /* Clear up the dcache tree. This should be cleaner.. */
- if (sb->s_root) {
- d_umount(sb->s_root);
- d_delete(sb->s_root);
- }
-
+ /* clean up dcache .. */
+ d_umount(sb->s_root);
sb->s_root = NULL;
- if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
- sb->s_op->write_super(sb);
- put_super(dev);
+
+ if (sb->s_op) {
+ if (sb->s_op->write_super && sb->s_dirt)
+ sb->s_op->write_super(sb);
+ if (sb->s_op->put_super)
+ sb->s_op->put_super(sb);
+ }
remove_vfsmnt(dev);
return 0;
}
+static int umount_dev(kdev_t dev)
+{
+ int retval;
+ struct inode * inode = get_empty_inode();
+
+ inode->i_rdev = dev;
+ if (MAJOR(dev) >= MAX_BLKDEV)
+ return -ENXIO;
+
+ retval = do_umount(dev,0);
+ if (!retval) {
+ fsync_dev(dev);
+ if (dev != ROOT_DEV) {
+ blkdev_release(inode);
+ put_unnamed_dev(dev);
+ }
+ }
+ iput(inode);
+ return retval;
+}
+
/*
* Now umount can handle mount points as well as block devices.
* This is important for filesystems which use unnamed block devices.
asmlinkage int sys_umount(char * name)
{
struct dentry * dentry;
- struct inode * inode;
- kdev_t dev;
- struct inode * dummy_inode = NULL;
int retval;
if (!suser())
lock_kernel();
dentry = namei(name);
retval = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- goto out;
-
- inode = dentry->d_inode;
- if (S_ISBLK(inode->i_mode)) {
- dev = inode->i_rdev;
- retval = -EACCES;
- if (IS_NODEV(inode)) {
- dput(dentry);
- goto out;
- }
- } else {
- retval = -EINVAL;
- if (!inode->i_sb || inode != inode->i_sb->s_root->d_inode) {
- dput(dentry);
- goto out;
+ if (!IS_ERR(dentry)) {
+ struct inode * inode = dentry->d_inode;
+ kdev_t dev = inode->i_rdev;
+
+ retval = 0;
+ if (S_ISBLK(inode->i_mode)) {
+ if (IS_NODEV(inode))
+ retval = -EACCES;
+ } else {
+ struct super_block *sb = inode->i_sb;
+ retval = -EINVAL;
+ if (sb && inode == sb->s_root->d_inode) {
+ dev = sb->s_dev;
+ retval = 0;
+ }
}
- dev = inode->i_sb->s_dev;
- dput(dentry);
- inode = dummy_inode = get_empty_inode();
- inode->i_rdev = dev;
- }
- retval = -ENXIO;
- if (MAJOR(dev) >= MAX_BLKDEV) {
dput(dentry);
- goto out;
- }
- retval = do_umount(dev,0);
- if (!retval) {
- fsync_dev(dev);
- if (dev != ROOT_DEV) {
- blkdev_release (inode);
- put_unnamed_dev(dev);
- }
+
+ if (!retval)
+ retval = umount_dev(dev);
}
- dput(dentry);
- if (!retval)
- fsync_dev(dev);
-out:
unlock_kernel();
return retval;
}
{
kdev_t old_root_dev;
struct vfsmount *vfsmnt;
- struct inode *old_root,*old_pwd,*inode;
- unsigned long old_fs;
+ struct dentry *old_root,*old_pwd,*dir_d = NULL;
int error;
old_root = current->fs->root;
}
ROOT_DEV = new_root_dev;
do_mount_root();
- old_fs = get_fs();
- set_fs(get_ds());
- error = namei(put_old, &inode);
- if (error) inode = NULL;
- set_fs(old_fs);
- if (!error && (atomic_read(&inode->i_count) != 1 || inode->i_mount))
+ dir_d = lookup_dentry(put_old, NULL, 1);
+ if (IS_ERR(dir_d)) {
+ error = PTR_ERR(dir_d);
+ } else if (!dir_d->d_inode) {
+ dput(dir_d);
+ error = -ENOENT;
+ } else {
+ error = 0;
+ }
+ if (!error && dir_d->d_covers != dir_d) {
+ dput(dir_d);
error = -EBUSY;
- if (!error && !S_ISDIR(inode->i_mode))
+ }
+ if (!error && !S_ISDIR(dir_d->d_inode->i_mode)) {
+ dput(dir_d);
error = -ENOTDIR;
- iput(old_root); /* current->fs->root */
- iput(old_pwd); /* current->fs->pwd */
+ }
+ dput(old_root);
+ dput(old_pwd);
if (error) {
int umount_error;
- if (inode) iput(inode);
printk(KERN_NOTICE "Trying to unmount old root ... ");
- old_root->i_mount = old_root;
- /* does this belong into do_mount_root ? */
umount_error = do_umount(old_root_dev,1);
if (umount_error) printk(KERN_ERR "error %d\n",umount_error);
else {
}
return umount_error ? error : 0;
}
- iput(old_root); /* sb->s_covered */
remove_vfsmnt(old_root_dev);
vfsmnt = add_vfsmnt(old_root_dev,"/dev/root.old",put_old);
if (!vfsmnt) printk(KERN_CRIT "Trouble: add_vfsmnt failed\n");
else {
- vfsmnt->mnt_sb = old_root->i_sb;
- vfsmnt->mnt_sb->s_covered = inode;
+ vfsmnt->mnt_sb = old_root->d_inode->i_sb;
+ d_mount(dir_d,vfsmnt->mnt_sb->s_root);
vfsmnt->mnt_flags = vfsmnt->mnt_sb->s_flags;
}
- inode->i_mount = old_root;
+ d_umount(old_root);
+ d_mount(dir_d,old_root);
return 0;
}