patch-2.4.20 linux-2.4.20/mm/shmem.c
Next file: linux-2.4.20/mm/slab.c
Previous file: linux-2.4.20/mm/page_io.c
Back to the patch index
Back to the overall index
- Lines: 278
- Date:
Thu Nov 28 15:53:15 2002
- Orig file:
linux-2.4.19/mm/shmem.c
- Orig date:
Fri Aug 2 17:39:46 2002
diff -urN linux-2.4.19/mm/shmem.c linux-2.4.20/mm/shmem.c
@@ -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
*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)