|
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)
|