[PATCH] tmpfs 1/6 use generic_write_checks

From: Hugh Dickins (hugh@veritas.com)
Date: Tue Apr 01 2003 - 17:31:00 EST


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/



This archive was generated by hypermail 2b29 : Mon Apr 07 2003 - 22:00:15 EST