Commit 1a15c9bc authored by Linus Torvalds's avatar Linus Torvalds

Import 2.3.32pre4

parent a0fb7c25
......@@ -1821,11 +1821,14 @@ S: Rueting 4
S: 23743 Groemitz
S: Germany
N: Paul Russell
E: Paul.Russell@rustcorp.com.au
N: Paul `Rusty' Russell
E: rusty@linuxcare.com
W: http://www.rustcorp.com
D: Ruggedly handsome.
D: Developed Generic IP Firewalling Chains with Michael Neuling.
D: netfilter, ipchains with Michael Neuling.
S: 301/222 City Walk
S: Canberra ACT 2601
S: Australia
N: Thomas Sailer
E: sailer@ife.ee.ethz.ch
......
......@@ -121,7 +121,7 @@ ifdef CONFIG_DRM
DRIVERS += drivers/char/drm/drm.o
endif
ifdef CONFIG_AGP
ifeq ($(CONFIG_AGP),y)
DRIVERS += drivers/char/agp/agp.o
endif
......@@ -206,7 +206,7 @@ DRIVERS := $(DRIVERS) drivers/sgi/sgi.a
endif
ifdef CONFIG_VT
DRIVERS := $(DRIVERS) drivers/video/video.a
DRIVERS := $(DRIVERS) drivers/video/video.o
endif
ifeq ($(CONFIG_PARIDE),y)
......
......@@ -430,7 +430,6 @@ CONFIG_EXT2_FS=y
# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
CONFIG_NFSD=y
# CONFIG_NFSD_SUN is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
# CONFIG_SMB_FS is not set
......
......@@ -655,7 +655,6 @@ void __init smp_store_cpu_info(int id)
*c = boot_cpu_data;
c->pte_quick = 0;
c->pmd_quick = 0;
c->pgd_quick = 0;
c->pgtable_cache_sz = 0;
identify_cpu(c);
/*
......
......@@ -162,11 +162,12 @@ int do_check_pgt_cache(int low, int high)
int freed = 0;
if(pgtable_cache_size > high) {
do {
if(pgd_quicklist)
mmlist_modify_lock(), \
free_pgd_slow(get_pgd_fast()), \
mmlist_modify_unlock(), \
if(pgd_quicklist) {
mmlist_modify_lock();
free_pgd_slow(get_pgd_fast());
mmlist_modify_unlock();
freed++;
}
if(pmd_quicklist)
free_pmd_slow(get_pmd_fast()), freed++;
if(pte_quicklist)
......
This diff is collapsed.
......@@ -7,6 +7,7 @@
* Copyright (C) 1998, 1999 Jens Axboe
*/
#include <linux/cdrom.h>
#include <asm/byteorder.h>
/* Turn this on to have the driver print out the meanings of the
......@@ -95,47 +96,14 @@ struct ide_cd_state_flags {
__u8 reserved : 4;
byte current_speed; /* Current speed of the drive */
};
#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags))
struct atapi_request_sense {
#if defined(__BIG_ENDIAN_BITFIELD)
unsigned char valid : 1;
unsigned char error_code : 7;
#elif defined(__LITTLE_ENDIAN_BITFIELD)
unsigned char error_code : 7;
unsigned char valid : 1;
#else
#error "Please fix <asm/byteorder.h>"
#endif
byte reserved1;
#if defined(__BIG_ENDIAN_BITFIELD)
unsigned char reserved3 : 2;
unsigned char ili : 1;
unsigned char reserved2 : 1;
unsigned char sense_key : 4;
#elif defined(__LITTLE_ENDIAN_BITFIELD)
unsigned char sense_key : 4;
unsigned char reserved2 : 1;
unsigned char ili : 1;
unsigned char reserved3 : 2;
#else
#error "Please fix <asm/byteorder.h>"
#endif
byte info[4];
byte sense_len;
byte command_info[4];
byte asc;
byte ascq;
byte fru;
byte sense_key_specific[3];
};
#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags))
struct packet_command {
char *buffer;
int buflen;
int stat;
struct atapi_request_sense *sense_data;
struct request_sense *sense_data;
unsigned char c[12];
};
......@@ -502,7 +470,7 @@ struct cdrom_info {
/* The result of the last successful request sense command
on this device. */
struct atapi_request_sense sense_data;
struct request_sense sense_data;
struct request request_sense_request;
struct packet_command request_sense_pc;
......
......@@ -158,6 +158,11 @@
V2.60 Implemented Auto-Probing; made changes for kernel's 2.1.xx blocksize
Adaption to linux kernel > 2.1.0
Werner Zimmermann, Nov 29, 97
November 1999 -- Make kernel-parameter implementation work with 2.3.x
Removed init_module & cleanup_module in favor of
module_init & module_exit.
Torben Mathiasen <tmm@image.dk>
*/
#include <linux/version.h>
......@@ -351,7 +356,6 @@ static int aztGetDiskInfo(void);
static int aztGetToc(int multi);
/* Kernel Interface Functions */
void aztcd_setup(char *str, int *ints);
static int check_aztcd_media_change(kdev_t full_dev);
static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
static void azt_transfer(void);
......@@ -365,11 +369,8 @@ static void aztcd_release(struct inode * inode, struct file * file);
static int aztcd_release(struct inode * inode, struct file * file);
#endif
int aztcd_init(void);
#ifdef MODULE
int init_module(void);
void cleanup_module(void);
#endif MODULE
int aztcd_init(void);
static struct file_operations azt_fops = {
NULL, /* lseek - default */
block_read, /* read - general block-dev read */
......@@ -1084,17 +1085,25 @@ static int aztGetToc(int multi)
Kernel Interface Functions
##########################################################################
*/
#ifdef AZT_KERNEL_PRIOR_2_1
void aztcd_setup(char *str, int *ints)
#else
void __init aztcd_setup(char *str, int *ints)
#endif
{ if (ints[0] > 0)
azt_port = ints[1];
if (ints[0] > 1)
azt_cont = ints[2];
#ifndef MODULE
static int __init aztcd_setup(char *str)
{
int ints[4];
(void)get_options(str, ARRAY_SIZE(ints), ints);
if (ints[0] > 0)
azt_port = ints[1];
if (ints[1] > 1)
azt_cont = ints[2];
return 1;
}
__setup("aztcd=", aztcd_setup);
#endif /* !MODULE */
/*
* Checking if the media has been changed
*/
......@@ -1614,11 +1623,7 @@ static int aztcd_release(struct inode * inode, struct file * file)
* Test for presence of drive and initialize it. Called at boot time.
*/
#ifdef AZT_KERNEL_PRIOR_2_1
int aztcd_init(void)
#else
int __init aztcd_init(void)
#endif
{ long int count, max_count;
unsigned char result[50];
int st;
......@@ -1815,14 +1820,7 @@ int __init aztcd_init(void)
return (0);
}
#ifdef MODULE
int init_module(void)
{
return aztcd_init();
}
void cleanup_module(void)
void __exit aztcd_exit(void)
{
if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL))
{ printk("What's that: can't unregister aztcd\n");
......@@ -1836,8 +1834,11 @@ void cleanup_module(void)
release_region(azt_port,4); /*proprietary interface*/
printk(KERN_INFO "aztcd module released.\n");
}
#endif MODULE
#ifdef MODULE
module_init(aztcd_init);
#endif
module_exit(aztcd_exit);
/*##########################################################################
Aztcd State Machine: Controls Drive Operating State
......@@ -2283,5 +2284,3 @@ static void azt_bin2bcd(unsigned char *p)
static int azt_bcd2bin(unsigned char bcd)
{ return (bcd >> 4) * 10 + (bcd & 0xF);
}
......@@ -186,11 +186,15 @@
-- Added setup of write mode for packet writing.
-- Fixed CDDA ripping with cdda2wav - accept much larger requests of
number of frames and split the reads in blocks of 8.
3.05 Dec 13, 1999 - Jens Axboe <axboe@image.dk>
-- Added support for changing the region of DVD drives.
-- Added sense data to generic command.
-------------------------------------------------------------------------*/
#define REVISION "Revision: 3.05"
#define VERSION "Id: cdrom.c 3.05 1999/10/24"
#define REVISION "Revision: 3.06"
#define VERSION "Id: cdrom.c 3.06 1999/12/13"
/* I use an error-log mask to give fine grain control over the type of
messages dumped to the system logs. The available masks include: */
......@@ -1909,7 +1913,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
cgc.cmd[5] = entry.cdte_addr.msf.frame;
entry.cdte_track = ti.cdti_trk1;
if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry))
if (cdo->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry))
return -EINVAL;
cgc.cmd[6] = entry.cdte_addr.msf.minute;
......@@ -2053,6 +2057,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
case CDROM_SEND_PACKET: {
__u8 *userbuf, copy = 0;
struct request_sense *sense;
if (!CDROM_CAN(CDC_GENERIC_PACKET))
return -ENOSYS;
cdinfo(CD_DO_IOCTL, "entering CDROM_SEND_PACKET\n");
......@@ -2060,6 +2065,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
copy = !!cgc.buflen;
userbuf = cgc.buffer;
cgc.buffer = NULL;
sense = cgc.sense;
if (userbuf != NULL && copy) {
/* usually commands just copy data one way, i.e.
* we send a buffer to the drive and the command
......@@ -2090,6 +2096,10 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
ret = cdo->generic_packet(cdi, &cgc);
if (copy && !ret)
__copy_to_user(userbuf, cgc.buffer, cgc.buflen);
/* copy back sense data */
if (ret && sense != NULL)
if (copy_to_user(sense, cgc.sense, sizeof(struct request_sense)))
ret = -EFAULT;
kfree(cgc.buffer);
return ret;
}
......
......@@ -142,6 +142,11 @@
* <kodis@jagunet.com>. Work begun on fixing driver to
* work under 2.1.X. Added temporary extra printks
* which seem to slow it down enough to work.
*
* 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
* Removed init_module & cleanup_module in favor of
* module_init & module_exit.
* Torben Mathiasen <tmm@image.dk>
*/
#include <linux/major.h>
......@@ -3317,11 +3322,15 @@ get_drive_configuration(unsigned short base_io,
#ifndef MODULE
/*
* Set up base I/O and interrupts, called from main.c.
*/
void __init
cdu31a_setup(char *strings,
int *ints)
static int __init cdu31a_setup(char *strings)
{
int ints[4];
(void)get_options(strings, ARRAY_SIZE(ints), ints);
if (ints[0] > 0)
{
cdu31a_port = ints[1];
......@@ -3341,7 +3350,12 @@ cdu31a_setup(char *strings,
printk("CDU31A: Unknown interface type: %s\n", strings);
}
}
return 1;
}
__setup("cdu31a=", cdu31a_setup);
#endif
static int cdu31a_block_size;
......@@ -3539,16 +3553,9 @@ cdu31a_init(void)
return -EIO;
}
#ifdef MODULE
int
init_module(void)
{
return cdu31a_init();
}
void
cleanup_module(void)
void __exit
cdu31a_exit(void)
{
if (unregister_cdrom(&scd_info))
{
......@@ -3567,4 +3574,9 @@ cleanup_module(void)
release_region(cdu31a_port,4);
printk(KERN_INFO "cdu31a module released.\n");
}
#endif MODULE
#ifdef MODULE
module_init(cdu31a_init);
#endif
module_exit(cdu31a_exit);
......@@ -151,6 +151,11 @@
24 jan 1998 Removed the cm206_disc_status() function, as it was now dead
code. The Uniform CDROM driver now provides this functionality.
9 Nov. 1999 Make kernel-parameter implementation work with 2.3.x
Removed init_module & cleanup_module in favor of
module_init & module_exit.
Torben Mathiasen <tmm@image.dk>
*
* Parts of the code are based upon lmscd.c written by Kai Petzke,
* sbpcd.c written by Eberhard Moenkeberg, and mcd.c by Martin
......@@ -1429,7 +1434,7 @@ void __init parse_options(void)
}
}
int init_module(void)
int __cm206_init(void)
{
parse_options();
#if !defined(AUTO_PROBE_MODULE)
......@@ -1438,19 +1443,26 @@ int init_module(void)
return cm206_init();
}
void cleanup_module(void)
void __exit cm206_exit(void)
{
cleanup(4);
printk(KERN_INFO "cm206 removed\n");
}
module_init(__cm206_init);
module_exit(cm206_exit);
#else /* !MODULE */
/* This setup function accepts either `auto' or numbers in the range
* 3--11 (for irq) or 0x300--0x370 (for base port) or both. */
void __init cm206_setup(char *s, int *p)
static int __init cm206_setup(char *s)
{
int i;
int i, p[4];
(void)get_options(s, ARRAY_SIZE(p), p);
if (!strcmp(s, "auto")) auto_probe=1;
for(i=1; i<=p[0]; i++) {
if (0x300 <= p[i] && i<= 0x370 && p[i] % 0x10 == 0) {
......@@ -1462,8 +1474,12 @@ void __init cm206_setup(char *s, int *p)
auto_probe = 0;
}
}
return 1;
}
#endif /* MODULE */
__setup("cm206=", cm206_setup);
#endif /* !MODULE */
/*
* Local variables:
* compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -D__SMP__ -pipe -fno-strength-reduce -m486 -DCPU=486 -D__SMP__ -DMODULE -DMODVERSIONS -include /usr/src/linux/include/linux/modversions.h -c -o cm206.o cm206.c"
......
......@@ -31,6 +31,13 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--------------------------------------------------------------------
9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
Removed init_module & cleanup_module in favor of
module_init & module_exit.
Torben Mathiasen <tmm@image.dk>
*/
......@@ -195,14 +202,24 @@ static int check_gscd_med_chg (kdev_t full_dev)
}
void __init gscd_setup (char *str, int *ints)
#ifndef MODULE
/* Using new interface for kernel-parameters */
static int __init gscd_setup (char *str)
{
int ints[2];
(void)get_options(str, ARRAY_SIZE(ints), ints);
if (ints[0] > 0)
{
gscd_port = ints[1];
}
return 1;
}
__setup("gscd=", gscd_setup);
#endif
static int gscd_ioctl (struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
{
......@@ -963,9 +980,8 @@ unsigned int AX;
}
#endif
#ifdef MODULE
/* Init for the Module-Version */
int init_module (void)
int init_gscd(void)
{
long err;
......@@ -984,7 +1000,7 @@ long err;
}
}
void cleanup_module (void)
void __exit exit_gscd(void)
{
if ((unregister_blkdev(MAJOR_NR, "gscd" ) == -EINVAL))
......@@ -996,7 +1012,11 @@ void cleanup_module (void)
release_region (gscd_port,4);
printk(KERN_INFO "GoldStar-module released.\n" );
}
#endif
#ifdef MODULE
module_init(init_gscd);
#endif
module_exit(exit_gscd);
/* Test for presence of drive and initialize it. Called only at boot time. */
......
......@@ -11,6 +11,11 @@
* Removed sound configuration.
* Added "module" support.
*
* 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
* Removed init_module & cleanup_module in favor of
* module_init & module_exit.
* Torben Mathiasen <tmm@image.dk>
*
* Detect cdrom interface on ISP16 sound card.
* Configure cdrom interface.
*
......@@ -69,17 +74,20 @@ MODULE_PARM(isp16_cdrom_base, "i");
MODULE_PARM(isp16_cdrom_irq, "i");
MODULE_PARM(isp16_cdrom_dma, "i");
MODULE_PARM(isp16_cdrom_type, "s");
int init_module(void);
void cleanup_module(void);
void isp16_exit(void);
#endif
#define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p))
#define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p))
#ifndef MODULE
void __init
isp16_setup(char *str, int *ints)
static int
__init isp16_setup(char *str)
{
int ints[4];
(void)get_options(str, ARRAY_SIZE(ints), ints);
if ( ints[0] > 0 )
isp16_cdrom_base = ints[1];
if ( ints[0] > 1 )
......@@ -88,8 +96,14 @@ isp16_setup(char *str, int *ints)
isp16_cdrom_dma = ints[3];
if ( str )
isp16_cdrom_type = str;
return 1;
}
__setup("isp16=", isp16_setup);
#endif /* MODULE */
/*
* ISP16 initialisation.
*
......@@ -307,15 +321,15 @@ isp16_cdi_config(int base, u_char drive_type, int irq, int dma)
return(0);
}
#ifdef MODULE
int init_module(void)
{
return isp16_init();
}
void cleanup_module(void)
void __exit isp16_exit(void)
{
release_region(ISP16_IO_BASE, ISP16_IO_SIZE);
printk(KERN_INFO "ISP16: module released.\n");
}
#endif /* MODULE */
#ifdef MODULE
module_init(isp16_init);
#endif
module_exit(isp16_exit);
......@@ -71,5 +71,4 @@
#define ISP16_IO_BASE 0xF8D
#define ISP16_IO_SIZE 5 /* ports used from 0xF8D up to 0xF91 */
void isp16_setup(char *str, int *ints);
int isp16_init(void);
......@@ -68,6 +68,13 @@
November 1997 -- ported to the Uniform CD-ROM driver by Erik Andersen.
March 1999 -- made io base and irq CONFIG_ options (Tigran Aivazian).
November 1999 -- Make kernel-parameter implementation work with 2.3.x
Removed init_module & cleanup_module in favor of
module_init & module_exit.
Torben Mathiasen <tmm@image.dk>
*/
#include <linux/module.h>
......@@ -229,9 +236,13 @@ static struct cdrom_device_info mcd_info = {
"mcd", /* name of the device type */
};
void __init mcd_setup(char *str, int *ints)
#ifndef MODULE
static int __init mcd_setup(char *str)
{
int ints[9];
(void)get_options(str, ARRAY_SIZE(ints), ints);
if (ints[0] > 0)
mcd_port = ints[1];
if (ints[0] > 1)
......@@ -240,8 +251,13 @@ void __init mcd_setup(char *str, int *ints)
if (ints[0] > 2)
mitsumi_bug_93_wait = ints[3];
#endif /* WORK_AROUND_MITSUMI_BUG_93 */
return 1;
}
__setup("mcd=", mcd_setup);
#endif /* MODULE */
static int mcd_media_changed(struct cdrom_device_info * cdi, int disc_nr)
{
......@@ -1127,7 +1143,7 @@ static void mcd_release(struct cdrom_device_info * cdi)
/* This routine gets called during initialization if things go wrong,
* and is used in cleanup_module as well. */
* and is used in mcd_exit as well. */
static void cleanup(int level)
{
switch (level) {
......@@ -1635,14 +1651,15 @@ Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
return limit > 0 ? 0 : -1;
}
#ifdef MODULE
int init_module(void)
{
return mcd_init();
}
void cleanup_module(void)
void __exit mcd_exit(void)
{
cleanup(3);
}
#endif MODULE
#ifdef MODULE
module_init(mcd_init);
#endif
module_exit(mcd_exit);
......@@ -44,6 +44,10 @@
* Marcin Dalecki (improved performance, shortened code)
* ... somebody forgotten?
*
* 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
* Removed init_module & cleanup_module in favor of
* module_init & module_exit.
* Torben Mathiasen <tmm@image.dk>
*/
......@@ -210,8 +214,6 @@ struct s_drive_stuff {
int mcdx_init(void);
void do_mcdx_request(request_queue_t * q);
/* already declared in init/main */
void mcdx_setup(char *, int *);
/* Indirect exported functions. These functions are exported by their
addresses, such as mcdx_open and mcdx_close in the
......@@ -770,12 +772,21 @@ static int mcdx_media_changed(struct cdrom_device_info * cdi, int disc_nr)
return 1;
}
void __init mcdx_setup(char *str, int *pi)
#ifndef MODULE
static int __init mcdx_setup(char *str)
{
int pi[4];
(void)get_options(str, ARRAY_SIZE(pi), pi);
if (pi[0] > 0) mcdx_drive_map[0][0] = pi[1];
if (pi[0] > 1) mcdx_drive_map[0][1] = pi[2];
return 1;
}
__setup("mcdx=", mcdx_setup);
#endif
/* DIRTY PART ******************************************************/
static void mcdx_delay(struct s_drive_stuff *stuff, long jifs)
......@@ -953,10 +964,10 @@ mcdx_talk (
}
/* MODULE STUFF ***********************************************************/
#ifdef MODULE
EXPORT_NO_SYMBOLS;
int init_module(void)
int __mcdx_init(void)
{
int i;
int drives = 0;
......@@ -976,7 +987,7 @@ int init_module(void)
return 0;
}
void cleanup_module(void)
void __exit mcdx_exit(void)
{
int i;
......@@ -1009,7 +1020,11 @@ void cleanup_module(void)
#endif
}
#endif MODULE
#ifdef MODULE
module_init(__mcdx_init);
#endif
module_exit(mcdx_exit);
/* Support functions ************************************************/
......
......@@ -57,6 +57,11 @@
thanks to Luke McFarlane. Also tidied up some
printk behaviour. ISP16 initialization
is now handled by a separate driver.
09-11-99 Make kernel-parameter implementation work with 2.3.x
Removed init_module & cleanup_module in favor of
module_init & module_exit.
Torben Mathiasen <tmm@image.dk>
*/
/* Includes */
......@@ -2020,14 +2025,23 @@ static struct file_operations opt_fops = {
NULL /* revalidate */
};
#ifndef MODULE
/* Get kernel parameter when used as a kernel driver */
void __init optcd_setup(char *str, int *ints)
static int optcd_setup(char *str)
{
int ints[4];
(void)get_options(str, ARRAY_SIZE(ints), ints);
if (ints[0] > 0)
optcd_port = ints[1];
return 1;
}
__setup("optcd=", optcd_setup);
#endif MODULE
/* Test for presence of drive and initialize it. Called at boot time
or during module initialisation. */
int __init optcd_init(void)
......@@ -2076,14 +2090,7 @@ int __init optcd_init(void)
}
#ifdef MODULE
int init_module(void)
{
return optcd_init();
}
void cleanup_module(void)
void __exit optcd_exit(void)
{
if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) {
printk(KERN_ERR "optcd: what's that: can't unregister\n");
......@@ -2092,4 +2099,10 @@ void cleanup_module(void)
release_region(optcd_port, 4);
printk(KERN_INFO "optcd: module released.\n");
}
#endif MODULE
#ifdef MODULE
module_init(optcd_init);
#endif
module_exit(optcd_exit);
......@@ -307,6 +307,11 @@
* 4.62 Fix a bug where playing audio left the drive in an unusable state.
* Heiko Eissfeldt <heiko@colossus.escape.de>
*
* November 1999 -- Make kernel-parameter implementation work with 2.3.x
* Removed init_module & cleanup_module in favor of
* module_init & module_exit.
* Torben Mathiasen <tmm@image.dk>
*
*
* TODO
* implement "read all subchannel data" (96 bytes per frame)
......@@ -324,6 +329,7 @@
#include <linux/module.h>
#include <linux/version.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
......@@ -5457,12 +5463,15 @@ static struct cdrom_device_info sbpcd_info = {
* bytes above).
*
*/
#if (SBPCD_ISSUE-1)
static void __init sbpcd_setup(const char *s, int *p)
static int sbpcd_setup(char *s)
#else
void __init sbpcd_setup(const char *s, int *p)
int sbpcd_setup(char *s)
#endif
{
int p[4];
(void)get_options(s, ARRAY_SIZE(p), p);
setup_done++;
msg(DBG_INI,"sbpcd_setup called with %04X,%s\n",p[1], s);
sbpro_type=0; /* default: "LaserMate" */
......@@ -5494,7 +5503,13 @@ void __init sbpcd_setup(const char *s, int *p)
}
}
else CDi_data=sbpcd_ioaddr+2;
return 1;
}
__setup("sbpcd=", sbpcd_setup);
/*==========================================================================*/
/*
* Sequoia S-1000 CD-ROM Interface Configuration
......@@ -5569,7 +5584,7 @@ static int __init config_spea(void)
* Called once at boot or load time.
*/
#ifdef MODULE
int init_module(void)
int __init __SBPCD_INIT(void)
#else
int __init SBPCD_INIT(void)
#endif MODULE
......@@ -5616,7 +5631,7 @@ int __init SBPCD_INIT(void)
else if (sbpcd[port_index+1]==1) type=str_sb;
else if (sbpcd[port_index+1]==3) type=str_t16;
else type=str_lm;
sbpcd_setup(type, addr);
sbpcd_setup((char *)type);
#if DISTRIBUTION
msg(DBG_INF,"Scanning 0x%X (%s)...\n", CDo_command, type);
#endif DISTRIBUTION
......@@ -5808,7 +5823,7 @@ int __init SBPCD_INIT(void)
}
/*==========================================================================*/
#ifdef MODULE
void cleanup_module(void)
void sbpcd_exit(void)
{
int j;
......@@ -5833,6 +5848,14 @@ void cleanup_module(void)
}
msg(DBG_INF, "%s module released.\n", major_name);
}
#ifdef MODULE
module_init(__SBPCD_INIT) /*HACK!*/;
#endif
module_exit(sbpcd_exit);
#endif MODULE
/*==========================================================================*/
/*
......
......@@ -49,6 +49,10 @@
* the previous version of this driver. Coded added by Anthony Barbachan
* from bugfix tip originally suggested by Alan Cox.
*
* November 1999 -- Make kernel-parameter implementation work with 2.3.x
* Removed init_module & cleanup_module in favor of
* module_init & module_exit.
* Torben Mathiasen <tmm@image.dk>
*/
#define SJCD_VERSION_MAJOR 1
......@@ -163,12 +167,21 @@ static int sjcd_cleanup(void);
* Set up device, i.e., use command line data to set
* base address.
*/
void __init sjcd_setup( char *str, int *ints )
#ifndef MODULE
static int __init sjcd_setup( char *str)
{
int ints[2];
(void)get_options(str, ARRAY_SIZE(ints), ints);
if (ints[0] > 0)
sjcd_base = ints[1];
return 1;
}
__setup("sjcd=", sjcd_setup);
#endif
/*
* Special converters.
*/
......@@ -1577,18 +1590,18 @@ sjcd_cleanup(void)
return(0);
}
#ifdef MODULE
int init_module(void)
{
return sjcd_init();
}
void cleanup_module(void)
void __exit sjcd_exit(void)
{
if ( sjcd_cleanup() )
printk( "SJCD: module: cannot be removed.\n" );
else
printk(KERN_INFO "SJCD: module: removed.\n");
}
#ifdef MODULE
module_init(sjcd_init);
#endif
module_exit(sjcd_exit);
......@@ -31,6 +31,11 @@
* More changes to support CDU-510/515 series
* (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>)
*
* November 1999 -- Make kernel-parameter implementation work with 2.3.x
* Removed init_module & cleanup_module in favor of
* module_init & module_exit.
* Torben Mathiasen <tmm@image.dk>
*
* Things to do:
* - handle errors and status better, put everything into a single word
* - use interrupts (code mostly there, but a big hole still missing)
......@@ -1648,6 +1653,7 @@ sony535_init(void)
}
#ifndef MODULE
/*
* accept "kernel command line" parameters
* (added by emoenke@gwdg.de)
......@@ -1657,9 +1663,11 @@ sony535_init(void)
*
* the address value has to be the existing CDROM port address.
*/
void __init
sonycd535_setup(char *strings, int *ints)
static int __init
sonycd535_setup(char *strings)
{
int ints[3];
(void)get_options(strings, ARRAY_SIZE(ints), ints);
/* if IRQ change and default io base desired,
* then call with io base of 0
*/
......@@ -1671,17 +1679,16 @@ sonycd535_setup(char *strings, int *ints)
if ((strings != NULL) && (*strings != '\0'))
printk(CDU535_MESSAGE_NAME
": Warning: Unknown interface type: %s\n", strings);
return 1;
}
#else /* MODULE */
__setup("sonycd535=", sonycd535_setup);
int init_module(void)
{
return sony535_init();
}
#endif /* MODULE */
void
cleanup_module(void)
void __exit
sony535_exit(void)
{
int i;
......@@ -1696,4 +1703,10 @@ cleanup_module(void)
else
printk(KERN_INFO CDU535_HANDLE " module released\n");
}
#endif /* MODULE */
#ifdef MODULE
module_init(sony535_init);
#endif
module_exit(sony535_exit);
......@@ -214,7 +214,7 @@ if [ "$CONFIG_FTAPE" != "n" ]; then
fi
endmenu
bool 'Direct Rendering Manager (XFree86 DRI support) (EXPERIMENTAL)' CONFIG_DRM
bool 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM
dep_tristate ' 3dfx Banshee/Voodoo3' CONFIG_DRM_TDFX $CONFIG_DRM
if [ "$CONFIG_DRM" = "y" ]; then
dep_tristate ' 3dlabs GMX 2000' CONFIG_DRM_GAMMA m
......
......@@ -27,6 +27,8 @@
#ifndef _AGP_BACKEND_PRIV_H
#define _AGP_BACKEND_PRIV_H 1
#include <linux/config.h>
enum aper_size_type {
U8_APER_SIZE,
U16_APER_SIZE,
......
......@@ -41,7 +41,6 @@
#include <linux/miscdevice.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/page.h>
......
......@@ -292,6 +292,8 @@ static struct dev_info device_list[] =
{"MATSHITA","PD-2 LF-D100","*", BLIST_GHOST},
{"HITACHI", "GF-1050","*", BLIST_GHOST}, /* Hitachi SCSI DVD-RAM */
{"TOSHIBA","CDROM","*", BLIST_ISROM},
{"Toshiba","DVD-RAM SD-W1101","*", BLIST_GHOST},
{"Toshiba","DVD-RAM SD-W1111","*", BLIST_GHOST},
/*
* Must be at end of list...
......
......@@ -619,9 +619,10 @@ struct scsi_cmnd {
struct request request; /* A copy of the command we are
working on */
unsigned char sense_buffer[64]; /* obtained by REQUEST SENSE when
CHECK CONDITION is received on
original command (auto-sense) */
unsigned char sense_buffer[64]; /* obtained by REQUEST SENSE
* when CHECK CONDITION is
* received on original command
* (auto-sense) */
unsigned flags;
......
......@@ -7,6 +7,7 @@
* anything out of the ordinary is seen.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
......
......@@ -32,6 +32,7 @@
*/
#define __NO_VERSION__
#include <linux/config.h>
#include <linux/module.h>
#include <linux/sched.h>
......
......@@ -314,7 +314,7 @@ static int sd_init_command(Scsi_Cmnd * SCpnt)
SCpnt->cmnd[1] = (SCpnt->lun << 5) & 0xe0;
if (((this_count > 0xff) || (block > 0x1fffff)) && SCpnt->device->ten) {
if (((this_count > 0xff) || (block > 0x1fffff)) || SCpnt->device->ten) {
if (this_count > 0xffff)
this_count = 0xffff;
......@@ -405,8 +405,9 @@ static int sd_open(struct inode *inode, struct file *filp)
return -EROFS;
}
/*
* It is possible that the disk changing stuff resulted in the device being taken
* offline. If this is the case, report this to the user, and don't pretend that
* It is possible that the disk changing stuff resulted in the device
* being taken offline. If this is the case, report this to the user,
* and don't pretend that
* the open actually succeeded.
*/
if (!rscsi_disks[target].device->online) {
......@@ -529,41 +530,50 @@ static void rw_intr(Scsi_Cmnd * SCpnt)
/*
Handle MEDIUM ERRORs that indicate partial success. Since this is a
relatively rare error condition, no care is taken to avoid unnecessary
additional work such as memcpy's that could be avoided.
relatively rare error condition, no care is taken to avoid
unnecessary additional work such as memcpy's that could be avoided.
*/
if (driver_byte(result) != 0 && /* An error occurred */
SCpnt->sense_buffer[0] == 0xF0 && /* Sense data is valid */
SCpnt->sense_buffer[2] == MEDIUM_ERROR) {
long error_sector = (SCpnt->sense_buffer[3] << 24) |
(SCpnt->sense_buffer[4] << 16) |
(SCpnt->sense_buffer[5] << 8) |
SCpnt->sense_buffer[6];
if (SCpnt->request.bh != NULL)
block_sectors = SCpnt->request.bh->b_size >> 9;
switch (SCpnt->device->sector_size) {
case 1024:
error_sector <<= 1;
if (block_sectors < 2)
block_sectors = 2;
break;
case 2048:
error_sector <<= 2;
if (block_sectors < 4)
block_sectors = 4;
break;
case 256:
error_sector >>= 1;
break;
default:
break;
/* An error occurred */
if (driver_byte(result) != 0) {
/* Sense data is valid */
if (SCpnt->sense_buffer[0] == 0xF0 && SCpnt->sense_buffer[2] == MEDIUM_ERROR) {
long error_sector = (SCpnt->sense_buffer[3] << 24) |
(SCpnt->sense_buffer[4] << 16) |
(SCpnt->sense_buffer[5] << 8) |
SCpnt->sense_buffer[6];
if (SCpnt->request.bh != NULL)
block_sectors = SCpnt->request.bh->b_size >> 9;
switch (SCpnt->device->sector_size) {
case 1024:
error_sector <<= 1;
if (block_sectors < 2)
block_sectors = 2;
break;
case 2048:
error_sector <<= 2;
if (block_sectors < 4)
block_sectors = 4;
break;
case 256:
error_sector >>= 1;
break;
default:
break;
}
error_sector -= sd[MINOR(SCpnt->request.rq_dev)].start_sect;
error_sector &= ~(block_sectors - 1);
good_sectors = error_sector - SCpnt->request.sector;
if (good_sectors < 0 || good_sectors >= this_count)
good_sectors = 0;
}
if (SCpnt->sense_buffer[2] == ILLEGAL_REQUEST) {
if (SCpnt->device->ten == 1) {
if (SCpnt->cmnd[0] == READ_10 ||
SCpnt->cmnd[0] == WRITE_10)
SCpnt->device->ten = 0;
}
}
error_sector -= sd[MINOR(SCpnt->request.rq_dev)].start_sect;
error_sector &= ~(block_sectors - 1);
good_sectors = error_sector - SCpnt->request.sector;
if (good_sectors < 0 || good_sectors >= this_count)
good_sectors = 0;
}
/*
* This calls the generic completion function, now that we know
......@@ -597,10 +607,10 @@ static int check_scsidisk_media_change(kdev_t full_dev)
return 0;
/*
* If the device is offline, don't send any commands - just pretend as if
* the command failed. If the device ever comes back online, we can deal with
* it then. It is only because of unrecoverable errors that we would ever
* take a device offline in the first place.
* If the device is offline, don't send any commands - just pretend as
* if the command failed. If the device ever comes back online, we
* can deal with it then. It is only because of unrecoverable errors
* that we would ever take a device offline in the first place.
*/
if (rscsi_disks[target].device->online == FALSE) {
rscsi_disks[target].ready = 0;
......@@ -618,10 +628,11 @@ static int check_scsidisk_media_change(kdev_t full_dev)
*/
retval = sd_ioctl(&inode, NULL, SCSI_IOCTL_START_UNIT, 0);
if (retval) { /* Unable to test, unit probably not ready. This usually
* means there is no disc in the drive. Mark as changed,
* and we will figure it out later once the drive is
* available again. */
if (retval) { /* Unable to test, unit probably not ready.
* This usually means there is no disc in the
* drive. Mark as changed, and we will figure
* it out later once the drive is available
* again. */
rscsi_disks[target].ready = 0;
rscsi_disks[target].device->changed = 1;
......@@ -744,8 +755,12 @@ static int sd_init_onedisk(int i)
}
spintime = 1;
spintime_value = jiffies;
time1 = jiffies + HZ;
while (time_before(jiffies, time1)); /* Wait 1 second for next try */
time1 = HZ;
/* Wait 1 second for next try */
do {
current->state = TASK_UNINTERRUPTIBLE;
time1 = schedule_timeout(time1);
} while(time1);
printk(".");
}
} while (the_result && spintime && time_after(spintime_value + 100 * HZ, jiffies));
......
......@@ -244,9 +244,12 @@ static void rw_intr(Scsi_Cmnd * SCpnt)
static request_queue_t *sr_find_queue(kdev_t dev)
{
if (MINOR(dev) >= sr_template.dev_max
|| !scsi_CDs[MINOR(dev)].device)
return NULL; /* No such device */
/*
* No such device
*/
if (MINOR(dev) >= sr_template.dev_max || !scsi_CDs[MINOR(dev)].device)
return NULL;
return &scsi_CDs[MINOR(dev)].device->request_queue;
}
......@@ -328,13 +331,13 @@ static int sr_init_command(Scsi_Cmnd * SCpnt)
SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
return 0;
}
SCpnt->cmnd[0] = WRITE_6;
SCpnt->cmnd[0] = WRITE_10;
break;
case READ:
SCpnt->cmnd[0] = READ_6;
SCpnt->cmnd[0] = READ_10;
break;
default:
panic("Unknown sd command %d\n", SCpnt->request.cmd);
panic("Unknown sr command %d\n", SCpnt->request.cmd);
}
SCSI_LOG_HLQUEUE(2, printk("sr%d : %s %d/%ld 512 byte blocks.\n",
......@@ -344,28 +347,16 @@ static int sr_init_command(Scsi_Cmnd * SCpnt)
SCpnt->cmnd[1] = (SCpnt->lun << 5) & 0xe0;
if (((this_count > 0xff) || (block > 0x1fffff)) && SCpnt->device->ten) {
if (this_count > 0xffff)
this_count = 0xffff;
SCpnt->cmnd[0] += READ_10 - READ_6;
SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff;
SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff;
SCpnt->cmnd[5] = (unsigned char) block & 0xff;
SCpnt->cmnd[6] = SCpnt->cmnd[9] = 0;
SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff;
SCpnt->cmnd[8] = (unsigned char) this_count & 0xff;
} else {
if (this_count > 0xff)
this_count = 0xff;
SCpnt->cmnd[1] |= (unsigned char) ((block >> 16) & 0x1f);
SCpnt->cmnd[2] = (unsigned char) ((block >> 8) & 0xff);
SCpnt->cmnd[3] = (unsigned char) block & 0xff;
SCpnt->cmnd[4] = (unsigned char) this_count;
SCpnt->cmnd[5] = 0;
}
if (this_count > 0xffff)
this_count = 0xffff;
SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff;
SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff;
SCpnt->cmnd[5] = (unsigned char) block & 0xff;
SCpnt->cmnd[6] = SCpnt->cmnd[9] = 0;
SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff;
SCpnt->cmnd[8] = (unsigned char) this_count & 0xff;
/*
* We shouldn't disconnect in the middle of a sector, so with a dumb
......@@ -666,7 +657,6 @@ static int sr_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command
Scsi_Device *device = scsi_CDs[MINOR(cdi->dev)].device;
unsigned char *buffer = cgc->buffer;
int buflen;
int stat;
/* get the device */
SCpnt = scsi_allocate_device(device, 1);
......@@ -695,7 +685,8 @@ static int sr_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command
scsi_wait_cmd(SCpnt, (void *) cgc->cmd, (void *) buffer, cgc->buflen,
sr_init_done, SR_TIMEOUT, MAX_RETRIES);
stat = SCpnt->result;
if ((cgc->stat = SCpnt->result))
cgc->sense = (struct request_sense *) SCpnt->sense_buffer;
/* release */
SCpnt->request.rq_dev = MKDEV(0, 0);
......@@ -707,7 +698,9 @@ static int sr_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command
memcpy(cgc->buffer, buffer, cgc->buflen);
scsi_free(buffer, buflen);
}
return stat;
return cgc->stat;
}
static int sr_registered = 0;
......
......@@ -56,7 +56,6 @@ int sr_do_ioctl(int target, unsigned char *sr_cmd, void *buffer, unsigned buflen
Scsi_Cmnd *SCpnt;
Scsi_Device *SDev;
int result, err = 0, retries = 0;
unsigned long flags;
char *bounce_buffer;
SDev = scsi_CDs[target].device;
......
......@@ -7,6 +7,12 @@ MOD_SUB_DIRS :=
MOD_IN_SUB_DIRS :=
ALL_SUB_DIRS :=
O_TARGET := video.o
O_OBJS :=
M_OBJS :=
# This is a nice idea but needs depmod altering
# MOD_LIST_NAME := VIDEO_MODULES
# All of the (potential) objects that export symbols.
# This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
......@@ -96,27 +102,35 @@ obj-$(CONFIG_FBCON_MAC) += fbcon-mac.o
obj-$(CONFIG_FBCON_MFB) += fbcon-mfb.o
obj-$(CONFIG_FBCON_VGA) += fbcon-vga.o
# Extract lists of the multi-part drivers.
# The 'int-*' lists are the intermediate files used to build the multi's.
multi-y := $(filter $(list-multi), $(obj-y))
multi-m := $(filter $(list-multi), $(obj-m))
int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
# Files that are both resident and modular: remove from modular.
obj-m := $(filter-out $(obj-y), $(obj-m))
int-m := $(filter-out $(int-y), $(int-m))
# Take multi-part drivers out of obj-y and put components in.
obj-y := $(filter-out $(list-multi), $(obj-y))
obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y)
# Translate to Rules.make lists.
L_TARGET := video.a
# This is a nice idea but needs depmod altering
#MOD_LIST_NAME := VIDEO_MODULES
L_OBJS := $(sort $(filter-out $(export-objs), $(obj-y)))
LX_OBJS := $(sort $(filter $(export-objs), $(obj-y)))
O_OBJS := $(filter-out $(export-objs), $(obj-y))
OX_OBJS := $(filter $(export-objs), $(obj-y))
M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
include $(TOPDIR)/Rules.make
clean:
rm -f core *.o *.a *.s
promcon_tbl.c: prom.uni ../char/conmakehash
../char/conmakehash prom.uni | \
sed -e '/#include <[^>]*>/p' -e 's/types/init/' \
......
......@@ -9,101 +9,19 @@
*/
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/malloc.h>
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/affs_fs.h>
#include <linux/amigaffs.h>
#include <asm/uaccess.h>
#include <linux/pagemap.h>
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
static int affs_readlink(struct dentry *, char *, int);
static struct dentry *affs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int);
struct inode_operations affs_symlink_inode_operations = {
NULL, /* no file-operations */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
affs_readlink, /* readlink */
affs_follow_link, /* follow_link */
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* truncate */
NULL, /* permission */
NULL /* revalidate */
};
static int
affs_readlink(struct dentry *dentry, char *buffer, int buflen)
static int affs_symlink_readpage(struct dentry *dentry, struct page *page)
{
struct buffer_head *bh;
struct inode *inode = dentry->d_inode;
struct buffer_head *bh;
struct slink_front *lf;
int i, j;
char c;
char lc;
char *pf;
pr_debug("AFFS: readlink(ino=%lu,buflen=%d)\n",inode->i_ino,buflen);
bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));
if (!bh) {
affs_warning(inode->i_sb,"follow_link","Unable to read i-node block %lu\n",
inode->i_ino);
return -EIO;
}
lf = (struct slink_front *)bh->b_data;
lc = 0;
i = 0;
j = 0;
pf = inode->i_sb->u.affs_sb.s_prefix ? inode->i_sb->u.affs_sb.s_prefix : "/";
if (strchr(lf->symname,':')) { /* Handle assign or volume name */
while (i < buflen && (c = pf[i])) {
put_user(c,buffer++);
i++;
}
while (i < buflen && (c = lf->symname[j]) != ':') {
put_user(c,buffer++);
i++, j++;
}
if (i < buflen) {
put_user('/',buffer++);
i++, j++;
}
lc = '/';
}
while (i < buflen && (c = lf->symname[j])) {
if (c == '/' && lc == '/' && (i + 3 < buflen)) { /* parent dir */
put_user('.',buffer++);
put_user('.',buffer++);
i += 2;
}
put_user(c,buffer++);
lc = c;
i++, j++;
}
affs_brelse(bh);
return i;
}
static struct dentry *
affs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow)
{
struct inode *inode = dentry->d_inode;
struct buffer_head *bh;
struct slink_front *lf;
char *buffer;
char *link = (char*)kmap(page);
struct slink_front *lf;
int err;
int i, j;
char c;
char lc;
......@@ -111,47 +29,49 @@ affs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow
pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino);
if (!(buffer = kmalloc(1024,GFP_KERNEL))) {
dput(base);
return ERR_PTR(-ENOSPC);
}
err = -EIO;
bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));
if (!bh) {
affs_warning(inode->i_sb,"follow_link","Unable to read i-node block %lu\n",
inode->i_ino);
kfree(buffer);
dput(base);
return ERR_PTR(-EIO);
}
if (!bh)
goto fail;
i = 0;
j = 0;
lf = (struct slink_front *)bh->b_data;
lc = 0;
pf = inode->i_sb->u.affs_sb.s_prefix ? inode->i_sb->u.affs_sb.s_prefix : "/";
if (strchr(lf->symname,':')) { /* Handle assign or volume name */
if (strchr(lf->symname,':')) { /* Handle assign or volume name */
while (i < 1023 && (c = pf[i]))
buffer[i++] = c;
link[i++] = c;
while (i < 1023 && lf->symname[j] != ':')
buffer[i++] = lf->symname[j++];
link[i++] = lf->symname[j++];
if (i < 1023)
buffer[i++] = '/';
link[i++] = '/';
j++;
lc = '/';
}
while (i < 1023 && (c = lf->symname[j])) {
if (c == '/' && lc == '/' && i < 1020) { /* parent dir */
buffer[i++] = '.';
buffer[i++] = '.';
link[i++] = '.';
link[i++] = '.';
}
buffer[i++] = c;
link[i++] = c;
lc = c;
j++;
}
buffer[i] = '\0';
link[i] = '\0';
affs_brelse(bh);
base = lookup_dentry(buffer,base,follow);
kfree(buffer);
return base;
kunmap(page);
UnlockPage(page);
return 0;
fail:
SetPageError(page);
kunmap(page);
UnlockPage(page);
return err;
}
struct inode_operations affs_symlink_inode_operations = {
readlink: page_readlink,
follow_link: page_follow_link,
readpage: affs_symlink_readpage,
};
......@@ -7,97 +7,48 @@
*/
#include <linux/string.h>
#include <linux/malloc.h>
#include <linux/efs_fs.h>
#include <linux/pagemap.h>
static int efs_readlink(struct dentry *, char *, int);
static struct dentry * efs_follow_link(struct dentry *, struct dentry *, unsigned int);
struct inode_operations efs_symlink_inode_operations = {
NULL, /* no symlink file-operations */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
efs_readlink, /* readlink */
efs_follow_link, /* follow_link */
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* truncate */
NULL, /* permission */
NULL /* revalidate */
};
static char *efs_linktarget(struct inode *in, int *len) {
char *name;
static int efs_symlink_readpage(struct dentry *dentry, struct page *page)
{
char *link = (char*)kmap(page);
struct buffer_head * bh;
efs_block_t size = in->i_size;
if (size > 2 * EFS_BLOCKSIZE) {
printk(KERN_ERR "EFS: linktarget(): name too long: %lu\n", in->i_size);
return NULL;
}
struct inode * inode = dentry->d_inode;
efs_block_t size = inode->i_size;
int err;
if (!(name = kmalloc(size + 1, GFP_KERNEL)))
return NULL;
err = -ENAMETOOLONG;
if (size > 2 * EFS_BLOCKSIZE)
goto fail;
/* read first 512 bytes of link target */
bh = bread(in->i_dev, efs_bmap(in, 0), EFS_BLOCKSIZE);
if (!bh) {
kfree(name);
printk(KERN_ERR "EFS: linktarget(): couldn't read block %d\n", efs_bmap(in, 0));
return NULL;
}
memcpy(name, bh->b_data, (size > EFS_BLOCKSIZE) ? EFS_BLOCKSIZE : size);
err = -EIO;
bh = bread(inode->i_dev, efs_bmap(inode, 0), EFS_BLOCKSIZE);
if (!bh)
goto fail;
memcpy(link, bh->b_data, (size > EFS_BLOCKSIZE) ? EFS_BLOCKSIZE : size);
brelse(bh);
if (size > EFS_BLOCKSIZE) {
bh = bread(in->i_dev, efs_bmap(in, 1), EFS_BLOCKSIZE);
if (!bh) {
kfree(name);
printk(KERN_ERR "EFS: linktarget(): couldn't read block %d\n", efs_bmap(in, 1));
return NULL;
}
memcpy(name + EFS_BLOCKSIZE, bh->b_data, size - EFS_BLOCKSIZE);
bh = bread(inode->i_dev, efs_bmap(inode, 1), EFS_BLOCKSIZE);
if (!bh)
goto fail;
memcpy(link + EFS_BLOCKSIZE, bh->b_data, size - EFS_BLOCKSIZE);
brelse(bh);
}
name[size] = (char) 0;
if (len) *len = size;
return name;
}
static struct dentry *efs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow) {
char *name;
struct inode *inode = dentry->d_inode;
if (!(name = efs_linktarget(inode, NULL))) {
dput(base);
return ERR_PTR(-ELOOP);
}
base = lookup_dentry(name, base, follow);
kfree(name);
return base;
}
static int efs_readlink(struct dentry * dir, char * buf, int bufsiz) {
int rc;
char *name;
struct inode *inode = dir->d_inode;
if (!(name = efs_linktarget(inode, &bufsiz))) return 0;
rc = copy_to_user(buf, name, bufsiz) ? -EFAULT : bufsiz;
kfree(name);
return rc;
link[size] = '\0';
kunmap(page);
UnlockPage(page);
return 0;
fail:
SetPageError(page);
kunmap(page);
UnlockPage(page);
return err;
}
struct inode_operations efs_symlink_inode_operations = {
readlink: page_readlink,
follow_link: page_follow_link,
readpage: efs_symlink_readpage
};
......@@ -69,8 +69,64 @@ static void set_indirect_ea(struct super_block *s, int ano, secno a, char *data,
hpfs_ea_write(s, a, ano, 0, size, data);
}
/* Read an extended attribute named 'key' */
/* Read an extended attribute named 'key' into the provided buffer */
int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key,
char *buf, int size)
{
unsigned pos;
int ano, len;
secno a;
struct extended_attribute *ea;
struct extended_attribute *ea_end = fnode_end_ea(fnode);
for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
if (!strcmp(ea->name, key)) {
if (ea->indirect)
goto indirect;
if (ea->valuelen >= size)
return -EINVAL;
memcpy(buf, ea_data(ea), ea->valuelen);
buf[ea->valuelen] = 0;
return 0;
}
a = fnode->ea_secno;
len = fnode->ea_size_l;
ano = fnode->ea_anode;
pos = 0;
while (pos < len) {
char ex[4 + 255 + 1 + 8];
ea = (struct extended_attribute *)ex;
if (pos + 4 > len) {
hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x",
ano ? "anode" : "sectors", a, len);
return -EIO;
}
if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return -EIO;
if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea->indirect ? 8 : 0), ex + 4))
return -EIO;
if (!strcmp(ea->name, key)) {
if (ea->indirect)
goto indirect;
if (ea->valuelen >= size)
return -EINVAL;
if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea->valuelen, buf))
return -EIO;
buf[ea->valuelen] = 0;
return 0;
}
pos += ea->namelen + ea->valuelen + 5;
}
return -ENOENT;
indirect:
if (ea_len(ea) >= size)
return -EINVAL;
if (hpfs_ea_read(s, ea_sec(ea), ea->anode, 0, ea_len(ea), buf))
return -EIO;
buf[ea_len(ea)] = 0;
return 0;
}
/* Read an extended attribute named 'key' */
char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *size)
{
char *ret;
......
......@@ -96,7 +96,7 @@ static int hpfs_write_partial_page(struct file *file, struct page *page, unsigne
pgpos = ((inode->i_blocks - 1) * 512) >> PAGE_CACHE_SHIFT;
while (pgpos < page->index) {
status = -ENOMEM;
new_page = grab_page_cache(&inode->i_data, pgpos);
new_page = grab_cache_page(&inode->i_data, pgpos);
if (!new_page)
goto out;
status = block_write_cont_page(file, new_page, PAGE_SIZE, 0, NULL);
......
......@@ -249,6 +249,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *, fnode_secno, struct f
/* ea.c */
void hpfs_ea_ext_remove(struct super_block *, secno, int, unsigned);
int hpfs_read_ea(struct super_block *, struct fnode *, char *, char *, int);
char *hpfs_get_ea(struct super_block *, struct fnode *, char *, int *);
void hpfs_set_ea(struct inode *, struct fnode *, char *, char *, int);
......@@ -283,10 +284,6 @@ struct anode *hpfs_map_anode(struct super_block *s, anode_secno, struct buffer_h
struct dnode *hpfs_map_dnode(struct super_block *s, dnode_secno, struct quad_buffer_head *);
dnode_secno hpfs_fnode_dno(struct super_block *s, ino_t ino);
/* mmap.c */
int hpfs_mmap(struct file *, struct vm_area_struct *);
/* name.c */
unsigned char hpfs_upcase(unsigned char *, unsigned char);
......@@ -305,8 +302,7 @@ int hpfs_mknod(struct inode *, struct dentry *, int, int);
int hpfs_symlink(struct inode *, struct dentry *, const char *);
int hpfs_unlink(struct inode *, struct dentry *);
int hpfs_rmdir(struct inode *, struct dentry *);
int hpfs_readlink(struct dentry *, char *, int);
struct dentry *hpfs_follow_link(struct dentry *, struct dentry *, unsigned int);
int hpfs_symlink_readpage(struct dentry *, struct page *);
int hpfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
/* super.c */
......
......@@ -16,7 +16,7 @@ static const struct file_operations hpfs_file_ops =
NULL, /* readdir - bad */
NULL, /* poll - default */
NULL, /* ioctl - default */
generic_file_mmap/*hpfs_mmap*/, /* mmap */
generic_file_mmap, /* mmap */
hpfs_open, /* open */
NULL, /* flush */
hpfs_file_release, /* release */
......@@ -92,27 +92,11 @@ static const struct inode_operations hpfs_dir_iops =
const struct inode_operations hpfs_symlink_iops =
{
NULL, /* default file operations */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
hpfs_readlink, /* readlink */
hpfs_follow_link, /* follow_link */
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* truncate */
NULL, /* permission */
NULL /* revalidate */
readlink: page_readlink,
follow_link: page_follow_link,
readpage: hpfs_symlink_readpage
};
void hpfs_read_inode(struct inode *i)
{
struct buffer_head *bh;
......
......@@ -396,54 +396,33 @@ int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
return r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;
}
int hpfs_readlink(struct dentry *dentry, char *buf, int len)
int hpfs_symlink_readpage(struct dentry *dentry, struct page *page)
{
char *link = (char*)kmap(page);
struct inode *i = dentry->d_inode;
struct fnode *fnode;
struct buffer_head *bh;
char *symlink;
int slen;
if (!S_ISLNK(i->i_mode)) {
return -EINVAL;
}
if (!(fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) {
return -EIO;
}
if (!(symlink = hpfs_get_ea(i->i_sb, fnode, "SYMLINK", &slen))) {
brelse(bh);
return -EFSERROR;
}
brelse(bh);
if (slen > len) slen = len;
memcpy_tofs(buf, symlink, slen);
kfree(symlink);
return slen;
}
int err;
struct dentry *hpfs_follow_link(struct dentry *dinode, struct dentry *ddir,
unsigned int follow)
{
struct inode *inode = dinode->d_inode;
char *link;
unsigned len;
struct buffer_head *bh;
struct fnode *fnode;
if (!(fnode = hpfs_map_fnode(inode->i_sb, inode->i_ino, &bh))) {
dput(dinode);
return ERR_PTR(-EIO);
}
if (!(link = hpfs_get_ea(inode->i_sb, fnode, "SYMLINK", &len))) {
brelse(bh);
dput(dinode);
return ERR_PTR(-EIO);
}
err = -EIO;
if (!(fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh)))
goto fail;
err = hpfs_read_ea(i->i_sb, fnode, "SYMLINK", link, PAGE_SIZE);
brelse(bh);
UPDATE_ATIME(inode);
ddir = lookup_dentry(link, ddir, follow);
kfree(link);
return ddir;
}
if (err)
goto fail;
SetPageUptodate(page);
kunmap(page);
UnlockPage(page);
return 0;
fail:
SetPageError(page);
kunmap(page);
UnlockPage(page);
return err;
}
int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
......
......@@ -12,6 +12,7 @@
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/malloc.h>
#include <linux/pagemap.h>
#include "rock.h"
......@@ -387,142 +388,155 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
return 0;
}
static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr)
{
int slen;
int rootflag;
struct SL_component *oldslp;
struct SL_component *slp;
slen = rr->len - 5;
slp = &rr->u.SL.link;
while (slen > 1) {
rootflag = 0;
switch (slp->flags & ~1) {
case 0:
memcpy(rpnt, slp->text, slp->len);
rpnt+=slp->len;
break;
case 4:
*rpnt++='.';
/* fallthru */
case 2:
*rpnt++='.';
break;
case 8:
rootflag = 1;
*rpnt++='/';
break;
default:
printk("Symlink component flag not implemented (%d)\n",
slp->flags);
}
slen -= slp->len + 2;
oldslp = slp;
slp = (struct SL_component *) ((char *) slp + slp->len + 2);
if (slen < 2) {
/*
* If there is another SL record, and this component
* record isn't continued, then add a slash.
*/
if ((rr->u.SL.flags & 1) && !(oldslp->flags & 1))
*rpnt++='/';
break;
}
/*
* If this component record isn't continued, then append a '/'.
*/
if (!rootflag && !(oldslp->flags & 1))
*rpnt++='/';
/* Returns the name of the file that this inode is symlinked to. This is
in malloc'd memory, so it needs to be freed, once we are through with it */
}
return rpnt;
}
char * get_rock_ridge_symlink(struct inode * inode)
{
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
struct buffer_head * bh;
char * rpnt = NULL;
unsigned char * pnt;
struct iso_directory_record * raw_inode;
CONTINUE_DECLS;
int block;
int sig;
int rootflag;
int len;
unsigned char * chr;
struct rock_ridge * rr;
if (!inode->i_sb->u.isofs_sb.s_rock)
panic("Cannot have symlink with high sierra variant of iso filesystem\n");
block = inode->i_ino >> bufbits;
bh = bread(inode->i_dev, block, bufsize);
if (!bh)
goto out_noread;
pnt = ((unsigned char *) bh->b_data) + (inode->i_ino & (bufsize - 1));
raw_inode = ((struct iso_directory_record *) pnt);
/*
* If we go past the end of the buffer, there is some sort of error.
*/
if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize)
goto out_bad_span;
/* Now test for possible Rock Ridge extensions which will override some of
these numbers in the inode structure. */
SETUP_ROCK_RIDGE(raw_inode, chr, len);
repeat:
while (len > 1){ /* There may be one byte for padding somewhere */
rr = (struct rock_ridge *) chr;
if (rr->len == 0) goto out; /* Something got screwed up here */
sig = (chr[0] << 8) + chr[1];
chr += rr->len;
len -= rr->len;
switch(sig){
case SIG('R','R'):
if((rr->u.RR.flags[0] & RR_SL) == 0) goto out;
break;
case SIG('S','P'):
CHECK_SP(goto out);
break;
case SIG('S','L'):
{int slen;
struct SL_component * oldslp;
struct SL_component * slp;
slen = rr->len - 5;
slp = &rr->u.SL.link;
while (slen > 1){
if (!rpnt){
rpnt = (char *) kmalloc (inode->i_size +1, GFP_KERNEL);
if (!rpnt) goto out;
*rpnt = 0;
};
rootflag = 0;
switch(slp->flags &~1){
case 0:
strncat(rpnt,slp->text, slp->len);
break;
case 2:
strcat(rpnt,".");
break;
case 4:
strcat(rpnt,"..");
break;
case 8:
rootflag = 1;
strcat(rpnt,"/");
break;
default:
printk("Symlink component flag not implemented (%d)\n",slen);
};
slen -= slp->len + 2;
oldslp = slp;
slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
if(slen < 2) {
/*
* If there is another SL record, and this component record
* isn't continued, then add a slash.
*/
if( ((rr->u.SL.flags & 1) != 0)
&& ((oldslp->flags & 1) == 0) ) strcat(rpnt,"/");
break;
}
/* readpage() for symlinks: reads symlink contents into the page and either
makes it uptodate and returns 0 or returns error (-EIO) */
/*
* If this component record isn't continued, then append a '/'.
*/
if( (!rootflag)
&& ((oldslp->flags & 1) == 0) ) strcat(rpnt,"/");
};
break;
case SIG('C','E'):
CHECK_CE; /* This tells is if there is a continuation record */
break;
default:
break;
}
};
};
MAYBE_CONTINUE(repeat,inode);
out_freebh:
int rock_ridge_symlink_readpage(struct dentry *dentry, struct page *page)
{
struct inode *inode = dentry->d_inode;
char *link = (char*)kmap(page);
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
struct buffer_head *bh;
char *rpnt = link;
unsigned char *pnt;
struct iso_directory_record *raw_inode;
CONTINUE_DECLS;
int block;
int sig;
int len;
unsigned char *chr;
struct rock_ridge *rr;
if (!inode->i_sb->u.isofs_sb.s_rock)
panic ("Cannot have symlink with high sierra variant of iso filesystem\n");
block = inode->i_ino >> bufbits;
bh = bread(inode->i_dev, block, bufsize);
if (!bh)
goto out_noread;
pnt = (unsigned char *) bh->b_data + (inode->i_ino & (bufsize - 1));
raw_inode = (struct iso_directory_record *) pnt;
/*
* If we go past the end of the buffer, there is some sort of error.
*/
if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize)
goto out_bad_span;
/* Now test for possible Rock Ridge extensions which will override
some of these numbers in the inode structure. */
SETUP_ROCK_RIDGE(raw_inode, chr, len);
repeat:
while (len > 1) { /* There may be one byte for padding somewhere */
rr = (struct rock_ridge *) chr;
if (rr->len == 0)
goto out; /* Something got screwed up here */
sig = (chr[0] << 8) + chr[1];
chr += rr->len;
len -= rr->len;
switch (sig) {
case SIG('R', 'R'):
if ((rr->u.RR.flags[0] & RR_SL) == 0)
goto out;
break;
case SIG('S', 'P'):
CHECK_SP(goto out);
break;
case SIG('S', 'L'):
rpnt = get_symlink_chunk(rpnt, rr);
break;
case SIG('C', 'E'):
/* This tells is if there is a continuation record */
CHECK_CE;
default:
break;
}
}
MAYBE_CONTINUE(repeat, inode);
if (rpnt == link)
goto fail;
brelse(bh);
return rpnt;
*rpnt = '\0';
SetPageUptodate(page);
kunmap(page);
UnlockPage(page);
return 0;
/* error exit from macro */
out:
if(buffer)
out:
if (buffer)
kfree(buffer);
if(rpnt)
kfree(rpnt);
rpnt = NULL;
goto out_freebh;
out_noread:
goto fail;
out_noread:
printk("unable to read i-node block");
goto out_freebh;
out_bad_span:
goto fail;
out_bad_span:
printk("symlink spans iso9660 blocks\n");
goto out_freebh;
fail:
brelse(bh);
SetPageError(page);
kunmap(page);
UnlockPage(page);
return -EIO;
}
......@@ -17,70 +17,11 @@
#include <linux/stat.h>
#include <linux/malloc.h>
#include <asm/uaccess.h>
static int isofs_readlink(struct dentry *, char *, int);
static struct dentry * isofs_follow_link(struct dentry *, struct dentry *, unsigned int);
/*
* symlinks can't do much...
*/
struct inode_operations isofs_symlink_inode_operations = {
NULL, /* no file-operations */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
isofs_readlink, /* readlink */
isofs_follow_link, /* follow_link */
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* truncate */
NULL, /* permission */
NULL /* revalidate */
readlink: page_readlink,
follow_link: page_follow_link,
readpage: rock_ridge_symlink_readpage
};
static int isofs_readlink(struct dentry * dentry, char * buffer, int buflen)
{
char * pnt;
int i;
if (buflen > 1023)
buflen = 1023;
pnt = get_rock_ridge_symlink(dentry->d_inode);
if (!pnt)
return 0;
i = strlen(pnt);
if (i > buflen)
i = buflen;
if (copy_to_user(buffer, pnt, i))
i = -EFAULT;
kfree(pnt);
return i;
}
static struct dentry * isofs_follow_link(struct dentry * dentry,
struct dentry *base,
unsigned int follow)
{
char * pnt;
pnt = get_rock_ridge_symlink(dentry->d_inode);
if(!pnt) {
dput(base);
return ERR_PTR(-ELOOP);
}
base = lookup_dentry(pnt, base, follow);
kfree(pnt);
return base;
}
......@@ -284,7 +284,7 @@ static struct dentry * do_follow_link(struct dentry *base, struct dentry *dentry
if ((follow & LOOKUP_FOLLOW)
&& inode && inode->i_op && inode->i_op->follow_link) {
if (current->link_count < 5) {
if (current->link_count < 32) {
struct dentry * result;
current->link_count++;
......@@ -1437,9 +1437,9 @@ int vfs_readlink(struct dentry *dentry, char *buffer, int buflen, char *link)
return len;
}
struct dentry *
vfs_follow_link(struct dentry *dentry, struct dentry *base,
unsigned int follow, char *link)
static inline struct dentry *
__vfs_follow_link(struct dentry *dentry, struct dentry *base,
unsigned follow, char *link)
{
struct dentry *result;
UPDATE_ATIME(dentry->d_inode);
......@@ -1455,6 +1455,13 @@ unsigned int follow, char *link)
return (struct dentry *)link;
}
struct dentry *
vfs_follow_link(struct dentry *dentry, struct dentry *base,
unsigned int follow, char *link)
{
return __vfs_follow_link(dentry,base,follow,link);
}
/* get the link contents into pagecache */
static char *page_getlink(struct dentry * dentry, struct page **ppage)
{
......@@ -1495,7 +1502,7 @@ page_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow
{
struct page *page = NULL;
char *s = page_getlink(dentry, &page);
struct dentry *res = vfs_follow_link(dentry,base,follow,s);
struct dentry *res = __vfs_follow_link(dentry,base,follow,s);
if (page) {
kunmap(page);
page_cache_release(page);
......
......@@ -38,152 +38,69 @@
#define NCP_SYMLINK_MAGIC0 le32_to_cpu(0x6c6d7973) /* "symlnk->" */
#define NCP_SYMLINK_MAGIC1 le32_to_cpu(0x3e2d6b6e)
static int ncp_readlink(struct dentry *, char *, int);
static struct dentry *ncp_follow_link(struct dentry *, struct dentry *, unsigned int);
int ncp_create_new(struct inode *dir, struct dentry *dentry,
int mode,int attributes);
/*
* symlinks can't do much...
*/
struct inode_operations ncp_symlink_inode_operations={
NULL, /* no file-operations */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
ncp_readlink, /* readlink */
ncp_follow_link, /* follow_link */
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* truncate */
NULL, /* permission */
NULL /* revalidate */
};
/* ----- follow a symbolic link ------------------------------------------ */
/* ----- read a symbolic link ------------------------------------------ */
static struct dentry *ncp_follow_link(struct dentry *dentry,
struct dentry *base,
unsigned int follow)
static int ncp_symlink_readpage(struct dentry *dentry, struct page *page)
{
struct inode *inode=dentry->d_inode;
int error, length, len, cnt;
char *link, *buf;
#ifdef DEBUG
PRINTK("ncp_follow_link(dentry=%p,base=%p,follow=%u)\n",dentry,base,follow);
#endif
if(!S_ISLNK(inode->i_mode)) {
dput(base);
return ERR_PTR(-EINVAL);
}
char *link;
char *buf = (char*)kmap(page);
if(ncp_make_open(inode,O_RDONLY)) {
dput(base);
return ERR_PTR(-EIO);
}
error = -EIO;
if (ncp_make_open(inode,O_RDONLY))
goto fail;
error = -ENOMEM;
for (cnt = 0; (link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_NFS))==NULL; cnt++) {
if (cnt > 10) {
dput(base);
return ERR_PTR(-EAGAIN); /* -ENOMEM? */
}
if (cnt > 10)
goto fail;
schedule();
}
error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
0,NCP_MAX_SYMLINK_SIZE,link,&length);
if (error!=0 || length<NCP_MIN_SYMLINK_SIZE ||
((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 || ((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) {
dput(base);
if (error) {
kfree(link);
return ERR_PTR(-EIO);
goto fail;
}
len = NCP_MAX_SYMLINK_SIZE;
buf = (char *) kmalloc(len, GFP_NFS);
if (!buf) {
dput(base);
if (length<NCP_MIN_SYMLINK_SIZE ||
((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 ||
((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) {
error = -EIO;
kfree(link);
return ERR_PTR(-EAGAIN);
}
error = ncp_vol2io(NCP_SERVER(inode), buf, &len, link+8, length-8, 0);
kfree(link);
if (error) {
dput(base);
kfree(buf);
return ERR_PTR(error);
}
/* UPDATE_ATIME(inode); */
base = lookup_dentry(buf, base, follow);
kfree(buf);
return base;
}
/* ----- read symbolic link ---------------------------------------------- */
static int ncp_readlink(struct dentry * dentry, char * buffer, int buflen)
{
struct inode *inode=dentry->d_inode;
char *link, *buf;
int length, len, error;
#ifdef DEBUG
PRINTK("ncp_readlink(dentry=%p,buffer=%p,buflen=%d)\n",dentry,buffer,buflen);
#endif
if(!S_ISLNK(inode->i_mode))
return -EINVAL;
if(ncp_make_open(inode,O_RDONLY))
return -EIO;
if((link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE,GFP_NFS))==NULL)
return -ENOMEM;
error = ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
0,NCP_MAX_SYMLINK_SIZE,link,&length);
if (error!=0 || length < NCP_MIN_SYMLINK_SIZE || buflen < (length-8) ||
((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 ||((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) {
error = -EIO;
goto out;
goto fail;
}
len = NCP_MAX_SYMLINK_SIZE;
buf = (char *) kmalloc(len, GFP_NFS);
if (!buf) {
error = -ENOMEM;
goto out;
}
error = ncp_vol2io(NCP_SERVER(inode), buf, &len, link+8, length-8, 0);
if (error || buflen < len) {
error = -EIO;
kfree(buf);
goto out;
}
error = len;
if(copy_to_user(buffer, buf, error))
error = -EFAULT;
kfree(buf);
out:
kfree(link);
if (error)
goto fail;
kunmap(page);
UnlockPage(page);
return 0;
fail:
SetPageError(page);
kunmap(page);
UnlockPage(page);
return error;
}
/*
* symlinks can't do much...
*/
struct inode_operations ncp_symlink_inode_operations={
readlink: page_readlink,
follow_link: page_follow_link,
readpage: ncp_symlink_readpage,
};
/* ----- create a new symbolic link -------------------------------------- */
int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
......
......@@ -5,141 +5,18 @@
* inspired from linux/fs/msdos/file.c Werner Almesberger
*
* Extended MS-DOS regular file handling primitives
*
* Wow. It looks like we could support them on FAT with little (if any)
* problems. Oh, well...
*/
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/msdos_fs.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/stat.h>
#include <linux/umsdos_fs.h>
#include <linux/malloc.h>
#include <asm/uaccess.h>
#include <asm/system.h>
static struct file_operations umsdos_symlink_operations;
/*
* Read the data associate with the symlink.
* Return length read in buffer or a negative error code.
*
*/
int umsdos_readlink_x ( struct dentry *dentry,
char *buffer,
int bufsiz)
{
size_t size = dentry->d_inode->i_size;
loff_t loffs = 0;
ssize_t ret;
struct file filp;
Printk((KERN_DEBUG "UMSDOS_read: %s/%s, size=%u\n",
dentry->d_parent->d_name.name, dentry->d_name.name, size));
fill_new_filp (&filp, dentry);
filp.f_reada = 0;
filp.f_flags = O_RDONLY;
filp.f_op = &umsdos_symlink_operations;
if (size > bufsiz)
size = bufsiz;
ret = fat_file_read (&filp, buffer, size, &loffs);
if (ret != size) {
ret = -EIO;
}
return ret;
}
static int UMSDOS_readlink (struct dentry *dentry, char *buffer, int buflen)
{
return umsdos_readlink_x (dentry, buffer, buflen);
}
/* this one mostly stolen from romfs :) */
static struct dentry *UMSDOS_followlink (struct dentry *dentry,
struct dentry *base,
unsigned int follow)
{
struct inode *inode = dentry->d_inode;
char *symname;
int len, cnt;
mm_segment_t old_fs = get_fs ();
Printk((KERN_DEBUG "UMSDOS_followlink /mn/: (%s/%s)\n",
dentry->d_parent->d_name.name, dentry->d_name.name));
len = inode->i_size;
if (!(symname = kmalloc (len + 1, GFP_KERNEL))) {
dentry = ERR_PTR (-ENOMEM);
goto outnobuf;
}
set_fs (KERNEL_DS); /* we read into kernel space this time */
cnt = umsdos_readlink_x (dentry, symname, len);
set_fs (old_fs);
if (len != cnt) {
dentry = ERR_PTR (-EIO);
goto out;
}
symname[len] = 0;
dentry = lookup_dentry (symname, base, follow);
kfree (symname);
if (0) {
out:
kfree (symname);
outnobuf:
dput (base);
}
return dentry;
}
/* needed to patch the file structure */
static struct file_operations umsdos_symlink_operations =
{
NULL, /* lseek - default */
NULL, /* read */
NULL, /* write */
NULL, /* readdir - bad */
NULL, /* poll - default */
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open is needed */
NULL, /* no flush code */
NULL, /* release */
NULL /* fsync */
};
struct inode_operations umsdos_symlink_inode_operations =
{
NULL, /* default file operations (none) */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
UMSDOS_readlink, /* readlink */
UMSDOS_followlink, /* followlink */
fat_get_block, /* get_block */
block_read_full_page, /* readpage */
NULL, /* writepage */
NULL, /* truncate */
NULL, /* permission */
NULL /* revalidate */
readlink: page_readlink,
follow_link: page_follow_link,
get_block: fat_get_block,
readpage: block_read_full_page
};
......@@ -88,6 +88,8 @@ extern inline void spin_unlock(spinlock_t *lock)
#if SPINLOCK_DEBUG
if (lock->magic != SPINLOCK_MAGIC)
BUG();
if (!lock->lock)
BUG();
#endif
__asm__ __volatile__(
spin_unlock_string
......
......@@ -12,6 +12,7 @@
#define _LINUX_CDROM_H
#include <linux/types.h>
#include <asm/byteorder.h>
/*******************************************************
* As of Linux 2.1.x, all Linux CD-ROM application programs will use this
......@@ -269,11 +270,12 @@ struct cdrom_blk
/* for CDROM_PACKET_COMMAND ioctl */
struct cdrom_generic_command
{
unsigned char cmd[CDROM_PACKET_SIZE];
unsigned char *buffer;
unsigned int buflen;
int stat;
void *reserved[4];
unsigned char cmd[CDROM_PACKET_SIZE];
unsigned char *buffer;
unsigned int buflen;
int stat;
struct request_sense *sense;
void *reserved[3];
};
......@@ -646,6 +648,7 @@ struct dvd_lu_send_asf {
};
struct dvd_host_send_rpcstate {
__u8 type;
__u8 pdrc;
};
......@@ -671,6 +674,36 @@ typedef union {
struct dvd_lu_send_rpcstate lrpcs;
} dvd_authinfo;
struct request_sense {
#if defined(__BIG_ENDIAN_BITFIELD)
__u8 valid : 1;
__u8 error_code : 7;
#elif defined(__LITTLE_ENDIAN_BITFIELD)
__u8 error_code : 7;
__u8 valid : 1;
#endif
__u8 segment_number;
#if defined(__BIG_ENDIAN_BITFIELD)
__u8 reserved1 : 2;
__u8 ili : 1;
__u8 reserved2 : 1;
__u8 sense_key : 4;
#elif defined(__LITTLE_ENDIAN_BITFIELD)
__u8 sense_key : 4;
__u8 reserved2 : 1;
__u8 ili : 1;
__u8 reserved1 : 2;
#endif
__u8 information[4];
__u8 add_sense_len;
__u8 command_info[4];
__u8 asc;
__u8 ascq;
__u8 fruc;
__u8 sks[3];
__u8 asb[46];
};
#ifdef __KERNEL__
struct cdrom_write_settings {
......
......@@ -62,6 +62,7 @@ extern int max_super_blocks, nr_super_blocks;
#define READ 0
#define WRITE 1
#define READA 2 /* read-ahead - don't block if no resources */
#define SPECIAL 4 /* For non-blockdevice requests in request queue */
#define WRITERAW 5 /* raw write - don't play with buffer lists */
......
......@@ -178,7 +178,7 @@ extern int iso_date(char *, int);
extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *);
extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *);
extern char * get_rock_ridge_symlink(struct inode *);
extern int rock_ridge_symlink_readpage(struct dentry *, struct page *);
extern int find_rock_ridge_relocation(struct iso_directory_record *, struct inode *);
int get_joliet_filename(struct iso_directory_record *, struct inode *, unsigned char *);
......
......@@ -320,7 +320,6 @@ struct mm_struct * mm_alloc(void)
mmlist_modify_unlock();
return mm;
}
mmlist_modify_unlock();
kmem_cache_free(mm_cachep, mm);
}
return NULL;
......
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