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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * intermezzo.c
  3.  *
  4.  * This file implements basic routines supporting the semantics
  5.  *
  6.  * Author: Peter J. Braam  <braam@cs.cmu.edu>
  7.  * Copyright (C) 1998 Stelias Computing Inc
  8.  * Copyright (C) 1999 Red Hat Inc.
  9.  *
  10.  */
  11. #include <linux/types.h>
  12. #include <linux/kernel.h>
  13. #include <linux/sched.h>
  14. #include <linux/fs.h>
  15. #include <linux/stat.h>
  16. #include <linux/errno.h>
  17. #include <linux/vmalloc.h>
  18. #include <linux/slab.h>
  19. #include <linux/locks.h>
  20. #include <asm/segment.h>
  21. #include <asm/uaccess.h>
  22. #include <linux/string.h>
  23. #include <linux/smp_lock.h>
  24. #include <linux/intermezzo_fs.h>
  25. #include <linux/intermezzo_upcall.h>
  26. #include <linux/intermezzo_psdev.h>
  27. #include <linux/intermezzo_kml.h>
  28. extern int presto_init_last_rcvd_file(struct presto_file_set *);
  29. extern int presto_init_lml_file(struct presto_file_set *);
  30. extern int presto_init_kml_file(struct presto_file_set *);
  31. int presto_walk(const char *name, struct nameidata *nd)
  32. {
  33.         int err;
  34.         /* we do not follow symlinks to support symlink operations 
  35.            correctly. The vfs should always hand us resolved dentries
  36.            so we should not be required to use LOOKUP_FOLLOW. At the
  37.    reintegrating end, lento again should be working with the 
  38.            resolved pathname and not the symlink. SHP
  39.            XXX: This code implies that direct symlinks do not work. SHP
  40.         */
  41.         unsigned int flags = LOOKUP_POSITIVE;
  42.         ENTRY;
  43.         err = 0;
  44.         if (path_init(name, flags, nd)) 
  45.                 err = path_walk(name, nd);
  46.         return err;
  47. }
  48. static inline int presto_dentry_is_fsetroot(struct dentry *dentry)
  49. {
  50.         return ((long) dentry->d_fsdata) & PRESTO_FSETROOT;
  51. }
  52. static inline struct presto_file_set *presto_dentry2fset(struct dentry *dentry)
  53. {
  54.         return (struct presto_file_set *)
  55.                 (((long) dentry->d_fsdata) - PRESTO_FSETROOT);
  56. }
  57. /* find the presto minor device for this inode */
  58. int presto_i2m(struct inode *inode)
  59. {
  60.         struct presto_cache *cache;
  61.         ENTRY;
  62.         cache = presto_get_cache(inode);
  63.         CDEBUG(D_PSDEV, "n");
  64.         if ( !cache ) {
  65.                 printk("PRESTO: BAD: cannot find cache for dev %d, ino %ldn",
  66.                        inode->i_dev, inode->i_ino);
  67.                 EXIT;
  68.                 return -1;
  69.         }
  70.         EXIT;
  71.         return cache->cache_psdev->uc_minor;
  72. }
  73. inline int presto_f2m(struct presto_file_set *fset)
  74. {
  75.         return fset->fset_cache->cache_psdev->uc_minor;
  76. }
  77. inline int presto_c2m(struct presto_cache *cache)
  78. {
  79.         return cache->cache_psdev->uc_minor;
  80. }
  81. int presto_has_all_data(struct inode *inode)
  82. {
  83.         ENTRY;
  84.         if ( (inode->i_size >> inode->i_sb->s_blocksize_bits) >
  85.              inode->i_blocks) {
  86.                 EXIT;
  87.                 return 0;
  88.         }
  89.         EXIT;
  90.         return 1;
  91. }
  92. /* find the fileset dentry for this dentry */
  93. struct presto_file_set *presto_fset(struct dentry *de)
  94. {
  95.         struct dentry *fsde;
  96.         ENTRY;
  97.         fsde = de;
  98.         for ( ; ; ) {
  99.                 if ( presto_dentry_is_fsetroot(fsde) ) {
  100.                         EXIT;
  101.                         return presto_dentry2fset(fsde);
  102.                 }
  103.                 /* are we at the cache "/" ?? */
  104.                 if ( fsde->d_parent == fsde ) {
  105.                         if ( !de->d_inode ) {
  106.                                 printk("Warning %*s has no fileset inode.n",
  107.                                        de->d_name.len, de->d_name.name);
  108.                         }
  109.                         /* better to return a BAD thing */
  110.                         EXIT;
  111.                         return NULL;
  112.                 }
  113.                 fsde = fsde->d_parent;
  114.         }
  115.         /* not reached */
  116.         EXIT;
  117.         return NULL;
  118. }
  119. /* XXX check this out */
  120. struct presto_file_set *presto_path2fileset(const char *name)
  121. {
  122.         struct nameidata nd;
  123.         struct presto_file_set *fileset;
  124.         int error;
  125.         ENTRY;
  126.         error = presto_walk(name, &nd);
  127.         if (!error) { 
  128. #if 0
  129.                 error = do_revalidate(nd.dentry);
  130. #endif
  131.                 if (!error) 
  132.                         fileset = presto_fset(nd.dentry); 
  133.                 path_release(&nd); 
  134.                 EXIT;
  135.         } else 
  136.                 fileset = ERR_PTR(error);
  137.         EXIT;
  138.         return fileset;
  139. }
  140. /* check a flag on this dentry or fset root.  Semantics:
  141.    - most flags: test if it is set
  142.    - PRESTO_ATTR, PRESTO_DATA return 1 if PRESTO_FSETINSYNC is set
  143. */
  144. int presto_chk(struct dentry *dentry, int flag)
  145. {
  146.         int minor;
  147.         struct presto_file_set *fset = presto_fset(dentry);
  148.         ENTRY;
  149.         minor = presto_i2m(dentry->d_inode);
  150.         if ( upc_comms[minor].uc_no_filter ) {
  151.                 EXIT;
  152.                 return ~0;
  153.         }
  154.         /* if the fileset is in sync DATA and ATTR are OK */
  155.         if ( fset &&
  156.              (flag == PRESTO_ATTR || flag == PRESTO_DATA) &&
  157.              (fset->fset_flags & FSET_INSYNC) ) {
  158.                 CDEBUG(D_INODE, "fset in sync (ino %ld)!n",
  159.                        fset->fset_mtpt->d_inode->i_ino);
  160.                 EXIT;
  161.                 return 1;
  162.         }
  163.         /* if it is a fsetroot, it's stored in the fset_flags */
  164.         if ( fset && presto_dentry_is_fsetroot(dentry) ) {
  165.                 EXIT;
  166.                 return fset->fset_data & flag;
  167.         }
  168.         EXIT;
  169.         return ((int)(long)dentry->d_fsdata & flag);
  170. }
  171. /* set a bit in the dentry flags */
  172. void presto_set(struct dentry *dentry, int flag)
  173. {
  174.         if ( dentry->d_inode ) {
  175.                 CDEBUG(D_INODE, "SET ino %ld, flag %xn",
  176.                        dentry->d_inode->i_ino, flag);
  177.         }
  178.         if ( presto_dentry_is_fsetroot(dentry)) {
  179.                 struct presto_file_set *fset = presto_dentry2fset(dentry);
  180.                 if (fset) {
  181.                         fset->fset_data |= flag;
  182.                         CDEBUG(D_INODE, "Setting fset->fset_data: now %xn",
  183.                                fset->fset_data);
  184.                 }
  185.         } else {
  186.                 CDEBUG(D_INODE, "Setting dentry->d_fsdatan");
  187.                 ((int)(long)dentry->d_fsdata) |= flag;
  188.         }
  189. }
  190. /* given a path: complete the closes on the fset */
  191. int lento_complete_closes(char *path)
  192. {
  193.         struct nameidata nd;
  194.         struct dentry *dentry;
  195.         int error;
  196.         struct presto_file_set *fset;
  197.         ENTRY;
  198.         error = presto_walk(path, &nd);
  199.         if (error) {
  200.                 EXIT;
  201.                 return error;
  202.         }
  203.         dentry = nd.dentry;
  204.         error = -ENXIO;
  205.         if ( !presto_ispresto(dentry->d_inode) ) {
  206.                 EXIT;
  207.                 goto out_complete;
  208.         }
  209.         
  210.         fset = presto_fset(dentry);
  211.         error = -EINVAL;
  212.         if ( !fset ) {
  213.                 printk("No fileset!n");
  214.                 EXIT;
  215.                 goto out_complete;
  216.         }
  217.         
  218.         /* transactions and locking are internal to this function */ 
  219.         error = presto_complete_lml(fset);
  220.         
  221.         EXIT;
  222.  out_complete:
  223.         path_release(&nd); 
  224.         return error;
  225. }       
  226. /* set the fset recno and offset to a given value */ 
  227. int lento_reset_fset(char *path, __u64 offset, __u32 recno)
  228. {
  229.         struct nameidata nd;
  230.         struct dentry *dentry;
  231.         int error;
  232.         struct presto_file_set *fset;
  233.         ENTRY;
  234.         error = presto_walk(path, &nd);
  235.         if (error)
  236.                 return error;
  237.         dentry = nd.dentry;
  238.         error = -ENXIO;
  239.         if ( !presto_ispresto(dentry->d_inode) ) {
  240.                 EXIT;
  241.                 goto out_complete;
  242.         }
  243.         
  244.         fset = presto_fset(dentry);
  245.         error = -EINVAL;
  246.         if ( !fset ) {
  247.                 printk("No fileset!n");
  248.                 EXIT;
  249.                 goto out_complete;
  250.         }
  251.         write_lock(&fset->fset_kml.fd_lock);
  252.         fset->fset_kml.fd_recno = recno;
  253.         fset->fset_kml.fd_offset = offset;
  254.         read_lock(&fset->fset_kml.fd_lock);
  255.         
  256.         EXIT;
  257.  out_complete:
  258.         path_release(&nd);
  259.         return error;
  260. }       
  261. /* given a path, write an LML record for it - thus must have root's 
  262.    group array settings, since lento is doing this 
  263. */ 
  264. int lento_write_lml(char *path,
  265.                      __u64 remote_ino, 
  266.                      __u32 remote_generation,
  267.                      __u32 remote_version,
  268.                      struct presto_version *remote_file_version)
  269. {
  270.         struct nameidata nd; 
  271.         struct rec_info rec;
  272.         struct dentry *dentry;
  273.         struct file file;
  274.         int error;
  275.         struct presto_file_set *fset;
  276.         ENTRY;
  277.         error = presto_walk(path, &nd);
  278.         if (error) {
  279.                 EXIT;
  280.                 return error;
  281.         }
  282.         dentry = nd.dentry;
  283.         file.f_dentry = dentry;
  284.         file.private_data = NULL;
  285.         error = -ENXIO;
  286.         if ( !presto_ispresto(dentry->d_inode) ) {
  287.                 EXIT;
  288.                 goto out_lml;
  289.         }
  290.         
  291.         fset = presto_fset(dentry);
  292.         error = -EINVAL;
  293.         if ( !fset ) {
  294.                 printk("No fileset!n");
  295.                 EXIT;
  296.                 goto out_lml;
  297.         }
  298.         
  299.         /* setting offset to -1 appends */
  300.         rec.offset = -1;
  301.         /* this only requires a transaction below which is automatic */
  302.         error = presto_write_lml_close(&rec, 
  303.                                        fset,
  304.                                        &file, 
  305.                                        remote_ino,
  306.                                        remote_generation,
  307.                                        remote_version,
  308.                                        remote_file_version);
  309.         
  310.         EXIT;
  311.  out_lml:
  312.         path_release(&nd);
  313.         return error;
  314. }       
  315. /* given a path: write a close record and cancel an LML record, finally
  316.    call truncate LML.  Lento is doing this so it goes in with uid/gid's 
  317.    root. 
  318. */ 
  319. int lento_cancel_lml(char *path, 
  320.                      __u64 lml_offset, 
  321.                      __u64 remote_ino, 
  322.                      __u32 remote_generation,
  323.                      __u32 remote_version, 
  324.                      struct lento_vfs_context *info)
  325. {
  326.         struct nameidata nd;
  327.         struct rec_info rec;
  328.         struct dentry *dentry;
  329.         int error;
  330.         struct presto_file_set *fset;
  331.         void *handle; 
  332.         struct presto_version new_ver;
  333.         ENTRY;
  334.         error = presto_walk(path, &nd);
  335.         if (error) {
  336.                 EXIT;
  337.                 return error;
  338.         }
  339.         dentry = nd.dentry;
  340.         error = -ENXIO;
  341.         if ( !presto_ispresto(dentry->d_inode) ) {
  342.                 EXIT;
  343.                 goto out_cancel_lml;
  344.         }
  345.         
  346.         fset = presto_fset(dentry);
  347.         error=-EINVAL;
  348.         if (fset==NULL) {
  349.                 printk("No fileset!n");
  350.                 EXIT;
  351.                 goto out_cancel_lml;
  352.         }
  353.         
  354.         /* this only requires a transaction below which is automatic */
  355.         handle = presto_trans_start(fset, dentry->d_inode, PRESTO_OP_RELEASE); 
  356.         if ( !handle ) {
  357.                 error = -ENOMEM; 
  358.                 EXIT; 
  359.                 goto out_cancel_lml; 
  360.         } 
  361.         
  362.         if (info->flags & LENTO_FL_CANCEL_LML) {
  363.                 error = presto_clear_lml_close(fset, lml_offset);
  364.                 if ( error ) {
  365.                         presto_trans_commit(fset, handle);
  366.                         EXIT; 
  367.                         goto out_cancel_lml;
  368.                 }
  369.         }
  370.         if (info->flags & LENTO_FL_WRITE_KML) {
  371.                 struct file file;
  372.                 file.private_data = NULL;
  373.                 file.f_dentry = dentry; 
  374.                 presto_getversion(&new_ver, dentry->d_inode);
  375.                 error = presto_journal_close(&rec, fset, &file, dentry, 
  376.                                              &new_ver);
  377.                 if ( error ) {
  378.                         EXIT; 
  379.                         presto_trans_commit(fset, handle);
  380.                         goto out_cancel_lml;
  381.                 }
  382.         }
  383.         if (info->flags & LENTO_FL_WRITE_EXPECT) {
  384.                 error = presto_write_last_rcvd(&rec, fset, info); 
  385.                 if ( error ) {
  386.                         EXIT; 
  387.                         presto_trans_commit(fset, handle);
  388.                         goto out_cancel_lml;
  389.                 }
  390.         }
  391.         presto_trans_commit(fset, handle);
  392.         if (info->flags & LENTO_FL_CANCEL_LML) {
  393.             presto_truncate_lml(fset); 
  394.         }
  395.                 
  396.  out_cancel_lml:
  397.         EXIT;
  398.         path_release(&nd); 
  399.         return error;
  400. }       
  401. /* given a path, operate on the flags in its dentry.  Used by downcalls */
  402. int presto_mark_dentry(const char *name, int and_flag, int or_flag, 
  403.                        int *res)
  404. {
  405.         struct nameidata nd;
  406.         struct dentry *dentry;
  407.         int error;
  408.         CDEBUG(D_INODE, "name: %s, and flag %x, or flag %xn",
  409.                name, and_flag, or_flag);
  410.         error = presto_walk(name, &nd);
  411.         if (error)
  412.                 return error;
  413.         dentry = nd.dentry;
  414.         CDEBUG(D_INODE, "dentry at %p, d_fsdata %pn", dentry, dentry->d_fsdata);
  415.         error = -ENXIO;
  416.         if ( !presto_ispresto(dentry->d_inode) )
  417.                 goto out;
  418.         error = 0;
  419.         if ( presto_dentry_is_fsetroot(dentry) ) {
  420.                 struct presto_file_set *fset = presto_dentry2fset(dentry);
  421.                 CDEBUG(D_INODE, "Setting fset fset_data: fset %pn", fset);
  422.                 if ( fset ) {
  423.                         fset->fset_data &= and_flag;
  424.                         fset->fset_data |= or_flag;
  425.                         if (res) {
  426.                                 *res = fset->fset_data;
  427.                         }
  428.                 }
  429.                 CDEBUG(D_INODE, "fset %p, flags %x data %xn", 
  430.                        fset, fset->fset_flags, fset->fset_data);
  431.         } else {
  432.                 ((int)(long)dentry->d_fsdata) &= and_flag;
  433.                 ((int)(long)dentry->d_fsdata) |= or_flag;
  434.                 if (res) 
  435.                         *res = (int)(long)dentry->d_fsdata;
  436.         }
  437.         /* indicate if we were the only users while changing the flag */
  438.         if ( atomic_read(&dentry->d_count) > 1 )
  439.                 error = -EBUSY;
  440. out:
  441.         path_release(&nd);
  442.         return error;
  443. }
  444. /* given a path, operate on the flags in its cache.  Used by mark_ioctl */
  445. int presto_mark_cache(const char *name, int and_flag, int or_flag, 
  446.                       int *res)
  447. {
  448.         struct nameidata nd;
  449.         struct dentry *dentry;
  450.         struct presto_cache *cache;
  451.         int error;
  452.         CDEBUG(D_INODE,
  453.                "presto_mark_cache :: name: %s, and flag %x, or flag %xn",
  454.                name, and_flag, or_flag);
  455.         error = presto_walk(name, &nd);
  456.         if (error)
  457.                 return error;
  458.         dentry = nd.dentry;
  459.         error = -ENXIO;
  460.         if ( !presto_ispresto(dentry->d_inode) )
  461.                 goto out;
  462.         error = -EBADF;
  463.         cache = presto_get_cache(dentry->d_inode);
  464.         if ( !cache ) {
  465.                 printk("PRESTO: BAD: cannot find cache in presto_mark_cachen");
  466.                 make_bad_inode(dentry->d_inode);
  467.                 goto out;
  468.         }
  469.         error = 0;
  470.         ((int)cache->cache_flags) &= and_flag;
  471.         ((int)cache->cache_flags) |= or_flag;
  472.         if (res) {
  473.                 *res = (int)cache->cache_flags;
  474.         }
  475. out:
  476.         path_release(&nd);
  477.         return error;
  478. }
  479. int presto_mark_fset_dentry(struct dentry *dentry, int and_flag, int or_flag, 
  480.                      int * res)
  481. {
  482.         int error;
  483.         struct presto_file_set *fset;
  484.         error = -ENXIO;
  485.         if ( !presto_ispresto(dentry->d_inode) )
  486.                 return error;
  487.         error = -EBADF;
  488.         fset = presto_fset(dentry);
  489.         if ( !fset ) {
  490.                 printk("PRESTO: BAD: cannot find cache in presto_mark_cachen");
  491.                 make_bad_inode(dentry->d_inode);
  492.                 return error;
  493.         }
  494.         error = 0;
  495.         ((int)fset->fset_flags) &= and_flag;
  496.         ((int)fset->fset_flags) |= or_flag;
  497.         if (res) { 
  498.                 *res = (int)fset->fset_flags;
  499.         }
  500.         return error;
  501. }
  502. /* given a path, operate on the flags in its cache.  Used by mark_ioctl */
  503. inline int presto_mark_fset(const char *name, int and_flag, int or_flag, 
  504.                      int * res)
  505. {
  506.         struct nameidata nd;
  507.         struct dentry *dentry;
  508.         int error;
  509.         ENTRY;
  510.         error = presto_walk(name, &nd);
  511.         if (error)
  512.                 return error;
  513.         dentry = nd.dentry;
  514.         error = presto_mark_fset_dentry(dentry, and_flag, or_flag, res);
  515.         path_release(&nd);
  516.         return error;
  517. }
  518. /* talk to Lento about the permit */
  519. static int presto_permit_upcall(struct dentry *dentry)
  520. {
  521.         int rc;
  522.         char *path, *buffer;
  523.         int pathlen;
  524.         int minor;
  525.         int fsetnamelen;
  526.         struct presto_file_set *fset = NULL;
  527.         if ( (minor = presto_i2m(dentry->d_inode)) < 0)
  528.                 return -EINVAL;
  529.         fset = presto_fset(dentry);
  530.         if (!fset) {
  531.                 EXIT;
  532.                 return -ENOTCONN;
  533.         }
  534.         
  535.         if ( !presto_lento_up(minor) ) {
  536.                 if ( fset->fset_flags & FSET_STEAL_PERMIT ) {
  537.                         return 0;
  538.                 } else {
  539.                         return -ENOTCONN;
  540.                 }
  541.         }
  542.         PRESTO_ALLOC(buffer, char *, PAGE_SIZE);
  543.         if ( !buffer ) {
  544.                 printk("PRESTO: out of memory!n");
  545.                 return -ENOMEM;
  546.         }
  547.         path = presto_path(dentry, fset->fset_mtpt, buffer, PAGE_SIZE);
  548.         pathlen = MYPATHLEN(buffer, path);
  549.         fsetnamelen = strlen(fset->fset_name); 
  550.         rc = lento_permit(minor, pathlen, fsetnamelen, path, fset->fset_name);
  551.         PRESTO_FREE(buffer, PAGE_SIZE);
  552.         return rc;
  553. }
  554. /* get a write permit for the fileset of this inode
  555.  *  - if this returns a negative value there was an error
  556.  *  - if 0 is returned the permit was already in the kernel -- or --
  557.  *    Lento gave us the permit without reintegration
  558.  *  - lento returns the number of records it reintegrated 
  559.  */
  560. int presto_get_permit(struct inode * inode)
  561. {
  562.         struct dentry *de;
  563.         struct presto_file_set *fset;
  564.         int minor = presto_i2m(inode);
  565.         int rc;
  566.         ENTRY;
  567.         if (minor < 0) {
  568.                 EXIT;
  569.                 return -1;
  570.         }
  571.         if ( ISLENTO(minor) ) {
  572.                 EXIT;
  573.                 return -EINVAL;
  574.         }
  575.         if (list_empty(&inode->i_dentry)) {
  576.                 printk("No alias for inode %dn", (int) inode->i_ino);
  577.                 EXIT;
  578.                 return -EINVAL;
  579.         }
  580.         de = list_entry(inode->i_dentry.next, struct dentry, d_alias);
  581.         fset = presto_fset(de);
  582.         if ( !fset ) {
  583.                 printk("Presto: no fileset in presto_get_permit!n");
  584.                 EXIT;
  585.                 return -EINVAL;
  586.         }
  587.         if (fset->fset_flags & FSET_HASPERMIT) {
  588.                 lock_kernel();
  589.                 fset->fset_permit_count++;
  590.                 CDEBUG(D_INODE, "permit count now %d, inode %lxn", 
  591.                        fset->fset_permit_count, inode->i_ino);
  592.                 unlock_kernel();
  593.                 EXIT;
  594.                 return 0;
  595.         } else {
  596. /* Allow reintegration to proceed without locks -SHP */
  597.                 rc = presto_permit_upcall(fset->fset_mtpt);
  598.                 lock_kernel();
  599.                 if ( !rc ) { 
  600.                  presto_mark_fset_dentry
  601. (fset->fset_mtpt, ~0, FSET_HASPERMIT, NULL);
  602.                  fset->fset_permit_count++;
  603.                 }
  604.                 CDEBUG(D_INODE, "permit count now %d, ino %lx (likely 1), rc %dn", 
  605.          fset->fset_permit_count, inode->i_ino, rc);
  606.                 unlock_kernel();
  607.                 EXIT;
  608.                 return rc;
  609.         }
  610. }
  611. int presto_put_permit(struct inode * inode)
  612. {
  613.         struct dentry *de;
  614.         struct presto_file_set *fset;
  615.         int minor = presto_i2m(inode);
  616.         ENTRY;
  617.         if (minor < 0) {
  618.                 EXIT;
  619.                 return -1;
  620.         }
  621.         if ( ISLENTO(minor) ) {
  622.                 EXIT;
  623.                 return -1;
  624.         }
  625.         if (list_empty(&inode->i_dentry)) {
  626.                 printk("No alias for inode %dn", (int) inode->i_ino);
  627.                 EXIT;
  628.                 return -1;
  629.         }
  630.         de = list_entry(inode->i_dentry.next, struct dentry, d_alias);
  631.         fset = presto_fset(de);
  632.         if ( !fset ) {
  633.                 printk("Presto: no fileset in presto_get_permit!n");
  634.                 EXIT;
  635.                 return -1;
  636.         }
  637.         lock_kernel();
  638.         if (fset->fset_flags & FSET_HASPERMIT) {
  639.                 if (fset->fset_permit_count > 0) fset->fset_permit_count--;
  640.                 else printk("Put permit while permit count is 0, inode %lx!n",
  641.                                 inode->i_ino); 
  642.         } else {
  643.          fset->fset_permit_count=0;
  644.          printk("Put permit while no permit, inode %lx, flags %x!n", 
  645.                 inode->i_ino, fset->fset_flags);
  646.         }
  647.         CDEBUG(D_INODE, "permit count now %d, inode %lxn", 
  648.          fset->fset_permit_count, inode->i_ino);
  649.         if (fset->fset_flags & FSET_PERMIT_WAITING &&
  650.                     fset->fset_permit_count == 0) {
  651.                 CDEBUG(D_INODE, "permit count now 0, ino %lx, notify Lenton", 
  652.                        inode->i_ino);
  653.                 presto_mark_fset_dentry(fset->fset_mtpt, ~FSET_PERMIT_WAITING, 0, NULL);
  654.                 presto_mark_fset_dentry(fset->fset_mtpt, ~FSET_HASPERMIT, 0, NULL);
  655.                 lento_release_permit(fset->fset_cache->cache_psdev->uc_minor,
  656.                                      fset->fset_permit_cookie);
  657.                 fset->fset_permit_cookie = 0; 
  658.         }
  659.         unlock_kernel();
  660.         EXIT;
  661.         return 0;
  662. }
  663. void presto_getversion(struct presto_version * presto_version,
  664.                        struct inode * inode)
  665. {
  666.         presto_version->pv_mtime = cpu_to_le64((__u64)inode->i_mtime);
  667.         presto_version->pv_ctime = cpu_to_le64((__u64)inode->i_ctime);
  668.         presto_version->pv_size = cpu_to_le64((__u64)inode->i_size);
  669. }
  670. /*
  671.  *  note: this routine "pins" a dentry for a fileset root
  672.  */
  673. int presto_set_fsetroot(char *path, char *fsetname, unsigned int fsetid,
  674.                         unsigned int flags)
  675. {
  676.         struct presto_file_set *fset;
  677.         struct presto_file_set *fset2;
  678.         struct dentry *dentry;
  679.         struct presto_cache *cache;
  680.         int error;
  681.         ENTRY;
  682.         PRESTO_ALLOC(fset, struct presto_file_set *, sizeof(*fset));
  683.         error = -ENOMEM;
  684.         if ( !fset ) {
  685.                 printk(KERN_ERR "No memory allocating fset for %sn", fsetname);
  686.                 EXIT;
  687.                 return -ENOMEM;
  688.         }
  689.         CDEBUG(D_INODE, "fset at %pn", fset);
  690.         printk("presto: fsetroot: path %s, fileset name %sn", path, fsetname);
  691.         error = presto_walk(path, &fset->fset_nd);
  692.         CDEBUG(D_INODE, "n");
  693.         if (error) {
  694.                 EXIT;
  695.                 goto out_free;
  696.         }
  697.         dentry = fset->fset_nd.dentry;
  698.         CDEBUG(D_INODE, "n");
  699.         error = -ENXIO;
  700.         if ( !presto_ispresto(dentry->d_inode) ) {
  701.                 EXIT;
  702.                 goto out_dput;
  703.         }
  704.         CDEBUG(D_INODE, "n");
  705.         cache = presto_get_cache(dentry->d_inode);
  706.         if (!cache) {
  707.                 printk(KERN_ERR "No cache found for %sn", path);
  708.                 EXIT;
  709.                 goto out_dput;
  710.         }
  711.         CDEBUG(D_INODE, "n");
  712.         error = -EINVAL;
  713.         if ( !cache->cache_mtpt) {
  714.                 printk(KERN_ERR "Presto - no mountpoint: fsetroot fails!n");
  715.                 EXIT;
  716.                 goto out_dput;
  717.         }
  718.         CDEBUG(D_INODE, "n");
  719.         if (!cache->cache_root_fileset)  {
  720.                 printk(KERN_ERR "Presto - no file set: fsetroot fails!n");
  721.                 EXIT;
  722.                 goto out_dput;
  723.         }
  724.         error = -EEXIST;
  725.         CDEBUG(D_INODE, "n");
  726.         fset2 = presto_fset(dentry);
  727.         if (fset2 && (fset2->fset_mtpt == dentry) ) { 
  728.                 printk(KERN_ERR "Fsetroot already set (path %s)n", path);
  729.                 EXIT;
  730.                 goto out_dput;
  731.         }
  732.         fset->fset_cache = cache;
  733.         fset->fset_mtpt = dentry;
  734.         fset->fset_name = fsetname;
  735.         fset->fset_chunkbits = CHUNK_BITS;
  736.         fset->fset_flags = flags;
  737. fset->fset_file_maxio = FSET_DEFAULT_MAX_FILEIO; 
  738.         dentry->d_fsdata = (void *) ( ((long)fset) + PRESTO_FSETROOT );
  739.         list_add(&fset->fset_list, &cache->cache_fset_list);
  740.         error = presto_init_kml_file(fset);
  741.         if ( error ) {
  742.                 EXIT;
  743.                 CDEBUG(D_JOURNAL, "Error init_kml %dn", error);
  744.                 goto out_list_del;
  745.         }
  746.         error = presto_init_last_rcvd_file(fset);
  747.         if ( error ) {
  748.                 int rc;
  749.                 EXIT;
  750.                 rc = presto_close_journal_file(fset);
  751.                 CDEBUG(D_JOURNAL, "Error init_lastrcvd %d, cleanup %dn", error, rc);
  752.                 goto out_list_del;
  753.         }
  754.         error = presto_init_lml_file(fset);
  755.         if ( error ) {
  756.                 int rc;
  757.                 EXIT;
  758.                 rc = presto_close_journal_file(fset);
  759.                 CDEBUG(D_JOURNAL, "Error init_lml %d, cleanup %dn", error, rc);
  760.                 goto out_list_del;
  761.         }
  762. #ifdef  CONFIG_KREINT
  763.         /* initialize kml reint buffer */
  764.         error = kml_init (fset); 
  765.         if ( error ) {
  766.                 int rc;
  767.                 EXIT;
  768.                 rc = presto_close_journal_file(fset);
  769.                 CDEBUG(D_JOURNAL, "Error init kml reint %d, cleanup %dn", 
  770.                                 error, rc);
  771.                 goto out_list_del;
  772.         }
  773. #endif
  774.         if ( dentry->d_inode == dentry->d_inode->i_sb->s_root->d_inode) {
  775.                 cache->cache_flags |= CACHE_FSETROOT_SET;
  776.         }
  777.         CDEBUG(D_PIOCTL, "-------> fset at %p, dentry at %p, mtpt %p, fset %s, cache %p, d_fsdata %pn",
  778.                fset, dentry, fset->fset_mtpt, fset->fset_name, cache, dentry->d_fsdata);
  779.         EXIT;
  780.         return 0;
  781.  out_list_del:
  782.         list_del(&fset->fset_list);
  783.         dentry->d_fsdata = 0;
  784.  out_dput:
  785.         path_release(&fset->fset_nd); 
  786.  out_free:
  787.         PRESTO_FREE(fset, sizeof(*fset));
  788.         return error;
  789. }
  790. int presto_get_kmlsize(char *path, size_t *size)
  791. {
  792.         struct nameidata nd;
  793.         struct presto_file_set *fset;
  794.         struct dentry *dentry;
  795.         int error;
  796.         ENTRY;
  797.         error = presto_walk(path, &nd);
  798.         if (error) {
  799.                 EXIT;
  800.                 return error;
  801.         }
  802.         dentry = nd.dentry;
  803.         error = -ENXIO;
  804.         if ( !presto_ispresto(dentry->d_inode) ) {
  805.                 EXIT;
  806.                 goto kml_out;
  807.         }
  808.         error = -EINVAL;
  809.         if ( ! presto_dentry_is_fsetroot(dentry)) {
  810.                 EXIT;
  811.                 goto kml_out;
  812.         }
  813.         fset = presto_dentry2fset(dentry);
  814.         if (!fset) {
  815.                 EXIT;
  816.                 goto kml_out;
  817.         }
  818.         error = 0;
  819.         *size = fset->fset_kml.fd_offset;
  820.  kml_out:
  821.         path_release(&nd);
  822.         return error;
  823. }
  824. int presto_clear_fsetroot(char *path)
  825. {
  826.         struct nameidata nd;
  827.         struct presto_file_set *fset;
  828.         struct dentry *dentry;
  829.         struct presto_cache *cache;
  830.         int error;
  831.         ENTRY;
  832.         error = presto_walk(path, &nd);
  833.         if (error) {
  834.                 EXIT;
  835.                 return error;
  836.         }
  837.         dentry = nd.dentry;
  838.         error = -ENXIO;
  839.         if ( !presto_ispresto(dentry->d_inode) ) {
  840.                 EXIT;
  841.                 goto put_out;
  842.         }
  843.         error = -EINVAL;
  844.         if ( ! presto_dentry_is_fsetroot(dentry)) {
  845.                 EXIT;
  846.                 goto put_out;
  847.         }
  848.         fset = presto_dentry2fset(dentry);
  849.         if (!fset) {
  850.                 EXIT;
  851.                 goto put_out;
  852.         }
  853. #ifdef  CONFIG_KREINT
  854.         error = kml_cleanup (fset);
  855.         if ( error ) {
  856.                 printk("InterMezzo: Closing kml for fset %s: %dn",
  857.                        fset->fset_name, error);
  858.         }
  859. #endif
  860.         error = presto_close_journal_file(fset);
  861.         if ( error ) {
  862.                 printk("InterMezzo: Closing journal for fset %s: %dn",
  863.                        fset->fset_name, error);
  864.         }
  865.         cache = fset->fset_cache;
  866.         cache->cache_flags &= ~CACHE_FSETROOT_SET;
  867.         list_del(&fset->fset_list);
  868.         dentry->d_fsdata = 0;
  869.         path_release(&fset->fset_nd);
  870.         fset->fset_mtpt = NULL;
  871.         PRESTO_FREE(fset->fset_name, strlen(fset->fset_name) + 1);
  872.         PRESTO_FREE(fset, sizeof(*fset));
  873.         EXIT;
  874. put_out:
  875.         path_release(&nd); /* for our lookup */
  876.         return error;
  877. }
  878. int presto_clear_all_fsetroots(char *path)
  879. {
  880.         struct nameidata nd;
  881.         struct presto_file_set *fset;
  882.         struct dentry *dentry;
  883.         struct presto_cache *cache;
  884.         int error;
  885.         struct list_head *tmp,*tmpnext;
  886.         ENTRY;
  887.         error = presto_walk(path, &nd);
  888.         if (error) {
  889.                 EXIT;
  890.                 return error;
  891.         }
  892.         dentry = nd.dentry;
  893.         error = -ENXIO;
  894.         if ( !presto_ispresto(dentry->d_inode) ) {
  895.                 EXIT;
  896.                 goto put_out;
  897.         }
  898.         error = -EINVAL;
  899.         if ( ! presto_dentry_is_fsetroot(dentry)) {
  900.                 EXIT;
  901.                 goto put_out;
  902.         }
  903.         fset = presto_dentry2fset(dentry);
  904.         if (!fset) {
  905.                 EXIT;
  906.                 goto put_out;
  907.         }
  908.         cache = fset->fset_cache;
  909.         cache = fset->fset_cache;
  910.         cache->cache_flags &= ~CACHE_FSETROOT_SET;
  911.         tmp = &cache->cache_fset_list;
  912.         tmpnext = tmp->next;
  913.         while ( tmpnext != &cache->cache_fset_list) {
  914. tmp=tmpnext;
  915.                 tmpnext=tmp->next;
  916.                 fset = list_entry(tmp, struct presto_file_set, fset_list);
  917.                 
  918.                 error = presto_close_journal_file(fset);
  919.                 if ( error ) {
  920.                         printk("InterMezzo: Closing journal for fset %s: %dn",
  921.                                fset->fset_name, error);
  922.                 }
  923.                 list_del(&fset->fset_list);
  924.                 fset->fset_mtpt->d_fsdata = 0;
  925.                 path_release(&fset->fset_nd);
  926.                 fset->fset_mtpt = NULL;
  927.                 PRESTO_FREE(fset->fset_name, strlen(fset->fset_name) +1);
  928.                 PRESTO_FREE(fset, sizeof(*fset));
  929.         }
  930.         EXIT;
  931.  put_out:
  932.         path_release(&nd); /* for our lookup */
  933.         return error;
  934. }
  935. int presto_get_lastrecno(char *path, off_t *recno)
  936. {
  937.         struct nameidata nd; 
  938.         struct presto_file_set *fset;
  939.         struct dentry *dentry;
  940.         int error;
  941.         ENTRY;
  942.         error = presto_walk(path, &nd);
  943.         if (error) {
  944.                 EXIT;
  945.                 return error;
  946.         }
  947.         dentry = nd.dentry;
  948.         error = -ENXIO;
  949.         if ( !presto_ispresto(dentry->d_inode) ) {
  950.                 EXIT;
  951.                 goto kml_out;
  952.         }
  953.         error = -EINVAL;
  954.         if ( ! presto_dentry_is_fsetroot(dentry)) {
  955.                 EXIT;
  956.                 goto kml_out;
  957.         }
  958.         fset = presto_dentry2fset(dentry);
  959.         if (!fset) {
  960.                 EXIT;
  961.                 goto kml_out;
  962.         }
  963.         error = 0;
  964.         *recno = fset->fset_kml.fd_recno;
  965.  kml_out:
  966.         path_release(&nd);
  967.         return error;
  968. }
  969. /* 
  970.    if *cookie != 0, lento must wait for this cookie
  971.    before releasing the permit, operations are in progress. 
  972. */ 
  973. int presto_permit_downcall( const char * path, int *cookie )
  974. {
  975.         int result;
  976.         struct presto_file_set *fset; 
  977.         fset = presto_path2fileset(path);
  978.         if (IS_ERR(fset)) { 
  979.                 EXIT;
  980.                 return PTR_ERR(fset);
  981.         }
  982. lock_kernel();
  983.         if (fset->fset_permit_count != 0) {
  984.                 /* is there are previous cookie? */
  985.                 if (fset->fset_permit_cookie == 0) {
  986.                         CDEBUG(D_CACHE, "presto installing cookie 0x%x, %sn",
  987.                                *cookie, path);
  988.                         fset->fset_permit_cookie = *cookie;
  989.                 } else {
  990.                         *cookie = fset->fset_permit_cookie;
  991.                         CDEBUG(D_CACHE, "presto has cookie 0x%x, %sn",
  992.                                *cookie, path);
  993.                 }
  994.                 result = presto_mark_fset(path, 0, FSET_PERMIT_WAITING, NULL);
  995.         } else {
  996.                 *cookie = 0;
  997.                 CDEBUG(D_CACHE, "presto releasing permit %sn", path);
  998.                 result = presto_mark_fset(path, ~FSET_HASPERMIT, 0, NULL);
  999.         }
  1000. unlock_kernel();
  1001.         return result;
  1002. }
  1003. inline int presto_is_read_only(struct presto_file_set * fset)
  1004. {
  1005.         int minor, mask;
  1006.         struct presto_cache *cache = fset->fset_cache;
  1007.         minor= cache->cache_psdev->uc_minor;
  1008.         mask= (ISLENTO(minor)? FSET_LENTO_RO : FSET_CLIENT_RO);
  1009.         if ( fset->fset_flags & mask )
  1010.                 return 1;
  1011.         mask= (ISLENTO(minor)? CACHE_LENTO_RO : CACHE_CLIENT_RO);
  1012.         return  ((cache->cache_flags & mask)? 1 : 0);
  1013. }