Commit c6145b38 authored by Linus Torvalds's avatar Linus Torvalds

Import 0.99.14j

parent 27c43263
VERSION = 0.99 VERSION = 0.99
PATCHLEVEL = 14 PATCHLEVEL = 14
ALPHA = i ALPHA = j
all: Version zImage all: Version zImage
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# #
# #
VERSION = 2.3 VERSION = 2.3b
TARGET_OS = linux TARGET_OS = linux
.c.s: .c.s:
......
...@@ -178,7 +178,7 @@ static int dsp_set_stereo(int mode) ...@@ -178,7 +178,7 @@ static int dsp_set_stereo(int mode)
{ {
DEB(printk("dsp_set_stereo(%d)\n",mode)); DEB(printk("dsp_set_stereo(%d)\n",mode));
if (mode) dsp_stereo=mode; dsp_stereo=mode;
return mode; return mode;
} }
......
/* /*
* linux/fs/ext2/acl.c * linux/fs/ext2/acl.c
* *
* Copyright (C) 1993 Remy Card (card@masi.ibp.fr) * Copyright (C) 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*/ */
/* /*
...@@ -12,7 +14,6 @@ ...@@ -12,7 +14,6 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/ext2_fs.h> #include <linux/ext2_fs.h>
#include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/stat.h> #include <linux/stat.h>
...@@ -25,10 +26,14 @@ int ext2_permission (struct inode * inode, int mask) ...@@ -25,10 +26,14 @@ int ext2_permission (struct inode * inode, int mask)
{ {
unsigned short mode = inode->i_mode; unsigned short mode = inode->i_mode;
/* Special case, access is always granted for root */ /*
* Special case, access is always granted for root
*/
if (suser ()) if (suser ())
return 1; return 1;
/* If no ACL, checks using the file mode */ /*
* If no ACL, checks using the file mode
*/
else if (current->euid == inode->i_uid) else if (current->euid == inode->i_uid)
mode >>= 6; mode >>= 6;
else if (in_group_p (inode->i_gid)) else if (in_group_p (inode->i_gid))
......
This diff is collapsed.
/* /*
* linux/fs/ext2/bitmap.c * linux/fs/ext2/bitmap.c
* *
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr) * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*/ */
#include <linux/fs.h> #include <linux/fs.h>
......
/* /*
* linux/fs/ext2/dcache.c * linux/fs/ext2/dcache.c
* *
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr) * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
* *
*/ */
...@@ -14,7 +16,6 @@ ...@@ -14,7 +16,6 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/ext2_fs.h> #include <linux/ext2_fs.h>
#include <linux/kernel.h>
#include <linux/string.h> #include <linux/string.h>
#ifndef DONT_USE_DCACHE #ifndef DONT_USE_DCACHE
......
/* /*
* linux/fs/ext2/dir.c * linux/fs/ext2/dir.c
* *
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr) * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
* *
* from * from
* *
...@@ -14,26 +16,32 @@ ...@@ -14,26 +16,32 @@
#include <asm/segment.h> #include <asm/segment.h>
#include <linux/autoconf.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/ext2_fs.h> #include <linux/ext2_fs.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/stat.h> #include <linux/stat.h>
#if 0 #ifndef CONFIG_EXT2_FS_DIR_READ
static int ext2_dir_read (struct inode * inode, struct file * filp, static int ext2_dir_read (struct inode * inode, struct file * filp,
char * buf, int count) char * buf, int count)
{ {
return -EISDIR; return -EISDIR;
} }
#else
int ext2_file_read (struct inode *, struct file *, char *, int);
#endif #endif
/* static */ int ext2_file_read (struct inode *, struct file *, char *, int);
static int ext2_readdir (struct inode *, struct file *, struct dirent *, int); static int ext2_readdir (struct inode *, struct file *, struct dirent *, int);
static struct file_operations ext2_dir_operations = { static struct file_operations ext2_dir_operations = {
NULL, /* lseek - default */ NULL, /* lseek - default */
#ifdef CONFIG_EXT2_FS_DIR_READ
ext2_file_read, /* read */ ext2_file_read, /* read */
#else
ext2_dir_read, /* read */
#endif
NULL, /* write - bad */ NULL, /* write - bad */
ext2_readdir, /* readdir */ ext2_readdir, /* readdir */
NULL, /* select - default */ NULL, /* select - default */
...@@ -92,9 +100,9 @@ int ext2_check_dir_entry (char * function, struct inode * dir, ...@@ -92,9 +100,9 @@ int ext2_check_dir_entry (char * function, struct inode * dir,
static int ext2_readdir (struct inode * inode, struct file * filp, static int ext2_readdir (struct inode * inode, struct file * filp,
struct dirent * dirent, int count) struct dirent * dirent, int count)
{ {
unsigned long offset; unsigned long offset, blk;
int i; int i, num;
struct buffer_head * bh; struct buffer_head * bh, * tmp, * bha[16];
struct ext2_dir_entry * de; struct ext2_dir_entry * de;
struct super_block * sb; struct super_block * sb;
int err; int err;
...@@ -104,16 +112,36 @@ static int ext2_readdir (struct inode * inode, struct file * filp, ...@@ -104,16 +112,36 @@ static int ext2_readdir (struct inode * inode, struct file * filp,
sb = inode->i_sb; sb = inode->i_sb;
while (filp->f_pos < inode->i_size) { while (filp->f_pos < inode->i_size) {
offset = filp->f_pos & (sb->s_blocksize - 1); offset = filp->f_pos & (sb->s_blocksize - 1);
bh = ext2_bread (inode, (filp->f_pos) >> EXT2_BLOCK_SIZE_BITS(sb), blk = (filp->f_pos) >> EXT2_BLOCK_SIZE_BITS(sb);
0, &err); bh = ext2_bread (inode, blk, 0, &err);
if (!bh) { if (!bh) {
filp->f_pos += sb->s_blocksize - offset; filp->f_pos += sb->s_blocksize - offset;
continue; continue;
} }
/*
* Do the readahead
*/
if (!offset) {
for (i = 16 >> (EXT2_BLOCK_SIZE_BITS(sb) - 9), num = 0;
i > 0; i--) {
tmp = ext2_getblk (inode, ++blk, 0, &err);
if (tmp && !tmp->b_uptodate && !tmp->b_lock)
bha[num++] = tmp;
else
brelse (tmp);
}
if (num) {
ll_rw_block (READA, num, bha);
for (i = 0; i < num; i++)
brelse (bha[i]);
}
}
de = (struct ext2_dir_entry *) (offset + bh->b_data); de = (struct ext2_dir_entry *) (offset + bh->b_data);
while (offset < sb->s_blocksize && filp->f_pos < inode->i_size) { while (offset < sb->s_blocksize && filp->f_pos < inode->i_size) {
if (! ext2_check_dir_entry ("ext2_readdir", inode, de, if (!ext2_check_dir_entry ("ext2_readdir", inode, de,
bh, offset)) { bh, offset)) {
brelse (bh); brelse (bh);
return 0; return 0;
} }
......
/* /*
* linux/fs/ext2/file.c * linux/fs/ext2/file.c
* *
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr) * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
* *
* from * from
* *
...@@ -15,11 +17,11 @@ ...@@ -15,11 +17,11 @@
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/system.h> #include <asm/system.h>
#include <linux/autoconf.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/ext2_fs.h> #include <linux/ext2_fs.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/locks.h> #include <linux/locks.h>
...@@ -32,8 +34,12 @@ ...@@ -32,8 +34,12 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/ext2_fs.h> #include <linux/ext2_fs.h>
/* static */ int ext2_file_read (struct inode *, struct file *, char *, int); #ifndef CONFIG_EXT2_FS_DIR_READ
static
#endif
int ext2_file_read (struct inode *, struct file *, char *, int);
static int ext2_file_write (struct inode *, struct file *, char *, int); static int ext2_file_write (struct inode *, struct file *, char *, int);
static void ext2_release_file (struct inode *, struct file *);
/* /*
* We have mostly NULL's here: the current defaults are ok for * We have mostly NULL's here: the current defaults are ok for
...@@ -48,7 +54,7 @@ static struct file_operations ext2_file_operations = { ...@@ -48,7 +54,7 @@ static struct file_operations ext2_file_operations = {
ext2_ioctl, /* ioctl */ ext2_ioctl, /* ioctl */
generic_mmap, /* mmap */ generic_mmap, /* mmap */
NULL, /* no special open is needed */ NULL, /* no special open is needed */
NULL, /* release */ ext2_release_file, /* release */
ext2_sync_file /* fsync */ ext2_sync_file /* fsync */
}; };
...@@ -70,8 +76,11 @@ struct inode_operations ext2_file_inode_operations = { ...@@ -70,8 +76,11 @@ struct inode_operations ext2_file_inode_operations = {
ext2_permission /* permission */ ext2_permission /* permission */
}; };
/* static */ int ext2_file_read (struct inode * inode, struct file * filp, #ifndef CONFIG_EXT2_FS_DIR_READ
char * buf, int count) static
#endif
int ext2_file_read (struct inode * inode, struct file * filp,
char * buf, int count)
{ {
int read, left, chars; int read, left, chars;
int block, blocks, offset; int block, blocks, offset;
...@@ -116,15 +125,17 @@ struct inode_operations ext2_file_inode_operations = { ...@@ -116,15 +125,17 @@ struct inode_operations ext2_file_inode_operations = {
blocks = size - block; blocks = size - block;
} }
/* We do this in a two stage process. We first try and request /*
as many blocks as we can, then we wait for the first one to * We do this in a two stage process. We first try and request
complete, and then we try and wrap up as many as are actually * as many blocks as we can, then we wait for the first one to
done. This routine is rather generic, in that it can be used * complete, and then we try and wrap up as many as are actually
in a filesystem by substituting the appropriate function in * done. This routine is rather generic, in that it can be used
for getblk * in a filesystem by substituting the appropriate function in
* for getblk
This routine is optimized to make maximum use of the various *
buffers and caches. */ * This routine is optimized to make maximum use of the various
* buffers and caches.
*/
do { do {
bhrequest = 0; bhrequest = 0;
...@@ -140,8 +151,10 @@ struct inode_operations ext2_file_inode_operations = { ...@@ -140,8 +151,10 @@ struct inode_operations ext2_file_inode_operations = {
if (++bhb == &buflist[NBUF]) if (++bhb == &buflist[NBUF])
bhb = buflist; bhb = buflist;
/* If the block we have on hand is uptodate, go ahead /*
and complete processing */ * If the block we have on hand is uptodate, go ahead
* and complete processing
*/
if (uptodate) if (uptodate)
break; break;
...@@ -149,11 +162,16 @@ struct inode_operations ext2_file_inode_operations = { ...@@ -149,11 +162,16 @@ struct inode_operations ext2_file_inode_operations = {
break; break;
} }
/* Now request them all */ /*
* Now request them all
*/
if (bhrequest) if (bhrequest)
ll_rw_block (READ, bhrequest, bhreq); ll_rw_block (READ, bhrequest, bhreq);
do { /* Finish off all I/O that has actually completed */ do {
/*
* Finish off all I/O that has actually completed
*/
if (*bhe) { if (*bhe) {
wait_on_buffer (*bhe); wait_on_buffer (*bhe);
if (!(*bhe)->b_uptodate) { /* read error? */ if (!(*bhe)->b_uptodate) { /* read error? */
...@@ -186,7 +204,9 @@ struct inode_operations ext2_file_inode_operations = { ...@@ -186,7 +204,9 @@ struct inode_operations ext2_file_inode_operations = {
} while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock)); } while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock));
} while (left > 0); } while (left > 0);
/* Release the read-ahead blocks */ /*
* Release the read-ahead blocks
*/
while (bhe != bhb) { while (bhe != bhb) {
brelse (*bhe); brelse (*bhe);
if (++bhe == &buflist[NBUF]) if (++bhe == &buflist[NBUF])
...@@ -217,6 +237,12 @@ static int ext2_file_write (struct inode * inode, struct file * filp, ...@@ -217,6 +237,12 @@ static int ext2_file_write (struct inode * inode, struct file * filp,
return -EINVAL; return -EINVAL;
} }
sb = inode->i_sb; sb = inode->i_sb;
if (sb->s_flags & MS_RDONLY)
/*
* This fs has been automatically remounted ro because of errors
*/
return -ENOSPC;
if (!S_ISREG(inode->i_mode)) { if (!S_ISREG(inode->i_mode)) {
ext2_warning (sb, "ext2_file_write", "mode = %07o\n", ext2_warning (sb, "ext2_file_write", "mode = %07o\n",
inode->i_mode); inode->i_mode);
...@@ -269,3 +295,14 @@ static int ext2_file_write (struct inode * inode, struct file * filp, ...@@ -269,3 +295,14 @@ static int ext2_file_write (struct inode * inode, struct file * filp,
inode->i_dirt = 1; inode->i_dirt = 1;
return written; return written;
} }
/*
* Called when a inode is released. Note that this is different
* from ext2_open: open gets called at every open, but release
* gets called only when /all/ the files are closed.
*/
static void ext2_release_file (struct inode * inode, struct file * filp)
{
if (filp->f_mode & 2)
ext2_discard_prealloc (inode);
}
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
* Copyright (C) 1993 Stephen Tweedie (sct@dcs.ed.ac.uk) * Copyright (C) 1993 Stephen Tweedie (sct@dcs.ed.ac.uk)
* from * from
* Copyright (C) 1992 Remy Card (card@masi.ibp.fr) * Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
* from * from
* linux/fs/minix/truncate.c Copyright (C) 1991, 1992 Linus Torvalds * linux/fs/minix/truncate.c Copyright (C) 1991, 1992 Linus Torvalds
* *
...@@ -171,8 +173,10 @@ int ext2_sync_file (struct inode * inode, struct file * file) ...@@ -171,8 +173,10 @@ int ext2_sync_file (struct inode * inode, struct file * file)
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode))) S_ISLNK(inode->i_mode)))
return -EINVAL; return -EINVAL;
/* Don't sync fast links! */
if (S_ISLNK(inode->i_mode) && !(inode->i_blocks)) if (S_ISLNK(inode->i_mode) && !(inode->i_blocks))
/*
* Don't sync fast links!
*/
goto skip; goto skip;
for (wait=0; wait<=1; wait++) for (wait=0; wait<=1; wait++)
......
This diff is collapsed.
/* /*
* linux/fs/ext2/inode.c * linux/fs/ext2/inode.c
* *
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr) * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
* *
* from * from
* *
...@@ -18,14 +20,22 @@ ...@@ -18,14 +20,22 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/ext2_fs.h> #include <linux/ext2_fs.h>
#include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/locks.h> #include <linux/locks.h>
#define clear_block(addr,size) \
__asm__("cld\n\t" \
"rep\n\t" \
"stosl" \
: \
:"a" (0), "c" (size / 4), "D" ((long) (addr)) \
:"cx", "di")
void ext2_put_inode (struct inode * inode) void ext2_put_inode (struct inode * inode)
{ {
ext2_discard_prealloc (inode);
if (inode->i_nlink || inode->i_ino == EXT2_ACL_IDX_INO || if (inode->i_nlink || inode->i_ino == EXT2_ACL_IDX_INO ||
inode->i_ino == EXT2_ACL_DATA_INO) inode->i_ino == EXT2_ACL_DATA_INO)
return; return;
...@@ -48,6 +58,78 @@ static int block_bmap (struct buffer_head * bh, int nr) ...@@ -48,6 +58,78 @@ static int block_bmap (struct buffer_head * bh, int nr)
return tmp; return tmp;
} }
/*
* ext2_discard_prealloc and ext2_alloc_block are atomic wrt. the
* superblock in the same manner as are ext2_free_blocks and
* ext2_new_block. We just wait on the super rather than locking it
* here, since ext2_new_block will do the necessary locking and we
* can't block until then.
*/
void ext2_discard_prealloc (struct inode * inode)
{
#ifdef EXT2_PREALLOCATE
if (inode->u.ext2_i.i_prealloc_count) {
ext2_free_blocks (inode->i_sb,
inode->u.ext2_i.i_prealloc_block,
inode->u.ext2_i.i_prealloc_count);
inode->u.ext2_i.i_prealloc_count = 0;
}
#endif
}
static int ext2_alloc_block (struct inode * inode, unsigned long goal)
{
#ifdef EXT2FS_DEBUG
static unsigned long alloc_hits = 0, alloc_attempts = 0;
#endif
unsigned long result;
struct buffer_head * bh;
wait_on_super (inode->i_sb);
#ifdef EXT2_PREALLOCATE
if (inode->u.ext2_i.i_prealloc_count &&
(goal == inode->u.ext2_i.i_prealloc_block ||
goal + 1 == inode->u.ext2_i.i_prealloc_block))
{
result = inode->u.ext2_i.i_prealloc_block++;
inode->u.ext2_i.i_prealloc_count--;
ext2_debug ("preallocation hit (%lu/%lu).\n",
++alloc_hits, ++alloc_attempts);
/* It doesn't matter if we block in getblk() since
we have already atomically allocated the block, and
are only clearing it now. */
if (!(bh = getblk (inode->i_sb->s_dev, result,
inode->i_sb->s_blocksize))) {
ext2_error (inode->i_sb, "ext2_alloc_block",
"cannot get block %lu", result);
return 0;
}
clear_block (bh->b_data, inode->i_sb->s_blocksize);
bh->b_uptodate = 1;
bh->b_dirt = 1;
brelse (bh);
} else {
ext2_discard_prealloc (inode);
ext2_debug ("preallocation miss (%lu/%lu).\n",
alloc_hits, ++alloc_attempts);
if (S_ISREG(inode->i_mode))
result = ext2_new_block
(inode->i_sb, goal,
&inode->u.ext2_i.i_prealloc_count,
&inode->u.ext2_i.i_prealloc_block);
else
result = ext2_new_block (inode->i_sb, goal, 0, 0);
}
#else
result = ext2_new_block (inode->i_sb, goal, 0, 0);
#endif
return result;
}
int ext2_bmap (struct inode * inode, int block) int ext2_bmap (struct inode * inode, int block)
{ {
int i; int i;
...@@ -147,12 +229,12 @@ static struct buffer_head * inode_getblk (struct inode * inode, int nr, ...@@ -147,12 +229,12 @@ static struct buffer_head * inode_getblk (struct inode * inode, int nr,
ext2_debug ("goal = %d.\n", goal); ext2_debug ("goal = %d.\n", goal);
tmp = ext2_new_block (inode->i_sb, goal); tmp = ext2_alloc_block (inode, goal);
if (!tmp) if (!tmp)
return NULL; return NULL;
result = getblk (inode->i_dev, tmp, inode->i_sb->s_blocksize); result = getblk (inode->i_dev, tmp, inode->i_sb->s_blocksize);
if (*p) { if (*p) {
ext2_free_block (inode->i_sb, tmp); ext2_free_blocks (inode->i_sb, tmp, 1);
brelse (result); brelse (result);
goto repeat; goto repeat;
} }
...@@ -219,14 +301,14 @@ static struct buffer_head * block_getblk (struct inode * inode, ...@@ -219,14 +301,14 @@ static struct buffer_head * block_getblk (struct inode * inode,
if (!goal) if (!goal)
goal = bh->b_blocknr + 1; goal = bh->b_blocknr + 1;
} }
tmp = ext2_new_block (inode->i_sb, goal); tmp = ext2_alloc_block (inode, goal);
if (!tmp) { if (!tmp) {
brelse (bh); brelse (bh);
return NULL; return NULL;
} }
result = getblk (bh->b_dev, tmp, blocksize); result = getblk (bh->b_dev, tmp, blocksize);
if (*p) { if (*p) {
ext2_free_block (inode->i_sb, tmp); ext2_free_blocks (inode->i_sb, tmp, 1);
brelse (result); brelse (result);
goto repeat; goto repeat;
} }
...@@ -263,9 +345,11 @@ struct buffer_head * ext2_getblk (struct inode * inode, long block, ...@@ -263,9 +345,11 @@ struct buffer_head * ext2_getblk (struct inode * inode, long block,
ext2_warning (inode->i_sb, "ext2_getblk", "block > big"); ext2_warning (inode->i_sb, "ext2_getblk", "block > big");
return NULL; return NULL;
} }
/* If this is a sequential block allocation, set the next_alloc_block /*
to this block now so that all the indblock and data block * If this is a sequential block allocation, set the next_alloc_block
allocations use the same goal zone */ * to this block now so that all the indblock and data block
* allocations use the same goal zone
*/
ext2_debug ("block %lu, next %lu, goal %lu.\n", block, ext2_debug ("block %lu, next %lu, goal %lu.\n", block,
inode->u.ext2_i.i_next_alloc_block, inode->u.ext2_i.i_next_alloc_block,
...@@ -379,6 +463,9 @@ void ext2_read_inode (struct inode * inode) ...@@ -379,6 +463,9 @@ void ext2_read_inode (struct inode * inode)
inode->u.ext2_i.i_block_group = block_group; inode->u.ext2_i.i_block_group = block_group;
inode->u.ext2_i.i_next_alloc_block = 0; inode->u.ext2_i.i_next_alloc_block = 0;
inode->u.ext2_i.i_next_alloc_goal = 0; inode->u.ext2_i.i_next_alloc_goal = 0;
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)) if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
inode->i_rdev = raw_inode->i_block[0]; inode->i_rdev = raw_inode->i_block[0];
else for (block = 0; block < EXT2_N_BLOCKS; block++) else for (block = 0; block < EXT2_N_BLOCKS; block++)
......
/* /*
* linux/fs/ext2/ioctl.c * linux/fs/ext2/ioctl.c
* *
* Copyright (C) 1993 Remy Card (card@masi.ibp.fr) * Copyright (C) 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*/ */
#include <asm/segment.h> #include <asm/segment.h>
......
/* /*
* linux/fs/ext2/namei.c * linux/fs/ext2/namei.c
* *
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr) * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
* *
* from * from
* *
...@@ -16,7 +18,6 @@ ...@@ -16,7 +18,6 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/ext2_fs.h> #include <linux/ext2_fs.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/string.h> #include <linux/string.h>
...@@ -27,7 +28,15 @@ ...@@ -27,7 +28,15 @@
* truncated. Else they will be disallowed. * truncated. Else they will be disallowed.
*/ */
/* #define NO_TRUNCATE */ /* #define NO_TRUNCATE */
/*
* define how far ahead to read directories while searching them.
*/
#define NAMEI_RA_CHUNKS 2
#define NAMEI_RA_BLOCKS 4
#define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
#define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b))
/* /*
* NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure. * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure.
*/ */
...@@ -38,7 +47,9 @@ static int ext2_match (int len, const char * const name, ...@@ -38,7 +47,9 @@ static int ext2_match (int len, const char * const name,
if (!de || !de->inode || len > EXT2_NAME_LEN) if (!de || !de->inode || len > EXT2_NAME_LEN)
return 0; return 0;
/* "" means "." ---> so paths like "/usr/lib//libc.a" work */ /*
* "" means "." ---> so paths like "/usr/lib//libc.a" work
*/
if (!len && de->name_len == 1 && (de->name[0] == '.') && if (!len && de->name_len == 1 && (de->name[0] == '.') &&
(de->name[1] == '\0')) (de->name[1] == '\0'))
return 1; return 1;
...@@ -60,22 +71,22 @@ static int ext2_match (int len, const char * const name, ...@@ -60,22 +71,22 @@ static int ext2_match (int len, const char * const name,
* returns the cache buffer in which the entry was found, and the entry * returns the cache buffer in which the entry was found, and the entry
* itself (as a parameter - res_dir). It does NOT read the inode of the * itself (as a parameter - res_dir). It does NOT read the inode of the
* entry - you'll have to do that yourself if you want to. * entry - you'll have to do that yourself if you want to.
*
*/ */
static struct buffer_head * ext2_find_entry (struct inode * dir, static struct buffer_head * ext2_find_entry (struct inode * dir,
const char * const name, int namelen, const char * const name, int namelen,
struct ext2_dir_entry ** res_dir) struct ext2_dir_entry ** res_dir)
{ {
unsigned long offset;
struct buffer_head * bh;
struct ext2_dir_entry * de;
struct super_block * sb; struct super_block * sb;
int err; struct buffer_head * bh_use[NAMEI_RA_SIZE];
struct buffer_head * bh_read[NAMEI_RA_SIZE];
unsigned long offset;
int block, toread, i, err;
*res_dir = NULL; *res_dir = NULL;
if (!dir) if (!dir)
return NULL; return NULL;
sb = dir->i_sb; sb = dir->i_sb;
#ifdef NO_TRUNCATE #ifdef NO_TRUNCATE
if (namelen > EXT2_NAME_LEN) if (namelen > EXT2_NAME_LEN)
return NULL; return NULL;
...@@ -83,34 +94,76 @@ static struct buffer_head * ext2_find_entry (struct inode * dir, ...@@ -83,34 +94,76 @@ static struct buffer_head * ext2_find_entry (struct inode * dir,
if (namelen > EXT2_NAME_LEN) if (namelen > EXT2_NAME_LEN)
namelen = EXT2_NAME_LEN; namelen = EXT2_NAME_LEN;
#endif #endif
bh = ext2_bread (dir, 0, 0, &err);
if (!bh) memset (bh_use, 0, sizeof (bh_use));
return NULL; toread = 0;
for (block = 0; block < NAMEI_RA_SIZE; ++block) {
struct buffer_head * bh;
if ((block << EXT2_BLOCK_SIZE_BITS (sb)) >= dir->i_size)
break;
bh = ext2_getblk (dir, block, 0, &err);
bh_use[block] = bh;
if (bh && !bh->b_uptodate)
bh_read[toread++] = bh;
}
block = 0;
offset = 0; offset = 0;
de = (struct ext2_dir_entry *) bh->b_data;
while (offset < dir->i_size) { while (offset < dir->i_size) {
if (!bh || (char *)de >= sb->s_blocksize + bh->b_data) { struct buffer_head * bh;
brelse (bh); struct ext2_dir_entry * de;
bh = ext2_bread (dir, offset >> EXT2_BLOCK_SIZE_BITS(sb), 0, &err); char * dlimit;
if (!bh) {
offset += sb->s_blocksize; if ((block % NAMEI_RA_BLOCKS) == 0 && toread) {
continue; ll_rw_block (READ, toread, bh_read);
} toread = 0;
de = (struct ext2_dir_entry *) bh->b_data;
} }
if (! ext2_check_dir_entry ("ext2_find_entry", dir, de, bh, bh = bh_use[block % NAMEI_RA_SIZE];
offset)) { if (!bh)
brelse (bh); ext2_panic (sb, "ext2_find_entry",
return NULL; "buffer head pointer is NULL");
wait_on_buffer (bh);
if (!bh->b_uptodate) {
/*
* read error: all bets are off
*/
break;
} }
if (de->inode != 0 && ext2_match (namelen, name, de)) {
*res_dir = de; de = (struct ext2_dir_entry *) bh->b_data;
return bh; dlimit = bh->b_data + sb->s_blocksize;
while ((char *) de < dlimit) {
if (!ext2_check_dir_entry ("ext2_find_entry", dir,
de, bh, offset))
goto failure;
if (de->inode != 0 && ext2_match (namelen, name, de)) {
for (i = 0; i < NAMEI_RA_SIZE; ++i) {
if (bh_use[i] != bh)
brelse (bh_use[i]);
}
*res_dir = de;
return bh;
}
offset += de->rec_len;
de = (struct ext2_dir_entry *)
((char *) de + de->rec_len);
} }
offset += de->rec_len;
de = (struct ext2_dir_entry *) ((char *) de + de->rec_len); brelse (bh);
if (((block + NAMEI_RA_SIZE) << EXT2_BLOCK_SIZE_BITS (sb)) >=
dir->i_size)
bh = NULL;
else
bh = ext2_getblk (dir, block + NAMEI_RA_SIZE, 0, &err);
bh_use[block++ % NAMEI_RA_SIZE] = bh;
if (bh && !bh->b_uptodate)
bh_read[toread++] = bh;
} }
brelse (bh);
failure:
for (i = 0; i < NAMEI_RA_SIZE; ++i)
brelse (bh_use[i]);
return NULL; return NULL;
} }
...@@ -187,8 +240,9 @@ static struct buffer_head * ext2_add_entry (struct inode * dir, ...@@ -187,8 +240,9 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
#endif #endif
if (!namelen) if (!namelen)
return NULL; return NULL;
/* Is this a busy deleted directory? Can't create new files /*
if so */ * Is this a busy deleted directory? Can't create new files if so
*/
if (dir->i_size == 0) if (dir->i_size == 0)
{ {
*err = -ENOENT; *err = -ENOENT;
...@@ -231,8 +285,8 @@ static struct buffer_head * ext2_add_entry (struct inode * dir, ...@@ -231,8 +285,8 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
de = (struct ext2_dir_entry *) bh->b_data; de = (struct ext2_dir_entry *) bh->b_data;
} }
} }
if (! ext2_check_dir_entry ("ext2_add_entry", dir, de, bh, if (!ext2_check_dir_entry ("ext2_add_entry", dir, de, bh,
offset)) { offset)) {
*err = -ENOENT; *err = -ENOENT;
brelse (bh); brelse (bh);
return NULL; return NULL;
...@@ -295,13 +349,12 @@ static int ext2_delete_entry (struct ext2_dir_entry * dir, ...@@ -295,13 +349,12 @@ static int ext2_delete_entry (struct ext2_dir_entry * dir,
pde = NULL; pde = NULL;
de = (struct ext2_dir_entry *) bh->b_data; de = (struct ext2_dir_entry *) bh->b_data;
while (i < bh->b_size) { while (i < bh->b_size) {
if (! ext2_check_dir_entry ("ext2_delete_entry", NULL, if (!ext2_check_dir_entry ("ext2_delete_entry", NULL,
de, bh, i)) de, bh, i))
return -EIO; return -EIO;
if (de == dir) { if (de == dir) {
if (pde) if (pde)
pde->rec_len += dir->rec_len; pde->rec_len += dir->rec_len;
/* XXX - must zero the inode number in every case !! */
dir->inode = 0; dir->inode = 0;
return 0; return 0;
} }
...@@ -548,8 +601,8 @@ static int empty_dir (struct inode * inode) ...@@ -548,8 +601,8 @@ static int empty_dir (struct inode * inode)
} }
de = (struct ext2_dir_entry *) bh->b_data; de = (struct ext2_dir_entry *) bh->b_data;
} }
if (! ext2_check_dir_entry ("empty_dir", inode, de, bh, if (!ext2_check_dir_entry ("empty_dir", inode, de, bh,
offset)) { offset)) {
brelse (bh); brelse (bh);
return 1; return 1;
} }
...@@ -609,10 +662,13 @@ int ext2_rmdir (struct inode * dir, const char * name, int len) ...@@ -609,10 +662,13 @@ int ext2_rmdir (struct inode * dir, const char * name, int len)
goto end_rmdir; goto end_rmdir;
} }
if (inode->i_count > 1) { if (inode->i_count > 1) {
/* Are we deleting the last instance of a busy directory? /*
Better clean up if so. */ * Are we deleting the last instance of a busy directory?
/* Make directory empty (it will be truncated when finally * Better clean up if so.
dereferenced). This also inhibits ext2_add_entry. */ *
* Make directory empty (it will be truncated when finally
* dereferenced). This also inhibits ext2_add_entry.
*/
inode->i_size = 0; inode->i_size = 0;
} }
retval = ext2_delete_entry (de, bh); retval = ext2_delete_entry (de, bh);
...@@ -969,14 +1025,18 @@ static int do_ext2_rename (struct inode * old_dir, const char * old_name, ...@@ -969,14 +1025,18 @@ static int do_ext2_rename (struct inode * old_dir, const char * old_name,
&retval); &retval);
if (!new_bh) if (!new_bh)
goto end_rename; goto end_rename;
/* sanity checking before doing the rename - avoid races */ /*
* sanity checking before doing the rename - avoid races
*/
if (new_inode && (new_de->inode != new_inode->i_ino)) if (new_inode && (new_de->inode != new_inode->i_ino))
goto try_again; goto try_again;
if (new_de->inode && !new_inode) if (new_de->inode && !new_inode)
goto try_again; goto try_again;
if (old_de->inode != old_inode->i_ino) if (old_de->inode != old_inode->i_ino)
goto try_again; goto try_again;
/* ok, that's it */ /*
* ok, that's it
*/
new_de->inode = old_inode->i_ino; new_de->inode = old_inode->i_ino;
#ifndef DONT_USE_DCACHE #ifndef DONT_USE_DCACHE
ext2_dcache_remove (old_dir->i_dev, old_dir->i_ino, old_de->name, ext2_dcache_remove (old_dir->i_dev, old_dir->i_ino, old_de->name,
......
This diff is collapsed.
/* /*
* linux/fs/ext2/symlink.c * linux/fs/ext2/symlink.c
* *
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr) * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
* *
* from * from
* *
......
/* /*
* linux/fs/ext2/truncate.c * linux/fs/ext2/truncate.c
* *
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr) * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
* *
* from * from
* *
...@@ -80,7 +82,7 @@ static int trunc_direct (struct inode * inode) ...@@ -80,7 +82,7 @@ static int trunc_direct (struct inode * inode)
bh->b_dirt = 1; bh->b_dirt = 1;
} }
brelse (bh); brelse (bh);
ext2_free_block (inode->i_sb, tmp); ext2_free_blocks (inode->i_sb, tmp, 1);
} }
return retry; return retry;
} }
...@@ -142,7 +144,7 @@ static int trunc_indirect (struct inode * inode, int offset, unsigned long * p) ...@@ -142,7 +144,7 @@ static int trunc_indirect (struct inode * inode, int offset, unsigned long * p)
bh->b_dirt = 1; bh->b_dirt = 1;
} }
brelse (bh); brelse (bh);
ext2_free_block (inode->i_sb, tmp); ext2_free_blocks (inode->i_sb, tmp, 1);
inode->i_blocks -= blocks; inode->i_blocks -= blocks;
inode->i_dirt = 1; inode->i_dirt = 1;
} }
...@@ -158,7 +160,7 @@ static int trunc_indirect (struct inode * inode, int offset, unsigned long * p) ...@@ -158,7 +160,7 @@ static int trunc_indirect (struct inode * inode, int offset, unsigned long * p)
*p = 0; *p = 0;
inode->i_blocks -= blocks; inode->i_blocks -= blocks;
inode->i_dirt = 1; inode->i_dirt = 1;
ext2_free_block (inode->i_sb, tmp); ext2_free_blocks (inode->i_sb, tmp, 1);
} }
if (IS_SYNC(inode) && ind_bh->b_dirt) { if (IS_SYNC(inode) && ind_bh->b_dirt) {
ll_rw_block (WRITE, 1, &ind_bh); ll_rw_block (WRITE, 1, &ind_bh);
...@@ -218,7 +220,7 @@ static int trunc_dindirect (struct inode * inode, int offset, ...@@ -218,7 +220,7 @@ static int trunc_dindirect (struct inode * inode, int offset,
*p = 0; *p = 0;
inode->i_blocks -= blocks; inode->i_blocks -= blocks;
inode->i_dirt = 1; inode->i_dirt = 1;
ext2_free_block (inode->i_sb, tmp); ext2_free_blocks (inode->i_sb, tmp, 1);
} }
if (IS_SYNC(inode) && dind_bh->b_dirt) { if (IS_SYNC(inode) && dind_bh->b_dirt) {
ll_rw_block (WRITE, 1, &dind_bh); ll_rw_block (WRITE, 1, &dind_bh);
...@@ -277,7 +279,7 @@ static int trunc_tindirect (struct inode * inode) ...@@ -277,7 +279,7 @@ static int trunc_tindirect (struct inode * inode)
*p = 0; *p = 0;
inode->i_blocks -= blocks; inode->i_blocks -= blocks;
inode->i_dirt = 1; inode->i_dirt = 1;
ext2_free_block (inode->i_sb, tmp); ext2_free_blocks (inode->i_sb, tmp, 1);
} }
if (IS_SYNC(inode) && tind_bh->b_dirt) { if (IS_SYNC(inode) && tind_bh->b_dirt) {
ll_rw_block (WRITE, 1, &tind_bh); ll_rw_block (WRITE, 1, &tind_bh);
...@@ -294,6 +296,7 @@ void ext2_truncate (struct inode * inode) ...@@ -294,6 +296,7 @@ void ext2_truncate (struct inode * inode)
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode))) S_ISLNK(inode->i_mode)))
return; return;
ext2_discard_prealloc(inode);
while (1) { while (1) {
retry = trunc_direct(inode); retry = trunc_direct(inode);
retry |= trunc_indirect (inode, EXT2_IND_BLOCK, retry |= trunc_indirect (inode, EXT2_IND_BLOCK,
...@@ -312,13 +315,3 @@ void ext2_truncate (struct inode * inode) ...@@ -312,13 +315,3 @@ void ext2_truncate (struct inode * inode)
inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1; inode->i_dirt = 1;
} }
/*
* Called when a inode is released. Note that this is different
* from ext2_open: open gets called at every open, but release
* gets called only when /all/ the files are closed.
*/
void ext2_release (struct inode * inode, struct file * filp)
{
printk ("ext2_release not implemented\n");
}
...@@ -36,7 +36,7 @@ extern int root_mountflags; ...@@ -36,7 +36,7 @@ extern int root_mountflags;
struct super_block super_blocks[NR_SUPER]; struct super_block super_blocks[NR_SUPER];
static int do_remount_sb(struct super_block *sb, int flags); static int do_remount_sb(struct super_block *sb, int flags, char * data);
/* this is initialized in init/main.c */ /* this is initialized in init/main.c */
dev_t ROOT_DEV = 0; dev_t ROOT_DEV = 0;
...@@ -210,7 +210,7 @@ static int do_umount(dev_t dev) ...@@ -210,7 +210,7 @@ static int do_umount(dev_t dev)
if (!(sb=get_super(dev))) if (!(sb=get_super(dev)))
return -ENOENT; return -ENOENT;
if (!(sb->s_flags & MS_RDONLY)) { if (!(sb->s_flags & MS_RDONLY)) {
retval = do_remount_sb(sb, MS_RDONLY); retval = do_remount_sb(sb, MS_RDONLY, 0);
if (retval) if (retval)
return retval; return retval;
} }
...@@ -344,7 +344,7 @@ static int do_mount(dev_t dev, const char * dir, char * type, int flags, void * ...@@ -344,7 +344,7 @@ static int do_mount(dev_t dev, const char * dir, char * type, int flags, void *
* FS-specific mount options can't be altered by remounting. * FS-specific mount options can't be altered by remounting.
*/ */
static int do_remount_sb(struct super_block *sb, int flags) static int do_remount_sb(struct super_block *sb, int flags, char *data)
{ {
int retval; int retval;
...@@ -353,7 +353,7 @@ static int do_remount_sb(struct super_block *sb, int flags) ...@@ -353,7 +353,7 @@ static int do_remount_sb(struct super_block *sb, int flags)
if (!fs_may_remount_ro(sb->s_dev)) if (!fs_may_remount_ro(sb->s_dev))
return -EBUSY; return -EBUSY;
if (sb->s_op && sb->s_op->remount_fs) { if (sb->s_op && sb->s_op->remount_fs) {
retval = sb->s_op->remount_fs(sb, &flags); retval = sb->s_op->remount_fs(sb, &flags, data);
if (retval) if (retval)
return retval; return retval;
} }
...@@ -362,7 +362,7 @@ static int do_remount_sb(struct super_block *sb, int flags) ...@@ -362,7 +362,7 @@ static int do_remount_sb(struct super_block *sb, int flags)
return 0; return 0;
} }
static int do_remount(const char *dir,int flags) static int do_remount(const char *dir,int flags,char *data)
{ {
struct inode *dir_i; struct inode *dir_i;
int retval; int retval;
...@@ -374,23 +374,54 @@ static int do_remount(const char *dir,int flags) ...@@ -374,23 +374,54 @@ static int do_remount(const char *dir,int flags)
iput(dir_i); iput(dir_i);
return -EINVAL; return -EINVAL;
} }
retval = do_remount_sb(dir_i->i_sb, flags); retval = do_remount_sb(dir_i->i_sb, flags, data);
iput(dir_i); iput(dir_i);
return retval; return retval;
} }
static int copy_mount_options (char * data, unsigned long *where)
{
int i;
unsigned long page;
struct vm_area_struct * vma;
*where = 0;
if (!data)
return 0;
for (vma = current->mmap ; ; ) {
if (!vma ||
(unsigned long) data < vma->vm_start) {
return -EFAULT;
}
if ((unsigned long) data < vma->vm_end)
break;
vma = vma->vm_next;
}
i = vma->vm_end - (unsigned long) data;
if (PAGE_SIZE <= (unsigned long) i)
i = PAGE_SIZE-1;
if (!(page = __get_free_page(GFP_KERNEL))) {
return -ENOMEM;
}
memcpy_fromfs((void *) page,data,i);
*where = page;
return 0;
}
/* /*
* Flags is a 16-bit value that allows up to 16 non-fs dependent flags to * Flags is a 16-bit value that allows up to 16 non-fs dependent flags to
* be given to the mount() call (ie: read-only, no-dev, no-suid etc). * be given to the mount() call (ie: read-only, no-dev, no-suid etc).
* *
* data is a (void *) that can point to any structure up to PAGE_SIZE-1 bytes, which * data is a (void *) that can point to any structure up to
* can contain arbitrary fs-dependent information (or be NULL). * PAGE_SIZE-1 bytes, which can contain arbitrary fs-dependent
* information (or be NULL).
* *
* NOTE! As old versions of mount() didn't use this setup, the flags has to have * NOTE! As old versions of mount() didn't use this setup, the flags
* a special 16-bit magic number in the hight word: 0xC0ED. If this magic word * has to have a special 16-bit magic number in the hight word:
* isn't present, the flags and data info isn't used, as the syscall assumes we * 0xC0ED. If this magic word isn't present, the flags and data info
* are talking to an older version that didn't understand them. * isn't used, as the syscall assumes we are talking to an older
* version that didn't understand them.
*/ */
asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type, asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
unsigned long new_flags, void * data) unsigned long new_flags, void * data)
...@@ -400,27 +431,29 @@ asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type, ...@@ -400,27 +431,29 @@ asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
struct file_operations * fops; struct file_operations * fops;
dev_t dev; dev_t dev;
int retval; int retval;
char tmp[100], * t; char * t;
int i;
unsigned long flags = 0; unsigned long flags = 0;
unsigned long page = 0; unsigned long page = 0;
if (!suser()) if (!suser())
return -EPERM; return -EPERM;
if ((new_flags & (MS_MGC_MSK | MS_REMOUNT)) == (MS_MGC_VAL | MS_REMOUNT)) { if ((new_flags &
return do_remount(dir_name,new_flags & ~MS_MGC_MSK & ~MS_REMOUNT); (MS_MGC_MSK | MS_REMOUNT)) == (MS_MGC_VAL | MS_REMOUNT)) {
retval = copy_mount_options (data, &page);
if (retval < 0)
return retval;
retval = do_remount(dir_name,
new_flags & ~MS_MGC_MSK & ~MS_REMOUNT,
(char *) page);
free_page(page);
return retval;
} }
if (type) { retval = copy_mount_options (type, &page);
for (i = 0 ; i < 100 ; i++) { if (retval < 0)
if (TASK_SIZE <= (unsigned long) type) return retval;
return -EFAULT; fstype = get_fs_type((char *) page);
if (!(tmp[i] = get_fs_byte(type++))) free_page(page);
break; if (!fstype)
}
t = tmp;
} else
t = NULL;
if (!(fstype = get_fs_type(t)))
return -ENODEV; return -ENODEV;
t = fstype->name; t = fstype->name;
if (fstype->requires_dev) { if (fstype->requires_dev) {
...@@ -455,26 +488,10 @@ asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type, ...@@ -455,26 +488,10 @@ asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
} }
if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL) { if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL) {
flags = new_flags & ~MS_MGC_MSK; flags = new_flags & ~MS_MGC_MSK;
if (data) { retval = copy_mount_options(data, &page);
struct vm_area_struct * vma; if (retval < 0) {
iput(inode);
for (vma = current->mmap ; ; ) { return retval;
if (!vma || (unsigned long) data < vma->vm_start) {
iput(inode);
return -EFAULT;
}
if ((unsigned long) data < vma->vm_end)
break;
vma = vma->vm_next;
}
i = vma->vm_end - (unsigned long) data;
if (PAGE_SIZE <= (unsigned long) i)
i = PAGE_SIZE-1;
if (!(page = __get_free_page(GFP_KERNEL))) {
iput(inode);
return -ENOMEM;
}
memcpy_fromfs((void *) page,data,i);
} }
} }
retval = do_mount(dev,dir_name,t,flags,(void *) page); retval = do_mount(dev,dir_name,t,flags,(void *) page);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* to guarantee better timings even on fast machines. * to guarantee better timings even on fast machines.
* *
* On the other hand, I'd like to be sure of a non-existent port: * On the other hand, I'd like to be sure of a non-existent port:
* I feel a bit unsafe about using 0x80. * I feel a bit unsafe about using 0x80 (should be safe, though)
* *
* Linus * Linus
*/ */
...@@ -24,73 +24,41 @@ ...@@ -24,73 +24,41 @@
#define SLOW_DOWN_IO __SLOW_DOWN_IO #define SLOW_DOWN_IO __SLOW_DOWN_IO
#endif #endif
/* This is the more general version of outb.. */ /*
extern inline void __outb(unsigned char value, unsigned short port) * Talk about misusing macros..
{ */
__asm__ __volatile__ ("outb %b0,%w1"
: /* no outputs */ #define __OUT1(s,x) \
:"a" (value),"d" (port)); extern inline void __out##s(unsigned x value, unsigned short port) {
}
#define __OUT2(s,s1,s2) \
/* this is used for constant port numbers < 256.. */ __asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
extern inline void __outbc(unsigned char value, unsigned short port)
{ #define __OUT(s,s1,x) \
__asm__ __volatile__ ("outb %b0,%1" __OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); } \
: /* no outputs */ __OUT1(s##c,x) __OUT2(s,s1,"") : : "a" (value), "i" (port)); } \
:"a" (value),"i" (port)); __OUT1(s##_p,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); SLOW_DOWN_IO; } \
} __OUT1(s##c_p,x) __OUT2(s,s1,"") : : "a" (value), "i" (port)); SLOW_DOWN_IO; }
/* general version of inb */ #define __IN1(s) \
extern inline unsigned int __inb(unsigned short port) extern inline unsigned int __in##s(unsigned short port) { unsigned int _v;
{
unsigned int _v; #define __IN2(s,s1,s2) \
__asm__ __volatile__ ("inb %w1,%b0" __asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
:"=a" (_v):"d" (port),"0" (0));
return _v; #define __IN(s,s1,i...) \
} __IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); return _v; } \
__IN1(s##c) __IN2(s,s1,"") : "=a" (_v) : "i" (port) ,##i ); return _v; } \
/* inb with constant port nr 0-255 */ __IN1(s##_p) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); SLOW_DOWN_IO; return _v; } \
extern inline unsigned int __inbc(unsigned short port) __IN1(s##c_p) __IN2(s,s1,"") : "=a" (_v) : "i" (port) ,##i ); SLOW_DOWN_IO; return _v; }
{
unsigned int _v; __IN(b,"b","0" (0))
__asm__ __volatile__ ("inb %1,%b0" __IN(w,"w","0" (0))
:"=a" (_v):"i" (port),"0" (0)); __IN(l,"")
return _v;
} __OUT(b,"b",char)
__OUT(w,"w",short)
extern inline void __outb_p(unsigned char value, unsigned short port) __OUT(l,,int)
{
__asm__ __volatile__ ("outb %b0,%w1"
: /* no outputs */
:"a" (value),"d" (port));
SLOW_DOWN_IO;
}
extern inline void __outbc_p(unsigned char value, unsigned short port)
{
__asm__ __volatile__ ("outb %b0,%1"
: /* no outputs */
:"a" (value),"i" (port));
SLOW_DOWN_IO;
}
extern inline unsigned int __inb_p(unsigned short port)
{
unsigned int _v;
__asm__ __volatile__ ("inb %w1,%b0"
:"=a" (_v):"d" (port),"0" (0));
SLOW_DOWN_IO;
return _v;
}
extern inline unsigned int __inbc_p(unsigned short port)
{
unsigned int _v;
__asm__ __volatile__ ("inb %1,%b0"
:"=a" (_v):"i" (port),"0" (0));
SLOW_DOWN_IO;
return _v;
}
/* /*
* Note that due to the way __builtin_constant_p() works, you * Note that due to the way __builtin_constant_p() works, you
...@@ -117,4 +85,44 @@ __asm__ __volatile__ ("inb %1,%b0" ...@@ -117,4 +85,44 @@ __asm__ __volatile__ ("inb %1,%b0"
__inbc_p(port) : \ __inbc_p(port) : \
__inb_p(port)) __inb_p(port))
#define outw(val,port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__outwc((val),(port)) : \
__outw((val),(port)))
#define inw(port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__inwc(port) : \
__inw(port))
#define outw_p(val,port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__outwc_p((val),(port)) : \
__outw_p((val),(port)))
#define inw_p(port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__inwc_p(port) : \
__inw_p(port))
#define outl(val,port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__outlc((val),(port)) : \
__outl((val),(port)))
#define inl(port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__inlc(port) : \
__inl(port))
#define outl_p(val,port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__outlc_p((val),(port)) : \
__outl_p((val),(port)))
#define inl_p(port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__inlc_p(port) : \
__inl_p(port))
#endif #endif
...@@ -35,7 +35,7 @@ extern void enable_irq(unsigned int); ...@@ -35,7 +35,7 @@ extern void enable_irq(unsigned int);
"movl $" STR(USER_DS) ",%edx\n\t" \ "movl $" STR(USER_DS) ",%edx\n\t" \
"mov %dx,%fs\n\t" \ "mov %dx,%fs\n\t" \
"movl $0,%edx\n\t" \ "movl $0,%edx\n\t" \
"movl %edx,%db7\n" "movl %edx,%db7\n\t"
/* /*
* SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers, * SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers,
......
/* /*
* linux/include/linux/ext2_fs.h * linux/include/linux/ext2_fs.h
* *
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr) * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
* *
* from * from
* *
...@@ -38,20 +40,20 @@ ...@@ -38,20 +40,20 @@
#undef EXT2FS_PRE_02B_COMPAT #undef EXT2FS_PRE_02B_COMPAT
/* /*
* Define EXT2FS_PRE_04_COMPAT to convert ext2 fs prior to 0.4 * Define DONT_USE_DCACHE to inhibit the directory cache
*/ */
#define EXT2_PRE_04_COMPAT #define DONT_USE_DCACHE
/* /*
* Define DONT_USE_DCACHE to inhibit the directory cache * Define EXT2_PREALLOCATE to preallocate data blocks for expanding files
*/ */
#define DONT_USE_DCACHE #define EXT2_PREALLOCATE
/* /*
* The second extended file system version * The second extended file system version
*/ */
#define EXT2FS_DATE "93/11/19" #define EXT2FS_DATE "93/12/30"
#define EXT2FS_VERSION "0.4a" #define EXT2FS_VERSION "0.4b"
/* /*
* Debug code * Debug code
...@@ -242,13 +244,33 @@ struct ext2_inode { ...@@ -242,13 +244,33 @@ struct ext2_inode {
/* /*
* Mount flags * Mount flags
*/ */
#define EXT2_MOUNT_CHECK 0x0001 /* Do some more checks */ #define EXT2_MOUNT_CHECK_NORMAL 0x0001 /* Do some more checks */
#define EXT2_MOUNT_CHECK_STRICT 0x0002 /* Do again more checks */
#define EXT2_MOUNT_CHECK (EXT2_MOUNT_CHECK_NORMAL | \
EXT2_MOUNT_CHECK_STRICT)
#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */
#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */
#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */
#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
#define test_opt(sb, opt) ((sb)->u.ext2_sb.s_mount_opt & \
EXT2_MOUNT_##opt)
/* /*
* Maximal mount counts between two filesystem checks * Maximal mount counts between two filesystem checks
*/ */
#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */ #define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
/*
* Behaviour when detecting errors
*/
#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */
#define EXT2_ERRORS_RO 2 /* Remount fs read-only */
#define EXT2_ERRORS_PANIC 3 /* Panic */
#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE
/* /*
* Structure of the super block * Structure of the super block
*/ */
...@@ -270,7 +292,9 @@ struct ext2_super_block { ...@@ -270,7 +292,9 @@ struct ext2_super_block {
unsigned short s_max_mnt_count; /* Maximal mount count */ unsigned short s_max_mnt_count; /* Maximal mount count */
unsigned short s_magic; /* Magic signature */ unsigned short s_magic; /* Magic signature */
unsigned short s_state; /* File system state */ unsigned short s_state; /* File system state */
unsigned long s_reserved[241]; /* Padding to the end of the block */ unsigned short s_errors; /* Behaviour when detecting errors */
unsigned short s_pad;
unsigned long s_reserved[240]; /* Padding to the end of the block */
}; };
/* /*
...@@ -300,12 +324,28 @@ struct ext2_dir_entry { ...@@ -300,12 +324,28 @@ struct ext2_dir_entry {
* Function prototypes * Function prototypes
*/ */
/*
* Ok, these declarations are also in <linux/kernel.h> but none of the
* ext2 source programs needs to include it so they are duplicated here.
*/
#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
# define NORET_TYPE __volatile__
# define ATTRIB_NORET /**/
# define NORET_AND /**/
#else
# define NORET_TYPE /**/
# define ATTRIB_NORET __attribute__((noreturn))
# define NORET_AND noreturn,
#endif
/* acl.c */ /* acl.c */
extern int ext2_permission (struct inode *, int); extern int ext2_permission (struct inode *, int);
/* balloc.c */ /* balloc.c */
extern int ext2_new_block (struct super_block *, unsigned long); extern int ext2_new_block (struct super_block *, unsigned long,
extern void ext2_free_block (struct super_block *, unsigned long); unsigned long *, unsigned long *);
extern void ext2_free_blocks (struct super_block *, unsigned long,
unsigned long);
extern unsigned long ext2_count_free_blocks (struct super_block *); extern unsigned long ext2_count_free_blocks (struct super_block *);
extern void ext2_check_blocks_bitmap (struct super_block *); extern void ext2_check_blocks_bitmap (struct super_block *);
...@@ -351,6 +391,7 @@ extern void ext2_read_inode (struct inode *); ...@@ -351,6 +391,7 @@ extern void ext2_read_inode (struct inode *);
extern void ext2_write_inode (struct inode *); extern void ext2_write_inode (struct inode *);
extern void ext2_put_inode (struct inode *); extern void ext2_put_inode (struct inode *);
extern int ext2_sync_inode (struct inode *); extern int ext2_sync_inode (struct inode *);
extern void ext2_discard_prealloc (struct inode *);
/* ioctl.c */ /* ioctl.c */
extern int ext2_ioctl (struct inode *, struct file *, unsigned int, extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
...@@ -374,14 +415,14 @@ extern int ext2_rename (struct inode *, const char *, int, ...@@ -374,14 +415,14 @@ extern int ext2_rename (struct inode *, const char *, int,
/* super.c */ /* super.c */
extern void ext2_error (struct super_block *, const char *, const char *, ...) extern void ext2_error (struct super_block *, const char *, const char *, ...)
__attribute__ ((format (printf, 3, 4))); __attribute__ ((format (printf, 3, 4)));
extern volatile void ext2_panic (struct super_block *, const char *, extern NORET_TYPE void ext2_panic (struct super_block *, const char *,
const char *, ...) const char *, ...)
__attribute__ ((format (printf, 3, 4))); __attribute__ ((NORET_AND format (printf, 3, 4)));
extern void ext2_warning (struct super_block *, const char *, const char *, ...) extern void ext2_warning (struct super_block *, const char *, const char *, ...)
__attribute__ ((format (printf, 3, 4))); __attribute__ ((format (printf, 3, 4)));
extern void ext2_put_super (struct super_block *); extern void ext2_put_super (struct super_block *);
extern void ext2_write_super (struct super_block *); extern void ext2_write_super (struct super_block *);
extern int ext2_remount (struct super_block *, int *); extern int ext2_remount (struct super_block *, int *, char *);
extern struct super_block * ext2_read_super (struct super_block *,void *,int); extern struct super_block * ext2_read_super (struct super_block *,void *,int);
extern void ext2_statfs (struct super_block *, struct statfs *); extern void ext2_statfs (struct super_block *, struct statfs *);
......
/* /*
* linux/include/linux/ext2_fs_i.h * linux/include/linux/ext2_fs_i.h
* *
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr) * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
* *
* from * from
* *
...@@ -30,6 +32,8 @@ struct ext2_inode_info { ...@@ -30,6 +32,8 @@ struct ext2_inode_info {
unsigned long i_block_group; unsigned long i_block_group;
unsigned long i_next_alloc_block; unsigned long i_next_alloc_block;
unsigned long i_next_alloc_goal; unsigned long i_next_alloc_goal;
unsigned long i_prealloc_block;
unsigned long i_prealloc_count;
}; };
#endif /* _LINUX_EXT2_FS_I */ #endif /* _LINUX_EXT2_FS_I */
/* /*
* linux/include/linux/ext2_fs_sb.h * linux/include/linux/ext2_fs_sb.h
* *
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr) * Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
* *
* from * from
* *
...@@ -26,6 +28,7 @@ struct ext2_sb_info { ...@@ -26,6 +28,7 @@ struct ext2_sb_info {
unsigned long s_frags_per_group;/* Number of fragments in a group */ unsigned long s_frags_per_group;/* Number of fragments in a group */
unsigned long s_blocks_per_group;/* Number of blocks in a group */ unsigned long s_blocks_per_group;/* Number of blocks in a group */
unsigned long s_inodes_per_group;/* Number of inodes in a group */ unsigned long s_inodes_per_group;/* Number of inodes in a group */
unsigned long s_itb_per_group; /* Number of inode table blocks per group */
unsigned long s_desc_per_block; /* Number of group descriptors per block */ unsigned long s_desc_per_block; /* Number of group descriptors per block */
unsigned long s_groups_count; /* Number of groups in the fs */ unsigned long s_groups_count; /* Number of groups in the fs */
struct buffer_head * s_sbh; /* Buffer containing the super block */ struct buffer_head * s_sbh; /* Buffer containing the super block */
......
...@@ -300,7 +300,7 @@ struct super_operations { ...@@ -300,7 +300,7 @@ struct super_operations {
void (*put_super) (struct super_block *); void (*put_super) (struct super_block *);
void (*write_super) (struct super_block *); void (*write_super) (struct super_block *);
void (*statfs) (struct super_block *, struct statfs *); void (*statfs) (struct super_block *, struct statfs *);
int (*remount_fs) (struct super_block *, int *); int (*remount_fs) (struct super_block *, int *, char *);
}; };
struct file_system_type { struct file_system_type {
......
...@@ -49,7 +49,7 @@ typedef enum { ...@@ -49,7 +49,7 @@ typedef enum {
SS_UNCONNECTED, /* unconnected to any socket */ SS_UNCONNECTED, /* unconnected to any socket */
SS_CONNECTING, /* in process of connecting */ SS_CONNECTING, /* in process of connecting */
SS_CONNECTED, /* connected to socket */ SS_CONNECTED, /* connected to socket */
SS_DISCONNECTING, /* in process of disconnecting */ SS_DISCONNECTING /* in process of disconnecting */
} socket_state; } socket_state;
#define SO_ACCEPTCON (1<<16) /* performed a listen */ #define SO_ACCEPTCON (1<<16) /* performed a listen */
......
...@@ -25,17 +25,17 @@ ...@@ -25,17 +25,17 @@
enum rpc_auth_flavor { enum rpc_auth_flavor {
RPC_AUTH_NULL = 0, RPC_AUTH_NULL = 0,
RPC_AUTH_UNIX = 1, RPC_AUTH_UNIX = 1,
RPC_AUTH_SHORT = 2, RPC_AUTH_SHORT = 2
}; };
enum rpc_msg_type { enum rpc_msg_type {
RPC_CALL = 0, RPC_CALL = 0,
RPC_REPLY = 1, RPC_REPLY = 1
}; };
enum rpc_reply_stat { enum rpc_reply_stat {
RPC_MSG_ACCEPTED = 0, RPC_MSG_ACCEPTED = 0,
RPC_MSG_DENIED = 1, RPC_MSG_DENIED = 1
}; };
enum rpc_accept_stat { enum rpc_accept_stat {
...@@ -43,12 +43,12 @@ enum rpc_accept_stat { ...@@ -43,12 +43,12 @@ enum rpc_accept_stat {
RPC_PROG_UNAVAIL = 1, RPC_PROG_UNAVAIL = 1,
RPC_PROG_MISMATCH = 2, RPC_PROG_MISMATCH = 2,
RPC_PROC_UNAVAIL = 3, RPC_PROC_UNAVAIL = 3,
RPC_GARBAGE_ARGS = 4, RPC_GARBAGE_ARGS = 4
}; };
enum rpc_reject_stat { enum rpc_reject_stat {
RPC_MISMATCH = 0, RPC_MISMATCH = 0,
RPC_AUTH_ERROR = 1, RPC_AUTH_ERROR = 1
}; };
enum rpc_auth_stat { enum rpc_auth_stat {
...@@ -56,7 +56,7 @@ enum rpc_auth_stat { ...@@ -56,7 +56,7 @@ enum rpc_auth_stat {
RPC_AUTH_REJECTEDCRED = 2, RPC_AUTH_REJECTEDCRED = 2,
RPC_AUTH_BADVERF = 3, RPC_AUTH_BADVERF = 3,
RPC_AUTH_REJECTEDVERF = 4, RPC_AUTH_REJECTEDVERF = 4,
RPC_AUTH_TOOWEAK = 5, RPC_AUTH_TOOWEAK = 5
}; };
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
...@@ -80,7 +80,7 @@ enum nfs_stat { ...@@ -80,7 +80,7 @@ enum nfs_stat {
NFSERR_NOTEMPTY = 66, NFSERR_NOTEMPTY = 66,
NFSERR_DQUOT = 69, NFSERR_DQUOT = 69,
NFSERR_STALE = 70, NFSERR_STALE = 70,
NFSERR_WFLUSH = 99, NFSERR_WFLUSH = 99
}; };
enum nfs_ftype { enum nfs_ftype {
...@@ -92,7 +92,7 @@ enum nfs_ftype { ...@@ -92,7 +92,7 @@ enum nfs_ftype {
NFLNK = 5, NFLNK = 5,
NFSOCK = 6, NFSOCK = 6,
NFBAD = 7, NFBAD = 7,
NFFIFO = 8, NFFIFO = 8
}; };
#define NFS_PROGRAM 100003 #define NFS_PROGRAM 100003
......
...@@ -28,7 +28,7 @@ struct ip_config { ...@@ -28,7 +28,7 @@ struct ip_config {
unsigned long paddr; unsigned long paddr;
unsigned long router; unsigned long router;
unsigned long net; unsigned long net;
unsigned long up:1,destroy:1; unsigned int up:1,destroy:1;
}; };
#endif /* FIXME: */ #endif /* FIXME: */
......
...@@ -170,7 +170,6 @@ rt_add(short flags, unsigned long dst, unsigned long gw, struct device *dev) ...@@ -170,7 +170,6 @@ rt_add(short flags, unsigned long dst, unsigned long gw, struct device *dev)
} else { } else {
if (!((dst ^ dev->pa_addr) & dev->pa_mask)) { if (!((dst ^ dev->pa_addr) & dev->pa_mask)) {
mask = dev->pa_mask; mask = dev->pa_mask;
dst &= mask;
flags &= ~RTF_GATEWAY; flags &= ~RTF_GATEWAY;
if (flags & RTF_DYNAMIC) { if (flags & RTF_DYNAMIC) {
/*printk("Dynamic route to my own net rejected\n");*/ /*printk("Dynamic route to my own net rejected\n");*/
...@@ -178,6 +177,7 @@ rt_add(short flags, unsigned long dst, unsigned long gw, struct device *dev) ...@@ -178,6 +177,7 @@ rt_add(short flags, unsigned long dst, unsigned long gw, struct device *dev)
} }
} else } else
mask = guess_mask(dst); mask = guess_mask(dst);
dst &= mask;
} }
if (gw == dev->pa_addr) if (gw == dev->pa_addr)
flags &= ~RTF_GATEWAY; flags &= ~RTF_GATEWAY;
......
...@@ -18,5 +18,4 @@ struct new_utsname system_utsname = { ...@@ -18,5 +18,4 @@ struct new_utsname system_utsname = {
char *linux_banner = char *linux_banner =
"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@" "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
LINUX_COMPILE_HOST "." LINUX_COMPILE_DOMAIN ") " LINUX_COMPILE_HOST ") " UTS_VERSION "\n";
UTS_VERSION ": " LINUX_COMPILE_TIME "\n";
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment