patch-2.4.0-test2 linux/arch/ia64/kernel/sys_ia64.c
Next file: linux/arch/ia64/kernel/time.c
Previous file: linux/arch/ia64/kernel/smp.c
Back to the patch index
Back to the overall index
- Lines: 217
- Date:
Thu Jun 22 07:09:44 2000
- Orig file:
v2.4.0-test1/linux/arch/ia64/kernel/sys_ia64.c
- Orig date:
Sun Feb 13 19:29:03 2000
diff -u --recursive --new-file v2.4.0-test1/linux/arch/ia64/kernel/sys_ia64.c linux/arch/ia64/kernel/sys_ia64.c
@@ -14,6 +14,9 @@
#include <linux/file.h> /* doh, must come after sched.h... */
#include <linux/smp.h>
#include <linux/smp_lock.h>
+#include <linux/highuid.h>
+
+#include <asm/uaccess.h>
asmlinkage long
ia64_getpriority (int which, int who, long arg2, long arg3, long arg4, long arg5, long arg6,
@@ -94,7 +97,11 @@
static inline unsigned long
do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, unsigned long pgoff)
{
+ long start_low, end_low, starting_region, ending_region;
+ unsigned long loff, hoff;
struct file *file = 0;
+ /* the virtual address space that is mappable in each region: */
+# define OCTANT_SIZE ((PTRS_PER_PGD<<PGDIR_SHIFT)/8)
/*
* A zero mmap always succeeds in Linux, independent of
@@ -103,15 +110,19 @@
if (PAGE_ALIGN(len) == 0)
return addr;
-#ifdef notyet
- /* Don't permit mappings that would cross a region boundary: */
- region_start = IA64_GET_REGION(addr);
- region_end = IA64_GET_REGION(addr + len);
- if (region_start != region_end)
+ /* Don't permit mappings into or across the address hole in a region: */
+ loff = REGION_OFFSET(addr);
+ hoff = loff - (REGION_SIZE - OCTANT_SIZE/2);
+ if ((len | loff | (loff + len)) >= OCTANT_SIZE/2
+ && (len | hoff | (hoff + len)) >= OCTANT_SIZE/2)
return -EINVAL;
- <<x??x>>
-#endif
+ /* Don't permit mappings that would cross a region boundary: */
+
+ starting_region = REGION_NUMBER(addr);
+ ending_region = REGION_NUMBER(addr + len);
+ if (starting_region != ending_region)
+ return -EINVAL;
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
if (!(flags & MAP_ANONYMOUS)) {
@@ -156,6 +167,9 @@
{
struct pt_regs *regs = (struct pt_regs *) &stack;
+ if ((off & ~PAGE_MASK) != 0)
+ return -EINVAL;
+
addr = do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
if (!IS_ERR(addr))
regs->r8 = 0; /* ensure large addresses are not mistaken as failures... */
@@ -196,6 +210,150 @@
return -ENOSYS;
}
+asmlinkage unsigned long
+ia64_create_module (const char *name_user, size_t size, long arg2, long arg3,
+ long arg4, long arg5, long arg6, long arg7, long stack)
+{
+ extern unsigned long sys_create_module (const char *, size_t);
+ struct pt_regs *regs = (struct pt_regs *) &stack;
+ unsigned long addr;
+
+ addr = sys_create_module (name_user, size);
+ if (!IS_ERR(addr))
+ regs->r8 = 0; /* ensure large addresses are not mistaken as failures... */
+ return addr;
+}
+
+#if 1
+/*
+ * This is here for a while to keep compatibillity with the old stat()
+ * call - it will be removed later once everybody migrates to the new
+ * kernel stat structure that matches the glibc one - Jes
+ */
+static __inline__ int
+do_revalidate (struct dentry *dentry)
+{
+ struct inode * inode = dentry->d_inode;
+ if (inode->i_op && inode->i_op->revalidate)
+ return inode->i_op->revalidate(dentry);
+ return 0;
+}
+
+static int
+cp_ia64_old_stat (struct inode *inode, struct ia64_oldstat *statbuf)
+{
+ struct ia64_oldstat tmp;
+ unsigned int blocks, indirect;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.st_dev = kdev_t_to_nr(inode->i_dev);
+ tmp.st_ino = inode->i_ino;
+ tmp.st_mode = inode->i_mode;
+ tmp.st_nlink = inode->i_nlink;
+ SET_STAT_UID(tmp, inode->i_uid);
+ SET_STAT_GID(tmp, inode->i_gid);
+ tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
+ tmp.st_size = inode->i_size;
+ tmp.st_atime = inode->i_atime;
+ tmp.st_mtime = inode->i_mtime;
+ tmp.st_ctime = inode->i_ctime;
+/*
+ * st_blocks and st_blksize are approximated with a simple algorithm if
+ * they aren't supported directly by the filesystem. The minix and msdos
+ * filesystems don't keep track of blocks, so they would either have to
+ * be counted explicitly (by delving into the file itself), or by using
+ * this simple algorithm to get a reasonable (although not 100% accurate)
+ * value.
+ */
+
+/*
+ * Use minix fs values for the number of direct and indirect blocks. The
+ * count is now exact for the minix fs except that it counts zero blocks.
+ * Everything is in units of BLOCK_SIZE until the assignment to
+ * tmp.st_blksize.
+ */
+#define D_B 7
+#define I_B (BLOCK_SIZE / sizeof(unsigned short))
+
+ if (!inode->i_blksize) {
+ blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
+ if (blocks > D_B) {
+ indirect = (blocks - D_B + I_B - 1) / I_B;
+ blocks += indirect;
+ if (indirect > 1) {
+ indirect = (indirect - 1 + I_B - 1) / I_B;
+ blocks += indirect;
+ if (indirect > 1)
+ blocks++;
+ }
+ }
+ tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
+ tmp.st_blksize = BLOCK_SIZE;
+ } else {
+ tmp.st_blocks = inode->i_blocks;
+ tmp.st_blksize = inode->i_blksize;
+ }
+ return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
+}
+
+asmlinkage long
+ia64_oldstat (char *filename, struct ia64_oldstat *statbuf)
+{
+ struct nameidata nd;
+ int error;
+
+ lock_kernel();
+ error = user_path_walk(filename, &nd);
+ if (!error) {
+ error = do_revalidate(nd.dentry);
+ if (!error)
+ error = cp_ia64_old_stat(nd.dentry->d_inode, statbuf);
+ path_release(&nd);
+ }
+ unlock_kernel();
+ return error;
+}
+
+
+asmlinkage long
+ia64_oldlstat (char *filename, struct ia64_oldstat *statbuf) {
+ struct nameidata nd;
+ int error;
+
+ lock_kernel();
+ error = user_path_walk_link(filename, &nd);
+ if (!error) {
+ error = do_revalidate(nd.dentry);
+ if (!error)
+ error = cp_ia64_old_stat(nd.dentry->d_inode, statbuf);
+ path_release(&nd);
+ }
+ unlock_kernel();
+ return error;
+}
+
+asmlinkage long
+ia64_oldfstat (unsigned int fd, struct ia64_oldstat *statbuf)
+{
+ struct file * f;
+ int err = -EBADF;
+
+ lock_kernel();
+ f = fget(fd);
+ if (f) {
+ struct dentry * dentry = f->f_dentry;
+
+ err = do_revalidate(dentry);
+ if (!err)
+ err = cp_ia64_old_stat(dentry->d_inode, statbuf);
+ fput(f);
+ }
+ unlock_kernel();
+ return err;
+}
+
+#endif
+
#ifndef CONFIG_PCI
asmlinkage long
@@ -211,6 +369,5 @@
{
return -ENOSYS;
}
-
#endif /* CONFIG_PCI */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)