Here is initial support for size truncation.
It has some problems with unconnected socket closing.

diff --git a/include/net/zerocopy.h b/include/net/zerocopy.h
--- a/include/net/zerocopy.h
+++ b/include/net/zerocopy.h
@@ -152,6 +152,7 @@ struct zsock
        u32                     zc_seq_first;
        void                    *priv;
        unsigned int            priv_size;
+       ssize_t                 written;
 };
 
 int sock_zc_setup_seq(struct zsock *zsk, u32 seq);
diff --git a/net/core/zerocopy.c b/net/core/zerocopy.c
--- a/net/core/zerocopy.c
+++ b/net/core/zerocopy.c
@@ -194,6 +194,7 @@ int commit_page(struct zc_page *zp, stru
                goto err_out;
        }
        ClearPageReserved(zp->page);
+       page_cache_release(zp->page);
        flush_dcache_page(zp->page);
        err = a_ops->commit_write(file, zp->page, zp->page_offset, 
zp->page_offset+zp->used);
        unlock_page(zp->page);
@@ -235,7 +236,7 @@ int prepare_page(struct zc_page *zp, str
        bytes = PAGE_CACHE_SIZE - page_offset;
        if (bytes > count)
                bytes = count;
-       
+
        if (down_interruptible(&mapping->host->i_sem)) {
                err = -EBUSY;
                goto err_out;
@@ -245,15 +246,17 @@ int prepare_page(struct zc_page *zp, str
                err = -ENOMEM;
                goto err_out_exit;
        }
+       page_cache_get(zp->page);
 
        err = a_ops->prepare_write(file, zp->page, page_offset, 
page_offset+bytes);
        if (unlikely(err)) {
+               page_cache_release(zp->page);
                unlock_page(zp->page);
                page_cache_release(zp->page);
                goto err_out_exit;
        }
        SetPageReserved(zp->page);
-       
+
        zc_clean_page(zp);
 
        zp->page_offset = page_offset;
@@ -272,6 +275,20 @@ err_out:
        return err;
 }
 
+static int zc_set_size(struct zsock *zsk)
+{
+       struct address_space *mapping = zsk->zc_file->f_mapping;
+       struct inode *inode = mapping->host;
+       int err;
+
+       down(&inode->i_sem);
+       down_write(&inode->i_alloc_sem);
+       err = vmtruncate(inode, zsk->written);
+       up_write(&inode->i_alloc_sem);
+       up(&inode->i_sem);
+
+       return err;
+}
 
 void sk_zc_fini(struct zsock *zsk)
 {
@@ -284,7 +301,7 @@ void sk_zc_fini(struct zsock *zsk)
                write_lock_irqsave(&zsk->zc_lock, flags);
                zc_page_num             = zsk->zc_page_num;
                zc_pages                = zsk->zc_pages;
-               
+
                zsk->zc_pages           = NULL;
                zsk->zc_page_num        = 0;
                zsk->zc_page_index      = 0;
@@ -301,7 +318,6 @@ void sk_zc_fini(struct zsock *zsk)
 
                if (zc_page_num) {
                        struct address_space *mapping = zsk->zc_file->f_mapping;
-                       loff_t size = 0;
                        int i;
 
                        if (sk)
@@ -318,10 +334,10 @@ void sk_zc_fini(struct zsock *zsk)
                         * due to above locked changes.
                         */
 
-                       for (i=0; i<zc_page_num; ++i) {
+                       for (i=zc_page_num-1; i>=0; --i) {
+                       //for (i=0; i<zc_page_num; ++i) {
                                struct zc_page *zp = &zc_pages[i];
 
-                               size += zp->used;
                                commit_page(zp, zsk->zc_file, mapping);
                                zc_clean_page(zp);
                        }
@@ -331,10 +347,8 @@ void sk_zc_fini(struct zsock *zsk)
                                zsk->zc_cached_page = NULL;
                        }
 
-                       pagevec_lru_add(&zsk->zc_lru_pvec);
+                       zc_set_size(zsk);
 
-                       if (!size)
-                               zsk->zc_file->f_pos = size;
                        zsk->zc_file->f_mode &= ~FMODE_ZEROCOPY;
                        fput(zsk->zc_file);
                        zsk->zc_file = NULL;
diff --git a/net/socket.c b/net/socket.c
--- a/net/socket.c
+++ b/net/socket.c
@@ -1212,7 +1212,6 @@ int tcp_udp_v4_sock_zc_init(struct socke
        }
 
        pagevec_init(&zsk->zc_lru_pvec, 0);
-       file->f_pos = 0;
 
        err = 0;
        for (i=0; i<pnum_max; ++i) {
@@ -1275,7 +1274,6 @@ static ssize_t sock_sendfile(struct file
        struct socket *sock;
        struct sock *sk;
        int err = 0;
-       size_t written = 0;
        struct file *file = target;
        struct address_space *mapping = file->f_mapping;
        struct inode *inode = mapping->host;
@@ -1304,6 +1302,7 @@ static ssize_t sock_sendfile(struct file
        }
 
        zsk_get(zsk);
+       zsk->written = 0;
 
        while (count) {
                struct zc_page *zp;
@@ -1319,7 +1318,7 @@ static ssize_t sock_sendfile(struct file
                                        goto err_out_release_all_pages;
                                
                                count -= zp->used;
-                               written += zp->used;
+                               zsk->written += zp->used;
 
                                err = prepare_page(zp, zsk, file, mapping, 
&zsk->zc_pos, count, &zsk->zc_lru_pvec);
                        }
@@ -1334,8 +1333,10 @@ static ssize_t sock_sendfile(struct file
                }
        }
 
-       *ppos = written;
-       err = written;
+       pagevec_lru_add(&zsk->zc_lru_pvec);
+
+       *ppos = zsk->written;
+       err = zsk->written;
 
 err_out_release_all_pages:
 

-- 
        Evgeniy Polyakov
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to