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,
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);
......@@ -97,7 +96,7 @@ asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr,
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;
......@@ -109,7 +108,7 @@ asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr,
up(&mm->mmap_sem);
if (user_mode(regs)) {
force_sig(SIGSEGV, tsk);
force_sig(SIGSEGV, current);
return;
}
......@@ -117,7 +116,7 @@ asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr,
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;
}
......
......@@ -625,7 +625,7 @@ asmlinkage int sys_execve(struct pt_regs regs)
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, &regs);
putname(filename);
......
......@@ -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? */
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;
......
......@@ -292,7 +292,7 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg)
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;
......
......@@ -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))
{
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;
......@@ -457,15 +458,19 @@ __initfunc(static void rd_load_image(kdev_t device,int offset))
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;
......@@ -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);
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]);
......@@ -637,7 +642,7 @@ __initfunc(static int fill_inbuf(void))
{
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;
......@@ -656,7 +661,7 @@ __initfunc(static void flush_window(void))
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++) {
......
......@@ -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)
{
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;
......
......@@ -246,7 +246,7 @@ sound_poll (struct file *file, poll_table * wait)
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;
......@@ -326,8 +326,7 @@ sound_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma)
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;
......
......@@ -194,7 +194,7 @@ struct super_block *autofs_read_super(struct super_block *s, void *data,
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");
......
......@@ -37,7 +37,7 @@ void autofs_catatonic_mode(struct autofs_sb_info *sbi)
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)
......@@ -55,7 +55,7 @@ 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;
}
......
......@@ -678,8 +678,7 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
__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;
......
......@@ -28,7 +28,9 @@ static int do_load_java(struct linux_binprm *bprm,struct pt_regs *regs)
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;
......@@ -42,8 +44,8 @@ static int do_load_java(struct linux_binprm *bprm,struct pt_regs *regs)
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
......@@ -75,15 +77,17 @@ static int do_load_java(struct linux_binprm *bprm,struct pt_regs *regs)
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);
......@@ -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)
{
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
......@@ -118,15 +124,17 @@ static int do_load_applet(struct linux_binprm *bprm,struct pt_regs *regs)
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);
......
......@@ -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)
{
struct binfmt_entry *fmt;
struct dentry * dentry;
char iname[128];
char *iname_addr = iname, *p;
int retval, fmt_flags = 0;
......@@ -179,8 +180,8 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
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) &&
......@@ -197,11 +198,14 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
}
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;
......
......@@ -186,7 +186,7 @@ struct dentry * d_alloc_root(struct inode * root_inode, struct dentry *old_root)
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;
......
......@@ -209,9 +209,7 @@ int check_disk_change(kdev_t dev)
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);
......
......@@ -509,7 +509,8 @@ int fs_may_mount(kdev_t 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)
......
......@@ -275,7 +275,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name)
}
/* 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);
......@@ -318,33 +318,16 @@ static struct dentry * reserved_lookup(struct dentry * parent, struct qstr * nam
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)
{
......@@ -355,23 +338,23 @@ 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;
}
......@@ -382,7 +365,7 @@ static struct dentry * do_follow_link(struct dentry *base, struct dentry *dentry
{
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 */
......@@ -415,7 +398,7 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo
base = dget(current->fs->pwd);
}
if (*name == '\0')
if (!*name)
return base;
/* 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
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;
......@@ -491,17 +482,13 @@ struct dentry * __namei(const char *pathname, int follow_link)
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;
}
......@@ -557,7 +544,6 @@ struct dentry * open_namei(const char * pathname, int flag, int mode)
acc_mode = 0;
}
up(&dir->i_sem);
iput(dir);
if (error)
goto exit;
}
......@@ -669,7 +655,6 @@ struct dentry * do_mknod(const char * filename, int mode, dev_t dev)
exit_lock:
up(&dir->i_sem);
iput(dir);
dput(dentry);
return retval;
}
......@@ -749,7 +734,6 @@ static inline int do_mkdir(const char * pathname, int mode)
exit_lock:
up(&dir->i_sem);
iput(dir);
dput(dentry);
exit:
return error;
......@@ -818,7 +802,6 @@ static inline int do_rmdir(const char * name)
exit_lock:
up(&dir->i_sem);
iput(dir);
dput(dentry);
exit:
return error;
......@@ -879,7 +862,6 @@ static inline int do_unlink(const char * name)
exit_lock:
up(&dir->i_sem);
iput(dir);
dput(dentry);
exit:
return error;
......@@ -937,7 +919,6 @@ static inline int do_symlink(const char * oldname, const char * newname)
exit_lock:
up(&dir->i_sem);
iput(dir);
dput(dentry);
exit:
return error;
......@@ -1021,7 +1002,6 @@ static inline int do_link(const char * oldname, const char * newname)
exit_lock:
up(&dir->i_sem);
iput(dir);
dput(new_dentry);
exit_old:
dput(old_dentry);
......@@ -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)
{
int error;
......@@ -1138,8 +1133,6 @@ static inline int do_rename(const char * oldname, const char * newname)
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);
......
......@@ -419,7 +419,7 @@ int do_pipe(int *fd)
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;
......
......@@ -455,26 +455,6 @@ struct super_block * get_super(kdev_t dev)
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;
......@@ -574,14 +554,12 @@ static void d_umount(struct dentry *dentry)
{
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)
......@@ -590,8 +568,8 @@ 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)
......@@ -599,13 +577,18 @@ 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
......@@ -621,9 +604,6 @@ static int do_umount(kdev_t dev,int unmount_root)
}
return 0;
}
sb=get_super(dev);
if (!sb)
return -ENOENT;
/*
* 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)
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.
......@@ -662,9 +663,6 @@ static int do_umount(kdev_t dev,int unmount_root)
asmlinkage int sys_umount(char * name)
{
struct dentry * dentry;
struct inode * inode;
kdev_t dev;
struct inode * dummy_inode = NULL;
int retval;
if (!suser())
......@@ -673,45 +671,27 @@ asmlinkage int sys_umount(char * name)
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;
}
......@@ -1101,8 +1081,7 @@ __initfunc(static int do_change_root(kdev_t new_root_dev,const char *put_old))
{
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;
......@@ -1114,24 +1093,29 @@ __initfunc(static int do_change_root(kdev_t new_root_dev,const char *put_old))
}
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 {
......@@ -1140,16 +1124,16 @@ __initfunc(static int do_change_root(kdev_t new_root_dev,const char *put_old))
}
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;
}
......
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