Commit 67de87c5 authored by Andrew Morton's avatar Andrew Morton Committed by Jaroslav Kysela

[PATCH] don't apply file size rlimits to blockdevs

generic_file_write()'s rlimit checks are preventing writes to large
offsets into blockdevs:

# ulimit -f 10000
# dd if=/dev/zero of=/dev/sde5 bs=1k count=1 seek=1000000
zsh: file size limit exceeded

So don't apply that check if it's a blockdev.

The patch also caches the S_ISBLK result in a local.
parent db0d232c
...@@ -1530,6 +1530,7 @@ generic_file_write_nolock(struct file *file, const struct iovec *iov, ...@@ -1530,6 +1530,7 @@ generic_file_write_nolock(struct file *file, const struct iovec *iov,
size_t count; /* after file limit checks */ size_t count; /* after file limit checks */
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur; unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
const int isblk = S_ISBLK(inode->i_mode);
long status = 0; long status = 0;
loff_t pos; loff_t pos;
struct page *page; struct page *page;
...@@ -1581,22 +1582,21 @@ generic_file_write_nolock(struct file *file, const struct iovec *iov, ...@@ -1581,22 +1582,21 @@ generic_file_write_nolock(struct file *file, const struct iovec *iov,
written = 0; written = 0;
/* FIXME: this is for backwards compatibility with 2.4 */ if (!isblk) {
if (!S_ISBLK(inode->i_mode) && file->f_flags & O_APPEND) /* FIXME: this is for backwards compatibility with 2.4 */
pos = inode->i_size; if (file->f_flags & O_APPEND)
pos = inode->i_size;
/* if (limit != RLIM_INFINITY) {
* Check whether we've reached the file size limit. if (pos >= limit) {
*/ send_sig(SIGXFSZ, current, 0);
if (unlikely(limit != RLIM_INFINITY)) { err = -EFBIG;
if (pos >= limit) { goto out;
send_sig(SIGXFSZ, current, 0); }
err = -EFBIG; if (pos > 0xFFFFFFFFULL || count > limit - (u32)pos) {
goto out; /* send_sig(SIGXFSZ, current, 0); */
} count = limit - (u32)pos;
if (pos > 0xFFFFFFFFULL || count > limit - (u32)pos) { }
/* send_sig(SIGXFSZ, current, 0); */
count = limit - (u32)pos;
} }
} }
...@@ -1623,7 +1623,7 @@ generic_file_write_nolock(struct file *file, const struct iovec *iov, ...@@ -1623,7 +1623,7 @@ generic_file_write_nolock(struct file *file, const struct iovec *iov,
* exceeded without writing data we send a signal and return EFBIG. * exceeded without writing data we send a signal and return EFBIG.
* Linus frestrict idea will clean these up nicely.. * Linus frestrict idea will clean these up nicely..
*/ */
if (likely(!S_ISBLK(inode->i_mode))) { if (likely(!isblk)) {
if (unlikely(pos >= inode->i_sb->s_maxbytes)) { if (unlikely(pos >= inode->i_sb->s_maxbytes)) {
if (count || pos > inode->i_sb->s_maxbytes) { if (count || pos > inode->i_sb->s_maxbytes) {
send_sig(SIGXFSZ, current, 0); send_sig(SIGXFSZ, current, 0);
...@@ -1667,7 +1667,7 @@ generic_file_write_nolock(struct file *file, const struct iovec *iov, ...@@ -1667,7 +1667,7 @@ generic_file_write_nolock(struct file *file, const struct iovec *iov,
iov, pos, nr_segs); iov, pos, nr_segs);
if (written > 0) { if (written > 0) {
loff_t end = pos + written; loff_t end = pos + written;
if (end > inode->i_size && !S_ISBLK(inode->i_mode)) { if (end > inode->i_size && !isblk) {
inode->i_size = end; inode->i_size = end;
mark_inode_dirty(inode); mark_inode_dirty(inode);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment