Background: I'm working with some web proxy cache software that ends up
doing a lot of writev's to sockets. We're using the lockstat/lockmeter
patch that was recently posted to linux-kernel to measure lock contention.
On a dual processor machine running 2 independent proxy processes, kernel_flag
contention was taking up about 30% of time before this patch. After the
patch it's closer to 10-15%. kernel_flag contention, which is the bulk of
all contention we see, still occurs in sock_alloc, do_close, sock_poll, and
a few other places.
One bit of paranoia.. in the case where kmalloc needs to be called, I
go back and call lock_kernel, since I'm not positive that kmalloc can
be called without the kernel being locked. This might be too
conservative.
gid
--- linux-2.3.19.orig/fs/read_write.c Tue Sep 7 12:22:12 1999
+++ linux-2.3.19.gid/fs/read_write.c Wed Oct 20 16:57:43 1999
@@ -173,6 +173,7 @@
ssize_t ret, i;
io_fn_t fn;
struct inode *inode;
+ int locked;
/*
* First get the "struct iovec" from user memory and
@@ -186,10 +187,22 @@
goto out_nofree;
if (count > UIO_FASTIOV) {
ret = -ENOMEM;
+ lock_kernel();
iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
- if (!iov)
+ if (!iov) {
+ unlock_kernel();
goto out_nofree;
+ }
+ locked = 1;
+ } else {
+ locked = 0;
}
+
+ /*
+ * after this point, if the kernel lock is held, then locked === 1;
+ * also, after this point, you can't jump to out_nofree.
+ */
+
ret = -EFAULT;
if (copy_from_user(iov, vector, count*sizeof(*vector)))
goto out;
@@ -214,6 +227,11 @@
ret = sock_readv_writev(type,inode,file,iov,count,tot_len);
goto out;
}
+
+ if (!locked) {
+ locked = 1;
+ lock_kernel();
+ }
ret = -EINVAL;
if (!file->f_op)
@@ -248,6 +266,8 @@
}
out:
+ if (locked)
+ unlock_kernel();
if (iov != iovstack)
kfree(iov);
out_nofree:
@@ -260,7 +280,7 @@
struct file * file;
ssize_t ret;
- lock_kernel();
+ /* lock_kernel(); */
ret = -EBADF;
file = fget(fd);
@@ -271,7 +291,7 @@
fput(file);
bad_file:
- unlock_kernel();
+ /* unlock_kernel(); */
return ret;
}
@@ -281,7 +301,7 @@
struct file * file;
ssize_t ret;
- lock_kernel();
+ /* lock_kernel(); */
ret = -EBADF;
file = fget(fd);
@@ -293,7 +313,7 @@
fput(file);
bad_file:
- unlock_kernel();
+ /* unlock_kernel(); */
return ret;
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/