lkml.org 
[lkml]   [1999]   [Jan]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: Linux 2.2.0pre2


On Wed, 30 Dec 1998, Linus Torvalds wrote:

>
> Well, some people obviously had problems with the first 2.2.0pre, so
> there's a second one there. Most of it is almost purely syntactic sugar:
> configuration issues and jiffies wraparound, but there were a few problems
> wrt some IDE disk geometry stuff in particular that made 2.2.0pre1 not
> boot for some people.
>
> Other real changes:
> - nfsd updated, and we have an official maintainer for knfsd (and I was
> happy by how many people were ready to stand up for it. Good show,
> guys!)
> - network driver updates (tulip/eepro)
> - some TCP fixes for occasional but nasty performance problems.
> - fix for an attack where you could cause a complete and utter lockup of
> the kernel as a normal user. Thanks to Michael Chastain for keeping the
> faith on this one and reminding me to fix it.
>
> If you haven't had problems with pre1, there should be no major cause to
> look at pre2. But if you haven't even looked at pre1 yet, please consider
> looking at the pre-2.2.0 kernels before it's too late. I'm going to be
> extremely rude to people who knew better but didn't test out the pre-
> kernels and then send me bug-reports on the released 2.2.0.
>
> Linus

D'oh. How rude would you be to those of us who are doing more or
less regular audits and may happen to find something nasty in the wrong
time? OK, anyway, we are in pre- times, so... Here's a bunch of
fixes/cleanups to VFS. Summary:

* sys_mknod() now uses ->create() for regular files. ->mknod()
methods of filesystems are cleaned up. In case of HFS cleanup
meant extermination of ->mknod(). RIP.
* new function init_special_inode() added to fs/devices.c; it
takes inode, mode and rdev and sets it up either as a device
inode or as a FIFO one (with init_fifo()).
* long-standing mess with pipes/fifos fixed.
Details: pipe-specific data in inode used to be available via
->u.pipe_i, fs-specific data - via *another* *field* *of* *the*
*same* *union*. We got out with it in ext2/minix/sysv/ufs
because the beginning of {ext2,...}_inode_info is used by
i_data[], which isn't used in case of FIFO's. Not so for other
filesystems.
I've taken pipe_i away from the union, made it separate from
struct inode (alloced in init_fifo() and get_pipe_inode(), freed
in clear_inode()) and added to struct inode a pointer to
pipe-specific part. It seems to work and it seems to be the
right thing.
* several fixes to UFS - it used to depend on definitions in
ext2_fs.h in ugly way and messed the mount-options logic.

Could you apply this stuff? It's against 2.2.0pre2.
TIA,
Al
Patch follows:

diff -urN linux.vanilla/fs/ChangeLog linux.bird/fs/ChangeLog
--- linux.vanilla/fs/ChangeLog Thu Dec 24 04:36:44 1998
+++ linux.bird/fs/ChangeLog Thu Dec 31 01:25:47 1998
@@ -143,6 +143,41 @@
do. Fixed.
* rmdir of immutable/append-only directory shouldn't be allowed. Fixed.

