[PATCH] tmpfs 1/6 use generic_write_checks

Hugh Dickins (hugh@veritas.com)
Tue, 1 Apr 2003 23:31:00 +0100 (BST)


First of a suite of six patches to 2.5.66-mm2 tmpfs (mm/shmem.c):
Documentation/filesystems/tmpfs.txt | 25 ++---
mm/shmem.c | 162 ++++++++++++------------------------
2 files changed, 66 insertions(+), 121 deletions(-)

tmpfs 1/6 use generic_write_checks
Blessings be upon the creator of generic_write_checks in filemap.c:
shmem_file_write call it instead of duplicating those tedious checks.

--- 2.5.66-mm2/mm/shmem.c Tue Apr 1 11:25:50 2003
+++ tmpfs1/mm/shmem.c Tue Apr 1 21:34:48 2003
@@ -1126,10 +1126,8 @@
shmem_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
struct inode *inode = file->f_dentry->d_inode;
- unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
loff_t pos;
unsigned long written;
- long status;
int err;
loff_t maxpos;

@@ -1142,88 +1140,25 @@
down(&inode->i_sem);

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;

- if (file->f_flags & O_APPEND)
- pos = inode->i_size;
+ err = generic_write_checks(inode, file, &pos, &count, 0);
+ if (err || !count)
+ goto out;

maxpos = inode->i_size;
- if (pos + count > inode->i_size) {
+ if (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))) {
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;
- }
- 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);
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
- }
+ remove_suid(file->f_dentry);
+ inode->i_ctime = inode->i_mtime = CURRENT_TIME;

- while (count) {
+ do {
struct page *page = NULL;
unsigned long bytes, index, offset;
char *kaddr;
@@ -1241,8 +1176,8 @@
* But it still may be a good idea to prefault below.
*/

- status = shmem_getpage(inode, index, &page, SGP_WRITE);
- if (status)
+ err = shmem_getpage(inode, index, &page, SGP_WRITE);
+ if (err)
break;

left = bytes;
@@ -1263,7 +1198,7 @@
flush_dcache_page(page);
if (left) {
page_cache_release(page);
- status = -EFAULT;
+ err = -EFAULT;
break;
}

@@ -1271,7 +1206,8 @@
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;
@@ -1280,15 +1216,16 @@
buf += bytes;
if (pos > inode->i_size)
inode->i_size = pos;
- }
+ } while (count);

*ppos = pos;
- err = written ? written : status;
-out:
+ if (written)
+ err = written;
+
/* Short writes give back address space */
if (inode->i_size != maxpos)
vm_unacct_memory(VM_ACCT(maxpos) - VM_ACCT(inode->i_size));
-out_nc:
+out:
up(&inode->i_sem);
return err;
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/