From 1eafe7093f4a8acc816dc3c50e0822bfcd6691de Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:32:59 -0500 Subject: [PATCH] Import 2.3.99pre2-2 --- arch/sparc64/kernel/sys_sparc32.c | 4 +- drivers/char/raw.c | 2 +- drivers/char/sysrq.c | 4 +- drivers/pnp/quirks.c | 51 ++++++- fs/binfmt_elf.c | 6 +- fs/binfmt_em86.c | 2 +- fs/binfmt_misc.c | 2 +- fs/binfmt_script.c | 2 +- fs/dquot.c | 230 ++++++++++++++---------------- fs/exec.c | 6 +- fs/namei.c | 10 +- fs/open.c | 6 +- fs/super.c | 41 +----- include/linux/fs.h | 12 +- include/linux/mount.h | 4 - include/linux/quota.h | 2 +- include/linux/quotaops.h | 6 +- ipc/shm.c | 112 ++------------- kernel/acct.c | 2 +- kernel/ksyms.c | 2 +- kernel/sysctl.c | 3 - net/unix/af_unix.c | 2 +- 22 files changed, 215 insertions(+), 296 deletions(-) diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index a24c53e45585..c27b342ea517 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -3059,7 +3059,7 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0])); lock_kernel(); - dentry = open_namei(filename, 0, 0); + dentry = open_namei(filename); unlock_kernel(); retval = PTR_ERR(dentry); @@ -4154,7 +4154,7 @@ asmlinkage long sparc32_open(const char * filename, int flags, int mode) if (fd >= 0) { struct file * f; lock_kernel(); - f = filp_open(tmp, flags, mode); + f = filp_open(tmp, flags, mode, NULL); unlock_kernel(); error = PTR_ERR(f); if (IS_ERR(f)) diff --git a/drivers/char/raw.c b/drivers/char/raw.c index a7c1b0703328..a3159c8367a4 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -102,7 +102,7 @@ int raw_open(struct inode *inode, struct file *filp) */ sector_size = 512; - if (lookup_vfsmnt(rdev) != NULL) { + if (get_super(rdev) != NULL) { if (blksize_size[MAJOR(rdev)]) sector_size = blksize_size[MAJOR(rdev)][MINOR(rdev)]; } else { diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 7fcbfbb527f4..48e426623809 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -203,7 +203,7 @@ static void go_sync(kdev_t dev, int remount_flag) file->f_mode &= ~2; } file_list_unlock(); - DQUOT_OFF(dev); + DQUOT_OFF(sb); fsync_dev(dev); flags = MS_RDONLY; if (sb->s_op && sb->s_op->remount_fs) { @@ -212,8 +212,6 @@ static void go_sync(kdev_t dev, int remount_flag) printk("error %d\n", ret); else { sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); - if ((vfsmnt = lookup_vfsmnt(sb->s_dev))) - vfsmnt->mnt_flags = sb->s_flags; printk("OK\n"); } } else diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index 12a82eba5814..50f24988128e 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c @@ -18,7 +18,6 @@ #include #include - static void __init quirk_awe32_resources(struct pci_dev *dev) { struct isapnp_port *port, *port2, *port3; @@ -67,6 +66,37 @@ static void __init quirk_cmi8330_resources(struct pci_dev *dev) printk(KERN_INFO "isapnp: CMI8330 quirk - fixing interrupts and dma\n"); } +static void __init quirk_sb16audio_resources(struct pci_dev *dev) +{ + struct isapnp_port *port; + struct isapnp_resources *res = dev->sysdata; + int changed = 0; + + /* + * The default range on the mtu port for these devices is 0x388-0x388. + * Here we increase that range so that two such cards can be + * auto-configured. + */ + + for( ; res ; res = res->alt ) { + port = res->port; + if(!port) + continue; + port = port->next; + if(!port) + continue; + port = port->next; + if(!port) + continue; + if(port->min != port->max) + continue; + port->max += 0x70; + changed = 1; + } + if(changed) + printk(KERN_INFO "ISAPnP: SB audio device quirk - increasing port range\n"); + return; +} /* * ISAPnP Quirks @@ -74,14 +104,31 @@ static void __init quirk_cmi8330_resources(struct pci_dev *dev) */ static struct isapnp_fixup isapnp_fixups[] __initdata = { + /* Soundblaster awe io port quirk */ { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0021), quirk_awe32_resources }, { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0022), quirk_awe32_resources }, { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0023), quirk_awe32_resources }, - { ISAPNP_VENDOR('@','X','@'), ISAPNP_DEVICE(0x0001), // CMI8330 + /* CMI 8330 interrupt and dma fix */ + { ISAPNP_VENDOR('@','X','@'), ISAPNP_DEVICE(0x0001), quirk_cmi8330_resources }, + /* Soundblaster audio device io port range quirk */ + { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0001), + quirk_sb16audio_resources }, + { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0031), + quirk_sb16audio_resources }, + { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0041), + quirk_sb16audio_resources }, + { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0042), + quirk_sb16audio_resources }, + { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0043), + quirk_sb16audio_resources }, + { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0044), + quirk_sb16audio_resources }, + { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045), + quirk_sb16audio_resources }, { 0 } }; diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index e79fdcac8c9c..20faef169538 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -495,16 +495,14 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) current->personality = PER_SVR4; lock_kernel(); - interpreter_dentry = open_namei(elf_interpreter, - 0, 0); + interpreter_dentry = open_namei(elf_interpreter); unlock_kernel(); current->personality = old_pers; } else #endif { lock_kernel(); - interpreter_dentry = open_namei(elf_interpreter, - 0, 0); + interpreter_dentry = open_namei(elf_interpreter); unlock_kernel(); } set_fs(old_fs); diff --git a/fs/binfmt_em86.c b/fs/binfmt_em86.c index 189d130cafab..e4a0410b40f5 100644 --- a/fs/binfmt_em86.c +++ b/fs/binfmt_em86.c @@ -81,7 +81,7 @@ static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs) * space, and we don't need to copy it. */ lock_kernel(); - dentry = open_namei(interp, 0, 0); + dentry = open_namei(interp); unlock_kernel(); if (IS_ERR(dentry)) return PTR_ERR(dentry); diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index c530a6ff29d8..9d98d7d70a58 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -213,7 +213,7 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) bprm->argc++; bprm->filename = iname; /* for binfmt_script */ - dentry = open_namei(iname, 0, 0); + dentry = open_namei(iname); retval = PTR_ERR(dentry); if (IS_ERR(dentry)) goto _ret; diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c index 84dbf11b0aa0..450f918a4f73 100644 --- a/fs/binfmt_script.c +++ b/fs/binfmt_script.c @@ -82,7 +82,7 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs) * OK, now restart the process with the interpreter's dentry. */ lock_kernel(); - dentry = open_namei(interp, 0, 0); + dentry = open_namei(interp); unlock_kernel(); if (IS_ERR(dentry)) return PTR_ERR(dentry); diff --git a/fs/dquot.c b/fs/dquot.c index 61dcef3662f3..c602697f5a41 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -66,6 +66,11 @@ static char *quotatypes[] = INITQFNAMES; static kmem_cache_t *dquot_cachep; +static inline struct quota_mount_options *sb_dqopt(struct super_block *sb) +{ + return &sb->s_dquot; +} + /* * Dquot List Management: * The quota code uses three lists for dquot management: the inuse_list, @@ -98,29 +103,20 @@ static DECLARE_WAIT_QUEUE_HEAD(update_wait); static void dqput(struct dquot *); static struct dquot *dqduplicate(struct dquot *); -static inline char is_enabled(struct vfsmount *vfsmnt, short type) +static inline char is_enabled(struct quota_mount_options *dqopt, short type) { switch (type) { case USRQUOTA: - return((vfsmnt->mnt_dquot.flags & DQUOT_USR_ENABLED) != 0); + return((dqopt->flags & DQUOT_USR_ENABLED) != 0); case GRPQUOTA: - return((vfsmnt->mnt_dquot.flags & DQUOT_GRP_ENABLED) != 0); + return((dqopt->flags & DQUOT_GRP_ENABLED) != 0); } return(0); } static inline char sb_has_quota_enabled(struct super_block *sb, short type) { - struct vfsmount *vfsmnt; - - return((vfsmnt = lookup_vfsmnt(sb->s_dev)) != (struct vfsmount *)NULL && is_enabled(vfsmnt, type)); -} - -static inline char dev_has_quota_enabled(kdev_t dev, short type) -{ - struct vfsmount *vfsmnt; - - return((vfsmnt = lookup_vfsmnt(dev)) != (struct vfsmount *)NULL && is_enabled(vfsmnt, type)); + return is_enabled(sb_dqopt(sb), type); } static inline int const hashfn(kdev_t dev, unsigned int id, short type) @@ -253,15 +249,15 @@ static void write_dquot(struct dquot *dquot) mm_segment_t fs; loff_t offset; ssize_t ret; - struct semaphore *sem = &dquot->dq_mnt->mnt_dquot.dqio_sem; + struct semaphore *sem = &dquot->dq_sb->s_dquot.dqio_sem; lock_dquot(dquot); - if (!dquot->dq_mnt) { /* Invalidated quota? */ + if (!dquot->dq_sb) { /* Invalidated quota? */ unlock_dquot(dquot); return; } down(sem); - filp = dquot->dq_mnt->mnt_dquot.files[type]; + filp = dquot->dq_sb->s_dquot.files[type]; offset = dqoff(dquot->dq_id); fs = get_fs(); set_fs(KERNEL_DS); @@ -293,20 +289,20 @@ static void read_dquot(struct dquot *dquot) mm_segment_t fs; loff_t offset; - filp = dquot->dq_mnt->mnt_dquot.files[type]; + filp = dquot->dq_sb->s_dquot.files[type]; if (filp == (struct file *)NULL) return; lock_dquot(dquot); - if (!dquot->dq_mnt) /* Invalidated quota? */ + if (!dquot->dq_sb) /* Invalidated quota? */ goto out_lock; /* Now we are sure filp is valid - the dquot isn't invalidated */ - down(&dquot->dq_mnt->mnt_dquot.dqio_sem); + down(&dquot->dq_sb->s_dquot.dqio_sem); offset = dqoff(dquot->dq_id); fs = get_fs(); set_fs(KERNEL_DS); filp->f_op->read(filp, (char *)&dquot->dq_dqb, sizeof(struct dqblk), &offset); - up(&dquot->dq_mnt->mnt_dquot.dqio_sem); + up(&dquot->dq_sb->s_dquot.dqio_sem); set_fs(fs); if (dquot->dq_bhardlimit == 0 && dquot->dq_bsoftlimit == 0 && @@ -326,7 +322,7 @@ void clear_dquot(struct dquot *dquot) { /* unhash it first */ unhash_dquot(dquot); - dquot->dq_mnt = NULL; + dquot->dq_sb = NULL; dquot->dq_flags = 0; dquot->dq_referenced = 0; memset(&dquot->dq_dqb, 0, sizeof(struct dqblk)); @@ -346,7 +342,7 @@ restart: continue; if (dquot->dq_type != type) continue; - if (!dquot->dq_mnt) /* Already invalidated entry? */ + if (!dquot->dq_sb) /* Already invalidated entry? */ continue; if (dquot->dq_flags & DQ_LOCKED) { __wait_on_dquot(dquot); @@ -360,7 +356,7 @@ restart: continue; if (dquot->dq_type != type) continue; - if (!dquot->dq_mnt) + if (!dquot->dq_sb) continue; } /* @@ -368,7 +364,7 @@ restart: * the quota needn't to be written to disk. So we write it * ourselves before discarding the data just for sure... */ - if (dquot->dq_flags & DQ_MOD && dquot->dq_mnt) + if (dquot->dq_flags & DQ_MOD && dquot->dq_sb) { write_dquot(dquot); need_restart = 1; /* We slept on IO */ @@ -397,7 +393,7 @@ restart: continue; if (type != -1 && dquot->dq_type != type) continue; - if (!dquot->dq_mnt) /* Invalidated? */ + if (!dquot->dq_sb) /* Invalidated? */ continue; if (!(dquot->dq_flags & (DQ_LOCKED | DQ_MOD))) continue; @@ -435,11 +431,11 @@ static void dqput(struct dquot *dquot) } /* - * If the dq_mnt pointer isn't initialized this entry needs no + * If the dq_sb pointer isn't initialized this entry needs no * checking and doesn't need to be written. It's just an empty * dquot that is put back on to the freelist. */ - if (dquot->dq_mnt) + if (dquot->dq_sb) dqstats.drops++; we_slept: if (dquot->dq_count > 1) { @@ -451,7 +447,7 @@ we_slept: printk(KERN_ERR "VFS: Locked quota to be put on the free list.\n"); dquot->dq_flags &= ~DQ_LOCKED; } - if (dquot->dq_mnt && dquot->dq_flags & DQ_MOD) { + if (dquot->dq_sb && dquot->dq_flags & DQ_MOD) { write_dquot(dquot); goto we_slept; } @@ -571,17 +567,17 @@ pressure: goto repeat; } -struct dquot *dqget(kdev_t dev, unsigned int id, short type) +static struct dquot *dqget(struct super_block *sb, unsigned int id, short type) { - unsigned int hashent = hashfn(dev, id, type); + unsigned int hashent = hashfn(sb->s_dev, id, type); struct dquot *dquot, *empty = NULL; - struct vfsmount *vfsmnt; + struct quota_mount_options *dqopt = sb_dqopt(sb); - if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL || !is_enabled(vfsmnt, type)) + if (!is_enabled(dqopt, type)) return(NODQUOT); we_slept: - if ((dquot = find_dquot(hashent, dev, id, type)) == NULL) { + if ((dquot = find_dquot(hashent, sb->s_dev, id, type)) == NULL) { if (empty == NULL) { dquot_updating[hashent]++; empty = get_empty_dquot(); @@ -592,8 +588,8 @@ we_slept: dquot = empty; dquot->dq_id = id; dquot->dq_type = type; - dquot->dq_dev = dev; - dquot->dq_mnt = vfsmnt; + dquot->dq_dev = sb->s_dev; + dquot->dq_sb = sb; /* hash it first so it can be found */ hash_dquot(dquot); read_dquot(dquot); @@ -610,7 +606,7 @@ we_slept: while (dquot_updating[hashent]) sleep_on(&update_wait); - if (!dquot->dq_mnt) { /* Has somebody invalidated entry under us? */ + if (!dquot->dq_sb) { /* Has somebody invalidated entry under us? */ /* * Do it as if the quota was invalidated before we started */ @@ -625,11 +621,11 @@ we_slept: static struct dquot *dqduplicate(struct dquot *dquot) { - if (dquot == NODQUOT || !dquot->dq_mnt) + if (dquot == NODQUOT || !dquot->dq_sb) return NODQUOT; dquot->dq_count++; wait_on_dquot(dquot); - if (!dquot->dq_mnt) { + if (!dquot->dq_sb) { dquot->dq_count--; return NODQUOT; } @@ -642,13 +638,12 @@ static struct dquot *dqduplicate(struct dquot *dquot) static inline int is_quotafile(struct inode *inode) { int cnt; - struct vfsmount *vfsmnt; + struct quota_mount_options *dqopt = sb_dqopt(inode->i_sb); struct file **files; - vfsmnt = lookup_vfsmnt(inode->i_dev); - if (!vfsmnt) + if (!dqopt) return 0; - files = vfsmnt->mnt_dquot.files; + files = dqopt->files; for (cnt = 0; cnt < MAXQUOTAS; cnt++) if (files[cnt] && files[cnt]->f_dentry->d_inode == inode) return 1; @@ -671,13 +666,12 @@ static int dqinit_needed(struct inode *inode, short type) return 0; } -static void add_dquot_ref(kdev_t dev, short type) +static void add_dquot_ref(struct super_block *sb, short type) { - struct super_block *sb = get_super(dev); struct list_head *p; struct inode *inode; - if (!sb || !sb->dq_op) + if (!sb->dq_op) return; /* nothing to do */ restart: @@ -804,7 +798,7 @@ static void print_warning(struct dquot *dquot, int flag, const char *fmtstr) if (!need_print_warning(dquot, flag)) return; - root = dquot->dq_mnt->mnt_sb->s_root; + root = dquot->dq_sb->s_root; dget(root); buffer = (char *) __get_free_page(GFP_KERNEL); path = buffer ? d_path(root, buffer, PAGE_SIZE) : "?"; @@ -817,7 +811,7 @@ static void print_warning(struct dquot *dquot, int flag, const char *fmtstr) static inline char ignore_hardlimit(struct dquot *dquot) { - return capable(CAP_SYS_RESOURCE) && !dquot->dq_mnt->mnt_dquot.rsquash[dquot->dq_type]; + return capable(CAP_SYS_RESOURCE) && !dquot->dq_sb->s_dquot.rsquash[dquot->dq_type]; } static int check_idq(struct dquot *dquot, u_long inodes) @@ -844,7 +838,7 @@ static int check_idq(struct dquot *dquot, u_long inodes) (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit && dquot->dq_itime == 0) { print_warning(dquot, 0, "%s: warning, %s file quota exceeded\n"); - dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.inode_expire[dquot->dq_type]; + dquot->dq_itime = CURRENT_TIME + dquot->dq_sb->s_dquot.inode_expire[dquot->dq_type]; } return QUOTA_OK; @@ -877,7 +871,7 @@ static int check_bdq(struct dquot *dquot, u_long blocks, char prealloc) dquot->dq_btime == 0) { if (!prealloc) { print_warning(dquot, 0, "%s: warning, %s disk quota exceeded\n"); - dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.block_expire[dquot->dq_type]; + dquot->dq_btime = CURRENT_TIME + dquot->dq_sb->s_dquot.block_expire[dquot->dq_type]; } else /* @@ -894,7 +888,7 @@ static int check_bdq(struct dquot *dquot, u_long blocks, char prealloc) * Initialize a dquot-struct with new quota info. This is used by the * system call interface functions. */ -static int set_dqblk(kdev_t dev, int id, short type, int flags, struct dqblk *dqblk) +static int set_dqblk(struct super_block *sb, int id, short type, int flags, struct dqblk *dqblk) { struct dquot *dquot; int error = -EFAULT; @@ -909,7 +903,7 @@ static int set_dqblk(kdev_t dev, int id, short type, int flags, struct dqblk *dq } else memcpy((caddr_t)&dq_dqblk, (caddr_t)dqblk, sizeof(struct dqblk)); - if ((dquot = dqget(dev, id, type)) != NODQUOT) { + if (sb && (dquot = dqget(sb, id, type)) != NODQUOT) { lock_dquot(dquot); if (id > 0 && ((flags & SET_QUOTA) || (flags & SET_QLIMIT))) { @@ -923,22 +917,22 @@ static int set_dqblk(kdev_t dev, int id, short type, int flags, struct dqblk *dq if (dquot->dq_isoftlimit && dquot->dq_curinodes < dquot->dq_isoftlimit && dq_dqblk.dqb_curinodes >= dquot->dq_isoftlimit) - dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.inode_expire[type]; + dquot->dq_itime = CURRENT_TIME + dquot->dq_sb->s_dquot.inode_expire[type]; dquot->dq_curinodes = dq_dqblk.dqb_curinodes; if (dquot->dq_curinodes < dquot->dq_isoftlimit) dquot->dq_flags &= ~DQ_INODES; if (dquot->dq_bsoftlimit && dquot->dq_curblocks < dquot->dq_bsoftlimit && dq_dqblk.dqb_curblocks >= dquot->dq_bsoftlimit) - dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.block_expire[type]; + dquot->dq_btime = CURRENT_TIME + dquot->dq_sb->s_dquot.block_expire[type]; dquot->dq_curblocks = dq_dqblk.dqb_curblocks; if (dquot->dq_curblocks < dquot->dq_bsoftlimit) dquot->dq_flags &= ~DQ_BLKS; } if (id == 0) { - dquot->dq_mnt->mnt_dquot.block_expire[type] = dquot->dq_btime = dq_dqblk.dqb_btime; - dquot->dq_mnt->mnt_dquot.inode_expire[type] = dquot->dq_itime = dq_dqblk.dqb_itime; + dquot->dq_sb->s_dquot.block_expire[type] = dquot->dq_btime = dq_dqblk.dqb_btime; + dquot->dq_sb->s_dquot.inode_expire[type] = dquot->dq_itime = dq_dqblk.dqb_itime; } if (dq_dqblk.dqb_bhardlimit == 0 && dq_dqblk.dqb_bsoftlimit == 0 && @@ -954,14 +948,14 @@ static int set_dqblk(kdev_t dev, int id, short type, int flags, struct dqblk *dq return(0); } -static int get_quota(kdev_t dev, int id, short type, struct dqblk *dqblk) +static int get_quota(struct super_block *sb, int id, short type, struct dqblk *dqblk) { struct dquot *dquot; int error = -ESRCH; - if (!dev_has_quota_enabled(dev, type)) + if (!sb || !sb_has_quota_enabled(sb, type)) goto out; - dquot = dqget(dev, id, type); + dquot = dqget(sb, id, type); if (dquot == NODQUOT) goto out; @@ -990,17 +984,16 @@ static int get_stats(caddr_t addr) return error; } -static int quota_root_squash(kdev_t dev, short type, int *addr) +static int quota_root_squash(struct super_block *sb, short type, int *addr) { - struct vfsmount *vfsmnt; int new_value, error; - if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL) + if (!sb) return(-ENODEV); error = -EFAULT; if (!copy_from_user(&new_value, addr, sizeof(int))) { - vfsmnt->mnt_dquot.rsquash[type] = new_value; + sb_dqopt(sb)->rsquash[type] = new_value; error = 0; } return error; @@ -1063,7 +1056,7 @@ void dquot_initialize(struct inode *inode, short type) id = inode->i_gid; break; } - dquot = dqget(inode->i_dev, id, cnt); + dquot = dqget(inode->i_sb, id, cnt); if (dquot == NODQUOT) continue; if (inode->i_dquot[cnt] != NODQUOT) { @@ -1219,10 +1212,13 @@ int dquot_transfer(struct dentry *dentry, struct iattr *iattr) if (!inode) return -ENOENT; + /* Arguably we could consider that as error, but... no fs - no quota */ + if (!inode->i_sb) + return 0; /* * Find out if this filesystem uses i_blocks. */ - if (!inode->i_sb || !inode->i_sb->s_blocksize) + if (!inode->i_sb->s_blocksize) blocks = isize_to_blocks(inode->i_size, BLOCK_SIZE_BITS); else blocks = (inode->i_blocks >> 1); @@ -1243,14 +1239,14 @@ int dquot_transfer(struct dentry *dentry, struct iattr *iattr) if (inode->i_uid == iattr->ia_uid) continue; /* We can get transfer_from from inode, can't we? */ - transfer_from[cnt] = dqget(inode->i_dev, inode->i_uid, cnt); - transfer_to[cnt] = dqget(inode->i_dev, iattr->ia_uid, cnt); + transfer_from[cnt] = dqget(inode->i_sb, inode->i_uid, cnt); + transfer_to[cnt] = dqget(inode->i_sb, iattr->ia_uid, cnt); break; case GRPQUOTA: if (inode->i_gid == iattr->ia_gid) continue; - transfer_from[cnt] = dqget(inode->i_dev, inode->i_gid, cnt); - transfer_to[cnt] = dqget(inode->i_dev, iattr->ia_gid, cnt); + transfer_from[cnt] = dqget(inode->i_sb, inode->i_gid, cnt); + transfer_to[cnt] = dqget(inode->i_sb, iattr->ia_gid, cnt); break; } @@ -1286,7 +1282,7 @@ int dquot_transfer(struct dentry *dentry, struct iattr *iattr) * dqget() could block and so the first structure might got * invalidated or locked... */ - if (!transfer_to[cnt]->dq_mnt || !transfer_from[cnt]->dq_mnt || + if (!transfer_to[cnt]->dq_sb || !transfer_from[cnt]->dq_sb || check_idq(transfer_to[cnt], 1) == NO_QUOTA || check_bdq(transfer_to[cnt], blocks, 0) == NO_QUOTA) { cnt++; @@ -1371,26 +1367,26 @@ struct dquot_operations dquot_operations = { dquot_transfer }; -static inline void set_enable_flags(struct vfsmount *vfsmnt, short type) +static inline void set_enable_flags(struct quota_mount_options *dqopt, short type) { switch (type) { case USRQUOTA: - vfsmnt->mnt_dquot.flags |= DQUOT_USR_ENABLED; + dqopt->flags |= DQUOT_USR_ENABLED; break; case GRPQUOTA: - vfsmnt->mnt_dquot.flags |= DQUOT_GRP_ENABLED; + dqopt->flags |= DQUOT_GRP_ENABLED; break; } } -static inline void reset_enable_flags(struct vfsmount *vfsmnt, short type) +static inline void reset_enable_flags(struct quota_mount_options *dqopt, short type) { switch (type) { case USRQUOTA: - vfsmnt->mnt_dquot.flags &= ~DQUOT_USR_ENABLED; + dqopt->flags &= ~DQUOT_USR_ENABLED; break; case GRPQUOTA: - vfsmnt->mnt_dquot.flags &= ~DQUOT_GRP_ENABLED; + dqopt->flags &= ~DQUOT_GRP_ENABLED; break; } } @@ -1401,38 +1397,36 @@ extern void remove_dquot_ref(kdev_t, short); /* * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount) */ -int quota_off(kdev_t dev, short type) +int quota_off(struct super_block *sb, short type) { - struct vfsmount *vfsmnt; struct file *filp; short cnt; int enabled = 0; + struct quota_mount_options *dqopt = sb_dqopt(sb); - /* We don't need to search for vfsmnt each time - umount has to wait for us */ - vfsmnt = lookup_vfsmnt(dev); - if (!vfsmnt || !vfsmnt->mnt_sb) + if (!sb) goto out; /* We need to serialize quota_off() for device */ - down(&vfsmnt->mnt_dquot.dqoff_sem); + down(&dqopt->dqoff_sem); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (type != -1 && cnt != type) continue; - if (!is_enabled(vfsmnt, cnt)) + if (!is_enabled(dqopt, cnt)) continue; - reset_enable_flags(vfsmnt, cnt); + reset_enable_flags(dqopt, cnt); /* Note: these are blocking operations */ - remove_dquot_ref(dev, cnt); - invalidate_dquots(dev, cnt); + remove_dquot_ref(sb->s_dev, cnt); + invalidate_dquots(sb->s_dev, cnt); /* Wait for any pending IO - remove me as soon as invalidate is more polite */ - down(&vfsmnt->mnt_dquot.dqio_sem); - filp = vfsmnt->mnt_dquot.files[cnt]; - vfsmnt->mnt_dquot.files[cnt] = (struct file *)NULL; - vfsmnt->mnt_dquot.inode_expire[cnt] = 0; - vfsmnt->mnt_dquot.block_expire[cnt] = 0; - up(&vfsmnt->mnt_dquot.dqio_sem); + down(&dqopt->dqio_sem); + filp = dqopt->files[cnt]; + dqopt->files[cnt] = (struct file *)NULL; + dqopt->inode_expire[cnt] = 0; + dqopt->block_expire[cnt] = 0; + up(&dqopt->dqio_sem); fput(filp); } @@ -1441,10 +1435,10 @@ int quota_off(kdev_t dev, short type) * and if not clear the dq_op pointer. */ for (cnt = 0; cnt < MAXQUOTAS; cnt++) - enabled |= is_enabled(vfsmnt, cnt); + enabled |= is_enabled(dqopt, cnt); if (!enabled) - vfsmnt->mnt_sb->dq_op = NULL; - up(&vfsmnt->mnt_dquot.dqoff_sem); + sb->dq_op = NULL; + up(&dqopt->dqoff_sem); out: return(0); } @@ -1457,31 +1451,25 @@ static inline int check_quotafile_size(loff_t size) return !(((blocks % sizeof(struct dqblk)) * BLOCK_SIZE + off % sizeof(struct dqblk)) % sizeof(struct dqblk)); } -int quota_on(kdev_t dev, short type, char *path) +static int quota_on(struct super_block *sb, short type, char *path) { struct file *f; - struct vfsmount *vfsmnt; struct inode *inode; struct dquot *dquot; - struct quota_mount_options *mnt_dquot; + struct quota_mount_options *dqopt = sb_dqopt(sb); char *tmp; int error; - vfsmnt = lookup_vfsmnt(dev); - if (vfsmnt == (struct vfsmount *)NULL) - return -ENODEV; - - if (is_enabled(vfsmnt, type)) + if (is_enabled(dqopt, type)) return -EBUSY; - mnt_dquot = &vfsmnt->mnt_dquot; - down(&mnt_dquot->dqoff_sem); + down(&dqopt->dqoff_sem); tmp = getname(path); error = PTR_ERR(tmp); if (IS_ERR(tmp)) goto out_lock; - f = filp_open(tmp, O_RDWR, 0600); + f = filp_open(tmp, O_RDWR, 0600, NULL); putname(tmp); error = PTR_ERR(f); @@ -1499,24 +1487,24 @@ int quota_on(kdev_t dev, short type, char *path) goto out_f; dquot_drop(inode); /* We don't want quota on quota files */ - set_enable_flags(vfsmnt, type); - mnt_dquot->files[type] = f; + set_enable_flags(dqopt, type); + dqopt->files[type] = f; - dquot = dqget(dev, 0, type); - mnt_dquot->inode_expire[type] = (dquot != NODQUOT) ? dquot->dq_itime : MAX_IQ_TIME; - mnt_dquot->block_expire[type] = (dquot != NODQUOT) ? dquot->dq_btime : MAX_DQ_TIME; + dquot = dqget(sb, 0, type); + dqopt->inode_expire[type] = (dquot != NODQUOT) ? dquot->dq_itime : MAX_IQ_TIME; + dqopt->block_expire[type] = (dquot != NODQUOT) ? dquot->dq_btime : MAX_DQ_TIME; dqput(dquot); - vfsmnt->mnt_sb->dq_op = &dquot_operations; - add_dquot_ref(dev, type); + sb->dq_op = &dquot_operations; + add_dquot_ref(sb, type); - up(&mnt_dquot->dqoff_sem); + up(&dqopt->dqoff_sem); return 0; out_f: filp_close(f, NULL); out_lock: - up(&mnt_dquot->dqoff_sem); + up(&dqopt->dqoff_sem); return error; } @@ -1531,6 +1519,7 @@ asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr) { int cmds = 0, type = 0, flags = 0; kdev_t dev; + struct super_block *sb = NULL; int ret = -EINVAL; lock_kernel(); @@ -1575,18 +1564,19 @@ asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr) ret = -ENOTBLK; if (!S_ISBLK(mode)) goto out; + sb = get_super(dev); } ret = -EINVAL; switch (cmds) { case Q_QUOTAON: - ret = quota_on(dev, type, (char *) addr); + ret = sb ? quota_on(sb, type, (char *) addr) : -ENODEV; goto out; case Q_QUOTAOFF: - ret = quota_off(dev, type); + ret = quota_off(sb, type); goto out; case Q_GETQUOTA: - ret = get_quota(dev, id, type, (struct dqblk *) addr); + ret = get_quota(sb, id, type, (struct dqblk *) addr); goto out; case Q_SETQUOTA: flags |= SET_QUOTA; @@ -1604,7 +1594,7 @@ asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr) ret = get_stats(addr); goto out; case Q_RSQUASH: - ret = quota_root_squash(dev, type, (int *) addr); + ret = quota_root_squash(sb, type, (int *) addr); goto out; default: goto out; @@ -1613,8 +1603,8 @@ asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr) flags |= QUOTA_SYSCALL; ret = -ESRCH; - if (dev_has_quota_enabled(dev, type)) - ret = set_dqblk(dev, id, type, flags, (struct dqblk *) addr); + if (sb && sb_has_quota_enabled(sb, type)) + ret = set_dqblk(sb, id, type, flags, (struct dqblk *) addr); out: unlock_kernel(); return ret; diff --git a/fs/exec.c b/fs/exec.c index e3ff2d0055ee..19a85f925c64 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -775,7 +775,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) bprm_loader.page[i] = NULL; lock_kernel(); - dentry = open_namei(dynloader[0], 0, 0); + dentry = open_namei(dynloader[0]); unlock_kernel(); retval = PTR_ERR(dentry); if (IS_ERR(dentry)) @@ -855,7 +855,7 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); lock_kernel(); - dentry = open_namei(filename, 0, 0); + dentry = open_namei(filename); unlock_kernel(); retval = PTR_ERR(dentry); @@ -944,7 +944,7 @@ int do_coredump(long signr, struct pt_regs * regs) #else corename[4] = '\0'; #endif - file = filp_open(corename, O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600); + file = filp_open(corename, O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600, NULL); if (IS_ERR(file)) goto fail; dentry = file->f_dentry; diff --git a/fs/namei.c b/fs/namei.c index 97c2399293b7..f57cb2a542d4 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -609,13 +609,13 @@ exit_lock: * which is a lot more logical, and also allows the "no perm" needed * for symlinks (where the permissions are checked later). */ -struct dentry * open_namei(const char * pathname, int flag, int mode) +struct dentry * __open_namei(const char * pathname, int flag, int mode, struct dentry * dir) { int acc_mode, error; struct inode *inode; struct dentry *dentry; - dentry = lookup_dentry(pathname, NULL, lookup_flags(flag)); + dentry = lookup_dentry(pathname, dir, lookup_flags(flag)); if (IS_ERR(dentry)) return dentry; @@ -1012,13 +1012,13 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) return error; } -int do_unlink(const char * name) +int do_unlink(const char * name, struct dentry * base) { int error; struct dentry *dir; struct dentry *dentry; - dentry = lookup_dentry(name, NULL, 0); + dentry = lookup_dentry(name, base, 0); error = PTR_ERR(dentry); if (IS_ERR(dentry)) goto exit; @@ -1043,7 +1043,7 @@ asmlinkage long sys_unlink(const char * pathname) if(IS_ERR(tmp)) return PTR_ERR(tmp); lock_kernel(); - error = do_unlink(tmp); + error = do_unlink(tmp, NULL); unlock_kernel(); putname(tmp); diff --git a/fs/open.c b/fs/open.c index 6b11f4ab0ed8..9f4d50a79c15 100644 --- a/fs/open.c +++ b/fs/open.c @@ -644,7 +644,7 @@ out: * for the internal routines (ie open_namei()/follow_link() etc). 00 is * used by symlinks. */ -struct file *filp_open(const char * filename, int flags, int mode) +struct file *filp_open(const char * filename, int flags, int mode, struct dentry * base) { struct inode * inode; struct dentry * dentry; @@ -661,7 +661,7 @@ struct file *filp_open(const char * filename, int flags, int mode) flag++; if (flag & O_TRUNC) flag |= 2; - dentry = open_namei(filename,flag,mode); + dentry = __open_namei(filename, flag, mode, base); error = PTR_ERR(dentry); if (IS_ERR(dentry)) goto cleanup_file; @@ -787,7 +787,7 @@ asmlinkage long sys_open(const char * filename, int flags, int mode) if (fd >= 0) { struct file * f; lock_kernel(); - f = filp_open(tmp, flags, mode); + f = filp_open(tmp, flags, mode, NULL); unlock_kernel(); error = PTR_ERR(f); if (IS_ERR(f)) diff --git a/fs/super.c b/fs/super.c index d54e850dfb83..a0fe6be7b226 100644 --- a/fs/super.c +++ b/fs/super.c @@ -247,32 +247,9 @@ static struct file_system_type *get_fs_type(const char *name) return fs; } - struct vfsmount *vfsmntlist = NULL; static struct vfsmount *vfsmnttail = NULL, *mru_vfsmnt = NULL; -/* - * This part handles the management of the list of mounted filesystems. - */ -struct vfsmount *lookup_vfsmnt(kdev_t dev) -{ - struct vfsmount *lptr; - - if (vfsmntlist == NULL) - return NULL; - - if (mru_vfsmnt != NULL && mru_vfsmnt->mnt_dev == dev) - return (mru_vfsmnt); - - for (lptr = vfsmntlist; lptr != NULL; lptr = lptr->mnt_next) - if (lptr->mnt_dev == dev) { - mru_vfsmnt = lptr; - return (lptr); - } - - return NULL; -} - static struct vfsmount *add_vfsmnt(struct super_block *sb, const char *dev_name, const char *dir_name) { @@ -286,11 +263,6 @@ static struct vfsmount *add_vfsmnt(struct super_block *sb, lptr->mnt_sb = sb; lptr->mnt_dev = sb->s_dev; - lptr->mnt_flags = sb->s_flags; - - sema_init(&lptr->mnt_dquot.dqio_sem, 1); - sema_init(&lptr->mnt_dquot.dqoff_sem, 1); - lptr->mnt_dquot.flags = 0; /* N.B. Is it really OK to have a vfsmount without names? */ if (dev_name && !IS_ERR(tmp = getname(dev_name))) { @@ -399,9 +371,9 @@ int get_filesystem_info( char *buf ) len += sprintf( buf + len, "%s %s %s %s", tmp->mnt_devname, path, tmp->mnt_sb->s_type->name, - tmp->mnt_flags & MS_RDONLY ? "ro" : "rw" ); + tmp->mnt_sb->s_flags & MS_RDONLY ? "ro" : "rw" ); for (fs_infop = fs_info; fs_infop->flag; fs_infop++) { - if (tmp->mnt_flags & fs_infop->flag) { + if (tmp->mnt_sb->s_flags & fs_infop->flag) { strcpy(buf + len, fs_infop->str); len += strlen(fs_infop->str); } @@ -592,6 +564,9 @@ static struct super_block * read_super(kdev_t dev, struct block_device *bdev, sema_init(&s->s_vfs_rename_sem,1); sema_init(&s->s_nfsd_free_path_sem,1); s->s_type = type; + sema_init(&s->s_dquot.dqio_sem, 1); + sema_init(&s->s_dquot.dqoff_sem, 1); + s->s_dquot.flags = 0; lock_super(s); if (!type->read_super(s, data, silent)) goto out_fail; @@ -688,7 +663,7 @@ static struct block_device *do_umount(kdev_t dev, int unmount_root, int flags) * on the device. If the umount fails, too bad -- there * are no quotas running any more. Just turn them on again. */ - DQUOT_OFF(dev); + DQUOT_OFF(sb); acct_auto_close(dev); /* @@ -990,7 +965,6 @@ out: static int do_remount_sb(struct super_block *sb, int flags, char *data) { int retval; - struct vfsmount *vfsmnt; if (!(flags & MS_RDONLY) && sb->s_dev && is_read_only(sb->s_dev)) return -EACCES; @@ -1007,9 +981,6 @@ static int do_remount_sb(struct super_block *sb, int flags, char *data) return retval; } sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); - vfsmnt = lookup_vfsmnt(sb->s_dev); - if (vfsmnt) - vfsmnt->mnt_flags = sb->s_flags; /* * Invalidate the inodes, as some mount options may be changed. diff --git a/include/linux/fs.h b/include/linux/fs.h index bd37850b7b57..cebc71f32a77 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -589,6 +589,7 @@ struct super_block { struct list_head s_files; struct block_device *s_bdev; + struct quota_mount_options s_dquot; /* Diskquota specific options */ union { struct minix_sb_info minix_sb; @@ -821,7 +822,7 @@ extern int do_truncate(struct dentry *, loff_t start); extern int get_unused_fd(void); extern void put_unused_fd(unsigned int); -extern struct file *filp_open(const char *, int, int); +extern struct file *filp_open(const char *, int, int, struct dentry *); extern int filp_close(struct file *, fl_owner_t id); extern char * getname(const char *); @@ -936,10 +937,15 @@ extern int notify_change(struct dentry *, struct iattr *); extern int permission(struct inode *, int); extern int get_write_access(struct inode *); extern void put_write_access(struct inode *); -extern struct dentry * open_namei(const char *, int, int); extern struct dentry * do_mknod(const char *, int, dev_t); extern int do_pipe(int *); -extern int do_unlink(const char * name); +extern int do_unlink(const char * name, struct dentry *); +extern struct dentry * __open_namei(const char *, int, int, struct dentry *); + +static inline struct dentry * open_namei(const char *pathname) +{ + return __open_namei(pathname, 0, 0, NULL); +} /* fs/dcache.c -- generic fs support functions */ extern int is_subdir(struct dentry *, struct dentry *); diff --git a/include/linux/mount.h b/include/linux/mount.h index 86dc89c4791f..c2dcfe93fb5f 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -30,14 +30,10 @@ struct vfsmount kdev_t mnt_dev; /* Device this applies to */ char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ char *mnt_dirname; /* Name of directory mounted on */ - unsigned int mnt_flags; /* Flags of this device */ struct super_block *mnt_sb; /* pointer to superblock */ - struct quota_mount_options mnt_dquot; /* Diskquota specific mount options */ struct vfsmount *mnt_next; /* pointer to next in linkedlist */ }; -struct vfsmount *lookup_vfsmnt(kdev_t dev); - /* * Umount options */ diff --git a/include/linux/quota.h b/include/linux/quota.h index ad23800191c6..9324b9a02380 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -174,7 +174,7 @@ struct dquot { int dq_count; /* Reference count */ /* fields after this point are cleared when invalidating */ - struct vfsmount *dq_mnt; /* VFS_mount_point this applies to */ + struct super_block *dq_sb; /* superblock this applies to */ unsigned int dq_id; /* ID this applies to (uid, gid) */ kdev_t dq_dev; /* Device this applies to */ short dq_type; /* Type of quota */ diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 17371e58c16b..14ad1b7ca2f4 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -20,7 +20,7 @@ extern void dquot_initialize(struct inode *inode, short type); extern void dquot_drop(struct inode *inode); extern void invalidate_dquots(kdev_t dev, short type); -extern int quota_off(kdev_t dev, short type); +extern int quota_off(struct super_block *sb, short type); extern int sync_dquots(kdev_t dev, short type); extern int dquot_alloc_block(const struct inode *inode, unsigned long number, char prealloc); @@ -103,7 +103,7 @@ extern __inline__ int DQUOT_TRANSFER(struct dentry *dentry, struct iattr *iattr) } #define DQUOT_SYNC(dev) sync_dquots(dev, -1) -#define DQUOT_OFF(dev) quota_off(dev, -1) +#define DQUOT_OFF(sb) quota_off(sb, -1) #else @@ -118,7 +118,7 @@ extern __inline__ int DQUOT_TRANSFER(struct dentry *dentry, struct iattr *iattr) #define DQUOT_FREE_BLOCK(sb, inode, nr) do { } while(0) #define DQUOT_FREE_INODE(sb, inode) do { } while(0) #define DQUOT_SYNC(dev) do { } while(0) -#define DQUOT_OFF(dev) do { } while(0) +#define DQUOT_OFF(sb) do { } while(0) /* * Special case expands to a simple notify_change. diff --git a/ipc/shm.c b/ipc/shm.c index 64039d6fda4c..2a89ce4b5015 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -18,10 +18,8 @@ * 1) It only can handle one directory. * 2) Because the directory is represented by the SYSV shm array it * can only be mounted one time. - * 3) This again leads to SYSV shm not working properly in a chrooted - * environment - * 4) Read and write are not implemented (should they?) - * 5) No special nodes are supported + * 3) Read and write are not implemented (should they?) + * 4) No special nodes are supported */ #include @@ -57,8 +55,6 @@ static void shm_delete (struct inode *); static int shm_mmap (struct file *, struct vm_area_struct *); static int shm_readdir (struct file *, void *, filldir_t); -char shm_path[256] = "/var/shm"; - #define SHM_NAME_LEN NAME_MAX #define SHM_FMT ".IPC_%08x" #define SHM_FMT_LEN 13 @@ -71,7 +67,6 @@ struct shmid_kernel /* private to the kernel */ unsigned long shm_npages; /* size of segment (pages) */ pte_t **shm_dir; /* ptr to arr of ptrs to frames */ int id; - int destroyed; /* set if the final detach kills */ union permap { struct shmem { time_t atime; @@ -116,7 +111,6 @@ static int newseg (key_t key, const char *name, int namelen, int shmflg, size_t static void killseg_core(struct shmid_kernel *shp, int doacc); static void shm_open (struct vm_area_struct *shmd); static void shm_close (struct vm_area_struct *shmd); -static void shm_remove_name(int id); static struct page * shm_nopage(struct vm_area_struct *, unsigned long, int); static int shm_swapout(struct page *, struct file *); #ifdef CONFIG_PROC_FS @@ -312,20 +306,6 @@ static int shm_remount_fs (struct super_block *sb, int *flags, char *data) return 0; } -static struct fs_struct *shm_push_root(void) -{ - struct fs_struct *old,*new; - new=init_task_union.task.fs; - old=current->fs; - current->fs=new; - return old; -} - -static void shm_pop_root(struct fs_struct *saved) -{ - current->fs=saved; -} - static void shm_put_super(struct super_block *sb) { struct super_block **p = &shm_sb; @@ -893,17 +873,6 @@ static inline unsigned long copy_shminfo_to_user(void *buf, struct shminfo64 *in } } -char * shm_getname(int id) -{ - char *result; - - if (!(result = __getname ())) - return ERR_PTR(-ENOMEM); - - sprintf (result, "%s/" SHM_FMT, shm_path, id); - return result; -} - asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf) { struct shm_setbuf setbuf; @@ -1033,36 +1002,15 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf) } case IPC_RMID: { - /* - * We cannot simply remove the file. The SVID states - * that the block remains until the last person - * detaches from it, then is deleted. A shmat() on - * an RMID segment is legal in older Linux and if - * we change it apps break... - * - * Instead we set a destroyed flag, and then blow - * the name away when the usage hits zero. - */ + char name[SHM_FMT_LEN+1]; if ((shmid % SEQ_MULTIPLIER)== zero_id) return -EINVAL; + sprintf (name, SHM_FMT, shmid); lock_kernel(); - shp = shm_lock(shmid); - if(shp==NULL) - { - unlock_kernel(); - return -EINVAL; - } - err=-EIDRM; - if(shm_checkid(shp,shmid)==0) - { - if(shp->shm_nattch==0) - shm_remove_name(shmid); - else - shp->destroyed=1; - err=0; - } - shm_unlock(shmid); + err = do_unlink (name, dget(shm_sb->s_root)); unlock_kernel(); + if (err == -ENOENT) + err = -EINVAL; return err; } @@ -1141,8 +1089,7 @@ asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr) struct file * file; int err; int flags; - char *name; - struct fs_struct *saved; + char name[SHM_FMT_LEN+1]; if (!shm_sb || (shmid % SEQ_MULTIPLIER) == zero_id) return -EINVAL; @@ -1159,19 +1106,13 @@ asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr) } else flags = MAP_SHARED; - name = shm_getname(shmid); - if (IS_ERR (name)) - return PTR_ERR (name); - + sprintf (name, SHM_FMT, shmid); lock_kernel(); - saved=shm_push_root(); - file = filp_open (name, O_RDWR, 0); - shm_pop_root(saved); - - putname (name); - if (IS_ERR (file)) + file = filp_open(name, O_RDWR, 0, dget(shm_sb->s_root)); + if (IS_ERR (file)) { + unlock_kernel(); goto bad_file; - + } *raddr = do_mmap (file, addr, file->f_dentry->d_inode->i_size, (shmflg & SHM_RDONLY ? PROT_READ : PROT_READ | PROT_WRITE), flags, 0); @@ -1184,7 +1125,6 @@ asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr) return err; bad_file: - unlock_kernel(); if ((err = PTR_ERR(file)) == -ENOENT) return -EINVAL; return err; @@ -1196,23 +1136,6 @@ static void shm_open (struct vm_area_struct *shmd) shm_inc (shmd->vm_file->f_dentry->d_inode->i_ino); } -/* - * Remove a name. Must be called with lock_kernel - */ - -static void shm_remove_name(int id) -{ - char *name = shm_getname(id); - if (!IS_ERR(name)) - { - struct fs_struct *saved; - saved=shm_push_root(); - do_unlink (name); - shm_pop_root(saved); - putname (name); - } -} - /* * remove the attach descriptor shmd. * free memory for segment if it is marked destroyed. @@ -1230,14 +1153,7 @@ static void shm_close (struct vm_area_struct *shmd) shp->shm_lprid = current->pid; shp->shm_dtim = CURRENT_TIME; shp->shm_nattch--; - if(shp->shm_nattch==0 && shp->destroyed) - { - shp->destroyed=0; - shm_remove_name(id); - shm_unlock(id); - } - else - shm_unlock(id); + shm_unlock(id); } /* diff --git a/kernel/acct.c b/kernel/acct.c index 63e66a558d50..f15b6971f281 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -154,7 +154,7 @@ asmlinkage long sys_acct(const char *name) if (IS_ERR(tmp)) goto out; /* Difference from BSD - they don't do O_APPEND */ - file = filp_open(tmp, O_WRONLY|O_APPEND, 0); + file = filp_open(tmp, O_WRONLY|O_APPEND, 0, NULL); putname(tmp); if (IS_ERR(file)) { error = PTR_ERR(file); diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 760d2e4683fb..64a9a8a6df41 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -141,7 +141,7 @@ EXPORT_SYMBOL(iget4); EXPORT_SYMBOL(iput); EXPORT_SYMBOL(__namei); EXPORT_SYMBOL(lookup_dentry); -EXPORT_SYMBOL(open_namei); +EXPORT_SYMBOL(__open_namei); EXPORT_SYMBOL(sys_close); EXPORT_SYMBOL(d_alloc_root); EXPORT_SYMBOL(d_delete); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 0001a14730ba..4e654fa3a63b 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -57,7 +57,6 @@ extern int sg_big_buff; #endif #ifdef CONFIG_SYSVIPC extern size_t shm_ctlmax; -extern char shm_path[]; extern int msg_ctlmax; extern int msg_ctlmnb; extern int msg_ctlmni; @@ -199,8 +198,6 @@ static ctl_table kern_table[] = { {KERN_RTSIGMAX, "rtsig-max", &max_queued_signals, sizeof(int), 0644, NULL, &proc_dointvec}, #ifdef CONFIG_SYSVIPC - {KERN_SHMPATH, "shmpath", &shm_path, 256, - 0644, NULL, &proc_dostring, &sysctl_string }, {KERN_SHMMAX, "shmmax", &shm_ctlmax, sizeof (size_t), 0644, NULL, &proc_doulongvec_minmax}, {KERN_MSGMAX, "msgmax", &msg_ctlmax, sizeof (int), diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index a57c2a06dec4..15a16c161319 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -569,7 +569,7 @@ static unix_socket *unix_find_other(struct sockaddr_un *sunname, int len, /* Do not believe to VFS, grab kernel lock */ lock_kernel(); - dentry = open_namei(sunname->sun_path, 2|O_NOFOLLOW, S_IFSOCK); + dentry = __open_namei(sunname->sun_path, 2|O_NOFOLLOW, S_IFSOCK, NULL); if (IS_ERR(dentry)) { *error = PTR_ERR(dentry); unlock_kernel(); -- 2.39.5