diff -u --recursive --new-file v2.1.51/linux/Documentation/Changes linux/Documentation/Changes --- v2.1.51/linux/Documentation/Changes Sun Jul 27 12:11:00 1997 +++ linux/Documentation/Changes Fri Aug 22 10:04:33 1997 @@ -54,6 +54,7 @@ - Autofs 0.3.7 ; automount --version - NFS 0.4.21 ; showmount --version - Bash 1.14.7 ; bash -version +- Smbfs 2.1.0 Upgrade notes ************* @@ -159,6 +160,10 @@ to a 2.6 release. Also, amd is being phased out in favor of the much better autofs. You'll also have to get the appropriate utils to use autofs as well as the new NFS utils. + +The smbfs code is also being revised. This results in an incompatible +mount interface. See the README of smbfs-2.1.0 or later for a +description of the new mount command. RPM === diff -u --recursive --new-file v2.1.51/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.1.51/linux/Documentation/Configure.help Mon Aug 18 18:19:42 1997 +++ linux/Documentation/Configure.help Mon Aug 25 13:01:58 1997 @@ -1982,12 +1982,10 @@ CONFIG_SCSI_NCR53C8XX This is the BSD ncr driver adapted to linux for the NCR53C8XX family of PCI-SCSI controllers. This driver supports parity checking, - tagged command queuing, fast scsi II transfer up to 10 MB/s with - narrow scsi devices and 20 MB/s with wide scsi devices. - Support of Ultra SCSI data transfers with NCR53C860 and NCR53C875 - controllers has been recently added to the driver. + tagged command queuing, Fast-20 data transfer up to 20 MB/s with + narrow scsi devices and 40 MB/s with wide scsi devices. Please read drivers/scsi/README.ncr53c8xx for more information. - Linux/i386 and Linux/Alpha are supported by this driver. + Linux/i386, Linux/Alpha and Linux/PPC are supported by this driver. synchronous data transfers frequency CONFIG_SCSI_NCR53C8XX_SYNC @@ -2015,10 +2013,11 @@ CONFIG_SCSI_NCR53C8XX_IOMAPPED This option allows you to force the driver to use normal IO. Memory mapped IO has less latency than normal IO and works for most - Intel-based hardware. - Under Linux/Alpha only normal IO is currently supported by the driver - and so, this option has no effect. - The normal answer therefore is N. Try Y only if you have problems. + Intel-based hardware. Under Linux/Alpha and Linux/PPC only normal + IO is currently supported by the driver and so, this option has no + effect. On Linux/PPC MMIO and normal IO are done the same (all IO + is memory mapped) so you loose nothing by using normal IO. The normal + answer therefore is N. Try Y only if you have problems. not allow targets to disconnect CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT diff -u --recursive --new-file v2.1.51/linux/Documentation/filesystems/smbfs.txt linux/Documentation/filesystems/smbfs.txt --- v2.1.51/linux/Documentation/filesystems/smbfs.txt Sun Jul 27 12:11:00 1997 +++ linux/Documentation/filesystems/smbfs.txt Fri Aug 22 10:04:33 1997 @@ -8,6 +8,6 @@ netbios name or share. To use smbfs, you need a special mount program, which can be found in -the ksmbfs package, found on +the smbfs package, found on - sunsite.unc.edu:/pub/Linux/system/filesystems/smbfs + ftp://ftp.gwdg.de/pub/linux/misc/smbfs/ diff -u --recursive --new-file v2.1.51/linux/arch/alpha/defconfig linux/arch/alpha/defconfig --- v2.1.51/linux/arch/alpha/defconfig Thu Jul 17 10:06:03 1997 +++ linux/arch/alpha/defconfig Sat Aug 23 23:45:10 1997 @@ -43,7 +43,7 @@ CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_EM86=y -# CONFIG_PNP_PARPORT is not set +# CONFIG_PARPORT is not set # # Plug and Play support @@ -67,7 +67,6 @@ # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set # CONFIG_BLK_DEV_XD is not set # CONFIG_BLK_DEV_EZ is not set # CONFIG_BLK_DEV_HD is not set @@ -142,6 +141,7 @@ # CONFIG_SCSI_NCR53C406A is not set # CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_NCR53C8XX is not set +# CONFIG_SCSI_PPA is not set # CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_QLOGIC_FAS is not set CONFIG_SCSI_QLOGIC_ISP=y @@ -150,6 +150,8 @@ # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_U14_34F is not set # CONFIG_SCSI_ULTRASTOR is not set +# CONFIG_SCSI_MESH is not set +# CONFIG_SCSI_MAC53C94 is not set # # Network device support @@ -174,6 +176,7 @@ # CONFIG_NET_POCKET is not set # CONFIG_FDDI is not set # CONFIG_DLCI is not set +# CONFIG_PLIP is not set # CONFIG_PPP is not set # CONFIG_NET_RADIO is not set # CONFIG_SLIP is not set @@ -215,6 +218,7 @@ # CONFIG_ROMFS_FS is not set # CONFIG_AUTOFS_FS is not set # CONFIG_UFS_FS is not set +# CONFIG_MAC_PARTITION is not set # # Character devices @@ -230,12 +234,15 @@ # CONFIG_MS_BUSMOUSE is not set CONFIG_PSMOUSE=y # CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set # CONFIG_UMISC is not set # CONFIG_QIC02_TAPE is not set # CONFIG_FTAPE is not set # CONFIG_APM is not set # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set +# CONFIG_NVRAM is not set +# CONFIG_JOYSTICK is not set # # Sound diff -u --recursive --new-file v2.1.51/linux/drivers/char/vt.c linux/drivers/char/vt.c --- v2.1.51/linux/drivers/char/vt.c Thu Aug 14 20:49:16 1997 +++ linux/drivers/char/vt.c Wed Aug 20 14:03:40 1997 @@ -490,6 +490,8 @@ case KIOCSOUND: if (!perm) return -EPERM; + if (arg) + arg = 1193180 / arg; kd_mksound(arg, 0); return 0; @@ -505,6 +507,8 @@ */ ticks = HZ * ((arg >> 16) & 0xffff) / 1000; count = ticks ? (arg & 0xffff) : 0; + if (count) + count = 1193180 / count; kd_mksound(count, ticks); return 0; } diff -u --recursive --new-file v2.1.51/linux/drivers/scsi/ChangeLog.ncr53c8xx linux/drivers/scsi/ChangeLog.ncr53c8xx --- v2.1.51/linux/drivers/scsi/ChangeLog.ncr53c8xx Mon Aug 11 14:47:04 1997 +++ linux/drivers/scsi/ChangeLog.ncr53c8xx Mon Aug 25 13:01:58 1997 @@ -1,3 +1,28 @@ +Thu Aug 23 23:43 1997 Gerard Roudier (groudier@club-internet.fr) + * revision 2.5a + - Update Configure.help for inclusion in linux-2.1.51/2/3 + - Use BASE_2 address from PCI config space instead of some + IO register for getting the on-board SRAM bus address. + - Remove error testing of pcibios_read/write functions. + These functions are intended to be used for successfully + detected PCI devices. Expecting error condition from them + is nothing but paranoia. + +Thu Aug 21 23:00 1997 Gerard Roudier (groudier@club-internet.fr) + * revision 2.5 + - 53C860 chip support fix. + - Move the 'host_status' to the last DWORD of the CCB header. + This header is copied back by the script processor. This + guarantees that the header is entirely copied back over + the PCI when the CPU completes a CCB. + - (re)read ISTAT prior to scanning CCBs for completion. This + ensure that any posted buffer are flushed prior CCBs scan. + - Support for BIG ENDIAN cpu. Added by Cort . + Initial patch did'nt support disconnections and tagged commands. + I've completed the patch and it seems that all is ok now. + Only some powerpc under 2.1.X is supported for the moment. + - Misc. trivial fixes and cleanups. + Sat July 26 18:00 1997 Gerard Roudier (groudier@club-internet.fr) * revision 2.4 Several clean-ups: diff -u --recursive --new-file v2.1.51/linux/drivers/scsi/README.ncr53c8xx linux/drivers/scsi/README.ncr53c8xx --- v2.1.51/linux/drivers/scsi/README.ncr53c8xx Mon Aug 11 14:47:05 1997 +++ linux/drivers/scsi/README.ncr53c8xx Mon Aug 25 13:01:58 1997 @@ -4,7 +4,7 @@ 21 Rue Carnot 95170 DEUIL LA BARRE - FRANCE -19 June 1997 +23 August 1997 =============================================================================== 1. Introduction @@ -46,6 +46,9 @@ 17.1 Features 17.2 Symbios NVRAM layout 17.3 Tekram NVRAM layout +18. Support for Big Endian + 18.1 Big Endian CPU + 18.2 NCR chip in Big Endian mode of operations =============================================================================== @@ -83,7 +86,7 @@ driver, configuration parameters and control commands available through the proc SCSI file system read / write operations. -This driver has been tested OK with linux/i386 and Linux/Alpha. +This driver has been tested OK with linux/i386, Linux/Alpha and Linux/PPC. Latest driver version and patches are available at: @@ -429,7 +432,10 @@ CONFIG_SCSI_NCR53C8XX_IOMAPPED (default answer: n) Answer "y" if you suspect your mother board to not allow memory mapped I/O. - May slow down performance a little. + May slow down performance a little. This option is required by + Linux/PPC and is used no matter what you select here. Linux/PPC + suffers no performance loss with this option since all IO is memory + mapped anyway. CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE (default answer: n) Answer "y" if you are sure that all your SCSI devices that are able to @@ -1430,8 +1436,29 @@ 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0xfbbc -=============================================================================== -End of NCR53C8XX driver README file +18. Support for Big Endian +The PCI local bus has been primarily designed for x86 architecture. +As a consequence, PCI devices generally expect DWORDS using little endian +byte ordering. + +18.1 Big Endian CPU + +In order to support NCR chips on a Big Endian architecture the driver has to +perform byte reordering each time it is needed. This feature has been +added to the driver by Cort and is available in driver +version 2.5 and later ones. For the moment Big Endian support has only +been tested on Linux/PPC (PowerPC). + +18.2 NCR chip in Big Endian mode of operations + +It can be read in SYMBIOS documentation that some chips support a special +Big Endian mode, on paper: 53C815, 53C825A, 53C875, 53C875N, 53C895. +This mode of operations is not software-selectable, but needs pin named +BigLit to be pulled-up. Using this mode, most of byte reorderings should +be avoided when the driver is running on a Big Endian CPU. +Driver version 2.5 is also, in theory, ready for this feature. +=============================================================================== +End of NCR53C8XX driver README file diff -u --recursive --new-file v2.1.51/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c --- v2.1.51/linux/drivers/scsi/ncr53c8xx.c Thu Aug 14 20:49:16 1997 +++ linux/drivers/scsi/ncr53c8xx.c Mon Aug 25 13:01:58 1997 @@ -60,11 +60,14 @@ ** May 19 1997 by Richard Waltham : ** Support for NvRAM detection and reading. ** +** August 18 1997 by Cort : +** Support for Power/PC (Big Endian). +** ******************************************************************************* */ /* -** 26 July 1997, version 2.4 +** 23 August 1997, version 2.5a ** ** Supported SCSI-II features: ** Synchronous negotiation @@ -306,6 +309,7 @@ ** architecture. */ +#ifndef NCR_IOMAPPED __initfunc( static vm_offset_t remap_pci_mem(u_long base, u_long size) ) @@ -332,6 +336,7 @@ vfree((void *) (vaddr & PAGE_MASK)); #endif } +#endif /* !NCR_IOMAPPED */ #else /* linux-1.2.13 */ @@ -657,6 +662,7 @@ int bus; u_char device_fn; u_int base; + u_int base_2; u_int io_port; int irq; /* port and reg fields to use INB, OUTB macros */ @@ -743,79 +749,156 @@ /*========================================================== ** -** Access to the controller chip. -** -** If NCR_IOMAPPED is defined, only IO are used by the driver. +** Big/Little endian support. ** **========================================================== */ /* -** IO mapped only input / ouput +** If the NCR uses big endian addressing mode over the +** PCI, actual io register addresses for byte and word +** accesses must be changed according to lane routing. +** Btw, ncr_offb() and ncr_offw() macros only apply to +** constants and so donnot generate bloated code. */ -#define IOM_INB(r) inb (np->port + offsetof(struct ncr_reg, r)) -#define IOM_INB_OFF(o) inb (np->port + (o)) -#define IOM_INW(r) inw (np->port + offsetof(struct ncr_reg, r)) -#define IOM_INL(r) inl (np->port + offsetof(struct ncr_reg, r)) -#define IOM_INL_OFF(o) inl (np->port + (o)) - -#define IOM_OUTB(r, val) outb ((val), np->port+offsetof(struct ncr_reg,r)) -#define IOM_OUTW(r, val) outw ((val), np->port+offsetof(struct ncr_reg,r)) -#define IOM_OUTL(r, val) outl ((val), np->port+offsetof(struct ncr_reg,r)) -#define IOM_OUTL_OFF(o, val) outl ((val), np->port + (o)) +#if defined(SCSI_NCR_BIG_ENDIAN) + +#define ncr_offb(o) (((o)&~3)+((~((o)&3))&3)) +#define ncr_offw(o) (((o)&~3)+((~((o)&3))&2)) + +#else + +#define ncr_offb(o) (o) +#define ncr_offw(o) (o) + +#endif /* -** MEMORY mapped IO input / output +** If the CPU and the NCR use same endian-ness adressing, +** no byte reordering is needed for script patching. +** Macro cpu_to_scr() is to be used for script patching. +** Macro scr_to_cpu() is to be used for getting a DWORD +** from the script. */ -#define MMIO_INB(r) readb(&np->reg->r) -#define MMIO_INB_OFF(o) readb((char *)np->reg + (o)) -#define MMIO_INW(r) readw(&np->reg->r) -#define MMIO_INL(r) readl(&np->reg->r) -#define MMIO_INL_OFF(o) readl((char *)np->reg + (o)) - -#define MMIO_OUTB(r, val) writeb((val), &np->reg->r) -#define MMIO_OUTW(r, val) writew((val), &np->reg->r) -#define MMIO_OUTL(r, val) writel((val), &np->reg->r) -#define MMIO_OUTL_OFF(o, val) writel((val), (char *)np->reg + (o)) +#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN) + +#define cpu_to_scr(dw) cpu_to_le32(dw) +#define scr_to_cpu(dw) le32_to_cpu(dw) + +#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN) + +#define cpu_to_scr(dw) cpu_to_be32(dw) +#define scr_to_cpu(dw) be32_to_cpu(dw) + +#else + +#define cpu_to_scr(dw) (dw) +#define scr_to_cpu(dw) (dw) + +#endif + +/*========================================================== +** +** Access to the controller chip. +** +** If NCR_IOMAPPED is defined, only IO are used by the driver. +** +**========================================================== +*/ /* -** IO mapped input / output +** If the CPU and the NCR use same endian-ness adressing, +** no byte reordering is needed for accessing chip io +** registers. Functions suffixed by '_raw' are assumed +** to access the chip over the PCI without doing byte +** reordering. Functions suffixed by '_l2b' are +** assumed to perform little-endian to big-endian byte +** reordering, those suffixed by '_b2l' blah, blah, +** blah, ... */ #if defined(NCR_IOMAPPED) -#define INB(r) IOM_INB(r) -#define INB_OFF(o) IOM_INB_OFF(o) -#define INW(r) IOM_INW(r) -#define INL(r) IOM_INL(r) -#define INL_OFF(o) IOM_INL_OFF(o) - -#define OUTB(r, val) IOM_OUTB(r, val) -#define OUTW(r, val) IOM_OUTW(r, val) -#define OUTL(r, val) IOM_OUTL(r, val) -#define OUTL_OFF(o, val) IOM_OUTL_OFF(o, val) +/* +** IO mapped only input / ouput +*/ + +#define INB_OFF(o) inb (np->port + ncr_offb(o)) +#define OUTB_OFF(o, val) outb ((val), np->port + ncr_offb(o)) + +#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN) + +#define INW_OFF(o) inw_l2b (np->port + ncr_offw(o)) +#define INL_OFF(o) inl_l2b (np->port + (o)) + +#define OUTW_OFF(o, val) outw_b2l ((val), np->port + ncr_offw(o)) +#define OUTL_OFF(o, val) outl_b2l ((val), np->port + (o)) + +#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN) + +#define INW_OFF(o) inw_b2l (np->port + ncr_offw(o)) +#define INL_OFF(o) inl_b2l (np->port + (o)) + +#define OUTW_OFF(o, val) outw_l2b ((val), np->port + ncr_offw(o)) +#define OUTL_OFF(o, val) outl_l2b ((val), np->port + (o)) + +#else + +#define INW_OFF(o) inw_raw (np->port + ncr_offw(o)) +#define INL_OFF(o) inl_raw (np->port + (o)) + +#define OUTW_OFF(o, val) outw_raw ((val), np->port + ncr_offw(o)) +#define OUTL_OFF(o, val) outl_raw ((val), np->port + (o)) + +#endif /* ENDIANs */ + +#else /* defined NCR_IOMAPPED */ /* -** MEMORY mapped only input / output +** MEMORY mapped IO input / output */ +#define INB_OFF(o) readb((char *)np->reg + ncr_offb(o)) +#define OUTB_OFF(o, val) writeb((val), (char *)np->reg + ncr_offb(o)) + +#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN) + +#define INW_OFF(o) readw_l2b((char *)np->reg + ncr_offw(o)) +#define INL_OFF(o) readl_l2b((char *)np->reg + (o)) + +#define OUTW_OFF(o, val) writew_b2l((val), (char *)np->reg + ncr_offw(o)) +#define OUTL_OFF(o, val) writel_b2l((val), (char *)np->reg + (o)) + +#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN) + +#define INW_OFF(o) readw_b2l((char *)np->reg + ncr_offw(o)) +#define INL_OFF(o) readl_b2l((char *)np->reg + (o)) + +#define OUTW_OFF(o, val) writew_l2b((val), (char *)np->reg + ncr_offw(o)) +#define OUTL_OFF(o, val) writel_l2b((val), (char *)np->reg + (o)) + #else -#define INB(r) MMIO_INB(r) -#define INB_OFF(o) MMIO_INB_OFF(o) -#define INW(r) MMIO_INW(r) -#define INL(r) MMIO_INL(r) -#define INL_OFF(o) MMIO_INL_OFF(o) - -#define OUTB(r, val) MMIO_OUTB(r, val) -#define OUTW(r, val) MMIO_OUTW(r, val) -#define OUTL(r, val) MMIO_OUTL(r, val) -#define OUTL_OFF(o, val) MMIO_OUTL_OFF(o, val) +#define INW_OFF(o) readw_raw((char *)np->reg + ncr_offw(o)) +#define INL_OFF(o) readl_raw((char *)np->reg + (o)) + +#define OUTW_OFF(o, val) writew_raw((val), (char *)np->reg + ncr_offw(o)) +#define OUTL_OFF(o, val) writel_raw((val), (char *)np->reg + (o)) #endif +#endif /* defined NCR_IOMAPPED */ + +#define INB(r) INB_OFF (offsetof(struct ncr_reg,r)) +#define INW(r) INW_OFF (offsetof(struct ncr_reg,r)) +#define INL(r) INL_OFF (offsetof(struct ncr_reg,r)) + +#define OUTB(r, val) OUTB_OFF (offsetof(struct ncr_reg,r), (val)) +#define OUTW(r, val) OUTW_OFF (offsetof(struct ncr_reg,r), (val)) +#define OUTL(r, val) OUTL_OFF (offsetof(struct ncr_reg,r), (val)) + /* ** Set bit field ON, OFF */ @@ -827,6 +910,7 @@ #define OUTONL(r, m) OUTL(r, INL(r) | (m)) #define OUTOFFL(r, m) OUTL(r, INL(r) & ~(m)) + /*========================================================== ** ** Command control block states. @@ -1264,27 +1348,36 @@ ** status fields. */ - u_char status[8]; + u_char scr_st[4]; /* script status */ + u_char status[4]; /* host status. Must be the last */ + /* DWORD of the CCB header */ }; /* ** The status bytes are used by the host and the script processor. ** -** The first four byte are copied to the scratchb register +** The byte corresponding to the host_status must be stored in the +** last DWORD of the CCB header since it is used for command +** completion (ncr_wakeup()). Doing so, we are sure that the header +** has been entirely copied back to the CCB when the host_status is +** seen complete by the CPU. +** +** The last four bytes (status[4]) are copied to the scratchb register ** (declared as scr0..scr3 in ncr_reg.h) just after the select/reselect, ** and copied back just after disconnecting. ** Inside the script the XX_REG are used. ** -** The last four bytes are used inside the script by "COPY" commands. +** The first four bytes (scr_st[4]) are used inside the script by +** "COPY" commands. ** Because source and destination must have the same alignment -** in a longword, the fields HAVE to be at the choosen offsets. -** xerr_st (4) 0 (0x34) scratcha -** sync_st (5) 1 (0x05) sxfer -** wide_st (7) 3 (0x03) scntl3 +** in a DWORD, the fields HAVE to be at the choosen offsets. +** xerr_st 0 (0x34) scratcha +** sync_st 1 (0x05) sxfer +** wide_st 3 (0x03) scntl3 */ /* -** First four bytes (script) +** Last four bytes (script) */ #define QU_REG scr0 #define HS_REG scr1 @@ -1293,7 +1386,7 @@ #define PS_REG scr3 /* -** First four bytes (host) +** Last four bytes (host) */ #define actualquirks phys.header.status[0] #define host_status phys.header.status[1] @@ -1301,15 +1394,15 @@ #define parity_status phys.header.status[3] /* -** Last four bytes (script) +** First four bytes (script) */ -#define xerr_st header.status[4] /* MUST be ==0 mod 4 */ -#define sync_st header.status[5] /* MUST be ==1 mod 4 */ -#define nego_st header.status[6] -#define wide_st header.status[7] /* MUST be ==3 mod 4 */ +#define xerr_st header.scr_st[0] +#define sync_st header.scr_st[1] +#define nego_st header.scr_st[2] +#define wide_st header.scr_st[3] /* -** Last four bytes (host) +** First four bytes (host) */ #define xerr_status phys.xerr_st #define sync_status phys.sync_st @@ -1677,9 +1770,11 @@ /* ** Timeout handler */ +#if 0 u_long heartbeat; u_short ticks; u_short latetime; +#endif u_long lasttime; /*----------------------------------------------- @@ -1771,7 +1866,7 @@ ** of 825A, 875 and 895 chips. */ struct script { - ncrcmd start [ 7]; + ncrcmd start [ 4]; ncrcmd start0 [ 2]; ncrcmd start1 [ 3]; ncrcmd startpos [ 1]; @@ -1974,13 +2069,14 @@ static struct script script0 __initdata = { /*--------------------------< START >-----------------------*/ { +#if 0 /* ** Claim to be still alive ... */ SCR_COPY (sizeof (((struct ncb *)0)->heartbeat)), KVAR(SCRIPT_KVAR_JIFFIES), NADDR (heartbeat), - +#endif /* ** Make data structure address invalid. ** clear SIGP. @@ -3593,7 +3689,8 @@ while (src < end) { - *dst++ = opcode = *src++; + opcode = *src++; + *dst++ = cpu_to_scr(opcode); /* ** If we forget to change the length @@ -3638,7 +3735,7 @@ ** the NO FLUSH bit if present. */ if ((opcode & SCR_NO_FLUSH) && !(np->features & FE_PFEN)) { - dst[-1] = (opcode & ~SCR_NO_FLUSH); + dst[-1] = cpu_to_scr(opcode & ~SCR_NO_FLUSH); ++opchanged; } break; @@ -3711,10 +3808,10 @@ break; } - *dst++ = new; + *dst++ = cpu_to_scr(new); } } else - *dst++ = *src++; + *dst++ = cpu_to_scr(*src++); }; if (bootverbose > 1 && opchanged) @@ -3974,15 +4071,6 @@ np->maxsync = period > 2540 ? 254 : period / 10; /* - ** Get on-board RAM bus address when supported - */ - if (np->features & FE_RAM) { - OUTONB(nc_ctest2, 0x8); - np->paddr2 = INL(nc_scr0); - OUTOFFB(nc_ctest2, 0x8); - } - - /* ** Prepare initial value of other IO registers */ #if defined SCSI_NCR_TRUST_BIOS_SETTING @@ -4338,7 +4426,8 @@ ** virtual and physical memory. */ - np->paddr = device->slot.base; + np->paddr = device->slot.base; + np->paddr2 = (np->features & FE_RAM)? device->slot.base_2 : 0; #ifndef NCR_IOMAPPED np->vaddr = remap_pci_mem((u_long) np->paddr, (u_long) 128); @@ -4446,17 +4535,20 @@ */ if (np->features & FE_LED0) { - np->script0->reselect[0] = SCR_REG_REG(gpreg, SCR_OR, 0x01); - np->script0->reselect1[0] = SCR_REG_REG(gpreg, SCR_AND, 0xfe); - np->script0->reselect2[0] = SCR_REG_REG(gpreg, SCR_AND, 0xfe); + np->script0->reselect[0] = + cpu_to_scr(SCR_REG_REG(gpreg, SCR_OR, 0x01)); + np->script0->reselect1[0] = + cpu_to_scr(SCR_REG_REG(gpreg, SCR_AND, 0xfe)); + np->script0->reselect2[0] = + cpu_to_scr(SCR_REG_REG(gpreg, SCR_AND, 0xfe)); } /* ** init data structure */ - np->jump_tcb.l_cmd = SCR_JUMP; - np->jump_tcb.l_paddr = NCB_SCRIPTH_PHYS (np, abort); + np->jump_tcb.l_cmd = cpu_to_scr(SCR_JUMP); + np->jump_tcb.l_paddr = cpu_to_scr(NCB_SCRIPTH_PHYS (np, abort)); /* ** Reset chip. @@ -4923,21 +5015,23 @@ u_long endp; default: case XferBoth: - cp->phys.header.savep = NCB_SCRIPT_PHYS (np, data_io); + cp->phys.header.savep = + cpu_to_scr(NCB_SCRIPT_PHYS (np, data_io)); cp->phys.header.goalp = cp->phys.header.savep; break; case XferIn: endp = NCB_SCRIPT_PHYS (np, data_in) + MAX_SCATTER*16; - cp->phys.header.goalp = endp + 8; - cp->phys.header.savep = endp - segments*16; + cp->phys.header.goalp = cpu_to_scr(endp + 8); + cp->phys.header.savep = cpu_to_scr(endp - segments*16); break; case XferOut: endp = NCB_SCRIPTH_PHYS (np, data_out) + MAX_SCATTER*16; - cp->phys.header.goalp = endp + 8; - cp->phys.header.savep = endp - segments*16; + cp->phys.header.goalp = cpu_to_scr(endp + 8); + cp->phys.header.savep = cpu_to_scr(endp - segments*16); break; case XferNone: - cp->phys.header.savep = NCB_SCRIPT_PHYS (np, no_data); + cp->phys.header.savep = + cpu_to_scr(NCB_SCRIPT_PHYS (np, no_data)); cp->phys.header.goalp = cp->phys.header.savep; break; } @@ -4958,8 +5052,9 @@ /* ** Startqueue */ - cp->phys.header.launch.l_paddr = NCB_SCRIPT_PHYS (np, select); - cp->phys.header.launch.l_cmd = SCR_JUMP; + cp->phys.header.launch.l_paddr = + cpu_to_scr(NCB_SCRIPT_PHYS (np, select)); + cp->phys.header.launch.l_cmd = cpu_to_scr(SCR_JUMP); /* ** select */ @@ -4969,21 +5064,21 @@ /* ** message */ - cp->phys.smsg.addr = CCB_PHYS (cp, scsi_smsg); - cp->phys.smsg.size = msglen; + cp->phys.smsg.addr = cpu_to_scr(CCB_PHYS (cp, scsi_smsg)); + cp->phys.smsg.size = cpu_to_scr(msglen); - cp->phys.smsg2.addr = CCB_PHYS (cp, scsi_smsg2); - cp->phys.smsg2.size = msglen2; + cp->phys.smsg2.addr = cpu_to_scr(CCB_PHYS (cp, scsi_smsg2)); + cp->phys.smsg2.size = cpu_to_scr(msglen2); /* ** command */ - cp->phys.cmd.addr = vtophys (&cmd->cmnd[0]); - cp->phys.cmd.size = cmd->cmd_len; + cp->phys.cmd.addr = cpu_to_scr(vtophys (&cmd->cmnd[0])); + cp->phys.cmd.size = cpu_to_scr(cmd->cmd_len); /* ** sense command */ - cp->phys.scmd.addr = CCB_PHYS (cp, sensecmd); - cp->phys.scmd.size = 6; + cp->phys.scmd.addr = cpu_to_scr(CCB_PHYS (cp, sensecmd)); + cp->phys.scmd.size = cpu_to_scr(6); /* ** patch requested size into sense command */ @@ -4993,8 +5088,9 @@ /* ** sense data */ - cp->phys.sense.addr = vtophys (&cmd->sense_buffer[0]); - cp->phys.sense.size = sizeof(cmd->sense_buffer); + cp->phys.sense.addr = + cpu_to_scr(vtophys (&cmd->sense_buffer[0])); + cp->phys.sense.size = cpu_to_scr(sizeof(cmd->sense_buffer)); /* ** status */ @@ -5019,8 +5115,10 @@ ** reselect pattern and activate this job. */ - cp->jump_ccb.l_cmd = (SCR_JUMP ^ IFFALSE (DATA (cp->tag))); - /* Compute a time limit bigger than the middle-level driver one */ + cp->jump_ccb.l_cmd = + cpu_to_scr((SCR_JUMP ^ IFFALSE (DATA (cp->tag)))); + + /* Compute a time limit greater than the middle-level driver one */ if (cmd->timeout_per_command > 0) cp->tlimit = jiffies + cmd->timeout_per_command + NCR_TIMEOUT_INCREASE; else @@ -5033,14 +5131,14 @@ qidx = np->squeueput + 1; if (qidx >= MAX_START) qidx=0; - np->squeue [qidx ] = NCB_SCRIPT_PHYS (np, idle); - np->squeue [np->squeueput] = CCB_PHYS (cp, phys); + np->squeue [qidx ] = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle)); + np->squeue [np->squeueput] = cpu_to_scr(CCB_PHYS (cp, phys)); np->squeueput = qidx; if(DEBUG_FLAGS & DEBUG_QUEUE) printf ("%s: queuepos=%d tryoffset=%d.\n", ncr_name (np), np->squeueput, - (unsigned)(np->script->startpos[0]- + (unsigned)(scr_to_cpu(np->script->startpos[0]) - (NCB_SCRIPTH_PHYS (np, tryloop)))); /* @@ -5246,10 +5344,12 @@ ** this condition in order to complete the canceled command ** after the script skipped the ccb, if necessary. */ - cp->jump_ccb.l_cmd = (SCR_JUMP); - if (cp->phys.header.launch.l_paddr == NCB_SCRIPT_PHYS (np, select)) { + cp->jump_ccb.l_cmd = cpu_to_scr(SCR_JUMP); + if (cp->phys.header.launch.l_paddr == + cpu_to_scr(NCB_SCRIPT_PHYS (np, select))) { printf ("%s: abort ccb=%p (skip)\n", ncr_name (np), cp); - cp->phys.header.launch.l_paddr = NCB_SCRIPT_PHYS (np, skip); + cp->phys.header.launch.l_paddr = + cpu_to_scr(NCB_SCRIPT_PHYS (np, skip)); } cp->tlimit = 0; @@ -5440,12 +5540,12 @@ /* ** No Reselect anymore. */ - cp->jump_ccb.l_cmd = (SCR_JUMP); + cp->jump_ccb.l_cmd = cpu_to_scr(SCR_JUMP); /* ** No starting. */ - cp->phys.header.launch.l_paddr= NCB_SCRIPT_PHYS (np, idle); + cp->phys.header.launch.l_paddr = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle)); /* ** timestamp @@ -5797,14 +5897,14 @@ ** Clear Start Queue */ for (i=0;i squeue [i] = NCB_SCRIPT_PHYS (np, idle); + np -> squeue [i] = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle)); /* ** Start at first entry. */ np->squeueput = 0; - np->script0->startpos[0] = NCB_SCRIPTH_PHYS (np, tryloop); - np->script0->start0 [0] = SCR_INT ^ IFFALSE (0); + np->script0->startpos[0] = cpu_to_scr(NCB_SCRIPTH_PHYS (np, tryloop)); + np->script0->start0 [0] = cpu_to_scr(SCR_INT ^ IFFALSE (0)); /* ** Wakeup all pending jobs. @@ -5856,7 +5956,11 @@ if (np->vaddr2) { if (bootverbose) printf ("%s: copying script fragments into the on-board RAM ...\n", ncr_name(np)); - bcopy(np->script0, np->script, sizeof(struct script)); +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,0,0) + memcpy_toio(np->script, np->script0, sizeof(struct script)); +#else + memcpy(np->script, np->script0, sizeof(struct script)); +#endif } /* @@ -6477,7 +6581,6 @@ { u_long thistime = jiffies; u_long count = 0; - long signed t; ccb_p cp; u_long flags; @@ -6551,10 +6654,12 @@ ** **---------------------------------------------------- */ - - t = (thistime - np->heartbeat) / HZ; - - if (t<2) np->latetime=0; else np->latetime++; +#if 0 + if (thistime < np->heartbeat + HZ + HZ) + np->latetime = 0; + else + np->latetime++; +#endif /*---------------------------------------------------- ** @@ -6597,7 +6702,7 @@ ** still in start queue ? */ if (cp->phys.header.launch.l_paddr == - NCB_SCRIPT_PHYS (np, skip)) + cpu_to_scr(NCB_SCRIPT_PHYS (np, skip))) continue; /* fall through */ @@ -6746,15 +6851,18 @@ /* ** interrupt on the fly ? - */ - while ((istat = INB (nc_istat)) & INTF) { + ** Since the global header may be copied back to a CCB + ** using a posted PCI memory write, the last operation on + ** the istat register is a READ in order to flush posted + ** PCI commands (Btw, the 'do' loop is probably useless). + */ + istat = INB (nc_istat); + if (istat & INTF) { + do { + OUTB (nc_istat, (istat & SIGP) | INTF); + istat = INB (nc_istat); + } while (istat & INTF); if (DEBUG_FLAGS & DEBUG_TINY) printf ("F "); -#ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT - if (np->stalling) - OUTB (nc_istat, INTF); - else -#endif - OUTB (nc_istat, (istat & SIGP) | INTF); np->profile.num_fly++; ncr_wakeup (np, 0); }; @@ -6944,7 +7052,7 @@ /* assert ((diff <= MAX_START * 20) && !(diff % 20));*/ if ((diff <= MAX_START * 20) && !(diff % 20)) { - np->script->startpos[0] = scratcha; + np->script->startpos[0] = cpu_to_scr(scratcha); OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, start)); return; }; @@ -7136,20 +7244,20 @@ ** get old startaddress and old length. */ - oadr = vdsp[1]; + oadr = scr_to_cpu(vdsp[1]); if (cmd & 0x10) { /* Table indirect */ tblp = (u_int32 *) ((char*) &cp->phys + oadr); - olen = tblp[0]; - oadr = tblp[1]; + olen = scr_to_cpu(tblp[0]); + oadr = scr_to_cpu(tblp[1]); } else { tblp = (u_int32 *) 0; - olen = vdsp[0] & 0xffffff; + olen = scr_to_cpu(vdsp[0]) & 0xffffff; }; if (DEBUG_FLAGS & DEBUG_PHASE) { printf ("OCMD=%x\nTBLP=%p OLEN=%x OADR=%x\n", - (unsigned) (vdsp[0] >> 24), + (unsigned) (scr_to_cpu(vdsp[0]) >> 24), tblp, (unsigned) olen, (unsigned) oadr); @@ -7159,10 +7267,10 @@ ** check cmd against assumed interrupted script command. */ - if (cmd != (vdsp[0] >> 24)) { + if (cmd != (scr_to_cpu(vdsp[0]) >> 24)) { PRINT_ADDR(cp->cmd); printf ("internal error: cmd=%02x != %02x=(vdsp[0] >> 24)\n", - (unsigned)cmd, (unsigned)vdsp[0] >> 24); + (unsigned)cmd, (unsigned)scr_to_cpu(vdsp[0]) >> 24); return; } @@ -7194,25 +7302,25 @@ */ newcmd = cp->patch; - if (cp->phys.header.savep == vtophys (newcmd)) newcmd+=4; + if (cp->phys.header.savep == cpu_to_scr(vtophys (newcmd))) newcmd+=4; /* ** fillin the commands */ - newcmd[0] = ((cmd & 0x0f) << 24) | rest; - newcmd[1] = oadr + olen - rest; - newcmd[2] = SCR_JUMP; - newcmd[3] = nxtdsp; + newcmd[0] = cpu_to_scr(((cmd & 0x0f) << 24) | rest); + newcmd[1] = cpu_to_scr(oadr + olen - rest); + newcmd[2] = cpu_to_scr(SCR_JUMP); + newcmd[3] = cpu_to_scr(nxtdsp); if (DEBUG_FLAGS & DEBUG_PHASE) { PRINT_ADDR(cp->cmd); printf ("newcmd[%d] %x %x %x %x.\n", (int) (newcmd - cp->patch), - (unsigned)newcmd[0], - (unsigned)newcmd[1], - (unsigned)newcmd[2], - (unsigned)newcmd[3]); + (unsigned)scr_to_cpu(newcmd[0]), + (unsigned)scr_to_cpu(newcmd[1]), + (unsigned)scr_to_cpu(newcmd[2]), + (unsigned)scr_to_cpu(newcmd[3])); } /* ** fake the return address (to the patch). @@ -7299,20 +7407,23 @@ */ if (num == SIR_DATA_IO_IS_OUT) { endp = NCB_SCRIPTH_PHYS (np, data_out) + MAX_SCATTER*16; - cp->phys.header.goalp = endp + 8; - cp->phys.header.savep = endp - cp->segments*16; + cp->phys.header.goalp = cpu_to_scr(endp + 8); + cp->phys.header.savep = + cpu_to_scr(endp - cp->segments*16); } else { endp = NCB_SCRIPT_PHYS (np, data_in) + MAX_SCATTER*16; - cp->phys.header.goalp = endp + 8; - cp->phys.header.savep = endp - cp->segments*16; + cp->phys.header.goalp = cpu_to_scr(endp + 8); + cp->phys.header.savep = + cpu_to_scr(endp - cp->segments*16); } cp->phys.header.lastp = cp->phys.header.savep; np->header.savep = cp->phys.header.savep; np->header.goalp = cp->phys.header.goalp; np->header.lastp = cp->phys.header.lastp; - OUTL (nc_temp, np->header.savep); - OUTL (nc_dsp, np->header.savep); + + OUTL (nc_temp, scr_to_cpu(np->header.savep)); + OUTL (nc_dsp, scr_to_cpu(np->header.savep)); return; /* break; */ @@ -7359,7 +7470,7 @@ ** no job, resume normal processing */ if (DEBUG_FLAGS & DEBUG_RESTART) printf (" -- remove trap\n"); - np->script->start0[0] = SCR_INT ^ IFFALSE (0); + np->script->start0[0] = cpu_to_scr(SCR_INT ^ IFFALSE (0)); break; case SIR_SENSE_FAILED: @@ -7385,7 +7496,7 @@ /* ** And patch code to restart it. */ - np->script->start0[0] = SCR_INT; + np->script->start0[0] = cpu_to_scr(SCR_INT); break; /*----------------------------------------------------------------------------- @@ -7742,7 +7853,7 @@ PRINT_ADDR(cp->cmd); printf ("M_REJECT received (%x:%x).\n", - (unsigned)np->lastmsg, np->msgout[0]); + (unsigned)scr_to_cpu(np->lastmsg), np->msgout[0]); break; case SIR_REJECT_SENT: @@ -7792,8 +7903,8 @@ printf ("M_DISCONNECT received, but datapointer not saved: " "data=%x save=%x goal=%x.\n", (unsigned) INL (nc_temp), - (unsigned) np->header.savep, - (unsigned) np->header.goalp); + (unsigned) scr_to_cpu(np->header.savep), + (unsigned) scr_to_cpu(np->header.goalp)); break; #if 0 /* This stuff does not work */ @@ -7824,7 +7935,7 @@ PRINT_ADDR(cp->cmd); printf ("queue full.\n"); - np->script->start1[0] = SCR_INT; + np->script->start1[0] = cpu_to_scr(SCR_INT); /* ** Try to disable tagged transfers. @@ -7872,7 +7983,7 @@ */ printf ("%s: queue empty.\n", ncr_name (np)); - np->script->start1[0] = SCR_INT ^ IFFALSE (0); + np->script->start1[0] = cpu_to_scr(SCR_INT ^ IFFALSE (0)); break; #endif /* This stuff does not work */ }; @@ -8011,33 +8122,37 @@ tp=&np->target[target]; if (!tp->jump_tcb.l_cmd) { - /* ** initialize it. */ - tp->jump_tcb.l_cmd = (SCR_JUMP^IFFALSE (DATA (0x80 + target))); + tp->jump_tcb.l_cmd = + cpu_to_scr((SCR_JUMP^IFFALSE (DATA (0x80 + target)))); tp->jump_tcb.l_paddr = np->jump_tcb.l_paddr; - tp->getscr[0] = - (np->features & FE_PFEN)? SCR_COPY(1) : SCR_COPY_F(1); - tp->getscr[1] = vtophys (&tp->sval); - tp->getscr[2] = np->paddr + offsetof (struct ncr_reg, nc_sxfer); - tp->getscr[3] = - (np->features & FE_PFEN)? SCR_COPY(1) : SCR_COPY_F(1); - tp->getscr[4] = vtophys (&tp->wval); - tp->getscr[5] = np->paddr + offsetof (struct ncr_reg, nc_scntl3); + tp->getscr[0] = (np->features & FE_PFEN) ? + cpu_to_scr(SCR_COPY(1)):cpu_to_scr(SCR_COPY_F(1)); + tp->getscr[1] = cpu_to_scr(vtophys (&tp->sval)); + tp->getscr[2] = + cpu_to_scr(np->paddr + offsetof (struct ncr_reg, nc_sxfer)); + + tp->getscr[3] = (np->features & FE_PFEN) ? + cpu_to_scr(SCR_COPY(1)):cpu_to_scr(SCR_COPY_F(1)); + tp->getscr[4] = cpu_to_scr(vtophys (&tp->wval)); + tp->getscr[5] = + cpu_to_scr(np->paddr + offsetof (struct ncr_reg, nc_scntl3)); assert (( (offsetof(struct ncr_reg, nc_sxfer) ^ offsetof(struct tcb , sval )) &3) == 0); assert (( (offsetof(struct ncr_reg, nc_scntl3) ^ offsetof(struct tcb , wval )) &3) == 0); - tp->call_lun.l_cmd = (SCR_CALL); - tp->call_lun.l_paddr = NCB_SCRIPT_PHYS (np, resel_lun); - - tp->jump_lcb.l_cmd = (SCR_JUMP); - tp->jump_lcb.l_paddr = NCB_SCRIPTH_PHYS (np, abort); - np->jump_tcb.l_paddr = vtophys (&tp->jump_tcb); + tp->call_lun.l_cmd = cpu_to_scr(SCR_CALL); + tp->call_lun.l_paddr = + cpu_to_scr(NCB_SCRIPT_PHYS (np, resel_lun)); + + tp->jump_lcb.l_cmd = cpu_to_scr(SCR_JUMP); + tp->jump_lcb.l_paddr = cpu_to_scr(NCB_SCRIPTH_PHYS (np, abort)); + np->jump_tcb.l_paddr = cpu_to_scr(vtophys (&tp->jump_tcb)); } /* @@ -8060,14 +8175,17 @@ ** Initialize it */ bzero (lp, sizeof (*lp)); - lp->jump_lcb.l_cmd = (SCR_JUMP ^ IFFALSE (DATA (lun))); + lp->jump_lcb.l_cmd = + cpu_to_scr(SCR_JUMP ^ IFFALSE (DATA (lun))); lp->jump_lcb.l_paddr = tp->jump_lcb.l_paddr; - lp->call_tag.l_cmd = (SCR_CALL); - lp->call_tag.l_paddr = NCB_SCRIPT_PHYS (np, resel_tag); - - lp->jump_ccb.l_cmd = (SCR_JUMP); - lp->jump_ccb.l_paddr = NCB_SCRIPTH_PHYS (np, aborttag); + lp->call_tag.l_cmd = cpu_to_scr(SCR_CALL); + lp->call_tag.l_paddr = + cpu_to_scr(NCB_SCRIPT_PHYS (np, resel_tag)); + + lp->jump_ccb.l_cmd = cpu_to_scr(SCR_JUMP); + lp->jump_ccb.l_paddr = + cpu_to_scr(NCB_SCRIPTH_PHYS (np, aborttag)); lp->actlink = 1; @@ -8076,7 +8194,7 @@ /* ** Chain into LUN list */ - tp->jump_lcb.l_paddr = vtophys (&lp->jump_lcb); + tp->jump_lcb.l_paddr = cpu_to_scr(vtophys (&lp->jump_lcb)); tp->lp[lun] = lp; ncr_setmaxtags (np, tp, driver_setup.default_tags); @@ -8128,11 +8246,11 @@ /* ** Chain into reselect list */ - cp->jump_ccb.l_cmd = SCR_JUMP; + cp->jump_ccb.l_cmd = cpu_to_scr(SCR_JUMP); cp->jump_ccb.l_paddr = lp->jump_ccb.l_paddr; - lp->jump_ccb.l_paddr = CCB_PHYS (cp, jump_ccb); - cp->call_tmp.l_cmd = SCR_CALL; - cp->call_tmp.l_paddr = NCB_SCRIPT_PHYS (np, resel_tmp); + lp->jump_ccb.l_paddr = cpu_to_scr(CCB_PHYS (cp, jump_ccb)); + cp->call_tmp.l_cmd = cpu_to_scr(SCR_CALL); + cp->call_tmp.l_paddr = cpu_to_scr(NCB_SCRIPT_PHYS (np, resel_tmp)); /* ** Chain into wakeup list @@ -8245,9 +8363,9 @@ if (!use_sg) { if (cmd->request_bufflen) { data = &data[MAX_SCATTER - 1]; - data[0].addr = vtophys(cmd->request_buffer); - data[0].size = cmd->request_bufflen; - cp->data_len = data[0].size; + data[0].addr = cpu_to_scr(vtophys(cmd->request_buffer)); + data[0].size = cpu_to_scr(cmd->request_bufflen); + cp->data_len = cmd->request_bufflen; segment = 1; } } @@ -8256,9 +8374,11 @@ data = &data[MAX_SCATTER - use_sg]; while (segment < use_sg) { - data[segment].addr = vtophys(scatter[segment].address); - data[segment].size = scatter[segment].length; - cp->data_len += data[segment].size; + data[segment].addr = + cpu_to_scr(vtophys(scatter[segment].address)); + data[segment].size = + cpu_to_scr(scatter[segment].length); + cp->data_len += scatter[segment].length; ++segment; } } @@ -8328,7 +8448,7 @@ /* ** Set memory and register. */ - np->ncr_cache = host_wr; + np->ncr_cache = cpu_to_scr(host_wr); OUTL (nc_temp, ncr_wr); /* ** Start script (exchange values) @@ -8347,7 +8467,7 @@ /* ** Read memory and register. */ - host_rd = np->ncr_cache; + host_rd = scr_to_cpu(np->ncr_cache); ncr_rd = INL (nc_scratcha); ncr_bk = INL (nc_temp); /* @@ -8791,7 +8911,7 @@ else if (!strncmp(cur, "safe:", 5) && val) memcpy(&driver_setup, &driver_safe_setup, sizeof(driver_setup)); else - printf("ncr53c8xx_setup: unexpected boot option '%.*s' ignored\n", pc-cur+1, cur); + printf("ncr53c8xx_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur); if ((cur = strchr(cur, ',')) != NULL) ++cur; @@ -9068,11 +9188,11 @@ uchar cache_line_size, latency_timer; uchar irq, revision; #if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0) - uint base, io_port; + uint base, base_2, io_port; #else - ulong base, io_port; + ulong base, base_2; #endif - int i, error; + int i; #ifdef SCSI_NCR_NVRAM_SUPPORT ncr_nvram *nvram = device->nvram; @@ -9082,20 +9202,32 @@ printk(KERN_INFO "ncr53c8xx: at PCI bus %d, device %d, function %d\n", bus, (int) (device_fn & 0xf8) >> 3, (int) device_fn & 7); /* - * Read info from the PCI config space + * Read info from the PCI config space. + * pcibios_read_config_xxx() functions are assumed to be used for + * successfully detected PCI devices. + * Expecting error conditions from them is just paranoia, + * thus void cast. */ - if ( - (error=pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID, &vendor_id)) || - (error=pcibios_read_config_word(bus, device_fn, PCI_DEVICE_ID, &device_id)) || - (error=pcibios_read_config_word( bus, device_fn, PCI_COMMAND, &command)) || - (error=pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0,&io_port)) || - (error=pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_1, &base)) || - (error=pcibios_read_config_byte(bus, device_fn, PCI_CLASS_REVISION,&revision)) || - (error=pcibios_read_config_byte(bus, device_fn, PCI_INTERRUPT_LINE, &irq)) || - (error=pcibios_read_config_byte(bus, device_fn, PCI_CACHE_LINE_SIZE, &cache_line_size)) || - (error=pcibios_read_config_byte(bus, device_fn, PCI_LATENCY_TIMER, &latency_timer)) - ) - goto err_pcibios; + (void) pcibios_read_config_word(bus, device_fn, + PCI_VENDOR_ID, &vendor_id); + (void) pcibios_read_config_word(bus, device_fn, + PCI_DEVICE_ID, &device_id); + (void) pcibios_read_config_word(bus, device_fn, + PCI_COMMAND, &command); + (void) pcibios_read_config_dword(bus, device_fn, + PCI_BASE_ADDRESS_0, &io_port); + (void) pcibios_read_config_dword(bus, device_fn, + PCI_BASE_ADDRESS_1, &base); + (void) pcibios_read_config_dword(bus, device_fn, + PCI_BASE_ADDRESS_2, &base_2); + (void) pcibios_read_config_byte(bus, device_fn, + PCI_CLASS_REVISION,&revision); + (void) pcibios_read_config_byte(bus, device_fn, + PCI_INTERRUPT_LINE, &irq); + (void) pcibios_read_config_byte(bus, device_fn, + PCI_CACHE_LINE_SIZE, &cache_line_size); + (void) pcibios_read_config_byte(bus, device_fn, + PCI_LATENCY_TIMER, &latency_timer); /* * Check if the chip is supported @@ -9148,6 +9280,8 @@ return -1; } + base_2 &= PCI_BASE_ADDRESS_MEM_MASK; + if (io_port && check_region (io_port, 128)) { printk("ncr53c8xx: IO region 0x%x to 0x%x is in use\n", (int) io_port, (int) (io_port + 127)); @@ -9188,9 +9322,8 @@ case 5: cache_line_size = 8; break; } if (cache_line_size) - error = pcibios_write_config_byte(bus, device_fn, PCI_CACHE_LINE_SIZE, cache_line_size); - if (error) - goto err_pcibios; + (void) pcibios_write_config_byte(bus, device_fn, + PCI_CACHE_LINE_SIZE, cache_line_size); if (initverbose) printk("ncr53c8xx: setting PCI_CACHE_LINE_SIZE to %d (fix-up).\n", cache_line_size); } @@ -9198,9 +9331,8 @@ if ((driver_setup.pci_fix_up & 2) && cache_line_size && (chip->features & FE_WRIE) && !(command & PCI_COMMAND_INVALIDATE)) { command |= PCI_COMMAND_INVALIDATE; - error=pcibios_write_config_word(bus, device_fn, PCI_COMMAND, command); - if (error) - goto err_pcibios; + (void) pcibios_write_config_word(bus, device_fn, + PCI_COMMAND, command); if (initverbose) printk("ncr53c8xx: setting PCI_COMMAND_INVALIDATE bit (fix-up).\n"); } @@ -9242,10 +9374,8 @@ latency_timer = lt; if (initverbose) printk("ncr53c8xx: setting PCI_LATENCY_TIMER to %d bus clocks (fix-up).\n", latency_timer); - error = pcibios_write_config_byte(bus, device_fn, + (void) pcibios_write_config_byte(bus, device_fn, PCI_LATENCY_TIMER, latency_timer); - if (error) - goto err_pcibios; } } @@ -9271,6 +9401,7 @@ device->slot.bus = bus; device->slot.device_fn = device_fn; device->slot.base = base; + device->slot.base_2 = base_2; device->slot.io_port = io_port; device->slot.irq = irq; device->attached = 0; @@ -9321,11 +9452,6 @@ #endif /* SCSI_NCR_NVRAM_SUPPORT */ return 0; - -err_pcibios: - printk("ncr53c8xx: error %s reading configuration space\n", - pcibios_strerror(error)); - return -1; } #if LINUX_VERSION_CODE >= LinuxVersionCode(2,0,0) diff -u --recursive --new-file v2.1.51/linux/drivers/scsi/ncr53c8xx.h linux/drivers/scsi/ncr53c8xx.h --- v2.1.51/linux/drivers/scsi/ncr53c8xx.h Mon Aug 11 14:47:05 1997 +++ linux/drivers/scsi/ncr53c8xx.h Mon Aug 25 13:01:58 1997 @@ -45,7 +45,7 @@ /* ** Name and revision of the driver */ -#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - revision 2.4" +#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - revision 2.5a" /* ** Check supported Linux versions @@ -155,9 +155,11 @@ #endif /* - * Use normal IO if configured. Forced for alpha. + * Use normal IO if configured. Forced for alpha and ppc. */ -#if defined(CONFIG_SCSI_NCR53C8XX_IOMAPPED) || defined(__alpha__) +#if defined(CONFIG_SCSI_NCR53C8XX_IOMAPPED) +#define SCSI_NCR_IOMAPPED +#elif defined(__alpha__) || defined(__powerpc__) #define SCSI_NCR_IOMAPPED #endif @@ -316,6 +318,45 @@ #ifndef HOSTS_C /* +** IO functions definition for big/little endian support. +** For now, the NCR is only supported in little endian addressing mode, +** and big endian byte ordering is only supported for the PPC. +** MMIO is not used on PPC. +*/ + +#ifdef __BIG_ENDIAN + +#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,0) +#error "BIG ENDIAN byte ordering needs kernel version >= 2.1.0" +#endif + +#ifdef __powerpc__ +#define inw_l2b inw +#define inl_l2b inl +#define outw_b2l outw +#define outl_b2l outl +#else +#error "Support for BIG ENDIAN is only available for the PowerPC" +#endif + +#else /* Assumed x86 or alpha */ + +#define inw_raw inw +#define inl_raw inl +#define outw_raw outw +#define outl_raw outl +#define readw_raw readw +#define readl_raw readl +#define writew_raw writew +#define writel_raw writel + +#endif + +#ifdef SCSI_NCR_BIG_ENDIAN +#error "The NCR in BIG ENDIAN adressing mode is not (yet) supported" +#endif + +/* ** NCR53C8XX Device Ids */ @@ -416,7 +457,7 @@ FE_WIDE|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} \ , \ {PCI_DEVICE_ID_NCR_53C860, 0xff, "860", 4, 8, 5, \ - FE_WIDE|FE_ULTRA|FE_CLK80|FE_CACHE_SET|FE_BOF|FE_LDSTR|FE_PFEN|FE_RAM} \ + FE_ULTRA|FE_CLK80|FE_CACHE_SET|FE_BOF|FE_LDSTR|FE_PFEN} \ , \ {PCI_DEVICE_ID_NCR_53C875, 0x01, "875", 7, 16, 5, \ FE_WIDE|FE_ULTRA|FE_CLK80|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\ diff -u --recursive --new-file v2.1.51/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c --- v2.1.51/linux/drivers/scsi/scsi_ioctl.c Tue Mar 4 10:25:24 1997 +++ linux/drivers/scsi/scsi_ioctl.c Mon Aug 25 12:52:54 1997 @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -23,7 +24,7 @@ #define MAX_RETRIES 5 #define MAX_TIMEOUT (9 * HZ) -#define MAX_BUF 4096 +#define MAX_BUF PAGE_SIZE #define max(a,b) (((a) > (b)) ? (a) : (b)) @@ -73,12 +74,9 @@ * * *(char *) ((int *) arg)[2] the actual command byte. * - * Note that no more than MAX_BUF data bytes will be transfered. Since - * SCSI block device size is 512 bytes, I figured 1K was good. - * but (WDE) changed it to 8192 to handle large bad track buffers. - * ERY: I changed this to a dynamic allocation using scsi_malloc - we were - * getting a kernel stack overflow which was crashing the system when we - * were using 8192 bytes. + * Note that if more than MAX_BUF bytes are requested to be transfered, + * the ioctl will fail with error EINVAL. MAX_BUF can be increased in + * the future by increasing the size that scsi_malloc will accept. * * This size *does not* include the initial lengths that were passed. * @@ -201,8 +199,8 @@ * If the user needs to transfer more data than this, they * should use scsi_generics instead. */ - if( inlen > MAX_BUF ) inlen = MAX_BUF; - if( outlen > MAX_BUF ) outlen = MAX_BUF; + if( inlen > MAX_BUF ) return -EINVAL; + if( outlen > MAX_BUF ) return -EINVAL; cmd_in = sic->data; get_user(opcode, cmd_in); diff -u --recursive --new-file v2.1.51/linux/fs/attr.c linux/fs/attr.c --- v2.1.51/linux/fs/attr.c Thu Jul 17 10:06:06 1997 +++ linux/fs/attr.c Fri Aug 22 21:18:39 1997 @@ -17,83 +17,87 @@ /* POSIX UID/GID verification for setting inode attributes. */ int inode_change_ok(struct inode *inode, struct iattr *attr) { + int retval = -EPERM; + unsigned int ia_valid = attr->ia_valid; + /* If force is set do it anyway. */ - if (attr->ia_valid & ATTR_FORCE) - return 0; + if (ia_valid & ATTR_FORCE) + goto fine; /* Make sure a caller can chown. */ - if ((attr->ia_valid & ATTR_UID) && + if ((ia_valid & ATTR_UID) && (current->fsuid != inode->i_uid || attr->ia_uid != inode->i_uid) && !fsuser()) - return -EPERM; + goto error; /* Make sure caller can chgrp. */ - if ((attr->ia_valid & ATTR_GID) && + if ((ia_valid & ATTR_GID) && (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid) && !fsuser()) - return -EPERM; + goto error; /* Make sure a caller can chmod. */ - if (attr->ia_valid & ATTR_MODE) { + if (ia_valid & ATTR_MODE) { if ((current->fsuid != inode->i_uid) && !fsuser()) - return -EPERM; + goto error; /* Also check the setgid bit! */ - if (!fsuser() && !in_group_p((attr->ia_valid & ATTR_GID) ? attr->ia_gid : + if (!fsuser() && !in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid : inode->i_gid)) attr->ia_mode &= ~S_ISGID; } /* Check for setting the inode time. */ - if ((attr->ia_valid & ATTR_ATIME_SET) && - ((current->fsuid != inode->i_uid) && !fsuser())) - return -EPERM; - if ((attr->ia_valid & ATTR_MTIME_SET) && - ((current->fsuid != inode->i_uid) && !fsuser())) - return -EPERM; - return 0; + if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) { + if (current->fsuid != inode->i_uid && !fsuser()) + goto error; + } +fine: + retval = 0; +error: + return retval; } void inode_setattr(struct inode * inode, struct iattr * attr) { - if(attr->ia_valid & - (ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_MODE)) { - if (attr->ia_valid & ATTR_UID) - inode->i_uid = attr->ia_uid; - if (attr->ia_valid & ATTR_GID) - inode->i_gid = attr->ia_gid; - if (attr->ia_valid & ATTR_SIZE) - inode->i_size = attr->ia_size; - if (attr->ia_valid & ATTR_ATIME) - inode->i_atime = attr->ia_atime; - if (attr->ia_valid & ATTR_MTIME) - inode->i_mtime = attr->ia_mtime; - if (attr->ia_valid & ATTR_CTIME) - inode->i_ctime = attr->ia_ctime; - if (attr->ia_valid & ATTR_MODE) { - inode->i_mode = attr->ia_mode; - if (!fsuser() && !in_group_p(inode->i_gid)) - inode->i_mode &= ~S_ISGID; - } - mark_inode_dirty(inode); + unsigned int ia_valid = attr->ia_valid; + + if (ia_valid & ATTR_UID) + inode->i_uid = attr->ia_uid; + if (ia_valid & ATTR_GID) + inode->i_gid = attr->ia_gid; + if (ia_valid & ATTR_SIZE) + inode->i_size = attr->ia_size; + if (ia_valid & ATTR_ATIME) + inode->i_atime = attr->ia_atime; + if (ia_valid & ATTR_MTIME) + inode->i_mtime = attr->ia_mtime; + if (ia_valid & ATTR_CTIME) + inode->i_ctime = attr->ia_ctime; + if (ia_valid & ATTR_MODE) { + inode->i_mode = attr->ia_mode; + if (!fsuser() && !in_group_p(inode->i_gid)) + inode->i_mode &= ~S_ISGID; } + mark_inode_dirty(inode); } int notify_change(struct inode * inode, struct iattr * attr) { int error; time_t now = CURRENT_TIME; + unsigned int ia_valid = attr->ia_valid; attr->ia_ctime = now; - if ((attr->ia_valid & (ATTR_ATIME | ATTR_ATIME_SET)) == ATTR_ATIME) + if (!(ia_valid & ATTR_ATIME_SET)) attr->ia_atime = now; - if ((attr->ia_valid & (ATTR_MTIME | ATTR_MTIME_SET)) == ATTR_MTIME) + if (!(ia_valid & ATTR_MTIME_SET)) attr->ia_mtime = now; - attr->ia_valid &= ~(ATTR_CTIME); + if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->notify_change) return inode->i_sb->s_op->notify_change(inode, attr); + error = inode_change_ok(inode, attr); - if(!error) + if (!error) inode_setattr(inode, attr); return error; } - diff -u --recursive --new-file v2.1.51/linux/fs/dcache.c linux/fs/dcache.c --- v2.1.51/linux/fs/dcache.c Mon Aug 18 18:19:46 1997 +++ linux/fs/dcache.c Sat Aug 23 23:45:10 1997 @@ -72,13 +72,13 @@ dentry->d_count = count; if (!count) { list_del(&dentry->d_lru); + if (dentry->d_op && dentry->d_op->d_delete) + dentry->d_op->d_delete(dentry); if (list_empty(&dentry->d_hash)) { struct inode *inode = dentry->d_inode; struct dentry * parent; - if (inode) { - list_del(&dentry->d_alias); + if (inode) iput(inode); - } parent = dentry->d_parent; d_free(dentry); if (dentry == parent) @@ -134,7 +134,6 @@ if (dentry->d_inode) { struct inode * inode = dentry->d_inode; - list_del(&dentry->d_alias); dentry->d_inode = NULL; iput(inode); } @@ -172,7 +171,6 @@ dentry->d_mounts = dentry; dentry->d_covers = dentry; INIT_LIST_HEAD(&dentry->d_hash); - INIT_LIST_HEAD(&dentry->d_alias); INIT_LIST_HEAD(&dentry->d_lru); dentry->d_name.name = str; @@ -194,9 +192,6 @@ */ void d_instantiate(struct dentry *entry, struct inode * inode) { - if (inode) - list_add(&entry->d_alias, &inode->i_dentry); - entry->d_inode = inode; } @@ -312,10 +307,10 @@ */ if (dentry->d_count == 1) { struct inode * inode = dentry->d_inode; - - dentry->d_inode = NULL; - list_del(&dentry->d_alias); - iput(inode); + if (inode) { + dentry->d_inode = NULL; + iput(inode); + } return; } diff -u --recursive --new-file v2.1.51/linux/fs/inode.c linux/fs/inode.c --- v2.1.51/linux/fs/inode.c Thu Aug 14 20:49:17 1997 +++ linux/fs/inode.c Tue Aug 19 10:53:21 1997 @@ -109,7 +109,6 @@ { memset(inode, 0, sizeof(*inode)); init_waitqueue(&inode->i_wait); - INIT_LIST_HEAD(&inode->i_dentry); INIT_LIST_HEAD(&inode->i_hash); sema_init(&inode->i_sem, 1); } diff -u --recursive --new-file v2.1.51/linux/fs/msdos/namei.c linux/fs/msdos/namei.c --- v2.1.51/linux/fs/msdos/namei.c Thu Aug 14 20:49:17 1997 +++ linux/fs/msdos/namei.c Wed Aug 20 15:46:44 1997 @@ -232,8 +232,11 @@ sb->s_op = &msdos_sops; res = fat_read_super(sb, data, silent); - if (res == NULL) + if (res == NULL) { + sb->s_dev = 0; MOD_DEC_USE_COUNT; + return NULL; + } sb->s_root->d_op = &msdos_dentry_operations; return res; } diff -u --recursive --new-file v2.1.51/linux/fs/namei.c linux/fs/namei.c --- v2.1.51/linux/fs/namei.c Mon Aug 18 18:19:46 1997 +++ linux/fs/namei.c Sat Aug 23 23:45:10 1997 @@ -460,16 +460,40 @@ return dentry; } -static inline struct inode *get_parent(struct dentry *dentry) +static inline struct dentry *get_parent(struct dentry *dentry) { - return dentry->d_parent->d_inode; + return dget(dentry->d_parent); } -static inline struct inode *lock_parent(struct dentry *dentry) +static inline void unlock_dir(struct dentry *dir) { - struct inode *dir = dentry->d_parent->d_inode; + up(&dir->d_inode->i_sem); + dput(dir); +} + +/* + * Locking the parent is needed to: + * - serialize directory operations + * - make sure the parent doesn't change from + * under us in the middle of an operation. + * + * NOTE! Right now we'd rather use a "struct inode" + * for this, but as I expect things to move toward + * using dentries instead for most things it is + * probably better to start with the conceptually + * better interface of relying on a path of dentries. + */ +static inline struct dentry *lock_parent(struct dentry *dentry) +{ + struct dentry *dir = dget(dentry->d_parent); - down(&dir->i_sem); + down(&dir->d_inode->i_sem); + + /* Un-hashed or moved? Punt if so.. */ + if (dir != dentry->d_parent || list_empty(&dentry->d_hash)) { + unlock_dir(dir); + dir = NULL; + } return dir; } @@ -501,9 +525,12 @@ acc_mode = ACC_MODE(flag); if (flag & O_CREAT) { - struct inode *dir; + struct dentry *dir; + error = -ENOENT; dir = lock_parent(dentry); + if (!dir) + goto exit; /* * The existence test must be done _after_ getting the directory * semaphore - the dentry might otherwise change. @@ -512,19 +539,19 @@ error = 0; if (flag & O_EXCL) error = -EEXIST; - } else if (IS_RDONLY(dir)) + } else if (IS_RDONLY(dir->d_inode)) error = -EROFS; - else if (!dir->i_op || !dir->i_op->create) + else if (!dir->d_inode->i_op || !dir->d_inode->i_op->create) error = -EACCES; - else if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) == 0) { - if (dir->i_sb && dir->i_sb->dq_op) - dir->i_sb->dq_op->initialize(dir, -1); - error = dir->i_op->create(dir, dentry, mode); + else if ((error = permission(dir->d_inode,MAY_WRITE | MAY_EXEC)) == 0) { + if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op) + dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1); + error = dir->d_inode->i_op->create(dir->d_inode, dentry, mode); /* Don't check for write permission, don't truncate */ acc_mode = 0; flag &= ~O_TRUNC; } - up(&dir->i_sem); + unlock_dir(dir); if (error) goto exit; } @@ -600,7 +627,7 @@ struct dentry * do_mknod(const char * filename, int mode, dev_t dev) { int error; - struct inode *dir; + struct dentry *dir; struct dentry *dentry, *retval; mode &= ~current->fs->umask; @@ -609,33 +636,37 @@ return dentry; dir = lock_parent(dentry); + retval = ERR_PTR(-ENOENT); + if (!dir) + goto exit; retval = ERR_PTR(-EEXIST); if (dentry->d_inode) goto exit_lock; retval = ERR_PTR(-EROFS); - if (IS_RDONLY(dir)) + if (IS_RDONLY(dir->d_inode)) goto exit_lock; - error = permission(dir,MAY_WRITE | MAY_EXEC); + error = permission(dir->d_inode,MAY_WRITE | MAY_EXEC); retval = ERR_PTR(error); if (error) goto exit_lock; retval = ERR_PTR(-EPERM); - if (!dir->i_op || !dir->i_op->mknod) + if (!dir->d_inode->i_op || !dir->d_inode->i_op->mknod) goto exit_lock; - if (dir->i_sb && dir->i_sb->dq_op) - dir->i_sb->dq_op->initialize(dir, -1); - error = dir->i_op->mknod(dir, dentry, mode, dev); + if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op) + dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1); + error = dir->d_inode->i_op->mknod(dir->d_inode, dentry, mode, dev); retval = ERR_PTR(error); if (!error) retval = dget(dentry); exit_lock: - up(&dir->i_sem); + unlock_dir(dir); +exit: dput(dentry); return retval; } @@ -682,7 +713,7 @@ static inline int do_mkdir(const char * pathname, int mode) { int error; - struct inode *dir; + struct dentry *dir; struct dentry *dentry; dentry = lookup_dentry(pathname, NULL, 1); @@ -692,29 +723,33 @@ dir = lock_parent(dentry); + error = -ENOENT; + if (!dir) + goto exit; + error = -EEXIST; if (dentry->d_inode) goto exit_lock; error = -EROFS; - if (IS_RDONLY(dir)) + if (IS_RDONLY(dir->d_inode)) goto exit_lock; - error = permission(dir,MAY_WRITE | MAY_EXEC); + error = permission(dir->d_inode,MAY_WRITE | MAY_EXEC); if (error) goto exit_lock; error = -EPERM; - if (!dir->i_op || !dir->i_op->mkdir) + if (!dir->d_inode->i_op || !dir->d_inode->i_op->mkdir) goto exit_lock; - if (dir->i_sb && dir->i_sb->dq_op) - dir->i_sb->dq_op->initialize(dir, -1); + if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op) + dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1); mode &= 0777 & ~current->fs->umask; - error = dir->i_op->mkdir(dir, dentry, mode); + error = dir->d_inode->i_op->mkdir(dir->d_inode, dentry, mode); exit_lock: - up(&dir->i_sem); + unlock_dir(dir); dput(dentry); exit: return error; @@ -739,7 +774,7 @@ static inline int do_rmdir(const char * name) { int error; - struct inode *dir; + struct dentry *dir; struct dentry *dentry; dentry = lookup_dentry(name, NULL, 0); @@ -748,15 +783,19 @@ goto exit; dir = lock_parent(dentry); + error = -ENOENT; + if (!dir) + goto exit; + if (!dentry->d_inode) goto exit_lock; error = -EROFS; - if (IS_RDONLY(dir)) + if (IS_RDONLY(dir->d_inode)) goto exit_lock; - error = permission(dir,MAY_WRITE | MAY_EXEC); + error = permission(dir->d_inode,MAY_WRITE | MAY_EXEC); if (error) goto exit_lock; @@ -764,7 +803,7 @@ * A subdirectory cannot be removed from an append-only directory. */ error = -EPERM; - if (IS_APPEND(dir)) + if (IS_APPEND(dir->d_inode)) goto exit_lock; /* Disallow removals of mountpoints. */ @@ -773,16 +812,16 @@ goto exit_lock; error = -EPERM; - if (!dir->i_op || !dir->i_op->rmdir) + if (!dir->d_inode->i_op || !dir->d_inode->i_op->rmdir) goto exit_lock; - if (dir->i_sb && dir->i_sb->dq_op) - dir->i_sb->dq_op->initialize(dir, -1); + if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op) + dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1); - error = dir->i_op->rmdir(dir, dentry); + error = dir->d_inode->i_op->rmdir(dir->d_inode, dentry); exit_lock: - up(&dir->i_sem); + unlock_dir(dir); dput(dentry); exit: return error; @@ -807,7 +846,7 @@ static inline int do_unlink(const char * name) { int error; - struct inode *dir; + struct dentry *dir; struct dentry *dentry; dentry = lookup_dentry(name, NULL, 0); @@ -818,14 +857,16 @@ dir = lock_parent(dentry); error = -ENOENT; + if (!dir) + goto exit; if (!dentry->d_inode) goto exit_lock; error = -EROFS; - if (IS_RDONLY(dir)) + if (IS_RDONLY(dir->d_inode)) goto exit_lock; - error = permission(dir,MAY_WRITE | MAY_EXEC); + error = permission(dir->d_inode,MAY_WRITE | MAY_EXEC); if (error) goto exit_lock; @@ -833,20 +874,20 @@ * A file cannot be removed from an append-only directory. */ error = -EPERM; - if (IS_APPEND(dir)) + if (IS_APPEND(dir->d_inode)) goto exit_lock; error = -EPERM; - if (!dir->i_op || !dir->i_op->unlink) + if (!dir->d_inode->i_op || !dir->d_inode->i_op->unlink) goto exit_lock; - if (dir->i_sb && dir->i_sb->dq_op) - dir->i_sb->dq_op->initialize(dir, -1); + if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op) + dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1); - error = dir->i_op->unlink(dir, dentry); + error = dir->d_inode->i_op->unlink(dir->d_inode, dentry); exit_lock: - up(&dir->i_sem); + unlock_dir(dir); dput(dentry); exit: return error; @@ -871,7 +912,7 @@ static inline int do_symlink(const char * oldname, const char * newname) { int error; - struct inode *dir; + struct dentry *dir; struct dentry *dentry; dentry = lookup_dentry(newname, NULL, 0); @@ -882,28 +923,32 @@ dir = lock_parent(dentry); + error = -ENOENT; + if (!dir) + goto exit; + error = -EEXIST; if (dentry->d_inode) goto exit_lock; error = -EROFS; - if (IS_RDONLY(dir)) + if (IS_RDONLY(dir->d_inode)) goto exit_lock; - error = permission(dir,MAY_WRITE | MAY_EXEC); + error = permission(dir->d_inode,MAY_WRITE | MAY_EXEC); if (error) goto exit_lock; error = -EPERM; - if (!dir->i_op || !dir->i_op->symlink) + if (!dir->d_inode->i_op || !dir->d_inode->i_op->symlink) goto exit_lock; - if (dir->i_sb && dir->i_sb->dq_op) - dir->i_sb->dq_op->initialize(dir, -1); - error = dir->i_op->symlink(dir, dentry, oldname); + if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op) + dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1); + error = dir->d_inode->i_op->symlink(dir->d_inode, dentry, oldname); exit_lock: - up(&dir->i_sem); + unlock_dir(dir); dput(dentry); exit: return error; @@ -933,8 +978,8 @@ static inline int do_link(const char * oldname, const char * newname) { - struct dentry *old_dentry, *new_dentry; - struct inode *dir, *inode; + struct dentry *old_dentry, *new_dentry, *dir; + struct inode *inode; int error; old_dentry = lookup_dentry(oldname, NULL, 1); @@ -950,6 +995,9 @@ dir = lock_parent(new_dentry); error = -ENOENT; + if (!dir) + goto exit; + inode = old_dentry->d_inode; if (!inode) goto exit_lock; @@ -959,14 +1007,14 @@ goto exit_lock; error = -EROFS; - if (IS_RDONLY(dir)) + if (IS_RDONLY(dir->d_inode)) goto exit_lock; error = -EXDEV; - if (dir->i_dev != inode->i_dev) + if (dir->d_inode->i_dev != inode->i_dev) goto exit_lock; - error = permission(dir, MAY_WRITE | MAY_EXEC); + error = permission(dir->d_inode, MAY_WRITE | MAY_EXEC); if (error) goto exit_lock; @@ -978,15 +1026,15 @@ goto exit_lock; error = -EPERM; - if (!dir->i_op || !dir->i_op->link) + if (!dir->d_inode->i_op || !dir->d_inode->i_op->link) goto exit_lock; - if (dir->i_sb && dir->i_sb->dq_op) - dir->i_sb->dq_op->initialize(dir, -1); - error = dir->i_op->link(inode, dir, new_dentry); + if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op) + dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1); + error = dir->d_inode->i_op->link(inode, dir->d_inode, new_dentry); exit_lock: - up(&dir->i_sem); + unlock_dir(dir); dput(new_dentry); exit_old: dput(old_dentry); @@ -1020,30 +1068,37 @@ * Whee.. Deadlock country. Happily there is only one VFS * operation that does this.. */ -static inline void double_down(struct semaphore *s1, struct semaphore *s2) +static inline void double_lock(struct dentry *d1, struct dentry *d2) { - if ((unsigned long) s1 < (unsigned long) s2) { - down(s1); - down(s2); - } else if (s1 == s2) { - down(s1); - } else { - down(s2); + struct semaphore *s1 = &d1->d_inode->i_sem; + struct semaphore *s2 = &d2->d_inode->i_sem; + + if (s1 != s2) { + if ((unsigned long) s1 < (unsigned long) s2) { + struct semaphore *tmp = s2; + s2 = s1; s1 = tmp; + } down(s1); } + down(s2); } -static inline void double_up(struct semaphore *s1, struct semaphore *s2) +static inline void double_unlock(struct dentry *d1, struct dentry *d2) { + struct semaphore *s1 = &d1->d_inode->i_sem; + struct semaphore *s2 = &d2->d_inode->i_sem; + up(s1); if (s1 != s2) up(s2); + dput(d1); + dput(d2); } static inline int do_rename(const char * oldname, const char * newname) { int error; - struct inode * old_dir, * new_dir; + struct dentry * old_dir, * new_dir; struct dentry * old_dentry, *new_dentry; old_dentry = lookup_dentry(oldname, NULL, 0); @@ -1061,16 +1116,16 @@ new_dir = get_parent(new_dentry); old_dir = get_parent(old_dentry); - double_down(&new_dir->i_sem, &old_dir->i_sem); + double_lock(new_dir, old_dir); error = -ENOENT; if (!old_dentry->d_inode) goto exit_lock; - error = permission(old_dir,MAY_WRITE | MAY_EXEC); + error = permission(old_dir->d_inode,MAY_WRITE | MAY_EXEC); if (error) goto exit_lock; - error = permission(new_dir,MAY_WRITE | MAY_EXEC); + error = permission(new_dir->d_inode,MAY_WRITE | MAY_EXEC); if (error) goto exit_lock; @@ -1083,30 +1138,30 @@ goto exit_lock; error = -EXDEV; - if (new_dir->i_dev != old_dir->i_dev) + if (new_dir->d_inode->i_dev != old_dir->d_inode->i_dev) goto exit_lock; error = -EROFS; - if (IS_RDONLY(new_dir) || IS_RDONLY(old_dir)) + if (IS_RDONLY(new_dir->d_inode) || IS_RDONLY(old_dir->d_inode)) goto exit_lock; /* * A file cannot be removed from an append-only directory. */ error = -EPERM; - if (IS_APPEND(old_dir)) + if (IS_APPEND(old_dir->d_inode)) goto exit_lock; error = -EPERM; - if (!old_dir->i_op || !old_dir->i_op->rename) + if (!old_dir->d_inode->i_op || !old_dir->d_inode->i_op->rename) goto exit_lock; - if (new_dir->i_sb && new_dir->i_sb->dq_op) - new_dir->i_sb->dq_op->initialize(new_dir, -1); - error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); + if (new_dir->d_inode->i_sb && new_dir->d_inode->i_sb->dq_op) + new_dir->d_inode->i_sb->dq_op->initialize(new_dir->d_inode, -1); + error = old_dir->d_inode->i_op->rename(old_dir->d_inode, old_dentry, new_dir->d_inode, new_dentry); exit_lock: - double_up(&new_dir->i_sem, &old_dir->i_sem); + double_unlock(new_dir, old_dir); dput(new_dentry); exit_old: dput(old_dentry); diff -u --recursive --new-file v2.1.51/linux/fs/nfs/dir.c linux/fs/nfs/dir.c --- v2.1.51/linux/fs/nfs/dir.c Mon Aug 18 18:19:46 1997 +++ linux/fs/nfs/dir.c Sun Aug 24 11:10:29 1997 @@ -7,6 +7,13 @@ * * 10 Apr 1996 Added silly rename for unlink --okir * 28 Sep 1996 Improved directory cache --okir + * 23 Aug 1997 Claus Heine claus@momo.math.rwth-aachen.de + * Re-implemented silly rename for unlink, newly implemented + * silly rename for nfs_rename() following the suggestions + * of Olaf Kirch (okir) found in this file. + * Following Linus comments on my original hack, this version + * depends only on the dcache stuff and doesn't touch the inode + * layer (iput() and friends). */ #include @@ -349,10 +356,13 @@ return time < max; } +static void nfs_silly_delete(struct dentry *); + static struct dentry_operations nfs_dentry_operations = { nfs_lookup_revalidate, 0, /* d_hash */ 0, /* d_compare */ + nfs_silly_delete, }; static int nfs_lookup(struct inode *dir, struct dentry * dentry) @@ -378,7 +388,6 @@ inode = NULL; if (!error) { - error = -ENOENT; inode = nfs_fhget(dir->i_sb, &fhandle, &fattr); if (!inode) return -EACCES; @@ -530,9 +539,150 @@ return 0; } -/* - * We should do silly-rename here, but I'm too lazy to fix - * up the directory entry implications of it.. + +/* Note: we copy the code from lookup_dentry() here, only: we have to + * omit the directory lock. We are already the owner of the lock when + * we reach here. And "down(&dir->i_sem)" would make us sleep forever + * ('cause WE have the lock) + * + * VERY IMPORTANT: calculate the hash for this dentry!!!!!!!! + * Otherwise the cached lookup DEFINITELY WILL fail. And a new dentry + * is created. Without the DCACHE_NFSFS_RENAMED flag. And with d_count + * == 1. And trouble. + * + * Concerning my choice of the temp name: it is just nice to have + * i_ino part of the temp name, as this offers another check whether + * somebody attempts to remove the "silly renamed" dentry + * itself. Which is something that I consider evil. Your opinion may + * vary. + * BUT: + * Now that I compute the hash value right, it should be possible to simply + * check for the DCACHE_NFSFS_RENAMED flag in dentry->d_flag instead of + * doing the string compare. + * WHICH MEANS: + * This offers the opportunity to shorten the temp name. Currently, I use + * the hex representation of i_ino + the hex value of jiffies. This + * sums up to as much as 36 characters for a 64 bit machine, and needs + * 20 chars on a 32 bit machine. Have a look at jiffiesize etc. + * QUINTESSENCE + * The use of i_ino is simply cosmetic. All we need is a unique temp + * file name for the .nfs files. The hex representation of "jiffies" + * seemed to be adequate. And as we retry in case such a file already + * exists we are guaranteed to succed (after some jiffies have passed + * by :) + */ + +static +struct dentry *nfs_silly_lookup(struct dentry *parent, char *silly, int slen) +{ + struct qstr sqstr; + struct dentry *sdentry; + int i, error; + + sqstr.name = silly; + sqstr.len = slen; + sqstr.hash = init_name_hash(); + for (i= 0; i < slen; i++) + sqstr.hash = partial_name_hash(silly[i], sqstr.hash); + sqstr.hash = end_name_hash(sqstr.hash); + sdentry = d_lookup(parent, &sqstr); + if (!sdentry) { + sdentry = d_alloc(parent, &sqstr); + if (sdentry == NULL) + return ERR_PTR(-ENOMEM); + error = nfs_lookup(parent->d_inode, sdentry); + if (error) { + dput(sdentry); + return ERR_PTR(error); + } + } + return sdentry; +} + +static int nfs_sillyrename(struct inode *dir, struct dentry *dentry) +{ + static unsigned int sillycounter = 0; + const int i_inosize = sizeof(dir->i_ino)*2; + const int countersize = sizeof(sillycounter)*2; + const int slen = strlen(".nfs") + i_inosize + countersize; + char silly[slen+1]; + int error; + struct dentry *sdentry; + + if (dentry->d_count == 1) { + return -EIO; /* No need to silly rename. */ + } + + if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { + return -EBUSY; /* don't allow to unlink silly inode -- nope, + * think a bit: silly DENTRY, NOT inode -- + * itself + */ + } + + sprintf(silly, ".nfs%*.*lx", + i_inosize, i_inosize, dentry->d_inode->i_ino); + + sdentry = NULL; + do { + char *suffix = silly + slen - countersize; + + dput(sdentry); + sillycounter++; + sprintf(suffix, "%*.*x", countersize, countersize, sillycounter); + + dfprintk(VFS, "trying to rename %s to %s\n", + dentry->d_name.name, silly); + + sdentry = nfs_silly_lookup(dentry->d_parent, silly, slen); + if (IS_ERR(sdentry)) { + return -EIO; /* FIXME ? */ + } + } while(sdentry->d_inode != NULL); /* need negative lookup */ + + error = nfs_proc_rename(NFS_SERVER(dir), + NFS_FH(dir), dentry->d_name.name, + NFS_FH(dir), silly); + if (error) { + dput(sdentry); + return error; + } + nfs_invalidate_dircache(dir); + d_move(dentry, sdentry); + dput(sdentry); + dentry->d_flags |= DCACHE_NFSFS_RENAMED; + + return 0; /* don't unlink */ +} + +static void nfs_silly_delete(struct dentry *dentry) +{ + if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { + struct inode *dir = dentry->d_parent->d_inode; + int error; + + dentry->d_flags &= ~DCACHE_NFSFS_RENAMED; + + /* Unhash it first */ + d_drop(dentry); + dfprintk(VFS, "trying to unlink %s\n", dentry->d_name.name); + error = nfs_proc_remove(NFS_SERVER(dir), + NFS_FH(dir), dentry->d_name.name); + if (error < 0) + printk("NFS " __FUNCTION__ " failed (err = %d)\n", + -error); + dentry->d_inode->i_nlink --; + nfs_invalidate_dircache(dir); + } +} + +/* We do silly rename. In case sillyrename() returns -EBUSY, the inode + * belongs to an active ".nfs..." file and we return -EBUSY. + * + * If sillyrename() returns 0, we do nothing, otherwise we unlink. + * + * inode->i_nlink is updated here rather than waiting for the next + * nfs_refresh_inode() for cosmetic reasons only. */ static int nfs_unlink(struct inode *dir, struct dentry *dentry) { @@ -549,12 +699,21 @@ if (dentry->d_name.len > NFS_MAXNAMLEN) return -ENAMETOOLONG; - error = nfs_proc_remove(NFS_SERVER(dir), NFS_FH(dir), dentry->d_name.name); - if (error) - return error; + error = nfs_sillyrename(dir, dentry); + + if (error == -EBUSY) { + return -EBUSY; + } else if (error < 0) { + error = nfs_proc_remove(NFS_SERVER(dir), + NFS_FH(dir), dentry->d_name.name); + if (error < 0) + return error; + + dentry->d_inode->i_nlink --; + nfs_invalidate_dircache(dir); + d_delete(dentry); + } - nfs_invalidate_dircache(dir); - d_delete(dentry); return 0; } @@ -588,7 +747,7 @@ return error; nfs_invalidate_dircache(dir); - /* this looks _funny_ doesn't it? But: nfs_proc_symlynk() + /* this looks _funny_ doesn't it? But: nfs_proc_symlink() * only fills in sattr, not fattr. Thus nfs_fhget() cannot be * called, it would be pointless, without a valid fattr * argument. Other possibility: call nfs_proc_lookup() @@ -623,7 +782,8 @@ return error; nfs_invalidate_dircache(dir); - inode->i_count++; + inode->i_count ++; + inode->i_nlink ++; /* no need to wait for nfs_refresh_inode() */ d_instantiate(dentry, inode); return 0; } @@ -634,8 +794,17 @@ * different file handle for the same inode after a rename (e.g. when * moving to a different directory). A fail-safe method to do so would * be to look up old_dir/old_name, create a link to new_dir/new_name and - * rename the old file using the silly_rename stuff. This way, the original + * rename the old file using the sillyrename stuff. This way, the original * file in old_dir will go away when the last process iput()s the inode. + * + * FIXED. + * + * It actually works quite well. One needs to have the possibility for + * at least one ".nfs..." file in each directory the file ever gets + * moved or linked to which happens automagically with the new + * implementation that only depends on the dcache stuff instead of + * using the inode layer + * */ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) @@ -659,10 +828,22 @@ if (old_dentry->d_name.len > NFS_MAXNAMLEN || new_dentry->d_name.len > NFS_MAXNAMLEN) return -ENAMETOOLONG; - error = nfs_proc_rename(NFS_SERVER(old_dir), - NFS_FH(old_dir), old_dentry->d_name.name, - NFS_FH(new_dir), new_dentry->d_name.name); + if (new_dir != old_dir) { + error = nfs_sillyrename(old_dir, old_dentry); + if (error == -EBUSY) { + return -EBUSY; + } else if (error == 0) { /* did silly rename stuff */ + error = nfs_link(old_dentry->d_inode, + new_dir, new_dentry); + + return error; + } + /* no need for silly rename, proceed as usual */ + } + error = nfs_proc_rename(NFS_SERVER(old_dir), + NFS_FH(old_dir), old_dentry->d_name.name, + NFS_FH(new_dir), new_dentry->d_name.name); if (error) return error; @@ -737,3 +918,10 @@ } else inode->i_op = NULL; } + +/* + * Local variables: + * version-control: t + * kept-new-versions: 5 + * End: + */ diff -u --recursive --new-file v2.1.51/linux/fs/nfs/inode.c linux/fs/nfs/inode.c --- v2.1.51/linux/fs/nfs/inode.c Thu Jul 17 10:06:07 1997 +++ linux/fs/nfs/inode.c Sat Aug 23 16:47:12 1997 @@ -77,10 +77,6 @@ dprintk("NFS: put_inode(%x/%ld)\n", inode->i_dev, inode->i_ino); } -/* - * This should do any silly-rename cleanups once we - * get silly-renaming working again.. - */ static void nfs_delete_inode(struct inode * inode) { @@ -454,6 +450,8 @@ init_nfs_fs(void) { #ifdef CONFIG_PROC_FS + rpc_register_sysctl(); + rpc_proc_init(); rpc_proc_register(&nfs_rpcstat); #endif return register_filesystem(&nfs_fs_type); diff -u --recursive --new-file v2.1.51/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c --- v2.1.51/linux/fs/nfsd/vfs.c Sun Jul 27 12:11:01 1997 +++ linux/fs/nfsd/vfs.c Tue Aug 19 13:26:22 1997 @@ -44,7 +44,7 @@ /* Hack until we have a macro check for mandatory locks. */ #ifndef IS_ISMNDLK -#define IS_ISMNDLK(i) (((i)->i_mode & (S_ISGID|S_ISVTX)) == S_ISGID) +#define IS_ISMNDLK(i) (((i)->i_mode & (S_ISGID|S_IXGRP)) == S_ISGID) #endif /* Check for dir entries '.' and '..' */ diff -u --recursive --new-file v2.1.51/linux/fs/proc/array.c linux/fs/proc/array.c --- v2.1.51/linux/fs/proc/array.c Mon Aug 4 16:25:39 1997 +++ linux/fs/proc/array.c Wed Aug 20 13:59:36 1997 @@ -295,14 +295,20 @@ static int get_meminfo(char * buffer) { struct sysinfo i; + int len; si_meminfo(&i); si_swapinfo(&i); - + len = sprintf(buffer, " total: used: free: shared: buffers: cached:\n" + "Mem: %8lu %8lu %8lu %8lu %8lu %8lu\n" + "Swap: %8lu %8lu %8lu\n", + i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram, page_cache_size*PAGE_SIZE, + i.totalswap, i.totalswap-i.freeswap, i.freeswap); /* - * Tagged format, for easy grepping and expansion. + * Tagged format, for easy grepping and expansion. The above will go away + * eventually, once the tools have been updated. */ - return sprintf(buffer, + return len + sprintf(buffer+len, "MemTotal: %8lu kB\n" "MemFree: %8lu kB\n" "MemShared: %8lu kB\n" diff -u --recursive --new-file v2.1.51/linux/fs/proc/openpromfs.c linux/fs/proc/openpromfs.c --- v2.1.51/linux/fs/proc/openpromfs.c Mon Aug 18 18:19:46 1997 +++ linux/fs/proc/openpromfs.c Mon Aug 18 20:17:14 1997 @@ -840,26 +840,19 @@ if (!dir) return -ENOENT; - if (dentry->d_name.len > 256) { - iput (dir); + if (dentry->d_name.len > 256) return -EINVAL; - } - if (aliases_nodes == ALIASES_NNODES) { - iput (dir); + if (aliases_nodes == ALIASES_NNODES) return -EIO; - } p = kmalloc (dentry->d_name.len + 1, GFP_KERNEL); - if (!p) { - iput (dir); + if (!p) return -ENOMEM; - } strncpy (p, dentry->d_name.name, dentry->d_name.len); p [dentry->d_name.len] = 0; alias_names [aliases_nodes++] = p; inode = proc_get_inode (dir->i_sb, NODEP2INO(NODE(dir->i_ino).first_prop) + aliases_nodes, 0); - iput (dir); if (!inode) return -EINVAL; inode->i_mode = S_IFREG | S_IRUGO | S_IWUSR; diff -u --recursive --new-file v2.1.51/linux/fs/romfs/inode.c linux/fs/romfs/inode.c --- v2.1.51/linux/fs/romfs/inode.c Mon Aug 4 16:25:39 1997 +++ linux/fs/romfs/inode.c Tue Aug 19 10:57:45 1997 @@ -455,15 +455,6 @@ int len, cnt; struct dentry *dentry; - /* Note: 2.1.46+ calls this for our strange directories... - * What I do is not really right, but I like it better for now, - * than a separate i_op table. Anyway, our directories won't - * have multiple "real" links to them, so it maybe loses nothing. */ - if (!S_ISLNK(inode->i_mode)) { - dentry = dget(i_dentry(inode)); - goto outnobuf; - } - len = inode->i_size; dentry = ERR_PTR(-EAGAIN); /* correct? */ @@ -548,7 +539,7 @@ * will protect from type mismatch. */ -static struct inode_operations romfs_dirlink_inode_operations = { +static struct inode_operations romfs_dir_inode_operations = { &romfs_dir_operations, NULL, /* create */ romfs_lookup, /* lookup */ @@ -559,6 +550,27 @@ NULL, /* rmdir */ NULL, /* mknod */ NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* readpage */ + NULL, /* writepage */ + NULL, /* bmap */ + NULL, /* truncate */ + NULL, /* permission */ + NULL, /* smap */ +}; + +static struct inode_operations romfs_link_inode_operations = { + NULL, /* no file operations on symlinks */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ romfs_readlink, /* readlink */ romfs_follow_link, /* follow_link */ NULL, /* readpage */ @@ -578,9 +590,9 @@ static struct inode_operations *romfs_inoops[] = { NULL, /* hardlink, handled elsewhere */ - &romfs_dirlink_inode_operations, + &romfs_dir_inode_operations, &romfs_file_inode_operations, - &romfs_dirlink_inode_operations, + &romfs_link_inode_operations, &blkdev_inode_operations, /* standard handlers */ &chrdev_inode_operations, NULL, /* socket */ diff -u --recursive --new-file v2.1.51/linux/fs/select.c linux/fs/select.c --- v2.1.51/linux/fs/select.c Mon Jun 16 16:35:59 1997 +++ linux/fs/select.c Fri Aug 22 19:56:43 1997 @@ -423,7 +423,7 @@ wait_table.nr = 0; wait_table.entry = entry; - fdcount = do_poll(nfds, fds, &wait_table); + fdcount = do_poll(nfds, fds, timeout ? &wait_table : NULL); current->timeout = 0; free_wait(&wait_table); diff -u --recursive --new-file v2.1.51/linux/fs/smbfs/Makefile linux/fs/smbfs/Makefile --- v2.1.51/linux/fs/smbfs/Makefile Sun Dec 1 08:22:08 1996 +++ linux/fs/smbfs/Makefile Fri Aug 22 10:04:33 1997 @@ -8,11 +8,11 @@ # Note 2! The CFLAGS definitions are now in the main makefile... O_TARGET := smbfs.o -O_OBJS := proc.o sock.o inode.o file.o dir.o ioctl.o mmap.o +O_OBJS := proc.o dir.o sock.o inode.o file.o ioctl.o M_OBJS := $(O_TARGET) # If you want debugging output, please uncomment the following line -# EXTRA_CFLAGS += -DDEBUG_SMB=1 -DDEBUG_SMB_MALLOC=1 +# EXTRA_CFLAGS += -DDEBUG -DDEBUG_SMB_MALLOC=1 include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.51/linux/fs/smbfs/dir.c linux/fs/smbfs/dir.c --- v2.1.51/linux/fs/smbfs/dir.c Mon Jun 16 16:35:59 1997 +++ linux/fs/smbfs/dir.c Fri Aug 22 10:13:04 1997 @@ -2,6 +2,7 @@ * dir.c * * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke + * Copyright (C) 1997 by Volker Lendecke * */ @@ -19,35 +20,19 @@ #include static long - smb_dir_read(struct inode *inode, struct file *filp, char *buf, unsigned long count); +smb_dir_read(struct inode *inode, struct file *filp, + char *buf, unsigned long count); static int - smb_readdir(struct inode *inode, struct file *filp, - void *dirent, filldir_t filldir); +smb_readdir(struct inode *inode, struct file *filp, + void *dirent, filldir_t filldir); -static struct smb_inode_info * - smb_find_dir_inode(struct inode *parent, const char *name, int len); - -static int - smb_lookup(struct inode *dir, const char *__name, - int len, struct inode **result); - -static int - smb_create(struct inode *dir, const char *name, int len, int mode, - struct inode **result); - -static int - smb_mkdir(struct inode *dir, const char *name, int len, int mode); - -static int - smb_rmdir(struct inode *dir, const char *name, int len); - -static int - smb_unlink(struct inode *dir, const char *name, int len); - -static int - smb_rename(struct inode *old_dir, const char *old_name, int old_len, - struct inode *new_dir, const char *new_name, int new_len); +static int smb_lookup(struct inode *, struct dentry *); +static int smb_create(struct inode *, struct dentry *, int); +static int smb_mkdir(struct inode *, struct dentry *, int); +static int smb_rmdir(struct inode *, struct dentry *); +static int smb_unlink(struct inode *, struct dentry *); +static int smb_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); static struct file_operations smb_dir_operations = { @@ -56,7 +41,7 @@ NULL, /* write - bad */ smb_readdir, /* readdir */ NULL, /* poll - default */ - smb_ioctl, /* ioctl - default */ + smb_ioctl, /* ioctl */ NULL, /* mmap */ NULL, /* no special open code */ NULL, /* no special release code */ @@ -76,6 +61,7 @@ NULL, /* mknod */ smb_rename, /* rename */ NULL, /* readlink */ + NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ @@ -84,100 +70,13 @@ NULL /* smap */ }; -static int -strncasecmp(const char *s1, const char *s2, int len) -{ - int result = 0; - - for (; len > 0; len -= 1) - { - char c1, c2; - - c1 = (*s1 >= 'a' && *s1 <= 'z') ? *s1 - ('a' - 'A') : *s1; - c2 = (*s2 >= 'a' && *s2 <= 'z') ? *s2 - ('a' - 'A') : *s2; - s1 += 1; - s2 += 1; - - if ((result = c1 - c2) != 0 || c1 == 0) - { - return result; - } - } - return result; -} - -static int -compare_filename(const struct smb_server *server, - const char *s1, int len, struct smb_dirent *entry) -{ - if (len != entry->len) - { - return 1; - } - if (server->case_handling == CASE_DEFAULT) - { - return strncasecmp(s1, entry->name, len); - } - return strncmp(s1, entry->name, len); -} - -struct smb_inode_info * -smb_find_inode(struct smb_server *server, ino_t ino) -{ - struct smb_inode_info *root = &(server->root); - struct smb_inode_info *this = root; - - do - { - if (ino == smb_info_ino(this)) - { - return this; - } - this = this->next; - } - while (this != root); - - return NULL; -} - -static ino_t -smb_fresh_inodes(struct smb_server *server, int no) -{ - static ino_t seed = 1; - struct smb_inode_info *root = &(server->root); - struct smb_inode_info *this; - - retry: - if (seed + no <= no) - { - /* avoid inode number of 0 at wrap-around */ - seed += no; - } - this = root; - do - { - /* We assume that ino_t is unsigned! */ - if (this->finfo.f_ino - seed < no) - { - seed += no; - goto retry; - } - this = this->next; - } - while (this != root); - - seed += no; - - return seed - no; -} - static long -smb_dir_read(struct inode *inode, struct file *filp, char *buf, unsigned long count) +smb_dir_read(struct inode *inode, struct file *filp, char *buf, + unsigned long count) { return -EISDIR; } - static unsigned long c_ino = 0; static kdev_t c_dev; static int c_size; @@ -206,8 +105,7 @@ } static int -smb_refill_dir_cache(struct smb_server *server, struct inode *dir, - unsigned long f_pos) +smb_refill_dir_cache(struct inode *dir, unsigned long f_pos) { int result; static struct semaphore sem = MUTEX; @@ -217,7 +115,7 @@ do { down(&sem); - result = smb_proc_readdir(server, dir, f_pos, + result = smb_proc_readdir(dir, f_pos, SMB_READDIR_CACHE_SIZE, c_entry); if (result <= 0) @@ -232,15 +130,12 @@ c_size = result; c_last_returned_index = 0; - ino = smb_fresh_inodes(server, c_size); + ino = smb_invent_inos(c_size); + for (i = 0; i < c_size; i++) - { - c_entry[i].f_ino = ino; - ino += 1; - } + c_entry[i].attr.f_ino = ino++; up(&sem); - } while ((c_dev != dir->i_dev) || (c_ino != dir->i_ino)); @@ -253,15 +148,13 @@ { int result, i = 0; struct smb_dirent *entry = NULL; - struct smb_server *server = SMB_SERVER(dir); - DPRINTK("smb_readdir: filp->f_pos = %d\n", (int) filp->f_pos); - DDPRINTK("smb_readdir: dir->i_ino = %ld, c_ino = %ld\n", + pr_debug("smb_readdir: filp->f_pos = %d\n", (int) filp->f_pos); + pr_debug("smb_readdir: dir->i_ino = %ld, c_ino = %ld\n", dir->i_ino, c_ino); if ((dir == NULL) || !S_ISDIR(dir->i_mode)) { - printk("smb_readdir: dir is NULL or not a directory\n"); return -EBADF; } if (c_entry == NULL) @@ -270,7 +163,6 @@ c_entry = (struct smb_dirent *) smb_vmalloc(i); if (c_entry == NULL) { - printk("smb_readdir: no MEMORY for cache\n"); return -ENOMEM; } } @@ -280,20 +172,17 @@ c_dev = 0; c_seen_eof = 0; - if (filldir(dirent, ".", 1, filp->f_pos, - smb_info_ino(SMB_INOP(dir))) < 0) - { + if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino) < 0) return 0; - } + filp->f_pos += 1; } if (filp->f_pos == 1) { if (filldir(dirent, "..", 2, filp->f_pos, - smb_info_ino(SMB_INOP(dir)->dir)) < 0) - { + filp->f_dentry->d_parent->d_inode->i_ino) < 0) return 0; - } + filp->f_pos += 1; } entry = smb_search_in_cache(dir, filp->f_pos); @@ -305,7 +194,7 @@ /* End of directory */ return 0; } - result = smb_refill_dir_cache(server, dir, filp->f_pos); + result = smb_refill_dir_cache(dir, filp->f_pos); if (result <= 0) { return result; @@ -314,35 +203,18 @@ } while (entry < &(c_entry[c_size])) { - /* We found it. For getwd(), we have to return the - correct inode in d_ino if the inode is currently in - use. Otherwise the inode number does not - matter. (You can argue a lot about this..) */ - - struct smb_inode_info *ino_info - = smb_find_dir_inode(dir, entry->name, entry->len); + ino_t ino = entry->attr.f_ino; - ino_t ino = entry->f_ino; - - if (ino_info != NULL) - { - ino = smb_info_ino(ino_info); - } - DDPRINTK("smb_readdir: entry->name = %s\n", entry->name); - DDPRINTK("smb_readdir: entry->f_pos = %ld\n", entry->f_pos); + pr_debug("smb_readdir: entry->name = %s\n", entry->name); if (filldir(dirent, entry->name, strlen(entry->name), entry->f_pos, ino) < 0) - { break; - } + if ((dir->i_dev != c_dev) || (dir->i_ino != c_ino) || (entry->f_pos != filp->f_pos)) - { - /* Someone has destroyed the cache while we slept - in filldir */ break; - } + filp->f_pos += 1; entry += 1; } @@ -360,7 +232,7 @@ void smb_invalid_dir_cache(unsigned long ino) { - /* TODO: check for dev as well */ + /* FIXME: check for dev as well */ if (ino == c_ino) { c_ino = 0; @@ -378,466 +250,198 @@ c_entry = NULL; } -/* Insert a NEW smb_inode_info into the inode tree of our filesystem, - under dir. The caller must assure that it's not already there. We - assume that path is allocated for us. */ - -static struct inode * -smb_iget(struct inode *dir, struct smb_inode_info *new_inode_info) +static int +smb_lookup(struct inode *dir, struct dentry *d_entry) { + struct smb_fattr finfo; struct inode *inode; - struct smb_inode_info *root; - - if ((dir == NULL) || (new_inode_info == NULL)) - { - printk("smb_iget: parameter is NULL\n"); - return NULL; - } - new_inode_info->state = SMB_INODE_LOOKED_UP; - new_inode_info->nused = 0; - new_inode_info->dir = SMB_INOP(dir); - - SMB_INOP(dir)->nused += 1; - - /* We have to link the new inode_info into the doubly linked - list of inode_infos to make a complete linear search - possible. */ - - root = &(SMB_SERVER(dir)->root); - - new_inode_info->prev = root; - new_inode_info->next = root->next; - root->next->prev = new_inode_info; - root->next = new_inode_info; - - if (!(inode = iget(dir->i_sb, smb_info_ino(new_inode_info)))) - { - new_inode_info->next->prev = new_inode_info->prev; - new_inode_info->prev->next = new_inode_info->next; - SMB_INOP(dir)->nused -= 1; - - printk("smb_iget: iget failed!"); - return NULL; - } - return inode; -} + int len = d_entry->d_name.len; + int error; -void -smb_free_inode_info(struct smb_inode_info *i) -{ - if (i == NULL) - { - printk("smb_free_inode: i == NULL\n"); - return; + if (!dir || !S_ISDIR(dir->i_mode)) { + printk("smb_lookup: inode is NULL or not a directory\n"); + return -ENOENT; } - i->state = SMB_INODE_CACHED; - while ((i->nused == 0) && (i->state == SMB_INODE_CACHED)) - { - struct smb_inode_info *dir = i->dir; - - i->next->prev = i->prev; - i->prev->next = i->next; - smb_kfree_s(i, sizeof(struct smb_inode_info)); + if (len > SMB_MAXNAMELEN) + return -ENAMETOOLONG; - if (dir == NULL) - { - return; - } - dir->nused -= 1; - i = dir; - } -} - -void -smb_init_root(struct smb_server *server) -{ - struct smb_inode_info *root = &(server->root); + error = smb_proc_getattr(dir, &(d_entry->d_name), &finfo); - root->state = SMB_INODE_LOOKED_UP; - root->nused = 1; - root->dir = NULL; - root->next = root->prev = root; + inode = NULL; + if (!error) { + error = -ENOENT; + finfo.f_ino = smb_invent_inos(1); + inode = smb_iget(dir->i_sb, &finfo); + if (!inode) + return -EACCES; + } else if (error != -ENOENT) + return error; - return; + d_add(d_entry, inode); + return 0; } -void -smb_free_all_inodes(struct smb_server *server) +static int smb_create(struct inode *dir, struct dentry *dentry, int mode) { - /* Here nothing should be to do. I do not know whether it's - better to leave some memory allocated or be stuck in an - endless loop */ -#if 1 - struct smb_inode_info *root = &(server->root); + struct smb_fattr fattr; + struct inode *inode; + int error; - if (root->next != root) - { - printk("smb_free_all_inodes: INODES LEFT!!!\n"); - } - while (root->next != root) + if (!dir || !S_ISDIR(dir->i_mode)) { - printk("smb_free_all_inodes: freeing inode\n"); - smb_free_inode_info(root->next); - /* In case we have an endless loop.. */ - schedule(); + printk("smb_create: inode is NULL or not a directory\n"); + return -ENOENT; } -#endif - return; -} + if (dentry->d_name.len > SMB_MAXNAMELEN) + return -ENAMETOOLONG; -/* This has to be called when a connection has gone down, so that all - file-handles we got from the server are invalid */ -void -smb_invalidate_all_inodes(struct smb_server *server) -{ - struct smb_inode_info *ino = &(server->root); + error = smb_proc_create(dir, &(dentry->d_name), 0, CURRENT_TIME); + if (error < 0) + return error; - do - { - ino->finfo.opened = 0; - ino = ino->next; - } - while (ino != &(server->root)); + smb_invalid_dir_cache(dir->i_ino); - return; -} + /* FIXME: In the CIFS create call we get the file in open + * state. Currently we close it directly again, although this + * is not necessary anymore. */ -/* We will search the inode that belongs to this name, currently by a - complete linear search through the inodes belonging to this - filesystem. This has to be fixed. */ -static struct smb_inode_info * -smb_find_dir_inode(struct inode *parent, const char *name, int len) -{ - struct smb_server *server = SMB_SERVER(parent); - struct smb_inode_info *dir = SMB_INOP(parent); - struct smb_inode_info *result = &(server->root); + error = smb_proc_getattr(dir, &(dentry->d_name), &fattr); + if (error < 0) + return error; - if (name == NULL) - { - return NULL; - } - if ((len == 1) && (name[0] == '.')) - { - return dir; - } - if ((len == 2) && (name[0] == '.') && (name[1] == '.')) - { - return dir->dir; - } - do - { - if (result->dir == dir) - { - if (compare_filename(server, name, len, - &(result->finfo)) == 0) - { - return result; - } - } - result = result->next; - } - while (result != &(server->root)); + fattr.f_ino = smb_invent_inos(1); - return NULL; + inode = smb_iget(dir->i_sb, &fattr); + if (!inode) + return -EACCES; + + d_instantiate(dentry, inode); + return 0; } static int -smb_lookup(struct inode *dir, const char *name, int len, - struct inode **result) +smb_mkdir(struct inode *dir, struct dentry *dentry, int mode) { - struct smb_dirent finfo; - struct smb_inode_info *result_info; + struct smb_fattr fattr; + struct inode *inode; int error; - int found_in_cache; - - struct smb_inode_info *new_inode_info = NULL; - - *result = NULL; if (!dir || !S_ISDIR(dir->i_mode)) { - printk("smb_lookup: inode is NULL or not a directory.\n"); - iput(dir); + printk("smb_mkdir: inode is NULL or not a directory\n"); return -ENOENT; } - DDPRINTK("smb_lookup: %s\n", name); - - /* Fast cheat for . */ - if (len == 0 || (len == 1 && name[0] == '.')) - { - *result = dir; - return 0; - } - /* ..and for .. */ - if (len == 2 && name[0] == '.' && name[1] == '.') - { - struct smb_inode_info *parent = SMB_INOP(dir)->dir; - - if (parent->state == SMB_INODE_CACHED) - { - parent->state = SMB_INODE_LOOKED_UP; - } - *result = iget(dir->i_sb, smb_info_ino(parent)); - iput(dir); - if (*result == 0) - { - return -EACCES; - } - return 0; - } - result_info = smb_find_dir_inode(dir, name, len); - - in_tree: - if (result_info != NULL) - { - if (result_info->state == SMB_INODE_CACHED) - { - result_info->state = SMB_INODE_LOOKED_UP; - } - *result = iget(dir->i_sb, smb_info_ino(result_info)); - iput(dir); - - if (new_inode_info != NULL) - { - smb_kfree_s(new_inode_info, - sizeof(struct smb_inode_info)); - } - if (*result == NULL) - { - return -EACCES; - } - return 0; - } - /* If the file is in the dir cache, we do not have to ask the - server. */ - found_in_cache = 0; - if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino) && (c_size != 0)) - { - int first = c_last_returned_index; - int i; + if (dentry->d_name.len > SMB_MAXNAMELEN) + return -ENAMETOOLONG; - i = first; - do - { - if (compare_filename(SMB_SERVER(dir), name, len, - &(c_entry[i])) == 0) - { - finfo = c_entry[i]; - found_in_cache = 1; - break; - } - i = (i + 1) % c_size; - } - while (i != first); - } - if (found_in_cache == 0) - { - DPRINTK("smb_lookup: not found in cache: %s\n", name); - if (len > SMB_MAXNAMELEN) - { - iput(dir); - return -ENAMETOOLONG; - } - error = smb_proc_getattr(dir, name, len, &finfo); - if (error < 0) - { - iput(dir); - return error; - } - finfo.f_ino = smb_fresh_inodes(SMB_SERVER(dir), 1); - } - new_inode_info = smb_kmalloc(sizeof(struct smb_inode_info), - GFP_KERNEL); + error = smb_proc_mkdir(dir, &(dentry->d_name)); + if (error) + return error; - /* Here somebody else might have inserted the inode */ + smb_invalid_dir_cache(dir->i_ino); - result_info = smb_find_dir_inode(dir, name, len); - if (result_info != NULL) - { - goto in_tree; - } - new_inode_info->finfo = finfo; + error = smb_proc_getattr(dir, &(dentry->d_name), &fattr); + if (error < 0) + return error; - DPRINTK("attr: %x\n", finfo.attr); + fattr.f_ino = smb_invent_inos(1); - if ((*result = smb_iget(dir, new_inode_info)) == NULL) - { - smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info)); - iput(dir); + inode = smb_iget(dir->i_sb, &fattr); + if (!inode) return -EACCES; - } - DDPRINTK("smb_lookup: %s => %lu\n", name, (unsigned long) result_info); - iput(dir); + + d_instantiate(dentry, inode); return 0; } static int -smb_create(struct inode *dir, const char *name, int len, int mode, - struct inode **result) +smb_rmdir(struct inode *dir, struct dentry *dentry) { int error; - struct smb_dirent entry; - struct smb_inode_info *new_inode_info; - - *result = NULL; if (!dir || !S_ISDIR(dir->i_mode)) { - printk("smb_create: inode is NULL or not a directory\n"); - iput(dir); + printk("smb_rmdir: inode is NULL or not a directory\n"); return -ENOENT; } - new_inode_info = smb_kmalloc(sizeof(struct smb_inode_info), - GFP_KERNEL); - if (new_inode_info == NULL) - { - iput(dir); - return -ENOMEM; - } - error = smb_proc_create(dir, name, len, 0, CURRENT_TIME); - if (error < 0) - { - smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info)); - iput(dir); - return error; - } - smb_invalid_dir_cache(dir->i_ino); - - if ((error = smb_proc_getattr(dir, name, len, &entry)) < 0) - { - smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info)); - iput(dir); - return error; - } - entry.f_ino = smb_fresh_inodes(SMB_SERVER(dir), 1); - new_inode_info->finfo = entry; + if (dentry->d_name.len > NFS_MAXNAMLEN) + return -ENAMETOOLONG; - if ((*result = smb_iget(dir, new_inode_info)) == NULL) - { - smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info)); - iput(dir); + error = smb_proc_rmdir(dir, &(dentry->d_name)); + if (error) return error; - } - iput(dir); + + d_delete(dentry); return 0; } static int -smb_mkdir(struct inode *dir, const char *name, int len, int mode) +smb_unlink(struct inode *dir, struct dentry *dentry) { int error; if (!dir || !S_ISDIR(dir->i_mode)) { - iput(dir); - return -EINVAL; - } - if ((error = smb_proc_mkdir(dir, name, len)) == 0) - { - smb_invalid_dir_cache(dir->i_ino); + printk("smb_unlink: inode is NULL or not a directory\n"); + return -ENOENT; } - iput(dir); - return error; -} -static int -smb_rmdir(struct inode *dir, const char *name, int len) -{ - int error; + if (dentry->d_name.len > SMB_MAXNAMELEN) + return -ENAMETOOLONG; - if (!dir || !S_ISDIR(dir->i_mode)) - { - printk("smb_rmdir: inode is NULL or not a directory\n"); - iput(dir); - return -ENOENT; - } - if (smb_find_dir_inode(dir, name, len) != NULL) - { - error = -EBUSY; - } else - { - if ((error = smb_proc_rmdir(dir, name, len)) == 0) - { - smb_invalid_dir_cache(dir->i_ino); - } - } - iput(dir); - return error; -} + error = smb_proc_unlink(dir, &(dentry->d_name)); + if (error) + return error; -static int -smb_unlink(struct inode *dir, const char *name, int len) -{ - int error; + smb_invalid_dir_cache(dir->i_ino); - if (!dir || !S_ISDIR(dir->i_mode)) - { - printk("smb_unlink: inode is NULL or not a directory\n"); - iput(dir); - return -ENOENT; - } - if (smb_find_dir_inode(dir, name, len) != NULL) - { - error = -EBUSY; - } else - { - if ((error = smb_proc_unlink(dir, name, len)) == 0) - { - smb_invalid_dir_cache(dir->i_ino); - } - } - iput(dir); - return error; + d_delete(dentry); + return 0; } -static int -smb_rename(struct inode *old_dir, const char *old_name, int old_len, - struct inode *new_dir, const char *new_name, int new_len) +static int smb_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry) { - int res; + int error; if (!old_dir || !S_ISDIR(old_dir->i_mode)) { printk("smb_rename: old inode is NULL or not a directory\n"); - res = -ENOENT; - goto finished; + return -ENOENT; } + if (!new_dir || !S_ISDIR(new_dir->i_mode)) { printk("smb_rename: new inode is NULL or not a directory\n"); - res = -ENOENT; - goto finished; - } - if ((smb_find_dir_inode(old_dir, old_name, old_len) != NULL) - || (smb_find_dir_inode(new_dir, new_name, new_len) != NULL)) - { - res = -EBUSY; - goto finished; + return -ENOENT; } - res = smb_proc_mv(old_dir, old_name, old_len, - new_dir, new_name, new_len); - if (res == -EEXIST) - { - int res1 = smb_proc_unlink(old_dir, new_name, new_len); + if (old_dentry->d_name.len > SMB_MAXNAMELEN || + new_dentry->d_name.len > SMB_MAXNAMELEN) + return -ENAMETOOLONG; + + error = smb_proc_mv(old_dir, &(old_dentry->d_name), + new_dir, &(new_dentry->d_name)); + + if (error == -EEXIST) + { + error = smb_proc_unlink(old_dir, &(new_dentry->d_name)); + + if (error) + return error; - if (res1 == 0) - { - res = smb_proc_mv(old_dir, old_name, old_len, - new_dir, new_name, new_len); - } - } - if (res == 0) - { - smb_invalid_dir_cache(old_dir->i_ino); - smb_invalid_dir_cache(new_dir->i_ino); + error = smb_proc_mv(old_dir, &(old_dentry->d_name), + new_dir, &(new_dentry->d_name)); } - finished: - iput(old_dir); - iput(new_dir); - return res; + + if (error) + return error; + + smb_invalid_dir_cache(old_dir->i_ino); + smb_invalid_dir_cache(new_dir->i_ino); + return 0; } diff -u --recursive --new-file v2.1.51/linux/fs/smbfs/file.c linux/fs/smbfs/file.c --- v2.1.51/linux/fs/smbfs/file.c Mon Aug 18 18:19:46 1997 +++ linux/fs/smbfs/file.c Fri Aug 22 10:04:33 1997 @@ -1,7 +1,8 @@ /* * file.c * - * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke + * Copyright (C) 1995, 1996, 1997 by Paal-Kr. Engstad and Volker Lendecke + * Copyright (C) 1997 by Volker Lendecke * */ @@ -13,6 +14,7 @@ #include #include #include +#include #include #include @@ -29,184 +31,204 @@ return 0; } -int -smb_make_open(struct inode *i, int right) +/* + * Read a page synchronously. + */ +static int +smb_readpage_sync(struct inode *inode, struct page *page) { - struct smb_dirent *dirent; + unsigned long offset = page->offset; + char *buffer = (char *) page_address(page); + int rsize = SMB_SERVER(inode)->opt.max_xmit - (SMB_HEADER_LEN+15); + int result, refresh = 0; + int count = PAGE_SIZE; + + pr_debug("SMB: smb_readpage_sync(%p)\n", page); + clear_bit(PG_error, &page->flags); + + result = smb_open(inode, O_RDONLY); + if (result < 0) + goto io_error; + + do { + if (count < rsize) + rsize = count; - if (i == NULL) - { - printk("smb_make_open: got NULL inode\n"); - return -EINVAL; - } - dirent = &(SMB_INOP(i)->finfo); - - DDPRINTK("smb_make_open: dirent->opened = %d\n", dirent->opened); + result = smb_proc_read(inode, offset, rsize, buffer); + if (result < 0) + goto io_error; - if ((dirent->opened) == 0) - { - /* tries max. rights */ - int open_result = smb_proc_open(SMB_SERVER(i), - SMB_INOP(i)->dir, - dirent->name, dirent->len, - dirent); - if (open_result) - { - return open_result; - } - } - if (((right == O_RDONLY) && ((dirent->access == O_RDONLY) - || (dirent->access == O_RDWR))) - || ((right == O_WRONLY) && ((dirent->access == O_WRONLY) - || (dirent->access == O_RDWR))) - || ((right == O_RDWR) && (dirent->access == O_RDWR))) - return 0; + refresh = 1; + count -= result; + offset += result; + buffer += result; + if (result < rsize) + break; + } while (count); - return -EACCES; + memset(buffer, 0, count); + set_bit(PG_uptodate, &page->flags); + result = 0; + +io_error: + if (refresh) + smb_refresh_inode(inode); + clear_bit(PG_locked, &page->flags); + wake_up(&page->wait); + return result; } -static long -smb_file_read(struct inode *inode, struct file *file, char *buf, unsigned long count) +int +smb_readpage(struct inode *inode, struct page *page) { - int result, bufsize, to_read, already_read; - off_t pos; - int errno; - - DPRINTK("smb_file_read: enter %s\n", SMB_FINFO(inode)->name); - - if (!inode) - { - DPRINTK("smb_file_read: inode = NULL\n"); - return -EINVAL; - } - if (!S_ISREG(inode->i_mode)) - { - DPRINTK("smb_file_read: read from non-file, mode %07o\n", - inode->i_mode); - return -EINVAL; - } - if ((errno = smb_make_open(inode, O_RDONLY)) != 0) - return errno; + unsigned long address; + int error = -1; - pos = file->f_pos; + pr_debug("SMB: smb_readpage %08lx\n", page_address(page)); + set_bit(PG_locked, &page->flags); + address = page_address(page); + atomic_inc(&page->count); + error = smb_readpage_sync(inode, page); + free_page(address); + return error; +} - if (pos + count > inode->i_size) - { - count = inode->i_size - pos; - } - if (count <= 0) - { - return 0; - } - bufsize = SMB_SERVER(inode)->max_xmit - SMB_HEADER_LEN - 5 * 2 - 5; +/* + * Write a page synchronously. + * Offset is the data offset within the page. + */ +static int +smb_writepage_sync(struct inode *inode, struct page *page, + unsigned long offset, unsigned int count) +{ + int wsize = SMB_SERVER(inode)->opt.max_xmit - (SMB_HEADER_LEN+15); + int result, refresh = 0, written = 0; + u8 *buffer; + + pr_debug("SMB: smb_writepage_sync(%x/%ld %d@%ld)\n", + inode->i_dev, inode->i_ino, + count, page->offset + offset); + + buffer = (u8 *) page_address(page) + offset; + offset += page->offset; + + do { + if (count < wsize) + wsize = count; + + result = smb_proc_write(inode, offset, wsize, buffer); + + if (result < 0) { + /* Must mark the page invalid after I/O error */ + clear_bit(PG_uptodate, &page->flags); + goto io_error; + } + refresh = 1; + buffer += wsize; + offset += wsize; + written += wsize; + count -= wsize; + } while (count); + +io_error: + if (refresh) + smb_refresh_inode(inode); - already_read = 0; + clear_bit(PG_locked, &page->flags); + return written ? written : result; +} - /* First read in as much as possible for each bufsize. */ - while (already_read < count) - { - to_read = min(bufsize, count - already_read); - result = smb_proc_read(SMB_SERVER(inode), SMB_FINFO(inode), - pos, to_read, buf, 1); - if (result < 0) - { - return result; - } - pos += result; - buf += result; - already_read += result; +/* + * Write a page to the server. This will be used for NFS swapping only + * (for now), and we currently do this synchronously only. + */ +static int +smb_writepage(struct inode *inode, struct page *page) +{ + return smb_writepage_sync(inode, page, 0, PAGE_SIZE); +} - if (result < to_read) - { - break; - } - } +static int +smb_updatepage(struct inode *inode, struct page *page, const char *buffer, + unsigned long offset, unsigned int count, int sync) +{ + u8 *page_addr; - file->f_pos = pos; + pr_debug("SMB: smb_updatepage(%x/%ld %d@%ld, sync=%d)\n", + inode->i_dev, inode->i_ino, + count, page->offset+offset, sync); - if (!IS_RDONLY(inode)) - inode->i_atime = CURRENT_TIME; - mark_inode_dirty(inode); - - DPRINTK("smb_file_read: exit %s\n", SMB_FINFO(inode)->name); + page_addr = (u8 *) page_address(page); - return already_read; + copy_from_user(page_addr + offset, buffer, count); + return smb_writepage_sync(inode, page, offset, count); } static long -smb_file_write(struct inode *inode, struct file *file, const char *buf, - unsigned long count) +smb_file_read(struct inode * inode, struct file * file, + char * buf, unsigned long count) { - int result, bufsize, to_write, already_written; - off_t pos; - int errno; - - if (!inode) - { - DPRINTK("smb_file_write: inode = NULL\n"); - return -EINVAL; - } - if (!S_ISREG(inode->i_mode)) - { - DPRINTK("smb_file_write: write to non-file, mode %07o\n", - inode->i_mode); - return -EINVAL; - } - DPRINTK("smb_file_write: enter %s\n", SMB_FINFO(inode)->name); + int status; - if (count <= 0) - { - return 0; - } - if ((errno = smb_make_open(inode, O_RDWR)) != 0) - { - return errno; - } - pos = file->f_pos; + pr_debug("SMB: read(%x/%ld (%d), %lu@%lu)\n", + inode->i_dev, inode->i_ino, inode->i_count, + count, (unsigned long) file->f_pos); + + status = smb_revalidate_inode(inode); + if (status < 0) + return status; - if (file->f_flags & O_APPEND) - pos = inode->i_size; + return generic_file_read(inode, file, buf, count); +} - bufsize = SMB_SERVER(inode)->max_xmit - SMB_HEADER_LEN - 5 * 2 - 5; +static int +smb_file_mmap(struct inode * inode, struct file * file, + struct vm_area_struct * vma) +{ + int status; - already_written = 0; + status = smb_revalidate_inode(inode); + if (status < 0) + return status; - DPRINTK("smb_write_file: blkmode = %d, blkmode & 2 = %d\n", - SMB_SERVER(inode)->blkmode, - SMB_SERVER(inode)->blkmode & 2); + return generic_file_mmap(inode, file, vma); +} - while (already_written < count) - { - to_write = min(bufsize, count - already_written); - result = smb_proc_write(SMB_SERVER(inode), SMB_FINFO(inode), - pos, to_write, buf); +/* + * Write to a file (through the page cache). + */ +static long +smb_file_write(struct inode *inode, struct file *file, + const char *buf, unsigned long count) +{ + int result; - if (result < 0) - { - return result; - } - pos += result; - buf += result; - already_written += result; + pr_debug("SMB: write(%x/%ld (%d), %lu@%lu)\n", + inode->i_dev, inode->i_ino, inode->i_count, + count, (unsigned long) file->f_pos); - if (result < to_write) - { - break; - } + if (!inode) { + printk("smb_file_write: inode = NULL\n"); + return -EINVAL; } - inode->i_mtime = inode->i_ctime = CURRENT_TIME; - mark_inode_dirty(inode); - - file->f_pos = pos; - - if (pos > inode->i_size) - { - inode->i_size = pos; + result = smb_revalidate_inode(inode); + if (result < 0) + return result; + + result = smb_open(inode, O_WRONLY); + if (result < 0) + return result; + + if (!S_ISREG(inode->i_mode)) { + printk("smb_file_write: write to non-file, mode %07o\n", + inode->i_mode); + return -EINVAL; } - DPRINTK("smb_file_write: exit %s\n", SMB_FINFO(inode)->name); + if (count <= 0) + return 0; - return already_written; + return generic_file_write(inode, file, buf, count); } static struct file_operations smb_file_operations = @@ -217,7 +239,7 @@ NULL, /* readdir - bad */ NULL, /* poll - default */ smb_ioctl, /* ioctl */ - smb_mmap, /* mmap */ + smb_file_mmap, /* mmap */ NULL, /* open */ NULL, /* release */ smb_fsync, /* fsync */ @@ -236,8 +258,13 @@ NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ - NULL, /* readpage */ - NULL, /* writepage */ + NULL, /* follow_link */ + smb_readpage, /* readpage */ + smb_writepage, /* writepage */ NULL, /* bmap */ - NULL /* truncate */ + NULL, /* truncate */ + NULL, /* permission */ + NULL, /* smap */ + smb_updatepage, /* updatepage */ + smb_revalidate_inode, /* revalidate */ }; diff -u --recursive --new-file v2.1.51/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c --- v2.1.51/linux/fs/smbfs/inode.c Mon Aug 18 18:19:46 1997 +++ linux/fs/smbfs/inode.c Fri Aug 22 10:04:33 1997 @@ -2,6 +2,7 @@ * inode.c * * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke + * Copyright (C) 1997 by Volker Lendecke * */ @@ -28,329 +29,237 @@ extern int close_fp(struct file *filp); static void smb_put_inode(struct inode *); +static void smb_delete_inode(struct inode *); static void smb_read_inode(struct inode *); static void smb_put_super(struct super_block *); -static void smb_statfs(struct super_block *, struct statfs *, int bufsiz); +static int smb_statfs(struct super_block *, struct statfs *, int); static struct super_operations smb_sops = { smb_read_inode, /* read inode */ - smb_notify_change, /* notify change */ NULL, /* write inode */ smb_put_inode, /* put inode */ + smb_delete_inode, /* delete inode */ + smb_notify_change, /* notify change */ smb_put_super, /* put superblock */ NULL, /* write superblock */ smb_statfs, /* stat filesystem */ - NULL + NULL /* remount filesystem */ }; -/* smb_read_inode: Called from iget, it only traverses the allocated - smb_inode_info's and initializes the inode from the data found - there. It does not allocate or deallocate anything. */ +/* FIXME: Look at all inodes whether so that we do not get duplicate + * inode numbers. */ + +unsigned long +smb_invent_inos(unsigned long n) +{ + static unsigned long ino = 1; + + if (ino + 2*n < ino) + { + /* wrap around */ + ino += n; + } + ino += n; + return ino; +} + +static struct smb_fattr *read_fattr; +static struct semaphore read_semaphore = MUTEX; + +struct inode * +smb_iget(struct super_block *sb, struct smb_fattr *fattr) +{ + struct inode *result; + + pr_debug("smb_iget: %p\n", fattr); + + down(&read_semaphore); + read_fattr = fattr; + result = iget(sb, fattr->f_ino); + up(&read_semaphore); + return result; +} static void smb_read_inode(struct inode *inode) { - /* Our task should be extremely simple here. We only have to - look up the information somebody else (smb_iget) put into - the inode tree. */ - struct smb_server *server = SMB_SERVER(inode); - struct smb_inode_info *inode_info - = smb_find_inode(server, inode->i_ino); + pr_debug("smb_iget: %p\n", read_fattr); - if (inode_info == NULL) + if ((atomic_read(&read_semaphore.count) == 1) || + (inode->i_ino != read_fattr->f_ino)) { - /* Ok, now we're in trouble. The inode info is not - there. What should we do now??? */ - printk("smb_read_inode: inode info not found\n"); + printk("smb_read_inode called from invalid point\n"); return; } - inode_info->state = SMB_INODE_VALID; + inode->i_mode = read_fattr->f_mode; + inode->i_nlink = read_fattr->f_nlink; + inode->i_uid = read_fattr->f_uid; + inode->i_gid = read_fattr->f_gid; + inode->i_rdev = read_fattr->f_rdev; + inode->i_size = read_fattr->f_size; + inode->i_mtime = read_fattr->f_mtime; + inode->i_ctime = read_fattr->f_ctime; + inode->i_atime = read_fattr->f_atime; + inode->i_blksize = read_fattr->f_blksize; + inode->i_blocks = read_fattr->f_blocks; - SMB_INOP(inode) = inode_info; - inode->i_mode = inode_info->finfo.f_mode; - inode->i_nlink = inode_info->finfo.f_nlink; - inode->i_uid = inode_info->finfo.f_uid; - inode->i_gid = inode_info->finfo.f_gid; - inode->i_rdev = inode_info->finfo.f_rdev; - inode->i_size = inode_info->finfo.f_size; - inode->i_mtime = inode_info->finfo.f_mtime; - inode->i_ctime = inode_info->finfo.f_ctime; - inode->i_atime = inode_info->finfo.f_atime; - inode->i_blksize = inode_info->finfo.f_blksize; - inode->i_blocks = inode_info->finfo.f_blocks; + memset(&(inode->u.smbfs_i), 0, sizeof(inode->u.smbfs_i)); if (S_ISREG(inode->i_mode)) - { inode->i_op = &smb_file_inode_operations; - } else if (S_ISDIR(inode->i_mode)) - { + else if (S_ISDIR(inode->i_mode)) inode->i_op = &smb_dir_inode_operations; - } else - { + else inode->i_op = NULL; - } +} + +void +smb_invalidate_inodes(struct smb_sb_info *server) +{ + printk("smb_invalidate_inodes\n"); +} + +int +smb_revalidate_inode(struct inode *i) +{ + pr_debug("smb_revalidate_inode\n"); + return 0; +} + +int +smb_refresh_inode(struct inode *i) +{ + pr_debug("smb_refresh_inode\n"); + return 0; } static void -smb_put_inode(struct inode *inode) +smb_put_inode(struct inode *ino) { - struct smb_dirent *finfo = SMB_FINFO(inode); - struct smb_server *server = SMB_SERVER(inode); - struct smb_inode_info *info = SMB_INOP(inode); + pr_debug("smb_put_inode: count = %d\n", ino->i_count); - if (S_ISDIR(inode->i_mode)) - { - smb_invalid_dir_cache(inode->i_ino); - } - if (finfo->opened != 0) - { - if (smb_proc_close(server, finfo->fileid, inode->i_mtime)) - { - /* We can't do anything but complain. */ - DPRINTK("smb_put_inode: could not close\n"); - } - } - smb_free_inode_info(info); - clear_inode(inode); + if (smb_close(ino)) + printk("smbfs: could not close inode\n"); } static void -smb_put_super(struct super_block *sb) +smb_delete_inode(struct inode *i) { - struct smb_server *server = &(SMB_SBP(sb)->s_server); + pr_debug("smb_delete_inode\n"); +} - smb_proc_disconnect(server); - smb_dont_catch_keepalive(server); - close_fp(server->sock_file); +static void +smb_put_super(struct super_block *sb) +{ + struct smb_sb_info *server = &(sb->u.smbfs_sb); lock_super(sb); - smb_free_all_inodes(server); + if (server->sock_file) { + smb_proc_disconnect(server); + smb_dont_catch_keepalive(server); + close_fp(server->sock_file); + } - smb_vfree(server->packet); - server->packet = NULL; + if (server->conn_pid) + kill_proc(server->conn_pid, SIGTERM, 0); + if (server->packet) + smb_vfree(server->packet); sb->s_dev = 0; - smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info)); unlock_super(sb); MOD_DEC_USE_COUNT; } -struct smb_mount_data_v4 -{ - int version; - unsigned int fd; - uid_t mounted_uid; - struct sockaddr_in addr; - - char server_name[17]; - char client_name[17]; - char service[64]; - char root_path[64]; - - char username[64]; - char password[64]; - - unsigned short max_xmit; - - uid_t uid; - gid_t gid; - mode_t file_mode; - mode_t dir_mode; -}; - -static int -smb_get_mount_data(struct smb_mount_data *target, void *source) -{ - struct smb_mount_data_v4 *v4 = (struct smb_mount_data_v4 *) source; - struct smb_mount_data *cur = (struct smb_mount_data *) source; - - if (source == NULL) - { - return 1; - } - if (cur->version == SMB_MOUNT_VERSION) - { - memcpy(target, cur, sizeof(struct smb_mount_data)); - return 0; - } - if (v4->version == 4) - { - target->version = 5; - target->fd = v4->fd; - target->mounted_uid = v4->mounted_uid; - target->addr = v4->addr; - - memcpy(target->server_name, v4->server_name, 17); - memcpy(target->client_name, v4->client_name, 17); - memcpy(target->service, v4->service, 64); - memcpy(target->root_path, v4->root_path, 64); - memcpy(target->username, v4->username, 64); - memcpy(target->password, v4->password, 64); - - target->max_xmit = v4->max_xmit; - target->uid = v4->uid; - target->gid = v4->gid; - target->file_mode = v4->file_mode; - target->dir_mode = v4->dir_mode; - - memset(target->domain, 0, 64); - strcpy(target->domain, "?"); - return 0; - } - return 1; -} - struct super_block * smb_read_super(struct super_block *sb, void *raw_data, int silent) { - struct smb_mount_data data; - struct smb_server *server; - struct smb_sb_info *smb_sb; - unsigned int fd; - struct file *filp; + struct smb_mount_data *data = (struct smb_mount_data *)raw_data; + struct smb_fattr root; kdev_t dev = sb->s_dev; - int error; + unsigned char *packet; - if (smb_get_mount_data(&data, raw_data) != 0) - { - printk("smb_read_super: wrong data argument\n"); - sb->s_dev = 0; - return NULL; - } - fd = data.fd; - if (fd >= NR_OPEN || !(filp = current->files->fd[fd])) - { - printk("smb_read_super: invalid file descriptor\n"); + MOD_INC_USE_COUNT; + + if (!data) { + printk("smb_read_super: missing data argument\n"); sb->s_dev = 0; + MOD_DEC_USE_COUNT; return NULL; } - if (!S_ISSOCK(filp->f_dentry->d_inode->i_mode)) + + if (data->version != SMB_MOUNT_VERSION) { - printk("smb_read_super: not a socket!\n"); + printk(KERN_ERR "smb_read_super: wrong data argument." + " Recompile smbmount.\n"); sb->s_dev = 0; + MOD_DEC_USE_COUNT; return NULL; } - /* We must malloc our own super-block info */ - smb_sb = (struct smb_sb_info *) smb_kmalloc(sizeof(struct smb_sb_info), - GFP_KERNEL); - if (smb_sb == NULL) + packet = smb_vmalloc(SMB_INITIAL_PACKET_SIZE); + if (!packet) { - printk("smb_read_super: could not alloc smb_sb_info\n"); - return NULL; - } - filp->f_count++; + pr_debug("smb_read_super: could not alloc packet\n"); + sb->s_dev = 0; + MOD_DEC_USE_COUNT; + return NULL; + } lock_super(sb); - SMB_SBP(sb) = smb_sb; - sb->s_blocksize = 1024; /* Eh... Is this correct? */ sb->s_blocksize_bits = 10; sb->s_magic = SMB_SUPER_MAGIC; sb->s_dev = dev; sb->s_op = &smb_sops; - server = &(SMB_SBP(sb)->s_server); - server->sock_file = filp; - server->lock = 0; - server->wait = NULL; - server->packet = NULL; - server->max_xmit = data.max_xmit; - if (server->max_xmit <= 0) - { - server->max_xmit = SMB_DEF_MAX_XMIT; - } - server->tid = 0; - server->pid = current->pid; - server->mid = current->pid + 20; - - server->m = data; - server->m.file_mode = (server->m.file_mode & - (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG; - server->m.dir_mode = (server->m.dir_mode & - (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR; - - smb_init_root(server); + sb->u.smbfs_sb.sock_file = NULL; + sb->u.smbfs_sb.sem = MUTEX; + sb->u.smbfs_sb.conn_pid = 0; + sb->u.smbfs_sb.packet = packet; + sb->u.smbfs_sb.packet_size = SMB_INITIAL_PACKET_SIZE; + sb->u.smbfs_sb.generation = 1; + + sb->u.smbfs_sb.m = *data; + sb->u.smbfs_sb.m.file_mode = (sb->u.smbfs_sb.m.file_mode & + (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG; + sb->u.smbfs_sb.m.dir_mode = (sb->u.smbfs_sb.m.dir_mode & + (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR; - error = smb_proc_connect(server); + smb_init_root_dirent(&(sb->u.smbfs_sb), &root); unlock_super(sb); - if (error < 0) - { - sb->s_dev = 0; - DPRINTK("smb_read_super: Failed connection, bailing out " - "(error = %d).\n", -error); - goto fail; - } - if (server->protocol >= PROTOCOL_LANMAN2) - { - server->case_handling = CASE_DEFAULT; - } else - { - server->case_handling = CASE_LOWER; - } - - if ((error = smb_proc_dskattr(sb, &(SMB_SBP(sb)->s_attr))) < 0) + sb->s_root = d_alloc_root(smb_iget(sb, &root), NULL); + if (!sb->s_root) { sb->s_dev = 0; - printk("smb_read_super: could not get super block " - "attributes\n"); - goto fail; - } - smb_init_root_dirent(server, &(server->root.finfo)); - - if (!(sb->s_root = d_alloc_root(iget(sb, - smb_info_ino(&(server->root))),NULL))) - { - sb->s_dev = 0; - printk("smb_read_super: get root inode failed\n"); - goto fail; + printk(KERN_ERR "smb_read_super: get root inode failed\n"); + smb_vfree(sb->u.smbfs_sb.packet); + MOD_DEC_USE_COUNT; + return NULL; } - MOD_INC_USE_COUNT; return sb; - - fail: - if (server->packet != NULL) - { - smb_vfree(server->packet); - server->packet = NULL; - } - put_filp(filp); - smb_dont_catch_keepalive(server); - smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info)); - return NULL; } -static void +static int smb_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) { - int error; - struct smb_dskattr attr; - struct statfs tmp; + struct statfs attr; - error = smb_proc_dskattr(sb, &attr); + memset(&attr, 0, sizeof(attr)); - if (error) - { - printk("smb_statfs: dskattr error = %d\n", -error); - attr.total = attr.allocblocks = attr.blocksize = - attr.free = 0; - } - tmp.f_type = SMB_SUPER_MAGIC; - tmp.f_bsize = attr.blocksize * attr.allocblocks; - tmp.f_blocks = attr.total; - tmp.f_bfree = attr.free; - tmp.f_bavail = attr.free; - tmp.f_files = -1; - tmp.f_ffree = -1; - tmp.f_namelen = SMB_MAXPATHLEN; - copy_to_user(buf, &tmp, bufsiz); + smb_proc_dskattr(sb, &attr); + + attr.f_type = SMB_SUPER_MAGIC; + attr.f_files = -1; + attr.f_ffree = -1; + attr.f_namelen = SMB_MAXPATHLEN; + return copy_to_user(buf, &attr, bufsiz) ? -EFAULT : 0; } int @@ -375,50 +284,48 @@ if ((attr->ia_valid & ATTR_SIZE) != 0) { - - if ((error = smb_make_open(inode, O_WRONLY)) < 0) + if ((error = smb_open(inode, O_WRONLY)) < 0) goto fail; if ((error = smb_proc_trunc(SMB_SERVER(inode), - SMB_FINFO(inode)->fileid, + inode->u.smbfs_i.fileid, attr->ia_size)) < 0) goto fail; - } if ((attr->ia_valid & (ATTR_CTIME | ATTR_MTIME | ATTR_ATIME)) != 0) { - struct smb_dirent finfo; + struct smb_fattr fattr; - finfo.attr = 0; - finfo.f_size = inode->i_size; - finfo.f_blksize = inode->i_blksize; + fattr.attr = 0; + fattr.f_size = inode->i_size; + fattr.f_blksize = inode->i_blksize; if ((attr->ia_valid & ATTR_CTIME) != 0) - finfo.f_ctime = attr->ia_ctime; + fattr.f_ctime = attr->ia_ctime; else - finfo.f_ctime = inode->i_ctime; + fattr.f_ctime = inode->i_ctime; if ((attr->ia_valid & ATTR_MTIME) != 0) - finfo.f_mtime = attr->ia_mtime; + fattr.f_mtime = attr->ia_mtime; else - finfo.f_mtime = inode->i_mtime; + fattr.f_mtime = inode->i_mtime; if ((attr->ia_valid & ATTR_ATIME) != 0) - finfo.f_atime = attr->ia_atime; + fattr.f_atime = attr->ia_atime; else - finfo.f_atime = inode->i_atime; + fattr.f_atime = inode->i_atime; if ((error = smb_proc_setattr(SMB_SERVER(inode), - inode, &finfo)) >= 0) + inode, &fattr)) >= 0) { - inode->i_ctime = finfo.f_ctime; - inode->i_mtime = finfo.f_mtime; - inode->i_atime = finfo.f_atime; + inode->i_ctime = fattr.f_ctime; + inode->i_mtime = fattr.f_mtime; + inode->i_atime = fattr.f_atime; } } fail: - smb_invalid_dir_cache(smb_info_ino(SMB_INOP(inode)->dir)); +/* smb_invalid_dir_cache(smb_info_ino(SMB_INOP(inode)->dir));*/ return error; } @@ -448,7 +355,7 @@ int init_module(void) { - DPRINTK("smbfs: init_module called\n"); + pr_debug("smbfs: init_module called\n"); #ifdef DEBUG_SMB_MALLOC smb_malloced = 0; @@ -457,6 +364,7 @@ #endif smb_init_dir_cache(); + read_semaphore = MUTEX; return init_smb_fs(); } @@ -464,13 +372,13 @@ void cleanup_module(void) { - DPRINTK("smbfs: cleanup_module called\n"); + pr_debug("smbfs: cleanup_module called\n"); smb_free_dir_cache(); unregister_filesystem(&smb_fs_type); #ifdef DEBUG_SMB_MALLOC - printk("smb_malloced: %d\n", smb_malloced); - printk("smb_current_kmalloced: %d\n", smb_current_kmalloced); - printk("smb_current_vmalloced: %d\n", smb_current_vmalloced); + printk(KERN_DEBUG "smb_malloced: %d\n", smb_malloced); + printk(KERN_DEBUG "smb_current_kmalloced: %d\n",smb_current_kmalloced); + printk(KERN_DEBUG "smb_current_vmalloced: %d\n",smb_current_vmalloced); #endif } diff -u --recursive --new-file v2.1.51/linux/fs/smbfs/ioctl.c linux/fs/smbfs/ioctl.c --- v2.1.51/linux/fs/smbfs/ioctl.c Sun Dec 1 09:02:04 1996 +++ linux/fs/smbfs/ioctl.c Fri Aug 22 10:04:33 1997 @@ -2,6 +2,7 @@ * ioctl.c * * Copyright (C) 1995, 1996 by Volker Lendecke + * Copyright (C) 1997 by Volker Lendecke * */ @@ -21,8 +22,29 @@ switch (cmd) { case SMB_IOC_GETMOUNTUID: - return put_user(SMB_SERVER(inode)->m.mounted_uid, (uid_t *) arg); + return put_user(SMB_SERVER(inode)->m.mounted_uid, + (uid_t *) arg); + case SMB_IOC_NEWCONN: + { + struct smb_conn_opt opt; + int result; + + if (arg == 0) + { + /* The process offers a new connection upon SIGUSR1 */ + return smb_offerconn(SMB_SERVER(inode)); + } + + if ((result = verify_area(VERIFY_READ, (uid_t *) arg, + sizeof(opt))) != 0) + { + return result; + } + copy_from_user(&opt, (void *)arg, sizeof(opt)); + + return smb_newconn(SMB_SERVER(inode), &opt); + } default: return -EINVAL; } diff -u --recursive --new-file v2.1.51/linux/fs/smbfs/mmap.c linux/fs/smbfs/mmap.c --- v2.1.51/linux/fs/smbfs/mmap.c Mon Aug 18 18:19:46 1997 +++ linux/fs/smbfs/mmap.c Wed Dec 31 16:00:00 1969 @@ -1,126 +0,0 @@ -/* - * mmap.c - * - * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/* - * Fill in the supplied page for mmap - */ -static unsigned long -smb_file_mmap_nopage(struct vm_area_struct *area, - unsigned long address, int no_share) -{ - struct inode *inode = area->vm_dentry->d_inode; - unsigned long page; - unsigned int clear; - unsigned long tmp; - int n; - int i; - int pos; - - page = __get_free_page(GFP_KERNEL); - if (!page) - return 0; - address &= PAGE_MASK; - pos = address - area->vm_start + area->vm_offset; - - clear = 0; - if (address + PAGE_SIZE > area->vm_end) - { - clear = address + PAGE_SIZE - area->vm_end; - } - /* what we can read in one go */ - n = SMB_SERVER(inode)->max_xmit - SMB_HEADER_LEN - 5 * 2 - 3 - 10; - - if (smb_make_open(inode, O_RDONLY) < 0) - { - clear = PAGE_SIZE; - } else - { - - for (i = 0; i < (PAGE_SIZE - clear); i += n) - { - int hunk, result; - - hunk = PAGE_SIZE - i; - if (hunk > n) - hunk = n; - - DDPRINTK("smb_file_mmap_nopage: reading\n"); - DDPRINTK("smb_file_mmap_nopage: pos = %d\n", pos); - result = smb_proc_read(SMB_SERVER(inode), - SMB_FINFO(inode), pos, hunk, - (char *) (page + i), 0); - DDPRINTK("smb_file_mmap_nopage: result= %d\n", result); - if (result < 0) - break; - pos += result; - if (result < n) - { - i += result; - break; - } - } - } - - tmp = page + PAGE_SIZE; - while (clear--) - { - *(char *) --tmp = 0; - } - return page; -} - -struct vm_operations_struct smb_file_mmap = -{ - NULL, /* open */ - NULL, /* close */ - NULL, /* unmap */ - NULL, /* protect */ - NULL, /* sync */ - NULL, /* advise */ - smb_file_mmap_nopage, /* nopage */ - NULL, /* wppage */ - NULL, /* swapout */ - NULL, /* swapin */ -}; - - -/* This is used for a general mmap of a smb file */ -int -smb_mmap(struct inode *inode, struct file *file, struct vm_area_struct *vma) -{ - DPRINTK("smb_mmap: called\n"); - - /* only PAGE_COW or read-only supported now */ - if (vma->vm_flags & VM_SHARED) - return -EINVAL; - if (!inode->i_sb || !S_ISREG(inode->i_mode)) - return -EACCES; - if (!IS_RDONLY(inode)) - { - inode->i_atime = CURRENT_TIME; - mark_inode_dirty(inode); - } - - vma->vm_dentry = dget(file->f_dentry); - vma->vm_ops = &smb_file_mmap; - return 0; -} diff -u --recursive --new-file v2.1.51/linux/fs/smbfs/proc.c linux/fs/smbfs/proc.c --- v2.1.51/linux/fs/smbfs/proc.c Mon Dec 30 01:54:12 1996 +++ linux/fs/smbfs/proc.c Fri Aug 22 10:04:33 1997 @@ -2,6 +2,7 @@ * proc.c * * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke + * Copyright (C) 1997 by Volker Lendecke * * 28/06/96 - Fixed long file name support (smb_proc_readdir_long) by Yuri Per */ @@ -20,15 +21,15 @@ #include #define SMB_VWV(packet) ((packet) + SMB_HEADER_LEN) -#define SMB_CMD(packet) (BVAL(packet,8)) -#define SMB_WCT(packet) (BVAL(packet, SMB_HEADER_LEN - 1)) +#define SMB_CMD(packet) (*(packet+8)) +#define SMB_WCT(packet) (*(packet+SMB_HEADER_LEN - 1)) #define SMB_BCC(packet) smb_bcc(packet) #define SMB_BUF(packet) ((packet) + SMB_HEADER_LEN + SMB_WCT(packet) * 2 + 2) #define SMB_DIRINFO_SIZE 43 #define SMB_STATUS_SIZE 21 -static int smb_request_ok(struct smb_server *s, int command, int wct, int bcc); +static int smb_request_ok(struct smb_sb_info *s, int command, int wct, int bcc); static inline int min(int a, int b) @@ -64,132 +65,57 @@ /* */ /*****************************************************************************/ -static inline byte * -smb_decode_word(byte * p, word * data) -{ - *data = WVAL(p, 0); - return p + 2; -} - -byte * -smb_encode_smb_length(byte * p, dword len) +__u8 * +smb_encode_smb_length(__u8 * p, __u32 len) { - BSET(p, 0, 0); - BSET(p, 1, 0); - BSET(p, 2, (len & 0xFF00) >> 8); - BSET(p, 3, (len & 0xFF)); + *p = 0; + *(p+1) = 0; + *(p+2) = (len & 0xFF00) >> 8; + *(p+3) = (len & 0xFF); if (len > 0xFFFF) { - BSET(p, 1, 1); + *(p+1) = 1; } return p + 4; } -static byte * -smb_encode_ascii(byte * p, const byte * name, int len) +static int smb_d_path(struct dentry * entry, char * buf) { - *p++ = 4; - strcpy(p, name); - return p + len + 1; -} - -static byte * -smb_encode_this_name(byte * p, const char *name, const int len) -{ - *p++ = '\\'; - strncpy(p, name, len); - return p + len; -} + if (IS_ROOT(entry)) { + *buf = '\\'; + return 1; + } else { + int len = smb_d_path(entry->d_parent, buf); -/* I put smb_encode_parents into a separate function so that the - recursion only takes 16 bytes on the stack per path component on a - 386. */ - -static byte * -smb_encode_parents(byte * p, struct smb_inode_info *ino) -{ - byte *q; - - if (ino->dir == NULL) - { - return p; - } - q = smb_encode_parents(p, ino->dir); - if (q - p + 1 + ino->finfo.len > SMB_MAXPATHLEN) - { - return p; + buf += len; + if (len > 1) { + *buf++ = '\\'; + len++; + } + memcpy(buf, entry->d_name.name, entry->d_name.len); + return len + entry->d_name.len; } - return smb_encode_this_name(q, ino->finfo.name, ino->finfo.len); } -static byte * -smb_encode_path(struct smb_server *server, - byte * p, struct smb_inode_info *dir, - const char *name, const int len) +static char *smb_encode_path(struct smb_sb_info *server, char *buf, + struct inode *dir, struct qstr *name) { - byte *start = p; - if (dir != NULL) - { - p = smb_encode_parents(p, dir); - } - p = smb_encode_this_name(p, name, len); - *p++ = 0; - if (server->protocol <= PROTOCOL_COREPLUS) - { - str_upper(start); - } - return p; -} + char *start = buf; -static byte * -smb_decode_data(byte * p, byte * data, word * data_len, int fs) -{ - word len; + if (dir != NULL) + buf += smb_d_path(i_dentry(dir), buf); - if (!(*p == 1 || *p == 5)) - { - printk("smb_decode_data: Warning! Data block not starting " - "with 1 or 5\n"); + if (name != NULL) { + *buf++ = '\\'; + memcpy(buf, name->name, name->len); + buf += name->len; + *buf++ = 0; } - len = WVAL(p, 1); - p += 3; - - if (fs) - copy_to_user(data, p, len); - else - memcpy(data, p, len); - - *data_len = len; - - return p + len; -} - -static byte * -smb_name_mangle(byte * p, const byte * name) -{ - int len, pad = 0; - - len = strlen(name); - - if (len < 16) - pad = 16 - len; - *p++ = 2 * (len + pad); - - while (*name) - { - *p++ = (*name >> 4) + 'A'; - *p++ = (*name & 0x0F) + 'A'; - name++; - } - while (pad--) - { - *p++ = 'C'; - *p++ = 'A'; - } - *p++ = '\0'; + if (server->opt.protocol <= SMB_PROTOCOL_COREPLUS) + str_upper(start); - return p; + return buf; } /* The following are taken directly from msdos-fs */ @@ -235,7 +161,7 @@ /* Convert linear UNIX date to a MS-DOS time/date pair. */ static void -date_unix2dos(int unix_date, byte * date, byte * time) +date_unix2dos(int unix_date, __u8 * date, __u8 * time) { int day, year, nl_day, month; @@ -271,16 +197,16 @@ /* */ /*****************************************************************************/ -dword -smb_len(byte * p) +__u32 +smb_len(__u8 * p) { - return ((BVAL(p, 1) & 0x1) << 16L) | (BVAL(p, 2) << 8L) | (BVAL(p, 3)); + return ((*(p+1) & 0x1) << 16L) | (*(p+2) << 8L) | *(p+3); } -static word -smb_bcc(byte * packet) +static __u16 +smb_bcc(__u8 * packet) { - int pos = SMB_HEADER_LEN + SMB_WCT(packet) * sizeof(word); + int pos = SMB_HEADER_LEN + SMB_WCT(packet) * sizeof(__u16); return WVAL(packet, pos); } @@ -288,10 +214,8 @@ requirements of a smb packet */ static int -smb_valid_packet(byte * packet) +smb_valid_packet(__u8 * packet) { - DDPRINTK("len: %d, wct: %d, bcc: %d\n", - smb_len(packet), SMB_WCT(packet), SMB_BCC(packet)); return (packet[4] == 0xff && packet[5] == 'S' && packet[6] == 'M' @@ -304,7 +228,7 @@ got enough data. If bcc == -1, we don't care. */ static int -smb_verify(byte * packet, int command, int wct, int bcc) +smb_verify(__u8 * packet, int command, int wct, int bcc) { return (SMB_CMD(packet) == command && SMB_WCT(packet) >= wct && @@ -404,23 +328,16 @@ return 0; } -static void -smb_lock_server(struct smb_server *server) +static inline void +smb_lock_server(struct smb_sb_info *server) { - while (server->lock) - sleep_on(&server->wait); - server->lock = 1; + down(&(server->sem)); } -static void -smb_unlock_server(struct smb_server *server) +static inline void +smb_unlock_server(struct smb_sb_info *server) { - if (server->lock != 1) - { - printk("smb_unlock_server: was not locked!\n"); - } - server->lock = 0; - wake_up(&server->wait); + up(&(server->sem)); } /* smb_request_ok: We expect the server to be locked. Then we do the @@ -429,7 +346,7 @@ the answer is <=0, the returned number is a valid unix errno. */ static int -smb_request_ok(struct smb_server *s, int command, int wct, int bcc) +smb_request_ok(struct smb_sb_info *s, int command, int wct, int bcc) { int result = 0; s->rcls = 0; @@ -437,18 +354,18 @@ if (smb_request(s) < 0) { - DPRINTK("smb_request failed\n"); + pr_debug("smb_request failed\n"); result = -EIO; } else if (smb_valid_packet(s->packet) != 0) { - DPRINTK("not a valid packet!\n"); + pr_debug("not a valid packet!\n"); result = -EIO; } else if (s->rcls != 0) { result = -smb_errno(s->rcls, s->err); } else if (smb_verify(s->packet, command, wct, bcc) != 0) { - DPRINTK("smb_verify failed\n"); + pr_debug("smb_verify failed\n"); result = -EIO; } return result; @@ -461,69 +378,111 @@ of any use. */ static int -smb_retry(struct smb_server *server) +smb_retry(struct smb_sb_info *server) { if (server->state != CONN_INVALID) { return 0; } - if (smb_release(server) < 0) + if (server->sock_file != NULL) { - DPRINTK("smb_retry: smb_release failed\n"); - server->state = CONN_RETRIED; - return 0; + close_fp(server->sock_file); + server->sock_file = NULL; } - if (smb_proc_reconnect(server) < 0) + + if (server->conn_pid == 0) { - DPRINTK("smb_proc_reconnect failed\n"); server->state = CONN_RETRIED; return 0; } - server->state = CONN_VALID; - return 1; + + kill_proc(server->conn_pid, SIGUSR1, 0); + server->conn_pid = 0; + + smb_lock_server(server); + + if (server->sock_file != NULL) + { + server->state = CONN_VALID; + return 1; + } + return 0; } -static int -smb_request_ok_unlock(struct smb_server *s, int command, int wct, int bcc) +int +smb_offerconn(struct smb_sb_info *server) { - int result = smb_request_ok(s, command, wct, bcc); + if (!suser() && (current->uid != server->m.mounted_uid)) + { + return -EACCES; + } + server->conn_pid = current->pid; + return 0; +} - smb_unlock_server(s); +int +smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt) +{ + struct file *filp; - return result; + if (opt->fd >= NR_OPEN || !(filp = current->files->fd[opt->fd])) + { + return -EBADF; + } + if (!S_ISSOCK(filp->f_dentry->d_inode->i_mode)) + { + return -EBADF; + } + if (!suser() && (current->uid != server->m.mounted_uid)) + { + return -EACCES; + } + if (server->sock_file != NULL) + { + close_fp(server->sock_file); + server->sock_file = NULL; + } + filp->f_count += 1; + server->sock_file = filp; + smb_catch_keepalive(server); + server->opt = *opt; + pr_debug("smb_newconn: protocol = %d\n", server->opt.protocol); + server->conn_pid = 0; + server->generation += 1; + smb_unlock_server(server); + return 0; } /* smb_setup_header: We completely set up the packet. You only have to insert the command-specific fields */ __u8 * -smb_setup_header(struct smb_server * server, byte command, word wct, word bcc) +smb_setup_header(struct smb_sb_info * server, __u8 command, __u16 wct, __u16 bcc) { - dword xmit_len = SMB_HEADER_LEN + wct * sizeof(word) + bcc + 2; - byte *p = server->packet; - byte *buf = server->packet; + __u32 xmit_len = SMB_HEADER_LEN + wct * sizeof(__u16) + bcc + 2; + __u8 *p = server->packet; + __u8 *buf = server->packet; p = smb_encode_smb_length(p, xmit_len - 4); - BSET(p, 0, 0xff); - BSET(p, 1, 'S'); - BSET(p, 2, 'M'); - BSET(p, 3, 'B'); - BSET(p, 4, command); + *p++ = 0xff; + *p++ = 'S'; + *p++ = 'M'; + *p++ = 'B'; + *p++ = command; - p += 5; memset(p, '\0', 19); p += 19; p += 8; - WSET(buf, smb_tid, server->tid); - WSET(buf, smb_pid, server->pid); - WSET(buf, smb_uid, server->server_uid); - WSET(buf, smb_mid, server->mid); + WSET(buf, smb_tid, server->opt.tid); + WSET(buf, smb_pid, 1); + WSET(buf, smb_uid, server->opt.server_uid); + WSET(buf, smb_mid, 1); - if (server->protocol > PROTOCOL_CORE) + if (server->opt.protocol > SMB_PROTOCOL_CORE) { - BSET(buf, smb_flg, 0x8); + *(buf+smb_flg) = 0x8; WSET(buf, smb_flg2, 0x3); } *p++ = wct; /* wct */ @@ -532,20 +491,8 @@ return p + 2; } -/* smb_setup_header_exclusive waits on server->lock and locks the - server, when it's free. You have to unlock it manually when you're - finished with server->packet! */ - -static byte * -smb_setup_header_exclusive(struct smb_server *server, - byte command, word wct, word bcc) -{ - smb_lock_server(server); - return smb_setup_header(server, command, wct, bcc); -} - static void -smb_setup_bcc(struct smb_server *server, byte * p) +smb_setup_bcc(struct smb_sb_info *server, __u8 * p) { __u8 *packet = server->packet; __u8 *pbcc = packet + SMB_HEADER_LEN + 2 * SMB_WCT(packet); @@ -557,101 +504,118 @@ } -/*****************************************************************************/ -/* */ -/* File operation section. */ -/* */ -/*****************************************************************************/ +/* + * We're called with the server locked, and we leave it that way. We + * try maximum permissions. + */ -int -smb_proc_open(struct smb_server *server, - struct smb_inode_info *dir, const char *name, int len, - struct smb_dirent *entry) +static int +smb_proc_open(struct inode *ino) { + struct smb_sb_info *server = SMB_SERVER(ino); int error; char *p; - char *buf; - const word o_attr = aSYSTEM | aHIDDEN | aDIR; - - DPRINTK("smb_proc_open: name=%s\n", name); - - smb_lock_server(server); - if (entry->opened != 0) - { - /* Somebody else opened the file while we slept */ - smb_unlock_server(server); - return 0; - } retry: - buf = server->packet; p = smb_setup_header(server, SMBopen, 2, 0); - WSET(buf, smb_vwv0, 0x42); /* read/write */ - WSET(buf, smb_vwv1, o_attr); + WSET(server->packet, smb_vwv0, 0x42); /* read/write */ + WSET(server->packet, smb_vwv1, aSYSTEM | aHIDDEN | aDIR); *p++ = 4; - p = smb_encode_path(server, p, dir, name, len); + p = smb_encode_path(server, p, ino, NULL); smb_setup_bcc(server, p); if ((error = smb_request_ok(server, SMBopen, 7, 0)) != 0) { - if (smb_retry(server)) - { goto retry; - } + if ((error != -EACCES) && (error != -ETXTBSY) && (error != -EROFS)) - { - smb_unlock_server(server); return error; - } + p = smb_setup_header(server, SMBopen, 2, 0); - WSET(buf, smb_vwv0, 0x40); /* read only */ - WSET(buf, smb_vwv1, o_attr); + WSET(server->packet, smb_vwv0, 0x40); /* read only */ + WSET(server->packet, smb_vwv1, aSYSTEM | aHIDDEN | aDIR); *p++ = 4; - p = smb_encode_path(server, p, dir, name, len); + p = smb_encode_path(server, p, ino, NULL); smb_setup_bcc(server, p); if ((error = smb_request_ok(server, SMBopen, 7, 0)) != 0) { if (smb_retry(server)) - { goto retry; - } - smb_unlock_server(server); + return error; } } /* We should now have data in vwv[0..6]. */ - entry->fileid = WVAL(buf, smb_vwv0); - entry->attr = WVAL(buf, smb_vwv1); - entry->f_ctime = entry->f_atime = - entry->f_mtime = local2utc(DVAL(buf, smb_vwv2)); - entry->f_size = DVAL(buf, smb_vwv4); - entry->access = WVAL(buf, smb_vwv6); - - entry->opened = 1; - entry->access &= 3; + ino->u.smbfs_i.fileid = WVAL(server->packet, smb_vwv0); + ino->u.smbfs_i.attr = WVAL(server->packet, smb_vwv1); + ino->u.smbfs_i.access = WVAL(server->packet, smb_vwv6); + ino->u.smbfs_i.access &= 3; - smb_unlock_server(server); + ino->u.smbfs_i.open = server->generation; - DPRINTK("smb_proc_open: entry->access = %d\n", entry->access); + pr_debug("smb_proc_open: entry->access = %d\n", ino->u.smbfs_i.access); return 0; } int -smb_proc_close(struct smb_server *server, - __u16 fileid, __u32 mtime) +smb_open(struct inode *i, int wish) { - char *buf; + struct smb_sb_info *server = SMB_SERVER(i); + int result = -EACCES; - smb_setup_header_exclusive(server, SMBclose, 3, 0); - buf = server->packet; - WSET(buf, smb_vwv0, fileid); - DSET(buf, smb_vwv1, utc2local(mtime)); + smb_lock_server(server); + + if (!smb_is_open(i)) { + int error = smb_proc_open(i); + if (error) { + smb_unlock_server(server); + return error; + } + } + + if (((wish == O_RDONLY) && ((i->u.smbfs_i.access == O_RDONLY) + || (i->u.smbfs_i.access == O_RDWR))) + || ((wish == O_WRONLY) && ((i->u.smbfs_i.access == O_WRONLY) + || (i->u.smbfs_i.access == O_RDWR))) + || ((wish == O_RDWR) && (i->u.smbfs_i.access == O_RDWR))) + result = 0; - return smb_request_ok_unlock(server, SMBclose, 0, 0); + smb_unlock_server(server); + return result; +} + +/* We're called with the server locked */ + +static int smb_proc_close(struct smb_sb_info *server, + __u16 fileid, __u32 mtime) +{ + smb_setup_header(server, SMBclose, 3, 0); + WSET(server->packet, smb_vwv0, fileid); + DSET(server->packet, smb_vwv1, mtime); + return smb_request_ok(server, SMBclose, 0, 0); +} + + +int smb_close(struct inode *ino) +{ + struct smb_sb_info *server = SMB_SERVER(ino); + int result; + + smb_lock_server(server); + + if (!smb_is_open(ino)) { + smb_unlock_server(server); + return 0; + } + + result = smb_proc_close(server, ino->u.smbfs_i.fileid, ino->i_mtime); + ino->u.smbfs_i.open = 0; + smb_unlock_server(server); + return result; } /* In smb_proc_read and smb_proc_write we do not retry, because the @@ -661,17 +625,18 @@ copy_to_user. */ int -smb_proc_read(struct smb_server *server, struct smb_dirent *finfo, - off_t offset, long count, char *data, int fs) +smb_proc_read(struct inode *ino, off_t offset, long count, char *data) { - word returned_count, data_len; + struct smb_sb_info *server = SMB_SERVER(ino); + __u16 returned_count, data_len; char *buf; int error; - smb_setup_header_exclusive(server, SMBread, 5, 0); + smb_lock_server(server); + smb_setup_header(server, SMBread, 5, 0); buf = server->packet; - WSET(buf, smb_vwv0, finfo->fileid); + WSET(buf, smb_vwv0, ino->u.smbfs_i.fileid); WSET(buf, smb_vwv1, count); DSET(buf, smb_vwv2, offset); WSET(buf, smb_vwv4, 0); @@ -683,56 +648,56 @@ } returned_count = WVAL(buf, smb_vwv0); - smb_decode_data(SMB_BUF(server->packet), data, &data_len, fs); + buf = SMB_BUF(server->packet); + data_len = WVAL(buf, 1); + + memcpy(data, buf+3, data_len); smb_unlock_server(server); if (returned_count != data_len) { - printk("smb_proc_read: Warning, returned_count != data_len\n"); - printk("smb_proc_read: ret_c=%d, data_len=%d\n", + printk(KERN_NOTICE "smb_proc_read: returned != data_len\n"); + printk(KERN_NOTICE "smb_proc_read: ret_c=%d, data_len=%d\n", returned_count, data_len); } return data_len; } int -smb_proc_write(struct smb_server *server, struct smb_dirent *finfo, - off_t offset, int count, const char *data) +smb_proc_write(struct inode *ino, off_t offset, int count, const char *data) { + struct smb_sb_info *server = SMB_SERVER(ino); int res = 0; - char *buf; - byte *p; + __u8 *p; - p = smb_setup_header_exclusive(server, SMBwrite, 5, count + 3); - buf = server->packet; - WSET(buf, smb_vwv0, finfo->fileid); - WSET(buf, smb_vwv1, count); - DSET(buf, smb_vwv2, offset); - WSET(buf, smb_vwv4, 0); + smb_lock_server(server); + p = smb_setup_header(server, SMBwrite, 5, count + 3); + WSET(server->packet, smb_vwv0, ino->u.smbfs_i.fileid); + WSET(server->packet, smb_vwv1, count); + DSET(server->packet, smb_vwv2, offset); + WSET(server->packet, smb_vwv4, 0); *p++ = 1; WSET(p, 0, count); - copy_from_user(p + 2, data, count); + memcpy(p+2, data, count); if ((res = smb_request_ok(server, SMBwrite, 1, 0)) >= 0) - { - res = WVAL(buf, smb_vwv0); - } + res = WVAL(server->packet, smb_vwv0); + smb_unlock_server(server); return res; } int -smb_proc_create(struct inode *dir, const char *name, int len, - word attr, time_t ctime) +smb_proc_create(struct inode *dir, struct qstr *name, + __u16 attr, time_t ctime) { int error; char *p; - struct smb_server *server = SMB_SERVER(dir); + struct smb_sb_info *server = SMB_SERVER(dir); char *buf; - __u16 fileid; smb_lock_server(server); retry: @@ -741,7 +706,7 @@ WSET(buf, smb_vwv0, attr); DSET(buf, smb_vwv1, utc2local(ctime)); *p++ = 4; - p = smb_encode_path(server, p, SMB_INOP(dir), name, len); + p = smb_encode_path(server, p, dir, name); smb_setup_bcc(server, p); if ((error = smb_request_ok(server, SMBcreate, 1, 0)) < 0) @@ -753,20 +718,18 @@ smb_unlock_server(server); return error; } - fileid = WVAL(buf, smb_vwv0); + smb_proc_close(server, WVAL(buf, smb_vwv0), CURRENT_TIME); smb_unlock_server(server); - smb_proc_close(server, fileid, CURRENT_TIME); - return 0; } int -smb_proc_mv(struct inode *odir, const char *oname, const int olen, - struct inode *ndir, const char *nname, const int nlen) +smb_proc_mv(struct inode *odir, struct qstr *oname, + struct inode *ndir, struct qstr *nname) { char *p; - struct smb_server *server = SMB_SERVER(odir); + struct smb_sb_info *server = SMB_SERVER(odir); int result; smb_lock_server(server); @@ -775,9 +738,9 @@ p = smb_setup_header(server, SMBmv, 1, 0); WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN); *p++ = 4; - p = smb_encode_path(server, p, SMB_INOP(odir), oname, olen); + p = smb_encode_path(server, p, odir, oname); *p++ = 4; - p = smb_encode_path(server, p, SMB_INOP(ndir), nname, nlen); + p = smb_encode_path(server, p, ndir, nname); smb_setup_bcc(server, p); if ((result = smb_request_ok(server, SMBmv, 0, 0)) < 0) @@ -792,18 +755,18 @@ } int -smb_proc_mkdir(struct inode *dir, const char *name, const int len) +smb_proc_mkdir(struct inode *dir, struct qstr *name) { char *p; int result; - struct smb_server *server = SMB_SERVER(dir); + struct smb_sb_info *server = SMB_SERVER(dir); smb_lock_server(server); retry: p = smb_setup_header(server, SMBmkdir, 0, 0); *p++ = 4; - p = smb_encode_path(server, p, SMB_INOP(dir), name, len); + p = smb_encode_path(server, p, dir, name); smb_setup_bcc(server, p); if ((result = smb_request_ok(server, SMBmkdir, 0, 0)) < 0) @@ -818,18 +781,18 @@ } int -smb_proc_rmdir(struct inode *dir, const char *name, const int len) +smb_proc_rmdir(struct inode *dir, struct qstr *name) { char *p; int result; - struct smb_server *server = SMB_SERVER(dir); + struct smb_sb_info *server = SMB_SERVER(dir); smb_lock_server(server); retry: p = smb_setup_header(server, SMBrmdir, 0, 0); *p++ = 4; - p = smb_encode_path(server, p, SMB_INOP(dir), name, len); + p = smb_encode_path(server, p, dir, name); smb_setup_bcc(server, p); if ((result = smb_request_ok(server, SMBrmdir, 0, 0)) < 0) @@ -844,10 +807,10 @@ } int -smb_proc_unlink(struct inode *dir, const char *name, const int len) +smb_proc_unlink(struct inode *dir, struct qstr *name) { char *p; - struct smb_server *server = SMB_SERVER(dir); + struct smb_sb_info *server = SMB_SERVER(dir); int result; smb_lock_server(server); @@ -856,7 +819,7 @@ p = smb_setup_header(server, SMBunlink, 1, 0); WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN); *p++ = 4; - p = smb_encode_path(server, p, SMB_INOP(dir), name, len); + p = smb_encode_path(server, p, dir, name); smb_setup_bcc(server, p); if ((result = smb_request_ok(server, SMBunlink, 0, 0)) < 0) @@ -871,7 +834,7 @@ } int -smb_proc_trunc(struct smb_server *server, word fid, dword length) +smb_proc_trunc(struct smb_sb_info *server, __u16 fid, __u32 length) { char *p; char *buf; @@ -886,7 +849,8 @@ WSET(buf, smb_vwv1, 0); DSET(buf, smb_vwv2, length); WSET(buf, smb_vwv4, 0); - p = smb_encode_ascii(p, "", 0); + *p++ = 4; + *p++ = 0; smb_setup_bcc(server, p); if ((result = smb_request_ok(server, SMBwrite, 1, 0)) < 0) @@ -901,59 +865,60 @@ } static void -smb_init_dirent(struct smb_server *server, struct smb_dirent *entry) +smb_init_dirent(struct smb_sb_info *server, struct smb_fattr *fattr) { - memset(entry, 0, sizeof(struct smb_dirent)); + memset(fattr, 0, sizeof(*fattr)); - entry->f_nlink = 1; - entry->f_uid = server->m.uid; - entry->f_gid = server->m.gid; - entry->f_blksize = 512; + fattr->f_nlink = 1; + fattr->f_uid = server->m.uid; + fattr->f_gid = server->m.gid; + fattr->f_blksize = 512; } static void -smb_finish_dirent(struct smb_server *server, struct smb_dirent *entry) +smb_finish_dirent(struct smb_sb_info *server, struct smb_fattr *fattr) { - if ((entry->attr & aDIR) != 0) + if (fattr->attr & aDIR) { - entry->f_mode = server->m.dir_mode; - entry->f_size = 512; + fattr->f_mode = server->m.dir_mode; + fattr->f_size = 512; } else { - entry->f_mode = server->m.file_mode; + fattr->f_mode = server->m.file_mode; } - if ((entry->f_blksize != 0) && (entry->f_size != 0)) + if ((fattr->f_blksize != 0) && (fattr->f_size != 0)) { - entry->f_blocks = - (entry->f_size - 1) / entry->f_blksize + 1; + fattr->f_blocks = + (fattr->f_size - 1) / fattr->f_blksize + 1; } else { - entry->f_blocks = 0; + fattr->f_blocks = 0; } return; } void -smb_init_root_dirent(struct smb_server *server, struct smb_dirent *entry) +smb_init_root_dirent(struct smb_sb_info *server, struct smb_fattr *fattr) { - smb_init_dirent(server, entry); - entry->attr = aDIR; - entry->f_ino = 1; - smb_finish_dirent(server, entry); + smb_init_dirent(server, fattr); + fattr->attr = aDIR; + fattr->f_ino = 1; + smb_finish_dirent(server, fattr); } -static char * -smb_decode_dirent(struct smb_server *server, char *p, struct smb_dirent *entry) +static __u8 * +smb_decode_dirent(struct smb_sb_info *server, __u8 *p, + struct smb_dirent *entry) { - smb_init_dirent(server, entry); + smb_init_dirent(server, &(entry->attr)); p += SMB_STATUS_SIZE; /* reserved (search_status) */ - entry->attr = BVAL(p, 0); - entry->f_mtime = entry->f_atime = entry->f_ctime = + entry->attr.attr = *p; + entry->attr.f_mtime = entry->attr.f_atime = entry->attr.f_ctime = date_dos2unix(WVAL(p, 1), WVAL(p, 3)); - entry->f_size = DVAL(p, 5); + entry->attr.f_size = DVAL(p, 5); entry->len = strlen(p + 9); if (entry->len > 12) { @@ -970,28 +935,28 @@ entry->name[entry->len] = '\0'; } } - switch (server->case_handling) + switch (server->opt.case_handling) { - case CASE_UPPER: + case SMB_CASE_UPPER: str_upper(entry->name); break; - case CASE_LOWER: + case SMB_CASE_LOWER: str_lower(entry->name); break; default: break; } - DPRINTK("smb_decode_dirent: name = %s\n", entry->name); - smb_finish_dirent(server, entry); + pr_debug("smb_decode_dirent: name = %s\n", entry->name); + smb_finish_dirent(server, &(entry->attr)); return p + 22; } /* This routine is used to read in directory entries from the network. Note that it is for short directory name seeks, i.e.: protocol < - PROTOCOL_LANMAN2 */ + SMB_PROTOCOL_LANMAN2 */ static int -smb_proc_readdir_short(struct smb_server *server, struct inode *dir, int fpos, +smb_proc_readdir_short(struct smb_sb_info *server, struct inode *dir, int fpos, int cache_size, struct smb_dirent *entry) { char *p; @@ -1001,12 +966,14 @@ int i; int first, total_count; struct smb_dirent *current_entry; - word bcc; - word count; + __u16 bcc; + __u16 count; char status[SMB_STATUS_SIZE]; - int entries_asked = (server->max_xmit - 100) / SMB_DIRINFO_SIZE; + int entries_asked = (server->opt.max_xmit - 100) / SMB_DIRINFO_SIZE; + + static struct qstr mask = { "*.*", 3, 0 }; - DPRINTK("SMB call readdir %d @ %d\n", cache_size, fpos); + pr_debug("SMB call readdir %d @ %d\n", cache_size, fpos); smb_lock_server(server); @@ -1024,7 +991,7 @@ WSET(buf, smb_vwv0, entries_asked); WSET(buf, smb_vwv1, aDIR); *p++ = 4; - p = smb_encode_path(server, p, SMB_INOP(dir), "*.*", 3); + p = smb_encode_path(server, p, dir, &mask); *p++ = 5; WSET(p, 0, 0); p += 2; @@ -1033,7 +1000,8 @@ p = smb_setup_header(server, SMBsearch, 2, 0); WSET(buf, smb_vwv0, entries_asked); WSET(buf, smb_vwv1, aDIR); - p = smb_encode_ascii(p, "", 0); + *p++ = 4; + *p++ = 0; *p++ = 5; WSET(p, 0, SMB_STATUS_SIZE); p += 2; @@ -1061,8 +1029,8 @@ } } p = SMB_VWV(server->packet); - p = smb_decode_word(p, &count); - p = smb_decode_word(p, &bcc); + count = WVAL(p, 0); + bcc = WVAL(p, 2); first = 0; @@ -1076,8 +1044,7 @@ result = -EIO; goto unlock_return; } - p += 3; /* Skipping VBLOCK header - (5, length lo, length hi). */ + p += 7; /* Read the last entry into the status field. */ memcpy(status, @@ -1092,8 +1059,8 @@ if (total_count < fpos) { p += SMB_DIRINFO_SIZE; - DDPRINTK("smb_proc_readdir: skipped entry.\n"); - DDPRINTK(" total_count = %d\n" + pr_debug("smb_proc_readdir: skipped entry.\n"); + pr_debug(" total_count = %d\n" " i = %d, fpos = %d\n", total_count, i, fpos); } else if (total_count >= fpos + cache_size) @@ -1105,8 +1072,8 @@ p = smb_decode_dirent(server, p, current_entry); current_entry->f_pos = total_count; - DDPRINTK("smb_proc_readdir: entry->f_pos = " - "%lu\n", entry->f_pos); + pr_debug("smb_proc_readdir: entry->f_pos = " + "%u\n", entry->f_pos); current_entry += 1; } total_count += 1; @@ -1123,52 +1090,52 @@ is used by OS/2. */ static char * -smb_decode_long_dirent(struct smb_server *server, char *p, +smb_decode_long_dirent(struct smb_sb_info *server, char *p, struct smb_dirent *entry, int level) { char *result; - smb_init_dirent(server, entry); + smb_init_dirent(server, &(entry->attr)); switch (level) { /* We might add more levels later... */ case 1: - entry->len = BVAL(p, 26); + entry->len = *(p+26); strncpy(entry->name, p + 27, entry->len); entry->name[entry->len] = '\0'; - entry->f_size = DVAL(p, 16); - entry->attr = BVAL(p, 24); + entry->attr.f_size = DVAL(p, 16); + entry->attr.attr = *(p+24); - entry->f_ctime = date_dos2unix(WVAL(p, 6), WVAL(p, 4)); - entry->f_atime = date_dos2unix(WVAL(p, 10), WVAL(p, 8)); - entry->f_mtime = date_dos2unix(WVAL(p, 14), WVAL(p, 12)); - result = p + 28 + BVAL(p, 26); + entry->attr.f_ctime = date_dos2unix(WVAL(p, 6), WVAL(p, 4)); + entry->attr.f_atime = date_dos2unix(WVAL(p, 10), WVAL(p, 8)); + entry->attr.f_mtime = date_dos2unix(WVAL(p, 14), WVAL(p, 12)); + result = p + 28 + *(p+26); break; default: - DPRINTK("Unknown long filename format %d\n", level); + pr_debug("Unknown long filename format %d\n", level); result = p + WVAL(p, 0); } - switch (server->case_handling) + switch (server->opt.case_handling) { - case CASE_UPPER: + case SMB_CASE_UPPER: str_upper(entry->name); break; - case CASE_LOWER: + case SMB_CASE_LOWER: str_lower(entry->name); break; default: break; } - smb_finish_dirent(server, entry); + smb_finish_dirent(server, &(entry->attr)); return result; } -int -smb_proc_readdir_long(struct smb_server *server, struct inode *dir, int fpos, +static int +smb_proc_readdir_long(struct smb_sb_info *server, struct inode *dir, int fpos, int cache_size, struct smb_dirent *cache) { /* NT uses 260, OS/2 uses 2. Both accept 1. */ @@ -1199,16 +1166,17 @@ char param[SMB_MAXPATHLEN + 2 + 12]; int mask_len; - unsigned char *mask = &(param[12]); + char *mask = &(param[12]); + + static struct qstr star = { "*", 1, 0 }; - mask_len = smb_encode_path(server, mask, - SMB_INOP(dir), "*", 1) - mask; + mask_len = smb_encode_path(server, mask, dir, &star) - mask; mask[mask_len] = 0; mask[mask_len + 1] = 0; - DPRINTK("smb_readdir_long cache=%d, fpos=%d, mask=%s\n", - cache_size, fpos, mask); + pr_debug("smb_readdir_long cache=%d, fpos=%d, mask=%s\n", + cache_size, fpos, mask); smb_lock_server(server); @@ -1223,7 +1191,7 @@ loop_count += 1; if (loop_count > 200) { - printk("smb_proc_readdir_long: " + printk(KERN_WARNING "smb_proc_readdir_long: " "Looping in FIND_NEXT??\n"); break; } @@ -1240,8 +1208,9 @@ } else { command = TRANSACT2_FINDNEXT; - DPRINTK("hand=0x%X resume=%d ff_lastname=%d mask=%s\n", - ff_dir_handle, ff_resume_key, ff_lastname, mask); + pr_debug("hand=0x%X resume=%d ff_lastnm=%d mask=%s\n", + ff_dir_handle, ff_resume_key, ff_lastname, + mask); WSET(param, 0, ff_dir_handle); WSET(param, 2, max_matches); /* max count */ WSET(param, 4, info_level); @@ -1270,8 +1239,8 @@ { goto retry; } - DPRINTK("smb_proc_readdir_long: " - "got error from trans2_request\n"); + pr_debug("smb_proc_readdir_long: " + "got error from trans2_request\n"); break; } if (server->rcls != 0) @@ -1314,7 +1283,7 @@ break; case 1: lastname = p + ff_lastname + 1; - lastname_len = BVAL(p, ff_lastname); + lastname_len = *(p+ff_lastname); ff_resume_key = 0; break; } @@ -1332,7 +1301,7 @@ p = smb_decode_long_dirent(server, p, entry, info_level); - DDPRINTK("smb_readdir_long: got %s\n", entry->name); + pr_debug("smb_readdir_long: got %s\n", entry->name); if ((entry->name[0] == '.') && ((entry->name[1] == '\0') @@ -1354,8 +1323,8 @@ entries_seen += 1; } - DPRINTK("received %d entries (eos=%d resume=%d)\n", - ff_searchcount, ff_eos, ff_resume_key); + pr_debug("received %d entries (eos=%d resume=%d)\n", + ff_searchcount, ff_eos, ff_resume_key); first = 0; } @@ -1366,10 +1335,12 @@ } int -smb_proc_readdir(struct smb_server *server, struct inode *dir, int fpos, +smb_proc_readdir(struct inode *dir, int fpos, int cache_size, struct smb_dirent *entry) { - if (server->protocol >= PROTOCOL_LANMAN2) + struct smb_sb_info *server = SMB_SERVER(dir); + + if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2) return smb_proc_readdir_long(server, dir, fpos, cache_size, entry); else @@ -1378,23 +1349,21 @@ } static int -smb_proc_getattr_core(struct inode *dir, const char *name, int len, - struct smb_dirent *entry) +smb_proc_getattr_core(struct inode *dir, struct qstr *name, + struct smb_fattr *attr) { int result; char *p; - struct smb_server *server = SMB_SERVER(dir); + struct smb_sb_info *server = SMB_SERVER(dir); char *buf; smb_lock_server(server); - DDPRINTK("smb_proc_getattr: %s\n", name); - retry: buf = server->packet; p = smb_setup_header(server, SMBgetatr, 0, 0); *p++ = 4; - p = smb_encode_path(server, p, SMB_INOP(dir), name, len); + p = smb_encode_path(server, p, dir, name); smb_setup_bcc(server, p); if ((result = smb_request_ok(server, SMBgetatr, 10, 0)) < 0) @@ -1406,20 +1375,20 @@ smb_unlock_server(server); return result; } - entry->attr = WVAL(buf, smb_vwv0); - entry->f_ctime = entry->f_atime = - entry->f_mtime = local2utc(DVAL(buf, smb_vwv1)); + attr->attr = WVAL(buf, smb_vwv0); + attr->f_ctime = attr->f_atime = + attr->f_mtime = local2utc(DVAL(buf, smb_vwv1)); - entry->f_size = DVAL(buf, smb_vwv3); + attr->f_size = DVAL(buf, smb_vwv3); smb_unlock_server(server); return 0; } static int -smb_proc_getattr_trans2(struct inode *dir, const char *name, int len, - struct smb_dirent *entry) +smb_proc_getattr_trans2(struct inode *dir, struct qstr *name, + struct smb_fattr *attr) { - struct smb_server *server = SMB_SERVER(dir); + struct smb_sb_info *server = SMB_SERVER(dir); char param[SMB_MAXPATHLEN + 20]; char *p; int result; @@ -1431,7 +1400,7 @@ WSET(param, 0, 1); /* Info level SMB_INFO_STANDARD */ DSET(param, 2, 0); - p = smb_encode_path(server, param + 6, SMB_INOP(dir), name, len); + p = smb_encode_path(server, param + 6, dir, name); smb_lock_server(server); retry: @@ -1459,41 +1428,34 @@ smb_unlock_server(server); return -ENOENT; } - entry->f_ctime = date_dos2unix(WVAL(resp_data, 2), - WVAL(resp_data, 0)); - entry->f_atime = date_dos2unix(WVAL(resp_data, 6), - WVAL(resp_data, 4)); - entry->f_mtime = date_dos2unix(WVAL(resp_data, 10), - WVAL(resp_data, 8)); - entry->f_size = DVAL(resp_data, 12); - entry->attr = WVAL(resp_data, 20); + attr->f_ctime = date_dos2unix(WVAL(resp_data, 2), + WVAL(resp_data, 0)); + attr->f_atime = date_dos2unix(WVAL(resp_data, 6), + WVAL(resp_data, 4)); + attr->f_mtime = date_dos2unix(WVAL(resp_data, 10), + WVAL(resp_data, 8)); + attr->f_size = DVAL(resp_data, 12); + attr->attr = WVAL(resp_data, 20); smb_unlock_server(server); return 0; } -int -smb_proc_getattr(struct inode *dir, const char *name, int len, - struct smb_dirent *entry) +int smb_proc_getattr(struct inode *dir, struct qstr *name, + struct smb_fattr *fattr) { - struct smb_server *server = SMB_SERVER(dir); + struct smb_sb_info *server = SMB_SERVER(dir); int result = 0; - smb_init_dirent(server, entry); + smb_init_dirent(server, fattr); - if (server->protocol >= PROTOCOL_LANMAN2) - { - result = smb_proc_getattr_trans2(dir, name, len, entry); - } - if ((server->protocol < PROTOCOL_LANMAN2) || (result < 0)) - { - result = smb_proc_getattr_core(dir, name, len, entry); - } - smb_finish_dirent(server, entry); + if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2) + result = smb_proc_getattr_trans2(dir, name, fattr); - entry->len = len; - memcpy(entry->name, name, len); - /* entry->name is null terminated from smb_init_dirent */ + if ((server->opt.protocol < SMB_PROTOCOL_LANMAN2) || (result < 0)) + result = smb_proc_getattr_core(dir, name, fattr); + + smb_finish_dirent(server, fattr); return result; } @@ -1502,8 +1464,8 @@ /* In core protocol, there is only 1 time to be set, we use entry->f_mtime, to make touch work. */ static int -smb_proc_setattr_core(struct smb_server *server, - struct inode *i, struct smb_dirent *new_finfo) +smb_proc_setattr_core(struct smb_sb_info *server, + struct inode *i, struct smb_fattr *fattr) { char *p; char *buf; @@ -1514,29 +1476,25 @@ retry: buf = server->packet; p = smb_setup_header(server, SMBsetatr, 8, 0); - WSET(buf, smb_vwv0, new_finfo->attr); - DSET(buf, smb_vwv1, utc2local(new_finfo->f_mtime)); + WSET(buf, smb_vwv0, fattr->attr); + DSET(buf, smb_vwv1, utc2local(fattr->f_mtime)); + *p++ = 4; + p = smb_encode_path(server, p, i, NULL); *p++ = 4; - p = smb_encode_path(server, p, - SMB_INOP(i)->dir, SMB_INOP(i)->finfo.name, - SMB_INOP(i)->finfo.len); - p = smb_encode_ascii(p, "", 0); + *p++ = 0; smb_setup_bcc(server, p); if ((result = smb_request_ok(server, SMBsetatr, 0, 0)) < 0) - { if (smb_retry(server)) - { goto retry; - } - } + smb_unlock_server(server); return result; } static int -smb_proc_setattr_trans2(struct smb_server *server, - struct inode *i, struct smb_dirent *new_finfo) +smb_proc_setattr_trans2(struct smb_sb_info *server, + struct inode *i, struct smb_fattr *fattr) { char param[SMB_MAXPATHLEN + 20]; char data[26]; @@ -1550,16 +1508,14 @@ WSET(param, 0, 1); /* Info level SMB_INFO_STANDARD */ DSET(param, 2, 0); - p = smb_encode_path(server, param + 6, - SMB_INOP(i)->dir, SMB_INOP(i)->finfo.name, - SMB_INOP(i)->finfo.len); - - date_unix2dos(new_finfo->f_ctime, &(data[0]), &(data[2])); - date_unix2dos(new_finfo->f_atime, &(data[4]), &(data[6])); - date_unix2dos(new_finfo->f_mtime, &(data[8]), &(data[10])); - DSET(data, 12, new_finfo->f_size); - DSET(data, 16, new_finfo->f_blksize); - WSET(data, 20, new_finfo->attr); + p = smb_encode_path(server, param + 6, i, NULL); + + date_unix2dos(fattr->f_ctime, &(data[0]), &(data[2])); + date_unix2dos(fattr->f_atime, &(data[4]), &(data[6])); + date_unix2dos(fattr->f_mtime, &(data[8]), &(data[10])); + DSET(data, 12, fattr->f_size); + DSET(data, 16, fattr->f_blksize); + WSET(data, 20, fattr->attr); WSET(data, 22, 0); smb_lock_server(server); @@ -1575,39 +1531,34 @@ return -smb_errno(server->rcls, server->err); } if (result < 0) - { if (smb_retry(server)) - { goto retry; - } - } + smb_unlock_server(server); return 0; } int -smb_proc_setattr(struct smb_server *server, struct inode *inode, - struct smb_dirent *new_finfo) +smb_proc_setattr(struct smb_sb_info *server, struct inode *inode, + struct smb_fattr *fattr) { int result; - if (server->protocol >= PROTOCOL_LANMAN2) - { - result = smb_proc_setattr_trans2(server, inode, new_finfo); - } - if ((server->protocol < PROTOCOL_LANMAN2) || (result < 0)) - { - result = smb_proc_setattr_core(server, inode, new_finfo); - } + if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2) + result = smb_proc_setattr_trans2(server, inode, fattr); + + if ((server->opt.protocol < SMB_PROTOCOL_LANMAN2) || (result < 0)) + result = smb_proc_setattr_core(server, inode, fattr); + return result; } int -smb_proc_dskattr(struct super_block *super, struct smb_dskattr *attr) +smb_proc_dskattr(struct super_block *sb, struct statfs *attr) { int error; char *p; - struct smb_server *server = &(SMB_SBP(super)->s_server); + struct smb_sb_info *server = &(sb->u.smbfs_sb); smb_lock_server(server); @@ -1617,351 +1568,26 @@ if ((error = smb_request_ok(server, SMBdskattr, 5, 0)) < 0) { if (smb_retry(server)) - { goto retry; - } + smb_unlock_server(server); return error; } p = SMB_VWV(server->packet); - p = smb_decode_word(p, &attr->total); - p = smb_decode_word(p, &attr->allocblocks); - p = smb_decode_word(p, &attr->blocksize); - p = smb_decode_word(p, &attr->free); + attr->f_bsize = WVAL(p, 2) * WVAL(p, 4); + attr->f_blocks = WVAL(p, 0); + attr->f_bavail = attr->f_bfree = WVAL(p, 6); smb_unlock_server(server); return 0; } -/*****************************************************************************/ -/* */ -/* Mount/umount operations. */ -/* */ -/*****************************************************************************/ - -struct smb_prots -{ - enum smb_protocol prot; - const char *name; -}; - -/* smb_proc_reconnect: We expect the server to be locked, so that you - can call the routine from within smb_retry. The socket must be - created, like after a user-level socket()-call. It may not be - connected. */ - -int -smb_proc_reconnect(struct smb_server *server) -{ - struct smb_prots prots[] = - { - {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"}, - {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"}, -#ifdef LANMAN1 - {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"}, - {PROTOCOL_LANMAN1, "LANMAN1.0"}, -#endif -#ifdef LANMAN2 - {PROTOCOL_LANMAN2, "LM1.2X002"}, -#endif -#ifdef NT1 - {PROTOCOL_NT1, "NT LM 0.12"}, - {PROTOCOL_NT1, "NT LANMAN 1.0"}, -#endif - {-1, NULL}}; - char dev[] = "A:"; - int i, plength; - int max_xmit = 1024; /* Space needed for first request. */ - int given_max_xmit = server->m.max_xmit; - int result; - byte *p; - - if ((result = smb_connect(server)) < 0) - { - DPRINTK("smb_proc_reconnect: could not smb_connect\n"); - goto fail; - } - /* Here we assume that the connection is valid */ - server->state = CONN_VALID; - - if (server->packet != NULL) - { - smb_vfree(server->packet); - server->packet_size = 0; - } - server->packet = smb_vmalloc(max_xmit); - - if (server->packet == NULL) - { - printk("smb_proc_connect: No memory! Bailing out.\n"); - result = -ENOMEM; - goto fail; - } - server->packet_size = server->max_xmit = max_xmit; - - /* - * Start with an RFC1002 session request packet. - */ - p = server->packet + 4; - - p = smb_name_mangle(p, server->m.server_name); - p = smb_name_mangle(p, server->m.client_name); - - smb_encode_smb_length(server->packet, - (void *) p - (void *) (server->packet)); - - server->packet[0] = 0x81; /* SESSION REQUEST */ - - if (smb_catch_keepalive(server) < 0) - { - printk("smb_proc_connect: could not catch_keepalives\n"); - } - if ((result = smb_request(server)) < 0) - { - DPRINTK("smb_proc_connect: Failed to send SESSION REQUEST.\n"); - smb_dont_catch_keepalive(server); - goto fail; - } - if (server->packet[0] != 0x82) - { - printk("smb_proc_connect: Did not receive positive response " - "(err = %x)\n", - server->packet[0]); - smb_dont_catch_keepalive(server); - result = -EIO; - goto fail; - } - DPRINTK("smb_proc_connect: Passed SESSION REQUEST.\n"); - - /* Now we are ready to send a SMB Negotiate Protocol packet. */ - memset(server->packet, 0, SMB_HEADER_LEN); - - plength = 0; - for (i = 0; prots[i].name != NULL; i++) - { - plength += strlen(prots[i].name) + 2; - } - - smb_setup_header(server, SMBnegprot, 0, plength); - - p = SMB_BUF(server->packet); - - for (i = 0; prots[i].name != NULL; i++) - { - *p++ = 2; - strcpy(p, prots[i].name); - p += strlen(prots[i].name) + 1; - } - - if ((result = smb_request_ok(server, SMBnegprot, 1, -1)) < 0) - { - DPRINTK("smb_proc_connect: Failure requesting SMBnegprot\n"); - smb_dont_catch_keepalive(server); - goto fail; - } else - { - DDPRINTK("smb_proc_connect: Request SMBnegprot.."); - } - - DDPRINTK("Verified!\n"); - - p = SMB_VWV(server->packet); - p = smb_decode_word(p, (word *) & i); - server->protocol = prots[i].prot; - - DPRINTK("smb_proc_connect: Server wants %s protocol.\n", - prots[i].name); - - if (server->protocol >= PROTOCOL_LANMAN1) - { - - word passlen = strlen(server->m.password); - word userlen = strlen(server->m.username); - - DPRINTK("smb_proc_connect: password = %s\n", - server->m.password); - DPRINTK("smb_proc_connect: usernam = %s\n", - server->m.username); - DPRINTK("smb_proc_connect: blkmode = %d\n", - WVAL(server->packet, smb_vwv5)); - - if (server->protocol >= PROTOCOL_NT1) - { - server->max_xmit = DVAL(server->packet, smb_vwv3 + 1); - server->maxmux = WVAL(server->packet, smb_vwv1 + 1); - server->maxvcs = WVAL(server->packet, smb_vwv2 + 1); - server->blkmode = DVAL(server->packet, smb_vwv9 + 1); - server->sesskey = DVAL(server->packet, smb_vwv7 + 1); - } else - { - server->max_xmit = WVAL(server->packet, smb_vwv2); - server->maxmux = WVAL(server->packet, smb_vwv3); - server->maxvcs = WVAL(server->packet, smb_vwv4); - server->blkmode = WVAL(server->packet, smb_vwv5); - server->sesskey = DVAL(server->packet, smb_vwv6); - } - - if (server->max_xmit < given_max_xmit) - { - /* We do not distinguish between the client - requests and the server response. */ - given_max_xmit = server->max_xmit; - } - if (server->protocol >= PROTOCOL_NT1) - { - char *workgroup = server->m.domain; - char *OS_id = "Unix"; - char *client_id = "ksmbfs"; - - smb_setup_header(server, SMBsesssetupX, 13, - 5 + userlen + passlen + - strlen(workgroup) + strlen(OS_id) + - strlen(client_id)); - - WSET(server->packet, smb_vwv0, 0x00ff); - WSET(server->packet, smb_vwv1, 0); - WSET(server->packet, smb_vwv2, given_max_xmit); - WSET(server->packet, smb_vwv3, 2); - WSET(server->packet, smb_vwv4, server->pid); - DSET(server->packet, smb_vwv5, server->sesskey); - WSET(server->packet, smb_vwv7, passlen + 1); - WSET(server->packet, smb_vwv8, 0); - WSET(server->packet, smb_vwv9, 0); - - p = SMB_BUF(server->packet); - strcpy(p, server->m.password); - p += passlen + 1; - strcpy(p, server->m.username); - p += userlen + 1; - strcpy(p, workgroup); - p += strlen(p) + 1; - strcpy(p, OS_id); - p += strlen(p) + 1; - strcpy(p, client_id); - } else - { - smb_setup_header(server, SMBsesssetupX, 10, - 2 + userlen + passlen); - - WSET(server->packet, smb_vwv0, 0x00ff); - WSET(server->packet, smb_vwv1, 0); - WSET(server->packet, smb_vwv2, given_max_xmit); - WSET(server->packet, smb_vwv3, 2); - WSET(server->packet, smb_vwv4, server->pid); - DSET(server->packet, smb_vwv5, server->sesskey); - WSET(server->packet, smb_vwv7, passlen + 1); - WSET(server->packet, smb_vwv8, 0); - WSET(server->packet, smb_vwv9, 0); - - p = SMB_BUF(server->packet); - strcpy(p, server->m.password); - p += passlen + 1; - strcpy(p, server->m.username); - } - - if ((result = smb_request_ok(server, SMBsesssetupX, 3, 0)) < 0) - { - DPRINTK("smb_proc_connect: SMBsessetupX failed\n"); - smb_dont_catch_keepalive(server); - goto fail; - } - smb_decode_word(server->packet + 32, &(server->server_uid)); - } else - { - server->max_xmit = 0; - server->maxmux = 0; - server->maxvcs = 0; - server->blkmode = 0; - server->sesskey = 0; - } - - /* Fine! We have a connection, send a tcon message. */ - - smb_setup_header(server, SMBtcon, 0, - 6 + strlen(server->m.service) + - strlen(server->m.password) + strlen(dev)); - - p = SMB_BUF(server->packet); - p = smb_encode_ascii(p, server->m.service, strlen(server->m.service)); - p = smb_encode_ascii(p, server->m.password, strlen(server->m.password)); - p = smb_encode_ascii(p, dev, strlen(dev)); - - if ((result = smb_request_ok(server, SMBtcon, 2, 0)) < 0) - { - DPRINTK("smb_proc_connect: SMBtcon not verified.\n"); - smb_dont_catch_keepalive(server); - goto fail; - } - DDPRINTK("OK! Managed to set up SMBtcon!\n"); - - p = SMB_VWV(server->packet); - - if (server->protocol <= PROTOCOL_COREPLUS) - { - word max_xmit; - - p = smb_decode_word(p, &max_xmit); - server->max_xmit = max_xmit; - - if (server->max_xmit > given_max_xmit) - { - server->max_xmit = given_max_xmit; - } - } else - { - p += 2; - } - - p = smb_decode_word(p, &server->tid); - - /* Ok, everything is fine. max_xmit does not include */ - /* the TCP-SMB header of 4 bytes. */ - server->max_xmit += 4; - - DPRINTK("max_xmit = %d, tid = %d\n", server->max_xmit, server->tid); - - /* Now make a new packet with the correct size. */ - smb_vfree(server->packet); - - server->packet = smb_vmalloc(server->max_xmit); - if (server->packet == NULL) - { - printk("smb_proc_connect: No memory left in end of " - "connection phase :-(\n"); - smb_dont_catch_keepalive(server); - goto fail; - } - server->packet_size = server->max_xmit; - - DPRINTK("smb_proc_connect: Normal exit\n"); - return 0; - - fail: - server->state = CONN_INVALID; - return result; -} - -/* smb_proc_reconnect: server->packet is allocated with - server->max_xmit bytes if and only if we return >= 0 */ int -smb_proc_connect(struct smb_server *server) +smb_proc_disconnect(struct smb_sb_info *server) { int result; smb_lock_server(server); - - result = smb_proc_reconnect(server); - - if ((result < 0) && (server->packet != NULL)) - { - smb_vfree(server->packet); - server->packet = NULL; - } + smb_setup_header(server, SMBtdis, 0, 0); + result = smb_request_ok(server, SMBtdis, 0, 0); smb_unlock_server(server); return result; -} - -int -smb_proc_disconnect(struct smb_server *server) -{ - smb_setup_header_exclusive(server, SMBtdis, 0, 0); - return smb_request_ok_unlock(server, SMBtdis, 0, 0); } diff -u --recursive --new-file v2.1.51/linux/fs/smbfs/sock.c linux/fs/smbfs/sock.c --- v2.1.51/linux/fs/smbfs/sock.c Mon Aug 18 18:19:46 1997 +++ linux/fs/smbfs/sock.c Fri Aug 22 10:04:33 1997 @@ -2,6 +2,7 @@ * sock.c * * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke + * Copyright (C) 1997 by Volker Lendecke * */ @@ -99,8 +100,7 @@ result = _recvfrom(sock, (void *) peek_buf, 4, MSG_DONTWAIT); - DDPRINTK("smb_data_callback:" - " got SESSION KEEP ALIVE\n"); + pr_debug("smb_data_callback: got SESSION KEEPALIVE\n"); if (result == -EAGAIN) { @@ -119,7 +119,7 @@ } int -smb_catch_keepalive(struct smb_server *server) +smb_catch_keepalive(struct smb_sb_info *server) { struct file *file; struct inode *inode; @@ -131,7 +131,7 @@ || ((inode = file->f_dentry->d_inode) == NULL) || (!S_ISSOCK(inode->i_mode))) { - printk("smb_catch_keepalive: did not get valid server!\n"); + pr_debug("smb_catch_keepalive: did not get valid server!\n"); server->data_ready = NULL; return -EINVAL; } @@ -139,7 +139,7 @@ if (sock->type != SOCK_STREAM) { - printk("smb_catch_keepalive: did not get SOCK_STREAM\n"); + pr_debug("smb_catch_keepalive: did not get SOCK_STREAM\n"); server->data_ready = NULL; return -EINVAL; } @@ -147,17 +147,17 @@ if (sk == NULL) { - printk("smb_catch_keepalive: sk == NULL"); + pr_debug("smb_catch_keepalive: sk == NULL"); server->data_ready = NULL; return -EINVAL; } - DDPRINTK("smb_catch_keepalive.: sk->d_r = %x, server->d_r = %x\n", + pr_debug("smb_catch_keepalive.: sk->d_r = %x, server->d_r = %x\n", (unsigned int) (sk->data_ready), (unsigned int) (server->data_ready)); if (sk->data_ready == smb_data_callback) { - printk("smb_catch_keepalive: already done\n"); + printk(KERN_ERR "smb_catch_keepalive: already done\n"); return -EINVAL; } server->data_ready = sk->data_ready; @@ -166,7 +166,7 @@ } int -smb_dont_catch_keepalive(struct smb_server *server) +smb_dont_catch_keepalive(struct smb_sb_info *server) { struct file *file; struct inode *inode; @@ -208,7 +208,7 @@ "sk->data_callback != smb_data_callback\n"); return -EINVAL; } - DDPRINTK("smb_dont_catch_keepalive: sk->d_r = %x, server->d_r = %x\n", + pr_debug("smb_dont_catch_keepalive: sk->d_r = %x, server->d_r = %x\n", (unsigned int) (sk->data_ready), (unsigned int) (server->data_ready)); @@ -235,8 +235,8 @@ } if (result < 0) { - DPRINTK("smb_send_raw: sendto error = %d\n", - -result); + pr_debug("smb_send_raw: sendto error = %d\n", + -result); return result; } already_sent += result; @@ -262,8 +262,8 @@ } if (result < 0) { - DPRINTK("smb_receive_raw: recvfrom error = %d\n", - -result); + pr_debug("smb_receive_raw: recvfrom error = %d\n", + -result); return result; } already_read += result; @@ -286,7 +286,7 @@ if (result < 0) { - DPRINTK("smb_get_length: recv error = %d\n", -result); + pr_debug("smb_get_length: recv error = %d\n", -result); return result; } switch (peek_buf[0]) @@ -296,11 +296,11 @@ break; case 0x85: - DPRINTK("smb_get_length: Got SESSION KEEP ALIVE\n"); + pr_debug("smb_get_length: Got SESSION KEEP ALIVE\n"); goto re_recv; default: - printk("smb_get_length: Invalid NBT packet\n"); + pr_debug("smb_get_length: Invalid NBT packet\n"); return -EIO; } @@ -313,7 +313,7 @@ } static struct socket * -server_sock(struct smb_server *server) +server_sock(struct smb_sb_info *server) { struct file *file; struct inode *inode; @@ -332,7 +332,7 @@ * fs points to the correct segment */ static int -smb_receive(struct smb_server *server) +smb_receive(struct smb_sb_info *server) { struct socket *sock = server_sock(server); int len; @@ -349,7 +349,7 @@ { /* Some servers do not care about our max_xmit. They send larger packets */ - DPRINTK("smb_receive: Increase packet size from %d to %d\n", + pr_debug("smb_receive: Increase packet size from %d to %d\n", server->packet_size, len + 4); smb_vfree(server->packet); server->packet_size = 0; @@ -365,22 +365,22 @@ if (result < 0) { - printk("smb_receive: receive error: %d\n", result); + pr_debug("smb_receive: receive error: %d\n", result); return result; } - server->rcls = BVAL(server->packet, 9); + server->rcls = *(server->packet+9); server->err = WVAL(server->packet, 11); if (server->rcls != 0) { - DPRINTK("smb_receive: rcls=%d, err=%d\n", - server->rcls, server->err); + pr_debug("smb_receive: rcls=%d, err=%d\n", + server->rcls, server->err); } return result; } static int -smb_receive_trans2(struct smb_server *server, +smb_receive_trans2(struct smb_sb_info *server, int *ldata, unsigned char **data, int *lparam, unsigned char **param) { @@ -405,12 +405,12 @@ total_data = WVAL(server->packet, smb_tdrcnt); total_param = WVAL(server->packet, smb_tprcnt); - DDPRINTK("smb_receive_trans2: td=%d,tp=%d\n", total_data, total_param); + pr_debug("smb_receive_trans2: td=%d,tp=%d\n", total_data, total_param); if ((total_data > TRANS2_MAX_TRANSFER) || (total_param > TRANS2_MAX_TRANSFER)) { - DPRINTK("smb_receive_trans2: data/param too long\n"); + pr_debug("smb_receive_trans2: data/param too long\n"); return -EIO; } buf_len = total_data + total_param; @@ -420,7 +420,7 @@ } if ((rcv_buf = smb_vmalloc(buf_len)) == NULL) { - DPRINTK("smb_receive_trans2: could not alloc data area\n"); + pr_debug("smb_receive_trans2: could not alloc data area\n"); return -ENOMEM; } *param = rcv_buf; @@ -433,7 +433,7 @@ if (WVAL(inbuf, smb_prdisp) + WVAL(inbuf, smb_prcnt) > total_param) { - DPRINTK("smb_receive_trans2: invalid parameters\n"); + pr_debug("smb_receive_trans2: invalid parameters\n"); result = -EIO; goto fail; } @@ -445,14 +445,11 @@ if (WVAL(inbuf, smb_drdisp) + WVAL(inbuf, smb_drcnt) > total_data) { - DPRINTK("smb_receive_trans2: invalid data block\n"); + pr_debug("smb_receive_trans2: invalid data block\n"); result = -EIO; goto fail; } - DDPRINTK("target: %X\n", *data + WVAL(inbuf, smb_drdisp)); - DDPRINTK("source: %X\n", - smb_base(inbuf) + WVAL(inbuf, smb_droff)); - DDPRINTK("disp: %d, off: %d, cnt: %d\n", + pr_debug("disp: %d, off: %d, cnt: %d\n", WVAL(inbuf, smb_drdisp), WVAL(inbuf, smb_droff), WVAL(inbuf, smb_drcnt)); @@ -464,7 +461,7 @@ if ((WVAL(inbuf, smb_tdrcnt) > total_data) || (WVAL(inbuf, smb_tprcnt) > total_param)) { - printk("smb_receive_trans2: data/params grew!\n"); + pr_debug("smb_receive_trans2: data/params grew!\n"); result = -EIO; goto fail; } @@ -499,50 +496,8 @@ return result; } -extern struct net_proto_family inet_family_ops; - -int -smb_release(struct smb_server *server) -{ - struct socket *sock = server_sock(server); - int result; - - if (sock == NULL) - { - return -EINVAL; - } - result = sock->ops->release(sock, NULL); - DPRINTK("smb_release: sock->ops->release = %d\n", result); - - /* inet_release does not set sock->state. Maybe someone is - confused about sock->state being SS_CONNECTED while there - is nothing behind it, so I set it to SS_UNCONNECTED. */ - sock->state = SS_UNCONNECTED; - - result = inet_family_ops.create(sock, 0); - DPRINTK("smb_release: inet_create = %d\n", result); - return result; -} - -int -smb_connect(struct smb_server *server) -{ - struct socket *sock = server_sock(server); - if (sock == NULL) - { - return -EINVAL; - } - if (sock->state != SS_UNCONNECTED) - { - DPRINTK("smb_connect: socket is not unconnected: %d\n", - sock->state); - } - return sock->ops->connect(sock, (struct sockaddr *) &(server->m.addr), - sizeof(struct sockaddr_in), 0); -} - int -smb_request(struct smb_server *server) +smb_request(struct smb_sb_info *server) { unsigned long old_mask; unsigned short fs; @@ -552,7 +507,7 @@ if (buffer == NULL) { - printk("smb_request: Bad server!\n"); + pr_debug("smb_request: Bad server!\n"); return -EBADF; } if (server->state != CONN_VALID) @@ -562,12 +517,12 @@ if ((result = smb_dont_catch_keepalive(server)) != 0) { server->state = CONN_INVALID; - smb_invalidate_all_inodes(server); + smb_invalidate_inodes(server); return result; } len = smb_len(buffer) + 4; - DDPRINTK("smb_request: len = %d cmd = 0x%X\n", len, buffer[8]); + pr_debug("smb_request: len = %d cmd = 0x%X\n", len, buffer[8]); old_mask = current->blocked; current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP)); @@ -595,16 +550,16 @@ if (result < 0) { server->state = CONN_INVALID; - smb_invalidate_all_inodes(server); + smb_invalidate_inodes(server); } - DDPRINTK("smb_request: result = %d\n", result); + pr_debug("smb_request: result = %d\n", result); return result; } #define ROUND_UP(x) (((x)+3) & ~3) static int -smb_send_trans2(struct smb_server *server, __u16 trans2_command, +smb_send_trans2(struct smb_sb_info *server, __u16 trans2_command, int ldata, unsigned char *data, int lparam, unsigned char *param) { @@ -632,7 +587,7 @@ struct iovec iov[4]; struct msghdr msg; - if ((bcc + oparam) > server->max_xmit) + if ((bcc + oparam) > server->opt.max_xmit) { return -ENOMEM; } @@ -687,7 +642,7 @@ * one packet to send. */ int -smb_trans2_request(struct smb_server *server, __u16 trans2_command, +smb_trans2_request(struct smb_sb_info *server, __u16 trans2_command, int ldata, unsigned char *data, int lparam, unsigned char *param, int *lrdata, unsigned char **rdata, @@ -697,7 +652,7 @@ unsigned short fs; int result; - DDPRINTK("smb_trans2_request: com=%d, ld=%d, lp=%d\n", + pr_debug("smb_trans2_request: com=%d, ld=%d, lp=%d\n", trans2_command, ldata, lparam); if (server->state != CONN_VALID) @@ -707,7 +662,7 @@ if ((result = smb_dont_catch_keepalive(server)) != 0) { server->state = CONN_INVALID; - smb_invalidate_all_inodes(server); + smb_invalidate_inodes(server); return result; } old_mask = current->blocked; @@ -738,9 +693,9 @@ if (result < 0) { server->state = CONN_INVALID; - smb_invalidate_all_inodes(server); + smb_invalidate_inodes(server); } - DDPRINTK("smb_trans2_request: result = %d\n", result); + pr_debug("smb_trans2_request: result = %d\n", result); return result; } diff -u --recursive --new-file v2.1.51/linux/fs/super.c linux/fs/super.c --- v2.1.51/linux/fs/super.c Mon Aug 18 18:19:46 1997 +++ linux/fs/super.c Tue Aug 19 12:39:41 1997 @@ -553,7 +553,7 @@ static int d_umount(struct super_block * sb) { struct dentry * root = sb->s_root; - struct dentry * covers = root->d_covers; + struct dentry * covered = root->d_covers; if (root->d_count != 1) return -EBUSY; @@ -563,22 +563,23 @@ sb->s_root = NULL; - covers->d_mounts = covers; - root->d_covers = root; - - dput(covers); + if (covered != root) { + root->d_covers = root; + covered->d_mounts = covered; + dput(covered); + } dput(root); return 0; } -static void d_mount(struct dentry *covers, struct dentry *dentry) +static void d_mount(struct dentry *covered, struct dentry *dentry) { - if (covers->d_mounts != covers) { + if (covered->d_mounts != covered) { printk("VFS: mount - already mounted\n"); return; } - covers->d_mounts = dentry; - dentry->d_covers = covers; + covered->d_mounts = dentry; + dentry->d_covers = covered; } static int do_umount(kdev_t dev,int unmount_root) diff -u --recursive --new-file v2.1.51/linux/include/linux/dcache.h linux/include/linux/dcache.h --- v2.1.51/linux/include/linux/dcache.h Mon Aug 18 18:19:47 1997 +++ linux/include/linux/dcache.h Sat Aug 23 16:47:12 1997 @@ -46,7 +46,6 @@ struct dentry * d_mounts; /* mount information */ struct dentry * d_covers; struct list_head d_hash; /* lookup hash list */ - struct list_head d_alias; /* inode alias list */ struct list_head d_lru; /* d_count = 0 LRU list */ struct qstr d_name; unsigned long d_time; /* used by d_revalidate */ @@ -57,6 +56,7 @@ int (*d_revalidate)(struct dentry *); int (*d_hash) (struct dentry *,struct qstr *); int (*d_compare) (struct dentry *,struct qstr *, struct qstr *); + void (*d_delete)(struct dentry *); }; /* the dentry parameter passed to d_hash and d_compare is the parent @@ -70,6 +70,10 @@ /* d_flags entries */ #define DCACHE_AUTOFS_PENDING 0x0001 /* autofs: "under construction" */ +#define DCACHE_NFSFS_RENAMED 0x0002 /* this dentry has been "silly + * renamed" and has to be + * deleted on the last dput() + */ /* * d_drop() unhashes the entry from the parent @@ -132,13 +136,5 @@ } extern void dput(struct dentry *); - -/* - * This is ugly. The inode:dentry relationship is a 1:n - * relationship, so we have to return one (random) dentry - * from the alias list. We select the first one.. - */ -#define i_dentry(inode) \ - list_entry((inode)->i_dentry.next, struct dentry, d_alias) #endif /* __LINUX_DCACHE_H */ diff -u --recursive --new-file v2.1.51/linux/include/linux/fs.h linux/include/linux/fs.h --- v2.1.51/linux/include/linux/fs.h Mon Aug 18 18:19:47 1997 +++ linux/include/linux/fs.h Mon Aug 25 12:50:11 1997 @@ -250,6 +250,7 @@ #include #include #include +#include /* * Attribute flags. These should be or-ed together to figure out what @@ -327,8 +328,6 @@ struct page *i_pages; struct dquot *i_dquot[MAXQUOTAS]; - struct list_head i_dentry; - unsigned long i_state; unsigned int i_flags; @@ -350,6 +349,7 @@ struct affs_inode_info affs_i; struct ufs_inode_info ufs_i; struct romfs_inode_info romfs_i; + struct smb_inode_info smbfs_i; struct socket socket_i; void *generic_ip; } u; @@ -481,6 +481,7 @@ #include #include #include +#include struct super_block { kdev_t s_dev; @@ -514,6 +515,7 @@ struct affs_sb_info affs_sb; struct ufs_sb_info ufs_sb; struct romfs_sb_info romfs_sb; + struct smb_sb_info smbfs_sb; void *generic_sbp; } u; }; diff -u --recursive --new-file v2.1.51/linux/include/linux/nfs_fs_i.h linux/include/linux/nfs_fs_i.h --- v2.1.51/linux/include/linux/nfs_fs_i.h Thu Jun 12 15:28:32 1997 +++ linux/include/linux/nfs_fs_i.h Sat Aug 23 16:47:12 1997 @@ -47,13 +47,6 @@ unsigned long attrtimeo; /* - * This is to support the clandestine rename on unlink. - * Instead of the directory inode, we might as well keep - * its NFS FH, but that requires a kmalloc. - */ - struct inode * silly_inode; - - /* * This is the list of dirty unwritten pages. * NFSv3 will want to add a list for written but uncommitted * pages. diff -u --recursive --new-file v2.1.51/linux/include/linux/smb.h linux/include/linux/smb.h --- v2.1.51/linux/include/linux/smb.h Sun Dec 1 08:21:33 1996 +++ linux/include/linux/smb.h Fri Aug 22 10:04:33 1997 @@ -1,119 +1,76 @@ /* * smb.h * - * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke + * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke + * Copyright (C) 1997 by Volker Lendecke * */ #ifndef _LINUX_SMB_H #define _LINUX_SMB_H -#define SMB_PORT 139 -#define SMB_MAXNAMELEN 255 -#define SMB_MAXPATHLEN 1024 - -#define SMB_DEF_MAX_XMIT 32768 - -/* Allocate max. 1 page */ -#define TRANS2_MAX_TRANSFER (4096-17) - -#include -#ifdef __KERNEL__ -typedef u8 byte; -typedef u16 word; -typedef u32 dword; -#else -typedef unsigned char byte; -typedef unsigned short word; -typedef unsigned long dword; -#endif - -/* The following macros have been taken directly from Samba. Thanks, - Andrew! */ - -#undef CAREFUL_ALIGNMENT +#include -/* we know that the 386 can handle misalignment and has the "right" - byteorder */ -#if defined(__i386__) -#define CAREFUL_ALIGNMENT 0 -#endif - -#ifndef CAREFUL_ALIGNMENT -#define CAREFUL_ALIGNMENT 1 -#endif +enum smb_protocol { + SMB_PROTOCOL_NONE, + SMB_PROTOCOL_CORE, + SMB_PROTOCOL_COREPLUS, + SMB_PROTOCOL_LANMAN1, + SMB_PROTOCOL_LANMAN2, + SMB_PROTOCOL_NT1 +}; -#define BVAL(buf,pos) (((u8 *)(buf))[pos]) -#define PVAL(buf,pos) ((unsigned)BVAL(buf,pos)) -#define BSET(buf,pos,val) (BVAL(buf,pos) = (val)) - - -#if CAREFUL_ALIGNMENT -#define WVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8) -#define DVAL(buf,pos) (WVAL(buf,pos)|WVAL(buf,(pos)+2)<<16) - -#define SSVALX(buf,pos,val) (BVAL(buf,pos)=(val)&0xFF,BVAL(buf,pos+1)=(val)>>8) -#define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16)) -#define WSET(buf,pos,val) { word __val = (val); \ - SSVALX((buf),(pos),((word)(__val))); } -#define DSET(buf,pos,val) { dword __val = (val); \ - SIVALX((buf),(pos),((dword)(__val))); } -#else -/* this handles things for architectures like the 386 that can handle - alignment errors */ -/* - WARNING: This section is dependent on the length of word and dword - being correct -*/ -#define WVAL(buf,pos) (*(word *)((char *)(buf) + (pos))) -#define DVAL(buf,pos) (*(dword *)((char *)(buf) + (pos))) -#define WSET(buf,pos,val) WVAL(buf,pos)=((word)(val)) -#define DSET(buf,pos,val) DVAL(buf,pos)=((dword)(val)) -#endif +enum smb_case_hndl { + SMB_CASE_DEFAULT, + SMB_CASE_LOWER, + SMB_CASE_UPPER +}; +struct smb_dskattr { + __u16 total; + __u16 allocblocks; + __u16 blocksize; + __u16 free; +}; -/* where to find the base of the SMB packet proper */ -#define smb_base(buf) ((byte *)(((byte *)(buf))+4)) +struct smb_conn_opt { -#define LANMAN1 -#define LANMAN2 -#define NT1 + /* The socket */ + unsigned int fd; -enum smb_protocol { - PROTOCOL_NONE, - PROTOCOL_CORE, - PROTOCOL_COREPLUS, - PROTOCOL_LANMAN1, - PROTOCOL_LANMAN2, - PROTOCOL_NT1 -}; + enum smb_protocol protocol; + enum smb_case_hndl case_handling; -enum smb_case_hndl { - CASE_DEFAULT, - CASE_LOWER, - CASE_UPPER + /* Connection-Options */ + + __u32 max_xmit; + __u16 server_uid; + __u16 tid; + + /* The following are LANMAN 1.0 options */ + __u16 secmode; + __u16 maxmux; + __u16 maxvcs; + __u16 rawmode; + __u32 sesskey; + + /* The following are NT LM 0.12 options */ + __u32 maxraw; + __u32 capabilities; + __u16 serverzone; }; #ifdef __KERNEL__ -enum smb_conn_state { - CONN_VALID, /* everything's fine */ - CONN_INVALID, /* Something went wrong, but did not - try to reconnect yet. */ - CONN_RETRIED /* Tried a reconnection, but was refused */ -}; - -struct smb_dskattr { - word total; - word allocblocks; - word blocksize; - word free; -}; +#define SMB_MAXNAMELEN 255 +#define SMB_MAXPATHLEN 1024 /* * Contains all relevant data on a SMB networked file. */ -struct smb_dirent { +struct smb_fattr { + + __u16 attr; unsigned long f_ino; umode_t f_mode; @@ -127,16 +84,40 @@ time_t f_ctime; unsigned long f_blksize; unsigned long f_blocks; - - int opened; /* is it open on the fileserver? */ - word fileid; /* What id to handle a file with? */ - word attr; /* Attribute fields, DOS value */ - - unsigned short access; /* Access bits. */ - unsigned long f_pos; /* File position. (For readdir.) */ - unsigned char name[SMB_MAXNAMELEN+1]; - int len; /* namelength */ }; -#endif /* __KERNEL__ */ -#endif /* _LINUX_SMB_H */ +struct smb_dirent { + struct smb_fattr attr; + + int f_pos; + int len; + __u8 name[SMB_MAXNAMELEN]; +}; + +enum smb_conn_state { + CONN_VALID, /* everything's fine */ + CONN_INVALID, /* Something went wrong, but did not + try to reconnect yet. */ + CONN_RETRIED /* Tried a reconnection, but was refused */ +}; + +/* + * The readdir cache size controls how many directory entries are cached. + */ +#define SMB_READDIR_CACHE_SIZE 64 + +#define SMB_SUPER_MAGIC 0x517B + +#define SMB_SERVER(inode) (&(inode->i_sb->u.smbfs_sb)) +#define SMB_INOP(inode) (&(inode->u.smbfs_i)) + +#define SMB_HEADER_LEN 37 /* includes everything up to, but not + * including smb_bcc */ +#define SMB_DEF_MAX_XMIT 32768 +#define SMB_INITIAL_PACKET_SIZE 4000 + +/* Allocate max. 1 page */ +#define TRANS2_MAX_TRANSFER (4096-17) + +#endif +#endif diff -u --recursive --new-file v2.1.51/linux/include/linux/smb_fs.h linux/include/linux/smb_fs.h --- v2.1.51/linux/include/linux/smb_fs.h Mon Jul 7 16:04:00 1997 +++ linux/include/linux/smb_fs.h Mon Aug 25 12:54:06 1997 @@ -2,6 +2,7 @@ * smb_fs.h * * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke + * Copyright (C) 1997 by Volker Lendecke * */ @@ -9,72 +10,37 @@ #define _LINUX_SMB_FS_H #include -#include -#include -#include -#include - -#include -#include -#include /* * ioctl commands */ #define SMB_IOC_GETMOUNTUID _IOR('u', 1, uid_t) +#define SMB_IOC_NEWCONN _IOW('u', 2, struct smb_conn_opt) #ifdef __KERNEL__ -/* - * The readdir cache size controls how many directory entries are cached. - */ -#define SMB_READDIR_CACHE_SIZE 64 - -/* - * This defines the number of filenames cached in memory to avoid - * constructing filenames from \ - */ -#define SMB_CACHE_TABLE_SIZE 64 - -#define SMB_SUPER_MAGIC 0x517B +#include +#define WVAL(buf,pos) \ +(le16_to_cpu(get_unaligned((__u16 *)((__u8 *)(buf) + (pos))))) +#define DVAL(buf,pos) \ +(le32_to_cpu(get_unaligned((__u32 *)((__u8 *)(buf) + (pos))))) +#define WSET(buf,pos,val) \ +put_unaligned(cpu_to_le16((__u16)(val)), (__u16 *)((__u8 *)(buf) + (pos))) +#define DSET(buf,pos,val) \ +put_unaligned(cpu_to_le32((__u32)(val)), (__u32 *)((__u8 *)(buf) + (pos))) +/* where to find the base of the SMB packet proper */ +#define smb_base(buf) ((__u8 *)(((__u8 *)(buf))+4)) -#define SMB_SBP(sb) ((struct smb_sb_info *)(sb->u.generic_sbp)) -#define SMB_INOP(inode) ((struct smb_inode_info *)(inode->u.generic_ip)) - -#define SMB_SERVER(inode) (&(SMB_SBP(inode->i_sb)->s_server)) -#define SMB_SERVATTR(inode) (&(SMB_SBP(inode->i_sb)->s_attr)) - -#define SMB_FINFO(inode) (&(SMB_INOP(inode)->finfo)) - -#define SMB_HEADER_LEN 37 /* includes everything up to, but not - * including smb_bcc */ +#include #ifdef DEBUG_SMB_MALLOC -#include - extern int smb_malloced; -extern int smb_current_kmalloced; extern int smb_current_vmalloced; static inline void * -smb_kmalloc(unsigned int size, int priority) -{ - smb_malloced += 1; - smb_current_kmalloced += 1; - return kmalloc(size, priority); -} - -static inline void -smb_kfree_s(void *obj, int size) -{ - smb_current_kmalloced -= 1; - kfree_s(obj, size); -} - -static inline void * smb_vmalloc(unsigned int size) { smb_malloced += 1; @@ -98,47 +64,20 @@ #endif /* DEBUG_SMB_MALLOC */ -#if DEBUG_SMB > 0 -#define DPRINTK(format, args...) printk(format , ## args) -#else -#define DPRINTK(format, args...) -#endif - -#if DEBUG_SMB > 1 -#define DDPRINTK(format, args...) printk(format , ## args) -#else -#define DDPRINTK(format, args...) -#endif - - -static inline ino_t -smb_info_ino(struct smb_inode_info *info) -{ -#if 0 - return (ino_t) info; -#else - if (info != NULL) - { - return info->finfo.f_ino; - } - return 1; -#endif -} +struct smb_sb_info; /* linux/fs/smbfs/file.c */ extern struct inode_operations smb_file_inode_operations; -int smb_make_open(struct inode *i, int right); /* linux/fs/smbfs/dir.c */ extern struct inode_operations smb_dir_inode_operations; -struct smb_inode_info *smb_find_inode(struct smb_server *server, ino_t ino); +struct smb_inode_info *smb_find_inode(struct smb_sb_info *server, ino_t ino); void smb_free_inode_info(struct smb_inode_info *i); -void smb_free_all_inodes(struct smb_server *server); -void smb_init_root(struct smb_server *server); -int smb_stat_root(struct smb_server *server); +void smb_free_all_inodes(struct smb_sb_info *server); +void smb_init_root(struct smb_sb_info *server); +int smb_stat_root(struct smb_sb_info *server); void smb_init_dir_cache(void); void smb_invalid_dir_cache(unsigned long ino); -void smb_invalidate_all_inodes(struct smb_server *server); void smb_free_dir_cache(void); /* linux/fs/smbfs/ioctl.c */ @@ -149,63 +88,63 @@ struct super_block *smb_read_super(struct super_block *sb, void *raw_data, int silent); extern int init_smb_fs(void); +void smb_invalidate_inodes(struct smb_sb_info *server); +int smb_revalidate_inode(struct inode *i); +int smb_refresh_inode(struct inode *i); int smb_notify_change(struct inode *inode, struct iattr *attr); -void smb_invalidate_connection(struct smb_server *server); -int smb_conn_is_valid(struct smb_server *server); +void smb_invalidate_connection(struct smb_sb_info *server); +int smb_conn_is_valid(struct smb_sb_info *server); +unsigned long smb_invent_inos(unsigned long n); +struct inode *smb_iget(struct super_block *, struct smb_fattr *); /* linux/fs/smbfs/proc.c */ -dword smb_len(unsigned char *packet); -byte *smb_encode_smb_length(byte *p, dword len); -__u8 *smb_setup_header(struct smb_server *server, byte command, - word wct, word bcc); -void smb_init_root_dirent(struct smb_server *server, struct smb_dirent *entry); -int smb_proc_open(struct smb_server *server, - struct smb_inode_info *dir, const char *name, int len, - struct smb_dirent *entry); -int smb_proc_close(struct smb_server *server, - __u16 fileid, __u32 mtime); -int smb_proc_read(struct smb_server *server, struct smb_dirent *finfo, - off_t offset, long count, char *data, int fs); -int smb_proc_read_raw(struct smb_server *server, struct smb_dirent *finfo, - off_t offset, long count, char *data); -int smb_proc_write(struct smb_server *server, struct smb_dirent *finfo, - off_t offset, int count, const char *data); -int smb_proc_write_raw(struct smb_server *server, struct smb_dirent *finfo, - off_t offset, long count, const char *data); -int smb_proc_create(struct inode *dir, const char *name, int len, - word attr, time_t ctime); -int smb_proc_mv(struct inode *odir, const char *oname, const int olen, - struct inode *ndir, const char *nname, const int nlen); -int smb_proc_mkdir(struct inode *dir, const char *name, const int len); -int smb_proc_rmdir(struct inode *dir, const char *name, const int len); -int smb_proc_unlink(struct inode *dir, const char *name, const int len); -int smb_proc_readdir(struct smb_server *server, struct inode *dir, +__u32 smb_len(unsigned char *packet); +__u8 *smb_encode_smb_length(__u8 *p, __u32 len); +__u8 *smb_setup_header(struct smb_sb_info *server, __u8 command, + __u16 wct, __u16 bcc); +int smb_offerconn(struct smb_sb_info *server); +int smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt); +int smb_close(struct inode *); +int smb_open(struct inode *, int); +static inline int +smb_is_open(struct inode *i) +{ + return (i->u.smbfs_i.open == SMB_SERVER(i)->generation); +} + +int smb_proc_read(struct inode *, off_t, long, char *); +int smb_proc_write(struct inode *, off_t, int, const char *); +int smb_proc_create(struct inode *, struct qstr *, __u16, time_t); +int smb_proc_mv(struct inode *, struct qstr *, struct inode *, struct qstr *); +int smb_proc_mkdir(struct inode *, struct qstr *); +int smb_proc_rmdir(struct inode *, struct qstr *); +int smb_proc_unlink(struct inode *dir, struct qstr *); +int smb_proc_readdir(struct inode *dir, int fpos, int cache_size, struct smb_dirent *entry); -int smb_proc_getattr(struct inode *dir, const char *name, int len, - struct smb_dirent *entry); -int smb_proc_setattr(struct smb_server *server, +int smb_proc_getattr(struct inode *dir, struct qstr *name, + struct smb_fattr *entry); +int smb_proc_setattr(struct smb_sb_info *server, struct inode *ino, - struct smb_dirent *new_finfo); -int smb_proc_chkpath(struct smb_server *server, char *path, int len, - int *result); -int smb_proc_dskattr(struct super_block *super, struct smb_dskattr *attr); -int smb_proc_reconnect(struct smb_server *server); -int smb_proc_connect(struct smb_server *server); -int smb_proc_disconnect(struct smb_server *server); -int smb_proc_trunc(struct smb_server *server, word fid, dword length); + struct smb_fattr *new_finfo); +int smb_proc_dskattr(struct super_block *sb, struct statfs *attr); +int smb_proc_reconnect(struct smb_sb_info *server); +int smb_proc_connect(struct smb_sb_info *server); +int smb_proc_disconnect(struct smb_sb_info *server); +int smb_proc_trunc(struct smb_sb_info *server, __u16 fid, __u32 length); +void smb_init_root_dirent(struct smb_sb_info *server, struct smb_fattr *); /* linux/fs/smbfs/sock.c */ -int smb_release(struct smb_server *server); -int smb_connect(struct smb_server *server); -int smb_request(struct smb_server *server); -int smb_request_read_raw(struct smb_server *server, +int smb_release(struct smb_sb_info *server); +int smb_connect(struct smb_sb_info *server); +int smb_request(struct smb_sb_info *server); +int smb_request_read_raw(struct smb_sb_info *server, unsigned char *target, int max_len); -int smb_request_write_raw(struct smb_server *server, +int smb_request_write_raw(struct smb_sb_info *server, unsigned const char *source, int length); -int smb_catch_keepalive(struct smb_server *server); -int smb_dont_catch_keepalive(struct smb_server *server); -int smb_trans2_request(struct smb_server *server, __u16 trans2_command, +int smb_catch_keepalive(struct smb_sb_info *server); +int smb_dont_catch_keepalive(struct smb_sb_info *server); +int smb_trans2_request(struct smb_sb_info *server, __u16 trans2_command, int ldata, unsigned char *data, int lparam, unsigned char *param, int *lrdata, unsigned char **rdata, diff -u --recursive --new-file v2.1.51/linux/include/linux/smb_fs_i.h linux/include/linux/smb_fs_i.h --- v2.1.51/linux/include/linux/smb_fs_i.h Sun Dec 1 08:59:35 1996 +++ linux/include/linux/smb_fs_i.h Fri Aug 22 10:04:33 1997 @@ -2,6 +2,7 @@ * smb_fs_i.h * * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke + * Copyright (C) 1997 by Volker Lendecke * */ @@ -9,25 +10,22 @@ #define _LINUX_SMB_FS_I #ifdef __KERNEL__ -#include - -enum smb_inode_state { - SMB_INODE_VALID = 19, /* Inode currently in use */ - SMB_INODE_LOOKED_UP, /* directly before iget */ - SMB_INODE_CACHED, /* in a path to an inode which is in use */ - SMB_INODE_INVALID -}; +#include /* * smb fs inode data (in memory only) */ struct smb_inode_info { - enum smb_inode_state state; - int nused; /* for directories: - number of references in memory */ - struct smb_inode_info *dir; - struct smb_inode_info *next, *prev; - struct smb_dirent finfo; + + /* + * file handles are local to a connection. A file is open if + * (open == generation). + */ + unsigned int open; + __u16 fileid; /* What id to handle a file with? */ + __u16 attr; /* Attribute fields, DOS value */ + + __u16 access; /* Access bits. */ }; #endif diff -u --recursive --new-file v2.1.51/linux/include/linux/smb_fs_sb.h linux/include/linux/smb_fs_sb.h --- v2.1.51/linux/include/linux/smb_fs_sb.h Mon Jul 7 16:04:00 1997 +++ linux/include/linux/smb_fs_sb.h Fri Aug 22 10:04:33 1997 @@ -2,76 +2,41 @@ * smb_fs_sb.h * * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke + * Copyright (C) 1997 by Volker Lendecke * */ #ifndef _SMB_FS_SB #define _SMB_FS_SB +#ifdef __KERNEL__ + +#include #include -#include #include -#include -#ifdef __KERNEL__ +struct smb_sb_info { + enum smb_conn_state state; + struct file * sock_file; -struct smb_server { - enum smb_protocol protocol; /* The protocol this - connection accepts. */ - enum smb_case_hndl case_handling; - struct file * sock_file; /* The socket we transfer - data on. */ - int lock; /* To prevent mismatch in - protocols. */ - struct wait_queue *wait; - - __u32 max_xmit; - char hostname[256]; - word pid; - word server_uid; - word mid; - word tid; - - struct smb_mount_data m; /* We store the complete information here - * to be able to reconnect. - */ + struct smb_mount_data m; - unsigned short rcls; /* The error codes we received */ - unsigned short err; + /* Connections are counted. Each time a new socket arrives, + * generation is incremented. + */ + unsigned int generation; + pid_t conn_pid; + struct smb_conn_opt opt; + + struct semaphore sem; __u32 packet_size; unsigned char * packet; - - enum smb_conn_state state; - unsigned long reconnect_time; /* The time of the last attempt */ - - /* The following are LANMAN 1.0 options transferred to us in - SMBnegprot */ - word secmode; - word maxmux; - word maxvcs; - word blkmode; - dword sesskey; + unsigned short rcls; /* The error codes we received */ + unsigned short err; /* We use our on data_ready callback, but need the original one */ void *data_ready; - - /* We do not have unique numbers for files in the smb protocol - like NFS-filehandles. (SMB was designed for DOS, not for - UNIX!) So we have to create our own inode numbers. We keep - a complete path of smb_inode_info's to each active - inode. The inode number is then created by the address of - this structure. */ - struct smb_inode_info root; -}; - -/* - * This is the part of the super-block (in memory) for the SMB file system. - */ - -struct smb_sb_info { - struct smb_server s_server; - struct smb_dskattr s_attr; }; #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.1.51/linux/include/linux/smb_mount.h linux/include/linux/smb_mount.h --- v2.1.51/linux/include/linux/smb_mount.h Mon Jul 7 16:03:54 1997 +++ linux/include/linux/smb_mount.h Fri Aug 22 10:04:33 1997 @@ -2,6 +2,7 @@ * smb_mount.h * * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke + * Copyright (C) 1997 by Volker Lendecke * */ @@ -9,26 +10,12 @@ #define _LINUX_SMB_MOUNT_H #include -#include -#define SMB_MOUNT_VERSION 5 +#define SMB_MOUNT_VERSION 6 struct smb_mount_data { int version; - unsigned int fd; uid_t mounted_uid; /* Who may umount() this filesystem? */ - struct sockaddr_in addr; - - char server_name[17]; - char client_name[17]; - char service[64]; - char root_path[64]; - - char username[64]; - char password[64]; - char domain[64]; - - unsigned short max_xmit; uid_t uid; gid_t gid;