Messages in this thread Patch in this message | | | Date | Wed, 23 Dec 1998 23:22:40 +0100 | From | Pavel Machek <> | Subject | Re: Sendfile/copyfd questions/suggestions |
| |
Hi!
> As you see I like the unix "everything is a file" philosophy. > And I view sendfile more as copyfd functionality. > Not just a possibility to send a file to a socket.
I completely agree. Here is patch. Feed it to Linus if you are able to :-).
> Said this specially the "connect this two files until I say stop" > functionality looks > promising to me.
Why not while(1) { sendfile (from, to, _SOME_BIG_NUMBER_ ) }, and send yourself signal if you want to stop?
Pavel
PS: Known problem with sendfile is that it ignores signals... Should be fixed. (My patch only extends this problem).
PPS: Linus, please, what is wrong with turning sendfile into copyfd? I think that having _interface_ limited to files only is just plain stupid.
--- clean//mm/filemap.c Mon Dec 7 17:46:10 1998 +++ linux/mm/filemap.c Fri Dec 4 15:01:25 1998 @@ -875,6 +875,48 @@ return written; } +ssize_t trivial_copyfd(int out_fd, int in_fd, size_t count) +{ +extern asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count); +extern asmlinkage ssize_t sys_write(unsigned int fd, const char * buf, size_t count); + + /* This is really trivial, we could be quite a bit more + * clever: checking both files outside of loop could be easily + * done... But this code is 'obviously right'. */ + char *buffer = (char *) __get_free_page( GFP_KERNEL ); + /* We do not need page to be cleared */ + int i, j; + int res = 0; + + if (!buffer) + return -ENOMEM; + set_fs(KERNEL_DS); + while (count && !signal_pending(current)) { + i = count>PAGE_SIZE ? PAGE_SIZE : count; + i = sys_read(in_fd, buffer, i ); + if (i<0) { + res = i; + break; + } + if (!i) + break; + j = sys_write(out_fd, buffer, i ); + if (j<0) { + res = j; + break; + } + res += j; + if (i!=j) + break; + count -= j; + + } + set_fs(USER_DS); + + free_page( (long) buffer ); + return res; +} + asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count) { ssize_t retval; @@ -895,9 +937,10 @@ retval = -EINVAL; in_inode = in_file->f_dentry->d_inode; if (!in_inode) - goto fput_in; + goto fallback; if (!in_inode->i_op || !in_inode->i_op->readpage) - goto fput_in; + goto fallback; + retval = locks_verify_area(FLOCK_VERIFY_READ, in_inode, in_file, in_file->f_pos, count); if (retval) goto fput_in; @@ -955,6 +998,12 @@ out: unlock_kernel(); return retval; + +fallback: + fput(in_file); + unlock_kernel(); + if (offset) return -EINVAL; + return trivial_copyfd( out_fd, in_fd, count ); } /*
-- I'm really pavel@atrey.karlin.mff.cuni.cz. Pavel Look at http://atrey.karlin.mff.cuni.cz/~pavel/ ;-).
- 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/
| |