Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

Advertisement
[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Advertisement

Kernel v2.4.20 /mm/shmem.c

Filename:/mm/shmem.c
Lines Added:56
Lines Deleted:50
Also changed in: (Previous) 2.4.20-rc4-ac1  2.4.20-rc4  2.4.20-rc3  2.4.20-rc2-ac3  2.4.20-rc2-ac2  2.4.20-rc2-ac1 
(Following) 2.4.20-ac1  2.4.20-ac2  2.4.21-pre3  2.4.21-pre3-ac1  2.4.21-pre3-ac2  2.4.21-pre3-ac3 

Location
[  2.4.20
  [  mm
     o  shmem.c

Patch

diff -urN linux-2.4.19/mm/shmem.c linux-2.4.20/mm/shmem.c
--- linux-2.4.19/mm/shmem.c   Fri Aug  2 17:39:46 2002
+++ linux-2.4.20/mm/shmem.c   Thu Nov 28 15:53:15 2002
@@ -34,6 +34,14 @@
 #define TMPFS_MAGIC   0x01021994
 
 #define ENTRIES_PER_PAGE (PAGE_CACHE_SIZE/sizeof(unsigned long))
+#define BLOCKS_PER_PAGE  (PAGE_CACHE_SIZE/512)
+
+#define SHMEM_MAX_INDEX  (SHMEM_NR_DIRECT + ENTRIES_PER_PAGE * (ENTRIES_PER_PAGE/2) * (ENTRIES_PER_PAGE+1))
+#define SHMEM_MAX_BYTES  ((unsigned long long)SHMEM_MAX_INDEX << PAGE_CACHE_SHIFT)
+#define VM_ACCT(size)    (((size) + PAGE_CACHE_SIZE - 1) >> PAGE_SHIFT)
+
+/* Pretend that each entry is of this size in directory's i_size */
+#define BOGO_DIRENT_SIZE 20
 
 #define SHMEM_SB(sb) (&sb->u.shmem_sb)
 
@@ -50,8 +58,6 @@
 
 static struct page *shmem_getpage_locked(struct shmem_inode_info *, struct inode *, unsigned long);
 
-#define BLOCKS_PER_PAGE (PAGE_CACHE_SIZE/512)
-
 /*
  * shmem_recalc_inode - recalculate the size of an inode
  *
@@ -127,9 +133,6 @@
  *                    +-> 48-51
  *                    +-> 52-55
  */
-
-#define SHMEM_MAX_BLOCKS (SHMEM_NR_DIRECT + ENTRIES_PER_PAGE * ENTRIES_PER_PAGE/2*(ENTRIES_PER_PAGE+1))
-
 static swp_entry_t * shmem_swp_entry (struct shmem_inode_info *info, unsigned long index, unsigned long page) 
 {
    unsigned long offset;
@@ -182,7 +185,7 @@
    unsigned long page = 0;
    swp_entry_t * res;
 
-   if (index >= SHMEM_MAX_BLOCKS)
+   if (index >= SHMEM_MAX_INDEX)
       return ERR_PTR(-EFBIG);
 
    if (info->next_index <= index)
@@ -358,11 +361,11 @@
 {
    struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
 
-   inode->i_size = 0;
-   if (inode->i_op->truncate == shmem_truncate){ 
+   if (inode->i_op->truncate == shmem_truncate) {
       spin_lock (&shmem_ilock);
       list_del (&SHMEM_I(inode)->list);
       spin_unlock (&shmem_ilock);
+      inode->i_size = 0;
       shmem_truncate (inode);
    }
    spin_lock (&sbinfo->stat_lock);
@@ -557,7 +560,7 @@
       unsigned long flags;
 
       /* Look it up and read it in.. */
-      page = find_get_page(&swapper_space, entry->val);
+      page = lookup_swap_cache(*entry);
       if (!page) {
          swp_entry_t swap = *entry;
          spin_unlock (&info->lock);
@@ -612,6 +615,7 @@
       if (!page)
          return ERR_PTR(-ENOMEM);
       clear_highpage(page);
+      flush_dcache_page(page);
       inode->i_blocks += BLOCKS_PER_PAGE;
       add_to_page_cache (page, mapping, idx);
    }
@@ -731,11 +735,13 @@
          inode->i_op = &shmem_inode_operations;
          inode->i_fop = &shmem_file_operations;
          spin_lock (&shmem_ilock);
-         list_add_tail(&SHMEM_I(inode)->list, &shmem_inodes);
+         list_add_tail(&info->list, &shmem_inodes);
          spin_unlock (&shmem_ilock);
          break;
       case S_IFDIR:
          inode->i_nlink++;
+         /* Some things misbehave if size == 0 on a directory */
+         inode->i_size = 2 * BOGO_DIRENT_SIZE;
          inode->i_op = &shmem_dir_inode_operations;
          inode->i_fop = &dcache_dir_ops;
          break;
@@ -999,7 +1005,7 @@
    buf->f_files = sbinfo->max_inodes;
    buf->f_ffree = sbinfo->free_inodes;
    spin_unlock (&sbinfo->stat_lock);
-   buf->f_namelen = 255;
+   buf->f_namelen = NAME_MAX;
    return 0;
 }
 
@@ -1022,6 +1028,7 @@
    int error = -ENOSPC;
 
    if (inode) {
+      dir->i_size += BOGO_DIRENT_SIZE;
       dir->i_ctime = dir->i_mtime = CURRENT_TIME;
       d_instantiate(dentry, inode);
       dget(dentry); /* Extra count - pin the dentry in core */
@@ -1055,6 +1062,7 @@
    if (S_ISDIR(inode->i_mode))
       return -EPERM;
 
+   dir->i_size += BOGO_DIRENT_SIZE;
    inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
    inode->i_nlink++;
    atomic_inc(&inode->i_count);   /* New dentry reference */
@@ -1099,6 +1107,8 @@
 static int shmem_unlink(struct inode * dir, struct dentry *dentry)
 {
    struct inode *inode = dentry->d_inode;
+
+   dir->i_size -= BOGO_DIRENT_SIZE;
    inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
    inode->i_nlink--;
    dput(dentry);   /* Undo the count from "create" - this does all the work */
@@ -1122,65 +1132,63 @@
  */
 static int shmem_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir,struct dentry *new_dentry)
 {
-   struct inode *inode;
+   struct inode *inode = old_dentry->d_inode;
+   int they_are_dirs = S_ISDIR(inode->i_mode);
 
    if (!shmem_empty(new_dentry)) 
       return -ENOTEMPTY;
 
-   inode = new_dentry->d_inode;
-   if (inode) {
-      inode->i_ctime = CURRENT_TIME;
-      inode->i_nlink--;
-      dput(new_dentry);
-   }
-   inode = old_dentry->d_inode;
-   if (S_ISDIR(inode->i_mode)) {
+   if (new_dentry->d_inode) {
+      (void) shmem_unlink(new_dir, new_dentry);
+      if (they_are_dirs)
+         old_dir->i_nlink--;
+   } else if (they_are_dirs) {
       old_dir->i_nlink--;
       new_dir->i_nlink++;
    }
 
-   inode->i_ctime = old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
+   old_dir->i_size -= BOGO_DIRENT_SIZE;
+   new_dir->i_size += BOGO_DIRENT_SIZE;
+   old_dir->i_ctime = old_dir->i_mtime =
+   new_dir->i_ctime = new_dir->i_mtime =
+   inode->i_ctime = CURRENT_TIME;
    return 0;
 }
 
 static int shmem_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
 {
-   int error;
    int len;
    struct inode *inode;
    struct page *page;
    char *kaddr;
    struct shmem_inode_info * info;
 
-   error = shmem_mknod(dir, dentry, S_IFLNK | S_IRWXUGO, 0);
-   if (error)
-      return error;
-
    len = strlen(symname) + 1;
-   inode = dentry->d_inode;
+   if (len > PAGE_CACHE_SIZE)
+      return -ENAMETOOLONG;
+
+   inode = shmem_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
+   if (!inode)
+      return -ENOSPC;
+
    info = SHMEM_I(inode);
    inode->i_size = len-1;
-   inode->i_op = &shmem_symlink_inline_operations;
-
    if (len <= sizeof(struct shmem_inode_info)) {
       /* do it inline */
       memcpy(info, symname, len);
+      inode->i_op = &shmem_symlink_inline_operations;
    } else {
-      if (len > PAGE_CACHE_SIZE) {
-         error = -ENAMETOOLONG;
-         goto rmnod;
-      }
-      inode->i_op = &shmem_symlink_inode_operations;
-      spin_lock (&shmem_ilock);
-      list_add_tail(&info->list, &shmem_inodes);
-      spin_unlock (&shmem_ilock);
       down(&info->sem);
       page = shmem_getpage_locked(info, inode, 0);
       if (IS_ERR(page)) {
          up(&info->sem);
-         error = PTR_ERR(page);
-         goto rmnod;
+         iput(inode);
+         return PTR_ERR(page);
       }
+      inode->i_op = &shmem_symlink_inode_operations;
+      spin_lock (&shmem_ilock);
+      list_add_tail(&info->list, &shmem_inodes);
+      spin_unlock (&shmem_ilock);
       kaddr = kmap(page);
       memcpy(kaddr, symname, len);
       kunmap(page);
@@ -1189,13 +1197,11 @@
       page_cache_release(page);
       up(&info->sem);
    }
+   dir->i_size += BOGO_DIRENT_SIZE;
    dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+   d_instantiate(dentry, inode);
+   dget(dentry);
    return 0;
-
-rmnod:
-   if (!shmem_unlink(dir, dentry))
-      d_delete(dentry);
-   return error;
 }
 
 static int shmem_readlink_inline(struct dentry *dentry, char *buffer, int buflen)
@@ -1355,7 +1361,7 @@
    sbinfo->free_blocks = blocks;
    sbinfo->max_inodes = inodes;
    sbinfo->free_inodes = inodes;
-   sb->s_maxbytes = (unsigned long long) SHMEM_MAX_BLOCKS << PAGE_CACHE_SHIFT;
+   sb->s_maxbytes = SHMEM_MAX_BYTES;
    sb->s_blocksize = PAGE_CACHE_SIZE;
    sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
    sb->s_magic = TMPFS_MAGIC;
@@ -1489,10 +1495,10 @@
    struct qstr this;
    int vm_enough_memory(long pages);
 
-   if (size > (unsigned long long) SHMEM_MAX_BLOCKS << PAGE_CACHE_SHIFT)
+   if (size > SHMEM_MAX_BYTES)
       return ERR_PTR(-EINVAL);
 
-   if (!vm_enough_memory((size) >> PAGE_CACHE_SHIFT))
+   if (!vm_enough_memory(VM_ACCT(size)))
       return ERR_PTR(-ENOMEM);
 
    this.name = name;
@@ -1514,13 +1520,12 @@
       goto close_file;
 
    d_instantiate(dentry, inode);
-   dentry->d_inode->i_size = size;
-   shmem_truncate(inode);
+   inode->i_size = size;
+   inode->i_nlink = 0;   /* It is unlinked */
    file->f_vfsmnt = mntget(shm_mnt);
    file->f_dentry = dentry;
    file->f_op = &shmem_file_operations;
    file->f_mode = FMODE_WRITE | FMODE_READ;
-   inode->i_nlink = 0;   /* It is unlinked */
    return(file);
 
 close_file:
@@ -1529,6 +1534,7 @@
    dput (dentry);
    return ERR_PTR(error);   
 }
+
 /*
  * shmem_zero_setup - setup a shared anonymous mapping
  *


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.