Skip to content

Commit 938e13a

Browse files
committed
netfs: Implement buffered write API
Institute a netfs write helper, netfs_file_write_iter(), to be pointed at by the network filesystem ->write_iter() call. Make it handled buffered writes by calling the previously defined netfs_perform_write() to copy the source data into the pagecache. Signed-off-by: David Howells <[email protected]> Reviewed-by: Jeff Layton <[email protected]> cc: [email protected] cc: [email protected] cc: [email protected]
1 parent 153a996 commit 938e13a

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

fs/netfs/buffered_write.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,3 +333,86 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter,
333333
goto out;
334334
}
335335
EXPORT_SYMBOL(netfs_perform_write);
336+
337+
/**
338+
* netfs_buffered_write_iter_locked - write data to a file
339+
* @iocb: IO state structure (file, offset, etc.)
340+
* @from: iov_iter with data to write
341+
* @netfs_group: Grouping for dirty pages (eg. ceph snaps).
342+
*
343+
* This function does all the work needed for actually writing data to a
344+
* file. It does all basic checks, removes SUID from the file, updates
345+
* modification times and calls proper subroutines depending on whether we
346+
* do direct IO or a standard buffered write.
347+
*
348+
* The caller must hold appropriate locks around this function and have called
349+
* generic_write_checks() already. The caller is also responsible for doing
350+
* any necessary syncing afterwards.
351+
*
352+
* This function does *not* take care of syncing data in case of O_SYNC write.
353+
* A caller has to handle it. This is mainly due to the fact that we want to
354+
* avoid syncing under i_rwsem.
355+
*
356+
* Return:
357+
* * number of bytes written, even for truncated writes
358+
* * negative error code if no data has been written at all
359+
*/
360+
ssize_t netfs_buffered_write_iter_locked(struct kiocb *iocb, struct iov_iter *from,
361+
struct netfs_group *netfs_group)
362+
{
363+
struct file *file = iocb->ki_filp;
364+
ssize_t ret;
365+
366+
trace_netfs_write_iter(iocb, from);
367+
368+
ret = file_remove_privs(file);
369+
if (ret)
370+
return ret;
371+
372+
ret = file_update_time(file);
373+
if (ret)
374+
return ret;
375+
376+
return netfs_perform_write(iocb, from, netfs_group);
377+
}
378+
EXPORT_SYMBOL(netfs_buffered_write_iter_locked);
379+
380+
/**
381+
* netfs_file_write_iter - write data to a file
382+
* @iocb: IO state structure
383+
* @from: iov_iter with data to write
384+
*
385+
* Perform a write to a file, writing into the pagecache if possible and doing
386+
* an unbuffered write instead if not.
387+
*
388+
* Return:
389+
* * Negative error code if no data has been written at all of
390+
* vfs_fsync_range() failed for a synchronous write
391+
* * Number of bytes written, even for truncated writes
392+
*/
393+
ssize_t netfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
394+
{
395+
struct file *file = iocb->ki_filp;
396+
struct inode *inode = file->f_mapping->host;
397+
struct netfs_inode *ictx = netfs_inode(inode);
398+
ssize_t ret;
399+
400+
_enter("%llx,%zx,%llx", iocb->ki_pos, iov_iter_count(from), i_size_read(inode));
401+
402+
if ((iocb->ki_flags & IOCB_DIRECT) ||
403+
test_bit(NETFS_ICTX_UNBUFFERED, &ictx->flags))
404+
return netfs_unbuffered_write_iter(iocb, from);
405+
406+
ret = netfs_start_io_write(inode);
407+
if (ret < 0)
408+
return ret;
409+
410+
ret = generic_write_checks(iocb, from);
411+
if (ret > 0)
412+
ret = netfs_buffered_write_iter_locked(iocb, from, NULL);
413+
netfs_end_io_write(inode);
414+
if (ret > 0)
415+
ret = generic_write_sync(iocb, ret);
416+
return ret;
417+
}
418+
EXPORT_SYMBOL(netfs_file_write_iter);

include/linux/netfs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,10 @@ ssize_t netfs_unbuffered_read_iter(struct kiocb *iocb, struct iov_iter *iter);
382382
/* High-level write API */
383383
ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter,
384384
struct netfs_group *netfs_group);
385+
ssize_t netfs_buffered_write_iter_locked(struct kiocb *iocb, struct iov_iter *from,
386+
struct netfs_group *netfs_group);
385387
ssize_t netfs_unbuffered_write_iter(struct kiocb *iocb, struct iov_iter *from);
388+
ssize_t netfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from);
386389

387390
/* Address operations API */
388391
struct readahead_control;

0 commit comments

Comments
 (0)