tmpfs 1/5 shmem_rename fixes

tmpfs 1/5 shmem_rename fixes

Post by Hugh Dickin » Mon, 16 Sep 2002 18:40:06



shmem_rename still didn't get parent directory link count quite right,
in the case where you rename a directory in place of an empty directory
(with rename syscall: doesn't happen like that with mv command); and it
forgot to update new directory's ctime and mtime.

--- 2.4.20-pre7/mm/shmem.c      Fri Sep 13 10:28:10 2002

  */
 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_ctime = old_dir->i_mtime =
+       new_dir->i_ctime = new_dir->i_mtime =
+       inode->i_ctime = CURRENT_TIME;
        return 0;
 }

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

tmpfs 1/5 shmem_rename fixes

Post by Hugh Dickin » Mon, 16 Sep 2002 18:40:05


shmem_symlink is okay, but I prefer the 2.5/ac ordering, which leaves
instantiation until the end: and is better for layering the next patch.

--- tmpfs1/mm/shmem.c   Sat Sep 14 18:21:23 2002

 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);

                up(&info->sem);
        }
        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)

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

tmpfs 1/5 shmem_rename fixes

Post by Hugh Dickin » Mon, 16 Sep 2002 18:50:04


2.4.20-pre6 had mod by hpa, to make tmpfs directory size always 1
instead of always 0, so as not to mislead apps.  Okay, but I think
it looks better if we use a pretend directory entry size instead.

--- tmpfs2/mm/shmem.c   Sat Sep 14 18:21:23 2002

 #define ENTRIES_PER_PAGE (PAGE_CACHE_SIZE/sizeof(unsigned long))

+/* 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)


                case S_IFDIR:
                        inode->i_nlink++;
                        /* Some things misbehave if size == 0 on a directory */
-                       inode->i_size = 1;
+                       inode->i_size = 2 * BOGO_DIRENT_SIZE;
                        inode->i_op = &shmem_dir_inode_operations;
                        inode->i_fop = &dcache_dir_ops;

        int error = -ENOSPC;

        if (inode) {
+               dir->i_size += BOGO_DIRENT_SIZE;
                dir->i_ctime = dir->i_mtime = CURRENT_TIME;
                d_instantiate(dentry, inode);

        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++;

 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--;

                new_dir->i_nlink++;
        }

+       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 =

                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);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

tmpfs 1/5 shmem_rename fixes

Post by Hugh Dickin » Mon, 16 Sep 2002 18:50:06


No functional change, but reduce source divergence with a few
definitions and line movements from the 2.5 and -ac trees,
and cutting out a pointless call to shmem_truncate as in 2.5.

--- tmpfs4/mm/shmem.c   Sat Sep 14 18:21:23 2002

 #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 */

 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

  *                    +-> 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 page = 0;
        swp_entry_t * res;

-       if (index >= SHMEM_MAX_BLOCKS)
+       if (index >= SHMEM_MAX_INDEX)
                return ERR_PTR(-EFBIG);


 {
        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);
        }

        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;

        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);


                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);


        dput (dentry);
        return ERR_PTR(error);  
 }
+
 /*
  * shmem_zero_setup - setup a shared anonymous mapping
  *

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

tmpfs 1/5 shmem_rename fixes

Post by Hugh Dickin » Mon, 16 Sep 2002 18:50:05


tmpfs contributes to the AltSysRqM swapcache add and delete
statistics, but not to its find statistics: use lookup_swap_cache
wrapper to find_get_page, to contribute to those statistics too.
Elsewhere, use existing info pointer and NAME_MAX definition.

--- tmpfs3/mm/shmem.c   Sat Sep 14 18:21:23 2002

                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;

                        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;

        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;
 }

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

1. tmpfs: [ID 610955 kern.warning] WARNING: tmp_memalloc: tmpfs over memory limit

Is there some kind of memory limit setting in /etc/system or
something?  This is the error I'm getting when my /tmp gets over about
70% full.  I've just never heard of this before, could someone explain
please.  Below is my vfstab if it matters at all...

#device         device          mount           FS      fsck    mount
 mount
#to mount       to fsck         point           type    pass    at
boot options
#
#/dev/dsk/c1d0s2 /dev/rdsk/c1d0s2 /usr          ufs     1       yes  
 -
fd      -       /dev/fd fd      -       no      -
/proc   -       /proc   proc    -       no      -
/dev/dsk/c0t0d0s1       -       -       swap    -       no      -
/dev/dsk/c0t0d0s0       /dev/rdsk/c0t0d0s0      /       ufs     1    
 no      -
/dev/dsk/c0t0d0s4       /dev/rdsk/c0t0d0s4      /usr    ufs     1    
 no      -
/dev/dsk/c0t0d0s3       /dev/rdsk/c0t0d0s3      /var    ufs     1    
 no      -
/dev/md/dsk/d0          /dev/md/rdsk/d0         /export/home    ufs  
 2       yes     logging
/dev/dsk/c0t0d0s5       /dev/rdsk/c0t0d0s5      /opt    ufs     2    
 yes     -
/dev/dsk/c1t15d0s7      /dev/rdsk/c1t15d0s7     /export/spool   ufs  
 2       yes     -
/dev/dsk/c1t2d0s7       /dev/rdsk/c1t2d0s7      /export ufs     2    
 yes     -
swap    -       /tmp    tmpfs   -       yes     -

2. Legal shell for NIS

3. tmpfs fixes against 2.4.6-pre

4. System Commander

5. tmpfs fixes against 2.4.6-pre(2)

6. SCSI H/D and Cdrom installation question

7. tmpfs fixes against 2.4.6-pre

8. any luck with 2.5x86 on Toshiba 410CDT??

9. PATCH: fix ALi 32bitisms, fix ALi FIFO, fix ALi IRQ crash

10. tmpfs -- where's the M to R?

11. Strange "df -k" output for /tmpfs

12. tmpfs: a way to get your system down

13. cachefs with tmpfs as "cache"...