+Tue Dec 22 10:44:18 1998 AV
+ * namei.c (vfs_create, vfs_mknod): wrappers for ->create() and ->mknod()
+ methods.
+ * namei.c (do_create) Analog of do_mkdir(). Now sys_mknod() calls it if
+ we are ask to create a regular file. It means that ->mknod()
+ may be cleaned up (e.g. bad anecdote known as hfs_mknod() may
+ be killed. RIP (Rot In Purgatory)).
+ * hfs/*.c ->mknod() methods made NULL. He's dead, Jim.
+ * {ext2,minix,sysv,ufs}/namei.c (*_mknod) Cleaned up.
+
+Sat Dec 26 12:13:56 1998 AV
+ * ARRRGH! Handling of named pipes is *seriously* braindead. The
+ following changes are somewhat fixing it, but we really need
+ layered fs support. Here it comes:
+ * fifo.c, pipe.c, inode.c, include/linux/{pipe_fs_i.h,fs.h}:
+ pipe_inode_info moves out of struct inode.
+ struct inode gets a new field, pointing to pipe_inode_info.
+ Definitions in pipe_fs_i.h are switched to new scheme.
+ get_pipe_inode() and init_fifo() do allocation.
+ clear_inode() does deallocation.
+
+Wed Dec 30 21:49:47 1998 AV
+ * devices.c: (init_special_inode) New function. It generalizes
+ init_fifo(), i.e. you pass inode, mode and rdev and it
+ sets the inode up corresponding to them. It doesn't belong
+ to particular filesystem, so it goes here.
+ Exported, indeed.
+ * coda/cnode.c, {ext2,minix,sysv,ufs}/{namei,inode}.c,
+ {isofs,qnx4,nfs,umsdos}/inode.c:
+ Handling of special inodes switched to init_special_inode.
+ romfs/inode.c, proc/openpromfs.c and romfs/inode.c are odd. They
+ use MKDEV explicitly (instead of to_kdev_t). Hmm... kdev_t
+ stuff belongs to aeb, oughtta ask him about it... For the
+ time being let's leave it as is.
+
Remains unfixed:
* UMSDOS_rename is broken. Call it with the dest. existing and being an
empty directory and you've got EBUSY. At least it doesn't do
@@ -161,7 +196,6 @@
wrt locking. Moreover, it would give strong lookup atomicity.
But it's a lot of changes to lookup and dcache code, so it will
go after the fs drivers' cleanup.
- * hfs allows mknod. Only for regular files ;-/ IMHO it's bogus.
* affs allows HARD links to directories. VFS is, to put it politely,
not too ready to cope with _that_. And I'm not sure it should
be - looks like they are pretty much similar to symlinks.
@@ -174,3 +208,4 @@
Stuff related to retries still needs cleanup/fixing.
Looks like I've found an extremely low-probability race
there...
+ * qnx4_read_inode: it doesn't set i_rdev for devices.
diff -urN linux.vanilla/fs/coda/cnode.c linux.bird/fs/coda/cnode.c
--- linux.vanilla/fs/coda/cnode.c Thu Dec 24 04:36:45 1998
+++ linux.bird/fs/coda/cnode.c Thu Dec 31 01:25:47 1998
@@ -29,21 +29,8 @@
inode->i_op = &coda_dir_inode_operations;
else if (S_ISLNK(inode->i_mode))
inode->i_op = &coda_symlink_inode_operations;
- else if (S_ISCHR(inode->i_mode)) {
- inode->i_op = &chrdev_inode_operations;
- inode->i_rdev = to_kdev_t(attr->va_rdev);
- } else if (S_ISBLK(inode->i_mode)) {
- inode->i_op = &blkdev_inode_operations;
- inode->i_rdev = to_kdev_t(attr->va_rdev);
- } else if (S_ISFIFO(inode->i_mode))
- init_fifo(inode);
- else if (S_ISSOCK(inode->i_mode))
- inode->i_op = NULL;
- else {
- printk ("coda_fill_inode: what's this? i_mode = %o\n",
- inode->i_mode);
- inode->i_op = NULL;
- }
+ else
+ init_special_inode(inode, inode->i_mode, attr->va_rdev);
}

/* this is effectively coda_iget:
diff -urN linux.vanilla/fs/devices.c linux.bird/fs/devices.c
--- linux.vanilla/fs/devices.c Wed Dec 30 20:24:29 1998
+++ linux.bird/fs/devices.c Thu Dec 31 01:25:47 1998
@@ -370,3 +370,21 @@
sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));
return buffer;
}
+
+void init_special_inode(struct inode *inode, umode_t mode, int rdev)
+{
+ inode->i_mode = mode;
+ inode->i_op = NULL;
+ if (S_ISCHR(mode)) {
+ inode->i_op = &chrdev_inode_operations;
+ inode->i_rdev = to_kdev_t(rdev);
+ } else if (S_ISBLK(mode)) {
+ inode->i_op = &blkdev_inode_operations;
+ inode->i_rdev = to_kdev_t(rdev);
+ } else if (S_ISFIFO(mode))
+ init_fifo(inode);
+ else if (S_ISSOCK(mode))
+ ;
+ else
+ printk(KERN_DEBUG "init_special_inode: bogus imode (%o)\n", mode);
+}
diff -urN linux.vanilla/fs/ext2/inode.c linux.bird/fs/ext2/inode.c
--- linux.vanilla/fs/ext2/inode.c Wed May 6 13:56:05 1998
+++ linux.bird/fs/ext2/inode.c Thu Dec 31 01:25:47 1998
@@ -559,15 +559,11 @@
if (inode->u.ext2_i.i_prealloc_count)
ext2_error (inode->i_sb, "ext2_read_inode",
"New inode has non-zero prealloc count!");
- if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
- inode->i_rdev = to_kdev_t(le32_to_cpu(raw_inode->i_block[0]));
- else if (S_ISLNK(inode->i_mode) && !inode->i_blocks)
+ if (S_ISLNK(inode->i_mode) && !inode->i_blocks)
for (block = 0; block < EXT2_N_BLOCKS; block++)
inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
else for (block = 0; block < EXT2_N_BLOCKS; block++)
inode->u.ext2_i.i_data[block] = le32_to_cpu(raw_inode->i_block[block]);
- brelse (bh);
- inode->i_op = NULL;
if (inode->i_ino == EXT2_ACL_IDX_INO ||
inode->i_ino == EXT2_ACL_DATA_INO)
/* Nothing to do */ ;
@@ -577,12 +573,10 @@
inode->i_op = &ext2_dir_inode_operations;
else if (S_ISLNK(inode->i_mode))
inode->i_op = &ext2_symlink_inode_operations;
- else if (S_ISCHR(inode->i_mode))
- inode->i_op = &chrdev_inode_operations;
- else if (S_ISBLK(inode->i_mode))
- inode->i_op = &blkdev_inode_operations;
- else if (S_ISFIFO(inode->i_mode))
- init_fifo(inode);
+ else
+ init_special_inode(inode, inode->i_mode,
+ le32_to_cpu(raw_inode->i_block[0]));
+ brelse (bh);
inode->i_attr_flags = 0;
if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) {
inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS;
diff -urN linux.vanilla/fs/ext2/namei.c linux.bird/fs/ext2/namei.c
--- linux.vanilla/fs/ext2/namei.c Thu Dec 24 04:36:46 1998
+++ linux.bird/fs/ext2/namei.c Thu Dec 31 01:25:47 1998
@@ -418,36 +418,23 @@
goto out;

inode->i_uid = current->fsuid;
- inode->i_mode = mode;
- inode->i_op = NULL;
+ init_special_inode(inode, mode, rdev);
bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
if (!bh)
goto out_no_entry;
de->inode = cpu_to_le32(inode->i_ino);
dir->i_version = ++event;
- if (S_ISREG(inode->i_mode)) {
- inode->i_op = &ext2_file_inode_operations;
- if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
- EXT2_FEATURE_INCOMPAT_FILETYPE))
- de->file_type = EXT2_FT_REG_FILE;
- } else if (S_ISCHR(inode->i_mode)) {
- inode->i_op = &chrdev_inode_operations;
- if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
- EXT2_FEATURE_INCOMPAT_FILETYPE))
+ if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
+ EXT2_FEATURE_INCOMPAT_FILETYPE)) {
+ if (S_ISCHR(inode->i_mode)) {
de->file_type = EXT2_FT_CHRDEV;
- } else if (S_ISBLK(inode->i_mode)) {
- inode->i_op = &blkdev_inode_operations;
- if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
- EXT2_FEATURE_INCOMPAT_FILETYPE))
+ } else if (S_ISBLK(inode->i_mode)) {
de->file_type = EXT2_FT_BLKDEV;
- } else if (S_ISFIFO(inode->i_mode)) {
- init_fifo(inode);
- if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
- EXT2_FEATURE_INCOMPAT_FILETYPE))
+ } else if (S_ISFIFO(inode->i_mode)) {
de->file_type = EXT2_FT_FIFO;
+ }
}
- if (S_ISBLK(mode) || S_ISCHR(mode))
- inode->i_rdev = to_kdev_t(rdev);
+
mark_inode_dirty(inode);
mark_buffer_dirty(bh, 1);
if (IS_SYNC(dir)) {
diff -urN linux.vanilla/fs/fifo.c linux.bird/fs/fifo.c
--- linux.vanilla/fs/fifo.c Fri Nov 20 09:38:42 1998
+++ linux.bird/fs/fifo.c Thu Dec 31 01:25:47 1998
@@ -5,6 +5,7 @@
*/

#include <linux/mm.h>
+#include <linux/malloc.h>

static int fifo_open(struct inode * inode,struct file * filp)
{
@@ -151,10 +152,17 @@
void init_fifo(struct inode * inode)
{
inode->i_op = &fifo_inode_operations;
+ /* XXX - we should use kmem_cache_alloc */
+ inode->pipe_i=kmalloc(sizeof(struct pipe_inode_info),GFP_KERNEL);
+ if (!inode->pipe_i)
+ goto out_no_mem;
PIPE_LOCK(*inode) = 0;
PIPE_BASE(*inode) = NULL;
PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0;
PIPE_WAIT(*inode) = NULL;
PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
+ return;
+out_no_mem:
+ inode->i_op = NULL;
}
diff -urN linux.vanilla/fs/hfs/ChangeLog linux.bird/fs/hfs/ChangeLog
--- linux.vanilla/fs/hfs/ChangeLog Wed Dec 30 20:24:29 1998
+++ linux.bird/fs/hfs/ChangeLog Thu Dec 31 01:25:47 1998
@@ -1,3 +1,9 @@
+1998-12-22 Al "I never munge" Viro <viro@math.psu.edu>
+
+ * dir*.c: Since handling of S_IFREG case in mknod had been switched to
+ ->create() method all ->mknod() methods here became no-ops. Removed.
+ For details of VFS changes see fs/namei.c:sys_mknod().
+
1998-12-20 a sun <asun@hecate.darksunrising.blah>

* bdelete.c (del_root): assign bthLNode and bthFNode only if the
diff -urN linux.vanilla/fs/hfs/dir.c linux.bird/fs/hfs/dir.c
--- linux.vanilla/fs/hfs/dir.c Thu Dec 24 04:36:46 1998
+++ linux.bird/fs/hfs/dir.c Thu Dec 31 01:25:47 1998
@@ -255,31 +255,6 @@
}

/*
- * hfs_mknod()
- *
- * This is the mknod() entry in the inode_operations structure for
- * regular HFS directories. The purpose is to create a new entry
- * in a directory, given the inode for the parent directory and the
- * name (and its length) and the mode of the new entry (and the device
- * number if the entry is to be a device special file).
- *
- * HFS only supports regular files and directories and Linux disallows
- * using mknod() to create directories. Thus we just check the arguments
- * and call hfs_create().
- */
-int hfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
-{
- if (!dir)
- return -ENOENT;
-
- /* the only thing we currently do. */
- if (S_ISREG(mode))
- return hfs_create(dir, dentry, mode);
-
- return -EPERM;
-}
-
-/*
* hfs_unlink()
*
* This is the unlink() entry in the inode_operations structure for
diff -urN linux.vanilla/fs/hfs/dir_cap.c linux.bird/fs/hfs/dir_cap.c
--- linux.vanilla/fs/hfs/dir_cap.c Fri Nov 13 18:02:38 1998
+++ linux.bird/fs/hfs/dir_cap.c Thu Dec 31 01:25:47 1998
@@ -83,7 +83,7 @@
NULL, /* symlink */
hfs_mkdir, /* mkdir */
hfs_rmdir, /* rmdir */
- hfs_mknod, /* mknod */
+ NULL, /* mknod */
hfs_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
diff -urN linux.vanilla/fs/hfs/dir_dbl.c linux.bird/fs/hfs/dir_dbl.c
--- linux.vanilla/fs/hfs/dir_dbl.c Fri Nov 13 18:02:38 1998
+++ linux.bird/fs/hfs/dir_dbl.c Thu Dec 31 01:25:47 1998
@@ -27,7 +27,6 @@
static int dbl_readdir(struct file *, void *, filldir_t);
static int dbl_create(struct inode *, struct dentry *, int);
static int dbl_mkdir(struct inode *, struct dentry *, int);
-static int dbl_mknod(struct inode *, struct dentry *, int, int);
static int dbl_unlink(struct inode *, struct dentry *);
static int dbl_rmdir(struct inode *, struct dentry *);
static int dbl_rename(struct inode *, struct dentry *,
@@ -83,7 +82,7 @@
NULL, /* symlink */
dbl_mkdir, /* mkdir */
dbl_rmdir, /* rmdir */
- dbl_mknod, /* mknod */
+ NULL, /* mknod */
dbl_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
@@ -322,28 +321,6 @@
error = -EEXIST;
} else {
error = hfs_mkdir(parent, dentry, mode);
- }
- return error;
-}
-
-/*
- * dbl_mknod()
- *
- * This is the mknod() entry in the inode_operations structure for
- * regular HFS directories. The purpose is to create a new entry
- * in a directory, given the inode for the parent directory and the
- * name (and its length) and the mode of the new entry (and the device
- * number if the entry is to be a device special file).
- */
-static int dbl_mknod(struct inode *dir, struct dentry *dentry,
- int mode, int rdev)
-{
- int error;
-
- if (is_hdr(dir, dentry->d_name.name, dentry->d_name.len)) {
- error = -EEXIST;
- } else {
- error = hfs_mknod(dir, dentry, mode, rdev);
}
return error;
}
diff -urN linux.vanilla/fs/hfs/dir_nat.c linux.bird/fs/hfs/dir_nat.c
--- linux.vanilla/fs/hfs/dir_nat.c Fri Nov 13 18:02:38 1998
+++ linux.bird/fs/hfs/dir_nat.c Thu Dec 31 01:25:47 1998
@@ -89,7 +89,7 @@
NULL, /* symlink */
hfs_mkdir, /* mkdir */
nat_rmdir, /* rmdir */
- hfs_mknod, /* mknod */
+ NULL, /* mknod */
hfs_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
diff -urN linux.vanilla/fs/inode.c linux.bird/fs/inode.c
--- linux.vanilla/fs/inode.c Fri Nov 13 18:02:03 1998
+++ linux.bird/fs/inode.c Thu Dec 31 01:25:48 1998
@@ -11,6 +11,8 @@
#include <linux/init.h>
#include <linux/quotaops.h>

+#include <linux/malloc.h>
+
/*
* New inode.c implementation.
*
@@ -228,10 +230,23 @@
wait_on_inode(inode);
if (IS_QUOTAINIT(inode))
DQUOT_DROP(inode);
+ /* Sorry, but let's keep the main path clean */
+ if (inode->pipe_i)
+ goto is_fifo;
+do_clear:
if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->clear_inode)
inode->i_sb->s_op->clear_inode(inode);

inode->i_state = 0;
+ return;
+
+is_fifo:
+ {
+ void *p=inode->pipe_i;
+ inode->pipe_i=NULL;
+ kfree(p);
+ goto do_clear;
+ }
}

/*
@@ -505,6 +520,7 @@
inode->i_size = 0;
memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
sema_init(&inode->i_sem, 1);
+ inode->pipe_i = NULL;
}

/*
diff -urN linux.vanilla/fs/isofs/inode.c linux.bird/fs/isofs/inode.c
--- linux.vanilla/fs/isofs/inode.c Thu Dec 31 00:40:29 1998
+++ linux.bird/fs/isofs/inode.c Thu Dec 31 01:25:48 1998
@@ -1210,12 +1210,9 @@
inode->i_op = &isofs_dir_inode_operations;
else if (S_ISLNK(inode->i_mode))
inode->i_op = &isofs_symlink_inode_operations;
- else if (S_ISCHR(inode->i_mode))
- inode->i_op = &chrdev_inode_operations;
- else if (S_ISBLK(inode->i_mode))
- inode->i_op = &blkdev_inode_operations;
- else if (S_ISFIFO(inode->i_mode))
- init_fifo(inode);
+ else
+ /* XXX - parse_rock_ridge_inode() had already set i_rdev. */
+ init_special_inode(inode, inode->i_mode, inode->i_rdev);
}
return;

diff -urN linux.vanilla/fs/minix/inode.c linux.bird/fs/minix/inode.c
--- linux.vanilla/fs/minix/inode.c Sat Nov 28 02:08:08 1998
+++ linux.bird/fs/minix/inode.c Thu Dec 31 01:25:48 1998
@@ -757,23 +757,17 @@
inode->i_size = raw_inode->i_size;
inode->i_mtime = inode->i_atime = inode->i_ctime = raw_inode->i_time;
inode->i_blocks = inode->i_blksize = 0;
- if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
- inode->i_rdev = to_kdev_t(raw_inode->i_zone[0]);
- else for (block = 0; block < 9; block++)
+ for (block = 0; block < 9; block++)
inode->u.minix_i.u.i1_data[block] = raw_inode->i_zone[block];
- brelse(bh);
if (S_ISREG(inode->i_mode))
inode->i_op = &minix_file_inode_operations;
else if (S_ISDIR(inode->i_mode))
inode->i_op = &minix_dir_inode_operations;
else if (S_ISLNK(inode->i_mode))
inode->i_op = &minix_symlink_inode_operations;
- else if (S_ISCHR(inode->i_mode))
- inode->i_op = &chrdev_inode_operations;
- else if (S_ISBLK(inode->i_mode))
- inode->i_op = &blkdev_inode_operations;
- else if (S_ISFIFO(inode->i_mode))
- init_fifo(inode);
+ else
+ init_special_inode(inode, inode->i_mode, raw_inode->i_zone[0]);
+ brelse(bh);
}

