Commit 13e551b9 authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.45pre6

parent ca6ede75
...@@ -67,8 +67,7 @@ asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr, ...@@ -67,8 +67,7 @@ asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr,
long cause, struct pt_regs *regs) long cause, struct pt_regs *regs)
{ {
struct vm_area_struct * vma; struct vm_area_struct * vma;
struct task_struct *tsk = current; struct mm_struct *mm = current->mm;
struct mm_struct *mm = tsk->mm;
unsigned fixup; unsigned fixup;
down(&mm->mmap_sem); down(&mm->mmap_sem);
...@@ -97,7 +96,7 @@ asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr, ...@@ -97,7 +96,7 @@ asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr,
if (!(vma->vm_flags & VM_WRITE)) if (!(vma->vm_flags & VM_WRITE))
goto bad_area; goto bad_area;
} }
handle_mm_fault(tsk, vma, address, cause > 0); handle_mm_fault(current, vma, address, cause > 0);
up(&mm->mmap_sem); up(&mm->mmap_sem);
return; return;
...@@ -109,7 +108,7 @@ asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr, ...@@ -109,7 +108,7 @@ asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr,
up(&mm->mmap_sem); up(&mm->mmap_sem);
if (user_mode(regs)) { if (user_mode(regs)) {
force_sig(SIGSEGV, tsk); force_sig(SIGSEGV, current);
return; return;
} }
...@@ -117,7 +116,7 @@ asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr, ...@@ -117,7 +116,7 @@ asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr,
if ((fixup = search_exception_table(regs->pc)) != 0) { if ((fixup = search_exception_table(regs->pc)) != 0) {
unsigned long newpc; unsigned long newpc;
newpc = fixup_exception(dpf_reg, fixup, regs->pc); 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; regs->pc = newpc;
return; return;
} }
......
...@@ -625,7 +625,7 @@ asmlinkage int sys_execve(struct pt_regs regs) ...@@ -625,7 +625,7 @@ asmlinkage int sys_execve(struct pt_regs regs)
lock_kernel(); lock_kernel();
filename = getname((char *) regs.ebx); filename = getname((char *) regs.ebx);
error = PTR_ERR(filename); error = PTR_ERR(filename);
if (IS_ERR(filename) if (IS_ERR(filename))
goto out; goto out;
error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs); error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs);
putname(filename); putname(filename);
......
...@@ -173,7 +173,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) ...@@ -173,7 +173,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
/* Are we prepared to handle this kernel fault? */ /* Are we prepared to handle this kernel fault? */
if ((fixup = search_exception_table(regs->eip)) != 0) { if ((fixup = search_exception_table(regs->eip)) != 0) {
printk(KERN_DEBUG "%s: Exception at [<%lx>] (%lx)\n", printk(KERN_DEBUG "%s: Exception at [<%lx>] (%lx)\n",
current->comm, tsk->comm,
regs->eip, regs->eip,
fixup); fixup);
regs->eip = fixup; regs->eip = fixup;
......
...@@ -292,7 +292,7 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg) ...@@ -292,7 +292,7 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg)
return -EBADF; return -EBADF;
if (lo->lo_inode) if (lo->lo_inode)
return -EBUSY; return -EBUSY;
inode = file->f_inode; inode = file->f_dentry->d_inode;
if (!inode) { if (!inode) {
printk("loop_set_fd: NULL inode?!?\n"); printk("loop_set_fd: NULL inode?!?\n");
return -EINVAL; return -EINVAL;
......
...@@ -444,8 +444,9 @@ identify_ramdisk_image(kdev_t device, struct file *fp, int start_block)) ...@@ -444,8 +444,9 @@ identify_ramdisk_image(kdev_t device, struct file *fp, int start_block))
*/ */
__initfunc(static void rd_load_image(kdev_t device,int offset)) __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 file infile, outfile;
struct dentry in_dentry, out_dentry;
unsigned short fs; unsigned short fs;
kdev_t ram_device; kdev_t ram_device;
int nblocks, i; int nblocks, i;
...@@ -457,15 +458,19 @@ __initfunc(static void rd_load_image(kdev_t device,int offset)) ...@@ -457,15 +458,19 @@ __initfunc(static void rd_load_image(kdev_t device,int offset))
memset(&infile, 0, sizeof(infile)); memset(&infile, 0, sizeof(infile));
memset(&inode, 0, sizeof(inode)); memset(&inode, 0, sizeof(inode));
memset(&in_dentry, 0, sizeof(in_dentry));
inode.i_rdev = device; inode.i_rdev = device;
infile.f_mode = 1; /* read only */ 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(&outfile, 0, sizeof(outfile));
memset(&out_inode, 0, sizeof(out_inode)); memset(&out_inode, 0, sizeof(out_inode));
memset(&out_dentry, 0, sizeof(out_dentry));
out_inode.i_rdev = ram_device; out_inode.i_rdev = ram_device;
outfile.f_mode = 3; /* read/write */ 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(&inode, &infile) != 0) return;
if (blkdev_open(&out_inode, &outfile) != 0) return; if (blkdev_open(&out_inode, &outfile) != 0) return;
...@@ -506,9 +511,9 @@ __initfunc(static void rd_load_image(kdev_t device,int offset)) ...@@ -506,9 +511,9 @@ __initfunc(static void rd_load_image(kdev_t device,int offset))
printk(KERN_NOTICE "RAMDISK: Loading %d blocks into ram disk... ", nblocks); printk(KERN_NOTICE "RAMDISK: Loading %d blocks into ram disk... ", nblocks);
for (i=0; i < nblocks; i++) { 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); BLOCK_SIZE);
outfile.f_op->write(outfile.f_inode, &outfile, buf, outfile.f_op->write(outfile.f_dentry->d_inode, &outfile, buf,
BLOCK_SIZE); BLOCK_SIZE);
if (!(i % 16)) { if (!(i % 16)) {
printk("%c\b", rotator[rotate & 0x3]); printk("%c\b", rotator[rotate & 0x3]);
...@@ -637,7 +642,7 @@ __initfunc(static int fill_inbuf(void)) ...@@ -637,7 +642,7 @@ __initfunc(static int fill_inbuf(void))
{ {
if (exit_code) return -1; 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); inbuf, INBUFSIZ);
if (insize == 0) return -1; if (insize == 0) return -1;
...@@ -656,7 +661,7 @@ __initfunc(static void flush_window(void)) ...@@ -656,7 +661,7 @@ __initfunc(static void flush_window(void))
unsigned n; unsigned n;
uch *in, ch; 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); outcnt);
in = window; in = window;
for (n = 0; n < outcnt; n++) { for (n = 0; n < outcnt; n++) {
......
...@@ -488,7 +488,7 @@ static long sg_write(struct inode *inode,struct file *filp,const char *buf,unsig ...@@ -488,7 +488,7 @@ static long sg_write(struct inode *inode,struct file *filp,const char *buf,unsig
static unsigned int sg_poll(struct file *file, poll_table * wait) 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]; struct scsi_generic *device = &scsi_generics[dev];
unsigned int mask = 0; unsigned int mask = 0;
......
...@@ -246,7 +246,7 @@ sound_poll (struct file *file, poll_table * wait) ...@@ -246,7 +246,7 @@ sound_poll (struct file *file, poll_table * wait)
struct inode *inode; struct inode *inode;
int ret = 0; int ret = 0;
inode = file->f_inode; inode = file->f_dentry->d_inode;
if (sound_select (inode, file, SEL_IN, wait)) if (sound_select (inode, file, SEL_IN, wait))
ret |= POLLIN; ret |= POLLIN;
...@@ -326,8 +326,7 @@ sound_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma) ...@@ -326,8 +326,7 @@ sound_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma)
vma->vm_page_prot)) vma->vm_page_prot))
return -EAGAIN; return -EAGAIN;
vma->vm_inode = inode; vma->vm_dentry = dget(file->f_dentry);
atomic_inc(&inode->i_count);
dmap->mapping_flags |= DMA_MAP_MAPPED; dmap->mapping_flags |= DMA_MAP_MAPPED;
......
...@@ -194,7 +194,7 @@ struct super_block *autofs_read_super(struct super_block *s, void *data, ...@@ -194,7 +194,7 @@ struct super_block *autofs_read_super(struct super_block *s, void *data,
sbi->pipe = fget(pipefd); sbi->pipe = fget(pipefd);
if ( !sbi->pipe || !sbi->pipe->f_op || !sbi->pipe->f_op->write ) { if ( !sbi->pipe || !sbi->pipe->f_op || !sbi->pipe->f_op->write ) {
if ( sbi->pipe ) { if ( sbi->pipe ) {
fput(sbi->pipe, sbi->pipe->f_inode); fput(sbi->pipe);
printk("autofs: pipe file descriptor does not contain proper ops\n"); printk("autofs: pipe file descriptor does not contain proper ops\n");
} else { } else {
printk("autofs: could not open pipe file descriptor\n"); printk("autofs: could not open pipe file descriptor\n");
......
...@@ -37,7 +37,7 @@ void autofs_catatonic_mode(struct autofs_sb_info *sbi) ...@@ -37,7 +37,7 @@ void autofs_catatonic_mode(struct autofs_sb_info *sbi)
wake_up(&wq->queue); wake_up(&wq->queue);
wq = nwq; 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) static int autofs_write(struct file *file, const void *addr, int bytes)
...@@ -55,7 +55,7 @@ static int autofs_write(struct file *file, const void *addr, int bytes) ...@@ -55,7 +55,7 @@ static int autofs_write(struct file *file, const void *addr, int bytes)
old_signal = current->signal; 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; data += written;
bytes -= written; bytes -= written;
} }
......
...@@ -678,8 +678,7 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -678,8 +678,7 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
__MOD_INC_USE_COUNT(current->binfmt->module); __MOD_INC_USE_COUNT(current->binfmt->module);
#ifndef VM_STACK_FLAGS #ifndef VM_STACK_FLAGS
current->executable = bprm->dentry; current->executable = dget(bprm->dentry);
atomic_inc(&bprm->dentry->i_count);
#endif #endif
#ifdef LOW_ELF_STACK #ifdef LOW_ELF_STACK
current->start_stack = bprm->p = elf_stack - 4; current->start_stack = bprm->p = elf_stack - 4;
......
...@@ -28,7 +28,9 @@ static int do_load_java(struct linux_binprm *bprm,struct pt_regs *regs) ...@@ -28,7 +28,9 @@ static int do_load_java(struct linux_binprm *bprm,struct pt_regs *regs)
char *i_name; char *i_name;
int len; int len;
int retval; int retval;
struct dentry * dentry;
unsigned char *ucp = (unsigned char *) bprm->buf; unsigned char *ucp = (unsigned char *) bprm->buf;
if ((ucp[0] != 0xca) || (ucp[1] != 0xfe) || (ucp[2] != 0xba) || (ucp[3] != 0xbe)) if ((ucp[0] != 0xca) || (ucp[1] != 0xfe) || (ucp[2] != 0xba) || (ucp[3] != 0xbe))
return -ENOEXEC; return -ENOEXEC;
...@@ -42,8 +44,8 @@ static int do_load_java(struct linux_binprm *bprm,struct pt_regs *regs) ...@@ -42,8 +44,8 @@ static int do_load_java(struct linux_binprm *bprm,struct pt_regs *regs)
bprm->java = 1; bprm->java = 1;
iput(bprm->inode); dput(bprm->dentry);
bprm->dont_iput=1; bprm->dentry = NULL;
/* /*
* Set args: [0] the name of the java interpreter * Set args: [0] the name of the java interpreter
...@@ -75,15 +77,17 @@ static int do_load_java(struct linux_binprm *bprm,struct pt_regs *regs) ...@@ -75,15 +77,17 @@ static int do_load_java(struct linux_binprm *bprm,struct pt_regs *regs)
if (!bprm->p) if (!bprm->p)
return -E2BIG; 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; bprm->filename = binfmt_java_interpreter;
retval = open_namei(binfmt_java_interpreter, 0, 0, &bprm->inode); dentry = open_namei(binfmt_java_interpreter, 0, 0);
if (retval) retval = PTR_ERR(dentry);
if (IS_ERR(dentry))
return retval; return retval;
bprm->dont_iput=0;
retval=prepare_binprm(bprm); bprm->dentry = dentry;
if(retval<0) retval = prepare_binprm(bprm);
if (retval < 0)
return retval; return retval;
return search_binary_handler(bprm,regs); return search_binary_handler(bprm,regs);
...@@ -92,12 +96,14 @@ static int do_load_java(struct linux_binprm *bprm,struct pt_regs *regs) ...@@ -92,12 +96,14 @@ static int do_load_java(struct linux_binprm *bprm,struct pt_regs *regs)
static int do_load_applet(struct linux_binprm *bprm,struct pt_regs *regs) static int do_load_applet(struct linux_binprm *bprm,struct pt_regs *regs)
{ {
char *i_name; char *i_name;
struct dentry * dentry;
int retval; int retval;
if (strncmp (bprm->buf, "<!--applet", 10)) if (strncmp (bprm->buf, "<!--applet", 10))
return -ENOEXEC; return -ENOEXEC;
iput(bprm->inode); dput(bprm->dentry);
bprm->dont_iput=1; bprm->dentry = NULL;
/* /*
* Set args: [0] the name of the appletviewer * Set args: [0] the name of the appletviewer
...@@ -118,15 +124,17 @@ static int do_load_applet(struct linux_binprm *bprm,struct pt_regs *regs) ...@@ -118,15 +124,17 @@ static int do_load_applet(struct linux_binprm *bprm,struct pt_regs *regs)
if (!bprm->p) if (!bprm->p)
return -E2BIG; 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; bprm->filename = binfmt_java_appletviewer;
retval = open_namei(binfmt_java_appletviewer, 0, 0, &bprm->inode); dentry = open_namei(binfmt_java_appletviewer, 0, 0);
if (retval) retval = PTR_ERR(dentry);
if (IS_ERR(dentry))
return retval; return retval;
bprm->dont_iput=0;
retval=prepare_binprm(bprm); bprm->dentry = dentry;
if(retval<0) retval = prepare_binprm(bprm);
if (retval < 0)
return retval; return retval;
return search_binary_handler(bprm,regs); return search_binary_handler(bprm,regs);
......
...@@ -157,6 +157,7 @@ static struct binfmt_entry *check_file(struct linux_binprm *bprm) ...@@ -157,6 +157,7 @@ static struct binfmt_entry *check_file(struct linux_binprm *bprm)
static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
{ {
struct binfmt_entry *fmt; struct binfmt_entry *fmt;
struct dentry * dentry;
char iname[128]; char iname[128];
char *iname_addr = iname, *p; char *iname_addr = iname, *p;
int retval, fmt_flags = 0; int retval, fmt_flags = 0;
...@@ -179,8 +180,8 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) ...@@ -179,8 +180,8 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
goto _ret; goto _ret;
} }
iput(bprm->inode); dput(bprm->dentry);
bprm->dont_iput = 1; bprm->dentry = NULL;
/* Build args for interpreter */ /* Build args for interpreter */
if ((fmt_flags & ENTRY_STRIP_EXT) && if ((fmt_flags & ENTRY_STRIP_EXT) &&
...@@ -197,11 +198,14 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) ...@@ -197,11 +198,14 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
} }
bprm->filename = iname; /* for binfmt_script */ 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; 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); retval = search_binary_handler(bprm, regs);
_ret: _ret:
return retval; return retval;
......
...@@ -186,7 +186,7 @@ struct dentry * d_alloc_root(struct inode * root_inode, struct dentry *old_root) ...@@ -186,7 +186,7 @@ struct dentry * d_alloc_root(struct inode * root_inode, struct dentry *old_root)
if (root_inode) { if (root_inode) {
res = d_alloc(NULL, &(const struct qstr) { "/", 1, 0 }); res = d_alloc(NULL, &(const struct qstr) { "/", 1, 0 });
res->d_parent = res; res->d_parent = res;
res->d_count = 2; res->d_count = 1;
d_instantiate(res, root_inode); d_instantiate(res, root_inode);
} }
return res; return res;
......
...@@ -209,9 +209,7 @@ int check_disk_change(kdev_t dev) ...@@ -209,9 +209,7 @@ int check_disk_change(kdev_t dev)
printk(KERN_DEBUG "VFS: Disk change detected on device %s\n", printk(KERN_DEBUG "VFS: Disk change detected on device %s\n",
kdevname(dev)); 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_inodes(dev);
invalidate_buffers(dev); invalidate_buffers(dev);
......
...@@ -509,7 +509,8 @@ int fs_may_mount(kdev_t dev) ...@@ -509,7 +509,8 @@ int fs_may_mount(kdev_t dev)
int fs_may_umount(kdev_t dev, struct dentry * root) 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) int fs_may_remount_ro(kdev_t dev)
......
...@@ -275,7 +275,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name) ...@@ -275,7 +275,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name)
} }
/* Internal lookup() using the new generic dcache. */ /* 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); struct dentry * dentry = d_lookup(parent, name);
...@@ -318,33 +318,16 @@ static struct dentry * reserved_lookup(struct dentry * parent, struct qstr * nam ...@@ -318,33 +318,16 @@ static struct dentry * reserved_lookup(struct dentry * parent, struct qstr * nam
if (name->name[1] != '.') if (name->name[1] != '.')
break; break;
if (parent != current->fs->root) { if (parent != current->fs->root)
parent = parent->d_covers->d_parent; parent = parent->d_covers->d_parent;
}
/* fallthrough */ /* fallthrough */
case 1: case 1:
result = dget(parent); result = parent;
break;
} }
} }
return result; 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. */ /* In difference to the former version, lookup() no longer eats the dir. */
static struct dentry * lookup(struct dentry * dir, struct qstr * name) static struct dentry * lookup(struct dentry * dir, struct qstr * name)
{ {
...@@ -355,23 +338,23 @@ static struct dentry * lookup(struct dentry * dir, struct qstr * name) ...@@ -355,23 +338,23 @@ static struct dentry * lookup(struct dentry * dir, struct qstr * name)
err = permission(dir->d_inode, MAY_EXEC); err = permission(dir->d_inode, MAY_EXEC);
result = ERR_PTR(err); result = ERR_PTR(err);
if (err) if (err)
goto done; goto done_error;
result = reserved_lookup(dir, name); result = reserved_lookup(dir, name);
if (result) if (result)
goto done; goto done_noerror;
result = cached_lookup(dir, name); result = cached_lookup(dir, name);
if (result) if (result)
goto done; goto done_noerror;
result = real_lookup(dir, name); 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; return result;
} }
...@@ -382,7 +365,7 @@ static struct dentry * do_follow_link(struct dentry *base, struct dentry *dentry ...@@ -382,7 +365,7 @@ static struct dentry * do_follow_link(struct dentry *base, struct dentry *dentry
{ {
struct inode * inode = dentry->d_inode; 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; struct dentry *result;
/* This eats the base */ /* This eats the base */
...@@ -415,7 +398,7 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo ...@@ -415,7 +398,7 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo
base = dget(current->fs->pwd); base = dget(current->fs->pwd);
} }
if (*name == '\0') if (!*name)
return base; return base;
/* At this point we know we have a real path component. */ /* At this point we know we have a real path component. */
...@@ -423,37 +406,45 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo ...@@ -423,37 +406,45 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo
int len; int len;
unsigned long hash; unsigned long hash;
struct qstr this; struct qstr this;
char c, trailing; char c, follow;
dentry = ERR_PTR(-ENOENT);
if (!base->d_inode)
break;
this.name = name; this.name = name;
hash = init_name_hash(); hash = init_name_hash();
for (len = 0; (c = *name++) && (c != '/') ; len++) len = 0;
c = *name;
do {
len++; name++;
hash = partial_name_hash(c, hash); hash = partial_name_hash(c, hash);
c = *name;
} while (c && (c != '/'));
this.len = len; this.len = len;
this.hash = end_name_hash(hash); this.hash = end_name_hash(hash);
/* remove trailing slashes? */ /* remove trailing slashes? */
trailing = c; follow = follow_link;
if (c) { if (c) {
while ((c = *name) == '/') follow |= c;
name++; do {
c = *++name;
} while (c == '/');
} }
dentry = lookup(base, &this); dentry = lookup(base, &this);
if (IS_ERR(dentry)) if (IS_ERR(dentry))
break; break;
if (!dentry->d_inode)
break;
/* Last component? */ if (!follow)
if (!c) { break;
if (!trailing && !follow_link)
break;
return do_follow_link(base, dentry);
}
base = do_follow_link(base, dentry); base = do_follow_link(base, dentry);
if (c)
continue;
return base;
} }
dput(base); dput(base);
return dentry; return dentry;
...@@ -491,17 +482,13 @@ struct dentry * __namei(const char *pathname, int follow_link) ...@@ -491,17 +482,13 @@ struct dentry * __namei(const char *pathname, int follow_link)
static inline struct inode *get_parent(struct dentry *dentry) static inline struct inode *get_parent(struct dentry *dentry)
{ {
struct inode *dir = dentry->d_parent->d_inode; return dentry->d_parent->d_inode;
atomic_inc(&dir->i_count);
return dir;
} }
static inline struct inode *lock_parent(struct dentry *dentry) static inline struct inode *lock_parent(struct dentry *dentry)
{ {
struct inode *dir = dentry->d_parent->d_inode; struct inode *dir = dentry->d_parent->d_inode;
atomic_inc(&dir->i_count);
down(&dir->i_sem); down(&dir->i_sem);
return dir; return dir;
} }
...@@ -557,7 +544,6 @@ struct dentry * open_namei(const char * pathname, int flag, int mode) ...@@ -557,7 +544,6 @@ struct dentry * open_namei(const char * pathname, int flag, int mode)
acc_mode = 0; acc_mode = 0;
} }
up(&dir->i_sem); up(&dir->i_sem);
iput(dir);
if (error) if (error)
goto exit; goto exit;
} }
...@@ -669,7 +655,6 @@ struct dentry * do_mknod(const char * filename, int mode, dev_t dev) ...@@ -669,7 +655,6 @@ struct dentry * do_mknod(const char * filename, int mode, dev_t dev)
exit_lock: exit_lock:
up(&dir->i_sem); up(&dir->i_sem);
iput(dir);
dput(dentry); dput(dentry);
return retval; return retval;
} }
...@@ -749,7 +734,6 @@ static inline int do_mkdir(const char * pathname, int mode) ...@@ -749,7 +734,6 @@ static inline int do_mkdir(const char * pathname, int mode)
exit_lock: exit_lock:
up(&dir->i_sem); up(&dir->i_sem);
iput(dir);
dput(dentry); dput(dentry);
exit: exit:
return error; return error;
...@@ -818,7 +802,6 @@ static inline int do_rmdir(const char * name) ...@@ -818,7 +802,6 @@ static inline int do_rmdir(const char * name)
exit_lock: exit_lock:
up(&dir->i_sem); up(&dir->i_sem);
iput(dir);
dput(dentry); dput(dentry);
exit: exit:
return error; return error;
...@@ -879,7 +862,6 @@ static inline int do_unlink(const char * name) ...@@ -879,7 +862,6 @@ static inline int do_unlink(const char * name)
exit_lock: exit_lock:
up(&dir->i_sem); up(&dir->i_sem);
iput(dir);
dput(dentry); dput(dentry);
exit: exit:
return error; return error;
...@@ -937,7 +919,6 @@ static inline int do_symlink(const char * oldname, const char * newname) ...@@ -937,7 +919,6 @@ static inline int do_symlink(const char * oldname, const char * newname)
exit_lock: exit_lock:
up(&dir->i_sem); up(&dir->i_sem);
iput(dir);
dput(dentry); dput(dentry);
exit: exit:
return error; return error;
...@@ -1021,7 +1002,6 @@ static inline int do_link(const char * oldname, const char * newname) ...@@ -1021,7 +1002,6 @@ static inline int do_link(const char * oldname, const char * newname)
exit_lock: exit_lock:
up(&dir->i_sem); up(&dir->i_sem);
iput(dir);
dput(new_dentry); dput(new_dentry);
exit_old: exit_old:
dput(old_dentry); dput(old_dentry);
...@@ -1069,6 +1049,21 @@ static inline void double_down(struct semaphore *s1, struct semaphore *s2) ...@@ -1069,6 +1049,21 @@ static inline void double_down(struct semaphore *s1, struct semaphore *s2)
} }
} }
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) static inline int do_rename(const char * oldname, const char * newname)
{ {
int error; int error;
...@@ -1138,8 +1133,6 @@ static inline int do_rename(const char * oldname, const char * newname) ...@@ -1138,8 +1133,6 @@ static inline int do_rename(const char * oldname, const char * newname)
exit_lock: exit_lock:
up(&new_dir->i_sem); up(&new_dir->i_sem);
up(&old_dir->i_sem); up(&old_dir->i_sem);
iput(old_dir);
iput(new_dir);
dput(new_dentry); dput(new_dentry);
exit_old: exit_old:
dput(old_dentry); dput(old_dentry);
......
...@@ -419,7 +419,7 @@ int do_pipe(int *fd) ...@@ -419,7 +419,7 @@ int do_pipe(int *fd)
goto close_f12_inode_i; goto close_f12_inode_i;
j = error; 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 */ /* read file */
f1->f_pos = f2->f_pos = 0; f1->f_pos = f2->f_pos = 0;
......
...@@ -455,26 +455,6 @@ struct super_block * get_super(kdev_t dev) ...@@ -455,26 +455,6 @@ struct super_block * get_super(kdev_t dev)
return NULL; 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) asmlinkage int sys_ustat(dev_t dev, struct ustat * ubuf)
{ {
struct super_block *s; struct super_block *s;
...@@ -574,14 +554,12 @@ static void d_umount(struct dentry *dentry) ...@@ -574,14 +554,12 @@ static void d_umount(struct dentry *dentry)
{ {
struct dentry * covers = dentry->d_covers; struct dentry * covers = dentry->d_covers;
if (covers == dentry) { if (covers != dentry) {
printk("VFS: unmount - covers == dentry?\n"); covers->d_mounts = covers;
return; 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) static void d_mount(struct dentry *covers, struct dentry *dentry)
...@@ -590,8 +568,8 @@ static void d_mount(struct dentry *covers, struct dentry *dentry) ...@@ -590,8 +568,8 @@ static void d_mount(struct dentry *covers, struct dentry *dentry)
printk("VFS: mount - already mounted\n"); printk("VFS: mount - already mounted\n");
return; return;
} }
covers->d_mounts = dget(dentry); covers->d_mounts = dentry;
dentry->d_covers = dget(covers); dentry->d_covers = covers;
} }
static int do_umount(kdev_t dev,int unmount_root) static int do_umount(kdev_t dev,int unmount_root)
...@@ -599,13 +577,18 @@ static int do_umount(kdev_t dev,int unmount_root) ...@@ -599,13 +577,18 @@ static int do_umount(kdev_t dev,int unmount_root)
struct super_block * sb; struct super_block * sb;
int retval; int retval;
sb = get_super(dev);
if (!sb)
return -ENOENT;
if (!sb->s_root)
return -ENOENT;
if (dev==ROOT_DEV && !unmount_root) { if (dev==ROOT_DEV && !unmount_root) {
/* /*
* Special case for "unmounting" root. We just try to remount * Special case for "unmounting" root. We just try to remount
* it readonly, and sync() the device. * it readonly, and sync() the device.
*/ */
if (!(sb=get_super(dev)))
return -ENOENT;
if (!(sb->s_flags & MS_RDONLY)) { if (!(sb->s_flags & MS_RDONLY)) {
/* /*
* Make sure all quotas are turned off on this device we need to mount * Make sure all quotas are turned off on this device we need to mount
...@@ -621,9 +604,6 @@ static int do_umount(kdev_t dev,int unmount_root) ...@@ -621,9 +604,6 @@ static int do_umount(kdev_t dev,int unmount_root)
} }
return 0; return 0;
} }
sb=get_super(dev);
if (!sb)
return -ENOENT;
/* /*
* Before checking if the filesystem is still busy make sure the kernel * Before checking if the filesystem is still busy make sure the kernel
...@@ -634,20 +614,41 @@ static int do_umount(kdev_t dev,int unmount_root) ...@@ -634,20 +614,41 @@ static int do_umount(kdev_t dev,int unmount_root)
if (!fs_may_umount(dev, sb->s_root)) if (!fs_may_umount(dev, sb->s_root))
return -EBUSY; return -EBUSY;
/* Clear up the dcache tree. This should be cleaner.. */ /* clean up dcache .. */
if (sb->s_root) { d_umount(sb->s_root);
d_umount(sb->s_root);
d_delete(sb->s_root);
}
sb->s_root = NULL; sb->s_root = NULL;
if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
sb->s_op->write_super(sb); if (sb->s_op) {
put_super(dev); 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); remove_vfsmnt(dev);
return 0; 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. * Now umount can handle mount points as well as block devices.
* This is important for filesystems which use unnamed block devices. * This is important for filesystems which use unnamed block devices.
...@@ -662,9 +663,6 @@ static int do_umount(kdev_t dev,int unmount_root) ...@@ -662,9 +663,6 @@ static int do_umount(kdev_t dev,int unmount_root)
asmlinkage int sys_umount(char * name) asmlinkage int sys_umount(char * name)
{ {
struct dentry * dentry; struct dentry * dentry;
struct inode * inode;
kdev_t dev;
struct inode * dummy_inode = NULL;
int retval; int retval;
if (!suser()) if (!suser())
...@@ -673,45 +671,27 @@ asmlinkage int sys_umount(char * name) ...@@ -673,45 +671,27 @@ asmlinkage int sys_umount(char * name)
lock_kernel(); lock_kernel();
dentry = namei(name); dentry = namei(name);
retval = PTR_ERR(dentry); retval = PTR_ERR(dentry);
if (IS_ERR(dentry)) if (!IS_ERR(dentry)) {
goto out; struct inode * inode = dentry->d_inode;
kdev_t dev = inode->i_rdev;
inode = dentry->d_inode;
if (S_ISBLK(inode->i_mode)) { retval = 0;
dev = inode->i_rdev; if (S_ISBLK(inode->i_mode)) {
retval = -EACCES; if (IS_NODEV(inode))
if (IS_NODEV(inode)) { retval = -EACCES;
dput(dentry); } else {
goto out; struct super_block *sb = inode->i_sb;
} retval = -EINVAL;
} else { if (sb && inode == sb->s_root->d_inode) {
retval = -EINVAL; dev = sb->s_dev;
if (!inode->i_sb || inode != inode->i_sb->s_root->d_inode) { retval = 0;
dput(dentry); }
goto out;
} }
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); dput(dentry);
goto out;
} if (!retval)
retval = do_umount(dev,0); retval = umount_dev(dev);
if (!retval) {
fsync_dev(dev);
if (dev != ROOT_DEV) {
blkdev_release (inode);
put_unnamed_dev(dev);
}
} }
dput(dentry);
if (!retval)
fsync_dev(dev);
out:
unlock_kernel(); unlock_kernel();
return retval; return retval;
} }
...@@ -1101,8 +1081,7 @@ __initfunc(static int do_change_root(kdev_t new_root_dev,const char *put_old)) ...@@ -1101,8 +1081,7 @@ __initfunc(static int do_change_root(kdev_t new_root_dev,const char *put_old))
{ {
kdev_t old_root_dev; kdev_t old_root_dev;
struct vfsmount *vfsmnt; struct vfsmount *vfsmnt;
struct inode *old_root,*old_pwd,*inode; struct dentry *old_root,*old_pwd,*dir_d = NULL;
unsigned long old_fs;
int error; int error;
old_root = current->fs->root; old_root = current->fs->root;
...@@ -1114,24 +1093,29 @@ __initfunc(static int do_change_root(kdev_t new_root_dev,const char *put_old)) ...@@ -1114,24 +1093,29 @@ __initfunc(static int do_change_root(kdev_t new_root_dev,const char *put_old))
} }
ROOT_DEV = new_root_dev; ROOT_DEV = new_root_dev;
do_mount_root(); do_mount_root();
old_fs = get_fs(); dir_d = lookup_dentry(put_old, NULL, 1);
set_fs(get_ds()); if (IS_ERR(dir_d)) {
error = namei(put_old, &inode); error = PTR_ERR(dir_d);
if (error) inode = NULL; } else if (!dir_d->d_inode) {
set_fs(old_fs); dput(dir_d);
if (!error && (atomic_read(&inode->i_count) != 1 || inode->i_mount)) error = -ENOENT;
} else {
error = 0;
}
if (!error && dir_d->d_covers != dir_d) {
dput(dir_d);
error = -EBUSY; error = -EBUSY;
if (!error && !S_ISDIR(inode->i_mode)) }
if (!error && !S_ISDIR(dir_d->d_inode->i_mode)) {
dput(dir_d);
error = -ENOTDIR; error = -ENOTDIR;
iput(old_root); /* current->fs->root */ }
iput(old_pwd); /* current->fs->pwd */ dput(old_root);
dput(old_pwd);
if (error) { if (error) {
int umount_error; int umount_error;
if (inode) iput(inode);
printk(KERN_NOTICE "Trying to unmount old root ... "); 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); umount_error = do_umount(old_root_dev,1);
if (umount_error) printk(KERN_ERR "error %d\n",umount_error); if (umount_error) printk(KERN_ERR "error %d\n",umount_error);
else { else {
...@@ -1140,16 +1124,16 @@ __initfunc(static int do_change_root(kdev_t new_root_dev,const char *put_old)) ...@@ -1140,16 +1124,16 @@ __initfunc(static int do_change_root(kdev_t new_root_dev,const char *put_old))
} }
return umount_error ? error : 0; return umount_error ? error : 0;
} }
iput(old_root); /* sb->s_covered */
remove_vfsmnt(old_root_dev); remove_vfsmnt(old_root_dev);
vfsmnt = add_vfsmnt(old_root_dev,"/dev/root.old",put_old); vfsmnt = add_vfsmnt(old_root_dev,"/dev/root.old",put_old);
if (!vfsmnt) printk(KERN_CRIT "Trouble: add_vfsmnt failed\n"); if (!vfsmnt) printk(KERN_CRIT "Trouble: add_vfsmnt failed\n");
else { else {
vfsmnt->mnt_sb = old_root->i_sb; vfsmnt->mnt_sb = old_root->d_inode->i_sb;
vfsmnt->mnt_sb->s_covered = inode; d_mount(dir_d,vfsmnt->mnt_sb->s_root);
vfsmnt->mnt_flags = vfsmnt->mnt_sb->s_flags; 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; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment