Re: [ANNOUNCEMENT PATCH COW] proof of concept impementation of cowlinks

From: Jan Harkes
Date: Tue May 11 2004 - 09:12:46 EST

On Tue, May 11, 2004 at 12:02:32PM +0200, Jörn Engel wrote:
> > Copyfile can trivially be implemented in libc. I don't see why it would
> > have to be a system call. If a network filesystem wants to optimize the
> > file copying it could do this based on the sendfile data. If source and
> > destination are within the same filesystem and we're copying the whole
> > file starting at offset 0, send a copyfile RPC.
> Can you explain this to Steve? I'm still quite clueless about network
> filesystems, but it sounded as if such an optimization was impossible
> to do in cifs without a combined create/copy/unlink_on_error system
> call.
> If your suggestion works and the network filesystems can be changed to
> work independently of a struct file*, I agree with you that copyfile()
> is a stupid idea and should be forgotten.

I would probably do it by overriding the file_operations.sendfile
function. A first approximation of a possible implementation follows. I
went a bit crazy on the comments. The only problem is that the type of
target is unknown, block/loop.c and nfsd/vfs.c are using sendfile to
to send to something that is not a struct file.


int my_file_sendfile(struct file *in_file, loff_t *ppos, size_t count,
read_actor_t actor, void __user *target)
struct file *out_file = NULL;

/* We have to check the read_actor callback function to see if the
* target actually points at a struct file. */
if (actor != file_send_actor)
goto copy_local;

/* are both source and destination within the same file system
* mountpoint? */
if (in_file->f_dentry->d_inode->i_sb != out_file->f_dentry->d_inode->i_sb)
goto copy_local;

/* are we copying the entire source file? */
if (*ppos != 0 || count != in_file->f_dentry->d_inode->i_size)
goto copy_local;

/* and are we at least overwriting the complete destination file?
(alternatively we could check that the out_file is currently empty) */
if (out_file->f_pos != 0 || out_file->f_dentry->d_inode->i_size > count)
goto copy_local;

/* we are in luck and can send a copyfile rpc */
int err = make_copyfile_rpc(in_file, out_file);

/* we probably should force a refresh of out_file as it changed on
* the server and not locally */
MY_I(out_file->f_dentry->d_inode)->time = 0;
return err;

/* no luck, we're sending to something that isn't a file or in the
* same filesystem, or we only copy a partial file. any case, we
* have to perform the copy locally. */
return generic_file_sendfile(in_file, ppos, count, actor, target);

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at
Please read the FAQ at