/*
@@ -813,23 +807,17 @@
inode->i_atime = raw_inode->i_atime;
inode->i_ctime = raw_inode->i_ctime;
inode->i_blocks = inode->i_blksize = 0;
- if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
- inode->i_rdev = to_kdev_t(raw_inode->i_zone[0]);
- else for (block = 0; block < 10; block++)
+ for (block = 0; block < 10; block++)
inode->u.minix_i.u.i2_data[block] = raw_inode->i_zone[block];
- brelse(bh);
if (S_ISREG(inode->i_mode))
inode->i_op = &minix_file_inode_operations;
else if (S_ISDIR(inode->i_mode))
inode->i_op = &minix_dir_inode_operations;
else if (S_ISLNK(inode->i_mode))
inode->i_op = &minix_symlink_inode_operations;
- else if (S_ISCHR(inode->i_mode))
- inode->i_op = &chrdev_inode_operations;
- else if (S_ISBLK(inode->i_mode))
- inode->i_op = &blkdev_inode_operations;
- else if (S_ISFIFO(inode->i_mode))
- init_fifo(inode);
+ else
+ init_special_inode(inode, inode->i_mode, raw_inode->i_zone[0]);
+ brelse(bh);
}

/*
diff -urN linux.vanilla/fs/minix/namei.c linux.bird/fs/minix/namei.c
--- linux.vanilla/fs/minix/namei.c Thu Dec 24 04:36:46 1998
+++ linux.bird/fs/minix/namei.c Thu Dec 31 01:25:48 1998
@@ -263,18 +263,7 @@
if (!inode)
return -ENOSPC;
inode->i_uid = current->fsuid;
- inode->i_mode = mode;
- inode->i_op = NULL;
- if (S_ISREG(inode->i_mode))
- inode->i_op = &minix_file_inode_operations;
- else if (S_ISCHR(inode->i_mode))
- inode->i_op = &chrdev_inode_operations;
- else if (S_ISBLK(inode->i_mode))
- inode->i_op = &blkdev_inode_operations;
- else if (S_ISFIFO(inode->i_mode))
- init_fifo(inode);
- if (S_ISBLK(mode) || S_ISCHR(mode))
- inode->i_rdev = to_kdev_t(rdev);
+ init_special_inode(inode, mode, rdev);
mark_inode_dirty(inode);
error = minix_add_entry(dir, dentry->d_name.name, dentry->d_name.len, &bh, &de);
if (error) {
diff -urN linux.vanilla/fs/namei.c linux.bird/fs/namei.c
--- linux.vanilla/fs/namei.c Wed Dec 30 20:24:30 1998
+++ linux.bird/fs/namei.c Thu Dec 31 01:25:48 1998
@@ -610,6 +610,37 @@
return retval;
}

+int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
+{
+ int error;
+
+ error = may_create(dir, dentry);
+ if (error)
+ return error;
+
+ if (!dir->i_op || !dir->i_op->create)
+ return -EPERM;
+
+ DQUOT_INIT(dir);
+ return dir->i_op->create(dir, dentry, mode);
+}
+
+int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
+ dev_t dev)
+{
+ int error;
+
+ error = may_create(dir, dentry);
+ if (error)
+ return error;
+
+ if (!dir->i_op || !dir->i_op->mknod)
+ return -EPERM;
+
+ DQUOT_INIT(dir);
+ return dir->i_op->mknod(dir, dentry, mode, dev);
+}
+
/*
* open_namei()
*
@@ -638,39 +669,19 @@

acc_mode = ACC_MODE(flag);
if (flag & O_CREAT) {
- struct dentry *dir;
-
- error = -EEXIST;
- if (dentry->d_inode && (flag & O_EXCL))
- goto exit;
-
- dir = lock_parent(dentry);
+ struct dentry *dir = lock_parent(dentry);
error = PTR_ERR(dir);
if (IS_ERR(dir))
goto exit;

- /*
- * Somebody might have created the file while we
- * waited for the directory lock.. So we have to
- * re-do the existence test.
- */
- if (dentry->d_inode) {
- error = 0;
- if (flag & O_EXCL)
- error = -EEXIST;
- } else if ((error = may_create(dir->d_inode, dentry)) == 0) {
- if (!dir->d_inode->i_op || !dir->d_inode->i_op->create)
- error = -EACCES;
- else {
- DQUOT_INIT(dir->d_inode);
- error = dir->d_inode->i_op->create(dir->d_inode, dentry, mode);
- /* Don't check for write permission, don't truncate */
- acc_mode = 0;
- flag &= ~O_TRUNC;
- }
- }
+ error = vfs_create(dir->d_inode, dentry, mode);
+
unlock_dir(dir);
- if (error)
+
+ if (!error) {
+ acc_mode = 0;
+ flag &= ~O_TRUNC;
+ } else if (error != -EEXIST || (flag & O_EXCL))
goto exit;
}

@@ -748,6 +759,32 @@
return ERR_PTR(error);
}

+static inline int do_create(const char * filename, int mode)
+{
+ int error;
+ struct dentry *dir;
+ struct dentry *dentry;
+
+ mode &= ~current->fs->umask;
+ dentry = lookup_dentry(filename, NULL, LOOKUP_FOLLOW);
+ error = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
+ goto exit;
+
+ dir = lock_parent(dentry);
+ error = PTR_ERR(dir);
+ if (IS_ERR(dir))
+ goto exit_dput;
+
+ error = vfs_create(dir->d_inode, dentry, mode);
+
+ unlock_dir(dir);
+exit_dput:
+ dput(dentry);
+exit:
+ return error;
+}
+
struct dentry * do_mknod(const char * filename, int mode, dev_t dev)
{
int error;
@@ -764,17 +801,8 @@
if (IS_ERR(dir))
goto exit;

- error = may_create(dir->d_inode, dentry);
- if (error)
- goto exit_lock;
-
- error = -EPERM;
- if (!dir->d_inode->i_op || !dir->d_inode->i_op->mknod)
- goto exit_lock;
+ error = vfs_mknod(dir->d_inode, dentry, mode, dev);

- DQUOT_INIT(dir->d_inode);
- error = dir->d_inode->i_op->mknod(dir->d_inode, dentry, mode, dev);
-exit_lock:
retval = ERR_PTR(error);
if (!error)
retval = dget(dentry);
@@ -806,13 +834,16 @@
tmp = getname(filename);
error = PTR_ERR(tmp);
if (!IS_ERR(tmp)) {
- struct dentry * dentry = do_mknod(tmp,mode,dev);
+ if (!S_ISREG(mode)) {
+ struct dentry * dentry = do_mknod(tmp,mode,dev);
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ dput(dentry);
+ error = 0;
+ }
+ } else
+ error = do_create(tmp,mode);
putname(tmp);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- dput(dentry);
- error = 0;
- }
}
out:
unlock_kernel();
diff -urN linux.vanilla/fs/nfs/inode.c linux.bird/fs/nfs/inode.c
--- linux.vanilla/fs/nfs/inode.c Wed Dec 30 20:24:31 1998
+++ linux.bird/fs/nfs/inode.c Thu Dec 31 01:25:48 1998
@@ -425,16 +425,8 @@
inode->i_op = &nfs_dir_inode_operations;
else if (S_ISLNK(inode->i_mode))
inode->i_op = &nfs_symlink_inode_operations;
- else if (S_ISCHR(inode->i_mode)) {
- inode->i_op = &chrdev_inode_operations;
- inode->i_rdev = to_kdev_t(fattr->rdev);
- } else if (S_ISBLK(inode->i_mode)) {
- inode->i_op = &blkdev_inode_operations;
- inode->i_rdev = to_kdev_t(fattr->rdev);
- } else if (S_ISFIFO(inode->i_mode))
- init_fifo(inode);
else
- inode->i_op = NULL;
+ init_special_inode(inode, inode->i_mode, fattr->rdev);
/*
* Preset the size and mtime, as there's no need
* to invalidate the caches.
diff -urN linux.vanilla/fs/pipe.c linux.bird/fs/pipe.c
--- linux.vanilla/fs/pipe.c Fri Nov 20 09:38:43 1998
+++ linux.bird/fs/pipe.c Thu Dec 31 01:25:48 1998
@@ -7,6 +7,7 @@
#include <linux/mm.h>
#include <linux/file.h>
#include <linux/poll.h>
+#include <linux/malloc.h>

#include <asm/uaccess.h>

@@ -404,36 +405,48 @@
{
extern struct inode_operations pipe_inode_operations;
struct inode *inode = get_empty_inode();
+ unsigned long page;

- if (inode) {
- unsigned long page = __get_free_page(GFP_USER);
+ if (!inode)
+ goto fail_inode;

- if (!page) {
- iput(inode);
- inode = NULL;
- } else {
- PIPE_BASE(*inode) = (char *) page;
- inode->i_op = &pipe_inode_operations;
- PIPE_WAIT(*inode) = NULL;
- PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
- PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0;
- PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
- PIPE_LOCK(*inode) = 0;
- /*
- * Mark the inode dirty from the very beginning,
- * that way it will never be moved to the dirty
- * list because "mark_inode_dirty()" will think
- * that it already _is_ on the dirty list.
- */
- inode->i_state = I_DIRTY;
- inode->i_mode = S_IFIFO | S_IRUSR | S_IWUSR;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- inode->i_blksize = PAGE_SIZE;
- }
- }
+ page = __get_free_page(GFP_USER);
+
+ if (!page)
+ goto fail_iput;
+
+ /* XXX */
+ inode->pipe_i = kmalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
+ if (!inode->pipe_i)
+ goto fail_pipe_i;
+
+ PIPE_BASE(*inode) = (char *) page;
+ inode->i_op = &pipe_inode_operations;
+ PIPE_WAIT(*inode) = NULL;
+ PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
+ PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0;
+ PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
+ PIPE_LOCK(*inode) = 0;
+ /*
+ * Mark the inode dirty from the very beginning,
+ * that way it will never be moved to the dirty
+ * list because "mark_inode_dirty()" will think
+ * that it already _is_ on the dirty list.
+ */
+ inode->i_state = I_DIRTY;
+ inode->i_mode = S_IFIFO | S_IRUSR | S_IWUSR;
+ inode->i_uid = current->fsuid;
+ inode->i_gid = current->fsgid;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_blksize = PAGE_SIZE;
return inode;
+
+fail_pipe_i:
+ free_page(page);
+fail_iput:
+ iput(inode);
+fail_inode:
+ return NULL;
}

struct inode_operations pipe_inode_operations = {
diff -urN linux.vanilla/fs/qnx4/inode.c linux.bird/fs/qnx4/inode.c
--- linux.vanilla/fs/qnx4/inode.c Fri Nov 13 18:00:05 1998
+++ linux.bird/fs/qnx4/inode.c Thu Dec 31 01:25:48 1998
@@ -408,29 +408,16 @@

memcpy(&inode->u.qnx4_i, (struct qnx4_inode_info *) raw_inode, QNX4_DIR_ENTRY_SIZE);
inode->i_op = &qnx4_file_inode_operations;
- if (S_ISREG(inode->i_mode)) {
+ if (S_ISREG(inode->i_mode))
inode->i_op = &qnx4_file_inode_operations;
- } else {
- if (S_ISDIR(inode->i_mode)) {
- inode->i_op = &qnx4_dir_inode_operations;
- } else {
- if (S_ISLNK(inode->i_mode)) {
- inode->i_op = &qnx4_symlink_inode_operations;
- } else {
- if (S_ISCHR(inode->i_mode)) {
- inode->i_op = &chrdev_inode_operations;
- } else {
- if (S_ISBLK(inode->i_mode)) {
- inode->i_op = &blkdev_inode_operations;
- } else {
- if (S_ISFIFO(inode->i_mode)) {
- init_fifo(inode);
- }
- }
- }
- }
- }
- }
+ else if (S_ISDIR(inode->i_mode))
+ inode->i_op = &qnx4_dir_inode_operations;
+ else if (S_ISLNK(inode->i_mode))
+ inode->i_op = &qnx4_symlink_inode_operations;
+ else
+ /* HUH??? Where is device number? Oh, well... */
+ init_special_inode(inode, inode->i_mode, 0);
+
brelse(bh);
}

diff -urN linux.vanilla/fs/sysv/inode.c linux.bird/fs/sysv/inode.c
--- linux.vanilla/fs/sysv/inode.c Thu Dec 31 00:40:31 1998
+++ linux.bird/fs/sysv/inode.c Thu Dec 31 01:25:48 1998
@@ -884,7 +884,7 @@
}
inode->i_blocks = inode->i_blksize = 0;
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
- inode->i_rdev = to_kdev_t(raw_inode->i_a.i_rdev);
+ ;
else
if (sb->sv_convert)
for (block = 0; block < 10+1+1+1; block++)
@@ -894,19 +894,15 @@
for (block = 0; block < 10+1+1+1; block++)
inode->u.sysv_i.i_data[block] =
read3byte(&raw_inode->i_a.i_addb[3*block]);
- brelse(bh);
if (S_ISREG(inode->i_mode))
inode->i_op = &sysv_file_inode_operations;
else if (S_ISDIR(inode->i_mode))
inode->i_op = &sysv_dir_inode_operations;
else if (S_ISLNK(inode->i_mode))
inode->i_op = &sysv_symlink_inode_operations;
- else if (S_ISCHR(inode->i_mode))
- inode->i_op = &chrdev_inode_operations;
- else if (S_ISBLK(inode->i_mode))
- inode->i_op = &blkdev_inode_operations;
- else if (S_ISFIFO(inode->i_mode))
- init_fifo(inode);
+ else
+ init_special_inode(inode, inode->i_mode, raw_inode->i_a.i_rdev);
+ brelse(bh);
}

/* To avoid inconsistencies between inodes in memory and inodes on disk. */
diff -urN linux.vanilla/fs/sysv/namei.c linux.bird/fs/sysv/namei.c
--- linux.vanilla/fs/sysv/namei.c Thu Dec 31 00:40:31 1998
+++ linux.bird/fs/sysv/namei.c Thu Dec 31 01:25:48 1998
@@ -251,18 +251,7 @@
if (!inode)
return -ENOSPC;
inode->i_uid = current->fsuid;
- inode->i_mode = mode;
- inode->i_op = NULL;
- if (S_ISREG(inode->i_mode))
- inode->i_op = &sysv_file_inode_operations;
- else if (S_ISCHR(inode->i_mode))
- inode->i_op = &chrdev_inode_operations;
- else if (S_ISBLK(inode->i_mode))
- inode->i_op = &blkdev_inode_operations;
- else if (S_ISFIFO(inode->i_mode))
- init_fifo(inode);
- if (S_ISBLK(mode) || S_ISCHR(mode))
- inode->i_rdev = to_kdev_t(rdev);
+ init_special_inode(inode, mode, rdev);
mark_inode_dirty(inode);
error = sysv_add_entry(dir, dentry->d_name.name,
dentry->d_name.len, &bh, &de);
diff -urN linux.vanilla/fs/ufs/ialloc.c linux.bird/fs/ufs/ialloc.c
--- linux.vanilla/fs/ufs/ialloc.c Fri Nov 13 18:02:04 1998
+++ linux.bird/fs/ufs/ialloc.c Thu Dec 31 01:25:48 1998
@@ -275,6 +275,7 @@
inode->i_nlink = 1;
inode->i_dev = sb->s_dev;
inode->i_uid = current->fsuid;
+#ifdef notyet
if (test_opt (sb, GRPID))
inode->i_gid = dir->i_gid;
else if (dir->i_mode & S_ISGID) {
@@ -283,6 +284,14 @@
mode |= S_ISGID;
} else
inode->i_gid = current->fsgid;
+#else
+ if (dir->i_mode & S_ISGID) {
+ inode->i_gid = dir->i_gid;
+ if (S_ISDIR(mode))
+ mode |= S_ISGID;
+ } else
+ inode->i_gid = current->fsgid;
+#endif

inode->i_ino = cg * uspi->s_ipg + bit;
inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat), not the fs block size */
diff -urN linux.vanilla/fs/ufs/inode.c linux.bird/fs/ufs/inode.c
--- linux.vanilla/fs/ufs/inode.c Fri Nov 13 18:02:04 1998
+++ linux.bird/fs/ufs/inode.c Thu Dec 31 01:25:48 1998
@@ -518,7 +518,7 @@
inode->u.ufs_i.i_lastfrag = howmany (inode->i_size, uspi->s_fsize);

if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
- inode->i_rdev = to_kdev_t(SWAB32(ufs_inode->ui_u2.ui_addr.ui_db[0]));
+ ;
else if (inode->i_blocks) {
for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++)
inode->u.ufs_i.i_u1.i_data[i] = ufs_inode->ui_u2.ui_addr.ui_db[i];
@@ -528,7 +528,6 @@
inode->u.ufs_i.i_u1.i_symlink[i] = ufs_inode->ui_u2.ui_symlink[i];
}

- brelse (bh);

inode->i_op = NULL;

@@ -538,12 +537,11 @@
inode->i_op = &ufs_dir_inode_operations;
else if (S_ISLNK(inode->i_mode))
inode->i_op = &ufs_symlink_inode_operations;
- else if (S_ISCHR(inode->i_mode))
- inode->i_op = &chrdev_inode_operations;
- else if (S_ISBLK(inode->i_mode))
- inode->i_op = &blkdev_inode_operations;
- else if (S_ISFIFO(inode->i_mode))
- init_fifo(inode);
+ else
+ init_special_inode(inode, inode->i_mode,
+ SWAB32(ufs_inode->ui_u2.ui_addr.ui_db[0]));
+
+ brelse (bh);

#ifdef UFS_INODE_DEBUG_MORE
ufs_print_inode (inode);
diff -urN linux.vanilla/fs/ufs/namei.c linux.bird/fs/ufs/namei.c
--- linux.vanilla/fs/ufs/namei.c Thu Dec 24 04:36:47 1998
+++ linux.bird/fs/ufs/namei.c Thu Dec 31 01:25:48 1998
@@ -471,18 +471,7 @@
goto out;

inode->i_uid = current->fsuid;
- inode->i_mode = mode;
- inode->i_op = NULL;
- if (S_ISREG(inode->i_mode))
- inode->i_op = &ufs_file_inode_operations;
- else if (S_ISCHR(inode->i_mode))
- inode->i_op = &chrdev_inode_operations;
- else if (S_ISBLK(inode->i_mode))
- inode->i_op = &blkdev_inode_operations;
- else if (S_ISFIFO(inode->i_mode))
- init_fifo(inode);
- if (S_ISBLK(mode) || S_ISCHR(mode))
- inode->i_rdev = to_kdev_t(rdev);
+ init_special_inode(inode, mode, rdev);
mark_inode_dirty(inode);
bh = ufs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
if (!bh)
diff -urN linux.vanilla/fs/umsdos/inode.c linux.bird/fs/umsdos/inode.c
--- linux.vanilla/fs/umsdos/inode.c Mon Dec 21 02:26:51 1998
+++ linux.bird/fs/umsdos/inode.c Thu Dec 31 01:25:48 1998
@@ -168,13 +168,8 @@
umsdos_setup_dir(dentry);
} else if (S_ISLNK (inode->i_mode)) {
inode->i_op = &umsdos_symlink_inode_operations;
- } else if (S_ISCHR (inode->i_mode)) {
- inode->i_op = &chrdev_inode_operations;
- } else if (S_ISBLK (inode->i_mode)) {
- inode->i_op = &blkdev_inode_operations;
- } else if (S_ISFIFO (inode->i_mode)) {
- init_fifo (inode);
- }
+ } else
+ init_special_inode(inode, inode->i_mode, inode->i_rdev);
}


diff -urN linux.vanilla/include/linux/fs.h linux.bird/include/linux/fs.h
--- linux.vanilla/include/linux/fs.h Wed Dec 30 20:24:32 1998
+++ linux.bird/include/linux/fs.h Thu Dec 31 01:25:48 1998
@@ -370,7 +370,6 @@
int i_writecount;
unsigned int i_attr_flags;
union {
- struct pipe_inode_info pipe_i;
struct minix_inode_info minix_i;
struct ext2_inode_info ext2_i;
struct hpfs_inode_info hpfs_i;
@@ -391,6 +390,7 @@
struct socket socket_i;
void *generic_ip;
} u;
+ struct pipe_inode_info *pipe_i; /* XXX */
};

/* Inode state bits.. */
@@ -712,6 +712,7 @@
extern char * bdevname(kdev_t dev);
extern char * cdevname(kdev_t dev);
extern char * kdevname(kdev_t dev);
+extern void init_special_inode(struct inode *, umode_t, int);


extern void init_fifo(struct inode * inode);
diff -urN linux.vanilla/include/linux/hfs_fs.h linux.bird/include/linux/hfs_fs.h
--- linux.vanilla/include/linux/hfs_fs.h Sat Nov 28 02:08:10 1998
+++ linux.bird/include/linux/hfs_fs.h Thu Dec 31 01:25:48 1998
@@ -225,7 +225,6 @@
loff_t *);
extern int hfs_create(struct inode *, struct dentry *, int);
extern int hfs_mkdir(struct inode *, struct dentry *, int);
-extern int hfs_mknod(struct inode *, struct dentry *, int, int);
extern int hfs_unlink(struct inode *, struct dentry *);
extern int hfs_rmdir(struct inode *, struct dentry *);
extern int hfs_rename(struct inode *, struct dentry *,
diff -urN linux.vanilla/include/linux/pipe_fs_i.h linux.bird/include/linux/pipe_fs_i.h
--- linux.vanilla/include/linux/pipe_fs_i.h Wed Jul 16 13:26:21 1997
+++ linux.bird/include/linux/pipe_fs_i.h Thu Dec 31 01:25:48 1998
@@ -12,15 +12,15 @@
unsigned int writers;
};

-#define PIPE_WAIT(inode) ((inode).u.pipe_i.wait)
-#define PIPE_BASE(inode) ((inode).u.pipe_i.base)
-#define PIPE_START(inode) ((inode).u.pipe_i.start)
+#define PIPE_WAIT(inode) ((inode).pipe_i->wait)
+#define PIPE_BASE(inode) ((inode).pipe_i->base)
+#define PIPE_START(inode) ((inode).pipe_i->start)
#define PIPE_LEN(inode) ((inode).i_size)
-#define PIPE_RD_OPENERS(inode) ((inode).u.pipe_i.rd_openers)
-#define PIPE_WR_OPENERS(inode) ((inode).u.pipe_i.wr_openers)
-#define PIPE_READERS(inode) ((inode).u.pipe_i.readers)
-#define PIPE_WRITERS(inode) ((inode).u.pipe_i.writers)
-#define PIPE_LOCK(inode) ((inode).u.pipe_i.lock)
+#define PIPE_RD_OPENERS(inode) ((inode).pipe_i->rd_openers)
+#define PIPE_WR_OPENERS(inode) ((inode).pipe_i->wr_openers)
+#define PIPE_READERS(inode) ((inode).pipe_i->readers)
+#define PIPE_WRITERS(inode) ((inode).pipe_i->writers)
+#define PIPE_LOCK(inode) ((inode).pipe_i->lock)
#define PIPE_SIZE(inode) PIPE_LEN(inode)

#define PIPE_EMPTY(inode) (PIPE_SIZE(inode)==0)
diff -urN linux.vanilla/include/linux/ufs_fs.h linux.bird/include/linux/ufs_fs.h
--- linux.vanilla/include/linux/ufs_fs.h Fri Nov 13 18:02:08 1998
+++ linux.bird/include/linux/ufs_fs.h Thu Dec 31 01:25:48 1998
@@ -203,7 +203,7 @@
#define UFS_MAXNAMLEN 255
#define UFS_MAXMNTLEN 512
#define UFS_MAXCSBUFS 31
-#define UFS_LINK_MAX EXT2_LINK_MAX
+#define UFS_LINK_MAX 32000

/*
* UFS_DIR_PAD defines the directory entries boundaries
diff -urN linux.vanilla/kernel/ksyms.c linux.bird/kernel/ksyms.c
--- linux.vanilla/kernel/ksyms.c Thu Dec 31 00:40:34 1998
+++ linux.bird/kernel/ksyms.c Thu Dec 31 01:25:48 1998
@@ -346,6 +346,7 @@
EXPORT_SYMBOL(refile_buffer);
EXPORT_SYMBOL(nr_async_pages);
EXPORT_SYMBOL(___strtok);
+EXPORT_SYMBOL(init_special_inode);
EXPORT_SYMBOL(init_fifo);
EXPORT_SYMBOL(fifo_inode_operations);
EXPORT_SYMBOL(chrdev_inode_operations);


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:49    [W:0.182 / U:0.624 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site