}
while (page_nr < spd_pages)
- page_cache_release(spd->pages[page_nr++]);
+ spd->spd_release(spd, page_nr++);
return ret;
}
+static void spd_release_page(struct splice_pipe_desc *spd, unsigned int i)
+{
+ page_cache_release(spd->pages[i]);
+}
+
static int
__generic_file_splice_read(struct file *in, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len,
.partial = partial,
.flags = flags,
.ops = &page_cache_pipe_buf_ops,
+ .spd_release = spd_release_page,
};
index = *ppos >> PAGE_CACHE_SHIFT;
{
struct address_space *mapping = out->f_mapping;
struct inode *inode = mapping->host;
+ int killsuid, killpriv;
ssize_t ret;
- int err;
+ int err = 0;
- err = should_remove_suid(out->f_path.dentry);
- if (unlikely(err)) {
+ killpriv = security_inode_need_killpriv(out->f_path.dentry);
+ killsuid = should_remove_suid(out->f_path.dentry);
+ if (unlikely(killsuid || killpriv)) {
mutex_lock(&inode->i_mutex);
- err = __remove_suid(out->f_path.dentry, err);
+ if (killpriv)
+ err = security_inode_killpriv(out->f_path.dentry);
+ if (!err && killsuid)
+ err = __remove_suid(out->f_path.dentry, killsuid);
mutex_unlock(&inode->i_mutex);
if (err)
return err;
if (unlikely(ret < 0))
return ret;
- ret = security_file_permission(out, MAY_WRITE);
- if (unlikely(ret < 0))
- return ret;
-
return out->f_op->splice_write(pipe, out, ppos, len, flags);
}
if (unlikely(ret < 0))
return ret;
- ret = security_file_permission(in, MAY_READ);
- if (unlikely(ret < 0))
- return ret;
-
return in->f_op->splice_read(in, ppos, pipe, len, flags);
}
goto out_release;
}
+done:
pipe->nrbufs = pipe->curbuf = 0;
+ file_accessed(in);
return bytes;
out_release:
buf->ops = NULL;
}
}
- pipe->nrbufs = pipe->curbuf = 0;
- /*
- * If we transferred some data, return the number of bytes:
- */
- if (bytes > 0)
- return bytes;
-
- return ret;
+ if (!bytes)
+ bytes = ret;
+ goto done;
}
EXPORT_SYMBOL(splice_direct_to_actor);
.partial = partial,
.flags = flags,
.ops = &user_page_pipe_buf_ops,
+ .spd_release = spd_release_page,
};
pipe = pipe_info(file->f_path.dentry->d_inode);