Commit 269f8f70 authored by Linus Torvalds's avatar Linus Torvalds

v2.4.9.13 -> v2.4.9.14

  - Richard Gooch: devfs update
  - Andrea Arcangeli: clean up/fix ramdisk handling now that it's in page cache
  - Al Viro: follow up the above with initrd cleanups
  - Keith Owens: get rid of drivers/scsi/53c700-mem.c file
  - Trond Myklebust: RPC over TCP race fix
  - Greg KH: USB update (ohci understands USB_ZERO_PACKET)
  - me: clean up reference bit handling, fix silly GFP_ATOMIC allocation bug
parent a27c6530
...@@ -1675,3 +1675,83 @@ Changes for patch v182 ...@@ -1675,3 +1675,83 @@ Changes for patch v182
- Fixed number leak for /dev/cdroms/cdrom%d - Fixed number leak for /dev/cdroms/cdrom%d
- Fixed number leak for /dev/discs/disc%d - Fixed number leak for /dev/discs/disc%d
===============================================================================
Changes for patch v183
- Fixed bug in <devfs_setup> which could hang boot process
===============================================================================
Changes for patch v184
- Documentation typo fix for fs/devfs/util.c
- Fixed drivers/char/stallion.c for devfs
- Added DEVFSD_NOTIFY_DELETE event
- Updated README from master HTML file
- Removed #include <asm/segment.h> from fs/devfs/base.c
===============================================================================
Changes for patch v185
- Made <block_semaphore> and <char_semaphore> in fs/devfs/util.c
private
- Fixed inode table races by removing it and using inode->u.generic_ip
instead
- Moved <devfs_read_inode> into <get_vfs_inode>
- Moved <devfs_write_inode> into <devfs_notify_change>
===============================================================================
Changes for patch v186
- Fixed race in <devfs_do_symlink> for uni-processor
- Updated README from master HTML file
===============================================================================
Changes for patch v187
- Fixed drivers/char/stallion.c for devfs
- Fixed drivers/char/rocket.c for devfs
- Fixed bug in <devfs_alloc_unique_number>: limited to 128 numbers
===============================================================================
Changes for patch v188
- Updated major masks in fs/devfs/util.c up to Linus' "no new majors"
proclamation. Block: were 126 now 122 free, char: were 26 now 19 free
- Updated README from master HTML file
- Removed remnant of multi-mount support in <devfs_mknod>
- Removed unused DEVFS_FL_SHOW_UNREG flag
===============================================================================
Changes for patch v189
- Removed nlink field from struct devfs_inode
- Removed auto-ownership for /dev/pty/* (BSD ptys) and used
DEVFS_FL_CURRENT_OWNER|DEVFS_FL_NO_PERSISTENCE for /dev/pty/s* (just
like Unix98 pty slaves) and made /dev/pty/m* rw-rw-rw- access
===============================================================================
Changes for patch v190
- Updated README from master HTML file
- Replaced BKL with global rwsem to protect symlink data (quick and
dirty hack)
===============================================================================
Changes for patch v191
- Replaced global rwsem for symlink with per-link refcount
===============================================================================
Changes for patch v192
- Removed unnecessary #ifdef CONFIG_DEVFS_FS from arch/i386/kernel/mtrr.c
- Ported to kernel 2.4.10-pre11
- Set inode->i_mapping->a_ops for block nodes in <get_vfs_inode>
...@@ -3,7 +3,7 @@ Devfs (Device File System) FAQ ...@@ -3,7 +3,7 @@ Devfs (Device File System) FAQ
Linux Devfs (Device File System) FAQ Linux Devfs (Device File System) FAQ
Richard Gooch Richard Gooch
26-APR-2001 23-AUG-2001
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
...@@ -18,17 +18,14 @@ find out more about it at: ...@@ -18,17 +18,14 @@ find out more about it at:
http://www.atnf.csiro.au/~rgooch/linux/ http://www.atnf.csiro.au/~rgooch/linux/
NEWSFLASH: The official 2.3.46 kernel has
included the devfs patch. Future patches will be released which
build on this. These patches are rolled into Linus' tree from time to
time.
A mailing list is available which you may subscribe to. Send A mailing list is available which you may subscribe to. Send
email email
to majordomo@oss.sgi.com with the following line in the to majordomo@oss.sgi.com with the following line in the
body of the message: body of the message:
subscribe devfs subscribe devfs
The list is archived at To unsubscribe, send the message body:
unsubscribe devfs
instead. The list is archived at
http://oss.sgi.com/projects/devfs/archive/. http://oss.sgi.com/projects/devfs/archive/.
...@@ -71,6 +68,8 @@ Alternatives to devfs ...@@ -71,6 +68,8 @@ Alternatives to devfs
Other resources Other resources
Translations of this document
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
...@@ -82,7 +81,7 @@ on your root filesystem. Kernel device drivers can register devices by ...@@ -82,7 +81,7 @@ on your root filesystem. Kernel device drivers can register devices by
name rather than major and minor numbers. These devices will appear in name rather than major and minor numbers. These devices will appear in
devfs automatically, with whatever default ownership and devfs automatically, with whatever default ownership and
protection the driver specified. A daemon (devfsd) can be used to protection the driver specified. A daemon (devfsd) can be used to
override these defaults. override these defaults. Devfs has been in the kernel since 2.3.46.
NOTE that devfs is entirely optional. If you prefer the old NOTE that devfs is entirely optional. If you prefer the old
disc-based device nodes, then simply leave CONFIG_DEVFS_FS=n (the disc-based device nodes, then simply leave CONFIG_DEVFS_FS=n (the
...@@ -604,6 +603,20 @@ services. Unfortunately, it's also fragile, complex and undocumented ...@@ -604,6 +603,20 @@ services. Unfortunately, it's also fragile, complex and undocumented
has problems with symbolic links. Append the following lines to your has problems with symbolic links. Append the following lines to your
/etc/securetty file: /etc/securetty file:
vc/1
vc/2
vc/3
vc/4
vc/5
vc/6
vc/7
vc/8
This will not weaken security. If you have a version of util-linux
earlier than 2.10.h, please upgrade to 2.10.h or later. If you
absolutely cannot upgrade, then also append the following lines to
your /etc/securetty file:
1 1
2 2
3 3
...@@ -618,27 +631,13 @@ network (a password is still required, though). However, since there ...@@ -618,27 +631,13 @@ network (a password is still required, though). However, since there
are problems with dealing with symlinks, I'm suspicious of the level are problems with dealing with symlinks, I'm suspicious of the level
of security offered in any case. of security offered in any case.
A better solution is to install util-linux-2.10.h or later, which
fixes a bug with ttyname handling in the login programme. Then append
the following lines to your /etc/securetty file:
vc/1
vc/2
vc/3
vc/4
vc/5
vc/6
vc/7
vc/8
This will not weaken security.
XFree86 XFree86
While not essential, it's probably a good idea to upgrade to XFree86 While not essential, it's probably a good idea to upgrade to XFree86
4.0, as patches went in to make it more devfs-friendly. If you don't, 4.0, as patches went in to make it more devfs-friendly. If you don't,
you'll probably need to apply the following patch to you'll probably need to apply the following patch to
/etc/security/console.perms so that ordinary users can run /etc/security/console.perms so that ordinary users can run
startx. startx. Note that not all distributions have this file (e.g. Debian),
so if it's not present, don't worry about it.
--- /etc/security/console.perms.orig Sat Apr 17 16:26:47 1999 --- /etc/security/console.perms.orig Sat Apr 17 16:26:47 1999
+++ /etc/security/console.perms Fri Feb 25 23:53:55 2000 +++ /etc/security/console.perms Fri Feb 25 23:53:55 2000
...@@ -691,9 +690,12 @@ Alternatively, use the same technique used for unsupported drivers ...@@ -691,9 +690,12 @@ Alternatively, use the same technique used for unsupported drivers
described above. described above.
The Kernel The Kernel
Finally, you need to make sure devfs is compiled into your Finally, you need to make sure devfs is compiled into your kernel. Set
kernel. Set CONFIG_DEVFS_FS=y and CONFIG_DEVFS_MOUNT=y and recompile CONFIG_EXPERIMENTAL=y, CONFIG_DEVFS_FS=y and CONFIG_DEVFS_MOUNT=y by
your kernel. At boot, devfs will be mounted onto /dev. using favourite configuration tool (i.e. make config or
make xconfig) and then make dep; make clean and then
recompile your kernel and modules. At boot, devfs will be mounted onto
/dev.
If you encounter problems booting (for example if you forgot a If you encounter problems booting (for example if you forgot a
configuration step), you can pass devfs=nomount at the kernel configuration step), you can pass devfs=nomount at the kernel
...@@ -805,8 +807,17 @@ mounted-over /dev. However, you can still use a regular ...@@ -805,8 +807,17 @@ mounted-over /dev. However, you can still use a regular
directory to store the database. The sample /etc/devfsd.conf directory to store the database. The sample /etc/devfsd.conf
file above may still be used. You will need to create the file above may still be used. You will need to create the
/dev-state directory prior to installing devfsd. If you have /dev-state directory prior to installing devfsd. If you have
old permissions in /dev, then just copy the device nodes over old permissions in /dev, then just copy (or move) the device
to the new directory. nodes over to the new directory.
Which method is better?
The best method is to have the permissions database stored in the
mounted-over /dev. This is because you will not need to copy
device nodes over to /dev-state, and because it allows you to
switch between devfs and non-devfs kernels, without requiring you to
copy permissions between /dev-state (for devfs) and
/dev (for non-devfs).
Dealing with drivers without devfs support Dealing with drivers without devfs support
...@@ -1038,6 +1049,13 @@ that class are available. Often, the entries are symbolic links into a ...@@ -1038,6 +1049,13 @@ that class are available. Often, the entries are symbolic links into a
directory tree that reflects the topology of available devices. The directory tree that reflects the topology of available devices. The
topological tree is useful for finding how your devices are arranged. topological tree is useful for finding how your devices are arranged.
Below is a list of the naming schemes for the most common drivers. A
list of reserved device names is
available for reference. Please send email to
rgooch@atnf.csiro.au to obtain an allocation. Please be
patient (the maintainer is busy). An alternative name may be allocated
instead of the requested name, at the discretion of the maintainer.
Disc Devices Disc Devices
All discs, whether SCSI, IDE or whatever, are placed under the All discs, whether SCSI, IDE or whatever, are placed under the
...@@ -1486,6 +1504,47 @@ raised the possibilty of moving network devices into the device ...@@ -1486,6 +1504,47 @@ raised the possibilty of moving network devices into the device
namespace, but have had no response. namespace, but have had no response.
How can I test if I have devfs compiled into my kernel?
All filesystems built-in or currently loaded are listed in
/proc/filesystems. If you see a devfs entry, then
you know that devfs was compiled into your kernel. If you have
correctly configured and rebuilt your kernel, then devfs will be
built-in. If you think you've configured it in, but
/proc/filesystems doesn't show it, you've made a mistake.
Common mistakes include:
Using a 2.2.x kernel without applying the devfs patch (if you
don't know how to patch your kernel, use 2.4.x instead, don't bother
asking me how to patch)
Forgetting to set CONFIG_EXPERIMENTAL=y
Forgetting to set CONFIG_DEVFS_FS=y
Forgetting to set CONFIG_DEVFS_MOUNT=y (if you want devfs
to be automatically mounted at boot)
Editing your .config manually, instead of using make
config or make xconfig
Forgetting to run make dep; make clean after changing the
configuration and before compiling
Forgetting to compile your kernel and modules
Forgetting to install your kernel
Forgetting to install your modules
Please check twice that you've done all these steps before sending in
a bug report.
How can I test if devfs is mounted on /dev?
The device filesystem will always create an entry called
".devfsd", which is used to communicate with the daemon. Even
if the daemon is not running, this entry will exist. Testing for the
existence of this entry is the approved method of determining if devfs
is mounted or not. Note that the type of entry (i.e. regular file,
character device, named pipe, etc.) may change without notice. Only
the existence of the entry should be relied upon.
...@@ -1716,3 +1775,20 @@ U.S.A. in October 2000. ...@@ -1716,3 +1775,20 @@ U.S.A. in October 2000.
-----------------------------------------------------------------------------
Translations of this document
This document has been translated into other languages.
A Korean translation by viatoris@nownuri.net is available at
http://home.nownuri.net/~viatoris/devfs/devfs.html
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
Richard Gooch <rgooch@atnf.csiro.au> Richard Gooch <rgooch@atnf.csiro.au>
30-APR-2000 18-AUG-2001
When CONFIG_DEVFS_DEBUG is enabled, you can pass several boot options When CONFIG_DEVFS_DEBUG is enabled, you can pass several boot options
...@@ -19,6 +19,8 @@ load requests and device registration, you would do: ...@@ -19,6 +19,8 @@ load requests and device registration, you would do:
devfs=dmod,dreg devfs=dmod,dreg
You may prefix "no" to any option. This will invert the option.
Debugging Options Debugging Options
================= =================
...@@ -42,11 +44,11 @@ dchange print device change requests to <devfs_set_flags> ...@@ -42,11 +44,11 @@ dchange print device change requests to <devfs_set_flags>
dilookup print inode lookup requests dilookup print inode lookup requests
diread print inode reads diget print VFS inode allocations
diunlink print inode unlinks diunlink print inode unlinks
diwrite print inode writes dichange print inode changes
dimknod print calls to mknod(2) dimknod print calls to mknod(2)
...@@ -58,10 +60,6 @@ Other Options ...@@ -58,10 +60,6 @@ Other Options
These control the default behaviour of devfs. The options are: These control the default behaviour of devfs. The options are:
show show unregistered devices by default
mount mount devfs onto /dev at boot time mount mount devfs onto /dev at boot time
nomount do not mount devfs onto /dev at boot time
only disable non-devfs device nodes for devfs-capable drivers only disable non-devfs device nodes for devfs-capable drivers
VERSION = 2 VERSION = 2
PATCHLEVEL = 4 PATCHLEVEL = 4
SUBLEVEL = 10 SUBLEVEL = 10
EXTRAVERSION =-pre13 EXTRAVERSION =-pre14
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
...@@ -202,6 +202,7 @@ CLEAN_FILES = \ ...@@ -202,6 +202,7 @@ CLEAN_FILES = \
drivers/scsi/aic7xxx/aicasm/aicasm_scan.c \ drivers/scsi/aic7xxx/aicasm/aicasm_scan.c \
drivers/scsi/aic7xxx/aicasm/y.tab.h \ drivers/scsi/aic7xxx/aicasm/y.tab.h \
drivers/scsi/aic7xxx/aicasm/aicasm \ drivers/scsi/aic7xxx/aicasm/aicasm \
drivers/scsi/53c700-mem.c \
net/khttpd/make_times_h \ net/khttpd/make_times_h \
net/khttpd/times.h \ net/khttpd/times.h \
submenu* submenu*
......
...@@ -2253,11 +2253,9 @@ int __init mtrr_init(void) ...@@ -2253,11 +2253,9 @@ int __init mtrr_init(void)
proc_root_mtrr->proc_fops = &mtrr_fops; proc_root_mtrr->proc_fops = &mtrr_fops;
} }
#endif #endif
#ifdef CONFIG_DEVFS_FS
devfs_handle = devfs_register (NULL, "cpu/mtrr", DEVFS_FL_DEFAULT, 0, 0, devfs_handle = devfs_register (NULL, "cpu/mtrr", DEVFS_FL_DEFAULT, 0, 0,
S_IFREG | S_IRUGO | S_IWUSR, S_IFREG | S_IRUGO | S_IWUSR,
&mtrr_fops, NULL); &mtrr_fops, NULL);
#endif
init_table (); init_table ();
return 0; return 0;
} /* End Function mtrr_init */ } /* End Function mtrr_init */
......
...@@ -100,7 +100,7 @@ static int rd_hardsec[NUM_RAMDISKS]; /* Size of real blocks in bytes */ ...@@ -100,7 +100,7 @@ static int rd_hardsec[NUM_RAMDISKS]; /* Size of real blocks in bytes */
static int rd_blocksizes[NUM_RAMDISKS]; /* Size of 1024 byte blocks :) */ static int rd_blocksizes[NUM_RAMDISKS]; /* Size of 1024 byte blocks :) */
static int rd_kbsize[NUM_RAMDISKS]; /* Size in blocks of 1024 bytes */ static int rd_kbsize[NUM_RAMDISKS]; /* Size in blocks of 1024 bytes */
static devfs_handle_t devfs_handle; static devfs_handle_t devfs_handle;
static struct inode *rd_inode[NUM_RAMDISKS]; /* Protected device inodes */ static struct block_device *rd_bdev[NUM_RAMDISKS];/* Protected device data */
/* /*
* Parameters for the boot-loading of the RAM disk. These are set by * Parameters for the boot-loading of the RAM disk. These are set by
...@@ -186,17 +186,67 @@ __setup("ramdisk_blocksize=", ramdisk_blocksize); ...@@ -186,17 +186,67 @@ __setup("ramdisk_blocksize=", ramdisk_blocksize);
#endif #endif
/*
* Copyright (C) 2000 Linus Torvalds.
* 2000 Transmeta Corp.
* aops copied from ramfs.
*/
static int ramdisk_readpage(struct file *file, struct page * page)
{
if (!Page_Uptodate(page)) {
memset(kmap(page), 0, PAGE_CACHE_SIZE);
kunmap(page);
flush_dcache_page(page);
SetPageUptodate(page);
}
UnlockPage(page);
return 0;
}
/*
* Writing: just make sure the page gets marked dirty, so that
* the page stealer won't grab it.
*/
static int ramdisk_writepage(struct page *page)
{
SetPageDirty(page);
UnlockPage(page);
return 0;
}
static int ramdisk_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
{
if (!Page_Uptodate(page)) {
void *addr = page_address(page);
memset(addr, 0, PAGE_CACHE_SIZE);
flush_dcache_page(page);
SetPageUptodate(page);
}
SetPageDirty(page);
return 0;
}
static int ramdisk_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
{
return 0;
}
static struct address_space_operations ramdisk_aops = {
readpage: ramdisk_readpage,
writepage: ramdisk_writepage,
prepare_write: ramdisk_prepare_write,
commit_write: ramdisk_commit_write,
};
static int rd_blkdev_pagecache_IO(int rw, struct buffer_head * sbh, int minor) static int rd_blkdev_pagecache_IO(int rw, struct buffer_head * sbh, int minor)
{ {
struct address_space * mapping = rd_inode[minor]->i_mapping; struct address_space * mapping;
unsigned long index; unsigned long index;
int offset, size, err = 0; int offset, size, err;
if (sbh->b_page->mapping == mapping) { err = -EIO;
if (rw != READ) err = 0;
SetPageDirty(sbh->b_page); mapping = rd_bdev[minor]->bd_inode->i_mapping;
goto out;
}
index = sbh->b_rsector >> (PAGE_CACHE_SHIFT - 9); index = sbh->b_rsector >> (PAGE_CACHE_SHIFT - 9);
offset = (sbh->b_rsector << 9) & ~PAGE_CACHE_MASK; offset = (sbh->b_rsector << 9) & ~PAGE_CACHE_MASK;
...@@ -206,8 +256,7 @@ static int rd_blkdev_pagecache_IO(int rw, struct buffer_head * sbh, int minor) ...@@ -206,8 +256,7 @@ static int rd_blkdev_pagecache_IO(int rw, struct buffer_head * sbh, int minor)
int count; int count;
struct page ** hash; struct page ** hash;
struct page * page; struct page * page;
const char * src; char * src, * dst;
char * dst;
int unlock = 0; int unlock = 0;
count = PAGE_CACHE_SIZE - offset; count = PAGE_CACHE_SIZE - offset;
...@@ -217,20 +266,24 @@ static int rd_blkdev_pagecache_IO(int rw, struct buffer_head * sbh, int minor) ...@@ -217,20 +266,24 @@ static int rd_blkdev_pagecache_IO(int rw, struct buffer_head * sbh, int minor)
hash = page_hash(mapping, index); hash = page_hash(mapping, index);
page = __find_get_page(mapping, index, hash); page = __find_get_page(mapping, index, hash);
if (!page && rw != READ) { if (!page) {
page = grab_cache_page(mapping, index); page = grab_cache_page(mapping, index);
err = -ENOMEM; err = -ENOMEM;
if (!page) if (!page)
goto out; goto out;
err = 0; err = 0;
if (!Page_Uptodate(page)) {
memset(kmap(page), 0, PAGE_CACHE_SIZE);
kunmap(page);
flush_dcache_page(page);
SetPageUptodate(page);
}
unlock = 1; unlock = 1;
} }
index++; index++;
if (!page) {
offset = 0;
continue;
}
if (rw == READ) { if (rw == READ) {
src = kmap(page); src = kmap(page);
...@@ -303,10 +356,11 @@ static int rd_make_request(request_queue_t * q, int rw, struct buffer_head *sbh) ...@@ -303,10 +356,11 @@ static int rd_make_request(request_queue_t * q, int rw, struct buffer_head *sbh)
static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{ {
int error = -EINVAL;
unsigned int minor; unsigned int minor;
if (!inode || !inode->i_rdev) if (!inode || !inode->i_rdev)
return -EINVAL; goto out;
minor = MINOR(inode->i_rdev); minor = MINOR(inode->i_rdev);
...@@ -317,40 +371,29 @@ static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un ...@@ -317,40 +371,29 @@ static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
/* special: we want to release the ramdisk memory, /* special: we want to release the ramdisk memory,
it's not like with the other blockdevices where it's not like with the other blockdevices where
this ioctl only flushes away the buffer cache. */ this ioctl only flushes away the buffer cache. */
{ error = -EBUSY;
struct block_device * bdev = inode->i_bdev; down(&inode->i_bdev->bd_sem);
if (inode->i_bdev->bd_openers <= 2) {
down(&bdev->bd_sem); truncate_inode_pages(inode->i_mapping, 0);
if (bdev->bd_openers > 2) { error = 0;
up(&bdev->bd_sem);
return -EBUSY;
}
bdev->bd_openers--;
bdev->bd_cache_openers--;
iput(rd_inode[minor]);
rd_inode[minor] = NULL;
rd_blocksizes[minor] = rd_blocksize;
up(&bdev->bd_sem);
} }
up(&inode->i_bdev->bd_sem);
break; break;
case BLKGETSIZE: /* Return device size */ case BLKGETSIZE: /* Return device size */
if (!arg) return -EINVAL; if (!arg)
return put_user(rd_kbsize[minor] << 1, (long *) arg); break;
error = put_user(rd_kbsize[minor] << 1, (long *) arg);
break;
case BLKGETSIZE64: case BLKGETSIZE64:
return put_user((u64)rd_kbsize[minor] << 10, (u64*)arg); error = put_user((u64)rd_kbsize[minor]<<10, (u64*)arg);
break;
case BLKROSET: case BLKROSET:
case BLKROGET: case BLKROGET:
case BLKSSZGET: case BLKSSZGET:
return blk_ioctl(inode->i_rdev, cmd, arg); error = blk_ioctl(inode->i_rdev, cmd, arg);
default:
return -EINVAL;
}; };
out:
return 0; return error;
} }
...@@ -377,6 +420,8 @@ static int initrd_release(struct inode *inode,struct file *file) ...@@ -377,6 +420,8 @@ static int initrd_release(struct inode *inode,struct file *file)
if (!--initrd_users) { if (!--initrd_users) {
free_initrd_mem(initrd_start, initrd_end); free_initrd_mem(initrd_start, initrd_end);
initrd_start = 0; initrd_start = 0;
inode->i_bdev->bd_cache_openers--;
blkdev_put(inode->i_bdev, BDEV_FILE);
} }
return 0; return 0;
} }
...@@ -384,6 +429,7 @@ static int initrd_release(struct inode *inode,struct file *file) ...@@ -384,6 +429,7 @@ static int initrd_release(struct inode *inode,struct file *file)
static struct file_operations initrd_fops = { static struct file_operations initrd_fops = {
read: initrd_read, read: initrd_read,
release: initrd_release,
}; };
#endif #endif
...@@ -391,36 +437,28 @@ static struct file_operations initrd_fops = { ...@@ -391,36 +437,28 @@ static struct file_operations initrd_fops = {
static int rd_open(struct inode * inode, struct file * filp) static int rd_open(struct inode * inode, struct file * filp)
{ {
#ifdef CONFIG_BLK_DEV_INITRD int unit = DEVICE_NR(inode->i_rdev);
if (DEVICE_NR(inode->i_rdev) == INITRD_MINOR) {
static struct block_device_operations initrd_bd_op = {
open: rd_open,
release: initrd_release,
};
#ifdef CONFIG_BLK_DEV_INITRD
if (unit == INITRD_MINOR) {
if (!initrd_start) return -ENODEV; if (!initrd_start) return -ENODEV;
initrd_users++; initrd_users++;
filp->f_op = &initrd_fops; filp->f_op = &initrd_fops;
inode->i_bdev->bd_op = &initrd_bd_op;
return 0; return 0;
} }
#endif #endif
if (DEVICE_NR(inode->i_rdev) >= NUM_RAMDISKS) if (unit >= NUM_RAMDISKS)
return -ENXIO; return -ENXIO;
/* /*
* Immunize device against invalidate_buffers() and prune_icache(). * Immunize device against invalidate_buffers() and prune_icache().
*/ */
if (rd_inode[DEVICE_NR(inode->i_rdev)] == NULL) { if (rd_bdev[unit] == NULL) {
if (!inode->i_bdev) return -ENXIO; rd_bdev[unit] = bdget(kdev_t_to_nr(inode->i_rdev));
if ((rd_inode[DEVICE_NR(inode->i_rdev)] = igrab(inode)) != NULL) { rd_bdev[unit]->bd_openers++;
struct block_device *bdev = inode->i_bdev; rd_bdev[unit]->bd_cache_openers++;
rd_bdev[unit]->bd_inode->i_mapping->a_ops = &ramdisk_aops;
/* bdev->bd_sem is held by caller */
bdev->bd_openers++;
bdev->bd_cache_openers++;
}
} }
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
...@@ -447,18 +485,13 @@ static void __exit rd_cleanup (void) ...@@ -447,18 +485,13 @@ static void __exit rd_cleanup (void)
int i; int i;
for (i = 0 ; i < NUM_RAMDISKS; i++) { for (i = 0 ; i < NUM_RAMDISKS; i++) {
if (rd_inode[i]) { struct block_device *bdev = rd_bdev[i];
/* withdraw invalidate_buffers() and prune_icache() immunity */ rd_bdev[i] = NULL;
struct block_device *bdev = rd_inode[i]->i_bdev; if (bdev) {
down(&bdev->bd_sem);
bdev->bd_openers--;
bdev->bd_cache_openers--; bdev->bd_cache_openers--;
up(&bdev->bd_sem); truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
blkdev_put(bdev, BDEV_FILE);
/* remove stale pointer to module address space */ bdput(bdev);
rd_inode[i]->i_bdev->bd_op = NULL;
iput(rd_inode[i]);
} }
destroy_buffers(MKDEV(MAJOR_NR, i)); destroy_buffers(MKDEV(MAJOR_NR, i));
} }
...@@ -777,7 +810,7 @@ static void __init rd_load_image(kdev_t device, int offset, int unit) ...@@ -777,7 +810,7 @@ static void __init rd_load_image(kdev_t device, int offset, int unit)
if (ROOT_DEVICE_NAME != NULL) strcpy (ROOT_DEVICE_NAME, "rd/0"); if (ROOT_DEVICE_NAME != NULL) strcpy (ROOT_DEVICE_NAME, "rd/0");
done: done:
blkdev_close(inode, &infile); infile.f_op->release(inode, &infile);
noclose_input: noclose_input:
blkdev_close(out_inode, &outfile); blkdev_close(out_inode, &outfile);
iput(inode); iput(inode);
...@@ -786,7 +819,7 @@ static void __init rd_load_image(kdev_t device, int offset, int unit) ...@@ -786,7 +819,7 @@ static void __init rd_load_image(kdev_t device, int offset, int unit)
return; return;
free_inodes: /* free inodes on error */ free_inodes: /* free inodes on error */
iput(out_inode); iput(out_inode);
blkdev_close(inode, &infile); infile.f_op->release(inode, &infile);
free_inode: free_inode:
iput(inode); iput(inode);
} }
......
...@@ -334,7 +334,8 @@ static int pty_open(struct tty_struct *tty, struct file * filp) ...@@ -334,7 +334,8 @@ static int pty_open(struct tty_struct *tty, struct file * filp)
/* Register a slave for the master */ /* Register a slave for the master */
if (tty->driver.major == PTY_MASTER_MAJOR) if (tty->driver.major == PTY_MASTER_MAJOR)
tty_register_devfs(&tty->link->driver, tty_register_devfs(&tty->link->driver,
DEVFS_FL_AUTO_OWNER | DEVFS_FL_WAIT, DEVFS_FL_CURRENT_OWNER |
DEVFS_FL_NO_PERSISTENCE | DEVFS_FL_WAIT,
tty->link->driver.minor_start + tty->link->driver.minor_start +
MINOR(tty->device)-tty->driver.minor_start); MINOR(tty->device)-tty->driver.minor_start);
retval = 0; retval = 0;
......
...@@ -2186,7 +2186,11 @@ int __init rp_init(void) ...@@ -2186,7 +2186,11 @@ int __init rp_init(void)
*/ */
memset(&rocket_driver, 0, sizeof(struct tty_driver)); memset(&rocket_driver, 0, sizeof(struct tty_driver));
rocket_driver.magic = TTY_DRIVER_MAGIC; rocket_driver.magic = TTY_DRIVER_MAGIC;
#ifdef CONFIG_DEVFS_FS
rocket_driver.name = "tts/R%d";
#else
rocket_driver.name = "ttyR"; rocket_driver.name = "ttyR";
#endif
rocket_driver.major = TTY_ROCKET_MAJOR; rocket_driver.major = TTY_ROCKET_MAJOR;
rocket_driver.minor_start = 0; rocket_driver.minor_start = 0;
rocket_driver.num = MAX_RP_PORTS; rocket_driver.num = MAX_RP_PORTS;
...@@ -2228,7 +2232,11 @@ int __init rp_init(void) ...@@ -2228,7 +2232,11 @@ int __init rp_init(void)
* the minor number and the subtype code. * the minor number and the subtype code.
*/ */
callout_driver = rocket_driver; callout_driver = rocket_driver;
#ifdef CONFIG_DEVFS_FS
callout_driver.name = "cua/R%d";
#else
callout_driver.name = "cur"; callout_driver.name = "cur";
#endif
callout_driver.major = CUA_ROCKET_MAJOR; callout_driver.major = CUA_ROCKET_MAJOR;
callout_driver.minor_start = 0; callout_driver.minor_start = 0;
callout_driver.subtype = SERIAL_TYPE_CALLOUT; callout_driver.subtype = SERIAL_TYPE_CALLOUT;
......
...@@ -139,8 +139,13 @@ static int stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t); ...@@ -139,8 +139,13 @@ static int stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t);
static char *stl_drvtitle = "Stallion Multiport Serial Driver"; static char *stl_drvtitle = "Stallion Multiport Serial Driver";
static char *stl_drvname = "stallion"; static char *stl_drvname = "stallion";
static char *stl_drvversion = "5.6.0"; static char *stl_drvversion = "5.6.0";
#ifdef CONFIG_DEVFS_FS
static char *stl_serialname = "tts/E%d";
static char *stl_calloutname = "cua/E%d";
#else
static char *stl_serialname = "ttyE"; static char *stl_serialname = "ttyE";
static char *stl_calloutname = "cue"; static char *stl_calloutname = "cue";
#endif
static struct tty_driver stl_serial; static struct tty_driver stl_serial;
static struct tty_driver stl_callout; static struct tty_driver stl_callout;
......
...@@ -2021,7 +2021,7 @@ void tty_register_devfs (struct tty_driver *driver, unsigned int flags, unsigned ...@@ -2021,7 +2021,7 @@ void tty_register_devfs (struct tty_driver *driver, unsigned int flags, unsigned
break; break;
default: default:
if (driver->major == PTY_MASTER_MAJOR) if (driver->major == PTY_MASTER_MAJOR)
flags |= DEVFS_FL_AUTO_OWNER; mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
break; break;
} }
if ( (minor < driver->minor_start) || if ( (minor < driver->minor_start) ||
......
This diff is collapsed.
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
* *
* History: * History:
* *
* 2001/09/19 USB_ZERO_PACKET support (Jean Tourrilhes)
* 2001/07/17 power management and pmac cleanup (Benjamin Herrenschmidt) * 2001/07/17 power management and pmac cleanup (Benjamin Herrenschmidt)
* 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam); * 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam);
pci_map_single (db) pci_map_single (db)
...@@ -537,6 +538,7 @@ static int sohci_submit_urb (urb_t * urb) ...@@ -537,6 +538,7 @@ static int sohci_submit_urb (urb_t * urb)
ed_t * ed; ed_t * ed;
urb_priv_t * urb_priv; urb_priv_t * urb_priv;
unsigned int pipe = urb->pipe; unsigned int pipe = urb->pipe;
int maxps = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe));
int i, size = 0; int i, size = 0;
unsigned long flags; unsigned long flags;
int bustime = 0; int bustime = 0;
...@@ -579,6 +581,15 @@ static int sohci_submit_urb (urb_t * urb) ...@@ -579,6 +581,15 @@ static int sohci_submit_urb (urb_t * urb)
switch (usb_pipetype (pipe)) { switch (usb_pipetype (pipe)) {
case PIPE_BULK: /* one TD for every 4096 Byte */ case PIPE_BULK: /* one TD for every 4096 Byte */
size = (urb->transfer_buffer_length - 1) / 4096 + 1; size = (urb->transfer_buffer_length - 1) / 4096 + 1;
/* If the transfer size is multiple of the pipe mtu,
* we may need an extra TD to create a empty frame
* Jean II */
if ((urb->transfer_flags & USB_ZERO_PACKET) &&
usb_pipeout (pipe) &&
(urb->transfer_buffer_length != 0) &&
((urb->transfer_buffer_length % maxps) == 0))
size++;
break; break;
case PIPE_ISOCHRONOUS: /* number of packets from URB */ case PIPE_ISOCHRONOUS: /* number of packets from URB */
size = urb->number_of_packets; size = urb->number_of_packets;
...@@ -1338,6 +1349,7 @@ static void td_submit_urb (urb_t * urb) ...@@ -1338,6 +1349,7 @@ static void td_submit_urb (urb_t * urb)
ohci_t * ohci = (ohci_t *) urb->dev->bus->hcpriv; ohci_t * ohci = (ohci_t *) urb->dev->bus->hcpriv;
dma_addr_t data; dma_addr_t data;
int data_len = urb->transfer_buffer_length; int data_len = urb->transfer_buffer_length;
int maxps = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe));
int cnt = 0; int cnt = 0;
__u32 info = 0; __u32 info = 0;
unsigned int toggle = 0; unsigned int toggle = 0;
...@@ -1374,6 +1386,19 @@ static void td_submit_urb (urb_t * urb) ...@@ -1374,6 +1386,19 @@ static void td_submit_urb (urb_t * urb)
TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ; TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ;
td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, urb, cnt); td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, urb, cnt);
cnt++; cnt++;
/* If the transfer size is multiple of the pipe mtu,
* we may need an extra TD to create a empty frame
* Note : another way to check this condition is
* to test if(urb_priv->length > cnt) - Jean II */
if ((urb->transfer_flags & USB_ZERO_PACKET) &&
usb_pipeout (urb->pipe) &&
(urb->transfer_buffer_length != 0) &&
((urb->transfer_buffer_length % maxps) == 0)) {
td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), 0, 0, urb, cnt);
cnt++;
}
if (!ohci->sleeping) if (!ohci->sleeping)
writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
break; break;
......
...@@ -697,7 +697,6 @@ int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind) ...@@ -697,7 +697,6 @@ int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind)
ret = bdev->bd_op->open(bdev->bd_inode, &fake_file); ret = bdev->bd_op->open(bdev->bd_inode, &fake_file);
if (!ret) { if (!ret) {
bdev->bd_openers++; bdev->bd_openers++;
atomic_inc(&bdev->bd_count);
} else if (!bdev->bd_openers) { } else if (!bdev->bd_openers) {
struct inode *bd_inode = bdev->bd_inode; struct inode *bd_inode = bdev->bd_inode;
bdev->bd_op = NULL; bdev->bd_op = NULL;
...@@ -778,7 +777,6 @@ int blkdev_put(struct block_device *bdev, int kind) ...@@ -778,7 +777,6 @@ int blkdev_put(struct block_device *bdev, int kind)
} }
unlock_kernel(); unlock_kernel();
up(&bdev->bd_sem); up(&bdev->bd_sem);
bdput(bdev);
return ret; return ret;
} }
......
This diff is collapsed.
...@@ -39,6 +39,15 @@ ...@@ -39,6 +39,15 @@
Created <devfs_*alloc_major> and <devfs_*alloc_devnum>. Created <devfs_*alloc_major> and <devfs_*alloc_devnum>.
20010710 Richard Gooch <rgooch@atnf.csiro.au> 20010710 Richard Gooch <rgooch@atnf.csiro.au>
Created <devfs_*alloc_unique_number>. Created <devfs_*alloc_unique_number>.
20010730 Richard Gooch <rgooch@atnf.csiro.au>
Documentation typo fix.
20010806 Richard Gooch <rgooch@atnf.csiro.au>
Made <block_semaphore> and <char_semaphore> private.
20010813 Richard Gooch <rgooch@atnf.csiro.au>
Fixed bug in <devfs_alloc_unique_number>: limited to 128 numbers
20010818 Richard Gooch <rgooch@atnf.csiro.au>
Updated major masks up to Linus' "no new majors" proclamation.
Block: were 126 now 122 free, char: were 26 now 19 free.
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -181,15 +190,15 @@ struct major_list ...@@ -181,15 +190,15 @@ struct major_list
}; };
/* Block majors already assigned: /* Block majors already assigned:
0-3, 7-9, 11-12, 13-63, 65-93, 95-99, 101, 103-111, 120-127, 199, 201, 0-3, 7-9, 11-63, 65-99, 101-113, 120-127, 199, 201, 240-255
240-255 Total free: 122
*/ */
static struct major_list block_major_list = static struct major_list block_major_list =
{SPIN_LOCK_UNLOCKED, {SPIN_LOCK_UNLOCKED,
{0xfffffb8f, /* Majors 0 to 31 */ {0xfffffb8f, /* Majors 0 to 31 */
0xffffffff, /* Majors 32 to 63 */ 0xffffffff, /* Majors 32 to 63 */
0xbffffffe, /* Majors 64 to 95 */ 0xfffffffe, /* Majors 64 to 95 */
0xff00ffaf, /* Majors 96 to 127 */ 0xff03ffef, /* Majors 96 to 127 */
0x00000000, /* Majors 128 to 159 */ 0x00000000, /* Majors 128 to 159 */
0x00000000, /* Majors 160 to 191 */ 0x00000000, /* Majors 160 to 191 */
0x00000280, /* Majors 192 to 223 */ 0x00000280, /* Majors 192 to 223 */
...@@ -197,7 +206,8 @@ static struct major_list block_major_list = ...@@ -197,7 +206,8 @@ static struct major_list block_major_list =
}; };
/* Char majors already assigned: /* Char majors already assigned:
0-7, 9-151, 154-158, 160-195, 198-211, 216-221, 224-225, 240-255 0-7, 9-151, 154-158, 160-211, 216-221, 224-230, 240-255
Total free: 19
*/ */
static struct major_list char_major_list = static struct major_list char_major_list =
{SPIN_LOCK_UNLOCKED, {SPIN_LOCK_UNLOCKED,
...@@ -207,14 +217,14 @@ static struct major_list char_major_list = ...@@ -207,14 +217,14 @@ static struct major_list char_major_list =
0xffffffff, /* Majors 96 to 127 */ 0xffffffff, /* Majors 96 to 127 */
0x7cffffff, /* Majors 128 to 159 */ 0x7cffffff, /* Majors 128 to 159 */
0xffffffff, /* Majors 160 to 191 */ 0xffffffff, /* Majors 160 to 191 */
0x3f0fffcf, /* Majors 192 to 223 */ 0x3f0fffff, /* Majors 192 to 223 */
0xffff0003} /* Majors 224 to 255 */ 0xffff007f} /* Majors 224 to 255 */
}; };
/** /**
* devfs_alloc_major - Allocate a major number. * devfs_alloc_major - Allocate a major number.
* @type: The type of the major (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLOCK) * @type: The type of the major (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK)
* Returns the allocated major, else -1 if none are available. * Returns the allocated major, else -1 if none are available.
* This routine is thread safe and does not block. * This routine is thread safe and does not block.
...@@ -238,7 +248,7 @@ EXPORT_SYMBOL(devfs_alloc_major); ...@@ -238,7 +248,7 @@ EXPORT_SYMBOL(devfs_alloc_major);
/** /**
* devfs_dealloc_major - Deallocate a major number. * devfs_dealloc_major - Deallocate a major number.
* @type: The type of the major (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLOCK) * @type: The type of the major (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK)
* @major: The major number. * @major: The major number.
* This routine is thread safe and does not block. * This routine is thread safe and does not block.
*/ */
...@@ -273,16 +283,16 @@ struct device_list ...@@ -273,16 +283,16 @@ struct device_list
int none_free; int none_free;
}; };
DECLARE_MUTEX (block_semaphore); static DECLARE_MUTEX (block_semaphore);
static struct device_list block_list; static struct device_list block_list;
DECLARE_MUTEX (char_semaphore); static DECLARE_MUTEX (char_semaphore);
static struct device_list char_list; static struct device_list char_list;
/** /**
* devfs_alloc_devnum - Allocate a device number. * devfs_alloc_devnum - Allocate a device number.
* @type: The type (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLOCK). * @type: The type (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK).
* *
* Returns the allocated device number, else NODEV if none are available. * Returns the allocated device number, else NODEV if none are available.
* This routine is thread safe and may block. * This routine is thread safe and may block.
...@@ -347,7 +357,7 @@ EXPORT_SYMBOL(devfs_alloc_devnum); ...@@ -347,7 +357,7 @@ EXPORT_SYMBOL(devfs_alloc_devnum);
/** /**
* devfs_dealloc_devnum - Dellocate a device number. * devfs_dealloc_devnum - Dellocate a device number.
* @type: The type (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLOCK). * @type: The type (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK).
* @devnum: The device number. * @devnum: The device number.
* *
* This routine is thread safe and does not block. * This routine is thread safe and does not block.
...@@ -437,6 +447,7 @@ int devfs_alloc_unique_number (struct unique_numspace *space) ...@@ -437,6 +447,7 @@ int devfs_alloc_unique_number (struct unique_numspace *space)
space->length = length; space->length = length;
} }
number = find_first_zero_bit (space->bits, space->length << 3); number = find_first_zero_bit (space->bits, space->length << 3);
--space->num_free;
__set_bit (number, space->bits); __set_bit (number, space->bits);
up (&space->semaphore); up (&space->semaphore);
return number; return number;
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#define DEVFSD_NOTIFY_LOOKUP 4 #define DEVFSD_NOTIFY_LOOKUP 4
#define DEVFSD_NOTIFY_CHANGE 5 #define DEVFSD_NOTIFY_CHANGE 5
#define DEVFSD_NOTIFY_CREATE 6 #define DEVFSD_NOTIFY_CREATE 6
#define DEVFSD_NOTIFY_DELETE 7
#define DEVFS_PATHLEN 1024 /* Never change this otherwise the #define DEVFS_PATHLEN 1024 /* Never change this otherwise the
binary interface will change */ binary interface will change */
......
...@@ -30,17 +30,15 @@ ...@@ -30,17 +30,15 @@
is closed, ownership reverts back to is closed, ownership reverts back to
<<uid>> and <<gid>> and the protection <<uid>> and <<gid>> and the protection
is set to read-write for all */ is set to read-write for all */
#define DEVFS_FL_SHOW_UNREG 0x002 /* Show unregistered entries in #define DEVFS_FL_HIDE 0x002 /* Do not show entry in directory list */
directory listings */ #define DEVFS_FL_AUTO_DEVNUM 0x004 /* Automatically generate device number
#define DEVFS_FL_HIDE 0x004 /* Do not show entry in directory list */
#define DEVFS_FL_AUTO_DEVNUM 0x008 /* Automatically generate device number
*/ */
#define DEVFS_FL_AOPEN_NOTIFY 0x010 /* Asynchronously notify devfsd on open #define DEVFS_FL_AOPEN_NOTIFY 0x008 /* Asynchronously notify devfsd on open
*/ */
#define DEVFS_FL_REMOVABLE 0x020 /* This is a removable media device */ #define DEVFS_FL_REMOVABLE 0x010 /* This is a removable media device */
#define DEVFS_FL_WAIT 0x040 /* Wait for devfsd to finish */ #define DEVFS_FL_WAIT 0x020 /* Wait for devfsd to finish */
#define DEVFS_FL_NO_PERSISTENCE 0x080 /* Forget changes after unregister */ #define DEVFS_FL_NO_PERSISTENCE 0x040 /* Forget changes after unregister */
#define DEVFS_FL_CURRENT_OWNER 0x100 /* Set initial ownership to current */ #define DEVFS_FL_CURRENT_OWNER 0x080 /* Set initial ownership to current */
#define DEVFS_FL_DEFAULT DEVFS_FL_NONE #define DEVFS_FL_DEFAULT DEVFS_FL_NONE
......
...@@ -135,15 +135,13 @@ struct rpc_xprt { ...@@ -135,15 +135,13 @@ struct rpc_xprt {
struct rpc_wait_queue sending; /* requests waiting to send */ struct rpc_wait_queue sending; /* requests waiting to send */
struct rpc_wait_queue pending; /* requests in flight */ struct rpc_wait_queue pending; /* requests in flight */
struct rpc_wait_queue backlog; /* waiting for slot */ struct rpc_wait_queue backlog; /* waiting for slot */
struct rpc_wait_queue reconn; /* waiting for reconnect */
struct rpc_rqst * free; /* free slots */ struct rpc_rqst * free; /* free slots */
struct rpc_rqst slot[RPC_MAXREQS]; struct rpc_rqst slot[RPC_MAXREQS];
unsigned long sockstate; /* Socket state */ unsigned long sockstate; /* Socket state */
unsigned char shutdown : 1, /* being shut down */ unsigned char shutdown : 1, /* being shut down */
nocong : 1, /* no congestion control */ nocong : 1, /* no congestion control */
stream : 1, /* TCP */ stream : 1, /* TCP */
tcp_more : 1, /* more record fragments */ tcp_more : 1; /* more record fragments */
connecting : 1; /* being reconnected */
/* /*
* State of TCP reply receive stuff * State of TCP reply receive stuff
...@@ -158,6 +156,8 @@ struct rpc_xprt { ...@@ -158,6 +156,8 @@ struct rpc_xprt {
/* /*
* Send stuff * Send stuff
*/ */
spinlock_t sock_lock; /* lock socket info */
spinlock_t xprt_lock; /* lock xprt info */
struct rpc_task * snd_task; /* Task blocked in send */ struct rpc_task * snd_task; /* Task blocked in send */
...@@ -185,10 +185,9 @@ int xprt_adjust_timeout(struct rpc_timeout *); ...@@ -185,10 +185,9 @@ int xprt_adjust_timeout(struct rpc_timeout *);
void xprt_release(struct rpc_task *); void xprt_release(struct rpc_task *);
void xprt_reconnect(struct rpc_task *); void xprt_reconnect(struct rpc_task *);
int xprt_clear_backlog(struct rpc_xprt *); int xprt_clear_backlog(struct rpc_xprt *);
int xprt_tcp_pending(void);
void __rpciod_tcp_dispatcher(void); void __rpciod_tcp_dispatcher(void);
extern struct list_head rpc_xprt_pending;
#define XPRT_WSPACE 0 #define XPRT_WSPACE 0
#define XPRT_CONNECT 1 #define XPRT_CONNECT 1
...@@ -201,12 +200,6 @@ extern struct list_head rpc_xprt_pending; ...@@ -201,12 +200,6 @@ extern struct list_head rpc_xprt_pending;
#define xprt_test_and_set_connected(xp) (test_and_set_bit(XPRT_CONNECT, &(xp)->sockstate)) #define xprt_test_and_set_connected(xp) (test_and_set_bit(XPRT_CONNECT, &(xp)->sockstate))
#define xprt_clear_connected(xp) (clear_bit(XPRT_CONNECT, &(xp)->sockstate)) #define xprt_clear_connected(xp) (clear_bit(XPRT_CONNECT, &(xp)->sockstate))
static inline
int xprt_tcp_pending(void)
{
return !list_empty(&rpc_xprt_pending);
}
static inline static inline
void rpciod_tcp_dispatcher(void) void rpciod_tcp_dispatcher(void)
{ {
......
...@@ -170,6 +170,8 @@ extern unsigned long swap_cache_find_success; ...@@ -170,6 +170,8 @@ extern unsigned long swap_cache_find_success;
extern spinlock_t pagemap_lru_lock; extern spinlock_t pagemap_lru_lock;
extern void FASTCALL(mark_page_accessed(struct page *));
/* /*
* List add/del helper macros. These must be called * List add/del helper macros. These must be called
* with the pagemap_lru_lock held! * with the pagemap_lru_lock held!
......
...@@ -86,19 +86,18 @@ lookup_exec_domain(u_long personality) ...@@ -86,19 +86,18 @@ lookup_exec_domain(u_long personality)
if (try_inc_mod_count(ep->module)) if (try_inc_mod_count(ep->module))
goto out; goto out;
} }
read_unlock(&exec_domains_lock);
#ifdef CONFIG_KMOD #ifdef CONFIG_KMOD
read_unlock(&exec_domains_lock);
sprintf(buffer, "personality-%ld", pers); sprintf(buffer, "personality-%ld", pers);
request_module(buffer); request_module(buffer);
read_lock(&exec_domains_lock); read_lock(&exec_domains_lock);
for (ep = exec_domains; ep; ep = ep->next) { for (ep = exec_domains; ep; ep = ep->next) {
if (pers >= ep->pers_low && pers <= ep->pers_high) if (pers >= ep->pers_low && pers <= ep->pers_high)
if (try_inc_mod_count(ep->module)) if (try_inc_mod_count(ep->module))
goto out; goto out;
} }
read_unlock(&exec_domains_lock);
#endif #endif
ep = &default_exec_domain; ep = &default_exec_domain;
......
...@@ -420,8 +420,6 @@ static inline struct page * __find_page_nolock(struct address_space *mapping, un ...@@ -420,8 +420,6 @@ static inline struct page * __find_page_nolock(struct address_space *mapping, un
break; break;
} }
SetPageReferenced(page);
not_found: not_found:
return page; return page;
} }
...@@ -1086,6 +1084,26 @@ static void generic_file_readahead(int reada_ok, ...@@ -1086,6 +1084,26 @@ static void generic_file_readahead(int reada_ok,
return; return;
} }
/*
* Mark a page as having seen activity.
*
* If it was already so marked, move it
* to the active queue and drop the referenced
* bit. Otherwise, just mark it for future
* action..
*/
void mark_page_accessed(struct page *page)
{
if (!PageActive(page) && PageReferenced(page)) {
activate_page(page);
ClearPageReferenced(page);
return;
}
/* Mark the page referenced, AFTER checking for previous usage.. */
SetPageReferenced(page);
}
/* /*
* This is a generic file read routine, and uses the * This is a generic file read routine, and uses the
* inode->i_op->readpage() function for the actual low-level * inode->i_op->readpage() function for the actual low-level
...@@ -1203,6 +1221,7 @@ void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * ...@@ -1203,6 +1221,7 @@ void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t *
index += offset >> PAGE_CACHE_SHIFT; index += offset >> PAGE_CACHE_SHIFT;
offset &= ~PAGE_CACHE_MASK; offset &= ~PAGE_CACHE_MASK;
mark_page_accessed(page);
page_cache_release(page); page_cache_release(page);
if (ret == nr && desc->count) if (ret == nr && desc->count)
continue; continue;
...@@ -2534,6 +2553,7 @@ struct page *__read_cache_page(struct address_space *mapping, ...@@ -2534,6 +2553,7 @@ struct page *__read_cache_page(struct address_space *mapping,
} }
if (cached_page) if (cached_page)
page_cache_release(cached_page); page_cache_release(cached_page);
mark_page_accessed(page);
return page; return page;
} }
......
...@@ -82,8 +82,13 @@ void __free_pte(pte_t pte) ...@@ -82,8 +82,13 @@ void __free_pte(pte_t pte)
* free_page() used to be able to clear swap cache * free_page() used to be able to clear swap cache
* entries. We may now have to do it manually. * entries. We may now have to do it manually.
*/ */
if (pte_dirty(pte) && page->mapping) if (page->mapping) {
if (pte_dirty(pte))
set_page_dirty(page); set_page_dirty(page);
if (pte_young(pte))
mark_page_accessed(page);
}
free_page_and_swap_cache(page); free_page_and_swap_cache(page);
} }
......
...@@ -340,11 +340,15 @@ struct page * __alloc_pages(unsigned int gfp_mask, unsigned int order, zonelist_ ...@@ -340,11 +340,15 @@ struct page * __alloc_pages(unsigned int gfp_mask, unsigned int order, zonelist_
zone = zonelist->zones; zone = zonelist->zones;
for (;;) { for (;;) {
unsigned long min;
zone_t *z = *(zone++); zone_t *z = *(zone++);
if (!z) if (!z)
break; break;
if (zone_free_pages(z, order) > (gfp_mask & __GFP_HIGH ? z->pages_min / 2 : z->pages_min)) { min = z->pages_min;
if (!(gfp_mask & __GFP_WAIT))
min >>= 2;
if (zone_free_pages(z, order) > min) {
page = rmqueue(z, order); page = rmqueue(z, order);
if (page) if (page)
return page; return page;
......
...@@ -52,10 +52,12 @@ static inline int try_to_swap_out(struct mm_struct * mm, struct vm_area_struct* ...@@ -52,10 +52,12 @@ static inline int try_to_swap_out(struct mm_struct * mm, struct vm_area_struct*
/* Don't look at this pte if it's been accessed recently. */ /* Don't look at this pte if it's been accessed recently. */
if (ptep_test_and_clear_young(page_table)) { if (ptep_test_and_clear_young(page_table)) {
flush_tlb_page(vma, address); flush_tlb_page(vma, address);
activate_page(page); mark_page_accessed(page);
return 0; return 0;
} }
if ((PageInactive(page) || PageActive(page)) && PageReferenced(page))
/* Don't bother with it if the page is otherwise active */
if (PageActive(page))
return 0; return 0;
if (TryLockPage(page)) if (TryLockPage(page))
...@@ -91,8 +93,6 @@ static inline int try_to_swap_out(struct mm_struct * mm, struct vm_area_struct* ...@@ -91,8 +93,6 @@ static inline int try_to_swap_out(struct mm_struct * mm, struct vm_area_struct*
UnlockPage(page); UnlockPage(page);
{ {
int freeable = page_count(page) - !!page->buffers <= 2; int freeable = page_count(page) - !!page->buffers <= 2;
if (freeable)
deactivate_page(page);
page_cache_release(page); page_cache_release(page);
return freeable & right_classzone; return freeable & right_classzone;
} }
...@@ -355,31 +355,10 @@ static int shrink_cache(struct list_head * lru, int * max_scan, int this_max_sca ...@@ -355,31 +355,10 @@ static int shrink_cache(struct list_head * lru, int * max_scan, int this_max_sca
this_max_scan--; this_max_scan--;
if (PageTestandClearReferenced(page)) {
if (!PageSwapCache(page)) {
if (PageInactive(page)) {
del_page_from_inactive_list(page);
add_page_to_active_list(page);
} else if (PageActive(page)) {
list_del(entry);
list_add(entry, &active_list);
} else
BUG();
} else {
list_del(entry); list_del(entry);
list_add(entry, lru); list_add(entry, lru);
} if (PageTestandClearReferenced(page))
continue; continue;
}
if (PageInactive(page)) {
/* just roll it over, no need to update any stat */
list_del(entry);
list_add(entry, &inactive_list);
} else {
del_page_from_active_list(page);
add_page_to_inactive_list(page);
}
if (unlikely(!memclass(page->zone, classzone))) if (unlikely(!memclass(page->zone, classzone)))
continue; continue;
...@@ -387,10 +366,8 @@ static int shrink_cache(struct list_head * lru, int * max_scan, int this_max_sca ...@@ -387,10 +366,8 @@ static int shrink_cache(struct list_head * lru, int * max_scan, int this_max_sca
__max_scan--; __max_scan--;
/* Racy check to avoid trylocking when not worthwhile */ /* Racy check to avoid trylocking when not worthwhile */
if (!page->buffers && page_count(page) != 1) { if (!page->buffers && page_count(page) != 1)
activate_page_nolock(page);
continue; continue;
}
/* /*
* The page is locked. IO in progress? * The page is locked. IO in progress?
...@@ -547,10 +524,17 @@ static void balance_inactive(int nr_pages) ...@@ -547,10 +524,17 @@ static void balance_inactive(int nr_pages)
page = list_entry(entry, struct page, lru); page = list_entry(entry, struct page, lru);
entry = entry->prev; entry = entry->prev;
if (PageTestandClearReferenced(page))
continue;
del_page_from_active_list(page); del_page_from_active_list(page);
add_page_to_inactive_list(page); add_page_to_inactive_list(page);
} }
/* move active list to between "entry" and "entry->next" */
__list_del(active_list.prev, active_list.next);
__list_add(&active_list, entry, entry->next);
spin_unlock(&pagemap_lru_lock); spin_unlock(&pagemap_lru_lock);
} }
...@@ -568,10 +552,6 @@ static int shrink_caches(int priority, zone_t * classzone, unsigned int gfp_mask ...@@ -568,10 +552,6 @@ static int shrink_caches(int priority, zone_t * classzone, unsigned int gfp_mask
if (nr_pages <= 0) if (nr_pages <= 0)
return 0; return 0;
nr_pages = shrink_cache(&active_list, &max_scan, nr_active_pages / DEF_PRIORITY, nr_pages, classzone, gfp_mask);
if (nr_pages <= 0)
return 0;
shrink_dcache_memory(priority, gfp_mask); shrink_dcache_memory(priority, gfp_mask);
shrink_icache_memory(priority, gfp_mask); shrink_icache_memory(priority, gfp_mask);
......
...@@ -69,7 +69,7 @@ rpcauth_destroy(struct rpc_auth *auth) ...@@ -69,7 +69,7 @@ rpcauth_destroy(struct rpc_auth *auth)
auth->au_ops->destroy(auth); auth->au_ops->destroy(auth);
} }
spinlock_t rpc_credcache_lock = SPIN_LOCK_UNLOCKED; static spinlock_t rpc_credcache_lock = SPIN_LOCK_UNLOCKED;
/* /*
* Initialize RPC credential cache * Initialize RPC credential cache
......
...@@ -55,6 +55,8 @@ static void call_refresh(struct rpc_task *task); ...@@ -55,6 +55,8 @@ static void call_refresh(struct rpc_task *task);
static void call_refreshresult(struct rpc_task *task); static void call_refreshresult(struct rpc_task *task);
static void call_timeout(struct rpc_task *task); static void call_timeout(struct rpc_task *task);
static void call_reconnect(struct rpc_task *task); static void call_reconnect(struct rpc_task *task);
static void child_reconnect(struct rpc_task *);
static void child_reconnect_status(struct rpc_task *);
static u32 * call_header(struct rpc_task *task); static u32 * call_header(struct rpc_task *task);
static u32 * call_verify(struct rpc_task *task); static u32 * call_verify(struct rpc_task *task);
...@@ -525,6 +527,7 @@ static void ...@@ -525,6 +527,7 @@ static void
call_reconnect(struct rpc_task *task) call_reconnect(struct rpc_task *task)
{ {
struct rpc_clnt *clnt = task->tk_client; struct rpc_clnt *clnt = task->tk_client;
struct rpc_task *child;
dprintk("RPC: %4d call_reconnect status %d\n", dprintk("RPC: %4d call_reconnect status %d\n",
task->tk_pid, task->tk_status); task->tk_pid, task->tk_status);
...@@ -532,10 +535,31 @@ call_reconnect(struct rpc_task *task) ...@@ -532,10 +535,31 @@ call_reconnect(struct rpc_task *task)
task->tk_action = call_transmit; task->tk_action = call_transmit;
if (task->tk_status < 0 || !clnt->cl_xprt->stream) if (task->tk_status < 0 || !clnt->cl_xprt->stream)
return; return;
clnt->cl_stats->netreconn++;
/* Run as a child to ensure it runs as an rpciod task */
child = rpc_new_child(clnt, task);
if (child) {
child->tk_action = child_reconnect;
rpc_run_child(task, child, NULL);
}
}
static void child_reconnect(struct rpc_task *task)
{
task->tk_client->cl_stats->netreconn++;
task->tk_status = 0;
task->tk_action = child_reconnect_status;
xprt_reconnect(task); xprt_reconnect(task);
} }
static void child_reconnect_status(struct rpc_task *task)
{
if (task->tk_status == -EAGAIN)
task->tk_action = child_reconnect;
else
task->tk_action = NULL;
}
/* /*
* 5. Transmit the RPC request, and wait for reply * 5. Transmit the RPC request, and wait for reply
*/ */
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
static struct rpc_clnt * pmap_create(char *, struct sockaddr_in *, int); static struct rpc_clnt * pmap_create(char *, struct sockaddr_in *, int);
static void pmap_getport_done(struct rpc_task *); static void pmap_getport_done(struct rpc_task *);
extern struct rpc_program pmap_program; extern struct rpc_program pmap_program;
spinlock_t pmap_lock = SPIN_LOCK_UNLOCKED; static spinlock_t pmap_lock = SPIN_LOCK_UNLOCKED;
/* /*
* Obtain the port for a given RPC service on a given host. This one can * Obtain the port for a given RPC service on a given host. This one can
......
...@@ -76,7 +76,7 @@ spinlock_t rpc_queue_lock = SPIN_LOCK_UNLOCKED; ...@@ -76,7 +76,7 @@ spinlock_t rpc_queue_lock = SPIN_LOCK_UNLOCKED;
/* /*
* Spinlock for other critical sections of code. * Spinlock for other critical sections of code.
*/ */
spinlock_t rpc_sched_lock = SPIN_LOCK_UNLOCKED; static spinlock_t rpc_sched_lock = SPIN_LOCK_UNLOCKED;
/* /*
* This is the last-ditch buffer for NFS swap requests * This is the last-ditch buffer for NFS swap requests
......
This diff is collapsed.
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