inode.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:7k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Super block/filesystem wide operations
  3.  *
  4.  * Copyright (C) 1996 Peter J. Braam <braam@maths.ox.ac.uk> and 
  5.  * Michael Callahan <callahan@maths.ox.ac.uk> 
  6.  * 
  7.  * Rewritten for Linux 2.1.  Peter Braam <braam@cs.cmu.edu>
  8.  * Copyright (C) Carnegie Mellon University
  9.  */
  10. #define __NO_VERSION__
  11. #include <linux/module.h>
  12. #include <linux/kernel.h>
  13. #include <linux/mm.h>
  14. #include <linux/string.h>
  15. #include <linux/stat.h>
  16. #include <linux/errno.h>
  17. #include <linux/locks.h>
  18. #include <linux/unistd.h>
  19. #include <linux/smp_lock.h>
  20. #include <linux/file.h>
  21. #include <asm/system.h>
  22. #include <asm/uaccess.h>
  23. #include <linux/fs.h>
  24. #include <linux/vmalloc.h>
  25. #include <asm/segment.h>
  26. #include <linux/coda.h>
  27. #include <linux/coda_linux.h>
  28. #include <linux/coda_psdev.h>
  29. #include <linux/coda_fs_i.h>
  30. #include <linux/coda_cache.h>
  31. /* VFS super_block ops */
  32. static struct super_block *coda_read_super(struct super_block *, void *, int);
  33. static void coda_read_inode(struct inode *);
  34. static void coda_clear_inode(struct inode *);
  35. static void coda_put_super(struct super_block *);
  36. static int coda_statfs(struct super_block *sb, struct statfs *buf);
  37. /* exported operations */
  38. struct super_operations coda_super_operations =
  39. {
  40. read_inode: coda_read_inode,
  41. clear_inode: coda_clear_inode,
  42. put_super: coda_put_super,
  43. statfs: coda_statfs,
  44. };
  45. static int get_device_index(struct coda_mount_data *data)
  46. {
  47. struct file *file;
  48. struct inode *inode;
  49. int idx;
  50. if(data == NULL) {
  51. printk("coda_read_super: Bad mount datan");
  52. return -1;
  53. }
  54. if(data->version != CODA_MOUNT_VERSION) {
  55. printk("coda_read_super: Bad mount versionn");
  56. return -1;
  57. }
  58. file = fget(data->fd);
  59. inode = NULL;
  60. if(file)
  61. inode = file->f_dentry->d_inode;
  62. if(!inode || !S_ISCHR(inode->i_mode) ||
  63.    MAJOR(inode->i_rdev) != CODA_PSDEV_MAJOR) {
  64. if(file)
  65. fput(file);
  66. printk("coda_read_super: Bad filen");
  67. return -1;
  68. }
  69. idx = MINOR(inode->i_rdev);
  70. fput(file);
  71. if(idx < 0 || idx >= MAX_CODADEVS) {
  72. printk("coda_read_super: Bad minor numbern");
  73. return -1;
  74. }
  75. return idx;
  76. }
  77. static struct super_block * coda_read_super(struct super_block *sb, 
  78.     void *data, int silent)
  79. {
  80.         struct inode *root = 0; 
  81. struct coda_sb_info *sbi = NULL;
  82. struct venus_comm *vc = NULL;
  83.         ViceFid fid;
  84.         int error;
  85. int idx;
  86. idx = get_device_index((struct coda_mount_data *) data);
  87. /* Ignore errors in data, for backward compatibility */
  88. if(idx == -1)
  89. idx = 0;
  90. printk(KERN_INFO "coda_read_super: device index: %in", idx);
  91. vc = &coda_comms[idx];
  92. if (!vc->vc_inuse) {
  93. printk("coda_read_super: No pseudo devicen");
  94. return NULL;
  95. }
  96.         if ( vc->vc_sb ) {
  97. printk("coda_read_super: Device already mountedn");
  98. return NULL;
  99. }
  100. sbi = kmalloc(sizeof(struct coda_sb_info), GFP_KERNEL);
  101. if(!sbi) {
  102. return NULL;
  103. }
  104. vc->vc_sb = sb;
  105. sbi->sbi_sb = sb;
  106. sbi->sbi_vcomm = vc;
  107. INIT_LIST_HEAD(&sbi->sbi_cihead);
  108.         sb->u.generic_sbp = sbi;
  109.         sb->s_blocksize = 1024; /* XXXXX  what do we put here?? */
  110.         sb->s_blocksize_bits = 10;
  111.         sb->s_magic = CODA_SUPER_MAGIC;
  112.         sb->s_op = &coda_super_operations;
  113. /* get root fid from Venus: this needs the root inode */
  114. error = venus_rootfid(sb, &fid);
  115. if ( error ) {
  116.         printk("coda_read_super: coda_get_rootfid failed with %dn",
  117.        error);
  118. goto error;
  119. }   
  120. printk("coda_read_super: rootfid is %sn", coda_f2s(&fid));
  121. /* make root inode */
  122.         error = coda_cnode_make(&root, &fid, sb);
  123.         if ( error || !root ) {
  124.     printk("Failure of coda_cnode_make for root: error %dn", error);
  125.     goto error;
  126. printk("coda_read_super: rootinode is %ld dev %dn", 
  127.        root->i_ino, root->i_dev);
  128. sb->s_root = d_alloc_root(root);
  129.         return sb;
  130.  error:
  131. if (sbi) {
  132. kfree(sbi);
  133. if(vc)
  134. vc->vc_sb = NULL;
  135. }
  136. if (root)
  137.                 iput(root);
  138.         return NULL;
  139. }
  140. static void coda_put_super(struct super_block *sb)
  141. {
  142.         struct coda_sb_info *sbi;
  143. sbi = coda_sbp(sb);
  144. sbi->sbi_vcomm->vc_sb = NULL;
  145.         list_del_init(&sbi->sbi_cihead);
  146. printk("Coda: Bye bye.n");
  147. kfree(sbi);
  148. }
  149. /* all filling in of inodes postponed until lookup */
  150. static void coda_read_inode(struct inode *inode)
  151. {
  152. struct coda_sb_info *sbi = coda_sbp(inode->i_sb);
  153. struct coda_inode_info *cii;
  154.         if (!sbi) BUG();
  155. #if 0
  156. /* check if the inode is already initialized */
  157. if (inode->u.generic_ip) {
  158.             printk("coda_read_inode: initialized inode");
  159.             return;
  160.         }
  161. inode->u.generic_ip = cii_alloc();
  162. if (!inode->u.generic_ip) {
  163. CDEBUG(D_CNODE, "coda_read_inode: failed to allocate inode infon");
  164. make_bad_inode(inode);
  165. return;
  166. }
  167. memset(inode->u.generic_ip, 0, sizeof(struct coda_inode_info));
  168. #endif
  169. cii = ITOC(inode);
  170. if (!coda_isnullfid(&cii->c_fid)) {
  171.             printk("coda_read_inode: initialized inode");
  172.             return;
  173.         }
  174. list_add(&cii->c_cilist, &sbi->sbi_cihead);
  175. }
  176. static void coda_clear_inode(struct inode *inode)
  177. {
  178. struct coda_inode_info *cii = ITOC(inode);
  179.         CDEBUG(D_SUPER, " inode->ino: %ld, count: %dn", 
  180.        inode->i_ino, atomic_read(&inode->i_count));        
  181. CDEBUG(D_DOWNCALL, "clearing inode: %ld, %xn", inode->i_ino, cii->c_flags);
  182. if (cii->c_container) BUG();
  183.         list_del_init(&cii->c_cilist);
  184. inode->i_mapping = &inode->i_data;
  185. coda_cache_clear_inode(inode);
  186. #if 0
  187. cii_free(inode->u.generic_ip);
  188. inode->u.generic_ip = NULL;
  189. #endif
  190. }
  191. int coda_notify_change(struct dentry *de, struct iattr *iattr)
  192. {
  193. struct inode *inode = de->d_inode;
  194.         struct coda_vattr vattr;
  195.         int error;
  196. inode->i_ctime = CURRENT_TIME;
  197.         memset(&vattr, 0, sizeof(vattr)); 
  198.         coda_iattr_to_vattr(iattr, &vattr);
  199.         vattr.va_type = C_VNON; /* cannot set type */
  200. CDEBUG(D_SUPER, "vattr.va_mode %on", vattr.va_mode);
  201. /* Venus is responsible for truncating the container-file!!! */
  202. error = venus_setattr(inode->i_sb, coda_i2f(inode), &vattr);
  203. if ( !error ) {
  204.         coda_vattr_to_iattr(inode, &vattr); 
  205. coda_cache_clear_inode(inode);
  206. }
  207. CDEBUG(D_SUPER, "inode.i_mode %o, error %dn", inode->i_mode, error);
  208. return error;
  209. }
  210. struct inode_operations coda_file_inode_operations = {
  211. permission: coda_permission,
  212. revalidate: coda_revalidate_inode,
  213. setattr: coda_notify_change,
  214. };
  215. static int coda_statfs(struct super_block *sb, struct statfs *buf)
  216. {
  217. int error;
  218. error = venus_statfs(sb, buf);
  219. if (error) {
  220. /* fake something like AFS does */
  221. buf->f_blocks = 9000000;
  222. buf->f_bfree  = 9000000;
  223. buf->f_bavail = 9000000;
  224. buf->f_files  = 9000000;
  225. buf->f_ffree  = 9000000;
  226. }
  227. /* and fill in the rest */
  228. buf->f_type = CODA_SUPER_MAGIC;
  229. buf->f_bsize = 1024;
  230. buf->f_namelen = CODA_MAXNAMLEN;
  231. return 0; 
  232. }
  233. /* init_coda: used by filesystems.c to register coda */
  234. DECLARE_FSTYPE( coda_fs_type, "coda", coda_read_super, 0);