~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/mm/shmem.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Resizable simple shmem filesystem for Linux.
  3  *
  4  * Copyright (C) 2000 Linus Torvalds.
  5  *               2000 Transmeta Corp.
  6  *               2000 Christoph Rohland
  7  * 
  8  * This file is released under the GPL.
  9  */
 10 
 11 /*
 12  * This shared memory handling is heavily based on the ramfs. It
 13  * extends the ramfs by the ability to use swap which would makes it a
 14  * completely usable filesystem.
 15  *
 16  * But read and write are not supported (yet)
 17  *
 18  */
 19 
 20 #include <linux/module.h>
 21 #include <linux/init.h>
 22 #include <linux/devfs_fs_kernel.h>
 23 #include <linux/fs.h>
 24 #include <linux/mm.h>
 25 #include <linux/file.h>
 26 #include <linux/swap.h>
 27 #include <linux/pagemap.h>
 28 #include <linux/string.h>
 29 #include <linux/locks.h>
 30 #include <asm/smplock.h>
 31 
 32 #include <asm/uaccess.h>
 33 
 34 #define SHMEM_MAGIC     0x01021994
 35 
 36 #define ENTRIES_PER_PAGE (PAGE_SIZE/sizeof(unsigned long))
 37 #define NR_SINGLE (ENTRIES_PER_PAGE + SHMEM_NR_DIRECT)
 38 
 39 static struct super_operations shmem_ops;
 40 static struct address_space_operations shmem_aops;
 41 static struct file_operations shmem_file_operations;
 42 static struct inode_operations shmem_inode_operations;
 43 static struct file_operations shmem_dir_operations;
 44 static struct inode_operations shmem_dir_inode_operations;
 45 static struct vm_operations_struct shmem_shared_vm_ops;
 46 static struct vm_operations_struct shmem_private_vm_ops;
 47 
 48 LIST_HEAD (shmem_inodes);
 49 static spinlock_t shmem_ilock = SPIN_LOCK_UNLOCKED;
 50 
 51 static swp_entry_t * shmem_swp_entry (struct shmem_inode_info *info, unsigned long index) 
 52 {
 53         if (index < SHMEM_NR_DIRECT)
 54                 return info->i_direct+index;
 55 
 56         index -= SHMEM_NR_DIRECT;
 57         if (index >= ENTRIES_PER_PAGE*ENTRIES_PER_PAGE)
 58                 return NULL;
 59 
 60         if (!info->i_indirect) {
 61                 info->i_indirect = (swp_entry_t **) get_zeroed_page(GFP_USER);
 62                 if (!info->i_indirect)
 63                         return NULL;
 64         }
 65         if(!(info->i_indirect[index/ENTRIES_PER_PAGE])) {
 66                 info->i_indirect[index/ENTRIES_PER_PAGE] = (swp_entry_t *) get_zeroed_page(GFP_USER);
 67                 if (!info->i_indirect[index/ENTRIES_PER_PAGE])
 68                         return NULL;
 69         }
 70         
 71         return info->i_indirect[index/ENTRIES_PER_PAGE]+index%ENTRIES_PER_PAGE;
 72 }
 73 
 74 static int shmem_free_swp(swp_entry_t *dir, unsigned int count)
 75 {
 76         swp_entry_t *ptr, entry;
 77         struct page * page;
 78         int freed = 0;
 79 
 80         for (ptr = dir; ptr < dir + count; ptr++) {
 81                 if (!ptr->val)
 82                         continue;
 83                 entry = *ptr;
 84                 swap_free (entry);
 85                 *ptr = (swp_entry_t){0};
 86                 freed++;
 87                 if (!(page = lookup_swap_cache(entry)))
 88                         continue;
 89                 delete_from_swap_cache(page);
 90                 page_cache_release(page);
 91         }
 92         return freed;
 93 }
 94 
 95 /*
 96  * shmem_truncate_part - free a bunch of swap entries
 97  *
 98  * @dir:        pointer to swp_entries 
 99  * @size:       number of entries in dir
100  * @start:      offset to start from
101  * @inode:      inode for statistics
102  * @freed:      counter for freed pages
103  *
104  * It frees the swap entries from dir+start til dir+size
105  *
106  * returns 0 if it truncated something, else (offset-size)
107  */
108 
109 static unsigned long 
110 shmem_truncate_part (swp_entry_t * dir, unsigned long size, 
111                      unsigned long start, struct inode * inode, unsigned long *freed) {
112         if (start > size)
113                 return start - size;
114         if (dir)
115                 *freed += shmem_free_swp (dir+start, size-start);
116         
117         return 0;
118 }
119 
120 static void shmem_truncate (struct inode * inode)
121 {
122         int clear_base;
123         unsigned long start;
124         unsigned long mmfreed, freed = 0;
125         swp_entry_t **base, **ptr;
126         struct shmem_inode_info * info = &inode->u.shmem_i;
127 
128         spin_lock (&info->lock);
129         start = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
130 
131         start = shmem_truncate_part (info->i_direct, SHMEM_NR_DIRECT, start, inode, &freed);
132 
133         if (!(base = info->i_indirect))
134                 goto out;;
135 
136         clear_base = 1;
137         for (ptr = base; ptr < base + ENTRIES_PER_PAGE; ptr++) {
138                 if (!start) {
139                         if (!*ptr)
140                                 continue;
141                         freed += shmem_free_swp (*ptr, ENTRIES_PER_PAGE);
142                         free_page ((unsigned long) *ptr);
143                         *ptr = 0;
144                         continue;
145                 }
146                 clear_base = 0;
147                 start = shmem_truncate_part (*ptr, ENTRIES_PER_PAGE, start, inode, &freed);
148         }
149 
150         if (!clear_base) 
151                 goto out;
152 
153         free_page ((unsigned long)base);
154         info->i_indirect = 0;
155 
156 out:
157 
158         /*
159          * We have to calculate the free blocks since we do not know
160          * how many pages the mm discarded
161          *
162          * But we know that normally
163          * inodes->i_blocks == inode->i_mapping->nrpages + info->swapped
164          *
165          * So the mm freed 
166          * inodes->i_blocks - (inode->i_mapping->nrpages + info->swapped)
167          */
168 
169         mmfreed = inode->i_blocks - (inode->i_mapping->nrpages + info->swapped);
170         info->swapped -= freed;
171         inode->i_blocks -= freed + mmfreed;
172         spin_unlock (&info->lock);
173 
174         spin_lock (&inode->i_sb->u.shmem_sb.stat_lock);
175         inode->i_sb->u.shmem_sb.free_blocks += freed + mmfreed;
176         spin_unlock (&inode->i_sb->u.shmem_sb.stat_lock);
177 }
178 
179 static void shmem_delete_inode(struct inode * inode)
180 {
181         struct shmem_sb_info *info = &inode->i_sb->u.shmem_sb;
182 
183         spin_lock (&shmem_ilock);
184         list_del (&inode->u.shmem_i.list);
185         spin_unlock (&shmem_ilock);
186         inode->i_size = 0;
187         shmem_truncate (inode);
188         spin_lock (&info->stat_lock);
189         info->free_inodes++;
190         spin_unlock (&info->stat_lock);
191         clear_inode(inode);
192 }
193 
194 /*
195  * Move the page from the page cache to the swap cache
196  */
197 static int shmem_writepage(struct page * page)
198 {
199         int error;
200         struct shmem_inode_info *info;
201         swp_entry_t *entry, swap;
202 
203         info = &page->mapping->host->u.shmem_i;
204         if (info->locked)
205                 return 1;
206         swap = __get_swap_page(2);
207         if (!swap.val)
208                 return 1;
209 
210         spin_lock(&info->lock);
211         entry = shmem_swp_entry (info, page->index);
212         if (!entry)     /* this had been allocted on page allocation */
213                 BUG();
214         error = -EAGAIN;
215         if (entry->val) {
216                 __swap_free(swap, 2);
217                 goto out;
218         }
219 
220         *entry = swap;
221         error = 0;
222         /* Remove the from the page cache */
223         lru_cache_del(page);
224         remove_inode_page(page);
225 
226         /* Add it to the swap cache */
227         add_to_swap_cache(page, swap);
228         page_cache_release(page);
229         set_page_dirty(page);
230         info->swapped++;
231 out:
232         spin_unlock(&info->lock);
233         UnlockPage(page);
234         return error;
235 }
236 
237 /*
238  * shmem_nopage - either get the page from swap or allocate a new one
239  *
240  * If we allocate a new one we do not mark it dirty. That's up to the
241  * vm. If we swap it in we mark it dirty since we also free the swap
242  * entry since a page cannot live in both the swap and page cache
243  */
244 struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address, int no_share)
245 {
246         unsigned long size;
247         struct page * page;
248         unsigned int idx;
249         swp_entry_t *entry;
250         struct inode * inode = vma->vm_file->f_dentry->d_inode;
251         struct address_space * mapping = inode->i_mapping;
252         struct shmem_inode_info *info;
253 
254         idx = (address - vma->vm_start) >> PAGE_SHIFT;
255         idx += vma->vm_pgoff;
256 
257         down (&inode->i_sem);
258         size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
259         page = NOPAGE_SIGBUS;
260         if ((idx >= size) && (vma->vm_mm == current->mm))
261                 goto out;
262 
263         /* retry, we may have slept */
264         page = __find_lock_page(mapping, idx, page_hash (mapping, idx));
265         if (page)
266                 goto cached_page;
267 
268         info = &inode->u.shmem_i;
269         entry = shmem_swp_entry (info, idx);
270         if (!entry)
271                 goto oom;
272         if (entry->val) {
273                 unsigned long flags;
274 
275                 /* Look it up and read it in.. */
276                 page = lookup_swap_cache(*entry);
277                 if (!page) {
278                         lock_kernel();
279                         swapin_readahead(*entry);
280                         page = read_swap_cache(*entry);
281                         unlock_kernel();
282                         if (!page) 
283                                 goto oom;
284                 }
285 
286                 /* We have to this with page locked to prevent races */
287                 spin_lock (&info->lock);
288                 swap_free(*entry);
289                 lock_page(page);
290                 delete_from_swap_cache_nolock(page);
291                 *entry = (swp_entry_t) {0};
292                 flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) | (1 << PG_referenced) | (1 << PG_arch_1));
293                 page->flags = flags | (1 << PG_dirty);
294                 add_to_page_cache_locked(page, mapping, idx);
295                 info->swapped--;
296                 spin_unlock (&info->lock);
297         } else {
298                 spin_lock (&inode->i_sb->u.shmem_sb.stat_lock);
299                 if (inode->i_sb->u.shmem_sb.free_blocks == 0)
300                         goto no_space;
301                 inode->i_sb->u.shmem_sb.free_blocks--;
302                 spin_unlock (&inode->i_sb->u.shmem_sb.stat_lock);
303                 /* Ok, get a new page */
304                 page = page_cache_alloc();
305                 if (!page)
306                         goto oom;
307                 clear_user_highpage(page, address);
308                 inode->i_blocks++;
309                 add_to_page_cache (page, mapping, idx);
310         }
311         /* We have the page */
312         SetPageUptodate (page);
313 
314 cached_page:
315         UnlockPage (page);
316         up(&inode->i_sem);
317 
318         if (no_share) {
319                 struct page *new_page = page_cache_alloc();
320 
321                 if (new_page) {
322                         copy_user_highpage(new_page, page, address);
323                         flush_page_to_ram(new_page);
324                 } else
325                         new_page = NOPAGE_OOM;
326                 page_cache_release(page);
327                 return new_page;
328         }
329 
330         flush_page_to_ram (page);
331         return(page);
332 no_space:
333         spin_unlock (&inode->i_sb->u.shmem_sb.stat_lock);
334 oom:
335         page = NOPAGE_OOM;
336 out:
337         up(&inode->i_sem);
338         return page;
339 }
340 
341 struct inode *shmem_get_inode(struct super_block *sb, int mode, int dev)
342 {
343         struct inode * inode;
344 
345         spin_lock (&sb->u.shmem_sb.stat_lock);
346         if (!sb->u.shmem_sb.free_inodes) {
347                 spin_unlock (&sb->u.shmem_sb.stat_lock);
348                 return NULL;
349         }
350         sb->u.shmem_sb.free_inodes--;
351         spin_unlock (&sb->u.shmem_sb.stat_lock);
352 
353         inode = new_inode(sb);
354         if (inode) {
355                 inode->i_mode = mode;
356                 inode->i_uid = current->fsuid;
357                 inode->i_gid = current->fsgid;
358                 inode->i_blksize = PAGE_CACHE_SIZE;
359                 inode->i_blocks = 0;
360                 inode->i_rdev = to_kdev_t(dev);
361                 inode->i_mapping->a_ops = &shmem_aops;
362                 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
363                 spin_lock_init (&inode->u.shmem_i.lock);
364                 switch (mode & S_IFMT) {
365                 default:
366                         init_special_inode(inode, mode, dev);
367                         break;
368                 case S_IFREG:
369                         inode->i_op = &shmem_inode_operations;
370                         inode->i_fop = &shmem_file_operations;
371                         break;
372                 case S_IFDIR:
373                         inode->i_op = &shmem_dir_inode_operations;
374                         inode->i_fop = &shmem_dir_operations;
375                         break;
376                 case S_IFLNK:
377                         inode->i_op = &page_symlink_inode_operations;
378                         break;
379                 }
380                 spin_lock (&shmem_ilock);
381                 list_add (&inode->u.shmem_i.list, &shmem_inodes);
382                 spin_unlock (&shmem_ilock);
383         }
384         return inode;
385 }
386 
387 static int shmem_statfs(struct super_block *sb, struct statfs *buf)
388 {
389         buf->f_type = SHMEM_MAGIC;
390         buf->f_bsize = PAGE_CACHE_SIZE;
391         spin_lock (&sb->u.shmem_sb.stat_lock);
392         if (sb->u.shmem_sb.max_blocks != ULONG_MAX || 
393             sb->u.shmem_sb.max_inodes != ULONG_MAX) {
394                 buf->f_blocks = sb->u.shmem_sb.max_blocks;
395                 buf->f_bavail = buf->f_bfree = sb->u.shmem_sb.free_blocks;
396                 buf->f_files = sb->u.shmem_sb.max_inodes;
397                 buf->f_ffree = sb->u.shmem_sb.free_inodes;
398         }
399         spin_unlock (&sb->u.shmem_sb.stat_lock);
400         buf->f_namelen = 255;
401         return 0;
402 }
403 
404 /*
405  * Lookup the data. This is trivial - if the dentry didn't already
406  * exist, we know it is negative.
407  */
408 static struct dentry * shmem_lookup(struct inode *dir, struct dentry *dentry)
409 {
410         d_add(dentry, NULL);
411         return NULL;
412 }
413 
414 /*
415  * File creation. Allocate an inode, and we're done..
416  */
417 static int shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev)
418 {
419         struct inode * inode = shmem_get_inode(dir->i_sb, mode, dev);
420         int error = -ENOSPC;
421 
422         if (inode) {
423                 d_instantiate(dentry, inode);
424                 dget(dentry); /* Extra count - pin the dentry in core */
425                 error = 0;
426         }
427         return error;
428 }
429 
430 static int shmem_mkdir(struct inode * dir, struct dentry * dentry, int mode)
431 {
432         return shmem_mknod(dir, dentry, mode | S_IFDIR, 0);
433 }
434 
435 static int shmem_create(struct inode *dir, struct dentry *dentry, int mode)
436 {
437         return shmem_mknod(dir, dentry, mode | S_IFREG, 0);
438 }
439 
440 /*
441  * Link a file..
442  */
443 static int shmem_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry)
444 {
445         struct inode *inode = old_dentry->d_inode;
446 
447         if (S_ISDIR(inode->i_mode))
448                 return -EPERM;
449 
450         inode->i_nlink++;
451         atomic_inc(&inode->i_count);    /* New dentry reference */
452         dget(dentry);           /* Extra pinning count for the created dentry */
453         d_instantiate(dentry, inode);
454         return 0;
455 }
456 
457 static inline int shmem_positive(struct dentry *dentry)
458 {
459         return dentry->d_inode && !d_unhashed(dentry);
460 }
461 
462 /*
463  * Check that a directory is empty (this works
464  * for regular files too, they'll just always be
465  * considered empty..).
466  *
467  * Note that an empty directory can still have
468  * children, they just all have to be negative..
469  */
470 static int shmem_empty(struct dentry *dentry)
471 {
472         struct list_head *list;
473 
474         spin_lock(&dcache_lock);
475         list = dentry->d_subdirs.next;
476 
477         while (list != &dentry->d_subdirs) {
478                 struct dentry *de = list_entry(list, struct dentry, d_child);
479 
480                 if (shmem_positive(de)) {
481                         spin_unlock(&dcache_lock);
482                         return 0;
483                 }
484                 list = list->next;
485         }
486         spin_unlock(&dcache_lock);
487         return 1;
488 }
489 
490 /*
491  * This works for both directories and regular files.
492  * (non-directories will always have empty subdirs)
493  */
494 static int shmem_unlink(struct inode * dir, struct dentry *dentry)
495 {
496         int retval = -ENOTEMPTY;
497 
498         if (shmem_empty(dentry)) {
499                 struct inode *inode = dentry->d_inode;
500 
501                 inode->i_nlink--;
502                 dput(dentry);   /* Undo the count from "create" - this does all the work */
503                 retval = 0;
504         }
505         return retval;
506 }
507 
508 #define shmem_rmdir shmem_unlink
509 
510 /*
511  * The VFS layer already does all the dentry stuff for rename,
512  * we just have to decrement the usage count for the target if
513  * it exists so that the VFS layer correctly free's it when it
514  * gets overwritten.
515  */
516 static int shmem_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir,struct dentry *new_dentry)
517 {
518         int error = -ENOTEMPTY;
519 
520         if (shmem_empty(new_dentry)) {
521                 struct inode *inode = new_dentry->d_inode;
522                 if (inode) {
523                         inode->i_nlink--;
524                         dput(new_dentry);
525                 }
526                 error = 0;
527         }
528         return error;
529 }
530 
531 static int shmem_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
532 {
533         int error;
534 
535         error = shmem_mknod(dir, dentry, S_IFLNK | S_IRWXUGO, 0);
536         if (!error) {
537                 int l = strlen(symname)+1;
538                 struct inode *inode = dentry->d_inode;
539                 error = block_symlink(inode, symname, l);
540         }
541         return error;
542 }
543 
544 static int shmem_mmap(struct file * file, struct vm_area_struct * vma)
545 {
546         struct vm_operations_struct * ops;
547         struct inode *inode = file->f_dentry->d_inode;
548 
549         ops = &shmem_private_vm_ops;
550         if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE))
551                 ops = &shmem_shared_vm_ops;
552         if (!inode->i_sb || !S_ISREG(inode->i_mode))
553                 return -EACCES;
554         UPDATE_ATIME(inode);
555         vma->vm_ops = ops;
556         return 0;
557 }
558 
559 static int shmem_parse_options(char *options, int *mode, unsigned long * blocks, unsigned long *inodes)
560 {
561         char *this_char, *value;
562 
563         this_char = NULL;
564         if ( options )
565                 this_char = strtok(options,",");
566         for ( ; this_char; this_char = strtok(NULL,",")) {
567                 if ((value = strchr(this_char,'=')) != NULL)
568                         *value++ = 0;
569                 if (!strcmp(this_char,"nr_blocks")) {
570                         if (!value || !*value || !blocks)
571                                 return 1;
572                         *blocks = simple_strtoul(value,&value,0);
573                         if (*value)
574                                 return 1;
575                 } else if (!strcmp(this_char,"nr_inodes")) {
576                         if (!value || !*value || !inodes)
577                                 return 1;
578                         *inodes = simple_strtoul(value,&value,0);
579                         if (*value)
580                                 return 1;
581                 } else if (!strcmp(this_char,"mode")) {
582                         if (!value || !*value || !mode)
583                                 return 1;
584                         *mode = simple_strtoul(value,&value,8);
585                         if (*value)
586                                 return 1;
587                 }
588                 else
589                         return 1;
590         }
591 
592         return 0;
593 }
594 
595 static struct super_block *shmem_read_super(struct super_block * sb, void * data, int silent)
596 {
597         struct inode * inode;
598         struct dentry * root;
599         unsigned long blocks = ULONG_MAX;       /* unlimited */
600         unsigned long inodes = ULONG_MAX;       /* unlimited */
601         int mode   = S_IRWXUGO | S_ISVTX;
602 
603         if (shmem_parse_options (data, &mode, &blocks, &inodes)) {
604                 printk(KERN_ERR "shmem fs invalid option\n");
605                 return NULL;
606         }
607 
608         spin_lock_init (&sb->u.shmem_sb.stat_lock);
609         sb->u.shmem_sb.max_blocks = blocks;
610         sb->u.shmem_sb.free_blocks = blocks;
611         sb->u.shmem_sb.max_inodes = inodes;
612         sb->u.shmem_sb.free_inodes = inodes;
613         sb->s_blocksize = PAGE_CACHE_SIZE;
614         sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
615         sb->s_magic = SHMEM_MAGIC;
616         sb->s_op = &shmem_ops;
617         inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
618         if (!inode)
619                 return NULL;
620 
621         root = d_alloc_root(inode);
622         if (!root) {
623                 iput(inode);
624                 return NULL;
625         }
626         sb->s_root = root;
627         return sb;
628 }
629 
630 static int shmem_remount_fs (struct super_block *sb, int *flags, char *data)
631 {
632         int error;
633         unsigned long max_blocks, blocks;
634         unsigned long max_inodes, inodes;
635         struct shmem_sb_info *info = &sb->u.shmem_sb;
636 
637         if (shmem_parse_options (data, NULL, &max_blocks, &max_inodes))
638                 return -EINVAL;
639 
640         spin_lock(&info->stat_lock);
641         blocks = info->max_blocks - info->free_blocks;
642         inodes = info->max_inodes - info->free_inodes;
643         error = -EINVAL;
644         if (max_blocks < blocks)
645                 goto out;
646         if (max_inodes < inodes)
647                 goto out;
648         error = 0;
649         info->max_blocks  = max_blocks;
650         info->free_blocks = max_blocks - blocks;
651         info->max_inodes  = max_inodes;
652         info->free_inodes = max_inodes - inodes;
653 out:
654         spin_unlock(&info->stat_lock);
655         return error;
656 }
657 
658 static struct address_space_operations shmem_aops = {
659         writepage: shmem_writepage
660 };
661 
662 static struct file_operations shmem_file_operations = {
663         mmap:           shmem_mmap
664 };
665 
666 static struct inode_operations shmem_inode_operations = {
667         truncate:       shmem_truncate,
668 };
669 
670 static struct file_operations shmem_dir_operations = {
671         read:           generic_read_dir,
672         readdir:        dcache_readdir,
673 };
674 
675 static struct inode_operations shmem_dir_inode_operations = {
676         create:         shmem_create,
677         lookup:         shmem_lookup,
678         link:           shmem_link,
679         unlink:         shmem_unlink,
680         symlink:        shmem_symlink,
681         mkdir:          shmem_mkdir,
682         rmdir:          shmem_rmdir,
683         mknod:          shmem_mknod,
684         rename:         shmem_rename,
685 };
686 
687 static struct super_operations shmem_ops = {
688         statfs:         shmem_statfs,
689         remount_fs:     shmem_remount_fs,
690         delete_inode:   shmem_delete_inode,
691         put_inode:      force_delete,   
692 };
693 
694 static struct vm_operations_struct shmem_private_vm_ops = {
695         nopage: shmem_nopage,
696 };
697 
698 static struct vm_operations_struct shmem_shared_vm_ops = {
699         nopage: shmem_nopage,
700 };
701 
702 static DECLARE_FSTYPE(shmem_fs_type, "shm", shmem_read_super, FS_LITTER);
703 
704 static int __init init_shmem_fs(void)
705 {
706         int error;
707         struct vfsmount * res;
708 
709         if ((error = register_filesystem(&shmem_fs_type))) {
710                 printk (KERN_ERR "Could not register shmem fs\n");
711                 return error;
712         }
713 
714         res = kern_mount(&shmem_fs_type);
715         if (IS_ERR (res)) {
716                 printk (KERN_ERR "could not kern_mount shmem fs\n");
717                 unregister_filesystem(&shmem_fs_type);
718                 return PTR_ERR(res);
719         }
720 
721         devfs_mk_dir (NULL, "shm", NULL);
722         return 0;
723 }
724 
725 static void __exit exit_shmem_fs(void)
726 {
727         unregister_filesystem(&shmem_fs_type);
728 }
729 
730 module_init(init_shmem_fs)
731 module_exit(exit_shmem_fs)
732 
733 static int shmem_clear_swp (swp_entry_t entry, swp_entry_t *ptr, int size) {
734         swp_entry_t *test;
735 
736         for (test = ptr; test < ptr + size; test++) {
737                 if (test->val == entry.val) {
738                         swap_free (entry);
739                         *test = (swp_entry_t) {0};
740                         return test - ptr;
741                 }
742         }
743         return -1;
744 }
745 
746 static int shmem_unuse_inode (struct inode *inode, swp_entry_t entry, struct page *page)
747 {
748         swp_entry_t **base, **ptr;
749         unsigned long idx;
750         int offset;
751         struct shmem_inode_info *info = &inode->u.shmem_i;
752         
753         idx = 0;
754         spin_lock (&info->lock);
755         if ((offset = shmem_clear_swp (entry,info->i_direct, SHMEM_NR_DIRECT)) >= 0)
756                 goto found;
757 
758         idx = SHMEM_NR_DIRECT;
759         if (!(base = info->i_indirect))
760                 goto out;
761 
762         for (ptr = base; ptr < base + ENTRIES_PER_PAGE; ptr++) {
763                 if (*ptr &&
764                     (offset = shmem_clear_swp (entry, *ptr, ENTRIES_PER_PAGE)) >= 0)
765                         goto found;
766                 idx += ENTRIES_PER_PAGE;
767         }
768 out:
769         spin_unlock (&info->lock);
770         return 0;
771 found:
772         add_to_page_cache(page, inode->i_mapping, offset + idx);
773         set_page_dirty(page);
774         SetPageUptodate(page);
775         UnlockPage(page);
776         info->swapped--;
777         spin_unlock(&info->lock);
778         return 1;
779 }
780 
781 /*
782  * unuse_shmem() search for an eventually swapped out shmem page.
783  */
784 void shmem_unuse(swp_entry_t entry, struct page *page)
785 {
786         struct list_head *p;
787         struct inode * inode;
788 
789         spin_lock (&shmem_ilock);
790         list_for_each(p, &shmem_inodes) {
791                 inode = list_entry(p, struct inode, u.shmem_i.list);
792 
793                 if (shmem_unuse_inode(inode, entry, page))
794                         break;
795         }
796         spin_unlock (&shmem_ilock);
797 }
798 
799 
800 /*
801  * shmem_file_setup - get an unlinked file living in shmem fs
802  *
803  * @name: name for dentry (to be seen in /proc/<pid>/maps
804  * @size: size to be set for the file
805  *
806  */
807 struct file *shmem_file_setup(char * name, loff_t size)
808 {
809         int error;
810         struct file *file;
811         struct inode * inode;
812         struct dentry *dentry, *root;
813         struct qstr this;
814         int vm_enough_memory(long pages);
815 
816         error = -ENOMEM;
817         if (!vm_enough_memory((size) >> PAGE_SHIFT))
818                 goto out;
819 
820         this.name = name;
821         this.len = strlen(name);
822         this.hash = 0; /* will go */
823         root = shmem_fs_type.kern_mnt->mnt_root;
824         dentry = d_alloc(root, &this);
825         if (!dentry)
826                 goto out;
827 
828         error = -ENFILE;
829         file = get_empty_filp();
830         if (!file)
831                 goto put_dentry;
832 
833         error = -ENOSPC;
834         inode = shmem_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0);
835         if (!inode) 
836                 goto close_file;
837 
838         d_instantiate(dentry, inode);
839         dentry->d_inode->i_size = size;
840         file->f_vfsmnt = mntget(shmem_fs_type.kern_mnt);
841         file->f_dentry = dentry;
842         file->f_op = &shmem_file_operations;
843         file->f_mode = FMODE_WRITE | FMODE_READ;
844         inode->i_nlink = 0;     /* It is unlinked */
845         return(file);
846 
847 close_file:
848         put_filp(file);
849 put_dentry:
850         dput (dentry);
851 out:
852         return ERR_PTR(error);  
853 }
854 /*
855  * shmem_zero_setup - setup a shared anonymous mapping
856  *
857  * @vma: the vma to be mmapped is prepared by do_mmap_pgoff
858  */
859 int shmem_zero_setup(struct vm_area_struct *vma)
860 {
861         struct file *file;
862         loff_t size = vma->vm_end - vma->vm_start;
863         
864         file = shmem_file_setup("dev/zero", size);
865         if (IS_ERR(file))
866                 return PTR_ERR(file);
867 
868         if (vma->vm_file)
869                 fput (vma->vm_file);
870         vma->vm_file = file;
871         vma->vm_ops = &shmem_shared_vm_ops;
872         return 0;
873 }
874 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.