Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro: "Assorted fixes all over the place. The iov_iter one is this cycle regression (splice from UDP triggering WARN_ON()), the rest is older" * 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: afs: Use d_instantiate() rather than d_add() and don't d_drop() afs: Fix missing net error handling afs: Fix validation/callback interaction iov_iter: teach csum_and_copy_to_iter() to handle pipe-backed ones exportfs: do not read dentry after free exportfs: fix 'passing zero to ERR_PTR()' warning aio: fix failure to put the file pointer sysv: return 'err' instead of 0 in __sysv_write_inode
This commit is contained in:
commit
5f1ca5c619
|
@ -1075,8 +1075,6 @@ static void afs_vnode_new_inode(struct afs_fs_cursor *fc,
|
|||
if (fc->ac.error < 0)
|
||||
return;
|
||||
|
||||
d_drop(new_dentry);
|
||||
|
||||
inode = afs_iget(fc->vnode->vfs_inode.i_sb, fc->key,
|
||||
newfid, newstatus, newcb, fc->cbi);
|
||||
if (IS_ERR(inode)) {
|
||||
|
@ -1090,7 +1088,7 @@ static void afs_vnode_new_inode(struct afs_fs_cursor *fc,
|
|||
vnode = AFS_FS_I(inode);
|
||||
set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
|
||||
afs_vnode_commit_status(fc, vnode, 0);
|
||||
d_add(new_dentry, inode);
|
||||
d_instantiate(new_dentry, inode);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -61,8 +61,11 @@ void afs_fileserver_probe_result(struct afs_call *call)
|
|||
afs_io_error(call, afs_io_error_fs_probe_fail);
|
||||
goto out;
|
||||
case -ECONNRESET: /* Responded, but call expired. */
|
||||
case -ERFKILL:
|
||||
case -EADDRNOTAVAIL:
|
||||
case -ENETUNREACH:
|
||||
case -EHOSTUNREACH:
|
||||
case -EHOSTDOWN:
|
||||
case -ECONNREFUSED:
|
||||
case -ETIMEDOUT:
|
||||
case -ETIME:
|
||||
|
@ -132,12 +135,14 @@ out:
|
|||
static int afs_do_probe_fileserver(struct afs_net *net,
|
||||
struct afs_server *server,
|
||||
struct key *key,
|
||||
unsigned int server_index)
|
||||
unsigned int server_index,
|
||||
struct afs_error *_e)
|
||||
{
|
||||
struct afs_addr_cursor ac = {
|
||||
.index = 0,
|
||||
};
|
||||
int ret;
|
||||
bool in_progress = false;
|
||||
int err;
|
||||
|
||||
_enter("%pU", &server->uuid);
|
||||
|
||||
|
@ -151,15 +156,17 @@ static int afs_do_probe_fileserver(struct afs_net *net,
|
|||
server->probe.rtt = UINT_MAX;
|
||||
|
||||
for (ac.index = 0; ac.index < ac.alist->nr_addrs; ac.index++) {
|
||||
ret = afs_fs_get_capabilities(net, server, &ac, key, server_index,
|
||||
err = afs_fs_get_capabilities(net, server, &ac, key, server_index,
|
||||
true);
|
||||
if (ret != -EINPROGRESS) {
|
||||
afs_fs_probe_done(server);
|
||||
return ret;
|
||||
}
|
||||
if (err == -EINPROGRESS)
|
||||
in_progress = true;
|
||||
else
|
||||
afs_prioritise_error(_e, err, ac.abort_code);
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (!in_progress)
|
||||
afs_fs_probe_done(server);
|
||||
return in_progress;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -169,21 +176,23 @@ int afs_probe_fileservers(struct afs_net *net, struct key *key,
|
|||
struct afs_server_list *list)
|
||||
{
|
||||
struct afs_server *server;
|
||||
int i, ret;
|
||||
struct afs_error e;
|
||||
bool in_progress = false;
|
||||
int i;
|
||||
|
||||
e.error = 0;
|
||||
e.responded = false;
|
||||
for (i = 0; i < list->nr_servers; i++) {
|
||||
server = list->servers[i].server;
|
||||
if (test_bit(AFS_SERVER_FL_PROBED, &server->flags))
|
||||
continue;
|
||||
|
||||
if (!test_and_set_bit_lock(AFS_SERVER_FL_PROBING, &server->flags)) {
|
||||
ret = afs_do_probe_fileserver(net, server, key, i);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (!test_and_set_bit_lock(AFS_SERVER_FL_PROBING, &server->flags) &&
|
||||
afs_do_probe_fileserver(net, server, key, i, &e))
|
||||
in_progress = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return in_progress ? 0 : e.error;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -382,7 +382,7 @@ void afs_zap_data(struct afs_vnode *vnode)
|
|||
int afs_validate(struct afs_vnode *vnode, struct key *key)
|
||||
{
|
||||
time64_t now = ktime_get_real_seconds();
|
||||
bool valid = false;
|
||||
bool valid;
|
||||
int ret;
|
||||
|
||||
_enter("{v={%llx:%llu} fl=%lx},%x",
|
||||
|
@ -402,15 +402,21 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
|
|||
vnode->cb_v_break = vnode->volume->cb_v_break;
|
||||
valid = false;
|
||||
} else if (vnode->status.type == AFS_FTYPE_DIR &&
|
||||
test_bit(AFS_VNODE_DIR_VALID, &vnode->flags) &&
|
||||
vnode->cb_expires_at - 10 > now) {
|
||||
valid = true;
|
||||
} else if (!test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags) &&
|
||||
vnode->cb_expires_at - 10 > now) {
|
||||
(!test_bit(AFS_VNODE_DIR_VALID, &vnode->flags) ||
|
||||
vnode->cb_expires_at - 10 <= now)) {
|
||||
valid = false;
|
||||
} else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags) ||
|
||||
vnode->cb_expires_at - 10 <= now) {
|
||||
valid = false;
|
||||
} else {
|
||||
valid = true;
|
||||
}
|
||||
} else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
|
||||
valid = true;
|
||||
} else {
|
||||
vnode->cb_s_break = vnode->cb_interest->server->cb_s_break;
|
||||
vnode->cb_v_break = vnode->volume->cb_v_break;
|
||||
valid = false;
|
||||
}
|
||||
|
||||
read_sequnlock_excl(&vnode->cb_lock);
|
||||
|
|
|
@ -695,6 +695,14 @@ struct afs_interface {
|
|||
unsigned mtu; /* MTU of interface */
|
||||
};
|
||||
|
||||
/*
|
||||
* Error prioritisation and accumulation.
|
||||
*/
|
||||
struct afs_error {
|
||||
short error; /* Accumulated error */
|
||||
bool responded; /* T if server responded */
|
||||
};
|
||||
|
||||
/*
|
||||
* Cursor for iterating over a server's address list.
|
||||
*/
|
||||
|
@ -1015,6 +1023,7 @@ static inline void __afs_stat(atomic_t *s)
|
|||
* misc.c
|
||||
*/
|
||||
extern int afs_abort_to_error(u32);
|
||||
extern void afs_prioritise_error(struct afs_error *, int, u32);
|
||||
|
||||
/*
|
||||
* mntpt.c
|
||||
|
|
|
@ -118,3 +118,55 @@ int afs_abort_to_error(u32 abort_code)
|
|||
default: return -EREMOTEIO;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Select the error to report from a set of errors.
|
||||
*/
|
||||
void afs_prioritise_error(struct afs_error *e, int error, u32 abort_code)
|
||||
{
|
||||
switch (error) {
|
||||
case 0:
|
||||
return;
|
||||
default:
|
||||
if (e->error == -ETIMEDOUT ||
|
||||
e->error == -ETIME)
|
||||
return;
|
||||
case -ETIMEDOUT:
|
||||
case -ETIME:
|
||||
if (e->error == -ENOMEM ||
|
||||
e->error == -ENONET)
|
||||
return;
|
||||
case -ENOMEM:
|
||||
case -ENONET:
|
||||
if (e->error == -ERFKILL)
|
||||
return;
|
||||
case -ERFKILL:
|
||||
if (e->error == -EADDRNOTAVAIL)
|
||||
return;
|
||||
case -EADDRNOTAVAIL:
|
||||
if (e->error == -ENETUNREACH)
|
||||
return;
|
||||
case -ENETUNREACH:
|
||||
if (e->error == -EHOSTUNREACH)
|
||||
return;
|
||||
case -EHOSTUNREACH:
|
||||
if (e->error == -EHOSTDOWN)
|
||||
return;
|
||||
case -EHOSTDOWN:
|
||||
if (e->error == -ECONNREFUSED)
|
||||
return;
|
||||
case -ECONNREFUSED:
|
||||
if (e->error == -ECONNRESET)
|
||||
return;
|
||||
case -ECONNRESET: /* Responded, but call expired. */
|
||||
if (e->responded)
|
||||
return;
|
||||
e->error = error;
|
||||
return;
|
||||
|
||||
case -ECONNABORTED:
|
||||
e->responded = true;
|
||||
e->error = afs_abort_to_error(abort_code);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,7 +136,8 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
|
|||
struct afs_addr_list *alist;
|
||||
struct afs_server *server;
|
||||
struct afs_vnode *vnode = fc->vnode;
|
||||
u32 rtt, abort_code;
|
||||
struct afs_error e;
|
||||
u32 rtt;
|
||||
int error = fc->ac.error, i;
|
||||
|
||||
_enter("%lx[%d],%lx[%d],%d,%d",
|
||||
|
@ -306,8 +307,11 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
|
|||
if (fc->error != -EDESTADDRREQ)
|
||||
goto iterate_address;
|
||||
/* Fall through */
|
||||
case -ERFKILL:
|
||||
case -EADDRNOTAVAIL:
|
||||
case -ENETUNREACH:
|
||||
case -EHOSTUNREACH:
|
||||
case -EHOSTDOWN:
|
||||
case -ECONNREFUSED:
|
||||
_debug("no conn");
|
||||
fc->error = error;
|
||||
|
@ -446,50 +450,15 @@ no_more_servers:
|
|||
if (fc->flags & AFS_FS_CURSOR_VBUSY)
|
||||
goto restart_from_beginning;
|
||||
|
||||
abort_code = 0;
|
||||
error = -EDESTADDRREQ;
|
||||
e.error = -EDESTADDRREQ;
|
||||
e.responded = false;
|
||||
for (i = 0; i < fc->server_list->nr_servers; i++) {
|
||||
struct afs_server *s = fc->server_list->servers[i].server;
|
||||
int probe_error = READ_ONCE(s->probe.error);
|
||||
|
||||
switch (probe_error) {
|
||||
case 0:
|
||||
continue;
|
||||
default:
|
||||
if (error == -ETIMEDOUT ||
|
||||
error == -ETIME)
|
||||
continue;
|
||||
case -ETIMEDOUT:
|
||||
case -ETIME:
|
||||
if (error == -ENOMEM ||
|
||||
error == -ENONET)
|
||||
continue;
|
||||
case -ENOMEM:
|
||||
case -ENONET:
|
||||
if (error == -ENETUNREACH)
|
||||
continue;
|
||||
case -ENETUNREACH:
|
||||
if (error == -EHOSTUNREACH)
|
||||
continue;
|
||||
case -EHOSTUNREACH:
|
||||
if (error == -ECONNREFUSED)
|
||||
continue;
|
||||
case -ECONNREFUSED:
|
||||
if (error == -ECONNRESET)
|
||||
continue;
|
||||
case -ECONNRESET: /* Responded, but call expired. */
|
||||
if (error == -ECONNABORTED)
|
||||
continue;
|
||||
case -ECONNABORTED:
|
||||
abort_code = s->probe.abort_code;
|
||||
error = probe_error;
|
||||
continue;
|
||||
}
|
||||
afs_prioritise_error(&e, READ_ONCE(s->probe.error),
|
||||
s->probe.abort_code);
|
||||
}
|
||||
|
||||
if (error == -ECONNABORTED)
|
||||
error = afs_abort_to_error(abort_code);
|
||||
|
||||
failed_set_error:
|
||||
fc->error = error;
|
||||
failed:
|
||||
|
@ -553,8 +522,11 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc)
|
|||
_leave(" = f [abort]");
|
||||
return false;
|
||||
|
||||
case -ERFKILL:
|
||||
case -EADDRNOTAVAIL:
|
||||
case -ENETUNREACH:
|
||||
case -EHOSTUNREACH:
|
||||
case -EHOSTDOWN:
|
||||
case -ECONNREFUSED:
|
||||
case -ETIMEDOUT:
|
||||
case -ETIME:
|
||||
|
@ -633,6 +605,7 @@ int afs_end_vnode_operation(struct afs_fs_cursor *fc)
|
|||
struct afs_net *net = afs_v2net(fc->vnode);
|
||||
|
||||
if (fc->error == -EDESTADDRREQ ||
|
||||
fc->error == -EADDRNOTAVAIL ||
|
||||
fc->error == -ENETUNREACH ||
|
||||
fc->error == -EHOSTUNREACH)
|
||||
afs_dump_edestaddrreq(fc);
|
||||
|
|
|
@ -61,8 +61,11 @@ void afs_vlserver_probe_result(struct afs_call *call)
|
|||
afs_io_error(call, afs_io_error_vl_probe_fail);
|
||||
goto out;
|
||||
case -ECONNRESET: /* Responded, but call expired. */
|
||||
case -ERFKILL:
|
||||
case -EADDRNOTAVAIL:
|
||||
case -ENETUNREACH:
|
||||
case -EHOSTUNREACH:
|
||||
case -EHOSTDOWN:
|
||||
case -ECONNREFUSED:
|
||||
case -ETIMEDOUT:
|
||||
case -ETIME:
|
||||
|
@ -129,15 +132,17 @@ out:
|
|||
* Probe all of a vlserver's addresses to find out the best route and to
|
||||
* query its capabilities.
|
||||
*/
|
||||
static int afs_do_probe_vlserver(struct afs_net *net,
|
||||
struct afs_vlserver *server,
|
||||
struct key *key,
|
||||
unsigned int server_index)
|
||||
static bool afs_do_probe_vlserver(struct afs_net *net,
|
||||
struct afs_vlserver *server,
|
||||
struct key *key,
|
||||
unsigned int server_index,
|
||||
struct afs_error *_e)
|
||||
{
|
||||
struct afs_addr_cursor ac = {
|
||||
.index = 0,
|
||||
};
|
||||
int ret;
|
||||
bool in_progress = false;
|
||||
int err;
|
||||
|
||||
_enter("%s", server->name);
|
||||
|
||||
|
@ -151,15 +156,17 @@ static int afs_do_probe_vlserver(struct afs_net *net,
|
|||
server->probe.rtt = UINT_MAX;
|
||||
|
||||
for (ac.index = 0; ac.index < ac.alist->nr_addrs; ac.index++) {
|
||||
ret = afs_vl_get_capabilities(net, &ac, key, server,
|
||||
err = afs_vl_get_capabilities(net, &ac, key, server,
|
||||
server_index, true);
|
||||
if (ret != -EINPROGRESS) {
|
||||
afs_vl_probe_done(server);
|
||||
return ret;
|
||||
}
|
||||
if (err == -EINPROGRESS)
|
||||
in_progress = true;
|
||||
else
|
||||
afs_prioritise_error(_e, err, ac.abort_code);
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (!in_progress)
|
||||
afs_vl_probe_done(server);
|
||||
return in_progress;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -169,21 +176,23 @@ int afs_send_vl_probes(struct afs_net *net, struct key *key,
|
|||
struct afs_vlserver_list *vllist)
|
||||
{
|
||||
struct afs_vlserver *server;
|
||||
int i, ret;
|
||||
struct afs_error e;
|
||||
bool in_progress = false;
|
||||
int i;
|
||||
|
||||
e.error = 0;
|
||||
e.responded = false;
|
||||
for (i = 0; i < vllist->nr_servers; i++) {
|
||||
server = vllist->servers[i].server;
|
||||
if (test_bit(AFS_VLSERVER_FL_PROBED, &server->flags))
|
||||
continue;
|
||||
|
||||
if (!test_and_set_bit_lock(AFS_VLSERVER_FL_PROBING, &server->flags)) {
|
||||
ret = afs_do_probe_vlserver(net, server, key, i);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (!test_and_set_bit_lock(AFS_VLSERVER_FL_PROBING, &server->flags) &&
|
||||
afs_do_probe_vlserver(net, server, key, i, &e))
|
||||
in_progress = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return in_progress ? 0 : e.error;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -71,8 +71,9 @@ bool afs_select_vlserver(struct afs_vl_cursor *vc)
|
|||
{
|
||||
struct afs_addr_list *alist;
|
||||
struct afs_vlserver *vlserver;
|
||||
struct afs_error e;
|
||||
u32 rtt;
|
||||
int error = vc->ac.error, abort_code, i;
|
||||
int error = vc->ac.error, i;
|
||||
|
||||
_enter("%lx[%d],%lx[%d],%d,%d",
|
||||
vc->untried, vc->index,
|
||||
|
@ -119,8 +120,11 @@ bool afs_select_vlserver(struct afs_vl_cursor *vc)
|
|||
goto failed;
|
||||
}
|
||||
|
||||
case -ERFKILL:
|
||||
case -EADDRNOTAVAIL:
|
||||
case -ENETUNREACH:
|
||||
case -EHOSTUNREACH:
|
||||
case -EHOSTDOWN:
|
||||
case -ECONNREFUSED:
|
||||
case -ETIMEDOUT:
|
||||
case -ETIME:
|
||||
|
@ -235,50 +239,15 @@ no_more_servers:
|
|||
if (vc->flags & AFS_VL_CURSOR_RETRY)
|
||||
goto restart_from_beginning;
|
||||
|
||||
abort_code = 0;
|
||||
error = -EDESTADDRREQ;
|
||||
e.error = -EDESTADDRREQ;
|
||||
e.responded = false;
|
||||
for (i = 0; i < vc->server_list->nr_servers; i++) {
|
||||
struct afs_vlserver *s = vc->server_list->servers[i].server;
|
||||
int probe_error = READ_ONCE(s->probe.error);
|
||||
|
||||
switch (probe_error) {
|
||||
case 0:
|
||||
continue;
|
||||
default:
|
||||
if (error == -ETIMEDOUT ||
|
||||
error == -ETIME)
|
||||
continue;
|
||||
case -ETIMEDOUT:
|
||||
case -ETIME:
|
||||
if (error == -ENOMEM ||
|
||||
error == -ENONET)
|
||||
continue;
|
||||
case -ENOMEM:
|
||||
case -ENONET:
|
||||
if (error == -ENETUNREACH)
|
||||
continue;
|
||||
case -ENETUNREACH:
|
||||
if (error == -EHOSTUNREACH)
|
||||
continue;
|
||||
case -EHOSTUNREACH:
|
||||
if (error == -ECONNREFUSED)
|
||||
continue;
|
||||
case -ECONNREFUSED:
|
||||
if (error == -ECONNRESET)
|
||||
continue;
|
||||
case -ECONNRESET: /* Responded, but call expired. */
|
||||
if (error == -ECONNABORTED)
|
||||
continue;
|
||||
case -ECONNABORTED:
|
||||
abort_code = s->probe.abort_code;
|
||||
error = probe_error;
|
||||
continue;
|
||||
}
|
||||
afs_prioritise_error(&e, READ_ONCE(s->probe.error),
|
||||
s->probe.abort_code);
|
||||
}
|
||||
|
||||
if (error == -ECONNABORTED)
|
||||
error = afs_abort_to_error(abort_code);
|
||||
|
||||
failed_set_error:
|
||||
vc->error = error;
|
||||
failed:
|
||||
|
@ -341,6 +310,7 @@ int afs_end_vlserver_operation(struct afs_vl_cursor *vc)
|
|||
struct afs_net *net = vc->cell->net;
|
||||
|
||||
if (vc->error == -EDESTADDRREQ ||
|
||||
vc->error == -EADDRNOTAVAIL ||
|
||||
vc->error == -ENETUNREACH ||
|
||||
vc->error == -EHOSTUNREACH)
|
||||
afs_vl_dump_edestaddrreq(vc);
|
||||
|
|
1
fs/aio.c
1
fs/aio.c
|
@ -1436,6 +1436,7 @@ static int aio_prep_rw(struct kiocb *req, struct iocb *iocb)
|
|||
ret = ioprio_check_cap(iocb->aio_reqprio);
|
||||
if (ret) {
|
||||
pr_debug("aio ioprio check cap error: %d\n", ret);
|
||||
fput(req->ki_filp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ static bool dentry_connected(struct dentry *dentry)
|
|||
struct dentry *parent = dget_parent(dentry);
|
||||
|
||||
dput(dentry);
|
||||
if (IS_ROOT(dentry)) {
|
||||
if (dentry == parent) {
|
||||
dput(parent);
|
||||
return false;
|
||||
}
|
||||
|
@ -147,6 +147,7 @@ static struct dentry *reconnect_one(struct vfsmount *mnt,
|
|||
tmp = lookup_one_len_unlocked(nbuf, parent, strlen(nbuf));
|
||||
if (IS_ERR(tmp)) {
|
||||
dprintk("%s: lookup failed: %d\n", __func__, PTR_ERR(tmp));
|
||||
err = PTR_ERR(tmp);
|
||||
goto out_err;
|
||||
}
|
||||
if (tmp != dentry) {
|
||||
|
|
|
@ -275,7 +275,7 @@ static int __sysv_write_inode(struct inode *inode, int wait)
|
|||
}
|
||||
}
|
||||
brelse(bh);
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
int sysv_write_inode(struct inode *inode, struct writeback_control *wbc)
|
||||
|
|
|
@ -560,6 +560,38 @@ static size_t copy_pipe_to_iter(const void *addr, size_t bytes,
|
|||
return bytes;
|
||||
}
|
||||
|
||||
static size_t csum_and_copy_to_pipe_iter(const void *addr, size_t bytes,
|
||||
__wsum *csum, struct iov_iter *i)
|
||||
{
|
||||
struct pipe_inode_info *pipe = i->pipe;
|
||||
size_t n, r;
|
||||
size_t off = 0;
|
||||
__wsum sum = *csum, next;
|
||||
int idx;
|
||||
|
||||
if (!sanity(i))
|
||||
return 0;
|
||||
|
||||
bytes = n = push_pipe(i, bytes, &idx, &r);
|
||||
if (unlikely(!n))
|
||||
return 0;
|
||||
for ( ; n; idx = next_idx(idx, pipe), r = 0) {
|
||||
size_t chunk = min_t(size_t, n, PAGE_SIZE - r);
|
||||
char *p = kmap_atomic(pipe->bufs[idx].page);
|
||||
next = csum_partial_copy_nocheck(addr, p + r, chunk, 0);
|
||||
sum = csum_block_add(sum, next, off);
|
||||
kunmap_atomic(p);
|
||||
i->idx = idx;
|
||||
i->iov_offset = r + chunk;
|
||||
n -= chunk;
|
||||
off += chunk;
|
||||
addr += chunk;
|
||||
}
|
||||
i->count -= bytes;
|
||||
*csum = sum;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
size_t _copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i)
|
||||
{
|
||||
const char *from = addr;
|
||||
|
@ -1438,8 +1470,12 @@ size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum,
|
|||
const char *from = addr;
|
||||
__wsum sum, next;
|
||||
size_t off = 0;
|
||||
|
||||
if (unlikely(iov_iter_is_pipe(i)))
|
||||
return csum_and_copy_to_pipe_iter(addr, bytes, csum, i);
|
||||
|
||||
sum = *csum;
|
||||
if (unlikely(iov_iter_is_pipe(i) || iov_iter_is_discard(i))) {
|
||||
if (unlikely(iov_iter_is_discard(i))) {
|
||||
WARN_ON(1); /* for now */
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue