Commit acad2c18 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] tmpfs 1/6 use generic_write_checks

From: Hugh Dickins <hugh@veritas.com>

Remove the duplicated checks in shmem_file-write(), use
generic_write_checks() instead.
parent d80bbda5
...@@ -1126,10 +1126,8 @@ static ssize_t ...@@ -1126,10 +1126,8 @@ static ssize_t
shmem_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) shmem_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{ {
struct inode *inode = file->f_dentry->d_inode; struct inode *inode = file->f_dentry->d_inode;
unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
loff_t pos; loff_t pos;
unsigned long written; unsigned long written;
long status;
int err; int err;
loff_t maxpos; loff_t maxpos;
...@@ -1142,88 +1140,25 @@ shmem_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) ...@@ -1142,88 +1140,25 @@ shmem_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
down(&inode->i_sem); down(&inode->i_sem);
pos = *ppos; pos = *ppos;
err = -EINVAL;
if (pos < 0)
goto out_nc;
err = file->f_error;
if (err) {
file->f_error = 0;
goto out_nc;
}
written = 0; written = 0;
if (file->f_flags & O_APPEND) err = generic_write_checks(inode, file, &pos, &count, 0);
pos = inode->i_size; if (err || !count)
goto out;
maxpos = inode->i_size; maxpos = inode->i_size;
if (pos + count > inode->i_size) { if (maxpos < pos + count) {
maxpos = pos + count; maxpos = pos + count;
if (maxpos > SHMEM_MAX_BYTES)
maxpos = SHMEM_MAX_BYTES;
if (!vm_enough_memory(VM_ACCT(maxpos) - VM_ACCT(inode->i_size))) { if (!vm_enough_memory(VM_ACCT(maxpos) - VM_ACCT(inode->i_size))) {
err = -ENOMEM; err = -ENOMEM;
goto out_nc;
}
}
/*
* Check whether we've reached the file size limit.
*/
err = -EFBIG;
if (limit != RLIM_INFINITY) {
if (pos >= limit) {
send_sig(SIGXFSZ, current, 0);
goto out; goto out;
} }
if (pos > 0xFFFFFFFFULL || count > limit - (u32)pos) {
/* send_sig(SIGXFSZ, current, 0); */
count = limit - (u32)pos;
}
} }
/*
* LFS rule
*/
if (pos + count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) {
if (pos >= MAX_NON_LFS) {
send_sig(SIGXFSZ, current, 0);
goto out;
}
if (count > MAX_NON_LFS - (u32)pos) {
/* send_sig(SIGXFSZ, current, 0); */
count = MAX_NON_LFS - (u32)pos;
}
}
/*
* Are we about to exceed the fs block limit ?
*
* If we have written data it becomes a short write
* If we have exceeded without writing data we send
* a signal and give them an EFBIG.
*
* Linus frestrict idea will clean these up nicely..
*/
if (pos >= SHMEM_MAX_BYTES) {
if (count || pos > SHMEM_MAX_BYTES) {
send_sig(SIGXFSZ, current, 0);
err = -EFBIG;
goto out;
}
/* zero-length writes at ->s_maxbytes are OK */
}
if (pos + count > SHMEM_MAX_BYTES)
count = SHMEM_MAX_BYTES - pos;
status = 0;
if (count) {
remove_suid(file->f_dentry); remove_suid(file->f_dentry);
inode->i_ctime = inode->i_mtime = CURRENT_TIME; inode->i_ctime = inode->i_mtime = CURRENT_TIME;
}
while (count) { do {
struct page *page = NULL; struct page *page = NULL;
unsigned long bytes, index, offset; unsigned long bytes, index, offset;
char *kaddr; char *kaddr;
...@@ -1241,8 +1176,8 @@ shmem_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) ...@@ -1241,8 +1176,8 @@ shmem_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
* But it still may be a good idea to prefault below. * But it still may be a good idea to prefault below.
*/ */
status = shmem_getpage(inode, index, &page, SGP_WRITE); err = shmem_getpage(inode, index, &page, SGP_WRITE);
if (status) if (err)
break; break;
left = bytes; left = bytes;
...@@ -1263,7 +1198,7 @@ shmem_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) ...@@ -1263,7 +1198,7 @@ shmem_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
flush_dcache_page(page); flush_dcache_page(page);
if (left) { if (left) {
page_cache_release(page); page_cache_release(page);
status = -EFAULT; err = -EFAULT;
break; break;
} }
...@@ -1271,7 +1206,8 @@ shmem_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) ...@@ -1271,7 +1206,8 @@ shmem_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
page_cache_release(page); page_cache_release(page);
/* /*
* Balance dirty pages?? * Our dirty pages are not counted in nr_dirty,
* and we do not attempt to balance dirty pages.
*/ */
written += bytes; written += bytes;
...@@ -1280,15 +1216,16 @@ shmem_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) ...@@ -1280,15 +1216,16 @@ shmem_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
buf += bytes; buf += bytes;
if (pos > inode->i_size) if (pos > inode->i_size)
inode->i_size = pos; inode->i_size = pos;
} } while (count);
*ppos = pos; *ppos = pos;
err = written ? written : status; if (written)
out: err = written;
/* Short writes give back address space */ /* Short writes give back address space */
if (inode->i_size != maxpos) if (inode->i_size != maxpos)
vm_unacct_memory(VM_ACCT(maxpos) - VM_ACCT(inode->i_size)); vm_unacct_memory(VM_ACCT(maxpos) - VM_ACCT(inode->i_size));
out_nc: out:
up(&inode->i_sem); up(&inode->i_sem);
return err; return err;
} }
......
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