diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index a2b3c594379d..d8667c07c4eb 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -548,24 +548,32 @@ static struct btrfs_path *alloc_path_for_send(void) static int write_buf(struct file *filp, const void *buf, u32 len, loff_t *off) { - int ret; + int ret = 0; u32 pos = 0; + unsigned nofs_flag; + /* + * Pipe writes can allocate pages which can trigger reclaim and cause + * a crash if reclaim triggers inode eviction and that needs to start a + * transaction. So use a NOFS context. + */ + nofs_flag = memalloc_nofs_save(); while (pos < len) { ret = kernel_write(filp, buf + pos, len - pos, off); /* TODO handle that correctly */ /*if (ret == -ERESTARTSYS) { continue; }*/ + if (ret == 0) + ret = -EIO; if (ret < 0) - return ret; - if (ret == 0) { - return -EIO; - } + break; pos += ret; + ret = 0; } + memalloc_nofs_restore(nofs_flag); - return 0; + return ret; } static int tlv_put(struct send_ctx *sctx, u16 attr, const void *data, int len)