This is based on released 2.3.26 This compiles *and* boots/runs at my PPro200. /Matti Aarnio This is compiled only at one PPro200 machine, and lacks support for arch/sh/ ! Syscall vectors are *not* defined at this patch set! - include/linux/fs.h VERIFY: block_write_cont_page() - include/linux/mm.h VERIFY: get_cached_page() VERIFY: all usage instanses of: locks_verify_area() HFS has wrong thing at hfs_bmap (baseline bug) NTFS has wrong thing at ntfs_bmap (baseline bug) NTFS calls update_vm_cache (baseline bug) AFFS has wrong thing at ntfs_bmap (baseline bug) AFFS calls update_vm_cache (baseline bug) ADFS has wrong thing at adfs_bmap (baseline bug) NCPFS needs checking (page cache usage) QNX4 calls update_vm_cache (baseline bug) QNX4 has wrong thing as qnx4_bmap (baseline bug) SMBFS needs "page->index" verification ... (baseline bug) UFS truncation ( truncate.c ) needs checking! KHTTPD needs updates ( sock_send_actor() code needs update ) (baseline bug) loopback driver could (?) be turned into LFS aware diff -ur linux-23026base/arch/alpha/kernel/osf_sys.c linux-23026m1/arch/alpha/kernel/osf_sys.c --- linux-23026base/arch/alpha/kernel/osf_sys.c Thu Jul 29 23:37:22 1999 +++ linux-23026m1/arch/alpha/kernel/osf_sys.c Sun Nov 7 23:18:41 1999 @@ -295,7 +295,7 @@ __kernel_fsid_t f_fsid; } *osf_stat; -static int linux_to_osf_statfs(struct statfs *linux_stat, struct osf_statfs *osf_stat, unsigned long bufsiz) +static int linux_to_osf_statfs(struct statvfs64 *linux_stat, struct osf_statfs *osf_stat, unsigned long bufsiz) { struct osf_statfs tmp_stat; @@ -317,16 +317,15 @@ static int do_osf_statfs(struct dentry * dentry, struct osf_statfs *buffer, unsigned long bufsiz) { - struct statfs linux_stat; + struct statvfs64 linux_stat; struct inode * inode = dentry->d_inode; struct super_block * sb = inode->i_sb; int error; error = -ENODEV; - if (sb && sb->s_op && sb->s_op->statfs) { - set_fs(KERNEL_DS); - error = sb->s_op->statfs(sb, &linux_stat, sizeof(linux_stat)); - set_fs(USER_DS); + if (sb && sb->s_op && sb->s_op->statvfs) { + memset(&linux_stat, 0, sizeof(linux_stat)); + error = sb->s_op->statvfs(sb, &linux_stat); if (!error) error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz); } diff -ur linux-23026base/arch/arm/kernel/sys_arm.c linux-23026m1/arch/arm/kernel/sys_arm.c --- linux-23026base/arch/arm/kernel/sys_arm.c Thu Oct 28 20:16:02 1999 +++ linux-23026m1/arch/arm/kernel/sys_arm.c Sun Nov 7 23:27:38 1999 @@ -91,7 +91,43 @@ return error; } +struct mmap_arg_struct64 { + __u32 addr; + __u32 len; + __u32 prot; + __u32 flags; + __u32 fd; + __u64 offset; /* 64 bits */ +}; +asmlinkage int old_mmap64(struct mmap_arg_struct64 *arg) +{ + int error = -EFAULT; + struct file * file = NULL; + struct mmap_arg_struct64 a; + + if (copy_from_user(&a, arg, sizeof(a))) + return -EFAULT; + + 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); + + error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset); + if (file) + fput(file); +out: + unlock_kernel(); + up(¤t->mm->mmap_sem); + return error; +} + extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); struct sel_arg_struct { diff -ur linux-23026base/arch/i386/kernel/sys_i386.c linux-23026m1/arch/i386/kernel/sys_i386.c --- linux-23026base/arch/i386/kernel/sys_i386.c Wed Nov 3 21:31:09 1999 +++ linux-23026m1/arch/i386/kernel/sys_i386.c Sun Nov 7 23:29:16 1999 @@ -85,6 +85,44 @@ return error; } + +struct mmap_arg_struct64 { + __u32 addr; + __u32 len; + __u32 prot; + __u32 flags; + __u32 fd; + __u64 offset; /* 64 bits */ +}; + +asmlinkage int old_mmap64(struct mmap_arg_struct64 *arg) +{ + int error = -EFAULT; + struct file * file = NULL; + struct mmap_arg_struct64 a; + + if (copy_from_user(&a, arg, sizeof(a))) + return -EFAULT; + + 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); + + error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset); + if (file) + fput(file); +out: + unlock_kernel(); + up(¤t->mm->mmap_sem); + return error; +} + extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); struct sel_arg_struct { diff -ur linux-23026base/arch/m68k/kernel/sys_m68k.c linux-23026m1/arch/m68k/kernel/sys_m68k.c --- linux-23026base/arch/m68k/kernel/sys_m68k.c Tue Jan 19 20:58:34 1999 +++ linux-23026m1/arch/m68k/kernel/sys_m68k.c Sun Nov 7 23:31:37 1999 @@ -88,6 +88,42 @@ return error; } +struct mmap_arg_struct64 { + __u32 addr; + __u32 len; + __u32 prot; + __u32 flags; + __u32 fd; + __u64 offset; /* 64 bits */ +}; + +asmlinkage int old_mmap64(struct mmap_arg_struct64 *arg) +{ + int error = -EFAULT; + struct file * file = NULL; + struct mmap_arg_struct64 a; + + if (copy_from_user(&a, arg, sizeof(a))) + return -EFAULT; + + 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); + + error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset); + if (file) + fput(file); +out: + unlock_kernel(); + up(¤t->mm->mmap_sem); + return error; +} extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); diff -ur linux-23026base/arch/mips/kernel/sysirix.c linux-23026m1/arch/mips/kernel/sysirix.c --- linux-23026base/arch/mips/kernel/sysirix.c Sat Jun 26 03:40:12 1999 +++ linux-23026m1/arch/mips/kernel/sysirix.c Sun Nov 7 23:36:34 1999 @@ -727,8 +727,7 @@ { struct dentry *dentry; struct inode *inode; - mm_segment_t old_fs; - struct statfs kbuf; + struct statvfs64 kbuf; int error, i; lock_kernel(); @@ -747,10 +746,7 @@ goto out; inode = dentry->d_inode; - old_fs = get_fs(); set_fs(get_ds()); - error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, - sizeof(struct statfs)); - set_fs(old_fs); + error = inode->i_sb->s_op->statvfs(inode->i_sb, &kbuf); if (error) goto dput_and_out; @@ -777,8 +773,7 @@ asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs *buf) { struct inode *inode; - struct statfs kbuf; - mm_segment_t old_fs; + struct statvfs64 kbuf; struct file *file; int error, i; @@ -799,15 +794,12 @@ error = -ENODEV; goto out_f; } - if (!inode->i_sb->s_op->statfs) { + if (!inode->i_sb->s_op->statvfs) { error = -ENOSYS; goto out_f; } - old_fs = get_fs(); set_fs(get_ds()); - error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, - sizeof(struct statfs)); - set_fs(old_fs); + error = inode->i_sb->s_op->statvfs(inode->i_sb, &kbuf); if (error) goto out_f; @@ -1510,8 +1502,7 @@ { struct dentry *dentry; struct inode *inode; - mm_segment_t old_fs; - struct statfs kbuf; + struct statvfs64 kbuf; int error, i; lock_kernel(); @@ -1527,13 +1518,10 @@ inode = dentry->d_inode; error = -ENOSYS; - if(!inode->i_sb->s_op->statfs) + if(!inode->i_sb->s_op->statvfs) goto dput_and_out; - old_fs = get_fs(); set_fs(get_ds()); - error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, - sizeof(struct statfs)); - set_fs(old_fs); + error = inode->i_sb->s_op->statvfs(inode->i_sb, &kbuf); if (error) goto dput_and_out; @@ -1569,8 +1557,7 @@ asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf) { struct inode *inode; - mm_segment_t old_fs; - struct statfs kbuf; + struct statvfs64 kbuf; struct file *file; int error, i; @@ -1593,15 +1580,12 @@ error = -ENODEV; goto out_f; } - if (!inode->i_sb->s_op->statfs) { + if (!inode->i_sb->s_op->statvfs) { error = -ENOSYS; goto out_f; } - old_fs = get_fs(); set_fs(get_ds()); - error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, - sizeof(struct statfs)); - set_fs(old_fs); + error = inode->i_sb->s_op->statvfs(inode->i_sb, &kbuf); if (error) goto out_f; @@ -1805,8 +1789,7 @@ { struct dentry *dentry; struct inode *inode; - mm_segment_t old_fs; - struct statfs kbuf; + struct statvfs64 kbuf; int error, i; lock_kernel(); @@ -1821,13 +1804,10 @@ goto out; error = -ENOSYS; inode = dentry->d_inode; - if(!inode->i_sb->s_op->statfs) + if(!inode->i_sb->s_op->statvfs) goto dput_and_out; - old_fs = get_fs(); set_fs(get_ds()); - error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, - sizeof(struct statfs)); - set_fs(old_fs); + error = inode->i_sb->s_op->statvfs(inode->i_sb, &kbuf); if (error) goto dput_and_out; @@ -1863,8 +1843,7 @@ asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf) { struct inode *inode; - mm_segment_t old_fs; - struct statfs kbuf; + struct statvfs64 kbuf; struct file *file; int error, i; @@ -1887,15 +1866,12 @@ error = -ENODEV; goto out_f; } - if (!inode->i_sb->s_op->statfs) { + if (!inode->i_sb->s_op->statvfs) { error = -ENOSYS; goto out_f; } - old_fs = get_fs(); set_fs(get_ds()); - error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, - sizeof(struct statfs)); - set_fs(old_fs); + error = inode->i_sb->s_op->statvfs(inode->i_sb, &kbuf); if (error) goto out_f; diff -ur linux-23026base/arch/sparc64/solaris/fs.c linux-23026m1/arch/sparc64/solaris/fs.c --- linux-23026base/arch/sparc64/solaris/fs.c Sat May 15 21:12:09 1999 +++ linux-23026m1/arch/sparc64/solaris/fs.c Sun Nov 7 23:57:48 1999 @@ -299,30 +299,41 @@ asmlinkage int solaris_statfs(u32 path, u32 buf, int len, int fstype) { - int ret; - struct statfs s; - mm_segment_t old_fs = get_fs(); - int (*sys_statfs)(const char *,struct statfs *) = - (int (*)(const char *,struct statfs *))SYS(statfs); + struct statvfs64 s; struct sol_statfs *ss = (struct sol_statfs *)A(buf); + struct dentry *dentry; + struct inode *inode; + int error, i; if (len != sizeof(struct sol_statfs)) return -EINVAL; + + lock_kernel(); + if (!fstype) { - set_fs (KERNEL_DS); - ret = sys_statfs((const char *)A(path), &s); - set_fs (old_fs); - if (!ret) { - if (put_user (s.f_type, &ss->f_type) || - __put_user (s.f_bsize, &ss->f_bsize) || - __put_user (0, &ss->f_frsize) || - __put_user (s.f_blocks, &ss->f_blocks) || - __put_user (s.f_bfree, &ss->f_bfree) || - __put_user (s.f_files, &ss->f_files) || - __put_user (s.f_ffree, &ss->f_ffree) || - __clear_user (&ss->f_fname, 12)) - return -EFAULT; + dentry = namei(path); + error = PTR_ERR(dentry); + if (IS_ERR(dentry)) + goto out; + + inode = dentry->d_inode; + error = inode->i_sb->s_op->statvfs(inode->i_sb, &s); + if (error) + goto dput_and_out; + + if (put_user (s.f_type, &ss->f_type) || + __put_user (s.f_bsize, &ss->f_bsize) || + __put_user (0, &ss->f_frsize) || + __put_user (s.f_blocks, &ss->f_blocks) || + __put_user (s.f_bfree, &ss->f_bfree) || + __put_user (s.f_files, &ss->f_files) || + __put_user (s.f_ffree, &ss->f_ffree) || + __clear_user (&ss->f_fname, 12)) { + error = -EFAULT; } - return ret; + dput_and_out: + dput(dentry); + + goto out; } /* Linux can't stat unmounted filesystems so we * simply lie and claim 100MB of 1GB is free. Sorry. @@ -335,39 +346,68 @@ __put_user (60000, &ss->f_files) || __put_user (50000, &ss->f_ffree) || __clear_user (&ss->f_fname, 12)) - return -EFAULT; - return 0; + error = -EFAULT; + +out: + unlock_kernel(); + return error; } asmlinkage int solaris_fstatfs(u32 fd, u32 buf, int len, int fstype) { - int ret; - struct statfs s; - mm_segment_t old_fs = get_fs(); - int (*sys_fstatfs)(unsigned,struct statfs *) = - (int (*)(unsigned,struct statfs *))SYS(fstatfs); + struct statvfs64 s; struct sol_statfs *ss = (struct sol_statfs *)A(buf); + struct inode *inode; + struct file *file; + int error, i; if (len != sizeof(struct sol_statfs)) return -EINVAL; - if (!fstype) { - set_fs (KERNEL_DS); - ret = sys_fstatfs(fd, &s); - set_fs (old_fs); - if (!ret) { - if (put_user (s.f_type, &ss->f_type) || - __put_user (s.f_bsize, &ss->f_bsize) || - __put_user (0, &ss->f_frsize) || - __put_user (s.f_blocks, &ss->f_blocks) || - __put_user (s.f_bfree, &ss->f_bfree) || - __put_user (s.f_files, &ss->f_files) || - __put_user (s.f_ffree, &ss->f_ffree) || - __clear_user (&ss->f_fname, 12)) - return -EFAULT; - } - return ret; + + if (fstype) { + /* Otherwise fstatfs is the same as statfs */ + return solaris_statfs(0, buf, len, fstype); } - /* Otherwise fstatfs is the same as statfs */ - return solaris_statfs(0, buf, len, fstype); + + lock_kernel(); + + if (!(file = fget(fd))) { + error = -EBADF; + goto out; + } + + if (!(inode = file->f_dentry->d_inode)) { + error = -ENOENT; + goto out_f; + } + if (!inode->i_sb) { + error = -ENODEV; + goto out_f; + } + if (!inode->i_sb->s_op->statvfs) { + error = -ENOSYS; + goto out_f; + } + + error = inode->i_sb->s_op->statvfs(inode->i_sb, &s); + if (error) + goto out_f; + + if (!error) { + if (put_user (s.f_type, &ss->f_type) || + __put_user (s.f_bsize, &ss->f_bsize) || + __put_user (0, &ss->f_frsize) || + __put_user (s.f_blocks, &ss->f_blocks) || + __put_user (s.f_bfree, &ss->f_bfree) || + __put_user (s.f_files, &ss->f_files) || + __put_user (s.f_ffree, &ss->f_ffree) || + __clear_user (&ss->f_fname, 12)) + error = -EFAULT; + } +out_f: + fput(file); +out: + unlock_kernel(); + return error; } struct sol_statvfs { @@ -406,18 +446,15 @@ static int report_statvfs(struct inode *inode, u32 buf) { - struct statfs s; - mm_segment_t old_fs = get_fs(); + struct statvfs64 s; int error; struct sol_statvfs *ss = (struct sol_statvfs *)A(buf); if (!inode->i_sb) return -ENODEV; - if (!inode->i_sb->s_op->statfs) + if (!inode->i_sb->s_op->statvfs) return -ENOSYS; - set_fs (KERNEL_DS); - error = inode->i_sb->s_op->statfs(inode->i_sb, &s, sizeof(struct statfs)); - set_fs (old_fs); + error = inode->i_sb->s_op->statvfs(inode->i_sb, &s); if (!error) { const char *p = inode->i_sb->s_type->name; int i = 0; @@ -447,18 +484,15 @@ static int report_statvfs64(struct inode *inode, u32 buf) { - struct statfs s; - mm_segment_t old_fs = get_fs(); + struct statvfs64 s; int error; struct sol_statvfs64 *ss = (struct sol_statvfs64 *)A(buf); if (!inode->i_sb) return -ENODEV; - if (!inode->i_sb->s_op->statfs) + if (!inode->i_sb->s_op->statvfs) return -ENOSYS; - set_fs (KERNEL_DS); - error = inode->i_sb->s_op->statfs(inode->i_sb, &s, sizeof(struct statfs)); - set_fs (old_fs); + error = inode->i_sb->s_op->statvfs(inode->i_sb, &s); if (!error) { const char *p = inode->i_sb->s_type->name; int i = 0; diff -ur linux-23026base/fs/adfs/dir.c linux-23026m1/fs/adfs/dir.c --- linux-23026base/fs/adfs/dir.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/adfs/dir.c Mon Nov 8 11:51:07 1999 @@ -9,6 +9,7 @@ #include #include #include +#include static ssize_t adfs_dirread (struct file *filp, char *buf, size_t siz, loff_t *ppos) @@ -17,6 +18,7 @@ } static int adfs_readdir (struct file *, void *, filldir_t); +extern int adfs_pathconf(struct inode *, int); static struct file_operations adfs_dir_operations = { NULL, /* lseek - default */ @@ -32,7 +34,7 @@ file_fsync, /* fsync */ NULL, /* fasync */ NULL, /* check_media_change */ - NULL /* revalidate */ + NULL, /* revalidate */ }; /* @@ -346,4 +348,30 @@ } adfs_dir_free (bh, buffers); return 0; +} + +int adfs_pathconf(struct inode *inode, int option) +{ + switch (option) { + case _PC_NAME_MAX: /* POSIX.1: Directory only */ + return ADFS_NAME_LEN; /* name component max length */ + case _PC_NO_TRUNC: + return 1; /* Semantics ??? */ + + case _PC_FILESIZEBITS: /* LFS: Regular files, and dirs */ + return 32; + + case _PC_LINK_MAX: /* POSIX.1: regular files and dirs */ + return 2; + + case _PC_CHOWN_RESTRICTED: /* POSIX.1: Any file, any dir */ + break; /* FIXME: some mount-option ??? */ + + case _PC_SYNC_IO: /* POSIX.4: Regular files only ? */ + case _PC_ASYNC_IO: /* TTY only ?? */ + break; + default: + break; + } + return -EINVAL; /* Unknown thing! */ } diff -ur linux-23026base/fs/adfs/file.c linux-23026m1/fs/adfs/file.c --- linux-23026base/fs/adfs/file.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/adfs/file.c Mon Nov 8 00:02:37 1999 @@ -48,6 +48,8 @@ NULL /* revalidate */ }; +extern int adfs_pathconf(struct inode *, int); + struct inode_operations adfs_file_inode_operations = { &adfs_file_operations, /* default file operations */ NULL, /* create */ @@ -68,5 +70,6 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + adfs_pathconf, /* pathconf */ }; diff -ur linux-23026base/fs/adfs/super.c linux-23026m1/fs/adfs/super.c --- linux-23026base/fs/adfs/super.c Fri Aug 27 00:18:06 1999 +++ linux-23026m1/fs/adfs/super.c Mon Nov 8 00:04:40 1999 @@ -23,7 +23,7 @@ static void adfs_put_super(struct super_block *sb); static int adfs_remount(struct super_block *sb, int *flags, char *data); -static int adfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz); +static int adfs_statvfs(struct super_block *sb, struct statvfs64 *buf); void adfs_read_inode(struct inode *inode); void adfs_error(struct super_block *sb, const char *function, const char *fmt, ...) @@ -92,7 +92,7 @@ NULL, adfs_put_super, NULL, - adfs_statfs, + adfs_statvfs, adfs_remount }; @@ -322,16 +322,15 @@ return NULL; } -static int adfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) +static int adfs_statvfs(struct super_block *sb, struct statvfs64 *buf) { - struct statfs tmp; const unsigned int nidlen = sb->u.adfs_sb.s_idlen + 1; - tmp.f_type = ADFS_SUPER_MAGIC; - tmp.f_bsize = sb->s_blocksize; - tmp.f_blocks = sb->u.adfs_sb.s_dr->disc_size_high << (32 - sb->s_blocksize_bits) | + buf->f_type = ADFS_SUPER_MAGIC; + buf->f_bsize = sb->s_blocksize; + buf->f_blocks = sb->u.adfs_sb.s_dr->disc_size_high << (32 - sb->s_blocksize_bits) | sb->u.adfs_sb.s_dr->disc_size >> sb->s_blocksize_bits; - tmp.f_files = tmp.f_blocks >> nidlen; + buf->f_files = buf->f_blocks >> nidlen; { unsigned int i, j = 0; const unsigned mask = (1 << (nidlen - 1)) - 1; @@ -373,12 +372,12 @@ else if (freelink) adfs_error(sb, NULL, "undersized free fragment\n"); } - tmp.f_bfree = tmp.f_bavail = j << + buf->f_bfree = buf->f_bavail = j << (sb->u.adfs_sb.s_dr->log2bpmb - sb->s_blocksize_bits); } - tmp.f_ffree = tmp.f_bfree >> nidlen; - tmp.f_namelen = ADFS_NAME_LEN; - return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; + buf->f_ffree = buf->f_bfree >> nidlen; + buf->f_namelen = ADFS_NAME_LEN; + return 0; } static struct file_system_type adfs_fs_type = { diff -ur linux-23026base/fs/affs/dir.c linux-23026m1/fs/affs/dir.c --- linux-23026base/fs/affs/dir.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/affs/dir.c Mon Nov 8 00:06:38 1999 @@ -23,9 +23,11 @@ #include #include #include +#include static int affs_readdir(struct file *, void *, filldir_t); static ssize_t affs_dir_read(struct file *, char *, size_t, loff_t *); +extern int affs_pathconf(struct inode *inode, int option); static struct file_operations affs_dir_operations = { NULL, /* lseek - default */ @@ -64,7 +66,8 @@ NULL, /* truncate */ NULL, /* permissions */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + affs_pathconf, /* pathconf */ }; static ssize_t @@ -181,4 +184,30 @@ affs_brelse(fh_bh); pr_debug("AFFS: readdir()=%d\n",stored); return stored; +} + +int affs_pathconf(struct inode *inode, int option) +{ + switch (option) { + case _PC_NAME_MAX: /* POSIX.1: Directory only */ + return 30; /* name component max length */ + case _PC_NO_TRUNC: + return 0; /* Will *silently* truncate */ + + case _PC_FILESIZEBITS: /* LFS: Regular files, and dirs */ + return 32; + + case _PC_LINK_MAX: /* POSIX.1: regular files and dirs */ + return -INT_MAX; /* Unknown ?? */ + + case _PC_CHOWN_RESTRICTED: /* POSIX.1: Any file, any dir */ + break; /* FIXME: some mount-option ??? */ + + case _PC_SYNC_IO: /* POSIX.4: Regular files only ? */ + case _PC_ASYNC_IO: /* TTY only ?? */ + break; + default: + break; + } + return -EINVAL; /* Unknown thing! */ } diff -ur linux-23026base/fs/affs/file.c linux-23026m1/fs/affs/file.c --- linux-23026base/fs/affs/file.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/affs/file.c Mon Nov 8 20:30:57 1999 @@ -560,7 +560,7 @@ sector = affs_bmap(inode,(u32)*ppos / blocksize); if (!sector) break; - offset = (u32)*ppos % blocksize; + offset = (u32)(*ppos) % blocksize; bh = affs_bread(inode->i_dev,sector,AFFS_I2BSIZE(inode)); if (!bh) break; @@ -580,17 +580,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"); @@ -609,16 +609,22 @@ else pos = *ppos; written = 0; - blocksize = AFFS_I2BSIZE(inode); + blocksize = AFFS_I2BSIZE(inode); /* power of two! */ + 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)) { @@ -631,7 +637,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); @@ -660,14 +666,15 @@ { struct inode *inode = filp->f_dentry->d_inode; off_t pos; + loff_t lpos; ssize_t written; ssize_t c; ssize_t blocksize; struct buffer_head *bh; char *p; - pr_debug("AFFS: file_write_ofs(ino=%lu,pos=%lu,count=%d)\n",inode->i_ino, - (unsigned long)*ppos,count); + pr_debug("AFFS: file_write_ofs(ino=%lu,pos=%Lu,count=%d)\n",inode->i_ino, + *ppos,count); if (!count) return 0; @@ -684,21 +691,25 @@ if (!inode->u.affs_i.i_ec && alloc_ext_cache(inode)) return -ENOMEM; if (filp->f_flags & O_APPEND) - pos = inode->i_size; + lpos = inode->i_size; else - pos = *ppos; + lpos = *ppos; + + if (lpos > 0x7fffffffLL) + return -EFBIG; + pos = lpos; bh = NULL; blocksize = AFFS_I2BSIZE(inode) - 24; written = 0; while (written < count) { - bh = affs_getblock(inode,pos / blocksize); + bh = affs_getblock(inode,(u32)pos / blocksize); if (!bh) { if (!written) written = -ENOSPC; break; } - c = blocksize - (pos % blocksize); + c = blocksize - ((u32)pos & blocksize); if (c > count - written) c = count - written; if (c != blocksize && !buffer_uptodate(bh)) { @@ -711,7 +722,7 @@ break; } } - p = (pos % blocksize) + bh->b_data + 24; + p = (((u_long)pos) % blocksize) + bh->b_data + 24; c -= copy_from_user(p,buf,c); if (!c) { affs_brelse(bh); @@ -780,10 +791,13 @@ 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); + if (inode->i_size > 0x7fffffffULL) + /* XXX Fine! No way to indicate an error. */ + return /* -EFBIG */; 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,7 +809,7 @@ affs_warning(inode->i_sb,"truncate","Cannot extend file"); inode->i_size = net_blocksize * (inode->u.affs_i.i_lastblock + 1); } 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; 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); @@ -862,7 +876,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, @@ -870,7 +884,7 @@ * so it cannot become accessible again. */ - rem = inode->i_size % net_blocksize; + rem = ((u_long)inode->i_size) % net_blocksize; if (rem) { if ((inode->i_sb->u.affs_sb.s_flags & SF_OFS)) rem += 24; diff -ur linux-23026base/fs/affs/inode.c linux-23026m1/fs/affs/inode.c --- linux-23026base/fs/affs/inode.c Mon Mar 8 01:25:23 1999 +++ linux-23026m1/fs/affs/inode.c Mon Nov 8 00:33:53 1999 @@ -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 -ur linux-23026base/fs/affs/super.c linux-23026m1/fs/affs/super.c --- linux-23026base/fs/affs/super.c Fri Aug 27 00:18:06 1999 +++ linux-23026m1/fs/affs/super.c Mon Nov 8 11:47:06 1999 @@ -35,7 +35,7 @@ #define MIN(a,b) (((a)<(b))?(a):(b)) -static int affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz); +static int affs_statvfs(struct super_block *sb, struct statvfs64 *buf); static int affs_remount (struct super_block *sb, int *flags, char *data); static void @@ -105,7 +105,7 @@ affs_notify_change, affs_put_super, affs_write_super, - affs_statfs, + affs_statvfs, affs_remount }; @@ -662,23 +662,22 @@ } static int -affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) +affs_statvfs(struct super_block *sb, struct statvfs64 *buf) { int free; - struct statfs tmp; - pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",sb->u.affs_sb.s_partition_size, + pr_debug("AFFS: statvfs() partsize=%d, reserved=%d\n",sb->u.affs_sb.s_partition_size, sb->u.affs_sb.s_reserved); free = affs_count_free_blocks(sb); - tmp.f_type = AFFS_SUPER_MAGIC; - tmp.f_bsize = sb->s_blocksize; - tmp.f_blocks = sb->u.affs_sb.s_partition_size - sb->u.affs_sb.s_reserved; - tmp.f_bfree = free; - tmp.f_bavail = free; - tmp.f_files = 0; - tmp.f_ffree = 0; - return copy_to_user(buf,&tmp,bufsiz) ? -EFAULT : 0; + buf->f_type = AFFS_SUPER_MAGIC; + buf->f_bsize = sb->s_blocksize; + buf->f_blocks = sb->u.affs_sb.s_partition_size - sb->u.affs_sb.s_reserved; + buf->f_bfree = free; + buf->f_bavail = free; + buf->f_files = 0; + buf->f_ffree = 0; + return 0; } static struct file_system_type affs_fs_type = { diff -ur linux-23026base/fs/autofs/inode.c linux-23026m1/fs/autofs/inode.c --- linux-23026base/fs/autofs/inode.c Tue Jun 8 20:47:58 1999 +++ linux-23026m1/fs/autofs/inode.c Mon Nov 8 00:36:22 1999 @@ -55,7 +55,7 @@ #endif } -static int autofs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz); +static int autofs_statvfs(struct super_block *sb, struct statvfs64 *buf); static void autofs_read_inode(struct inode *inode); static void autofs_write_inode(struct inode *inode); @@ -67,7 +67,7 @@ NULL, /* notify_change */ autofs_put_super, NULL, /* write_super */ - autofs_statfs, + autofs_statvfs, NULL }; @@ -277,19 +277,17 @@ return NULL; } -static int autofs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) +static int autofs_statvfs(struct super_block *sb, struct statvfs64 *buf) { - struct statfs tmp; - - tmp.f_type = AUTOFS_SUPER_MAGIC; - tmp.f_bsize = 1024; - tmp.f_blocks = 0; - tmp.f_bfree = 0; - tmp.f_bavail = 0; - tmp.f_files = 0; - tmp.f_ffree = 0; - tmp.f_namelen = NAME_MAX; - return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; + buf->f_type = AUTOFS_SUPER_MAGIC; + buf->f_bsize = 1024; + buf->f_blocks = 0; + buf->f_bfree = 0; + buf->f_bavail = 0; + buf->f_files = 0; + buf->f_ffree = 0; + buf->f_namelen = NAME_MAX; + return 0; } static void autofs_read_inode(struct inode *inode) diff -ur linux-23026base/fs/bad_inode.c linux-23026m1/fs/bad_inode.c --- linux-23026base/fs/bad_inode.c Sat Jun 26 22:04:39 1999 +++ linux-23026m1/fs/bad_inode.c Mon Nov 8 00:37:42 1999 @@ -67,7 +67,8 @@ EIO_ERROR, /* truncate */ EIO_ERROR, /* permission */ EIO_ERROR, /* smap */ - EIO_ERROR /* revalidate */ + EIO_ERROR, /* revalidate */ + EIO_ERROR, /* pathconf */ }; diff -ur linux-23026base/fs/bfs/inode.c linux-23026m1/fs/bfs/inode.c --- linux-23026base/fs/bfs/inode.c Fri Nov 5 20:30:13 1999 +++ linux-23026m1/fs/bfs/inode.c Mon Nov 8 11:36:15 1999 @@ -200,19 +200,17 @@ MOD_DEC_USE_COUNT; } -static int bfs_statfs(struct super_block *s, struct statfs *buf, int bufsiz) +static int bfs_statvfs(struct super_block *s, struct statvfs64 *buf) { - struct statfs tmp; - - tmp.f_type = BFS_MAGIC; - tmp.f_bsize = s->s_blocksize; - tmp.f_blocks = s->su_blocks; - tmp.f_bfree = tmp.f_bavail = s->su_freeb; - tmp.f_files = s->su_lasti + 1 - BFS_ROOT_INO; - tmp.f_ffree = s->su_freei; - tmp.f_fsid.val[0] = s->s_dev; - tmp.f_namelen = BFS_NAMELEN; - return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; + buf->f_type = BFS_MAGIC; + buf->f_bsize = s->s_blocksize; + buf->f_blocks = s->su_blocks; + buf->f_bfree = buf->f_bavail = s->su_freeb; + buf->f_files = s->su_lasti + 1 - BFS_ROOT_INO; + buf->f_ffree = s->su_freei; + buf->f_fsid.val[0] = s->s_dev; + buf->f_namelen = BFS_NAMELEN; + return 0; } static void bfs_write_super(struct super_block *s) @@ -230,7 +228,7 @@ notify_change: NULL, put_super: bfs_put_super, write_super: bfs_write_super, - statfs: bfs_statfs, + statvfs: bfs_statvfs, remount_fs: NULL, clear_inode: NULL, umount_begin: NULL diff -ur linux-23026base/fs/buffer.c linux-23026m1/fs/buffer.c --- linux-23026base/fs/buffer.c Fri Nov 5 05:36:33 1999 +++ linux-23026m1/fs/buffer.c Mon Nov 8 00:38:11 1999 @@ -43,6 +43,7 @@ #include #include #include +#include #include #include diff -ur linux-23026base/fs/coda/dir.c linux-23026m1/fs/coda/dir.c --- linux-23026base/fs/coda/dir.c Mon Aug 23 20:14:44 1999 +++ linux-23026m1/fs/coda/dir.c Mon Nov 8 00:43:17 1999 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -50,7 +51,8 @@ /* support routines */ static int coda_venus_readdir(struct file *filp, void *dirent, filldir_t filldir); -int coda_fsync(struct file *, struct dentry *dentry); +extern int coda_fsync(struct file *, struct dentry *dentry); +extern int coda_pathconf(struct inode *, int); int coda_crossvol_rename = 0; int coda_hasmknod = 0; @@ -84,8 +86,8 @@ NULL, /* truncate */ coda_permission, /* permission */ NULL, /* smap */ - NULL, /* update page */ - coda_revalidate_inode /* revalidate */ + coda_revalidate_inode, /* revalidate */ + coda_pathconf, /* pathconf */ }; struct file_operations coda_dir_operations = { @@ -909,3 +911,29 @@ return 0; } +int coda_pathconf(struct inode *inode, int option) +{ + switch (option) { + case _PC_NAME_MAX: /* POSIX.1: Directory only */ + return CODA_MAXNAMLEN; /* name component max length */ + case _PC_NO_TRUNC: + return 1; /* Will yield -ENAMETOOLONG */ + + case _PC_FILESIZEBITS: /* LFS: Regular files, and dirs */ + return 32; /* 64-bits really, except local cache isn't + very good (at all) at it... */ + + case _PC_LINK_MAX: /* POSIX.1: regular files and dirs */ + return -INT_MAX; /* Unknown ?? */ + + case _PC_CHOWN_RESTRICTED: /* POSIX.1: Any file, any dir */ + break; /* FIXME: some mount-option ??? */ + + case _PC_SYNC_IO: /* POSIX.4: Regular files only ? */ + case _PC_ASYNC_IO: /* TTY only ?? */ + break; + default: + break; + } + return -EINVAL; /* Unknown thing! */ +} diff -ur linux-23026base/fs/coda/file.c linux-23026m1/fs/coda/file.c --- linux-23026base/fs/coda/file.c Sat Oct 30 02:45:32 1999 +++ linux-23026m1/fs/coda/file.c Mon Nov 8 00:44:40 1999 @@ -32,7 +32,8 @@ static int coda_file_mmap(struct file * file, struct vm_area_struct * vma); /* also exported from this file (used for dirs) */ -int coda_fsync(struct file *, struct dentry *dentry); +extern int coda_fsync(struct file *, struct dentry *dentry); +extern int coda_pathconf(struct inode *, int); struct inode_operations coda_file_inode_operations = { &coda_file_operations, /* default file operations */ @@ -54,7 +55,8 @@ NULL, /* truncate */ coda_permission, /* permission */ NULL, /* smap */ - coda_revalidate_inode /* revalidate */ + coda_revalidate_inode, /* revalidate */ + coda_pathconf, /* pathconf */ }; struct file_operations coda_file_operations = { @@ -98,7 +100,7 @@ coda_prepare_openfile(coda_inode, coda_file, cii->c_ovp, &cont_file, &cont_dentry); - CDEBUG(D_INODE, "coda ino: %ld, cached ino %ld, page offset: %lx\n", + CDEBUG(D_INODE, "coda ino: %ld, cached ino %ld, page index: %lx\n", coda_inode->i_ino, cii->c_ovp->i_ino, page->index); block_read_full_page(&cont_file, page); diff -ur linux-23026base/fs/coda/inode.c linux-23026m1/fs/coda/inode.c --- linux-23026base/fs/coda/inode.c Mon Aug 23 20:14:44 1999 +++ linux-23026m1/fs/coda/inode.c Mon Nov 8 00:49:13 1999 @@ -38,8 +38,7 @@ static void coda_put_inode(struct inode *); static void coda_delete_inode(struct inode *); static void coda_put_super(struct super_block *); -static int coda_statfs(struct super_block *sb, struct statfs *buf, - int bufsiz); +static int coda_statvfs(struct super_block *sb, struct statvfs64 *buf); /* exported operations */ struct super_operations coda_super_operations = @@ -51,7 +50,7 @@ coda_notify_change, /* notify_change */ coda_put_super, /* put_super */ NULL, /* write_super */ - coda_statfs, /* statfs */ + coda_statvfs, /* statvfs */ NULL /* remount_fs */ }; @@ -237,31 +236,25 @@ return error; } -static int coda_statfs(struct super_block *sb, struct statfs *buf, - int bufsiz) +static int coda_statvfs(struct super_block *sb, struct statvfs64 *buf) { - struct statfs tmp; int error; - memset(&tmp, 0, sizeof(struct statfs)); - - error = venus_statfs(sb, &tmp); + error = venus_statvfs(sb, buf); if (error) { /* fake something like AFS does */ - tmp.f_blocks = 9000000; - tmp.f_bfree = 9000000; - tmp.f_bavail = 9000000; - tmp.f_files = 9000000; - tmp.f_ffree = 9000000; + buf->f_blocks = 9000000; + buf->f_bfree = 9000000; + buf->f_bavail = 9000000; + buf->f_files = 9000000; + buf->f_ffree = 9000000; } /* and fill in the rest */ - tmp.f_type = CODA_SUPER_MAGIC; - tmp.f_bsize = 1024; - tmp.f_namelen = CODA_MAXNAMLEN; - - copy_to_user(buf, &tmp, bufsiz); + buf->f_type = CODA_SUPER_MAGIC; + buf->f_bsize = 1024; + buf->f_namelen = CODA_MAXNAMLEN; return 0; } diff -ur linux-23026base/fs/coda/upcall.c linux-23026m1/fs/coda/upcall.c --- linux-23026base/fs/coda/upcall.c Tue Aug 31 21:30:48 1999 +++ linux-23026m1/fs/coda/upcall.c Mon Nov 8 00:49:56 1999 @@ -580,7 +580,7 @@ return error; } -int venus_statfs(struct super_block *sb, struct statfs *sfs) +int venus_statvfs(struct super_block *sb, struct statvfs64 *sfs) { union inputArgs *inp; union outputArgs *outp; diff -ur linux-23026base/fs/devices.c linux-23026m1/fs/devices.c --- linux-23026base/fs/devices.c Sun Jul 4 20:02:30 1999 +++ linux-23026m1/fs/devices.c Mon Nov 8 00:52:32 1999 @@ -285,7 +285,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + NULL, /* pathconf */ }; /* @@ -342,7 +343,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + NULL, /* pathconf */ }; /* diff -ur linux-23026base/fs/devpts/inode.c linux-23026m1/fs/devpts/inode.c --- linux-23026base/fs/devpts/inode.c Fri Aug 27 00:18:06 1999 +++ linux-23026m1/fs/devpts/inode.c Mon Nov 8 00:53:37 1999 @@ -57,7 +57,7 @@ #endif } -static int devpts_statfs(struct super_block *sb, struct statfs *buf, int bufsiz); +static int devpts_statvfs(struct super_block *sb, struct statvfs64 *buf); static void devpts_read_inode(struct inode *inode); static void devpts_write_inode(struct inode *inode); @@ -69,7 +69,7 @@ NULL, /* notify_change */ devpts_put_super, NULL, /* write_super */ - devpts_statfs, + devpts_statvfs, NULL, /* remount_fs */ NULL, /* clear_inode */ }; @@ -244,19 +244,17 @@ return NULL; } -static int devpts_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) +static int devpts_statvfs(struct super_block *sb, struct statvfs64 *buf) { - struct statfs tmp; - - tmp.f_type = DEVPTS_SUPER_MAGIC; - tmp.f_bsize = 1024; - tmp.f_blocks = 0; - tmp.f_bfree = 0; - tmp.f_bavail = 0; - tmp.f_files = 0; - tmp.f_ffree = 0; - tmp.f_namelen = NAME_MAX; - return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; + buf->f_type = DEVPTS_SUPER_MAGIC; + buf->f_bsize = 1024; + buf->f_blocks = 0; + buf->f_bfree = 0; + buf->f_bavail = 0; + buf->f_files = 0; + buf->f_ffree = 0; + buf->f_namelen = NAME_MAX; + return 0; } static void devpts_read_inode(struct inode *inode) diff -ur linux-23026base/fs/dquot.c linux-23026m1/fs/dquot.c --- linux-23026base/fs/dquot.c Thu Oct 7 22:47:37 1999 +++ linux-23026m1/fs/dquot.c Mon Nov 8 05:15:10 1999 @@ -513,6 +513,8 @@ dquot = find_best_candidate_weighted(); if (dquot) goto got_it; + + count = 2; // "count" not initialized above! /* * Try pruning the dcache to free up some dquots ... */ diff -ur linux-23026base/fs/efs/super.c linux-23026m1/fs/efs/super.c --- linux-23026base/fs/efs/super.c Fri Aug 27 00:18:06 1999 +++ linux-23026m1/fs/efs/super.c Mon Nov 8 00:55:10 1999 @@ -13,6 +13,8 @@ #include #include +static int efs_statvfs(struct super_block *s, struct statvfs64 *buf); + static struct file_system_type efs_fs_type = { "efs", /* filesystem name */ FS_REQUIRES_DEV, /* fs_flags */ @@ -28,7 +30,7 @@ NULL, /* notify_change */ efs_put_super, /* put_super */ NULL, /* write_super */ - efs_statfs, /* statfs */ + efs_statvfs, /* statvfs */ NULL /* remount */ }; @@ -231,24 +233,23 @@ MOD_DEC_USE_COUNT; } -int efs_statfs(struct super_block *s, struct statfs *buf, int bufsiz) { +int efs_statvfs(struct super_block *s, struct statvfs64 *buf) { struct statfs ret; struct efs_sb_info *sb = SUPER_INFO(s); - ret.f_type = EFS_SUPER_MAGIC; /* efs magic number */ - ret.f_bsize = EFS_BLOCKSIZE; /* blocksize */ - ret.f_blocks = sb->total_groups * /* total data blocks */ + buf->f_type = EFS_SUPER_MAGIC; /* efs magic number */ + buf->f_bsize = EFS_BLOCKSIZE; /* blocksize */ + buf->f_blocks = sb->total_groups * /* total data blocks */ (sb->group_size - sb->inode_blocks); - ret.f_bfree = sb->data_free; /* free data blocks */ - ret.f_bavail = sb->data_free; /* free blocks for non-root */ - ret.f_files = sb->total_groups * /* total inodes */ + buf->f_bfree = sb->data_free; /* free data blocks */ + buf->f_bavail = sb->data_free; /* free blocks for non-root */ + buf->f_files = sb->total_groups * /* total inodes */ sb->inode_blocks * (EFS_BLOCKSIZE / sizeof(struct efs_dinode)); - ret.f_ffree = sb->inode_free; /* free inodes */ - ret.f_fsid.val[0] = (sb->fs_magic >> 16) & 0xffff; /* fs ID */ - ret.f_fsid.val[1] = sb->fs_magic & 0xffff; /* fs ID */ - ret.f_namelen = EFS_MAXNAMELEN; /* max filename length */ + buf->f_ffree = sb->inode_free; /* free inodes */ + buf->f_fsid.val[0] = (sb->fs_magic >> 16) & 0xffff; /* fs ID */ + buf->f_fsid.val[1] = sb->fs_magic & 0xffff; /* fs ID */ + buf->f_namelen = EFS_MAXNAMELEN; /* max filename length */ - return copy_to_user(buf, &ret, bufsiz) ? -EFAULT : 0; + return 0; } - diff -ur linux-23026base/fs/efs/symlink.c linux-23026m1/fs/efs/symlink.c --- linux-23026base/fs/efs/symlink.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/efs/symlink.c Mon Nov 8 00:55:32 1999 @@ -42,7 +42,7 @@ efs_block_t size = in->i_size; if (size > 2 * EFS_BLOCKSIZE) { - printk(KERN_ERR "EFS: linktarget(): name too long: %lu\n", in->i_size); + printk(KERN_ERR "EFS: linktarget(): name too long: %Lu\n", in->i_size); return NULL; } diff -ur linux-23026base/fs/ext2/dir.c linux-23026m1/fs/ext2/dir.c --- linux-23026base/fs/ext2/dir.c Thu Oct 28 23:23:10 1999 +++ linux-23026m1/fs/ext2/dir.c Mon Nov 8 00:56:25 1999 @@ -30,6 +30,7 @@ } static int ext2_readdir(struct file *, void *, filldir_t); +extern int ext2_pathconf(struct inode *, int); static struct file_operations ext2_dir_operations = { NULL, /* lseek - default */ @@ -71,7 +72,8 @@ NULL, /* truncate */ ext2_permission, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + ext2_pathconf, /* pathconf */ }; int ext2_check_dir_entry (const char * function, struct inode * dir, diff -ur linux-23026base/fs/ext2/file.c linux-23026m1/fs/ext2/file.c --- linux-23026base/fs/ext2/file.c Fri Nov 5 19:57:30 1999 +++ linux-23026m1/fs/ext2/file.c Mon Nov 8 04:51:56 1999 @@ -21,8 +21,9 @@ #include #include #include +#include - +extern int ext2_pathconf(struct inode *, int); #define NBUF 32 @@ -30,9 +31,6 @@ #define MAX(a,b) (((a)>(b))?(a):(b)) static long long ext2_file_lseek(struct file *, long long, int); -#if BITS_PER_LONG < 64 -static int ext2_open_file (struct inode *, struct file *); -#endif #define EXT2_MAX_SIZE(bits) \ (((EXT2_NDIR_BLOCKS + (1LL << (bits - 2)) + \ @@ -45,9 +43,6 @@ EXT2_MAX_SIZE(10), EXT2_MAX_SIZE(11), EXT2_MAX_SIZE(12), EXT2_MAX_SIZE(13) }; -/* - * Make sure the offset never goes beyond the 32-bit mark.. - */ static long long ext2_file_lseek( struct file *file, long long offset, @@ -62,10 +57,19 @@ case 1: offset += file->f_pos; } - if (((unsigned long long) offset >> 32) != 0) { + if (offset < 0) + return -EINVAL; + if ((offset >> 32) != 0) { if (offset > ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(inode->i_sb)]) return -EINVAL; } + + /* L-F-S spec 2.2.1.27: */ + if (!(file->f_flags & O_LARGEFILE)) { + if (!off_t_presentable(offset +1)) /* pos@LONG_MAX forbidden */ + return -EOVERFLOW; + } + if (offset != file->f_pos) { file->f_pos = offset; file->f_reada = 0; @@ -120,20 +124,6 @@ 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 if - * the caller didn't specify O_LARGEFILE. - */ -static int ext2_open_file (struct inode * inode, struct file * filp) -{ - if (inode->u.ext2_i.i_high_size && !(filp->f_flags & O_LARGEFILE)) - return -EFBIG; - return 0; -} -#endif - /* * We have mostly NULL's here: the current defaults are ok for * the ext2 filesystem. @@ -146,11 +136,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 */ @@ -180,4 +166,31 @@ ext2_permission, /* permission */ NULL, /* smap */ NULL, /* revalidate */ + ext2_pathconf, /* pathconf */ }; + +int ext2_pathconf(struct inode *inode, int option) +{ + switch (option) { + case _PC_NAME_MAX: /* POSIX.1: Directory only */ + return EXT2_NAME_LEN; /* name component max length */ + case _PC_NO_TRUNC: + return 1; /* Semantics ??? */ + + case _PC_FILESIZEBITS: /* LFS: Regular files, and dirs */ + return 64; /* FIXME: L-F-S: mount-option: nolargefiles ? */ + + case _PC_LINK_MAX: /* POSIX.1: regular files and dirs */ + return EXT2_LINK_MAX; + + case _PC_CHOWN_RESTRICTED: /* POSIX.1: Any file, any dir */ + break; /* FIXME: some mount-option ??? */ + + case _PC_SYNC_IO: /* POSIX.4: Regular files only ? */ + case _PC_ASYNC_IO: /* TTY only ?? */ + break; + default: + break; + } + return -EINVAL; /* Unknown thing! */ +} diff -ur linux-23026base/fs/ext2/inode.c linux-23026m1/fs/ext2/inode.c --- linux-23026base/fs/ext2/inode.c Fri Nov 5 19:57:30 1999 +++ linux-23026m1/fs/ext2/inode.c Mon Nov 8 01:06:07 1999 @@ -216,14 +216,12 @@ /* Check file limits.. */ { - unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit < RLIM_INFINITY) { - limit >>= EXT2_BLOCK_SIZE_BITS(inode->i_sb); - if (new_block >= limit) { - send_sig(SIGXFSZ, current, 0); - *err = -EFBIG; - return NULL; - } + u_long limit = (current->rlimfsz.rlim_cur >> + EXT2_BLOCK_SIZE_BITS(inode->i_sb)); + if (new_block >= limit) { + send_sig(SIGXFSZ, current, 0); + *err = -EFBIG; + return NULL; } } @@ -337,13 +335,14 @@ } *err = -EFBIG; - limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit < RLIM_INFINITY) { - limit >>= EXT2_BLOCK_SIZE_BITS(inode->i_sb); - if (new_block >= limit) { - send_sig(SIGXFSZ, current, 0); - goto out; - } + /* "infinity" value is 2^63-1, shifting it down a few bits + will stay so high that it doesn't matter.. */ + limit = (current->rlimfsz.rlim_cur >> + EXT2_BLOCK_SIZE_BITS(inode->i_sb)); + + if (new_block >= limit) { + send_sig(SIGXFSZ, current, 0); + goto out; } if (inode->u.ext2_i.i_next_alloc_block == new_block) diff -ur linux-23026base/fs/ext2/super.c linux-23026m1/fs/ext2/super.c --- linux-23026base/fs/ext2/super.c Thu Oct 28 23:23:10 1999 +++ linux-23026m1/fs/ext2/super.c Mon Nov 8 01:08:21 1999 @@ -128,7 +128,7 @@ NULL, ext2_put_super, ext2_write_super, - ext2_statfs, + ext2_statvfs, ext2_remount }; @@ -750,10 +750,9 @@ #endif -int ext2_statfs (struct super_block * sb, struct statfs * buf, int bufsiz) +int ext2_statvfs (struct super_block * sb, struct statvfs64 * buf) { unsigned long overhead; - struct statfs tmp; int ngroups, i; if (test_opt (sb, MINIX_DF)) @@ -793,15 +792,15 @@ (2 + sb->u.ext2_sb.s_itb_per_group)); } - tmp.f_type = EXT2_SUPER_MAGIC; - tmp.f_bsize = sb->s_blocksize; - tmp.f_blocks = le32_to_cpu(sb->u.ext2_sb.s_es->s_blocks_count) - overhead; - tmp.f_bfree = ext2_count_free_blocks (sb); - tmp.f_bavail = tmp.f_bfree - le32_to_cpu(sb->u.ext2_sb.s_es->s_r_blocks_count); - if (tmp.f_bfree < le32_to_cpu(sb->u.ext2_sb.s_es->s_r_blocks_count)) - tmp.f_bavail = 0; - tmp.f_files = le32_to_cpu(sb->u.ext2_sb.s_es->s_inodes_count); - tmp.f_ffree = ext2_count_free_inodes (sb); - tmp.f_namelen = EXT2_NAME_LEN; - return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; + buf->f_type = EXT2_SUPER_MAGIC; + buf->f_bsize = sb->s_blocksize; + buf->f_blocks = le32_to_cpu(sb->u.ext2_sb.s_es->s_blocks_count) - overhead; + buf->f_bfree = ext2_count_free_blocks (sb); + buf->f_bavail = buf->f_bfree - le32_to_cpu(sb->u.ext2_sb.s_es->s_r_blocks_count); + if (buf->f_bfree < le32_to_cpu(sb->u.ext2_sb.s_es->s_r_blocks_count)) + buf->f_bavail = 0; + buf->f_files = le32_to_cpu(sb->u.ext2_sb.s_es->s_inodes_count); + buf->f_ffree = ext2_count_free_inodes (sb); + buf->f_namelen = EXT2_NAME_LEN; + return 0; } diff -ur linux-23026base/fs/fat/fatfs_syms.c linux-23026m1/fs/fat/fatfs_syms.c --- linux-23026base/fs/fat/fatfs_syms.c Tue Oct 26 21:21:46 1999 +++ linux-23026m1/fs/fat/fatfs_syms.c Mon Nov 8 20:24:04 1999 @@ -43,7 +43,8 @@ EXPORT_SYMBOL(fat_search_long); EXPORT_SYMBOL(fat_readdir); EXPORT_SYMBOL(fat_scan); -EXPORT_SYMBOL(fat_statfs); +EXPORT_SYMBOL(fat_statvfs); +EXPORT_SYMBOL(fat_pathconf); EXPORT_SYMBOL(fat_uni2esc); EXPORT_SYMBOL(fat_unlock_creation); EXPORT_SYMBOL(fat_write_inode); diff -ur linux-23026base/fs/fat/file.c linux-23026m1/fs/fat/file.c --- linux-23026base/fs/fat/file.c Sat Nov 6 02:27:28 1999 +++ linux-23026m1/fs/fat/file.c Mon Nov 8 20:23:23 1999 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -64,7 +65,8 @@ fat_truncate, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + fat_statvfs, /* statvfs */ }; ssize_t fat_file_read( @@ -196,4 +198,31 @@ MSDOS_I(inode)->i_attrs |= ATTR_ARCH; inode->i_ctime = inode->i_mtime = CURRENT_TIME; mark_inode_dirty(inode); +} + +int fat_pathconf(struct inode *inode, int option) +{ + switch (option) { + case _PC_NAME_MAX: /* POSIX.1: Directory only */ + // FIXME: Detect VFAT operational mode of SB ! (namemax: 260) + return 8+1+3; /* name component max length */ + case _PC_NO_TRUNC: + return 1; /* Semantics ??? */ + + case _PC_FILESIZEBITS: /* LFS: Regular files, and dirs */ + return 32; + + case _PC_LINK_MAX: /* POSIX.1: regular files and dirs */ + return 1; + + case _PC_CHOWN_RESTRICTED: /* POSIX.1: Any file, any dir */ + break; /* FIXME: some mount-option ??? */ + + case _PC_SYNC_IO: /* POSIX.4: Regular files only ? */ + case _PC_ASYNC_IO: /* TTY only ?? */ + break; + default: + break; + } + return -EINVAL; /* Unknown thing! */ } diff -ur linux-23026base/fs/fat/inode.c linux-23026m1/fs/fat/inode.c --- linux-23026base/fs/fat/inode.c Sat Nov 6 02:27:28 1999 +++ linux-23026m1/fs/fat/inode.c Mon Nov 8 11:33:16 1999 @@ -413,7 +413,7 @@ fat_notify_change, fat_put_super, NULL, /* write_super */ - fat_statfs, + fat_statvfs, NULL, /* remount */ fat_clear_inode }; @@ -707,14 +707,13 @@ return NULL; } -int fat_statfs(struct super_block *sb,struct statfs *buf, int bufsiz) +int fat_statvfs(struct super_block *sb,struct statvfs64 *buf) { int free,nr; - struct statfs tmp; if (MSDOS_SB(sb)->cvf_format && - MSDOS_SB(sb)->cvf_format->cvf_statfs) - return MSDOS_SB(sb)->cvf_format->cvf_statfs(sb,buf,bufsiz); + MSDOS_SB(sb)->cvf_format->cvf_statvfs) + return MSDOS_SB(sb)->cvf_format->cvf_statvfs(sb,buf); lock_fat(sb); if (MSDOS_SB(sb)->free_clusters != -1) @@ -726,15 +725,15 @@ MSDOS_SB(sb)->free_clusters = free; } unlock_fat(sb); - tmp.f_type = sb->s_magic; - tmp.f_bsize = MSDOS_SB(sb)->cluster_size*SECTOR_SIZE; - tmp.f_blocks = MSDOS_SB(sb)->clusters; - tmp.f_bfree = free; - tmp.f_bavail = free; - tmp.f_files = 0; - tmp.f_ffree = 0; - tmp.f_namelen = MSDOS_SB(sb)->options.isvfat ? 260 : 12; - return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; + buf->f_type = sb->s_magic; + buf->f_bsize = MSDOS_SB(sb)->cluster_size*SECTOR_SIZE; + buf->f_blocks = MSDOS_SB(sb)->clusters; + buf->f_bfree = free; + buf->f_bavail = free; + buf->f_files = 0; + buf->f_ffree = 0; + buf->f_namelen = MSDOS_SB(sb)->options.isvfat ? 260 : 12; + return 0; } static int is_exec(char *extension) diff -ur linux-23026base/fs/fcntl.c linux-23026m1/fs/fcntl.c --- linux-23026base/fs/fcntl.c Mon Oct 11 20:13:25 1999 +++ linux-23026m1/fs/fcntl.c Mon Nov 8 01:14:25 1999 @@ -215,6 +215,15 @@ case F_SETLKW: err = fcntl_setlk(fd, cmd, (struct flock *) arg); break; + 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; case F_GETOWN: /* * XXX If f_owner is a process group, the diff -ur linux-23026base/fs/fifo.c linux-23026m1/fs/fifo.c --- linux-23026base/fs/fifo.c Tue Aug 24 20:12:00 1999 +++ linux-23026m1/fs/fifo.c Mon Nov 8 01:14:59 1999 @@ -11,6 +11,7 @@ #include #include +#include static int fifo_open(struct inode *inode, struct file *filp) { @@ -187,7 +188,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + NULL, /* pathconf */ }; diff -ur linux-23026base/fs/hfs/dir_cap.c linux-23026m1/fs/hfs/dir_cap.c --- linux-23026base/fs/hfs/dir_cap.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/hfs/dir_cap.c Mon Nov 8 01:15:42 1999 @@ -94,7 +94,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + hfs_pathconf, /* pathconf */ }; struct inode_operations hfs_cap_fdir_inode_operations = { @@ -117,7 +118,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + hfs_pathconf, /* pathconf */ }; struct inode_operations hfs_cap_rdir_inode_operations = { @@ -140,7 +142,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + hfs_pathconf, /* pathconf */ }; /*================ File-local functions ================*/ diff -ur linux-23026base/fs/hfs/dir_dbl.c linux-23026m1/fs/hfs/dir_dbl.c --- linux-23026base/fs/hfs/dir_dbl.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/hfs/dir_dbl.c Mon Nov 8 01:16:03 1999 @@ -93,7 +93,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + hfs_pathconf, /* pathconf */ }; diff -ur linux-23026base/fs/hfs/dir_nat.c linux-23026m1/fs/hfs/dir_nat.c --- linux-23026base/fs/hfs/dir_nat.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/hfs/dir_nat.c Mon Nov 8 01:16:24 1999 @@ -100,7 +100,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + hfs_pathconf, /* pathconf */ }; struct inode_operations hfs_nat_hdir_inode_operations = { @@ -123,7 +124,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + hfs_pathconf, /* pathconf */ }; /*================ File-local functions ================*/ diff -ur linux-23026base/fs/hfs/file.c linux-23026m1/fs/hfs/file.c --- linux-23026base/fs/hfs/file.c Sat Nov 6 01:53:26 1999 +++ linux-23026m1/fs/hfs/file.c Mon Nov 8 01:17:20 1999 @@ -20,6 +20,7 @@ #include #include #include +#include /*================ Forward declarations ================*/ @@ -70,7 +71,8 @@ hfs_file_truncate, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + hfs_pathconf, /* pathconf */ }; /*================ Variable-like macros ================*/ @@ -544,4 +546,30 @@ } } } +} + +int hfs_pathconf(struct inode *inode, int option) +{ + switch (option) { + case _PC_NAME_MAX: /* POSIX.1: Directory only */ + return HFS_NAMELEN; + case _PC_NO_TRUNC: + return 0; + + case _PC_FILESIZEBITS: /* LFS: Regular files, and dirs */ + return 32; + + case _PC_LINK_MAX: /* POSIX.1: regular files and dirs */ + return 1; /* No classical UNIX links */ + + case _PC_CHOWN_RESTRICTED: /* POSIX.1: Any file, any dir */ + break; /* FIXME: some mount-option ??? */ + + case _PC_SYNC_IO: /* POSIX.4: Regular files only ? */ + case _PC_ASYNC_IO: /* TTY only ?? */ + break; + default: + break; + } + return -EINVAL; /* Unknown thing! */ } diff -ur linux-23026base/fs/hfs/file_cap.c linux-23026m1/fs/hfs/file_cap.c --- linux-23026base/fs/hfs/file_cap.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/hfs/file_cap.c Mon Nov 8 01:17:31 1999 @@ -84,7 +84,8 @@ cap_info_truncate, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidata */ + NULL, /* revalidata */ + hfs_pathconf, /* pathconf */ }; /*================ File-local functions ================*/ diff -ur linux-23026base/fs/hfs/file_hdr.c linux-23026m1/fs/hfs/file_hdr.c --- linux-23026base/fs/hfs/file_hdr.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/hfs/file_hdr.c Mon Nov 8 01:17:42 1999 @@ -86,7 +86,8 @@ hdr_truncate, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + hfs_pathconf, /* pathconf */ }; const struct hfs_hdr_layout hfs_dbl_fil_hdr_layout = { diff -ur linux-23026base/fs/hfs/hfs.h linux-23026m1/fs/hfs/hfs.h --- linux-23026base/fs/hfs/hfs.h Mon Nov 8 17:25:29 1999 +++ linux-23026m1/fs/hfs/hfs.h Mon Nov 8 20:38:49 1999 @@ -494,6 +494,9 @@ extern void hfs_extent_adj(struct hfs_fork *); extern void hfs_extent_free(struct hfs_fork *); +/* file.c */ +extern int hfs_pathconf(struct inode *, int); + /* mdb.c */ extern struct hfs_mdb *hfs_mdb_get(hfs_sysmdb, int, hfs_s32); extern void hfs_mdb_commit(struct hfs_mdb *, int); diff -ur linux-23026base/fs/hfs/super.c linux-23026m1/fs/hfs/super.c --- linux-23026base/fs/hfs/super.c Fri Aug 27 00:18:06 1999 +++ linux-23026m1/fs/hfs/super.c Mon Nov 8 01:19:34 1999 @@ -36,7 +36,7 @@ static void hfs_read_inode(struct inode *); static void hfs_put_super(struct super_block *); -static int hfs_statfs(struct super_block *, struct statfs *, int); +static int hfs_statvfs(struct super_block *, struct statvfs64 *); static void hfs_write_super(struct super_block *); /*================ Global variables ================*/ @@ -49,7 +49,7 @@ hfs_notify_change, /* notify_change - in inode.c */ hfs_put_super, /* put_super */ hfs_write_super, /* write_super */ - hfs_statfs, /* statfs */ + hfs_statvfs, /* statvfs */ NULL /* remount_fs */ }; @@ -136,29 +136,28 @@ } /* - * hfs_statfs() + * hfs_statvfs() * - * This is the statfs() entry in the super_operations structure for + * This is the statvfs() entry in the super_operations structure for * HFS filesystems. The purpose is to return various data about the * filesystem. * * changed f_files/f_ffree to reflect the fs_ablock/free_ablocks. */ -static int hfs_statfs(struct super_block *sb, struct statfs *buf, int len) +static int hfs_statvfs(struct super_block *sb, struct statvfs64 *buf) { struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb; - struct statfs tmp; - tmp.f_type = HFS_SUPER_MAGIC; - tmp.f_bsize = HFS_SECTOR_SIZE; - tmp.f_blocks = mdb->alloc_blksz * mdb->fs_ablocks; - tmp.f_bfree = mdb->alloc_blksz * mdb->free_ablocks; - tmp.f_bavail = tmp.f_bfree; - tmp.f_files = mdb->fs_ablocks; - tmp.f_ffree = mdb->free_ablocks; - tmp.f_namelen = HFS_NAMELEN; + buf->f_type = HFS_SUPER_MAGIC; + buf->f_bsize = HFS_SECTOR_SIZE; + buf->f_blocks = mdb->alloc_blksz * mdb->fs_ablocks; + buf->f_bfree = mdb->alloc_blksz * mdb->free_ablocks; + buf->f_bavail = buf->f_bfree; + buf->f_files = mdb->fs_ablocks; + buf->f_ffree = mdb->free_ablocks; + buf->f_namelen = HFS_NAMELEN; - return copy_to_user(buf, &tmp, len) ? -EFAULT : 0; + return 0; } /* diff -ur linux-23026base/fs/hpfs/file.c linux-23026m1/fs/hpfs/file.c --- linux-23026base/fs/hpfs/file.c Tue Oct 26 21:23:31 1999 +++ linux-23026m1/fs/hpfs/file.c Mon Nov 8 11:41:07 1999 @@ -94,9 +94,10 @@ struct page * page_cache = NULL; long status; - printk("- off: %08x\n", (int)page->offset); - pgpos = (inode->i_blocks - 1) * 512 & PAGE_CACHE_MASK; - while (pgpos < page->offset) { + printk("- off: %Ld\n", (((loff_t)page->index) << PAGE_CACHE_SHIFT)); + /* Blocks are 512 byte entities */ + pgpos = (inode->i_blocks - 1) >> (PAGE_CACHE_SHIFT - 9); + while (pgpos < page->index) { long pgp = pgpos; printk("pgpos: %08x, bl: %d\n", (int)pgpos, (int)inode->i_blocks); hash = page_hash(&inode->i_data, pgpos); diff -ur linux-23026base/fs/hpfs/super.c linux-23026m1/fs/hpfs/super.c --- linux-23026base/fs/hpfs/super.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/hpfs/super.c Mon Nov 8 01:27:54 1999 @@ -132,22 +132,21 @@ return count; } -int hpfs_statfs(struct super_block *s, struct statfs *buf, int bufsiz) +int hpfs_statvfs(struct super_block *s, struct statvfs64 *buf) { - struct statfs tmp; /*if (s->s_hpfs_n_free == -1) {*/ s->s_hpfs_n_free = count_bitmaps(s); s->s_hpfs_n_free_dnodes = hpfs_count_one_bitmap(s, s->s_hpfs_dmap); /*}*/ - tmp.f_type = s->s_magic; - tmp.f_bsize = 512; - tmp.f_blocks = s->s_hpfs_fs_size; - tmp.f_bfree = s->s_hpfs_n_free; - tmp.f_bavail = s->s_hpfs_n_free; - tmp.f_files = s->s_hpfs_dirband_size / 4; - tmp.f_ffree = s->s_hpfs_n_free_dnodes; - tmp.f_namelen = 254; - return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; + buf->f_type = s->s_magic; + buf->f_bsize = 512; + buf->f_blocks = s->s_hpfs_fs_size; + buf->f_bfree = s->s_hpfs_n_free; + buf->f_bavail = s->s_hpfs_n_free; + buf->f_files = s->s_hpfs_dirband_size / 4; + buf->f_ffree = s->s_hpfs_n_free_dnodes; + buf->f_namelen = 254; + return 0; } /* Super operations */ @@ -161,7 +160,7 @@ hpfs_notify_change, /* notify_change */ hpfs_put_super, /* put_super */ NULL, /* write_super */ - hpfs_statfs, /* statfs */ + hpfs_statvfs, /* statvfs */ hpfs_remount_fs, /* remount_fs */ NULL, /* clear inode */ NULL, /* umount_begin */ diff -ur linux-23026base/fs/isofs/dir.c linux-23026m1/fs/isofs/dir.c --- linux-23026base/fs/isofs/dir.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/isofs/dir.c Mon Nov 8 01:30:07 1999 @@ -21,11 +21,39 @@ #include #include #include +#include #include static int isofs_readdir(struct file *, void *, filldir_t); +int isofs_pathconf(struct inode *inode, int option) +{ + switch (option) { + case _PC_NAME_MAX: /* POSIX.1: Directory only */ + break; /* This is read-only filesystem! */ + case _PC_NO_TRUNC: + break; /* This is read-only filesystem! */ + + case _PC_FILESIZEBITS: /* LFS: Regular files, and dirs */ + return 32; // FIXME: DVD-XXX ??? + + case _PC_LINK_MAX: /* POSIX.1: regular files and dirs */ + break; /* This is read-only filesystem! */ + + case _PC_CHOWN_RESTRICTED: /* POSIX.1: Any file, any dir */ + break; /* FIXME: some mount-option ??? */ + + case _PC_SYNC_IO: /* POSIX.4: Regular files only ? */ + case _PC_ASYNC_IO: /* TTY only ?? */ + break; + default: + break; + } + return -EINVAL; /* Unknown thing! */ +} + + static struct file_operations isofs_dir_operations = { NULL, /* lseek - default */ @@ -64,7 +92,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + isofs_pathconf, /* pathconf */ }; static int isofs_name_translate(char * old, int len, char * new) diff -ur linux-23026base/fs/isofs/file.c linux-23026m1/fs/isofs/file.c --- linux-23026base/fs/isofs/file.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/isofs/file.c Mon Nov 8 01:30:43 1999 @@ -17,6 +17,8 @@ #include #include +extern int isofs_pathconf(struct inode *, int); + /* * We have mostly NULLs here: the current defaults are OK for * the isofs filesystem. @@ -55,5 +57,6 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + isofs_pathconf, /* pathconf */ }; diff -ur linux-23026base/fs/isofs/inode.c linux-23026m1/fs/isofs/inode.c --- linux-23026base/fs/isofs/inode.c Fri Nov 5 01:50:50 1999 +++ linux-23026m1/fs/isofs/inode.c Mon Nov 8 11:36:34 1999 @@ -74,7 +74,7 @@ } static void isofs_read_inode(struct inode *); -static int isofs_statfs (struct super_block *, struct statfs *, int); +static int isofs_statvfs (struct super_block *, struct statvfs64 *); static struct super_operations isofs_sops = { isofs_read_inode, @@ -84,7 +84,7 @@ NULL, /* notify_change */ isofs_put_super, NULL, /* write_super */ - isofs_statfs, + isofs_statvfs, NULL }; @@ -905,20 +905,18 @@ return NULL; } -static int isofs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz) +static int isofs_statvfs (struct super_block *sb, struct statvfs64 *buf) { - struct statfs tmp; - - tmp.f_type = ISOFS_SUPER_MAGIC; - tmp.f_bsize = sb->s_blocksize; - tmp.f_blocks = (sb->u.isofs_sb.s_nzones + buf->f_type = ISOFS_SUPER_MAGIC; + buf->f_bsize = sb->s_blocksize; + buf->f_blocks = (sb->u.isofs_sb.s_nzones << (sb->u.isofs_sb.s_log_zone_size - sb->s_blocksize_bits)); - tmp.f_bfree = 0; - tmp.f_bavail = 0; - tmp.f_files = sb->u.isofs_sb.s_ninodes; - tmp.f_ffree = 0; - tmp.f_namelen = NAME_MAX; - return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; + buf->f_bfree = 0; + buf->f_bavail = 0; + buf->f_files = sb->u.isofs_sb.s_ninodes; + buf->f_ffree = 0; + buf->f_namelen = NAME_MAX; + return 0; } /* Life is simpler than for other filesystem since we never @@ -1008,8 +1006,8 @@ goto abort; abort_beyond_end: - printk("_isofs_bmap: block >= EOF (%ld, %ld)\n", - iblock, (unsigned long) inode->i_size); + printk("_isofs_bmap: block >= EOF (%ld, %Ld)\n", + iblock, inode->i_size); goto abort; abort_too_many_sections: @@ -1228,7 +1226,7 @@ #endif #ifdef DEBUG - printk("Get inode %x: %d %d: %d\n",inode->i_ino, block, + printk("Get inode %x: %d %d: %Ld\n",inode->i_ino, block, ((int)pnt) & 0x3ff, inode->i_size); #endif diff -ur linux-23026base/fs/lockd/svclock.c linux-23026m1/fs/lockd/svclock.c --- linux-23026base/fs/lockd/svclock.c Mon Aug 23 20:16:34 1999 +++ linux-23026m1/fs/lockd/svclock.c Mon Nov 8 01:38:41 1999 @@ -93,12 +93,12 @@ struct nlm_block **head, *block; struct file_lock *fl; - dprintk("lockd: nlmsvc_lookup_block f=%p pd=%d %ld-%ld ty=%d\n", + 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); for (head = &nlm_blocked; (block = *head); head = &block->b_next) { fl = &block->b_call.a_args.lock.fl; - dprintk(" check f=%p pd=%d %ld-%ld ty=%d\n", + dprintk(" check f=%p pd=%d %Ld-%Ld ty=%d\n", block->b_file, fl->fl_pid, fl->fl_start, fl->fl_end, fl->fl_type); if (block->b_file == file && nlm_compare_locks(fl, &lock->fl)) { @@ -282,7 +282,7 @@ struct nlm_block *block; 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, @@ -355,7 +355,7 @@ { 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, @@ -363,7 +363,7 @@ lock->fl.fl_end); if ((fl = posix_test_lock(&file->f_file, &lock->fl)) != NULL) { - dprintk("lockd: conflicting lock(ty=%d, %ld-%ld)\n", + dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n", fl->fl_type, fl->fl_start, fl->fl_end); conflock->caller = "somehost"; /* FIXME */ conflock->oh.len = 0; /* don't return OH info */ @@ -386,7 +386,7 @@ { 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, @@ -414,7 +414,7 @@ { 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, diff -ur linux-23026base/fs/lockd/xdr.c linux-23026m1/fs/lockd/xdr.c --- linux-23026base/fs/lockd/xdr.c Sat Feb 6 22:46:21 1999 +++ linux-23026m1/fs/lockd/xdr.c Mon Nov 8 01:41:35 1999 @@ -142,7 +142,7 @@ 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++); + fl->fl_start = (u_long)ntohl(*p++); // Up to 4G-1 len = ntohl(*p++); if (len == 0 || (fl->fl_end = fl->fl_start + len - 1) < 0) fl->fl_end = NLM_OFFSET_MAX; @@ -163,11 +163,11 @@ return NULL; *p++ = htonl(fl->fl_pid); - *p++ = htonl(lock->fl.fl_start); + *p++ = htonl((u_long)lock->fl.fl_start); if (lock->fl.fl_end == NLM_OFFSET_MAX) *p++ = xdr_zero; else - *p++ = htonl(lock->fl.fl_end - lock->fl.fl_start + 1); + *p++ = htonl((u_long)(lock->fl.fl_end - lock->fl.fl_start + 1)); return p; } @@ -192,11 +192,11 @@ if (!(p = xdr_encode_netobj(p, &resp->lock.oh))) return 0; - *p++ = htonl(fl->fl_start); + *p++ = htonl((u_long)fl->fl_start); if (fl->fl_end == NLM_OFFSET_MAX) *p++ = xdr_zero; else - *p++ = htonl(fl->fl_end - fl->fl_start + 1); + *p++ = htonl((u_long)(fl->fl_end - fl->fl_start + 1)); } return p; @@ -425,7 +425,7 @@ fl->fl_flags = FL_POSIX; fl->fl_type = excl? F_WRLCK : F_RDLCK; - fl->fl_start = ntohl(*p++); + fl->fl_start = (u_long)ntohl(*p++); len = ntohl(*p++); if (len == 0 || (fl->fl_end = fl->fl_start + len - 1) < 0) fl->fl_end = NLM_OFFSET_MAX; diff -ur linux-23026base/fs/locks.c linux-23026m1/fs/locks.c --- linux-23026base/fs/locks.c Mon Aug 23 21:15:53 1999 +++ linux-23026m1/fs/locks.c Mon Nov 8 01:48:40 1999 @@ -111,12 +111,12 @@ #include -#define OFFSET_MAX ((off_t)LONG_MAX) /* FIXME: move elsewhere? */ +#define OFFSET_MAX ((loff_t)((~0ULL)>>1)) /* 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, - struct flock *l); + 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); @@ -323,7 +323,192 @@ { struct file *filp; struct file_lock *fl,file_lock; - struct flock flock; + int error = -EFAULT; + + struct flock flock32; + struct flock64 flock; + + if (copy_from_user(&flock32, l, sizeof(flock32))) + goto out; + error = -EINVAL; + if ((flock32.l_type != F_RDLCK) && (flock32.l_type != F_WRLCK)) + goto out; + /* Convert to 64-bit offsets for internal use */ + flock.l_type = flock32.l_type; + flock.l_whence = flock32.l_whence; + flock.l_start = (u_long)flock32.l_start; + flock.l_len = (u_long)flock32.l_len; + flock.l_pid = flock32.l_pid; + + error = -EBADF; + filp = fget(fd); + if (!filp) + goto out; + + error = -EINVAL; + if (!filp->f_dentry || !filp->f_dentry->d_inode) + goto out_putf; + + if (!posix_make_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; + fl = &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; + } + + /* Convert to 32-bit offsets (at 32-bit systems) */ + + if (!off_t_presentable(flock.l_start) || + !off_t_presentable(flock.l_len) || + !off_t_presentable(flock.l_start + flock.l_len)) { + error = -EOVERFLOW; + goto out_putf; + } + + flock32.l_type = flock.l_type; + flock32.l_whence = flock.l_whence; + flock32.l_start = flock.l_start; + flock32.l_len = flock.l_len; + flock32.l_pid = flock.l_pid; + + error = -EFAULT; + if (!copy_to_user(l, &flock32, sizeof(flock32))) + 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_setlk(unsigned int fd, unsigned int cmd, struct flock *l) +{ + struct file *filp; + struct file_lock file_lock; + struct flock64 flock; + struct flock flock32; + 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(&flock32, l, sizeof(flock32))) + goto out; + /* Convert to 64-bit offsets for internal use */ + flock.l_type = flock32.l_type; + flock.l_whence = flock32.l_whence; + flock.l_start = (u_long)flock32.l_start; + flock.l_len = (u_long)flock32.l_len; + flock.l_pid = flock32.l_pid; + + /* 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; + + /* 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 (!posix_make_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_SETLKW); + +out_putf: + fput(filp); +out: + return error; +} + +/* 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; @@ -380,11 +565,11 @@ /* 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_setlk(unsigned int fd, unsigned int cmd, struct flock *l) +int fcntl_setlk64(unsigned int fd, unsigned int cmd, struct flock64 *l) { struct file *filp; struct file_lock file_lock; - struct flock flock; + struct flock64 flock; struct dentry * dentry; struct inode *inode; int error; @@ -647,9 +832,9 @@ * style lock. */ static int posix_make_lock(struct file *filp, struct file_lock *fl, - struct flock *l) + struct flock64 *l) { - off_t start; + loff_t start; memset(fl, 0, sizeof(*fl)); @@ -1200,7 +1385,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); diff -ur linux-23026base/fs/minix/dir.c linux-23026m1/fs/minix/dir.c --- linux-23026base/fs/minix/dir.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/minix/dir.c Mon Nov 8 01:50:44 1999 @@ -21,6 +21,7 @@ } static int minix_readdir(struct file *, void *, filldir_t); +extern int minix_pathconf(struct inode *, int); static struct file_operations minix_dir_operations = { NULL, /* lseek - default */ @@ -59,7 +60,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + minix_pathconf, /* pathconf */ }; static int minix_readdir(struct file * filp, diff -ur linux-23026base/fs/minix/file.c linux-23026m1/fs/minix/file.c --- linux-23026base/fs/minix/file.c Fri Jul 23 20:30:42 1999 +++ linux-23026m1/fs/minix/file.c Mon Nov 8 01:51:57 1999 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -26,6 +27,34 @@ #include #include +int minix_pathconf(struct inode *inode, int option) +{ + switch (option) { + case _PC_NAME_MAX: /* POSIX.1: Directory only */ + return inode->i_sb->u.minix_sb.s_namelen; + + case _PC_NO_TRUNC: + return 1; /* UNIX semantics */ + + case _PC_FILESIZEBITS: /* LFS: Regular files, and dirs */ + return 32; + + case _PC_LINK_MAX: /* POSIX.1: regular files and dirs */ + return inode->i_sb->u.minix_sb.s_link_max; + + case _PC_CHOWN_RESTRICTED: /* POSIX.1: Any file, any dir */ + break; /* FIXME: some mount-option ??? */ + + case _PC_SYNC_IO: /* POSIX.4: Regular files only ? */ + case _PC_ASYNC_IO: /* TTY only ?? */ + break; + default: + break; + } + return -EINVAL; /* Unknown thing! */ +} + + /* * Write to a file (through the page cache). */ @@ -78,4 +107,5 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* revalidate */ + minix_pathconf, /* pathconf */ }; diff -ur linux-23026base/fs/minix/inode.c linux-23026m1/fs/minix/inode.c --- linux-23026base/fs/minix/inode.c Tue Aug 31 21:23:03 1999 +++ linux-23026m1/fs/minix/inode.c Mon Nov 8 01:52:36 1999 @@ -29,7 +29,7 @@ static void minix_read_inode(struct inode * inode); static void minix_write_inode(struct inode * inode); -static int minix_statfs(struct super_block *sb, struct statfs *buf, int bufsiz); +static int minix_statvfs(struct super_block *sb, struct statvfs64 *buf); static int minix_remount (struct super_block * sb, int * flags, char * data); static void minix_delete_inode(struct inode *inode) @@ -87,7 +87,7 @@ NULL, /* notify_change */ minix_put_super, minix_write_super, - minix_statfs, + minix_statvfs, minix_remount }; @@ -331,19 +331,17 @@ return NULL; } -static int minix_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) +static int minix_statvfs(struct super_block *sb, struct statvfs64 *buf) { - struct statfs tmp; - - tmp.f_type = sb->s_magic; - tmp.f_bsize = sb->s_blocksize; - tmp.f_blocks = (sb->u.minix_sb.s_nzones - sb->u.minix_sb.s_firstdatazone) << sb->u.minix_sb.s_log_zone_size; - tmp.f_bfree = minix_count_free_blocks(sb); - tmp.f_bavail = tmp.f_bfree; - tmp.f_files = sb->u.minix_sb.s_ninodes; - tmp.f_ffree = minix_count_free_inodes(sb); - tmp.f_namelen = sb->u.minix_sb.s_namelen; - return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; + buf->f_type = sb->s_magic; + buf->f_bsize = sb->s_blocksize; + buf->f_blocks = (sb->u.minix_sb.s_nzones - sb->u.minix_sb.s_firstdatazone) << sb->u.minix_sb.s_log_zone_size; + buf->f_bfree = minix_count_free_blocks(sb); + buf->f_bavail = buf->f_bfree; + buf->f_files = sb->u.minix_sb.s_ninodes; + buf->f_ffree = minix_count_free_inodes(sb); + buf->f_namelen = sb->u.minix_sb.s_namelen; + return 0; } /* diff -ur linux-23026base/fs/minix/symlink.c linux-23026m1/fs/minix/symlink.c --- linux-23026base/fs/minix/symlink.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/minix/symlink.c Mon Nov 8 12:19:47 1999 @@ -16,6 +16,7 @@ static int minix_readlink(struct dentry *, char *, int); static struct dentry *minix_follow_link(struct dentry *, struct dentry *, unsigned int); +extern int minix_pathconf(struct inode *, int); /* * symlinks can't do much... @@ -40,7 +41,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + minix_pathconf, /* pathconf */ }; static struct dentry * minix_follow_link(struct dentry * dentry, diff -ur linux-23026base/fs/msdos/namei.c linux-23026m1/fs/msdos/namei.c --- linux-23026base/fs/msdos/namei.c Tue Aug 31 21:23:03 1999 +++ linux-23026m1/fs/msdos/namei.c Mon Nov 8 01:55:21 1999 @@ -583,6 +583,8 @@ } +extern int fat_pathconf(struct inode *, int); + /* The public inode operations for the msdos fs */ struct inode_operations msdos_dir_inode_operations = { &fat_dir_operations, /* default directory file-ops */ @@ -605,6 +607,7 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* revalidate */ + fat_pathconf, /* pathconf */ }; static void msdos_put_super_callback(struct super_block *sb) diff -ur linux-23026base/fs/ncpfs/dir.c linux-23026m1/fs/ncpfs/dir.c --- linux-23026base/fs/ncpfs/dir.c Mon Nov 1 20:31:34 1999 +++ linux-23026m1/fs/ncpfs/dir.c Mon Nov 8 01:57:49 1999 @@ -45,6 +45,8 @@ extern int ncp_symlink(struct inode *, struct dentry *, const char *); #endif +extern int ncp_pathconf(struct inode *, int); + static struct file_operations ncp_dir_operations = { NULL, /* lseek - default */ @@ -86,6 +88,7 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* revalidate */ + ncp_pathconf, /* pathconf */ }; static ssize_t diff -ur linux-23026base/fs/ncpfs/file.c linux-23026m1/fs/ncpfs/file.c --- linux-23026base/fs/ncpfs/file.c Fri Oct 29 20:53:32 1999 +++ linux-23026m1/fs/ncpfs/file.c Mon Nov 8 02:16:54 1999 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "ncplib_kernel.h" @@ -94,7 +95,7 @@ struct dentry *dentry = file->f_dentry; struct inode *inode = dentry->d_inode; size_t already_read = 0; - off_t pos; + loff_t pos; size_t bufsize; int error; void* freepage; @@ -145,7 +146,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), @@ -185,7 +186,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; @@ -222,12 +223,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)) { @@ -262,6 +269,34 @@ return already_written ? already_written : errno; } + +int ncp_pathconf(struct inode *inode, int option) +{ + switch (option) { + case _PC_NAME_MAX: /* POSIX.1: Directory only */ + return NCP_MAXNAMELEN; /* name component max length */ + case _PC_NO_TRUNC: + return 1; /* varies per server.. */ + + case _PC_FILESIZEBITS: /* LFS: Regular files, and dirs */ + return 32; + + case _PC_LINK_MAX: /* POSIX.1: regular files and dirs */ + return 1; + + case _PC_CHOWN_RESTRICTED: /* POSIX.1: Any file, any dir */ + break; /* FIXME: some mount-option ??? */ + + case _PC_SYNC_IO: /* POSIX.4: Regular files only ? */ + case _PC_ASYNC_IO: /* TTY only ?? */ + break; + default: + break; + } + return -EINVAL; /* Unknown thing! */ +} + + static struct file_operations ncp_file_operations = { NULL, /* lseek - default */ @@ -298,5 +333,6 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + ncp_pathconf, /* pathconf */ }; diff -ur linux-23026base/fs/ncpfs/inode.c linux-23026m1/fs/ncpfs/inode.c --- linux-23026base/fs/ncpfs/inode.c Sat Nov 6 00:22:05 1999 +++ linux-23026m1/fs/ncpfs/inode.c Mon Nov 8 02:17:42 1999 @@ -34,7 +34,7 @@ static void ncp_put_inode(struct inode *); static void ncp_delete_inode(struct inode *); static void ncp_put_super(struct super_block *); -static int ncp_statfs(struct super_block *, struct statfs *, int); +static int ncp_statvfs(struct super_block *, struct statvfs64 *); static struct super_operations ncp_sops = { @@ -45,7 +45,7 @@ ncp_notify_change, /* notify change */ ncp_put_super, /* put superblock */ NULL, /* write superblock */ - ncp_statfs, /* stat filesystem */ + ncp_statvfs, /* stat filesystem */ NULL /* remount */ }; @@ -485,25 +485,23 @@ MOD_DEC_USE_COUNT; } -static int ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) +static int ncp_statvfs(struct super_block *sb, struct statvfs64 *buf) { - struct statfs tmp; - /* We cannot say how much disk space is left on a mounted NetWare Server, because free space is distributed over volumes, and the current user might have disk quotas. So free space is not that simple to determine. Our decision here is to err conservatively. */ - tmp.f_type = NCP_SUPER_MAGIC; - tmp.f_bsize = NCP_BLOCK_SIZE; - tmp.f_blocks = 0; - tmp.f_bfree = 0; - tmp.f_bavail = 0; - tmp.f_files = -1; - tmp.f_ffree = -1; - tmp.f_namelen = 12; - return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; + buf->f_type = NCP_SUPER_MAGIC; + buf->f_bsize = NCP_BLOCK_SIZE; + buf->f_blocks = 0; + buf->f_bfree = 0; + buf->f_bavail = 0; + buf->f_files = -1; + buf->f_ffree = -1; + buf->f_namelen = 12; + return 0; } int ncp_notify_change(struct dentry *dentry, struct iattr *attr) diff -ur linux-23026base/fs/nfs/dir.c linux-23026m1/fs/nfs/dir.c --- linux-23026base/fs/nfs/dir.c Sat Oct 30 19:37:26 1999 +++ linux-23026m1/fs/nfs/dir.c Mon Nov 8 02:19:49 1999 @@ -50,6 +50,7 @@ static int nfs_mknod(struct inode *, struct dentry *, int, int); static int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); +extern int nfs_pathconf(struct inode *, int); static struct file_operations nfs_dir_operations = { NULL, /* lseek - default */ @@ -86,6 +87,7 @@ NULL, /* permission */ NULL, /* smap */ nfs_revalidate, /* revalidate */ + nfs_pathconf, /* pathconf */ }; static ssize_t diff -ur linux-23026base/fs/nfs/file.c linux-23026m1/fs/nfs/file.c --- linux-23026base/fs/nfs/file.c Fri Oct 15 00:22:09 1999 +++ linux-23026m1/fs/nfs/file.c Mon Nov 8 04:54:58 1999 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,7 @@ static ssize_t nfs_file_write(struct file *, const char *, size_t, loff_t *); static int nfs_file_flush(struct file *); static int nfs_fsync(struct file *, struct dentry *dentry); +extern int nfs_pathconf(struct inode *, int); static struct file_operations nfs_file_operations = { NULL, /* lseek - default */ @@ -116,6 +118,11 @@ dentry->d_parent->d_name.name, dentry->d_name.name, (unsigned long) count, (unsigned long) *ppos); + /* Unconditionally allow only up to 2G files */ + /* FIXME: NFSv3 could allow 64-bit file offsets! */ + if ((*ppos+1LL) >= 0x7fffffffLL) + return -EOVERFLOW; + result = nfs_revalidate_inode(NFS_DSERVER(dentry), dentry); if (!result) result = generic_file_read(file, buf, count, ppos); @@ -191,9 +198,16 @@ struct inode * inode = dentry->d_inode; ssize_t result; - dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%lu)\n", + dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%Ld)\n", dentry->d_parent->d_name.name, dentry->d_name.name, - inode->i_ino, (unsigned long) count, (unsigned long) *ppos); + inode->i_ino, (unsigned long) count, *ppos); + + /* Unconditionally allow only up to 2G files */ + /* FIXME: NFSv3 could allow 64-bit file offsets! */ + if ((*ppos+1LL) > 0x7fffffffLL) { + result = -EOVERFLOW; + goto out; + } result = -EBUSY; if (IS_SWAPFILE(inode)) @@ -224,7 +238,7 @@ struct inode * inode = filp->f_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); @@ -273,4 +287,32 @@ out_ok: NFS_CACHEINV(inode); return status; +} + + +int nfs_pathconf(struct inode *inode, int option) +{ + switch (option) { + case _PC_NAME_MAX: /* POSIX.1: Directory only */ + return -INT_MAX; /* Unknown */ + + case _PC_NO_TRUNC: + return -INT_MAX; /* Unknown */ + + case _PC_FILESIZEBITS: /* LFS: Regular files, and dirs */ + return 32; /* NFSv3 would allow 64-bit sizes */ + + case _PC_LINK_MAX: /* POSIX.1: regular files and dirs */ + return -INT_MAX; /* Unknown */ + + case _PC_CHOWN_RESTRICTED: /* POSIX.1: Any file, any dir */ + break; /* FIXME: some mount-option ??? */ + + case _PC_SYNC_IO: /* POSIX.4: Regular files only ? */ + case _PC_ASYNC_IO: /* TTY only ?? */ + break; + default: + break; + } + return -EINVAL; /* Unknown thing! */ } diff -ur linux-23026base/fs/nfs/inode.c linux-23026m1/fs/nfs/inode.c --- linux-23026base/fs/nfs/inode.c Fri Nov 5 01:48:15 1999 +++ linux-23026m1/fs/nfs/inode.c Mon Nov 8 05:06:48 1999 @@ -46,7 +46,7 @@ static int nfs_notify_change(struct dentry *, struct iattr *); static void nfs_put_super(struct super_block *); static void nfs_umount_begin(struct super_block *); -static int nfs_statfs(struct super_block *, struct statfs *, int); +static int nfs_statvfs(struct super_block *, struct statvfs64 *); static struct super_operations nfs_sops = { nfs_read_inode, /* read inode */ @@ -56,7 +56,7 @@ nfs_notify_change, /* notify change */ nfs_put_super, /* put superblock */ NULL, /* write superblock */ - nfs_statfs, /* stat filesystem */ + nfs_statvfs, /* stat filesystem */ NULL, /* no remount */ NULL, /* no clear inode */ nfs_umount_begin /* umount attempt begin */ @@ -370,27 +370,26 @@ } static int -nfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) +nfs_statvfs(struct super_block *sb, struct statvfs64 *buf) { int error; struct nfs_fsinfo res; - struct statfs tmp; - error = nfs_proc_statfs(&sb->u.nfs_sb.s_server, &sb->u.nfs_sb.s_root, + error = nfs_proc_statvfs(&sb->u.nfs_sb.s_server, &sb->u.nfs_sb.s_root, &res); if (error) { - printk("nfs_statfs: statfs error = %d\n", -error); + printk("nfs_statvfs: statfs error = %d\n", -error); res.bsize = res.blocks = res.bfree = res.bavail = 0; } - tmp.f_type = NFS_SUPER_MAGIC; - tmp.f_bsize = res.bsize; - tmp.f_blocks = res.blocks; - tmp.f_bfree = res.bfree; - tmp.f_bavail = res.bavail; - tmp.f_files = 0; - tmp.f_ffree = 0; - tmp.f_namelen = NAME_MAX; - return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; + buf->f_type = NFS_SUPER_MAGIC; + buf->f_bsize = res.bsize; + buf->f_blocks = res.blocks; + buf->f_bfree = res.bfree; + buf->f_bavail = res.bavail; + buf->f_files = 0; + buf->f_ffree = 0; + buf->f_namelen = NAME_MAX; + return 0; } /* @@ -680,7 +679,7 @@ */ if (attr->ia_valid & ATTR_SIZE) { if (attr->ia_size != fattr.size) - printk("nfs_notify_change: attr=%Ld, fattr=%d??\n", + printk("nfs_notify_change: attr.size=%Ld, fattr.size=%Ld??\n", attr->ia_size, fattr.size); inode->i_size = attr->ia_size; inode->i_mtime = fattr.mtime.seconds; diff -ur linux-23026base/fs/nfs/proc.c linux-23026m1/fs/nfs/proc.c --- linux-23026base/fs/nfs/proc.c Mon Oct 18 21:26:37 1999 +++ linux-23026m1/fs/nfs/proc.c Mon Nov 8 12:26:49 1999 @@ -92,14 +92,14 @@ int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle, int swap, - unsigned long offset, unsigned int count, + loff_t offset, unsigned int count, void *buffer, struct nfs_fattr *fattr) { struct nfs_readargs arg = { fhandle, offset, count, buffer }; struct nfs_readres res = { fattr, count }; int status; - dprintk("NFS call read %d @ %ld\n", count, offset); + dprintk("NFS call read %d @ %Ld\n", count, offset); status = rpc_call(server->client, NFSPROC_READ, &arg, &res, swap? NFS_RPC_SWAPFLAGS : 0); dprintk("NFS reply read: %d\n", status); @@ -108,13 +108,13 @@ int nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle, int swap, - unsigned long offset, unsigned int count, + loff_t offset, unsigned int count, const void *buffer, struct nfs_fattr *fattr) { struct nfs_writeargs arg = { fhandle, offset, count, buffer }; int status; - dprintk("NFS call write %d @ %ld\n", count, offset); + dprintk("NFS call write %d @ %Ld\n", count, offset); status = rpc_call(server->client, NFSPROC_WRITE, &arg, fattr, swap? (RPC_TASK_SWAPPER|RPC_TASK_ROOTCREDS) : 0); dprintk("NFS reply read: %d\n", status); @@ -217,7 +217,7 @@ } int -nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, +nfs_proc_statvfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *info) { int status; diff -ur linux-23026base/fs/nfs/read.c linux-23026m1/fs/nfs/read.c --- linux-23026base/fs/nfs/read.c Sat Oct 30 02:45:32 1999 +++ linux-23026m1/fs/nfs/read.c Mon Nov 8 04:55:20 1999 @@ -52,7 +52,7 @@ */ static inline void nfs_readreq_setup(struct nfs_rreq *req, struct nfs_fh *fh, - unsigned long offset, void *buffer, unsigned int rsize) + loff_t offset, void *buffer, unsigned int rsize) { req->ra_args.fh = fh; req->ra_args.offset = offset; @@ -70,10 +70,10 @@ nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page) { struct nfs_rreq rqst; - unsigned long offset = page->index << PAGE_CACHE_SHIFT; + loff_t offset = ((loff_t)page->index) << PAGE_CACHE_SHIFT; char *buffer = (char *) page_address(page); int rsize = NFS_SERVER(inode)->rsize; - int result, refresh = 0; + int result = 0, refresh = 0; int count = PAGE_SIZE; int flags = IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0; @@ -83,11 +83,24 @@ if (count < rsize) rsize = count; - dprintk("NFS: nfs_proc_read(%s, (%s/%s), %ld, %d, %p)\n", + dprintk("NFS: nfs_proc_read(%s, (%s/%s), %Ld, %d, %p)\n", NFS_SERVER(inode)->hostname, dentry->d_parent->d_name.name, dentry->d_name.name, offset, rsize, buffer); + /* FIXME: NFSv3 could allow 64-bit offsets! ... */ + + if (offset > 0x7ffffffeULL) { + if (result) + break; + result = -EOVERFLOW; + goto io_error; + } + if ((offset + rsize) > 0x7fffffffULL) /* 2G-1 */ + rsize = 0x7fffffffULL - offset; + + /* ... END FIXME! */ + /* Set up arguments and perform rpc call */ nfs_readreq_setup(&rqst, NFS_FH(dentry), offset, buffer, rsize); lock_kernel(); @@ -166,8 +179,16 @@ unsigned long address = page_address(page); struct nfs_rreq *req; int result = -1, flags; + loff_t loffset = ((loff_t)page->index) << PAGE_CACHE_SHIFT; dprintk("NFS: nfs_readpage_async(%p)\n", page); + + /* FIXME: NFSv3 allows 64-bit offsets.. */ + if ((loffset + PAGE_SIZE) >= 0x7fffffffULL) { + dprintk("NFS: Async read beyond 2G-1 marker!\n"); + return -EOVERFLOW; + } + if (NFS_CONGESTED(inode)) goto out_defer; @@ -179,7 +200,7 @@ /* Initialize request */ /* N.B. Will the dentry remain valid for life of request? */ - nfs_readreq_setup(req, NFS_FH(dentry), page->index << PAGE_CACHE_SHIFT, + nfs_readreq_setup(req, NFS_FH(dentry), loffset, (void *) address, PAGE_SIZE); req->ra_inode = inode; req->ra_page = page; /* count has been incremented by caller */ @@ -224,8 +245,8 @@ int error; lock_kernel(); - dprintk("NFS: nfs_readpage (%p %ld@%lu)\n", - page, PAGE_SIZE, page->index); + dprintk("NFS: nfs_readpage (%p %ld@%Lu)\n", + page, PAGE_SIZE, ((loff_t)page->index) << PAGE_CACHE_SHIFT); get_page(page); /* diff -ur linux-23026base/fs/nfs/symlink.c linux-23026m1/fs/nfs/symlink.c --- linux-23026base/fs/nfs/symlink.c Tue Oct 26 20:41:06 1999 +++ linux-23026m1/fs/nfs/symlink.c Mon Nov 8 05:07:59 1999 @@ -26,6 +26,7 @@ static int nfs_readlink(struct dentry *, char *, int); static struct dentry *nfs_follow_link(struct dentry *, struct dentry *, unsigned int); +extern int nfs_pathconf(struct inode *, int); /* * symlinks can't do much... @@ -50,7 +51,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + nfs_pathconf, /* pathconf */ }; /* Symlink caching in the page cache is even more simplistic diff -ur linux-23026base/fs/nfs/write.c linux-23026m1/fs/nfs/write.c --- linux-23026base/fs/nfs/write.c Sat Oct 30 02:45:32 1999 +++ linux-23026m1/fs/nfs/write.c Mon Nov 8 05:07:25 1999 @@ -93,21 +93,39 @@ int result, refresh = 0, written = 0; u8 *buffer; struct nfs_fattr fattr; + loff_t loffset = (((loff_t)page->index) << PAGE_CACHE_SHIFT) + offset; lock_kernel(); - dprintk("NFS: nfs_writepage_sync(%s/%s %d@%lu/%ld)\n", + dprintk("NFS: nfs_writepage_sync(%s/%s %d@%Lu/%ld)\n", dentry->d_parent->d_name.name, dentry->d_name.name, - count, page->index, offset); + count, loffset, offset); buffer = (u8 *) page_address(page) + offset; - offset += page->index << PAGE_CACHE_SHIFT; + loffset += offset; + + /* FIXME: NFSv3 !!! */ +#if 1 + if (loffset >= 0x7ffffffeULL) + return -EFBIG; + if ((loffset + count) >= 0x7fffffffULL) { + /* At MOST this much! */ + count = 0x7fffffffULL - loffset; + } +#else + if (S_ISREG(inode->i_flags) && + !(dentry->d_file->f_flags & O_LARGEFILE) && + (!off_t_presentable(loffset) || + !off_t_presentable(loffset + count))) { + /* Writing beyond LargeFile maximums without O_LARGEFILE */ + } +#endif do { if (count < wsize && !IS_SWAPFILE(inode)) wsize = count; result = nfs_proc_write(NFS_DSERVER(dentry), NFS_FH(dentry), - IS_SWAPFILE(inode), offset, wsize, + IS_SWAPFILE(inode), loffset, wsize, buffer, &fattr); if (result < 0) { @@ -120,15 +138,15 @@ wsize, result); refresh = 1; buffer += wsize; - offset += wsize; + loffset += 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 (loffset > inode->i_size) + inode->i_size = loffset; } while (count); io_error: @@ -285,9 +303,9 @@ struct nfs_wreq *wreq; struct rpc_task *task; - dprintk("NFS: create_write_request(%s/%s, %ld+%d)\n", + dprintk("NFS: create_write_request(%s/%s, %Ld+%d)\n", dentry->d_parent->d_name.name, dentry->d_name.name, - (page->index << PAGE_CACHE_SHIFT) + offset, bytes); + (((loff_t)page->index) << PAGE_CACHE_SHIFT) + offset, bytes); /* FIXME: Enforce hard limit on number of concurrent writes? */ wreq = kmem_cache_alloc(nfs_wreq_cachep, SLAB_KERNEL); @@ -433,9 +451,9 @@ int synchronous = file->f_flags & O_SYNC; int retval; - dprintk("NFS: nfs_updatepage(%s/%s %d@%ld)\n", + dprintk("NFS: nfs_updatepage(%s/%s %d@%Ld)\n", dentry->d_parent->d_name.name, dentry->d_name.name, - count, (page->index << PAGE_CACHE_SHIFT) +offset); + count, (((loff_t)page->index) << PAGE_CACHE_SHIFT) +offset); /* * Try to find a corresponding request on the writeback queue. @@ -620,7 +638,7 @@ /* Setup the task struct for a writeback call */ req->wb_flags |= NFS_WRITE_INPROGRESS; req->wb_args.fh = NFS_FH(dentry); - req->wb_args.offset = (page->index << PAGE_CACHE_SHIFT) + req->wb_offset; + req->wb_args.offset = (((loff_t)page->index) << PAGE_CACHE_SHIFT) + req->wb_offset; req->wb_args.count = req->wb_bytes; req->wb_args.buffer = (void *) (page_address(page) + req->wb_offset); diff -ur linux-23026base/fs/nfsd/nfs3proc.c linux-23026m1/fs/nfsd/nfs3proc.c --- linux-23026base/fs/nfsd/nfs3proc.c Mon Apr 12 20:07:36 1999 +++ linux-23026m1/fs/nfsd/nfs3proc.c Mon Nov 8 12:31:44 1999 @@ -427,16 +427,16 @@ * Get file system info */ static int -nfsd3_proc_statfs(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, +nfsd3_proc_statvfs(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, struct nfsd3_statfsres *resp) { int nfserr; - dprintk("nfsd: STATFS %x/%ld\n", + dprintk("nfsd: STATVFS %x/%ld\n", SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh)); - nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats); + nfserr = nfsd_statvfs(rqstp, &argp->fh, &resp->stats); fh_put(&argp->fh); RETURN(nfserr); } @@ -479,7 +479,7 @@ PROC(mkdir, createargs, diropres, fhandle, RC_REPLBUFF), PROC(rmdir, diropargs, void, void, RC_REPLSTAT), PROC(readdir, readdirargs, readdirres, void, RC_REPLSTAT), - PROC(statfs, fhandle, statfsres, void, RC_NOCACHE), + PROC(statvfs, fhandle, statfsres, void, RC_NOCACHE), }; diff -ur linux-23026base/fs/nfsd/nfs3xdr.c linux-23026m1/fs/nfsd/nfs3xdr.c --- linux-23026base/fs/nfsd/nfs3xdr.c Mon Apr 7 21:35:31 1997 +++ linux-23026m1/fs/nfsd/nfs3xdr.c Mon Nov 8 12:33:11 1999 @@ -690,8 +690,8 @@ nfs3svc_encode_statfsres(struct svc_rqst *rqstp, u32 *p, struct nfsd3_statfsres *resp) { - struct statfs *s = &resp->stats; - u64 bs = s->f_bsize; + struct statvfs64 *s = &resp->stats; + u64 bs = s->f_bsize; *p++ = xdr_zero; /* no post_op_attr */ diff -ur linux-23026base/fs/nfsd/nfsproc.c linux-23026m1/fs/nfsd/nfsproc.c --- linux-23026base/fs/nfsd/nfsproc.c Mon Apr 12 20:08:18 1999 +++ linux-23026m1/fs/nfsd/nfsproc.c Mon Nov 8 02:51:28 1999 @@ -471,14 +471,14 @@ * Get file system info */ static int -nfsd_proc_statfs(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, +nfsd_proc_statvfs(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, struct nfsd_statfsres *resp) { int nfserr; - dprintk("nfsd: STATFS %p\n", SVCFH_DENTRY(&argp->fh)); + dprintk("nfsd: STATVFS %p\n", SVCFH_DENTRY(&argp->fh)); - nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats); + nfserr = nfsd_statvfs(rqstp, &argp->fh, &resp->stats); fh_put(&argp->fh); RETURN(nfserr); } @@ -519,7 +519,7 @@ PROC(mkdir, createargs, diropres, fhandle, RC_REPLBUFF), PROC(rmdir, diropargs, void, none, RC_REPLSTAT), PROC(readdir, readdirargs, readdirres, none, RC_REPLBUFF), - PROC(statfs, fhandle, statfsres, none, RC_NOCACHE), + PROC(statvfs, fhandle, statfsres, none, RC_NOCACHE), }; diff -ur linux-23026base/fs/nfsd/nfsxdr.c linux-23026m1/fs/nfsd/nfsxdr.c --- linux-23026base/fs/nfsd/nfsxdr.c Wed Nov 26 23:08:38 1997 +++ linux-23026m1/fs/nfsd/nfsxdr.c Mon Nov 8 02:51:55 1999 @@ -412,7 +412,7 @@ nfssvc_encode_statfsres(struct svc_rqst *rqstp, u32 *p, struct nfsd_statfsres *resp) { - struct statfs *stat = &resp->stats; + struct statvfs64 *stat = &resp->stats; *p++ = htonl(8 * 1024); /* max transfer size */ *p++ = htonl(stat->f_bsize); diff -ur linux-23026base/fs/nfsd/vfs.c linux-23026m1/fs/nfsd/vfs.c --- linux-23026base/fs/nfsd/vfs.c Wed Nov 3 07:36:07 1999 +++ linux-23026m1/fs/nfsd/vfs.c Mon Nov 8 12:38:22 1999 @@ -492,8 +492,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, + dprintk("nfsd: raparms %d %d %Ld %d %d\n", + file.f_reada, file.f_ramax, + ((loff_t)file.f_raend) << PAGE_CACHE_SHIFT, file.f_ralen, file.f_rawin); ra->p_reada = file.f_reada; ra->p_ramax = file.f_ramax; @@ -1298,12 +1299,11 @@ * N.B. After this call fhp needs an fh_put */ int -nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct statfs *stat) +nfsd_statvfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct statvfs64 *stat) { struct dentry *dentry; struct inode *inode; struct super_block *sb; - mm_segment_t oldfs; int err; err = fh_verify(rqstp, fhp, 0, MAY_NOP); @@ -1313,13 +1313,10 @@ inode = dentry->d_inode; err = nfserr_io; - if (!(sb = inode->i_sb) || !sb->s_op->statfs) + if (!(sb = inode->i_sb) || !sb->s_op->statvfs) goto out; - oldfs = get_fs(); - set_fs (KERNEL_DS); - sb->s_op->statfs(sb, stat, sizeof(*stat)); - set_fs (oldfs); + sb->s_op->statvfs(sb, stat); err = 0; out: diff -ur linux-23026base/fs/ntfs/fs.c linux-23026m1/fs/ntfs/fs.c --- linux-23026base/fs/ntfs/fs.c Fri Aug 27 00:18:06 1999 +++ linux-23026m1/fs/ntfs/fs.c Mon Nov 8 03:01:14 1999 @@ -28,12 +28,40 @@ #include #include #include +#include /* Forward declarations */ static struct inode_operations ntfs_dir_inode_operations; #define ITEM_SIZE 2040 +static int ntfs_pathconf(struct inode *inode, int option) +{ + switch (option) { + case _PC_NAME_MAX: /* POSIX.1: Directory only */ + return 255; + + case _PC_NO_TRUNC: + return 0; /* Non-UNIX semantics */ + + case _PC_FILESIZEBITS: /* LFS: Regular files, and dirs */ + return 32; + + case _PC_LINK_MAX: /* POSIX.1: regular files and dirs */ + return 1; + + case _PC_CHOWN_RESTRICTED: /* POSIX.1: Any file, any dir */ + break; /* FIXME: some mount-option ??? */ + + case _PC_SYNC_IO: /* POSIX.4: Regular files only ? */ + case _PC_ASYNC_IO: /* TTY only ?? */ + break; + default: + break; + } + return -EINVAL; /* Unknown thing! */ +} + /* io functions to user space */ static void ntfs_putuser(ntfs_io* dest,void *src,ntfs_size_t len) { @@ -447,6 +475,7 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* revalidate */ + ntfs_pathconf, /* pathconf */ }; #ifdef CONFIG_NTFS_RW @@ -630,6 +659,7 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* revalidate */ + ntfs_pathconf, /* pathconf */ }; static struct file_operations ntfs_dir_operations = { @@ -679,6 +709,7 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* revalidate */ + ntfs_pathconf, /* pathconf */ }; /* ntfs_read_inode is called by the Virtual File System (the kernel layer that @@ -813,34 +844,33 @@ } /* Called by the kernel when asking for stats */ -static int ntfs_statfs(struct super_block *sb, struct statfs *sf, int bufsize) +static int ntfs_statvfs(struct super_block *sb, struct statvfs64 *sf) { - struct statfs fs; struct inode *mft; ntfs_volume *vol; int error; - ntfs_debug(DEBUG_OTHER, "ntfs_statfs\n"); + ntfs_debug(DEBUG_OTHER, "ntfs_statvfs\n"); vol=NTFS_SB2VOL(sb); - memset(&fs,0,sizeof(fs)); - fs.f_type=NTFS_SUPER_MAGIC; - fs.f_bsize=vol->clustersize; + sf->f_type=NTFS_SUPER_MAGIC; + sf->f_bsize=vol->clustersize; - error = ntfs_get_volumesize( NTFS_SB2VOL( sb ), &fs.f_blocks ); + error = ntfs_get_volumesize( NTFS_SB2VOL( sb ), &sf->f_blocks ); if( error ) return -error; - fs.f_bfree=ntfs_get_free_cluster_count(vol->bitmap); - fs.f_bavail=fs.f_bfree; + sf->f_bfree=ntfs_get_free_cluster_count(vol->bitmap); + sf->f_bavail=sf->f_bfree; /* Number of files is limited by free space only, so we lie here */ - fs.f_ffree=0; + sf->f_ffree=0; mft=iget(sb,FILE_MFT); - fs.f_files=mft->i_size/vol->mft_recordsize; + /* So ... we lie... thus this following cast of loff_t value + is ok here.. */ + sf->f_files = (u_long)mft->i_size / vol->mft_recordsize; iput(mft); /* should be read from volume */ - fs.f_namelen=255; - copy_to_user(sf,&fs,bufsize); + sf->f_namelen=255; return 0; } @@ -865,7 +895,7 @@ NULL, /* notify_change */ ntfs_put_super, NULL, /* write_super */ - ntfs_statfs, + ntfs_statvfs, ntfs_remount_fs, /* remount */ _ntfs_clear_inode, /* clear_inode */ }; diff -ur linux-23026base/fs/ntfs/super.c linux-23026m1/fs/ntfs/super.c --- linux-23026base/fs/ntfs/super.c Mon Apr 12 20:05:58 1999 +++ linux-23026m1/fs/ntfs/super.c Mon Nov 8 03:02:17 1999 @@ -253,7 +253,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; @@ -274,9 +274,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 -ur linux-23026base/fs/ntfs/super.h linux-23026m1/fs/ntfs/super.h --- linux-23026base/fs/ntfs/super.h Mon Apr 12 20:05:58 1999 +++ linux-23026m1/fs/ntfs/super.h Mon Nov 8 03:02:38 1999 @@ -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 -ur linux-23026base/fs/open.c linux-23026m1/fs/open.c --- linux-23026base/fs/open.c Sun Oct 31 19:25:38 1999 +++ linux-23026m1/fs/open.c Mon Nov 8 20:02:06 1999 @@ -9,12 +9,14 @@ #include #include #include +#include #include asmlinkage long sys_statfs(const char * path, struct statfs * buf) { struct dentry * dentry; + struct statvfs64 sbuf64; int error; lock_kernel(); @@ -25,10 +27,25 @@ struct super_block * sb = inode->i_sb; error = -ENODEV; - if (sb && sb->s_op && sb->s_op->statfs) - error = sb->s_op->statfs(sb, buf, sizeof(struct statfs)); + if (sb && sb->s_op && sb->s_op->statvfs) + error = sb->s_op->statvfs(sb, &sbuf64); dput(dentry); + + if (!error) { + struct statfs sbuf; + memset(&sbuf,0,sizeof(sbuf)); + sbuf.f_type = sbuf64.f_type; + sbuf.f_bsize = sbuf64.f_bsize; + sbuf.f_blocks = sbuf64.f_blocks; + sbuf.f_bfree = sbuf64.f_bfree; + sbuf.f_bavail = sbuf64.f_bavail; + sbuf.f_files = sbuf64.f_files; + sbuf.f_ffree = sbuf64.f_ffree; + sbuf.f_fsid = sbuf64.f_fsid; + sbuf.f_namelen = sbuf64.f_namelen; + error = copy_to_user(buf, &sbuf, sizeof(*buf)); + } } unlock_kernel(); return error; @@ -38,6 +55,7 @@ { struct file * file; struct super_block * sb; + struct statvfs64 sbuf64; int error; error = -EBADF; @@ -47,24 +65,113 @@ error = -ENODEV; sb = file->f_dentry->d_inode->i_sb; lock_kernel(); - if (sb && sb->s_op && sb->s_op->statfs) - error = sb->s_op->statfs(sb, buf, sizeof(struct statfs)); + if (sb && sb->s_op && sb->s_op->statvfs) + error = sb->s_op->statvfs(sb, &sbuf64); + if (!error) { + struct statfs sbuf; + memset(&sbuf,0,sizeof(sbuf)); + sbuf.f_type = sbuf64.f_type; + sbuf.f_bsize = sbuf64.f_bsize; + sbuf.f_blocks = sbuf64.f_blocks; + sbuf.f_bfree = sbuf64.f_bfree; + sbuf.f_bavail = sbuf64.f_bavail; + sbuf.f_files = sbuf64.f_files; + sbuf.f_ffree = sbuf64.f_ffree; + sbuf.f_fsid = sbuf64.f_fsid; + sbuf.f_namelen = sbuf64.f_namelen; + error = copy_to_user(buf, &sbuf, sizeof(*buf)); + } unlock_kernel(); fput(file); out: return error; } -int do_truncate(struct dentry *dentry, unsigned long length) +asmlinkage int sys_statvfs64(const char * path, struct statvfs64 * buf) +{ + struct dentry * dentry; + int error; + struct statvfs64 sbuf64; + + lock_kernel(); + dentry = namei(path); + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { + struct inode * inode = dentry->d_inode; + + error = -ENOSYS; + if (inode->i_sb->s_op->statvfs) + error = inode->i_sb->s_op->statvfs(inode->i_sb, &sbuf64); + dput(dentry); + if (!error) + error = copy_to_user(buf, &sbuf64, sizeof(*buf)); + } + unlock_kernel(); + return error; +} + +asmlinkage int sys_fstatvfs64(unsigned int fd, struct statvfs64 * buf) +{ + struct file * file; + struct inode * inode; + struct dentry * dentry; + struct super_block * sb; + struct statvfs64 sbuf64; + int error; + + lock_kernel(); + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + error = -ENOENT; + if (!(dentry = file->f_dentry)) + goto out_putf; + if (!(inode = dentry->d_inode)) + goto out_putf; + error = -ENODEV; + if (!(sb = inode->i_sb)) + goto out_putf; + error = -ENOSYS; + if (sb->s_op->statvfs) + error = sb->s_op->statvfs(sb, &sbuf64); + if (!error) + error = copy_to_user(buf, &sbuf64, sizeof(*buf)); + +out_putf: + fput(file); +out: + unlock_kernel(); + return error; +} + +long 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) + if (length < 0) return -EINVAL; + if (inode->i_op->pathconf && + inode->i_op->pathconf(inode,_PC_FILESIZEBITS) <= 32) { + if (length > 0x7fffffffULL) { + /* Target filesystem doesn't support Large Files; + now we presume this means *only* 2G, although some + may have up to 4G ... */ + return -EFBIG; + } + } + + if (current->rlimfsz.rlim_cur < inode->i_size) { + /* If the target size is higher than our current (soft) + file size limit, a SIGXFSZ shall be sent along + with error -EFBIG. */ + send_sig(SIGXFSZ, current, 0); + return -EFBIG; + } + down(&inode->i_sem); newattrs.ia_size = length; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; @@ -79,11 +186,12 @@ return error; } -asmlinkage long sys_truncate(const char * path, unsigned long length) +asmlinkage long sys_truncate(const char * path, unsigned long slength) { struct dentry * dentry; struct inode * inode; int error; + loff_t length = slength; lock_kernel(); dentry = namei(path); @@ -93,7 +201,7 @@ goto out; inode = dentry->d_inode; - error = -EACCES; + error = -EISDIR; if (S_ISDIR(inode->i_mode)) goto dput_and_out; @@ -109,6 +217,10 @@ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto dput_and_out; + error = -EINVAL; /* New length may not exceed current size */ + if (inode->i_size < length) + goto dput_and_out; + error = get_write_access(inode); if (error) goto dput_and_out; @@ -144,12 +256,120 @@ goto out_putf; if (!(inode = dentry->d_inode)) goto out_putf; + error = -EISDIR; + if (S_ISDIR(inode->i_mode)) + goto out_putf; + error = -EACCES; + if (!(file->f_mode & FMODE_WRITE)) + goto out_putf; + error = -EPERM; + if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) + goto out_putf; + error = -EINVAL; + if (inode->i_size < length) + goto out_putf; + /* Large File Summit */ + error = -EFBIG; + if (S_ISREG(inode->i_mode) && !(file->f_flags & O_LARGEFILE) && + !off_t_presentable(inode->i_size)) + goto out_putf; + error = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, + lengthi_size ? length : inode->i_size, + abs(inode->i_size - length)); + if (!error) + error = do_truncate(dentry, length); +out_putf: + fput(file); +out: + unlock_kernel(); + return error; +} + +#if BITS_PER_LONG < 64 +asmlinkage int sys_truncate64(const char * path, loff_t length) +{ + struct dentry * dentry; + struct inode * inode; + int error; + + lock_kernel(); + dentry = namei(path); + + error = PTR_ERR(dentry); + if (IS_ERR(dentry)) + goto out; + inode = dentry->d_inode; + + error = -EACCES; + if (S_ISDIR(inode->i_mode)) + goto dput_and_out; + + error = permission(inode,MAY_WRITE); + if (error) + goto dput_and_out; + + error = -EROFS; + if (IS_RDONLY(inode)) + goto dput_and_out; + + error = -EPERM; + if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) + goto dput_and_out; + + error = -EFBIG; + if (inode->i_size < length) + goto dput_and_out; + + error = get_write_access(inode); + if (error) + goto dput_and_out; + + error = locks_verify_area(FLOCK_VERIFY_WRITE, inode, NULL, + length < inode->i_size ? length : inode->i_size, + abs(inode->i_size - length)); + if (!error) { + DQUOT_INIT(inode); + error = do_truncate(dentry, length); + } + put_write_access(inode); +dput_and_out: + dput(dentry); +out: + unlock_kernel(); + return error; +} + +asmlinkage int sys_ftruncate64(unsigned int fd, loff_t length) +{ + struct inode * inode; + struct dentry *dentry; + struct file * file; + int error; + + lock_kernel(); + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + error = -ENOENT; + if (!(dentry = file->f_dentry)) + goto out_putf; + if (!(inode = dentry->d_inode)) + goto out_putf; error = -EACCES; if (S_ISDIR(inode->i_mode) || !(file->f_mode & FMODE_WRITE)) goto out_putf; error = -EPERM; if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto out_putf; + error = -EINVAL; + if (inode->i_size < length || length < 0) + goto out_putf; + /* Large File Summit */ + error = -EFBIG; + if (S_ISREG(inode->i_mode) && !(file->f_flags & O_LARGEFILE) && + !off_t_presentable(inode->i_size)) + goto out_putf; error = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, lengthi_size ? length : inode->i_size, abs(inode->i_size - length)); @@ -162,6 +382,7 @@ out: return error; } +#endif /* BITS_PER_LONG < 64 */ #if !(defined(__alpha__) || defined(__ia64__)) @@ -653,6 +874,16 @@ goto cleanup_dentry; } + /* L-F-S spec: 3.1.1.3: If open() is done without O_LARGEFILE, + and the target (regular) file size exceeds that presentable with + 'off_t' datatype in the system, the open shall be rejected with + EOVERFLOW error. */ + if (S_ISREG(inode->i_mode) && !(flags & O_LARGEFILE) && + !off_t_presentable(inode->i_size)) { + error = -EOVERFLOW; + goto cleanup_all; + } + f->f_dentry = dentry; f->f_pos = 0; f->f_reada = 0; @@ -786,8 +1017,7 @@ #ifndef __alpha__ /* - * For backward compatibility? Maybe this should be moved - * into arch/i386 instead? + * This one is used at about all platforms, except Alpha.. */ asmlinkage long sys_creat(const char * pathname, int mode) { @@ -827,7 +1057,7 @@ * or not in the open-files bitmap. dup2 uses this to retain the fd * without races. */ -int do_close(unsigned int fd, int release) +long do_close(unsigned int fd, int release) { int error; struct file * filp; diff -ur linux-23026base/fs/partitions/acorn.c linux-23026m1/fs/partitions/acorn.c --- linux-23026base/fs/partitions/acorn.c Thu Sep 30 00:02:59 1999 +++ linux-23026m1/fs/partitions/acorn.c Mon Nov 8 04:51:25 1999 @@ -16,6 +16,8 @@ #include "acorn.h" +extern unsigned int get_ptable_blocksize(kdev_t); + extern void add_gd_partition(struct gendisk *hd, unsigned int minor, unsigned int start, unsigned int size); static void diff -ur linux-23026base/fs/pipe.c linux-23026m1/fs/pipe.c --- linux-23026base/fs/pipe.c Wed Sep 8 21:20:20 1999 +++ linux-23026m1/fs/pipe.c Mon Nov 8 05:13:05 1999 @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -529,9 +530,10 @@ NULL }; +static struct inode_operations pipe_inode_operations; + static struct inode * get_pipe_inode(void) { - extern struct inode_operations pipe_inode_operations; struct inode *inode = get_empty_inode(); unsigned long page; @@ -575,7 +577,14 @@ return NULL; } -struct inode_operations pipe_inode_operations = { +int pipe_pathconf(struct inode *inode, int option) +{ + if (option == _PC_PIPE_BUF) + return PIPE_BUF; + return -EINVAL; +} + +static struct inode_operations pipe_inode_operations = { &rdwr_pipe_fops, NULL, /* create */ NULL, /* lookup */ @@ -595,7 +604,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + pipe_pathconf, /* pathconf */ }; int do_pipe(int *fd) diff -ur linux-23026base/fs/proc/array.c linux-23026m1/fs/proc/array.c --- linux-23026base/fs/proc/array.c Fri Nov 5 20:22:51 1999 +++ linux-23026m1/fs/proc/array.c Mon Nov 8 04:54:22 1999 @@ -913,11 +913,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 %16Lx %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 @@ -1001,7 +1001,7 @@ len = sprintf(line, sizeof(void*) == 4 ? MAPS_LINE_FORMAT4 : MAPS_LINE_FORMAT8, - map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT, + map->vm_start, map->vm_end, str, ((loff_t)map->vm_pgoff) << PAGE_SHIFT, kdevname(dev), ino); if(map->vm_file) { diff -ur linux-23026base/fs/proc/inode.c linux-23026m1/fs/proc/inode.c --- linux-23026base/fs/proc/inode.c Sun Jul 4 20:18:52 1999 +++ linux-23026m1/fs/proc/inode.c Mon Nov 8 03:18:03 1999 @@ -108,7 +108,7 @@ NULL, proc_put_super, NULL, - proc_statfs, + proc_statvfs, NULL }; @@ -349,19 +349,17 @@ return NULL; } -int proc_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) +int proc_statvfs(struct super_block *sb, struct statvfs64 *buf) { - struct statfs tmp; - - tmp.f_type = PROC_SUPER_MAGIC; - tmp.f_bsize = PAGE_SIZE/sizeof(long); - tmp.f_blocks = 0; - tmp.f_bfree = 0; - tmp.f_bavail = 0; - tmp.f_files = 0; - tmp.f_ffree = 0; - tmp.f_namelen = NAME_MAX; - return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; + buf->f_type = PROC_SUPER_MAGIC; + buf->f_bsize = PAGE_SIZE/sizeof(long); + buf->f_blocks = 0; + buf->f_bfree = 0; + buf->f_bavail = 0; + buf->f_files = 0; + buf->f_ffree = 0; + buf->f_namelen = NAME_MAX; + return 0; } void proc_read_inode(struct inode * inode) diff -ur linux-23026base/fs/qnx4/dir.c linux-23026m1/fs/qnx4/dir.c --- linux-23026base/fs/qnx4/dir.c Tue Jul 6 05:59:55 1999 +++ linux-23026m1/fs/qnx4/dir.c Mon Nov 8 03:19:01 1999 @@ -20,6 +20,8 @@ #include +extern int qnx4_pathconf(struct inode *, int); + static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir); static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir) @@ -126,5 +128,6 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + qnx4_pathconf, /* pathconf */ }; diff -ur linux-23026base/fs/qnx4/file.c linux-23026m1/fs/qnx4/file.c --- linux-23026base/fs/qnx4/file.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/qnx4/file.c Mon Nov 8 03:23:16 1999 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -144,8 +145,34 @@ } #endif +int qnx4_pathconf(struct inode *inode, int option) +{ + switch (option) { + case _PC_NAME_MAX: /* POSIX.1: Directory only */ + return QNX4_NAME_MAX; + case _PC_NO_TRUNC: + return 0; /* silent truncation */ + + case _PC_FILESIZEBITS: /* LFS: Regular files, and dirs */ + return 32; + + case _PC_LINK_MAX: /* POSIX.1: regular files and dirs */ + return 1; + + case _PC_CHOWN_RESTRICTED: /* POSIX.1: Any file, any dir */ + break; /* FIXME: some mount-option ??? */ + + case _PC_SYNC_IO: /* POSIX.4: Regular files only ? */ + case _PC_ASYNC_IO: /* TTY only ?? */ + break; + default: + break; + } + return -EINVAL; /* Unknown thing! */ +} + /* - * We have moostly NULL's here: the current defaults are ok for + * We have mostly NULL's here: the current defaults are ok for * the qnx4 filesystem. */ static struct file_operations qnx4_file_operations = @@ -200,7 +227,8 @@ #endif NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + qnx4_pathconf, /* pathconf */ }; static int qnx4_readpage(struct file *file, struct page *page) @@ -209,13 +237,13 @@ struct inode *inode = dentry->d_inode; struct qnx4_inode_info *qnx4_ino = &inode->u.qnx4_i; unsigned long buf; - unsigned long offset, avail, readlen; + unsigned long offset, avail, readlen; // 4G max size! unsigned long start; unsigned long count; struct buffer_head *bh; int res = -EIO; - QNX4DEBUG(("qnx4: readpage offset=[%ld]\n", (long) page->offset)); + QNX4DEBUG(("qnx4: readpage offset=[%Ld]\n", page->index << PAGE_CACHE_SHIFT)); if (qnx4_ino->i_xblk != 0) { printk("qnx4: sorry, this file is extended, don't know how to handle it (yet) !\n"); @@ -226,7 +254,7 @@ buf = page_address(page); clear_bit(PG_uptodate, &page->flags); clear_bit(PG_error, &page->flags); - offset = page->offset; + offset = page->index << PAGE_CACHE_SHIFT; // 4G limit if (offset < inode->i_size) { res = 0; diff -ur linux-23026base/fs/qnx4/inode.c linux-23026m1/fs/qnx4/inode.c --- linux-23026base/fs/qnx4/inode.c Sat Oct 2 17:49:29 1999 +++ linux-23026m1/fs/qnx4/inode.c Mon Nov 8 11:49:29 1999 @@ -124,7 +124,7 @@ static void qnx4_put_super(struct super_block *sb); static void qnx4_read_inode(struct inode *); static int qnx4_remount(struct super_block *sb, int *flags, char *data); -static int qnx4_statfs(struct super_block *, struct statfs *, int); +static int qnx4_statvfs(struct super_block *, struct statvfs64 *); static struct super_operations qnx4_sops = { @@ -149,7 +149,7 @@ #else NULL, #endif - qnx4_statfs, + qnx4_statvfs, qnx4_remount, NULL /* clear_inode */ }; @@ -225,22 +225,18 @@ return NULL; } -static int qnx4_statfs(struct super_block *sb, - struct statfs *buf, int bufsize) +static int qnx4_statvfs(struct super_block *sb, struct statvfs64 *buf) { - struct statfs tmp; + buf->f_type = sb->s_magic; + buf->f_bsize = sb->s_blocksize; + buf->f_blocks = le32_to_cpu(sb->u.qnx4_sb.BitMap->di_size) * 8; + buf->f_bfree = qnx4_count_free_blocks(sb); + buf->f_bavail = buf->f_bfree; + buf->f_files = 0x00; /* change this !!! */ + buf->f_ffree = qnx4_count_free_inodes(sb); + buf->f_namelen = QNX4_NAME_MAX; - memset(&tmp, 0, sizeof tmp); - tmp.f_type = sb->s_magic; - tmp.f_bsize = sb->s_blocksize; - tmp.f_blocks = le32_to_cpu(sb->u.qnx4_sb.BitMap->di_size) * 8; - tmp.f_bfree = qnx4_count_free_blocks(sb); - tmp.f_bavail = tmp.f_bfree; - tmp.f_files = 0x00; /* change this !!! */ - tmp.f_ffree = qnx4_count_free_inodes(sb); - tmp.f_namelen = QNX4_NAME_MAX; - - return copy_to_user(buf, &tmp, bufsize) ? -EFAULT : 0; + return 0; } /* diff -ur linux-23026base/fs/qnx4/symlinks.c linux-23026m1/fs/qnx4/symlinks.c --- linux-23026base/fs/qnx4/symlinks.c Tue Jul 6 05:59:55 1999 +++ linux-23026m1/fs/qnx4/symlinks.c Mon Nov 8 03:25:04 1999 @@ -25,6 +25,7 @@ static int qnx4_readlink(struct dentry *, char *, int); static struct dentry *qnx4_follow_link(struct dentry *, struct dentry *, unsigned int follow); +extern int qnx4_pathconf(struct inode *, int); /* * symlinks can't do much... @@ -50,7 +51,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + qnx4_pathconf, /* pathconf */ }; static struct dentry *qnx4_follow_link(struct dentry *dentry, diff -ur linux-23026base/fs/read_write.c linux-23026m1/fs/read_write.c --- linux-23026base/fs/read_write.c Fri Nov 5 19:57:30 1999 +++ linux-23026m1/fs/read_write.c Mon Nov 8 03:35:35 1999 @@ -39,6 +39,11 @@ static inline loff_t llseek(struct file *file, loff_t offset, int origin) { loff_t (*fn)(struct file *, loff_t, int); + umode_t mode = file->f_dentry->d_inode->i_mode; + + /* SUS: Seek done at pipe/fifo/socket must yield ESPIPE .. */ + if (S_ISFIFO(mode) || S_ISSOCK(mode)) + return -ESPIPE; fn = default_llseek; if (file->f_op && file->f_op->llseek) @@ -49,6 +54,7 @@ asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin) { off_t retval; + loff_t oldpos; struct file * file; struct dentry * dentry; struct inode * inode; @@ -62,13 +68,25 @@ if (!(dentry = file->f_dentry) || !(inode = dentry->d_inode)) goto out_putf; + + oldpos = file->f_pos; retval = -EINVAL; if (origin <= 2) { - loff_t res = llseek(file, offset, origin); + loff_t res = llseek(file, (loff_t)offset, origin); retval = res; - if (res != (loff_t)retval) - retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */ + + /* Demand L-F-S compliance only from normal files, + thus raw devices can do whatever they please.. */ + if (res >= 0 && S_ISREG(inode->i_mode) && + !(file->f_flags & O_LARGEFILE) && + !off_t_presentable(file->f_pos+1LL)) { + printk("sys_lseek(.., %ld, %d) (oldpos=%Ld) -> %Ld - EOVERFLOW!\n", + offset, origin, oldpos, file->f_pos); + file->f_pos = oldpos; + retval = -EOVERFLOW; + } } + out_putf: fput(file); bad: @@ -85,7 +103,7 @@ struct file * file; struct dentry * dentry; struct inode * inode; - loff_t offset; + loff_t offset, oldpos; lock_kernel(); retval = -EBADF; @@ -100,6 +118,7 @@ if (origin > 2) goto out_putf; + oldpos = file->f_pos; offset = llseek(file, ((loff_t) offset_high << 32) | offset_low, origin); @@ -109,6 +128,18 @@ if (!copy_to_user(result, &offset, sizeof(offset))) retval = 0; } + +#if 0 /* With *THIS* call the resulting offset *IS* presentable */ + if (!(file->f_flags & O_LARGEFILE) && S_ISREG(inode->i_mode) && + !off_t_presentable(file->f_pos+1LL)) { + /* 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; + } +#endif + out_putf: fput(file); bad: @@ -311,6 +342,7 @@ ssize_t ret; struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); + struct inode * inode; lock_kernel(); @@ -318,10 +350,30 @@ 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); + + /* Start position must be non-negative! */ + if (pos < 0) { + ret = -EINVAL; + goto out; + } + /* Read starting from beyond the end of file ? */ + if (inode->i_size <= pos) { + ret = -EOVERFLOW; + goto out; + } + + if (!(file->f_flags & O_LARGEFILE) && S_ISREG(inode->i_mode) && + !off_t_presentable(pos+1LL)) { + ret = -EOVERFLOW; + goto out; + } + + ret = locks_verify_area(FLOCK_VERIFY_READ, inode, file, pos, count); if (ret) goto out; ret = -EINVAL; @@ -343,6 +395,7 @@ ssize_t ret; struct file * file; ssize_t (*write)(struct file *, const char *, size_t, loff_t *); + struct inode * inode; lock_kernel(); @@ -352,8 +405,21 @@ 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); + /* Start position must be non-negative! */ + if (pos < 0) { + ret = -EINVAL; + goto out; + } + + inode = file->f_dentry->d_inode; + + if (!(file->f_flags & O_LARGEFILE) && S_ISREG(inode->i_mode) && + !off_t_presentable(pos+1LL)) { + ret = -EOVERFLOW; + goto out; + } + + ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, pos, count); if (ret) goto out; ret = -EINVAL; diff -ur linux-23026base/fs/readdir.c linux-23026m1/fs/readdir.c --- linux-23026base/fs/readdir.c Mon Aug 23 21:15:53 1999 +++ linux-23026m1/fs/readdir.c Mon Nov 8 03:39:44 1999 @@ -196,3 +196,105 @@ unlock_kernel(); return error; } + +/* + * New, even-more-improved getdents64() (for LFS) interface. + */ +struct linux_dirent64 { + __u64 d_ino; /* 64 bits *should* be enough */ + __u32 d_off; /* position within directory */ + __u32 d_flags; /* what is stored in d_data[] */ + __u32 d_data[8]; /* for future extensions */ + __u16 d_reclen; + char d_name[1]; /* We must not include limits.h! */ +}; + +struct getdents_callback64 { + struct linux_dirent64 * current_dir; + struct linux_dirent64 * previous; + int count; + int error; + int ctrlflags; +}; + +static int filldir64(void * __buf, const char * name, int namlen, off_t offset, ino_t ino) +{ + struct linux_dirent64 * dirent; + struct getdents_callback64 * buf = (struct getdents_callback64 *) __buf; + int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1); + __u64 ino64; + + buf->error = -EINVAL; /* only used if we fail.. */ + if (reclen > buf->count) + return -EINVAL; + dirent = buf->previous; + if (dirent) + put_user(offset, &dirent->d_off); + dirent = buf->current_dir; + buf->previous = dirent; + ino64 = ino; + copy_to_user(&dirent->d_reclen, &ino64, sizeof(ino64)); + 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, long flags) +{ + struct file * file; + struct dentry * dentry; + struct inode * inode; + struct linux_dirent64 * lastdirent; + struct getdents_callback64 buf; + int error; + + if (flags) return -EINVAL; /* until flags defined.. */ + + 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) { + put_user(file->f_pos, &lastdirent->d_off); + error = count - buf.count; + } + +out_putf: + fput(file); +out: + unlock_kernel(); + return error; +} diff -ur linux-23026base/fs/romfs/inode.c linux-23026m1/fs/romfs/inode.c --- linux-23026base/fs/romfs/inode.c Wed Oct 27 01:03:19 1999 +++ linux-23026m1/fs/romfs/inode.c Mon Nov 8 11:49:09 1999 @@ -58,6 +58,7 @@ #include #include #include +#include #include @@ -166,16 +167,13 @@ /* That's simple too. */ static int -romfs_statfs(struct super_block *sb, struct statfs *buf, int bufsize) +romfs_statvfs(struct super_block *sb, struct statvfs64 *buf) { - struct statfs tmp; - - memset(&tmp, 0, sizeof(tmp)); - tmp.f_type = ROMFS_MAGIC; - tmp.f_bsize = ROMBSIZE; - tmp.f_blocks = (sb->u.romfs_sb.s_maxsize+ROMBSIZE-1)>>ROMBSBITS; - tmp.f_namelen = ROMFS_MAXFN; - return copy_to_user(buf, &tmp, bufsize) ? -EFAULT : 0; + buf->f_type = ROMFS_MAGIC; + buf->f_bsize = ROMBSIZE; + buf->f_blocks = (sb->u.romfs_sb.s_maxsize+ROMBSIZE-1)>>ROMBSBITS; + buf->f_namelen = ROMFS_MAXFN; + return 0; } /* some helper routines */ @@ -404,7 +402,7 @@ get_page(page); buf = page_address(page); - offset = page->offset; + offset = (page->index) << PAGE_CACHE_SHIFT; if (offset < inode->i_size) { avail = inode->i_size-offset; readlen = min(avail, PAGE_SIZE); @@ -486,6 +484,32 @@ return dentry; } +static int romfs_pathconf(struct inode *inode, int option) +{ + switch (option) { + case _PC_NAME_MAX: /* POSIX.1: Directory only */ + break; /* This is read-only filesystem! */ + case _PC_NO_TRUNC: + break; /* This is read-only filesystem! */ + + case _PC_FILESIZEBITS: /* LFS: Regular files, and dirs */ + return 32; + + case _PC_LINK_MAX: /* POSIX.1: regular files and dirs */ + break; /* This is read-only filesystem! */ + + case _PC_CHOWN_RESTRICTED: /* POSIX.1: Any file, any dir */ + break; /* FIXME: some mount-option ??? */ + + case _PC_SYNC_IO: /* POSIX.4: Regular files only ? */ + case _PC_ASYNC_IO: /* TTY only ?? */ + break; + default: + break; + } + return -EINVAL; /* Unknown thing! */ +} + /* Mapping from our types to the kernel */ static struct file_operations romfs_file_operations = { @@ -525,7 +549,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + romfs_pathconf, /* pathconf */ }; static struct file_operations romfs_dir_operations = { @@ -542,7 +567,7 @@ NULL, /* fsync */ NULL, /* fasync */ NULL, /* check_media_change */ - NULL /* revalidate */ + NULL, /* revalidate */ }; /* Merged dir/symlink op table. readdir/lookup/readlink/follow_link @@ -569,7 +594,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + romfs_pathconf, /* pathconf */ }; static struct inode_operations romfs_link_inode_operations = { @@ -592,7 +618,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + romfs_pathconf, /* pathconf */ }; static mode_t romfs_modemap[] = @@ -678,7 +705,7 @@ NULL, /* notify change */ romfs_put_super, /* put super */ NULL, /* write super */ - romfs_statfs, /* statfs */ + romfs_statvfs, /* statvfs */ NULL /* remount */ }; diff -ur linux-23026base/fs/smbfs/cache.c linux-23026m1/fs/smbfs/cache.c --- linux-23026base/fs/smbfs/cache.c Thu Oct 28 20:53:51 1999 +++ linux-23026m1/fs/smbfs/cache.c Mon Nov 8 11:37:56 1999 @@ -44,15 +44,15 @@ * smb-cache code assumes we return a locked page. */ static unsigned long -get_cached_page(struct address_space *mapping, unsigned long offset, int new) +get_cached_page(struct address_space *mapping, unsigned long index, int new) { struct page * page; struct page ** hash; struct page *cached_page = NULL; again: - hash = page_hash(mapping, offset); - page = __find_lock_page(mapping, offset, hash); + hash = page_hash(mapping, index); + page = __find_lock_page(mapping, index, hash); if(!page && new) { /* not in cache, alloc a new page if we didn't do it yet */ if (!cached_page) { @@ -67,7 +67,7 @@ if (page->buffers) BUG(); printk(KERN_DEBUG "smbfs: get_cached_page\n"); - if (add_to_page_cache_unique(page, mapping, offset, hash)) + if (add_to_page_cache_unique(page, mapping, index, hash)) /* Hmm, a page has materialized in the cache. Fine. Go back and get that page instead... */ @@ -92,7 +92,7 @@ /* * Get a pointer to the cache_head structure, - * mapped as the page at offset 0. The page is + * mapped as the page at index 0. The page is * kept locked while we're using the cache. */ struct cache_head * @@ -112,7 +112,6 @@ { struct cache_index * index = cachep->index; struct cache_block * block; - unsigned long offset; int i; cachep->valid = 0; @@ -126,9 +125,8 @@ printk("smb_get_dircache: cache %s/%s has existing block!\n", dentry->d_parent->d_name.name, dentry->d_name.name); #endif - offset = PAGE_SIZE + (i << PAGE_SHIFT); block = (struct cache_block *) get_cached_page(mapping, - offset, 0); + i+1, 0); if (!block) goto out; index->block = block; diff -ur linux-23026base/fs/smbfs/dir.c linux-23026m1/fs/smbfs/dir.c --- linux-23026base/fs/smbfs/dir.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/smbfs/dir.c Mon Nov 8 03:47:47 1999 @@ -29,6 +29,8 @@ static int smb_unlink(struct inode *, struct dentry *); static int smb_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); +extern int smb_pathconf(struct inode *, int); + static struct file_operations smb_dir_operations = { @@ -67,6 +69,7 @@ NULL, /* permission */ NULL, /* smap */ smb_revalidate_inode, /* revalidate */ + smb_pathconf, /* pathconf */ }; static ssize_t diff -ur linux-23026base/fs/smbfs/file.c linux-23026m1/fs/smbfs/file.c --- linux-23026base/fs/smbfs/file.c Sat Oct 30 02:45:32 1999 +++ linux-23026m1/fs/smbfs/file.c Mon Nov 8 11:38:54 1999 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -120,25 +121,42 @@ * 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; - offset += page->index << PAGE_CACHE_SHIFT; + loff_t loffset = offset + (((loff_t)page->index) << PAGE_CACHE_SHIFT); + #ifdef SMBFS_DEBUG_VERBOSE -printk("smb_writepage_sync: file %s/%s, count=%d@%ld, wsize=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, count, offset, wsize); +printk("smb_writepage_sync: file %s/%s, count=%d@%Ld, wsize=%d\n", +dentry->d_parent->d_name.name, dentry->d_name.name, count, loffset, wsize); #endif + if (!(file->f_flags & O_LARGEFILE) && + !off_t_presentable(loffset+1)) + /* Write starts beyond allowed type-range of off_t */ + return -EFBIG; /* Might trap at 2G, or might go above .. */ + + if (!(file->f_flags & O_LARGEFILE) && + !off_t_presentable(loffset + count)) + /* Writing beyond LargeFile maximums without O_LARGEFILE */ + count = LONG_MAX - loffset; + + if (loffset >= 0x7fffffffULL) /* 2G-1 */ + return -EFBIG; + if ((loffset + count) >= 0x7fffffffULL) + count = 0x7fffffffULL - 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?? */ @@ -147,15 +165,15 @@ printk("smb_writepage_sync: short write, wsize=%d, result=%d\n", wsize, result); #endif buffer += wsize; - offset += wsize; + loffset += wsize; written += 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; @@ -170,7 +188,6 @@ static int smb_writepage(struct file *file, struct page *page) { - struct dentry *dentry = file->f_dentry; int result; #ifdef SMBFS_PARANOIA @@ -178,7 +195,7 @@ printk("smb_writepage: page not already locked!\n"); #endif get_page(page); - result = smb_writepage_sync(dentry, page, 0, PAGE_SIZE); + result = smb_writepage_sync(file, page, 0, PAGE_SIZE); SetPageUptodate(page); put_page(page); return result; @@ -189,11 +206,11 @@ { struct dentry *dentry = file->f_dentry; - pr_debug("SMBFS: smb_updatepage(%s/%s %d@%ld)\n", + pr_debug("SMBFS: smb_updatepage(%s/%s %d@%Ld)\n", dentry->d_parent->d_name.name, dentry->d_name.name, - count, (page->index << PAGE_CACHE_SHIFT)+offset); + count, (((loff_t)page->index) << PAGE_CACHE_SHIFT)+offset); - return smb_writepage_sync(dentry, page, offset, count); + return smb_writepage_sync(file, page, offset, count); } static ssize_t @@ -203,9 +220,9 @@ ssize_t status; #ifdef SMBFS_DEBUG_VERBOSE -printk("smb_file_read: file %s/%s, count=%lu@%lu\n", +printk("smb_file_read: file %s/%s, count=%lu@%Lu\n", dentry->d_parent->d_name.name, dentry->d_name.name, -(unsigned long) count, (unsigned long) *ppos); +(unsigned long) count, *ppos); #endif status = smb_revalidate_inode(dentry); @@ -286,9 +303,9 @@ ssize_t result; #ifdef SMBFS_DEBUG_VERBOSE -printk("smb_file_write: file %s/%s, count=%lu@%lu, pages=%ld\n", +printk("smb_file_write: file %s/%s, count=%lu@%Ld, pages=%ld\n", dentry->d_parent->d_name.name, dentry->d_name.name, -(unsigned long) count, (unsigned long) *ppos, dentry->d_inode->i_nrpages); +(unsigned long) count, *ppos, dentry->d_inode->i_nrpages); #endif result = smb_revalidate_inode(dentry); @@ -309,8 +326,8 @@ { result = generic_file_write(file, buf, count, ppos, smb_write_one_page); #ifdef SMBFS_DEBUG_VERBOSE -printk("smb_file_write: pos=%ld, size=%ld, mtime=%ld, atime=%ld\n", -(long) file->f_pos, dentry->d_inode->i_size, dentry->d_inode->i_mtime, +printk("smb_file_write: 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); #endif } @@ -367,6 +384,33 @@ return error; } + +int smb_pathconf(struct inode *inode, int option) +{ + switch (option) { + case _PC_NAME_MAX: /* POSIX.1: Directory only */ + return SMB_MAXNAMELEN; + case _PC_NO_TRUNC: + return 1; /* UNIX-like semantics */ + + case _PC_FILESIZEBITS: /* LFS: Regular files, and dirs */ + return 32; + + case _PC_LINK_MAX: /* POSIX.1: regular files and dirs */ + return 1; + + case _PC_CHOWN_RESTRICTED: /* POSIX.1: Any file, any dir */ + break; /* FIXME: some mount-option ??? */ + + case _PC_SYNC_IO: /* POSIX.4: Regular files only ? */ + case _PC_ASYNC_IO: /* TTY only ?? */ + break; + default: + break; + } + return -EINVAL; /* Unknown thing! */ +} + static struct file_operations smb_file_operations = { NULL, /* lseek - default */ @@ -408,4 +452,5 @@ smb_file_permission, /* permission */ NULL, /* smap */ smb_revalidate_inode, /* revalidate */ + smb_pathconf, /* pathconf */ }; diff -ur linux-23026base/fs/smbfs/inode.c linux-23026m1/fs/smbfs/inode.c --- linux-23026base/fs/smbfs/inode.c Fri Oct 15 00:22:09 1999 +++ linux-23026m1/fs/smbfs/inode.c Mon Nov 8 11:38:08 1999 @@ -33,7 +33,7 @@ static void smb_put_inode(struct inode *); static void smb_delete_inode(struct inode *); static void smb_put_super(struct super_block *); -static int smb_statfs(struct super_block *, struct statfs *, int); +static int smb_statvfs(struct super_block *, struct statvfs64 *); static void smb_set_inode_attr(struct inode *, struct smb_fattr *); static struct super_operations smb_sops = @@ -45,7 +45,7 @@ smb_notify_change, /* notify change */ smb_put_super, /* put superblock */ NULL, /* write superblock */ - smb_statfs, /* stat filesystem */ + smb_statvfs, /* stat filesystem */ NULL /* remount filesystem */ }; @@ -427,19 +427,15 @@ } static int -smb_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) +smb_statvfs(struct super_block *sb, struct statvfs64 *buf) { - struct statfs attr; + smb_proc_dskattr(sb, buf); - memset(&attr, 0, sizeof(attr)); - - smb_proc_dskattr(sb, &attr); - - attr.f_type = SMB_SUPER_MAGIC; - attr.f_files = -1; - attr.f_ffree = -1; - attr.f_namelen = SMB_MAXPATHLEN; - return copy_to_user(buf, &attr, bufsiz) ? -EFAULT : 0; + buf->f_type = SMB_SUPER_MAGIC; + buf->f_files = -1; + buf->f_ffree = -1; + buf->f_namelen = SMB_MAXPATHLEN; + return 0; } int diff -ur linux-23026base/fs/smbfs/proc.c linux-23026m1/fs/smbfs/proc.c --- linux-23026base/fs/smbfs/proc.c Thu Jun 17 05:26:27 1999 +++ linux-23026m1/fs/smbfs/proc.c Mon Nov 8 03:59:00 1999 @@ -1003,7 +1003,7 @@ 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; @@ -1045,14 +1045,14 @@ } 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; #if SMBFS_DEBUG_VERBOSE -printk("smb_proc_write: file %s/%s, count=%d@%ld, packet_size=%d\n", +printk("smb_proc_write: file %s/%s, count=%d@%Ld, packet_size=%d\n", DENTRY_PATH(dentry), count, offset, server->packet_size); #endif smb_lock_server(server); @@ -2234,7 +2234,7 @@ } int -smb_proc_dskattr(struct super_block *sb, struct statfs *attr) +smb_proc_dskattr(struct super_block *sb, struct statvfs64 *attr) { struct smb_sb_info *server = &(sb->u.smbfs_sb); int error; diff -ur linux-23026base/fs/stat.c linux-23026m1/fs/stat.c --- linux-23026base/fs/stat.c Mon Aug 23 21:15:53 1999 +++ linux-23026m1/fs/stat.c Mon Nov 8 04:03:37 1999 @@ -8,10 +8,22 @@ #include #include #include +#include #include /* + * Large File Summit rules tell that fstat() with insufficient st_size + * value space shall fail with errno=EOVERFLOW, while other *stat() + * calls just return some arbitary value (e.g. MAXINT) at the same field. + * This constant tells to behave differently. + * + */ +#define all_fail_alike_fstat 0 + + + +/* * Revalidate the inode. This is required for proper NFS attribute caching. */ static __inline__ int @@ -28,7 +40,7 @@ /* * For backward compatibility? Maybe this should be moved - * into arch/i386 instead? + * into arch/i386 instead? (and to m68k ???) */ static int cp_old_stat(struct inode * inode, struct __old_kernel_stat * statbuf) { @@ -57,7 +69,12 @@ #endif -static int cp_new_stat(struct inode * inode, struct stat * statbuf) +/* "No lie" policy yields EOVERFLOW if file size exceeds + a value which is presentable in field st_size (or st_blocks, + or st_ino). But then the file will not appear in the directory + listing at all before we have stat64() syscalls in use.. */ + +static int cp_new_stat(struct inode * inode, struct stat * statbuf, int f) { struct stat tmp; unsigned int blocks, indirect; @@ -65,12 +82,29 @@ memset(&tmp, 0, sizeof(tmp)); tmp.st_dev = kdev_t_to_nr(inode->i_dev); tmp.st_ino = inode->i_ino; + if (tmp.st_ino != inode->i_ino) { + if (f || all_fail_alike_fstat) + return -EOVERFLOW; /* See LFS spec: 2.2.1.14 + Xstat() shall fail with + EOVERFLOW. */ + tmp.st_ino = -1; + } 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); + /* large-file stat() problem... + If your file size is 4G-1, it *propably* + is over 4G in a 32-bit system... */ tmp.st_size = inode->i_size; + if (inode->i_size != tmp.st_size) { + if (f || all_fail_alike_fstat) + return -EOVERFLOW; /* See LFS spec: 2.2.1.14 + Xstat() shall fail with + EOVERFLOW. */ + tmp.st_size = ULONG_MAX; + } tmp.st_atime = inode->i_atime; tmp.st_mtime = inode->i_mtime; tmp.st_ctime = inode->i_ctime; @@ -110,6 +144,15 @@ tmp.st_blocks = inode->i_blocks; tmp.st_blksize = inode->i_blksize; } +#if BITS_PER_LONG < 64 + if (tmp.st_blocks != inode->i_blocks) { + if (f || all_fail_alike_fstat) + return -EOVERFLOW; /* See LFS spec: 2.2.1.14 + Xstat() shall fail with + EOVERFLOW. */ + tmp.st_blocks = ULONG_MAX; + } +#endif return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; } @@ -152,7 +195,7 @@ if (!IS_ERR(dentry)) { error = do_revalidate(dentry); if (!error) - error = cp_new_stat(dentry->d_inode, statbuf); + error = cp_new_stat(dentry->d_inode, statbuf, 0); dput(dentry); } @@ -200,7 +243,7 @@ if (!IS_ERR(dentry)) { error = do_revalidate(dentry); if (!error) - error = cp_new_stat(dentry->d_inode, statbuf); + error = cp_new_stat(dentry->d_inode, statbuf, 0); dput(dentry); } @@ -247,7 +290,7 @@ err = do_revalidate(dentry); if (!err) - err = cp_new_stat(dentry->d_inode, statbuf); + err = cp_new_stat(dentry->d_inode, statbuf, 1); fput(f); } unlock_kernel(); @@ -279,4 +322,249 @@ } unlock_kernel(); return error; +} + + +/* ---------- LFS-64 ----------- */ + +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; + 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_newstat64(char * filename, struct stat64 * statbuf) +{ + 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_newlstat64(char * filename, struct stat64 * statbuf) +{ + 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_newfstat64(unsigned int fd, struct stat64 * statbuf) +{ + struct file * f; + int err = -EBADF; + + lock_kernel(); + f = fget(fd); + if (f) { + struct dentry * dentry = f->f_dentry; + + err = do_revalidate(dentry); + if (!err) + err = cp_new_stat64(dentry->d_inode, statbuf); + fput(f); + } + unlock_kernel(); + return err; +} + + + +/* + * POSIX pathconf() + * + * return value rules differ from sysconf(); If no explicite limit + * is in effect for given option, pathconf() shall return -1 without + * touching errno. If the failure is anywhere else, errors like EINVAL, + * EACCESS, ENOENT, etc. are possible.. + * + * Returning ``-1'' without errno is indicated by returning ``-INT_MAX'' + */ + +extern int pipe_pathconf(struct inode *inode, int option); +extern __u32 sysctl_wmem_max; + +static int dpathconf(struct dentry *dentry, int option) +{ + int (*pathconf)(struct inode*, int); + umode_t mode = dentry->d_inode->i_mode; + + switch (option) { + case _PC_ASYNC_IO: /* POSIX.4: TTY only (per Solaris) */ + case _PC_PRIO_IO: + case _PC_MAX_CANON: /* POSIX.1: TTY only */ + case _PC_MAX_INPUT: + case _PC_VDISABLE: + if (!S_ISCHR(mode)) /* CHAR devices -- at least */ + return -EINVAL; + break; + + case _PC_NAME_MAX: /* POSIX.1: Directory only */ + case _PC_NO_TRUNC: + if (!S_ISDIR(mode)) + return -EINVAL; + break; + + case _PC_PATH_MAX: + if (!S_ISDIR(mode)) + return -EINVAL; + return PATH_MAX; + + case _PC_FILESIZEBITS: /* LFS: Regular files, and dirs */ + case _PC_LINK_MAX: /* POSIX.1: regular files and dirs */ + if (!S_ISREG(mode) && !S_ISDIR(mode)) + return -EINVAL; + break; + + case _PC_PIPE_BUF: /* POSIX.1: Pipes & dirs only */ + if (!S_ISFIFO(mode) && !S_ISDIR(mode)) + return -EINVAL; + /* This direct call to pipe_pathconf() is done this + way, because with named pipes the names may exist + in some remote directories, but the pipes them- + selves live only in the local system kernel */ + return pipe_pathconf(dentry->d_inode, option); + + case _PC_SOCK_MAXBUF: /* POSIX.1g: fpathconf() */ + if (!S_ISSOCK(mode)) + return -EINVAL; + return sysctl_wmem_max; + + case _PC_CHOWN_RESTRICTED: /* POSIX.1: Any file, any dir */ + if (!S_ISREG(mode) && !S_ISDIR(mode)) + return -EINVAL; + break; + + case _PC_SYNC_IO: /* POSIX.4: Regular files only */ + /* Solaris: Dirs ok too! */ + if (!S_ISREG(mode) && !S_ISDIR(mode)) + return -EINVAL; + break; + + default: /* Eh ?? */ + return -EINVAL; + } + + pathconf = dentry->d_inode->i_op->pathconf; + if (pathconf) + return pathconf(dentry->d_inode, option); + + return -EINVAL; /* No pathconf, no direct processing! */ +} + +asmlinkage int sys_pathconf(char *pathname, int option) +{ + struct dentry * dentry; + int error; + + lock_kernel(); + dentry = namei(pathname); + + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { + error = do_revalidate(dentry); + if (!error) + error = dpathconf(dentry, option); + dput(dentry); + } + unlock_kernel(); + return error; +} + +/* + * POSIX fpathconf() -- pathconf() with 'fd' + */ + +asmlinkage int sys_fpathconf(int fd, int option) +{ + struct file * f; + int err; + + lock_kernel(); + f = fget(fd); + if (f) { + struct dentry * dentry = f->f_dentry; + + err = do_revalidate(dentry); + if (!err) + err = dpathconf(dentry, option); + fput(f); + } else + err = -EBADF; + unlock_kernel(); + return err; } diff -ur linux-23026base/fs/super.c linux-23026m1/fs/super.c --- linux-23026base/fs/super.c Sun Oct 31 09:19:22 1999 +++ linux-23026m1/fs/super.c Mon Nov 8 04:05:38 1999 @@ -478,8 +478,7 @@ { struct super_block *s; struct ustat tmp; - struct statfs sbuf; - mm_segment_t old_fs; + struct statvfs64 sbuf64; int err = -EINVAL; lock_kernel(); @@ -487,17 +486,14 @@ if (s == NULL) goto out; err = -ENOSYS; - if (!(s->s_op->statfs)) + if (!(s->s_op->statvfs)) goto out; - old_fs = get_fs(); - set_fs(get_ds()); - s->s_op->statfs(s,&sbuf,sizeof(struct statfs)); - set_fs(old_fs); + s->s_op->statvfs(s,&sbuf64); memset(&tmp,0,sizeof(struct ustat)); - tmp.f_tfree = sbuf.f_bfree; - tmp.f_tinode = sbuf.f_ffree; + tmp.f_tfree = sbuf64.f_bfree; + tmp.f_tinode = sbuf64.f_ffree; err = copy_to_user(ubuf,&tmp,sizeof(struct ustat)) ? -EFAULT : 0; out: diff -ur linux-23026base/fs/sysv/dir.c linux-23026m1/fs/sysv/dir.c --- linux-23026base/fs/sysv/dir.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/sysv/dir.c Mon Nov 8 04:08:17 1999 @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -28,6 +29,7 @@ } static int sysv_readdir(struct file *, void *, filldir_t); +extern int sysv_pathconf(struct inode *inode, int option); static struct file_operations sysv_dir_operations = { NULL, /* lseek - default */ @@ -66,7 +68,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + sysv_pathconf, /* pathconf */ }; static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir) @@ -114,4 +117,30 @@ brelse(bh); } return 0; +} + +int sysv_pathconf(struct inode *inode, int option) +{ + switch (option) { + case _PC_NAME_MAX: /* POSIX.1: Directory only */ + return SYSV_NAMELEN; /* name component max length */ + case _PC_NO_TRUNC: + return !inode->i_sb->sv_truncate; + + case _PC_FILESIZEBITS: /* LFS: Regular files, and dirs */ + return 32; + + case _PC_LINK_MAX: /* POSIX.1: regular files and dirs */ + return inode->i_sb->sv_link_max; + + case _PC_CHOWN_RESTRICTED: /* POSIX.1: Any file, any dir */ + break; /* FIXME: some mount-option ??? */ + + case _PC_SYNC_IO: /* POSIX.4: Regular files only ? */ + case _PC_ASYNC_IO: /* TTY only ?? */ + break; + default: + break; + } + return -EINVAL; /* Unknown thing! */ } diff -ur linux-23026base/fs/sysv/file.c linux-23026m1/fs/sysv/file.c --- linux-23026base/fs/sysv/file.c Tue Jul 6 06:35:18 1999 +++ linux-23026m1/fs/sysv/file.c Mon Nov 8 04:09:00 1999 @@ -40,6 +40,8 @@ ppos, block_write_partial_page); } +extern int sysv_pathconf(struct inode *, int); + /* * We have mostly NULLs here: the current defaults are OK for * the coh filesystem. @@ -81,5 +83,6 @@ sysv_truncate, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + sysv_pathconf, /* pathconf */ }; diff -ur linux-23026base/fs/sysv/inode.c linux-23026m1/fs/sysv/inode.c --- linux-23026base/fs/sysv/inode.c Thu Oct 7 20:17:09 1999 +++ linux-23026m1/fs/sysv/inode.c Mon Nov 8 04:09:51 1999 @@ -67,7 +67,7 @@ static void sysv_write_super(struct super_block *); static void sysv_read_inode(struct inode *); static int sysv_notify_change(struct dentry *, struct iattr *); -static int sysv_statfs(struct super_block *, struct statfs *, int); +static int sysv_statvfs(struct super_block *, struct statvfs64 *); static struct super_operations sysv_sops = { sysv_read_inode, @@ -77,7 +77,7 @@ sysv_notify_change, sysv_put_super, sysv_write_super, - sysv_statfs, + sysv_statvfs, NULL /* remount_fs */ }; @@ -564,20 +564,18 @@ MOD_DEC_USE_COUNT; } -static int sysv_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) +static int sysv_statvfs(struct super_block *sb, struct statvfs64 *buf) { - struct statfs tmp; - - tmp.f_type = sb->s_magic; /* type of filesystem */ - tmp.f_bsize = sb->sv_block_size; /* block size */ - tmp.f_blocks = sb->sv_ndatazones; /* total data blocks in file system */ - tmp.f_bfree = sysv_count_free_blocks(sb); /* free blocks in fs */ - tmp.f_bavail = tmp.f_bfree; /* free blocks available to non-superuser */ - tmp.f_files = sb->sv_ninodes; /* total file nodes in file system */ - tmp.f_ffree = sysv_count_free_inodes(sb); /* free file nodes in fs */ - tmp.f_namelen = SYSV_NAMELEN; - /* Don't know what value to put in tmp.f_fsid */ /* file system id */ - return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; + buf->f_type = sb->s_magic; /* type of filesystem */ + buf->f_bsize = sb->sv_block_size; /* block size */ + buf->f_blocks = sb->sv_ndatazones; /* total data blocks in file system */ + buf->f_bfree = sysv_count_free_blocks(sb); /* free blocks in fs */ + buf->f_bavail = buf->f_bfree; /* free blocks available to non-superuser */ + buf->f_files = sb->sv_ninodes; /* total file nodes in file system */ + buf->f_ffree = sysv_count_free_inodes(sb); /* free file nodes in fs */ + buf->f_namelen = SYSV_NAMELEN; + /* Don't know what value to put in buf->f_fsid */ /* file system id */ + return 0; } diff -ur linux-23026base/fs/sysv/symlink.c linux-23026m1/fs/sysv/symlink.c --- linux-23026base/fs/sysv/symlink.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/sysv/symlink.c Mon Nov 8 04:10:35 1999 @@ -22,6 +22,7 @@ static int sysv_readlink(struct dentry *, char *, int); static struct dentry *sysv_follow_link(struct dentry *, struct dentry *, unsigned int); +extern int sysv_pathconf(struct inode *, int); /* * symlinks can't do much... @@ -46,7 +47,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + sysv_pathconf, /* pathconf */ }; static struct dentry *sysv_follow_link(struct dentry * dentry, diff -ur linux-23026base/fs/udf/super.c linux-23026m1/fs/udf/super.c --- linux-23026base/fs/udf/super.c Sat Nov 6 19:51:19 1999 +++ linux-23026m1/fs/udf/super.c Mon Nov 8 04:12:51 1999 @@ -86,7 +86,7 @@ static unsigned int udf_count_free(struct super_block *); /* version specific functions */ -static int udf_statfs(struct super_block *, struct statfs *, int); +static int udf_statvfs(struct super_block *, struct statvfs64 *); /* UDF filesystem type */ static struct file_system_type udf_fstype = { @@ -114,7 +114,7 @@ NULL, /* notify_change */ udf_put_super, /* put_super */ NULL, /* write_super */ - udf_statfs, /* statfs */ + udf_statvfs, /* statvfs */ udf_remount_fs, /* remount_fs */ NULL, /* clear_inode */ NULL, /* umount_begin */ @@ -1508,36 +1508,27 @@ * Return info about the filesystem. * * DESCRIPTION - * Called by sys_statfs() + * Called by sys_statvfs() * * HISTORY * July 1, 1997 - Andrew E. Mileski * Written, tested, and released. */ static int -udf_statfs(struct super_block *sb, struct statfs *buf, int bufsize) +udf_statvfs(struct super_block *sb, struct statvfs64 *buf) { - int size; - struct statfs tmp; - int rc; - - size = (bufsize < sizeof(tmp)) ? bufsize: sizeof(tmp); - - memset(&tmp, 0, sizeof(tmp)); - tmp.f_type = UDF_SUPER_MAGIC; - tmp.f_bsize = sb->s_blocksize; - tmp.f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb)); - tmp.f_bfree = udf_count_free(sb); - tmp.f_bavail = tmp.f_bfree; - tmp.f_files = (UDF_SB_LVIDBH(sb) ? + buf->f_type = UDF_SUPER_MAGIC; + buf->f_bsize = sb->s_blocksize; + buf->f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb)); + buf->f_bfree = udf_count_free(sb); + buf->f_bavail = buf->f_bfree; + buf->f_files = (UDF_SB_LVIDBH(sb) ? (le32_to_cpu(UDF_SB_LVIDIU(sb)->numFiles) + - le32_to_cpu(UDF_SB_LVIDIU(sb)->numDirs)) : 0) + tmp.f_bfree; - tmp.f_ffree = tmp.f_bfree; + le32_to_cpu(UDF_SB_LVIDIU(sb)->numDirs)) : 0) + buf->f_bfree; + buf->f_ffree = buf->f_bfree; /* __kernel_fsid_t f_fsid */ - tmp.f_namelen = UDF_NAME_LEN; - - rc= copy_to_user(buf, &tmp, size) ? -EFAULT: 0; - return rc; + buf->f_namelen = UDF_NAME_LEN; + return 0; } static unsigned char udf_bitmap_lookup[16] = { diff -ur linux-23026base/fs/ufs/balloc.c linux-23026m1/fs/ufs/balloc.c --- linux-23026base/fs/ufs/balloc.c Tue Jul 6 05:59:55 1999 +++ linux-23026m1/fs/ufs/balloc.c Mon Nov 8 11:42:36 1999 @@ -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 -ur linux-23026base/fs/ufs/dir.c linux-23026m1/fs/ufs/dir.c --- linux-23026base/fs/ufs/dir.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/ufs/dir.c Mon Nov 8 11:43:14 1999 @@ -18,6 +18,7 @@ #include "swab.h" #include "util.h" +#include #undef UFS_DIR_DEBUG @@ -168,7 +169,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), @@ -177,6 +178,32 @@ return (error_msg == NULL ? 1 : 0); } +int ufs_pathconf(struct inode *inode, int option) +{ + switch (option) { + case _PC_NAME_MAX: /* POSIX.1: Directory only */ + return UFS_MAXNAMLEN; /* name component max length */ + case _PC_NO_TRUNC: + return 1; /* UNIX semantics */ + + case _PC_FILESIZEBITS: /* LFS: Regular files, and dirs */ + return 64; /* FIXME: L-F-S: mount-option: nolargefiles ? */ + + case _PC_LINK_MAX: /* POSIX.1: regular files and dirs */ + return UFS_LINK_MAX; + + case _PC_CHOWN_RESTRICTED: /* POSIX.1: Any file, any dir */ + break; /* FIXME: some mount-option ??? */ + + case _PC_SYNC_IO: /* POSIX.4: Regular files only ? */ + case _PC_ASYNC_IO: /* TTY only ?? */ + break; + default: + break; + } + return -EINVAL; /* Unknown thing! */ +} + static struct file_operations ufs_dir_operations = { NULL, /* lseek */ NULL, /* read */ @@ -214,5 +241,6 @@ NULL, /* truncate */ ufs_permission, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + ufs_pathconf, /* pathconf */ }; diff -ur linux-23026base/fs/ufs/file.c linux-23026m1/fs/ufs/file.c --- linux-23026base/fs/ufs/file.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/ufs/file.c Mon Nov 8 04:15:33 1999 @@ -137,6 +137,8 @@ NULL /* revalidate */ }; +extern int ufs_pathconf(struct inode *, int); + struct inode_operations ufs_file_inode_operations = { &ufs_file_operations,/* default file operations */ NULL, /* create */ @@ -157,5 +159,6 @@ ufs_truncate, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + ufs_pathconf, /* pathconf */ }; diff -ur linux-23026base/fs/ufs/inode.c linux-23026m1/fs/ufs/inode.c --- linux-23026base/fs/ufs/inode.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/ufs/inode.c Mon Nov 8 12:10:50 1999 @@ -55,7 +55,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); @@ -222,13 +222,10 @@ } *err = -EFBIG; - limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit < RLIM_INFINITY) { - limit >>= sb->s_blocksize_bits; - if (new_fragment >= limit) { - send_sig(SIGXFSZ, current, 0); - return NULL; - } + limit = (current->rlimfsz.rlim_cur >> sb->s_blocksize_bits); + if (new_fragment >= limit) { + send_sig(SIGXFSZ, current, 0); + return NULL; } lastblock = ufs_fragstoblks (lastfrag); @@ -319,7 +316,7 @@ block = ufs_fragstoblks (fragment); blockoff = ufs_fragnum (fragment); - UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u\n", inode->i_ino, fragment, new_fragment)) + UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u\n", inode->i_ino, fragment, new_fragment)) result = NULL; if (!bh) @@ -350,14 +347,12 @@ *err = -EFBIG; { - unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit < RLIM_INFINITY) { - limit >>= sb->s_blocksize_bits; - if (new_fragment >= limit) { - brelse (bh); - send_sig(SIGXFSZ, current, 0); - return NULL; - } + unsigned long limit = (current->rlimfsz.rlim_cur >> sb->s_blocksize_bits); + /* Infinity for this is rather 'large', even shifted down. */ + if (new_fragment >= limit) { + brelse (bh); + send_sig(SIGXFSZ, current, 0); + return NULL; } } if (block && (tmp = SWAB32(((u32*)bh->b_data)[block-1]) + uspi->s_fpb)) @@ -591,13 +586,11 @@ } /* - * 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 = inode->u.ufs_i.i_size; inode->i_atime = SWAB32(ufs_inode->ui_atime.tv_sec); inode->i_ctime = SWAB32(ufs_inode->ui_ctime.tv_sec); @@ -610,7 +603,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)) ; diff -ur linux-23026base/fs/ufs/super.c linux-23026m1/fs/ufs/super.c --- linux-23026base/fs/ufs/super.c Fri Aug 27 00:18:06 1999 +++ linux-23026m1/fs/ufs/super.c Mon Nov 8 20:32:59 1999 @@ -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; @@ -892,28 +892,27 @@ return 0; } -int ufs_statfs (struct super_block * sb, struct statfs * buf, int bufsiz) +int ufs_statvfs (struct super_block * sb, struct statvfs64 * buf) { struct ufs_sb_private_info * uspi; struct ufs_super_block_first * usb1; - struct statfs tmp; unsigned swab; swab = sb->u.ufs_sb.s_swab; uspi = sb->u.ufs_sb.s_uspi; usb1 = ubh_get_usb_first (USPI_UBH); - tmp.f_type = UFS_MAGIC; - tmp.f_bsize = sb->s_blocksize; - tmp.f_blocks = uspi->s_dsize; - tmp.f_bfree = ufs_blkstofrags(SWAB32(usb1->fs_cstotal.cs_nbfree)) + + buf->f_type = UFS_MAGIC; + buf->f_bsize = sb->s_blocksize; + buf->f_blocks = uspi->s_dsize; + buf->f_bfree = ufs_blkstofrags(SWAB32(usb1->fs_cstotal.cs_nbfree)) + SWAB32(usb1->fs_cstotal.cs_nffree); - tmp.f_bavail = (tmp.f_bfree > ((tmp.f_blocks / 100) * uspi->s_minfree)) - ? (tmp.f_bfree - ((tmp.f_blocks / 100) * uspi->s_minfree)) : 0; - tmp.f_files = uspi->s_ncg * uspi->s_ipg; - tmp.f_ffree = SWAB32(usb1->fs_cstotal.cs_nifree); - tmp.f_namelen = UFS_MAXNAMLEN; - return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; + buf->f_bavail = (buf->f_bfree > (((u_long)buf->f_blocks / 100) * uspi->s_minfree)) + ? (buf->f_bfree - (((u_long)buf->f_blocks / 100) * uspi->s_minfree)) : 0; + buf->f_files = uspi->s_ncg * uspi->s_ipg; + buf->f_ffree = SWAB32(usb1->fs_cstotal.cs_nifree); + buf->f_namelen = UFS_MAXNAMLEN; + return 0; } static struct super_operations ufs_super_ops = { @@ -924,7 +923,7 @@ NULL, /* notify_change() */ ufs_put_super, ufs_write_super, - ufs_statfs, + ufs_statvfs, ufs_remount }; diff -ur linux-23026base/fs/ufs/symlink.c linux-23026m1/fs/ufs/symlink.c --- linux-23026base/fs/ufs/symlink.c Sun Jun 27 20:10:41 1999 +++ linux-23026m1/fs/ufs/symlink.c Mon Nov 8 04:20:44 1999 @@ -116,6 +116,8 @@ return i; } +extern int ufs_pathconf(struct inode *, int); + struct inode_operations ufs_symlink_inode_operations = { NULL, /* no file-operations */ NULL, /* create */ @@ -136,5 +138,6 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + ufs_pathconf, /* pathconf */ }; diff -ur linux-23026base/fs/ufs/truncate.c linux-23026m1/fs/ufs/truncate.c --- linux-23026base/fs/ufs/truncate.c Wed Aug 18 20:15:19 1999 +++ linux-23026m1/fs/ufs/truncate.c Mon Nov 8 04:26:51 1999 @@ -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) #define DATA_BUFFER_USED(bh) \ (atomic_read(&bh->b_count) || buffer_locked(bh)) @@ -312,7 +312,7 @@ uspi = sb->u.ufs_sb.s_uspi; dindirect_block = (DIRECT_BLOCK > offset) - ? ((DIRECT_BLOCK - offset) / uspi->s_apb) : 0; + ? ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0; retry = 0; tmp = SWAB32(*p); @@ -382,7 +382,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; @@ -471,7 +471,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 -ur linux-23026base/fs/ufs/util.h linux-23026m1/fs/ufs/util.h --- linux-23026base/fs/ufs/util.h Mon Nov 8 17:28:13 1999 +++ linux-23026m1/fs/ufs/util.h Mon Nov 8 19:21:40 1999 @@ -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 -ur linux-23026base/fs/umsdos/dir.c linux-23026m1/fs/umsdos/dir.c --- linux-23026base/fs/umsdos/dir.c Mon Aug 9 21:43:49 1999 +++ linux-23026m1/fs/umsdos/dir.c Mon Nov 8 12:41:33 1999 @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -801,6 +802,32 @@ goto out_free; } + +static int umsdos_pathconf(struct inode *inode, int option) +{ + switch (option) { + case _PC_NAME_MAX: /* POSIX.1: Directory only */ + return 256; /* name component max length */ + case _PC_NO_TRUNC: + return 1; /* Semantics ??? */ + + case _PC_FILESIZEBITS: /* LFS: Regular files, and dirs */ + return 32; + + case _PC_LINK_MAX: /* POSIX.1: regular files and dirs */ + return 1; + + case _PC_CHOWN_RESTRICTED: /* POSIX.1: Any file, any dir */ + break; /* FIXME: some mount-option ??? */ + + case _PC_SYNC_IO: /* POSIX.4: Regular files only ? */ + case _PC_ASYNC_IO: /* TTY only ?? */ + break; + default: + break; + } + return -EINVAL; /* Unknown thing! */ +} static struct file_operations umsdos_dir_operations = { @@ -839,4 +866,5 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* revalidate */ + umsdos_pathconf, /* pathconf */ }; diff -ur linux-23026base/fs/umsdos/inode.c linux-23026m1/fs/umsdos/inode.c --- linux-23026base/fs/umsdos/inode.c Fri Aug 27 00:18:06 1999 +++ linux-23026m1/fs/umsdos/inode.c Mon Nov 8 11:37:38 1999 @@ -309,7 +309,7 @@ UMSDOS_notify_change, /* notify_change */ UMSDOS_put_super, /* put_super */ NULL, /* write_super */ - fat_statfs, /* statfs */ + fat_statvfs, /* statvfs */ NULL, /* remount_fs */ fat_clear_inode, /* clear_inode */ }; diff -ur linux-23026base/fs/vfat/namei.c linux-23026m1/fs/vfat/namei.c --- linux-23026base/fs/vfat/namei.c Mon Aug 9 21:43:49 1999 +++ linux-23026m1/fs/vfat/namei.c Mon Nov 8 12:42:40 1999 @@ -23,6 +23,7 @@ #include #include #include +#include #include "../fat/msbuffer.h" @@ -1187,6 +1188,31 @@ } +static int vfat_pathconf(struct inode *inode, int option) +{ + switch (option) { + case _PC_NAME_MAX: /* POSIX.1: Directory only */ + return 256; /* name component max length */ + case _PC_NO_TRUNC: + return 1; /* Semantics ??? */ + + case _PC_FILESIZEBITS: /* LFS: Regular files, and dirs */ + return 32; + + case _PC_LINK_MAX: /* POSIX.1: regular files and dirs */ + return 1; + + case _PC_CHOWN_RESTRICTED: /* POSIX.1: Any file, any dir */ + break; /* FIXME: some mount-option ??? */ + + case _PC_SYNC_IO: /* POSIX.4: Regular files only ? */ + case _PC_ASYNC_IO: /* TTY only ?? */ + break; + default: + break; + } + return -EINVAL; /* Unknown thing! */ +} /* Public inode operations for the VFAT fs */ struct inode_operations vfat_dir_inode_operations = { @@ -1209,7 +1235,8 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ - NULL /* revalidate */ + NULL, /* revalidate */ + vfat_pathconf, /* pathconf */ }; struct super_block *vfat_read_super(struct super_block *sb,void *data, diff -ur linux-23026base/include/asm-alpha/fcntl.h linux-23026m1/include/asm-alpha/fcntl.h --- linux-23026base/include/asm-alpha/fcntl.h Wed Oct 21 20:02:48 1998 +++ linux-23026m1/include/asm-alpha/fcntl.h Sun Nov 7 19:41:56 1999 @@ -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 /* 64-bit offsets ok -- default at Alpha */ #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ @@ -35,6 +36,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 +65,14 @@ __kernel_off_t l_start; __kernel_off_t l_len; __kernel_pid_t l_pid; +}; + +struct flock64 { + int l_type; + int l_whence; + off64_t l_start; + off64_t l_len; + int l_pid; }; #endif diff -ur linux-23026base/include/asm-alpha/posix_types.h linux-23026m1/include/asm-alpha/posix_types.h --- linux-23026base/include/asm-alpha/posix_types.h Fri Aug 21 16:33:36 1998 +++ linux-23026m1/include/asm-alpha/posix_types.h Sun Nov 7 19:43:22 1999 @@ -9,9 +9,11 @@ typedef unsigned int __kernel_dev_t; typedef unsigned int __kernel_ino_t; +typedef unsigned long __kernel_ino64_t; typedef unsigned int __kernel_mode_t; typedef unsigned int __kernel_nlink_t; typedef long __kernel_off_t; +typedef long __kernel_off64_t; typedef int __kernel_pid_t; typedef int __kernel_ipc_pid_t; typedef unsigned int __kernel_uid_t; diff -ur linux-23026base/include/asm-alpha/statfs.h linux-23026m1/include/asm-alpha/statfs.h --- linux-23026base/include/asm-alpha/statfs.h Sun Aug 18 10:42:02 1996 +++ linux-23026m1/include/asm-alpha/statfs.h Sun Nov 7 19:49:27 1999 @@ -22,4 +22,17 @@ int f_spare[6]; }; +struct statvfs64 { + int f_type; + int f_bsize; + __u64 f_blocks; + __u64 f_bfree; + __u64 f_bavail; + __u64 f_files; + __u64 f_ffree; + __kernel_fsid_t f_fsid; + int f_namelen; + int f_spare[6]; +}; + #endif diff -ur linux-23026base/include/asm-arm/fcntl.h linux-23026m1/include/asm-arm/fcntl.h --- linux-23026base/include/asm-arm/fcntl.h Wed Oct 21 23:30:46 1998 +++ linux-23026m1/include/asm-arm/fcntl.h Sun Nov 7 19:51:47 1999 @@ -18,6 +18,7 @@ #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 /* file sizes exceeding 32-bit signed value */ #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ @@ -33,6 +34,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 +63,14 @@ off_t l_start; off_t l_len; pid_t l_pid; +}; + +struct flock64 { + int l_type; + int l_whence; + loff_t l_start; + loff_t l_len; + int l_pid; }; #endif diff -ur linux-23026base/include/asm-arm/posix_types.h linux-23026m1/include/asm-arm/posix_types.h --- linux-23026base/include/asm-arm/posix_types.h Sat May 8 21:06:57 1999 +++ linux-23026m1/include/asm-arm/posix_types.h Sun Nov 7 19:52:35 1999 @@ -17,9 +17,11 @@ typedef unsigned short __kernel_dev_t; typedef unsigned long __kernel_ino_t; +typedef unsigned long long __kernel_ino64_t; typedef unsigned short __kernel_mode_t; typedef unsigned short __kernel_nlink_t; typedef long __kernel_off_t; +typedef long long __kernel_off64_t; typedef int __kernel_pid_t; typedef unsigned short __kernel_ipc_pid_t; typedef unsigned short __kernel_uid_t; diff -ur linux-23026base/include/asm-arm/statfs.h linux-23026m1/include/asm-arm/statfs.h --- linux-23026base/include/asm-arm/statfs.h Wed Jan 21 02:39:43 1998 +++ linux-23026m1/include/asm-arm/statfs.h Sun Nov 7 19:54:17 1999 @@ -22,4 +22,17 @@ long f_spare[6]; }; +struct statvfs64 { + __u32 f_type; + __u32 f_bsize; + __u64 f_blocks; + __u64 f_bfree; + __u64 f_bavail; + __u64 f_files; + __u64 f_ffree; + __kernel_fsid_t f_fsid; + int f_namelen; + int f_spare[6]; +}; + #endif diff -ur linux-23026base/include/asm-i386/fcntl.h linux-23026m1/include/asm-i386/fcntl.h --- linux-23026base/include/asm-i386/fcntl.h Wed Oct 21 20:02:48 1998 +++ linux-23026m1/include/asm-i386/fcntl.h Sun Nov 7 19:55:02 1999 @@ -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 { + int l_type; + int l_whence; + loff_t l_start; + loff_t l_len; + int l_pid; }; #endif diff -ur linux-23026base/include/asm-i386/posix_types.h linux-23026m1/include/asm-i386/posix_types.h --- linux-23026base/include/asm-i386/posix_types.h Sun Dec 27 20:39:50 1998 +++ linux-23026m1/include/asm-i386/posix_types.h Sun Nov 7 19:57:40 1999 @@ -9,9 +9,11 @@ typedef unsigned short __kernel_dev_t; typedef unsigned long __kernel_ino_t; +typedef unsigned long long __kernel_ino64_t; typedef unsigned short __kernel_mode_t; typedef unsigned short __kernel_nlink_t; typedef long __kernel_off_t; +typedef long long __kernel_off64_t; typedef int __kernel_pid_t; typedef unsigned short __kernel_ipc_pid_t; typedef unsigned short __kernel_uid_t; diff -ur linux-23026base/include/asm-i386/statfs.h linux-23026m1/include/asm-i386/statfs.h --- linux-23026base/include/asm-i386/statfs.h Mon Nov 8 14:11:09 1999 +++ linux-23026m1/include/asm-i386/statfs.h Mon Nov 8 04:42:28 1999 @@ -22,4 +22,17 @@ long f_spare[6]; }; +struct statvfs64 { + __u32 f_type; + __u32 f_bsize; + __u64 f_blocks; + __u64 f_bfree; + __u64 f_bavail; + __u64 f_files; + __u64 f_ffree; + __kernel_fsid_t f_fsid; + int f_namelen; + int f_spare[6]; +}; + #endif diff -ur linux-23026base/include/asm-m68k/fcntl.h linux-23026m1/include/asm-m68k/fcntl.h --- linux-23026base/include/asm-m68k/fcntl.h Wed Oct 21 23:30:56 1998 +++ linux-23026m1/include/asm-m68k/fcntl.h Sun Nov 7 19:59:07 1999 @@ -18,6 +18,7 @@ #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 /* file sizes exceeding 32-bit signed value */ #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ @@ -33,6 +34,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 +63,14 @@ off_t l_start; off_t l_len; pid_t l_pid; +}; + +struct flock64 { + int l_type; + int l_whence; + loff_t l_start; + loff_t l_len; + int l_pid; }; #endif /* _M68K_FCNTL_H */ diff -ur linux-23026base/include/asm-m68k/posix_types.h linux-23026m1/include/asm-m68k/posix_types.h --- linux-23026base/include/asm-m68k/posix_types.h Mon Aug 10 21:02:24 1998 +++ linux-23026m1/include/asm-m68k/posix_types.h Sun Nov 7 19:59:34 1999 @@ -9,9 +9,11 @@ typedef unsigned short __kernel_dev_t; typedef unsigned long __kernel_ino_t; +typedef unsigned long long __kernel_ino64_t; typedef unsigned short __kernel_mode_t; typedef unsigned short __kernel_nlink_t; typedef long __kernel_off_t; +typedef long long __kernel_off64_t; typedef int __kernel_pid_t; typedef unsigned short __kernel_ipc_pid_t; typedef unsigned short __kernel_uid_t; diff -ur linux-23026base/include/asm-m68k/statfs.h linux-23026m1/include/asm-m68k/statfs.h --- linux-23026base/include/asm-m68k/statfs.h Mon Jun 3 10:09:13 1996 +++ linux-23026m1/include/asm-m68k/statfs.h Sun Nov 7 19:59:54 1999 @@ -22,4 +22,17 @@ long f_spare[6]; }; +struct statvfs64 { + __u32 f_type; + __u32 f_bsize; + __u64 f_blocks; + __u64 f_bfree; + __u64 f_bavail; + __u64 f_files; + __u64 f_ffree; + __kernel_fsid_t f_fsid; + int f_namelen; + int f_spare[6]; +}; + #endif /* _M68K_STATFS_H */ diff -ur linux-23026base/include/asm-mips/fcntl.h linux-23026m1/include/asm-mips/fcntl.h --- linux-23026base/include/asm-mips/fcntl.h Sat Jun 26 03:37:53 1999 +++ linux-23026m1/include/asm-mips/fcntl.h Sun Nov 7 20:00:50 1999 @@ -44,6 +44,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 */ @@ -72,5 +76,15 @@ __kernel_pid_t l_pid; long pad[4]; /* ZZZZZZZZZZZZZZZZZZZZZZZZZZ */ } flock_t; + +typedef struct flock64 { + int l_type; + int l_whence; + __kernel_loff_t l_start; + __kernel_loff_t l_len; + long l_sysid; /* XXXXXXXXXXXXXXXXXXXXXXXXX */ + __kernel_pid_t l_pid; + long pad[4]; /* ZZZZZZZZZZZZZZZZZZZZZZZZZZ */ +} flock64_t; #endif /* __ASM_MIPS_FCNTL_H */ diff -ur linux-23026base/include/asm-mips/posix_types.h linux-23026m1/include/asm-mips/posix_types.h --- linux-23026base/include/asm-mips/posix_types.h Tue Oct 20 23:52:53 1998 +++ linux-23026m1/include/asm-mips/posix_types.h Sun Nov 7 20:01:43 1999 @@ -38,6 +38,8 @@ typedef char * __kernel_caddr_t; #ifdef __GNUC__ +typedef unsigned long long __kernel_ino64_t; +typedef long long __kernel_off64_t; typedef long long __kernel_loff_t; #endif diff -ur linux-23026base/include/asm-mips/statfs.h linux-23026m1/include/asm-mips/statfs.h --- linux-23026base/include/asm-mips/statfs.h Thu Jun 26 22:33:40 1997 +++ linux-23026m1/include/asm-mips/statfs.h Sun Nov 7 20:02:26 1999 @@ -37,4 +37,21 @@ long f_spare[6]; }; +struct statvfs64 { + long f_type; +#define f_fstyp f_type + long f_bsize; + __u64 f_frsize; /* Fragment size - fs specific */ + __u64 f_blocks; + __u64 f_bfree; + __u64 f_files; + __u64 f_ffree; + + /* Linux specials */ + __u64 f_bavail; + __kernel_fsid_t f_fsid; + long f_namelen; + long f_spare[6]; +}; + #endif /* __ASM_MIPS_STATFS_H */ diff -ur linux-23026base/include/asm-ppc/fcntl.h linux-23026m1/include/asm-ppc/fcntl.h --- linux-23026base/include/asm-ppc/fcntl.h Wed Oct 21 23:31:06 1998 +++ linux-23026m1/include/asm-ppc/fcntl.h Sun Nov 7 20:03:39 1999 @@ -18,6 +18,7 @@ #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 /* file sizes exceeding 'off_t' */ #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ @@ -33,6 +34,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 +69,14 @@ off_t l_start; off_t l_len; pid_t l_pid; +}; + +struct flock64 { + int l_type; + int l_whence; + loff_t l_start; + loff_t l_len; + int l_pid; }; #endif diff -ur linux-23026base/include/asm-ppc/posix_types.h linux-23026m1/include/asm-ppc/posix_types.h --- linux-23026base/include/asm-ppc/posix_types.h Thu Apr 29 22:39:01 1999 +++ linux-23026m1/include/asm-ppc/posix_types.h Sun Nov 7 20:04:08 1999 @@ -26,6 +26,8 @@ typedef short __kernel_ipc_pid_t; #ifdef __GNUC__ +typedef unsigned long long __kernel_ino64_t; +typedef long long __kernel_off64_t; typedef long long __kernel_loff_t; #endif diff -ur linux-23026base/include/asm-ppc/statfs.h linux-23026m1/include/asm-ppc/statfs.h --- linux-23026base/include/asm-ppc/statfs.h Mon Jun 3 10:09:13 1996 +++ linux-23026m1/include/asm-ppc/statfs.h Sun Nov 7 20:04:37 1999 @@ -22,7 +22,17 @@ long f_spare[6]; }; -#endif - - +struct statvfs64 { + long f_type; + long f_bsize; + __u64 f_blocks; + __u64 f_bfree; + __u64 f_bavail; + __u64 f_files; + __u64 f_ffree; + __kernel_fsid_t f_fsid; + long f_namelen; + long f_spare[6]; +}; +#endif diff -ur linux-23026base/include/asm-sparc/fcntl.h linux-23026m1/include/asm-sparc/fcntl.h --- linux-23026base/include/asm-sparc/fcntl.h Tue Oct 27 19:52:21 1998 +++ linux-23026m1/include/asm-sparc/fcntl.h Sun Nov 7 20:05:47 1999 @@ -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 /* file sizes exceeding 'off_t' range (2G) */ #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ @@ -33,6 +34,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 */ @@ -59,6 +64,14 @@ off_t l_len; pid_t l_pid; short __unused; +}; + +struct flock64 { + int l_type; + int l_whence; + loff_t l_start; + loff_t l_len; + int l_pid; }; #endif diff -ur linux-23026base/include/asm-sparc/posix_types.h linux-23026m1/include/asm-sparc/posix_types.h --- linux-23026base/include/asm-sparc/posix_types.h Thu Mar 11 02:53:37 1999 +++ linux-23026m1/include/asm-sparc/posix_types.h Sun Nov 7 20:06:42 1999 @@ -33,6 +33,8 @@ typedef char * __kernel_caddr_t; #ifdef __GNUC__ +typedef unsigned long long __kernel_ino64_t; +typedef long long __kernel_off64_t; typedef long long __kernel_loff_t; #endif diff -ur linux-23026base/include/asm-sparc/statfs.h linux-23026m1/include/asm-sparc/statfs.h --- linux-23026base/include/asm-sparc/statfs.h Sat Nov 9 21:39:33 1996 +++ linux-23026m1/include/asm-sparc/statfs.h Sun Nov 7 20:07:03 1999 @@ -23,4 +23,17 @@ long f_spare[6]; }; +struct statvfs64 { + long f_type; + long f_bsize; + __u64 f_blocks; + __u64 f_bfree; + __u64 f_bavail; + __u64 f_files; + __u64 f_ffree; + __kernel_fsid_t f_fsid; + long f_namelen; /* SunOS ignores this field. */ + long f_spare[6]; +}; + #endif diff -ur linux-23026base/include/asm-sparc64/fcntl.h linux-23026m1/include/asm-sparc64/fcntl.h --- linux-23026base/include/asm-sparc64/fcntl.h Tue Oct 27 19:52:21 1998 +++ linux-23026m1/include/asm-sparc64/fcntl.h Sun Nov 7 20:07:49 1999 @@ -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 /* file sizes exceeding 'off_t' range (2G) */ #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ @@ -33,6 +34,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 */ @@ -71,5 +76,13 @@ short __unused; }; #endif + +struct flock64 { + int l_type; + int l_whence; + loff_t l_start; + loff_t l_len; + int l_pid; +}; #endif /* !(_SPARC64_FCNTL_H) */ diff -ur linux-23026base/include/asm-sparc64/posix_types.h linux-23026m1/include/asm-sparc64/posix_types.h --- linux-23026base/include/asm-sparc64/posix_types.h Thu Mar 11 02:53:38 1999 +++ linux-23026m1/include/asm-sparc64/posix_types.h Sun Nov 7 20:08:35 1999 @@ -34,6 +34,8 @@ typedef int __kernel_suseconds_t; #ifdef __GNUC__ +typedef unsigned long __kernel_ino64_t; +typedef long __kernel_off64_t; typedef long long __kernel_loff_t; #endif diff -ur linux-23026base/include/asm-sparc64/statfs.h linux-23026m1/include/asm-sparc64/statfs.h --- linux-23026base/include/asm-sparc64/statfs.h Thu Apr 24 05:01:28 1997 +++ linux-23026m1/include/asm-sparc64/statfs.h Sun Nov 7 20:08:57 1999 @@ -36,4 +36,17 @@ long f_spare[6]; }; +struct statvfs64 { + long f_type; + long f_bsize; + __u64 f_blocks; + __u64 f_bfree; + __u64 f_bavail; + __u64 f_files; + __u64 f_ffree; + __kernel_fsid_t f_fsid; + long f_namelen; + long f_spare[6]; +}; + #endif diff -ur linux-23026base/include/linux/coda_psdev.h linux-23026m1/include/linux/coda_psdev.h --- linux-23026base/include/linux/coda_psdev.h Wed Jul 7 05:08:33 1999 +++ linux-23026m1/include/linux/coda_psdev.h Mon Nov 8 00:47:39 1999 @@ -80,7 +80,7 @@ unsigned int cmd, struct PioctlData *data); int coda_downcall(int opcode, union outputArgs *out, struct super_block *sb); int venus_fsync(struct super_block *sb, struct ViceFid *fid); -int venus_statfs(struct super_block *sb, struct statfs *sfs); +int venus_statvfs(struct super_block *sb, struct statvfs64 *sfs); /* messages between coda filesystem in kernel and Venus */ diff -ur linux-23026base/include/linux/dirent.h linux-23026m1/include/linux/dirent.h --- linux-23026base/include/linux/dirent.h Wed Jul 10 07:38:08 1996 +++ linux-23026m1/include/linux/dirent.h Sun Nov 7 20:15:23 1999 @@ -8,4 +8,13 @@ char d_name[256]; /* We must not include limits.h! */ }; +struct dirent64 { + __u64 d_ino; /* 64 bits *should* be enough */ + __u32 d_off; /* position within directory */ + __u32 d_flags; /* what is stored in d_data[] */ + __u32 d_data[8]; /* for future extensions */ + __u16 d_reclen; + char d_name[256]; /* We must not include limits.h! */ +}; + #endif diff -ur linux-23026base/include/linux/ext2_fs.h linux-23026m1/include/linux/ext2_fs.h --- linux-23026base/include/linux/ext2_fs.h Mon Nov 8 14:11:09 1999 +++ linux-23026m1/include/linux/ext2_fs.h Mon Nov 8 04:52:32 1999 @@ -598,7 +598,7 @@ extern int ext2_remount (struct super_block *, int *, char *); extern struct super_block * ext2_read_super (struct super_block *,void *,int); extern int init_ext2_fs(void); -extern int ext2_statfs (struct super_block *, struct statfs *, int); +extern int ext2_statvfs (struct super_block *, struct statvfs64 *); /* truncate.c */ extern void ext2_truncate (struct inode *); diff -ur linux-23026base/include/linux/fat_cvf.h linux-23026m1/include/linux/fat_cvf.h --- linux-23026base/include/linux/fat_cvf.h Mon Aug 9 21:43:49 1999 +++ linux-23026m1/include/linux/fat_cvf.h Mon Nov 8 05:02:37 1999 @@ -25,7 +25,7 @@ int nbreq, struct buffer_head *bh[32]); int (*fat_access) (struct super_block *sb,int nr,int new_value); - int (*cvf_statfs) (struct super_block *sb,struct statfs *buf, int bufsiz); + int (*cvf_statvfs) (struct super_block *sb,struct statvfs64 *buf); int (*cvf_bmap) (struct inode *inode,int block); ssize_t (*cvf_file_read) ( struct file *, char *, size_t, loff_t *); ssize_t (*cvf_file_write) ( struct file *, const char *, size_t, loff_t *); diff -ur linux-23026base/include/linux/fs.h linux-23026m1/include/linux/fs.h --- linux-23026base/include/linux/fs.h Mon Nov 8 14:11:15 1999 +++ linux-23026m1/include/linux/fs.h Mon Nov 8 18:53:44 1999 @@ -249,6 +249,16 @@ #define buffer_page(bh) (mem_map + MAP_NR((bh)->b_data)) #define touch_buffer(bh) set_bit(PG_referenced, &buffer_page(bh)->flags) +static int off_t_presentable(loff_t) __attribute__ ((const)); +static __inline__ int off_t_presentable(loff_t loff) +{ +#if BITS_PER_LONG < 64 + return (loff <= (loff_t)LONG_MAX); +#else + return 1; +#endif +} + #include #include #include @@ -426,7 +436,25 @@ unsigned int f_flags; mode_t f_mode; loff_t f_pos; - unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin; + +/* + * Read-ahead context: + * ------------------- + * The read ahead context fields of the "struct file" are the following: + * - f_raend : index of the last+1 page after attempted read-ahead. + * - f_ramax : current read-ahead maximum size. + * - f_ralen : length of the current IO read block we tried to read-ahead. + * - f_rawin : length of the current read-ahead window. + * + * For more info, see mm/filemap.c + */ + int f_reada; /* bool */ /* all around */ + /* following u_long could be done with u_int as well, and + have slightly smaller 'struct file' for 64-bit machines. + Presuming, of course, that we stay under 2 GB read-ahead ... */ + u_int f_ramax, f_ralen, f_rawin; /* mm/filemap.c */ + u_long f_raend; /* mm/filemap.c */ + struct fown_struct f_owner; unsigned int f_uid, f_gid; int f_error; @@ -472,8 +500,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 */ @@ -489,6 +517,9 @@ extern int fcntl_getlk(unsigned int, struct flock *); extern int fcntl_setlk(unsigned int, unsigned int, struct flock *); +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); extern void locks_remove_flock(struct file *); @@ -653,6 +684,7 @@ int (*permission) (struct inode *, int); int (*smap) (struct inode *,int); int (*revalidate) (struct dentry *); + int (*pathconf) (struct inode *, int option); }; struct super_operations { @@ -663,7 +695,7 @@ int (*notify_change) (struct dentry *, struct iattr *); void (*put_super) (struct super_block *); void (*write_super) (struct super_block *); - int (*statfs) (struct super_block *, struct statfs *, int); + int (*statvfs) (struct super_block *, struct statvfs64 *); int (*remount_fs) (struct super_block *, int *, char *); void (*clear_inode) (struct inode *); void (*umount_begin) (struct super_block *); @@ -728,8 +760,8 @@ asmlinkage long sys_open(const char *, int, int); asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */ -extern int do_close(unsigned int, int); /* yes, it's really unsigned */ -extern int do_truncate(struct dentry *, unsigned long); +extern long do_close(unsigned int, int); /* yes, it's really unsigned */ +extern long do_truncate(struct dentry *, loff_t); extern int get_unused_fd(void); extern void put_unused_fd(unsigned int); @@ -976,7 +1008,7 @@ extern int block_fsync(struct file *, struct dentry *); extern int file_fsync(struct file *, struct dentry *); -extern int generic_buffer_fdatasync(struct inode *inode, unsigned long start, unsigned long end); +extern int generic_buffer_fdatasync(struct inode *inode, loff_t start, loff_t end); extern int inode_change_ok(struct inode *, struct iattr *); extern void inode_setattr(struct inode *, struct iattr *); diff -ur linux-23026base/include/linux/mm.h linux-23026m1/include/linux/mm.h --- linux-23026base/include/linux/mm.h Mon Nov 8 14:11:15 1999 +++ linux-23026m1/include/linux/mm.h Mon Nov 8 20:07:00 1999 @@ -324,7 +324,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); extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write); @@ -351,7 +351,7 @@ 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); + unsigned long, unsigned long, loff_t); extern int do_munmap(unsigned long, size_t); extern unsigned long do_brk(unsigned long, unsigned long); @@ -359,7 +359,7 @@ 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 void truncate_inode_pages(struct inode *, loff_t); extern void put_cached_page(unsigned long); /* diff -ur linux-23026base/include/linux/msdos_fs.h linux-23026m1/include/linux/msdos_fs.h --- linux-23026base/include/linux/msdos_fs.h Mon Nov 8 14:14:22 1999 +++ linux-23026m1/include/linux/msdos_fs.h Mon Nov 8 20:23:41 1999 @@ -247,7 +247,7 @@ extern struct inode *fat_build_inode(struct super_block*,struct msdos_dir_entry*,int,int*); extern struct super_block *fat_read_super(struct super_block *s, void *data, int silent, struct inode_operations *dir_ops); extern void msdos_put_super(struct super_block *sb); -extern int fat_statfs(struct super_block *sb,struct statfs *buf, int); +extern int fat_statvfs(struct super_block *sb,struct statvfs64 *buf); extern void fat_write_inode(struct inode *inode); /* dir.c */ @@ -270,6 +270,7 @@ extern ssize_t fat_file_read(struct file *, char *, size_t, loff_t *); extern ssize_t fat_file_write(struct file *, const char *, size_t, loff_t *); extern void fat_truncate(struct inode *inode); +extern int fat_pathconf(struct inode *, int); /* mmap.c */ extern int fat_mmap(struct file *, struct vm_area_struct *); diff -ur linux-23026base/include/linux/nfs.h linux-23026m1/include/linux/nfs.h --- linux-23026base/include/linux/nfs.h Mon Oct 18 21:26:37 1999 +++ linux-23026m1/include/linux/nfs.h Sun Nov 7 20:32:46 1999 @@ -111,7 +111,7 @@ __u32 nlink; __u32 uid; __u32 gid; - __u32 size; + __u64 size; __u32 blocksize; __u32 rdev; __u32 blocks; @@ -132,7 +132,7 @@ struct nfs_writeargs { struct nfs_fh * fh; - __u32 offset; + __u64 offset; __u32 count; const void * buffer; }; @@ -156,7 +156,7 @@ struct nfs_readargs { struct nfs_fh * fh; - __u32 offset; + __u64 offset; __u32 count; void * buffer; }; diff -ur linux-23026base/include/linux/nfs_fs.h linux-23026m1/include/linux/nfs_fs.h --- linux-23026base/include/linux/nfs_fs.h Mon Nov 8 14:11:45 1999 +++ linux-23026m1/include/linux/nfs_fs.h Mon Nov 8 20:10:48 1999 @@ -145,10 +145,10 @@ const char *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr); extern int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle, - int swap, unsigned long offset, unsigned int count, + int swap, loff_t offset, unsigned int count, void *buffer, struct nfs_fattr *fattr); extern int nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle, - int swap, unsigned long offset, unsigned int count, + int swap, loff_t offset, unsigned int count, const void *buffer, struct nfs_fattr *fattr); extern int nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir, const char *name, struct iattr *sattr, @@ -168,7 +168,7 @@ struct nfs_fh *fhandle, struct nfs_fattr *fattr); extern int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir, const char *name); -extern int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, +extern int nfs_proc_statvfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *res); diff -ur linux-23026base/include/linux/nfsd/nfsd.h linux-23026m1/include/linux/nfsd/nfsd.h --- linux-23026base/include/linux/nfsd/nfsd.h Mon Nov 8 14:13:05 1999 +++ linux-23026m1/include/linux/nfsd/nfsd.h Mon Nov 8 18:58:56 1999 @@ -105,8 +105,8 @@ int nfsd_readdir(struct svc_rqst *, struct svc_fh *, loff_t, encode_dent_fn, u32 *buffer, int *countp); -int nfsd_statfs(struct svc_rqst *, struct svc_fh *, - struct statfs *); +int nfsd_statvfs(struct svc_rqst *, struct svc_fh *, + struct statvfs64 *); int nfsd_notify_change(struct inode *, struct iattr *); int nfsd_permission(struct svc_export *, struct dentry *, int); diff -ur linux-23026base/include/linux/nfsd/xdr.h linux-23026m1/include/linux/nfsd/xdr.h --- linux-23026base/include/linux/nfsd/xdr.h Mon Nov 8 14:13:05 1999 +++ linux-23026m1/include/linux/nfsd/xdr.h Mon Nov 8 18:58:56 1999 @@ -101,7 +101,7 @@ }; struct nfsd_statfsres { - struct statfs stats; + struct statvfs64 stats; }; /* diff -ur linux-23026base/include/linux/nfsd/xdr3.h linux-23026m1/include/linux/nfsd/xdr3.h --- linux-23026base/include/linux/nfsd/xdr3.h Mon Apr 7 21:35:32 1997 +++ linux-23026m1/include/linux/nfsd/xdr3.h Sun Nov 7 20:39:40 1999 @@ -163,7 +163,7 @@ struct nfsd3_statfsres { __u32 status; - struct statfs stats; + struct statvfs64 stats; __u32 invarsec; }; diff -ur linux-23026base/include/linux/proc_fs.h linux-23026m1/include/linux/proc_fs.h --- linux-23026base/include/linux/proc_fs.h Mon Nov 8 14:11:18 1999 +++ linux-23026m1/include/linux/proc_fs.h Mon Nov 8 20:07:02 1999 @@ -289,7 +289,7 @@ extern struct super_block *proc_read_super(struct super_block *,void *,int); extern int init_proc_fs(void); extern struct inode * proc_get_inode(struct super_block *, int, struct proc_dir_entry *); -extern int proc_statfs(struct super_block *, struct statfs *, int); +extern int proc_statvfs(struct super_block *, struct statvfs64 *); extern void proc_read_inode(struct inode *); extern void proc_write_inode(struct inode *); extern int proc_permission(struct inode *, int); diff -ur linux-23026base/include/linux/resource.h linux-23026m1/include/linux/resource.h --- linux-23026base/include/linux/resource.h Mon Nov 8 14:11:09 1999 +++ linux-23026m1/include/linux/resource.h Mon Nov 8 20:06:54 1999 @@ -43,11 +43,26 @@ * Which makes a ton more sense anyway. */ #define RLIM_INFINITY (~0UL) +#define RLIM_SAVED_MAX ((~0UL)-1UL) +#define RLIM_SAVED_CUR ((~0UL)-2UL) + +/* We compare against SIGNED 64-bit loff_t, better to limit ourself + to 2^63-1, which is rather high value anyway... */ +#define RLIM64_INFINITY ((long long)((~0ULL) >> 1)) +#define RLIM64_SAVED_MAX RLIM64_INFINITY +#define RLIM64_SAVED_CUR RLIM64_INFINITY struct rlimit { unsigned long rlim_cur; unsigned long rlim_max; }; + +struct rlimit64 { + __u64 rlim_cur; + __u64 rlim_max; +}; + +#define INIT_RLIMFSZ { RLIM64_INFINITY, RLIM64_INFINITY } #define PRIO_MIN (-20) #define PRIO_MAX 20 diff -ur linux-23026base/include/linux/sched.h linux-23026m1/include/linux/sched.h --- linux-23026base/include/linux/sched.h Mon Nov 8 14:11:15 1999 +++ linux-23026m1/include/linux/sched.h Mon Nov 8 20:07:00 1999 @@ -332,6 +332,7 @@ struct user_struct *user; /* limits */ struct rlimit rlim[RLIM_NLIMITS]; + struct rlimit64 rlimfsz; /* RLIM_FSIZE -- only! */ unsigned short used_math; char comm[16]; /* file system info */ @@ -417,6 +418,7 @@ /* caps */ CAP_INIT_EFF_SET,CAP_INIT_INH_SET,CAP_FULL_SET, \ /* user */ NULL, \ /* rlimits */ INIT_RLIMITS, \ +/* rlimfsz */ INIT_RLIMFSZ, \ /* math */ 0, \ /* comm */ "swapper", \ /* fs info */ 0,NULL, \ diff -ur linux-23026base/include/linux/smb_fs.h linux-23026m1/include/linux/smb_fs.h --- linux-23026base/include/linux/smb_fs.h Mon Nov 8 14:14:22 1999 +++ linux-23026m1/include/linux/smb_fs.h Mon Nov 8 20:12:25 1999 @@ -128,8 +128,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 *); @@ -139,7 +139,7 @@ int smb_proc_getattr(struct dentry *, struct smb_fattr *); int smb_proc_setattr(struct dentry *, struct smb_fattr *); int smb_proc_settime(struct dentry *, struct smb_fattr *); -int smb_proc_dskattr(struct super_block *, struct statfs *); +int smb_proc_dskattr(struct super_block *, struct statvfs64 *); int smb_proc_reconnect(struct smb_sb_info *); int smb_proc_connect(struct smb_sb_info *); int smb_proc_disconnect(struct smb_sb_info *); diff -ur linux-23026base/include/linux/stat.h linux-23026m1/include/linux/stat.h --- linux-23026base/include/linux/stat.h Mon May 25 20:32:52 1998 +++ linux-23026m1/include/linux/stat.h Mon Nov 8 04:42:28 1999 @@ -3,8 +3,43 @@ #ifdef __KERNEL__ +#include #include +#ifndef __ARCH_STRUCT_STAT64 + +struct stat64 { /* Generically sized structure for all Linuxes */ + __u64 st_dev; /* Usually 16 or 32 bits */ + __u64 st_rdev; + + __u32 st_mode; + __u32 st_nlink; + + __u32 st_uid; + __u32 st_gid; + + __u64 st_ino; /* inode is usually mere 32-bits */ + + __s64 st_size; /* Large File Support */ + __s64 st_blocks; + __u32 st_blksize; + __u32 __unused0; + + long st_atime; /* Yup, 32 bits or 64 bits per natural */ + long __unused1; /* .. size of the 'long'. */ + long st_mtime; + long __unused2; + long st_ctime; + long __unused3; + + __u64 st_gen; /* Linux-FS things */ + __u64 st_flags; + + char st_fstype[16]; /* Filesystem type name; From SysV */ + + __u32 __unused4[32]; /* some reserved space for possible extensions */ +}; +#endif #endif #if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) diff -ur linux-23026base/include/linux/types.h linux-23026m1/include/linux/types.h --- linux-23026base/include/linux/types.h Mon Nov 8 14:11:09 1999 +++ linux-23026m1/include/linux/types.h Mon Nov 8 04:42:28 1999 @@ -9,9 +9,11 @@ typedef __kernel_fd_set fd_set; typedef __kernel_dev_t dev_t; typedef __kernel_ino_t ino_t; +typedef __kernel_ino64_t ino64_t; typedef __kernel_mode_t mode_t; typedef __kernel_nlink_t nlink_t; typedef __kernel_off_t off_t; +typedef __kernel_off64_t off64_t; typedef __kernel_pid_t pid_t; typedef __kernel_uid_t uid_t; typedef __kernel_gid_t gid_t; diff -ur linux-23026base/include/linux/unistd.h linux-23026m1/include/linux/unistd.h --- linux-23026base/include/linux/unistd.h Fri Oct 29 23:41:57 1999 +++ linux-23026m1/include/linux/unistd.h Sun Nov 7 20:49:07 1999 @@ -8,4 +8,350 @@ */ #include + +/* ---------- KERNEL SPACE NEEDS THESE FOR pathconf() AND sysconf() + THINGS AT ALL PLATFORMS ----------------------------- */ +/* ---------- THESE ARE PICKED FROM GLIBC 2.1(pre) HEADERFILES ----- */ +/* ---------- VALUES FOR confstr ARE REMOVED ----------------------- */ + +/* `sysconf', `pathconf', and `confstr' NAME values. Generic version. + Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifdef __KERNEL__ + +/* Values for the NAME argument to `pathconf' and `fpathconf'. */ +enum + { + _PC_LINK_MAX = 0, +#define _PC_LINK_MAX _PC_LINK_MAX + _PC_MAX_CANON = 1, +#define _PC_MAX_CANON _PC_MAX_CANON + _PC_MAX_INPUT = 2, +#define _PC_MAX_INPUT _PC_MAX_INPUT + _PC_NAME_MAX = 3, +#define _PC_NAME_MAX _PC_NAME_MAX + _PC_PATH_MAX = 4, +#define _PC_PATH_MAX _PC_PATH_MAX + _PC_PIPE_BUF = 5, +#define _PC_PIPE_BUF _PC_PIPE_BUF + _PC_CHOWN_RESTRICTED = 6, +#define _PC_CHOWN_RESTRICTED _PC_CHOWN_RESTRICTED + _PC_NO_TRUNC = 7, +#define _PC_NO_TRUNC _PC_NO_TRUNC + _PC_VDISABLE = 8, +#define _PC_VDISABLE _PC_VDISABLE + _PC_SYNC_IO = 9, +#define _PC_SYNC_IO _PC_SYNC_IO + _PC_ASYNC_IO = 10, +#define _PC_ASYNC_IO _PC_ASYNC_IO + _PC_PRIO_IO = 11, +#define _PC_PRIO_IO _PC_PRIO_IO + _PC_SOCK_MAXBUF = 12, +#define _PC_SOCK_MAXBUF _PC_SOCK_MAXBUF + _PC_FILESIZEBITS = 13 +#define _PC_FILESIZEBITS _PC_FILESIZEBITS + }; + +/* Values for the argument to `sysconf'. */ +enum + { + _SC_ARG_MAX = 0, +#define _SC_ARG_MAX _SC_ARG_MAX + _SC_CHILD_MAX = 1, +#define _SC_CHILD_MAX _SC_CHILD_MAX + _SC_CLK_TCK = 2, +#define _SC_CLK_TCK _SC_CLK_TCK + _SC_NGROUPS_MAX = 3, +#define _SC_NGROUPS_MAX _SC_NGROUPS_MAX + _SC_OPEN_MAX = 4, +#define _SC_OPEN_MAX _SC_OPEN_MAX + _SC_STREAM_MAX = 5, +#define _SC_STREAM_MAX _SC_STREAM_MAX + _SC_TZNAME_MAX = 6, +#define _SC_TZNAME_MAX _SC_TZNAME_MAX + _SC_JOB_CONTROL = 7, +#define _SC_JOB_CONTROL _SC_JOB_CONTROL + _SC_SAVED_IDS = 8, +#define _SC_SAVED_IDS _SC_SAVED_IDS + _SC_REALTIME_SIGNALS = 9, +#define _SC_REALTIME_SIGNALS _SC_REALTIME_SIGNALS + _SC_PRIORITY_SCHEDULING = 10, +#define _SC_PRIORITY_SCHEDULING _SC_PRIORITY_SCHEDULING + _SC_TIMERS = 11, +#define _SC_TIMERS _SC_TIMERS + _SC_ASYNCHRONOUS_IO = 12, +#define _SC_ASYNCHRONOUS_IO _SC_ASYNCHRONOUS_IO + _SC_PRIORITIZED_IO = 13, +#define _SC_PRIORITIZED_IO _SC_PRIORITIZED_IO + _SC_SYNCHRONIZED_IO = 14, +#define _SC_SYNCHRONIZED_IO _SC_SYNCHRONIZED_IO + _SC_FSYNC = 15, +#define _SC_FSYNC _SC_FSYNC + _SC_MAPPED_FILES = 16, +#define _SC_MAPPED_FILES _SC_MAPPED_FILES + _SC_MEMLOCK = 17, +#define _SC_MEMLOCK _SC_MEMLOCK + _SC_MEMLOCK_RANGE = 18, +#define _SC_MEMLOCK_RANGE _SC_MEMLOCK_RANGE + _SC_MEMORY_PROTECTION = 19, +#define _SC_MEMORY_PROTECTION _SC_MEMORY_PROTECTION + _SC_MESSAGE_PASSING = 20, +#define _SC_MESSAGE_PASSING _SC_MESSAGE_PASSING + _SC_SEMAPHORES = 21, +#define _SC_SEMAPHORES _SC_SEMAPHORES + _SC_SHARED_MEMORY_OBJECTS = 22, +#define _SC_SHARED_MEMORY_OBJECTS _SC_SHARED_MEMORY_OBJECTS + _SC_AIO_LISTIO_MAX = 23, +#define _SC_AIO_LISTIO_MAX _SC_AIO_LISTIO_MAX + _SC_AIO_MAX = 24, +#define _SC_AIO_MAX _SC_AIO_MAX + _SC_AIO_PRIO_DELTA_MAX = 25, +#define _SC_AIO_PRIO_DELTA_MAX _SC_AIO_PRIO_DELTA_MAX + _SC_DELAYTIMER_MAX = 26, +#define _SC_DELAYTIMER_MAX _SC_DELAYTIMER_MAX + _SC_MQ_OPEN_MAX = 27, +#define _SC_MQ_OPEN_MAX _SC_MQ_OPEN_MAX + _SC_MQ_PRIO_MAX = 28, +#define _SC_MQ_PRIO_MAX _SC_MQ_PRIO_MAX + _SC_VERSION = 29, +#define _SC_VERSION _SC_VERSION + _SC_PAGESIZE = 30, +#define _SC_PAGESIZE _SC_PAGESIZE +#define _SC_PAGE_SIZE _SC_PAGESIZE + _SC_RTSIG_MAX = 31, +#define _SC_RTSIG_MAX _SC_RTSIG_MAX + _SC_SEM_NSEMS_MAX = 32, +#define _SC_SEM_NSEMS_MAX _SC_SEM_NSEMS_MAX + _SC_SEM_VALUE_MAX = 33, +#define _SC_SEM_VALUE_MAX _SC_SEM_VALUE_MAX + _SC_SIGQUEUE_MAX = 34, +#define _SC_SIGQUEUE_MAX _SC_SIGQUEUE_MAX + _SC_TIMER_MAX = 35, +#define _SC_TIMER_MAX _SC_TIMER_MAX + + /* Values for the argument to `sysconf' + corresponding to _POSIX2_* symbols. */ + _SC_BC_BASE_MAX = 36, +#define _SC_BC_BASE_MAX _SC_BC_BASE_MAX + _SC_BC_DIM_MAX = 37, +#define _SC_BC_DIM_MAX _SC_BC_DIM_MAX + _SC_BC_SCALE_MAX = 38, +#define _SC_BC_SCALE_MAX _SC_BC_SCALE_MAX + _SC_BC_STRING_MAX = 39, +#define _SC_BC_STRING_MAX _SC_BC_STRING_MAX + _SC_COLL_WEIGHTS_MAX = 40, +#define _SC_COLL_WEIGHTS_MAX _SC_COLL_WEIGHTS_MAX + _SC_EQUIV_CLASS_MAX = 41, +#define _SC_EQUIV_CLASS_MAX _SC_EQUIV_CLASS_MAX + _SC_EXPR_NEST_MAX = 42, +#define _SC_EXPR_NEST_MAX _SC_EXPR_NEST_MAX + _SC_LINE_MAX = 43, +#define _SC_LINE_MAX _SC_LINE_MAX + _SC_RE_DUP_MAX = 44, +#define _SC_RE_DUP_MAX _SC_RE_DUP_MAX + _SC_CHARCLASS_NAME_MAX = 45, +#define _SC_CHARCLASS_NAME_MAX _SC_CHARCLASS_NAME_MAX + + _SC_2_VERSION = 46, +#define _SC_2_VERSION _SC_2_VERSION + _SC_2_C_BIND = 47, +#define _SC_2_C_BIND _SC_2_C_BIND + _SC_2_C_DEV = 48, +#define _SC_2_C_DEV _SC_2_C_DEV + _SC_2_FORT_DEV = 49, +#define _SC_2_FORT_DEV _SC_2_FORT_DEV + _SC_2_FORT_RUN = 50, +#define _SC_2_FORT_RUN _SC_2_FORT_RUN + _SC_2_SW_DEV = 51, +#define _SC_2_SW_DEV _SC_2_SW_DEV + _SC_2_LOCALEDEF = 52, +#define _SC_2_LOCALEDEF _SC_2_LOCALEDEF + + _SC_PII = 53, +#define _SC_PII _SC_PII + _SC_PII_XTI = 54, +#define _SC_PII_XTI _SC_PII_XTI + _SC_PII_SOCKET = 55, +#define _SC_PII_SOCKET _SC_PII_SOCKET + _SC_PII_INTERNET = 56, +#define _SC_PII_INTERNET _SC_PII_INTERNET + _SC_PII_OSI = 57, +#define _SC_PII_OSI _SC_PII_OSI + _SC_POLL = 58, +#define _SC_POLL _SC_POLL + _SC_SELECT = 59, +#define _SC_SELECT _SC_SELECT + _SC_UIO_MAXIOV = 60, +#define _SC_UIO_MAXIOV _SC_UIO_MAXIOV + _SC_PII_INTERNET_STREAM = 61, +#define _SC_PII_INTERNET_STREAM _SC_PII_INTERNET_STREAM + _SC_PII_INTERNET_DGRAM = 62, +#define _SC_PII_INTERNET_DGRAM _SC_PII_INTERNET_DGRAM + _SC_PII_OSI_COTS = 63, +#define _SC_PII_OSI_COTS _SC_PII_OSI_COTS + _SC_PII_OSI_CLTS = 64, +#define _SC_PII_OSI_CLTS _SC_PII_OSI_CLTS + _SC_PII_OSI_M = 65, +#define _SC_PII_OSI_M _SC_PII_OSI_M + _SC_T_IOV_MAX = 66, +#define _SC_T_IOV_MAX _SC_T_IOV_MAX + + /* Values according to POSIX 1003.1c (POSIX threads). */ + _SC_THREADS = 67, +#define _SC_THREADS _SC_THREADS + _SC_THREAD_SAFE_FUNCTIONS = 68, +#define _SC_THREAD_SAFE_FUNCTIONS _SC_THREAD_SAFE_FUNCTIONS + _SC_GETGR_R_SIZE_MAX = 69, +#define _SC_GETGR_R_SIZE_MAX _SC_GETGR_R_SIZE_MAX + _SC_GETPW_R_SIZE_MAX = 70, +#define _SC_GETPW_R_SIZE_MAX _SC_GETPW_R_SIZE_MAX + _SC_LOGIN_NAME_MAX = 71, +#define _SC_LOGIN_NAME_MAX _SC_LOGIN_NAME_MAX + _SC_TTY_NAME_MAX = 72, +#define _SC_TTY_NAME_MAX _SC_TTY_NAME_MAX + _SC_THREAD_DESTRUCTOR_ITERATIONS = 73, +#define _SC_THREAD_DESTRUCTOR_ITERATIONS _SC_THREAD_DESTRUCTOR_ITERATIONS + _SC_THREAD_KEYS_MAX = 74, +#define _SC_THREAD_KEYS_MAX _SC_THREAD_KEYS_MAX + _SC_THREAD_STACK_MIN = 75, +#define _SC_THREAD_STACK_MIN _SC_THREAD_STACK_MIN + _SC_THREAD_THREADS_MAX = 76, +#define _SC_THREAD_THREADS_MAX _SC_THREAD_THREADS_MAX + _SC_THREAD_ATTR_STACKADDR = 77, +#define _SC_THREAD_ATTR_STACKADDR _SC_THREAD_ATTR_STACKADDR + _SC_THREAD_ATTR_STACKSIZE = 78, +#define _SC_THREAD_ATTR_STACKSIZE _SC_THREAD_ATTR_STACKSIZE + _SC_THREAD_PRIORITY_SCHEDULING = 79, +#define _SC_THREAD_PRIORITY_SCHEDULING _SC_THREAD_PRIORITY_SCHEDULING + _SC_THREAD_PRIO_INHERIT = 80, +#define _SC_THREAD_PRIO_INHERIT _SC_THREAD_PRIO_INHERIT + _SC_THREAD_PRIO_PROTECT = 81, +#define _SC_THREAD_PRIO_PROTECT _SC_THREAD_PRIO_PROTECT + _SC_THREAD_PROCESS_SHARED = 82, +#define _SC_THREAD_PROCESS_SHARED _SC_THREAD_PROCESS_SHARED + + _SC_NPROCESSORS_CONF = 83, +#define _SC_NPROCESSORS_CONF _SC_NPROCESSORS_CONF + _SC_NPROCESSORS_ONLN = 84, +#define _SC_NPROCESSORS_ONLN _SC_NPROCESSORS_ONLN + _SC_PHYS_PAGES = 85, +#define _SC_PHYS_PAGES _SC_PHYS_PAGES + _SC_AVPHYS_PAGES = 86, +#define _SC_AVPHYS_PAGES _SC_AVPHYS_PAGES + _SC_ATEXIT_MAX = 87, +#define _SC_ATEXIT_MAX _SC_ATEXIT_MAX + _SC_PASS_MAX = 88, +#define _SC_PASS_MAX _SC_PASS_MAX + + _SC_XOPEN_VERSION = 89, +#define _SC_XOPEN_VERSION _SC_XOPEN_VERSION + _SC_XOPEN_XCU_VERSION = 90, +#define _SC_XOPEN_XCU_VERSION _SC_XOPEN_XCU_VERSION + _SC_XOPEN_UNIX = 91, +#define _SC_XOPEN_UNIX _SC_XOPEN_UNIX + _SC_XOPEN_CRYPT = 92, +#define _SC_XOPEN_CRYPT _SC_XOPEN_CRYPT + _SC_XOPEN_ENH_I18N = 93, +#define _SC_XOPEN_ENH_I18N _SC_XOPEN_ENH_I18N + _SC_XOPEN_SHM = 94, +#define _SC_XOPEN_SHM _SC_XOPEN_SHM + + _SC_2_CHAR_TERM = 95, +#define _SC_2_CHAR_TERM _SC_2_CHAR_TERM + _SC_2_C_VERSION = 96, +#define _SC_2_C_VERSION _SC_2_C_VERSION + _SC_2_UPE = 97, +#define _SC_2_UPE _SC_2_UPE + + _SC_XOPEN_XPG2 = 98, +#define _SC_XOPEN_XPG2 _SC_XOPEN_XPG2 + _SC_XOPEN_XPG3 = 99, +#define _SC_XOPEN_XPG3 _SC_XOPEN_XPG3 + _SC_XOPEN_XPG4 = 100, +#define _SC_XOPEN_XPG4 _SC_XOPEN_XPG4 + + _SC_CHAR_BIT = 101, +#define _SC_CHAR_BIT _SC_CHAR_BIT + _SC_CHAR_MAX = 102, +#define _SC_CHAR_MAX _SC_CHAR_MAX + _SC_CHAR_MIN = 103, +#define _SC_CHAR_MIN _SC_CHAR_MIN + _SC_INT_MAX = 104, +#define _SC_INT_MAX _SC_INT_MAX + _SC_INT_MIN = 105, +#define _SC_INT_MIN _SC_INT_MIN + _SC_LONG_BIT = 106, +#define _SC_LONG_BIT _SC_LONG_BIT + _SC_WORD_BIT = 107, +#define _SC_WORD_BIT _SC_WORD_BIT + _SC_MB_LEN_MAX = 108, +#define _SC_MB_LEN_MAX _SC_MB_LEN_MAX + _SC_NZERO = 109, +#define _SC_NZERO _SC_NZERO + _SC_SSIZE_MAX = 110, +#define _SC_SSIZE_MAX _SC_SSIZE_MAX + _SC_SCHAR_MAX = 111, +#define _SC_SCHAR_MAX _SC_SCHAR_MAX + _SC_SCHAR_MIN = 112, +#define _SC_SCHAR_MIN _SC_SCHAR_MIN + _SC_SHRT_MAX = 113, +#define _SC_SHRT_MAX _SC_SHRT_MAX + _SC_SHRT_MIN = 114, +#define _SC_SHRT_MIN _SC_SHRT_MIN + _SC_UCHAR_MAX = 115, +#define _SC_UCHAR_MAX _SC_UCHAR_MAX + _SC_UINT_MAX = 116, +#define _SC_UINT_MAX _SC_UINT_MAX + _SC_ULONG_MAX = 117, +#define _SC_ULONG_MAX _SC_ULONG_MAX + _SC_USHRT_MAX = 118, +#define _SC_USHRT_MAX _SC_USHRT_MAX + + _SC_NL_ARGMAX = 119, +#define _SC_NL_ARGMAX _SC_NL_ARGMAX + _SC_NL_LANGMAX = 120, +#define _SC_NL_LANGMAX _SC_NL_LANGMAX + _SC_NL_MSGMAX = 121, +#define _SC_NL_MSGMAX _SC_NL_MSGMAX + _SC_NL_NMAX = 122, +#define _SC_NL_NMAX _SC_NL_NMAX + _SC_NL_SETMAX = 123, +#define _SC_NL_SETMAX _SC_NL_SETMAX + _SC_NL_TEXTMAX = 124, +#define _SC_NL_TEXTMAX _SC_NL_TEXTMAX + + _SC_XBS5_ILP32_OFF32 = 125, +#define _SC_XBS5_ILP32_OFF32 _SC_XBS5_ILP32_OFF32 + _SC_XBS5_ILP32_OFFBIG = 126, +#define _SC_XBS5_ILP32_OFFBIG _SC_XBS5_ILP32_OFFBIG + _SC_XBS5_LP64_OFF64 = 127, +#define _SC_XBS5_LP64_OFF64 _SC_XBS5_LP64_OFF64 + _SC_XBS5_LPBIG_OFFBIG = 128, +#define _SC_XBS5_LPBIG_OFFBIG _SC_XBS5_LPBIG_OFFBIG + + _SC_XOPEN_LEGACY = 129, +#define _SC_XOPEN_LEGACY _SC_XOPEN_LEGACY + _SC_XOPEN_REALTIME = 130, +#define _SC_XOPEN_REALTIME _SC_XOPEN_REALTIME + _SC_XOPEN_REALTIME_THREADS = 131, +#define _SC_XOPEN_REALTIME_THREADS _SC_XOPEN_REALTIME_THREADS + }; +#endif + #endif /* _LINUX_UNISTD_H_ */ diff -ur linux-23026base/kernel/acct.c linux-23026m1/kernel/acct.c --- linux-23026base/kernel/acct.c Mon Aug 23 21:15:53 1999 +++ linux-23026m1/kernel/acct.c Mon Nov 8 12:08:55 1999 @@ -88,8 +88,7 @@ */ static int check_free_space(struct file *file) { - mm_segment_t fs; - struct statfs sbuf; + struct statvfs64 sbuf; struct super_block *sb; int res = acct_active; int act; @@ -98,18 +97,15 @@ return res; sb = file->f_dentry->d_inode->i_sb; - if (!sb->s_op || !sb->s_op->statfs) + if (!sb->s_op || !sb->s_op->statvfs) return res; - fs = get_fs(); - set_fs(KERNEL_DS); /* May block */ - sb->s_op->statfs(sb, &sbuf, sizeof(struct statfs)); - set_fs(fs); + sb->s_op->statvfs(sb, &sbuf); - if (sbuf.f_bavail <= SUSPEND * sbuf.f_blocks / 100) + if (sbuf.f_bavail <= (u_long)(SUSPEND * sbuf.f_blocks) / 100) act = -1; - else if (sbuf.f_bavail >= RESUME * sbuf.f_blocks / 100) + else if (sbuf.f_bavail >= (u_long)(RESUME * sbuf.f_blocks) / 100) act = 1; else act = 0; diff -ur linux-23026base/kernel/sys.c linux-23026m1/kernel/sys.c --- linux-23026base/kernel/sys.c Fri Oct 29 23:19:49 1999 +++ linux-23026m1/kernel/sys.c Mon Nov 8 18:50:35 1999 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -882,11 +883,44 @@ asmlinkage long sys_getrlimit(unsigned int resource, struct rlimit *rlim) { + struct rlimit rl; + if (resource >= RLIM_NLIMITS) return -EINVAL; - else - return copy_to_user(rlim, current->rlim + resource, sizeof(*rlim)) - ? -EFAULT : 0; + + rl = current->rlim[resource]; + if (resource == RLIMIT_FSIZE) { + rl.rlim_cur = current->rlimfsz.rlim_cur; + if (current->rlimfsz.rlim_cur > RLIM_INFINITY) + rl.rlim_cur = RLIM_INFINITY; + rl.rlim_max = current->rlimfsz.rlim_max; + if (current->rlimfsz.rlim_max > RLIM_INFINITY) + rl.rlim_max = RLIM_INFINITY; + + /* XX: RLIM_SAVED_MAX ? RLIM_SAVED_CUR ? (See Large-File-Summit) */ + } + return (copy_to_user(rlim, &rl, sizeof(*rlim)) ? -EFAULT : 0); +} + +asmlinkage long sys_getrlimit64(unsigned int resource, struct rlimit64 *rlim) +{ + struct rlimit64 rlim64; + + if (resource >= RLIM_NLIMITS) + return -EINVAL; + + if (resource == RLIMIT_FSIZE) + rlim64 = current->rlimfsz; + else { + rlim64.rlim_cur = current->rlim[resource].rlim_cur; + rlim64.rlim_max = current->rlim[resource].rlim_max; + if (rlim64.rlim_cur == RLIM_INFINITY) + rlim64.rlim_cur = RLIM64_INFINITY; + if (rlim64.rlim_max == RLIM_INFINITY) + rlim64.rlim_max = RLIM64_INFINITY; + /* XX: RLIM_SAVED_MAX ? RLIM_SAVED_CUR ? (See Large-File-Summit) */ + } + return (copy_to_user(rlim, &rlim64, sizeof(*rlim)) ? -EFAULT : 0); } /* @@ -899,7 +933,18 @@ if (resource >= RLIM_NLIMITS) return -EINVAL; - memcpy(&x, current->rlim + resource, sizeof(*rlim)); + x = current->rlim[resource]; + if (resource == RLIMIT_FSIZE) { + x.rlim_cur = current->rlimfsz.rlim_cur; + if (current->rlimfsz.rlim_cur > RLIM_INFINITY) + x.rlim_cur = RLIM_INFINITY; + x.rlim_max = current->rlimfsz.rlim_max; + if (current->rlimfsz.rlim_max > RLIM_INFINITY) + x.rlim_max = RLIM_INFINITY; + + /* XX: RLIM_SAVED_MAX ? RLIM_SAVED_CUR ? (See Large-File-Summit) */ + } + if(x.rlim_cur > 0x7FFFFFFF) x.rlim_cur = 0x7FFFFFFF; if(x.rlim_max > 0x7FFFFFFF) @@ -916,8 +961,15 @@ return -EINVAL; if(copy_from_user(&new_rlim, rlim, sizeof(*rlim))) return -EFAULT; - if (new_rlim.rlim_cur < 0 || new_rlim.rlim_max < 0) - return -EINVAL; + +#if BITS_PER_LONG < 64 + /* compability with old RLIM_INFINITY value .. */ + if (new_rlim.rlim_cur == 0x7fffffffUL) + new_rlim.rlim_cur = RLIM_INFINITY; + if (new_rlim.rlim_max == 0x7fffffffUL) + new_rlim.rlim_max = RLIM_INFINITY; +#endif + old_rlim = current->rlim + resource; if (((new_rlim.rlim_cur > old_rlim->rlim_max) || (new_rlim.rlim_max > old_rlim->rlim_max)) && @@ -927,10 +979,62 @@ if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN) return -EPERM; } + if (resource == RLIMIT_FSIZE) { + if (new_rlim.rlim_cur == RLIM_INFINITY) { + current->rlimfsz.rlim_cur = RLIM64_INFINITY; + } + if (new_rlim.rlim_max == RLIM_INFINITY) { + current->rlimfsz.rlim_max = RLIM64_INFINITY; + } + } *old_rlim = new_rlim; return 0; } +asmlinkage long sys_setrlimit64(unsigned int resource, struct rlimit64 *rlim) +{ + struct rlimit64 new_rlim; + struct rlimit *old_rlim; + + if (resource >= RLIM_NLIMITS) + return -EINVAL; + if(copy_from_user(&new_rlim, rlim, sizeof(*rlim))) + return -EFAULT; + old_rlim = ¤t->rlim[resource]; + + + if (new_rlim.rlim_cur > RLIM_INFINITY && resource != RLIMIT_FSIZE) + new_rlim.rlim_cur = RLIM_INFINITY; + if (new_rlim.rlim_max > RLIM_INFINITY && resource != RLIMIT_FSIZE) + new_rlim.rlim_max = RLIM_INFINITY; + + if (resource == RLIMIT_FSIZE) { + if (((new_rlim.rlim_cur > current->rlimfsz.rlim_max) || + (new_rlim.rlim_max > current->rlimfsz.rlim_max)) && + !capable(CAP_SYS_RESOURCE)) + return -EPERM; + } else + if (((new_rlim.rlim_cur > old_rlim->rlim_max) || + (new_rlim.rlim_max > old_rlim->rlim_max)) && + !capable(CAP_SYS_RESOURCE)) + return -EPERM; + if (resource == RLIMIT_NOFILE) { + if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN) + return -EPERM; + } + if (resource == RLIMIT_FSIZE) { + current->rlimfsz = new_rlim; + + if (new_rlim.rlim_cur > RLIM_INFINITY) + new_rlim.rlim_cur = RLIM_INFINITY; + if (new_rlim.rlim_max > RLIM_INFINITY) + new_rlim.rlim_max = RLIM_INFINITY; + } + old_rlim->rlim_cur = new_rlim.rlim_cur; + old_rlim->rlim_max = new_rlim.rlim_max; + return 0; +} + /* * It would make sense to put struct rusage in the task_struct, * except that would make the task_struct be *really big*. After @@ -948,7 +1052,7 @@ * * FIXME! Get the fault counts properly! */ -int getrusage(struct task_struct *p, int who, struct rusage *ru) +long getrusage(struct task_struct *p, int who, struct rusage *ru) { struct rusage r; @@ -1034,3 +1138,70 @@ return error; } + +/* + * POSIX sysconf() things + * + * There are things for which the existence of this makes + * a lot of sense; Adding new facilities to the system allows + * things like libc to detect availability of those way easier + * thru sysconf(), than by any other means. + * Mostly these are for other than POSIX.1 things, e.g. for + * POSIX.1b, POSIX.1b (aka REAL TIME and THREADS, respectively) + * + * sysconf() returns -1 for all those option values it does + * not recognize. *Never* shall it set errno! + * + * Returning ``-1'' without errno is indicated by returning ``-INT_MAX'' + */ + +asmlinkage long sys_sysconf(int option) +{ + switch(option) { +#if 0 /* Drepper thinking: These shouldn't be in kernel */ + case _SC_JOB_CONTROL: /* POSIX.1 */ + return 1; + case _SC_SAVED_IDS: + return -INT_MAX; /* FIXME! What the value *should* be ? */ + case _SC_VERSION: + return -INT_MAX; /* FIXME! What _POSIX_VERSION we have + in the kernel proper ? */ +#endif + case _SC_ARG_MAX: + return ARG_MAX; + + case _SC_CHILD_MAX: + return -INT_MAX; + + case _SC_CLK_TCK: + return HZ; + + case _SC_NGROUPS_MAX: + return NGROUPS_MAX; + + case _SC_OPEN_MAX: /* POSIX.1 Max simultaneous files */ + case _SC_STREAM_MAX: /* POSIX.1: Max simultaneous streams */ + return NR_OPEN; /* The upper hard limit; Normally something + like 1024, but insanely large file arrays + can also be supported in the system giving + this here 1024*1024 (yep, MILLION!) */ + +#if 0 /* Library thing */ + case _SC_TZNAME_MAX: + return -INT_MAX; +#endif +#if 0 /* Drepper thinking: Most of these are library things, and don't + belong to kernel.. Must sort them out someday.. */ + case _SC_ASYNCHRONOUS_IO: /* POSIX.4 */ + case _SC_MAPPED_FILES: + case _SC_MEMLOCK: + case _SC_MEMLOCK_RANGE: + case _SC_MEMORY_PROTECTION: + /* ... more! ... */ + break; +#endif + default: /* Anything not considered in kernel -> EINVAL */ + break; + } + return -EINVAL; +} diff -ur linux-23026base/lib/vsprintf.c linux-23026m1/lib/vsprintf.c --- linux-23026base/lib/vsprintf.c Sun Jul 25 02:42:01 1999 +++ linux-23026m1/lib/vsprintf.c Sun Nov 7 19:30:58 1999 @@ -7,6 +7,9 @@ /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ /* * Wirzenius wrote this portably, Torvalds fucked it up :-) + * + * Matti Aarnio added '%L' support + * */ #include @@ -67,10 +70,107 @@ #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 = ((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) @@ -208,8 +308,11 @@ /* get the conversion qualifier */ qualifier = -1; - if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='z') { - qualifier = *fmt; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'z') { + if (*fmt == 'l' && qualifier == 'l') + qualifier = 'L'; + else + qualifier = *fmt; ++fmt; } @@ -295,7 +398,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 == 'z') num = va_arg(args, size_t); diff -ur linux-23026base/mm/filemap.c linux-23026m1/mm/filemap.c --- linux-23026base/mm/filemap.c Sat Nov 6 02:16:48 1999 +++ linux-23026m1/mm/filemap.c Mon Nov 8 20:13:27 1999 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -122,13 +123,14 @@ * 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 lstart) { struct list_head *head, *curr; struct page * page; - unsigned partial = start & (PAGE_CACHE_SIZE - 1); + unsigned partial = lstart & (PAGE_CACHE_SIZE - 1); + unsigned long start; - start = (start + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + start = (lstart + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; repeat: head = &inode->i_data.pages; @@ -412,7 +414,7 @@ return error; } -static int do_buffer_fdatasync(struct inode *inode, unsigned long start, unsigned long end, int (*fn)(struct page *)) +static int do_buffer_fdatasync(struct inode *inode, unsigned long startidx, unsigned long endidx, int (*fn)(struct page *)) { struct list_head *head, *curr; struct page *page; @@ -427,9 +429,9 @@ curr = curr->next; if (!page->buffers) continue; - if (page->index >= end) + if (page->index >= endidx) continue; - if (page->index < start) + if (page->index < startidx) continue; get_page(page); @@ -454,7 +456,7 @@ * Two-stage data sync: first start the IO, then go back and * collect the information.. */ -int generic_buffer_fdatasync(struct inode *inode, unsigned long start, unsigned long end) +int generic_buffer_fdatasync(struct inode *inode, loff_t start, loff_t end) { unsigned long start_idx = start >> PAGE_CACHE_SHIFT; unsigned long end_idx = (end + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; @@ -550,19 +552,19 @@ /* * Read in an entire cluster at once. A cluster is usually a 64k- - * aligned block that includes the address requested in "offset." + * aligned block that includes the address requested in "index." */ -static int read_cluster_nonblocking(struct file * file, unsigned long offset) +static int read_cluster_nonblocking(struct file * file, unsigned long index) { int error = 0; unsigned long filesize = (file->f_dentry->d_inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; unsigned long pages = CLUSTER_PAGES; - offset = CLUSTER_OFFSET(offset); - while ((pages-- > 0) && (offset < filesize)) { - error = page_cache_read(file, offset); + index = CLUSTER_OFFSET(index); + while ((pages-- > 0) && (index < filesize)) { + error = page_cache_read(file, index); if (error >= 0) - offset ++; + index ++; else break; } @@ -776,8 +778,7 @@ * Read-ahead context: * ------------------- * The read ahead context fields of the "struct file" are the following: - * - f_raend : position of the first byte after the last page we tried to - * read ahead. + * - f_raend : index of the last page+1 we tried to read ahead. * - f_ramax : current read-ahead maximum size. * - f_ralen : length of the current IO read block we tried to read-ahead. * - f_rawin : length of the current read-ahead window. @@ -1166,11 +1167,23 @@ 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; retval = -EFAULT; if (access_ok(VERIFY_WRITE, buf, count)) { retval = 0; + /* L-F-S spec 2.2.1.25: */ + if (count && !(filp->f_flags & O_LARGEFILE) && + S_ISREG(inode->i_mode) && + (*ppos < inode->i_size) && + !off_t_presentable(*ppos + count)) { + if (*ppos >= LONG_MAX) /* pos@LONG_MAX forbidden! */ + return -EOVERFLOW; + /* Read only until end of allowed region */ + count = LONG_MAX - *ppos; + } + if (count) { read_descriptor_t desc; @@ -1213,6 +1226,10 @@ return written; } +/* + * sys_sendfile() isn't LARGEFILE compatible in all systems + */ + asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count) { ssize_t retval; @@ -1261,12 +1278,14 @@ if (count) { read_descriptor_t desc; loff_t pos = 0, *ppos; + off_t posp; retval = -EFAULT; ppos = &in_file->f_pos; if (offset) { - if (get_user(pos, offset)) + if (get_user(posp, offset)) goto fput_out; + pos = posp; ppos = &pos; } @@ -1279,8 +1298,9 @@ retval = desc.written; if (!retval) retval = desc.error; + posp = pos; if (offset) - put_user(pos, offset); + put_user(posp, offset); } fput_out: @@ -1434,19 +1454,18 @@ * if the disk is full. */ static inline int do_write_page(struct inode * inode, struct file * file, - struct page * page, unsigned long offset) + struct page * page, unsigned long pgindex) { int retval; - unsigned long size; int (*writepage) (struct file *, struct page *); - size = (offset << PAGE_CACHE_SHIFT) + PAGE_CACHE_SIZE; /* refuse to extend file size.. */ if (S_ISREG(inode->i_mode)) { - if (size > inode->i_size) - size = inode->i_size; /* Ho humm.. We should have tested for this earlier */ - if (size < offset) + unsigned long pgsize; + pgsize = inode->i_size >> PAGE_CACHE_SHIFT; + /* This is a matter of full cluster blocks */ + if (pgindex >= pgsize) return -EIO; } retval = -EIO; @@ -1460,7 +1479,7 @@ } static int filemap_write_page(struct file *file, - unsigned long offset, + unsigned long pgindex, struct page * page, int wait) { @@ -1477,7 +1496,7 @@ * vma/file is guaranteed to exist in the unmap/sync cases because * mmap_sem is held. */ - result = do_write_page(inode, file, page, offset); + result = do_write_page(inode, file, page, pgindex); return result; } @@ -1792,7 +1811,7 @@ { struct dentry *dentry = file->f_dentry; struct inode *inode = dentry->d_inode; - unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur; + loff_t limit = current->rlimfsz.rlim_cur; loff_t pos = *ppos; struct page *page, **hash, *cached_page; unsigned long written; @@ -1820,16 +1839,59 @@ * Check whether we've reached the file size limit. */ err = -EFBIG; - if (limit != RLIM_INFINITY) { - if (pos >= limit) { - send_sig(SIGXFSZ, current, 0); - goto out; - } - if (count > limit - pos) { - send_sig(SIGXFSZ, current, 0); - count = limit - pos; - } + if (pos >= limit) { +// printk(" generic_file_write() EFBIG: pos=%Lx limit=%Lx\n",pos,limit); + send_sig(SIGXFSZ, current, 0); + goto out; + } + if (count > limit - pos) { + /* send_sig(SIGXFSZ, current, 0); */ + count = limit - pos; } + +#if 0 + /* REGULAR files have Large File Summit rules */ + + if (S_ISREG(inode->i_mode)) { + + const loff_t lim2G = 0x7FFFFFFFLL; + + if (!inode->i_op->pathconf || + inode->i_op->pathconf(inode,_PC_FILESIZEBITS) <= 32) { + /* Hmm... 31 = 2G, 32 = 4G ?? */ + + /* L-F-S: Must limit down to 2G! */ + + if ((pos+count) > lim2G) { + if (pos >= lim2G) { /* over 2G-1 */ + /* Fails completely! Err = -EFBIG */ + send_sig(SIGXFSZ, current, 0); + goto out; + } else { /* At most 2G-1 */ + count = lim2G-pos; + } + } + } + +#if BITS_PER_LONG < 64 /* Large File Summit has meaning ! */ + else { + /* This filesystem *can* support Large Files */ + if (!(file->f_flags & O_LARGEFILE)) { + /* Not opened as Large File */ + if ((pos+count) > lim2G) { + if (pos >= lim2G) { /* over 2G-1 */ + /* Fails completely! Err = -EFBIG */ + send_sig(SIGXFSZ, current, 0); + goto out; + } else { /* At most 2G-1 */ + count = lim2G-pos; + } + } + } + } +#endif + } /* ... was REGULAR file */ +#endif status = 0; diff -ur linux-23026base/mm/memory.c linux-23026m1/mm/memory.c --- linux-23026base/mm/memory.c Fri Nov 5 05:36:33 1999 +++ linux-23026m1/mm/memory.c Sun Nov 7 22:51:43 1999 @@ -885,7 +885,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) { unsigned long partial, pgoff; struct vm_area_struct * mpnt; diff -ur linux-23026base/mm/mmap.c linux-23026m1/mm/mmap.c --- linux-23026base/mm/mmap.c Thu Oct 28 23:03:38 1999 +++ linux-23026m1/mm/mmap.c Sun Nov 7 23:08:34 1999 @@ -161,11 +161,12 @@ } unsigned long do_mmap(struct file * file, unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, unsigned long off) + unsigned long prot, unsigned long flags, loff_t loff) { struct mm_struct * mm = current->mm; struct vm_area_struct * vma; int error; + unsigned long off; if (file && (!file->f_op || !file->f_op->mmap)) return -ENODEV; @@ -176,14 +177,14 @@ if (len > TASK_SIZE || addr > TASK_SIZE-len) return -EINVAL; - if (off & ~PAGE_MASK) + if (loff & ~PAGE_MASK) return -EINVAL; - /* offset overflow? */ - if (off + len < off) + /* offset overflow? (propably not..) */ + if (loff + len < loff) return -EINVAL; - off = off >> PAGE_SHIFT; + off = loff >> PAGE_SHIFT; /* Too many mappings? */ if (mm->map_count > MAX_MAP_COUNT) diff -ur linux-23026base/mm/vmscan.c linux-23026m1/mm/vmscan.c --- linux-23026base/mm/vmscan.c Sat Oct 30 02:45:32 1999 +++ linux-23026m1/mm/vmscan.c Sun Nov 7 23:15:27 1999 @@ -19,6 +19,8 @@ #include #include #include +#define __KERNEL_SYSCALLS__ +#include #include diff -ur linux-23026base/net/atm/lec.c linux-23026m1/net/atm/lec.c --- linux-23026base/net/atm/lec.c Wed Sep 8 21:14:32 1999 +++ linux-23026m1/net/atm/lec.c Mon Nov 8 11:56:04 1999 @@ -1535,7 +1535,7 @@ if (entry) entry->next = to_remove->next; } - if (!entry) + if (!entry) { if (to_remove == priv->lec_no_forward) { priv->lec_no_forward = to_remove->next; } else { @@ -1545,6 +1545,7 @@ if (entry) entry->next = to_remove->next; } + } lec_arp_clear_vccs(to_remove); kfree(to_remove); } diff -ur linux-23026base/net/khttpd/datasending.c linux-23026m1/net/khttpd/datasending.c --- linux-23026base/net/khttpd/datasending.c Thu Aug 26 19:41:36 1999 +++ linux-23026m1/net/khttpd/datasending.c Mon Nov 8 12:15:09 1999 @@ -55,7 +55,11 @@ It sends the data to the socket indicated by desc->buf. */ -static int sock_send_actor(read_descriptor_t * desc, const char *area, unsigned long size) + +// FIXME: usage of these parameters is not corrected in code below, +// FIXME: while call parameters are now modern... + +static int sock_send_actor(read_descriptor_t * desc, struct page * page, unsigned long offset, unsigned long size) { int written; unsigned long count = desc->count; @@ -63,7 +67,7 @@ if (size > count) size = count; - written = SendBuffer_async(sock,(char *)area,size); + written = SendBuffer_async(sock, page, size); if (written < 0) { desc->error = written; diff -ur linux-23026base/net/khttpd/main.c linux-23026m1/net/khttpd/main.c --- linux-23026base/net/khttpd/main.c Tue Aug 31 21:30:48 1999 +++ linux-23026m1/net/khttpd/main.c Sun Nov 7 23:16:14 1999 @@ -58,7 +58,7 @@ #include #include #include -#include +#include #include "structure.h" #include "prototypes.h"