From: Andy P. <at...@us...> - 2002-04-09 14:08:27
|
Update of /cvsroot/linux-vax/kernel-2.4/fs In directory usw-pr-cvs1:/tmp/cvs-serv29245 Modified Files: locks.c namei.c open.c pipe.c Added Files: namespace.c Log Message: synch 2.4.15 commit 13 --- NEW FILE --- /* * linux/fs/namespace.c * * (C) Copyright Al Viro 2000, 2001 * Released under GPL v2. * * Based on code from fs/super.c, copyright Linus Torvalds and others. * Heavily rewritten. */ #include <linux/config.h> #include <linux/slab.h> #include <linux/smp_lock.h> #include <linux/init.h> #include <linux/quotaops.h> #include <linux/acct.h> #include <linux/module.h> #include <linux/devfs_fs_kernel.h> [...1059 lines suppressed...] return error; } spin_lock(&dcache_lock); attach_mnt(old_rootmnt, &nd); if (new_devname) { if (old_rootmnt->mnt_devname) kfree(old_rootmnt->mnt_devname); old_rootmnt->mnt_devname = new_devname; } spin_unlock(&dcache_lock); /* put the old stuff */ path_release(&parent_nd); mntput(old_rootmnt); path_release(&nd); return 0; } #endif Index: locks.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/locks.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- locks.c 25 Feb 2001 23:14:46 -0000 1.1.1.2 +++ locks.c 9 Apr 2002 13:19:31 -0000 1.2 @@ -112,7 +112,7 @@ * * Leases and LOCK_MAND * Matthew Wilcox <wi...@li...>, June, 2000. - * Stephen Rothwell <sf...@li...>, June, 2000. + * Stephen Rothwell <sf...@ca...>, June, 2000. */ #include <linux/slab.h> @@ -257,7 +257,7 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl, struct flock *l) { - loff_t start; + off_t start, end; switch (l->l_whence) { case 0: /*SEEK_SET*/ @@ -270,17 +270,16 @@ start = filp->f_dentry->d_inode->i_size; break; default: - return (0); + return -EINVAL; } if (((start += l->l_start) < 0) || (l->l_len < 0)) - return (0); - fl->fl_end = start + l->l_len - 1; - if (l->l_len > 0 && fl->fl_end < 0) - return (0); - if (fl->fl_end > OFFT_OFFSET_MAX) - return 0; + return -EINVAL; + end = start + l->l_len - 1; + if (l->l_len > 0 && end < 0) + return -EOVERFLOW; fl->fl_start = start; /* we record the absolute position */ + fl->fl_end = end; if (l->l_len == 0) fl->fl_end = OFFSET_MAX; @@ -292,7 +291,7 @@ fl->fl_insert = NULL; fl->fl_remove = NULL; - return (assign_type(fl, l->l_type) == 0); + return assign_type(fl, l->l_type); } #if BITS_PER_LONG == 32 @@ -312,14 +311,14 @@ start = filp->f_dentry->d_inode->i_size; break; default: - return (0); + return -EINVAL; } if (((start += l->l_start) < 0) || (l->l_len < 0)) - return (0); + return -EINVAL; fl->fl_end = start + l->l_len - 1; if (l->l_len > 0 && fl->fl_end < 0) - return (0); + return -EOVERFLOW; fl->fl_start = start; /* we record the absolute position */ if (l->l_len == 0) fl->fl_end = OFFSET_MAX; @@ -339,10 +338,10 @@ fl->fl_type = l->l_type; break; default: - return (0); + return -EINVAL; } - return (1); + return (0); } #endif @@ -473,21 +472,26 @@ fl->fl_insert(fl); } -/* Delete a lock and then free it. - * Remove our lock from the lock lists, wake up processes that are blocked - * waiting for this lock, notify the FS that the lock has been cleared and - * finally free the lock. +/* + * Remove lock from the lock lists */ -static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait) +static inline void _unhash_lock(struct file_lock **thisfl_p) { struct file_lock *fl = *thisfl_p; *thisfl_p = fl->fl_next; fl->fl_next = NULL; - list_del(&fl->fl_link); - INIT_LIST_HEAD(&fl->fl_link); + list_del_init(&fl->fl_link); +} +/* + * Wake up processes that are blocked waiting for this lock, + * notify the FS that the lock has been cleared and + * finally free the lock. + */ +static inline void _delete_lock(struct file_lock *fl, unsigned int wait) +{ fasync_helper(0, fl->fl_file, 0, &fl->fl_fasync); if (fl->fl_fasync != NULL){ printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync); @@ -502,6 +506,17 @@ } /* + * Delete a lock and then free it. + */ +static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait) +{ + struct file_lock *fl = *thisfl_p; + + _unhash_lock(thisfl_p); + _delete_lock(fl, wait); +} + +/* * Call back client filesystem in order to get it to unregister a lock, * then delete lock. Essentially useful only in locks_remove_*(). * Note: this must be called with the semaphore already held! @@ -511,12 +526,13 @@ struct file_lock *fl = *thisfl_p; int (*lock)(struct file *, int, struct file_lock *); + _unhash_lock(thisfl_p); if (fl->fl_file->f_op && (lock = fl->fl_file->f_op->lock) != NULL) { fl->fl_type = F_UNLCK; lock(fl->fl_file, F_SETLK, fl); } - locks_delete_lock(thisfl_p, 0); + _delete_lock(fl, 0); } /* Determine if lock sys_fl blocks lock caller_fl. Common functionality @@ -532,7 +548,7 @@ return (1); default: - printk("locks_conflict(): impossible lock type - %d\n", + printk(KERN_ERR "locks_conflict(): impossible lock type - %d\n", caller_fl->fl_type); break; } @@ -644,7 +660,7 @@ * from a broken NFS client. But broken NFS clients have a lot more to * worry about than proper deadlock detection anyway... --okir */ -static int posix_locks_deadlock(struct file_lock *caller_fl, +int posix_locks_deadlock(struct file_lock *caller_fl, struct file_lock *block_fl) { struct list_head *tmp; @@ -699,6 +715,9 @@ struct file_lock *new_fl = locks_alloc_lock(0); int error; + if (new_fl == NULL) + return -ENOMEM; + new_fl->fl_owner = current->files; new_fl->fl_pid = current->pid; new_fl->fl_file = filp; @@ -857,7 +876,7 @@ new_fl2 = locks_alloc_lock(0); error = -ENOLCK; /* "no luck" */ if (!(new_fl && new_fl2)) - goto out; + goto out_nolock; lock_kernel(); if (caller->fl_type != F_UNLCK) { @@ -1005,6 +1024,7 @@ } out: unlock_kernel(); +out_nolock: /* * Free any unused locks. */ @@ -1352,8 +1372,8 @@ if (!filp) goto out; - error = -EINVAL; - if (!flock_to_posix_lock(filp, &file_lock, &flock)) + error = flock_to_posix_lock(filp, &file_lock, &flock); + if (error) goto out_putf; if (filp->f_op && filp->f_op->lock) { @@ -1411,6 +1431,9 @@ struct inode *inode; int error; + if (file_lock == NULL) + return -ENOLCK; + /* * This might block, so we do it before checking the inode. */ @@ -1442,8 +1465,8 @@ } } - error = -EINVAL; - if (!flock_to_posix_lock(filp, file_lock, &flock)) + error = flock_to_posix_lock(filp, file_lock, &flock); + if (error) goto out_putf; error = -EBADF; @@ -1517,8 +1540,8 @@ if (!filp) goto out; - error = -EINVAL; - if (!flock64_to_posix_lock(filp, &file_lock, &flock)) + error = flock64_to_posix_lock(filp, &file_lock, &flock); + if (error) goto out_putf; if (filp->f_op && filp->f_op->lock) { @@ -1564,6 +1587,9 @@ struct inode *inode; int error; + if (file_lock == NULL) + return -ENOLCK; + /* * This might block, so we do it before checking the inode. */ @@ -1595,8 +1621,8 @@ } } - error = -EINVAL; - if (!flock64_to_posix_lock(filp, file_lock, &flock)) + error = flock64_to_posix_lock(filp, file_lock, &flock); + if (error) goto out_putf; error = -EBADF; @@ -1660,6 +1686,7 @@ while ((fl = *before) != NULL) { if ((fl->fl_flags & FL_POSIX) && fl->fl_owner == owner) { locks_unlock_delete(before); + before = &inode->i_flock; continue; } before = &fl->fl_next; Index: namei.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/namei.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- namei.c 14 Jan 2001 16:25:10 -0000 1.1.1.1 +++ namei.c 9 Apr 2002 13:19:31 -0000 1.2 @@ -15,21 +15,16 @@ */ #include <linux/init.h> -#include <linux/mm.h> -#include <linux/proc_fs.h> -#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/fs.h> #include <linux/quotaops.h> #include <linux/pagemap.h> -#include <linux/dcache.h> #include <linux/dnotify.h> - -#include <asm/uaccess.h> -#include <asm/unaligned.h> -#include <asm/semaphore.h> -#include <asm/page.h> -#include <asm/pgtable.h> +#include <linux/smp_lock.h> +#include <linux/personality.h> #include <asm/namei.h> +#include <asm/uaccess.h> #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) @@ -113,7 +108,7 @@ if ((unsigned long) filename >= TASK_SIZE) { if (!segment_eq(get_fs(), KERNEL_DS)) return -EFAULT; - } else if (TASK_SIZE - (unsigned long) filename < PAGE_SIZE) + } else if (TASK_SIZE - (unsigned long) filename < PATH_MAX + 1) len = TASK_SIZE - (unsigned long) filename; retval = strncpy_from_user((char *)page, filename, len); @@ -145,35 +140,55 @@ } /* - * permission() + * vfs_permission() * * is used to check for read/write/execute permissions on a file. * We use "fsuid" for this, letting us set arbitrary permissions * for filesystem access without changing the "normal" uids which * are used for other things.. */ -int vfs_permission(struct inode * inode,int mask) +int vfs_permission(struct inode * inode, int mask) { - int mode = inode->i_mode; + umode_t mode = inode->i_mode; - if ((mask & S_IWOTH) && IS_RDONLY(inode) && - (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) - return -EROFS; /* Nobody gets write access to a read-only fs */ + if (mask & MAY_WRITE) { + /* + * Nobody gets write access to a read-only fs. + */ + if (IS_RDONLY(inode) && + (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) + return -EROFS; - if ((mask & S_IWOTH) && IS_IMMUTABLE(inode)) - return -EACCES; /* Nobody gets write access to an immutable file */ + /* + * Nobody gets write access to an immutable file. + */ + if (IS_IMMUTABLE(inode)) + return -EACCES; + } if (current->fsuid == inode->i_uid) mode >>= 6; else if (in_group_p(inode->i_gid)) mode >>= 3; - if (((mode & mask & S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE)) + /* + * If the DACs are ok we don't need any capability check. + */ + if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask)) return 0; - /* read and search access */ - if ((mask == S_IROTH) || - (S_ISDIR(inode->i_mode) && !(mask & ~(S_IROTH | S_IXOTH)))) + /* + * Read/write DACs are always overridable. + * Executable DACs are overridable if at least one exec bit is set. + */ + if ((mask & (MAY_READ|MAY_WRITE)) || (inode->i_mode & S_IXUGO)) + if (capable(CAP_DAC_OVERRIDE)) + return 0; + + /* + * Searching includes executable on directories, else just read. + */ + if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE))) if (capable(CAP_DAC_READ_SEARCH)) return 0; @@ -309,12 +324,26 @@ return result; } +/* + * This limits recursive symlink follows to 8, while + * limiting consecutive symlinks to 40. + * + * Without that kind of total limit, nasty chains of consecutive + * symlinks can cause almost arbitrarily long lookups. + */ static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) { int err; - if (current->link_count >= 8) + if (current->link_count >= 5) + goto loop; + if (current->total_link_count >= 40) goto loop; + if (current->need_resched) { + current->state = TASK_RUNNING; + schedule(); + } current->link_count++; + current->total_link_count++; UPDATE_ATIME(dentry->d_inode); err = dentry->d_inode->i_op->follow_link(dentry, nd); current->link_count--; @@ -351,22 +380,17 @@ static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry) { - struct list_head *p; + struct vfsmount *mounted; + spin_lock(&dcache_lock); - p = (*dentry)->d_vfsmnt.next; - while (p != &(*dentry)->d_vfsmnt) { - struct vfsmount *tmp; - tmp = list_entry(p, struct vfsmount, mnt_clash); - if (tmp->mnt_parent == *mnt) { - *mnt = mntget(tmp); - spin_unlock(&dcache_lock); - mntput(tmp->mnt_parent); - /* tmp holds the mountpoint, so... */ - dput(*dentry); - *dentry = dget(tmp->mnt_root); - return 1; - } - p = p->next; + mounted = lookup_mnt(*mnt, *dentry); + if (mounted) { + *mnt = mntget(mounted); + spin_unlock(&dcache_lock); + dput(*dentry); + mntput(mounted->mnt_parent); + *dentry = dget(mounted->mnt_root); + return 1; } spin_unlock(&dcache_lock); return 0; @@ -411,6 +435,7 @@ nd->mnt = parent; } } + /* * Name resolution. * @@ -419,7 +444,7 @@ * * We expect 'base' to be positive and a directory. */ -int path_walk(const char * name, struct nameidata *nd) +int link_path_walk(const char * name, struct nameidata *nd) { struct dentry *dentry; struct inode *inode; @@ -610,15 +635,25 @@ return err; } +int path_walk(const char * name, struct nameidata *nd) +{ + current->total_link_count = 0; + return link_path_walk(name, nd); +} + /* SMP-safe */ /* returns 1 if everything is done */ static int __emul_lookup_dentry(const char *name, struct nameidata *nd) { if (path_walk(name, nd)) - return 0; + return 0; /* something went wrong... */ - if (!nd->dentry->d_inode) { + if (!nd->dentry->d_inode || S_ISDIR(nd->dentry->d_inode->i_mode)) { struct nameidata nd_root; + /* + * NAME was not found in alternate root or it's a directory. Try to find + * it in the normal root: + */ nd_root.last_type = LAST_ROOT; nd_root.flags = nd->flags; read_lock(¤t->fs->lock); @@ -748,26 +783,24 @@ } /* SMP-safe */ -struct dentry * lookup_one(const char * name, struct dentry * base) +struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) { unsigned long hash; struct qstr this; unsigned int c; this.name = name; - c = *(const unsigned char *)name; - if (!c) + this.len = len; + if (!len) goto access; hash = init_name_hash(); - do { - name++; - if (c == '/') + while (len--) { + c = *(const unsigned char *)name++; + if (c == '/' || c == '\0') goto access; hash = partial_name_hash(c, hash); - c = *(const unsigned char *)name; - } while (c); - this.len = name - (const char *) this.name; + } this.hash = end_name_hash(hash); return lookup_hash(&this, base); @@ -899,7 +932,7 @@ { int error; - mode &= S_IALLUGO & ~current->fs->umask; + mode &= S_IALLUGO; mode |= S_IFREG; down(&dir->i_zombie); @@ -988,7 +1021,8 @@ /* Negative dentry, just create the file */ if (!dentry->d_inode) { - error = vfs_create(dir->d_inode, dentry, mode); + error = vfs_create(dir->d_inode, dentry, + mode & ~current->fs->umask); up(&dir->d_inode->i_sem); dput(nd->dentry); nd->dentry = dentry; @@ -1013,7 +1047,7 @@ error = -ELOOP; if (flag & O_NOFOLLOW) goto exit_dput; - do __follow_down(&nd->mnt,&dentry); while(d_mountpoint(dentry)); + while (__follow_down(&nd->mnt,&dentry) && d_mountpoint(dentry)); } error = -ENOENT; if (!dentry->d_inode) @@ -1053,7 +1087,7 @@ flag &= ~O_TRUNC; } else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { error = -EACCES; - if (IS_NODEV(inode)) + if (nd->mnt->mnt_flags & MNT_NODEV) goto exit; flag &= ~O_TRUNC; @@ -1139,10 +1173,10 @@ putname(nd->last.name); goto exit; } + error = -ELOOP; if (count++==32) { - dentry = nd->dentry; putname(nd->last.name); - goto ok; + goto exit; } dir = nd->dentry; down(&dir->d_inode->i_sem); @@ -1177,8 +1211,6 @@ { int error = -EPERM; - mode &= ~current->fs->umask; - down(&dir->i_zombie); if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD)) goto exit_lock; @@ -1221,6 +1253,8 @@ goto out; dentry = lookup_create(&nd, 0); error = PTR_ERR(dentry); + + mode &= ~current->fs->umask; if (!IS_ERR(dentry)) { switch (mode & S_IFMT) { case 0: case S_IFREG: @@ -1259,7 +1293,7 @@ goto exit_lock; DQUOT_INIT(dir); - mode &= (S_IRWXUGO|S_ISVTX) & ~current->fs->umask; + mode &= (S_IRWXUGO|S_ISVTX); lock_kernel(); error = dir->i_op->mkdir(dir, dentry, mode); unlock_kernel(); @@ -1289,7 +1323,8 @@ dentry = lookup_create(&nd, 1); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { - error = vfs_mkdir(nd.dentry->d_inode, dentry, mode); + error = vfs_mkdir(nd.dentry->d_inode, dentry, + mode & ~current->fs->umask); dput(dentry); } up(&nd.dentry->d_inode->i_sem); @@ -1699,6 +1734,10 @@ error = -EINVAL; if (is_subdir(new_dentry, old_dentry)) goto out_unlock; + /* Don't eat your daddy, dear... */ + /* This also avoids locking issues */ + if (old_dentry->d_parent == new_dentry) + goto out_unlock; target = new_dentry->d_inode; if (target) { /* Hastur! Hastur! Hastur! */ triple_down(&old_dir->i_zombie, @@ -1917,7 +1956,7 @@ /* weird __emul_prefix() stuff did it */ goto out; } - res = path_walk(link, nd); + res = link_path_walk(link, nd); out: if (current->link_count || res || nd->last_type!=LAST_NORM) return res; @@ -1927,13 +1966,11 @@ * bloody create() on broken symlinks. Furrfu... */ name = __getname(); - if (IS_ERR(name)) - goto fail_name; + if (!name) + return -ENOMEM; strcpy(name, nd->last.name); nd->last.name = name; return 0; -fail_name: - link = name; fail: path_release(nd); return PTR_ERR(link); Index: open.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/open.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- open.c 25 Feb 2001 23:14:45 -0000 1.1.1.2 +++ open.c 9 Apr 2002 13:19:32 -0000 1.2 @@ -14,6 +14,7 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/tty.h> +#include <linux/iobuf.h> #include <asm/uaccess.h> @@ -103,7 +104,12 @@ goto out; inode = nd.dentry->d_inode; - error = -EACCES; + /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ + error = -EISDIR; + if (S_ISDIR(inode->i_mode)) + goto dput_and_out; + + error = -EINVAL; if (!S_ISREG(inode->i_mode)) goto dput_and_out; @@ -145,10 +151,11 @@ asmlinkage long sys_truncate(const char * path, unsigned long length) { - return do_sys_truncate(path, length); + /* on 32-bit boxen it will cut the range 2^31--2^32-1 off */ + return do_sys_truncate(path, (long)length); } -static inline long do_sys_ftruncate(unsigned int fd, loff_t length) +static inline long do_sys_ftruncate(unsigned int fd, loff_t length, int small) { struct inode * inode; struct dentry *dentry; @@ -162,13 +169,24 @@ file = fget(fd); if (!file) goto out; + + /* explicitly opened as large or we are on 64-bit box */ + if (file->f_flags & O_LARGEFILE) + small = 0; + dentry = file->f_dentry; inode = dentry->d_inode; - error = -EACCES; + error = -EINVAL; if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE)) goto out_putf; + + error = -EINVAL; + /* Cannot ftruncate over 2^31 bytes without large file support */ + if (small && length > MAX_NON_LFS) + goto out_putf; + error = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) + if (IS_APPEND(inode)) goto out_putf; error = locks_verify_truncate(inode, file, length); @@ -182,7 +200,7 @@ asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length) { - return do_sys_ftruncate(fd, length); + return do_sys_ftruncate(fd, length, 1); } /* LFS versions of truncate are only needed on 32 bit machines */ @@ -194,7 +212,7 @@ asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length) { - return do_sys_ftruncate(fd, length); + return do_sys_ftruncate(fd, length, 0); } #endif @@ -506,7 +524,7 @@ error = -ENOENT; if (!(inode = dentry->d_inode)) { - printk("chown_common: NULL inode\n"); + printk(KERN_ERR "chown_common: NULL inode\n"); goto out; } error = -EROFS; @@ -553,7 +571,7 @@ newattrs.ia_mode &= ~S_ISGID; newattrs.ia_valid |= ATTR_MODE; } - error = DQUOT_TRANSFER(dentry, &newattrs); + error = notify_change(dentry, &newattrs); out: return error; } @@ -634,6 +652,7 @@ { struct file * f; struct inode *inode; + static LIST_HEAD(kill_list); int error; error = -ENFILE; @@ -654,8 +673,17 @@ f->f_pos = 0; f->f_reada = 0; f->f_op = fops_get(inode->i_fop); - if (inode->i_sb) - file_move(f, &inode->i_sb->s_files); + file_move(f, &inode->i_sb->s_files); + + /* preallocate kiobuf for O_DIRECT */ + f->f_iobuf = NULL; + f->f_iobuf_lock = 0; + if (f->f_flags & O_DIRECT) { + error = alloc_kiovec(1, &f->f_iobuf); + if (error) + goto cleanup_all; + } + if (f->f_op && f->f_op->open) { error = f->f_op->open(inode,f); if (error) @@ -666,9 +694,12 @@ return f; cleanup_all: + if (f->f_iobuf) + free_kiovec(1, &f->f_iobuf); fops_put(f->f_op); if (f->f_mode & FMODE_WRITE) put_write_access(inode); + file_move(f, &kill_list); /* out of the way.. */ f->f_dentry = NULL; f->f_vfsmnt = NULL; cleanup_file: @@ -730,7 +761,7 @@ #if 1 /* Sanity check */ if (files->fd[fd] != NULL) { - printk("get_unused_fd: slot %d not NULL!\n", fd); + printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd); files->fd[fd] = NULL; } #endif @@ -793,7 +824,7 @@ int retval; if (!file_count(filp)) { - printk("VFS: Close: file count is 0\n"); + printk(KERN_ERR "VFS: Close: file count is 0\n"); return 0; } retval = 0; @@ -847,3 +878,18 @@ } return -EPERM; } + +/* + * Called when an inode is about to be open. + * We use this to disallow opening RW large files on 32bit systems if + * the caller didn't specify O_LARGEFILE. On 64bit systems we force + * on this flag in sys_open. + */ +int generic_file_open(struct inode * inode, struct file * filp) +{ + if (!(filp->f_flags & O_LARGEFILE) && inode->i_size > MAX_NON_LFS) + return -EFBIG; + return 0; +} + +EXPORT_SYMBOL(generic_file_open); Index: pipe.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/pipe.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- pipe.c 25 Feb 2001 23:14:46 -0000 1.1.1.2 +++ pipe.c 9 Apr 2002 13:19:32 -0000 1.2 @@ -476,7 +476,7 @@ static struct inode * get_pipe_inode(void) { - struct inode *inode = get_empty_inode(); + struct inode *inode = new_inode(pipe_mnt->mnt_sb); if (!inode) goto fail_inode; @@ -485,7 +485,6 @@ goto fail_iput; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1; inode->i_fop = &rdwr_pipe_fops; - inode->i_sb = pipe_mnt->mnt_sb; /* * Mark the inode dirty from the very beginning, @@ -630,8 +629,7 @@ return sb; } -static DECLARE_FSTYPE(pipe_fs_type, "pipefs", pipefs_read_super, - FS_NOMOUNT|FS_SINGLE); +static DECLARE_FSTYPE(pipe_fs_type, "pipefs", pipefs_read_super, FS_NOMOUNT); static int __init init_pipe_fs(void) { @@ -650,7 +648,7 @@ static void __exit exit_pipe_fs(void) { unregister_filesystem(&pipe_fs_type); - kern_umount(pipe_mnt); + mntput(pipe_mnt); } module_init(init_pipe_fs) |