1 diff -rupN --exclude='ide*' linux-2.4.20.orig/include/linux/mm.h linux-2.4.20/include/linux/mm.h
2 --- linux-2.4.20.orig/include/linux/mm.h 2004-02-10 11:43:10.000000000 +0200
3 +++ linux-2.4.20/include/linux/mm.h 2004-03-01 13:44:45.000000000 +0200
4 @@ -468,7 +468,8 @@ extern void clear_page_tables(struct mm_
5 extern int fail_writepage(struct page *);
6 struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address, int unused);
7 struct file *shmem_file_setup(char * name, loff_t size);
8 -int shmem_getpage(struct inode * inode, unsigned long idx, struct page **ptr);
9 +struct page *shmem_getpage_locked(struct inode *inode, unsigned long idx);
10 +struct page *shmem_getpage_unlocked(struct inode *inode, unsigned long idx);
11 extern void shmem_lock(struct file * file, int lock);
12 extern int shmem_zero_setup(struct vm_area_struct *);
14 diff -rupN --exclude='ide*' linux-2.4.20.orig/include/linux/shmem_fs.h linux-2.4.20/include/linux/shmem_fs.h
15 --- linux-2.4.20.orig/include/linux/shmem_fs.h 2004-02-10 18:39:17.000000000 +0200
16 +++ linux-2.4.20/include/linux/shmem_fs.h 2004-02-23 12:40:28.000000000 +0200
19 #define SHMEM_NR_DIRECT 16
21 +#define SHMEM_MOUNT_IOPEN 0x8000 /* Allow access via iopen */
22 +#define SHMEM_MOUNT_IOPEN_NOPRIV 0x10000 /* Make iopen world-readable */
25 * A swap entry has to fit into a "unsigned long", as
26 * the entry is hidden in the "index" field of the
27 @@ -38,6 +41,9 @@ struct shmem_inode_info {
30 struct shmem_sb_info {
31 + struct dentry *iopen;
32 + unsigned long options;
33 + unsigned long root_ino;
34 unsigned long max_blocks; /* How many blocks are allowed */
35 unsigned long free_blocks; /* How many are left for allocation */
36 unsigned long max_inodes; /* How many inodes are allowed */
37 @@ -59,11 +65,9 @@ shmem_xattr_find(struct inode *inode, co
39 shmem_xattr_set(struct inode *inode, const char *name,
40 const void *value, u16 valuelen, int flags);
43 shmem_xattr_get(struct inode *inode, const char *name,
44 void *value, size_t valuelen);
47 shmem_xattr_delete(struct inode *inode, struct shmem_xattr *xattr);
49 diff -rupN --exclude='ide*' linux-2.4.20.orig/mm/shmem.c linux-2.4.20/mm/shmem.c
50 --- linux-2.4.20.orig/mm/shmem.c 2004-02-10 18:44:05.000000000 +0200
51 +++ linux-2.4.20/mm/shmem.c 2004-03-01 14:37:21.000000000 +0200
53 #define TMPFS_MAGIC 0x01021994
55 #define ENTRIES_PER_PAGE (PAGE_CACHE_SIZE/sizeof(unsigned long))
57 #define BLOCKS_PER_PAGE (PAGE_CACHE_SIZE/512)
59 -#define SHMEM_MAX_INDEX (SHMEM_NR_DIRECT + ENTRIES_PER_PAGE * (ENTRIES_PER_PAGE/2) * (ENTRIES_PER_PAGE+1))
60 +#define SHMEM_MAX_INDEX (SHMEM_NR_DIRECT + ENTRIES_PER_PAGE * \
61 + (ENTRIES_PER_PAGE/2) * (ENTRIES_PER_PAGE+1))
63 #define SHMEM_MAX_BYTES ((unsigned long long)SHMEM_MAX_INDEX << PAGE_CACHE_SHIFT)
64 #define VM_ACCT(size) (((size) + PAGE_CACHE_SIZE - 1) >> PAGE_SHIFT)
66 /* Pretend that each entry is of this size in directory's i_size */
67 -#define BOGO_DIRENT_SIZE 20
69 +#define BOGO_DIRENT_SIZE (20)
70 #define SHMEM_SB(sb) (&sb->u.shmem_sb)
72 +#define SHMEM_IOPEN_INO 2
73 +#define SHMEM_IOPEN_NAME_LEN 32
75 +#define ASSERT(cond) \
78 + printk (KERN_EMERG \
79 + "Assertion failure in %s() at %s:%d: \"%s\"\n", \
80 + __FUNCTION__, __FILE__, __LINE__, # cond); \
85 static struct super_operations shmem_ops;
86 +static struct vm_operations_struct shmem_vm_ops;
87 static struct address_space_operations shmem_aops;
88 static struct file_operations shmem_file_operations;
89 static struct inode_operations shmem_inode_operations;
90 static struct inode_operations shmem_dir_inode_operations;
91 -static struct vm_operations_struct shmem_vm_ops;
93 LIST_HEAD (shmem_inodes);
94 static spinlock_t shmem_ilock = SPIN_LOCK_UNLOCKED;
95 atomic_t shmem_nrpages = ATOMIC_INIT(0); /* Not used right now */
97 -static struct page *shmem_getpage_locked(struct shmem_inode_info *, struct inode *, unsigned long);
98 +struct page *shmem_getpage_locked(struct inode *inode, unsigned long idx);
99 +struct page *shmem_getpage_unlocked(struct inode *inode, unsigned long idx);
102 static struct inode_operations shmem_symlink_inode_operations;
103 @@ -327,7 +343,7 @@ shmem_getxattr(struct dentry *dentry, co
104 * inode attributes list.*/
106 shmem_setxattr(struct dentry *dentry, const char *name,
107 - void *value, size_t valuelen, int flags)
108 + const void *value, size_t valuelen, int flags)
111 struct inode *inode = dentry->d_inode;
112 @@ -404,8 +420,8 @@ shmem_listxattr(struct dentry *dentry, c
113 * @inode: inode to recalc
114 * @swap: additional swap pages freed externally
116 - * We have to calculate the free blocks since the mm can drop pages
118 + * We have to calculate the free blocks since the mm can drop pages behind our
121 * But we know that normally
122 * inodes->i_blocks/BLOCKS_PER_PAGE ==
123 @@ -441,24 +457,23 @@ static void shmem_recalc_inode(struct in
124 * @page: optional page to add to the structure. Has to be preset to
127 - * If there is no space allocated yet it will return -ENOMEM when
128 - * page == 0 else it will use the page for the needed block.
129 + * If there is no space allocated yet it will return -ENOMEM when page == 0 else
130 + * it will use the page for the needed block.
132 * returns -EFBIG if the index is too big.
135 * The swap vector is organized the following way:
137 - * There are SHMEM_NR_DIRECT entries directly stored in the
138 - * shmem_inode_info structure. So small files do not need an addional
141 - * For pages with index > SHMEM_NR_DIRECT there is the pointer
142 - * i_indirect which points to a page which holds in the first half
143 - * doubly indirect blocks, in the second half triple indirect blocks:
144 + * There are SHMEM_NR_DIRECT entries directly stored in the shmem_inode_info
145 + * structure. So small files do not need an addional allocation.
147 + * For pages with index > SHMEM_NR_DIRECT there is the pointer i_indirect which
148 + * points to a page which holds in the first half doubly indirect blocks, in the
149 + * second half triple indirect blocks:
151 - * For an artificial ENTRIES_PER_PAGE = 4 this would lead to the
152 - * following layout (for SHMEM_NR_DIRECT == 16):
153 + * For an artificial ENTRIES_PER_PAGE = 4 this would lead to the following
154 + * layout (for SHMEM_NR_DIRECT == 16):
156 * i_indirect -> dir --> 16-19
158 @@ -473,7 +488,9 @@ static void shmem_recalc_inode(struct in
162 -static swp_entry_t * shmem_swp_entry (struct shmem_inode_info *info, unsigned long index, unsigned long page)
163 +static swp_entry_t *
164 +shmem_swp_entry (struct shmem_inode_info *info, unsigned long index,
165 + unsigned long page)
167 unsigned long offset;
169 @@ -520,7 +537,8 @@ static swp_entry_t * shmem_swp_entry (st
170 * @info: info structure for the inode
171 * @index: index of the page to find
173 -static inline swp_entry_t * shmem_alloc_entry (struct shmem_inode_info *info, unsigned long index)
174 +static inline swp_entry_t *
175 +shmem_alloc_entry(struct shmem_inode_info *info, unsigned long index)
177 unsigned long page = 0;
179 @@ -545,7 +563,8 @@ static inline swp_entry_t * shmem_alloc_
180 * @dir: pointer to the directory
181 * @count: number of entries to scan
183 -static int shmem_free_swp(swp_entry_t *dir, unsigned int count)
185 +shmem_free_swp(swp_entry_t *dir, unsigned int count)
187 swp_entry_t *ptr, entry;
189 @@ -573,7 +592,9 @@ static int shmem_free_swp(swp_entry_t *d
192 static inline unsigned long
193 -shmem_truncate_direct(swp_entry_t *** dir, unsigned long start, unsigned long len) {
194 +shmem_truncate_direct(swp_entry_t ***dir, unsigned long start,
197 swp_entry_t **last, **ptr;
198 unsigned long off, freed = 0;
200 @@ -639,7 +660,8 @@ shmem_truncate_indirect(struct shmem_ino
203 baseidx = max & ~(ENTRIES_PER_PAGE*ENTRIES_PER_PAGE-1);
204 - base = (swp_entry_t ***) info->i_indirect + ENTRIES_PER_PAGE/2 + baseidx/ENTRIES_PER_PAGE/ENTRIES_PER_PAGE ;
205 + base = (swp_entry_t ***) info->i_indirect + ENTRIES_PER_PAGE/2 +
206 + baseidx/ENTRIES_PER_PAGE/ENTRIES_PER_PAGE ;
207 len = max - baseidx + 1;
208 baseidx += ENTRIES_PER_PAGE*ENTRIES_PER_PAGE/2+SHMEM_NR_DIRECT;
210 @@ -654,7 +676,8 @@ shmem_truncate_indirect(struct shmem_ino
211 return shmem_truncate_direct(base, start, len);
214 -static void shmem_truncate (struct inode * inode)
216 +shmem_truncate(struct inode *inode)
219 unsigned long partial;
220 @@ -668,16 +691,16 @@ static void shmem_truncate (struct inode
221 partial = inode->i_size & ~PAGE_CACHE_MASK;
224 - swp_entry_t *entry = shmem_swp_entry(info, index-1, 0);
227 - * This check is racy: it's faintly possible that page
228 - * was assigned to swap during truncate_inode_pages,
229 - * and now assigned to file; but better than nothing.
230 + swp_entry_t *entry = shmem_swp_entry(info, index - 1, 0);
232 + /* This check is racy: it's faintly possible that page was
233 + * assigned to swap during truncate_inode_pages, and now
234 + * assigned to file; but better than nothing.
236 if (!IS_ERR(entry) && entry->val) {
237 spin_unlock(&info->lock);
238 - page = shmem_getpage_locked(info, inode, index-1);
239 + page = shmem_getpage_locked(inode, index - 1);
241 memclear_highpage_flush(page, partial,
242 PAGE_CACHE_SIZE - partial);
243 @@ -697,8 +720,166 @@ static void shmem_truncate (struct inode
247 -static void shmem_delete_inode(struct inode * inode)
248 +static struct inode *
249 +shmem_find_inode(struct super_block *sb, long int ino)
251 + struct list_head *p;
252 + struct inode *inode = NULL;
253 + struct shmem_inode_info *info;
255 + spin_lock (&shmem_ilock);
256 + list_for_each(p, &shmem_inodes) {
257 + info = list_entry(p, struct shmem_inode_info, list);
259 + if (info->inode->i_ino == ino &&
260 + info->inode->i_sb == sb)
262 + inode = info->inode;
267 + spin_unlock (&shmem_ilock);
275 +#define switch_fields(x,y) do { \
276 + __typeof__ (x) __tmp = x; \
277 + x = y; y = __tmp; } while (0)
280 +switch_names(struct dentry *dentry, struct dentry *target)
282 + const unsigned char *old_name, *new_name;
284 + memcpy(dentry->d_iname, target->d_iname,
287 + old_name = target->d_name.name;
288 + new_name = dentry->d_name.name;
290 + if (old_name == target->d_iname)
291 + old_name = dentry->d_iname;
293 + if (new_name == dentry->d_iname)
294 + new_name = target->d_iname;
296 + target->d_name.name = new_name;
297 + dentry->d_name.name = old_name;
300 +static struct dentry *
301 +shmem_iopen_lookup(struct inode *dir,
302 + struct dentry *dentry)
304 + struct inode *inode;
306 + struct list_head *lp;
307 + struct dentry *alternate;
308 + char buf[SHMEM_IOPEN_NAME_LEN];
309 + struct shmem_sb_info *sbinfo = SHMEM_SB(dir->i_sb);
311 + if (dentry->d_name.len >= SHMEM_IOPEN_NAME_LEN)
312 + return ERR_PTR(-ENAMETOOLONG);
314 + memcpy(buf, dentry->d_name.name, dentry->d_name.len);
315 + buf[dentry->d_name.len] = 0;
317 + if (strcmp(buf, ".") == 0)
319 + else if (strcmp(buf, "..") == 0)
320 + ino = sbinfo->root_ino;
322 + ino = simple_strtoul(buf, 0, 0);
324 + if (ino < sbinfo->root_ino)
325 + return ERR_PTR(-ENOENT);
327 + if (!(inode = shmem_find_inode(dir->i_sb, ino)))
328 + return ERR_PTR(-ENOENT);
330 + ASSERT(list_empty(&dentry->d_alias));
331 + ASSERT(list_empty(&dentry->d_hash));
333 + /* preferrably return a connected dentry */
334 + spin_lock(&dcache_lock);
335 + list_for_each(lp, &inode->i_dentry) {
336 + alternate = list_entry(lp, struct dentry, d_alias);
337 + ASSERT(!(alternate->d_flags & DCACHE_NFSD_DISCONNECTED));
340 + if (!list_empty(&inode->i_dentry)) {
341 + alternate = list_entry(inode->i_dentry.next,
342 + struct dentry, d_alias);
343 + dget_locked(alternate);
344 + alternate->d_vfs_flags |= DCACHE_REFERENCED;
346 + spin_unlock(&dcache_lock);
349 + dentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
351 + /* d_add(), but don't drop dcache_lock before adding dentry to inode */
352 + list_add(&dentry->d_alias, &inode->i_dentry);
353 + dentry->d_inode = inode;
355 + __d_rehash(dentry, 0);
356 + spin_unlock(&dcache_lock);
362 +shmem_iopen_unalias(struct dentry *dentry, struct inode *inode)
364 + struct dentry *tmp, *goal = NULL;
365 + struct list_head *lp;
367 + list_for_each(lp, &inode->i_dentry) {
368 + tmp = list_entry(lp, struct dentry, d_alias);
369 + if (tmp->d_flags & DCACHE_NFSD_DISCONNECTED) {
370 + ASSERT(tmp->d_alias.next == &inode->i_dentry);
371 + ASSERT(tmp->d_alias.prev == &inode->i_dentry);
381 + goal->d_flags &= ~DCACHE_NFSD_DISCONNECTED;
382 + list_del_init(&goal->d_hash);
384 + list_del(&goal->d_child);
385 + list_del(&dentry->d_child);
387 + switch_names(goal, dentry);
388 + switch_fields(goal->d_parent, dentry->d_parent);
389 + switch_fields(goal->d_name.len, dentry->d_name.len);
390 + switch_fields(goal->d_name.hash, dentry->d_name.hash);
392 + list_add(&goal->d_child, &goal->d_parent->d_subdirs);
393 + list_add(&dentry->d_child, &dentry->d_parent->d_subdirs);
394 + __d_rehash(goal, 0);
399 +static struct inode_operations iopen_inode_operations = {
400 + lookup: shmem_iopen_lookup,
404 +shmem_delete_inode(struct inode *inode)
406 + struct dentry *dentry;
408 #ifdef CONFIG_TMPFS_XATTR
409 struct list_head *tmp, *p;
410 struct shmem_xattr *xattr;
411 @@ -706,16 +887,30 @@ static void shmem_delete_inode(struct in
413 struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
415 - if (inode->i_op->truncate == shmem_truncate) {
416 + if (inode->i_ino != SHMEM_IOPEN_INO) {
417 + /* eliminating iopen alias */
418 + spin_lock(&dcache_lock);
419 + if (!list_empty(&inode->i_dentry)) {
420 + dentry = list_entry(inode->i_dentry.next,
421 + struct dentry, d_alias);
422 + shmem_iopen_unalias(dentry, inode);
424 + spin_unlock(&dcache_lock);
426 spin_lock (&shmem_ilock);
427 list_del (&SHMEM_I(inode)->list);
428 spin_unlock (&shmem_ilock);
430 - shmem_truncate (inode);
432 + if (inode->i_op->truncate == shmem_truncate) {
434 + shmem_truncate (inode);
437 + spin_lock (&sbinfo->stat_lock);
438 + sbinfo->free_inodes++;
439 + spin_unlock (&sbinfo->stat_lock);
441 - spin_lock (&sbinfo->stat_lock);
442 - sbinfo->free_inodes++;
443 - spin_unlock (&sbinfo->stat_lock);
445 #ifdef CONFIG_TMPFS_XATTR
446 list_for_each_safe(p, tmp, &info->xattrs) {
447 xattr = list_entry(p, struct shmem_xattr, list);
448 @@ -725,7 +920,8 @@ static void shmem_delete_inode(struct in
452 -static inline int shmem_find_swp(swp_entry_t entry, swp_entry_t *ptr, swp_entry_t *eptr)
454 +shmem_find_swp(swp_entry_t entry, swp_entry_t *ptr, swp_entry_t *eptr)
458 @@ -736,7 +932,9 @@ static inline int shmem_find_swp(swp_ent
462 -static int shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry, struct page *page)
464 +shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry,
469 @@ -875,9 +1073,11 @@ getswap:
470 * still need to guard against racing with shm_writepage(), which might
471 * be trying to move the page to the swap cache as we run.
473 -static struct page * shmem_getpage_locked(struct shmem_inode_info *info, struct inode * inode, unsigned long idx)
475 +shmem_getpage_locked(struct inode *inode, unsigned long idx)
477 struct address_space * mapping = inode->i_mapping;
478 + struct shmem_inode_info *info = SHMEM_I(inode);
479 struct shmem_sb_info *sbinfo;
482 @@ -941,7 +1141,8 @@ repeat:
484 *entry = (swp_entry_t) {0};
485 delete_from_swap_cache(page);
486 - flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) | (1 << PG_referenced) | (1 << PG_arch_1));
487 + flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) |
488 + (1 << PG_referenced) | (1 << PG_arch_1));
489 page->flags = flags | (1 << PG_dirty);
490 add_to_page_cache_locked(page, mapping, idx);
492 @@ -985,46 +1186,53 @@ wait_retry:
496 -int shmem_getpage(struct inode * inode, unsigned long idx, struct page **ptr)
498 +shmem_getpage_unlocked(struct inode *inode, unsigned long idx)
501 struct shmem_inode_info *info = SHMEM_I(inode);
505 - *ptr = ERR_PTR(-EFAULT);
506 - if (inode->i_size <= (loff_t) idx * PAGE_CACHE_SIZE)
508 + page = ERR_PTR(-EFAULT);
510 + if (inode->i_size <= (loff_t)idx * PAGE_CACHE_SIZE)
513 - *ptr = shmem_getpage_locked(info, inode, idx);
515 + page = shmem_getpage_locked(inode, idx);
528 - error = PTR_ERR(*ptr);
529 - *ptr = NOPAGE_SIGBUS;
530 - if (error == -ENOMEM)
535 + if (PTR_ERR(page) == -ENOMEM)
541 -struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address, int unused)
543 +shmem_nopage(struct vm_area_struct *vma,
544 + unsigned long address, int unused)
546 - struct page * page;
548 + struct page * page;
549 struct inode * inode = vma->vm_file->f_dentry->d_inode;
551 - idx = (address - vma->vm_start) >> PAGE_CACHE_SHIFT;
552 - idx += vma->vm_pgoff;
553 + idx = ((address - vma->vm_start) >> PAGE_CACHE_SHIFT) +
556 - if (shmem_getpage(inode, idx, &page))
557 + page = shmem_getpage_unlocked(inode, idx);
562 flush_page_to_ram(page);
567 void shmem_lock(struct file * file, int lock)
568 @@ -1037,7 +1245,8 @@ void shmem_lock(struct file * file, int
572 -static int shmem_mmap(struct file * file, struct vm_area_struct * vma)
574 +shmem_mmap(struct file * file, struct vm_area_struct * vma)
576 struct vm_operations_struct * ops;
577 struct inode *inode = file->f_dentry->d_inode;
578 @@ -1050,39 +1259,53 @@ static int shmem_mmap(struct file * file
582 -struct inode *shmem_get_inode(struct super_block *sb, int mode, int dev)
584 +shmem_fill_inode(struct inode *inode, int mode, int dev)
586 - struct inode * inode;
587 struct shmem_inode_info *info;
588 - struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
590 + info = SHMEM_I(inode);
591 + info->inode = inode;
592 + spin_lock_init (&info->lock);
593 + sema_init (&info->sem, 1);
595 - spin_lock (&sbinfo->stat_lock);
596 - if (!sbinfo->free_inodes) {
597 - spin_unlock (&sbinfo->stat_lock);
600 - sbinfo->free_inodes--;
601 - spin_unlock (&sbinfo->stat_lock);
602 +#ifdef CONFIG_TMPFS_XATTR
603 + INIT_LIST_HEAD(&info->xattrs);
604 + info->xtail = &info->xattrs;
607 - inode = new_inode(sb);
609 + inode->i_blocks = 0;
610 + inode->i_rdev = NODEV;
611 + inode->i_atime = CURRENT_TIME;
612 + inode->i_ctime = CURRENT_TIME;
613 + inode->i_mtime = CURRENT_TIME;
614 + inode->i_blksize = PAGE_CACHE_SIZE;
616 + /* handling speciall iopen inode. */
617 + if (inode->i_ino == SHMEM_IOPEN_INO) {
618 + struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
620 + inode->i_mode = S_IFDIR | S_IRUSR | S_IXUSR;
622 + if (sbinfo->options & SHMEM_MOUNT_IOPEN_NOPRIV)
623 + inode->i_mode |= 0777;
627 + inode->i_nlink = 1;
628 + inode->i_size = 2 * BOGO_DIRENT_SIZE;
629 + inode->i_version = 1;
630 + inode->i_generation = 0;
632 + inode->i_op = &iopen_inode_operations;
633 + inode->i_fop = &dcache_dir_ops;
634 + inode->i_mapping->a_ops = 0;
636 inode->i_mode = mode;
637 inode->i_uid = current->fsuid;
638 inode->i_gid = current->fsgid;
639 - inode->i_blksize = PAGE_CACHE_SIZE;
640 - inode->i_blocks = 0;
641 - inode->i_rdev = NODEV;
642 inode->i_mapping->a_ops = &shmem_aops;
643 - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
644 - info = SHMEM_I(inode);
645 - info->inode = inode;
646 - spin_lock_init (&info->lock);
647 - sema_init (&info->sem, 1);
649 -#ifdef CONFIG_TMPFS_XATTR
650 - INIT_LIST_HEAD(&info->xattrs);
651 - info->xtail = &info->xattrs;
653 switch (mode & S_IFMT) {
655 init_special_inode(inode, mode, dev);
656 @@ -1090,9 +1313,6 @@ struct inode *shmem_get_inode(struct sup
658 inode->i_op = &shmem_inode_operations;
659 inode->i_fop = &shmem_file_operations;
660 - spin_lock (&shmem_ilock);
661 - list_add_tail(&info->list, &shmem_inodes);
662 - spin_unlock (&shmem_ilock);
666 @@ -1104,12 +1324,59 @@ struct inode *shmem_get_inode(struct sup
671 + spin_lock (&shmem_ilock);
672 + list_add_tail(&info->list, &shmem_inodes);
673 + spin_unlock (&shmem_ilock);
678 +shmem_get_inode(struct super_block *sb,
679 + int mode, int dev, int root)
681 + struct inode *inode;
682 + struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
684 + spin_lock (&sbinfo->stat_lock);
685 + if (!sbinfo->free_inodes) {
686 + spin_unlock (&sbinfo->stat_lock);
689 + sbinfo->free_inodes--;
690 + spin_unlock (&sbinfo->stat_lock);
692 + if ((inode = new_inode(sb))) {
693 + shmem_fill_inode(inode, mode, dev);
695 + sbinfo->root_ino = inode->i_ino;
701 -static int shmem_set_size(struct shmem_sb_info *info,
702 - unsigned long max_blocks, unsigned long max_inodes)
703 +void shmem_read_inode(struct inode *inode)
705 + struct shmem_sb_info *sbinfo;
707 + if (inode->i_ino != SHMEM_IOPEN_INO)
710 + sbinfo = SHMEM_SB(inode->i_sb);
712 + spin_lock (&sbinfo->stat_lock);
713 + if (!sbinfo->free_inodes) {
714 + spin_unlock (&sbinfo->stat_lock);
717 + sbinfo->free_inodes--;
718 + spin_unlock (&sbinfo->stat_lock);
719 + shmem_fill_inode(inode, 0, 0);
723 +shmem_set_size(struct shmem_sb_info *info, unsigned long max_blocks,
724 + unsigned long max_inodes)
727 unsigned long blocks, inodes;
728 @@ -1192,7 +1459,6 @@ shmem_file_write(struct file *file,const
731 unsigned long bytes, index, offset;
735 * Try to find the page in the cache. If it isn't there,
736 @@ -1201,9 +1467,9 @@ shmem_file_write(struct file *file,const
737 offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
738 index = pos >> PAGE_CACHE_SHIFT;
739 bytes = PAGE_CACHE_SIZE - offset;
740 - if (bytes > count) {
747 * Bring in the user page that we will copy from _first_.
748 @@ -1218,7 +1484,7 @@ shmem_file_write(struct file *file,const
750 info = SHMEM_I(inode);
752 - page = shmem_getpage_locked(info, inode, index);
753 + page = shmem_getpage_locked(inode, index);
756 status = PTR_ERR(page);
757 @@ -1226,17 +1492,19 @@ shmem_file_write(struct file *file,const
760 /* We have exclusive IO access to the page.. */
761 - if (!PageLocked(page)) {
762 + if (!PageLocked(page))
766 - kaddr = kmap(page);
767 - status = copy_from_user(kaddr+offset, buf, bytes);
768 + status = copy_from_user(kmap(page) + offset,
776 flush_dcache_page(page);
781 @@ -1266,7 +1534,8 @@ fail_write:
785 -static void do_shmem_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * desc)
787 +do_shmem_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * desc)
789 struct inode *inode = filp->f_dentry->d_inode;
790 struct address_space *mapping = inode->i_mapping;
791 @@ -1292,15 +1561,18 @@ static void do_shmem_file_read(struct fi
795 - if ((desc->error = shmem_getpage(inode, index, &page)))
796 + page = shmem_getpage_unlocked(inode, index);
798 + if (IS_ERR(page)) {
799 + desc->error = PTR_ERR(page);
803 if (mapping->i_mmap_shared != NULL)
804 flush_dcache_page(page);
807 - * Ok, we have the page, and it's up-to-date, so
808 - * now we can copy it to user space...
809 + /* Ok, we have the page, and it's up-to-date, so now we can copy
810 + * it to user space...
812 * The actor routine returns how many bytes were actually used..
813 * NOTE! This may not be the same as how much of a user buffer
814 @@ -1309,6 +1581,8 @@ static void do_shmem_file_read(struct fi
815 * pointers and the remaining count).
817 nr = file_read_actor(desc, page, offset, nr);
819 + /* updating counters */
821 index += offset >> PAGE_CACHE_SHIFT;
822 offset &= ~PAGE_CACHE_MASK;
823 @@ -1320,7 +1594,8 @@ static void do_shmem_file_read(struct fi
827 -static ssize_t shmem_file_read(struct file * filp, char * buf, size_t count, loff_t *ppos)
829 +shmem_file_read(struct file * filp, char * buf, size_t count, loff_t *ppos)
833 @@ -1345,7 +1620,8 @@ static ssize_t shmem_file_read(struct fi
837 -static int shmem_statfs(struct super_block *sb, struct statfs *buf)
839 +shmem_statfs(struct super_block *sb, struct statfs *buf)
841 struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
843 @@ -1361,22 +1637,62 @@ static int shmem_statfs(struct super_blo
848 - * Lookup the data. This is trivial - if the dentry didn't already
849 - * exist, we know it is negative.
851 -static struct dentry * shmem_lookup(struct inode *dir, struct dentry *dentry)
853 +match_dentry(struct dentry *dentry, const char *name)
855 + int len = strlen(name);
857 + if (dentry->d_name.len != len)
860 + if (strncmp(dentry->d_name.name, name, len))
867 +shmem_iopen_check(struct inode *dir, struct dentry *dentry)
869 + struct inode *inode;
870 + struct shmem_sb_info *sbinfo = SHMEM_SB(dir->i_sb);
872 + if (dir->i_ino != sbinfo->root_ino ||
873 + !(sbinfo->options & SHMEM_MOUNT_IOPEN) ||
874 + !match_dentry(dentry, "__iopen__"))
879 + if (!(inode = iget(dir->i_sb, SHMEM_IOPEN_INO)))
882 + d_add(dentry, inode);
884 + spin_lock (&sbinfo->stat_lock);
885 + sbinfo->iopen = dentry;
886 + spin_unlock (&sbinfo->stat_lock);
892 +static struct dentry *
893 +shmem_lookup(struct inode *dir, struct dentry *dentry)
895 - d_add(dentry, NULL);
896 + if (!shmem_iopen_check(dir, dentry))
897 + d_add(dentry, NULL);
903 * File creation. Allocate an inode, and we're done..
905 -static int shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev)
907 +shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev)
909 - struct inode * inode = shmem_get_inode(dir->i_sb, mode, dev);
910 + struct inode *inode = shmem_get_inode(dir->i_sb, mode, dev, 0);
914 @@ -1386,20 +1702,24 @@ static int shmem_mknod(struct inode *dir
915 dget(dentry); /* Extra count - pin the dentry in core */
922 -static int shmem_mkdir(struct inode * dir, struct dentry * dentry, int mode)
924 +shmem_mkdir(struct inode * dir, struct dentry * dentry, int mode)
928 if ((error = shmem_mknod(dir, dentry, mode | S_IFDIR, 0)))
935 -static int shmem_create(struct inode *dir, struct dentry *dentry, int mode)
937 +shmem_create(struct inode *dir, struct dentry *dentry, int mode)
939 return shmem_mknod(dir, dentry, mode | S_IFREG, 0);
941 @@ -1407,7 +1727,8 @@ static int shmem_create(struct inode *di
945 -static int shmem_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry)
947 +shmem_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry)
949 struct inode *inode = old_dentry->d_inode;
951 @@ -1429,13 +1750,11 @@ static inline int shmem_positive(struct
955 - * Check that a directory is empty (this works
956 - * for regular files too, they'll just always be
957 - * considered empty..).
958 + * Check that a directory is empty (this works for regular files too, they'll
959 + * just always be considered empty..).
961 - * Note that an empty directory can still have
962 - * children, they just all have to be negative..
964 + * Note that an empty directory can still have children, they just all have to
966 static int shmem_empty(struct dentry *dentry)
968 struct list_head *list;
969 @@ -1456,18 +1775,22 @@ static int shmem_empty(struct dentry *de
973 -static int shmem_unlink(struct inode * dir, struct dentry *dentry)
975 +shmem_unlink(struct inode *dir, struct dentry *dentry)
977 struct inode *inode = dentry->d_inode;
979 dir->i_size -= BOGO_DIRENT_SIZE;
980 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
982 - dput(dentry); /* Undo the count from "create" - this does all the work */
984 + /* undo the count from "create" - this does all the work. */
989 -static int shmem_rmdir(struct inode * dir, struct dentry *dentry)
991 +shmem_rmdir(struct inode *dir, struct dentry *dentry)
993 if (!shmem_empty(dentry))
995 @@ -1477,12 +1800,13 @@ static int shmem_rmdir(struct inode * di
999 - * The VFS layer already does all the dentry stuff for rename,
1000 - * we just have to decrement the usage count for the target if
1001 - * it exists so that the VFS layer correctly free's it when it
1002 - * gets overwritten.
1003 + * The VFS layer already does all the dentry stuff for rename, we just have to
1004 + * decrement the usage count for the target if it exists so that the VFS layer
1005 + * correctly free's it when it gets overwritten.
1007 -static int shmem_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir,struct dentry *new_dentry)
1009 +shmem_rename(struct inode *old_dir, struct dentry *old_dentry,
1010 + struct inode *new_dir, struct dentry *new_dentry)
1012 struct inode *inode = old_dentry->d_inode;
1013 int they_are_dirs = S_ISDIR(inode->i_mode);
1014 @@ -1507,19 +1831,20 @@ static int shmem_rename(struct inode * o
1018 -static int shmem_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
1020 +shmem_symlink(struct inode *dir, struct dentry *dentry,
1021 + const char *symname)
1024 - struct inode *inode;
1027 - struct shmem_inode_info * info;
1028 + struct inode *inode;
1029 + struct shmem_inode_info *info;
1031 len = strlen(symname) + 1;
1032 if (len > PAGE_CACHE_SIZE)
1033 return -ENAMETOOLONG;
1035 - inode = shmem_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
1036 + inode = shmem_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0, 0);
1040 @@ -1531,7 +1856,7 @@ static int shmem_symlink(struct inode *
1041 inode->i_op = &shmem_symlink_inline_operations;
1044 - page = shmem_getpage_locked(info, inode, 0);
1045 + page = shmem_getpage_locked(inode, 0);
1049 @@ -1541,8 +1866,7 @@ static int shmem_symlink(struct inode *
1050 spin_lock (&shmem_ilock);
1051 list_add_tail(&info->list, &shmem_inodes);
1052 spin_unlock (&shmem_ilock);
1053 - kaddr = kmap(page);
1054 - memcpy(kaddr, symname, len);
1055 + memcpy(kmap(page), symname, len);
1059 @@ -1556,40 +1880,52 @@ static int shmem_symlink(struct inode *
1063 -static int shmem_readlink_inline(struct dentry *dentry, char *buffer, int buflen)
1065 +shmem_readlink_inline(struct dentry *dentry, char *buffer, int buflen)
1067 - return vfs_readlink(dentry,buffer,buflen, (const char *)SHMEM_I(dentry->d_inode));
1068 + return vfs_readlink(dentry,buffer, buflen,
1069 + (const char *)SHMEM_I(dentry->d_inode));
1072 -static int shmem_follow_link_inline(struct dentry *dentry, struct nameidata *nd)
1074 +shmem_follow_link_inline(struct dentry *dentry, struct nameidata *nd)
1076 return vfs_follow_link(nd, (const char *)SHMEM_I(dentry->d_inode));
1079 -static int shmem_readlink(struct dentry *dentry, char *buffer, int buflen)
1081 +shmem_readlink(struct dentry *dentry, char *buffer, int buflen)
1083 - struct page * page;
1084 - int res = shmem_getpage(dentry->d_inode, 0, &page);
1086 + struct page *page;
1088 + page = shmem_getpage_unlocked(dentry->d_inode, 0);
1093 + return PTR_ERR(page);
1095 res = vfs_readlink(dentry,buffer,buflen, kmap(page));
1097 page_cache_release(page);
1102 -static int shmem_follow_link(struct dentry *dentry, struct nameidata *nd)
1104 +shmem_follow_link(struct dentry *dentry, struct nameidata *nd)
1107 - int res = shmem_getpage(dentry->d_inode, 0, &page);
1112 + page = shmem_getpage_unlocked(dentry->d_inode, 0);
1115 + return PTR_ERR(page);
1117 res = vfs_follow_link(nd, kmap(page));
1119 page_cache_release(page);
1124 @@ -1610,7 +1946,10 @@ static struct inode_operations shmem_sym
1128 -static int shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid, unsigned long * blocks, unsigned long *inodes)
1130 +shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid,
1131 + unsigned long *blocks, unsigned long *inodes,
1132 + unsigned long *opts)
1134 char *this_char, *value, *rest;
1136 @@ -1620,11 +1959,6 @@ static int shmem_parse_options(char *opt
1137 for ( ; this_char; this_char = strtok(NULL,",")) {
1138 if ((value = strchr(this_char,'=')) != NULL) {
1142 - "tmpfs: No value for mount option '%s'\n",
1147 if (!strcmp(this_char,"size")) {
1148 @@ -1659,6 +1993,17 @@ static int shmem_parse_options(char *opt
1149 *gid = simple_strtoul(value,&rest,0);
1152 + } else if (!strcmp(this_char, "iopen")) {
1153 + *opts |= SHMEM_MOUNT_IOPEN;
1154 + *opts &= ~SHMEM_MOUNT_IOPEN_NOPRIV;
1156 + else if (!strcmp(this_char, "noiopen")) {
1157 + *opts &= ~SHMEM_MOUNT_IOPEN;
1158 + *opts &= ~SHMEM_MOUNT_IOPEN_NOPRIV;
1160 + else if (!strcmp (this_char, "iopen_nopriv")) {
1161 + *opts |= SHMEM_MOUNT_IOPEN;
1162 + *opts |= SHMEM_MOUNT_IOPEN_NOPRIV;
1164 printk(KERN_ERR "tmpfs: Bad mount option %s\n",
1166 @@ -1674,14 +2019,19 @@ bad_val:
1170 -static int shmem_remount_fs (struct super_block *sb, int *flags, char *data)
1172 +shmem_remount_fs(struct super_block *sb, int *flags, char *data)
1174 struct shmem_sb_info *sbinfo = &sb->u.shmem_sb;
1175 unsigned long max_blocks = sbinfo->max_blocks;
1176 unsigned long max_inodes = sbinfo->max_inodes;
1178 - if (shmem_parse_options (data, NULL, NULL, NULL, &max_blocks, &max_inodes))
1179 + if (shmem_parse_options (data, NULL, NULL, NULL, &max_blocks,
1180 + &max_inodes, &sbinfo->options))
1185 return shmem_set_size(sbinfo, max_blocks, max_inodes);
1188 @@ -1691,7 +2041,8 @@ int shmem_sync_file(struct file * file,
1192 -static struct super_block *shmem_read_super(struct super_block * sb, void * data, int silent)
1193 +static struct super_block *
1194 +shmem_read_super(struct super_block * sb, void * data, int silent)
1196 struct inode * inode;
1197 struct dentry * root;
1198 @@ -1710,11 +2061,15 @@ static struct super_block *shmem_read_su
1199 blocks = inodes = si.totalram / 2;
1202 - if (shmem_parse_options (data, &mode, &uid, &gid, &blocks, &inodes))
1203 + if (shmem_parse_options (data, &mode, &uid, &gid, &blocks,
1204 + &inodes, &sbinfo->options))
1210 spin_lock_init (&sbinfo->stat_lock);
1211 + sbinfo->iopen = NULL;
1212 sbinfo->max_blocks = blocks;
1213 sbinfo->free_blocks = blocks;
1214 sbinfo->max_inodes = inodes;
1215 @@ -1724,7 +2079,7 @@ static struct super_block *shmem_read_su
1216 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
1217 sb->s_magic = TMPFS_MAGIC;
1218 sb->s_op = &shmem_ops;
1219 - inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
1220 + inode = shmem_get_inode(sb, S_IFDIR | mode, 0, 1);
1224 @@ -1739,7 +2094,19 @@ static struct super_block *shmem_read_su
1228 +void shmem_put_super(struct super_block *sb)
1230 + struct dentry *iopen;
1231 + struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
1233 + spin_lock(&sbinfo->stat_lock);
1234 + iopen = sbinfo->iopen;
1235 + sbinfo->iopen = NULL;
1236 + spin_unlock(&sbinfo->stat_lock);
1242 static struct address_space_operations shmem_aops = {
1243 writepage: shmem_writepage,
1244 @@ -1790,11 +2157,13 @@ static struct super_operations shmem_ops
1245 remount_fs: shmem_remount_fs,
1247 delete_inode: shmem_delete_inode,
1248 - put_inode: force_delete,
1249 + read_inode: shmem_read_inode,
1250 + put_inode: force_delete,
1251 + put_super: shmem_put_super,
1254 static struct vm_operations_struct shmem_vm_ops = {
1255 - nopage: shmem_nopage,
1256 + nopage: shmem_nopage,
1260 @@ -1885,7 +2254,7 @@ struct file *shmem_file_setup(char * nam
1264 - inode = shmem_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0);
1265 + inode = shmem_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0, 0);
1269 @@ -1921,15 +2290,17 @@ int shmem_zero_setup(struct vm_area_stru
1272 fput (vma->vm_file);
1274 vma->vm_file = file;
1275 vma->vm_ops = &shmem_vm_ops;
1279 EXPORT_SYMBOL(shmem_file_setup);
1280 -EXPORT_SYMBOL(shmem_getpage);
1281 EXPORT_SYMBOL(shmem_xattr_find);
1282 EXPORT_SYMBOL(shmem_xattr_set);
1283 EXPORT_SYMBOL(shmem_xattr_get);
1284 EXPORT_SYMBOL(shmem_xattr_delete);
1285 EXPORT_SYMBOL(shmem_xattr_remove);
1286 +EXPORT_SYMBOL(shmem_getpage_locked);
1287 +EXPORT_SYMBOL(shmem_getpage_unlocked);