diff -urN linux-2.4.18-pre9/Documentation/filesystems/Locking linux/Documentation/filesystems/Locking --- linux-2.4.18-pre9/Documentation/filesystems/Locking Thu Feb 7 15:27:09 2002 +++ linux/Documentation/filesystems/Locking Mon Feb 11 20:44:25 2002 @@ -234,7 +234,7 @@ locking rules: All except ->poll() may block. BKL -llseek: yes +llseek: yes (see below) read: no write: no readdir: yes (see below) @@ -250,6 +250,13 @@ readv: no writev: no +->llseek() locking has moved from llseek to the individual llseek +implementations. If your fs is not using generic_file_llseek, you +need to acquire and release the appropriate lock(s) in your ->llseek(). +For many filesystems, it is probably safe to acquire the inode +semaphore. Note some filesystems (i.e. remote ones) provide no +protection for i_size so you will need to use the BKL. + ->open() locking is in-transit: big lock partially moved into the methods. The only exception is ->open() in the instances of file_operations that never end up in ->i_fop/->proc_fops, i.e. ones that belong to character devices diff -urN linux-2.4.18-pre9/arch/cris/drivers/eeprom.c linux/arch/cris/drivers/eeprom.c --- linux-2.4.18-pre9/arch/cris/drivers/eeprom.c Thu Feb 7 15:27:08 2002 +++ linux/arch/cris/drivers/eeprom.c Mon Feb 11 20:44:40 2002 @@ -71,6 +71,7 @@ #include #include #include +#include #include #include "i2c.h" @@ -445,36 +446,39 @@ * orig 1: relative from current position * orig 2: position from last eeprom address */ - + loff_t ret; + + lock_kernel(); switch (orig) { case 0: - file->f_pos = offset; + ret = file->f_pos = offset; break; case 1: - file->f_pos += offset; + ret = file->f_pos += offset; break; case 2: - file->f_pos = eeprom.size - offset; + ret = file->f_pos = eeprom.size - offset; break; default: - return -EINVAL; + ret = -EINVAL; } /* truncate position */ if (file->f_pos < 0) { file->f_pos = 0; - return(-EOVERFLOW); + unlock_kernel(); + ret = -EOVERFLOW; } if (file->f_pos >= eeprom.size) { file->f_pos = eeprom.size - 1; - return(-EOVERFLOW); + ret = -EOVERFLOW; } - return ( file->f_pos ); + return ( ret ); } /* Reads data from eeprom. */ diff -urN linux-2.4.18-pre9/arch/i386/kernel/cpuid.c linux/arch/i386/kernel/cpuid.c --- linux-2.4.18-pre9/arch/i386/kernel/cpuid.c Thu Feb 7 15:26:57 2002 +++ linux/arch/i386/kernel/cpuid.c Mon Feb 11 20:46:00 2002 @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -82,16 +83,25 @@ static loff_t cpuid_seek(struct file *file, loff_t offset, int orig) { + loff_t ret; + + lock_kernel(); + switch (orig) { case 0: file->f_pos = offset; - return file->f_pos; + ret = file->f_pos; + break; case 1: file->f_pos += offset; - return file->f_pos; + ret = file->f_pos; + break; default: - return -EINVAL; /* SEEK_END not supported */ + ret = -EINVAL; } + + unlock_kernel(); + return ret; } static ssize_t cpuid_read(struct file * file, char * buf, diff -urN linux-2.4.18-pre9/arch/i386/kernel/msr.c linux/arch/i386/kernel/msr.c --- linux-2.4.18-pre9/arch/i386/kernel/msr.c Thu Feb 7 15:26:57 2002 +++ linux/arch/i386/kernel/msr.c Mon Feb 11 20:44:40 2002 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -162,16 +163,19 @@ static loff_t msr_seek(struct file *file, loff_t offset, int orig) { + loff_t ret = -EINVAL; + lock_kernel(); switch (orig) { case 0: file->f_pos = offset; - return file->f_pos; + ret = file->f_pos; + break; case 1: file->f_pos += offset; - return file->f_pos; - default: - return -EINVAL; /* SEEK_END not supported */ + ret = file->f_pos; } + unlock_kernel(); + return ret; } static ssize_t msr_read(struct file * file, char * buf, diff -urN linux-2.4.18-pre9/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c --- linux-2.4.18-pre9/arch/ppc/kernel/ppc_htab.c Thu Feb 7 15:27:01 2002 +++ linux/arch/ppc/kernel/ppc_htab.c Mon Feb 11 20:44:40 2002 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -430,18 +431,20 @@ static long long ppc_htab_lseek(struct file * file, loff_t offset, int orig) { + long long ret = -EINVAL; + + lock_kernel(); switch (orig) { case 0: file->f_pos = offset; - return(file->f_pos); + ret = file->f_pos; + break; case 1: file->f_pos += offset; - return(file->f_pos); - case 2: - return(-EINVAL); - default: - return(-EINVAL); + ret = file->f_pos; } + unlock_kernel(); + return ret; } int proc_dol2crvec(ctl_table *table, int write, struct file *filp, diff -urN linux-2.4.18-pre9/drivers/char/mem.c linux/drivers/char/mem.c --- linux-2.4.18-pre9/drivers/char/mem.c Thu Feb 7 15:26:33 2002 +++ linux/drivers/char/mem.c Mon Feb 11 20:44:40 2002 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -503,16 +504,23 @@ */ static loff_t memory_lseek(struct file * file, loff_t offset, int orig) { + int ret; + + lock_kernel(); switch (orig) { case 0: file->f_pos = offset; - return file->f_pos; + ret = file->f_pos; + break; case 1: file->f_pos += offset; - return file->f_pos; + ret = file->f_pos; + break; default: - return -EINVAL; + ret = -EINVAL; } + unlock_kernel(); + return ret; } static int open_port(struct inode * inode, struct file * filp) diff -urN linux-2.4.18-pre9/drivers/char/nvram.c linux/drivers/char/nvram.c --- linux-2.4.18-pre9/drivers/char/nvram.c Thu Feb 7 15:26:33 2002 +++ linux/drivers/char/nvram.c Mon Feb 11 20:44:40 2002 @@ -213,6 +213,7 @@ static long long nvram_llseek(struct file *file,loff_t offset, int origin ) { + lock_kernel(); switch( origin ) { case 0: /* nothing to do */ @@ -224,6 +225,7 @@ offset += NVRAM_BYTES; break; } + unlock_kernel(); return( (offset >= 0) ? (file->f_pos = offset) : -EINVAL ); } diff -urN linux-2.4.18-pre9/drivers/char/nwflash.c linux/drivers/char/nwflash.c --- linux-2.4.18-pre9/drivers/char/nwflash.c Thu Feb 7 15:26:34 2002 +++ linux/drivers/char/nwflash.c Mon Feb 11 20:44:40 2002 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -301,30 +302,45 @@ */ static long long flash_llseek(struct file *file, long long offset, int orig) { + long long ret; + + lock_kernel(); if (flashdebug) printk(KERN_DEBUG "flash_llseek: offset=0x%X, orig=0x%X.\n", (unsigned int) offset, orig); switch (orig) { case 0: - if (offset < 0) - return -EINVAL; + if (offset < 0) { + ret = -EINVAL; + break; + } - if ((unsigned int) offset > gbFlashSize) - return -EINVAL; + if ((unsigned int) offset > gbFlashSize) { + ret = -EINVAL; + break; + } file->f_pos = (unsigned int) offset; - return file->f_pos; + ret = file->f_pos; + break; case 1: - if ((file->f_pos + offset) > gbFlashSize) - return -EINVAL; - if ((file->f_pos + offset) < 0) - return -EINVAL; + if ((file->f_pos + offset) > gbFlashSize) { + ret = -EINVAL; + break; + } + if ((file->f_pos + offset) < 0) { + ret = -EINVAL; + break; + } file->f_pos += offset; - return file->f_pos; + ret = file->f_pos; + break; default: - return -EINVAL; + ret = -EINVAL; } + unlock_kernel(); + return ret; } diff -urN linux-2.4.18-pre9/drivers/char/vc_screen.c linux/drivers/char/vc_screen.c --- linux-2.4.18-pre9/drivers/char/vc_screen.c Thu Feb 7 15:26:33 2002 +++ linux/drivers/char/vc_screen.c Mon Feb 11 20:44:40 2002 @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -66,10 +67,13 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig) { - int size = vcs_size(file->f_dentry->d_inode); + int size; + lock_kernel(); + size = vcs_size(file->f_dentry->d_inode); switch (orig) { default: + unlock_kernel(); return -EINVAL; case 2: offset += size; @@ -79,9 +83,12 @@ case 0: break; } - if (offset < 0 || offset > size) + if (offset < 0 || offset > size) { + unlock_kernel(); return -EINVAL; + } file->f_pos = offset; + unlock_kernel(); return file->f_pos; } diff -urN linux-2.4.18-pre9/drivers/ieee1394/pcilynx.c linux/drivers/ieee1394/pcilynx.c --- linux-2.4.18-pre9/drivers/ieee1394/pcilynx.c Thu Feb 7 15:26:51 2002 +++ linux/drivers/ieee1394/pcilynx.c Mon Feb 11 20:44:40 2002 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -891,8 +892,9 @@ loff_t mem_llseek(struct file *file, loff_t offs, int orig) { - loff_t newoffs; + loff_t newoffs = -1; + lock_kernel(); switch (orig) { case 0: newoffs = offs; @@ -902,12 +904,12 @@ break; case 2: newoffs = PCILYNX_MAX_MEMORY + 1 + offs; - break; - default: - return -EINVAL; } - if (newoffs < 0 || newoffs > PCILYNX_MAX_MEMORY + 1) return -EINVAL; + if (newoffs < 0 || newoffs > PCILYNX_MAX_MEMORY + 1) { + lock_kernel(); + return -EINVAL; + } file->f_pos = newoffs; return newoffs; diff -urN linux-2.4.18-pre9/drivers/macintosh/nvram.c linux/drivers/macintosh/nvram.c --- linux-2.4.18-pre9/drivers/macintosh/nvram.c Thu Feb 7 15:26:47 2002 +++ linux/drivers/macintosh/nvram.c Mon Feb 11 20:44:40 2002 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -20,6 +21,7 @@ static loff_t nvram_llseek(struct file *file, loff_t offset, int origin) { + lock_kernel(); switch (origin) { case 1: offset += file->f_pos; @@ -28,9 +30,12 @@ offset += NVRAM_SIZE; break; } - if (offset < 0) + if (offset < 0) { + unlock_kernel(); return -EINVAL; + } file->f_pos = offset; + unlock_kernel(); return file->f_pos; } diff -urN linux-2.4.18-pre9/drivers/mtd/mtdchar.c linux/drivers/mtd/mtdchar.c --- linux-2.4.18-pre9/drivers/mtd/mtdchar.c Thu Feb 7 15:26:53 2002 +++ linux/drivers/mtd/mtdchar.c Mon Feb 11 20:44:40 2002 @@ -10,6 +10,7 @@ #include #include #include +#include #include #ifdef CONFIG_DEVFS_FS @@ -31,6 +32,7 @@ { struct mtd_info *mtd=(struct mtd_info *)file->private_data; + lock_kernel(); switch (orig) { case 0: /* SEEK_SET */ @@ -45,6 +47,7 @@ file->f_pos =mtd->size + offset; break; default: + unlock_kernel(); return -EINVAL; } @@ -53,6 +56,7 @@ else if (file->f_pos >= mtd->size) file->f_pos = mtd->size - 1; + unlock_kernel(); return file->f_pos; } diff -urN linux-2.4.18-pre9/drivers/pci/proc.c linux/drivers/pci/proc.c --- linux-2.4.18-pre9/drivers/pci/proc.c Thu Feb 7 15:26:42 2002 +++ linux/drivers/pci/proc.c Mon Feb 11 20:44:40 2002 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -21,8 +22,9 @@ static loff_t proc_bus_pci_lseek(struct file *file, loff_t off, int whence) { - loff_t new; + loff_t new = -1; + lock_kernel(); switch (whence) { case 0: new = off; @@ -33,9 +35,8 @@ case 2: new = PCI_CFG_SPACE_SIZE + off; break; - default: - return -EINVAL; } + unlock_kernel(); if (new < 0 || new > PCI_CFG_SPACE_SIZE) return -EINVAL; return (file->f_pos = new); diff -urN linux-2.4.18-pre9/drivers/pnp/isapnp_proc.c linux/drivers/pnp/isapnp_proc.c --- linux-2.4.18-pre9/drivers/pnp/isapnp_proc.c Thu Feb 7 15:26:44 2002 +++ linux/drivers/pnp/isapnp_proc.c Mon Feb 11 20:44:40 2002 @@ -84,18 +84,26 @@ static loff_t isapnp_info_entry_lseek(struct file *file, loff_t offset, int orig) { + loff_t ret; + + lock_kernel(); + switch (orig) { case 0: /* SEEK_SET */ file->f_pos = offset; - return file->f_pos; + ret = file->f_pos; + break; case 1: /* SEEK_CUR */ file->f_pos += offset; - return file->f_pos; + ret = file->f_pos; + break; case 2: /* SEEK_END */ default: - return -EINVAL; + ret = -EINVAL; } - return -ENXIO; + + unlock_kernel(); + return ret; } static ssize_t isapnp_info_entry_read(struct file *file, char *buffer, @@ -215,8 +223,9 @@ static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence) { - loff_t new; - + loff_t new = -1; + + lock_kernel(); switch (whence) { case 0: new = off; @@ -227,11 +236,12 @@ case 2: new = 256 + off; break; - default: - return -EINVAL; } - if (new < 0 || new > 256) + if (new < 0 || new > 256) { + unlock_kernel(); return -EINVAL; + } + unlock_kernel(); return (file->f_pos = new); } diff -urN linux-2.4.18-pre9/drivers/sbus/char/flash.c linux/drivers/sbus/char/flash.c --- linux-2.4.18-pre9/drivers/sbus/char/flash.c Thu Feb 7 15:26:43 2002 +++ linux/drivers/sbus/char/flash.c Mon Feb 11 20:44:40 2002 @@ -83,6 +83,7 @@ static long long flash_llseek(struct file *file, long long offset, int origin) { + lock_kernel(); switch (origin) { case 0: file->f_pos = offset; @@ -96,8 +97,10 @@ file->f_pos = flash.read_size; break; default: + unlock_kernel(); return -EINVAL; } + unlock_kernel(); return file->f_pos; } diff -urN linux-2.4.18-pre9/drivers/sbus/char/jsflash.c linux/drivers/sbus/char/jsflash.c --- linux-2.4.18-pre9/drivers/sbus/char/jsflash.c Thu Feb 7 15:26:43 2002 +++ linux/drivers/sbus/char/jsflash.c Mon Feb 11 20:44:40 2002 @@ -259,16 +259,23 @@ */ static loff_t jsf_lseek(struct file * file, loff_t offset, int orig) { + loff_t ret; + + lock_kernel(); switch (orig) { case 0: file->f_pos = offset; - return file->f_pos; + ret = file->f_pos; + break; case 1: file->f_pos += offset; - return file->f_pos; + ret = file->f_pos; + break; default: - return -EINVAL; + ret = -EINVAL; } + unlock_kernel(); + return ret; } /* diff -urN linux-2.4.18-pre9/drivers/usb/devices.c linux/drivers/usb/devices.c --- linux-2.4.18-pre9/drivers/usb/devices.c Thu Feb 7 15:26:48 2002 +++ linux/drivers/usb/devices.c Mon Feb 11 20:44:40 2002 @@ -554,21 +554,26 @@ static loff_t usb_device_lseek(struct file * file, loff_t offset, int orig) { + loff_t ret; + + lock_kernel(); + switch (orig) { case 0: file->f_pos = offset; - return file->f_pos; - + ret = file->f_pos; + break; case 1: file->f_pos += offset; - return file->f_pos; - + ret = file->f_pos; + break; case 2: - return -EINVAL; - default: - return -EINVAL; + ret = -EINVAL; } + + unlock_kernel(); + return ret; } struct file_operations usbdevfs_devices_fops = { diff -urN linux-2.4.18-pre9/drivers/usb/devio.c linux/drivers/usb/devio.c --- linux-2.4.18-pre9/drivers/usb/devio.c Thu Feb 7 15:26:48 2002 +++ linux/drivers/usb/devio.c Mon Feb 11 20:44:40 2002 @@ -57,21 +57,26 @@ static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig) { + loff_t ret; + + lock_kernel(); + switch (orig) { case 0: file->f_pos = offset; - return file->f_pos; - + ret = file->f_pos; + break; case 1: file->f_pos += offset; - return file->f_pos; - + ret = file->f_pos; + break; case 2: - return -EINVAL; - default: - return -EINVAL; + ret = -EINVAL; } + + unlock_kernel(); + return ret; } static ssize_t usbdev_read(struct file *file, char * buf, size_t nbytes, loff_t *ppos) diff -urN linux-2.4.18-pre9/drivers/usb/drivers.c linux/drivers/usb/drivers.c --- linux-2.4.18-pre9/drivers/usb/drivers.c Thu Feb 7 15:26:48 2002 +++ linux/drivers/usb/drivers.c Mon Feb 11 20:44:40 2002 @@ -38,6 +38,7 @@ #include #include #include +#include #include /*****************************************************************/ @@ -96,21 +97,24 @@ static loff_t usb_driver_lseek(struct file * file, loff_t offset, int orig) { + loff_t ret; + + lock_kernel(); switch (orig) { case 0: file->f_pos = offset; - return file->f_pos; - + ret = file->f_pos; + break; case 1: file->f_pos += offset; - return file->f_pos; - + ret = file->f_pos; + break; case 2: - return -EINVAL; - default: - return -EINVAL; + ret = -EINVAL; } + unlock_kernel(); + return ret; } struct file_operations usbdevfs_drivers_fops = { diff -urN linux-2.4.18-pre9/drivers/usb/uhci-debug.h linux/drivers/usb/uhci-debug.h --- linux-2.4.18-pre9/drivers/usb/uhci-debug.h Thu Feb 7 15:26:48 2002 +++ linux/drivers/usb/uhci-debug.h Mon Feb 11 20:44:41 2002 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "uhci.h" @@ -507,8 +508,11 @@ static loff_t uhci_proc_lseek(struct file *file, loff_t off, int whence) { - struct uhci_proc *up = file->private_data; - loff_t new; + struct uhci_proc *up; + loff_t new = -1; + + lock_kernel(); + up = file->private_data; switch (whence) { case 0: @@ -517,12 +521,12 @@ case 1: new = file->f_pos + off; break; - case 2: - default: - return -EINVAL; } - if (new < 0 || new > up->size) + if (new < 0 || new > up->size) { + unlock_kernel(); return -EINVAL; + } + unlock_kernel(); return (file->f_pos = new); } diff -urN linux-2.4.18-pre9/drivers/zorro/proc.c linux/drivers/zorro/proc.c --- linux-2.4.18-pre9/drivers/zorro/proc.c Thu Feb 7 15:26:48 2002 +++ linux/drivers/zorro/proc.c Mon Feb 11 20:46:22 2002 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -21,8 +22,9 @@ static loff_t proc_bus_zorro_lseek(struct file *file, loff_t off, int whence) { - loff_t new; + loff_t new = -1; + lock_kernel(); switch (whence) { case 0: new = off; @@ -33,11 +35,12 @@ case 2: new = sizeof(struct ConfigDev) + off; break; - default: - return -EINVAL; } - if (new < 0 || new > sizeof(struct ConfigDev)) + if (new < 0 || new > sizeof(struct ConfigDev)) { + unlock_kernel(); return -EINVAL; + } + unlock_kernel(); return (file->f_pos = new); } diff -urN linux-2.4.18-pre9/fs/block_dev.c linux/fs/block_dev.c --- linux-2.4.18-pre9/fs/block_dev.c Thu Feb 7 15:26:12 2002 +++ linux/fs/block_dev.c Mon Feb 11 20:41:35 2002 @@ -149,6 +149,7 @@ loff_t size = file->f_dentry->d_inode->i_bdev->bd_inode->i_size; loff_t retval; + lock_kernel(); switch (origin) { case 2: offset += size; @@ -165,6 +166,7 @@ } retval = offset; } + unlock_kernel(); return retval; } diff -urN linux-2.4.18-pre9/fs/hfs/file_cap.c linux/fs/hfs/file_cap.c --- linux-2.4.18-pre9/fs/hfs/file_cap.c Thu Feb 7 15:26:13 2002 +++ linux/fs/hfs/file_cap.c Mon Feb 11 20:41:35 2002 @@ -24,6 +24,7 @@ #include #include #include +#include /*================ Forward declarations ================*/ static loff_t cap_info_llseek(struct file *, loff_t, @@ -91,6 +92,7 @@ { long long retval; + lock_kernel(); switch (origin) { case 2: offset += file->f_dentry->d_inode->i_size; @@ -107,6 +109,7 @@ } retval = offset; } + unlock_kernel(); return retval; } diff -urN linux-2.4.18-pre9/fs/hfs/file_hdr.c linux/fs/hfs/file_hdr.c --- linux-2.4.18-pre9/fs/hfs/file_hdr.c Thu Feb 7 15:26:13 2002 +++ linux/fs/hfs/file_hdr.c Mon Feb 11 20:41:35 2002 @@ -29,6 +29,7 @@ #include #include #include +#include /* prodos types */ #define PRODOSI_FTYPE_DIR 0x0F @@ -347,6 +348,7 @@ { long long retval; + lock_kernel(); switch (origin) { case 2: offset += file->f_dentry->d_inode->i_size; @@ -363,6 +365,7 @@ } retval = offset; } + unlock_kernel(); return retval; } diff -urN linux-2.4.18-pre9/fs/hpfs/dir.c linux/fs/hpfs/dir.c --- linux-2.4.18-pre9/fs/hpfs/dir.c Thu Feb 7 15:26:13 2002 +++ linux/fs/hpfs/dir.c Mon Feb 11 20:41:35 2002 @@ -29,6 +29,7 @@ struct inode *i = filp->f_dentry->d_inode; struct super_block *s = i->i_sb; /*printk("dir lseek\n");*/ + lock_kernel(); if (new_off == 0 || new_off == 1 || new_off == 11 || new_off == 12 || new_off == 13) goto ok; hpfs_lock_inode(i); pos = ((loff_t) hpfs_de_as_down_as_possible(s, i->i_hpfs_dno) << 4) + 1; @@ -39,10 +40,12 @@ } hpfs_unlock_inode(i); ok: + unlock_kernel(); return filp->f_pos = new_off; fail: hpfs_unlock_inode(i); /*printk("illegal lseek: %016llx\n", new_off);*/ + unlock_kernel(); return -ESPIPE; } diff -urN linux-2.4.18-pre9/fs/ncpfs/file.c linux/fs/ncpfs/file.c --- linux-2.4.18-pre9/fs/ncpfs/file.c Thu Feb 7 15:26:13 2002 +++ linux/fs/ncpfs/file.c Mon Feb 11 20:41:47 2002 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "ncplib_kernel.h" @@ -281,7 +282,7 @@ struct file_operations ncp_file_operations = { - llseek: generic_file_llseek, + llseek: remote_llseek, read: ncp_file_read, write: ncp_file_write, ioctl: ncp_ioctl, diff -urN linux-2.4.18-pre9/fs/nfs/file.c linux/fs/nfs/file.c --- linux-2.4.18-pre9/fs/nfs/file.c Thu Feb 7 15:26:13 2002 +++ linux/fs/nfs/file.c Mon Feb 11 20:41:47 2002 @@ -41,7 +41,7 @@ static int nfs_fsync(struct file *, struct dentry *dentry, int datasync); struct file_operations nfs_file_operations = { - llseek: generic_file_llseek, + llseek: remote_llseek, read: nfs_file_read, write: nfs_file_write, mmap: nfs_file_mmap, diff -urN linux-2.4.18-pre9/fs/proc/generic.c linux/fs/proc/generic.c --- linux-2.4.18-pre9/fs/proc/generic.c Thu Feb 7 15:26:13 2002 +++ linux/fs/proc/generic.c Mon Feb 11 20:41:35 2002 @@ -16,6 +16,7 @@ #include #define __NO_VERSION__ #include +#include #include static ssize_t proc_file_read(struct file * file, char * buf, @@ -140,22 +141,26 @@ static loff_t proc_file_lseek(struct file * file, loff_t offset, int orig) { + lock_kernel(); + switch (orig) { case 0: if (offset < 0) - return -EINVAL; + goto out; file->f_pos = offset; - return(file->f_pos); + goto out; case 1: if (offset + file->f_pos < 0) - return -EINVAL; + goto out; file->f_pos += offset; - return(file->f_pos); + goto out; case 2: - return(-EINVAL); default: - return(-EINVAL); } + +out: + unlock_kernel(); + return -EINVAL; } /* diff -urN linux-2.4.18-pre9/fs/read_write.c linux/fs/read_write.c --- linux-2.4.18-pre9/fs/read_write.c Thu Feb 7 15:26:12 2002 +++ linux/fs/read_write.c Mon Feb 11 20:41:47 2002 @@ -28,7 +28,37 @@ loff_t generic_file_llseek(struct file *file, loff_t offset, int origin) { long long retval; + struct inode *inode = file->f_dentry->d_inode->i_mapping->host; + down(&inode->i_sem); + + switch (origin) { + case 2: + offset += inode->i_size; + break; + case 1: + offset += file->f_pos; + } + retval = -EINVAL; + if (offset>=0 && offset<=file->f_dentry->d_inode->i_sb->s_maxbytes) { + if (offset>=0 && offset<=inode->i_sb->s_maxbytes) { + file->f_pos = offset; + file->f_reada = 0; + file->f_version = ++event; + } + retval = offset; + } + + up(&inode->i_sem); + + return retval; +} + +loff_t remote_llseek(struct file *file, loff_t offset, int origin) +{ + long long retval; + + lock_kernel(); switch (origin) { case 2: offset += file->f_dentry->d_inode->i_size; @@ -45,6 +75,7 @@ } retval = offset; } + unlock_kernel(); return retval; } @@ -57,6 +88,7 @@ { long long retval; + lock_kernel(); switch (origin) { case 2: offset += file->f_dentry->d_inode->i_size; @@ -73,21 +105,18 @@ } retval = offset; } + unlock_kernel(); return retval; } static inline loff_t llseek(struct file *file, loff_t offset, int origin) { loff_t (*fn)(struct file *, loff_t, int); - loff_t retval; fn = default_llseek; if (file->f_op && file->f_op->llseek) fn = file->f_op->llseek; - lock_kernel(); - retval = fn(file, offset, origin); - unlock_kernel(); - return retval; + return fn(file, offset, origin); } asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin) diff -urN linux-2.4.18-pre9/fs/smbfs/file.c linux/fs/smbfs/file.c --- linux-2.4.18-pre9/fs/smbfs/file.c Thu Feb 7 15:26:13 2002 +++ linux/fs/smbfs/file.c Mon Feb 11 20:41:47 2002 @@ -381,7 +381,7 @@ struct file_operations smb_file_operations = { - llseek: generic_file_llseek, + llseek: remote_llseek, read: smb_file_read, write: smb_file_write, ioctl: smb_ioctl, diff -urN linux-2.4.18-pre9/include/linux/fs.h linux/include/linux/fs.h --- linux-2.4.18-pre9/include/linux/fs.h Thu Feb 7 15:26:14 2002 +++ linux/include/linux/fs.h Mon Feb 11 20:41:47 2002 @@ -1415,6 +1415,7 @@ extern void do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, read_actor_t); extern loff_t no_llseek(struct file *file, loff_t offset, int origin); extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin); +extern loff_t remote_llseek(struct file *file, loff_t offset, int origin); extern ssize_t generic_read_dir(struct file *, char *, size_t, loff_t *); extern int generic_file_open(struct inode * inode, struct file * filp); diff -urN linux-2.4.18-pre9/kernel/ksyms.c linux/kernel/ksyms.c --- linux-2.4.18-pre9/kernel/ksyms.c Thu Feb 7 15:26:13 2002 +++ linux/kernel/ksyms.c Mon Feb 11 20:41:47 2002 @@ -248,6 +248,7 @@ EXPORT_SYMBOL(vfs_statfs); EXPORT_SYMBOL(generic_read_dir); EXPORT_SYMBOL(generic_file_llseek); +EXPORT_SYMBOL(remote_llseek); EXPORT_SYMBOL(no_llseek); EXPORT_SYMBOL(__pollwait); EXPORT_SYMBOL(poll_freewait);