lkml.org 
[lkml]   [2012]   [Dec]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [PATCH 5/6] fuse: truncate file if async dio failed
    On 12/14/2012 10:21 AM, Maxim V. Patlasov wrote:
    > The patch improves error handling in fuse_direct_IO(): if we successfully
    > submitted several fuse requests on behalf of synchronous direct write
    > extending file and some of them failed, let's try to do our best to clean-up.
    >
    > Signed-off-by: Maxim Patlasov <mpatlasov@parallels.com>
    > ---
    > fs/fuse/file.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
    > 1 files changed, 53 insertions(+), 2 deletions(-)
    >
    > diff --git a/fs/fuse/file.c b/fs/fuse/file.c
    > index 05eed23..b6e9b8d 100644
    > --- a/fs/fuse/file.c
    > +++ b/fs/fuse/file.c
    > @@ -2340,6 +2340,53 @@ int fuse_notify_poll_wakeup(struct fuse_conn *fc,
    > return 0;
    > }
    >
    > +static void fuse_do_truncate(struct file *file)
    > +{
    > + struct fuse_file *ff = file->private_data;
    > + struct inode *inode = file->f_mapping->host;
    > + struct fuse_conn *fc = get_fuse_conn(inode);
    > + struct fuse_req *req;
    > + struct fuse_setattr_in inarg;
    > + struct fuse_attr_out outarg;
    > + int err;
    > +
    > + req = fuse_get_req_nopages(fc);
    > + if (IS_ERR(req)) {
    > + printk(KERN_WARNING "failed to allocate req for truncate "
    > + "(%ld)\n", PTR_ERR(req));
    > + return;
    > + }
    > +
    > + memset(&inarg, 0, sizeof(inarg));
    > + memset(&outarg, 0, sizeof(outarg));
    > +
    > + inarg.valid |= FATTR_SIZE;
    > + inarg.size = i_size_read(inode);
    > +
    > + inarg.valid |= FATTR_FH;
    > + inarg.fh = ff->fh;
    > +
    > + req->in.h.opcode = FUSE_SETATTR;
    > + req->in.h.nodeid = get_node_id(inode);
    > + req->in.numargs = 1;
    > + req->in.args[0].size = sizeof(inarg);
    > + req->in.args[0].value = &inarg;
    > + req->out.numargs = 1;
    > + if (fc->minor < 9)
    > + req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
    > + else
    > + req->out.args[0].size = sizeof(outarg);
    > + req->out.args[0].value = &outarg;
    > +
    > + fuse_request_send(fc, req);
    > + err = req->out.h.error;
    > + fuse_put_request(fc, req);
    > +
    > + if (err)
    > + printk(KERN_WARNING "failed to truncate to %lld with error "
    > + "%d\n", i_size_read(inode), err);
    > +}
    > +

    fuse_do_truncate() looks fairly close to fuse_do_setattr(). Is there any
    reason we couldn't make fuse_do_setattr() non-static, change the dentry
    parameter to an inode and use that?

    Brian

    > static ssize_t
    > fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
    > loff_t offset, unsigned long nr_segs)
    > @@ -2400,8 +2447,12 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
    > kfree(io);
    > }
    >
    > - if (rw == WRITE && ret > 0)
    > - fuse_write_update_size(inode, pos);
    > + if (rw == WRITE) {
    > + if (ret > 0)
    > + fuse_write_update_size(inode, pos);
    > + else if (ret < 0 && offset + count > i_size)
    > + fuse_do_truncate(file);
    > + }
    >
    > return ret;
    > }
    >



    \
     
     \ /
      Last update: 2012-12-14 22:01    [W:4.311 / U:0.264 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site