home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / fs / msdos / inode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-26  |  14.8 KB  |  525 lines

  1. /*
  2.  *  linux/fs/msdos/inode.c
  3.  *
  4.  *  Written 1992,1993 by Werner Almesberger
  5.  */
  6.  
  7. #ifdef MODULE
  8. #include <linux/module.h>
  9. #include <linux/version.h>
  10. #else
  11. #define MOD_INC_USE_COUNT
  12. #define MOD_DEC_USE_COUNT
  13. #endif
  14.  
  15. #include <linux/msdos_fs.h>
  16. #include <linux/kernel.h>
  17. #include <linux/sched.h>
  18. #include <linux/errno.h>
  19. #include <linux/string.h>
  20. #include <linux/ctype.h>
  21. #include <linux/major.h>
  22. #include <linux/blkdev.h>
  23. #include <linux/fs.h>
  24. #include <linux/stat.h>
  25. #include <linux/locks.h>
  26.  
  27. #include "msbuffer.h"
  28.  
  29. #include <asm/segment.h>
  30.  
  31. extern int *blksize_size[];
  32.  
  33. void msdos_put_inode(struct inode *inode)
  34. {
  35.     struct inode *depend;
  36.     struct super_block *sb;
  37.  
  38.     if (inode->i_nlink) {
  39.         if (MSDOS_I(inode)->i_busy) cache_inval_inode(inode);
  40.         return;
  41.     }
  42.     inode->i_size = 0;
  43.     msdos_truncate(inode);
  44.     depend = MSDOS_I(inode)->i_depend;
  45.     sb = inode->i_sb;
  46.     clear_inode(inode);
  47.     if (depend) {
  48.         if (MSDOS_I(depend)->i_old != inode) {
  49.             printk("Invalid link (0x%p): expected 0x%p, got 0x%p\n",
  50.                 depend, inode, MSDOS_I(depend)->i_old);
  51.             fs_panic(sb,"...");
  52.             return;
  53.         }
  54.         MSDOS_I(depend)->i_old = NULL;
  55.         iput(depend);
  56.     }
  57. }
  58.  
  59.  
  60. void msdos_put_super(struct super_block *sb)
  61. {
  62.     cache_inval_dev(sb->s_dev);
  63.     set_blocksize (sb->s_dev,BLOCK_SIZE);
  64.     lock_super(sb);
  65.     sb->s_dev = 0;
  66.     unlock_super(sb);
  67.     MOD_DEC_USE_COUNT;
  68.     return;
  69. }
  70.  
  71.  
  72. static struct super_operations msdos_sops = { 
  73.     msdos_read_inode,
  74.     msdos_notify_change,
  75.     msdos_write_inode,
  76.     msdos_put_inode,
  77.     msdos_put_super,
  78.     NULL, /* added in 0.96c */
  79.     msdos_statfs,
  80.     NULL
  81. };
  82.  
  83.  
  84. static int parse_options(char *options,char *check,char *conversion,uid_t *uid,
  85.     gid_t *gid,int *umask,int *debug,int *fat,int *quiet,
  86.     int *blksize)
  87. {
  88.     char *this_char,*value;
  89.  
  90.     *check = 'n';
  91.     *conversion = 'b';
  92.     *uid = current->uid;
  93.     *gid = current->gid;
  94.     *umask = current->fs->umask;
  95.     *debug = *fat = *quiet = 0;
  96.     if (!options) return 1;
  97.     for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
  98.         if ((value = strchr(this_char,'=')) != NULL)
  99.             *value++ = 0;
  100.         if (!strcmp(this_char,"check") && value) {
  101.             if (value[0] && !value[1] && strchr("rns",*value))
  102.                 *check = *value;
  103.             else if (!strcmp(value,"relaxed")) *check = 'r';
  104.             else if (!strcmp(value,"normal")) *check = 'n';
  105.             else if (!strcmp(value,"strict")) *check = 's';
  106.             else return 0;
  107.         }
  108.         else if (!strcmp(this_char,"conv") && value) {
  109.             if (value[0] && !value[1] && strchr("bta",*value))
  110.                 *conversion = *value;
  111.             else if (!strcmp(value,"binary")) *conversion = 'b';
  112.             else if (!strcmp(value,"text")) *conversion = 't';
  113.             else if (!strcmp(value,"auto")) *conversion = 'a';
  114.             else return 0;
  115.         }
  116.         else if (!strcmp(this_char,"uid")) {
  117.             if (!value || !*value)
  118.                 return 0;
  119.             *uid = simple_strtoul(value,&value,0);
  120.             if (*value)
  121.                 return 0;
  122.         }
  123.         else if (!strcmp(this_char,"gid")) {
  124.             if (!value || !*value)
  125.                 return 0;
  126.             *gid = simple_strtoul(value,&value,0);
  127.             if (*value)
  128.                 return 0;
  129.         }
  130.         else if (!strcmp(this_char,"umask")) {
  131.             if (!value || !*value)
  132.                 return 0;
  133.             *umask = simple_strtoul(value,&value,8);
  134.             if (*value)
  135.                 return 0;
  136.         }
  137.         else if (!strcmp(this_char,"debug")) {
  138.             if (value) return 0;
  139.             *debug = 1;
  140.         }
  141.         else if (!strcmp(this_char,"fat")) {
  142.             if (!value || !*value)
  143.                 return 0;
  144.             *fat = simple_strtoul(value,&value,0);
  145.             if (*value || (*fat != 12 && *fat != 16))
  146.                 return 0;
  147.         }
  148.         else if (!strcmp(this_char,"quiet")) {
  149.             if (value) return 0;
  150.             *quiet = 1;
  151.         }
  152.         else if (!strcmp(this_char,"blocksize")) {
  153.             *blksize = simple_strtoul(value,&value,0);
  154.             if (*value)
  155.                 return 0;
  156.             if (*blksize != 512 && *blksize != 1024){
  157.                 printk ("MSDOS FS: Invalid blocksize (512 or 1024)\n");
  158.             }
  159.         }
  160.         else return 0;
  161.     }
  162.     return 1;
  163. }
  164.  
  165.  
  166. /* Read the super block of an MS-DOS FS. */
  167.  
  168. struct super_block *msdos_read_super(struct super_block *sb,void *data,
  169.                      int silent)
  170. {
  171.     struct buffer_head *bh;
  172.     struct msdos_boot_sector *b;
  173.     int data_sectors,logical_sector_size,sector_mult;
  174.     int debug,error,fat,quiet;
  175.     char check,conversion;
  176.     uid_t uid;
  177.     gid_t gid;
  178.     int umask;
  179.     int blksize = 512;
  180.  
  181.     MOD_INC_USE_COUNT;
  182.     if (hardsect_size[MAJOR(sb->s_dev)] != NULL){
  183.         blksize = hardsect_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)];
  184.         if (blksize != 512){
  185.             printk ("MSDOS: Hardware sector size is %d\n",blksize);
  186.         }
  187.     }
  188.     if (!parse_options((char *) data,&check,&conversion,&uid,&gid,&umask,
  189.         &debug,&fat,&quiet,&blksize)
  190.         || (blksize != 512 && blksize != 1024)) {
  191.         sb->s_dev = 0;
  192.         MOD_DEC_USE_COUNT;
  193.         return NULL;
  194.     }
  195.     cache_init();
  196.     lock_super(sb);
  197.     /* The first read is always 1024 bytes */
  198.     sb->s_blocksize = 1024;
  199.     set_blocksize(sb->s_dev, 1024);
  200.     bh = bread(sb->s_dev, 0, 1024);
  201.     unlock_super(sb);
  202.     if (bh == NULL || !msdos_is_uptodate(sb,bh)) {
  203.         brelse (bh);
  204.         sb->s_dev = 0;
  205.         printk("MSDOS bread failed\n");
  206.         MOD_DEC_USE_COUNT;
  207.         return NULL;
  208.     }
  209.     b = (struct msdos_boot_sector *) bh->b_data;
  210.     set_blocksize(sb->s_dev, blksize);
  211. /*
  212.  * The DOS3 partition size limit is *not* 32M as many people think.  
  213.  * Instead, it is 64K sectors (with the usual sector size being
  214.  * 512 bytes, leading to a 32M limit).
  215.  * 
  216.  * DOS 3 partition managers got around this problem by faking a 
  217.  * larger sector size, ie treating multiple physical sectors as 
  218.  * a single logical sector.
  219.  * 
  220.  * We can accommodate this scheme by adjusting our cluster size,
  221.  * fat_start, and data_start by an appropriate value.
  222.  *
  223.  * (by Drew Eckhardt)
  224.  */
  225.  
  226. #define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0)
  227.     /* don't divide by zero */
  228.  
  229.     logical_sector_size = CF_LE_W(*(unsigned short *) &b->sector_size);
  230.     sector_mult = logical_sector_size >> SECTOR_BITS;
  231.     MSDOS_SB(sb)->cluster_size = b->cluster_size*sector_mult;
  232.     MSDOS_SB(sb)->fats = b->fats;
  233.     MSDOS_SB(sb)->fat_start = CF_LE_W(b->reserved)*sector_mult;
  234.     MSDOS_SB(sb)->fat_length = CF_LE_W(b->fat_length)*sector_mult;
  235.     MSDOS_SB(sb)->dir_start = (CF_LE_W(b->reserved)+b->fats*CF_LE_W(
  236.         b->fat_length))*sector_mult;
  237.     MSDOS_SB(sb)->dir_entries = CF_LE_W(*((unsigned short *) &b->dir_entries
  238.         ));
  239.     MSDOS_SB(sb)->data_start = MSDOS_SB(sb)->dir_start+ROUND_TO_MULTIPLE((
  240.         MSDOS_SB(sb)->dir_entries << MSDOS_DIR_BITS) >> SECTOR_BITS,
  241.         sector_mult);
  242.     data_sectors = (CF_LE_W(*((unsigned short *) &b->sectors)) ?
  243.         CF_LE_W(*((unsigned short *) &b->sectors)) :
  244.         CF_LE_L(b->total_sect))*sector_mult-MSDOS_SB(sb)->data_start;
  245.     error = !b->cluster_size || !sector_mult;
  246.     if (!error) {
  247.         MSDOS_SB(sb)->clusters = b->cluster_size ? data_sectors/
  248.             b->cluster_size/sector_mult : 0;
  249.         MSDOS_SB(sb)->fat_bits = fat ? fat : MSDOS_SB(sb)->clusters >
  250.             MSDOS_FAT12 ? 16 : 12;
  251.         error = !MSDOS_SB(sb)->fats || (MSDOS_SB(sb)->dir_entries &
  252.             (MSDOS_DPS-1)) || MSDOS_SB(sb)->clusters+2 > MSDOS_SB(sb)->
  253.             fat_length*SECTOR_SIZE*8/MSDOS_SB(sb)->fat_bits ||
  254.             (logical_sector_size & (SECTOR_SIZE-1)) || !b->secs_track ||
  255.             !b->heads;
  256.     }
  257.     brelse(bh);
  258.     /*
  259.         This must be done after the brelse because the bh is a dummy
  260.         allocated by msdos_bread (see buffer.c)
  261.     */
  262.     sb->s_blocksize = blksize;    /* Using this small block size solve the */
  263.                 /* the misfit with buffer cache and cluster */
  264.                 /* because cluster (DOS) are often aligned */
  265.                 /* on odd sector */
  266.     sb->s_blocksize_bits = blksize == 512 ? 9 : 10;
  267.     if (error || debug) {
  268.         /* The MSDOS_CAN_BMAP is obsolete, but left just to remember */
  269.         printk("[MS-DOS FS Rel. 12,FAT %d,check=%c,conv=%c,"
  270.             "uid=%d,gid=%d,umask=%03o%s]\n",MSDOS_SB(sb)->fat_bits,check,
  271.             conversion,uid,gid,umask,MSDOS_CAN_BMAP(MSDOS_SB(sb)) ?
  272.             ",bmap" : "");
  273.         printk("[me=0x%x,cs=%d,#f=%d,fs=%d,fl=%d,ds=%d,de=%d,data=%d,"
  274.             "se=%d,ts=%ld,ls=%d]\n",b->media,MSDOS_SB(sb)->cluster_size,
  275.             MSDOS_SB(sb)->fats,MSDOS_SB(sb)->fat_start,MSDOS_SB(sb)->
  276.             fat_length,MSDOS_SB(sb)->dir_start,MSDOS_SB(sb)->dir_entries,
  277.             MSDOS_SB(sb)->data_start,CF_LE_W(*(unsigned short *) &b->
  278.             sectors),(unsigned long)b->total_sect,logical_sector_size);
  279.         printk ("Transaction block size = %d\n",blksize);
  280.     }
  281.     if (error) {
  282.         if (!silent)
  283.             printk("VFS: Can't find a valid MSDOS filesystem on dev 0x%04x.\n",
  284.                    sb->s_dev);
  285.         sb->s_dev = 0;
  286.         MOD_DEC_USE_COUNT;
  287.         return NULL;
  288.     }
  289.     sb->s_magic = MSDOS_SUPER_MAGIC;
  290.     MSDOS_SB(sb)->name_check = check;
  291.     MSDOS_SB(sb)->conversion = conversion;
  292.     /* set up enough so that it can read an inode */
  293.     sb->s_op = &msdos_sops;
  294.     MSDOS_SB(sb)->fs_uid = uid;
  295.     MSDOS_SB(sb)->fs_gid = gid;
  296.     MSDOS_SB(sb)->fs_umask = umask;
  297.     MSDOS_SB(sb)->quiet = quiet;
  298.     MSDOS_SB(sb)->free_clusters = -1; /* don't know yet */
  299.     MSDOS_SB(sb)->fat_wait = NULL;
  300.     MSDOS_SB(sb)->fat_lock = 0;
  301.     MSDOS_SB(sb)->prev_free = 0;
  302.     if (!(sb->s_mounted = iget(sb,MSDOS_ROOT_INO))) {
  303.         sb->s_dev = 0;
  304.         printk("get root inode failed\n");
  305.         MOD_DEC_USE_COUNT;
  306.         return NULL;
  307.     }
  308.     return sb;
  309. }
  310.  
  311.  
  312. void msdos_statfs(struct super_block *sb,struct statfs *buf)
  313. {
  314.     int free,nr;
  315.  
  316.     put_fs_long(sb->s_magic,&buf->f_type);
  317.     put_fs_long(MSDOS_SB(sb)->cluster_size*SECTOR_SIZE,&buf->f_bsize);
  318.     put_fs_long(MSDOS_SB(sb)->clusters,&buf->f_blocks);
  319.     lock_fat(sb);
  320.     if (MSDOS_SB(sb)->free_clusters != -1)
  321.         free = MSDOS_SB(sb)->free_clusters;
  322.     else {
  323.         free = 0;
  324.         for (nr = 2; nr < MSDOS_SB(sb)->clusters+2; nr++)
  325.             if (!fat_access(sb,nr,-1)) free++;
  326.         MSDOS_SB(sb)->free_clusters = free;
  327.     }
  328.     unlock_fat(sb);
  329.     put_fs_long(free,&buf->f_bfree);
  330.     put_fs_long(free,&buf->f_bavail);
  331.     put_fs_long(0,&buf->f_files);
  332.     put_fs_long(0,&buf->f_ffree);
  333.     put_fs_long(12,&buf->f_namelen);
  334. }
  335.  
  336.  
  337. int msdos_bmap(struct inode *inode,int block)
  338. {
  339.     struct msdos_sb_info *sb;
  340.     int cluster,offset;
  341.  
  342.     sb = MSDOS_SB(inode->i_sb);
  343.     if (inode->i_ino == MSDOS_ROOT_INO) {
  344.         return sb->dir_start + block;
  345.     }
  346.     cluster = block/sb->cluster_size;
  347.     offset = block % sb->cluster_size;
  348.     if (!(cluster = get_cluster(inode,cluster))) return 0;
  349.     return (cluster-2)*sb->cluster_size+sb->data_start+offset;
  350. }
  351.  
  352.  
  353. void msdos_read_inode(struct inode *inode)
  354. {
  355.     struct super_block *sb = inode->i_sb;
  356.     struct buffer_head *bh;
  357.     struct msdos_dir_entry *raw_entry;
  358.     int nr;
  359.  
  360. /* printk("read inode %d\n",inode->i_ino); */
  361.     MSDOS_I(inode)->i_busy = 0;
  362.     MSDOS_I(inode)->i_depend = MSDOS_I(inode)->i_old = NULL;
  363.     MSDOS_I(inode)->i_binary = 1;
  364.     inode->i_uid = MSDOS_SB(inode->i_sb)->fs_uid;
  365.     inode->i_gid = MSDOS_SB(inode->i_sb)->fs_gid;
  366.     if (inode->i_ino == MSDOS_ROOT_INO) {
  367.         inode->i_mode = (S_IRWXUGO & ~MSDOS_SB(inode->i_sb)->fs_umask) |
  368.             S_IFDIR;
  369.         inode->i_op = &msdos_dir_inode_operations;
  370.         inode->i_nlink = msdos_subdirs(inode)+2;
  371.             /* subdirs (neither . nor ..) plus . and "self" */
  372.         inode->i_size = MSDOS_SB(inode->i_sb)->dir_entries*
  373.             sizeof(struct msdos_dir_entry);
  374.         inode->i_blksize = MSDOS_SB(inode->i_sb)->cluster_size*
  375.             SECTOR_SIZE;
  376.         inode->i_blocks = (inode->i_size+inode->i_blksize-1)/
  377.             inode->i_blksize*MSDOS_SB(inode->i_sb)->cluster_size;
  378.         MSDOS_I(inode)->i_start = 0;
  379.         MSDOS_I(inode)->i_attrs = 0;
  380.         inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
  381.         return;
  382.     }
  383.     if (!(bh = bread(inode->i_dev,inode->i_ino >> MSDOS_DPB_BITS,
  384.         SECTOR_SIZE))) {
  385.         printk("dev = 0x%04X, ino = %ld\n",inode->i_dev,inode->i_ino);
  386.         panic("msdos_read_inode: unable to read i-node block");
  387.     }
  388.     raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
  389.         [inode->i_ino & (MSDOS_DPB-1)];
  390.     if ((raw_entry->attr & ATTR_DIR) && !IS_FREE(raw_entry->name)) {
  391.         inode->i_mode = MSDOS_MKMODE(raw_entry->attr,S_IRWXUGO &
  392.             ~MSDOS_SB(inode->i_sb)->fs_umask) | S_IFDIR;
  393.         inode->i_op = &msdos_dir_inode_operations;
  394.         MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start);
  395.         inode->i_nlink = msdos_subdirs(inode);
  396.             /* includes .., compensating for "self" */
  397. #ifdef DEBUG
  398.         if (!inode->i_nlink) {
  399.             printk("directory %d: i_nlink == 0\n",inode->i_ino);
  400.             inode->i_nlink = 1;
  401.         }
  402. #endif
  403.         inode->i_size = 0;
  404.         if ((nr = CF_LE_W(raw_entry->start)) != 0)
  405.             while (nr != -1) {
  406.                 inode->i_size += SECTOR_SIZE*MSDOS_SB(inode->
  407.                     i_sb)->cluster_size;
  408.                 if (!(nr = fat_access(inode->i_sb,nr,-1))) {
  409.                     printk("Directory %ld: bad FAT\n",
  410.                         inode->i_ino);
  411.                     break;
  412.                 }
  413.             }
  414.     }
  415.     else {
  416.         inode->i_mode = MSDOS_MKMODE(raw_entry->attr,(IS_NOEXEC(inode)
  417.             ? S_IRUGO|S_IWUGO : S_IRWXUGO) & ~MSDOS_SB(inode->i_sb)->fs_umask) |
  418.             S_IFREG;
  419.         inode->i_op = sb->s_blocksize == 1024
  420.             ? &msdos_file_inode_operations_1024
  421.             : &msdos_file_inode_operations;
  422.         MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start);
  423.         inode->i_nlink = 1;
  424.         inode->i_size = CF_LE_L(raw_entry->size);
  425.     }
  426.     MSDOS_I(inode)->i_binary = is_binary(MSDOS_SB(inode->i_sb)->conversion,
  427.         raw_entry->ext);
  428.     MSDOS_I(inode)->i_attrs = raw_entry->attr & ATTR_UNUSED;
  429.     /* this is as close to the truth as we can get ... */
  430.     inode->i_blksize = MSDOS_SB(inode->i_sb)->cluster_size*SECTOR_SIZE;
  431.     inode->i_blocks = (inode->i_size+inode->i_blksize-1)/
  432.         inode->i_blksize*MSDOS_SB(inode->i_sb)->cluster_size;
  433.     inode->i_mtime = inode->i_atime = inode->i_ctime =
  434.         date_dos2unix(CF_LE_W(raw_entry->time),CF_LE_W(raw_entry->date));
  435.     brelse(bh);
  436. }
  437.  
  438.  
  439. void msdos_write_inode(struct inode *inode)
  440. {
  441.     struct super_block *sb = inode->i_sb;
  442.     struct buffer_head *bh;
  443.     struct msdos_dir_entry *raw_entry;
  444.  
  445.     inode->i_dirt = 0;
  446.     if (inode->i_ino == MSDOS_ROOT_INO || !inode->i_nlink) return;
  447.     if (!(bh = bread(inode->i_dev,inode->i_ino >> MSDOS_DPB_BITS,
  448.         SECTOR_SIZE))) {
  449.         printk("dev = 0x%04X, ino = %ld\n",inode->i_dev,inode->i_ino);
  450.         panic("msdos_write_inode: unable to read i-node block");
  451.     }
  452.     raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
  453.         [inode->i_ino & (MSDOS_DPB-1)];
  454.     if (S_ISDIR(inode->i_mode)) {
  455.         raw_entry->attr = ATTR_DIR;
  456.         raw_entry->size = 0;
  457.     }
  458.     else {
  459.         raw_entry->attr = ATTR_NONE;
  460.         raw_entry->size = CT_LE_L(inode->i_size);
  461.     }
  462.     raw_entry->attr |= MSDOS_MKATTR(inode->i_mode) |
  463.         MSDOS_I(inode)->i_attrs;
  464.     raw_entry->start = CT_LE_L(MSDOS_I(inode)->i_start);
  465.     date_unix2dos(inode->i_mtime,&raw_entry->time,&raw_entry->date);
  466.     raw_entry->time = CT_LE_W(raw_entry->time);
  467.     raw_entry->date = CT_LE_W(raw_entry->date);
  468.     mark_buffer_dirty(bh, 1);
  469.     brelse(bh);
  470. }
  471.  
  472.  
  473. int msdos_notify_change(struct inode * inode,struct iattr * attr)
  474. {
  475.     int error;
  476.  
  477.     error = inode_change_ok(inode, attr);
  478.     if (error)
  479.         return error;
  480.  
  481.     if (((attr->ia_valid & ATTR_UID) && 
  482.          (attr->ia_uid != MSDOS_SB(inode->i_sb)->fs_uid)) ||
  483.         ((attr->ia_valid & ATTR_GID) && 
  484.          (attr->ia_gid != MSDOS_SB(inode->i_sb)->fs_gid)) ||
  485.         ((attr->ia_valid & ATTR_MODE) &&
  486.          (attr->ia_mode & ~MSDOS_VALID_MODE)))
  487.         error = -EPERM;
  488.  
  489.     if (error)
  490.         return MSDOS_SB(inode->i_sb)->quiet ? 0 : error;
  491.  
  492.     inode_setattr(inode, attr);
  493.  
  494.     if (IS_NOEXEC(inode) && !S_ISDIR(inode->i_mode))
  495.         inode->i_mode &= S_IFMT | S_IRUGO | S_IWUGO;
  496.     else
  497.         inode->i_mode |= S_IXUGO;
  498.  
  499.     inode->i_mode = ((inode->i_mode & S_IFMT) | ((((inode->i_mode & S_IRWXU
  500.         & ~MSDOS_SB(inode->i_sb)->fs_umask) | S_IRUSR) >> 6)*S_IXUGO)) &
  501.         ~MSDOS_SB(inode->i_sb)->fs_umask;
  502.     return 0;
  503. }
  504. #ifdef MODULE
  505.  
  506. char kernel_version[] = UTS_RELEASE;
  507.  
  508. static struct file_system_type msdos_fs_type = {
  509.     msdos_read_super, "msdos", 1, NULL
  510. };
  511.  
  512. int init_module(void)
  513. {
  514.     register_filesystem(&msdos_fs_type);
  515.     return 0;
  516. }
  517.  
  518. void cleanup_module(void)
  519. {
  520.     unregister_filesystem(&msdos_fs_type);
  521. }
  522.  
  523. #endif
  524.  
  525.