net: do some cleanups and backport tcp friends v4 patch

Now tcp friends patch has been applied into ali kernel.  But the version
of this patch is v3.  Later the patch has been updated and a newer patch
set has been sent out.  So this patch backport v4 patch.

Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
net: fix a panic in tcp_close()

For tcp friends data skb, it has no tcp header,
and its transport_header is NULL, so it will panic if we deference tcp_hdr(skb)
in tcp_close().

So I add a check before we use tcp_hdr().

Signed-off-by: Weiping Pan <wpan@redhat.com>
Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
net: delete request_sock->sk_friends

The sock pointed by request_sock->friend may be freed since it does not have a
lock to protect it.
I just delete request_sock->friend since I think it is useless.

For sk_buff->friend, it has the same problem, and we use
"atomic_add(skb->truesize, &sk->sk_wmem_alloc)" to guarantee that the sock can
not be freed before the skb is freed.

Then for 3-way handshake with tcp friends enabled,
SYN->friend is NULL, SYN/ACK->friend is set in tcp_make_synack(),
and ACK->friend is set in tcp_send_ack().

Signed-off-by: Weiping Pan <wpan@redhat.com>
Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
scsi: export request_queue retries via sysfs

The request's retries of scsi disk is default SD_MAX_RETRIES(5),
which is timeing consuming under some applications. Export it
to sysfs, which can be modified via:
	/sys/block/sdx/device/retries OR
	/sys/class/scsi_device/x:0:0:0/device/retries

Signed-off-by: Sha Zhengju <handai.szj@taobao.com>
scsi: set request's retries to be the value of request_queue

This patch assigns request_queue's rq_retries to request's retries,
which will be further assigned to scsi command later. In scsi EH handler,
it will affect the total completion time.

Signed-off-by: Sha Zhengju <handai.szj@taobao.com>
scsi: don't send timeout request to EH anymore

For timeout request, complete it directly without sending it to
LLD driver for processing. We increment the ref_count of request
which will prevent the request from releasing. Though this will
lead to memory leak to some extent, but can avoid system panic if
the LLD driver begin to handle the request again. Meanwhile, we
also don't free scsi_cmnd.

Signed-off-by: Sha Zhengju <handai.szj@taobao.com>
scsi: add timeout_shortcut to enable/disable the hacky request timeout path

Default we enable the hacky request timeout path, but we can choose to
disable it in runtime. It can be modified via:
        /sys/block/sdx/device/timeout_shortcut OR
        /sys/class/scsi_device/x:0:0:0/device/timeout_shortcut

Signed-off-by: Sha Zhengju <handai.szj@taobao.com>
Merge pull request #51 from shazj99/scsi_timeout

Thanks. Applied.
vfs: fix a bug when we do some buffered reads with append dio writes

Currently we check i_size in buffered read path after we know the page
is update.  But it could return some zero-filled pages to the userspace
when we do some append dio writes.  We could use the following code
snippet to reproduce this problem in a ext2/3/4 filesystem.

code snippet:
  #define _GNU_SOURCE

  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <memory.h>

  #include <unistd.h>
  #include <fcntl.h>
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <errno.h>

  #include <pthread.h>

  #define BUF_ALIGN	1024

  struct writer_data {
  	int fd;
  	size_t blksize;
  	char *buf;
  };

  static void *writer(void *arg)
  {
  	struct writer_data *data = (struct writer_data *)arg;
  	int ret;

  	ret = write(data->fd, data->buf, data->blksize);
  	if (ret < 0)
  		fprintf(stderr, "write file failed: %s\n", strerror(errno));

  	return NULL;
  }

  int main(int argc, char *argv[])
  {
  	pthread_t tid;
  	struct writer_data wdata;
  	size_t max_blocks = 10 * 1024;
  	size_t blksize = 1 * 1024 * 1024;
  	char *rbuf, *wbuf;
  	int readfd, writefd;
  	int i, j;

  	if (argc < 2) {
  		fprintf(stderr, "usage: %s [filename]\n", argv[0]);
  		exit(1);
  	}

  	writefd = open(argv[1], O_CREAT|O_DIRECT|O_WRONLY|O_APPEND|O_TRUNC, S_IRWXU);
  	if (writefd < 0) {
  		fprintf(stderr, "failed to open wfile: %s\n", strerror(errno));
  		exit(1);
  	}
  	readfd = open(argv[1], O_RDONLY, S_IRWXU);
  	if (readfd < 0) {
  		fprintf(stderr, "failed to open rfile: %s\n", strerror(errno));
  		exit(1);
  	}

  	if (posix_memalign((void **)&wbuf, BUF_ALIGN, blksize)) {
  		fprintf(stderr, "failed to alloc memory: %s\n", strerror(errno));
  		exit(1);
  	}

  	if (posix_memalign((void **)&rbuf, 4096, blksize)) {
  		fprintf(stderr, "failed to alloc memory: %s\n", strerror(errno));
  		exit(1);
  	}

  	memset(wbuf, 'a', blksize);

  	wdata.fd = writefd;
  	wdata.blksize = blksize;
  	wdata.buf = wbuf;

  	for (i = 0; i < max_blocks; i++) {
  		void *retval;
  		int ret;

  		ret = pthread_create(&tid, NULL, writer, &wdata);
  		if (ret) {
  			fprintf(stderr, "create thread failed: %s\n", strerror(errno));
  			exit(1);
  		}

  		memset(rbuf, 'b', blksize);
  		do {
  			ret = pread(readfd, rbuf, blksize, i * blksize);
  		} while (ret <= 0);

  		if (ret < 0) {
  			fprintf(stderr, "read file failed: %s\n", strerror(errno));
  			exit(1);
  		}

  		if (pthread_join(tid, &retval)) {
  			fprintf(stderr, "pthread join failed: %s\n", strerror(errno));
  			exit(1);
  		}

  		if (ret >= 0) {
  			for (j = 0; j < ret; j++) {
  				if (rbuf[j] != 'a') {
  					fprintf(stderr, "encounter an error: offset %ld\n",
  						i);
  					goto err;
  				}
  			}
  		}
  	}

  err:
  	free(wbuf);
  	free(rbuf);

  	return 0;
  }

build & run:
  $ gcc code.c -o code -lpthread # build
  $ ./code ${filename} # run

As we expected, we should read nothing or data with 'a'.  But now we
read data with '0'.  I take a closer look at the code and it seems that
there is a bug in vfs.  Let me describe my found here.

  reader					writer
                                                generic_file_aio_write()
                                                ->__generic_file_aio_write()
                                                  ->generic_file_direct_write()
  generic_file_aio_read()
  ->do_generic_file_read()
    [fallback to buffered read]

    ->find_get_page()
    ->page_cache_sync_readahead()
    ->find_get_page()
    [in find_page label, we couldn't find a
     page before and after calling
     page_cache_sync_readahead().  So go to
     no_cached_page label]

    ->page_cache_alloc_cold()
    ->add_to_page_cache_lru()
    [in no_cached_page label, we alloc a page
     and goto readpage label.]

    ->aops->readpage()
    [in readpage label, readpage() callback
     is called and mpage_readpage() return a
     zero-filled page (e.g. ext3/4), and go
     to page_ok label]

                                                  ->a_ops->direct_IO()
                                                  ->i_size_write()
                                                  [we enlarge the i_size]

    Here we check i_size
    [in page_ok label, we check i_size but
     it has been enlarged.  Thus, we pass
     the check and return a zero-filled page]

This commit first trims desc->count to avoid to read too much data if
(*ppos + desc->count) >= i_size.  Then we will return directly if
desc->count == 0.  After doing that, we could fix the above problem.
Meanwhile this also can fix the problem that the reader does some
buffered reads with append dio write.

[Note from Zheng Liu]
This patch doesn't be applied into upstream kernel because the folks
think that no one really wants to use buffered IO and direct IO at the
same time.  But at Taobao we do have an application that does it.  So
that is the reason why this patch is applied into ali-kernel.

Cc: Christoph Hellwig <hch@infradead.org>
Cc: Dmitry Monakhov <dmonakhov@openvz.org>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
Merge pull request #52 from gnehzuil/dio-bug-fix

vfs: fix a bug when we do some buffered reads with append dio writes
Merge pull request #53 from gnehzuil/tcp-friends-bug-fix

Tcp friends bug fix
vfs: fix a bug when we do some buffered reads with append dio writes, again

When pread is given a ppos greater than isize, the original check will fail
and we can still get the stale data. This bug can be exposed by modifying the
test case in commit 104bbfa583a with the following changes:

                memset(rbuf, 'b', blksize);
                do {
-                        ret = pread(readfd, rbuf, blksize, i * blksize);
+                        ret = pread(readfd, rbuf, blksize, i * blksize + 10);
                } while (ret <= 0);

Signed-off-by: Tao Ma <boyu.mt@taobao.com>
Merge pull request #54 from taoma-tm/read_fix

buffer read+dio write fix again