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);
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))
*/
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 {
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) {
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
#include <linux/isapnp.h>
#include <linux/string.h>
-
static void __init quirk_awe32_resources(struct pci_dev *dev)
{
struct isapnp_port *port, *port2, *port3;
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
*/
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 }
};
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);
* 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);
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;
* 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);
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,
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)
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);
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 &&
{
/* 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));
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);
continue;
if (dquot->dq_type != type)
continue;
- if (!dquot->dq_mnt)
+ if (!dquot->dq_sb)
continue;
}
/*
* 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 */
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;
}
/*
- * 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) {
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;
}
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();
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);
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
*/
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;
}
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;
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:
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) : "?";
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)
(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;
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
/*
* 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;
} 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))) {
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 &&
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;
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;
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) {
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);
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;
}
* 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++;
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;
}
}
/*
* 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);
}
* 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);
}
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);
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;
}
{
int cmds = 0, type = 0, flags = 0;
kdev_t dev;
+ struct super_block *sb = NULL;
int ret = -EINVAL;
lock_kernel();
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;
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;
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;
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))
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);
#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;
* 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;
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;
if(IS_ERR(tmp))
return PTR_ERR(tmp);
lock_kernel();
- error = do_unlink(tmp);
+ error = do_unlink(tmp, NULL);
unlock_kernel();
putname(tmp);
* 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;
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;
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))
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)
{
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))) {
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);
}
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;
* 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);
/*
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;
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.
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;
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 *);
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 *);
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
*/
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 */
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);
}
#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
#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.
* 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 <linux/config.h>
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
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;
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
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;
}
}
-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;
}
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;
}
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;
} 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);
return err;
bad_file:
- unlock_kernel();
if ((err = PTR_ERR(file)) == -ENOENT)
return -EINVAL;
return err;
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.
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);
}
/*
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);
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);
#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;
{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),
/* 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();