diff -urN lfs-ref/arch/alpha/kernel/entry.S lfs/arch/alpha/kernel/entry.S --- lfs-ref/arch/alpha/kernel/entry.S Wed Sep 12 02:39:56 2001 +++ lfs/arch/alpha/kernel/entry.S Wed Sep 12 02:42:14 2001 @@ -8,7 +8,7 @@ #define SIGCHLD 20 -#define NR_SYSCALLS 377 +#define NR_SYSCALLS 378 /* * These offsets must match with alpha_mv in . @@ -1162,3 +1162,4 @@ .quad sys_ni_syscall .quad sys_ni_syscall /* 375 */ .quad sys_pciconfig_iobase + .quad sys_getdents64 diff -urN lfs-ref/arch/alpha/kernel/osf_sys.c lfs/arch/alpha/kernel/osf_sys.c --- lfs-ref/arch/alpha/kernel/osf_sys.c Fri Apr 20 22:31:15 2001 +++ lfs/arch/alpha/kernel/osf_sys.c Wed Sep 12 02:42:14 2001 @@ -110,7 +110,7 @@ int error; }; -static int osf_filldir(void *__buf, const char *name, int namlen, off_t offset, ino_t ino) +static int osf_filldir(void *__buf, const char *name, int namlen, off_t offset, ino_t ino, unsigned int d_type) { struct osf_dirent *dirent; struct osf_dirent_callback *buf = (struct osf_dirent_callback *) __buf; diff -urN lfs-ref/arch/i386/kernel/entry.S lfs/arch/i386/kernel/entry.S --- lfs-ref/arch/i386/kernel/entry.S Wed Sep 12 02:39:56 2001 +++ lfs/arch/i386/kernel/entry.S Wed Sep 12 02:42:14 2001 @@ -572,6 +572,18 @@ .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */ .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */ .long SYMBOL_NAME(sys_vfork) /* 190 */ + .long SYMBOL_NAME(sys_ni_syscall) /* getrlimit */ + .long SYMBOL_NAME(sys_mmap2) /* 192 */ + .long SYMBOL_NAME(sys_truncate64) /* 193 */ + .long SYMBOL_NAME(sys_ftruncate64) /* 194 */ + .long SYMBOL_NAME(sys_stat64) /* 195 */ + .long SYMBOL_NAME(sys_lstat64) /* 196 */ + .long SYMBOL_NAME(sys_fstat64) /* 197 */ + .rept 22 + .long SYMBOL_NAME(sys_ni_syscall) + .endr + .long SYMBOL_NAME(sys_getdents64) /* 220 */ + .long SYMBOL_NAME(sys_fcntl64) /* 221 */ /* * NOTE!! This doesn't have to be exact - we just have @@ -579,6 +591,6 @@ * entries. Don't panic if you notice that this hasn't * been shrunk every time we add a new system call. */ - .rept NR_syscalls-190 + .rept NR_syscalls-221 .long SYMBOL_NAME(sys_ni_syscall) .endr diff -urN lfs-ref/arch/i386/kernel/sys_i386.c lfs/arch/i386/kernel/sys_i386.c --- lfs-ref/arch/i386/kernel/sys_i386.c Mon Jan 17 16:44:33 2000 +++ lfs/arch/i386/kernel/sys_i386.c Wed Sep 12 02:42:14 2001 @@ -41,6 +41,42 @@ return error; } +/* common code for old and new mmaps */ +static inline long do_mmap2( + unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff) +{ + int error = -EBADF; + struct file * file = NULL; + + down(¤t->mm->mmap_sem); + lock_kernel(); + + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + if (!(flags & MAP_ANONYMOUS)) { + file = fget(fd); + if (!file) + goto out; + } + + error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); + + if (file) + fput(file); +out: + unlock_kernel(); + up(¤t->mm->mmap_sem); + return error; +} + +asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff) +{ + return do_mmap2(addr, len, prot, flags, fd, pgoff); +} + /* * Perform the select(nd, in, out, ex, tv) and mmap() system * calls. Linux/i386 didn't use to be able to handle more than @@ -59,30 +95,19 @@ asmlinkage int old_mmap(struct mmap_arg_struct *arg) { - int error = -EFAULT; - struct file * file = NULL; struct mmap_arg_struct a; + int err = -EFAULT; if (copy_from_user(&a, arg, sizeof(a))) - return -EFAULT; + goto out; - down(¤t->mm->mmap_sem); - lock_kernel(); - if (!(a.flags & MAP_ANONYMOUS)) { - error = -EBADF; - file = fget(a.fd); - if (!file) - goto out; - } - a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + err = -EINVAL; + if (a.offset & ~PAGE_MASK) + goto out; - error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset); - if (file) - fput(file); + err = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); out: - unlock_kernel(); - up(¤t->mm->mmap_sem); - return error; + return err; } extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); diff -urN lfs-ref/arch/mips/kernel/sysirix.c lfs/arch/mips/kernel/sysirix.c --- lfs-ref/arch/mips/kernel/sysirix.c Mon Jan 17 16:44:34 2000 +++ lfs/arch/mips/kernel/sysirix.c Wed Sep 12 02:42:14 2001 @@ -1984,7 +1984,7 @@ #define ROUND_UP32(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1)) static int irix_filldir32(void *__buf, const char *name, int namlen, - off_t offset, ino_t ino) + off_t offset, ino_t ino, unsigned int d_type) { struct irix_dirent32 *dirent; struct irix_dirent32_callback *buf = @@ -2097,7 +2097,7 @@ #define ROUND_UP64(x) (((x)+sizeof(u64)-1) & ~(sizeof(u64)-1)) static int irix_filldir64(void * __buf, const char * name, int namlen, - off_t offset, ino_t ino) + off_t offset, ino_t ino, unsigned int d_type) { struct irix_dirent64 *dirent; struct irix_dirent64_callback * buf = diff -urN lfs-ref/arch/ppc/kernel/misc.S lfs/arch/ppc/kernel/misc.S --- lfs-ref/arch/ppc/kernel/misc.S Fri Apr 20 22:31:15 2001 +++ lfs/arch/ppc/kernel/misc.S Wed Sep 12 02:42:14 2001 @@ -958,7 +958,7 @@ .long sys_swapon .long sys_reboot .long old_readdir - .long sys_mmap /* 90 */ + .long old_mmap /* 90 */ .long sys_munmap .long sys_truncate .long sys_ftruncate @@ -1058,18 +1058,20 @@ .long sys_ni_syscall /* streams1 */ .long sys_ni_syscall /* streams2 */ .long sys_vfork - .long sys_ni_syscall /* 190 */ /* MacOnLinux - old */ + .long sys_ni_syscall /* 190 getrlimit */ .long sys_ni_syscall /* 191 */ /* Unused */ - .long sys_ni_syscall /* 192 - reserved - mmap2 */ - .long sys_ni_syscall /* 193 - reserved - truncate64 */ - .long sys_ni_syscall /* 194 - reserved - ftruncate64 */ - .long sys_ni_syscall /* 195 - reserved - stat64 */ - .long sys_ni_syscall /* 196 - reserved - lstat64 */ - .long sys_ni_syscall /* 197 - reserved - fstat64 */ + .long sys_mmap2 /* 192 */ + .long sys_truncate64 /* 193 */ + .long sys_ftruncate64 /* 194 */ + .long sys_stat64 /* 195 */ + .long sys_lstat64 /* 196 */ + .long sys_fstat64 /* 197 */ .long sys_pciconfig_read /* 198 */ .long sys_pciconfig_write /* 199 */ .long sys_pciconfig_iobase /* 200 */ .long sys_ni_syscall /* 201 - reserved - MacOnLinux - new */ - .rept NR_syscalls-201 + .long sys_getdents64 /* 202 */ + .long sys_fcntl64 /* 203 */ + .rept NR_syscalls-203 .long sys_ni_syscall .endr diff -urN lfs-ref/arch/ppc/kernel/syscalls.c lfs/arch/ppc/kernel/syscalls.c --- lfs-ref/arch/ppc/kernel/syscalls.c Mon Dec 11 16:57:46 2000 +++ lfs/arch/ppc/kernel/syscalls.c Wed Sep 12 02:42:14 2001 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -192,25 +193,55 @@ return error; } -asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, - unsigned long prot, unsigned long flags, - unsigned long fd, off_t offset) +/* common code for old and new mmaps */ +static inline long do_mmap2( + unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff) { struct file * file = NULL; int ret = -EBADF; down(¤t->mm->mmap_sem); - lock_kernel(); + if (!(flags & MAP_ANONYMOUS)) { - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) + file = fget(fd); + if (!file) goto out; } - + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - ret = do_mmap(file, addr, len, prot, flags, offset); -out: + ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); + + if (file) + fput(file); + out: unlock_kernel(); up(¤t->mm->mmap_sem); + return ret; + +} + +asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff) +{ + return do_mmap2(addr, len, prot, flags, fd, pgoff); +} + +asmlinkage unsigned long old_mmap(unsigned long addr, size_t len, + unsigned long prot, unsigned long flags, + unsigned long fd, off_t offset) +{ + int ret; + + ret = -EINVAL; + if (offset & ~PAGE_MASK) + goto out; + + ret = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); + + out: return ret; } diff -urN lfs-ref/arch/sparc/kernel/sys_sparc.c lfs/arch/sparc/kernel/sys_sparc.c --- lfs-ref/arch/sparc/kernel/sys_sparc.c Thu May 4 13:00:36 2000 +++ lfs/arch/sparc/kernel/sys_sparc.c Wed Sep 12 02:42:14 2001 @@ -176,9 +176,9 @@ } /* Linux version of mmap */ -asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, +asmlinkage unsigned long do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, - unsigned long off) + unsigned long pgoff) { struct file * file = NULL; unsigned long retval = -EBADF; @@ -211,7 +211,7 @@ goto out_putf; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - retval = do_mmap(file, addr, len, prot, flags, off); + retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); out_putf: if (file) @@ -220,6 +220,22 @@ unlock_kernel(); up(¤t->mm->mmap_sem); return retval; +} + +asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, unsigned long fd, + unsigned long pgoff) +{ + /* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE + we have. */ + return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT - 12)); +} + +asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, unsigned long fd, + unsigned long off) +{ + return do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT); } /* we come to here via sys_nis_syscall so it can setup the regs argument */ diff -urN lfs-ref/arch/sparc/kernel/sys_sunos.c lfs/arch/sparc/kernel/sys_sunos.c --- lfs-ref/arch/sparc/kernel/sys_sunos.c Wed Sep 12 02:39:57 2001 +++ lfs/arch/sparc/kernel/sys_sunos.c Wed Sep 12 02:42:14 2001 @@ -409,7 +409,7 @@ #define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1)) static int sunos_filldir(void * __buf, const char * name, int namlen, - off_t offset, ino_t ino) + off_t offset, ino_t ino, unsigned int d_type) { struct sunos_dirent * dirent; struct sunos_dirent_callback * buf = (struct sunos_dirent_callback *) __buf; @@ -500,7 +500,7 @@ }; static int sunos_filldirentry(void * __buf, const char * name, int namlen, - off_t offset, ino_t ino) + off_t offset, ino_t ino, unsigned int d_type) { struct sunos_direntry * dirent; struct sunos_direntry_callback * buf = (struct sunos_direntry_callback *) __buf; diff -urN lfs-ref/arch/sparc/kernel/systbls.S lfs/arch/sparc/kernel/systbls.S --- lfs-ref/arch/sparc/kernel/systbls.S Fri Apr 20 22:31:15 2001 +++ lfs/arch/sparc/kernel/systbls.S Wed Sep 12 02:42:14 2001 @@ -29,12 +29,12 @@ /*40*/ .long sys_newlstat, sys_dup, sys_pipe, sys_times, sys_lfs_syscall /*45*/ .long sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid /*50*/ .long sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys_ioctl -/*55*/ .long sys_reboot, sys_lfs_syscall, sys_symlink, sys_readlink, sys_execve -/*60*/ .long sys_umask, sys_chroot, sys_newfstat, sys_lfs_syscall, sys_getpagesize +/*55*/ .long sys_reboot, sys_mmap2, sys_symlink, sys_readlink, sys_execve +/*60*/ .long sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize /*65*/ .long sys_msync, sys_vfork, sys_pread, sys_pwrite, sys_nis_syscall /*70*/ .long sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_munmap, sys_mprotect -/*75*/ .long sys_nis_syscall, sys_vhangup, sys_lfs_syscall, sys_nis_syscall, sys_getgroups -/*80*/ .long sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_lfs_syscall +/*75*/ .long sys_nis_syscall, sys_vhangup, sys_truncate64, sys_nis_syscall, sys_getgroups +/*80*/ .long sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_ftruncate64 /*85*/ .long sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall /*90*/ .long sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall /*95*/ .long sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall @@ -44,12 +44,12 @@ /*115*/ .long sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_nis_syscall, sys_getcwd /*120*/ .long sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod /*125*/ .long sys_nis_syscall, sys_setreuid, sys_setregid, sys_rename, sys_truncate -/*130*/ .long sys_ftruncate, sys_flock, sys_lfs_syscall, sys_nis_syscall, sys_nis_syscall -/*135*/ .long sys_nis_syscall, sys_mkdir, sys_rmdir, sys_utimes, sys_lfs_syscall +/*130*/ .long sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall +/*135*/ .long sys_nis_syscall, sys_mkdir, sys_rmdir, sys_utimes, sys_stat64 /*140*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getrlimit /*145*/ .long sys_setrlimit, sys_nis_syscall, sys_prctl, sys_pciconfig_read, sys_pciconfig_write -/*150*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_lfs_syscall -/*155*/ .long sys_lfs_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount +/*150*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64 +/*155*/ .long sys_fcntl64, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount /*160*/ .long sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall /*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall /*170*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents diff -urN lfs-ref/arch/sparc64/kernel/sparc64_ksyms.c lfs/arch/sparc64/kernel/sparc64_ksyms.c --- lfs-ref/arch/sparc64/kernel/sparc64_ksyms.c Wed Sep 12 02:05:39 2001 +++ lfs/arch/sparc64/kernel/sparc64_ksyms.c Wed Sep 12 02:42:14 2001 @@ -84,6 +84,7 @@ extern int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg); extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *); extern void VISenter(void); +extern long sparc32_open(const char * filename, int flags, int mode); extern int io_remap_page_range(unsigned long from, unsigned long offset, unsigned long size, pgprot_t prot, int space); extern void bcopy (const char *, char *, int); @@ -283,6 +284,7 @@ EXPORT_SYMBOL(prom_cpu_nodes); EXPORT_SYMBOL(sys_ioctl); EXPORT_SYMBOL(sys32_ioctl); +EXPORT_SYMBOL(sparc32_open); EXPORT_SYMBOL(move_addr_to_kernel); EXPORT_SYMBOL(move_addr_to_user); #endif diff -urN lfs-ref/arch/sparc64/kernel/sys32.S lfs/arch/sparc64/kernel/sys32.S --- lfs-ref/arch/sparc64/kernel/sys32.S Thu May 4 13:00:36 2000 +++ lfs/arch/sparc64/kernel/sys32.S Wed Sep 12 02:42:14 2001 @@ -60,3 +60,12 @@ sethi %hi(sys_bdflush), %g1 jmpl %g1 + %lo(sys_bdflush), %g0 sra %o1, 0, %o1 + + .align 32 + .globl sys32_mmap2 +sys32_mmap2: + srl %o4, 0, %o4 + sethi %hi(sys_mmap), %g1 + srl %o5, 0, %o5 + jmpl %g1 + %lo(sys_mmap), %g0 + sllx %o5, 12, %o5 diff -urN lfs-ref/arch/sparc64/kernel/sys_sparc32.c lfs/arch/sparc64/kernel/sys_sparc32.c --- lfs-ref/arch/sparc64/kernel/sys_sparc32.c Wed Sep 12 02:05:39 2001 +++ lfs/arch/sparc64/kernel/sys_sparc32.c Wed Sep 12 02:42:14 2001 @@ -600,15 +600,27 @@ old_fs = get_fs(); set_fs (KERNEL_DS); ret = sys_fcntl(fd, cmd, (unsigned long)&f); set_fs (old_fs); + if (ret) return ret; + if (f.l_start >= 0x7fffffffUL || + f.l_len >= 0x7fffffffUL || + f.l_start + f.l_len >= 0x7fffffffUL) + return -EOVERFLOW; if(put_flock(&f, (struct flock32 *)arg)) return -EFAULT; - return ret; + return 0; } default: return sys_fcntl(fd, cmd, (unsigned long)arg); } } +asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + if (cmd >= F_GETLK64 && cmd <= F_SETLKW64) + return sys_fcntl(fd, cmd + F_GETLK - F_GETLK64, arg); + return sys32_fcntl(fd, cmd, arg); +} + struct dqblk32 { __u32 dqb_bhardlimit; __u32 dqb_bsoftlimit; @@ -720,6 +732,25 @@ return ret; } +extern asmlinkage long sys_truncate(const char * path, unsigned long length); +extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length); + +asmlinkage int sys32_truncate64(const char * path, unsigned long high, unsigned long low) +{ + if ((int)high < 0) + return -EINVAL; + else + return sys_truncate(path, (high << 32) | low); +} + +asmlinkage int sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low) +{ + if ((int)high < 0) + return -EINVAL; + else + return sys_ftruncate(fd, (high << 32) | low); +} + extern asmlinkage int sys_utime(char * filename, struct utimbuf * times); struct utimbuf32 { @@ -917,7 +948,7 @@ }; static int fillonedir(void * __buf, const char * name, int namlen, - off_t offset, ino_t ino) + off_t offset, ino_t ino, unsigned int d_type) { struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf; struct old_linux_dirent32 * dirent; @@ -982,7 +1013,8 @@ int error; }; -static int filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino) +static int filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino, + unsigned int d_type) { struct linux_dirent32 * dirent; struct getdents_callback32 * buf = (struct getdents_callback32 *) __buf; @@ -4049,6 +4081,39 @@ return -EFAULT; return ret; +} + +/* This is just a version for 32-bit applications which does + * not force O_LARGEFILE on. + */ + +asmlinkage long sparc32_open(const char * filename, int flags, int mode) +{ + char * tmp; + int fd, error; + + tmp = getname(filename); + fd = PTR_ERR(tmp); + if (!IS_ERR(tmp)) { + lock_kernel(); + fd = get_unused_fd(); + if (fd >= 0) { + struct file * f = filp_open(tmp, flags, mode); + error = PTR_ERR(f); + if (IS_ERR(f)) + goto out_error; + fd_install(fd, f); + } +out: + unlock_kernel(); + putname(tmp); + } + return fd; + +out_error: + put_unused_fd(fd); + fd = error; + goto out; } /* Handle adjtimex compatability. */ diff -urN lfs-ref/arch/sparc64/kernel/sys_sunos32.c lfs/arch/sparc64/kernel/sys_sunos32.c --- lfs-ref/arch/sparc64/kernel/sys_sunos32.c Fri Apr 20 22:31:15 2001 +++ lfs/arch/sparc64/kernel/sys_sunos32.c Wed Sep 12 02:42:14 2001 @@ -366,7 +366,7 @@ #define ROUND_UP(x) (((x)+sizeof(s32)-1) & ~(sizeof(s32)-1)) static int sunos_filldir(void * __buf, const char * name, int namlen, - off_t offset, ino_t ino) + off_t offset, ino_t ino, unsigned int d_type) { struct sunos_dirent * dirent; struct sunos_dirent_callback * buf = (struct sunos_dirent_callback *) __buf; @@ -458,7 +458,7 @@ }; static int sunos_filldirentry(void * __buf, const char * name, int namlen, - off_t offset, ino_t ino) + off_t offset, ino_t ino, unsigned int d_type) { struct sunos_direntry * dirent; struct sunos_direntry_callback * buf = (struct sunos_direntry_callback *) __buf; @@ -1297,13 +1297,15 @@ return rval; } +extern asmlinkage long sparc32_open(const char * filename, int flags, int mode); + asmlinkage int sunos_open(u32 filename, int flags, int mode) { int ret; lock_kernel(); current->personality |= PER_BSD; - ret = sys_open ((char *)A(filename), flags, mode); + ret = sparc32_open ((char *)A(filename), flags, mode); unlock_kernel(); return ret; } diff -urN lfs-ref/arch/sparc64/kernel/systbls.S lfs/arch/sparc64/kernel/systbls.S --- lfs-ref/arch/sparc64/kernel/systbls.S Fri Apr 20 22:31:15 2001 +++ lfs/arch/sparc64/kernel/systbls.S Wed Sep 12 02:42:14 2001 @@ -20,7 +20,7 @@ .globl sys_call_table32 sys_call_table32: /*0*/ .word sys_nis_syscall, sparc_exit, sys_fork, sys_read, sys_write -/*5*/ .word sys_open, sys_close, sys32_wait4, sys_creat, sys_link +/*5*/ .word sparc32_open, sys_close, sys32_wait4, sys_creat, sys_link /*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys32_chown16, sys32_mknod /*15*/ .word sys32_chmod, sys32_lchown16, sparc_brk, sys_perfctr, sys32_lseek /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid @@ -30,12 +30,12 @@ /*40*/ .word sys32_newlstat, sys_dup, sys_pipe, sys32_times, sys_lfs_syscall .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid /*50*/ .word sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys32_ioctl - .word sys_reboot, sys_lfs_syscall, sys_symlink, sys_readlink, sys32_execve -/*60*/ .word sys_umask, sys_chroot, sys32_newfstat, sys_lfs_syscall, sys_getpagesize + .word sys_reboot, sys32_mmap2, sys_symlink, sys_readlink, sys32_execve +/*60*/ .word sys_umask, sys_chroot, sys32_newfstat, sys_fstat64, sys_getpagesize .word sys_msync, sys_vfork, sys32_pread, sys32_pwrite, sys_nis_syscall /*70*/ .word sys_nis_syscall, sys32_mmap, sys_nis_syscall, sys_munmap, sys_mprotect - .word sys_nis_syscall, sys_vhangup, sys_lfs_syscall, sys_nis_syscall, sys32_getgroups -/*80*/ .word sys32_setgroups, sys_getpgrp, sys_nis_syscall, sys32_setitimer, sys_lfs_syscall + .word sys_nis_syscall, sys_vhangup, sys32_truncate64, sys_nis_syscall, sys32_getgroups +/*80*/ .word sys32_setgroups, sys_getpgrp, sys_nis_syscall, sys32_setitimer, sys32_ftruncate64 .word sys_swapon, sys32_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall /*90*/ .word sys_dup2, sys_nis_syscall, sys32_fcntl, sys32_select, sys_nis_syscall .word sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall @@ -45,12 +45,12 @@ .word sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd /*120*/ .word sys32_readv, sys32_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod .word sys_nis_syscall, sys32_setreuid, sys32_setregid, sys_rename, sys_truncate -/*130*/ .word sys_ftruncate, sys_flock, sys_lfs_syscall, sys_nis_syscall, sys_nis_syscall - .word sys_nis_syscall, sys_mkdir, sys_rmdir, sys32_utimes, sys_lfs_syscall +/*130*/ .word sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall + .word sys_nis_syscall, sys_mkdir, sys_rmdir, sys32_utimes, sys_stat64 /*140*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getrlimit .word sys32_setrlimit, sys_nis_syscall, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write -/*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_lfs_syscall - .word sys_lfs_syscall, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount +/*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64 + .word sys32_fcntl64, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount /*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_nis_syscall /*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents @@ -108,7 +108,7 @@ .word sys_socketpair, sys_mkdir, sys_rmdir, sys_utimes, sys_nis_syscall /*140*/ .word sys_nis_syscall, sys_getpeername, sys_nis_syscall, sys_nis_syscall, sys_getrlimit .word sys_setrlimit, sys_nis_syscall, sys_prctl, sys_pciconfig_read, sys_pciconfig_write -/*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall +/*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64 .word sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount /*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_utrap_install .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall diff -urN lfs-ref/arch/sparc64/solaris/fs.c lfs/arch/sparc64/solaris/fs.c --- lfs-ref/arch/sparc64/solaris/fs.c Mon Jan 17 16:44:36 2000 +++ lfs/arch/sparc64/solaris/fs.c Wed Sep 12 02:42:14 2001 @@ -572,20 +572,20 @@ return error; } +extern asmlinkage long sparc32_open(const char * filename, int flags, int mode); + asmlinkage int solaris_open(u32 filename, int flags, u32 mode) { - int (*sys_open)(const char *,int,int) = - (int (*)(const char *,int,int))SYS(open); int fl = flags & 0xf; -/* if (flags & 0x2000) - allow LFS */ + if (flags & 0x2000) fl |= O_LARGEFILE; if (flags & 0x8050) fl |= O_SYNC; if (flags & 0x80) fl |= O_NONBLOCK; if (flags & 0x100) fl |= O_CREAT; if (flags & 0x200) fl |= O_TRUNC; if (flags & 0x400) fl |= O_EXCL; if (flags & 0x800) fl |= O_NOCTTY; - return sys_open((const char *)A(filename), fl, mode); + return sparc32_open((const char *)A(filename), fl, mode); } #define SOL_F_SETLK 6 diff -urN lfs-ref/drivers/block/loop.c lfs/drivers/block/loop.c --- lfs-ref/drivers/block/loop.c Wed Sep 12 02:39:57 2001 +++ lfs/drivers/block/loop.c Wed Sep 12 02:42:14 2001 @@ -143,12 +143,12 @@ int size; if (S_ISREG(lo->lo_dentry->d_inode->i_mode)) - size = (lo->lo_dentry->d_inode->i_size - lo->lo_offset) / BLOCK_SIZE; + size = (lo->lo_dentry->d_inode->i_size - lo->lo_offset) >> BLOCK_SIZE_BITS; else { kdev_t lodev = lo->lo_device; if (blk_size[MAJOR(lodev)]) size = blk_size[MAJOR(lodev)][MINOR(lodev)] - - lo->lo_offset / BLOCK_SIZE; + (lo->lo_offset >> BLOCK_SIZE_BITS); else size = MAX_DISK_SIZE; } diff -urN lfs-ref/drivers/usb/inode.c lfs/drivers/usb/inode.c --- lfs-ref/drivers/usb/inode.c Mon Dec 11 16:57:58 2000 +++ lfs/drivers/usb/inode.c Wed Sep 12 02:42:14 2001 @@ -302,14 +302,14 @@ i = filp->f_pos; switch (i) { case 0: - if (filldir(dirent, ".", 1, i, IROOT) < 0) + if (filldir(dirent, ".", 1, i, IROOT, DT_DIR) < 0) return 0; filp->f_pos++; i++; /* fall through */ case 1: - if (filldir(dirent, "..", 2, i, IROOT) < 0) + if (filldir(dirent, "..", 2, i, IROOT, DT_DIR) < 0) return 0; filp->f_pos++; i++; @@ -319,7 +319,7 @@ while (i >= 2 && i < 2+NRSPECIAL) { spec = &special[filp->f_pos-2]; - if (filldir(dirent, spec->name, strlen(spec->name), i, ISPECIAL | (filp->f_pos-2+IROOT)) < 0) + if (filldir(dirent, spec->name, strlen(spec->name), i, ISPECIAL | (filp->f_pos-2+IROOT), DT_UNKNOWN) < 0) return 0; filp->f_pos++; i++; @@ -335,7 +335,7 @@ } bus = list_entry(list, struct usb_bus, bus_list); sprintf(numbuf, "%03d", bus->busnum); - if (filldir(dirent, numbuf, 3, filp->f_pos, IBUS | ((bus->busnum & 0xff) << 8)) < 0) + if (filldir(dirent, numbuf, 3, filp->f_pos, IBUS | ((bus->busnum & 0xff) << 8), DT_UNKNOWN) < 0) break; filp->f_pos++; } @@ -355,7 +355,7 @@ if (pos > 0) pos--; else { - if (filldir(dirent, numbuf, 3, filp->f_pos, ino | (dev->devnum & 0xff)) < 0) + if (filldir(dirent, numbuf, 3, filp->f_pos, ino | (dev->devnum & 0xff), DT_UNKNOWN) < 0) return -1; filp->f_pos++; } @@ -380,13 +380,13 @@ return -EINVAL; switch ((unsigned int)filp->f_pos) { case 0: - if (filldir(dirent, ".", 1, filp->f_pos, ino) < 0) + if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) < 0) return 0; filp->f_pos++; /* fall through */ case 1: - if (filldir(dirent, "..", 2, filp->f_pos, IROOT) < 0) + if (filldir(dirent, "..", 2, filp->f_pos, IROOT, DT_DIR) < 0) return 0; filp->f_pos++; /* fall through */ diff -urN lfs-ref/fs/adfs/dir.c lfs/fs/adfs/dir.c --- lfs-ref/fs/adfs/dir.c Mon Dec 11 16:58:00 2000 +++ lfs/fs/adfs/dir.c Wed Sep 12 02:42:14 2001 @@ -40,12 +40,12 @@ switch ((unsigned long)filp->f_pos) { case 0: - if (filldir(dirent, ".", 1, 0, inode->i_ino) < 0) + if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0) goto free_out; filp->f_pos += 1; case 1: - if (filldir(dirent, "..", 2, 1, dir.parent_id) < 0) + if (filldir(dirent, "..", 2, 1, dir.parent_id, DT_DIR) < 0) goto free_out; filp->f_pos += 1; @@ -60,7 +60,7 @@ goto unlock_out; while (ops->getnext(&dir, &obj) == 0) { if (filldir(dirent, obj.name, obj.name_len, - filp->f_pos, obj.file_id) < 0) + filp->f_pos, obj.file_id, DT_UNKNOWN) < 0) goto unlock_out; filp->f_pos += 1; } diff -urN lfs-ref/fs/affs/dir.c lfs/fs/affs/dir.c --- lfs-ref/fs/affs/dir.c Mon Jan 17 16:44:41 2000 +++ lfs/fs/affs/dir.c Wed Sep 12 02:42:14 2001 @@ -98,14 +98,14 @@ if (filp->f_pos == 0) { filp->private_data = (void *)0; - if (filldir(dirent,".",1,filp->f_pos,inode->i_ino) < 0) { + if (filldir(dirent,".",1,filp->f_pos,inode->i_ino, DT_DIR) < 0) { return 0; } ++filp->f_pos; stored++; } if (filp->f_pos == 1) { - if (filldir(dirent,"..",2,filp->f_pos,affs_parent_ino(inode)) < 0) { + if (filldir(dirent,"..",2,filp->f_pos,affs_parent_ino(inode), DT_DIR) < 0) { return stored; } filp->f_pos = 2; @@ -161,7 +161,7 @@ pr_debug("AFFS: readdir(): filldir(\"%.*s\",ino=%lu), i=%d\n", namelen,name,ino,i); filp->private_data = (void *)ino; - if (filldir(dirent,name,namelen,filp->f_pos,ino) < 0) + if (filldir(dirent,name,namelen,filp->f_pos,ino, DT_UNKNOWN) < 0) goto readdir_done; filp->private_data = (void *)i; affs_brelse(fh_bh); diff -urN lfs-ref/fs/affs/file.c lfs/fs/affs/file.c --- lfs-ref/fs/affs/file.c Tue Sep 5 02:28:47 2000 +++ lfs/fs/affs/file.c Wed Sep 12 02:42:14 2001 @@ -582,17 +582,17 @@ affs_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos) { struct inode *inode = filp->f_dentry->d_inode; - off_t pos; + loff_t pos; ssize_t written; ssize_t c; - ssize_t blocksize; + ssize_t blocksize, blockshift; struct buffer_head *bh; char *p; if (!count) return 0; - pr_debug("AFFS: file_write(ino=%lu,pos=%lu,count=%d)\n",inode->i_ino, - (unsigned long)*ppos,count); + pr_debug("AFFS: file_write(ino=%lu,pos=%Lu,count=%d)\n",inode->i_ino, + *ppos,count); if (!inode) { affs_error(inode->i_sb,"file_write","Inode = NULL"); @@ -611,16 +611,22 @@ else pos = *ppos; written = 0; - blocksize = AFFS_I2BSIZE(inode); + blocksize = AFFS_I2BSIZE(inode); + blockshift = AFFS_I2BITS(inode); + + if (pos >= 0x7fffffff) /* Max size: 2G-1 */ + return -EFBIG; + if ((pos + count) > 0x7fffffff) + count = 0x7fffffff - pos; while (written < count) { - bh = affs_getblock(inode,pos / blocksize); + bh = affs_getblock(inode, pos >> blockshift); if (!bh) { if (!written) written = -ENOSPC; break; } - c = blocksize - (pos % blocksize); + c = blocksize - (pos & (blocksize -1)); if (c > count - written) c = count - written; if (c != blocksize && !buffer_uptodate(bh)) { @@ -633,7 +639,7 @@ break; } } - p = (pos % blocksize) + bh->b_data; + p = (pos & (blocksize -1)) + bh->b_data; c -= copy_from_user(p,buf,c); if (!c) { affs_brelse(bh); @@ -664,7 +670,7 @@ off_t pos; ssize_t written; ssize_t c; - ssize_t blocksize; + ssize_t blocksize, blockshift; struct buffer_head *bh; char *p; @@ -692,15 +698,16 @@ bh = NULL; blocksize = AFFS_I2BSIZE(inode) - 24; + blockshift = AFFS_I2BITS(inode); written = 0; while (written < count) { - bh = affs_getblock(inode,pos / blocksize); + bh = affs_getblock(inode,pos >> blockshift); if (!bh) { if (!written) written = -ENOSPC; break; } - c = blocksize - (pos % blocksize); + c = blocksize - (pos & (blocksize -1)); if (c > count - written) c = count - written; if (c != blocksize && !buffer_uptodate(bh)) { @@ -713,7 +720,7 @@ break; } } - p = (pos % blocksize) + bh->b_data + 24; + p = (pos & (blocksize -1)) + bh->b_data + 24; c -= copy_from_user(p,buf,c); if (!c) { affs_brelse(bh); @@ -782,10 +789,10 @@ int rem; int ext; - pr_debug("AFFS: truncate(inode=%ld,size=%lu)\n",inode->i_ino,inode->i_size); + pr_debug("AFFS: truncate(inode=%ld,size=%Lu)\n",inode->i_ino,inode->i_size); net_blocksize = blocksize - ((inode->i_sb->u.affs_sb.s_flags & SF_OFS) ? 24 : 0); - first = (inode->i_size + net_blocksize - 1) / net_blocksize; + first = (u_long)(inode->i_size + net_blocksize - 1) / net_blocksize; if (inode->u.affs_i.i_lastblock < first - 1) { /* There has to be at least one new block to be allocated */ if (!inode->u.affs_i.i_ec && alloc_ext_cache(inode)) { @@ -795,9 +802,9 @@ bh = affs_getblock(inode,first - 1); if (!bh) { affs_warning(inode->i_sb,"truncate","Cannot extend file"); - inode->i_size = net_blocksize * (inode->u.affs_i.i_lastblock + 1); + inode->i_size = (inode->u.affs_i.i_lastblock + 1) * net_blocksize; } else if (inode->i_sb->u.affs_sb.s_flags & SF_OFS) { - rem = inode->i_size % net_blocksize; + rem = ((u_long)inode->i_size) & (net_blocksize -1); DATA_FRONT(bh)->data_size = cpu_to_be32(rem ? rem : net_blocksize); affs_fix_checksum(blocksize,bh->b_data,5); mark_buffer_dirty(bh,0); @@ -864,7 +871,7 @@ affs_free_block(inode->i_sb,ekey); ekey = key; } - block = ((inode->i_size + net_blocksize - 1) / net_blocksize) - 1; + block = (((u_long)inode->i_size + net_blocksize - 1) / net_blocksize) - 1; inode->u.affs_i.i_lastblock = block; /* If the file is not truncated to a block boundary, @@ -872,7 +879,7 @@ * so it cannot become accessible again. */ - rem = inode->i_size % net_blocksize; + rem = inode->i_size & (net_blocksize -1); if (rem) { if ((inode->i_sb->u.affs_sb.s_flags & SF_OFS)) rem += 24; diff -urN lfs-ref/fs/affs/inode.c lfs/fs/affs/inode.c --- lfs-ref/fs/affs/inode.c Sun Apr 2 21:07:49 2000 +++ lfs/fs/affs/inode.c Wed Sep 12 02:42:14 2001 @@ -146,7 +146,7 @@ block = AFFS_I2BSIZE(inode) - 24; else block = AFFS_I2BSIZE(inode); - inode->u.affs_i.i_lastblock = ((inode->i_size + block - 1) / block) - 1; + inode->u.affs_i.i_lastblock = (((u_long)inode->i_size + block - 1) / block) - 1; break; case ST_SOFTLINK: inode->i_mode |= S_IFLNK; diff -urN lfs-ref/fs/autofs/dir.c lfs/fs/autofs/dir.c --- lfs-ref/fs/autofs/dir.c Mon Jan 17 16:44:41 2000 +++ lfs/fs/autofs/dir.c Wed Sep 12 02:42:14 2001 @@ -20,12 +20,12 @@ switch((unsigned long) filp->f_pos) { case 0: - if (filldir(dirent, ".", 1, 0, inode->i_ino) < 0) + if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0) return 0; filp->f_pos++; /* fall through */ case 1: - if (filldir(dirent, "..", 2, 1, AUTOFS_ROOT_INO) < 0) + if (filldir(dirent, "..", 2, 1, AUTOFS_ROOT_INO, DT_DIR) < 0) return 0; filp->f_pos++; /* fall through */ diff -urN lfs-ref/fs/autofs/root.c lfs/fs/autofs/root.c --- lfs-ref/fs/autofs/root.c Mon Jan 17 16:44:41 2000 +++ lfs/fs/autofs/root.c Wed Sep 12 02:42:14 2001 @@ -79,19 +79,19 @@ switch(nr) { case 0: - if (filldir(dirent, ".", 1, nr, inode->i_ino) < 0) + if (filldir(dirent, ".", 1, nr, inode->i_ino, DT_DIR) < 0) return 0; filp->f_pos = ++nr; /* fall through */ case 1: - if (filldir(dirent, "..", 2, nr, inode->i_ino) < 0) + if (filldir(dirent, "..", 2, nr, inode->i_ino, DT_DIR) < 0) return 0; filp->f_pos = ++nr; /* fall through */ default: while ( onr = nr, ent = autofs_hash_enum(dirhash,&nr,ent) ) { if ( !ent->dentry || ent->dentry->d_mounts != ent->dentry ) { - if (filldir(dirent,ent->name,ent->len,onr,ent->ino) < 0) + if (filldir(dirent,ent->name,ent->len,onr,ent->ino, DT_UNKNOWN) < 0) return 0; filp->f_pos = nr; } diff -urN lfs-ref/fs/binfmt_aout.c lfs/fs/binfmt_aout.c --- lfs-ref/fs/binfmt_aout.c Wed Sep 12 02:05:57 2001 +++ lfs/fs/binfmt_aout.c Wed Sep 12 02:42:14 2001 @@ -369,7 +369,11 @@ file = fget(fd); if (!file->f_op || !file->f_op->mmap || +#if 0 fd_offset & (bprm->dentry->d_inode->i_sb->s_blocksize-1)) { +#else /* LFS enforces PAGE_SIZE file offset granularity in mmap */ + fd_offset & ~PAGE_MASK) { +#endif if (warnings++<10) printk(KERN_NOTICE "fd_offset is not blocksize aligned. Loading %s in anonymous memory.\n", @@ -467,7 +471,11 @@ start_addr = ex.a_entry & 0xfffff000; +#if 0 if (N_TXTOFF(ex) & (inode->i_sb->s_blocksize-1)) { +#else /* LFS enforces PAGE_SIZE file offset granularity in mmap */ + if (N_TXTOFF(ex) & ~PAGE_MASK) { +#endif if (warnings++<10) printk(KERN_NOTICE "N_TXTOFF is not blocksize aligned. Loading library %s in anonymous memory.\n", diff -urN lfs-ref/fs/buffer.c lfs/fs/buffer.c --- lfs-ref/fs/buffer.c Wed Sep 12 02:39:58 2001 +++ lfs/fs/buffer.c Wed Sep 12 02:42:15 2001 @@ -1219,7 +1219,7 @@ #endif } if (test_and_clear_bit(PG_swap_unlock_after, &page->flags)) - swap_after_unlock_page(page->offset); + swap_after_unlock_page(pgoff2ulong(page->index)); if (test_and_clear_bit(PG_free_after, &page->flags)) __free_page(page); } @@ -1682,15 +1682,46 @@ set_bit(PG_locked, &page->flags); set_bit(PG_free_after, &page->flags); + /* Blocks within a page */ i = PAGE_SIZE >> inode->i_sb->s_blocksize_bits; - block = page->offset >> inode->i_sb->s_blocksize_bits; - p = nr; - do { - *p = inode->i_op->bmap(inode, block); - i--; - block++; - p++; - } while (i > 0); + + block = pgoff2ulong(page->index); + /* Scaled already by PAGE_SHIFT, which said shift should + be same or larger, than that of any filesystem in + this system -- that is, at i386 with 4k pages one + can't use 8k (primitive) blocks at the filesystems... */ + + if (i > 0) { + /* Filesystem blocksize is same, or smaller than CPU + page size, we can easily process this.. */ + + if (i > 1) + block *= i; + /* Scale by FS blocks per page, presuming FS-blocks are smaller + than the processor page... */ + + p = nr; + do { + *p = inode->i_op->bmap(inode, block); + i--; + block++; + p++; + } while (i > 0); + } else { + /* Filesystem blocksize is larger than CPU page size, + but if the underlying storage system block size is + smaller than CPU page size, all is well, else we + are in deep trouble -- for direct paging in at least.. */ + /* Nobody needs such monsterous fs block sizes ? + Well, it is the only way to get files in terabyte + range.. Nobody needs them ? You are for a surprise.. + However EXT2 (at least) needs access to internal + blocks and there it needs allocations of 8k/16k (or + whatever the block size is) for internal uses.. + Fixing this function alone isn't enough, although + perhaps fairly trivial.. */ + /* FIXME: WRITE THE CODE HERE !!! */ + } /* IO start */ brw_page(READ, page, inode->i_dev, nr, inode->i_sb->s_blocksize, 1); diff -urN lfs-ref/fs/coda/dir.c lfs/fs/coda/dir.c --- lfs-ref/fs/coda/dir.c Tue Sep 5 02:28:47 2000 +++ lfs/fs/coda/dir.c Wed Sep 12 02:42:15 2001 @@ -749,7 +749,7 @@ char *name = vdirent->d_name; errfill = filldir(getdent, name, namlen, - offs, ino); + offs, ino, DT_UNKNOWN); CDEBUG(D_FILE, "entry %d: ino %ld, namlen %d, reclen %d, type %d, pos %d, string_offs %d, name %*s, offset %d, result: %d, errfill: %d.\n", i,vdirent->d_fileno, vdirent->d_namlen, vdirent->d_reclen, vdirent->d_type, pos, string_offset, vdirent->d_namlen, vdirent->d_name, (u_int) offs, result, errfill); /* errfill means no space for filling in this round */ if ( errfill < 0 ) { diff -urN lfs-ref/fs/coda/file.c lfs/fs/coda/file.c --- lfs-ref/fs/coda/file.c Fri Apr 20 22:31:20 2001 +++ lfs/fs/coda/file.c Wed Sep 12 02:42:15 2001 @@ -99,7 +99,7 @@ &cont_file, &cont_dentry); CDEBUG(D_INODE, "coda ino: %ld, cached ino %ld, page offset: %lx\n", - coda_inode->i_ino, cii->c_ovp->i_ino, page->offset); + coda_inode->i_ino, cii->c_ovp->i_ino, pgoff2ulong(page->index)); generic_readpage(&cont_file, page); EXIT; diff -urN lfs-ref/fs/devpts/root.c lfs/fs/devpts/root.c --- lfs-ref/fs/devpts/root.c Mon Jan 17 16:44:41 2000 +++ lfs/fs/devpts/root.c Wed Sep 12 02:42:15 2001 @@ -86,12 +86,12 @@ switch(nr) { case 0: - if (filldir(dirent, ".", 1, nr, inode->i_ino) < 0) + if (filldir(dirent, ".", 1, nr, inode->i_ino, DT_DIR) < 0) return 0; filp->f_pos = ++nr; /* fall through */ case 1: - if (filldir(dirent, "..", 2, nr, inode->i_ino) < 0) + if (filldir(dirent, "..", 2, nr, inode->i_ino, DT_DIR) < 0) return 0; filp->f_pos = ++nr; /* fall through */ @@ -100,7 +100,7 @@ int ptynr = nr - 2; if ( sbi->inodes[ptynr] ) { genptsname(numbuf, ptynr); - if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr) < 0 ) + if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr, DT_CHR) < 0 ) return 0; } filp->f_pos = ++nr; diff -urN lfs-ref/fs/dquot.c lfs/fs/dquot.c --- lfs-ref/fs/dquot.c Wed Sep 12 02:05:57 2001 +++ lfs/fs/dquot.c Wed Sep 12 02:42:15 2001 @@ -1529,7 +1529,7 @@ if (!S_ISREG(inode->i_mode)) goto out_f; error = -EINVAL; - if (inode->i_size == 0 || (inode->i_size % sizeof(struct dqblk)) != 0) + if (inode->i_size == 0 || ((off_t)inode->i_size % sizeof(struct dqblk)) != 0) goto out_f; dquot_drop(inode); /* We don't want quota on quota files */ diff -urN lfs-ref/fs/efs/dir.c lfs/fs/efs/dir.c --- lfs-ref/fs/efs/dir.c Mon Jan 17 16:44:41 2000 +++ lfs/fs/efs/dir.c Wed Sep 12 02:42:15 2001 @@ -107,7 +107,7 @@ filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot; /* copy filename and data in dirslot */ - filldir(dirent, nameptr, namelen, filp->f_pos, inodenum); + filldir(dirent, nameptr, namelen, filp->f_pos, inodenum, DT_UNKNOWN); /* sanity check */ if (nameptr - (char *) dirblock + namelen > EFS_DIRBSIZE) { diff -urN lfs-ref/fs/ext2/dir.c lfs/fs/ext2/dir.c --- lfs-ref/fs/ext2/dir.c Thu May 4 13:00:39 2000 +++ lfs/fs/ext2/dir.c Wed Sep 12 02:42:15 2001 @@ -32,6 +32,10 @@ return -EISDIR; } +static unsigned char ext2_filetype_table[] = { + DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK +}; + static int ext2_readdir(struct file *, void *, filldir_t); static struct file_operations ext2_dir_operations = { @@ -201,10 +205,14 @@ * the descriptor. */ unsigned long version = filp->f_version; + unsigned char d_type = DT_UNKNOWN; + if (EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_FILETYPE) + && de->file_type < EXT2_FT_MAX) + d_type = ext2_filetype_table[de->file_type]; error = filldir(dirent, de->name, de->name_len, - filp->f_pos, le32_to_cpu(de->inode)); + filp->f_pos, le32_to_cpu(de->inode), d_type); if (error) break; if (version != filp->f_version) diff -urN lfs-ref/fs/ext2/file.c lfs/fs/ext2/file.c --- lfs-ref/fs/ext2/file.c Wed Sep 12 02:39:57 2001 +++ lfs/fs/ext2/file.c Wed Sep 12 02:42:15 2001 @@ -39,10 +39,6 @@ static long long ext2_file_lseek(struct file *, long long, int); static ssize_t ext2_file_write (struct file *, const char *, size_t, loff_t *); static int ext2_release_file (struct inode *, struct file *); -#if BITS_PER_LONG < 64 -static int ext2_open_file (struct inode *, struct file *); - -#else #define EXT2_MAX_SIZE(bits) \ (((EXT2_NDIR_BLOCKS + (1LL << (bits - 2)) + \ @@ -55,8 +51,6 @@ EXT2_MAX_SIZE(10), EXT2_MAX_SIZE(11), EXT2_MAX_SIZE(12), EXT2_MAX_SIZE(13) }; -#endif - /* * We have mostly NULL's here: the current defaults are ok for * the ext2 filesystem. @@ -69,11 +63,7 @@ NULL, /* poll - default */ ext2_ioctl, /* ioctl */ generic_file_mmap, /* mmap */ -#if BITS_PER_LONG == 64 NULL, /* no special open is needed */ -#else - ext2_open_file, -#endif NULL, /* flush */ ext2_release_file, /* release */ ext2_sync_file, /* fsync */ @@ -120,14 +110,9 @@ case 1: offset += file->f_pos; } -#if BITS_PER_LONG < 64 - if (offset >> 31) - return -EINVAL; -#else if (offset < 0 || offset > ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(inode->i_sb)]) return -EINVAL; -#endif if (offset != file->f_pos) { file->f_pos = offset; file->f_reada = 0; @@ -155,7 +140,7 @@ size_t count, loff_t *ppos) { struct inode * inode = filp->f_dentry->d_inode; - off_t pos; + loff_t pos; long block; int offset; size_t written, c; @@ -202,24 +187,17 @@ /* Check for overflow.. */ -#if BITS_PER_LONG < 64 - /* If the fd's pos is already greater than or equal to the file - * descriptor's offset maximum, then we need to return EFBIG for - * any non-zero count (and we already tested for zero above). */ - if (((unsigned long) pos) >= 0x7FFFFFFFUL) - return -EFBIG; - - /* If we are about to overflow the maximum file size, we also - * need to return the error, but only if no bytes can be written - * successfully. */ - if (((unsigned long) pos + count) > 0x7FFFFFFFUL) { - count = 0x7FFFFFFFL - pos; - if (((ssize_t) count) < 0) + /* L-F-S spec 2.2.1.27: */ + if (!(filp->f_flags & O_LARGEFILE)) { + if (pos >= 0x7fffffffULL) /* pos@2G forbidden */ return -EFBIG; } -#else + + if (pos + count > 0x7fffffffULL) + /* Write only until end of allowed region */ + count = 0x7fffffffULL - pos; { - off_t max = ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(sb)]; + loff_t max = ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(sb)]; if (pos >= max) return -EFBIG; @@ -239,20 +217,18 @@ mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); } } -#endif /* From SUS: We must generate a SIGXFSZ for file size overflow * only if no bytes were actually written to the file. --sct */ limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit < RLIM_INFINITY) { - if (((size_t) pos+count) >= limit) { - count = limit - pos; - if (((ssize_t) count) <= 0) { - send_sig(SIGXFSZ, current, 0); - return -EFBIG; - } + if (limit != RLIM_INFINITY) { + if (pos >= limit) { + send_sig(SIGXFSZ, current, 0); + return -EFBIG; } + if (pos+count > limit) + count = limit - pos; } /* @@ -382,15 +358,3 @@ return 0; } -#if BITS_PER_LONG < 64 -/* - * Called when an inode is about to be open. - * We use this to disallow opening RW large files on 32bit systems. - */ -static int ext2_open_file (struct inode * inode, struct file * filp) -{ - if (inode->u.ext2_i.i_high_size && (filp->f_mode & FMODE_WRITE)) - return -EFBIG; - return 0; -} -#endif diff -urN lfs-ref/fs/ext2/inode.c lfs/fs/ext2/inode.c --- lfs-ref/fs/ext2/inode.c Wed Sep 12 02:39:57 2001 +++ lfs/fs/ext2/inode.c Wed Sep 12 02:42:15 2001 @@ -537,15 +537,8 @@ inode->u.ext2_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl); else { inode->u.ext2_i.i_dir_acl = 0; - inode->u.ext2_i.i_high_size = - le32_to_cpu(raw_inode->i_size_high); -#if BITS_PER_LONG < 64 - if (raw_inode->i_size_high) - inode->i_size = (__u32)-1; -#else - inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high)) - << 32; -#endif + inode->i_size = ((__u64)(inode->i_size & 0xFFFFFFFFUL)) | + (((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32); } inode->u.ext2_i.i_block_group = block_group; inode->u.ext2_i.i_next_alloc_block = 0; @@ -667,12 +660,7 @@ if (S_ISDIR(inode->i_mode)) raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext2_i.i_dir_acl); else { -#if BITS_PER_LONG < 64 - raw_inode->i_size_high = - cpu_to_le32(inode->u.ext2_i.i_high_size); -#else raw_inode->i_size_high = cpu_to_le32(inode->i_size >> 32); -#endif } if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) raw_inode->i_block[0] = cpu_to_le32(kdev_t_to_nr(inode->i_rdev)); @@ -724,21 +712,18 @@ } if (iattr->ia_valid & ATTR_SIZE) { - off_t size = iattr->ia_size; + loff_t size = iattr->ia_size; unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur; if (size < 0) return -EINVAL; -#if BITS_PER_LONG == 64 if (size > ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(inode->i_sb)]) return -EFBIG; -#endif - if (limit < RLIM_INFINITY && size > limit) { + if (limit != RLIM_INFINITY && size > limit) { send_sig(SIGXFSZ, current, 0); return -EFBIG; } -#if BITS_PER_LONG == 64 if (size >> 31) { struct super_block *sb = inode->i_sb; struct ext2_super_block *es = sb->u.ext2_sb.s_es; @@ -751,7 +736,6 @@ mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); } } -#endif } retval = inode_change_ok(inode, iattr); diff -urN lfs-ref/fs/ext2/truncate.c lfs/fs/ext2/truncate.c --- lfs-ref/fs/ext2/truncate.c Mon Dec 11 16:58:00 2000 +++ lfs/fs/ext2/truncate.c Wed Sep 12 02:42:15 2001 @@ -53,9 +53,10 @@ * Currently we always hold the inode semaphore during truncate, so * there's no need to test for changes during the operation. */ -#define DIRECT_BLOCK(inode) \ - ((inode->i_size + inode->i_sb->s_blocksize - 1) / \ - inode->i_sb->s_blocksize) +#define DIRECT_BLOCK(inode) \ + ((long) \ + ((inode->i_size + inode->i_sb->s_blocksize - 1) >> \ + inode->i_sb->s_blocksize_bits)) #define INDIRECT_BLOCK(inode,offset) ((int)DIRECT_BLOCK(inode) - offset) #define DINDIRECT_BLOCK(inode,offset) \ (INDIRECT_BLOCK(inode,offset) / addr_per_block) diff -urN lfs-ref/fs/fat/dir.c lfs/fs/fat/dir.c --- lfs-ref/fs/fat/dir.c Mon Dec 11 16:58:00 2000 +++ lfs/fs/fat/dir.c Wed Sep 12 02:42:15 2001 @@ -315,7 +315,7 @@ /* Fake . and .. for the root directory. */ if (inode->i_ino == MSDOS_ROOT_INO) { while (cpos < 2) { - if (filldir(dirent, "..", cpos+1, cpos, MSDOS_ROOT_INO) < 0) + if (filldir(dirent, "..", cpos+1, cpos, MSDOS_ROOT_INO, DT_DIR) < 0) return 0; cpos++; filp->f_pos++; @@ -458,7 +458,8 @@ if (!long_slots||shortnames) { if (both) bufname[i] = '\0'; - if (filldir(dirent, bufname, i, *furrfu, inum) < 0) + if (filldir(dirent, bufname, i, *furrfu, inum, + (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0) goto FillFailed; } else { char longname[275]; @@ -469,7 +470,8 @@ memcpy(&longname[long_len+1], bufname, i); long_len += i; } - if (filldir(dirent, longname, long_len, *furrfu, inum) < 0) + if (filldir(dirent, longname, long_len, *furrfu, inum, + (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0) goto FillFailed; } @@ -499,7 +501,8 @@ const char * name, int name_len, off_t offset, - ino_t ino) + ino_t ino, + unsigned int d_type) { struct dirent *d1 = (struct dirent *)buf; struct dirent *d2 = d1 + 1; diff -urN lfs-ref/fs/fat/file.c lfs/fs/fat/file.c --- lfs-ref/fs/fat/file.c Mon Jan 17 16:44:42 2000 +++ lfs/fs/fat/file.c Wed Sep 12 02:42:15 2001 @@ -227,7 +227,7 @@ Each time we process one block in bhlist, we replace it by a new prefetch block if needed. */ - PRINTK (("#### ino %ld pos %ld size %ld count %d\n",inode->i_ino,*ppos,inode->i_size,count)); + PRINTK (("#### ino %ld pos %ld size %ld count %d\n",inode->i_ino,*ppos,(u_long)inode->i_size,count)); { /* We must prefetch complete block, so we must @@ -253,7 +253,7 @@ } pre.nolist = 0; PRINTK (("count %d ahead %d nblist %d\n",count,read_ahead[MAJOR(inode->i_dev)],pre.nblist)); - while ((left_in_file = inode->i_size - *ppos) > 0 + while ((left_in_file = (u_long)inode->i_size - *ppos) > 0 && buf < end){ struct buffer_head *bh = pre.bhlist[pre.nolist]; char *data; @@ -451,7 +451,7 @@ void fat_truncate(struct inode *inode) { - int cluster; + int cluster_bytes, cluster_shift; /* Why no return value? Surely the disk could fail... */ if (IS_IMMUTABLE(inode)) @@ -460,8 +460,10 @@ printk("FAT: fat_truncate called though fs is read-only, uhh...\n"); return /* -EROFS */; } - cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size; - (void) fat_free(inode,(inode->i_size+(cluster-1))/cluster); + cluster_bytes = SECTOR_SIZE * MSDOS_SB(inode->i_sb)->cluster_size; + cluster_shift = fslog2(cluster_bytes); + (void) fat_free(inode, + (inode->i_size+(cluster_bytes-1)) >> cluster_shift); MSDOS_I(inode)->i_attrs |= ATTR_ARCH; mark_inode_dirty(inode); } diff -urN lfs-ref/fs/fat/inode.c lfs/fs/fat/inode.c --- lfs-ref/fs/fat/inode.c Mon Dec 11 16:58:00 2000 +++ lfs/fs/fat/inode.c Wed Sep 12 02:42:15 2001 @@ -399,8 +399,9 @@ sizeof(struct msdos_dir_entry); } inode->i_blksize = MSDOS_SB(sb)->cluster_size* SECTOR_SIZE; - inode->i_blocks = (inode->i_size+inode->i_blksize-1)/ - inode->i_blksize*MSDOS_SB(sb)->cluster_size; + inode->i_blocks = (((inode->i_size+inode->i_blksize-1) >> + fslog2(inode->i_blksize)) * + MSDOS_SB(sb)->cluster_size); MSDOS_I(inode)->i_logstart = 0; MSDOS_I(inode)->i_attrs = 0; @@ -830,8 +831,9 @@ MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED; /* this is as close to the truth as we can get ... */ inode->i_blksize = MSDOS_SB(sb)->cluster_size*SECTOR_SIZE; - inode->i_blocks = (inode->i_size+inode->i_blksize-1)/ - inode->i_blksize*MSDOS_SB(sb)->cluster_size; + inode->i_blocks = (((inode->i_size+inode->i_blksize-1) >> + fslog2(inode->i_blksize)) * + MSDOS_SB(sb)->cluster_size); inode->i_mtime = inode->i_atime = date_dos2unix(CF_LE_W(de->time),CF_LE_W(de->date)); inode->i_ctime = diff -urN lfs-ref/fs/fcntl.c lfs/fs/fcntl.c --- lfs-ref/fs/fcntl.c Wed Sep 12 02:39:56 2001 +++ lfs/fs/fcntl.c Wed Sep 12 02:42:15 2001 @@ -145,17 +145,11 @@ return 0; } -asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct file * filp; - long err = -EBADF; - - lock_kernel(); - filp = fget(fd); - if (!filp) - goto out; +static long do_fcntl(unsigned int fd, unsigned int cmd, + unsigned long arg, struct file * filp) +{ + long err = 0; - err = 0; switch (cmd) { case F_DUPFD: err = dupfd(fd, arg); @@ -219,11 +213,60 @@ err = sock_fcntl (filp, cmd, arg); break; } + + return err; +} + +asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct file * filp; + long err = -EBADF; + + lock_kernel(); + filp = fget(fd); + if (!filp) + goto out; + + err = do_fcntl(fd, cmd, arg, filp); + + fput(filp); +out: + unlock_kernel(); + return err; +} + +#if BITS_PER_LONG == 32 +asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct file * filp; + long err = -EBADF; + + lock_kernel(); + filp = fget(fd); + if (!filp) + goto out; + + switch (cmd) { + case F_GETLK64: + err = fcntl_getlk64(fd, (struct flock64 *) arg); + break; + case F_SETLK64: + err = fcntl_setlk64(fd, cmd, (struct flock64 *) arg); + break; + case F_SETLKW64: + err = fcntl_setlk64(fd, cmd, (struct flock64 *) arg); + break; + default: + err = do_fcntl(fd, cmd, arg, filp); + break; + } + fput(filp); out: unlock_kernel(); return err; } +#endif /* Table to convert sigio signal codes into poll band bitmaps */ diff -urN lfs-ref/fs/hfs/dir_cap.c lfs/fs/hfs/dir_cap.c --- lfs-ref/fs/hfs/dir_cap.c Mon Jan 17 16:44:42 2000 +++ lfs/fs/hfs/dir_cap.c Wed Sep 12 02:42:15 2001 @@ -243,7 +243,7 @@ if (filp->f_pos == 0) { /* Entry 0 is for "." */ - if (filldir(dirent, DOT->Name, DOT_LEN, 0, dir->i_ino)) { + if (filldir(dirent, DOT->Name, DOT_LEN, 0, dir->i_ino, DT_DIR)) { return 0; } filp->f_pos = 1; @@ -260,7 +260,7 @@ } if (filldir(dirent, DOT_DOT->Name, - DOT_DOT_LEN, 1, ntohl(cnid))) { + DOT_DOT_LEN, 1, ntohl(cnid), DT_DIR)) { return 0; } filp->f_pos = 2; @@ -287,7 +287,7 @@ len = hfs_namein(dir, tmp_name, &((struct hfs_cat_key *)brec.key)->CName); if (filldir(dirent, tmp_name, len, - filp->f_pos, ino)) { + filp->f_pos, ino, DT_UNKNOWN)) { hfs_cat_close(entry, &brec); return 0; } @@ -303,7 +303,7 @@ /* In root dir last-2 entry is for ".rootinfo" */ if (filldir(dirent, DOT_ROOTINFO->Name, DOT_ROOTINFO_LEN, filp->f_pos, - ntohl(entry->cnid) | HFS_CAP_FNDR)) { + ntohl(entry->cnid) | HFS_CAP_FNDR, DT_UNKNOWN)) { return 0; } } @@ -315,7 +315,7 @@ /* In normal dirs last-1 entry is for ".finderinfo" */ if (filldir(dirent, DOT_FINDERINFO->Name, DOT_FINDERINFO_LEN, filp->f_pos, - ntohl(entry->cnid) | HFS_CAP_FDIR)) { + ntohl(entry->cnid) | HFS_CAP_FDIR, DT_UNKNOWN)) { return 0; } } @@ -327,7 +327,7 @@ /* In normal dirs last entry is for ".resource" */ if (filldir(dirent, DOT_RESOURCE->Name, DOT_RESOURCE_LEN, filp->f_pos, - ntohl(entry->cnid) | HFS_CAP_RDIR)) { + ntohl(entry->cnid) | HFS_CAP_RDIR, DT_UNKNOWN)) { return 0; } } diff -urN lfs-ref/fs/hfs/dir_dbl.c lfs/fs/hfs/dir_dbl.c --- lfs-ref/fs/hfs/dir_dbl.c Mon Jan 17 16:44:42 2000 +++ lfs/fs/hfs/dir_dbl.c Wed Sep 12 02:42:15 2001 @@ -206,7 +206,7 @@ if (filp->f_pos == 0) { /* Entry 0 is for "." */ - if (filldir(dirent, DOT->Name, DOT_LEN, 0, dir->i_ino)) { + if (filldir(dirent, DOT->Name, DOT_LEN, 0, dir->i_ino, DT_DIR)) { return 0; } filp->f_pos = 1; @@ -215,7 +215,7 @@ if (filp->f_pos == 1) { /* Entry 1 is for ".." */ if (filldir(dirent, DOT_DOT->Name, DOT_DOT_LEN, 1, - hfs_get_hl(entry->key.ParID))) { + hfs_get_hl(entry->key.ParID), DT_DIR)) { return 0; } filp->f_pos = 2; @@ -252,7 +252,7 @@ &((struct hfs_cat_key *)brec.key)->CName); } - if (filldir(dirent, tmp_name, len, filp->f_pos, ino)) { + if (filldir(dirent, tmp_name, len, filp->f_pos, ino, DT_UNKNOWN)) { hfs_cat_close(entry, &brec); return 0; } @@ -266,7 +266,7 @@ /* In root dir last entry is for "%RootInfo" */ if (filldir(dirent, PCNT_ROOTINFO->Name, PCNT_ROOTINFO_LEN, filp->f_pos, - ntohl(entry->cnid) | HFS_DBL_HDR)) { + ntohl(entry->cnid) | HFS_DBL_HDR, DT_UNKNOWN)) { return 0; } } diff -urN lfs-ref/fs/hfs/dir_nat.c lfs/fs/hfs/dir_nat.c --- lfs-ref/fs/hfs/dir_nat.c Mon Jan 17 16:44:42 2000 +++ lfs/fs/hfs/dir_nat.c Wed Sep 12 02:42:15 2001 @@ -231,7 +231,7 @@ if (filp->f_pos == 0) { /* Entry 0 is for "." */ - if (filldir(dirent, DOT->Name, DOT_LEN, 0, dir->i_ino)) { + if (filldir(dirent, DOT->Name, DOT_LEN, 0, dir->i_ino, DT_DIR)) { return 0; } filp->f_pos = 1; @@ -248,7 +248,7 @@ } if (filldir(dirent, DOT_DOT->Name, - DOT_DOT_LEN, 1, ntohl(cnid))) { + DOT_DOT_LEN, 1, ntohl(cnid), DT_DIR)) { return 0; } filp->f_pos = 2; @@ -275,7 +275,7 @@ len = hfs_namein(dir, tmp_name, &((struct hfs_cat_key *)brec.key)->CName); if (filldir(dirent, tmp_name, len, - filp->f_pos, ino)) { + filp->f_pos, ino, DT_UNKNOWN)) { hfs_cat_close(entry, &brec); return 0; } @@ -290,14 +290,14 @@ /* In normal dirs entry 2 is for ".AppleDouble" */ if (filldir(dirent, DOT_APPLEDOUBLE->Name, DOT_APPLEDOUBLE_LEN, filp->f_pos, - ntohl(entry->cnid) | HFS_NAT_HDIR)) { + ntohl(entry->cnid) | HFS_NAT_HDIR, DT_UNKNOWN)) { return 0; } } else if (type == HFS_NAT_HDIR) { /* In .AppleDouble entry 2 is for ".Parent" */ if (filldir(dirent, DOT_PARENT->Name, DOT_PARENT_LEN, filp->f_pos, - ntohl(entry->cnid) | HFS_NAT_HDR)) { + ntohl(entry->cnid) | HFS_NAT_HDR, DT_UNKNOWN)) { return 0; } } @@ -310,7 +310,7 @@ (type == HFS_NAT_HDIR)) { if (filldir(dirent, ROOTINFO->Name, ROOTINFO_LEN, filp->f_pos, - ntohl(entry->cnid) | HFS_NAT_HDR)) { + ntohl(entry->cnid) | HFS_NAT_HDR, DT_UNKNOWN)) { return 0; } } diff -urN lfs-ref/fs/hpfs/hpfs_fs.c lfs/fs/hpfs/hpfs_fs.c --- lfs-ref/fs/hpfs/hpfs_fs.c Mon Jan 17 16:44:42 2000 +++ lfs/fs/hpfs/hpfs_fs.c Wed Sep 12 02:42:15 2001 @@ -1376,13 +1376,13 @@ break; case 0: - if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino) < 0) + if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino, DT_DIR) < 0) break; filp->f_pos = -1; /* fall through */ case -1: - if (filldir(dirent, "..", 2, filp->f_pos, inode->i_hpfs_parent_dir) < 0) + if (filldir(dirent, "..", 2, filp->f_pos, inode->i_hpfs_parent_dir, DT_DIR) < 0) break; filp->f_pos = 1; /* fall through */ @@ -1402,7 +1402,7 @@ else ino = file_ino(de->fnode); brelse4(&qbh); - if (filldir(dirent, tempname, namelen, old_pos, ino) < 0) { + if (filldir(dirent, tempname, namelen, old_pos, ino, DT_UNKNOWN) < 0) { filp->f_pos = old_pos; break; } diff -urN lfs-ref/fs/isofs/dir.c lfs/fs/isofs/dir.c --- lfs-ref/fs/isofs/dir.c Fri Apr 20 22:31:20 2001 +++ lfs/fs/isofs/dir.c Wed Sep 12 02:42:15 2001 @@ -206,7 +206,7 @@ /* Handle the case of the '.' directory */ if (de->name_len[0] == 1 && de->name[0] == 0) { - if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino) < 0) + if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino, DT_DIR) < 0) break; filp->f_pos += de_len; continue; @@ -217,7 +217,7 @@ /* Handle the case of the '..' directory */ if (de->name_len[0] == 1 && de->name[0] == 1) { inode_number = filp->f_dentry->d_parent->d_inode->i_ino; - if (filldir(dirent, "..", 2, filp->f_pos, inode_number) < 0) + if (filldir(dirent, "..", 2, filp->f_pos, inode_number, DT_DIR) < 0) break; filp->f_pos += de_len; continue; @@ -261,7 +261,7 @@ } } if (len > 0) { - if (filldir(dirent, p, len, filp->f_pos, inode_number) < 0) + if (filldir(dirent, p, len, filp->f_pos, inode_number, DT_UNKNOWN) < 0) break; } filp->f_pos += de_len; diff -urN lfs-ref/fs/isofs/inode.c lfs/fs/isofs/inode.c --- lfs-ref/fs/isofs/inode.c Fri Apr 20 22:31:20 2001 +++ lfs/fs/isofs/inode.c Wed Sep 12 02:42:15 2001 @@ -908,7 +908,8 @@ int isofs_bmap(struct inode * inode,int block) { - off_t b_off, offset, size; + loff_t b_off; + unsigned offset, size; struct inode *ino; unsigned int firstext; unsigned long nextino; @@ -919,7 +920,7 @@ return 0; } - b_off = block << ISOFS_BUFFER_BITS(inode); + b_off = (loff_t)block << ISOFS_BUFFER_BITS(inode); /* * If we are beyond the end of this file, don't give out any @@ -927,7 +928,7 @@ */ if( b_off >= inode->i_size ) { - off_t max_legal_read_offset; + loff_t max_legal_read_offset; /* * If we are *way* beyond the end of the file, print a message. @@ -942,7 +943,7 @@ if( b_off >= max_legal_read_offset ) { - printk("_isofs_bmap: block>= EOF(%d, %ld)\n", block, + printk("_isofs_bmap: block>= EOF(%d, %Ld)\n", block, inode->i_size); } return 0; @@ -1209,7 +1210,7 @@ #ifdef DEBUG printk("Get inode %x: %d %d: %d\n",inode->i_ino, block, - ((int)pnt) & 0x3ff, inode->i_size); + ((int)pnt) & 0x3ff, (u_long)inode->i_size); #endif inode->i_mtime = inode->i_atime = inode->i_ctime = diff -urN lfs-ref/fs/lockd/svclock.c lfs/fs/lockd/svclock.c --- lfs-ref/fs/lockd/svclock.c Fri Apr 20 22:31:20 2001 +++ lfs/fs/lockd/svclock.c Wed Sep 12 02:42:15 2001 @@ -100,14 +100,18 @@ struct nlm_block **head, *block; struct file_lock *fl; - dprintk("lockd: nlmsvc_lookup_block f=%p pd=%d %ld-%ld ty=%d\n", - file, lock->fl.fl_pid, lock->fl.fl_start, - lock->fl.fl_end, lock->fl.fl_type); + dprintk("lockd: nlmsvc_lookup_block f=%p pd=%d %Ld-%Ld ty=%d\n", + file, lock->fl.fl_pid, + (long long)lock->fl.fl_start, + (long long)lock->fl.fl_end, + lock->fl.fl_type); for (head = &nlm_blocked; (block = *head); head = &block->b_next) { fl = &block->b_call.a_args.lock.fl; - dprintk("lockd: check f=%p pd=%d %ld-%ld ty=%d cookie=%x\n", - block->b_file, fl->fl_pid, fl->fl_start, - fl->fl_end, fl->fl_type, + dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%x\n", + block->b_file, fl->fl_pid, + (long long)lock->fl.fl_start, + (long long)lock->fl.fl_end, + fl->fl_type, *(u32 *)(&block->b_call.a_args.cookie.data)); if (block->b_file == file && nlm_compare_locks(fl, &lock->fl)) { if (remove) @@ -293,12 +297,12 @@ struct inode *inode = file->f_file.f_dentry->d_inode; int error; - dprintk("lockd: nlmsvc_lock(%04x/%ld, ty=%d, pi=%d, %ld-%ld, bl=%d)\n", + dprintk("lockd: nlmsvc_lock(%04x/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n", file->f_file.f_dentry->d_inode->i_dev, file->f_file.f_dentry->d_inode->i_ino, lock->fl.fl_type, lock->fl.fl_pid, - lock->fl.fl_start, - lock->fl.fl_end, + (long long)lock->fl.fl_start, + (long long)lock->fl.fl_end, wait); /* Checking for read only file system */ @@ -371,16 +375,18 @@ { struct file_lock *fl; - dprintk("lockd: nlmsvc_testlock(%04x/%ld, ty=%d, %ld-%ld)\n", + dprintk("lockd: nlmsvc_testlock(%04x/%ld, ty=%d, %Ld-%Ld)\n", file->f_file.f_dentry->d_inode->i_dev, file->f_file.f_dentry->d_inode->i_ino, lock->fl.fl_type, - lock->fl.fl_start, - lock->fl.fl_end); + (long long)lock->fl.fl_start, + (long long)lock->fl.fl_end); if ((fl = posix_test_lock(&file->f_file, &lock->fl)) != NULL) { - dprintk("lockd: conflicting lock(ty=%d, %ld-%ld)\n", - fl->fl_type, fl->fl_start, fl->fl_end ); + dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n", + fl->fl_type, + (long long)lock->fl.fl_start, + (long long)lock->fl.fl_end); conflock->caller = "somehost"; /* FIXME */ conflock->oh.len = 0; /* don't return OH info */ @@ -403,12 +409,12 @@ { int error; - dprintk("lockd: nlmsvc_unlock(%04x/%ld, pi=%d, %ld-%ld)\n", + dprintk("lockd: nlmsvc_unlock(%04x/%ld, pi=%d, %Ld-%Ld)\n", file->f_file.f_dentry->d_inode->i_dev, file->f_file.f_dentry->d_inode->i_ino, lock->fl.fl_pid, - lock->fl.fl_start, - lock->fl.fl_end); + (long long)lock->fl.fl_start, + (long long)lock->fl.fl_end); /* First, cancel any lock that might be there */ nlmsvc_cancel_blocked(file, lock); @@ -431,12 +437,12 @@ { struct nlm_block *block; - dprintk("lockd: nlmsvc_cancel(%04x/%ld, pi=%d, %ld-%ld)\n", + dprintk("lockd: nlmsvc_cancel(%04x/%ld, pi=%d, %Ld-%Ld)\n", file->f_file.f_dentry->d_inode->i_dev, file->f_file.f_dentry->d_inode->i_ino, lock->fl.fl_pid, - lock->fl.fl_start, - lock->fl.fl_end); + (long long)lock->fl.fl_start, + (long long)lock->fl.fl_end); down(&file->f_sema); if ((block = nlmsvc_lookup_block(file, lock, 1)) != NULL) diff -urN lfs-ref/fs/lockd/xdr.c lfs/fs/lockd/xdr.c --- lfs-ref/fs/lockd/xdr.c Mon Dec 11 16:58:00 2000 +++ lfs/fs/lockd/xdr.c Wed Sep 12 02:42:15 2001 @@ -24,7 +24,6 @@ #define NLMDBG_FACILITY NLMDBG_XDR #define NLM_MAXSTRLEN 1024 -#define OFFSET_MAX LONG_MAX #define QUADLEN(len) (((len) + 3) >> 2) @@ -37,6 +36,25 @@ static void nlm_register_stats(void); static void nlm_unregister_stats(void); +static inline loff_t +s32_to_loff_t(__s32 offset) +{ + return (loff_t)offset; +} + +static inline __s32 +loff_t_to_s32(loff_t offset) +{ + __s32 res; + if (offset >= NLM_OFFSET_MAX) + res = NLM_OFFSET_MAX; + else if (offset <= -NLM_OFFSET_MAX) + res = -NLM_OFFSET_MAX; + else + res = offset; + return res; +} + /* * Initialization of NFS status variables */ @@ -157,7 +175,7 @@ nlm_decode_lock(u32 *p, struct nlm_lock *lock) { struct file_lock *fl = &lock->fl; - int len; + s32 start, len, end; if (!(p = xdr_decode_string(p, &lock->caller, &len, NLM_MAXSTRLEN)) || !(p = nlm_decode_fh(p, &lock->fh)) @@ -169,10 +187,16 @@ fl->fl_pid = ntohl(*p++); fl->fl_flags = FL_POSIX; fl->fl_type = F_RDLCK; /* as good as anything else */ - fl->fl_start = ntohl(*p++); + start = ntohl(*p++); len = ntohl(*p++); - if (len == 0 || (fl->fl_end = fl->fl_start + len - 1) < 0) + end = start + len - 1; + + fl->fl_start = s32_to_loff_t(start); + + if (len == 0 || end < 0) fl->fl_end = OFFSET_MAX; + else + fl->fl_end = s32_to_loff_t(end); return p; } @@ -183,6 +207,7 @@ nlm_encode_lock(u32 *p, struct nlm_lock *lock) { struct file_lock *fl = &lock->fl; + __s32 start, len; if (!(p = xdr_encode_string(p, lock->caller, -1)) || !(p = nlm_encode_fh(p, &lock->fh)) @@ -193,12 +218,15 @@ || (fl->fl_end > NLM_OFFSET_MAX && fl->fl_end != OFFSET_MAX)) return NULL; - *p++ = htonl(fl->fl_pid); - *p++ = htonl(fl->fl_start); + start = loff_t_to_s32(fl->fl_start); if (fl->fl_end == OFFSET_MAX) - *p++ = xdr_zero; + len = 0; else - *p++ = htonl(fl->fl_end - fl->fl_start + 1); + len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1); + + *p++ = htonl(fl->fl_pid); + *p++ = htonl(start); + *p++ = htonl(len); return p; } @@ -209,6 +237,8 @@ static u32 * nlm_encode_testres(u32 *p, struct nlm_res *resp) { + s32 start, len; + if (!(p = nlm_encode_cookie(p, &resp->cookie))) return 0; *p++ = resp->status; @@ -223,11 +253,14 @@ if (!(p = xdr_encode_netobj(p, &resp->lock.oh))) return 0; - *p++ = htonl(fl->fl_start); + start = loff_t_to_s32(fl->fl_start); if (fl->fl_end == OFFSET_MAX) - *p++ = xdr_zero; + len = xdr_zero; else - *p++ = htonl(fl->fl_end - fl->fl_start + 1); + len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1); + + *p++ = htonl(start); + *p++ = htonl(len); } return p; @@ -446,7 +479,8 @@ resp->status = ntohl(*p++); if (resp->status == NLM_LCK_DENIED) { struct file_lock *fl = &resp->lock.fl; - u32 excl, len; + u32 excl; + s32 start, len, end; memset(&resp->lock, 0, sizeof(resp->lock)); excl = ntohl(*p++); @@ -456,10 +490,15 @@ fl->fl_flags = FL_POSIX; fl->fl_type = excl? F_WRLCK : F_RDLCK; - fl->fl_start = ntohl(*p++); + start = ntohl(*p++); len = ntohl(*p++); - if (len == 0 || (fl->fl_end = fl->fl_start + len - 1) < 0) + end = start + len - 1; + + fl->fl_start = s32_to_loff_t(start); + if (len == 0 || end < 0) fl->fl_end = OFFSET_MAX; + else + fl->fl_end = s32_to_loff_t(end); } return 0; } diff -urN lfs-ref/fs/lockd/xdr4.c lfs/fs/lockd/xdr4.c --- lfs-ref/fs/lockd/xdr4.c Mon Dec 11 16:58:00 2000 +++ lfs/fs/lockd/xdr4.c Wed Sep 12 02:42:15 2001 @@ -23,7 +23,6 @@ #define NLMDBG_FACILITY NLMDBG_XDR #define NLM_MAXSTRLEN 1024 -#define OFFSET_MAX ((off_t)LONG_MAX) #define QUADLEN(len) (((len) + 3) >> 2) @@ -34,11 +33,23 @@ typedef struct nlm_args nlm_args; -static inline off_t -size_to_off_t(__s64 size) +static inline loff_t +s64_to_loff_t(__s64 offset) { - size = (size > (__s64)LONG_MAX) ? (off_t)LONG_MAX : (off_t) size; - return (size < (__s64)-LONG_MAX) ? (off_t)-LONG_MAX : (off_t) size; + return (loff_t)offset; +} + +static inline s64 +loff_t_to_s64(loff_t offset) +{ + s64 res; + if (offset > NLM4_OFFSET_MAX) + res = NLM4_OFFSET_MAX; + else if (offset < -NLM4_OFFSET_MAX) + res = -NLM4_OFFSET_MAX; + else + res = offset; + return res; } /* @@ -139,11 +150,12 @@ p = xdr_decode_hyper(p, &len); end = start + len - 1; - fl->fl_start = size_to_off_t(start); - fl->fl_end = size_to_off_t(end); + fl->fl_start = s64_to_loff_t(start); - if (len == 0 || fl->fl_end < 0) + if (len == 0 || end < 0) fl->fl_end = OFFSET_MAX; + else + fl->fl_end = s64_to_loff_t(end); return p; } @@ -154,18 +166,26 @@ nlm4_encode_lock(u32 *p, struct nlm_lock *lock) { struct file_lock *fl = &lock->fl; + __s64 start, len; if (!(p = xdr_encode_string(p, lock->caller, -1)) || !(p = nlm4_encode_fh(p, &lock->fh)) || !(p = nlm4_encode_oh(p, &lock->oh))) return NULL; - *p++ = htonl(fl->fl_pid); - p = xdr_encode_hyper(p, fl->fl_start); + if (fl->fl_start > NLM4_OFFSET_MAX + || (fl->fl_end > NLM4_OFFSET_MAX && fl->fl_end != OFFSET_MAX)) + return NULL; + + start = loff_t_to_s64(fl->fl_start); if (fl->fl_end == OFFSET_MAX) - p = xdr_encode_hyper(p, 0); + len = 0; else - p = xdr_encode_hyper(p, fl->fl_end - fl->fl_start + 1); + len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1); + + *p++ = htonl(fl->fl_pid); + p = xdr_encode_hyper(p, start); + p = xdr_encode_hyper(p, len); return p; } @@ -176,6 +196,7 @@ static u32 * nlm4_encode_testres(u32 *p, struct nlm_res *resp) { + s64 start, len; dprintk("xdr: before encode_testres (p %p resp %p)\n", p, resp); if (!(p = nlm4_encode_cookie(p, &resp->cookie))) @@ -192,14 +213,17 @@ if (!(p = xdr_encode_netobj(p, &resp->lock.oh))) return 0; - p = xdr_encode_hyper(p, fl->fl_start); + start = loff_t_to_s64(fl->fl_start); if (fl->fl_end == OFFSET_MAX) - p = xdr_encode_hyper(p, 0); + len = 0; else - p = xdr_encode_hyper(p, fl->fl_end - fl->fl_start + 1); - dprintk("xdr: encode_testres (status %d pid %d type %d start %ld end %ld)\n", resp->status, fl->fl_pid, fl->fl_type, fl->fl_start, fl->fl_end); - - + len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1); + + p = xdr_encode_hyper(p, start); + p = xdr_encode_hyper(p, len); + dprintk("xdr: encode_testres (status %d pid %d type %d start %Ld end %Ld)\n", + resp->status, fl->fl_pid, fl->fl_type, + fl->fl_start, fl->fl_end); } dprintk("xdr: after encode_testres (p %p resp %p)\n", p, resp); @@ -435,10 +459,11 @@ p = xdr_decode_hyper(p, &len); end = start + len - 1; - fl->fl_start = size_to_off_t(start); - fl->fl_end = size_to_off_t(end); - if (len == 0 || fl->fl_end < 0) + fl->fl_start = s64_to_loff_t(start); + if (len == 0 || end < 0) fl->fl_end = OFFSET_MAX; + else + fl->fl_end = s64_to_loff_t(end); } return 0; } diff -urN lfs-ref/fs/locks.c lfs/fs/locks.c --- lfs-ref/fs/locks.c Wed Sep 12 02:05:57 2001 +++ lfs/fs/locks.c Wed Sep 12 02:42:15 2001 @@ -111,12 +111,12 @@ #include -#define OFFSET_MAX ((off_t)LONG_MAX) /* FIXME: move elsewhere? */ - static int flock_make_lock(struct file *filp, struct file_lock *fl, unsigned int cmd); -static int posix_make_lock(struct file *filp, struct file_lock *fl, +static int flock_to_posix_lock(struct file *filp, struct file_lock *fl, struct flock *l); +static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl, + struct flock64 *l); static int flock_locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl); static int posix_locks_conflict(struct file_lock *caller_fl, @@ -195,7 +195,7 @@ if (waiter->fl_prevblock) { printk(KERN_ERR "locks_insert_block: remove duplicated lock " - "(pid=%d %ld-%ld type=%d)\n", + "(pid=%d %Ld-%Ld type=%d)\n", waiter->fl_pid, waiter->fl_start, waiter->fl_end, waiter->fl_type); locks_delete_block(waiter->fl_prevblock, waiter); @@ -344,9 +344,10 @@ if (!filp->f_dentry || !filp->f_dentry->d_inode || !filp->f_op) goto out_putf; - if (!posix_make_lock(filp, &file_lock, &flock)) + if ((error = flock_to_posix_lock(filp, &file_lock, &flock))) goto out_putf; + error = -EINVAL; if (filp->f_op->lock) { error = filp->f_op->lock(filp, F_GETLK, &file_lock); if (error < 0) @@ -363,6 +364,18 @@ flock.l_type = F_UNLCK; if (fl != NULL) { flock.l_pid = fl->fl_pid; +#if BITS_PER_LONG == 32 + /* + * Make sure we can represent the posix lock via + * legacy 32bit flock. + */ + error = -EOVERFLOW; + if (fl->fl_start > OFFT_OFFSET_MAX) + goto out_putf; + if ((fl->fl_end != OFFSET_MAX) + && (fl->fl_end > OFFT_OFFSET_MAX)) + goto out_putf; +#endif flock.l_start = fl->fl_start; flock.l_len = fl->fl_end == OFFSET_MAX ? 0 : fl->fl_end - fl->fl_start + 1; @@ -424,8 +437,7 @@ goto out_putf; } - error = -EINVAL; - if (!posix_make_lock(filp, &file_lock, &flock)) + if ((error = flock_to_posix_lock(filp, &file_lock, &flock))) goto out_putf; error = -EBADF; @@ -475,6 +487,169 @@ return error; } +#if BITS_PER_LONG == 32 +/* Report the first existing lock that would conflict with l. + * This implements the F_GETLK command of fcntl(). + */ +int fcntl_getlk64(unsigned int fd, struct flock64 *l) +{ + struct file *filp; + struct file_lock *fl,file_lock; + struct flock64 flock; + int error; + + error = -EFAULT; + if (copy_from_user(&flock, l, sizeof(flock))) + goto out; + error = -EINVAL; + if ((flock.l_type != F_RDLCK) && (flock.l_type != F_WRLCK)) + goto out; + + error = -EBADF; + filp = fget(fd); + if (!filp) + goto out; + + error = -EINVAL; + if (!filp->f_dentry || !filp->f_dentry->d_inode || !filp->f_op) + goto out_putf; + + if (!flock64_to_posix_lock(filp, &file_lock, &flock)) + goto out_putf; + + if (filp->f_op->lock) { + error = filp->f_op->lock(filp, F_GETLK, &file_lock); + if (error < 0) + goto out_putf; + else if (error == LOCK_USE_CLNT) + /* Bypass for NFS with no locking - 2.0.36 compat */ + fl = posix_test_lock(filp, &file_lock); + else + fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock); + } else { + fl = posix_test_lock(filp, &file_lock); + } + + flock.l_type = F_UNLCK; + if (fl != NULL) { + flock.l_pid = fl->fl_pid; + flock.l_start = fl->fl_start; + flock.l_len = fl->fl_end == OFFSET_MAX ? 0 : + fl->fl_end - fl->fl_start + 1; + flock.l_whence = 0; + flock.l_type = fl->fl_type; + } + error = -EFAULT; + if (!copy_to_user(l, &flock, sizeof(flock))) + error = 0; + +out_putf: + fput(filp); +out: + return error; +} + +/* Apply the lock described by l to an open file descriptor. + * This implements both the F_SETLK and F_SETLKW commands of fcntl(). + */ +int fcntl_setlk64(unsigned int fd, unsigned int cmd, struct flock64 *l) +{ + struct file *filp; + struct file_lock file_lock; + struct flock64 flock; + struct dentry * dentry; + struct inode *inode; + int error; + + /* + * This might block, so we do it before checking the inode. + */ + error = -EFAULT; + if (copy_from_user(&flock, l, sizeof(flock))) + goto out; + + /* Get arguments and validate them ... + */ + + error = -EBADF; + filp = fget(fd); + if (!filp) + goto out; + + error = -EINVAL; + if (!(dentry = filp->f_dentry)) + goto out_putf; + if (!(inode = dentry->d_inode)) + goto out_putf; + if (!filp->f_op) + goto out_putf; + + /* Don't allow mandatory locks on files that may be memory mapped + * and shared. + */ + if (IS_MANDLOCK(inode) && + (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID && + inode->i_mmap) { + struct vm_area_struct *vma = inode->i_mmap; + error = -EAGAIN; + do { + if (vma->vm_flags & VM_MAYSHARE) + goto out_putf; + } while ((vma = vma->vm_next_share) != NULL); + } + + error = -EINVAL; + if (!flock64_to_posix_lock(filp, &file_lock, &flock)) + goto out_putf; + + error = -EBADF; + switch (flock.l_type) { + case F_RDLCK: + if (!(filp->f_mode & FMODE_READ)) + goto out_putf; + break; + case F_WRLCK: + if (!(filp->f_mode & FMODE_WRITE)) + goto out_putf; + break; + case F_UNLCK: + break; + case F_SHLCK: + case F_EXLCK: +#ifdef __sparc__ +/* warn a bit for now, but don't overdo it */ +{ + static int count = 0; + if (!count) { + count=1; + printk(KERN_WARNING + "fcntl_setlk() called by process %d (%s) with broken flock() emulation\n", + current->pid, current->comm); + } +} + if (!(filp->f_mode & 3)) + goto out_putf; + break; +#endif + default: + error = -EINVAL; + goto out_putf; + } + + if (filp->f_op->lock != NULL) { + error = filp->f_op->lock(filp, cmd, &file_lock); + if (error < 0) + goto out_putf; + } + error = posix_lock_file(filp, &file_lock, cmd == F_SETLKW64); + +out_putf: + fput(filp); +out: + return error; +} +#endif /* BITS_PER_LONG == 32 */ + /* * This function is called when the file is being removed * from the task's fd array. @@ -655,10 +830,70 @@ /* Verify a "struct flock" and copy it to a "struct file_lock" as a POSIX * style lock. */ -static int posix_make_lock(struct file *filp, struct file_lock *fl, - struct flock *l) +static int flock_to_posix_lock(struct file *filp, struct file_lock *fl, + struct flock *l) +{ + loff_t start; + int ret = -EINVAL; + + memset(fl, 0, sizeof(*fl)); + + fl->fl_flags = FL_POSIX; + + switch (l->l_type) { + case F_RDLCK: + case F_WRLCK: + case F_UNLCK: + fl->fl_type = l->l_type; + break; + default: + goto out; + } + + switch (l->l_whence) { + case 0: /*SEEK_SET*/ + start = 0; + break; + case 1: /*SEEK_CUR*/ + start = filp->f_pos; + break; + case 2: /*SEEK_END*/ + start = filp->f_dentry->d_inode->i_size; + break; + default: + goto out; + } + + if (((start += l->l_start) < 0) || (l->l_len < 0)) + goto out; + fl->fl_end = start + l->l_len - 1; + if (l->l_len > 0 && fl->fl_end < 0) + goto out; + fl->fl_start = start; /* we record the absolute position */ + if (l->l_len != 0) { + start = fl->fl_end; + } else { + start = fl->fl_start; + fl->fl_end = OFFSET_MAX; + } + ret = -EOVERFLOW; + if (start > OFFT_OFFSET_MAX) + goto out; + + fl->fl_file = filp; + fl->fl_owner = current->files; + fl->fl_pid = current->pid; + + ret = 0; + out: + return ret; +} + +#if BITS_PER_LONG == 32 +static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl, + struct flock64 *l) { - off_t start; + loff_t start; memset(fl, 0, sizeof(*fl)); @@ -703,6 +938,7 @@ return (1); } +#endif /* Verify a call to flock() and fill in a file_lock structure with * an appropriate FLOCK lock. @@ -1218,7 +1454,7 @@ p += sprintf(p, "FLOCK ADVISORY "); } p += sprintf(p, "%s ", (fl->fl_type == F_RDLCK) ? "READ " : "WRITE"); - p += sprintf(p, "%d %s:%ld %ld %ld ", + p += sprintf(p, "%d %s:%ld %Ld %Ld ", fl->fl_pid, kdevname(inode->i_dev), inode->i_ino, fl->fl_start, fl->fl_end); @@ -1282,6 +1518,3 @@ *start = buffer; return (q - buffer); } - - - diff -urN lfs-ref/fs/minix/dir.c lfs/fs/minix/dir.c --- lfs-ref/fs/minix/dir.c Mon Jan 17 16:44:42 2000 +++ lfs/fs/minix/dir.c Wed Sep 12 02:42:15 2001 @@ -82,7 +82,7 @@ de = (struct minix_dir_entry *) (offset + bh->b_data); if (de->inode) { int size = strnlen(de->name, info->s_namelen); - if (filldir(dirent, de->name, size, filp->f_pos, de->inode) < 0) { + if (filldir(dirent, de->name, size, filp->f_pos, de->inode, DT_UNKNOWN) < 0) { brelse(bh); return 0; } diff -urN lfs-ref/fs/minix/file.c lfs/fs/minix/file.c --- lfs-ref/fs/minix/file.c Mon Jan 17 16:44:42 2000 +++ lfs/fs/minix/file.c Wed Sep 12 02:42:15 2001 @@ -70,8 +70,8 @@ size_t count, loff_t *ppos) { struct inode * inode = filp->f_dentry->d_inode; - off_t pos; - ssize_t written, c; + loff_t pos; + ssize_t written, c, m; struct buffer_head * bh; char * p; @@ -87,15 +87,34 @@ pos = inode->i_size; else pos = *ppos; + + /* L-F-S spec 2.2.1.27: */ + if (!(filp->f_flags & O_LARGEFILE)) { + if (pos >= 0x7fffffffULL) /* pos@2G forbidden */ + return -EFBIG; + + if (pos + count > 0x7fffffffULL) + /* Write only until end of allowed region */ + count = 0x7fffffffULL - pos; + } + /* MINIX i-node file-size can't exceed 4G-1 */ + /* With 1k blocks and triple indirection MINIX can have files + up to 16 GB in size -- filesystem maximum is then 4G*1k = 4T */ + if (pos >= 0xffffffffULL) + return -EFBIG; /* Absolutely too much! */ + if ((pos + count) >= 0x100000000ULL) /* too much to write! */ + count = 0xffffffffULL - pos; + written = 0; while (written < count) { - bh = minix_getblk(inode,pos/BLOCK_SIZE,1); + bh = minix_getblk(inode, pos >> BLOCK_SIZE_BITS, 1); if (!bh) { if (!written) written = -ENOSPC; break; } - c = BLOCK_SIZE - (pos % BLOCK_SIZE); + m = pos & (BLOCK_SIZE - 1); + c = BLOCK_SIZE - m; if (c > count-written) c = count-written; if (c != BLOCK_SIZE && !buffer_uptodate(bh)) { @@ -108,7 +127,7 @@ break; } } - p = (pos % BLOCK_SIZE) + bh->b_data; + p = bh->b_data + m; c -= copy_from_user(p,buf,c); if (!c) { brelse(bh); diff -urN lfs-ref/fs/ncpfs/dir.c lfs/fs/ncpfs/dir.c --- lfs-ref/fs/ncpfs/dir.c Mon Dec 11 16:58:00 2000 +++ lfs/fs/ncpfs/dir.c Wed Sep 12 02:42:15 2001 @@ -449,14 +449,14 @@ result = 0; if (filp->f_pos == 0) { ncp_invalid_dir_cache(inode); - if (filldir(dirent, ".", 1, 0, inode->i_ino) < 0) { + if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0) { goto finished; } filp->f_pos = 1; } if (filp->f_pos == 1) { if (filldir(dirent, "..", 2, 1, - dentry->d_parent->d_inode->i_ino) < 0) { + dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { goto finished; } filp->f_pos = 2; @@ -537,7 +537,7 @@ ino = ncp_invent_inos(1); if (filldir(dirent, entry->i.entryName, entry->i.nameLen, - entry->f_pos, ino) < 0) { + entry->f_pos, ino, DT_UNKNOWN) < 0) { break; } if ((inode->i_dev != c_dev) diff -urN lfs-ref/fs/ncpfs/file.c lfs/fs/ncpfs/file.c --- lfs-ref/fs/ncpfs/file.c Mon Dec 11 16:58:00 2000 +++ lfs/fs/ncpfs/file.c Wed Sep 12 02:42:15 2001 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "ncplib_kernel.h" @@ -161,7 +162,7 @@ /* First read in as much as possible for each bufsize. */ while (already_read < count) { int read_this_time; - size_t to_read = min(bufsize - (pos % bufsize), + size_t to_read = min(bufsize - (pos & (bufsize-1)), count - already_read); error = ncp_read_bounce(NCP_SERVER(inode), @@ -201,7 +202,7 @@ struct dentry *dentry = file->f_dentry; struct inode *inode = dentry->d_inode; size_t already_written = 0; - off_t pos; + loff_t pos; size_t bufsize; int errno; void* bouncebuffer; @@ -238,12 +239,18 @@ already_written = 0; + /* Maximum file size: 2G-1 */ + if (pos >= 0x7fffffffULL) + return -EFBIG; + if ((pos + count) >= 0x7fffffffULL) + count = 0x7fffffffULL - pos; + bouncebuffer = kmalloc(bufsize, GFP_NFS); if (!bouncebuffer) return -EIO; /* -ENOMEM */ while (already_written < count) { int written_this_time; - size_t to_write = min(bufsize - (pos % bufsize), + size_t to_write = min(bufsize - (pos & (bufsize-1)), count - already_written); if (copy_from_user(bouncebuffer, buf, to_write)) { diff -urN lfs-ref/fs/ncpfs/inode.c lfs/fs/ncpfs/inode.c --- lfs-ref/fs/ncpfs/inode.c Tue Jun 13 03:48:14 2000 +++ lfs/fs/ncpfs/inode.c Wed Sep 12 02:42:15 2001 @@ -131,7 +131,7 @@ } inode->i_blocks = 0; if ((inode->i_size)&&(inode->i_blksize)) { - inode->i_blocks = (inode->i_size-1)/(inode->i_blksize)+1; + inode->i_blocks = ((inode->i_size-1) >> fslog2(inode->i_blksize)) +1; } inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(nwi->modifyTime), @@ -201,8 +201,7 @@ inode->i_blocks = 0; if ((inode->i_blksize != 0) && (inode->i_size != 0)) { - inode->i_blocks = - (inode->i_size - 1) / inode->i_blksize + 1; + inode->i_blocks = ((inode->i_size - 1) >> fslog2(inode->i_blksize)) + 1; } inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(nwi->modifyTime), diff -urN lfs-ref/fs/nfs/dir.c lfs/fs/nfs/dir.c --- lfs-ref/fs/nfs/dir.c Wed Sep 12 02:05:57 2001 +++ lfs/fs/nfs/dir.c Wed Sep 12 02:42:15 2001 @@ -137,7 +137,7 @@ int plus = NFS_USE_READDIRPLUS(inode); int error; - dfprintk(VFS, "NFS: nfs_readdir_filler() reading cookie %Lu into page %lu.\n", (long long)desc->entry->cookie, page->offset); + dfprintk(VFS, "NFS: nfs_readdir_filler() reading cookie %Lu into page %Lu.\n", (long long)desc->entry->cookie, (long long) nfs_page_offset(page)); again: error = NFS_PROTO(inode)->readdir(inode, cred, @@ -158,7 +158,7 @@ * Note: assumes we have exclusive access to this inode either * throught inode->i_sem or some other mechanism. */ - if (page->offset == 0) + if (page_index(page) == 0) invalidate_inode_pages(inode); nfs_unlock_page(page); return 0; @@ -294,7 +294,7 @@ * retrieving the current dirent on the server */ fileid = nfs_fileid_to_ino_t(entry->ino); res = filldir(dirent, entry->name, entry->len, - entry->prev_cookie, fileid); + entry->prev_cookie, fileid, DT_UNKNOWN); if (res < 0) break; file->f_pos = desc->target = entry->cookie; diff -urN lfs-ref/fs/nfs/file.c lfs/fs/nfs/file.c --- lfs-ref/fs/nfs/file.c Fri Apr 20 22:31:20 2001 +++ lfs/fs/nfs/file.c Wed Sep 12 02:42:15 2001 @@ -164,6 +164,9 @@ static int nfs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) { + if (!NFS_PROTO(file->f_dentry->d_inode)->bigfiles && + page_index(page) > (0x7fffffff>>PAGE_SHIFT)) + return -EFBIG; return nfs_flush_incompatible(file, page); } @@ -232,10 +235,10 @@ struct inode * inode = dentry->d_inode; int status = 0; - dprintk("NFS: nfs_lock(f=%4x/%ld, t=%x, fl=%x, r=%ld:%ld)\n", + dprintk("NFS: nfs_lock(f=%4x/%ld, t=%x, fl=%x, r=%Ld:%Ld)\n", inode->i_dev, inode->i_ino, fl->fl_type, fl->fl_flags, - fl->fl_start, fl->fl_end); + (long long)fl->fl_start, (long long)fl->fl_end); if (!inode) return -EINVAL; diff -urN lfs-ref/fs/nfs/inode.c lfs/fs/nfs/inode.c --- lfs-ref/fs/nfs/inode.c Wed Sep 12 02:05:57 2001 +++ lfs/fs/nfs/inode.c Wed Sep 12 02:42:15 2001 @@ -639,7 +639,7 @@ * Preset the size and mtime, as there's no need * to invalidate the caches. */ - inode->i_size = nfs_size_to_off_t(fattr->size); + inode->i_size = nfs_size_to_loff_t(fattr->size); inode->i_mtime = nfs_time_to_secs(fattr->mtime); inode->i_atime = nfs_time_to_secs(fattr->atime); inode->i_ctime = nfs_time_to_secs(fattr->ctime); @@ -773,6 +773,11 @@ if (!S_ISREG(inode->i_mode)) attr->ia_valid &= ~ATTR_SIZE; + error = -EFBIG; + if ((attr->ia_valid & ATTR_SIZE) && !NFS_PROTO(inode)->bigfiles && + attr->ia_size > 0x7fffffff) + goto out; + error = nfs_wb_all(inode); if (error < 0) goto out; @@ -831,6 +836,10 @@ struct rpc_cred *cred = rpcauth_lookupcred(auth, 0); filp->private_data = cred; + + if (!NFS_PROTO(filp->f_dentry->d_inode)->bigfiles) + filp->f_flags &= ~O_LARGEFILE; + return 0; } @@ -912,8 +921,8 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) { - off_t new_size, new_isize; - __u64 new_mtime; + __u64 new_size, new_mtime; + loff_t new_isize; int invalid = 0; int error = -EIO; @@ -960,7 +969,7 @@ new_mtime = fattr->mtime; new_size = fattr->size; - new_isize = nfs_size_to_off_t(fattr->size); + new_isize = nfs_size_to_loff_t(fattr->size); error = 0; diff -urN lfs-ref/fs/nfs/nfs3proc.c lfs/fs/nfs/nfs3proc.c --- lfs-ref/fs/nfs/nfs3proc.c Fri Apr 20 22:31:20 2001 +++ lfs/fs/nfs/nfs3proc.c Wed Sep 12 02:42:15 2001 @@ -145,7 +145,7 @@ static int nfs3_proc_read(struct inode *inode, struct rpc_cred *cred, struct nfs_fattr *fattr, int flags, - unsigned long offset, unsigned int count, + loff_t offset, unsigned int count, void *buffer, int *eofp) { struct nfs_readargs arg = { NFS_FH(inode), offset, count, 1, @@ -155,7 +155,7 @@ struct rpc_message msg = { NFS3PROC_READ, &arg, &res, cred }; int status; - dprintk("NFS call read %d @ %ld\n", count, offset); + dprintk("NFS call read %d @ %Ld\n", count, (long long) offset); fattr->valid = 0; status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); dprintk("NFS reply read: %d\n", status); @@ -166,7 +166,7 @@ static int nfs3_proc_write(struct inode *inode, struct rpc_cred *cred, struct nfs_fattr *fattr, int flags, - unsigned long offset, unsigned int count, + loff_t offset, unsigned int count, void *buffer, struct nfs_writeverf *verf) { struct nfs_writeargs arg = { NFS_FH(inode), offset, count, @@ -177,7 +177,7 @@ struct rpc_message msg = { NFS3PROC_WRITE, &arg, &res, cred }; int status, rpcflags = 0; - dprintk("NFS call write %d @ %ld\n", count, offset); + dprintk("NFS call write %d @ %Ld\n", count, (long long) offset); fattr->valid = 0; if (flags & NFS_RW_SWAP) rpcflags |= NFS_RPC_SWAPFLAGS; @@ -517,4 +517,6 @@ nfs3_proc_statfs, nfs3_decode_dirent, + + 1, }; diff -urN lfs-ref/fs/nfs/proc.c lfs/fs/nfs/proc.c --- lfs-ref/fs/nfs/proc.c Fri Apr 20 22:31:20 2001 +++ lfs/fs/nfs/proc.c Wed Sep 12 02:42:15 2001 @@ -134,7 +134,7 @@ static int nfs_proc_read(struct inode *inode, struct rpc_cred *cred, fattr *fattr, - int flags, unsigned long offset, unsigned int count, + int flags, loff_t offset, unsigned int count, void *buffer, int *eofp) { struct nfs_readargs arg = { NFS_FH(inode), offset, count, 1, @@ -144,7 +144,7 @@ struct rpc_message msg = { NFSPROC_READ, &arg, &res, cred }; int status; - dprintk("NFS call read %d @ %ld\n", count, offset); + dprintk("NFS call read %d @ %Ld\n", count, (long long) offset); fattr->valid = 0; status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); @@ -155,7 +155,7 @@ static int nfs_proc_write(struct inode *inode, struct rpc_cred *cred, fattr *fattr, - int how, unsigned long offset, unsigned int count, + int how, loff_t offset, unsigned int count, void *buffer, struct nfs_writeverf *verf) { struct nfs_writeargs arg = {NFS_FH(inode), offset, count, @@ -166,7 +166,7 @@ struct rpc_message msg = { NFSPROC_WRITE, &arg, &res, cred }; int status, flags = 0; - dprintk("NFS call write %d @ %ld\n", count, offset); + dprintk("NFS call write %d @ %Ld\n", count, (long long) offset); fattr->valid = 0; if (how & NFS_RW_SWAP) flags |= NFS_RPC_SWAPFLAGS; @@ -407,4 +407,5 @@ nfs_proc_mknod, nfs_proc_statfs, nfs_decode_dirent, + 0, }; diff -urN lfs-ref/fs/nfs/read.c lfs/fs/nfs/read.c --- lfs-ref/fs/nfs/read.c Fri Apr 20 22:31:20 2001 +++ lfs/fs/nfs/read.c Wed Sep 12 02:42:15 2001 @@ -91,7 +91,7 @@ { struct rpc_cred *cred = NULL; struct nfs_fattr fattr; - unsigned long offset = nfs_page_offset(page); + loff_t offset = nfs_page_offset(page); char *buffer = (char *) page_address(page); int rsize = NFS_SERVER(inode)->rsize; int result, refresh = 0; @@ -112,10 +112,10 @@ if ((chunk = rsize) > count) chunk = count; - dprintk("NFS: nfs_proc_read(%s, (%x/%Ld), %ld, %d, %p)\n", + dprintk("NFS: nfs_proc_read(%s, (%x/%Ld), %Ld, %d, %p)\n", NFS_SERVER(inode)->hostname, inode->i_dev, (long long)NFS_FILEID(inode), - offset, chunk, buffer); + (long long) offset, chunk, buffer); result = NFS_PROTO(inode)->read(inode, cred, &fattr, flags, offset, chunk, buffer, &eof); @@ -439,11 +439,11 @@ set_bit(PG_error, &page->flags); nfs_unlock_page(page); - dprintk("NFS: read (%x/%Ld %d@%ld)\n", + dprintk("NFS: read (%x/%Ld %d@%Ld)\n", req->wb_inode->i_dev, (long long)NFS_FILEID(req->wb_inode), req->wb_bytes, - (nfs_page_offset(page) + req->wb_offset)); + (long long)(nfs_page_offset(page) + req->wb_offset)); nfs_unlock_request(req); nfs_release_request(req); } @@ -475,8 +475,8 @@ else inode = file->f_dentry->d_inode; - dprintk("NFS: nfs_readpage (%p %ld@%lu)\n", - page, PAGE_CACHE_SIZE, page->offset); + dprintk("NFS: nfs_readpage (%p %ld@%Lu)\n", + page, PAGE_CACHE_SIZE, (long long) nfs_page_offset(page)); /* * Try to flush any pending writes to the file diff -urN lfs-ref/fs/nfs/write.c lfs/fs/nfs/write.c --- lfs-ref/fs/nfs/write.c Fri Apr 20 22:31:20 2001 +++ lfs/fs/nfs/write.c Wed Sep 12 02:42:15 2001 @@ -144,7 +144,7 @@ */ static int nfs_writepage_sync(struct file *file, struct inode *inode, struct page *page, - unsigned long offset, unsigned int count) + unsigned int offset, unsigned int count) { struct rpc_cred *cred = NULL; unsigned int wsize = NFS_SERVER(inode)->wsize; @@ -152,16 +152,17 @@ u8 *buffer; struct nfs_fattr fattr; struct nfs_writeverf verifier; + loff_t base; if (file) cred = nfs_file_cred(file); - dprintk("NFS: nfs_writepage_sync(%x/%Ld %d@%ld)\n", + dprintk("NFS: nfs_writepage_sync(%x/%Ld %d@%Ld)\n", inode->i_dev, (long long)NFS_FILEID(inode), - count, nfs_page_offset(page) + offset); + count, (long long) (nfs_page_offset(page) + offset)); buffer = (u8 *) page_address(page) + offset; - offset += nfs_page_offset(page); + base = nfs_page_offset(page) + offset; flags = ((IS_SWAPFILE(inode)) ? NFS_RW_SWAP : 0) | NFS_RW_SYNC; @@ -170,7 +171,7 @@ wsize = count; result = NFS_PROTO(inode)->write(inode, cred, &fattr, flags, - offset, wsize, buffer, + base, wsize, buffer, &verifier); nfs_write_attributes(inode, &fattr); @@ -184,15 +185,15 @@ wsize, result); refresh = 1; buffer += wsize; - offset += wsize; + base += wsize; written += wsize; count -= wsize; /* * If we've extended the file, update the inode * now so we don't invalidate the cache. */ - if (offset > inode->i_size) - inode->i_size = offset; + if (base > inode->i_size) + inode->i_size = base; } while (count); io_error: @@ -213,9 +214,9 @@ inode = page->inode; else inode = file->f_dentry->d_inode; - if (page->offset >= inode->i_size) + if (nfs_page_offset(page) >= inode->i_size) return -EIO; - if (page->offset + offset > inode->i_size) + if (nfs_page_offset(page) + offset > inode->i_size) offset = inode->i_size & (PAGE_CACHE_SIZE-1); return nfs_writepage_sync(file, inode, page, 0, offset); } @@ -228,7 +229,7 @@ region_locked(struct inode *inode, struct nfs_page *req) { struct file_lock *fl; - unsigned long rqstart, rqend; + loff_t rqstart, rqend; /* Don't optimize writes if we don't use NLM */ if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM) @@ -895,9 +896,9 @@ struct nfs_page *req; int status = 0; - dprintk("NFS: nfs_updatepage(%s/%s %d@%ld, sync=%d)\n", + dprintk("NFS: nfs_updatepage(%s/%s %d@%Ld, sync=%d)\n", dentry->d_parent->d_name.name, dentry->d_name.name, - count, nfs_page_offset(page)+offset, sync); + count, (long long) (nfs_page_offset(page)+offset), sync); /* * If wsize is smaller than page size, update and write @@ -947,8 +948,8 @@ } nfs_release_request(req); done: - dprintk("NFS: nfs_updatepage returns %d (isize %ld)\n", - status, inode->i_size); + dprintk("NFS: nfs_updatepage returns %d (isize %Ld)\n", + status, (long long) inode->i_size); if (status < 0) clear_bit(PG_uptodate, &page->flags); return status; @@ -1193,18 +1194,18 @@ { struct nfs_page *req; struct inode *inode; - unsigned long start, end, len; + loff_t start, end, len; /* Set up the RPC argument and reply structs * NB: take care not to mess about with data->commit et al. */ end = 0; - start = ~0; + start = NFS_OFFSET_MAX; req = nfs_list_entry(head->next); inode = req->wb_inode; while (!list_empty(head)) { struct nfs_page *req; - unsigned long rqstart, rqend; + loff_t rqstart, rqend; req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_list_add_request(req, &data->pages); @@ -1220,7 +1221,7 @@ data->args.fh = NFS_FH(inode); data->args.offset = start; len = end - start; - if (end >= inode->i_size || len > (~((u32)0) >> 1)) + if (end >= inode->i_size || len < 0 || len > (~((u32)0) >> 1)) len = 0; data->res.count = data->args.count = (u32)len; data->res.fattr = &data->fattr; @@ -1298,11 +1299,11 @@ req = nfs_list_entry(data->pages.next); nfs_list_remove_request(req); - dprintk("NFS: commit (%x/%Ld %d@%ld)", + dprintk("NFS: commit (%x/%Ld %d@%Ld)", req->wb_inode->i_dev, (long long)NFS_FILEID(req->wb_inode), req->wb_bytes, - nfs_page_offset(req->wb_page) + req->wb_offset); + (long long) (nfs_page_offset(req->wb_page) + req->wb_offset)); if (task->tk_status < 0) { if (req->wb_file) req->wb_file->f_error = task->tk_status; diff -urN lfs-ref/fs/nfsd/nfs3xdr.c lfs/fs/nfsd/nfs3xdr.c --- lfs-ref/fs/nfsd/nfs3xdr.c Fri Apr 20 22:31:20 2001 +++ lfs/fs/nfsd/nfs3xdr.c Wed Sep 12 02:42:15 2001 @@ -131,9 +131,9 @@ iap->ia_valid |= ATTR_SIZE; p = xdr_decode_hyper(p, &newsize); if (newsize <= NFS_OFFSET_MAX) - iap->ia_size = (u32) newsize; + iap->ia_size = newsize; else - iap->ia_size = ~(size_t) 0; + iap->ia_size = NFS_OFFSET_MAX; } if ((tmp = ntohl(*p++)) == 1) { /* set to server time */ iap->ia_valid |= ATTR_ATIME; @@ -678,11 +678,6 @@ if (name == 0) return 0; - /* - dprintk("encode_entry(%.*s @%ld%s)\n", - namlen, name, (long) offset, plus? " plus" : ""); - */ - /* truncate filename if too long */ if (namlen > NFS3_MAXNAMLEN) namlen = NFS3_MAXNAMLEN; @@ -727,14 +722,14 @@ int nfs3svc_encode_entry(struct readdir_cd *cd, const char *name, - int namlen, off_t offset, ino_t ino) + int namlen, off_t offset, ino_t ino, unsigned int d_type) { return encode_entry(cd, name, namlen, offset, ino, 0); } int nfs3svc_encode_entry_plus(struct readdir_cd *cd, const char *name, - int namlen, off_t offset, ino_t ino) + int namlen, off_t offset, ino_t ino, unsigned int d_type) { return encode_entry(cd, name, namlen, offset, ino, 1); } diff -urN lfs-ref/fs/nfsd/nfsfh.c lfs/fs/nfsd/nfsfh.c --- lfs-ref/fs/nfsd/nfsfh.c Fri Apr 20 22:31:20 2001 +++ lfs/fs/nfsd/nfsfh.c Wed Sep 12 02:42:15 2001 @@ -41,7 +41,7 @@ * the name matching the specified inode number. */ static int filldir_one(void * __buf, const char * name, int len, - off_t pos, ino_t ino) + off_t pos, ino_t ino, unsigned int d_type) { struct nfsd_getdents_callback *buf = __buf; struct qstr *qs = buf->name; diff -urN lfs-ref/fs/nfsd/nfssvc.c lfs/fs/nfsd/nfssvc.c --- lfs-ref/fs/nfsd/nfssvc.c Wed Sep 12 02:05:57 2001 +++ lfs/fs/nfsd/nfssvc.c Wed Sep 12 02:42:15 2001 @@ -123,6 +123,7 @@ current->session = 1; current->pgrp = 1; current->fs->umask = 0; + current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; /* Count active threads */ atomic_inc(&nfsd_active); diff -urN lfs-ref/fs/nfsd/nfsxdr.c lfs/fs/nfsd/nfsxdr.c --- lfs-ref/fs/nfsd/nfsxdr.c Fri Apr 20 22:31:20 2001 +++ lfs/fs/nfsd/nfsxdr.c Wed Sep 12 02:42:15 2001 @@ -394,7 +394,7 @@ int nfssvc_encode_entry(struct readdir_cd *cd, const char *name, - int namlen, off_t offset, ino_t ino) + int namlen, off_t offset, ino_t ino, unsigned int d_type) { u32 *p = cd->buffer; int buflen, slen; diff -urN lfs-ref/fs/nfsd/vfs.c lfs/fs/nfsd/vfs.c --- lfs-ref/fs/nfsd/vfs.c Fri Apr 20 22:31:20 2001 +++ lfs/fs/nfsd/vfs.c Wed Sep 12 02:42:15 2001 @@ -513,11 +513,11 @@ filp->f_count = 1; filp->f_dentry = dentry; if (access & MAY_WRITE) { - filp->f_flags = O_WRONLY; + filp->f_flags = O_WRONLY | O_LARGEFILE; filp->f_mode = FMODE_WRITE; DQUOT_INIT(inode); } else { - filp->f_flags = O_RDONLY; + filp->f_flags = O_RDONLY | O_LARGEFILE; filp->f_mode = FMODE_READ; } @@ -658,8 +658,9 @@ /* Write back readahead params */ if (ra != NULL) { dprintk("nfsd: raparms %ld %ld %ld %ld %ld\n", - file.f_reada, file.f_ramax, file.f_raend, - file.f_ralen, file.f_rawin); + (u_long)file.f_reada, (u_long)file.f_ramax, + (u_long)file.f_raend, (u_long)file.f_ralen, + (u_long)file.f_rawin); ra->p_reada = file.f_reada; ra->p_ramax = file.f_ramax; ra->p_raend = file.f_raend; diff -urN lfs-ref/fs/ntfs/fs.c lfs/fs/ntfs/fs.c --- lfs-ref/fs/ntfs/fs.c Wed Sep 12 02:05:57 2001 +++ lfs/fs/ntfs/fs.c Wed Sep 12 02:42:15 2001 @@ -200,7 +200,7 @@ /* filldir expects an off_t rather than an loff_t. Hope we don't have more than 65535 index records */ error=nf->filldir(nf->dirent,nf->name,nf->namelen, - (nf->ph<<16)|nf->pl,inum); + (nf->ph<<16)|nf->pl,inum,DT_UNKNOWN); ntfs_free(nf->name); /* Linux filldir errors are negative, other errors positive */ return error; @@ -226,11 +226,11 @@ if(cb.ph==0xFFFF){ /* FIXME: Maybe we can return those with the previous call */ switch(cb.pl){ - case 0: filldir(dirent,".",1,filp->f_pos,dir->i_ino); + case 0: filldir(dirent,".",1,filp->f_pos,dir->i_ino,DT_DIR); filp->f_pos=0xFFFF0001; return 0; /* FIXME: parent directory */ - case 1: filldir(dirent,"..",2,filp->f_pos,0); + case 1: filldir(dirent,"..",2,filp->f_pos,0,DT_DIR); filp->f_pos=0xFFFF0002; return 0; } @@ -823,6 +823,7 @@ struct statfs fs; struct inode *mft; ntfs_volume *vol; + ntfs_u64 size; int error; ntfs_debug(DEBUG_OTHER, "ntfs_statfs\n"); @@ -831,16 +832,17 @@ fs.f_type=NTFS_SUPER_MAGIC; fs.f_bsize=vol->clustersize; - error = ntfs_get_volumesize( NTFS_SB2VOL( sb ), &fs.f_blocks ); + error = ntfs_get_volumesize( NTFS_SB2VOL( sb ), &size ); if( error ) return -error; + fs.f_blocks = size; fs.f_bfree=ntfs_get_free_cluster_count(vol->bitmap); fs.f_bavail=fs.f_bfree; /* Number of files is limited by free space only, so we lie here */ fs.f_ffree=0; mft=iget(sb,FILE_MFT); - fs.f_files=mft->i_size/vol->mft_recordsize; + fs.f_files = (long)mft->i_size / vol->mft_recordsize; iput(mft); /* should be read from volume */ diff -urN lfs-ref/fs/ntfs/super.c lfs/fs/ntfs/super.c --- lfs-ref/fs/ntfs/super.c Mon Dec 11 16:58:03 2000 +++ lfs/fs/ntfs/super.c Wed Sep 12 02:42:15 2001 @@ -304,7 +304,7 @@ * Writes the volume size into vol_size. Returns 0 if successful * or error. */ -int ntfs_get_volumesize(ntfs_volume *vol, long *vol_size ) +int ntfs_get_volumesize(ntfs_volume *vol, ntfs_u64 *vol_size ) { ntfs_io io; ntfs_u64 size; @@ -325,9 +325,7 @@ ntfs_getput_clusters(vol,0,0,&io); size=NTFS_GETU64(cluster0+0x28); ntfs_free(cluster0); - /* FIXME: more than 2**32 cluster */ - /* FIXME: gcc will emit udivdi3 if we don't truncate it */ - *vol_size = ((unsigned long)size)/vol->clusterfactor; + *vol_size = size; return 0; } diff -urN lfs-ref/fs/ntfs/super.h lfs/fs/ntfs/super.h --- lfs-ref/fs/ntfs/super.h Mon Jan 17 16:44:42 2000 +++ lfs/fs/ntfs/super.h Wed Sep 12 02:42:15 2001 @@ -10,7 +10,7 @@ #define ALLOC_REQUIRE_SIZE 2 int ntfs_get_free_cluster_count(ntfs_inode *bitmap); -int ntfs_get_volumesize(ntfs_volume *vol, long *vol_size ); +int ntfs_get_volumesize(ntfs_volume *vol, ntfs_u64 *vol_size ); int ntfs_init_volume(ntfs_volume *vol,char *boot); int ntfs_load_special_files(ntfs_volume *vol); int ntfs_release_volume(ntfs_volume *vol); diff -urN lfs-ref/fs/open.c lfs/fs/open.c --- lfs-ref/fs/open.c Wed Sep 12 02:05:57 2001 +++ lfs/fs/open.c Wed Sep 12 02:42:15 2001 @@ -12,7 +12,7 @@ #include -asmlinkage int sys_statfs(const char * path, struct statfs * buf) +asmlinkage long sys_statfs(const char * path, struct statfs * buf) { struct dentry * dentry; int error; @@ -34,7 +34,7 @@ return error; } -asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf) +asmlinkage long sys_fstatfs(unsigned int fd, struct statfs * buf) { struct file * file; struct inode * inode; @@ -63,15 +63,16 @@ return error; } -int do_truncate(struct dentry *dentry, unsigned long length) +int do_truncate(struct dentry *dentry, loff_t length) { struct inode *inode = dentry->d_inode; int error; struct iattr newattrs; - /* Not pretty: "inode->i_size" shouldn't really be "off_t". But it is. */ - if ((off_t) length < 0) - return -EINVAL; + /* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */ + error = -EINVAL; + if (length < 0) + goto out; fs_down(&inode->i_sem); newattrs.ia_size = length; @@ -84,10 +85,11 @@ inode->i_op->truncate(inode); } fs_up(&inode->i_sem); +out: return error; } -asmlinkage int sys_truncate(const char * path, unsigned long length) +static inline long do_sys_truncate(const char * path, loff_t length) { struct dentry * dentry; struct inode * inode; @@ -136,7 +138,12 @@ return error; } -asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length) +asmlinkage long sys_truncate(const char * path, unsigned long length) +{ + return do_sys_truncate(path, length); +} + +static inline long do_sys_ftruncate(unsigned int fd, loff_t length) { struct inode * inode; struct dentry *dentry; @@ -171,6 +178,24 @@ return error; } +asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length) +{ + return do_sys_ftruncate(fd, length); +} + +/* LFS versions of truncate are only needed on 32 bit machines */ +#if BITS_PER_LONG == 32 +asmlinkage long sys_truncate64(const char * path, loff_t length) +{ + return do_sys_truncate(path, length); +} + +asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length) +{ + return do_sys_ftruncate(fd, length); +} +#endif + #ifndef __alpha__ /* @@ -184,7 +209,7 @@ * must be owner or have write permission. * Else, update from *times, must be owner or super user. */ -asmlinkage int sys_utime(char * filename, struct utimbuf * times) +asmlinkage long sys_utime(char * filename, struct utimbuf * times) { int error; struct dentry * dentry; @@ -232,7 +257,7 @@ * must be owner or have write permission. * Else, update from *times, must be owner or super user. */ -asmlinkage int sys_utimes(char * filename, struct timeval * utimes) +asmlinkage long sys_utimes(char * filename, struct timeval * utimes) { int error; struct dentry * dentry; @@ -278,7 +303,7 @@ * We do this by temporarily clearing all FS-related capabilities and * switching the fsuid/fsgid around to the real ones. */ -asmlinkage int sys_access(const char * filename, int mode) +asmlinkage long sys_access(const char * filename, int mode) { struct dentry * dentry; int old_fsuid, old_fsgid; @@ -325,7 +350,7 @@ return res; } -asmlinkage int sys_chdir(const char * filename) +asmlinkage long sys_chdir(const char * filename) { int error; struct inode *inode; @@ -360,7 +385,7 @@ return error; } -asmlinkage int sys_fchdir(unsigned int fd) +asmlinkage long sys_fchdir(unsigned int fd) { struct file *file; struct dentry *dentry; @@ -397,7 +422,7 @@ return error; } -asmlinkage int sys_chroot(const char * filename) +asmlinkage long sys_chroot(const char * filename) { int error; struct inode *inode; @@ -437,7 +462,7 @@ return error; } -asmlinkage int sys_fchmod(unsigned int fd, mode_t mode) +asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) { struct inode * inode; struct dentry * dentry; @@ -475,7 +500,7 @@ return err; } -asmlinkage int sys_chmod(const char * filename, mode_t mode) +asmlinkage long sys_chmod(const char * filename, mode_t mode) { struct dentry * dentry; struct inode * inode; @@ -571,7 +596,7 @@ return error; } -asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group) +asmlinkage long sys_chown(const char * filename, uid_t user, gid_t group) { struct dentry * dentry; int error; @@ -588,7 +613,7 @@ return error; } -asmlinkage int sys_lchown(const char * filename, uid_t user, gid_t group) +asmlinkage long sys_lchown(const char * filename, uid_t user, gid_t group) { struct dentry * dentry; int error; @@ -606,7 +631,7 @@ } -asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group) +asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group) { struct dentry * dentry; struct file * file; @@ -651,6 +676,9 @@ f = get_empty_filp(); if (!f) goto out; +#if BITS_PER_LONG != 32 + flags |= O_LARGEFILE; +#endif f->f_flags = flag = flags; f->f_mode = (flag+1) & O_ACCMODE; if (f->f_mode) @@ -789,7 +817,7 @@ * For backward compatibility? Maybe this should be moved * into arch/i386 instead? */ -asmlinkage int sys_creat(const char * pathname, int mode) +asmlinkage long sys_creat(const char * pathname, int mode) { return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode); } @@ -862,7 +890,7 @@ * This routine simulates a hangup on the tty, to arrange that users * are given clean terminals at login time. */ -asmlinkage int sys_vhangup(void) +asmlinkage long sys_vhangup(void) { int ret = -EPERM; diff -urN lfs-ref/fs/proc/array.c lfs/fs/proc/array.c --- lfs-ref/fs/proc/array.c Wed Sep 12 02:39:57 2001 +++ lfs/fs/proc/array.c Wed Sep 12 02:42:15 2001 @@ -1173,11 +1173,11 @@ * + (index into the line) */ /* for systems with sizeof(void*) == 4: */ -#define MAPS_LINE_FORMAT4 "%08lx-%08lx %s %08lx %s %lu" -#define MAPS_LINE_MAX4 49 /* sum of 8 1 8 1 4 1 8 1 5 1 10 1 */ +#define MAPS_LINE_FORMAT4 "%08lx-%08lx %s %016Lx %s %lu" +#define MAPS_LINE_MAX4 57 /* sum of 8 1 8 1 4 1 16 1 5 1 10 1 */ /* for systems with sizeof(void*) == 8: */ -#define MAPS_LINE_FORMAT8 "%016lx-%016lx %s %016lx %s %lu" +#define MAPS_LINE_FORMAT8 "%016lx-%016lx %s %016Lx %s %lu" #define MAPS_LINE_MAX8 73 /* sum of 16 1 16 1 4 1 16 1 5 1 10 1 */ #define MAPS_LINE_MAX MAPS_LINE_MAX8 diff -urN lfs-ref/fs/proc/fd.c lfs/fs/proc/fd.c --- lfs-ref/fs/proc/fd.c Wed Sep 12 02:39:56 2001 +++ lfs/fs/proc/fd.c Wed Sep 12 02:42:15 2001 @@ -146,7 +146,7 @@ ino = inode->i_ino; if (fd) ino = (ino & 0xffff0000) | PROC_PID_INO; - if (filldir(dirent, "..", fd+1, fd, ino) < 0) + if (filldir(dirent, "..", fd+1, fd, ino, DT_DIR) < 0) goto out; } @@ -176,7 +176,7 @@ read_unlock(&tasklist_lock); ino = (pid << 16) + PROC_PID_FD_DIR + fd; - if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino) < 0) + if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino, DT_LNK) < 0) goto out; read_lock(&tasklist_lock); diff -urN lfs-ref/fs/proc/openpromfs.c lfs/fs/proc/openpromfs.c --- lfs-ref/fs/proc/openpromfs.c Mon Jan 17 16:44:43 2000 +++ lfs/fs/proc/openpromfs.c Wed Sep 12 02:42:15 2001 @@ -846,14 +846,14 @@ i = filp->f_pos; switch (i) { case 0: - if (filldir(dirent, ".", 1, i, ino) < 0) return 0; + if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) return 0; i++; filp->f_pos++; /* fall thru */ case 1: if (filldir(dirent, "..", 2, i, (NODE(ino).parent == 0xffff) ? - PROC_ROOT_INO : NODE2INO(NODE(ino).parent)) < 0) + PROC_ROOT_INO : NODE2INO(NODE(ino).parent), DT_DIR) < 0) return 0; i++; filp->f_pos++; @@ -869,14 +869,14 @@ if (prom_getname (nodes[node].node, buffer, 128) < 0) return 0; if (filldir(dirent, buffer, strlen(buffer), - filp->f_pos, NODE2INO(node)) < 0) + filp->f_pos, NODE2INO(node), DT_DIR) < 0) return 0; filp->f_pos++; node = nodes[node].next; } j = NODEP2INO(NODE(ino).first_prop); if (!i) { - if (filldir(dirent, ".node", 5, filp->f_pos, j) < 0) + if (filldir(dirent, ".node", 5, filp->f_pos, j, DT_REG) < 0) return 0; filp->f_pos++; } else @@ -887,7 +887,7 @@ if (alias_names [i]) { if (filldir (dirent, alias_names [i], strlen (alias_names [i]), - filp->f_pos, j) < 0) return 0; + filp->f_pos, j, DT_REG) < 0) return 0; filp->f_pos++; } } @@ -899,7 +899,7 @@ if (i) i--; else { if (filldir(dirent, p, strlen(p), - filp->f_pos, j) < 0) + filp->f_pos, j, DT_REG) < 0) return 0; filp->f_pos++; } @@ -911,7 +911,7 @@ else { if (filldir(dirent, d->name, strlen(d->name), - filp->f_pos, d->inode) < 0) + filp->f_pos, d->inode, d->mode >> 12) < 0) return 0; filp->f_pos++; } diff -urN lfs-ref/fs/proc/root.c lfs/fs/proc/root.c --- lfs-ref/fs/proc/root.c Wed Sep 12 02:39:56 2001 +++ lfs/fs/proc/root.c Wed Sep 12 02:42:15 2001 @@ -890,13 +890,13 @@ i = filp->f_pos; switch (i) { case 0: - if (filldir(dirent, ".", 1, i, ino) < 0) + if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) return 0; i++; filp->f_pos++; /* fall through */ case 1: - if (filldir(dirent, "..", 2, i, de->parent->low_ino) < 0) + if (filldir(dirent, "..", 2, i, de->parent->low_ino, DT_DIR) < 0) return 0; i++; filp->f_pos++; @@ -915,7 +915,7 @@ } do { - if (filldir(dirent, de->name, de->namelen, filp->f_pos, ino | de->low_ino) < 0) + if (filldir(dirent, de->name, de->namelen, filp->f_pos, ino | de->low_ino, de->mode >> 12) < 0) return 0; filp->f_pos++; de = de->next; @@ -982,7 +982,7 @@ pid /= 10; } while (pid); - if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino) < 0) + if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino, DT_DIR) < 0) break; filp->f_pos++; } diff -urN lfs-ref/fs/qnx4/dir.c lfs/fs/qnx4/dir.c --- lfs-ref/fs/qnx4/dir.c Thu May 4 13:00:40 2000 +++ lfs/fs/qnx4/dir.c Wed Sep 12 02:42:15 2001 @@ -61,7 +61,7 @@ QNX4_INODES_PER_BLOCK + le->dl_inode_ndx; } - if (filldir(dirent, de->di_fname, size, filp->f_pos, ino) < 0) { + if (filldir(dirent, de->di_fname, size, filp->f_pos, ino, DT_UNKNOWN) < 0) { brelse(bh); return 0; } diff -urN lfs-ref/fs/read_write.c lfs/fs/read_write.c --- lfs-ref/fs/read_write.c Fri Apr 20 22:31:20 2001 +++ lfs/fs/read_write.c Wed Sep 12 02:42:15 2001 @@ -48,7 +48,7 @@ asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin) { - off_t retval; + off_t retval, oldpos; struct file * file; struct dentry * dentry; struct inode * inode; @@ -62,9 +62,19 @@ if (!(dentry = file->f_dentry) || !(inode = dentry->d_inode)) goto out_putf; + oldpos = file->f_pos; retval = -EINVAL; if (origin <= 2) retval = llseek(file, offset, origin); + + /* Demand L-F-S compliance only from normal files, + thus raw devices can do whatever they please.. */ + if (!(file->f_flags & O_LARGEFILE) && + retval >= 0 && S_ISREG(inode->i_mode) && + file->f_pos > 0x7fffffff) { + file->f_pos = oldpos; + retval = -EOVERFLOW; + } out_putf: fput(file); bad: @@ -81,7 +91,7 @@ struct file * file; struct dentry * dentry; struct inode * inode; - loff_t offset; + loff_t offset, oldpos; lock_kernel(); retval = -EBADF; @@ -96,6 +106,7 @@ if (origin > 2) goto out_putf; + oldpos = file->f_pos; offset = llseek(file, ((loff_t) offset_high << 32) | offset_low, origin); @@ -105,6 +116,14 @@ if (!copy_to_user(result, &offset, sizeof(offset))) retval = 0; } + if (!(file->f_flags & O_LARGEFILE) && S_ISREG(inode->i_mode) && + file->f_pos > 0x7fffffff) { + /* The target position isn't presentable without + O_LARGEFILE flag being set --> yield error, and + restore the file position. */ + file->f_pos = oldpos; + retval = -EOVERFLOW; + } out_putf: fput(file); bad: @@ -335,6 +354,7 @@ ssize_t ret; struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); + struct inode * inode; lock_kernel(); @@ -342,10 +362,13 @@ file = fget(fd); if (!file) goto bad_file; + + inode = file->f_dentry->d_inode; + if (!(file->f_mode & FMODE_READ)) goto out; - ret = locks_verify_area(FLOCK_VERIFY_READ, file->f_dentry->d_inode, - file, pos, count); + + ret = locks_verify_area(FLOCK_VERIFY_READ, inode, file, pos, count); if (ret) goto out; ret = -EINVAL; @@ -367,6 +390,7 @@ ssize_t ret; struct file * file; ssize_t (*write)(struct file *, const char *, size_t, loff_t *); + struct inode * inode; lock_kernel(); @@ -376,8 +400,10 @@ goto bad_file; if (!(file->f_mode & FMODE_WRITE)) goto out; - ret = locks_verify_area(FLOCK_VERIFY_WRITE, file->f_dentry->d_inode, - file, pos, count); + + inode = file->f_dentry->d_inode; + + ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, pos, count); if (ret) goto out; ret = -EINVAL; @@ -386,9 +412,9 @@ if (pos < 0) goto out; - fs_down(&file->f_dentry->d_inode->i_sem); + fs_down(&inode->i_sem); ret = write(file, buf, count, &pos); - fs_up(&file->f_dentry->d_inode->i_sem); + fs_up(&inode->i_sem); out: fput(file); diff -urN lfs-ref/fs/readdir.c lfs/fs/readdir.c --- lfs-ref/fs/readdir.c Mon Jan 17 16:44:43 2000 +++ lfs/fs/readdir.c Wed Sep 12 02:42:15 2001 @@ -36,7 +36,7 @@ int count; }; -static int fillonedir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino) +static int fillonedir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino, unsigned int d_type) { struct readdir_callback * buf = (struct readdir_callback *) __buf; struct old_linux_dirent * dirent; @@ -118,7 +118,7 @@ int error; }; -static int filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino) +static int filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino, unsigned int d_type) { struct linux_dirent * dirent; struct getdents_callback * buf = (struct getdents_callback *) __buf; @@ -187,6 +187,123 @@ lastdirent = buf.previous; if (lastdirent) { put_user(file->f_pos, &lastdirent->d_off); + error = count - buf.count; + } + +out_putf: + fput(file); +out: + unlock_kernel(); + return error; +} + + +/* + * And even better one including d_type field and 64bit d_ino and d_off. + */ +struct linux_dirent64 { + u64 d_ino; + s64 d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[0]; +}; + +#define ROUND_UP64(x) (((x)+sizeof(u64)-1) & ~(sizeof(u64)-1)) + +struct getdents_callback64 { + struct linux_dirent64 * current_dir; + struct linux_dirent64 * previous; + int count; + int error; +}; + +static int filldir64(void * __buf, const char * name, int namlen, off_t offset, + ino_t ino, unsigned int d_type) +{ + struct linux_dirent64 * dirent, d; + struct getdents_callback64 * buf = (struct getdents_callback64 *) __buf; + int reclen = ROUND_UP64(NAME_OFFSET(dirent) + namlen + 1); + + buf->error = -EINVAL; /* only used if we fail.. */ + if (reclen > buf->count) + return -EINVAL; + dirent = buf->previous; + if (dirent) { +#if BITS_PER_LONG < 64 + d.d_off = offset; + copy_to_user(&dirent->d_off, &d.d_off, sizeof(d.d_off)); +#else + put_user(offset, &dirent->d_off); +#endif + } + dirent = buf->current_dir; + buf->previous = dirent; + memset(&d, 0, NAME_OFFSET(&d)); + d.d_ino = ino; + d.d_reclen = reclen; + d.d_type = d_type; + copy_to_user(dirent, &d, NAME_OFFSET(&d)); + copy_to_user(dirent->d_name, name, namlen); + put_user(0, dirent->d_name + namlen); + ((char *) dirent) += reclen; + buf->current_dir = dirent; + buf->count -= reclen; + return 0; +} + +asmlinkage int sys_getdents64(unsigned int fd, void * dirent, unsigned int count) +{ + struct file * file; + struct dentry * dentry; + struct inode * inode; + struct linux_dirent64 * lastdirent; + struct getdents_callback64 buf; + int error; + + lock_kernel(); + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + + dentry = file->f_dentry; + if (!dentry) + goto out_putf; + + inode = dentry->d_inode; + if (!inode) + goto out_putf; + + buf.current_dir = (struct linux_dirent64 *) dirent; + buf.previous = NULL; + buf.count = count; + buf.error = 0; + + error = -ENOTDIR; + if (!file->f_op || !file->f_op->readdir) + goto out_putf; + + + /* + * Get the inode's semaphore to prevent changes + * to the directory while we read it. + */ + down(&inode->i_sem); + error = file->f_op->readdir(file, &buf, filldir64); + up(&inode->i_sem); + if (error < 0) + goto out_putf; + error = buf.error; + lastdirent = buf.previous; + if (lastdirent) { +#if BITS_PER_LONG < 64 + s64 d_off; + d_off = file->f_pos; + copy_to_user(&lastdirent->d_off, &d_off, sizeof(d_off)); +#else + put_user(file->f_pos, &lastdirent->d_off); +#endif error = count - buf.count; } diff -urN lfs-ref/fs/romfs/inode.c lfs/fs/romfs/inode.c --- lfs-ref/fs/romfs/inode.c Thu May 4 13:00:40 2000 +++ lfs/fs/romfs/inode.c Wed Sep 12 02:42:15 2001 @@ -258,6 +258,10 @@ return res; } +static unsigned char romfs_dtype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_SOCK, DT_FIFO +}; + static int romfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { @@ -302,7 +306,8 @@ nextfh = ntohl(ri.next); if ((nextfh & ROMFH_TYPE) == ROMFH_HRD) ino = ntohl(ri.spec); - if (filldir(dirent, fsname, j, offset, ino) < 0) { + if (filldir(dirent, fsname, j, offset, ino, + romfs_dtype_table[nextfh & ROMFH_TYPE]) < 0) { return stored; } stored++; @@ -396,7 +401,7 @@ buf = page_address(page); clear_bit(PG_uptodate, &page->flags); clear_bit(PG_error, &page->flags); - offset = page->offset; + offset = pgoff2loff(page->index); if (offset < inode->i_size) { avail = inode->i_size-offset; readlen = min(avail, PAGE_SIZE); diff -urN lfs-ref/fs/smbfs/cache.c lfs/fs/smbfs/cache.c --- lfs-ref/fs/smbfs/cache.c Tue Sep 5 02:28:49 2000 +++ lfs/fs/smbfs/cache.c Wed Sep 12 02:42:15 2001 @@ -40,7 +40,7 @@ struct cache_head * cachep; VERBOSE("finding cache for %s/%s\n", DENTRY_PATH(dentry)); - cachep = (struct cache_head *) get_cached_page(inode, 0, 1); + cachep = (struct cache_head *) get_cached_page(inode, ulong2pgoff(0), 1); if (!cachep) goto out; if (cachep->valid) @@ -61,9 +61,10 @@ PARANOIA("cache %s/%s has existing block!\n", DENTRY_PATH(dentry)); #endif - offset = PAGE_SIZE + (i << PAGE_SHIFT); - block = (struct cache_block *) get_cached_page(inode, - offset, 0); + /* byte_offset = PAGE_SIZE + (i << PAGE_SHIFT); */ + /* --> page_offset = 1 + i */ + block = (struct cache_block *) + get_cached_page(inode, ulong2pgoff(i+1), 0); if (!block) goto out; index->block = block; @@ -128,7 +129,7 @@ struct inode * inode = get_cache_inode(cachep); struct cache_index * index; struct cache_block * block; - unsigned long page_off; + pgoff_t page_off; unsigned int nent, offset, len = entry->len; unsigned int needed = len + sizeof(struct cache_entry); @@ -180,14 +181,15 @@ */ get_block: cachep->pages++; - page_off = PAGE_SIZE + (cachep->idx << PAGE_SHIFT); + /* page_byte_off = PAGE_SIZE + (cachep->idx << PAGE_SHIFT); */ + page_off = ulong2pgoff(1 + cachep->idx); block = (struct cache_block *) get_cached_page(inode, page_off, 1); if (block) { index->block = block; index->space = PAGE_SIZE; VERBOSE("inode=%p, pages=%d, block at %ld\n", - inode, cachep->pages, page_off); + inode, cachep->pages, (u_long)pgoff2loff(page_off)); goto add_entry; } /* diff -urN lfs-ref/fs/smbfs/dir.c lfs/fs/smbfs/dir.c --- lfs-ref/fs/smbfs/dir.c Mon Dec 11 16:58:03 2000 +++ lfs/fs/smbfs/dir.c Wed Sep 12 02:42:15 2001 @@ -91,12 +91,12 @@ switch ((unsigned int) filp->f_pos) { case 0: - if (filldir(dirent, ".", 1, 0, dir->i_ino) < 0) + if (filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR) < 0) goto out; filp->f_pos = 1; case 1: if (filldir(dirent, "..", 2, 1, - dentry->d_parent->d_inode->i_ino) < 0) + dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) goto out; filp->f_pos = 2; } @@ -151,7 +151,7 @@ } if (filldir(dirent, entry->name, entry->len, - filp->f_pos, entry->ino) < 0) + filp->f_pos, entry->ino, DT_UNKNOWN) < 0) break; filp->f_pos += 1; } diff -urN lfs-ref/fs/smbfs/file.c lfs/fs/smbfs/file.c --- lfs-ref/fs/smbfs/file.c Tue Sep 5 02:28:49 2000 +++ lfs/fs/smbfs/file.c Wed Sep 12 02:42:15 2001 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -47,15 +48,15 @@ smb_readpage_sync(struct dentry *dentry, struct page *page) { char *buffer = (char *) page_address(page); - unsigned long offset = page->offset; + loff_t loffset = pgoff2loff(page->index); int rsize = smb_get_rsize(server_from_dentry(dentry)); int count = PAGE_SIZE; int result; clear_bit(PG_error, &page->flags); - VERBOSE("file %s/%s, count=%d@%ld, rsize=%d\n", - DENTRY_PATH(dentry), count, offset, rsize); + VERBOSE("file %s/%s, count=%d@%Ld, rsize=%d\n", + DENTRY_PATH(dentry), count, loffset, rsize); result = smb_open(dentry, SMB_O_RDONLY); if (result < 0) { @@ -68,12 +69,12 @@ if (count < rsize) rsize = count; - result = smb_proc_read(dentry, offset, rsize, buffer); + result = smb_proc_read(dentry, loffset, rsize, buffer); if (result < 0) goto io_error; count -= result; - offset += result; + loffset += result; buffer += result; dentry->d_inode->i_atime = CURRENT_TIME; if (result < rsize) @@ -113,23 +114,36 @@ * Offset is the data offset within the page. */ static int -smb_writepage_sync(struct dentry *dentry, struct page *page, +smb_writepage_sync(struct file *file, struct page *page, unsigned long offset, unsigned int count) { + struct dentry * dentry = file->f_dentry; struct inode *inode = dentry->d_inode; u8 *buffer = (u8 *) page_address(page) + offset; int wsize = smb_get_wsize(server_from_dentry(dentry)); int result, written = 0; + loff_t loffset = pgoff2loff(page->index) + offset; + + VERBOSE("file %s/%s, count=%d@%Ld, wsize=%d\n", + DENTRY_PATH(dentry), count, loffset, wsize); - offset += page->offset; - VERBOSE("file %s/%s, count=%d@%ld, wsize=%d\n", - DENTRY_PATH(dentry), count, offset, wsize); + if (!(file->f_flags & O_LARGEFILE)) { + if (loffset >= 0x7fffffffULL) + return -EFBIG; + if (loffset + count > 0x7fffffffULL) + count = 0x7fffffff - loffset; + } + + if (loffset >= 0xffffffffULL) /* 4G-1 ??? Or 2G-1 ??? */ + return -EFBIG; + if ((loffset + count) > 0xffffffffULL) + count = 0xffffffffULL - loffset; do { if (count < wsize) wsize = count; - result = smb_proc_write(dentry, offset, wsize, buffer); + result = smb_proc_write(dentry, loffset, wsize, buffer); if (result < 0) break; /* N.B. what if result < wsize?? */ @@ -138,29 +152,27 @@ printk(KERN_DEBUG "short write, wsize=%d, result=%d\n", wsize, result); #endif - buffer += wsize; - offset += wsize; + buffer += wsize; + loffset += wsize; written += wsize; - count -= wsize; + count -= wsize; /* * Update the inode now rather than waiting for a refresh. */ inode->i_mtime = inode->i_atime = CURRENT_TIME; - if (offset > inode->i_size) - inode->i_size = offset; + if (loffset > inode->i_size) + inode->i_size = loffset; inode->u.smbfs_i.cache_valid |= SMB_F_LOCALWRITE; } while (count); return written ? written : result; } /* - * Write a page to the server. This will be used for NFS swapping only - * (for now), and we currently do this synchronously only. + * Write a page to the server. */ static int smb_writepage(struct file *file, struct page *page) { - struct dentry *dentry = file->f_dentry; int result; #ifdef SMBFS_PARANOIA @@ -169,7 +181,7 @@ #endif set_bit(PG_locked, &page->flags); atomic_inc(&page->count); - result = smb_writepage_sync(dentry, page, 0, PAGE_SIZE); + result = smb_writepage_sync(file, page, 0, PAGE_SIZE); smb_unlock_page(page); free_page(page_address(page)); return result; @@ -180,10 +192,10 @@ { struct dentry *dentry = file->f_dentry; - DEBUG1("(%s/%s %d@%ld, sync=%d)\n", - DENTRY_PATH(dentry), count, page->offset+offset, sync); + DEBUG1("(%s/%s %d@%Ld, sync=%d)\n", + DENTRY_PATH(dentry), count, pgoff2loff(page->index)+offset, sync); - return smb_writepage_sync(dentry, page, offset, count); + return smb_writepage_sync(file, page, offset, count); } static ssize_t @@ -192,8 +204,8 @@ struct dentry * dentry = file->f_dentry; ssize_t status; - VERBOSE("file %s/%s, count=%lu@%lu\n", DENTRY_PATH(dentry), - (unsigned long) count, (unsigned long) *ppos); + VERBOSE("file %s/%s, count=%lu@%Lu\n", DENTRY_PATH(dentry), + (unsigned long) count, *ppos); status = smb_revalidate_inode(dentry); if (status) @@ -242,8 +254,8 @@ struct dentry * dentry = file->f_dentry; ssize_t result; - VERBOSE("file %s/%s, count=%lu@%lu, pages=%ld\n", DENTRY_PATH(dentry), - (unsigned long) count, (unsigned long) *ppos, + VERBOSE("file %s/%s, count=%lu@%Lu, pages=%ld\n", DENTRY_PATH(dentry), + (unsigned long) count, *ppos, dentry->d_inode->i_nrpages); result = smb_revalidate_inode(dentry); @@ -261,8 +273,8 @@ if (count > 0) { result = generic_file_write(file, buf, count, ppos); - VERBOSE("pos=%ld, size=%ld, mtime=%ld, atime=%ld\n", - (long) file->f_pos, dentry->d_inode->i_size, + VERBOSE("pos=%Ld, size=%Ld, mtime=%ld, atime=%ld\n", + file->f_pos, dentry->d_inode->i_size, dentry->d_inode->i_mtime, dentry->d_inode->i_atime); } out: diff -urN lfs-ref/fs/smbfs/proc.c lfs/fs/smbfs/proc.c --- lfs-ref/fs/smbfs/proc.c Wed Sep 12 02:05:57 2001 +++ lfs/fs/smbfs/proc.c Wed Sep 12 02:42:15 2001 @@ -1084,13 +1084,16 @@ file-id would not be valid after a reconnection. */ int -smb_proc_read(struct dentry *dentry, off_t offset, int count, char *data) +smb_proc_read(struct dentry *dentry, loff_t offset, int count, char *data) { struct smb_sb_info *server = server_from_dentry(dentry); __u16 returned_count, data_len; unsigned char *buf; int result; + if (offset > 0xffffffff) + return -EIO; + smb_lock_server(server); smb_setup_header(server, SMBread, 5, 0); buf = server->packet; @@ -1133,13 +1136,16 @@ } int -smb_proc_write(struct dentry *dentry, off_t offset, int count, const char *data) +smb_proc_write(struct dentry *dentry, loff_t offset, int count, const char *data) { struct smb_sb_info *server = server_from_dentry(dentry); int result; __u8 *p; - VERBOSE("file %s/%s, count=%d@%ld, packet_size=%d\n", + if (offset > 0xffffffff) + return -EIO; + + VERBOSE("file %s/%s, count=%d@%Ld, packet_size=%d\n", DENTRY_PATH(dentry), count, offset, server->packet_size); smb_lock_server(server); diff -urN lfs-ref/fs/stat.c lfs/fs/stat.c --- lfs-ref/fs/stat.c Mon Jan 17 16:44:43 2000 +++ lfs/fs/stat.c Wed Sep 12 02:42:15 2001 @@ -48,6 +48,10 @@ tmp.st_uid = inode->i_uid; tmp.st_gid = inode->i_gid; tmp.st_rdev = kdev_t_to_nr(inode->i_rdev); +#if BITS_PER_LONG == 32 + if (inode->i_size > 0x7fffffff) + return -EOVERFLOW; +#endif tmp.st_size = inode->i_size; tmp.st_atime = inode->i_atime; tmp.st_mtime = inode->i_mtime; @@ -70,6 +74,10 @@ tmp.st_uid = inode->i_uid; tmp.st_gid = inode->i_gid; tmp.st_rdev = kdev_t_to_nr(inode->i_rdev); +#if BITS_PER_LONG == 32 + if (inode->i_size > 0x7fffffff) + return -EOVERFLOW; +#endif tmp.st_size = inode->i_size; tmp.st_atime = inode->i_atime; tmp.st_mtime = inode->i_mtime; @@ -280,3 +288,127 @@ unlock_kernel(); return error; } + + +/* ---------- LFS-64 ----------- */ +#if !defined(__alpha__) + +static long cp_new_stat64(struct inode * inode, struct stat64 * statbuf) +{ + struct stat64 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; +#ifdef STAT64_HAS_BROKEN_ST_INO + tmp.__st_ino = inode->i_ino; +#endif + tmp.st_mode = inode->i_mode; + tmp.st_nlink = inode->i_nlink; + tmp.st_uid = inode->i_uid; + tmp.st_gid = inode->i_gid; + tmp.st_rdev = kdev_t_to_nr(inode->i_rdev); + tmp.st_atime = inode->i_atime; + tmp.st_mtime = inode->i_mtime; + tmp.st_ctime = inode->i_ctime; + tmp.st_size = inode->i_size; +/* + * 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_BITS; + 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 sys_stat64(char * filename, struct stat64 * statbuf, long flags) +{ + struct dentry * dentry; + int error; + + lock_kernel(); + dentry = namei(filename); + + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { + error = do_revalidate(dentry); + if (!error) + error = cp_new_stat64(dentry->d_inode, statbuf); + + dput(dentry); + } + unlock_kernel(); + return error; +} + +asmlinkage long sys_lstat64(char * filename, struct stat64 * statbuf, long flags) +{ + struct dentry * dentry; + int error; + + lock_kernel(); + dentry = lnamei(filename); + + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { + error = do_revalidate(dentry); + if (!error) + error = cp_new_stat64(dentry->d_inode, statbuf); + + dput(dentry); + } + unlock_kernel(); + return error; +} + +asmlinkage long sys_fstat64(unsigned long fd, struct stat64 * statbuf, long flags) +{ + 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_new_stat64(dentry->d_inode, statbuf); + fput(f); + } + unlock_kernel(); + return err; +} + +#endif /* LFS-64 */ diff -urN lfs-ref/fs/sysv/dir.c lfs/fs/sysv/dir.c --- lfs-ref/fs/sysv/dir.c Mon Jan 17 16:44:43 2000 +++ lfs/fs/sysv/dir.c Wed Sep 12 02:42:15 2001 @@ -100,7 +100,7 @@ inode->i_ino, (off_t) filp->f_pos, sde.inode); i = strnlen(sde.name, SYSV_NAMELEN); - if (filldir(dirent, sde.name, i, filp->f_pos, sde.inode) < 0) { + if (filldir(dirent, sde.name, i, filp->f_pos, sde.inode, DT_UNKNOWN) < 0) { brelse(bh); return 0; } diff -urN lfs-ref/fs/sysv/file.c lfs/fs/sysv/file.c --- lfs-ref/fs/sysv/file.c Mon Jan 17 16:44:43 2000 +++ lfs/fs/sysv/file.c Wed Sep 12 02:42:15 2001 @@ -207,7 +207,7 @@ { struct inode * inode = filp->f_dentry->d_inode; struct super_block * sb = inode->i_sb; - off_t pos; + loff_t pos; ssize_t written, c; struct buffer_head * bh; char * p; @@ -232,6 +232,21 @@ else pos = *ppos; written = 0; + + /* L-F-S spec 2.2.1.27: */ + if (!(filp->f_flags & O_LARGEFILE)) { + if (pos >= 0x7fffffffULL) /* pos@2G forbidden */ + return -EFBIG; + + if (pos + count > 0x7fffffffULL) + /* Write only until end of allowed region */ + count = 0x7fffffffULL - pos; + } + if (pos >= 0xffffffffULL) + return -EFBIG; /* Only up to 4G-1! */ + if ((pos + count) > 0xffffffffULL) + count = 0xffffffffULL - pos; + while (written> sb->sv_block_size_bits, 1); if (!bh) { diff -urN lfs-ref/fs/ufs/balloc.c lfs/fs/ufs/balloc.c --- lfs-ref/fs/ufs/balloc.c Mon Jan 17 16:44:43 2000 +++ lfs/fs/ufs/balloc.c Wed Sep 12 02:42:15 2001 @@ -660,9 +660,9 @@ struct ufs_sb_private_info * uspi; struct ufs_super_block_first * usb1; struct ufs_cylinder_group * ucg; - unsigned start, length, location, result; - unsigned possition, fragsize, blockmap, mask; - unsigned swab; + unsigned int start, length, location, result; + unsigned int possition, fragsize, blockmap, mask; + unsigned int swab; UFSD(("ENTER, cg %u, goal %u, count %u\n", ucpi->c_cgx, goal, count)) @@ -676,7 +676,7 @@ else start = ucpi->c_frotor >> 3; - length = howmany(uspi->s_fpg, 8) - start; + length = ((uspi->s_fpg + 7) >> 3) - start; location = ubh_scanc(UCPI_UBH, ucpi->c_freeoff + start, length, (uspi->s_fpb == 8) ? ufs_fragtable_8fpb : ufs_fragtable_other, 1 << (count - 1 + (uspi->s_fpb & 7))); diff -urN lfs-ref/fs/ufs/dir.c lfs/fs/ufs/dir.c --- lfs-ref/fs/ufs/dir.c Thu May 4 13:00:40 2000 +++ lfs/fs/ufs/dir.c Wed Sep 12 02:42:15 2001 @@ -15,6 +15,7 @@ #include #include +#include #include "swab.h" #include "util.h" @@ -124,11 +125,14 @@ * not the directory has been modified * during the copy operation. */ unsigned long version = inode->i_version; + unsigned char d_type = DT_UNKNOWN; UFSD(("filldir(%s,%u)\n", de->d_name, SWAB32(de->d_ino))) UFSD(("namlen %u\n", ufs_get_de_namlen(de))) + if ((flags & UFS_DE_MASK) == UFS_DE_44BSD) + d_type = de->d_u.d_44.d_type; error = filldir(dirent, de->d_name, ufs_get_de_namlen(de), - filp->f_pos, SWAB32(de->d_ino)); + filp->f_pos, SWAB32(de->d_ino), d_type); if (error) break; if (version != inode->i_version) @@ -170,7 +174,7 @@ error_msg = "inode out of bounds"; if (error_msg != NULL) - ufs_error (sb, function, "bad entry in directory #%lu, size %lu: %s - " + ufs_error (sb, function, "bad entry in directory #%lu, size %Lu: %s - " "offset=%lu, inode=%lu, reclen=%d, namlen=%d", dir->i_ino, dir->i_size, error_msg, offset, (unsigned long) SWAB32(de->d_ino), diff -urN lfs-ref/fs/ufs/file.c lfs/fs/ufs/file.c --- lfs-ref/fs/ufs/file.c Sun Apr 2 21:07:49 2000 +++ lfs/fs/ufs/file.c Wed Sep 12 02:42:15 2001 @@ -140,7 +140,7 @@ loff_t *ppos ) { struct inode * inode = filp->f_dentry->d_inode; - __u32 pos; + loff_t pos; long block; int offset; int written, c; @@ -177,11 +177,14 @@ return -EINVAL; } - /* Check for overflow.. */ - if (pos > (__u32) (pos + count)) { - count = ~pos; /* == 0xFFFFFFFF - pos */ - if (!count) + /* L-F-S spec 2.2.1.27: */ + if (!(filp->f_flags & O_LARGEFILE)) { + if (pos >= 0x7fffffffULL) /* pos@2G forbidden */ return -EFBIG; + + if (pos + count > 0x7fffffffULL) + /* Write only until end of allowed region */ + count = 0x7fffffffULL - pos; } /* diff -urN lfs-ref/fs/ufs/inode.c lfs/fs/ufs/inode.c --- lfs-ref/fs/ufs/inode.c Tue Jun 13 03:48:15 2000 +++ lfs/fs/ufs/inode.c Wed Sep 12 02:42:15 2001 @@ -54,7 +54,7 @@ { unsigned swab = inode->i_sb->u.ufs_sb.s_swab; printk("ino %lu mode 0%6.6o nlink %d uid %d uid32 %u" - " gid %d gid32 %u size %lu blocks %lu\n", + " gid %d gid32 %u size %Lu blocks %lu\n", inode->i_ino, inode->i_mode, inode->i_nlink, inode->i_uid, inode->u.ufs_i.i_uid, inode->i_gid, inode->u.ufs_i.i_gid, inode->i_size, inode->i_blocks); @@ -213,13 +213,14 @@ if (!create) return NULL; limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit < RLIM_INFINITY) { + if (limit != RLIM_INFINITY) { limit >>= sb->s_blocksize_bits; if (new_fragment >= limit) { send_sig(SIGXFSZ, current, 0); return NULL; } } + lastblock = ufs_fragstoblks (lastfrag); lastblockoff = ufs_fragnum (lastfrag); /* @@ -321,7 +322,8 @@ brelse (result); goto repeat; } - if (!create || new_fragment >= (current->rlim[RLIMIT_FSIZE].rlim_cur >> sb->s_blocksize)) { + if (!create || (current->rlim[RLIMIT_FSIZE].rlim_cur != RLIM_INFINITY && + new_fragment >= (current->rlim[RLIMIT_FSIZE].rlim_cur >> sb->s_blocksize))) { brelse (bh); *err = -EFBIG; return NULL; @@ -497,13 +499,10 @@ } /* - * Linux i_size can be 32 on some architectures. We will mark - * big files as read only and let user access first 32 bits. + * Linux i_size used to be 32 bits on some architectures. + * These days we allow access to the entire file as is.. */ - inode->u.ufs_i.i_size = SWAB64(ufs_inode->ui_size); - inode->i_size = (off_t) inode->u.ufs_i.i_size; - if (sizeof(off_t) == 4 && (inode->u.ufs_i.i_size >> 32)) - inode->i_size = (__u32)-1; + inode->i_size = SWAB64(ufs_inode->ui_size); inode->i_atime = SWAB32(ufs_inode->ui_atime.tv_sec); inode->i_ctime = SWAB32(ufs_inode->ui_ctime.tv_sec); @@ -516,7 +515,7 @@ inode->u.ufs_i.i_gen = SWAB32(ufs_inode->ui_gen); inode->u.ufs_i.i_shadow = SWAB32(ufs_inode->ui_u3.ui_sun.ui_shadow); inode->u.ufs_i.i_oeftflag = SWAB32(ufs_inode->ui_u3.ui_sun.ui_oeftflag); - inode->u.ufs_i.i_lastfrag = howmany (inode->i_size, uspi->s_fsize); + inode->u.ufs_i.i_lastfrag = (inode->i_size + uspi->s_fsize -1) >> uspi->s_fshift; if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) inode->i_rdev = to_kdev_t(SWAB32(ufs_inode->ui_u2.ui_addr.ui_db[0])); diff -urN lfs-ref/fs/ufs/super.c lfs/fs/ufs/super.c --- lfs-ref/fs/ufs/super.c Mon Jan 17 16:44:43 2000 +++ lfs/fs/ufs/super.c Wed Sep 12 02:42:15 2001 @@ -328,7 +328,7 @@ * on the device. */ size = uspi->s_cssize; - blks = howmany(size, uspi->s_fsize); + blks = (size + uspi->s_fsize-1) >> uspi->s_fshift; base = space = kmalloc(size, GFP_KERNEL); if (!base) goto failed; @@ -405,7 +405,7 @@ uspi = sb->u.ufs_sb.s_uspi; size = uspi->s_cssize; - blks = howmany(size, uspi->s_fsize); + blks = (size + uspi->s_fsize-1) >> uspi->s_fshift; base = space = (char*) sb->u.ufs_sb.s_csp[0]; for (i = 0; i < blks; i += uspi->s_fpb) { size = uspi->s_bsize; diff -urN lfs-ref/fs/ufs/truncate.c lfs/fs/ufs/truncate.c --- lfs-ref/fs/ufs/truncate.c Mon Jan 17 16:44:43 2000 +++ lfs/fs/ufs/truncate.c Wed Sep 12 02:42:15 2001 @@ -59,8 +59,8 @@ * Linus */ -#define DIRECT_BLOCK howmany (inode->i_size, uspi->s_bsize) -#define DIRECT_FRAGMENT howmany (inode->i_size, uspi->s_fsize) +#define DIRECT_BLOCK ((inode->i_size + uspi->s_bsize -1) >> uspi->s_bshift) +#define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize -1) >> uspi->s_fshift) static int ufs_trunc_direct (struct inode * inode) { @@ -194,7 +194,7 @@ } -static int ufs_trunc_indirect (struct inode * inode, unsigned offset, u32 * p) +static int ufs_trunc_indirect (struct inode * inode, u_long offset, u32 * p) { struct super_block * sb; struct ufs_sb_private_info * uspi; @@ -297,7 +297,7 @@ struct super_block * sb; struct ufs_sb_private_info * uspi; struct ufs_buffer_head * dind_bh; - unsigned i, tmp, dindirect_block; + unsigned int i, tmp, dindirect_block; u32 * dind; int retry = 0; unsigned swab; @@ -308,8 +308,8 @@ swab = sb->u.ufs_sb.s_swab; uspi = sb->u.ufs_sb.s_uspi; - dindirect_block = (DIRECT_BLOCK > offset) - ? ((DIRECT_BLOCK - offset) / uspi->s_apb) : 0; + dindirect_block = ((DIRECT_BLOCK > offset) ? + ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0); retry = 0; tmp = SWAB32(*p); @@ -379,7 +379,7 @@ retry = 0; tindirect_block = (DIRECT_BLOCK > (UFS_NDADDR + uspi->s_apb + uspi->s_2apb)) - ? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) / uspi->s_2apb) : 0; + ? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) >> uspi->s_2apbshift) : 0; p = inode->u.ufs_i.i_u1.i_data + UFS_TIND_BLOCK; if (!(tmp = SWAB32(*p))) return 0; @@ -467,7 +467,8 @@ } } inode->i_mtime = inode->i_ctime = CURRENT_TIME; - inode->u.ufs_i.i_lastfrag = howmany (inode->i_size, uspi->s_fsize); + inode->u.ufs_i.i_lastfrag = + (inode->i_size + uspi->s_fsize -1) >> uspi->s_fshift; mark_inode_dirty(inode); UFSD(("EXIT\n")) } diff -urN lfs-ref/fs/ufs/util.h lfs/fs/ufs/util.h --- lfs-ref/fs/ufs/util.h Sat May 20 00:06:21 2000 +++ lfs/fs/ufs/util.h Wed Sep 12 02:42:15 2001 @@ -14,7 +14,6 @@ * some useful macros */ #define in_range(b,first,len) ((b)>=(first)&&(b)<(first)+(len)) -#define howmany(x,y) (((x)+(y)-1)/(y)) #define min(x,y) ((x)<(y)?(x):(y)) #define max(x,y) ((x)>(y)?(x):(y)) diff -urN lfs-ref/fs/umsdos/dir.c lfs/fs/umsdos/dir.c --- lfs-ref/fs/umsdos/dir.c Thu May 4 13:00:40 2000 +++ lfs/fs/umsdos/dir.c Wed Sep 12 02:42:15 2001 @@ -90,7 +90,7 @@ if (d->count == 0) { PRINTK ((KERN_DEBUG "dir_once :%.*s: offset %Ld\n", len, name, offset)); - ret = d->filldir (d->dirbuf, name, len, offset, ino); + ret = d->filldir (d->dirbuf, name, len, offset, ino, DT_UNKNOWN); d->stop = ret < 0; d->count = 1; } @@ -136,7 +136,7 @@ Printk ((KERN_WARNING "umsdos_readdir_x: pseudo_root thing UMSDOS_SPECIAL_DIRFPOS\n")); if (filldir (dirbuf, "DOS", 3, - UMSDOS_SPECIAL_DIRFPOS, UMSDOS_ROOT_INO) == 0) { + UMSDOS_SPECIAL_DIRFPOS, UMSDOS_ROOT_INO, DT_DIR) == 0) { filp->f_pos++; } goto out_end; @@ -255,7 +255,7 @@ if (inode != pseudo_root && (internal_read || !(entry.flags & UMSDOS_HIDDEN))) { if (filldir (dirbuf, entry.name, entry.name_len, - cur_f_pos, inode->i_ino) < 0) { + cur_f_pos, inode->i_ino, DT_UNKNOWN) < 0) { new_filp.f_pos = cur_f_pos; } Printk(("umsdos_readdir_x: got %s/%s, ino=%ld\n", diff -urN lfs-ref/fs/umsdos/rdir.c lfs/fs/umsdos/rdir.c --- lfs-ref/fs/umsdos/rdir.c Thu May 4 13:00:40 2000 +++ lfs/fs/umsdos/rdir.c Wed Sep 12 02:42:15 2001 @@ -33,7 +33,8 @@ const char *name, int name_len, off_t offset, - ino_t ino) + ino_t ino, + unsigned int d_type) { int ret = 0; struct RDIR_FILLDIR *d = (struct RDIR_FILLDIR *) buf; @@ -48,11 +49,11 @@ /* Make sure the .. entry points back to the pseudo_root */ ino = pseudo_root->i_ino; } - ret = d->filldir (d->dirbuf, name, name_len, offset, ino); + ret = d->filldir (d->dirbuf, name, name_len, offset, ino, DT_UNKNOWN); } } else { /* Any DOS directory */ - ret = d->filldir (d->dirbuf, name, name_len, offset, ino); + ret = d->filldir (d->dirbuf, name, name_len, offset, ino, DT_UNKNOWN); } return ret; } diff -urN lfs-ref/include/asm-alpha/fcntl.h lfs/include/asm-alpha/fcntl.h --- lfs-ref/include/asm-alpha/fcntl.h Mon Jan 17 16:44:43 2000 +++ lfs/include/asm-alpha/fcntl.h Wed Sep 12 02:42:15 2001 @@ -20,6 +20,7 @@ #define O_DIRECT 040000 /* direct disk access - should check with OSF/1 */ #define O_DIRECTORY 0100000 /* must be a directory */ #define O_NOFOLLOW 0200000 /* don't follow links */ +#define O_LARGEFILE 0400000 /* will be set by the kernel on every open */ #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ @@ -61,5 +62,9 @@ __kernel_off_t l_len; __kernel_pid_t l_pid; }; + +#ifdef __KERNEL__ +#define flock64 flock +#endif #endif diff -urN lfs-ref/include/asm-alpha/unistd.h lfs/include/asm-alpha/unistd.h --- lfs-ref/include/asm-alpha/unistd.h Mon Dec 11 16:58:03 2000 +++ lfs/include/asm-alpha/unistd.h Wed Sep 12 02:42:15 2001 @@ -314,6 +314,7 @@ #define __NR_pivot_root 374 /* implemented in 2.3 */ #define __NR_mincore 375 /* implemented in 2.3 */ #define __NR_pciconfig_iobase 376 +#define __NR_getdents64 377 #if defined(__GNUC__) diff -urN lfs-ref/include/asm-arm/fcntl.h lfs/include/asm-arm/fcntl.h --- lfs-ref/include/asm-arm/fcntl.h Mon Jan 17 16:44:44 2000 +++ lfs/include/asm-arm/fcntl.h Wed Sep 12 02:42:15 2001 @@ -18,6 +18,8 @@ #define FASYNC 020000 /* fcntl, for BSD compatibility */ #define O_DIRECTORY 040000 /* must be a directory */ #define O_NOFOLLOW 0100000 /* don't follow links */ +#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */ +#define O_LARGEFILE 0400000 #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ @@ -33,6 +35,10 @@ #define F_SETSIG 10 /* for sockets. */ #define F_GETSIG 11 /* for sockets. */ +#define F_GETLK64 12 /* using 'struct flock64' */ +#define F_SETLK64 13 +#define F_SETLKW64 14 + /* for F_[GET|SET]FL */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ @@ -58,6 +64,14 @@ off_t l_start; off_t l_len; pid_t l_pid; +}; + +struct flock64 { + short l_type; + short l_whence; + loff_t l_start; + loff_t l_len; + pid_t l_pid; }; #endif diff -urN lfs-ref/include/asm-arm/stat.h lfs/include/asm-arm/stat.h --- lfs-ref/include/asm-arm/stat.h Mon Jan 17 16:44:44 2000 +++ lfs/include/asm-arm/stat.h Wed Sep 12 02:42:15 2001 @@ -38,4 +38,5 @@ unsigned long __unused5; }; +/* Someone please add a glibc/arm compatible stat64 struct here. */ #endif diff -urN lfs-ref/include/asm-arm/unistd.h lfs/include/asm-arm/unistd.h --- lfs-ref/include/asm-arm/unistd.h Mon Dec 11 16:58:04 2000 +++ lfs/include/asm-arm/unistd.h Wed Sep 12 02:42:15 2001 @@ -198,6 +198,13 @@ /* 188 reserved */ /* 189 reserved */ #define __NR_vfork (__NR_SYSCALL_BASE+190) +/* #define __NR_getrlimit (__NR_SYSCALL_BASE+191) */ +#define __NR_mmap2 (__NR_SYSCALL_BASE+192) +#define __NR_truncate64 (__NR_SYSCALL_BASE+193) +#define __NR_ftruncate64 (__NR_SYSCALL_BASE+194) +#define __NR_stat64 (__NR_SYSCALL_BASE+195) +#define __NR_lstat64 (__NR_SYSCALL_BASE+196) +#define __NR_fstat64 (__NR_SYSCALL_BASE+197) #define __sys2(x) #x #define __sys1(x) __sys2(x) diff -urN lfs-ref/include/asm-i386/fcntl.h lfs/include/asm-i386/fcntl.h --- lfs-ref/include/asm-i386/fcntl.h Mon Jan 17 16:44:44 2000 +++ lfs/include/asm-i386/fcntl.h Wed Sep 12 02:42:15 2001 @@ -35,6 +35,10 @@ #define F_SETSIG 10 /* for sockets. */ #define F_GETSIG 11 /* for sockets. */ +#define F_GETLK64 12 /* using 'struct flock64' */ +#define F_SETLK64 13 +#define F_SETLKW64 14 + /* for F_[GET|SET]FL */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ @@ -60,6 +64,14 @@ off_t l_start; off_t l_len; pid_t l_pid; +}; + +struct flock64 { + short l_type; + short l_whence; + loff_t l_start; + loff_t l_len; + pid_t l_pid; }; #endif diff -urN lfs-ref/include/asm-i386/stat.h lfs/include/asm-i386/stat.h --- lfs-ref/include/asm-i386/stat.h Mon Jan 17 16:44:44 2000 +++ lfs/include/asm-i386/stat.h Wed Sep 12 02:42:15 2001 @@ -38,4 +38,41 @@ unsigned long __unused5; }; +/* This matches struct stat64 in glibc2.1, hence the absolutely + * insane amounts of padding around dev_t's. + */ +struct stat64 { + unsigned short st_dev; + unsigned char __pad0[10]; + +#define STAT64_HAS_BROKEN_ST_INO 1 + unsigned long __st_ino; + + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + unsigned short st_rdev; + unsigned char __pad3[10]; + + long long st_size; + unsigned long st_blksize; + + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + + unsigned long st_atime; + unsigned long __pad5; + + unsigned long st_mtime; + unsigned long __pad6; + + unsigned long st_ctime; + unsigned long __pad7; /* will be high 32 bits of ctime someday */ + + unsigned long long st_ino; +}; + #endif diff -urN lfs-ref/include/asm-i386/unistd.h lfs/include/asm-i386/unistd.h --- lfs-ref/include/asm-i386/unistd.h Mon Jan 17 16:44:44 2000 +++ lfs/include/asm-i386/unistd.h Wed Sep 12 02:42:15 2001 @@ -80,7 +80,7 @@ #define __NR_sigpending 73 #define __NR_sethostname 74 #define __NR_setrlimit 75 -#define __NR_getrlimit 76 +#define __NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */ #define __NR_getrusage 77 #define __NR_gettimeofday 78 #define __NR_settimeofday 79 @@ -195,8 +195,42 @@ #define __NR_getpmsg 188 /* some people actually want streams */ #define __NR_putpmsg 189 /* some people actually want streams */ #define __NR_vfork 190 +/* #define __NR_ugetrlimit 191 SuS compliant getrlimit */ +#define __NR_mmap2 192 +#define __NR_truncate64 193 +#define __NR_ftruncate64 194 +#define __NR_stat64 195 +#define __NR_lstat64 196 +#define __NR_fstat64 197 +#if 0 /* 2.3.x */ +#define __NR_lchown32 198 +#define __NR_getuid32 199 +#define __NR_getgid32 200 +#define __NR_geteuid32 201 +#define __NR_getegid32 202 +#define __NR_setreuid32 203 +#define __NR_setregid32 204 +#define __NR_getgroups32 205 +#define __NR_setgroups32 206 +#define __NR_fchown32 207 +#define __NR_setresuid32 208 +#define __NR_getresuid32 209 +#define __NR_setresgid32 210 +#define __NR_getresgid32 211 +#define __NR_chown32 212 +#define __NR_setuid32 213 +#define __NR_setgid32 214 +#define __NR_setfsuid32 215 +#define __NR_setfsgid32 216 +#define __NR_pivot_root 217 +#define __NR_mincore 218 +#define __NR_madvise 219 +#define __NR_madvise1 219 /* delete when C lib stub is removed */ +#endif +#define __NR_getdents64 220 +#define __NR_fcntl64 221 -/* user-visible error numbers are in the range -1 - -122: see */ +/* user-visible error numbers are in the range -1 - -124: see */ #define __syscall_return(type, res) \ do { \ @@ -269,6 +303,19 @@ : "=a" (__res) \ : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \ +__syscall_return(type,__res); \ +} + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \ +{ \ +long __res; \ +__asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; int $0x80 ; pop %%ebp" \ + : "=a" (__res) \ + : "i" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)), \ + "0" ((long)(arg6))); \ __syscall_return(type,__res); \ } diff -urN lfs-ref/include/asm-m68k/fcntl.h lfs/include/asm-m68k/fcntl.h --- lfs-ref/include/asm-m68k/fcntl.h Mon Jan 17 16:44:44 2000 +++ lfs/include/asm-m68k/fcntl.h Wed Sep 12 02:42:15 2001 @@ -33,6 +33,10 @@ #define F_SETSIG 10 /* for sockets. */ #define F_GETSIG 11 /* for sockets. */ +#define F_GETLK64 12 /* using 'struct flock64' */ +#define F_SETLK64 13 +#define F_SETLKW64 14 + /* for F_[GET|SET]FL */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ @@ -58,6 +62,14 @@ off_t l_start; off_t l_len; pid_t l_pid; +}; + +struct flock64 { + short l_type; + short l_whence; + loff_t l_start; + loff_t l_len; + pid_t l_pid; }; #endif /* _M68K_FCNTL_H */ diff -urN lfs-ref/include/asm-m68k/stat.h lfs/include/asm-m68k/stat.h --- lfs-ref/include/asm-m68k/stat.h Mon Jan 17 16:44:45 2000 +++ lfs/include/asm-m68k/stat.h Wed Sep 12 02:42:15 2001 @@ -38,4 +38,8 @@ unsigned long __unused5; }; +/* stat64 struct goes here -- someone please make + * it mesh with whatever glibc does in userland on + * m68k's. + */ #endif /* _M68K_STAT_H */ diff -urN lfs-ref/include/asm-m68k/unistd.h lfs/include/asm-m68k/unistd.h --- lfs-ref/include/asm-m68k/unistd.h Mon Jan 17 16:44:45 2000 +++ lfs/include/asm-m68k/unistd.h Wed Sep 12 02:42:15 2001 @@ -80,7 +80,7 @@ #define __NR_sigpending 73 #define __NR_sethostname 74 #define __NR_setrlimit 75 -#define __NR_getrlimit 76 +#define __NR_getrlimit 76 #define __NR_getrusage 77 #define __NR_gettimeofday 78 #define __NR_settimeofday 79 @@ -194,6 +194,13 @@ #define __NR_getpmsg 188 /* some people actually want streams */ #define __NR_putpmsg 189 /* some people actually want streams */ #define __NR_vfork 190 +/* #define __NR_getrlimit 191 */ +#define __NR_mmap2 192 +#define __NR_truncate64 193 +#define __NR_ftruncate64 194 +#define __NR_stat64 195 +#define __NR_lstat64 196 +#define __NR_fstat64 197 /* user-visible error numbers are in the range -1 - -122: see */ diff -urN lfs-ref/include/asm-mips/fcntl.h lfs/include/asm-mips/fcntl.h --- lfs-ref/include/asm-mips/fcntl.h Mon Jan 17 16:44:45 2000 +++ lfs/include/asm-mips/fcntl.h Wed Sep 12 02:42:15 2001 @@ -44,6 +44,10 @@ #define F_SETSIG 10 /* for sockets. */ #define F_GETSIG 11 /* for sockets. */ +#define F_GETLK64 33 /* using 'struct flock64' */ +#define F_SETLK64 34 +#define F_SETLKW64 35 + /* for F_[GET|SET]FL */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ @@ -72,5 +76,13 @@ __kernel_pid_t l_pid; long pad[4]; /* ZZZZZZZZZZZZZZZZZZZZZZZZZZ */ } flock_t; + +typedef struct flock64 { + short l_type; + short l_whence; + loff_t l_start; + loff_t l_len; + pid_t l_pid; +} flock64_t; #endif /* __ASM_MIPS_FCNTL_H */ diff -urN lfs-ref/include/asm-ppc/fcntl.h lfs/include/asm-ppc/fcntl.h --- lfs-ref/include/asm-ppc/fcntl.h Mon Jan 17 16:44:45 2000 +++ lfs/include/asm-ppc/fcntl.h Wed Sep 12 02:42:15 2001 @@ -18,6 +18,8 @@ #define FASYNC 020000 /* fcntl, for BSD compatibility */ #define O_DIRECTORY 040000 /* must be a directory */ #define O_NOFOLLOW 0100000 /* don't follow links */ +#define O_LARGEFILE 0200000 +#define O_DIRECT 0400000 /* direct disk access hint - currently ignored */ #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ @@ -33,6 +35,10 @@ #define F_SETSIG 10 /* for sockets. */ #define F_GETSIG 11 /* for sockets. */ +#define F_GETLK64 12 /* using 'struct flock64' */ +#define F_SETLK64 13 +#define F_SETLKW64 14 + /* for F_[GET|SET]FL */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ @@ -64,6 +70,14 @@ off_t l_start; off_t l_len; pid_t l_pid; +}; + +struct flock64 { + short l_type; + short l_whence; + loff_t l_start; + loff_t l_len; + pid_t l_pid; }; #endif diff -urN lfs-ref/include/asm-ppc/stat.h lfs/include/asm-ppc/stat.h --- lfs-ref/include/asm-ppc/stat.h Mon Jan 17 16:44:45 2000 +++ lfs/include/asm-ppc/stat.h Wed Sep 12 02:42:15 2001 @@ -37,4 +37,29 @@ unsigned long __unused5; }; +/* This matches struct stat64 in glibc2.1. + */ +struct stat64 { + unsigned long long st_dev; /* Device. */ + unsigned long long st_ino; /* File serial number. */ + unsigned int st_mode; /* File mode. */ + unsigned int st_nlink; /* Link count. */ + unsigned int st_uid; /* User ID of the file's owner. */ + unsigned int st_gid; /* Group ID of the file's group. */ + unsigned long long st_rdev; /* Device number, if device. */ + unsigned short int __pad2; + long long st_size; /* Size of file, in bytes. */ + long st_blksize; /* Optimal block size for I/O. */ + + long long st_blocks; /* Number 512-byte blocks allocated. */ + long st_atime; /* Time of last access. */ + unsigned long int __unused1; + long st_mtime; /* Time of last modification. */ + unsigned long int __unused2; + long st_ctime; /* Time of last status change. */ + unsigned long int __unused3; + unsigned long int __unused4; + unsigned long int __unused5; +}; + #endif diff -urN lfs-ref/include/asm-ppc/unistd.h lfs/include/asm-ppc/unistd.h --- lfs-ref/include/asm-ppc/unistd.h Mon Dec 11 16:58:05 2000 +++ lfs/include/asm-ppc/unistd.h Wed Sep 12 02:42:15 2001 @@ -194,11 +194,18 @@ #define __NR_getpmsg 187 /* some people actually want streams */ #define __NR_putpmsg 188 /* some people actually want streams */ #define __NR_vfork 189 - +#define __NR_mmap2 192 +#define __NR_truncate64 193 +#define __NR_ftruncate64 194 +#define __NR_stat64 195 +#define __NR_lstat64 196 +#define __NR_fstat64 197 #define __NR_pciconfig_read 198 #define __NR_pciconfig_write 199 #define __NR_pciconfig_iobase 200 #define __NR_multiplexer 201 +#define __NR_getdents64 202 +#define __NR_fcntl64 203 #define __NR(n) #n diff -urN lfs-ref/include/asm-sparc/fcntl.h lfs/include/asm-sparc/fcntl.h --- lfs-ref/include/asm-sparc/fcntl.h Mon Jan 17 16:44:46 2000 +++ lfs/include/asm-sparc/fcntl.h Wed Sep 12 02:42:15 2001 @@ -19,6 +19,7 @@ #define O_NOCTTY 0x8000 /* not fcntl */ #define O_DIRECTORY 0x10000 /* must be a directory */ #define O_NOFOLLOW 0x20000 /* don't follow links */ +#define O_LARGEFILE 0x40000 /* LFS */ #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ @@ -32,6 +33,9 @@ #define F_SETLKW 9 #define F_SETSIG 10 /* for sockets. */ #define F_GETSIG 11 /* for sockets. */ +#define F_GETLK64 12 +#define F_SETLK64 13 +#define F_SETLKW64 14 /* for F_[GET|SET]FL */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ @@ -57,6 +61,15 @@ short l_whence; off_t l_start; off_t l_len; + pid_t l_pid; + short __unused; +}; + +struct flock64 { + short l_type; + short l_whence; + loff_t l_start; + loff_t l_len; pid_t l_pid; short __unused; }; diff -urN lfs-ref/include/asm-sparc/stat.h lfs/include/asm-sparc/stat.h --- lfs-ref/include/asm-sparc/stat.h Mon Jan 17 16:44:46 2000 +++ lfs/include/asm-sparc/stat.h Wed Sep 12 02:42:15 2001 @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id$ */ #ifndef _SPARC_STAT_H #define _SPARC_STAT_H @@ -36,6 +36,42 @@ off_t st_blksize; off_t st_blocks; unsigned long __unused4[2]; +}; + +struct stat64 { + unsigned char __pad0[6]; + unsigned short st_dev; + + unsigned long long st_ino; + + unsigned int st_mode; + unsigned int st_nlink; + + unsigned int st_uid; + unsigned int st_gid; + + unsigned char __pad2[6]; + unsigned short st_rdev; + + unsigned char __pad3[8]; + + long long st_size; + unsigned int st_blksize; + + unsigned char __pad4[8]; + unsigned int st_blocks; + + unsigned int st_atime; + unsigned int __unused1; + + unsigned int st_mtime; + unsigned int __unused2; + + unsigned int st_ctime; + unsigned int __unused3; + + unsigned int __unused4; + unsigned int __unused5; }; #endif diff -urN lfs-ref/include/asm-sparc/unistd.h lfs/include/asm-sparc/unistd.h --- lfs-ref/include/asm-sparc/unistd.h Fri Apr 20 22:31:20 2001 +++ lfs/include/asm-sparc/unistd.h Wed Sep 12 02:42:15 2001 @@ -71,14 +71,14 @@ /* #define __NR_mctl 53 SunOS specific */ #define __NR_ioctl 54 /* Common */ #define __NR_reboot 55 /* Common */ -/* #define __NR_ni_syscall 56 ENOSYS under SunOS */ +#define __NR_mmap2 56 /* Linux sparc32 Specific */ #define __NR_symlink 57 /* Common */ #define __NR_readlink 58 /* Common */ #define __NR_execve 59 /* Common */ #define __NR_umask 60 /* Common */ #define __NR_chroot 61 /* Common */ #define __NR_fstat 62 /* Common */ -/* #define __NR_ni_syscall 63 ENOSYS under SunOS */ +#define __NR_fstat64 63 /* Linux sparc32 Specific */ #define __NR_getpagesize 64 /* Common */ #define __NR_msync 65 /* Common in newer 1.3.x revs... */ #define __NR_vfork 66 /* Common */ @@ -92,14 +92,14 @@ #define __NR_mprotect 74 /* Common */ /* #define __NR_madvise 75 SunOS Specific */ #define __NR_vhangup 76 /* Common */ -/* #define __NR_ni_syscall 77 ENOSYS under SunOS */ +#define __NR_truncate64 77 /* Linux sparc32 Specific */ /* #define __NR_mincore 78 SunOS Specific */ #define __NR_getgroups 79 /* Common */ #define __NR_setgroups 80 /* Common */ #define __NR_getpgrp 81 /* Common */ /* #define __NR_setpgrp 82 setpgid, same difference... */ #define __NR_setitimer 83 /* Common */ -/* #define __NR_ni_syscall 84 ENOSYS under SunOS */ +#define __NR_ftruncate64 84 /* Linux sparc32 Specific */ #define __NR_swapon 85 /* Common */ #define __NR_getitimer 86 /* Common */ /* #define __NR_gethostname 87 SunOS Specific */ @@ -147,14 +147,14 @@ #define __NR_truncate 129 /* Common */ #define __NR_ftruncate 130 /* Common */ #define __NR_flock 131 /* Common */ -/* #define __NR_ni_syscall 132 ENOSYS under SunOS */ +#define __NR_lstat64 132 /* Linux sparc32 Specific */ #define __NR_sendto 133 /* Common */ #define __NR_shutdown 134 /* Common */ #define __NR_socketpair 135 /* Common */ #define __NR_mkdir 136 /* Common */ #define __NR_rmdir 137 /* Common */ #define __NR_utimes 138 /* SunOS Specific */ -/* #define __NR_ni_syscall 139 ENOSYS under SunOS */ +#define __NR_stat64 139 /* Linux sparc32 Specific */ /* #define __NR_adjtime 140 SunOS Specific */ #define __NR_getpeername 141 /* Common */ /* #define __NR_gethostid 142 SunOS Specific */ @@ -169,8 +169,8 @@ /* #define __NR_getmsg 151 SunOS Specific */ /* #define __NR_putmsg 152 SunOS Specific */ #define __NR_poll 153 /* Common */ -/* #define __NR_getdents64 154 Linux Sparc32 Specific */ -/* #define __NR_fcntl64 155 Linux Sparc32 Specific */ +#define __NR_getdents64 154 /* Linux Sparc32 Specific */ +#define __NR_fcntl64 155 /* Linux Sparc32 Specific */ /* #define __NR_getdirentries 156 SunOS Specific */ #define __NR_statfs 157 /* Common */ #define __NR_fstatfs 158 /* Common */ diff -urN lfs-ref/include/asm-sparc64/fcntl.h lfs/include/asm-sparc64/fcntl.h --- lfs-ref/include/asm-sparc64/fcntl.h Mon Jan 17 16:44:46 2000 +++ lfs/include/asm-sparc64/fcntl.h Wed Sep 12 02:42:15 2001 @@ -19,6 +19,7 @@ #define O_NOCTTY 0x8000 /* not fcntl */ #define O_DIRECTORY 0x10000 /* must be a directory */ #define O_NOFOLLOW 0x20000 /* don't follow links */ +#define O_LARGEFILE 0x40000 #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ @@ -32,6 +33,11 @@ #define F_SETLKW 9 #define F_SETSIG 10 /* for sockets. */ #define F_GETSIG 11 /* for sockets. */ +#ifdef __KERNEL__ +#define F_GETLK64 12 +#define F_SETLK64 13 +#define F_SETLKW64 14 +#endif /* for F_[GET|SET]FL */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ @@ -58,7 +64,6 @@ off_t l_start; off_t l_len; pid_t l_pid; - short __unused; }; #ifdef __KERNEL__ @@ -70,6 +75,17 @@ __kernel_pid_t32 l_pid; short __unused; }; + +struct flock32_64 { + short l_type; + short l_whence; + __kernel_loff_t32 l_start; + __kernel_loff_t32 l_len; + __kernel_pid_t32 l_pid; + short __unused; +}; + +#define flock64 flock #endif #endif /* !(_SPARC64_FCNTL_H) */ diff -urN lfs-ref/include/asm-sparc64/stat.h lfs/include/asm-sparc64/stat.h --- lfs-ref/include/asm-sparc64/stat.h Fri Dec 22 17:22:30 2000 +++ lfs/include/asm-sparc64/stat.h Wed Sep 12 02:42:15 2001 @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id$ */ #ifndef _SPARC64_STAT_H #define _SPARC64_STAT_H @@ -41,5 +41,46 @@ off_t st_blocks; unsigned long __unused4[2]; }; + +#ifdef __KERNEL__ +/* This is sparc32 stat64 structure. */ + +struct stat64 { + unsigned char __pad0[6]; + unsigned short st_dev; + + unsigned long long st_ino; + + unsigned int st_mode; + unsigned int st_nlink; + + unsigned int st_uid; + unsigned int st_gid; + + unsigned char __pad2[6]; + unsigned short st_rdev; + + unsigned char __pad3[8]; + + long long st_size; + unsigned int st_blksize; + + unsigned char __pad4[8]; + unsigned int st_blocks; + + unsigned int st_atime; + unsigned int __unused1; + + unsigned int st_mtime; + unsigned int __unused2; + + unsigned int st_ctime; + unsigned int __unused3; + + unsigned int __unused4; + unsigned int __unused5; +}; + +#endif #endif diff -urN lfs-ref/include/asm-sparc64/unistd.h lfs/include/asm-sparc64/unistd.h --- lfs-ref/include/asm-sparc64/unistd.h Fri Apr 20 22:31:20 2001 +++ lfs/include/asm-sparc64/unistd.h Wed Sep 12 02:42:15 2001 @@ -71,14 +71,14 @@ /* #define __NR_mctl 53 SunOS specific */ #define __NR_ioctl 54 /* Common */ #define __NR_reboot 55 /* Common */ -/* #define __NR_ni_syscall 56 ENOSYS under SunOS */ +/* #define __NR_mmap2 56 Linux sparc32 Specific */ #define __NR_symlink 57 /* Common */ #define __NR_readlink 58 /* Common */ #define __NR_execve 59 /* Common */ #define __NR_umask 60 /* Common */ #define __NR_chroot 61 /* Common */ #define __NR_fstat 62 /* Common */ -/* #define __NR_ni_syscall 63 ENOSYS under SunOS */ +/* #define __NR_fstat64 63 Linux sparc32 Specific */ #define __NR_getpagesize 64 /* Common */ #define __NR_msync 65 /* Common in newer 1.3.x revs... */ #define __NR_vfork 66 /* Common */ @@ -92,14 +92,14 @@ #define __NR_mprotect 74 /* Common */ /* #define __NR_madvise 75 SunOS Specific */ #define __NR_vhangup 76 /* Common */ -/* #define __NR_ni_syscall 77 ENOSYS under SunOS */ +/* #define __NR_truncate64 77 Linux sparc32 Specific */ /* #define __NR_mincore 78 SunOS Specific */ #define __NR_getgroups 79 /* Common */ #define __NR_setgroups 80 /* Common */ #define __NR_getpgrp 81 /* Common */ /* #define __NR_setpgrp 82 setpgid, same difference... */ #define __NR_setitimer 83 /* Common */ -/* #define __NR_ni_syscall 84 ENOSYS under SunOS */ +/* #define __NR_ftruncate64 84 Linux sparc32 Specific */ #define __NR_swapon 85 /* Common */ #define __NR_getitimer 86 /* Common */ /* #define __NR_gethostname 87 SunOS Specific */ @@ -147,19 +147,19 @@ #define __NR_truncate 129 /* Common */ #define __NR_ftruncate 130 /* Common */ #define __NR_flock 131 /* Common */ -/* #define __NR_ni_syscall 132 ENOSYS under SunOS */ +/* #define __NR_lstat64 132 Linux sparc32 Specific */ #define __NR_sendto 133 /* Common */ #define __NR_shutdown 134 /* Common */ #define __NR_socketpair 135 /* Common */ #define __NR_mkdir 136 /* Common */ #define __NR_rmdir 137 /* Common */ #define __NR_utimes 138 /* SunOS Specific */ -/* #define __NR_ni_syscall 139 ENOSYS under SunOS */ +/* #define __NR_stat64 139 Linux sparc32 Specific */ /* #define __NR_adjtime 140 SunOS Specific */ #define __NR_getpeername 141 /* Common */ /* #define __NR_gethostid 142 SunOS Specific */ /* #define __NR_ni_syscall 143 ENOSYS under SunOS */ -#define __NR_getrlimit 144 /* Common */ +#define __NR_getrlimit 144 /* Common */ #define __NR_setrlimit 145 /* Common */ /* #define __NR_killpg 146 SunOS Specific */ #define __NR_prctl 147 /* ENOSYS under SunOS */ diff -urN lfs-ref/include/linux/dirent.h lfs/include/linux/dirent.h --- lfs-ref/include/linux/dirent.h Tue May 25 00:49:30 1999 +++ lfs/include/linux/dirent.h Wed Sep 12 02:42:15 2001 @@ -8,4 +8,12 @@ char d_name[256]; /* We must not include limits.h! */ }; +struct dirent64 { + __u64 d_ino; + __s64 d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[256]; +}; + #endif diff -urN lfs-ref/include/linux/ext2_fs_i.h lfs/include/linux/ext2_fs_i.h --- lfs-ref/include/linux/ext2_fs_i.h Mon Dec 11 16:58:05 2000 +++ lfs/include/linux/ext2_fs_i.h Wed Sep 12 02:42:15 2001 @@ -35,7 +35,6 @@ __u32 i_next_alloc_goal; __u32 i_prealloc_block; __u32 i_prealloc_count; - __u32 i_high_size; int i_new_inode:1; /* Is a freshly allocated inode */ }; diff -urN lfs-ref/include/linux/fs.h lfs/include/linux/fs.h --- lfs-ref/include/linux/fs.h Wed Sep 12 02:39:58 2001 +++ lfs/include/linux/fs.h Wed Sep 12 02:42:15 2001 @@ -266,6 +266,25 @@ #define buffer_page(bh) (mem_map + MAP_NR((bh)->b_data)) #define touch_buffer(bh) set_bit(PG_referenced, &buffer_page(bh)->flags) +/* log of base-2 for filesystem uses, in case their super-blocks + don't have the shift counts readily calculated.. -- presuming + the divisors in question are power-of-two values! */ +static int fslog2(unsigned long val) __attribute__ ((const)); +static __inline__ int fslog2(unsigned long val) +{ + int i; + for (i = 0; val != 0; ++i, val >>= 1) { + if (val & 1) return i; + } + return 0; +} + +static int off_t_presentable(loff_t) __attribute((const)); +static __inline__ int off_t_presentable(loff_t loff) +{ + return loff >= 0 && loff <= (~0UL >> 1); +} + #include #include #include @@ -317,7 +336,7 @@ umode_t ia_mode; uid_t ia_uid; gid_t ia_gid; - off_t ia_size; + loff_t ia_size; time_t ia_atime; time_t ia_mtime; time_t ia_ctime; @@ -352,7 +371,7 @@ uid_t i_uid; gid_t i_gid; kdev_t i_rdev; - off_t i_size; + loff_t i_size; time_t i_atime; time_t i_mtime; time_t i_ctime; @@ -431,7 +450,7 @@ mode_t f_mode; loff_t f_pos; unsigned int f_count, f_flags; - unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin; + loff_t f_reada, f_ramax, f_raend, f_ralen, f_rawin; struct fown_struct f_owner; unsigned int f_uid, f_gid; int f_error; @@ -471,8 +490,8 @@ struct file *fl_file; unsigned char fl_flags; unsigned char fl_type; - off_t fl_start; - off_t fl_end; + loff_t fl_start; + loff_t fl_end; void (*fl_notify)(struct file_lock *); /* unblock callback */ void (*fl_insert)(struct file_lock *); /* lock insertion callback */ @@ -483,6 +502,9 @@ } fl_u; }; +#define OFFSET_MAX ((loff_t)((~0ULL)>>1)) +#define OFFT_OFFSET_MAX ((off_t)((~0UL)>>1)) + extern struct file_lock *file_lock_table; #include @@ -490,6 +512,9 @@ extern int fcntl_getlk(unsigned int fd, struct flock *l); extern int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l); +extern int fcntl_getlk64(unsigned int fd, struct flock64 *l); +extern int fcntl_setlk64(unsigned int fd, unsigned int cmd, struct flock64 *l); + /* fs/locks.c */ extern void locks_remove_posix(struct file *, fl_owner_t id); extern void locks_remove_flock(struct file *); @@ -596,12 +621,25 @@ extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); /* + * File types + */ +#define DT_UNKNOWN 0 +#define DT_FIFO 1 +#define DT_CHR 2 +#define DT_DIR 4 +#define DT_BLK 6 +#define DT_REG 8 +#define DT_LNK 10 +#define DT_SOCK 12 +#define DT_WHT 14 + +/* * This is the "filldir" function type, used by readdir() to let * the kernel specify what kind of dirent layout it wants to have. * This allows the kernel to read directories into kernel space or * to have different dirent layouts depending on the binary type. */ -typedef int (*filldir_t)(void *, const char *, int, off_t, ino_t); +typedef int (*filldir_t)(void *, const char *, int, off_t, ino_t, unsigned); struct file_operations { loff_t (*llseek) (struct file *, loff_t, int); @@ -733,7 +771,7 @@ asmlinkage int sys_open(const char *, int, int); asmlinkage int sys_close(unsigned int); /* yes, it's really unsigned */ -extern int do_truncate(struct dentry *, unsigned long); +extern int do_truncate(struct dentry *, loff_t); extern struct file *filp_open(const char *, int, int); extern int filp_close(struct file *, fl_owner_t id); diff -urN lfs-ref/include/linux/mm.h lfs/include/linux/mm.h --- lfs-ref/include/linux/mm.h Wed Sep 12 02:39:57 2001 +++ lfs/include/linux/mm.h Wed Sep 12 02:42:15 2001 @@ -54,7 +54,7 @@ struct vm_area_struct **vm_pprev_share; struct vm_operations_struct * vm_ops; - unsigned long vm_offset; + loff_t vm_offset; struct file * vm_file; unsigned long vm_pte; /* shared mem */ }; @@ -108,9 +108,46 @@ unsigned long (*wppage)(struct vm_area_struct * area, unsigned long address, unsigned long page); int (*swapout)(struct vm_area_struct *, struct page *); - pte_t (*swapin)(struct vm_area_struct *, unsigned long, unsigned long); + pte_t (*swapin)(struct vm_area_struct *, loff_t, unsigned long); }; + +/* + * pgoff_t type -- a complex one, and its simple alternate. + * The complex one has type that compiler can trap at compile + * time, but the simple one does simpler code (?) + */ + +#if 0 +typedef struct pgoff_t { + unsigned long pgoff; +} pgoff_t; + +#define pgoff2ulong(pgof) ((pgof).pgoff) +extern __inline__ pgoff_t ulong2pgoff(unsigned long ul) { + pgoff_t up; + up.pgoff = ul; + return up; +} + +#define pgoff2loff(pgof) (((loff_t)(pgof).pgoff) << PAGE_SHIFT) +#define loff2pgoff(loff) ulong2pgoff((loff) >> PAGE_SHIFT) + +#else /* Integer scalars -- simpler code.. */ + +typedef unsigned long pgoff_t; + +#define pgoff2ulong(pgof) (pgof) +#define ulong2pgoff(pgof) (pgof) + +#define pgoff2loff(pgof) (((loff_t)(pgof)) << PAGE_SHIFT) +#define loff2pgoff(loff) ulong2pgoff((loff) >> PAGE_SHIFT) + +#endif + +#define PAGE_MASK_loff ((loff_t)(long)(PAGE_MASK)) + + /* * Try to keep the most commonly accessed fields in single cache lines * here (16 bytes or greater). This ordering should be particularly @@ -119,12 +156,13 @@ * The first line is data used in page cache lookup, the second line * is used for linear searches (eg. clock algorithm scans). */ + typedef struct page { /* these must be first (free area handling) */ struct page *next; struct page *prev; + pgoff_t index; struct inode *inode; - unsigned long offset; struct page *next_hash; atomic_t count; unsigned long flags; /* atomic flags, some possibly updated asynchronously */ @@ -299,7 +337,7 @@ extern int remap_page_range(unsigned long from, unsigned long to, unsigned long size, pgprot_t prot); extern int zeromap_page_range(unsigned long from, unsigned long size, pgprot_t prot); -extern void vmtruncate(struct inode * inode, unsigned long offset); +extern void vmtruncate(struct inode * inode, loff_t offset); extern int handle_mm_fault(struct task_struct *tsk,struct vm_area_struct *vma, unsigned long address, int write_access); extern int make_pages_present(unsigned long addr, unsigned long end); @@ -319,16 +357,22 @@ extern void exit_mmap(struct mm_struct *); extern unsigned long get_unmapped_area(unsigned long, unsigned long); -extern unsigned long do_mmap(struct file *, unsigned long, unsigned long, - unsigned long, unsigned long, unsigned long); +extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flag, unsigned long pgoff); + +extern unsigned long do_mmap(struct file *, unsigned long, + unsigned long, unsigned long, + unsigned long, unsigned long); + extern int do_munmap(unsigned long, size_t); /* filemap.c */ extern void remove_inode_page(struct page *); extern unsigned long page_unuse(struct page *); extern int shrink_mmap(int, int); -extern void truncate_inode_pages(struct inode *, unsigned long); -extern unsigned long get_cached_page(struct inode *, unsigned long, int); +extern void truncate_inode_pages(struct inode *, loff_t); +extern unsigned long get_cached_page(struct inode *, pgoff_t, int); extern void put_cached_page(unsigned long); /* diff -urN lfs-ref/include/linux/nfs.h lfs/include/linux/nfs.h --- lfs-ref/include/linux/nfs.h Fri Apr 20 22:31:21 2001 +++ lfs/include/linux/nfs.h Wed Sep 12 02:42:15 2001 @@ -78,11 +78,7 @@ #define NFS_MNTPROC_MNT 1 #define NFS_MNTPROC_UMNT 3 -/* - * This is really a general kernel constant, but since nothing like - * this is defined in the kernel headers, I have to do it here. - */ -#define NFS_OFFSET_MAX LONG_MAX +#define NFS_OFFSET_MAX ((__s64)((~(__u64)0) >> 1)) /* * These data types are used exlusively by the NFS client implementation. diff -urN lfs-ref/include/linux/nfs_fs.h lfs/include/linux/nfs_fs.h --- lfs-ref/include/linux/nfs_fs.h Wed Sep 12 02:05:58 2001 +++ lfs/include/linux/nfs_fs.h Wed Sep 12 02:42:15 2001 @@ -113,15 +113,15 @@ static inline -unsigned long nfs_page_offset(struct page *page) +loff_t nfs_page_offset(struct page *page) { - return page->offset; + return ((loff_t)page->index) << PAGE_CACHE_SHIFT; } static inline unsigned long page_index(struct page *page) { - return page->offset >> PAGE_CACHE_SHIFT; + return page->index; } /* @@ -284,6 +284,15 @@ nfs_size_to_off_t(__u64 size) { return (size > (__u64)LONG_MAX) ? (off_t)LONG_MAX : (off_t) size; +} + +static inline loff_t +nfs_size_to_loff_t(__u64 size) +{ + loff_t maxsz = (((loff_t) ULONG_MAX) << PAGE_CACHE_SHIFT) + PAGE_CACHE_SIZE - 1; + if (size > maxsz) + return maxsz; + return (loff_t) size; } static inline ino_t diff -urN lfs-ref/include/linux/nfs_xdr.h lfs/include/linux/nfs_xdr.h --- lfs-ref/include/linux/nfs_xdr.h Wed Sep 12 02:05:59 2001 +++ lfs/include/linux/nfs_xdr.h Wed Sep 12 02:42:15 2001 @@ -329,11 +329,11 @@ int (*readlink)(struct inode *, void *buffer, unsigned int buflen); int (*read)(struct inode *, struct rpc_cred *, struct nfs_fattr *, - int flags, unsigned long offset, + int flags, loff_t offset, unsigned int count, void *buffer, int *eofp); int (*write)(struct inode *, struct rpc_cred *, struct nfs_fattr *, - int flags, unsigned long offset, + int flags, loff_t offset, unsigned int count, void *buffer, struct nfs_writeverf *verfp); int (*commit)(struct inode *, struct nfs_fattr *, @@ -361,6 +361,7 @@ int (*statfs)(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); __u32 * (*decode_dirent)(__u32 *, struct nfs_entry *, int plus); + int bigfiles; }; /* diff -urN lfs-ref/include/linux/nfsd/nfsd.h lfs/include/linux/nfsd/nfsd.h --- lfs-ref/include/linux/nfsd/nfsd.h Sat Apr 21 18:21:21 2001 +++ lfs/include/linux/nfsd/nfsd.h Wed Sep 12 02:42:15 2001 @@ -57,7 +57,7 @@ char dotonly; }; typedef int (*encode_dent_fn)(struct readdir_cd *, const char *, - int, off_t, ino_t); + int, off_t, ino_t, unsigned int); typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int); /* diff -urN lfs-ref/include/linux/nfsd/xdr.h lfs/include/linux/nfsd/xdr.h --- lfs-ref/include/linux/nfsd/xdr.h Sat Apr 21 18:21:21 2001 +++ lfs/include/linux/nfsd/xdr.h Wed Sep 12 02:42:15 2001 @@ -152,7 +152,7 @@ int nfssvc_encode_readdirres(struct svc_rqst *, u32 *, struct nfsd_readdirres *); int nfssvc_encode_entry(struct readdir_cd *, const char *name, - int namlen, off_t offset, ino_t ino); + int namlen, off_t offset, ino_t ino, unsigned int d_type); int nfssvc_release_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *); diff -urN lfs-ref/include/linux/nfsd/xdr3.h lfs/include/linux/nfsd/xdr3.h --- lfs-ref/include/linux/nfsd/xdr3.h Sat Apr 21 18:21:24 2001 +++ lfs/include/linux/nfsd/xdr3.h Wed Sep 12 02:42:15 2001 @@ -292,9 +292,9 @@ int nfs3svc_release_fhandle2(struct svc_rqst *, u32 *, struct nfsd3_fhandle_pair *); int nfs3svc_encode_entry(struct readdir_cd *, const char *name, - int namlen, off_t offset, ino_t ino); + int namlen, off_t offset, ino_t ino, unsigned int d_type); int nfs3svc_encode_entry_plus(struct readdir_cd *, const char *name, - int namlen, off_t offset, ino_t ino); + int namlen, off_t offset, ino_t ino, unsigned int d_type); #endif /* _LINUX_NFSD_XDR3_H */ diff -urN lfs-ref/include/linux/pagemap.h lfs/include/linux/pagemap.h --- lfs-ref/include/linux/pagemap.h Sat Apr 21 18:19:44 2001 +++ lfs/include/linux/pagemap.h Wed Sep 12 02:42:15 2001 @@ -28,6 +28,7 @@ #define PAGE_CACHE_SHIFT PAGE_SHIFT #define PAGE_CACHE_SIZE PAGE_SIZE #define PAGE_CACHE_MASK PAGE_MASK +#define PAGE_CACHE_MASK_loff PAGE_MASK_loff #define page_cache_alloc() __get_free_page(GFP_USER) #define page_cache_free(x) free_page(x) @@ -54,10 +55,10 @@ * inode pointer and offsets are distributed (ie, we * roughly know which bits are "significant") */ -static inline unsigned long _page_hashfn(struct inode * inode, unsigned long offset) +static inline unsigned long _page_hashfn(struct inode * inode, pgoff_t index) { #define i (((unsigned long) inode)/(sizeof(struct inode) & ~ (sizeof(struct inode) - 1))) -#define o ((offset >> PAGE_SHIFT) + (offset & ~PAGE_MASK)) +#define o (index + (index >> PAGE_HASH_BITS)) return ((i+o) & PAGE_HASH_MASK); #undef i #undef o @@ -65,7 +66,7 @@ #define page_hash(inode,offset) (page_hash_table+_page_hashfn(inode,offset)) -static inline struct page * __find_page(struct inode * inode, unsigned long offset, struct page *page) +static inline struct page * __find_page(struct inode * inode, pgoff_t index, struct page *page) { goto inside; for (;;) { @@ -75,7 +76,7 @@ goto not_found; if (page->inode != inode) continue; - if (page->offset == offset) + if (pgoff2ulong(page->index) == pgoff2ulong(index)) break; } /* Found the page. */ @@ -85,9 +86,9 @@ return page; } -static inline struct page *find_page(struct inode * inode, unsigned long offset) +static inline struct page *find_page(struct inode * inode, pgoff_t poffset) { - return __find_page(inode, offset, *page_hash(inode, offset)); + return __find_page(inode, poffset, *page_hash(inode, poffset)); } static inline void remove_page_from_hash_queue(struct page * page) @@ -110,9 +111,9 @@ page->pprev_hash = p; } -static inline void add_page_to_hash_queue(struct page * page, struct inode * inode, unsigned long offset) +static inline void add_page_to_hash_queue(struct page * page, struct inode * inode, pgoff_t poffset) { - __add_page_to_hash_queue(page, page_hash(inode,offset)); + __add_page_to_hash_queue(page, page_hash(inode,poffset)); } static inline void remove_page_from_inode_queue(struct page * page) @@ -150,8 +151,8 @@ __wait_on_page(page); } -extern void update_vm_cache_conditional(struct inode *, unsigned long, const char *, int, unsigned long); -extern void update_vm_cache(struct inode *, unsigned long, const char *, int); +extern void update_vm_cache_conditional(struct inode *, loff_t, const char *, int, unsigned long); +extern void update_vm_cache(struct inode *, loff_t, const char *, int); typedef int filler_t(void *, struct page*); diff -urN lfs-ref/include/linux/sched.h lfs/include/linux/sched.h --- lfs-ref/include/linux/sched.h Wed Sep 12 02:39:57 2001 +++ lfs/include/linux/sched.h Wed Sep 12 02:42:15 2001 @@ -317,7 +317,7 @@ int keep_capabilities:1; struct user_struct *user; /* limits */ - struct rlimit rlim[RLIM_NLIMITS]; + struct rlimit rlim[RLIM_NLIMITS]; unsigned short used_math; char comm[16]; /* file system info */ diff -urN lfs-ref/include/linux/smb_fs.h lfs/include/linux/smb_fs.h --- lfs-ref/include/linux/smb_fs.h Sat Apr 21 18:48:37 2001 +++ lfs/include/linux/smb_fs.h Wed Sep 12 02:42:15 2001 @@ -121,8 +121,8 @@ void smb_close_dentry(struct dentry *); int smb_close_fileid(struct dentry *, __u16); int smb_open(struct dentry *, int); -int smb_proc_read(struct dentry *, off_t, int, char *); -int smb_proc_write(struct dentry *, off_t, int, const char *); +int smb_proc_read(struct dentry *, loff_t, int, char *); +int smb_proc_write(struct dentry *, loff_t, int, const char *); int smb_proc_create(struct dentry *, __u16, time_t, __u16 *); int smb_proc_mv(struct dentry *, struct dentry *); int smb_proc_mkdir(struct dentry *); diff -urN lfs-ref/include/linux/swap.h lfs/include/linux/swap.h --- lfs-ref/include/linux/swap.h Sat Apr 21 18:19:44 2001 +++ lfs/include/linux/swap.h Wed Sep 12 02:42:15 2001 @@ -114,7 +114,7 @@ extern unsigned int nr_swapfiles; extern struct swap_info_struct swap_info[]; void si_swapinfo(struct sysinfo *); -unsigned long get_swap_page(void); +extern unsigned long get_swap_page(void); extern void FASTCALL(swap_free(unsigned long)); struct swap_list_t { int head; /* head of priority-ordered swapfile list */ @@ -147,7 +147,7 @@ extern inline unsigned long in_swap_cache(struct page *page) { if (PageSwapCache(page)) - return page->offset; + return pgoff2ulong(page->index); return 0; } @@ -164,7 +164,7 @@ return 1; count = atomic_read(&page->count); if (PageSwapCache(page)) - count += swap_count(page->offset) - 2; + count += swap_count(pgoff2ulong(page->index)) - 2; if (PageFreeAfter(page)) count--; return count > 1; diff -urN lfs-ref/include/linux/ufs_fs_i.h lfs/include/linux/ufs_fs_i.h --- lfs-ref/include/linux/ufs_fs_i.h Tue Feb 1 18:24:19 2000 +++ lfs/include/linux/ufs_fs_i.h Wed Sep 12 02:42:15 2001 @@ -18,7 +18,6 @@ __u32 i_data[15]; __u8 i_symlink[4*15]; } i_u1; - __u64 i_size; __u32 i_flags; __u32 i_gen; __u32 i_shadow; diff -urN lfs-ref/kernel/ksyms.c lfs/kernel/ksyms.c --- lfs-ref/kernel/ksyms.c Wed Sep 12 02:39:58 2001 +++ lfs/kernel/ksyms.c Wed Sep 12 02:42:15 2001 @@ -96,6 +96,7 @@ /* process memory management */ EXPORT_SYMBOL(do_mmap); +EXPORT_SYMBOL(do_mmap_pgoff); EXPORT_SYMBOL(do_munmap); EXPORT_SYMBOL(exit_mm); EXPORT_SYMBOL(exit_files); diff -urN lfs-ref/lib/vsprintf.c lfs/lib/vsprintf.c --- lfs-ref/lib/vsprintf.c Mon Jan 17 16:44:50 2000 +++ lfs/lib/vsprintf.c Wed Sep 12 02:42:15 2001 @@ -67,10 +67,106 @@ #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ #define do_div(n,base) ({ \ -int __res; \ -__res = ((unsigned long) n) % (unsigned) base; \ -n = ((unsigned long) n) / (unsigned) base; \ -__res; }) + int __res; \ + __res = ((unsigned long) n) % (unsigned) base; \ + n = ((unsigned long) n) / (unsigned) base; \ + __res; }) + +#if BITS_PER_LONG < 64 + +/* Note: do_ldiv assumes that unsigned long long is a 64 bit long + * and unsigned long is at least a 32 bits long. + */ +#define do_ldiv(n, base) \ +({ \ + unsigned long long value = n; \ + unsigned long long leftover; \ + unsigned long temp; \ + unsigned long result_div1, result_div2, result_div3, result_mod; \ +\ + temp = value >> 32; \ + result_div1 = temp/(base); \ + result_mod = temp%(base); \ +\ + temp = (result_mod << 24) | ((value >> 8) & 0xFFFFFF); \ + result_div2 = temp/(base); \ + result_mod = temp%(base); \ +\ + temp = (result_mod << 8) | (value & 0xFF); \ + result_div3 = temp/(base); \ + result_mod = temp%(base);\ +\ + leftover = ((unsigned long long)result_div1 << 32) | \ + ((unsigned long long)result_div2 << 8) | (result_div3); \ +\ + n = leftover; \ + result_mod; \ +}) + + +static char * lnumber(char * str, long long num, int base, int size, + int precision, int type) +{ + char c,sign,tmp[66]; + const char *digits="0123456789abcdef"; + int i; + + if (type & LARGE) + digits = "0123456789ABCDEF"; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return 0; + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = '-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + } + i = 0; + if (num == 0) + tmp[i++]='0'; + else while (num != 0) + tmp[i++] = digits[do_ldiv(num,base)]; + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + *str++ = ' '; + if (sign) + *str++ = sign; + if (type & SPECIAL) { + if (base==16) { + *str++ = '0'; + *str++ = digits[33]; + } + } + if (!(type & LEFT)) + while (size-- > 0) + *str++ = c; + while (i < precision--) + *str++ = '0'; + while (i-- > 0) + *str++ = tmp[i]; + while (size-- > 0) + *str++ = ' '; + return str; +} +#endif static char * number(char * str, long num, int base, int size, int precision ,int type) @@ -207,7 +303,10 @@ /* get the conversion qualifier */ qualifier = -1; if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { - qualifier = *fmt; + if (*fmt == 'l' && qualifier == 'l') + qualifier = 'L'; + else + qualifier = *fmt; ++fmt; } @@ -290,7 +389,22 @@ --fmt; continue; } - if (qualifier == 'l') + if (qualifier == 'L') { + +#if BITS_PER_LONG < 64 + /* 64-bit printout in 32-bit systems !! + Needed at some point for 64-bit file offsets and + mmap() reporting functions. */ + + unsigned long long lnum; + lnum = va_arg(args, unsigned long long); + str = lnumber(str, lnum, base, field_width, + precision, flags); + continue; +#else + num = va_arg(args, unsigned long); /* 64-bit longs..*/ +#endif + } else if (qualifier == 'l') num = va_arg(args, unsigned long); else if (qualifier == 'h') { num = (unsigned short) va_arg(args, int); diff -urN lfs-ref/mm/filemap.c lfs/mm/filemap.c --- lfs-ref/mm/filemap.c Wed Sep 12 02:39:57 2001 +++ lfs/mm/filemap.c Wed Sep 12 02:42:15 2001 @@ -78,7 +78,7 @@ * Truncate the page cache at a set offset, removing the pages * that are beyond that offset (and zeroing out partial pages). */ -void truncate_inode_pages(struct inode * inode, unsigned long start) +void truncate_inode_pages(struct inode * inode, loff_t start) { struct page ** p; struct page * page; @@ -86,10 +86,10 @@ repeat: p = &inode->i_pages; while ((page = *p) != NULL) { - unsigned long offset = page->offset; + loff_t loffset = pgoff2loff(page->index); /* page wholly truncated - free it */ - if (offset >= start) { + if (loffset >= start) { if (PageLocked(page)) { wait_on_page(page); goto repeat; @@ -105,9 +105,10 @@ continue; } p = &page->next; - offset = start - offset; + loffset = start - loffset; /* partial truncate, clear end of page */ - if (offset < PAGE_CACHE_SIZE) { + if (loffset < PAGE_CACHE_SIZE) { + unsigned int offset = loffset; /* truncate ok */ unsigned long address = page_address(page); memset((void *) (offset + address), 0, PAGE_CACHE_SIZE - offset); flush_page_to_ram(address); @@ -195,7 +196,8 @@ * were to be marked referenced.. */ if (PageSwapCache(page)) { - if (referenced && swap_count(page->offset) != 1) + if (referenced && + swap_count(pgoff2ulong(page->index)) != 1) continue; delete_from_swap_cache(page); return 1; @@ -250,11 +252,12 @@ * memory maps. --sct */ -void update_vm_cache_conditional(struct inode * inode, unsigned long pos, const char * buf, int count, unsigned long source_address) +void update_vm_cache_conditional(struct inode * inode, loff_t pos, const char * buf, int count, unsigned long source_address) { unsigned long offset, len; + pgoff_t pgoff = loff2pgoff(pos); - offset = (pos & ~PAGE_CACHE_MASK); + offset = ((unsigned long)pos & ~PAGE_CACHE_MASK); pos = pos & PAGE_CACHE_MASK; len = PAGE_CACHE_SIZE - offset; do { @@ -262,7 +265,7 @@ if (len > count) len = count; - page = find_page(inode, pos); + page = find_page(inode, pgoff); if (page) { char *dest = (char*) (offset + page_address(page)); @@ -282,19 +285,20 @@ } while (count); } -void update_vm_cache(struct inode * inode, unsigned long pos, const char * buf, int count) +void update_vm_cache(struct inode * inode, loff_t pos, const char * buf, int count) { update_vm_cache_conditional(inode, pos, buf, count, 0); } static inline void add_to_page_cache(struct page * page, - struct inode * inode, unsigned long offset, - struct page **hash) + struct inode * inode, + pgoff_t pgoff, + struct page **hash) { atomic_inc(&page->count); page->flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) | (1 << PG_referenced)); - page->offset = offset; + page->index = pgoff; add_page_to_inode_queue(inode, page); __add_page_to_hash_queue(page, hash); } @@ -305,29 +309,32 @@ * this is all overlapped with the IO on the previous page finishing anyway) */ static unsigned long try_to_read_ahead(struct file * file, - unsigned long offset, unsigned long page_cache) + pgoff_t pgoff, unsigned long page_cache) { struct inode *inode = file->f_dentry->d_inode; - struct page * page; - struct page ** hash; + pgoff_t pg_size; - offset &= PAGE_CACHE_MASK; - switch (page_cache) { - case 0: + /* Calculate file size in 'pages' -- if even one byte (according to + the 'i_size') exceeds the final page-size block, round up. */ + pg_size = loff2pgoff(inode->i_size+(PAGE_SIZE-1)); + + if (!page_cache) { page_cache = page_cache_alloc(); if (!page_cache) - break; - default: - if (offset >= inode->i_size) - break; - hash = page_hash(inode, offset); - page = __find_page(inode, offset, *hash); + return 0; /* Can't allocate! */ + } + /* Ok, we have a page, make sure it is in the page cache */ + if (pgoff2ulong(pgoff) < pgoff2ulong(pg_size)) { + struct page * page; + struct page ** hash; + hash = page_hash(inode, pgoff); + page = __find_page(inode, pgoff, *hash); if (!page) { /* * Ok, add the new page to the hash-queues... */ page = page_cache_entry(page_cache); - add_to_page_cache(page, inode, offset, hash); + add_to_page_cache(page, inode, pgoff, hash); inode->i_op->readpage(file, page); page_cache = 0; } @@ -381,11 +388,11 @@ #define PROFILE_MAXREADCOUNT 1000 -static unsigned long total_reada; -static unsigned long total_async; -static unsigned long total_ramax; -static unsigned long total_ralen; -static unsigned long total_rawin; +static u_long total_reada; +static u_long total_async; +static u_long total_ramax; +static u_long total_ralen; +static u_long total_rawin; static void profile_readahead(int async, struct file *filp) { @@ -493,13 +500,13 @@ static inline unsigned long generic_file_readahead(int reada_ok, struct file * filp, struct inode * inode, - unsigned long ppos, struct page * page, unsigned long page_cache) + loff_t ppos, struct page * page, unsigned long page_cache) { - unsigned long max_ahead, ahead; - unsigned long raend; + loff_t max_ahead, ahead; + loff_t raend; int max_readahead = get_max_readahead(inode); - raend = filp->f_raend & PAGE_CACHE_MASK; + raend = filp->f_raend & PAGE_CACHE_MASK_loff; max_ahead = 0; /* @@ -557,7 +564,7 @@ ahead = 0; while (ahead < max_ahead) { ahead += PAGE_CACHE_SIZE; - page_cache = try_to_read_ahead(filp, raend + ahead, + page_cache = try_to_read_ahead(filp, loff2pgoff(raend + ahead), page_cache); } /* @@ -626,14 +633,14 @@ struct dentry *dentry = filp->f_dentry; struct inode *inode = dentry->d_inode; unsigned long page_cache; - size_t pos, pgpos; + loff_t pos, posp; int reada_ok; int max_readahead = get_max_readahead(inode); page_cache = 0; pos = *ppos; - pgpos = pos & PAGE_CACHE_MASK; + posp = pos & PAGE_CACHE_MASK_loff; /* * If the current position is outside the previous read-ahead window, * we reset the current read-ahead context and set read ahead max to zero @@ -641,7 +648,7 @@ * otherwise, we assume that the file accesses are sequential enough to * continue read-ahead. */ - if (pgpos > filp->f_raend || pgpos + filp->f_rawin < filp->f_raend) { + if (posp > filp->f_raend || posp + filp->f_rawin < filp->f_raend) { reada_ok = 0; filp->f_raend = 0; filp->f_ralen = 0; @@ -657,12 +664,12 @@ * Then, at least MIN_READAHEAD if read ahead is ok, * and at most MAX_READAHEAD in all cases. */ - if (pos + desc->count <= (PAGE_CACHE_SIZE >> 1)) { + if (pos + desc->count <= (loff_t)(PAGE_CACHE_SIZE >> 1)) { filp->f_ramax = 0; } else { - unsigned long needed; + loff_t needed; - needed = ((pos + desc->count) & PAGE_CACHE_MASK) - pgpos; + needed = ((pos + desc->count) & PAGE_CACHE_MASK) - posp; if (filp->f_ramax < needed) filp->f_ramax = needed; @@ -675,6 +682,7 @@ for (;;) { struct page *page, **hash; + pgoff_t pgoff; if (pos >= inode->i_size) break; @@ -682,8 +690,9 @@ /* * Try to find the data in the page cache.. */ - hash = page_hash(inode, pos & PAGE_CACHE_MASK); - page = __find_page(inode, pos & PAGE_CACHE_MASK, *hash); + pgoff = loff2pgoff(pos); + hash = page_hash(inode, pgoff); + page = __find_page(inode, pgoff, *hash); if (!page) goto no_cached_page; @@ -696,7 +705,7 @@ * the page has been rewritten. */ if (PageUptodate(page) || PageLocked(page)) - page_cache = generic_file_readahead(reada_ok, filp, inode, pos & PAGE_CACHE_MASK, page, page_cache); + page_cache = generic_file_readahead(reada_ok, filp, inode, pos & PAGE_CACHE_MASK_loff, page, page_cache); else if (reada_ok && filp->f_ramax > MIN_READAHEAD) filp->f_ramax = MIN_READAHEAD; @@ -721,8 +730,8 @@ flush_dcache_page(page_address(page)); offset = pos & ~PAGE_CACHE_MASK; - nr = PAGE_CACHE_SIZE - offset; - if (nr > inode->i_size - pos) + nr = PAGE_CACHE_SIZE - offset; /* small value */ + if ((loff_t)nr > (inode->i_size - pos)) nr = inode->i_size - pos; /* @@ -762,7 +771,7 @@ */ page = page_cache_entry(page_cache); page_cache = 0; - add_to_page_cache(page, inode, pos & PAGE_CACHE_MASK, hash); + add_to_page_cache(page, inode, pgoff, hash); /* * Error handling is tricky. If we get a read error, @@ -843,10 +852,26 @@ ssize_t generic_file_read(struct file * filp, char * buf, size_t count, loff_t *ppos) { ssize_t retval; + struct inode *inode = filp->f_dentry->d_inode; + + if (((ssize_t) count) < 0) + return -EINVAL; retval = -EFAULT; if (access_ok(VERIFY_WRITE, buf, count)) { retval = 0; + + /* L-F-S spec 2.2.1.25: */ + if (!(filp->f_flags & O_LARGEFILE) && + S_ISREG(inode->i_mode) && + (*ppos < inode->i_size) && count) { + if (*ppos >= 0x7fffffff) /* pos@2G forbidden */ + return -EOVERFLOW; + if (*ppos + count > 0x7fffffff) + /* Read only until end of allowed region */ + count = 0x7fffffff - *ppos; + } + if (count) { read_descriptor_t desc; @@ -895,6 +920,9 @@ struct file * in_file, * out_file; struct inode * in_inode, * out_inode; + if (((ssize_t) count) < 0) + return -EINVAL; + lock_kernel(); /* @@ -988,20 +1016,25 @@ struct file * file = area->vm_file; struct dentry * dentry = file->f_dentry; struct inode * inode = dentry->d_inode; - unsigned long offset, reada, i; + loff_t offset; + pgoff_t pgoff, reada; + int i; struct page * page, **hash; unsigned long old_page, new_page; new_page = 0; - offset = (address & PAGE_MASK) - area->vm_start + area->vm_offset; + offset = ((loff_t)((address & PAGE_MASK) - area->vm_start) + + area->vm_offset); + if (offset >= inode->i_size && (area->vm_flags & VM_SHARED) && area->vm_mm == current->mm) goto no_page; /* * Do we have something in the page cache already? */ - hash = page_hash(inode, offset); - page = __find_page(inode, offset, *hash); + pgoff = loff2pgoff(offset); + hash = page_hash(inode, pgoff); + page = __find_page(inode, pgoff, *hash); if (!page) goto no_cached_page; @@ -1052,11 +1085,12 @@ /* * Try to read in an entire cluster at once. */ - reada = offset; - reada >>= PAGE_CACHE_SHIFT + page_cluster; - reada <<= PAGE_CACHE_SHIFT + page_cluster; + reada = loff2pgoff(offset); + /* Mask lowest 'page_cluster' worth of the lowest bits */ + reada = ulong2pgoff(pgoff2ulong(reada) & ((~(0UL)) << page_cluster)); - for (i = 1 << page_cluster; i > 0; --i, reada += PAGE_CACHE_SIZE) + for (i = 1 << page_cluster; i > 0; + --i, reada = ulong2pgoff(pgoff2ulong(reada)+1)) new_page = try_to_read_ahead(file, reada, new_page); if (!new_page) @@ -1070,7 +1104,7 @@ * cache.. The page we just got may be useful if we * can't share, so don't get rid of it here. */ - page = find_page(inode, offset); + page = find_page(inode, pgoff); if (page) goto found_page; @@ -1079,7 +1113,7 @@ */ page = page_cache_entry(new_page); new_page = 0; - add_to_page_cache(page, inode, offset, hash); + add_to_page_cache(page, inode, pgoff, hash); if (inode->i_op->readpage(file, page) != 0) goto failure; @@ -1128,10 +1162,10 @@ * if the disk is full. */ static inline int do_write_page(struct inode * inode, struct file * file, - const char * page, unsigned long offset) + const char * page, loff_t offset) { int retval; - unsigned long size; + loff_t size; loff_t loff = offset; mm_segment_t old_fs; @@ -1155,7 +1189,7 @@ } static int filemap_write_page(struct vm_area_struct * vma, - unsigned long offset, + loff_t offset, unsigned long page) { int result; @@ -1189,7 +1223,7 @@ */ int filemap_swapout(struct vm_area_struct * vma, struct page * page) { - return filemap_write_page(vma, page->offset, page_address(page)); + return filemap_write_page(vma, pgoff2loff(page->index), page_address(page)); } static inline int filemap_sync_pte(pte_t * ptep, struct vm_area_struct *vma, @@ -1553,7 +1587,7 @@ { struct dentry *dentry = file->f_dentry; struct inode *inode = dentry->d_inode; - unsigned long pos = *ppos; + loff_t pos = *ppos; unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur; struct page *page, **hash; unsigned long page_cache = 0; @@ -1569,6 +1603,9 @@ return error; } + if (((ssize_t) count) < 0) + return -EINVAL; + sync = file->f_flags & O_SYNC; written = 0; @@ -1579,31 +1616,39 @@ * Check whether we've reached the file size limit. */ status = -EFBIG; - if (pos >= limit) { + if (limit != RLIM_INFINITY && pos >= limit) { send_sig(SIGXFSZ, current, 0); goto out; } + /* L-F-S */ + if (!(file->f_flags & O_LARGEFILE) && + S_ISREG(inode->i_mode) && count) { + if (pos >= 0x7fffffff) /* pos@2G forbidden */ + goto out; + + if (pos + count > 0x7fffffff) + count = 0x7fffffff - pos; + } + status = 0; /* * Check whether to truncate the write, * and send the signal if we do. */ - if (count > limit - pos) { - send_sig(SIGXFSZ, current, 0); + if (limit != RLIM_INFINITY && count > limit - pos) count = limit - pos; - } while (count) { - unsigned long bytes, pgpos, offset; + unsigned long bytes, offset; + pgoff_t pgpos = loff2pgoff(pos); char * dest; /* * Try to find the page in the cache. If it isn't there, * allocate a free page. */ - offset = (pos & ~PAGE_CACHE_MASK); - pgpos = pos & PAGE_CACHE_MASK; + offset = ((unsigned long)pos & ~PAGE_CACHE_MASK); bytes = PAGE_CACHE_SIZE - offset; if (bytes > count) bytes = count; @@ -1681,15 +1726,14 @@ * Note: we don't have to worry about races here, as the caller * is holding the inode semaphore. */ -unsigned long get_cached_page(struct inode * inode, unsigned long offset, - int new) +unsigned long get_cached_page(struct inode * inode, pgoff_t pgoff, int new) { struct page * page; struct page ** hash; unsigned long page_cache = 0; - hash = page_hash(inode, offset); - page = __find_page(inode, offset, *hash); + hash = page_hash(inode, pgoff); + page = __find_page(inode, pgoff, *hash); if (!page) { if (!new) goto out; @@ -1698,7 +1742,7 @@ goto out; clear_page(page_cache); page = page_cache_entry(page_cache); - add_to_page_cache(page, inode, offset, hash); + add_to_page_cache(page, inode, pgoff, hash); } if (atomic_read(&page->count) != 2) printk(KERN_ERR "get_cached_page: page count=%d\n", diff -urN lfs-ref/mm/memory.c lfs/mm/memory.c --- lfs-ref/mm/memory.c Wed Sep 12 02:39:58 2001 +++ lfs/mm/memory.c Wed Sep 12 02:42:15 2001 @@ -862,7 +862,7 @@ case 2: if (!PageSwapCache(page_map)) break; - if (swap_count(page_map->offset) != 1) + if (swap_count(pgoff2ulong(page_map->index)) != 1) break; delete_from_swap_cache(page_map); /* FallThrough */ @@ -986,7 +986,7 @@ * between the file and the memory map for a potential last * incomplete page. Ugly, but necessary. */ -void vmtruncate(struct inode * inode, unsigned long offset) +void vmtruncate(struct inode * inode, loff_t offset) { truncate_inode_pages(inode, offset); if (inode->i_mmap) diff -urN lfs-ref/mm/mmap.c lfs/mm/mmap.c --- lfs-ref/mm/mmap.c Wed Sep 12 02:39:57 2001 +++ lfs/mm/mmap.c Wed Sep 12 02:42:15 2001 @@ -169,11 +169,25 @@ #undef _trans } -unsigned long do_mmap(struct file * file, unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, unsigned long off) +unsigned long do_mmap(struct file *file, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flag, unsigned long offset) +{ + unsigned long ret = -EINVAL; + if ((offset + PAGE_ALIGN(len)) < offset) + goto out; + if (!(offset & ~PAGE_MASK)) + ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); +out: + return ret; +} + +unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, unsigned long pg_off) { struct mm_struct * mm = current->mm; struct vm_area_struct * vma; + loff_t off = (loff_t)pg_off << PAGE_SHIFT; int error; if (file && (!file->f_op || !file->f_op->mmap)) @@ -847,7 +861,8 @@ * the offsets must be contiguous.. */ if ((mpnt->vm_file != NULL) || (mpnt->vm_flags & VM_SHM)) { - unsigned long off = prev->vm_offset+prev->vm_end-prev->vm_start; + loff_t off = (prev->vm_offset + + (loff_t)(prev->vm_end - prev->vm_start)); if (off != mpnt->vm_offset) continue; } diff -urN lfs-ref/mm/page_alloc.c lfs/mm/page_alloc.c --- lfs-ref/mm/page_alloc.c Wed Sep 12 02:39:57 2001 +++ lfs/mm/page_alloc.c Wed Sep 12 02:42:15 2001 @@ -115,7 +115,7 @@ add_mem_queue(area, list(map_nr)); static void free_local_pages(struct page * page) { - unsigned long order = page->offset; + unsigned long order = page->index; unsigned int type = PageDMA(page) ? 1 : 0; struct free_area_struct *area; unsigned long map_nr = page - mem_map; @@ -172,7 +172,7 @@ page = mem_map + map_nr; list_add((struct list_head *) page, ¤t->local_pages); - page->offset = order; + page->index = order; current->nr_local_pages++; } diff -urN lfs-ref/mm/page_io.c lfs/mm/page_io.c --- lfs-ref/mm/page_io.c Tue Jun 13 03:48:15 2000 +++ lfs/mm/page_io.c Wed Sep 12 02:42:15 2001 @@ -112,7 +112,7 @@ * as if it were: we are not allowed to manipulate the inode * hashing for locked pages. */ - if (page->offset != entry) { + if (pgoff2ulong(page->index) != entry) { printk ("swap entry mismatch"); return; } @@ -265,8 +265,8 @@ printk("VM: swap page is not in swap cache\n"); return; } - if (page->offset != entry) { - printk ("swap entry mismatch"); + if (pgoff2ulong(page->index) != entry) { + printk ("VM: swap entry mismatch"); return; } rw_swap_page_base(rw, entry, page, wait); @@ -291,12 +291,12 @@ printk ("VM: read_swap_page: page already in page cache!\n"); return; } - page->inode = &swapper_inode; - page->offset = entry; + page->inode = &swapper_inode; + page->index = ulong2pgoff(entry); atomic_inc(&page->count); /* Protect from shrink_mmap() */ rw_swap_page(rw, entry, buffer, 1); atomic_dec(&page->count); - page->inode = 0; + page->inode = 0; clear_bit(PG_swap_cache, &page->flags); } diff -urN lfs-ref/mm/swap_state.c lfs/mm/swap_state.c --- lfs-ref/mm/swap_state.c Fri Apr 20 22:31:21 2001 +++ lfs/mm/swap_state.c Wed Sep 12 02:42:15 2001 @@ -54,7 +54,7 @@ if (PageTestandSetSwapCache(page)) { printk(KERN_ERR "swap_cache: replacing non-empty entry %08lx " "on page %08lx\n", - page->offset, page_address(page)); + pgoff2ulong(page->index), page_address(page)); return 0; } if (page->inode) { @@ -65,8 +65,8 @@ atomic_inc(&page->count); page->flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) | (1 << PG_referenced)); page->inode = &swapper_inode; - page->offset = entry; - add_page_to_hash_queue(page, &swapper_inode, entry); + page->index = ulong2pgoff(entry); + add_page_to_hash_queue(page, &swapper_inode, ulong2pgoff(entry)); add_page_to_inode_queue(&swapper_inode, page); return 1; } @@ -204,7 +204,7 @@ */ void delete_from_swap_cache(struct page *page) { - long entry = page->offset; + long entry = pgoff2ulong(page->index); #ifdef SWAP_CACHE_INFO swap_cache_del_total++; @@ -252,7 +252,7 @@ swap_cache_find_total++; #endif while (1) { - found = find_page(&swapper_inode, entry); + found = find_page(&swapper_inode, ulong2pgoff(entry)); if (!found) return 0; if (found->inode != &swapper_inode || !PageSwapCache(found)) diff -urN lfs-ref/mm/vmscan.c lfs/mm/vmscan.c --- lfs-ref/mm/vmscan.c Wed Sep 12 02:39:57 2001 +++ lfs/mm/vmscan.c Wed Sep 12 02:42:15 2001 @@ -74,7 +74,7 @@ * memory, and we should just continue our scan. */ if (PageSwapCache(page_map)) { - entry = page_map->offset; + entry = pgoff2ulong(page_map->index); swap_duplicate(entry); set_pte(page_table, __pte(entry)); drop_pte: