Commit cbb2f9cb authored by Anton Altaparmakov's avatar Anton Altaparmakov

Merge ssh://linux-ntfs@bkbits.net/ntfs-2.6

into cantab.net:/home/src/ntfs-2.6
parents 7fec76df ae0a09f7
......@@ -447,6 +447,16 @@ sys_call_table:
.quad sys_stat64 /* 425 */
.quad sys_lstat64
.quad sys_fstat64
.quad sys_ni_syscall /* sys_vserver */
.quad sys_ni_syscall /* sys_mbind */
.quad sys_ni_syscall /* sys_get_mempolicy */
.quad sys_ni_syscall /* sys_set_mempolicy */
.quad sys_mq_open
.quad sys_mq_unlink
.quad sys_mq_timedsend
.quad sys_mq_timedreceive /* 435 */
.quad sys_mq_notify
.quad sys_mq_getsetattr
.size sys_call_table, . - sys_call_table
.type sys_call_table, @object
......
......@@ -430,6 +430,7 @@ static void setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
regs->gpr[1] = newsp;
err |= get_user(regs->gpr[2], &funct_desc_ptr->toc);
regs->gpr[3] = signr;
regs->result = 0;
if (ka->sa.sa_flags & SA_SIGINFO) {
err |= get_user(regs->gpr[4], (unsigned long *)&frame->pinfo);
err |= get_user(regs->gpr[5], (unsigned long *)&frame->puc);
......
......@@ -676,6 +676,7 @@ static void handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
regs->nip = (unsigned long) ka->sa.sa_handler;
regs->link = (unsigned long) frame->tramp;
regs->trap = 0;
regs->result = 0;
return;
......@@ -784,7 +785,6 @@ long sys32_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
*/
sys32_sigaltstack((u32)(u64)&rt_sf->uc.uc_stack, 0, 0, 0, 0, 0, regs);
regs->result &= 0xFFFFFFFF;
ret = regs->result;
return ret;
......@@ -841,6 +841,7 @@ static void handle_signal32(unsigned long sig, struct k_sigaction *ka,
regs->nip = (unsigned long) ka->sa.sa_handler;
regs->link = (unsigned long) frame->mctx.tramp;
regs->trap = 0;
regs->result = 0;
return;
......@@ -885,7 +886,6 @@ long sys32_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
|| restore_user_regs(regs, sr, 1))
goto badframe;
regs->result &= 0xFFFFFFFF;
ret = regs->result;
return ret;
......
......@@ -57,7 +57,8 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
/* We do not accept a shared mapping if it would violate
* cache aliasing constraints.
*/
if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1)))
if ((flags & MAP_SHARED) &&
((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
return -EINVAL;
return addr;
}
......
......@@ -81,10 +81,6 @@ static const char *mcdx_c_version
#define mcdx_drive_map mcdx
#include "mcdx.h"
#if BITS_PER_LONG != 32
# error FIXME: this driver only works on 32-bit platforms
#endif
#ifndef HZ
#error HZ not defined
#endif
......@@ -189,12 +185,12 @@ struct s_drive_stuff {
#endif /* AK2 */
/* adds and odds */
void *wreg_data; /* w data */
void *wreg_reset; /* w hardware reset */
void *wreg_hcon; /* w hardware conf */
void *wreg_chn; /* w channel */
void *rreg_data; /* r data */
void *rreg_status; /* r status */
unsigned wreg_data; /* w data */
unsigned wreg_reset; /* w hardware reset */
unsigned wreg_hcon; /* w hardware conf */
unsigned wreg_chn; /* w channel */
unsigned rreg_data; /* r data */
unsigned rreg_status; /* r status */
int irq; /* irq used by this drive */
int present; /* drive present and its capabilities */
......@@ -274,7 +270,7 @@ static void log2msf(unsigned int, struct cdrom_msf0 *);
static unsigned int msf2log(const struct cdrom_msf0 *);
static unsigned int uint2bcd(unsigned int);
static unsigned int bcd2uint(unsigned char);
static char *port(int *);
static unsigned port(int *);
static int irq(int *);
static void mcdx_delay(struct s_drive_stuff *, long jifs);
static int mcdx_transfer(struct s_drive_stuff *, char *buf, int sector,
......@@ -868,7 +864,7 @@ static irqreturn_t mcdx_intr(int irq, void *dev_id, struct pt_regs *regs)
#endif /* AK2 */
/* get the interrupt status */
b = inb((unsigned int) stuffp->rreg_status);
b = inb(stuffp->rreg_status);
stuffp->introk = ~b & MCDX_RBIT_DTEN;
/* NOTE: We only should get interrupts if the data we
......@@ -882,7 +878,7 @@ static irqreturn_t mcdx_intr(int irq, void *dev_id, struct pt_regs *regs)
xtrace(IRQ, "intr() irq %d hw status 0x%02x\n", irq, b);
if (~b & MCDX_RBIT_STEN) {
xinfo("intr() irq %d status 0x%02x\n",
irq, inb((unsigned int) stuffp->rreg_data));
irq, inb(stuffp->rreg_data));
} else {
xinfo("intr() irq %d ambiguous hw status\n", irq);
}
......@@ -945,7 +941,7 @@ static int mcdx_talk(struct s_drive_stuff *stuffp,
char *bp = (char *) buffer;
size_t sz = size;
outsb((unsigned int) stuffp->wreg_data, cmd, cmdlen);
outsb(stuffp->wreg_data, cmd, cmdlen);
xtrace(TALK, "talk() command sent\n");
/* get the status byte */
......@@ -1049,8 +1045,7 @@ void __exit mcdx_exit(void)
continue;
}
put_disk(stuffp->disk);
release_region((unsigned long) stuffp->wreg_data,
MCDX_IO_SIZE);
release_region(stuffp->wreg_data, MCDX_IO_SIZE);
free_irq(stuffp->irq, NULL);
if (stuffp->toc) {
xtrace(MALLOC, "cleanup_module() free toc @ %p\n",
......@@ -1116,8 +1111,7 @@ int __init mcdx_init_drive(int drive)
/* setup our irq and i/o addresses */
stuffp->irq = irq(mcdx_drive_map[drive]);
stuffp->wreg_data = stuffp->rreg_data =
port(mcdx_drive_map[drive]);
stuffp->wreg_data = stuffp->rreg_data = port(mcdx_drive_map[drive]);
stuffp->wreg_reset = stuffp->rreg_status = stuffp->wreg_data + 1;
stuffp->wreg_hcon = stuffp->wreg_reset + 1;
stuffp->wreg_chn = stuffp->wreg_hcon + 1;
......@@ -1127,10 +1121,9 @@ int __init mcdx_init_drive(int drive)
init_waitqueue_head(&stuffp->sleepq);
/* check if i/o addresses are available */
if (!request_region((unsigned int) stuffp->wreg_data, MCDX_IO_SIZE,
"mcdx")) {
xwarn("0x%3p,%d: Init failed. "
"I/O ports (0x%3p..0x%3p) already in use.\n",
if (!request_region(stuffp->wreg_data, MCDX_IO_SIZE, "mcdx")) {
xwarn("0x%03x,%d: Init failed. "
"I/O ports (0x%03x..0x%03x) already in use.\n",
stuffp->wreg_data, stuffp->irq,
stuffp->wreg_data,
stuffp->wreg_data + MCDX_IO_SIZE - 1);
......@@ -1141,7 +1134,7 @@ int __init mcdx_init_drive(int drive)
return 0; /* next drive */
}
xtrace(INIT, "init() i/o port is available at 0x%3p\n",
xtrace(INIT, "init() i/o port is available at 0x%03x\n"
stuffp->wreg_data);
xtrace(INIT, "init() hardware reset\n");
mcdx_reset(stuffp, HARD, 1);
......@@ -1149,9 +1142,8 @@ int __init mcdx_init_drive(int drive)
xtrace(INIT, "init() get version\n");
if (-1 == mcdx_requestversion(stuffp, &version, 4)) {
/* failed, next drive */
release_region((unsigned long) stuffp->wreg_data,
MCDX_IO_SIZE);
xwarn("%s=0x%3p,%d: Init failed. Can't get version.\n",
release_region(stuffp->wreg_data, MCDX_IO_SIZE);
xwarn("%s=0x%03x,%d: Init failed. Can't get version.\n",
MCDX, stuffp->wreg_data, stuffp->irq);
xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
kfree(stuffp);
......@@ -1181,9 +1173,8 @@ int __init mcdx_init_drive(int drive)
stuffp->playcmd = READ1X;
if (!stuffp->present) {
release_region((unsigned long) stuffp->wreg_data,
MCDX_IO_SIZE);
xwarn("%s=0x%3p,%d: Init failed. No Mitsumi CD-ROM?.\n",
release_region(stuffp->wreg_data, MCDX_IO_SIZE);
xwarn("%s=0x%03x,%d: Init failed. No Mitsumi CD-ROM?.\n",
MCDX, stuffp->wreg_data, stuffp->irq);
kfree(stuffp);
put_disk(disk);
......@@ -1192,8 +1183,7 @@ int __init mcdx_init_drive(int drive)
xtrace(INIT, "init() register blkdev\n");
if (register_blkdev(MAJOR_NR, "mcdx")) {
release_region((unsigned long) stuffp->wreg_data,
MCDX_IO_SIZE);
release_region(stuffp->wreg_data, MCDX_IO_SIZE);
kfree(stuffp);
put_disk(disk);
return 1;
......@@ -1202,8 +1192,7 @@ int __init mcdx_init_drive(int drive)
mcdx_queue = blk_init_queue(do_mcdx_request, &mcdx_lock);
if (!mcdx_queue) {
unregister_blkdev(MAJOR_NR, "mcdx");
release_region((unsigned long) stuffp->wreg_data,
MCDX_IO_SIZE);
release_region(stuffp->wreg_data, MCDX_IO_SIZE);
kfree(stuffp);
put_disk(disk);
return 1;
......@@ -1212,9 +1201,8 @@ int __init mcdx_init_drive(int drive)
xtrace(INIT, "init() subscribe irq and i/o\n");
mcdx_irq_map[stuffp->irq] = stuffp;
if (request_irq(stuffp->irq, mcdx_intr, SA_INTERRUPT, "mcdx", NULL)) {
release_region((unsigned long) stuffp->wreg_data,
MCDX_IO_SIZE);
xwarn("%s=0x%3p,%d: Init failed. Can't get irq (%d).\n",
release_region(stuffp->wreg_data, MCDX_IO_SIZE);
xwarn("%s=0x%03x,%d: Init failed. Can't get irq (%d).\n",
MCDX, stuffp->wreg_data, stuffp->irq, stuffp->irq);
stuffp->irq = 0;
blk_cleanup_queue(mcdx_queue);
......@@ -1228,13 +1216,13 @@ int __init mcdx_init_drive(int drive)
int i;
mcdx_delay(stuffp, HZ / 2);
for (i = 100; i; i--)
(void) inb((unsigned int) stuffp->rreg_status);
(void) inb(stuffp->rreg_status);
}
#if WE_KNOW_WHY
/* irq 11 -> channel register */
outb(0x50, (unsigned int) stuffp->wreg_chn);
outb(0x50, stuffp->wreg_chn);
#endif
xtrace(INIT, "init() set non dma but irq mode\n");
......@@ -1252,15 +1240,14 @@ int __init mcdx_init_drive(int drive)
disk->flags = GENHD_FL_CD;
stuffp->disk = disk;
sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%3p, irq %d."
sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%03x, irq %d."
" (Firmware version %c %x)\n",
stuffp->wreg_data, stuffp->irq, version.code, version.ver);
mcdx_stuffp[drive] = stuffp;
xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp);
if (register_cdrom(&stuffp->info) != 0) {
printk("Cannot register Mitsumi CD-ROM!\n");
release_region((unsigned long) stuffp->wreg_data,
MCDX_IO_SIZE);
release_region(stuffp->wreg_data, MCDX_IO_SIZE);
free_irq(stuffp->irq, NULL);
kfree(stuffp);
put_disk(disk);
......@@ -1413,19 +1400,17 @@ static int mcdx_xfer(struct s_drive_stuff *stuffp,
const int HEAD =
CD_FRAMESIZE_RAW - CD_XA_TAIL -
CD_FRAMESIZE;
insb((unsigned int) stuffp->rreg_data, p,
HEAD);
insb(stuffp->rreg_data, p, HEAD);
}
/* now actually read the data */
insb((unsigned int) stuffp->rreg_data, p, 512);
insb(stuffp->rreg_data, p, 512);
/* test if it's the last sector of a block,
* if so, we have to handle XA special */
if ((3 == (stuffp->pending & 3)) && stuffp->xa) {
char dummy[CD_XA_TAIL];
insb((unsigned int) stuffp->rreg_data,
&dummy[0], CD_XA_TAIL);
insb(stuffp->rreg_data, &dummy[0], CD_XA_TAIL);
}
if (stuffp->pending == sector) {
......@@ -1493,7 +1478,7 @@ static int mcdx_xfer(struct s_drive_stuff *stuffp,
stuffp->busy = 1;
/* Now really issue the request command */
outsb((unsigned int) stuffp->wreg_data, cmd, sizeof cmd);
outsb(stuffp->wreg_data, cmd, sizeof cmd);
}
#ifdef AK2
......@@ -1514,9 +1499,9 @@ static int mcdx_xfer(struct s_drive_stuff *stuffp,
/* Access to elements of the mcdx_drive_map members */
static char *port(int *ip)
static unsigned port(int *ip)
{
return (char *) ip[0];
return ip[0];
}
static int irq(int *ip)
{
......@@ -1682,7 +1667,7 @@ mcdx_playmsf(struct s_drive_stuff *stuffp, const struct cdrom_msf *msf)
"%02x:%02x:%02x -- %02x:%02x:%02x\n",
cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6]);
outsb((unsigned int) stuffp->wreg_data, cmd, sizeof cmd);
outsb(stuffp->wreg_data, cmd, sizeof cmd);
if (-1 == mcdx_getval(stuffp, 3 * HZ, 0, NULL)) {
xwarn("playmsf() timeout\n");
......@@ -1910,8 +1895,8 @@ static int mcdx_requestversion(struct s_drive_stuff *stuffp, struct s_version *v
static int mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries)
{
if (mode == HARD) {
outb(0, (unsigned int) stuffp->wreg_chn); /* no dma, no irq -> hardware */
outb(0, (unsigned int) stuffp->wreg_reset); /* hw reset */
outb(0, stuffp->wreg_chn); /* no dma, no irq -> hardware */
outb(0, stuffp->wreg_reset); /* hw reset */
return 0;
} else
return mcdx_talk(stuffp, "\x60", 1, NULL, 1, 5 * HZ, tries);
......@@ -1945,13 +1930,13 @@ mcdx_getval(struct s_drive_stuff *stuffp, int to, int delay, char *buf)
if (!buf)
buf = &c;
while (inb((unsigned int) stuffp->rreg_status) & MCDX_RBIT_STEN) {
while (inb(stuffp->rreg_status) & MCDX_RBIT_STEN) {
if (time_after(jiffies, timeout))
return -1;
mcdx_delay(stuffp, delay);
}
*buf = (unsigned char) inb((unsigned int) stuffp->rreg_data) & 0xff;
*buf = (unsigned char) inb(stuffp->rreg_data) & 0xff;
return 0;
}
......
......@@ -472,7 +472,9 @@ static int svwks_config_drive_xfer_rate (ide_drive_t *drive)
int dma = config_chipset_for_dma(drive);
if ((id->field_valid & 2) && !dma)
goto try_dma_modes;
}
} else
/* UDMA disabled by mask, try other DMA modes */
goto try_dma_modes;
} else if (id->field_valid & 2) {
try_dma_modes:
if ((id->dma_mword & hwif->mwdma_mask) ||
......
......@@ -104,7 +104,7 @@ static struct net_device **dummies;
/* Number of dummy devices to be set up by this module. */
module_param(numdummies, int, 0);
MODULE_PARM_DESC(numdimmies, "Number of dummy psuedo devices");
MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices");
static int __init dummy_init_one(int index)
{
......
......@@ -525,7 +525,7 @@ pci_default_setup(struct pci_dev *dev, struct pci_board *board,
else
offset += idx * board->uart_offset;
maxnr = (pci_resource_len(dev, bar) - board->uart_offset) /
maxnr = (pci_resource_len(dev, bar) - board->first_offset) /
(8 << board->reg_shift);
if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
......
......@@ -21,11 +21,13 @@ Zwane Mwaikambo
Andi Kleen
Amrut Joshi
Shobhit Dayal
Sergey Vlasov
Test case and Bug Report contributors
-------------------------------------
Thanks to those in the community who have submitted detailed bug reports
and debug of problems they have found: Jochen Dolze, David Blaine,
Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori,
Urban Widmark, Massimiliano Ferrero, Howard Owen and others.
Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
Kieron Briggs and others.
Version 1.13
------------
Fix open of files in which O_CREATE can cause the mode to change in
some cases. Fix case in which retry of write overlaps file close.
Fix PPC64 build error. Reduce excessive stack usage in smb password
hashing.
Version 1.12
------------
Fixes for large file copy, signal handling, socket retry, buffer
allocation and low memory situations.
Version 1.11
------------
Better port 139 support to Windows servers (RFC1001/RFC1002 Session_Initialize)
also now allowing support for specifying client netbiosname. NT4 support added.
Version 1.10
------------
Fix reconnection (and certain failed mounts) to properly wake up the
......
......@@ -148,8 +148,8 @@ If no password is provided, mount.cifs will prompt for password entry
Restrictions
============
Servers must support the NTLM SMB dialect (which is the most recent, supported
by Samba and Windows NT, 2000 and XP and many other SMB/CIFS servers) and
servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC
by Samba and Windows NT version 4, 2000 and XP and many other SMB/CIFS servers)
Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC
1001/1002 support for "Netbios-Over-TCP/IP." Neither of these is likely to be a
problem as most servers support this. IPv6 support is planned for the future.
......@@ -276,6 +276,15 @@ and for more extensive tracing including the start of smb requests and responses
echo 1 > /proc/fs/cifs/traceSMB
Three other experimental features are under development and to test
require enabling an ifdef (e.g. by adding "#define CIFS_FCNTL" in cifsglob.h)
CIFS_QUOTA
CIFS_XATTR
CIFS_FCNTL (fcntl needed for support of directory change notification)
Also note that "cat /proc/fs/cifs/DebugData" will display some information about
the active sessions and the shares that are mounted. Note: NTLMv2 enablement
will not work since they its implementation is not quite complete yet.
......
......@@ -65,14 +65,27 @@ but recognizes them
3) create of new files to FAT partitions on Windows servers can
succeed but still return access denied (appears to be Windows
not client problem). NTFS partitions do not have this problem.
4) debug connectathon special test case nfs_idem (which does
some invalid symlink naming, or at least what Samba thinks
is an invalid symlink target).
5) debug connectation lock test case 10 which fails against
Samba (may be unmappable due to POSIX to Windows lock model
differences but worth investigating). Also debug Samba to
see why lock test case 7 takes longer to complete to Samba
than to Windows.
Misc testing to do
=================
1) check out max path names and max path name components against various server
types.
2) Run dbench. Modify file portion of ltp so it can run against a mounted network
2) Modify file portion of ltp so it can run against a mounted network
share and run it against cifs vfs.
3) Additional performance testing and optimization using iozone and similar tools.
3) Additional performance testing and optimization using iozone and similar -
there are some easy changes that can be done to parallelize sequential writes,
and when signing is disabled to request larger read sizes (larger than
negotiated size) and send larger write sizes to modern servers.
4) More exhaustively test the recently added NT4 support
......@@ -672,8 +672,10 @@ static int cifs_oplock_thread(void * dummyarg)
/* down(&inode->i_sem);*/
if (S_ISREG(inode->i_mode)) {
rc = filemap_fdatawrite(inode->i_mapping);
if(CIFS_I(inode)->clientCanCacheRead == 0)
if(CIFS_I(inode)->clientCanCacheRead == 0) {
filemap_fdatawait(inode->i_mapping);
invalidate_remote_inode(inode);
}
} else
rc = 0;
/* up(&inode->i_sem);*/
......@@ -773,5 +775,6 @@ MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
MODULE_DESCRIPTION
("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows");
MODULE_VERSION(CIFS_VERSION);
module_init(init_cifs)
module_exit(exit_cifs)
......@@ -93,4 +93,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t, int);
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
#endif /* _CIFSSMB_H */
#define CIFS_VERSION "1.13"
#endif /* _CIFSFS_H */
......@@ -139,6 +139,7 @@ struct TCP_Server_Info {
int capabilities; /* allow selective disabling of caps by smb sess */
__u16 timeZone;
char cryptKey[CIFS_CRYPTO_KEY_SIZE];
char workstation_RFC1001_name[16]; /* 16th byte is always zero */
};
/*
......
......@@ -641,6 +641,9 @@ typedef struct smb_com_open_req { /* also handles create */
#define OPLOCK_BATCH 2
#define OPLOCK_READ 3 /* level 2 oplock */
/* open response for CreateAction shifted left */
#define CIFS_CREATE_ACTION 0x20000 /* file created */
typedef struct smb_com_open_rsp {
struct smb_hdr hdr; /* wct = 34 BB */
__u8 AndXCommand;
......
......@@ -594,7 +594,10 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
} else {
*pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
*netfid = pSMBr->Fid; /* cifs fid stays in le */
/* Do we care about the CreateAction in any cases? */
/* Let caller know file was created so we can set the mode. */
/* Do we care about the CreateAction in any other cases? */
if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
*pOplock |= CIFS_CREATE_ACTION;
if(pfile_info) {
memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
36 /* CreationTime to Attributes */);
......@@ -1509,7 +1512,7 @@ CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
TRANSACTION2_QPI_REQ *pSMB = NULL;
TRANSACTION2_QPI_RSP *pSMBr = NULL;
int rc = 0;
int bytes_returned;
int bytes_returned = 0;
int name_len;
cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
......@@ -1565,9 +1568,13 @@ CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
} else { /* decode response */
pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
/* BB also check if enough total bytes returned */
if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) ||
(pSMBr->DataOffset > 512) ||
(pSMBr->DataOffset < sizeof(struct smb_hdr))) {
cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d",
(int)pSMBr->DataOffset,bytes_returned));
rc = -EIO; /* bad smb */
else {
} else {
memcpy((char *) pFindData,
(char *) &pSMBr->hdr.Protocol +
pSMBr->DataOffset,
......
This diff is collapsed.
......@@ -179,14 +179,31 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
if (rc) {
cFYI(1, ("cifs_create returned 0x%x ", rc));
} else {
/* BB for case of overwriting existing file can we use the inode that was
passed in rather than creating new one?? */
/* If Open reported that we actually created a file
then we now have to set the mode if possible */
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
(oplock & CIFS_CREATE_ACTION))
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
(__u64)-1,
(__u64)-1,
0 /* dev */,
cifs_sb->local_nls);
else {
/* BB implement via Windows security descriptors */
/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
/* could set r/o dos attribute if mode & 0222 == 0 */
}
/* BB server might mask mode so we have to query for Unix case*/
if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb);
else
else {
rc = cifs_get_inode_info(&newinode, full_path,
buf, inode->i_sb);
if(newinode)
newinode->i_mode = mode;
}
if (rc != 0) {
cFYI(1,("Create worked but get_inode_info failed with rc = %d",
......@@ -198,21 +215,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
if((nd->flags & LOOKUP_OPEN) == FALSE) {
/* mknod case - do not leave file open */
CIFSSMBClose(xid, pTcon, fileHandle);
if(newinode)
newinode->i_mode = mode;
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
(__u64)-1,
(__u64)-1,
0 /* dev */,
cifs_sb->local_nls);
else { /* BB implement via Windows security descriptors */
/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
/* in the meantime could set r/o dos attribute when perms are eg:
mode & 0222 == 0 */
}
} else if(newinode) {
newinode->i_mode = mode;
pCifsFile = (struct cifsFileInfo *)
kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
......@@ -231,25 +234,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
pCifsInode = CIFS_I(newinode);
if(pCifsInode) {
list_add(&pCifsFile->flist,&pCifsInode->openFileList);
if(oplock == OPLOCK_EXCLUSIVE) {
if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE;
cFYI(1,("Exclusive Oplock granted on inode %p",newinode));
} else if(oplock == OPLOCK_READ)
} else if((oplock & 0xF) == OPLOCK_READ)
pCifsInode->clientCanCacheRead = TRUE;
}
write_unlock(&GlobalSMBSeslock);
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
(__u64)-1,
(__u64)-1,
0 /* dev */,
cifs_sb->local_nls);
else { /* BB implement via Windows security descriptors */
/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
/* in the meantime could set r/o dos attribute when perms are eg:
mode & 0222 == 0 */
}
}
}
}
......
......@@ -63,7 +63,7 @@ cifs_open(struct inode *inode, struct file *file)
list_for_each(tmp, &pCifsInode->openFileList) {
pCifsFile = list_entry(tmp,struct cifsFileInfo, flist);
if((pCifsFile->pfile == NULL)&& (pCifsFile->pid = current->pid)){
/* set mode ?? */
/* mode set in cifs_create */
pCifsFile->pfile = file; /* needed for writepage */
file->private_data = pCifsFile;
break;
......@@ -187,6 +187,12 @@ cifs_open(struct inode *inode, struct file *file)
(file->f_dentry->d_inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) {
cFYI(1,("inode unchanged on server"));
} else {
if(file->f_dentry->d_inode->i_mapping) {
/* BB no need to lock inode until after invalidate*/
/* since namei code should already have it locked?*/
filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
}
cFYI(1,("invalidating remote inode since open detected it changed"));
invalidate_remote_inode(file->f_dentry->d_inode);
}
......@@ -199,17 +205,17 @@ cifs_open(struct inode *inode, struct file *file)
rc = cifs_get_inode_info(&file->f_dentry->d_inode,
full_path, buf, inode->i_sb);
if(oplock == OPLOCK_EXCLUSIVE) {
if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE;
cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
} else if(oplock == OPLOCK_READ)
} else if((oplock & 0xF) == OPLOCK_READ)
pCifsInode->clientCanCacheRead = TRUE;
} else {
write_unlock(&GlobalSMBSeslock);
write_unlock(&file->f_owner.lock);
}
if(file->f_flags & O_CREAT) {
if(oplock & CIFS_CREATE_ACTION) {
/* time to set mode which we can not set earlier due
to problems creating new read-only files */
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
......@@ -330,11 +336,11 @@ static int cifs_reopen_file(struct inode *inode, struct file *file)
rc = cifs_get_inode_info(&inode,
full_path, buf, inode->i_sb);
if(oplock == OPLOCK_EXCLUSIVE) {
if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE;
cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
} else if(oplock == OPLOCK_READ) {
} else if((oplock & 0xF) == OPLOCK_READ) {
pCifsInode->clientCanCacheRead = TRUE;
pCifsInode->clientCanCacheAll = FALSE;
} else {
......@@ -555,6 +561,10 @@ cifs_write(struct file * file, const char *write_data,
}
open_file = (struct cifsFileInfo *) file->private_data;
if(file->f_dentry->d_inode == NULL) {
FreeXid(xid);
return -EBADF;
}
if (*poffset > file->f_dentry->d_inode->i_size)
long_op = 2; /* writes past end of file can take a long time */
......@@ -565,7 +575,16 @@ cifs_write(struct file * file, const char *write_data,
total_written += bytes_written) {
rc = -EAGAIN;
while(rc == -EAGAIN) {
if(file->private_data == NULL) {
/* file has been closed on us */
FreeXid(xid);
return total_written;
}
if ((open_file->invalidHandle) && (!open_file->closePend)) {
if((file->f_dentry == NULL) || (file->f_dentry->d_inode == NULL)) {
FreeXid(xid);
return total_written;
}
rc = cifs_reopen_file(file->f_dentry->d_inode,file);
if(rc != 0)
break;
......@@ -588,6 +607,10 @@ cifs_write(struct file * file, const char *write_data,
*poffset += bytes_written;
long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */
}
/* since the write may have blocked check these pointers again */
if(file->f_dentry) {
if(file->f_dentry->d_inode) {
file->f_dentry->d_inode->i_ctime = file->f_dentry->d_inode->i_mtime =
CURRENT_TIME;
if (bytes_written > 0) {
......@@ -595,6 +618,8 @@ cifs_write(struct file * file, const char *write_data,
i_size_write(file->f_dentry->d_inode, *poffset);
}
mark_inode_dirty_sync(file->f_dentry->d_inode);
}
}
FreeXid(xid);
return total_written;
}
......@@ -1049,7 +1074,7 @@ cifs_readpages(struct file *file, struct address_space *mapping,
} else if (bytes_read > 0) {
pSMBr = (struct smb_com_read_rsp *)smb_read_data;
cifs_copy_cache_pages(mapping, page_list, bytes_read,
smb_read_data + 4 /* RFC1000 hdr */ +
smb_read_data + 4 /* RFC1001 hdr */ +
le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
i += bytes_read >> PAGE_CACHE_SHIFT;
......@@ -1159,7 +1184,6 @@ fill_in_inode(struct inode *tmp_inode,
pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
cifsInfo->cifsAttrs = pfindData->ExtFileAttributes;
cifsInfo->time = jiffies;
atomic_inc(&cifsInfo->inUse); /* inc on every refresh of inode info */
/* Linux can not store file creation time unfortunately so ignore it */
tmp_inode->i_atime =
......@@ -1172,10 +1196,12 @@ fill_in_inode(struct inode *tmp_inode,
/* 2767 perms - indicate mandatory locking */
/* BB fill in uid and gid here? with help from winbind?
or retrieve from NTFS stream extended attribute */
if(atomic_read(&cifsInfo->inUse) == 0) {
tmp_inode->i_uid = cifs_sb->mnt_uid;
tmp_inode->i_gid = cifs_sb->mnt_gid;
/* set default mode. will override for dirs below */
tmp_inode->i_mode = cifs_sb->mnt_file_mode;
}
cFYI(0,
("CIFS FFIRST: Attributes came in as 0x%x",
......@@ -1187,7 +1213,9 @@ fill_in_inode(struct inode *tmp_inode,
} else if (pfindData->ExtFileAttributes & ATTR_DIRECTORY) {
*pobject_type = DT_DIR;
/* override default perms since we do not lock dirs */
if(atomic_read(&cifsInfo->inUse) == 0) {
tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
}
tmp_inode->i_mode |= S_IFDIR;
} else {
*pobject_type = DT_REG;
......@@ -1198,6 +1226,10 @@ fill_in_inode(struct inode *tmp_inode,
}/* could add code here - to validate if device or weird share type? */
/* can not fill in nlink here as in qpathinfo version and Unx search */
if(atomic_read(&cifsInfo->inUse) == 0) {
atomic_set(&cifsInfo->inUse,1);
}
i_size_write(tmp_inode,pfindData->EndOfFile);
tmp_inode->i_blocks =
(tmp_inode->i_blksize - 1 + pfindData->AllocationSize) >> tmp_inode->i_blkbits;
......@@ -1277,20 +1309,20 @@ unix_fill_in_inode(struct inode *tmp_inode,
(tmp_inode->i_blksize - 1 + pfindData->NumOfBytes) >> tmp_inode->i_blkbits;
if (S_ISREG(tmp_inode->i_mode)) {
cFYI(1, (" File inode "));
cFYI(1, ("File inode"));
tmp_inode->i_op = &cifs_file_inode_ops;
tmp_inode->i_fop = &cifs_file_ops;
tmp_inode->i_data.a_ops = &cifs_addr_ops;
} else if (S_ISDIR(tmp_inode->i_mode)) {
cFYI(1, (" Directory inode"));
cFYI(1, ("Directory inode"));
tmp_inode->i_op = &cifs_dir_inode_ops;
tmp_inode->i_fop = &cifs_dir_ops;
} else if (S_ISLNK(tmp_inode->i_mode)) {
cFYI(1, (" Symbolic Link inode "));
cFYI(1, ("Symbolic Link inode"));
tmp_inode->i_op = &cifs_symlink_inode_ops;
/* tmp_inode->i_fop = *//* do not need to set to anything */
} else {
cFYI(1, (" Init special inode "));
cFYI(1, ("Special inode"));
init_special_inode(tmp_inode, tmp_inode->i_mode,
tmp_inode->i_rdev);
}
......@@ -1356,6 +1388,11 @@ static void reset_resume_key(struct file * dir_file,
cifsFile->search_resume_name =
kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
if(cifsFile->search_resume_name == NULL) {
cERROR(1,("failed new resume key allocate, length %d",
cifsFile->resume_name_length));
return;
}
if(Unicode)
cifs_strtoUCS((wchar_t *) cifsFile->search_resume_name,
filename, len, nls_tab);
......@@ -1842,15 +1879,18 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
file->f_pos++;
}
}
pfindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData + le32_to_cpu(pfindData->NextEntryOffset)); /* works also for Unix find struct since this is the first field of both */
/* BB also should check to make sure that pointer is not beyond the end of the SMB */
pfindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData +
le32_to_cpu(pfindData->NextEntryOffset));
/* works also for Unix find struct since first field of both */
/* BB also should check to ensure pointer not beyond end of SMB */
} /* end for loop */
if (findNextParms.EndofSearch != 0) {
cifsFile->endOfSearch = TRUE;
}
} else {
cifsFile->endOfSearch = TRUE;
rc = 0; /* unless parent directory disappeared - do not return error here (eg Access Denied or no more files) */
rc = 0; /* unless parent directory disappeared - do not
return error here (eg Access Denied or no more files) */
}
}
} /* end switch */
......
......@@ -94,7 +94,7 @@ cifs_get_inode_info_unix(struct inode **pinode,
cFYI(1, (" Old time %ld ", cifsInfo->time));
cifsInfo->time = jiffies;
cFYI(1, (" New time %ld ", cifsInfo->time));
atomic_inc(&cifsInfo->inUse); /* inc on every refresh of inode */
atomic_set(&cifsInfo->inUse,1); /* ok to set on every refresh of inode */
inode->i_atime =
cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
......@@ -238,7 +238,6 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
cFYI(1, (" Old time %ld ", cifsInfo->time));
cifsInfo->time = jiffies;
cFYI(1, (" New time %ld ", cifsInfo->time));
atomic_inc(&cifsInfo->inUse); /* inc on every refresh of inode */
/* blksize needs to be multiple of two. So safer to default to blksize
and blkbits set in superblock so 2**blkbits and blksize will match */
......@@ -256,6 +255,8 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
(" Attributes came in as 0x%x ", pfindData->Attributes));
/* set default mode. will override for dirs below */
if(atomic_read(&cifsInfo->inUse) == 0)
/* new inode, can safely set these fields */
inode->i_mode = cifs_sb->mnt_file_mode;
if (pfindData->Attributes & ATTR_REPARSE) {
......@@ -281,8 +282,13 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
/* BB fill in uid and gid here? with help from winbind?
or retrieve from NTFS stream extended attribute */
if(atomic_read(&cifsInfo->inUse) == 0) {
inode->i_uid = cifs_sb->mnt_uid;
inode->i_gid = cifs_sb->mnt_gid;
/* set so we do not keep refreshing these fields with
bad data after user has changed them in memory */
atomic_set(&cifsInfo->inUse,1);
}
if (S_ISREG(inode->i_mode)) {
cFYI(1, (" File inode "));
......
......@@ -153,7 +153,7 @@ cifs_buf_get(void)
albeit slightly larger than necessary and maxbuffersize
defaults to this and can not be bigger */
ret_buf =
(struct smb_hdr *) kmem_cache_alloc(cifs_req_cachep, SLAB_KERNEL);
(struct smb_hdr *) kmem_cache_alloc(cifs_req_cachep, SLAB_KERNEL | SLAB_NOFS);
/* clear the first few header bytes */
if (ret_buf) {
......
......@@ -42,8 +42,12 @@ struct rfc1002_session_packet {
__u16 length;
union {
struct {
__u8 called_name[16];
__u8 calling_name[16];
__u8 called_len;
__u8 called_name[32];
__u8 scope1; /* null */
__u8 calling_len;
__u8 calling_name[32];
__u8 scope2; /* null */
} session_req;
struct {
__u32 retarget_ip_addr;
......
......@@ -6,7 +6,7 @@
SMB authentication protocol
Copyright (C) Andrew Tridgell 1998
Modified by Steve French (sfrench@us.ibm.com) 2002,2003
Modified by Steve French (sfrench@us.ibm.com) 2002,2004
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -44,7 +44,7 @@
should confirm it for yourself (and maybe let me know if you come
up with a different answer to the one above)
*/
#include <linux/slab.h>
#define uchar unsigned char
static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9,
......@@ -191,14 +191,23 @@ static void
dohash(char *out, char *in, char *key, int forw)
{
int i, j, k;
char pk1[56];
char *pk1;
char c[28];
char d[28];
char cd[56];
char *cd;
char ki[16][48];
char pd1[64];
char *pd1;
char l[32], r[32];
char rl[64];
char *rl;
/* Have to reduce stack usage */
pk1 = kmalloc(56+56+64+64,GFP_KERNEL);
if(pk1 == NULL)
return;
cd = pk1 + 56;
pd1= cd + 56;
rl = pd1 + 64;
permute(pk1, key, perm1, 56);
......@@ -223,12 +232,22 @@ dohash(char *out, char *in, char *key, int forw)
}
for (i = 0; i < 16; i++) {
char er[48];
char erk[48];
char *er; /* er[48] */
char *erk; /* erk[48] */
char b[8][6];
char cb[32];
char pcb[32];
char r2[32];
char *cb; /* cb[32] */
char *pcb; /* pcb[32] */
char *r2; /* r2[32] */
er = kmalloc(48+48+32+32+32, GFP_KERNEL);
if(er == NULL) {
kfree(pk1);
return;
}
erk = er+48;
cb = erk+48;
pcb = cb+32;
r2 = pcb+32;
permute(er, r, perm4, 48);
......@@ -262,11 +281,14 @@ dohash(char *out, char *in, char *key, int forw)
for (j = 0; j < 32; j++)
r[j] = r2[j];
kfree(er);
}
concat(rl, r, l, 32, 32);
permute(out, rl, perm6, 64);
kfree(pk1);
}
static void
......@@ -291,11 +313,18 @@ static void
smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
{
int i;
char outb[64];
char inb[64];
char keyb[64];
char *outb; /* outb[64] */
char *inb; /* inb[64] */
char *keyb; /* keyb[64] */
unsigned char key2[8];
outb = kmalloc(64 * 3,GFP_KERNEL);
if(outb == NULL)
return;
inb = outb + 64;
keyb = inb + 64;
str_to_key(key, key2);
for (i = 0; i < 64; i++) {
......@@ -314,6 +343,7 @@ smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
if (outb[i])
out[i / 8] |= (1 << (7 - (i % 8)));
}
kfree(outb);
}
void
......
......@@ -149,19 +149,25 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
temp_fs = get_fs(); /* we must turn off socket api parm checking */
set_fs(get_ds());
while(iov.iov_len > 0) {
rc = sock_sendmsg(ssocket, &smb_msg, smb_buf_length + 4);
while((rc == -ENOSPC) || (rc == -EAGAIN)) {
if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ/2);
rc = sock_sendmsg(ssocket, &smb_msg, smb_buf_length + 4);
continue;
}
if (rc < 0)
break;
iov.iov_base += rc;
iov.iov_len -= rc;
}
set_fs(temp_fs);
if (rc < 0) {
cERROR(1,
("Error %d sending data on socket to server.", rc));
} else
cERROR(1,("Error %d sending data on socket to server.", rc));
} else {
rc = 0;
}
return rc;
}
......@@ -239,7 +245,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
but we still give response a change to complete */
if(midQ->midState & MID_REQUEST_SUBMITTED) {
set_current_state(TASK_UNINTERRUPTIBLE);
timeout = schedule_timeout(2 * HZ);
timeout = sleep_on_timeout(&ses->server->response_q,2 * HZ);
}
} else { /* using normal timeout */
/* timeout = wait_event_interruptible_timeout(ses->server->response_q,
......@@ -250,22 +256,16 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
/* Can not allow user interrupts- wreaks havoc with performance */
if(midQ->midState & MID_REQUEST_SUBMITTED) {
set_current_state(TASK_UNINTERRUPTIBLE);
timeout = schedule_timeout(timeout);
timeout = sleep_on_timeout(&ses->server->response_q,timeout);
}
}
if (signal_pending(current)) {
if (midQ->resp_buf == NULL)
rc = -EINTR; /* BB are we supposed to return -ERESTARTSYS ? */
DeleteMidQEntry(midQ);
return rc; /* why bother returning an error if it succeeded */
} else { /* BB spinlock protect this against races with demux thread */
spin_lock(&GlobalMid_Lock);
if (midQ->resp_buf) {
spin_unlock(&GlobalMid_Lock);
receive_len =
be32_to_cpu(midQ->resp_buf->smb_buf_length);
receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length);
} else {
cFYI(1,("No response buffer"));
cERROR(1,("No response buffer"));
if(midQ->midState == MID_REQUEST_SUBMITTED) {
if(ses->server->tcpStatus == CifsExiting)
rc = -EHOSTDOWN;
......@@ -287,7 +287,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
DeleteMidQEntry(midQ);
return rc;
}
}
if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) {
cERROR(1,
......
......@@ -50,7 +50,7 @@ int fat_get_block(struct inode *inode, sector_t iblock,
BUG();
return -EIO;
}
if (!((unsigned long)iblock % MSDOS_SB(sb)->sec_per_clus)) {
if (!((unsigned long)iblock & (MSDOS_SB(sb)->sec_per_clus - 1))) {
int error;
error = fat_add_cluster(inode);
......
......@@ -557,11 +557,13 @@ static int fat_read_root(struct inode *inode)
* 0/ i_ino - for fast, reliable lookup if still in the cache
* 1/ i_generation - to see if i_ino is still valid
* bit 0 == 0 iff directory
* 2/ i_pos - if ino has changed, but still in cache (hi)
* 3/ i_pos - if ino has changed, but still in cache (low)
* 4/ i_logstart - to semi-verify inode found at i_location
* 5/ parent->i_logstart - maybe used to hunt for the file on disc
* 2/ i_pos(8-39) - if ino has changed, but still in cache
* 3/ i_pos(4-7)|i_logstart - to semi-verify inode found at i_pos
* 4/ i_pos(0-3)|parent->i_logstart - maybe used to hunt for the file on disc
*
* Hack for NFSv2: Maximum FAT entry number is 28bits and maximum
* i_pos is 40bits (blocknr(32) + dir offset(8)), so two 4bits
* of i_logstart is used to store the directory entry offset.
*/
struct dentry *fat_decode_fh(struct super_block *sb, __u32 *fh,
......@@ -572,7 +574,7 @@ struct dentry *fat_decode_fh(struct super_block *sb, __u32 *fh,
if (fhtype != 3)
return ERR_PTR(-ESTALE);
if (len < 6)
if (len < 5)
return ERR_PTR(-ESTALE);
return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable, context);
......@@ -585,13 +587,17 @@ struct dentry *fat_get_dentry(struct super_block *sb, void *inump)
__u32 *fh = inump;
inode = iget(sb, fh[0]);
if (!inode || is_bad_inode(inode) ||
inode->i_generation != fh[1]) {
if (inode) iput(inode);
if (!inode || is_bad_inode(inode) || inode->i_generation != fh[1]) {
if (inode)
iput(inode);
inode = NULL;
}
if (!inode) {
loff_t i_pos = ((loff_t)fh[2] << 32) | fh[3];
loff_t i_pos;
int i_logstart = fh[3] & 0x0fffffff;
i_pos = (loff_t)fh[2] << 8;
i_pos |= ((fh[3] >> 24) & 0xf0) | (fh[4] >> 28);
/* try 2 - see if i_pos is in F-d-c
* require i_logstart to be the same
......@@ -599,7 +605,7 @@ struct dentry *fat_get_dentry(struct super_block *sb, void *inump)
*/
inode = fat_iget(sb, i_pos);
if (inode && MSDOS_I(inode)->i_logstart != fh[4]) {
if (inode && MSDOS_I(inode)->i_logstart != i_logstart) {
iput(inode);
inode = NULL;
}
......@@ -638,17 +644,21 @@ int fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable)
{
int len = *lenp;
struct inode *inode = de->d_inode;
u32 ipos_h, ipos_m, ipos_l;
if (len < 6)
if (len < 5)
return 255; /* no room */
*lenp = 6;
ipos_h = MSDOS_I(inode)->i_pos >> 8;
ipos_m = (MSDOS_I(inode)->i_pos & 0xf0) << 24;
ipos_l = (MSDOS_I(inode)->i_pos & 0x0f) << 28;
*lenp = 5;
fh[0] = inode->i_ino;
fh[1] = inode->i_generation;
fh[2] = (__u32)(MSDOS_I(inode)->i_pos >> 32);
fh[3] = (__u32)MSDOS_I(inode)->i_pos;
fh[4] = MSDOS_I(inode)->i_logstart;
fh[2] = ipos_h;
fh[3] = ipos_m | MSDOS_I(inode)->i_logstart;
spin_lock(&de->d_lock);
fh[5] = MSDOS_I(de->d_parent->d_inode)->i_logstart;
fh[4] = ipos_l | MSDOS_I(de->d_parent->d_inode)->i_logstart;
spin_unlock(&de->d_lock);
return 3;
}
......
......@@ -205,7 +205,7 @@ struct buffer_head *fat_extend_dir(struct inode *inode)
if (inode->i_size & (sb->s_blocksize - 1)) {
fat_fs_panic(sb, "Odd directory size");
inode->i_size = (inode->i_size + sb->s_blocksize)
& ~(sb->s_blocksize - 1);
& ~((loff_t)sb->s_blocksize - 1);
}
inode->i_size += MSDOS_SB(sb)->cluster_size;
MSDOS_I(inode)->mmu_private += MSDOS_SB(sb)->cluster_size;
......
......@@ -4,4 +4,4 @@
obj-$(CONFIG_MSDOS_FS) += msdos.o
msdos-objs := namei.o msdosfs_syms.o
msdos-y := namei.o
/*
* linux/fs/msdos/msdosfs_syms.c
*
* Exported kernel symbols for the MS-DOS filesystem.
* These symbols are used by umsdos.
*/
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/msdos_fs.h>
#include <linux/init.h>
/*
* Support for umsdos fs
*
* These symbols are _always_ exported, in case someone
* wants to install the umsdos module later.
*/
EXPORT_SYMBOL(msdos_create);
EXPORT_SYMBOL(msdos_lookup);
EXPORT_SYMBOL(msdos_mkdir);
EXPORT_SYMBOL(msdos_rename);
EXPORT_SYMBOL(msdos_rmdir);
EXPORT_SYMBOL(msdos_unlink);
static struct super_block *msdos_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super);
}
static struct file_system_type msdos_fs_type = {
.owner = THIS_MODULE,
.name = "msdos",
.get_sb = msdos_get_sb,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
static int __init init_msdos_fs(void)
{
return register_filesystem(&msdos_fs_type);
}
static void __exit exit_msdos_fs(void)
{
unregister_filesystem(&msdos_fs_type);
}
module_init(init_msdos_fs)
module_exit(exit_msdos_fs)
MODULE_LICENSE("GPL");
......@@ -193,7 +193,8 @@ static struct dentry_operations msdos_dentry_operations = {
*/
/***** Get inode using directory and name */
struct dentry *msdos_lookup(struct inode *dir,struct dentry *dentry, struct nameidata *nd)
static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry,
struct nameidata *nd)
{
struct super_block *sb = dir->i_sb;
struct inode *inode = NULL;
......@@ -257,12 +258,8 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name,
return 0;
}
/*
* AV. Huh??? It's exported. Oughtta check usage.
*/
/***** Create a file */
int msdos_create(struct inode *dir,struct dentry *dentry,int mode,
static int msdos_create(struct inode *dir, struct dentry *dentry, int mode,
struct nameidata *nd)
{
struct super_block *sb = dir->i_sb;
......@@ -307,7 +304,7 @@ int msdos_create(struct inode *dir,struct dentry *dentry,int mode,
}
/***** Remove a directory */
int msdos_rmdir(struct inode *dir, struct dentry *dentry)
static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
loff_t i_pos;
......@@ -346,7 +343,7 @@ int msdos_rmdir(struct inode *dir, struct dentry *dentry)
}
/***** Make a directory */
int msdos_mkdir(struct inode *dir,struct dentry *dentry,int mode)
static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
struct super_block *sb = dir->i_sb;
struct buffer_head *bh;
......@@ -413,7 +410,7 @@ int msdos_mkdir(struct inode *dir,struct dentry *dentry,int mode)
}
/***** Unlink a file */
int msdos_unlink( struct inode *dir, struct dentry *dentry)
static int msdos_unlink(struct inode *dir, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
loff_t i_pos;
......@@ -539,8 +536,8 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
}
/***** Rename, a wrapper for rename_same_dir & rename_diff_dir */
int msdos_rename(struct inode *old_dir,struct dentry *old_dentry,
struct inode *new_dir,struct dentry *new_dentry)
static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
struct buffer_head *old_bh;
struct msdos_dir_entry *old_de;
......@@ -576,9 +573,7 @@ int msdos_rename(struct inode *old_dir,struct dentry *old_dentry,
return error;
}
/* The public inode operations for the msdos fs */
struct inode_operations msdos_dir_inode_operations = {
static struct inode_operations msdos_dir_inode_operations = {
.create = msdos_create,
.lookup = msdos_lookup,
.unlink = msdos_unlink,
......@@ -588,7 +583,7 @@ struct inode_operations msdos_dir_inode_operations = {
.setattr = fat_notify_change,
};
int msdos_fill_super(struct super_block *sb,void *data, int silent)
static int msdos_fill_super(struct super_block *sb,void *data, int silent)
{
int res;
......@@ -599,3 +594,34 @@ int msdos_fill_super(struct super_block *sb,void *data, int silent)
sb->s_root->d_op = &msdos_dentry_operations;
return 0;
}
static struct super_block *msdos_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super);
}
static struct file_system_type msdos_fs_type = {
.owner = THIS_MODULE,
.name = "msdos",
.get_sb = msdos_get_sb,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
static int __init init_msdos_fs(void)
{
return register_filesystem(&msdos_fs_type);
}
static void __exit exit_msdos_fs(void)
{
unregister_filesystem(&msdos_fs_type);
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Werner Almesberger");
MODULE_DESCRIPTION("MS-DOS filesystem support");
module_init(init_msdos_fs)
module_exit(exit_msdos_fs)
......@@ -4,4 +4,4 @@
obj-$(CONFIG_VFAT_FS) += vfat.o
vfat-objs := namei.o vfatfs_syms.o
vfat-y := namei.o
......@@ -805,7 +805,8 @@ static int vfat_find(struct inode *dir,struct qstr* qname,
return res ? res : -ENOENT;
}
struct dentry *vfat_lookup(struct inode *dir,struct dentry *dentry, struct nameidata *nd)
static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
struct nameidata *nd)
{
int res;
struct vfat_slot_info sinfo;
......@@ -854,7 +855,7 @@ struct dentry *vfat_lookup(struct inode *dir,struct dentry *dentry, struct namei
return dentry;
}
int vfat_create(struct inode *dir,struct dentry* dentry,int mode,
static int vfat_create(struct inode *dir, struct dentry* dentry, int mode,
struct nameidata *nd)
{
struct super_block *sb = dir->i_sb;
......@@ -866,24 +867,22 @@ int vfat_create(struct inode *dir,struct dentry* dentry,int mode,
lock_kernel();
res = vfat_add_entry(dir, &dentry->d_name, 0, &sinfo, &bh, &de);
if (res < 0) {
unlock_kernel();
return res;
}
if (res < 0)
goto out;
inode = fat_build_inode(sb, de, sinfo.i_pos, &res);
brelse(bh);
if (!inode) {
unlock_kernel();
return res;
}
if (!inode)
goto out;
res = 0;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
mark_inode_dirty(inode);
inode->i_version++;
dir->i_version++;
dentry->d_time = dentry->d_parent->d_inode->i_version;
d_instantiate(dentry,inode);
out:
unlock_kernel();
return 0;
return res;
}
static void vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
......@@ -910,7 +909,7 @@ static void vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
brelse(bh);
}
int vfat_rmdir(struct inode *dir,struct dentry* dentry)
static int vfat_rmdir(struct inode *dir, struct dentry* dentry)
{
int res;
struct vfat_slot_info sinfo;
......@@ -919,16 +918,13 @@ int vfat_rmdir(struct inode *dir,struct dentry* dentry)
lock_kernel();
res = fat_dir_empty(dentry->d_inode);
if (res) {
unlock_kernel();
return res;
}
if (res)
goto out;
res = vfat_find(dir,&dentry->d_name,&sinfo, &bh, &de);
if (res<0) {
unlock_kernel();
return res;
}
if (res < 0)
goto out;
res = 0;
dentry->d_inode->i_nlink = 0;
dentry->d_inode->i_mtime = dentry->d_inode->i_atime = CURRENT_TIME;
fat_detach(dentry->d_inode);
......@@ -936,11 +932,12 @@ int vfat_rmdir(struct inode *dir,struct dentry* dentry)
/* releases bh */
vfat_remove_entry(dir,&sinfo,bh,de);
dir->i_nlink--;
out:
unlock_kernel();
return 0;
return res;
}
int vfat_unlink(struct inode *dir, struct dentry* dentry)
static int vfat_unlink(struct inode *dir, struct dentry *dentry)
{
int res;
struct vfat_slot_info sinfo;
......@@ -949,23 +946,21 @@ int vfat_unlink(struct inode *dir, struct dentry* dentry)
lock_kernel();
res = vfat_find(dir,&dentry->d_name,&sinfo,&bh,&de);
if (res < 0) {
unlock_kernel();
return res;
}
if (res < 0)
goto out;
dentry->d_inode->i_nlink = 0;
dentry->d_inode->i_mtime = dentry->d_inode->i_atime = CURRENT_TIME;
fat_detach(dentry->d_inode);
mark_inode_dirty(dentry->d_inode);
/* releases bh */
vfat_remove_entry(dir,&sinfo,bh,de);
out:
unlock_kernel();
return res;
}
int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
static int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
{
struct super_block *sb = dir->i_sb;
struct inode *inode = NULL;
......@@ -976,13 +971,11 @@ int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
lock_kernel();
res = vfat_add_entry(dir, &dentry->d_name, 1, &sinfo, &bh, &de);
if (res < 0) {
unlock_kernel();
return res;
}
if (res < 0)
goto out;
inode = fat_build_inode(sb, de, sinfo.i_pos, &res);
if (!inode)
goto out;
goto out_brelse;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
mark_inode_dirty(inode);
inode->i_version++;
......@@ -994,8 +987,9 @@ int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
goto mkdir_failed;
dentry->d_time = dentry->d_parent->d_inode->i_version;
d_instantiate(dentry,inode);
out:
out_brelse:
brelse(bh);
out:
unlock_kernel();
return res;
......@@ -1008,12 +1002,11 @@ int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
vfat_remove_entry(dir,&sinfo,bh,de);
iput(inode);
dir->i_nlink--;
unlock_kernel();
return res;
goto out;
}
int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
struct inode *new_dir,struct dentry *new_dentry)
static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
struct buffer_head *old_bh,*new_bh,*dotdot_bh;
struct msdos_dir_entry *old_de,*new_de,*dotdot_de;
......@@ -1101,9 +1094,7 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
}
/* Public inode operations for the VFAT fs */
struct inode_operations vfat_dir_inode_operations = {
static struct inode_operations vfat_dir_inode_operations = {
.create = vfat_create,
.lookup = vfat_lookup,
.unlink = vfat_unlink,
......@@ -1113,7 +1104,7 @@ struct inode_operations vfat_dir_inode_operations = {
.setattr = fat_notify_change,
};
int vfat_fill_super(struct super_block *sb, void *data, int silent)
static int vfat_fill_super(struct super_block *sb, void *data, int silent)
{
int res;
......@@ -1128,3 +1119,34 @@ int vfat_fill_super(struct super_block *sb, void *data, int silent)
return 0;
}
static struct super_block *vfat_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
return get_sb_bdev(fs_type, flags, dev_name, data, vfat_fill_super);
}
static struct file_system_type vfat_fs_type = {
.owner = THIS_MODULE,
.name = "vfat",
.get_sb = vfat_get_sb,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
static int __init init_vfat_fs(void)
{
return register_filesystem(&vfat_fs_type);
}
static void __exit exit_vfat_fs(void)
{
unregister_filesystem(&vfat_fs_type);
}
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("VFAT filesystem support");
MODULE_AUTHOR("Gordon Chaffee");
module_init(init_vfat_fs)
module_exit(exit_vfat_fs)
/*
* linux/fs/msdos/vfatfs_syms.c
*
* Exported kernel symbols for the VFAT filesystem.
* These symbols are used by dmsdos.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/msdos_fs.h>
static struct super_block *vfat_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
return get_sb_bdev(fs_type, flags, dev_name, data, vfat_fill_super);
}
static struct file_system_type vfat_fs_type = {
.owner = THIS_MODULE,
.name = "vfat",
.get_sb = vfat_get_sb,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
EXPORT_SYMBOL(vfat_create);
EXPORT_SYMBOL(vfat_unlink);
EXPORT_SYMBOL(vfat_mkdir);
EXPORT_SYMBOL(vfat_rmdir);
EXPORT_SYMBOL(vfat_rename);
EXPORT_SYMBOL(vfat_lookup);
static int __init init_vfat_fs(void)
{
return register_filesystem(&vfat_fs_type);
}
static void __exit exit_vfat_fs(void)
{
unregister_filesystem(&vfat_fs_type);
}
module_init(init_vfat_fs)
module_exit(exit_vfat_fs)
MODULE_LICENSE("GPL");
......@@ -363,7 +363,18 @@
#define __NR_stat64 425
#define __NR_lstat64 426
#define __NR_fstat64 427
#define NR_SYSCALLS 428
#define __NR_vserver 428
#define __NR_mbind 429
#define __NR_get_mempolicy 430
#define __NR_set_mempolicy 431
#define __NR_mq_open 432
#define __NR_mq_unlink 433
#define __NR_mq_timedsend 434
#define __NR_mq_timedreceive 435
#define __NR_mq_notify 436
#define __NR_mq_getsetattr 437
#define NR_SYSCALLS 438
#if defined(__GNUC__)
......
......@@ -115,12 +115,12 @@ static inline unsigned long generic_hweight64(__u64 w)
generic_hweight32((unsigned int)w);
#else
u64 res;
res = (w & 0x5555555555555555) + ((w >> 1) & 0x5555555555555555);
res = (res & 0x3333333333333333) + ((res >> 2) & 0x3333333333333333);
res = (res & 0x0F0F0F0F0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F0F0F0F0F);
res = (res & 0x00FF00FF00FF00FF) + ((res >> 8) & 0x00FF00FF00FF00FF);
res = (res & 0x0000FFFF0000FFFF) + ((res >> 16) & 0x0000FFFF0000FFFF);
return (res & 0x00000000FFFFFFFF) + ((res >> 32) & 0x00000000FFFFFFFF);
res = (w & 0x5555555555555555ul) + ((w >> 1) & 0x5555555555555555ul);
res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul);
res = (res & 0x0F0F0F0F0F0F0F0Ful) + ((res >> 4) & 0x0F0F0F0F0F0F0F0Ful);
res = (res & 0x00FF00FF00FF00FFul) + ((res >> 8) & 0x00FF00FF00FF00FFul);
res = (res & 0x0000FFFF0000FFFFul) + ((res >> 16) & 0x0000FFFF0000FFFFul);
return (res & 0x00000000FFFFFFFFul) + ((res >> 32) & 0x00000000FFFFFFFFul);
#endif
}
......
......@@ -309,29 +309,6 @@ static __inline__ int fat_get_entry(struct inode *dir, loff_t *pos,
return fat__get_entry(dir, pos, bh, de, i_pos);
}
/* msdos/namei.c - these are for Umsdos */
extern struct dentry *msdos_lookup(struct inode *dir, struct dentry *, struct nameidata *);
extern int msdos_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *);
extern int msdos_rmdir(struct inode *dir, struct dentry *dentry);
extern int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode);
extern int msdos_unlink(struct inode *dir, struct dentry *dentry);
extern int msdos_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry);
extern int msdos_fill_super(struct super_block *sb, void *data, int silent);
/* vfat/namei.c - these are for dmsdos */
extern struct dentry *vfat_lookup(struct inode *dir, struct dentry *, struct nameidata *);
extern int vfat_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *);
extern int vfat_rmdir(struct inode *dir, struct dentry *dentry);
extern int vfat_unlink(struct inode *dir, struct dentry *dentry);
extern int vfat_mkdir(struct inode *dir, struct dentry *dentry, int mode);
extern int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry);
extern int vfat_fill_super(struct super_block *sb, void *data, int silent);
/* vfat/vfatfs_syms.c */
extern struct file_system_type vfat_fs_type;
#endif /* __KERNEL__ */
#endif
......@@ -5,6 +5,7 @@
#ifdef __KERNEL__
#include <linux/compiler.h> /* for inline */
#include <linux/types.h> /* for size_t */
#include <linux/stddef.h> /* for NULL */
......
......@@ -45,12 +45,13 @@ void fastcall init_rwsem(struct rw_semaphore *sem)
* - the 'active count' _reached_ zero
* - the 'waiting count' is non-zero
* - the spinlock must be held by the caller
* - woken process blocks are discarded from the list after having flags zeroised
* - woken process blocks are discarded from the list after having task zeroed
* - writers are only woken if wakewrite is non-zero
*/
static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int wakewrite)
{
struct rwsem_waiter *waiter;
struct task_struct *tsk;
int woken;
rwsemtrace(sem,"Entering __rwsem_do_wake");
......@@ -70,8 +71,10 @@ static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int
if (waiter->flags & RWSEM_WAITING_FOR_WRITE) {
sem->activity = -1;
list_del(&waiter->list);
waiter->flags = 0;
wake_up_process(waiter->task);
mb();
tsk = waiter->task;
waiter->task = NULL;
wake_up_process(tsk);
goto out;
}
......@@ -82,8 +85,10 @@ static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int
struct list_head *next = waiter->list.next;
list_del(&waiter->list);
waiter->flags = 0;
wake_up_process(waiter->task);
mb();
tsk = waiter->task;
waiter->task = NULL;
wake_up_process(tsk);
woken++;
if (list_empty(&sem->wait_list))
break;
......@@ -103,14 +108,17 @@ static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int
static inline struct rw_semaphore *__rwsem_wake_one_writer(struct rw_semaphore *sem)
{
struct rwsem_waiter *waiter;
struct task_struct *tsk;
sem->activity = -1;
waiter = list_entry(sem->wait_list.next,struct rwsem_waiter,list);
list_del(&waiter->list);
waiter->flags = 0;
wake_up_process(waiter->task);
mb();
tsk = waiter->task;
waiter->task = NULL;
wake_up_process(tsk);
return sem;
}
......@@ -147,7 +155,7 @@ void fastcall __down_read(struct rw_semaphore *sem)
/* wait to be given the lock */
for (;;) {
if (!waiter.flags)
if (!waiter.task)
break;
schedule();
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
......@@ -215,7 +223,7 @@ void fastcall __down_write(struct rw_semaphore *sem)
/* wait to be given the lock */
for (;;) {
if (!waiter.flags)
if (!waiter.task)
break;
schedule();
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
......
......@@ -34,12 +34,13 @@ void rwsemtrace(struct rw_semaphore *sem, const char *str)
* - the 'waiting part' of the count (&0xffff0000) is negative (and will still be so)
* - there must be someone on the queue
* - the spinlock must be held by the caller
* - woken process blocks are discarded from the list after having flags zeroised
* - woken process blocks are discarded from the list after having task zeroed
* - writers are only woken if wakewrite is non-zero
*/
static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int wakewrite)
{
struct rwsem_waiter *waiter;
struct task_struct *tsk;
struct list_head *next;
signed long oldcount, woken, loop;
......@@ -64,8 +65,10 @@ static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int
goto readers_only;
list_del(&waiter->list);
waiter->flags = 0;
wake_up_process(waiter->task);
mb();
tsk = waiter->task;
waiter->task = NULL;
wake_up_process(tsk);
goto out;
/* don't want to wake any writers */
......@@ -99,8 +102,10 @@ static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int
for (; loop>0; loop--) {
waiter = list_entry(next,struct rwsem_waiter,list);
next = waiter->list.next;
waiter->flags = 0;
wake_up_process(waiter->task);
mb();
tsk = waiter->task;
waiter->task = NULL;
wake_up_process(tsk);
}
sem->wait_list.next = next;
......@@ -148,7 +153,7 @@ static inline struct rw_semaphore *rwsem_down_failed_common(struct rw_semaphore
/* wait to be given the lock */
for (;;) {
if (!waiter->flags)
if (!waiter->task)
break;
schedule();
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
......
......@@ -1479,7 +1479,7 @@ static void neigh_app_notify(struct neighbour *n)
#ifdef CONFIG_SYSCTL
struct neigh_sysctl_table {
static struct neigh_sysctl_table {
struct ctl_table_header *sysctl_header;
ctl_table neigh_vars[17];
ctl_table neigh_dev[2];
......
......@@ -280,7 +280,7 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
return err;
}
int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
{
int idx;
int s_idx = cb->family;
......@@ -553,7 +553,7 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi
return NOTIFY_DONE;
}
struct notifier_block rtnetlink_dev_notifier = {
static struct notifier_block rtnetlink_dev_notifier = {
.notifier_call = rtnetlink_event,
};
......
......@@ -144,7 +144,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
static int rt_garbage_collect(void);
struct dst_ops ipv4_dst_ops = {
static struct dst_ops ipv4_dst_ops = {
.family = AF_INET,
.protocol = __constant_htons(ETH_P_IP),
.gc = rt_garbage_collect,
......@@ -1525,7 +1525,7 @@ static int ip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr,
* 2. IP spoofing attempts are filtered with 100% of guarantee.
*/
int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
static int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
u8 tos, struct net_device *dev)
{
struct fib_result res;
......@@ -1910,7 +1910,7 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
* Major route resolver routine.
*/
int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
{
u32 tos = oldflp->fl4_tos & (IPTOS_RT_MASK | RTO_ONLINK);
struct flowi fl = { .nl_u = { .ip4_u =
......
......@@ -2137,46 +2137,6 @@ static inline struct tcp_tw_bucket *tw_next(struct tcp_tw_bucket *tw)
hlist_entry(tw->tw_node.next, typeof(*tw), tw_node) : NULL;
}
static void *listening_get_first(struct seq_file *seq)
{
struct tcp_iter_state* st = seq->private;
void *rc = NULL;
for (st->bucket = 0; st->bucket < TCP_LHTABLE_SIZE; ++st->bucket) {
struct open_request *req;
struct tcp_opt *tp;
struct sock *sk = sk_head(&tcp_listening_hash[st->bucket]);
if (!sk)
continue;
if (sk->sk_family == st->family) {
rc = sk;
goto out;
}
tp = tcp_sk(sk);
read_lock_bh(&tp->syn_wait_lock);
if (tp->listen_opt && tp->listen_opt->qlen) {
st->uid = sock_i_uid(sk);
st->syn_wait_sk = sk;
st->state = TCP_SEQ_STATE_OPENREQ;
for (st->sbucket = 0; st->sbucket < TCP_SYNQ_HSIZE;
++st->sbucket) {
for (req = tp->listen_opt->syn_table[st->sbucket];
req; req = req->dl_next) {
if (req->class->family != st->family)
continue;
rc = req;
goto out;
}
}
st->state = TCP_SEQ_STATE_LISTENING;
}
read_unlock_bh(&tp->syn_wait_lock);
}
out:
return rc;
}
static void *listening_get_next(struct seq_file *seq, void *cur)
{
struct tcp_opt *tp;
......@@ -2184,6 +2144,12 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
struct sock *sk = cur;
struct tcp_iter_state* st = seq->private;
if (!sk) {
st->bucket = 0;
sk = sk_head(&tcp_listening_hash[0]);
goto get_sk;
}
++st->num;
if (st->state == TCP_SEQ_STATE_OPENREQ) {
......@@ -2237,7 +2203,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
static void *listening_get_idx(struct seq_file *seq, loff_t *pos)
{
void *rc = listening_get_first(seq);
void *rc = listening_get_next(seq, NULL);
while (rc && *pos) {
rc = listening_get_next(seq, rc);
......
......@@ -539,7 +539,7 @@ struct proto_ops inet6_dgram_ops = {
.sendpage = sock_no_sendpage,
};
struct net_proto_family inet6_family_ops = {
static struct net_proto_family inet6_family_ops = {
.family = PF_INET6,
.create = inet6_create,
.owner = THIS_MODULE,
......
......@@ -1418,7 +1418,7 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event,
return NOTIFY_DONE;
}
struct notifier_block ndisc_netdev_notifier = {
static struct notifier_block ndisc_netdev_notifier = {
.notifier_call = ndisc_netdev_event,
};
......
......@@ -809,7 +809,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
return err ? : copied;
}
void netlink_data_ready(struct sock *sk, int len)
static void netlink_data_ready(struct sock *sk, int len)
{
struct netlink_opt *nlk = nlk_sk(sk);
......@@ -1126,7 +1126,7 @@ static int netlink_seq_show(struct seq_file *seq, void *v)
return 0;
}
struct seq_operations netlink_seq_ops = {
static struct seq_operations netlink_seq_ops = {
.start = netlink_seq_start,
.next = netlink_seq_next,
.stop = netlink_seq_stop,
......@@ -1159,7 +1159,7 @@ int netlink_unregister_notifier(struct notifier_block *nb)
return notifier_chain_unregister(&netlink_chain, nb);
}
struct proto_ops netlink_ops = {
static struct proto_ops netlink_ops = {
.family = PF_NETLINK,
.owner = THIS_MODULE,
.release = netlink_release,
......@@ -1180,7 +1180,7 @@ struct proto_ops netlink_ops = {
.sendpage = sock_no_sendpage,
};
struct net_proto_family netlink_family_ops = {
static struct net_proto_family netlink_family_ops = {
.family = PF_NETLINK,
.create = netlink_create,
.owner = THIS_MODULE, /* for consistency 8) */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment