You can subscribe to this list here.
2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(6) |
Sep
(2) |
Oct
(43) |
Nov
(4) |
Dec
(12) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2001 |
Jan
(78) |
Feb
(97) |
Mar
(29) |
Apr
(2) |
May
(22) |
Jun
(38) |
Jul
(11) |
Aug
(27) |
Sep
(40) |
Oct
(2) |
Nov
(17) |
Dec
(8) |
2002 |
Jan
|
Feb
(2) |
Mar
(1) |
Apr
(480) |
May
(456) |
Jun
(12) |
Jul
|
Aug
(1) |
Sep
|
Oct
(18) |
Nov
(3) |
Dec
(6) |
2003 |
Jan
|
Feb
(18) |
Mar
(1) |
Apr
|
May
(6) |
Jun
(147) |
Jul
(7) |
Aug
(3) |
Sep
(235) |
Oct
(10) |
Nov
(2) |
Dec
(1) |
2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Andy P. <at...@us...> - 2002-04-09 14:08:27
|
Update of /cvsroot/linux-vax/kernel-2.4/fs In directory usw-pr-cvs1:/tmp/cvs-serv29245 Modified Files: locks.c namei.c open.c pipe.c Added Files: namespace.c Log Message: synch 2.4.15 commit 13 --- NEW FILE --- /* * linux/fs/namespace.c * * (C) Copyright Al Viro 2000, 2001 * Released under GPL v2. * * Based on code from fs/super.c, copyright Linus Torvalds and others. * Heavily rewritten. */ #include <linux/config.h> #include <linux/slab.h> #include <linux/smp_lock.h> #include <linux/init.h> #include <linux/quotaops.h> #include <linux/acct.h> #include <linux/module.h> #include <linux/devfs_fs_kernel.h> [...1059 lines suppressed...] return error; } spin_lock(&dcache_lock); attach_mnt(old_rootmnt, &nd); if (new_devname) { if (old_rootmnt->mnt_devname) kfree(old_rootmnt->mnt_devname); old_rootmnt->mnt_devname = new_devname; } spin_unlock(&dcache_lock); /* put the old stuff */ path_release(&parent_nd); mntput(old_rootmnt); path_release(&nd); return 0; } #endif Index: locks.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/locks.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- locks.c 25 Feb 2001 23:14:46 -0000 1.1.1.2 +++ locks.c 9 Apr 2002 13:19:31 -0000 1.2 @@ -112,7 +112,7 @@ * * Leases and LOCK_MAND * Matthew Wilcox <wi...@li...>, June, 2000. - * Stephen Rothwell <sf...@li...>, June, 2000. + * Stephen Rothwell <sf...@ca...>, June, 2000. */ #include <linux/slab.h> @@ -257,7 +257,7 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl, struct flock *l) { - loff_t start; + off_t start, end; switch (l->l_whence) { case 0: /*SEEK_SET*/ @@ -270,17 +270,16 @@ start = filp->f_dentry->d_inode->i_size; break; default: - return (0); + return -EINVAL; } if (((start += l->l_start) < 0) || (l->l_len < 0)) - return (0); - fl->fl_end = start + l->l_len - 1; - if (l->l_len > 0 && fl->fl_end < 0) - return (0); - if (fl->fl_end > OFFT_OFFSET_MAX) - return 0; + return -EINVAL; + end = start + l->l_len - 1; + if (l->l_len > 0 && end < 0) + return -EOVERFLOW; fl->fl_start = start; /* we record the absolute position */ + fl->fl_end = end; if (l->l_len == 0) fl->fl_end = OFFSET_MAX; @@ -292,7 +291,7 @@ fl->fl_insert = NULL; fl->fl_remove = NULL; - return (assign_type(fl, l->l_type) == 0); + return assign_type(fl, l->l_type); } #if BITS_PER_LONG == 32 @@ -312,14 +311,14 @@ start = filp->f_dentry->d_inode->i_size; break; default: - return (0); + return -EINVAL; } if (((start += l->l_start) < 0) || (l->l_len < 0)) - return (0); + return -EINVAL; fl->fl_end = start + l->l_len - 1; if (l->l_len > 0 && fl->fl_end < 0) - return (0); + return -EOVERFLOW; fl->fl_start = start; /* we record the absolute position */ if (l->l_len == 0) fl->fl_end = OFFSET_MAX; @@ -339,10 +338,10 @@ fl->fl_type = l->l_type; break; default: - return (0); + return -EINVAL; } - return (1); + return (0); } #endif @@ -473,21 +472,26 @@ fl->fl_insert(fl); } -/* Delete a lock and then free it. - * Remove our lock from the lock lists, wake up processes that are blocked - * waiting for this lock, notify the FS that the lock has been cleared and - * finally free the lock. +/* + * Remove lock from the lock lists */ -static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait) +static inline void _unhash_lock(struct file_lock **thisfl_p) { struct file_lock *fl = *thisfl_p; *thisfl_p = fl->fl_next; fl->fl_next = NULL; - list_del(&fl->fl_link); - INIT_LIST_HEAD(&fl->fl_link); + list_del_init(&fl->fl_link); +} +/* + * Wake up processes that are blocked waiting for this lock, + * notify the FS that the lock has been cleared and + * finally free the lock. + */ +static inline void _delete_lock(struct file_lock *fl, unsigned int wait) +{ fasync_helper(0, fl->fl_file, 0, &fl->fl_fasync); if (fl->fl_fasync != NULL){ printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync); @@ -502,6 +506,17 @@ } /* + * Delete a lock and then free it. + */ +static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait) +{ + struct file_lock *fl = *thisfl_p; + + _unhash_lock(thisfl_p); + _delete_lock(fl, wait); +} + +/* * Call back client filesystem in order to get it to unregister a lock, * then delete lock. Essentially useful only in locks_remove_*(). * Note: this must be called with the semaphore already held! @@ -511,12 +526,13 @@ struct file_lock *fl = *thisfl_p; int (*lock)(struct file *, int, struct file_lock *); + _unhash_lock(thisfl_p); if (fl->fl_file->f_op && (lock = fl->fl_file->f_op->lock) != NULL) { fl->fl_type = F_UNLCK; lock(fl->fl_file, F_SETLK, fl); } - locks_delete_lock(thisfl_p, 0); + _delete_lock(fl, 0); } /* Determine if lock sys_fl blocks lock caller_fl. Common functionality @@ -532,7 +548,7 @@ return (1); default: - printk("locks_conflict(): impossible lock type - %d\n", + printk(KERN_ERR "locks_conflict(): impossible lock type - %d\n", caller_fl->fl_type); break; } @@ -644,7 +660,7 @@ * from a broken NFS client. But broken NFS clients have a lot more to * worry about than proper deadlock detection anyway... --okir */ -static int posix_locks_deadlock(struct file_lock *caller_fl, +int posix_locks_deadlock(struct file_lock *caller_fl, struct file_lock *block_fl) { struct list_head *tmp; @@ -699,6 +715,9 @@ struct file_lock *new_fl = locks_alloc_lock(0); int error; + if (new_fl == NULL) + return -ENOMEM; + new_fl->fl_owner = current->files; new_fl->fl_pid = current->pid; new_fl->fl_file = filp; @@ -857,7 +876,7 @@ new_fl2 = locks_alloc_lock(0); error = -ENOLCK; /* "no luck" */ if (!(new_fl && new_fl2)) - goto out; + goto out_nolock; lock_kernel(); if (caller->fl_type != F_UNLCK) { @@ -1005,6 +1024,7 @@ } out: unlock_kernel(); +out_nolock: /* * Free any unused locks. */ @@ -1352,8 +1372,8 @@ if (!filp) goto out; - error = -EINVAL; - if (!flock_to_posix_lock(filp, &file_lock, &flock)) + error = flock_to_posix_lock(filp, &file_lock, &flock); + if (error) goto out_putf; if (filp->f_op && filp->f_op->lock) { @@ -1411,6 +1431,9 @@ struct inode *inode; int error; + if (file_lock == NULL) + return -ENOLCK; + /* * This might block, so we do it before checking the inode. */ @@ -1442,8 +1465,8 @@ } } - error = -EINVAL; - if (!flock_to_posix_lock(filp, file_lock, &flock)) + error = flock_to_posix_lock(filp, file_lock, &flock); + if (error) goto out_putf; error = -EBADF; @@ -1517,8 +1540,8 @@ if (!filp) goto out; - error = -EINVAL; - if (!flock64_to_posix_lock(filp, &file_lock, &flock)) + error = flock64_to_posix_lock(filp, &file_lock, &flock); + if (error) goto out_putf; if (filp->f_op && filp->f_op->lock) { @@ -1564,6 +1587,9 @@ struct inode *inode; int error; + if (file_lock == NULL) + return -ENOLCK; + /* * This might block, so we do it before checking the inode. */ @@ -1595,8 +1621,8 @@ } } - error = -EINVAL; - if (!flock64_to_posix_lock(filp, file_lock, &flock)) + error = flock64_to_posix_lock(filp, file_lock, &flock); + if (error) goto out_putf; error = -EBADF; @@ -1660,6 +1686,7 @@ while ((fl = *before) != NULL) { if ((fl->fl_flags & FL_POSIX) && fl->fl_owner == owner) { locks_unlock_delete(before); + before = &inode->i_flock; continue; } before = &fl->fl_next; Index: namei.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/namei.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- namei.c 14 Jan 2001 16:25:10 -0000 1.1.1.1 +++ namei.c 9 Apr 2002 13:19:31 -0000 1.2 @@ -15,21 +15,16 @@ */ #include <linux/init.h> -#include <linux/mm.h> -#include <linux/proc_fs.h> -#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/fs.h> #include <linux/quotaops.h> #include <linux/pagemap.h> -#include <linux/dcache.h> #include <linux/dnotify.h> - -#include <asm/uaccess.h> -#include <asm/unaligned.h> -#include <asm/semaphore.h> -#include <asm/page.h> -#include <asm/pgtable.h> +#include <linux/smp_lock.h> +#include <linux/personality.h> #include <asm/namei.h> +#include <asm/uaccess.h> #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) @@ -113,7 +108,7 @@ if ((unsigned long) filename >= TASK_SIZE) { if (!segment_eq(get_fs(), KERNEL_DS)) return -EFAULT; - } else if (TASK_SIZE - (unsigned long) filename < PAGE_SIZE) + } else if (TASK_SIZE - (unsigned long) filename < PATH_MAX + 1) len = TASK_SIZE - (unsigned long) filename; retval = strncpy_from_user((char *)page, filename, len); @@ -145,35 +140,55 @@ } /* - * permission() + * vfs_permission() * * is used to check for read/write/execute permissions on a file. * We use "fsuid" for this, letting us set arbitrary permissions * for filesystem access without changing the "normal" uids which * are used for other things.. */ -int vfs_permission(struct inode * inode,int mask) +int vfs_permission(struct inode * inode, int mask) { - int mode = inode->i_mode; + umode_t mode = inode->i_mode; - if ((mask & S_IWOTH) && IS_RDONLY(inode) && - (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) - return -EROFS; /* Nobody gets write access to a read-only fs */ + if (mask & MAY_WRITE) { + /* + * Nobody gets write access to a read-only fs. + */ + if (IS_RDONLY(inode) && + (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) + return -EROFS; - if ((mask & S_IWOTH) && IS_IMMUTABLE(inode)) - return -EACCES; /* Nobody gets write access to an immutable file */ + /* + * Nobody gets write access to an immutable file. + */ + if (IS_IMMUTABLE(inode)) + return -EACCES; + } if (current->fsuid == inode->i_uid) mode >>= 6; else if (in_group_p(inode->i_gid)) mode >>= 3; - if (((mode & mask & S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE)) + /* + * If the DACs are ok we don't need any capability check. + */ + if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask)) return 0; - /* read and search access */ - if ((mask == S_IROTH) || - (S_ISDIR(inode->i_mode) && !(mask & ~(S_IROTH | S_IXOTH)))) + /* + * Read/write DACs are always overridable. + * Executable DACs are overridable if at least one exec bit is set. + */ + if ((mask & (MAY_READ|MAY_WRITE)) || (inode->i_mode & S_IXUGO)) + if (capable(CAP_DAC_OVERRIDE)) + return 0; + + /* + * Searching includes executable on directories, else just read. + */ + if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE))) if (capable(CAP_DAC_READ_SEARCH)) return 0; @@ -309,12 +324,26 @@ return result; } +/* + * This limits recursive symlink follows to 8, while + * limiting consecutive symlinks to 40. + * + * Without that kind of total limit, nasty chains of consecutive + * symlinks can cause almost arbitrarily long lookups. + */ static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) { int err; - if (current->link_count >= 8) + if (current->link_count >= 5) + goto loop; + if (current->total_link_count >= 40) goto loop; + if (current->need_resched) { + current->state = TASK_RUNNING; + schedule(); + } current->link_count++; + current->total_link_count++; UPDATE_ATIME(dentry->d_inode); err = dentry->d_inode->i_op->follow_link(dentry, nd); current->link_count--; @@ -351,22 +380,17 @@ static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry) { - struct list_head *p; + struct vfsmount *mounted; + spin_lock(&dcache_lock); - p = (*dentry)->d_vfsmnt.next; - while (p != &(*dentry)->d_vfsmnt) { - struct vfsmount *tmp; - tmp = list_entry(p, struct vfsmount, mnt_clash); - if (tmp->mnt_parent == *mnt) { - *mnt = mntget(tmp); - spin_unlock(&dcache_lock); - mntput(tmp->mnt_parent); - /* tmp holds the mountpoint, so... */ - dput(*dentry); - *dentry = dget(tmp->mnt_root); - return 1; - } - p = p->next; + mounted = lookup_mnt(*mnt, *dentry); + if (mounted) { + *mnt = mntget(mounted); + spin_unlock(&dcache_lock); + dput(*dentry); + mntput(mounted->mnt_parent); + *dentry = dget(mounted->mnt_root); + return 1; } spin_unlock(&dcache_lock); return 0; @@ -411,6 +435,7 @@ nd->mnt = parent; } } + /* * Name resolution. * @@ -419,7 +444,7 @@ * * We expect 'base' to be positive and a directory. */ -int path_walk(const char * name, struct nameidata *nd) +int link_path_walk(const char * name, struct nameidata *nd) { struct dentry *dentry; struct inode *inode; @@ -610,15 +635,25 @@ return err; } +int path_walk(const char * name, struct nameidata *nd) +{ + current->total_link_count = 0; + return link_path_walk(name, nd); +} + /* SMP-safe */ /* returns 1 if everything is done */ static int __emul_lookup_dentry(const char *name, struct nameidata *nd) { if (path_walk(name, nd)) - return 0; + return 0; /* something went wrong... */ - if (!nd->dentry->d_inode) { + if (!nd->dentry->d_inode || S_ISDIR(nd->dentry->d_inode->i_mode)) { struct nameidata nd_root; + /* + * NAME was not found in alternate root or it's a directory. Try to find + * it in the normal root: + */ nd_root.last_type = LAST_ROOT; nd_root.flags = nd->flags; read_lock(¤t->fs->lock); @@ -748,26 +783,24 @@ } /* SMP-safe */ -struct dentry * lookup_one(const char * name, struct dentry * base) +struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) { unsigned long hash; struct qstr this; unsigned int c; this.name = name; - c = *(const unsigned char *)name; - if (!c) + this.len = len; + if (!len) goto access; hash = init_name_hash(); - do { - name++; - if (c == '/') + while (len--) { + c = *(const unsigned char *)name++; + if (c == '/' || c == '\0') goto access; hash = partial_name_hash(c, hash); - c = *(const unsigned char *)name; - } while (c); - this.len = name - (const char *) this.name; + } this.hash = end_name_hash(hash); return lookup_hash(&this, base); @@ -899,7 +932,7 @@ { int error; - mode &= S_IALLUGO & ~current->fs->umask; + mode &= S_IALLUGO; mode |= S_IFREG; down(&dir->i_zombie); @@ -988,7 +1021,8 @@ /* Negative dentry, just create the file */ if (!dentry->d_inode) { - error = vfs_create(dir->d_inode, dentry, mode); + error = vfs_create(dir->d_inode, dentry, + mode & ~current->fs->umask); up(&dir->d_inode->i_sem); dput(nd->dentry); nd->dentry = dentry; @@ -1013,7 +1047,7 @@ error = -ELOOP; if (flag & O_NOFOLLOW) goto exit_dput; - do __follow_down(&nd->mnt,&dentry); while(d_mountpoint(dentry)); + while (__follow_down(&nd->mnt,&dentry) && d_mountpoint(dentry)); } error = -ENOENT; if (!dentry->d_inode) @@ -1053,7 +1087,7 @@ flag &= ~O_TRUNC; } else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { error = -EACCES; - if (IS_NODEV(inode)) + if (nd->mnt->mnt_flags & MNT_NODEV) goto exit; flag &= ~O_TRUNC; @@ -1139,10 +1173,10 @@ putname(nd->last.name); goto exit; } + error = -ELOOP; if (count++==32) { - dentry = nd->dentry; putname(nd->last.name); - goto ok; + goto exit; } dir = nd->dentry; down(&dir->d_inode->i_sem); @@ -1177,8 +1211,6 @@ { int error = -EPERM; - mode &= ~current->fs->umask; - down(&dir->i_zombie); if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD)) goto exit_lock; @@ -1221,6 +1253,8 @@ goto out; dentry = lookup_create(&nd, 0); error = PTR_ERR(dentry); + + mode &= ~current->fs->umask; if (!IS_ERR(dentry)) { switch (mode & S_IFMT) { case 0: case S_IFREG: @@ -1259,7 +1293,7 @@ goto exit_lock; DQUOT_INIT(dir); - mode &= (S_IRWXUGO|S_ISVTX) & ~current->fs->umask; + mode &= (S_IRWXUGO|S_ISVTX); lock_kernel(); error = dir->i_op->mkdir(dir, dentry, mode); unlock_kernel(); @@ -1289,7 +1323,8 @@ dentry = lookup_create(&nd, 1); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { - error = vfs_mkdir(nd.dentry->d_inode, dentry, mode); + error = vfs_mkdir(nd.dentry->d_inode, dentry, + mode & ~current->fs->umask); dput(dentry); } up(&nd.dentry->d_inode->i_sem); @@ -1699,6 +1734,10 @@ error = -EINVAL; if (is_subdir(new_dentry, old_dentry)) goto out_unlock; + /* Don't eat your daddy, dear... */ + /* This also avoids locking issues */ + if (old_dentry->d_parent == new_dentry) + goto out_unlock; target = new_dentry->d_inode; if (target) { /* Hastur! Hastur! Hastur! */ triple_down(&old_dir->i_zombie, @@ -1917,7 +1956,7 @@ /* weird __emul_prefix() stuff did it */ goto out; } - res = path_walk(link, nd); + res = link_path_walk(link, nd); out: if (current->link_count || res || nd->last_type!=LAST_NORM) return res; @@ -1927,13 +1966,11 @@ * bloody create() on broken symlinks. Furrfu... */ name = __getname(); - if (IS_ERR(name)) - goto fail_name; + if (!name) + return -ENOMEM; strcpy(name, nd->last.name); nd->last.name = name; return 0; -fail_name: - link = name; fail: path_release(nd); return PTR_ERR(link); Index: open.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/open.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- open.c 25 Feb 2001 23:14:45 -0000 1.1.1.2 +++ open.c 9 Apr 2002 13:19:32 -0000 1.2 @@ -14,6 +14,7 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/tty.h> +#include <linux/iobuf.h> #include <asm/uaccess.h> @@ -103,7 +104,12 @@ goto out; inode = nd.dentry->d_inode; - error = -EACCES; + /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ + error = -EISDIR; + if (S_ISDIR(inode->i_mode)) + goto dput_and_out; + + error = -EINVAL; if (!S_ISREG(inode->i_mode)) goto dput_and_out; @@ -145,10 +151,11 @@ asmlinkage long sys_truncate(const char * path, unsigned long length) { - return do_sys_truncate(path, length); + /* on 32-bit boxen it will cut the range 2^31--2^32-1 off */ + return do_sys_truncate(path, (long)length); } -static inline long do_sys_ftruncate(unsigned int fd, loff_t length) +static inline long do_sys_ftruncate(unsigned int fd, loff_t length, int small) { struct inode * inode; struct dentry *dentry; @@ -162,13 +169,24 @@ file = fget(fd); if (!file) goto out; + + /* explicitly opened as large or we are on 64-bit box */ + if (file->f_flags & O_LARGEFILE) + small = 0; + dentry = file->f_dentry; inode = dentry->d_inode; - error = -EACCES; + error = -EINVAL; if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE)) goto out_putf; + + error = -EINVAL; + /* Cannot ftruncate over 2^31 bytes without large file support */ + if (small && length > MAX_NON_LFS) + goto out_putf; + error = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) + if (IS_APPEND(inode)) goto out_putf; error = locks_verify_truncate(inode, file, length); @@ -182,7 +200,7 @@ asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length) { - return do_sys_ftruncate(fd, length); + return do_sys_ftruncate(fd, length, 1); } /* LFS versions of truncate are only needed on 32 bit machines */ @@ -194,7 +212,7 @@ asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length) { - return do_sys_ftruncate(fd, length); + return do_sys_ftruncate(fd, length, 0); } #endif @@ -506,7 +524,7 @@ error = -ENOENT; if (!(inode = dentry->d_inode)) { - printk("chown_common: NULL inode\n"); + printk(KERN_ERR "chown_common: NULL inode\n"); goto out; } error = -EROFS; @@ -553,7 +571,7 @@ newattrs.ia_mode &= ~S_ISGID; newattrs.ia_valid |= ATTR_MODE; } - error = DQUOT_TRANSFER(dentry, &newattrs); + error = notify_change(dentry, &newattrs); out: return error; } @@ -634,6 +652,7 @@ { struct file * f; struct inode *inode; + static LIST_HEAD(kill_list); int error; error = -ENFILE; @@ -654,8 +673,17 @@ f->f_pos = 0; f->f_reada = 0; f->f_op = fops_get(inode->i_fop); - if (inode->i_sb) - file_move(f, &inode->i_sb->s_files); + file_move(f, &inode->i_sb->s_files); + + /* preallocate kiobuf for O_DIRECT */ + f->f_iobuf = NULL; + f->f_iobuf_lock = 0; + if (f->f_flags & O_DIRECT) { + error = alloc_kiovec(1, &f->f_iobuf); + if (error) + goto cleanup_all; + } + if (f->f_op && f->f_op->open) { error = f->f_op->open(inode,f); if (error) @@ -666,9 +694,12 @@ return f; cleanup_all: + if (f->f_iobuf) + free_kiovec(1, &f->f_iobuf); fops_put(f->f_op); if (f->f_mode & FMODE_WRITE) put_write_access(inode); + file_move(f, &kill_list); /* out of the way.. */ f->f_dentry = NULL; f->f_vfsmnt = NULL; cleanup_file: @@ -730,7 +761,7 @@ #if 1 /* Sanity check */ if (files->fd[fd] != NULL) { - printk("get_unused_fd: slot %d not NULL!\n", fd); + printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd); files->fd[fd] = NULL; } #endif @@ -793,7 +824,7 @@ int retval; if (!file_count(filp)) { - printk("VFS: Close: file count is 0\n"); + printk(KERN_ERR "VFS: Close: file count is 0\n"); return 0; } retval = 0; @@ -847,3 +878,18 @@ } return -EPERM; } + +/* + * Called when an inode is about to be open. + * We use this to disallow opening RW large files on 32bit systems if + * the caller didn't specify O_LARGEFILE. On 64bit systems we force + * on this flag in sys_open. + */ +int generic_file_open(struct inode * inode, struct file * filp) +{ + if (!(filp->f_flags & O_LARGEFILE) && inode->i_size > MAX_NON_LFS) + return -EFBIG; + return 0; +} + +EXPORT_SYMBOL(generic_file_open); Index: pipe.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/pipe.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- pipe.c 25 Feb 2001 23:14:46 -0000 1.1.1.2 +++ pipe.c 9 Apr 2002 13:19:32 -0000 1.2 @@ -476,7 +476,7 @@ static struct inode * get_pipe_inode(void) { - struct inode *inode = get_empty_inode(); + struct inode *inode = new_inode(pipe_mnt->mnt_sb); if (!inode) goto fail_inode; @@ -485,7 +485,6 @@ goto fail_iput; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1; inode->i_fop = &rdwr_pipe_fops; - inode->i_sb = pipe_mnt->mnt_sb; /* * Mark the inode dirty from the very beginning, @@ -630,8 +629,7 @@ return sb; } -static DECLARE_FSTYPE(pipe_fs_type, "pipefs", pipefs_read_super, - FS_NOMOUNT|FS_SINGLE); +static DECLARE_FSTYPE(pipe_fs_type, "pipefs", pipefs_read_super, FS_NOMOUNT); static int __init init_pipe_fs(void) { @@ -650,7 +648,7 @@ static void __exit exit_pipe_fs(void) { unregister_filesystem(&pipe_fs_type); - kern_umount(pipe_mnt); + mntput(pipe_mnt); } module_init(init_pipe_fs) |
From: Andy P. <at...@us...> - 2002-04-09 14:08:27
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/acpi In directory usw-pr-cvs1:/tmp/cvs-serv13840/acpi Modified Files: Makefile acpi_ksyms.c driver.c os.c Added Files: Config.in Removed Files: cmbatt.c cpu.c driver.h ec.c ec.h ksyms.c power.c sys.c table.c Log Message: synch 2.4.15 commit 17 --- NEW FILE --- # # ACPI configuration # #mainmenu_option next_comment #comment 'ACPI Configuration' dep_bool ' ACPI Debug Statements' CONFIG_ACPI_DEBUG $CONFIG_ACPI dep_tristate ' ACPI Bus Manager' CONFIG_ACPI_BUSMGR $CONFIG_ACPI dep_tristate ' System' CONFIG_ACPI_SYS $CONFIG_ACPI_BUSMGR $CONFIG_ACPI dep_tristate ' Processor' CONFIG_ACPI_CPU $CONFIG_ACPI_BUSMGR $CONFIG_ACPI dep_tristate ' Button' CONFIG_ACPI_BUTTON $CONFIG_ACPI_BUSMGR $CONFIG_ACPI dep_tristate ' AC Adapter' CONFIG_ACPI_AC $CONFIG_ACPI_BUSMGR $CONFIG_ACPI dep_tristate ' Embedded Controller' CONFIG_ACPI_EC $CONFIG_ACPI_BUSMGR $CONFIG_ACPI dep_tristate ' Control Method Battery' CONFIG_ACPI_CMBATT $CONFIG_ACPI_BUSMGR $CONFIG_ACPI $CONFIG_ACPI_EC dep_tristate ' Thermal' CONFIG_ACPI_THERMAL $CONFIG_ACPI_BUSMGR $CONFIG_ACPI $CONFIG_ACPI_EC #endmenu Index: Makefile =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/acpi/Makefile,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- Makefile 25 Feb 2001 23:15:15 -0000 1.1.1.2 +++ Makefile 9 Apr 2002 14:05:42 -0000 1.2 @@ -1,13 +1,14 @@ # # Makefile for the Linux ACPI interpreter -# +# O_TARGET := acpi.o export-objs := acpi_ksyms.o export ACPI_CFLAGS -ACPI_CFLAGS := -D_LINUX + +ACPI_CFLAGS := -D_LINUX -I$(CURDIR)/include # # CONFIG_ACPI_KERNEL_CONFIG is currently only IA64 @@ -16,33 +17,38 @@ ACPI_CFLAGS += -DCONFIG_ACPI_KERNEL_CONFIG_ONLY endif -EXTRA_CFLAGS += -I./include - -EXTRA_CFLAGS += $(ACPI_CFLAGS) +acpi-subdirs := utilities dispatcher events hardware \ + executer namespace parser resources tables -# genksyms only reads $(CFLAGS), it should really read $(EXTRA_CFLAGS) as well. -# Without EXTRA_CFLAGS the gcc pass for genksyms fails, resulting in an empty -# include/linux/modules/acpi_ksyms.ver. Changing genkyms to use EXTRA_CFLAGS -# will hit everything, too risky in 2.4.0-prerelease. Bandaid by tweaking -# CFLAGS only for .ver targets. Review after 2.4.0 release. KAO +ifdef CONFIG_ACPI_DEBUG + ACPI_CFLAGS += -DACPI_DEBUG -Wno-unused +endif -$(MODINCL)/%.ver: CFLAGS := -I./include $(CFLAGS) +ifdef CONFIG_ACPI_DEBUGGER + ACPI_CFLAGS += -DENABLE_DEBUGGER + acpi-subdirs += debugger +endif -acpi-subdirs := common dispatcher events hardware \ - interpreter namespace parser resources tables +EXTRA_CFLAGS += $(ACPI_CFLAGS) -subdir-$(CONFIG_ACPI) += $(acpi-subdirs) +mod-subdirs := ospm -obj-$(CONFIG_ACPI) := $(patsubst %,%.o,$(acpi-subdirs)) -obj-$(CONFIG_ACPI) += os.o acpi_ksyms.o +subdir-$(CONFIG_ACPI) += $(acpi-subdirs) +subdir-$(CONFIG_ACPI_BUSMGR) += ospm +obj-$(CONFIG_ACPI) += driver.o os.o acpi_ksyms.o +obj-$(CONFIG_ACPI) += $(foreach dir,$(acpi-subdirs),$(dir)/$(dir).o) ifdef CONFIG_ACPI_KERNEL_CONFIG - obj-$(CONFIG_ACPI) += acpiconf.o osconf.o -else - obj-$(CONFIG_ACPI) += driver.o cmbatt.o cpu.o ec.o acpi_ksyms.o sys.o table.o power.o + obj-$(CONFIG_ACPI) += acpiconf.o osconf.o endif -include $(TOPDIR)/Rules.make +ifeq ($(CONFIG_ACPI_BUSMGR),y) + obj-y += ospm/ospm.o +endif -clean: - $(RM) *.o */*.o +# commented out until we distribute it -ASG +#ifeq ($(CONFIG_KDB),y) +# obj-m += kdb/kdbm_acpi.o +#endif + +include $(TOPDIR)/Rules.make Index: acpi_ksyms.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/acpi/acpi_ksyms.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- acpi_ksyms.c 25 Feb 2001 23:15:15 -0000 1.1.1.1 +++ acpi_ksyms.c 9 Apr 2002 14:05:42 -0000 1.2 @@ -18,6 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <linux/config.h> #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> @@ -27,6 +28,7 @@ #include "acdebug.h" extern int acpi_in_debugger; +extern FADT_DESCRIPTOR acpi_fadt; #define _COMPONENT OS_DEPENDENT MODULE_NAME ("symbols") @@ -36,28 +38,27 @@ EXPORT_SYMBOL(acpi_db_user_commands); #endif +#ifdef ACPI_DEBUG +EXPORT_SYMBOL(acpi_ut_debug_print_raw); +EXPORT_SYMBOL(acpi_ut_debug_print); +EXPORT_SYMBOL(acpi_ut_status_exit); +EXPORT_SYMBOL(acpi_ut_exit); +EXPORT_SYMBOL(acpi_ut_trace); +#endif + +EXPORT_SYMBOL(acpi_gbl_FADT); + EXPORT_SYMBOL(acpi_os_free); -EXPORT_SYMBOL(acpi_os_breakpoint); EXPORT_SYMBOL(acpi_os_printf); EXPORT_SYMBOL(acpi_os_callocate); EXPORT_SYMBOL(acpi_os_sleep); -EXPORT_SYMBOL(acpi_os_sleep_usec); -EXPORT_SYMBOL(acpi_os_in8); -EXPORT_SYMBOL(acpi_os_out8); +EXPORT_SYMBOL(acpi_os_stall); EXPORT_SYMBOL(acpi_os_queue_for_execution); EXPORT_SYMBOL(acpi_dbg_layer); EXPORT_SYMBOL(acpi_dbg_level); -EXPORT_SYMBOL(function_exit); -EXPORT_SYMBOL(function_trace); -EXPORT_SYMBOL(function_status_exit); -EXPORT_SYMBOL(function_value_exit); -EXPORT_SYMBOL(debug_print_raw); -EXPORT_SYMBOL(debug_print_prefix); - -EXPORT_SYMBOL(acpi_cm_strncmp); -EXPORT_SYMBOL(acpi_cm_memcpy); -EXPORT_SYMBOL(acpi_cm_memset); + +EXPORT_SYMBOL(acpi_format_exception); EXPORT_SYMBOL(acpi_get_handle); EXPORT_SYMBOL(acpi_get_parent); @@ -66,6 +67,7 @@ EXPORT_SYMBOL(acpi_get_object_info); EXPORT_SYMBOL(acpi_get_next_object); EXPORT_SYMBOL(acpi_evaluate_object); +EXPORT_SYMBOL(acpi_get_table); EXPORT_SYMBOL(acpi_install_notify_handler); EXPORT_SYMBOL(acpi_remove_notify_handler); @@ -73,6 +75,11 @@ EXPORT_SYMBOL(acpi_remove_gpe_handler); EXPORT_SYMBOL(acpi_install_address_space_handler); EXPORT_SYMBOL(acpi_remove_address_space_handler); +EXPORT_SYMBOL(acpi_install_fixed_event_handler); +EXPORT_SYMBOL(acpi_remove_fixed_event_handler); + +EXPORT_SYMBOL(acpi_acquire_global_lock); +EXPORT_SYMBOL(acpi_release_global_lock); EXPORT_SYMBOL(acpi_get_current_resources); EXPORT_SYMBOL(acpi_get_possible_resources); @@ -81,3 +88,28 @@ EXPORT_SYMBOL(acpi_enable_event); EXPORT_SYMBOL(acpi_disable_event); EXPORT_SYMBOL(acpi_clear_event); + +EXPORT_SYMBOL(acpi_get_timer_duration); +EXPORT_SYMBOL(acpi_get_timer); + +EXPORT_SYMBOL(acpi_os_signal_semaphore); +EXPORT_SYMBOL(acpi_os_create_semaphore); +EXPORT_SYMBOL(acpi_os_delete_semaphore); +EXPORT_SYMBOL(acpi_os_wait_semaphore); + +EXPORT_SYMBOL(acpi_os_read_port); +EXPORT_SYMBOL(acpi_os_write_port); + +EXPORT_SYMBOL(acpi_fadt); +EXPORT_SYMBOL(acpi_hw_register_bit_access); +EXPORT_SYMBOL(acpi_hw_obtain_sleep_type_register_data); +EXPORT_SYMBOL(acpi_enter_sleep_state); +EXPORT_SYMBOL(acpi_get_system_info); +EXPORT_SYMBOL(acpi_leave_sleep_state); +/*EXPORT_SYMBOL(acpi_save_state_mem);*/ +/*EXPORT_SYMBOL(acpi_save_state_disk);*/ +EXPORT_SYMBOL(acpi_hw_register_read); +EXPORT_SYMBOL(acpi_set_firmware_waking_vector); +EXPORT_SYMBOL(acpi_subsystem_status); + +EXPORT_SYMBOL(acpi_os_signal); Index: driver.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/acpi/driver.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- driver.c 25 Feb 2001 23:15:15 -0000 1.1.1.2 +++ driver.c 9 Apr 2002 14:05:42 -0000 1.2 @@ -2,6 +2,7 @@ * driver.c - ACPI driver * * Copyright (C) 2000 Andrew Henroid + * Copyright (C) 2001 Andrew Grover * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,6 +22,10 @@ * Changes * David Woodhouse <dw...@re...> 2000-12-6 * - Fix interruptible_sleep_on() races + * Andrew Grover <and...@in...> 2001-2-28 + * - Major revamping + * Peter Breuer <pt...@it...> 2001-5-20 + * - parse boot time params. */ #include <linux/config.h> @@ -35,431 +40,123 @@ #include <linux/acpi.h> #include <asm/uaccess.h> #include "acpi.h" -#include "driver.h" - -#ifdef CONFIG_ACPI_KERNEL_CONFIG -#include <asm/efi.h> -#define ACPI_CAN_USE_EFI_STRUCT -#endif #define _COMPONENT OS_DEPENDENT MODULE_NAME ("driver") -struct acpi_run_entry -{ - void (*callback)(void*); - void *context; - struct tq_struct task; -}; - -static spinlock_t acpi_event_lock = SPIN_LOCK_UNLOCKED; -static volatile u32 acpi_event_status = 0; -static volatile acpi_sstate_t acpi_event_state = ACPI_STATE_S0; -static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait); - -static volatile int acpi_thread_pid = -1; - -static int acpi_start = 1; - -/************************************************/ -/* DECLARE_TASK_QUEUE is defined in */ -/* /usr/src/linux/include/linux/tqueue.h */ -/* So, acpi_thread_run is a pointer to a */ -/* tq_struct structure,defined in the same file.*/ -/************************************************/ -static DECLARE_TASK_QUEUE(acpi_thread_run); +FADT_DESCRIPTOR acpi_fadt; -static DECLARE_WAIT_QUEUE_HEAD(acpi_thread_wait); +static int acpi_disabled = 0; -static struct ctl_table_header *acpi_sysctl = NULL; - -/* - * Examine/modify value - */ -static int -acpi_do_ulong(ctl_table * ctl, - int write, - struct file *file, - void *buffer, - size_t * len) +enum acpi_blacklist_predicates { - char str[2 * sizeof(unsigned long) + 4], *strend; - unsigned long val; - int size; - - if (!write) { - if (file->f_pos) { - *len = 0; - return 0; - } - - val = *(unsigned long *) ctl->data; - size = sprintf(str, "0x%08lx\n", val); - if (*len >= size) { - copy_to_user(buffer, str, size); - *len = size; - } - else - *len = 0; - } - else { - size = sizeof(str) - 1; - if (size > *len) - size = *len; - copy_from_user(str, buffer, size); - str[size] = '\0'; - val = simple_strtoul(str, &strend, 0); - if (strend == str) - return -EINVAL; - *(unsigned long *) ctl->data = val; - } - - file->f_pos += *len; - return 0; -} + all_versions, + less_than_or_equal, + equal, + greater_than_or_equal, +}; -static int -acpi_do_pm_timer(ctl_table * ctl, - int write, - struct file *file, - void *buffer, - size_t * len) +struct acpi_blacklist_item { - int size; - u32 val = 0; - - char str[12]; - - if (file->f_pos) { - *len = 0; - return 0; - } - - val = acpi_read_pm_timer(); - - size = sprintf(str, "0x%08x\n", val); - if (*len >= size) { - copy_to_user(buffer, str, size); - *len = size; - } - else - *len = 0; - - file->f_pos += *len; - - return 0; -} + char oem_id[7]; + char oem_table_id[9]; + u32 oem_revision; + enum acpi_blacklist_predicates oem_revision_predicate; +}; /* - * Handle ACPI event + * Currently, this blacklists based on items in the FADT. We may want to + * expand this to using other ACPI tables in the future, too. */ -static u32 -acpi_event(void *context) +static struct acpi_blacklist_item acpi_blacklist[] __initdata = { - unsigned long flags; - int event = (int)(long)context; - int mask = 0; - - switch (event) { - case ACPI_EVENT_POWER_BUTTON: - mask = ACPI_PWRBTN; - break; - case ACPI_EVENT_SLEEP_BUTTON: - mask = ACPI_SLPBTN; - break; - default: - return AE_ERROR; - } - - if (mask) { - // notify process waiting on /dev/acpi - spin_lock_irqsave(&acpi_event_lock, flags); - acpi_event_status |= mask; - spin_unlock_irqrestore(&acpi_event_lock, flags); - acpi_event_state = acpi_sleep_state; - wake_up_interruptible(&acpi_event_wait); - } - - return AE_OK; -} + {"TOSHIB", "750 ", 0x970814, less_than_or_equal}, /* Portege 7020, BIOS 8.10 */ + {""} +}; -/* - * Wait for next event - */ -static int -acpi_do_event(ctl_table * ctl, - int write, - struct file *file, - void *buffer, - size_t * len) +int +acpi_blacklisted(FADT_DESCRIPTOR *fadt) { - u32 event_status = 0; - acpi_sstate_t event_state = 0; - char str[27]; - int size; - - if (write) - return -EPERM; - if (*len < sizeof(str)) { - *len = 0; - return 0; - } - - while (!event_status) { - unsigned long flags; - DECLARE_WAITQUEUE(wait, current); - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&acpi_event_wait, &wait); - - // we need an atomic exchange here - spin_lock_irqsave(&acpi_event_lock, flags); - event_status = acpi_event_status; - acpi_event_status = 0; - spin_unlock_irqrestore(&acpi_event_lock, flags); - event_state = acpi_event_state; - - if (!event_status) - schedule(); + int i = 0; - remove_wait_queue(&acpi_event_wait, &wait); - set_current_state(TASK_RUNNING); - - if (signal_pending(current)) - return -ERESTARTSYS; - } - - size = sprintf(str, - "0x%08x 0x%08x 0x%01x\n", - event_status, - 0, - event_state); - copy_to_user(buffer, str, size); - *len = size; - file->f_pos += size; - - return 0; -} + while (acpi_blacklist[i].oem_id[0] != '\0') + { + if (strncmp(acpi_blacklist[i].oem_id, fadt->header.oem_id, 6)) { + i++; + continue; + } -/* - * Enter system sleep state - */ -/*static int -acpi_do_sleep(ctl_table * ctl, - int write, - struct file *file, - void *buffer, - size_t * len) -{ - if (!write) { - if (file->f_pos) { - *len = 0; - return 0; + if (strncmp(acpi_blacklist[i].oem_table_id, fadt->header.oem_table_id, 8)) { + i++; + continue; } - } - else { - int status = acpi_enter_sx(ACPI_STATE_S1); - if (status) - return status; - } - file->f_pos += *len; - return 0; -}*/ + if (acpi_blacklist[i].oem_revision_predicate == all_versions) + return TRUE; -/* - * Output important ACPI tables to proc - */ -static int -acpi_do_table(ctl_table * ctl, - int write, - struct file *file, - void *buffer, - size_t * len) -{ - u32 table_type; - size_t size; - ACPI_BUFFER buf; - u8* data; - - table_type = (u32) ctl->data; - size = 0; - buf.length = 0; - buf.pointer = NULL; - - /* determine what buffer size we will need */ - if (acpi_get_table(table_type, 1, &buf) != AE_BUFFER_OVERFLOW) { - *len = 0; - return 0; - } + if (acpi_blacklist[i].oem_revision_predicate == less_than_or_equal + && fadt->header.oem_revision <= acpi_blacklist[i].oem_revision) + return TRUE; - buf.pointer = kmalloc(buf.length, GFP_KERNEL); - if (!buf.pointer) { - return -ENOMEM; - } + if (acpi_blacklist[i].oem_revision_predicate == greater_than_or_equal + && fadt->header.oem_revision >= acpi_blacklist[i].oem_revision) + return TRUE; - /* get the table for real */ - if (!ACPI_SUCCESS(acpi_get_table(table_type, 1, &buf))) { - kfree(buf.pointer); - *len = 0; - return 0; - } + if (acpi_blacklist[i].oem_revision_predicate == equal + && fadt->header.oem_revision == acpi_blacklist[i].oem_revision) + return TRUE; - if (file->f_pos < buf.length) { - data = buf.pointer + file->f_pos; - size = buf.length - file->f_pos; - if (size > *len) - size = *len; - if (copy_to_user(buffer, data, size)) - return -EFAULT; + i++; } - kfree(buf.pointer); - - *len = size; - file->f_pos += size; - return 0; -} - -/********************************************************************/ -/* R U N Q U E U E D C A L L B A C K */ -/* */ -/* The "callback" function address that was tramped through via */ -/* "acpi_run" below is finally called and executed. If we trace all */ -/* this down, the function is acpi_ev_asynch_execute_gpe_method, in */ -/* evevent.c The only other function that is ever queued is */ -/* acpi_ev_global_lock_thread in evmisc.c. */ -/********************************************************************/ -static void -acpi_run_exec(void *context) -{ - struct acpi_run_entry *entry - = (struct acpi_run_entry*) context; - (*entry->callback)(entry->context); - kfree(entry); + return FALSE; } /* - * Queue for execution by the ACPI thread + * Start the interpreter */ int -acpi_run(void (*callback)(void*), void *context) -{ - struct acpi_run_entry *entry; - - entry = kmalloc(sizeof(*entry), GFP_ATOMIC); - if (!entry) - return -1; - - memset(entry, 0, sizeof(entry)); - entry->callback = callback; - entry->context = context; - entry->task.routine = acpi_run_exec; - entry->task.data = entry; - - queue_task(&entry->task, &acpi_thread_run); - - if (waitqueue_active(&acpi_thread_wait)) - wake_up(&acpi_thread_wait); - - return 0; -} - -static struct ctl_table acpi_table[] = +acpi_init(void) { - {ACPI_P_LVL2_LAT, "c2_exit_latency", - &acpi_c2_exit_latency, sizeof(acpi_c2_exit_latency), - 0644, NULL, &acpi_do_ulong}, - - {ACPI_ENTER_LVL2_LAT, "c2_enter_latency", - &acpi_c2_enter_latency, sizeof(acpi_c2_enter_latency), - 0644, NULL, &acpi_do_ulong}, - - {ACPI_P_LVL3_LAT, "c3_exit_latency", - &acpi_c3_exit_latency, sizeof(acpi_c3_exit_latency), - 0644, NULL, &acpi_do_ulong}, - - {ACPI_ENTER_LVL3_LAT, "c3_enter_latency", - &acpi_c3_enter_latency, sizeof(acpi_c3_enter_latency), - 0644, NULL, &acpi_do_ulong}, - - {ACPI_C1_COUNT, "c1_count", - &acpi_c1_count, sizeof(acpi_c1_count), - 0644, NULL, &acpi_do_ulong}, - - {ACPI_C2_COUNT, "c2_count", - &acpi_c2_count, sizeof(acpi_c2_count), - 0644, NULL, &acpi_do_ulong}, - - {ACPI_C3_COUNT, "c3_count", - &acpi_c3_count, sizeof(acpi_c3_count), - 0644, NULL, &acpi_do_ulong}, - - -/* until it actually works */ -/* {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep},*/ - - {ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event}, - - {ACPI_FADT, "fadt", (void *) ACPI_TABLE_FADT, sizeof(int), - 0444, NULL, &acpi_do_table}, - - {ACPI_DSDT, "dsdt", (void *) ACPI_TABLE_DSDT, sizeof(int), - 0444, NULL, &acpi_do_table}, - - {ACPI_FACS, "facs", (void *) ACPI_TABLE_FACS, sizeof(int), - 0444, NULL, &acpi_do_table}, - - {ACPI_XSDT, "xsdt", (void *) ACPI_TABLE_XSDT, sizeof(int), - 0444, NULL, &acpi_do_table}, - - {ACPI_PMTIMER, "pm_timer", NULL, 0, 0444, NULL, &acpi_do_pm_timer}, - - {0} -}; + acpi_buffer buffer; + acpi_system_info sys_info; -static struct ctl_table acpi_dir_table[] = -{ - {CTL_ACPI, "acpi", NULL, 0, 0555, acpi_table}, - {0} -}; + if (PM_IS_ACTIVE()) { + printk(KERN_NOTICE "ACPI: APM is already active, exiting\n"); + return -ENODEV; + } -/* - * Initialize and run interpreter within a kernel thread - */ -static int -acpi_thread(void *context) -{ - ACPI_PHYSICAL_ADDRESS rsdp_phys; - ACPI_BUFFER buffer; - ACPI_SYSTEM_INFO sys_info; - - /* - * initialize - */ - daemonize(); - strcpy(current->comm, "kacpid"); + if (acpi_disabled) { + printk(KERN_NOTICE "ACPI: disabled by cmdline, exiting\n"); + return -ENODEV; + } if (!ACPI_SUCCESS(acpi_initialize_subsystem())) { printk(KERN_ERR "ACPI: Driver initialization failed\n"); return -ENODEV; } -#ifndef ACPI_CAN_USE_EFI_STRUCT - if (!ACPI_SUCCESS(acpi_find_root_pointer(&rsdp_phys))) { - printk(KERN_ERR "ACPI: System description tables not found\n"); + /* from this point on, on error we must call acpi_terminate() */ + if (!ACPI_SUCCESS(acpi_load_tables())) { + printk(KERN_ERR "ACPI: System description table load failed\n"); + acpi_terminate(); return -ENODEV; } -#else - rsdp_phys = efi.acpi; -#endif - - if (!ACPI_SUCCESS(acpi_find_and_load_tables(rsdp_phys))) + + /* get a separate copy of the FADT for use by other drivers */ + memset(&acpi_fadt, 0, sizeof(acpi_fadt)); + buffer.pointer = &acpi_fadt; + buffer.length = sizeof(acpi_fadt); + + if (!ACPI_SUCCESS(acpi_get_table(ACPI_TABLE_FADT, 1, &buffer))) { + printk(KERN_ERR "ACPI: Could not get FADT\n"); + acpi_terminate(); return -ENODEV; + } - if (PM_IS_ACTIVE()) { - printk(KERN_NOTICE "ACPI: APM is already active, exiting\n"); + if (acpi_blacklisted(&acpi_fadt)) { + printk(KERN_ERR "ACPI: On blacklist -- BIOS not fully ACPI compliant\n"); acpi_terminate(); return -ENODEV; } @@ -481,129 +178,37 @@ return -ENODEV; } - printk(KERN_ERR "ACPI: Subsystem enabled\n"); + printk(KERN_INFO "ACPI: Subsystem enabled\n"); pm_active = 1; - acpi_cpu_init(); - acpi_sys_init(); - acpi_ec_init(); - acpi_power_init(); - - /* - * Non-intuitive: 0 means pwr and sleep are implemented using the fixed - * feature model, so we install handlers. 1 means a control method - * implementation, or none at all, so do nothing. See ACPI spec. - */ - if (acpi_fadt.pwr_button == 0) { - if (!ACPI_SUCCESS(acpi_install_fixed_event_handler( - ACPI_EVENT_POWER_BUTTON, - acpi_event, - (void *) ACPI_EVENT_POWER_BUTTON))) { - printk(KERN_ERR "ACPI: power button enable failed\n"); - } - } - - if (acpi_fadt.sleep_button == 0) { - if (!ACPI_SUCCESS(acpi_install_fixed_event_handler( - ACPI_EVENT_SLEEP_BUTTON, - acpi_event, - (void *) ACPI_EVENT_SLEEP_BUTTON))) { - printk(KERN_ERR "ACPI: sleep button enable failed\n"); - } - } - - acpi_sysctl = register_sysctl_table(acpi_dir_table, 1); - - /* - * run - */ - for (;;) { - DECLARE_WAITQUEUE(wait, current); - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&acpi_thread_wait, &wait); - - if (list_empty(&acpi_thread_run)) - schedule(); - - remove_wait_queue(&acpi_thread_wait, &wait); - set_current_state(TASK_RUNNING); - - if (signal_pending(current)) - break; - - run_task_queue(&acpi_thread_run); - } - - /* - * terminate - */ - unregister_sysctl_table(acpi_sysctl); - - /* do not terminate, because we need acpi in order to shut down */ - /*acpi_terminate();*/ - - acpi_thread_pid = -1; - return 0; } /* - * Start the interpreter - */ -int __init -acpi_init(void) -{ - if (acpi_start) { - acpi_thread_pid = kernel_thread(acpi_thread, - NULL, - (CLONE_FS | CLONE_FILES - | CLONE_SIGHAND | SIGCHLD)); - } - else { - printk(KERN_INFO "ACPI: Disabled\n"); - } - - return ((acpi_thread_pid >= 0) ? 0:-ENODEV); -} - -/* * Terminate the interpreter */ -void __exit +void acpi_exit(void) { - int count; + acpi_terminate(); - if (!kill_proc(acpi_thread_pid, SIGTERM, 1)) { - // wait until thread terminates (at most 5 seconds) - count = 5 * HZ; - while (acpi_thread_pid >= 0 && --count) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - } - } - - pm_idle = NULL; - pm_power_off = NULL; pm_active = 0; + + printk(KERN_ERR "ACPI: Subsystem disabled\n"); } module_init(acpi_init); module_exit(acpi_exit); #ifndef MODULE -static int __init acpi_setup(char *str) -{ - while ((str != NULL) && (*str != '\0')) { - if (strncmp(str, "no-idle", 7) == 0) - acpi_use_idle = 0; - if (strncmp(str, "off", 3) == 0) - acpi_start = 0; - str = strchr(str, ','); - if (str != NULL) - str += strspn(str, ", \t"); +static int __init acpi_setup(char *str) { + while (str && *str) { + if (strncmp(str, "off", 3) == 0) + acpi_disabled = 1; + str = strchr(str, ','); + if (str) + str += strspn(str, ", \t"); } return 1; } Index: os.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/acpi/os.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- os.c 25 Feb 2001 23:15:15 -0000 1.1.1.2 +++ os.c 9 Apr 2002 14:05:42 -0000 1.2 @@ -1,7 +1,15 @@ +/****************************************************************************** + * + * Module Name: os.c - Linux OSL functions + * $Revision$ + * + *****************************************************************************/ + /* * os.c - OS-dependent functions * * Copyright (C) 2000 Andrew Henroid [...987 lines suppressed...] + { + char *bp_info = (char*) info; + + printk(KERN_ERR "ACPI breakpoint: %s\n", bp_info); + } + default: + break; + } + + return AE_OK; +} + +acpi_status +acpi_os_breakpoint(NATIVE_CHAR *msg) +{ + acpi_os_printf("breakpoint: %s", msg); + + return AE_OK; +} + --- cmbatt.c DELETED --- --- cpu.c DELETED --- --- driver.h DELETED --- --- ec.c DELETED --- --- ec.h DELETED --- --- ksyms.c DELETED --- --- power.c DELETED --- --- sys.c DELETED --- --- table.c DELETED --- |
From: Andy P. <at...@us...> - 2002-04-09 14:08:26
|
Update of /cvsroot/linux-vax/kernel-2.4/fs/msdos In directory usw-pr-cvs1:/tmp/cvs-serv29245/msdos Modified Files: namei.c Log Message: synch 2.4.15 commit 13 Index: namei.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/msdos/namei.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- namei.c 14 Jan 2001 16:25:47 -0000 1.1.1.1 +++ namei.c 9 Apr 2002 13:19:34 -0000 1.2 @@ -17,8 +17,6 @@ #include <asm/uaccess.h> -#include "../fat/msbuffer.h" - #define MSDOS_DEBUG 0 #define PRINTK(x) @@ -389,7 +387,7 @@ return res; mkdir_error: - printk("msdos_mkdir: error=%d, attempting cleanup\n", res); + printk(KERN_WARNING "msdos_mkdir: error=%d, attempting cleanup\n", res); inode->i_nlink = 0; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; dir->i_nlink--; |
Update of /cvsroot/linux-vax/kernel-2.4/fs In directory usw-pr-cvs1:/tmp/cvs-serv27691 Modified Files: dcache.c devices.c dquot.c exec.c fcntl.c file_table.c filesystems.c inode.c iobuf.c Log Message: sync 2.4.15 commit 11 Index: dcache.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/dcache.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- dcache.c 25 Feb 2001 23:14:46 -0000 1.1.1.2 +++ dcache.c 9 Apr 2002 13:11:16 -0000 1.2 @@ -22,6 +22,7 @@ #include <linux/init.h> #include <linux/smp_lock.h> #include <linux/cache.h> +#include <linux/module.h> #include <asm/uaccess.h> @@ -138,10 +139,6 @@ goto kill_it; list_add(&dentry->d_lru, &dentry_unused); dentry_stat.nr_unused++; - /* - * Update the timestamp - */ - dentry->d_reftime = jiffies; spin_unlock(&dcache_lock); return; @@ -223,8 +220,7 @@ atomic_inc(&dentry->d_count); if (atomic_read(&dentry->d_count) == 1) { dentry_stat.nr_unused--; - list_del(&dentry->d_lru); - INIT_LIST_HEAD(&dentry->d_lru); /* make "list_empty()" work */ + list_del_init(&dentry->d_lru); } return dentry; } @@ -337,10 +333,10 @@ dentry = list_entry(tmp, struct dentry, d_lru); /* If the dentry was recently referenced, don't free it. */ - if (dentry->d_flags & DCACHE_REFERENCED) { - dentry->d_flags &= ~DCACHE_REFERENCED; + if (dentry->d_vfs_flags & DCACHE_REFERENCED) { + dentry->d_vfs_flags &= ~DCACHE_REFERENCED; list_add(&dentry->d_lru, &dentry_unused); - goto next; + continue; } dentry_stat.nr_unused--; @@ -349,7 +345,6 @@ BUG(); prune_one_dentry(dentry); - next: if (!--count) break; } @@ -413,8 +408,7 @@ if (atomic_read(&dentry->d_count)) continue; dentry_stat.nr_unused--; - list_del(tmp); - INIT_LIST_HEAD(tmp); + list_del_init(tmp); prune_one_dentry(dentry); goto repeat; } @@ -553,7 +547,7 @@ * ... * 6 - base-level: try to shrink a bit. */ -void shrink_dcache_memory(int priority, unsigned int gfp_mask) +int shrink_dcache_memory(int priority, unsigned int gfp_mask) { int count = 0; @@ -568,14 +562,14 @@ * We should make sure we don't hold the superblock lock over * block allocations, but for now: */ - if (!(gfp_mask & __GFP_IO)) - return; + if (!(gfp_mask & __GFP_FS)) + return 0; - if (priority) - count = dentry_stat.nr_unused / priority; + count = dentry_stat.nr_unused / priority; prune_dcache(count); kmem_cache_shrink(dentry_cache); + return 0; } #define NAME_ALLOC_LEN(len) ((len+16) & ~15) @@ -612,6 +606,7 @@ str[name->len] = 0; atomic_set(&dentry->d_count, 1); + dentry->d_vfs_flags = 0; dentry->d_flags = 0; dentry->d_inode = NULL; dentry->d_parent = NULL; @@ -621,7 +616,7 @@ dentry->d_name.hash = name->hash; dentry->d_op = NULL; dentry->d_fsdata = NULL; - INIT_LIST_HEAD(&dentry->d_vfsmnt); + dentry->d_mounted = 0; INIT_LIST_HEAD(&dentry->d_hash); INIT_LIST_HEAD(&dentry->d_lru); INIT_LIST_HEAD(&dentry->d_subdirs); @@ -656,6 +651,7 @@ void d_instantiate(struct dentry *entry, struct inode * inode) { + if (!list_empty(&entry->d_alias)) BUG(); spin_lock(&dcache_lock); if (inode) list_add(&entry->d_alias, &inode->i_dentry); @@ -734,7 +730,7 @@ continue; } __dget_locked(dentry); - dentry->d_flags |= DCACHE_REFERENCED; + dentry->d_vfs_flags |= DCACHE_REFERENCED; spin_unlock(&dcache_lock); return dentry; } @@ -744,58 +740,48 @@ /** * d_validate - verify dentry provided from insecure source - * @dentry: The dentry alleged to be valid - * @dparent: The parent dentry + * @dentry: The dentry alleged to be valid child of @dparent + * @dparent: The parent dentry (known to be valid) * @hash: Hash of the dentry * @len: Length of the name * * An insecure source has sent us a dentry, here we verify it and dget() it. * This is used by ncpfs in its readdir implementation. * Zero is returned in the dentry is invalid. - * - * NOTE: This function does _not_ dereference the pointers before we have - * validated them. We can test the pointer values, but we - * must not actually use them until we have found a valid - * copy of the pointer in kernel space.. */ -int d_validate(struct dentry *dentry, struct dentry *dparent, - unsigned int hash, unsigned int len) +int d_validate(struct dentry *dentry, struct dentry *dparent) { + unsigned long dent_addr = (unsigned long) dentry; + unsigned long min_addr = PAGE_OFFSET; + unsigned long align_mask = 0x0F; struct list_head *base, *lhp; - int valid = 1; - spin_lock(&dcache_lock); - if (dentry != dparent) { - base = d_hash(dparent, hash); - lhp = base; - while ((lhp = lhp->next) != base) { - if (dentry == list_entry(lhp, struct dentry, d_hash)) { - __dget_locked(dentry); - goto out; - } - } - } else { - /* - * Special case: local mount points don't live in - * the hashes, so we search the super blocks. - */ - struct super_block *sb = sb_entry(super_blocks.next); + if (dent_addr < min_addr) + goto out; + if (dent_addr > (unsigned long)high_memory - sizeof(struct dentry)) + goto out; + if (dent_addr & align_mask) + goto out; + if ((!kern_addr_valid(dent_addr)) || (!kern_addr_valid(dent_addr -1 + + sizeof(struct dentry)))) + goto out; - for (; sb != sb_entry(&super_blocks); - sb = sb_entry(sb->s_list.next)) { - if (!sb->s_dev) - continue; - if (sb->s_root == dentry) { - __dget_locked(dentry); - goto out; - } + if (dentry->d_parent != dparent) + goto out; + + spin_lock(&dcache_lock); + lhp = base = d_hash(dparent, dentry->d_name.hash); + while ((lhp = lhp->next) != base) { + if (dentry == list_entry(lhp, struct dentry, d_hash)) { + __dget_locked(dentry); + spin_unlock(&dcache_lock); + return 1; } } - valid = 0; -out: spin_unlock(&dcache_lock); - return valid; +out: + return 0; } /* @@ -848,6 +834,7 @@ void d_rehash(struct dentry * entry) { struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash); + if (!list_empty(&entry->d_hash)) BUG(); spin_lock(&dcache_lock); list_add(&entry->d_hash, list); spin_unlock(&dcache_lock); @@ -922,8 +909,7 @@ list_add(&dentry->d_hash, &target->d_hash); /* Unhash the target: dput() will then get rid of it */ - list_del(&target->d_hash); - INIT_LIST_HEAD(&target->d_hash); + list_del_init(&target->d_hash); list_del(&dentry->d_child); list_del(&target->d_child); @@ -1239,6 +1225,18 @@ } while (i); } +static void init_buffer_head(void * foo, kmem_cache_t * cachep, unsigned long flags) +{ + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == + SLAB_CTOR_CONSTRUCTOR) + { + struct buffer_head * bh = (struct buffer_head *) foo; + + memset(bh, 0, sizeof(*bh)); + init_waitqueue_head(&bh->b_wait); + } +} + /* SLAB cache for __getname() consumers */ kmem_cache_t *names_cachep; @@ -1250,12 +1248,16 @@ /* SLAB cache for buffer_head structures */ kmem_cache_t *bh_cachep; +EXPORT_SYMBOL(bh_cachep); + +extern void bdev_cache_init(void); +extern void cdev_cache_init(void); void __init vfs_caches_init(unsigned long mempages) { bh_cachep = kmem_cache_create("buffer_head", sizeof(struct buffer_head), 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); + SLAB_HWCACHE_ALIGN, init_buffer_head, NULL); if(!bh_cachep) panic("Cannot create buffer head SLAB cache"); @@ -1280,4 +1282,8 @@ #endif dcache_init(mempages); + inode_init(mempages); + mnt_init(mempages); + bdev_cache_init(); + cdev_cache_init(); } Index: devices.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/devices.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- devices.c 14 Jan 2001 16:25:21 -0000 1.1.1.1 +++ devices.c 9 Apr 2002 13:11:16 -0000 1.2 @@ -203,10 +203,10 @@ if (S_ISCHR(mode)) { inode->i_fop = &def_chr_fops; inode->i_rdev = to_kdev_t(rdev); + inode->i_cdev = cdget(rdev); } else if (S_ISBLK(mode)) { inode->i_fop = &def_blk_fops; inode->i_rdev = to_kdev_t(rdev); - inode->i_bdev = bdget(rdev); } else if (S_ISFIFO(mode)) inode->i_fop = &def_fifo_fops; else if (S_ISSOCK(mode)) Index: dquot.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/dquot.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- dquot.c 25 Feb 2001 23:14:46 -0000 1.1.1.2 +++ dquot.c 9 Apr 2002 13:11:16 -0000 1.2 @@ -26,7 +26,7 @@ * dquot_incr_...() to calling functions. * invalidate_dquots() now writes modified dquots. * Serialized quota_off() and quota_on() for mount point. - * Fixed a few bugs in grow_dquots. + * Fixed a few bugs in grow_dquots(). * Fixed deadlock in write_dquot() - we no longer account quotas on * quota files * remove_dquot_ref() moved to inode.c - it now traverses through inodes @@ -34,13 +34,24 @@ * Added check for bogus uid and fixed check for group in quotactl. * Jan Kara, <ja...@su...>, sponsored by SuSE CR, 10-11/99 [...1541 lines suppressed...] + ret = quota_on(sb, type, (char *) addr); goto out; case Q_QUOTAOFF: ret = quota_off(sb, type); @@ -1597,12 +1468,12 @@ goto out; } - flags |= QUOTA_SYSCALL; - - ret = -ESRCH; + ret = -NODEV; if (sb && sb_has_quota_enabled(sb, type)) ret = set_dqblk(sb, id, type, flags, (struct dqblk *) addr); out: + if (sb) + drop_super(sb); unlock_kernel(); return ret; } Index: exec.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/exec.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- exec.c 25 Feb 2001 23:14:45 -0000 1.1.1.2 +++ exec.c 9 Apr 2002 13:11:16 -0000 1.2 @@ -34,6 +34,7 @@ #include <linux/pagemap.h> #include <linux/highmem.h> #include <linux/spinlock.h> +#include <linux/personality.h> #define __NO_VERSION__ #include <linux/module.h> @@ -45,6 +46,8 @@ #include <linux/kmod.h> #endif +int core_uses_pid; + static struct linux_binfmt *formats; static rwlock_t binfmt_lock = RW_LOCK_UNLOCKED; @@ -159,11 +162,9 @@ if (argv != NULL) { for (;;) { char * p; - int error; - error = get_user(p,argv); - if (error) - return error; + if (get_user(p, argv)) + return -EFAULT; if (!p) break; argv++; @@ -186,7 +187,7 @@ int len; unsigned long pos; - if (get_user(str, argv+argc) || !str || !(len = strnlen_user(str, bprm->p))) + if (get_user(str, argv+argc) || !(len = strnlen_user(str, bprm->p))) return -EFAULT; if (bprm->p < len) return -E2BIG; @@ -252,6 +253,8 @@ /* * This routine is used to map in a page into an address space: needed by * execve() for the initial stack and environment pages. + * + * tsk->mmap_sem is held for writing. */ void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long address) { @@ -260,29 +263,32 @@ pte_t * pte; if (page_count(page) != 1) - printk("mem_map disagrees with %p at %08lx\n", page, address); + printk(KERN_ERR "mem_map disagrees with %p at %08lx\n", page, address); pgd = pgd_offset(tsk->mm, address); - pmd = pmd_alloc(pgd, address); - if (!pmd) { - __free_page(page); - force_sig(SIGKILL, tsk); - return; - } - pte = pte_alloc(pmd, address); - if (!pte) { - __free_page(page); - force_sig(SIGKILL, tsk); - return; - } - if (!pte_none(*pte)) { - pte_ERROR(*pte); - __free_page(page); - return; - } + + spin_lock(&tsk->mm->page_table_lock); + pmd = pmd_alloc(tsk->mm, pgd, address); + if (!pmd) + goto out; + pte = pte_alloc(tsk->mm, pmd, address); + if (!pte) + goto out; + if (!pte_none(*pte)) + goto out; + lru_cache_add(page); flush_dcache_page(page); flush_page_to_ram(page); set_pte(pte, pte_mkdirty(pte_mkwrite(mk_pte(page, PAGE_COPY)))); -/* no need for flush_tlb */ + tsk->mm->rss++; + spin_unlock(&tsk->mm->page_table_lock); + + /* no need for flush_tlb */ + return; +out: + spin_unlock(&tsk->mm->page_table_lock); + __free_page(page); + force_sig(SIGKILL, tsk); + return; } int setup_arg_pages(struct linux_binprm *bprm) @@ -302,7 +308,7 @@ if (!mpnt) return -ENOMEM; - down(¤t->mm->mmap_sem); + down_write(¤t->mm->mmap_sem); { mpnt->vm_mm = current->mm; mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p; @@ -321,12 +327,11 @@ struct page *page = bprm->page[i]; if (page) { bprm->page[i] = NULL; - current->mm->rss++; put_dirty_page(current,page,stack_base); } stack_base += PAGE_SIZE; } - up(¤t->mm->mmap_sem); + up_write(¤t->mm->mmap_sem); return 0; } @@ -344,8 +349,11 @@ if (!err) { inode = nd.dentry->d_inode; file = ERR_PTR(-EACCES); - if (!IS_NOEXEC(inode) && S_ISREG(inode->i_mode)) { + if (!(nd.mnt->mnt_flags & MNT_NOEXEC) && + S_ISREG(inode->i_mode)) { int err = permission(inode, MAY_EXEC); + if (!err && !(inode->i_mode & 0111)) + err = -EACCES; file = ERR_PTR(err); if (!err) { file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); @@ -545,7 +553,7 @@ current->sas_ss_sp = current->sas_ss_size = 0; if (current->euid == current->uid && current->egid == current->gid) - current->dumpable = 1; + current->mm->dumpable = 1; name = bprm->filename; for (i=0; (ch = *(name++)) != '\0';) { if (ch == '/') @@ -562,7 +570,7 @@ if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || permission(bprm->file->f_dentry->d_inode,MAY_READ)) - current->dumpable = 0; + current->mm->dumpable = 0; /* An exec changes our domain. We are no longer part of the thread group */ @@ -577,9 +585,10 @@ mmap_failed: flush_failed: spin_lock_irq(¤t->sigmask_lock); - if (current->sig != oldsig) + if (current->sig != oldsig) { kfree(current->sig); - current->sig = oldsig; + current->sig = oldsig; + } spin_unlock_irq(¤t->sigmask_lock); return retval; } @@ -590,7 +599,7 @@ */ static inline int must_not_trace_exec(struct task_struct * p) { - return (p->ptrace & PT_PTRACED) && !cap_raised(p->p_pptr->cap_effective, CAP_SYS_PTRACE); + return (p->ptrace & PT_PTRACED) && !(p->ptrace & PT_PTRACE_CAP); } /* @@ -603,7 +612,10 @@ struct inode * inode = bprm->file->f_dentry->d_inode; mode = inode->i_mode; - /* Huh? We had already checked for MAY_EXEC, WTF do we check this? */ + /* + * Check execute perms again - if the caller has CAP_DAC_OVERRIDE, + * vfs_permission lets a non-executable through + */ if (!(mode & 0111)) /* with at least _one_ execute bit set */ return -EACCES; if (bprm->file->f_op == NULL) @@ -612,7 +624,7 @@ bprm->e_uid = current->euid; bprm->e_gid = current->egid; - if(!IS_NOSUID(inode)) { + if(!(bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID)) { /* Set-uid? */ if (mode & S_ISUID) bprm->e_uid = inode->i_uid; @@ -680,7 +692,7 @@ if (bprm->e_uid != current->uid || bprm->e_gid != current->gid || !cap_issubset(new_permitted, current->cap_permitted)) { - current->dumpable = 0; + current->mm->dumpable = 0; lock_kernel(); if (must_not_trace_exec(current) @@ -759,7 +771,6 @@ if (!bprm->loader && eh->fh.f_magic == 0x183 && (eh->fh.f_flags & 0x3000) == 0x3000) { - char * dynloader[] = { "/sbin/loader" }; struct file * file; unsigned long loader; @@ -769,10 +780,14 @@ loader = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); - file = open_exec(dynloader[0]); + file = open_exec("/sbin/loader"); retval = PTR_ERR(file); if (IS_ERR(file)) return retval; + + /* Remember if the application is TASO. */ + bprm->sh_bang = eh->ah.entry < 0x100000000; + bprm->file = file; bprm->loader = loader; retval = prepare_binprm(bprm); @@ -783,6 +798,9 @@ } } #endif + /* kernel module loader fixup */ + /* so we don't try to load run modprobe in kernel space. */ + set_fs(USER_DS); for (try=0; try<2; try++) { read_lock(&binfmt_lock); for (fmt = formats ; fmt ; fmt = fmt->next) { @@ -918,26 +936,25 @@ int do_coredump(long signr, struct pt_regs * regs) { struct linux_binfmt * binfmt; - char corename[6+sizeof(current->comm)]; + char corename[6+sizeof(current->comm)+10]; struct file * file; struct inode * inode; + int retval = 0; lock_kernel(); binfmt = current->binfmt; if (!binfmt || !binfmt->core_dump) goto fail; - if (!current->dumpable || atomic_read(¤t->mm->mm_users) != 1) + if (!current->mm->dumpable) goto fail; - current->dumpable = 0; + current->mm->dumpable = 0; if (current->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump) goto fail; memcpy(corename,"core.", 5); -#if 0 - memcpy(corename+5,current->comm,sizeof(current->comm)); -#else corename[4] = '\0'; -#endif + if (core_uses_pid || atomic_read(¤t->mm->mm_users) != 1) + sprintf(&corename[4], ".%d", current->pid); file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW, 0600); if (IS_ERR(file)) goto fail; @@ -955,15 +972,14 @@ goto close_fail; if (do_truncate(file->f_dentry, 0) != 0) goto close_fail; - if (!binfmt->core_dump(signr, regs, file)) - goto close_fail; - unlock_kernel(); - filp_close(file, NULL); - return 1; + + down_read(¤t->mm->mmap_sem); + retval = binfmt->core_dump(signr, regs, file); + up_read(¤t->mm->mmap_sem); close_fail: filp_close(file, NULL); fail: unlock_kernel(); - return 0; + return retval; } Index: fcntl.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/fcntl.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- fcntl.c 14 Jan 2001 16:25:03 -0000 1.1.1.1 +++ fcntl.c 9 Apr 2002 13:11:16 -0000 1.2 @@ -10,6 +10,7 @@ #include <linux/dnotify.h> #include <linux/smp_lock.h> #include <linux/slab.h> +#include <linux/iobuf.h> #include <asm/poll.h> #include <asm/siginfo.h> @@ -194,7 +195,7 @@ return ret; } -#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC) +#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC | O_DIRECT) static int setfl(int fd, struct file * filp, unsigned long arg) { @@ -217,6 +218,25 @@ } } + if (arg & O_DIRECT) { + /* + * alloc_kiovec() can sleep and we are only serialized by + * the big kernel lock here, so abuse the i_sem to serialize + * this case too. We of course wouldn't need to go deep down + * to the inode layer, we could stay at the file layer, but + * we don't want to pay for the memory of a semaphore in each + * file structure too and we use the inode semaphore that we just + * pay for anyways. + */ + error = 0; + down(&inode->i_sem); + if (!filp->f_iobuf) + error = alloc_kiovec(1, &filp->f_iobuf); + up(&inode->i_sem); + if (error < 0) + return error; + } + /* required for strict SunOS emulation */ if (O_NONBLOCK != O_NDELAY) if (arg & O_NDELAY) @@ -338,7 +358,6 @@ if (!filp) goto out; - lock_kernel(); switch (cmd) { case F_GETLK64: err = fcntl_getlk64(fd, (struct flock64 *) arg); @@ -353,7 +372,6 @@ err = do_fcntl(fd, cmd, arg, filp); break; } - unlock_kernel(); fput(filp); out: return err; Index: file_table.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/file_table.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- file_table.c 14 Jan 2001 16:24:51 -0000 1.1.1.1 +++ file_table.c 9 Apr 2002 13:11:16 -0000 1.2 @@ -11,6 +11,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/smp_lock.h> +#include <linux/iobuf.h> /* sysctl tunables... */ struct files_stat_struct files_stat = {0, 0, NR_FILE}; @@ -66,10 +67,10 @@ goto new_one; } /* Big problems... */ - printk("VFS: filp allocation failed\n"); + printk(KERN_WARNING "VFS: filp allocation failed\n"); } else if (files_stat.max_files > old_max) { - printk("VFS: file-max limit %d reached\n", files_stat.max_files); + printk(KERN_INFO "VFS: file-max limit %d reached\n", files_stat.max_files); old_max = files_stat.max_files; } file_list_unlock(); @@ -104,21 +105,24 @@ if (atomic_dec_and_test(&file->f_count)) { locks_remove_flock(file); + + if (file->f_iobuf) + free_kiovec(1, &file->f_iobuf); + if (file->f_op && file->f_op->release) file->f_op->release(inode, file); fops_put(file->f_op); - file->f_dentry = NULL; - file->f_vfsmnt = NULL; if (file->f_mode & FMODE_WRITE) put_write_access(inode); - dput(dentry); - if (mnt) - mntput(mnt); file_list_lock(); + file->f_dentry = NULL; + file->f_vfsmnt = NULL; list_del(&file->f_list); list_add(&file->f_list, &free_list); files_stat.nr_free_files++; file_list_unlock(); + dput(dentry); + mntput(mnt); } } @@ -158,14 +162,6 @@ file_list_unlock(); } -void file_moveto(struct file *new, struct file *old) -{ - file_list_lock(); - list_del(&new->f_list); - list_add(&new->f_list, &old->f_list); - file_list_unlock(); -} - int fs_may_remount_ro(struct super_block *sb) { struct list_head *p; @@ -174,12 +170,7 @@ file_list_lock(); for (p = sb->s_files.next; p != &sb->s_files; p = p->next) { struct file *file = list_entry(p, struct file, f_list); - struct inode *inode; - - if (!file->f_dentry) - continue; - - inode = file->f_dentry->d_inode; + struct inode *inode = file->f_dentry->d_inode; /* File with pending delete? */ if (inode->i_nlink == 0) Index: filesystems.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/filesystems.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- filesystems.c 14 Jan 2001 16:25:21 -0000 1.1.1.1 +++ filesystems.c 9 Apr 2002 13:11:16 -0000 1.2 @@ -7,36 +7,11 @@ */ #include <linux/config.h> -#include <linux/fs.h> - -#include <linux/devfs_fs_kernel.h> -#include <linux/nfs_fs.h> -#include <linux/auto_fs.h> -#include <linux/devpts_fs.h> -#include <linux/major.h> -#include <linux/smp.h> +#include <linux/module.h> +#include <linux/sched.h> #include <linux/smp_lock.h> #include <linux/kmod.h> -#include <linux/init.h> -#include <linux/module.h> #include <linux/nfsd/interface.h> - -#ifdef CONFIG_DEVPTS_FS -extern int init_devpts_fs(void); -#endif - -void __init filesystem_setup(void) -{ - init_devfs_fs(); /* Header file may make this empty */ - -#ifdef CONFIG_NFS_FS - init_nfs_fs(); -#endif - -#ifdef CONFIG_DEVPTS_FS - init_devpts_fs(); -#endif -} #if defined(CONFIG_NFSD_MODULE) struct nfsd_linkage *nfsd_linkage = NULL; Index: inode.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/inode.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- inode.c 25 Feb 2001 23:14:45 -0000 1.1.1.2 +++ inode.c 9 Apr 2002 13:11:16 -0000 1.2 @@ -13,6 +13,10 @@ #include <linux/quotaops.h> #include <linux/slab.h> #include <linux/cache.h> +#include <linux/swap.h> +#include <linux/swapctl.h> +#include <linux/prefetch.h> +#include <linux/locks.h> /* * New inode.c implementation. @@ -62,7 +66,7 @@ * NOTE! You also have to own the lock if you change * the i_state of an inode while it is in use.. */ -spinlock_t inode_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t inode_lock = SPIN_LOCK_UNLOCKED; /* * Statistics gathering.. @@ -75,7 +79,7 @@ ((struct inode *) kmem_cache_alloc(inode_cachep, SLAB_KERNEL)) static void destroy_inode(struct inode *inode) { - if (!list_empty(&inode->i_dirty_buffers)) + if (inode_has_buffers(inode)) BUG(); kmem_cache_free(inode_cachep, (inode)); } @@ -101,6 +105,8 @@ INIT_LIST_HEAD(&inode->i_data.locked_pages); INIT_LIST_HEAD(&inode->i_dentry); INIT_LIST_HEAD(&inode->i_dirty_buffers); + INIT_LIST_HEAD(&inode->i_dirty_data_buffers); + INIT_LIST_HEAD(&inode->i_devices); sema_init(&inode->i_sem, 1); sema_init(&inode->i_zombie, 1); spin_lock_init(&inode->i_data.i_shared_lock); @@ -123,36 +129,38 @@ /** * __mark_inode_dirty - internal function * @inode: inode to mark - * - * Mark an inode as dirty. Callers should use mark_inode_dirty. + * @flags: what kind of dirty (i.e. I_DIRTY_SYNC) + * Mark an inode as dirty. Callers should use mark_inode_dirty or + * mark_inode_dirty_sync. */ void __mark_inode_dirty(struct inode *inode, int flags) { struct super_block * sb = inode->i_sb; - if (sb) { - /* Don't do this for I_DIRTY_PAGES - that doesn't actually dirty the inode itself */ - if (flags & (I_DIRTY | I_DIRTY_SYNC)) { - if (sb->s_op && sb->s_op->dirty_inode) - sb->s_op->dirty_inode(inode); - } + if (!sb) + return; - /* avoid the locking if we can */ - if ((inode->i_state & flags) == flags) - return; + /* Don't do this for I_DIRTY_PAGES - that doesn't actually dirty the inode itself */ + if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { + if (sb->s_op && sb->s_op->dirty_inode) + sb->s_op->dirty_inode(inode); + } - spin_lock(&inode_lock); - if ((inode->i_state & flags) != flags) { - inode->i_state |= flags; - /* Only add valid (ie hashed) inodes to the dirty list */ - if (!list_empty(&inode->i_hash)) { - list_del(&inode->i_list); - list_add(&inode->i_list, &sb->s_dirty); - } + /* avoid the locking if we can */ + if ((inode->i_state & flags) == flags) + return; + + spin_lock(&inode_lock); + if ((inode->i_state & flags) != flags) { + inode->i_state |= flags; + /* Only add valid (ie hashed) inodes to the dirty list */ + if (!(inode->i_state & I_LOCK) && !list_empty(&inode->i_hash)) { + list_del(&inode->i_list); + list_add(&inode->i_list, &sb->s_dirty); } - spin_unlock(&inode_lock); } + spin_unlock(&inode_lock); } static void __wait_on_inode(struct inode * inode) @@ -179,7 +187,7 @@ static inline void write_inode(struct inode *inode, int sync) { - if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->write_inode) + if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->write_inode && !is_bad_inode(inode)) inode->i_sb->s_op->write_inode(inode, sync); } @@ -190,13 +198,53 @@ return; } atomic_inc(&inode->i_count); - if (!(inode->i_state & I_DIRTY)) { + if (!(inode->i_state & (I_DIRTY|I_LOCK))) { list_del(&inode->i_list); list_add(&inode->i_list, &inode_in_use); } inodes_stat.nr_unused--; } +static inline void __sync_one(struct inode *inode, int sync) +{ + unsigned dirty; + + list_del(&inode->i_list); + list_add(&inode->i_list, &inode->i_sb->s_locked_inodes); + + if (inode->i_state & I_LOCK) + BUG(); + + /* Set I_LOCK, reset I_DIRTY */ + dirty = inode->i_state & I_DIRTY; + inode->i_state |= I_LOCK; + inode->i_state &= ~I_DIRTY; + spin_unlock(&inode_lock); + + filemap_fdatasync(inode->i_mapping); + + /* Don't write the inode if only I_DIRTY_PAGES was set */ + if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) + write_inode(inode, sync); + + filemap_fdatawait(inode->i_mapping); + + spin_lock(&inode_lock); + inode->i_state &= ~I_LOCK; + if (!(inode->i_state & I_FREEING)) { + struct list_head *to; + if (inode->i_state & I_DIRTY) + to = &inode->i_sb->s_dirty; + else if (atomic_read(&inode->i_count)) + to = &inode_in_use; + else + to = &inode_unused; + list_del(&inode->i_list); + list_add(&inode->i_list, to); + } + wake_up(&inode->i_wait); +} + static inline void sync_one(struct inode *inode, int sync) { if (inode->i_state & I_LOCK) { @@ -206,38 +254,117 @@ iput(inode); spin_lock(&inode_lock); } else { - unsigned dirty; + __sync_one(inode, sync); + } +} - list_del(&inode->i_list); - list_add(&inode->i_list, atomic_read(&inode->i_count) - ? &inode_in_use - : &inode_unused); - /* Set I_LOCK, reset I_DIRTY */ - dirty = inode->i_state & I_DIRTY; - inode->i_state |= I_LOCK; - inode->i_state &= ~I_DIRTY; +static inline void sync_list(struct list_head *head) +{ + struct list_head * tmp; + + while ((tmp = head->prev) != head) + __sync_one(list_entry(tmp, struct inode, i_list), 0); +} + +static inline void wait_on_locked(struct list_head *head) +{ + struct list_head * tmp; + while ((tmp = head->prev) != head) { + struct inode *inode = list_entry(tmp, struct inode, i_list); + __iget(inode); spin_unlock(&inode_lock); + __wait_on_inode(inode); + iput(inode); + spin_lock(&inode_lock); + } +} - filemap_fdatasync(inode->i_mapping); +static inline int try_to_sync_unused_list(struct list_head *head, int nr_inodes) +{ + struct list_head *tmp = head; + struct inode *inode; - /* Don't write the inode if only I_DIRTY_PAGES was set */ - if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) - write_inode(inode, sync); + while (nr_inodes && (tmp = tmp->prev) != head) { + inode = list_entry(tmp, struct inode, i_list); - filemap_fdatawait(inode->i_mapping); + if (!atomic_read(&inode->i_count)) { + __sync_one(inode, 0); + nr_inodes--; - spin_lock(&inode_lock); - inode->i_state &= ~I_LOCK; - wake_up(&inode->i_wait); + /* + * __sync_one moved the inode to another list, + * so we have to start looking from the list head. + */ + tmp = head; + } + } + + return nr_inodes; +} + +void sync_inodes_sb(struct super_block *sb) +{ + spin_lock(&inode_lock); + while (!list_empty(&sb->s_dirty)||!list_empty(&sb->s_locked_inodes)) { + sync_list(&sb->s_dirty); + wait_on_locked(&sb->s_locked_inodes); } + spin_unlock(&inode_lock); } -static inline void sync_list(struct list_head *head) +/* + * Note: + * We don't need to grab a reference to superblock here. If it has non-empty + * ->s_dirty it's hadn't been killed yet and kill_super() won't proceed + * past sync_inodes_sb() until both ->s_dirty and ->s_locked_inodes are + * empty. Since __sync_one() regains inode_lock before it finally moves + * inode from superblock lists we are OK. + */ + +void sync_unlocked_inodes(void) { - struct list_head * tmp; + struct super_block * sb; + spin_lock(&inode_lock); + spin_lock(&sb_lock); + sb = sb_entry(super_blocks.next); + for (; sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.next)) { + if (!list_empty(&sb->s_dirty)) { + spin_unlock(&sb_lock); + sync_list(&sb->s_dirty); + spin_lock(&sb_lock); + } + } + spin_unlock(&sb_lock); + spin_unlock(&inode_lock); +} - while ((tmp = head->prev) != head) - sync_one(list_entry(tmp, struct inode, i_list), 0); +/* + * Find a superblock with inodes that need to be synced + */ + +static struct super_block *get_super_to_sync(void) +{ + struct list_head *p; +restart: + spin_lock(&inode_lock); + spin_lock(&sb_lock); + list_for_each(p, &super_blocks) { + struct super_block *s = list_entry(p,struct super_block,s_list); + if (list_empty(&s->s_dirty) && list_empty(&s->s_locked_inodes)) + continue; + s->s_count++; + spin_unlock(&sb_lock); + spin_unlock(&inode_lock); + down_read(&s->s_umount); + if (!s->s_root) { + drop_super(s); + goto restart; + } + return s; + } + spin_unlock(&sb_lock); + spin_unlock(&inode_lock); + return NULL; } /** @@ -247,42 +374,48 @@ * sync_inodes goes through the super block's dirty list, * writes them out, and puts them back on the normal list. */ - + void sync_inodes(kdev_t dev) { - struct super_block * sb = sb_entry(super_blocks.next); + struct super_block * s; /* * Search the super_blocks array for the device(s) to sync. */ - spin_lock(&inode_lock); - for (; sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.next)) { - if (!sb->s_dev) - continue; - if (dev && sb->s_dev != dev) - continue; - - sync_list(&sb->s_dirty); - - if (dev) - break; + if (dev) { + if ((s = get_super(dev)) != NULL) { + sync_inodes_sb(s); + drop_super(s); + } + } else { + while ((s = get_super_to_sync()) != NULL) { + sync_inodes_sb(s); + drop_super(s); + } } - spin_unlock(&inode_lock); } -/* - * Called with the spinlock already held.. - */ -static void sync_all_inodes(void) +static void try_to_sync_unused_inodes(void * arg) { - struct super_block * sb = sb_entry(super_blocks.next); - for (; sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.next)) { - if (!sb->s_dev) + struct super_block * sb; + int nr_inodes = inodes_stat.nr_unused; + + spin_lock(&inode_lock); + spin_lock(&sb_lock); + sb = sb_entry(super_blocks.next); + for (; nr_inodes && sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.next)) { + if (list_empty(&sb->s_dirty)) continue; - sync_list(&sb->s_dirty); + spin_unlock(&sb_lock); + nr_inodes = try_to_sync_unused_list(&sb->s_dirty, nr_inodes); + spin_lock(&sb_lock); } + spin_unlock(&sb_lock); + spin_unlock(&inode_lock); } +static struct tq_struct unused_inodes_flush_task; + /** * write_inode_now - write an inode to disk * @inode: inode to write to disk @@ -301,9 +434,11 @@ while (inode->i_state & I_DIRTY) sync_one(inode, sync); spin_unlock(&inode_lock); + if (sync) + wait_on_inode(inode); } else - printk("write_inode_now: no super block\n"); + printk(KERN_ERR "write_inode_now: no super block\n"); } /** @@ -315,9 +450,9 @@ * O_SYNC flag set, to flush dirty writes to disk. */ -int generic_osync_inode(struct inode *inode, int datasync) +int generic_osync_inode(struct inode *inode, int what) { - int err; + int err = 0, err2 = 0, need_write_inode_now = 0; /* * WARNING @@ -340,23 +475,24 @@ * every O_SYNC write, not just the synchronous I/Os. --sct */ -#ifdef WRITERS_QUEUE_IO - err = osync_inode_buffers(inode); -#else - err = fsync_inode_buffers(inode); -#endif + if (what & OSYNC_METADATA) + err = fsync_inode_buffers(inode); + if (what & OSYNC_DATA) + err2 = fsync_inode_data_buffers(inode); + if (!err) + err = err2; spin_lock(&inode_lock); - if (!(inode->i_state & I_DIRTY)) - goto out; - if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) - goto out; + if ((inode->i_state & I_DIRTY) && + ((what & OSYNC_INODE) || (inode->i_state & I_DIRTY_DATASYNC))) + need_write_inode_now = 1; spin_unlock(&inode_lock); - write_inode_now(inode, 1); - return err; - out: - spin_unlock(&inode_lock); + if (need_write_inode_now) + write_inode_now(inode, 1); + else + wait_on_inode(inode); + return err; } @@ -371,8 +507,7 @@ void clear_inode(struct inode *inode) { - if (!list_empty(&inode->i_dirty_buffers)) - invalidate_inode_buffers(inode); + invalidate_inode_buffers(inode); if (inode->i_data.nrpages) BUG(); @@ -381,13 +516,14 @@ if (inode->i_state & I_CLEAR) BUG(); wait_on_inode(inode); - if (IS_QUOTAINIT(inode)) - DQUOT_DROP(inode); + DQUOT_DROP(inode); if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->clear_inode) inode->i_sb->s_op->clear_inode(inode); - if (inode->i_bdev) { - bdput(inode->i_bdev); - inode->i_bdev = NULL; + if (inode->i_bdev) + bd_forget(inode); + else if (inode->i_cdev) { + cdput(inode->i_cdev); + inode->i_cdev = NULL; } inode->i_state = I_CLEAR; } @@ -435,8 +571,7 @@ continue; invalidate_inode_buffers(inode); if (!atomic_read(&inode->i_count)) { - list_del(&inode->i_hash); - INIT_LIST_HEAD(&inode->i_hash); + list_del_init(&inode->i_hash); list_del(&inode->i_list); list_add(&inode->i_list, dispose); inode->i_state |= I_FREEING; @@ -476,12 +611,39 @@ busy = invalidate_list(&inode_in_use, sb, &throw_away); busy |= invalidate_list(&inode_unused, sb, &throw_away); busy |= invalidate_list(&sb->s_dirty, sb, &throw_away); + busy |= invalidate_list(&sb->s_locked_inodes, sb, &throw_away); spin_unlock(&inode_lock); dispose_list(&throw_away); return busy; } + +int invalidate_device(kdev_t dev, int do_sync) +{ + struct super_block *sb; + int res; + + if (do_sync) + fsync_dev(dev); + + res = 0; + sb = get_super(dev); + if (sb) { + /* + * no need to lock the super, get_super holds the + * read semaphore so the filesystem cannot go away + * under us (->put_super runs with the write lock + * hold). + */ + shrink_dcache_sb(sb); + res = invalidate_inodes(sb); + drop_super(sb); + } + invalidate_buffers(dev); + return res; +} + /* * This is called with the inode lock held. It searches @@ -503,13 +665,12 @@ { LIST_HEAD(list); struct list_head *entry, *freeable = &list; - int count = 0; + int count; struct inode * inode; spin_lock(&inode_lock); - /* go simple and safe syncing everything before starting */ - sync_all_inodes(); + count = 0; entry = inode_unused.prev; while (entry != &inode_unused) { @@ -517,12 +678,12 @@ entry = entry->prev; inode = INODE(tmp); - if (inode->i_state & (I_FREEING|I_CLEAR)) - BUG(); + if (inode->i_state & (I_FREEING|I_CLEAR|I_LOCK)) + continue; if (!CAN_UNUSE(inode)) continue; if (atomic_read(&inode->i_count)) - BUG(); + continue; list_del(tmp); list_del(&inode->i_hash); INIT_LIST_HEAD(&inode->i_hash); @@ -536,9 +697,18 @@ spin_unlock(&inode_lock); dispose_list(freeable); + + /* + * If we didn't freed enough clean inodes schedule + * a sync of the dirty inodes, we cannot do it + * from here or we're either synchronously dogslow + * or we deadlock with oom. + */ + if (goal) + schedule_task(&unused_inodes_flush_task); } -void shrink_icache_memory(int priority, int gfp_mask) +int shrink_icache_memory(int priority, int gfp_mask) { int count = 0; @@ -549,14 +719,14 @@ * want to recurse into the FS that called us * in clear_inode() and friends.. */ - if (!(gfp_mask & __GFP_IO)) - return; + if (!(gfp_mask & __GFP_FS)) + return 0; - if (priority) - count = inodes_stat.nr_unused / priority; + count = inodes_stat.nr_unused / priority; prune_icache(count); kmem_cache_shrink(inode_cachep); + return 0; } /* @@ -607,12 +777,15 @@ inode->i_nlink = 1; atomic_set(&inode->i_writecount, 0); inode->i_size = 0; + inode->i_blocks = 0; inode->i_generation = 0; memset(&inode->i_dquot, 0, sizeof(inode->i_dquot)); inode->i_pipe = NULL; inode->i_bdev = NULL; + inode->i_cdev = NULL; inode->i_data.a_ops = &empty_aops; inode->i_data.host = inode; + inode->i_data.gfp_mask = GFP_HIGHUSER; inode->i_mapping = &inode->i_data; } @@ -634,6 +807,8 @@ static unsigned long last_ino; struct inode * inode; + spin_lock_prefetch(&inode_lock); + inode = alloc_inode(); if (inode) { @@ -642,6 +817,7 @@ list_add(&inode->i_list, &inode_in_use); inode->i_sb = NULL; inode->i_dev = 0; + inode->i_blkbits = 0; inode->i_ino = ++last_ino; inode->i_flags = 0; atomic_set(&inode->i_count, 1); @@ -675,6 +851,7 @@ list_add(&inode->i_hash, head); inode->i_sb = sb; inode->i_dev = sb->s_dev; + inode->i_blkbits = sb->s_blocksize_bits; inode->i_ino = ino; inode->i_flags = 0; atomic_set(&inode->i_count, 1); @@ -781,8 +958,6 @@ */ inode = NULL; spin_unlock(&inode_lock); - if (inode) - wait_on_inode(inode); return inode; } @@ -853,10 +1028,14 @@ void iput(struct inode *inode) { if (inode) { + struct super_block *sb = inode->i_sb; struct super_operations *op = NULL; - if (inode->i_sb && inode->i_sb->s_op) - op = inode->i_sb->s_op; + if (inode->i_state == I_CLEAR) + BUG(); + + if (sb && sb->s_op) + op = sb->s_op; if (op && op->put_inode) op->put_inode(inode); @@ -877,6 +1056,8 @@ if (op && op->delete_inode) { void (*delete)(struct inode *) = op->delete_inode; + if (!is_bad_inode(inode)) + DQUOT_INIT(inode); /* s_op->delete_inode internally recalls clear_inode() */ delete(inode); } else @@ -884,22 +1065,22 @@ if (inode->i_state != I_CLEAR) BUG(); } else { - if (!list_empty(&inode->i_hash)) { - if (!(inode->i_state & I_DIRTY)) { + if (!list_empty(&inode->i_hash) && sb && sb->s_root) { + if (!(inode->i_state & (I_DIRTY|I_LOCK))) { list_del(&inode->i_list); - list_add(&inode->i_list, - &inode_unused); + list_add(&inode->i_list, &inode_unused); } inodes_stat.nr_unused++; spin_unlock(&inode_lock); return; } else { - /* magic nfs path */ - list_del(&inode->i_list); - INIT_LIST_HEAD(&inode->i_list); + list_del_init(&inode->i_list); + list_del_init(&inode->i_hash); inode->i_state|=I_FREEING; inodes_stat.nr_inodes--; spin_unlock(&inode_lock); + if (inode->i_data.nrpages) + truncate_inode_pages(&inode->i_data, 0); clear_inode(inode); } } @@ -988,6 +1169,8 @@ NULL); if (!inode_cachep) panic("cannot create inode slab cache"); + + unused_inodes_flush_task.routine = try_to_sync_unused_inodes; } /** @@ -1018,38 +1201,40 @@ void put_dquot_list(struct list_head *); int remove_inode_dquot_ref(struct inode *, short, struct list_head *); -void remove_dquot_ref(kdev_t dev, short type) +void remove_dquot_ref(struct super_block *sb, short type) { - struct super_block *sb = get_super(dev); struct inode *inode; struct list_head *act_head; LIST_HEAD(tofree_head); - if (!sb || !sb->dq_op) + if (!sb->dq_op) return; /* nothing to do */ - /* We have to be protected against other CPUs */ - spin_lock(&inode_lock); + lock_kernel(); /* This lock is for quota code */ + spin_lock(&inode_lock); /* This lock is for inodes code */ - for (act_head = inode_in_use.next; act_head != &inode_in_use; act_head = act_head->next) { + list_for_each(act_head, &inode_in_use) { inode = list_entry(act_head, struct inode, i_list); - if (inode->i_sb != sb || !IS_QUOTAINIT(inode)) - continue; - remove_inode_dquot_ref(inode, type, &tofree_head); + if (inode->i_sb == sb && IS_QUOTAINIT(inode)) + remove_inode_dquot_ref(inode, type, &tofree_head); } - for (act_head = inode_unused.next; act_head != &inode_unused; act_head = act_head->next) { + list_for_each(act_head, &inode_unused) { inode = list_entry(act_head, struct inode, i_list); - if (inode->i_sb != sb || !IS_QUOTAINIT(inode)) - continue; - remove_inode_dquot_ref(inode, type, &tofree_head); + if (inode->i_sb == sb && IS_QUOTAINIT(inode)) + remove_inode_dquot_ref(inode, type, &tofree_head); } - for (act_head = sb->s_dirty.next; act_head != &sb->s_dirty; act_head = act_head->next) { + list_for_each(act_head, &sb->s_dirty) { inode = list_entry(act_head, struct inode, i_list); - if (!IS_QUOTAINIT(inode)) - continue; - remove_inode_dquot_ref(inode, type, &tofree_head); + if (IS_QUOTAINIT(inode)) + remove_inode_dquot_ref(inode, type, &tofree_head); + } + list_for_each(act_head, &sb->s_locked_inodes) { + inode = list_entry(act_head, struct inode, i_list); + if (IS_QUOTAINIT(inode)) + remove_inode_dquot_ref(inode, type, &tofree_head); } spin_unlock(&inode_lock); + unlock_kernel(); put_dquot_list(&tofree_head); } Index: iobuf.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/iobuf.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- iobuf.c 25 Feb 2001 23:14:46 -0000 1.1.1.2 +++ iobuf.c 9 Apr 2002 13:11:16 -0000 1.2 @@ -8,9 +8,7 @@ #include <linux/iobuf.h> #include <linux/slab.h> - -static kmem_cache_t *kiobuf_cachep; - +#include <linux/vmalloc.h> void end_kio_request(struct kiobuf *kiobuf, int uptodate) { @@ -24,18 +22,7 @@ } } - -void __init kiobuf_setup(void) -{ - kiobuf_cachep = kmem_cache_create("kiobuf", - sizeof(struct kiobuf), - 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); - if(!kiobuf_cachep) - panic("Cannot create kernel iobuf cache\n"); -} - -void kiobuf_init(struct kiobuf *iobuf) +static void kiobuf_init(struct kiobuf *iobuf) { memset(iobuf, 0, sizeof(*iobuf)); init_waitqueue_head(&iobuf->wait_queue); @@ -43,19 +30,49 @@ iobuf->maplist = iobuf->map_array; } +int alloc_kiobuf_bhs(struct kiobuf * kiobuf) +{ + int i; + + for (i = 0; i < KIO_MAX_SECTORS; i++) + if (!(kiobuf->bh[i] = kmem_cache_alloc(bh_cachep, SLAB_KERNEL))) { + while (i--) { + kmem_cache_free(bh_cachep, kiobuf->bh[i]); + kiobuf->bh[i] = NULL; + } + return -ENOMEM; + } + return 0; +} + +void free_kiobuf_bhs(struct kiobuf * kiobuf) +{ + int i; + + for (i = 0; i < KIO_MAX_SECTORS; i++) { + kmem_cache_free(bh_cachep, kiobuf->bh[i]); + kiobuf->bh[i] = NULL; + } +} + int alloc_kiovec(int nr, struct kiobuf **bufp) { int i; struct kiobuf *iobuf; for (i = 0; i < nr; i++) { - iobuf = kmem_cache_alloc(kiobuf_cachep, SLAB_KERNEL); + iobuf = vmalloc(sizeof(struct kiobuf)); if (!iobuf) { free_kiovec(i, bufp); return -ENOMEM; } kiobuf_init(iobuf); - *bufp++ = iobuf; + if (alloc_kiobuf_bhs(iobuf)) { + vfree(iobuf); + free_kiovec(i, bufp); + return -ENOMEM; + } + bufp[i] = iobuf; } return 0; @@ -72,7 +89,8 @@ unlock_kiovec(1, &iobuf); if (iobuf->array_len > KIO_STATIC_PAGES) kfree (iobuf->maplist); - kmem_cache_free(kiobuf_cachep, bufp[i]); + free_kiobuf_bhs(iobuf); + vfree(bufp[i]); } } @@ -115,11 +133,12 @@ add_wait_queue(&kiobuf->wait_queue, &wait); repeat: - run_task_queue(&tq_disk); set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (atomic_read(&kiobuf->io_count) != 0) { + run_task_queue(&tq_disk); schedule(); - goto repeat; + if (atomic_read(&kiobuf->io_count) != 0) + goto repeat; } tsk->state = TASK_RUNNING; remove_wait_queue(&kiobuf->wait_queue, &wait); |
From: Andy P. <at...@us...> - 2002-04-09 14:08:19
|
Update of /cvsroot/linux-vax/kernel-2.4/fs/devfs In directory usw-pr-cvs1:/tmp/cvs-serv27691/devfs Modified Files: base.c util.c Log Message: sync 2.4.15 commit 11 Index: base.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/devfs/base.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- base.c 25 Feb 2001 23:14:48 -0000 1.1.1.2 +++ base.c 9 Apr 2002 13:11:17 -0000 1.2 @@ -1,6 +1,6 @@ /* devfs (Device FileSystem) driver. - Copyright (C) 1998-2000 Richard Gooch + Copyright (C) 1998-2001 Richard Gooch This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -388,7 +388,7 @@ Work sponsored by SGI. v0.83 19991107 Richard Gooch <rg...@at...> [...1783 lines suppressed...] } /* End Function devfsd_close */ -int __init init_devfs_fs (void) +static int __init init_devfs_fs (void) { int err; @@ -3364,8 +3333,10 @@ { int err; - if ( (boot_options & OPTION_NOMOUNT) ) return; + if ( !(boot_options & OPTION_MOUNT) ) return; err = do_mount ("none", "/dev", "devfs", 0, ""); if (err == 0) printk ("Mounted devfs on /dev\n"); else printk ("Warning: unable to mount devfs, err: %d\n", err); } /* End Function mount_devfs_fs */ + +module_init(init_devfs_fs) Index: util.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/devfs/util.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- util.c 14 Jan 2001 16:40:09 -0000 1.1.1.1 +++ util.c 9 Apr 2002 13:11:17 -0000 1.2 @@ -1,6 +1,6 @@ /* devfs (Device FileSystem) utilities. - Copyright (C) 1999-2000 Richard Gooch + Copyright (C) 1999-2001 Richard Gooch This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -33,12 +33,29 @@ 20000622 Richard Gooch <rg...@at...> Took account of interface change to <devfs_mk_symlink>. Took account of interface change to <devfs_mk_dir>. + 20010519 Richard Gooch <rg...@at...> + Documentation cleanup. + 20010709 Richard Gooch <rg...@at...> + Created <devfs_*alloc_major> and <devfs_*alloc_devnum>. + 20010710 Richard Gooch <rg...@at...> + Created <devfs_*alloc_unique_number>. + 20010730 Richard Gooch <rg...@at...> + Documentation typo fix. + 20010806 Richard Gooch <rg...@at...> + Made <block_semaphore> and <char_semaphore> private. + 20010813 Richard Gooch <rg...@at...> + Fixed bug in <devfs_alloc_unique_number>: limited to 128 numbers + 20010818 Richard Gooch <rg...@at...> + Updated major masks up to Linus' "no new majors" proclamation. + Block: were 126 now 122 free, char: were 26 now 19 free. */ #include <linux/module.h> #include <linux/init.h> -#include <linux/locks.h> -#include <linux/kdev_t.h> #include <linux/devfs_fs_kernel.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> + +#include <asm/bitops.h> /* Private functions follow */ @@ -132,9 +149,10 @@ /** * devfs_register_series - Register a sequence of device entries. - * @dir: The handle to the parent devfs directory entry. If this is %NULL the - * new names are relative to the root of the devfs. + * @dir: The handle to the parent devfs directory entry. If this is %NULL + * the new names are relative to the root of the devfs. * @format: The printf-style format string. A single "\%u" is allowed. + * @num_entries: The number of entries to register. * @flags: A set of bitwise-ORed flags (DEVFS_FL_*). * @major: The major number. Not needed for regular files. * @minor_start: The starting minor number. Not needed for regular files. @@ -142,9 +160,9 @@ * @ops: The &file_operations or &block_device_operations structure. * This must not be externally deallocated. * @info: An arbitrary pointer which will be written to the private_data - * field of the &file structure passed to the device driver. You can set - * this to whatever you like, and change it once the file is opened (the next - * file opened will not see this change). + * field of the &file structure passed to the device driver. You + * can set this to whatever you like, and change it once the file + * is opened (the next file opened will not see this change). */ void devfs_register_series (devfs_handle_t dir, const char *format, @@ -163,3 +181,299 @@ } } /* End Function devfs_register_series */ EXPORT_SYMBOL(devfs_register_series); + + +struct major_list +{ + spinlock_t lock; + __u32 bits[8]; +}; + +/* Block majors already assigned: + 0-3, 7-9, 11-63, 65-99, 101-113, 120-127, 199, 201, 240-255 + Total free: 122 +*/ +static struct major_list block_major_list = +{SPIN_LOCK_UNLOCKED, + {0xfffffb8f, /* Majors 0 to 31 */ + 0xffffffff, /* Majors 32 to 63 */ + 0xfffffffe, /* Majors 64 to 95 */ + 0xff03ffef, /* Majors 96 to 127 */ + 0x00000000, /* Majors 128 to 159 */ + 0x00000000, /* Majors 160 to 191 */ + 0x00000280, /* Majors 192 to 223 */ + 0xffff0000} /* Majors 224 to 255 */ +}; + +/* Char majors already assigned: + 0-7, 9-151, 154-158, 160-211, 216-221, 224-230, 240-255 + Total free: 19 +*/ +static struct major_list char_major_list = +{SPIN_LOCK_UNLOCKED, + {0xfffffeff, /* Majors 0 to 31 */ + 0xffffffff, /* Majors 32 to 63 */ + 0xffffffff, /* Majors 64 to 95 */ + 0xffffffff, /* Majors 96 to 127 */ + 0x7cffffff, /* Majors 128 to 159 */ + 0xffffffff, /* Majors 160 to 191 */ + 0x3f0fffff, /* Majors 192 to 223 */ + 0xffff007f} /* Majors 224 to 255 */ +}; + + +/** + * devfs_alloc_major - Allocate a major number. + * @type: The type of the major (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK) + + * Returns the allocated major, else -1 if none are available. + * This routine is thread safe and does not block. + */ + +int devfs_alloc_major (char type) +{ + int major; + struct major_list *list; + + list = (type == DEVFS_SPECIAL_CHR) ? &char_major_list : &block_major_list; + spin_lock (&list->lock); + major = find_first_zero_bit (list->bits, 256); + if (major < 256) __set_bit (major, list->bits); + else major = -1; + spin_unlock (&list->lock); + return major; +} /* End Function devfs_alloc_major */ +EXPORT_SYMBOL(devfs_alloc_major); + + +/** + * devfs_dealloc_major - Deallocate a major number. + * @type: The type of the major (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK) + * @major: The major number. + * This routine is thread safe and does not block. + */ + +void devfs_dealloc_major (char type, int major) +{ + int was_set; + struct major_list *list; + + if (major < 0) return; + list = (type == DEVFS_SPECIAL_CHR) ? &char_major_list : &block_major_list; + spin_lock (&list->lock); + was_set = __test_and_clear_bit (major, list->bits); + spin_unlock (&list->lock); + if (!was_set) + printk (KERN_ERR __FUNCTION__ "(): major %d was already free\n", + major); +} /* End Function devfs_dealloc_major */ +EXPORT_SYMBOL(devfs_dealloc_major); + + +struct minor_list +{ + int major; + __u32 bits[8]; + struct minor_list *next; +}; + +struct device_list +{ + struct minor_list *first, *last; + int none_free; +}; + +static DECLARE_MUTEX (block_semaphore); +static struct device_list block_list; + +static DECLARE_MUTEX (char_semaphore); +static struct device_list char_list; + + +/** + * devfs_alloc_devnum - Allocate a device number. + * @type: The type (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK). + * + * Returns the allocated device number, else NODEV if none are available. + * This routine is thread safe and may block. + */ + +kdev_t devfs_alloc_devnum (char type) +{ + int minor; + struct semaphore *semaphore; + struct device_list *list; + struct minor_list *entry; + + if (type == DEVFS_SPECIAL_CHR) + { + semaphore = &char_semaphore; + list = &char_list; + } + else + { + semaphore = &block_semaphore; + list = &block_list; + } + if (list->none_free) return NODEV; /* Fast test */ + down (semaphore); + if (list->none_free) + { + up (semaphore); + return NODEV; + } + for (entry = list->first; entry != NULL; entry = entry->next) + { + minor = find_first_zero_bit (entry->bits, 256); + if (minor >= 256) continue; + __set_bit (minor, entry->bits); + up (semaphore); + return MKDEV (entry->major, minor); + } + /* Need to allocate a new major */ + if ( ( entry = kmalloc (sizeof *entry, GFP_KERNEL) ) == NULL ) + { + list->none_free = 1; + up (semaphore); + return NODEV; + } + memset (entry, 0, sizeof *entry); + if ( ( entry->major = devfs_alloc_major (type) ) < 0 ) + { + list->none_free = 1; + up (semaphore); + kfree (entry); + return NODEV; + } + __set_bit (0, entry->bits); + if (list->first == NULL) list->first = entry; + else list->last->next = entry; + list->last = entry; + up (semaphore); + return MKDEV (entry->major, 0); +} /* End Function devfs_alloc_devnum */ +EXPORT_SYMBOL(devfs_alloc_devnum); + + +/** + * devfs_dealloc_devnum - Dellocate a device number. + * @type: The type (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK). + * @devnum: The device number. + * + * This routine is thread safe and does not block. + */ + +void devfs_dealloc_devnum (char type, kdev_t devnum) +{ + int major, minor; + struct semaphore *semaphore; + struct device_list *list; + struct minor_list *entry; + + if (devnum == NODEV) return; + if (type == DEVFS_SPECIAL_CHR) + { + semaphore = &char_semaphore; + list = &char_list; + } + else + { + semaphore = &block_semaphore; + list = &block_list; + } + major = MAJOR (devnum); + minor = MINOR (devnum); + down (semaphore); + for (entry = list->first; entry != NULL; entry = entry->next) + { + int was_set; + + if (entry->major != major) continue; + was_set = __test_and_clear_bit (minor, entry->bits); + if (was_set) list->none_free = 0; + up (semaphore); + if (!was_set) + printk ( KERN_ERR __FUNCTION__ "(): device %s was already free\n", + kdevname (devnum) ); + return; + } + up (semaphore); + printk ( KERN_ERR __FUNCTION__ "(): major for %s not previously allocated\n", + kdevname (devnum) ); +} /* End Function devfs_dealloc_devnum */ +EXPORT_SYMBOL(devfs_dealloc_devnum); + + +/** + * devfs_alloc_unique_number - Allocate a unique (positive) number. + * @space: The number space to allocate from. + * + * Returns the allocated unique number, else a negative error code. + * This routine is thread safe and may block. + */ + +int devfs_alloc_unique_number (struct unique_numspace *space) +{ + int number; + unsigned int length; + __u32 *bits; + + /* Get around stupid lack of semaphore initialiser */ + spin_lock (&space->init_lock); + if (!space->sem_initialised) + { + sema_init (&space->semaphore, 1); + space->sem_initialised = 1; + } + spin_unlock (&space->init_lock); + down (&space->semaphore); + if (space->num_free < 1) + { + if (space->length < 16) length = 16; + else length = space->length << 1; + if ( ( bits = vmalloc (length) ) == NULL ) + { + up (&space->semaphore); + return -ENOMEM; + } + if (space->bits != NULL) + { + memcpy (bits, space->bits, space->length); + vfree (space->bits); + } + space->num_free = (length - space->length) << 3; + space->bits = bits; + memset (bits + space->length, 0, length - space->length); + space->length = length; + } + number = find_first_zero_bit (space->bits, space->length << 3); + --space->num_free; + __set_bit (number, space->bits); + up (&space->semaphore); + return number; +} /* End Function devfs_alloc_unique_number */ +EXPORT_SYMBOL(devfs_alloc_unique_number); + + +/** + * devfs_dealloc_unique_number - Deallocate a unique (positive) number. + * @space: The number space to deallocate from. + * @number: The number to deallocate. + * + * This routine is thread safe and may block. + */ + +void devfs_dealloc_unique_number (struct unique_numspace *space, int number) +{ + int was_set; + + if (number < 0) return; + down (&space->semaphore); + was_set = __test_and_clear_bit (number, space->bits); + if (was_set) ++space->num_free; + up (&space->semaphore); + if (!was_set) + printk (KERN_ERR __FUNCTION__ "(): number %d was already free\n", + number); +} /* End Function devfs_dealloc_unique_number */ +EXPORT_SYMBOL(devfs_dealloc_unique_number); |
From: Andy P. <at...@us...> - 2002-04-09 14:08:16
|
Update of /cvsroot/linux-vax/kernel-2.4/fs/devpts In directory usw-pr-cvs1:/tmp/cvs-serv27691/devpts Modified Files: inode.c Log Message: sync 2.4.15 commit 11 Index: inode.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/devpts/inode.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- inode.c 25 Feb 2001 23:14:48 -0000 1.1.1.2 +++ inode.c 9 Apr 2002 13:11:17 -0000 1.2 @@ -220,7 +220,7 @@ } } -int __init init_devpts_fs(void) +static int __init init_devpts_fs(void) { int err = register_filesystem(&devpts_fs_type); if (!err) { @@ -228,28 +228,27 @@ err = PTR_ERR(devpts_mnt); if (!IS_ERR(devpts_mnt)) err = 0; - } - return err; -} - #ifdef MODULE - -int init_module(void) -{ - int err = init_devpts_fs(); - if ( !err ) { - devpts_upcall_new = devpts_pty_new; - devpts_upcall_kill = devpts_pty_kill; + if ( !err ) { + devpts_upcall_new = devpts_pty_new; + devpts_upcall_kill = devpts_pty_kill; + } +#endif } return err; } -void cleanup_module(void) +static void __exit exit_devpts_fs(void) { +#ifdef MODULE devpts_upcall_new = NULL; devpts_upcall_kill = NULL; +#endif unregister_filesystem(&devpts_fs_type); kern_umount(devpts_mnt); } -#endif +module_init(init_devpts_fs) +module_exit(exit_devpts_fs) +MODULE_LICENSE("GPL"); + |
From: Andy P. <at...@us...> - 2002-04-09 14:08:14
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/acpi/dispatcher In directory usw-pr-cvs1:/tmp/cvs-serv13840/acpi/dispatcher Modified Files: Makefile dsfield.c dsmethod.c dsmthdat.c dsobject.c dsopcode.c dsutils.c dswexec.c dswload.c dswscope.c dswstate.c Log Message: synch 2.4.15 commit 17 Index: Makefile =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/acpi/dispatcher/Makefile,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- Makefile 14 Jan 2001 19:15:24 -0000 1.1.1.1 +++ Makefile 9 Apr 2002 14:05:42 -0000 1.2 @@ -1,16 +1,12 @@ # # Makefile for all Linux ACPI interpreter subdirectories +# EXCEPT for the ospm directory # -O_TARGET := ../$(shell basename `pwd`).o +O_TARGET := $(notdir $(CURDIR)).o obj-$(CONFIG_ACPI) := $(patsubst %.c,%.o,$(wildcard *.c)) -EXTRA_CFLAGS += -I../include - EXTRA_CFLAGS += $(ACPI_CFLAGS) include $(TOPDIR)/Rules.make - -clean: - $(RM) *.o Index: dsfield.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/acpi/dispatcher/dsfield.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- dsfield.c 25 Feb 2001 23:15:15 -0000 1.1.1.2 +++ dsfield.c 9 Apr 2002 14:05:42 -0000 1.2 @@ -29,264 +29,359 @@ #include "acdispat.h" #include "acinterp.h" #include "acnamesp.h" +#include "acparser.h" -#define _COMPONENT DISPATCHER +#define _COMPONENT ACPI_DISPATCHER MODULE_NAME ("dsfield") -/* - * Field flags: Bits 00 - 03 : Access_type (Any_acc, Byte_acc, etc.) - * 04 : Lock_rule (1 == Lock) - * 05 - 06 : Update_rule - */ - -#define FIELD_ACCESS_TYPE_MASK 0x0F -#define FIELD_LOCK_RULE_MASK 0x10 -#define FIELD_UPDATE_RULE_MASK 0x60 - - /******************************************************************************* * - * FUNCTION: Acpi_ds_create_field + * FUNCTION: Acpi_ds_create_buffer_field * - * PARAMETERS: Op - Op containing the Field definition and args - * Region_node - Object for the containing Operation Region + * PARAMETERS: Opcode - The opcode to be executed + * Operands - List of operands for the opcode + * Walk_state - Current state * * RETURN: Status * - * DESCRIPTION: Create a new field in the specified operation region + * DESCRIPTION: Execute the Create_field operators: + * Create_bit_field_op, + * Create_byte_field_op, + * Create_word_field_op, + * Create_dWord_field_op, + * Create_qWord_field_op, + * Create_field_op (all of which define fields in buffers) * ******************************************************************************/ -ACPI_STATUS -acpi_ds_create_field ( - ACPI_PARSE_OBJECT *op, - ACPI_NAMESPACE_NODE *region_node, - ACPI_WALK_STATE *walk_state) +acpi_status +acpi_ds_create_buffer_field ( + acpi_parse_object *op, + acpi_walk_state *walk_state) { - ACPI_STATUS status = AE_AML_ERROR; - ACPI_PARSE_OBJECT *arg; - ACPI_NAMESPACE_NODE *node; - u8 field_flags; - u8 access_attribute = 0; - u32 field_bit_position = 0; + acpi_parse_object *arg; + acpi_namespace_node *node; + acpi_status status; + acpi_operand_object *obj_desc; - /* First arg is the name of the parent Op_region */ + FUNCTION_TRACE ("Ds_create_buffer_field"); - arg = op->value.arg; - if (!region_node) { - status = acpi_ns_lookup (walk_state->scope_info, arg->value.name, - ACPI_TYPE_REGION, IMODE_EXECUTE, - NS_SEARCH_PARENT, walk_state, - ®ion_node); - if (ACPI_FAILURE (status)) { - return (status); - } + /* Get the Name_string argument */ + + if (op->opcode == AML_CREATE_FIELD_OP) { + arg = acpi_ps_get_arg (op, 3); } + else { + /* Create Bit/Byte/Word/Dword field */ - /* Second arg is the field flags */ + arg = acpi_ps_get_arg (op, 2); + } - arg = arg->next; - field_flags = (u8) arg->value.integer; + if (!arg) { + return_ACPI_STATUS (AE_AML_NO_OPERAND); + } - /* Each remaining arg is a Named Field */ + /* + * Enter the Name_string into the namespace + */ + status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, + INTERNAL_TYPE_DEF_ANY, IMODE_LOAD_PASS1, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + walk_state, &(node)); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* We could put the returned object (Node) on the object stack for later, but + * for now, we will put it in the "op" object that the parser uses, so we + * can get it again at the end of this scope + */ + op->node = node; + + /* + * If there is no object attached to the node, this node was just created and + * we need to create the field object. Otherwise, this was a lookup of an + * existing node and we don't want to create the field object again. + */ + if (node->object) { + return_ACPI_STATUS (AE_OK); + } + + /* + * The Field definition is not fully parsed at this time. + * (We must save the address of the AML for the buffer and index operands) + */ + + /* Create the buffer field object */ + + obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER_FIELD); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Allocate a method object for this field unit + */ + obj_desc->buffer_field.extra = acpi_ut_create_internal_object ( + INTERNAL_TYPE_EXTRA); + if (!obj_desc->buffer_field.extra) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Remember location in AML stream of the field unit + * opcode and operands -- since the buffer and index + * operands must be evaluated. + */ + obj_desc->buffer_field.extra->extra.aml_start = ((acpi_parse2_object *) op)->data; + obj_desc->buffer_field.extra->extra.aml_length = ((acpi_parse2_object *) op)->length; + obj_desc->buffer_field.node = node; + + /* Attach constructed field descriptor to parent node */ + + status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_BUFFER_FIELD); + + +cleanup: + + /* Remove local reference to the object */ + + acpi_ut_remove_reference (obj_desc); + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_get_field_names + * + * PARAMETERS: Info - Create_field info structure + * ` Walk_state - Current method state + * Arg - First parser arg for the field name list + * + * RETURN: Status + * + * DESCRIPTION: Process all named fields in a field declaration. Names are + * entered into the namespace. + * + ******************************************************************************/ + +acpi_status +acpi_ds_get_field_names ( + ACPI_CREATE_FIELD_INFO *info, + acpi_walk_state *walk_state, + acpi_parse_object *arg) +{ + acpi_status status; + + + FUNCTION_TRACE_U32 ("Ds_get_field_names", info); + + + /* First field starts at bit zero */ + + info->field_bit_position = 0; + + /* Process all elements in the field list (of parse nodes) */ - arg = arg->next; while (arg) { - switch (arg->opcode) - { - case AML_RESERVEDFIELD_OP: + /* + * Three types of field elements are handled: + * 1) Offset - specifies a bit offset + * 2) Access_as - changes the access mode + * 3) Name - Enters a new named field into the namespace + */ + switch (arg->opcode) { + case AML_INT_RESERVEDFIELD_OP: - field_bit_position += arg->value.size; + info->field_bit_position += arg->value.size; break; - case AML_ACCESSFIELD_OP: + case AML_INT_ACCESSFIELD_OP: /* * Get a new Access_type and Access_attribute for all * entries (until end or another Access_as keyword) */ - - access_attribute = (u8) arg->value.integer; - field_flags = (u8) - ((field_flags & FIELD_ACCESS_TYPE_MASK) || + info->field_flags = (u8) ((info->field_flags & FIELD_ACCESS_TYPE_MASK) || ((u8) (arg->value.integer >> 8))); break; - case AML_NAMEDFIELD_OP: + case AML_INT_NAMEDFIELD_OP: + + /* Enter a new field name into the namespace */ status = acpi_ns_lookup (walk_state->scope_info, - (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)arg)->name, - INTERNAL_TYPE_DEF_FIELD, - IMODE_LOAD_PASS1, + (NATIVE_CHAR *) &((acpi_parse2_object *)arg)->name, + info->field_type, IMODE_LOAD_PASS1, NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, - NULL, &node); - + NULL, &info->field_node); if (ACPI_FAILURE (status)) { - return (status); + return_ACPI_STATUS (status); } - /* - * Initialize an object for the new Node that is on - * the object stack - */ + /* Create and initialize an object for the new Field Node */ - status = acpi_aml_prep_def_field_value (node, region_node, field_flags, - access_attribute, field_bit_position, arg->value.size); + info->field_bit_length = arg->value.size; + status = acpi_ex_prep_field_value (info); if (ACPI_FAILURE (status)) { - return (status); + return_ACPI_STATUS (status); } - /* Keep track of bit position for *next* field */ + /* Keep track of bit position for the next field */ + + info->field_bit_position += info->field_bit_length; + break; + + + default: - field_bit_position += arg->value.size; + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid opcode in field list: %X\n", + arg->opcode)); + return_ACPI_STATUS (AE_AML_ERROR); break; } arg = arg->next; } - return (status); + return_ACPI_STATUS (AE_OK); } /******************************************************************************* * - * FUNCTION: Acpi_ds_create_bank_field + * FUNCTION: Acpi_ds_create_field * * PARAMETERS: Op - Op containing the Field definition and args - * Region_node - Object for the containing Operation Region + * Region_node - Object for the containing Operation Region + * ` Walk_state - Current method state * * RETURN: Status * - * DESCRIPTION: Create a new bank field in the specified operation region + * DESCRIPTION: Create a new field in the specified operation region * ******************************************************************************/ -ACPI_STATUS -acpi_ds_create_bank_field ( - ACPI_PARSE_OBJECT *op, - ACPI_NAMESPACE_NODE *region_node, - ACPI_WALK_STATE *walk_state) +acpi_status +acpi_ds_create_field ( + acpi_parse_object *op, + acpi_namespace_node *region_node, + acpi_walk_state *walk_state) { - ACPI_STATUS status = AE_AML_ERROR; - ACPI_PARSE_OBJECT *arg; - ACPI_NAMESPACE_NODE *register_node; - ACPI_NAMESPACE_NODE *node; - u32 bank_value; - u8 field_flags; - u8 access_attribute = 0; - u32 field_bit_position = 0; + acpi_status status = AE_AML_ERROR; + acpi_parse_object *arg; + ACPI_CREATE_FIELD_INFO info; + + + FUNCTION_TRACE_PTR ("Ds_create_field", op); - /* First arg is the name of the parent Op_region */ + /* First arg is the name of the parent Op_region (must already exist) */ arg = op->value.arg; if (!region_node) { status = acpi_ns_lookup (walk_state->scope_info, arg->value.name, - ACPI_TYPE_REGION, IMODE_EXECUTE, - NS_SEARCH_PARENT, walk_state, - ®ion_node); - + ACPI_TYPE_REGION, IMODE_EXECUTE, + NS_SEARCH_PARENT, walk_state, ®ion_node); if (ACPI_FAILURE (status)) { - return (status); + return_ACPI_STATUS (status); } } - /* Second arg is the Bank Register */ - - arg = arg->next; - - status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, - INTERNAL_TYPE_BANK_FIELD_DEFN, - IMODE_LOAD_PASS1, - NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, - NULL, ®ister_node); - - if (ACPI_FAILURE (status)) { - return (status); - } - - /* Third arg is the Bank_value */ + /* Second arg is the field flags */ arg = arg->next; - bank_value = arg->value.integer; + info.field_flags = arg->value.integer8; + /* Each remaining arg is a Named Field */ - /* Next arg is the field flags */ + info.field_type = INTERNAL_TYPE_REGION_FIELD; + info.region_node = region_node; - arg = arg->next; - field_flags = (u8) arg->value.integer; + status = acpi_ds_get_field_names (&info, walk_state, arg->next); - /* Each remaining arg is a Named Field */ + return_ACPI_STATUS (status); +} - arg = arg->next; - while (arg) { - switch (arg->opcode) - { - case AML_RESERVEDFIELD_OP: - field_bit_position += arg->value.size; - break; +/******************************************************************************* + * + * FUNCTION: Acpi_ds_create_bank_field + * + * PARAMETERS: Op - Op containing the Field definition and args + * Region_node - Object for the containing Operation Region + * ` Walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Create a new bank field in the specified operation region + * + ******************************************************************************/ +acpi_status +acpi_ds_create_bank_field ( + acpi_parse_object *op, + acpi_namespace_node *region_node, + acpi_walk_state *walk_state) +{ + acpi_status status = AE_AML_ERROR; + acpi_parse_object *arg; + ACPI_CREATE_FIELD_INFO info; - case AML_ACCESSFIELD_OP: - /* - * Get a new Access_type and Access_attribute for - * all entries (until end or another Access_as keyword) - */ + FUNCTION_TRACE_PTR ("Ds_create_bank_field", op); - access_attribute = (u8) arg->value.integer; - field_flags = (u8) - ((field_flags & FIELD_ACCESS_TYPE_MASK) || - ((u8) (arg->value.integer >> 8))); - break; + /* First arg is the name of the parent Op_region (must already exist) */ - case AML_NAMEDFIELD_OP: + arg = op->value.arg; + if (!region_node) { + status = acpi_ns_lookup (walk_state->scope_info, arg->value.name, + ACPI_TYPE_REGION, IMODE_EXECUTE, + NS_SEARCH_PARENT, walk_state, ®ion_node); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + } - status = acpi_ns_lookup (walk_state->scope_info, - (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)arg)->name, - INTERNAL_TYPE_DEF_FIELD, - IMODE_LOAD_PASS1, - NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, - NULL, &node); + /* Second arg is the Bank Register (must already exist) */ - if (ACPI_FAILURE (status)) { - return (status); - } + arg = arg->next; + status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, + INTERNAL_TYPE_BANK_FIELD_DEFN, IMODE_EXECUTE, + NS_SEARCH_PARENT, walk_state, &info.register_node); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - /* - * Initialize an object for the new Node that is on - * the object stack - */ + /* Third arg is the Bank_value */ - status = acpi_aml_prep_bank_field_value (node, region_node, register_node, - bank_value, field_flags, access_attribute, - field_bit_position, arg->value.size); + arg = arg->next; + info.bank_value = arg->value.integer32; - if (ACPI_FAILURE (status)) { - return (status); - } + /* Fourth arg is the field flags */ - /* Keep track of bit position for the *next* field */ + arg = arg->next; + info.field_flags = arg->value.integer8; - field_bit_position += arg->value.size; - break; + /* Each remaining arg is a Named Field */ - } + info.field_type = INTERNAL_TYPE_BANK_FIELD; + info.region_node = region_node; - arg = arg->next; - } + status = acpi_ds_get_field_names (&info, walk_state, arg->next); - return (status); + return_ACPI_STATUS (status); } @@ -295,7 +390,8 @@ * FUNCTION: Acpi_ds_create_index_field * * PARAMETERS: Op - Op containing the Field definition and args - * Region_node - Object for the containing Operation Region + * Region_node - Object for the containing Operation Region + * ` Walk_state - Current method state * * RETURN: Status * @@ -303,124 +399,54 @@ * ******************************************************************************/ -ACPI_STATUS +acpi_status acpi_ds_create_index_field ( - ACPI_PARSE_OBJECT *op, - ACPI_HANDLE region_node, - ACPI_WALK_STATE *walk_state) + acpi_parse_object *op, + acpi_namespace_node *region_node, + acpi_walk_state *walk_state) { - ACPI_STATUS status; - ACPI_PARSE_OBJECT *arg; - ACPI_NAMESPACE_NODE *node; - ACPI_NAMESPACE_NODE *index_register_node; - ACPI_NAMESPACE_NODE *data_register_node; - u8 field_flags; - u8 access_attribute = 0; - u32 field_bit_position = 0; + acpi_status status; + acpi_parse_object *arg; + ACPI_CREATE_FIELD_INFO info; - arg = op->value.arg; + FUNCTION_TRACE_PTR ("Ds_create_index_field", op); - /* First arg is the name of the Index register */ - status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, - ACPI_TYPE_ANY, IMODE_LOAD_PASS1, - NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, - NULL, &index_register_node); + /* First arg is the name of the Index register (must already exist) */ + arg = op->value.arg; + status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, + ACPI_TYPE_ANY, IMODE_EXECUTE, + NS_SEARCH_PARENT, walk_state, &info.register_node); if (ACPI_FAILURE (status)) { - return (status); + return_ACPI_STATUS (status); } - /* Second arg is the data register */ + /* Second arg is the data register (must already exist) */ arg = arg->next; - status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, - INTERNAL_TYPE_INDEX_FIELD_DEFN, - IMODE_LOAD_PASS1, - NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, - NULL, &data_register_node); - + INTERNAL_TYPE_INDEX_FIELD_DEFN, IMODE_EXECUTE, + NS_SEARCH_PARENT, walk_state, &info.data_register_node); if (ACPI_FAILURE (status)) { - return (status); + return_ACPI_STATUS (status); } - /* Next arg is the field flags */ arg = arg->next; - field_flags = (u8) arg->value.integer; + info.field_flags = arg->value.integer8; /* Each remaining arg is a Named Field */ - arg = arg->next; - while (arg) { - switch (arg->opcode) - { - case AML_RESERVEDFIELD_OP: - - field_bit_position += arg->value.size; - break; - + info.field_type = INTERNAL_TYPE_INDEX_FIELD; + info.region_node = region_node; - case AML_ACCESSFIELD_OP: - - /* - * Get a new Access_type and Access_attribute for all - * entries (until end or another Access_as keyword) - */ - - access_attribute = (u8) arg->value.integer; - field_flags = (u8) - ((field_flags & FIELD_ACCESS_TYPE_MASK) || - ((u8) (arg->value.integer >> 8))); - break; - - - case AML_NAMEDFIELD_OP: - - status = acpi_ns_lookup (walk_state->scope_info, - (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)arg)->name, - INTERNAL_TYPE_INDEX_FIELD, - IMODE_LOAD_PASS1, - NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, - NULL, &node); - - if (ACPI_FAILURE (status)) { - return (status); - } - - /* - * Initialize an object for the new Node that is on - * the object stack - */ - - status = acpi_aml_prep_index_field_value (node, index_register_node, data_register_node, - field_flags, access_attribute, - field_bit_position, arg->value.size); - - if (ACPI_FAILURE (status)) { - return (status); - } - - /* Keep track of bit position for the *next* field */ - - field_bit_position += arg->value.size; - break; - - - default: - - status = AE_AML_ERROR; - break; - } - - arg = arg->next; - } + status = acpi_ds_get_field_names (&info, walk_state, arg->next); - return (status); + return_ACPI_STATUS (status); } Index: dsmethod.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/acpi/dispatcher/dsmethod.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- dsmethod.c 25 Feb 2001 23:15:15 -0000 1.1.1.2 +++ dsmethod.c 9 Apr 2002 14:05:42 -0000 1.2 @@ -34,7 +34,7 @@ #include "acdebug.h" -#define _COMPONENT DISPATCHER +#define _COMPONENT ACPI_DISPATCHER MODULE_NAME ("dsmethod") @@ -56,41 +56,48 @@ * ******************************************************************************/ -ACPI_STATUS +acpi_status acpi_ds_parse_method ( - ACPI_HANDLE obj_handle) + acpi_handle obj_handle) { - ACPI_STATUS status; - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_PARSE_OBJECT *op; - ACPI_NAMESPACE_NODE *node; - ACPI_OWNER_ID owner_id; + acpi_status status; + acpi_operand_object *obj_desc; + acpi_parse_object *op; + acpi_namespace_node *node; + acpi_owner_id owner_id; + acpi_walk_state *walk_state; + + + FUNCTION_TRACE_PTR ("Ds_parse_method", obj_handle); /* Parameter Validation */ if (!obj_handle) { - return (AE_NULL_ENTRY); + return_ACPI_STATUS (AE_NULL_ENTRY); } + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Parsing [%4.4s] **** Named_obj=%p\n", + (char*)&((acpi_namespace_node *)obj_handle)->name, obj_handle)); + /* Extract the method object from the method Node */ - node = (ACPI_NAMESPACE_NODE *) obj_handle; + node = (acpi_namespace_node *) obj_handle; obj_desc = node->object; if (!obj_desc) { - return (AE_NULL_OBJECT); + return_ACPI_STATUS (AE_NULL_OBJECT); } - /* Create a mutex for the method if there is a concurrency limit */ + /* Create a mutex for the method if there is a concurrency limit */ if ((obj_desc->method.concurrency != INFINITE_CONCURRENCY) && - (!obj_desc->method.semaphore)) - { - status = acpi_os_create_semaphore (1,obj_desc->method.concurrency, + (!obj_desc->method.semaphore)) { + status = acpi_os_create_semaphore (obj_desc->method.concurrency, + obj_desc->method.concurrency, &obj_desc->method.semaphore); if (ACPI_FAILURE (status)) { - return (status); + return_ACPI_STATUS (status); } } @@ -98,10 +105,9 @@ * Allocate a new parser op to be the root of the parsed * method tree */ - op = acpi_ps_alloc_op (AML_METHOD_OP); if (!op) { - return (AE_NO_MEMORY); + return_ACPI_STATUS (AE_NO_MEMORY); } /* Init new op with the method name and pointer back to the Node */ @@ -109,41 +115,47 @@ acpi_ps_set_name (op, node->name); op->node = node; + /* Create and initialize a new walk state */ + + walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, + NULL, NULL, NULL); + if (!walk_state) { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + status = acpi_ds_init_aml_walk (walk_state, op, node, obj_desc->method.aml_start, + obj_desc->method.aml_length, NULL, NULL, 1); + if (ACPI_FAILURE (status)) { + /* TBD: delete walk state */ + return_ACPI_STATUS (status); + } /* * Parse the method, first pass * - * The first pass load is - * where newly declared named objects are + * The first pass load is where newly declared named objects are * added into the namespace. Actual evaluation of * the named objects (what would be called a "second * pass") happens during the actual execution of the * method so that operands to the named objects can * take on dynamic run-time values. */ - - status = acpi_ps_parse_aml (op, obj_desc->method.pcode, - obj_desc->method.pcode_length, - ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE, - node, NULL, NULL, - acpi_ds_load1_begin_op, acpi_ds_load1_end_op); - + status = acpi_ps_parse_aml (walk_state); if (ACPI_FAILURE (status)) { - return (status); + return_ACPI_STATUS (status); } /* Get a new Owner_id for objects created by this method */ - owner_id = acpi_cm_allocate_owner_id (OWNER_TYPE_METHOD); + owner_id = acpi_ut_allocate_owner_id (OWNER_TYPE_METHOD); obj_desc->method.owning_id = owner_id; - /* Install the parsed tree in the method object */ - /* TBD: [Restructure] Obsolete field? */ + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** [%4.4s] Parsed **** Named_obj=%p Op=%p\n", + (char*)&((acpi_namespace_node *)obj_handle)->name, obj_handle, op)); acpi_ps_delete_parse_tree (op); - - return (status); + return_ACPI_STATUS (status); } @@ -151,8 +163,9 @@ * * FUNCTION: Acpi_ds_begin_method_execution * - * PARAMETERS: Method_node - Node of the method + * PARAMETERS: Method_node - Node of the method * Obj_desc - The method object + * Calling_method_node - Caller of this method (if non-null) * * RETURN: Status * @@ -164,47 +177,58 @@ * ******************************************************************************/ -ACPI_STATUS +acpi_status acpi_ds_begin_method_execution ( - ACPI_NAMESPACE_NODE *method_node, - ACPI_OPERAND_OBJECT *obj_desc) + acpi_namespace_node *method_node, + acpi_operand_object *obj_desc, + acpi_namespace_node *calling_method_node) { - ACPI_STATUS status = AE_OK; + acpi_status status = AE_OK; - if (!method_node) { - return (AE_NULL_ENTRY); - } + FUNCTION_TRACE_PTR ("Ds_begin_method_execution", method_node); - obj_desc = acpi_ns_get_attached_object (method_node); - if (!obj_desc) { - return (AE_NULL_OBJECT); + + if (!method_node) { + return_ACPI_STATUS (AE_NULL_ENTRY); } /* * If there is a concurrency limit on this method, we need to - * obtain a unit from the method semaphore. This releases the - * interpreter if we block + * obtain a unit from the method semaphore. */ - if (obj_desc->method.semaphore) { - status = acpi_aml_system_wait_semaphore (obj_desc->method.semaphore, + /* + * Allow recursive method calls, up to the reentrancy/concurrency + * limit imposed by the SERIALIZED rule and the Sync_level method + * parameter. + * + * The point of this code is to avoid permanently blocking a + * thread that is making recursive method calls. + */ + if (method_node == calling_method_node) { + if (obj_desc->method.thread_count >= obj_desc->method.concurrency) { + return_ACPI_STATUS (AE_AML_METHOD_LIMIT); + } + } + + /* + * Get a unit from the method semaphore. This releases the + * interpreter if we block + */ + status = acpi_ex_system_wait_semaphore (obj_desc->method.semaphore, WAIT_FOREVER); } /* - * Increment the method parse tree thread count since there - * is one additional thread executing in it. If configured - * for deletion-on-exit, the parse tree will be deleted when - * the last thread completes execution of the method + * Increment the method parse tree thread count since it has been + * reentered one more time (even if it is the same thread) */ - obj_desc->method.thread_count++; - - return (status); + return_ACPI_STATUS (status); } @@ -221,123 +245,107 @@ * ******************************************************************************/ -ACPI_STATUS +acpi_status acpi_ds_call_control_method ( - ACPI_WALK_LIST *walk_list, - ACPI_WALK_STATE *this_walk_state, - ACPI_PARSE_OBJECT *op) + acpi_walk_list *walk_list, + acpi_walk_state *this_walk_state, + acpi_parse_object *op) /* TBD: This operand is obsolete */ { - ACPI_STATUS status; - ACPI_NAMESPACE_NODE *method_node; - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_WALK_STATE *next_walk_state; - ACPI_PARSE_STATE *parser_state; + acpi_status status; + acpi_namespace_node *method_node; + acpi_operand_object *obj_desc; + acpi_walk_state *next_walk_state; u32 i; + FUNCTION_TRACE_PTR ("Ds_call_control_method", this_walk_state); + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Execute method %p, currentstate=%p\n", + this_walk_state->prev_op, this_walk_state)); + /* * Get the namespace entry for the control method we are about to call */ - method_node = this_walk_state->method_call_node; if (!method_node) { - return (AE_NULL_ENTRY); + return_ACPI_STATUS (AE_NULL_ENTRY); } obj_desc = acpi_ns_get_attached_object (method_node); if (!obj_desc) { - return (AE_NULL_OBJECT); + return_ACPI_STATUS (AE_NULL_OBJECT); } - /* Init for new method, wait on concurrency semaphore */ - status = acpi_ds_begin_method_execution (method_node, obj_desc); + status = acpi_ds_begin_method_execution (method_node, obj_desc, + this_walk_state->method_node); if (ACPI_FAILURE (status)) { - return (status); + return_ACPI_STATUS (status); } - /* Create and initialize a new parser state */ + /* 1) Parse: Create a new walk state for the preempting walk */ - parser_state = acpi_ps_create_state (obj_desc->method.pcode, - obj_desc->method.pcode_length); - if (!parser_state) { - return (AE_NO_MEMORY); + next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, + op, obj_desc, NULL); + if (!next_walk_state) { + return_ACPI_STATUS (AE_NO_MEMORY); + goto cleanup; } - acpi_ps_init_scope (parser_state, NULL); - parser_state->start_node = method_node; - - - /* Create a new state for the preempting walk */ + /* Create and init a Root Node */ - next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, - NULL, obj_desc, walk_list); - if (!next_walk_state) { - /* TBD: delete parser state */ + op = acpi_ps_alloc_op (AML_SCOPE_OP); + if (!op) { + status = AE_NO_MEMORY; + goto cleanup; + } - return (AE_NO_MEMORY); + status = acpi_ds_init_aml_walk (next_walk_state, op, method_node, + obj_desc->method.aml_start, obj_desc->method.aml_length, + NULL, NULL, 1); + if (ACPI_FAILURE (status)) { + /* TBD: delete walk state */ + goto cleanup; } - next_walk_state->walk_type = WALK_METHOD; - next_walk_state->method_node = method_node; - next_walk_state->parser_state = parser_state; - next_walk_state->parse_flags = this_walk_state->parse_flags; - next_walk_state->descending_callback = this_walk_state->descending_callback; - next_walk_state->ascending_callback = this_walk_state->ascending_callback; + /* Begin AML parse */ - /* The Next_op of the Next_walk will be the beginning of the method */ - /* TBD: [Restructure] -- obsolete? */ + status = acpi_ps_parse_aml (next_walk_state); + acpi_ps_delete_parse_tree (op); - next_walk_state->next_op = NULL; - /* Open a new scope */ + /* 2) Execute: Create a new state for the preempting walk */ - status = acpi_ds_scope_stack_push (method_node, - ACPI_TYPE_METHOD, next_walk_state); - if (ACPI_FAILURE (status)) { + next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, + NULL, obj_desc, walk_list); + if (!next_walk_state) { + status = AE_NO_MEMORY; goto cleanup; } - /* - * Initialize the arguments for the method. The resolved - * arguments were put on the previous walk state's operand + * The resolved arguments were put on the previous walk state's operand * stack. Operands on the previous walk state stack always * start at index 0. + * Null terminate the list of arguments */ + this_walk_state->operands [this_walk_state->num_operands] = NULL; - status = acpi_ds_method_data_init_args (&this_walk_state->operands[0], - this_walk_state->num_operands, - next_walk_state); + status = acpi_ds_init_aml_walk (next_walk_state, NULL, method_node, + obj_desc->method.aml_start, obj_desc->method.aml_length, + &this_walk_state->operands[0], NULL, 3); if (ACPI_FAILURE (status)) { goto cleanup; } - - /* Create and init a Root Node */ - - op = acpi_ps_alloc_op (AML_SCOPE_OP); - if (!op) { - return (AE_NO_MEMORY); - } - - status = acpi_ps_parse_aml (op, obj_desc->method.pcode, - obj_desc->method.pcode_length, - ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE, - method_node, NULL, NULL, - acpi_ds_load1_begin_op, acpi_ds_load1_end_op); - acpi_ps_delete_parse_tree (op); - - /* * Delete the operands on the previous walkstate operand stack * (they were copied to new objects) */ - for (i = 0; i < obj_desc->method.param_count; i++) { - acpi_cm_remove_reference (this_walk_state->operands [i]); + acpi_ut_remove_reference (this_walk_state->operands [i]); this_walk_state->operands [i] = NULL; } @@ -345,8 +353,10 @@ this_walk_state->num_operands = 0; + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Starting nested execution, newstate=%p\n", + next_walk_state)); - return (AE_OK); + return_ACPI_STATUS (AE_OK); /* On error, we must delete the new walk state */ @@ -354,7 +364,7 @@ cleanup: acpi_ds_terminate_control_method (next_walk_state); acpi_ds_delete_walk_state (next_walk_state); - return (status); + return_ACPI_STATUS (status); } @@ -372,12 +382,15 @@ * ******************************************************************************/ -ACPI_STATUS +acpi_status acpi_ds_restart_control_method ( - ACPI_WALK_STATE *walk_state, - ACPI_OPERAND_OBJECT *return_desc) + acpi_walk_state *walk_state, + acpi_operand_object *return_desc) { - ACPI_STATUS status; + acpi_status status; + + + FUNCTION_TRACE_PTR ("Ds_restart_control_method", walk_state); if (return_desc) { @@ -386,11 +399,10 @@ * Get the return value (if any) from the previous method. * NULL if no return value */ - status = acpi_ds_result_push (return_desc, walk_state); if (ACPI_FAILURE (status)) { - acpi_cm_remove_reference (return_desc); - return (status); + acpi_ut_remove_reference (return_desc); + return_ACPI_STATUS (status); } } @@ -399,13 +411,18 @@ * Delete the return value if it will not be used by the * calling method */ - acpi_cm_remove_reference (return_desc); + acpi_ut_remove_reference (return_desc); } } + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Method=%p Return=%p Return_used?=%X Res_stack=%p State=%p\n", + walk_state->method_call_op, return_desc, walk_state->return_used, + walk_state->results, walk_state)); + - return (AE_OK); + return_ACPI_STATUS (AE_OK); } @@ -423,20 +440,22 @@ * ******************************************************************************/ -ACPI_STATUS +acpi_status acpi_ds_terminate_control_method ( - ACPI_WALK_STATE *walk_state) + acpi_walk_state *walk_state) { - ACPI_STATUS status; - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_NAMESPACE_NODE *method_node; + acpi_operand_object *obj_desc; + acpi_namespace_node *method_node; + + + FUNCTION_TRACE_PTR ("Ds_terminate_control_method", walk_state); /* The method object should be stored in the walk state */ obj_desc = walk_state->method_desc; if (!obj_desc) { - return (AE_OK); + return_ACPI_STATUS (AE_OK); } /* Delete all arguments and locals */ @@ -448,15 +467,14 @@ * If this is the last thread executing the method, * we have additional cleanup to perform */ - - acpi_cm_acquire_mutex (ACPI_MTX_PARSER); + acpi_ut_acquire_mutex (ACPI_MTX_PARSER); /* Signal completion of the execution of this method if necessary */ if (walk_state->method_desc->method.semaphore) { - status = acpi_os_signal_semaphore ( - walk_state->method_desc->method.semaphore, 1); + acpi_os_signal_semaphore ( + walk_state->method_desc->method.semaphore, 1); } /* Decrement the thread count on the method parse tree */ @@ -470,11 +488,12 @@ * The method Node is stored in the walk state */ method_node = walk_state->method_node; + /* * Delete any namespace entries created immediately underneath * the method */ - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); if (method_node->child) { acpi_ns_delete_namespace_subtree (method_node); } @@ -484,11 +503,11 @@ * the namespace */ acpi_ns_delete_namespace_by_owner (walk_state->method_desc->method.owning_id); - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); } - acpi_cm_release_mutex (ACPI_MTX_PARSER); - return (AE_OK); + acpi_ut_release_mutex (ACPI_MTX_PARSER); + return_ACPI_STATUS (AE_OK); } Index: dsmthdat.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/acpi/dispatcher/dsmthdat.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- dsmthdat.c 25 Feb 2001 23:15:15 -0000 1.1.1.2 +++ dsmthdat.c 9 Apr 2002 14:05:42 -0000 1.2 @@ -32,7 +32,7 @@ #include "acnamesp.h" -#define _COMPONENT DISPATCHER +#define _COMPONENT ACPI_DISPATCHER MODULE_NAME ("dsmthdat") @@ -51,16 +51,18 @@ * ******************************************************************************/ -ACPI_STATUS +acpi_status acpi_ds_method_data_init ( - ACPI_WALK_STATE *walk_state) + acpi_walk_state *walk_state) { u32 i; + FUNCTION_TRACE ("Ds_method_data_init"); + /* * Walk_state fields are initialized to zero by the - * Acpi_cm_callocate(). + * ACPI_MEM_CALLOCATE(). * * An Node is assigned to each argument and local so * that Ref_of() can return a pointer to the Node. @@ -89,7 +91,7 @@ walk_state->local_variables[i].flags = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_LOCAL; } - return (AE_OK); + return_ACPI_STATUS (AE_OK); } @@ -106,46 +108,57 @@ * ******************************************************************************/ -ACPI_STATUS +acpi_status acpi_ds_method_data_delete_all ( - ACPI_WALK_STATE *walk_state) + acpi_walk_state *walk_state) { u32 index; - ACPI_OPERAND_OBJECT *object; + acpi_operand_object *object; + + + FUNCTION_TRACE ("Ds_method_data_delete_all"); /* Delete the locals */ + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Deleting local variables in %p\n", walk_state)); + for (index = 0; index < MTH_NUM_LOCALS; index++) { object = walk_state->local_variables[index].object; if (object) { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Local%d=%p\n", index, object)); + /* Remove first */ walk_state->local_variables[index].object = NULL; /* Was given a ref when stored */ - acpi_cm_remove_reference (object); + acpi_ut_remove_reference (object); } } /* Delete the arguments */ + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Deleting arguments in %p\n", walk_state)); + for (index = 0; index < MTH_NUM_ARGS; index++) { object = walk_state->arguments[index].object; if (object) { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Arg%d=%p\n", index, object)); + /* Remove first */ walk_state->arguments[index].object = NULL; /* Was given a ref when stored */ - acpi_cm_remove_reference (object); + acpi_ut_remove_reference (object); } } - return (AE_OK); + return_ACPI_STATUS (AE_OK); } @@ -163,35 +176,38 @@ * ******************************************************************************/ -ACPI_STATUS +acpi_status acpi_ds_method_data_init_args ( - ACPI_OPERAND_OBJECT **params, + acpi_operand_object **params, u32 max_param_count, - ACPI_WALK_STATE *walk_state) + acpi_walk_state *walk_state) { - ACPI_STATUS status; + acpi_status status; u32 mindex; u32 pindex; + FUNCTION_TRACE_PTR ("Ds_method_data_init_args", params); + + if (!params) { - return (AE_OK); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "No param list passed to method\n")); + return_ACPI_STATUS (AE_OK); } /* Copy passed parameters into the new method stack frame */ for (pindex = mindex = 0; (mindex < MTH_NUM_ARGS) && (pindex < max_param_count); - mindex++) - { + mindex++) { if (params[pindex]) { /* * A valid parameter. * Set the current method argument to the * Params[Pindex++] argument object descriptor */ - status = acpi_ds_method_data_set_value (MTH_TYPE_ARG, mindex, - params[pindex], walk_state); + status = acpi_ds_store_object_to_local (AML_ARG_OP, mindex, + params[pindex], walk_state); if (ACPI_FAILURE (status)) { break; } @@ -204,7 +220,8 @@ } } - return (AE_OK); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%d args passed to method\n", pindex)); + return_ACPI_STATUS (AE_OK); } @@ -212,7 +229,7 @@ * * FUNCTION: Acpi_ds_method_data_get_entry * - * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP * Index - Which local_var or argument to get * Entry - Pointer to where a pointer to the stack * entry is returned. @@ -220,55 +237,60 @@ * * RETURN: Status * - * DESCRIPTION: Get the address of the stack entry given by Type:Index + * DESCRIPTION: Get the address of the object entry given by Opcode:Index * ******************************************************************************/ -ACPI_STATUS +acpi_status acpi_ds_method_data_get_entry ( - u32 type, + u16 opcode, u32 index, - ACPI_WALK_STATE *walk_state, - ACPI_OPERAND_OBJECT ***entry) + acpi_walk_state *walk_state, + acpi_operand_object ***entry) { + FUNCTION_TRACE_U32 ("Ds_method_data_get_entry", index); + /* * Get the requested object. - * The stack "Type" is either a Local_variable or an Argument + * The stack "Opcode" is either a Local_variable or an Argument */ + switch (opcode) { - switch (type) - { - - case MTH_TYPE_LOCAL: + case AML_LOCAL_OP: if (index > MTH_MAX_LOCAL) { - return (AE_BAD_PARAMETER); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Local_var index %d is invalid (max %d)\n", + index, MTH_MAX_LOCAL)); + return_ACPI_STATUS (AE_BAD_PARAMETER); } - *entry = - (ACPI_OPERAND_OBJECT **) &walk_state->local_variables[index].object; + *entry = (acpi_operand_object **) + &walk_state->local_variables[index].object; break; - case MTH_TYPE_ARG: + case AML_ARG_OP: if (index > MTH_MAX_ARG) { - return (AE_BAD_PARAMETER); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Arg index %d is invalid (max %d)\n", + index, MTH_MAX_ARG)); + return_ACPI_STATUS (AE_BAD_PARAMETER); } - *entry = - (ACPI_OPERAND_OBJECT **) &walk_state->arguments[index].object; + *entry = (acpi_operand_object **) + &walk_state->arguments[index].object; break; default: - return (AE_BAD_PARAMETER); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Opcode %d is invalid\n", opcode)); + return_ACPI_STATUS (AE_BAD_PARAMETER); } - return (AE_OK); + return_ACPI_STATUS (AE_OK); } @@ -276,44 +298,47 @@ * * FUNCTION: Acpi_ds_method_data_set_entry * - * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP * Index - Which local_var or argument to get * Object - Object to be inserted into the stack entry * Walk_state - Current walk state object * * RETURN: Status * - * DESCRIPTION: Insert an object onto the method stack at entry Type:Index. + * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index. * ******************************************************************************/ -ACPI_STATUS +acpi_status acpi_ds_method_data_set_entry ( - u32 type, + u16 opcode, u32 index, - ACPI_OPERAND_OBJECT *object, - ACPI_WALK_STATE *walk_state) + acpi_operand_object *object, + acpi_walk_state *walk_state) { - ACPI_STATUS status; - ACPI_OPERAND_OBJECT **entry; + acpi_status status; + acpi_operand_object **entry; + + + FUNCTION_TRACE ("Ds_method_data_set_entry"); /* Get a pointer to the stack entry to set */ - status = acpi_ds_method_data_get_entry (type, index, walk_state, &entry); + status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); if (ACPI_FAILURE (status)) { - return (status); + return_ACPI_STATUS (status); } /* Increment ref count so object can't be deleted while installed */ - acpi_cm_add_reference (object); + acpi_ut_add_reference (object); /* Install the object into the stack entry */ *entry = object; - return (AE_OK); + return_ACPI_STATUS (AE_OK); } @@ -321,7 +346,7 @@ * * FUNCTION: Acpi_ds_method_data_get_type * - * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP * Index - Which local_var or argument whose type * to get * Walk_state - Current walk state object @@ -331,22 +356,25 @@ * ******************************************************************************/ -OBJECT_TYPE_INTERNAL +acpi_object_type8 acpi_ds_method_data_get_type ( - u32 type, + u16 opcode, u32 index, - ACPI_WALK_STATE *walk_state) + acpi_walk_state *walk_state) { - ACPI_STATUS status; - ACPI_OPERAND_OBJECT **entry; - ACPI_OPERAND_OBJECT *object; + acpi_status status; + acpi_operand_object **entry; + acpi_operand_object *object; + + + FUNCTION_TRACE ("Ds_method_data_get_type"); /* Get a pointer to the requested stack entry */ - status = acpi_ds_method_data_get_entry (type, index, walk_state, &entry); + status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); if (ACPI_FAILURE (status)) { - return ((ACPI_TYPE_NOT_FOUND)); + return_VALUE ((ACPI_TYPE_NOT_FOUND)); } /* Get the object from the method stack */ @@ -357,18 +385,18 @@ if (!object) { /* Any == 0 => "uninitialized" -- see spec 15.2.3.5.2.28 */ - return (ACPI_TYPE_ANY); + return_VALUE (ACPI_TYPE_ANY); } - return (object->common.type); + return_VALUE (object->common.type); } /******************************************************************************* * - * FUNCTION: Acpi_ds_method_data_get_nte + * FUNCTION: Acpi_ds_method_data_get_node * - * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP * Index - Which local_var or argument whose type * to get * Walk_state - Current walk state object @@ -377,32 +405,38 @@ * ******************************************************************************/ -ACPI_NAMESPACE_NODE * -acpi_ds_method_data_get_nte ( - u32 type, +acpi_namespace_node * +acpi_ds_method_data_get_node ( + u16 opcode, u32 index, - ACPI_WALK_STATE *walk_state) + acpi_walk_state *walk_state) { - ACPI_NAMESPACE_NODE *node = NULL; + acpi_namespace_node *node = NULL; + + FUNCTION_TRACE ("Ds_method_data_get_node"); - switch (type) - { - case MTH_TYPE_LOCAL: + switch (opcode) { + + case AML_LOCAL_OP: if (index > MTH_MAX_LOCAL) { - return (node); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Local index %d is invalid (max %d)\n", + index, MTH_MAX_LOCAL)); + return_PTR (node); } node = &walk_state->local_variables[index]; break; - case MTH_TYPE_ARG: + case AML_ARG_OP: if (index > MTH_MAX_ARG) { - return (node); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Arg index %d is invalid (max %d)\n", + index, MTH_MAX_ARG)); + return_PTR (node); } node = &walk_state->arguments[index]; @@ -410,11 +444,12 @@ default: + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Opcode %d is invalid\n", opcode)); break; } - return (node); + return_PTR (node); } @@ -422,7 +457,7 @@ * * FUNCTION: Acpi_ds_method_data_get_value * - * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP * Index - Which local_var or argument to get * Walk_state - Current walk state object * *Dest_desc - Ptr to Descriptor into which selected Arg @@ -432,34 +467,38 @@ * * DESCRIPTION: Retrieve value of selected Arg or Local from the method frame * at the current top of the method stack. - * Used only in Acpi_aml_resolve_to_value(). + * Used only in Acpi_ex_resolve_to_value(). * ******************************************************************************/ -ACPI_STATUS +acpi_status acpi_ds_method_data_get_value ( - u32 type, + u16 opcode, u32 index, - ACPI_WALK_STATE *walk_state, - ACPI_OPERAND_OBJECT **dest_desc) + acpi_walk_state *walk_state, + acpi_operand_object **dest_desc) { - ACPI_STATUS status; - ACPI_OPERAND_OBJECT **entry; - ACPI_OPERAND_OBJECT *object; + acpi_status status; + acpi_operand_object **entry; + acpi_operand_object *object; + + + FUNCTION_TRACE ("Ds_method_data_get_value"); /* Validate the object descriptor */ if (!dest_desc) { - return (AE_BAD_PARAMETER); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null object descriptor pointer\n")); + return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Get a pointer to the requested method stack entry */ - status = acpi_ds_method_data_get_entry (type, index, walk_state, &entry); + status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); if (ACPI_FAILURE (status)) { - return (status); + return_ACPI_STATUS (status); } /* Get the object from the method stack */ @@ -477,17 +516,21 @@ * was referenced by the method (via the ASL) * before it was initialized. Either case is an error. */ + switch (opcode) { + case AML_ARG_OP: - switch (type) - { - case MTH_TYPE_ARG: + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Uninitialized Arg[%d] at entry %p\n", + index, entry)); - return (AE_AML_UNINITIALIZED_ARG); + return_ACPI_STATUS (AE_AML_UNINITIALIZED_ARG); break; - case MTH_TYPE_LOCAL: + case AML_LOCAL_OP: + + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Uninitialized Local[%d] at entry %p\n", + index, entry)); - return (AE_AML_UNINITIALIZED_LOCAL); + return_ACPI_STATUS (AE_AML_UNINITIALIZED_LOCAL); break; } } @@ -497,11 +540,10 @@ * Index points to initialized and valid object stack value. * Return an additional reference to the object */ - *dest_desc = object; - acpi_cm_add_reference (object); + acpi_ut_add_reference (object); - return (AE_OK); + return_ACPI_STATUS (AE_OK); } @@ -509,33 +551,36 @@ * * FUNCTION: Acpi_ds_method_data_delete_value * - * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP * Index - Which local_var or argument to delete * Walk_state - Current walk state object * * RETURN: Status * - * DESCRIPTION: Delete the entry at Type:Index on the method stack. Inserts + * DESCRIPTION: Delete the entry at Opcode:Index on the method stack. Inserts * a null into the stack slot after the object is deleted. * ******************************************************************************/ -ACPI_STATUS +acpi_status acpi_ds_method_data_delete_value ( - u32 type, + u16 opcode, u32 index, - ACPI_WALK_STATE *walk_state) + acpi_walk_state *walk_state) { - ACPI_STATUS status; - ACPI_OPERAND_OBJECT **entry; - ACPI_OPERAND_OBJECT *object; + acpi_status status; + acpi_operand_object **entry; + acpi_operand_object *object; + + + FUNCTION_TRACE ("Ds_method_data_delete_value"); /* Get a pointer to the requested entry */ - status = acpi_ds_method_data_get_entry (type, index, walk_state, &entry); + status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); if (ACPI_FAILURE (status)) { - return (status); + return_ACPI_STATUS (status); } /* Get the current entry in this slot k */ @@ -549,28 +594,25 @@ */ *entry = NULL; - if ((object) && - (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_INTERNAL))) - { + (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_INTERNAL))) { /* * There is a valid object in this slot * Decrement the reference count by one to balance the * increment when the object was stored in the slot. */ - acpi_cm_remove_reference (object); + acpi_ut_remove_reference (object); } - - return (AE_OK); + return_ACPI_STATUS (AE_OK); } /******************************************************************************* * - * FUNCTION: Acpi_ds_method_data_set_value + * FUNCTION: Acpi_ds_store_object_to_local * - * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP * Index - Which local_var or argument to set * Src_desc - Value to be stored * Walk_state - Current walk state @@ -583,32 +625,38 @@ * ******************************************************************************/ -ACPI_STATUS -acpi_ds_method_data_set_value ( - u32 type, +acpi_status +acpi_ds_store_object_to_local ( + u16 opcode, u32 index, - ACPI_OPERAND_OBJECT *src_desc, - ACPI_WALK_STATE *walk_state) + acpi_operand_object *src_desc, + acpi_walk_state *walk_state) { - ACPI_STATUS status; - ACPI_OPERAND_OBJECT **entry; + acpi_status status; + acpi_operand_object **entry; + + + FUNCTION_TRACE ("Ds_method_data_set_value"); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode=%d Idx=%d Obj=%p\n", + opcode, index, src_desc)); /* Parameter validation */ if (!src_desc) { - return (AE_BAD_PARAMETER); + return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Get a pointer to the requested method stack entry */ - status = acpi_ds_method_data_get_entry (type, index, walk_state, &entry); + status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); if (ACPI_FAILURE (status)) { goto cleanup; } if (*entry == src_desc) { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p already installed!\n", src_desc)); goto cleanup; } @@ -619,7 +667,6 @@ * is an object reference stored there, we have to do * an indirect store! */ - if (*entry) { /* * Check for an indirect store if an argument @@ -637,38 +684,42 @@ * * Weird, but true. */ + if ((opcode == AML_ARG_OP) && + (VALID_DESCRIPTOR_TYPE (*entry, ACPI_DESC_TYPE_NAMED))) { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Arg (%p) is an Obj_ref(Node), storing in %p\n", + src_desc, *entry)); - if ((type == MTH_TYPE_ARG) && - (VALID_DESCRIPTOR_TYPE (*entry, ACPI_DESC_TYPE_NAMED))) - { /* Detach an existing object from the Node */ - acpi_ns_detach_object ((ACPI_NAMESPACE_NODE *) *entry); + acpi_ns_detach_object ((acpi_namespace_node *) *entry); /* * Store this object into the Node * (do the indirect store) */ - status = acpi_ns_attach_object ((ACPI_NAMESPACE_NODE *) *entry, src_desc, + status = acpi_ns_attach_object ((acpi_namespace_node *) *entry, src_desc, src_desc->common.type); - return (status); + return_ACPI_STATUS (status); } +#ifdef ACPI_ENABLE_IMPLICIT_CONVERSION /* * Perform "Implicit conversion" of the new object to the type of the * existing object */ - status = acpi_aml_convert_to_target_type ((*entry)->common.type, &src_desc, walk_state); + status = acpi_ex_convert_to_target_type ((*entry)->common.type, &src_desc, walk_state); if (ACPI_FAILURE (status)) { goto cleanup; } +#endif /* * Delete the existing object * before storing the new one */ - acpi_ds_method_data_delete_value (type, index, walk_state); + acpi_ds_method_data_delete_value (opcode, index, walk_state); } @@ -678,20 +729,20 @@ * Install the new object in the stack entry * (increments the object reference count by one) */ - status = acpi_ds_method_data_set_entry (type, index, src_desc, walk_state); + status = acpi_ds_method_data_set_entry (opcode, index, src_desc, walk_state); if (ACPI_FAILURE (status)) { goto cleanup; } /* Normal exit */ - return (AE_OK); + return_ACPI_STATUS (AE_OK); /* Error exit */ cleanup: - return (status); + return_ACPI_STATUS (status); } Index: dsobject.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/acpi/dispatcher/dsobject.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- dsobject.c 25 Feb 2001 23:15:15 -0000 1.1.1.2 +++ dsobject.c 9 Apr 2002 14:05:42 -0000 1.2 @@ -31,7 +31,7 @@ #include "acinterp.h" #include "acnamesp.h" -#define _COMPONENT DISPATCHER +#define _COMPONENT ACPI_DISPATCHER MODULE_NAME ("dsobject") @@ -55,19 +55,22 @@ * ******************************************************************************/ -ACPI_STATUS +acpi_status acpi_ds_init_one_object ( - ACPI_HANDLE obj_handle, + acpi_handle obj_handle, u32 level, void *context, void **return_value) { - OBJECT_TYPE_INTERNAL type; - ACPI_STATUS status; - ACPI_INIT_WALK_INFO *info = (ACPI_INIT_WALK_INFO *) context; + acpi_object_type8 type; + acpi_status status; + acpi_init_walk_info *info = (acpi_init_walk_info *) context; u8 table_revision; + PROC_NAME ("Ds_init_one_object"); + + info->object_count++; table_revision = info->table_desc->pointer->revision; @@ -75,10 +78,8 @@ * We are only interested in objects owned by the table that * was just loaded */ - - if (((ACPI_NAMESPACE_NODE *) obj_handle)->owner_id != - info->table_desc->table_id) - { + if (((acpi_namespace_node *) obj_handle)->owner_id != + info->table_desc->table_id) { return (AE_OK); } @@ -87,8 +88,7 @@ type = acpi_ns_get_type (obj_handle); - switch (type) - { + switch (type) { case ACPI_TYPE_REGION: @@ -102,26 +102,30 @@ info->method_count++; + if (!(acpi_dbg_level & ACPI_LV_INIT)) { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, ".")); + } /* * Set the execution data width (32 or 64) based upon the * revision number of the parent ACPI table. */ - if (table_revision == 1) { - ((ACPI_NAMESPACE_NODE *)obj_handle)->flags |= ANOBJ_DATA_WIDTH_32; + ((acpi_namespace_node *)obj_handle)->flags |= ANOBJ_DATA_WIDTH_32; } /* * Always parse methods to detect errors, we may delete * the parse tree below */ - status = acpi_ds_parse_method (obj_handle); + if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Method %p [%4.4s] - parse failure, %s\n", + obj_handle, (char*)&((acpi_namespace_node *)obj_handle)->name, + acpi_format_exception (status))); - /* TBD: [Errors] what do we do with an error? */ + /* This parse failed, but we will continue parsing more methods */ - if (ACPI_FAILURE (status)) { break; } @@ -157,13 +161,21 @@ * ******************************************************************************/ -ACPI_STATUS +acpi_status acpi_ds_initialize_objects ( - ACPI_TABLE_DESC *table_desc, - ACPI_NAMESPACE_NODE *start_node) + acpi_table_desc *table_desc, + acpi_namespace_node *start_node) { - ACPI_STATUS status; - ACPI_INIT_WALK_INFO in... [truncated message content] |
From: Andy P. <at...@us...> - 2002-04-09 14:08:14
|
Update of /cvsroot/linux-vax/kernel-2.4/fs/efs In directory usw-pr-cvs1:/tmp/cvs-serv27691/efs Modified Files: inode.c super.c Log Message: sync 2.4.15 commit 11 Index: inode.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/efs/inode.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- inode.c 14 Jan 2001 16:39:06 -0000 1.1.1.1 +++ inode.c 9 Apr 2002 13:11:17 -0000 1.2 @@ -9,6 +9,8 @@ #include <linux/efs_fs.h> #include <linux/efs_fs_sb.h> +#include <linux/module.h> + extern int efs_get_block(struct inode *, long, struct buffer_head *, int); static int efs_readpage(struct file *file, struct page *page) @@ -302,3 +304,4 @@ return 0; } +MODULE_LICENSE("GPL"); Index: super.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/efs/super.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- super.c 14 Jan 2001 16:39:04 -0000 1.1.1.1 +++ super.c 9 Apr 2002 13:11:17 -0000 1.2 @@ -178,6 +178,7 @@ s->s_magic = EFS_SUPER_MAGIC; s->s_blocksize = EFS_BLOCKSIZE; s->s_blocksize_bits = EFS_BLOCKSIZE_BITS; + if (!(s->s_flags & MS_RDONLY)) { #ifdef DEBUG printk(KERN_INFO "EFS: forcing read-only mode\n"); |
From: Andy P. <at...@us...> - 2002-04-09 14:07:47
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/hotplug In directory usw-pr-cvs1:/tmp/cvs-serv15748/drivers/hotplug Log Message: Directory /cvsroot/linux-vax/kernel-2.4/drivers/hotplug added to the repository |
From: Andy P. <at...@us...> - 2002-04-09 13:58:32
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/mtd/nand In directory usw-pr-cvs1:/tmp/cvs-serv12167/drivers/mtd/nand Log Message: Directory /cvsroot/linux-vax/kernel-2.4/drivers/mtd/nand added to the repository |
From: Andy P. <at...@us...> - 2002-04-09 13:58:22
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/mtd/maps In directory usw-pr-cvs1:/tmp/cvs-serv12123/drivers/mtd/maps Log Message: Directory /cvsroot/linux-vax/kernel-2.4/drivers/mtd/maps added to the repository |
From: Andy P. <at...@us...> - 2002-04-09 13:58:15
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/mtd/devices In directory usw-pr-cvs1:/tmp/cvs-serv12085/drivers/mtd/devices Log Message: Directory /cvsroot/linux-vax/kernel-2.4/drivers/mtd/devices added to the repository |
From: Andy P. <at...@us...> - 2002-04-09 13:58:04
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/mtd/chips In directory usw-pr-cvs1:/tmp/cvs-serv12012/drivers/mtd/chips Log Message: Directory /cvsroot/linux-vax/kernel-2.4/drivers/mtd/chips added to the repository |
From: Andy P. <at...@us...> - 2002-04-09 13:51:46
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/acpi/ospm/thermal In directory usw-pr-cvs1:/tmp/cvs-serv9642/thermal Log Message: Directory /cvsroot/linux-vax/kernel-2.4/drivers/acpi/ospm/thermal added to the repository |
From: Andy P. <at...@us...> - 2002-04-09 13:51:46
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/acpi/ospm/ac_adapter In directory usw-pr-cvs1:/tmp/cvs-serv9642/ac_adapter Log Message: Directory /cvsroot/linux-vax/kernel-2.4/drivers/acpi/ospm/ac_adapter added to the repository |
From: Andy P. <at...@us...> - 2002-04-09 13:51:46
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/acpi/ospm/battery In directory usw-pr-cvs1:/tmp/cvs-serv9642/battery Log Message: Directory /cvsroot/linux-vax/kernel-2.4/drivers/acpi/ospm/battery added to the repository |
From: Andy P. <at...@us...> - 2002-04-09 13:51:46
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/acpi/ospm/busmgr In directory usw-pr-cvs1:/tmp/cvs-serv9642/busmgr Log Message: Directory /cvsroot/linux-vax/kernel-2.4/drivers/acpi/ospm/busmgr added to the repository |
From: Andy P. <at...@us...> - 2002-04-09 13:51:45
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/acpi/ospm/button In directory usw-pr-cvs1:/tmp/cvs-serv9642/button Log Message: Directory /cvsroot/linux-vax/kernel-2.4/drivers/acpi/ospm/button added to the repository |
From: Andy P. <at...@us...> - 2002-04-09 13:51:44
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/acpi/ospm/include In directory usw-pr-cvs1:/tmp/cvs-serv9642/include Log Message: Directory /cvsroot/linux-vax/kernel-2.4/drivers/acpi/ospm/include added to the repository |
From: Andy P. <at...@us...> - 2002-04-09 13:51:44
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/acpi/ospm/processor In directory usw-pr-cvs1:/tmp/cvs-serv9642/processor Log Message: Directory /cvsroot/linux-vax/kernel-2.4/drivers/acpi/ospm/processor added to the repository |
From: Andy P. <at...@us...> - 2002-04-09 13:51:43
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/acpi/ospm/system In directory usw-pr-cvs1:/tmp/cvs-serv9642/system Log Message: Directory /cvsroot/linux-vax/kernel-2.4/drivers/acpi/ospm/system added to the repository |
From: Andy P. <at...@us...> - 2002-04-09 13:51:43
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/acpi/ospm/ec In directory usw-pr-cvs1:/tmp/cvs-serv9642/ec Log Message: Directory /cvsroot/linux-vax/kernel-2.4/drivers/acpi/ospm/ec added to the repository |
From: Andy P. <at...@us...> - 2002-04-09 12:59:23
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/video/aty In directory usw-pr-cvs1:/tmp/cvs-serv25019/drivers/video/aty Log Message: Directory /cvsroot/linux-vax/kernel-2.4/drivers/video/aty added to the repository |
From: Andy P. <at...@us...> - 2002-04-09 12:59:19
|
Update of /cvsroot/linux-vax/kernel-2.4/include/scsi In directory usw-pr-cvs1:/tmp/cvs-serv24871/scsi Modified Files: scsi.h sg.h Log Message: synch 2.4.15 commit 8 Index: scsi.h =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/include/scsi/scsi.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- scsi.h 14 Jan 2001 16:56:15 -0000 1.1.1.1 +++ scsi.h 9 Apr 2002 12:59:15 -0000 1.2 @@ -196,8 +196,9 @@ * Here are some scsi specific ioctl commands which are sometimes useful. */ /* These are a few other constants only used by scsi devices */ +/* Note that include/linux/cdrom.h also defines IOCTL 0x5300 - 0x5395 */ -#define SCSI_IOCTL_GET_IDLUN 0x5382 +#define SCSI_IOCTL_GET_IDLUN 0x5382 /* conflicts with CDROMAUDIOBUFSIZ */ /* Used to turn on and off tagged queuing for scsi devices */ @@ -209,6 +210,9 @@ /* Used to get the bus number for a device */ #define SCSI_IOCTL_GET_BUS_NUMBER 0x5386 + +/* Used to get the PCI location of a device */ +#define SCSI_IOCTL_GET_PCI 0x5387 /* * Overrides for Emacs so that we follow Linus's tabbing style. Index: sg.h =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/include/scsi/sg.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sg.h 14 Jan 2001 16:56:18 -0000 1.1.1.1 +++ sg.h 9 Apr 2002 12:59:15 -0000 1.2 @@ -9,89 +9,47 @@ Original driver (sg.h): * Copyright (C) 1992 Lawrence Foard Version 2 and 3 extensions to driver: -* Copyright (C) 1998 - 2000 Douglas Gilbert +* Copyright (C) 1998 - 2001 Douglas Gilbert - Version: 3.1.17 (20000921) + Version: 3.1.20 (20010814) This version is for 2.4 series kernels. - Changes since 3.1.16 (20000716) - - changes for new scsi subsystem initialization - - change Scsi_Cmnd usage to Scsi_Request - - cleanup for no procfs - Changes since 3.1.15 (20000528) - - further (scatter gather) buffer length changes - Changes since 3.1.14 (20000503) - - fix aha1542 odd length buffer problem - - make multiple readers on same fd safe - Changes since 3.1.13 (20000324) - - revert change so sg_header interface doesn't send _UNKNOWN - - "discon" and "tq" in /proc/scsi/sg/devices replaced with - "bopens" and "busy"; correct duration output in procfs - - provision for SG_RESET - - lock file descriptor and request lists - Changes since 3.1.12 (20000222) - - make sg_header interface use SCSI_DATA_UNKNOWN - - add SG_DXFER_UNKNOWN define to sg interface - - stop allocating data buffers to non data transfer commands - Changes since 3.1.10 (20000123) - - make device allocation dynamic (get rid of SG_EXTRA_DEVS) - - move to sg0,sg1,sg2 rather than sga,sgb,sgc - - make sg_io_hdr_t safer across architectures - Changes since 2.1.34 (990603) and 2.3.35 (990708) - - add new interface structure: sg_io_hdr_t - - supports larger sense buffer, DMA residual count + direct IO - - add SG_IO ioctl (combines function of write() + read() ) - - remove SG_SET_MERGE_FD, UNDERRUN_FLAG + _GET_ ioctls + logic - - add proc_fs support in /proc/scsi/sg/ directory - - add queuing info into struct sg_scsi_id - - def_reserved_size can be given at driver or module load time - Changes since 2.1.33 (990521) - - implement SG_SET_RESERVED_SIZE and associated memory re-org. - - add SG_NEXT_CMD_LEN to override SCSI command lengths - - add SG_GET_VERSION_NUM to get version expressed as an integer - Changes since 2.1.32 (990501) - - fix race condition in sg_read() and sg_open() - Changes since 2.1.31 (990327) - - add ioctls SG_GET_UNDERRUN_FLAG and _SET_. Change the default - to _not_ flag underruns (affects aic7xxx driver) - - clean up logging of pointers to use %p (for 64 bit architectures) - - rework usage of get_user/copy_to_user family of kernel calls - - "disown" scsi_command blocks before releasing them + Changes since 3.1.19 (20010623) + - add SG_GET_ACCESS_COUNT ioctl + - make open() increment and close() decrement access_count + - only register first 256 devices, reject subsequent devices + Changes since 3.1.18 (20010505) + - fix bug that caused long wait when large buffer requested + - fix leak in error case of sg_new_read() [report: Eric Barton] + - add 'online' column to /proc/scsi/sg/devices + Changes since 3.1.17 (20000921) + - add CAP_SYS_RAWIO capability for sensitive stuff + - compile in dio stuff, procfs 'allow_dio' defaulted off (0) + - make premature close and detach more robust + - lun masked into commands <= SCSI_2 + - poll() and async notification now yield POLL_HUP on detach + - various 3rd party tweaks tracking lk 2.4 internal changes Map of SG verions to the Linux kernels in which they appear: ---------- ---------------------------------- original all kernels < 2.2.6 - 2.1.31 2.2.6 and 2.2.7 - 2.1.32 2.2.8 and 2.2.9 - 2.1.34 2.2.10 to 2.2.13 - 2.1.36 2.2.14 and 2.2.15 + 2.1.38 2.2.16 + 2.1.39 2.2.17 - 2.2.19 3.0.x optional version 3 sg driver for 2.2 series - 3.1.x first appeared in lk 2.3.43 + 3.1.17 2.4.0 ++ Major new features in SG 3.x driver (cf SG 2.x drivers) - SG_IO ioctl() combines function if write() and read() - new interface (sg_io_hdr_t) but still supports old interface - scatter/gather in user space and direct IO supported -Major features in SG 2.x driver (cf original SG driver) - - per file descriptor (fd) write-read sequencing - - command queuing supported - - scatter-gather supported at kernel level allowing potentially - large transfers - - more SCSI status information returned - - asynchronous notification support added (SIGPOLL, SIGIO) - - read() can fetch by given pack_id - - uses kernel memory as appropriate for SCSI adapter being used - - single SG_BIG_BUFF replaced by per file descriptor "reserve - buffer" whose size can be manipulated by ioctls() - The term "indirect IO" refers a method by which data is DMAed into kernel buffers from the hardware and afterwards is transferred into the user space (or vice versa if you are writing). Transfer speeds of up to 20 to 30MBytes/sec have been measured using indirect IO. For faster throughputs "direct IO" which cuts out the double handling of data is required. - Direct IO is supported by the SG 3.x drivers on 2.3 series Linux kernels - (or later) and requires the use of the new interface. + Direct IO is supported by the SG 3.x drivers on 2.4 series Linux kernels + and requires the use of the new interface. Requests for direct IO with the new interface will automatically fall back to indirect IO mode if they cannot be fulfilled. An example of such a case @@ -107,6 +65,9 @@ kernel memory that is suitable for DMA may be constrained by the architecture of the SCSI adapter (e.g. ISA adapters). + ** N.B. To use direct IO 'echo 1 > /proc/scsi/sg/allow_dio' may be + needed. That pseudo file's content is defaulted to 0. ** + Documentation ============= A web site for SG device drivers can be found at: @@ -116,9 +77,10 @@ http://www.torque.net/sg/p/scsi-generic_long.txt Documentation on the changes and additions in 3.x version of the sg driver can be found at: http://www.torque.net/sg/p/scsi-generic_v3.txt - This document can also be found in the kernel source tree, probably at: + A version of this document (potentially out of date) may also be found in + the kernel source tree, probably at: /usr/src/linux/Documentation/scsi-generic.txt . - Utility and test programs are also available at that web site. + Utility and test programs are available at the sg web site. */ /* New interface introduced in the 3.x SG drivers follows */ @@ -262,6 +224,9 @@ /* How to treat EINTR during SG_IO ioctl(), only in SG 3.x series */ #define SG_SET_KEEP_ORPHAN 0x2287 /* 1 -> hold for read(), 0 -> drop (def) */ #define SG_GET_KEEP_ORPHAN 0x2288 + +/* yields scsi midlevel's access_count for this SCSI device */ +#define SG_GET_ACCESS_COUNT 0x2289 #define SG_SCATTER_SZ (8 * 4096) /* PAGE_SIZE not available to user */ |
From: Andy P. <at...@us...> - 2002-04-09 12:57:31
|
Update of /cvsroot/linux-vax/kernel-2.4/fs/adfs In directory usw-pr-cvs1:/tmp/cvs-serv24187/adfs Modified Files: file.c inode.c map.c super.c Log Message: synch 2.4.15 commit 6 Index: file.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/adfs/file.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- file.c 14 Jan 2001 16:38:37 -0000 1.1.1.1 +++ file.c 9 Apr 2002 12:57:25 -0000 1.2 @@ -29,6 +29,7 @@ #include "adfs.h" struct file_operations adfs_file_operations = { + llseek: generic_file_llseek, read: generic_file_read, mmap: generic_file_mmap, fsync: file_fsync, Index: inode.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/adfs/inode.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- inode.c 14 Jan 2001 16:38:36 -0000 1.1.1.1 +++ inode.c 9 Apr 2002 12:57:25 -0000 1.2 @@ -17,6 +17,8 @@ #include <linux/locks.h> #include <linux/mm.h> #include <linux/smp_lock.h> +#include <linux/module.h> + #include "adfs.h" @@ -220,7 +222,7 @@ if (inode->u.adfs_i.stamped) { /* convert 32-bit seconds to 40-bit centi-seconds */ low = (secs & 255) * 100; - high = (secs / 256) * 100 + (low << 8) + 0x336e996a; + high = (secs / 256) * 100 + (low >> 8) + 0x336e996a; inode->u.adfs_i.loadaddr = (high >> 24) | (inode->u.adfs_i.loadaddr & ~0xff); @@ -319,7 +321,11 @@ goto out; if (ia_valid & ATTR_SIZE) - vmtruncate(inode, attr->ia_size); + error = vmtruncate(inode, attr->ia_size); + + if (error) + goto out; + if (ia_valid & ATTR_MTIME) { inode->i_mtime = attr->ia_mtime; adfs_unix2adfs_time(inode, attr->ia_mtime); @@ -369,3 +375,4 @@ adfs_dir_update(sb, &obj); unlock_kernel(); } +MODULE_LICENSE("GPL"); Index: map.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/adfs/map.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- map.c 14 Jan 2001 16:38:39 -0000 1.1.1.1 +++ map.c 9 Apr 2002 12:57:25 -0000 1.2 @@ -20,6 +20,18 @@ */ static rwlock_t adfs_map_lock; +#define GET_FRAG_ID(_map,_start,_idmask) \ + ({ \ + unsigned long _v2, _frag; \ + unsigned int _tmp; \ + _tmp = _start >> 5; \ + _frag = le32_to_cpu(_map[_tmp]); \ + _v2 = le32_to_cpu(_map[_tmp + 1]); \ + _tmp = start & 31; \ + _frag = (_frag >> _tmp) | (_v2 << (32 - _tmp)); \ + _frag & _idmask; \ + }) + /* * return the map bit offset of the fragment frag_id in * the zone dm. @@ -40,25 +52,7 @@ do { unsigned long frag; - /* - * get fragment id - */ - { - unsigned long v2; - unsigned int tmp; - - tmp = start >> 5; - - frag = le32_to_cpu(map[tmp]); - v2 = le32_to_cpu(map[tmp + 1]); - - tmp = start & 31; - - frag = (frag >> tmp) | (v2 << (32 - tmp)); - - frag &= idmask; - } - + frag = GET_FRAG_ID(map, start, idmask); mapptr = start + idlen; /* @@ -117,21 +111,7 @@ /* * get fragment id */ - { - unsigned long v2; - unsigned int tmp; - - tmp = start >> 5; - - frag = le32_to_cpu(map[tmp]); - v2 = le32_to_cpu(map[tmp + 1]); - - tmp = start & 31; - - frag = (frag >> tmp) | (v2 << (32 - tmp)); - - frag &= idmask; - } + frag = GET_FRAG_ID(map, start, idmask); /* * If the freelink is null, then no free fragments @@ -146,22 +126,7 @@ /* * get fragment id */ - { - unsigned long v2; - unsigned int tmp; - - tmp = start >> 5; - - frag = le32_to_cpu(map[tmp]); - v2 = le32_to_cpu(map[tmp + 1]); - - tmp = start & 31; - - frag = (frag >> tmp) | (v2 << (32 - tmp)); - - frag &= idmask; - } - + frag = GET_FRAG_ID(map, start, idmask); mapptr = start + idlen; /* Index: super.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/adfs/super.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- super.c 25 Feb 2001 23:14:48 -0000 1.1.1.2 +++ super.c 9 Apr 2002 12:57:25 -0000 1.2 @@ -39,7 +39,7 @@ va_end(args); printk(KERN_CRIT "ADFS-fs error (device %s)%s%s: %s\n", - kdevname(sb->s_dev), function ? ": " : "", + bdevname(sb->s_dev), function ? ": " : "", function ? function : "", error_buf); } @@ -330,7 +330,7 @@ if (adfs_checkbblk(b_data)) { if (!silent) printk("VFS: Can't find an adfs filesystem on dev " - "%s.\n", kdevname(dev)); + "%s.\n", bdevname(dev)); goto error_free_bh; } @@ -342,7 +342,7 @@ if (adfs_checkdiscrecord(dr)) { if (!silent) printk("VPS: Can't find an adfs filesystem on dev " - "%s.\n", kdevname(dev)); + "%s.\n", bdevname(dev)); goto error_free_bh; } @@ -370,7 +370,7 @@ if (sb->s_blocksize != bh->b_size) { if (!silent) printk(KERN_ERR "VFS: Unsupported blocksize on dev " - "%s.\n", kdevname(dev)); + "%s.\n", bdevname(dev)); goto error_free_bh; } @@ -385,7 +385,7 @@ sb->u.adfs_sb.s_size = adfs_discsize(dr, sb->s_blocksize_bits); sb->u.adfs_sb.s_version = dr->format_version; sb->u.adfs_sb.s_log2sharesize = dr->log2sharesize; - + sb->u.adfs_sb.s_map = adfs_read_map(sb, dr); if (!sb->u.adfs_sb.s_map) goto error_free_bh; |