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

Linux Cross Reference
Linux/mm/shmem.c

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

~ [ 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.