VirtualBox

Ignore:
Timestamp:
Mar 14, 2019 5:00:37 PM (6 years ago)
Author:
vboxsync
Message:

linux/vboxsf: Implemented inode_operations::atomic_open (introduced in linux 3.6) to more efficiently create new files. There is a 30-40% speedup compared to the previous lookup+create approach. bugref:9172

Location:
trunk/src/VBox/Additions/linux/sharedfolders
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/linux/sharedfolders/dirops.c

    r77561 r77704  
    562562};
    563563
    564 /* iops */
    565 
    566 /**
    567  * Worker for vbsf_inode_lookup() and vbsf_inode_instantiate().
     564
     565
     566/*********************************************************************************************************************************
     567*   Directory Inode Operations                                                                                                   *
     568*********************************************************************************************************************************/
     569
     570/**
     571 * Worker for vbsf_inode_lookup(), vbsf_create_worker() and
     572 * vbsf_inode_instantiate().
    568573 */
    569574static struct inode *vbsf_create_inode(struct inode *parent, struct dentry *dentry, PSHFLSTRING path,
     
    614619    return NULL;
    615620}
     621
     622
     623/** Helper for vbsf_create_worker() and vbsf_inode_lookup() that wraps
     624 *  d_add() and setting d_op. */
     625DECLINLINE(void) vbsf_d_add_inode(struct dentry *dentry, struct inode *pNewInode)
     626{
     627#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
     628    Assert(dentry->d_op == &vbsf_dentry_ops); /* (taken from the superblock) */
     629#else
     630    dentry->d_op = &vbsf_dentry_ops;
     631#endif
     632    d_add(dentry, pNewInode);
     633}
     634
    616635
    617636/**
     
    702721            if (dret == dentry) {
    703722                vbsf_dentry_set_update_jiffies(dentry, jiffies);
    704 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
    705                 Assert(dentry->d_op == &vbsf_dentry_ops); /* (taken from the superblock) */
    706 #else
    707                 dentry->d_op = &vbsf_dentry_ops;
    708 #endif
    709                 d_add(dentry, pInode);
     723                vbsf_d_add_inode(dentry, pInode);
    710724                dret = NULL;
    711725            }
     
    719733}
    720734
     735
    721736/**
    722737 * This should allocate memory for vbsf_inode_info, compute a unique inode
     
    745760}
    746761
     762
    747763/**
    748764 * Create a new regular file / directory.
     
    751767 * @param dentry        directory cache entry
    752768 * @param mode          file mode
    753  * @param fDirectory    true if directory, false otherwise
     769 * @param fCreateFlags  SHFL_CF_XXX.
    754770 * @returns 0 on success, Linux error code otherwise
    755771 */
    756 static int vbsf_create_worker(struct inode *parent, struct dentry *dentry, umode_t mode, int fDirectory)
    757 {
    758     int rc, err;
     772static int vbsf_create_worker(struct inode *parent, struct dentry *dentry, umode_t mode, uint32_t fCreateFlags,
     773                              bool fStashHandle, bool fDoLookup, SHFLHANDLE *phHostFile, bool *pfCreated)
     774
     775{
     776#ifdef SFLOG_ENABLED
     777    const char * const      pszPrefix   = S_ISDIR(mode) ? "vbsf_create_worker/dir:" : "vbsf_create_worker/file:";
     778#endif
    759779    struct vbsf_inode_info *sf_parent_i = VBSF_GET_INODE_INFO(parent);
    760     struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(parent->i_sb);
    761     SHFLSTRING *path;
    762     union CreateAuxReq
    763     {
    764         VBOXSFCREATEREQ Create;
    765         VBOXSFCLOSEREQ  Close;
    766     } *pReq;
    767 
    768     TRACE();
    769     BUG_ON(!sf_parent_i);
    770     BUG_ON(!sf_g);
    771 
    772     err = vbsf_path_from_dentry(__func__, sf_g, sf_parent_i, dentry, &path);
    773     if (err)
    774         goto fail0;
    775 
    776     /** @todo combine with vbsf_path_from_dentry? */
    777     pReq = (union CreateAuxReq *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + path->u16Size);
    778     if (pReq) {
    779         memcpy(&pReq->Create.StrPath, path, SHFLSTRING_HEADER_SIZE + path->u16Size);
     780    struct vbsf_super_info *sf_g        = VBSF_GET_SUPER_INFO(parent->i_sb);
     781    PSHFLSTRING             path;
     782    int                     rc;
     783
     784    AssertReturn(sf_parent_i, -EINVAL);
     785    AssertReturn(sf_g, -EINVAL);
     786
     787    /*
     788     * Build a path.  We'll donate this to the inode on success.
     789     */
     790    rc = vbsf_path_from_dentry(__func__, sf_g, sf_parent_i, dentry, &path);
     791    if (rc == 0) {
     792        /*
     793         * Allocate, initialize and issue the SHFL_CREATE request.
     794         */
     795        /** @todo combine with vbsf_path_from_dentry? */
     796        union CreateAuxReq
     797        {
     798            VBOXSFCREATEREQ Create;
     799            VBOXSFCLOSEREQ  Close;
     800        } *pReq = (union CreateAuxReq *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + path->u16Size);
     801        if (pReq) {
     802            memcpy(&pReq->Create.StrPath, path, SHFLSTRING_HEADER_SIZE + path->u16Size);
     803
     804            RT_ZERO(pReq->Create.CreateParms);
     805            pReq->Create.CreateParms.Handle                  = SHFL_HANDLE_NIL;
     806            pReq->Create.CreateParms.CreateFlags             = fCreateFlags;
     807            pReq->Create.CreateParms.Info.Attr.fMode         = (S_ISDIR(mode) ? RTFS_TYPE_DIRECTORY : RTFS_TYPE_FILE)
     808                                                             | sf_access_permissions_to_vbox(mode);
     809            pReq->Create.CreateParms.Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING;
     810
     811            SFLOGFLOW(("%s calling VbglR0SfHostReqCreate(%s, %#x)\n", pszPrefix, path->String.ach, pReq->Create.CreateParms.CreateFlags));
     812            rc = VbglR0SfHostReqCreate(sf_g->map.root, &pReq->Create);
     813            if (RT_SUCCESS(rc)) {
     814                SFLOGFLOW(("%s VbglR0SfHostReqCreate returned %Rrc Result=%d Handle=%#llx\n",
     815                           pszPrefix, rc, pReq->Create.CreateParms.Result, pReq->Create.CreateParms.Handle));
     816
     817                /*
     818                 * Work the dentry cache and inode restatting.
     819                 */
     820                if (   pReq->Create.CreateParms.Result == SHFL_FILE_CREATED
     821                    || pReq->Create.CreateParms.Result == SHFL_FILE_REPLACED) {
     822                    vbsf_dentry_chain_increase_parent_ttl(dentry);
     823                    sf_parent_i->force_restat = 1;
     824                } else if (   pReq->Create.CreateParms.Result == SHFL_FILE_EXISTS
     825                           || pReq->Create.CreateParms.Result == SHFL_FILE_NOT_FOUND)
     826                    vbsf_dentry_chain_increase_parent_ttl(dentry);
     827
     828                /*
     829                 * If we got a handle back, we're good.  Create an inode for it and return.
     830                 */
     831                if (pReq->Create.CreateParms.Handle != SHFL_HANDLE_NIL) {
     832                    struct inode *pNewInode = vbsf_create_inode(parent, dentry, path, &pReq->Create.CreateParms.Info, sf_g,
     833                                                                !fDoLookup /*fInstantiate*/);
     834                    if (pNewInode) {
     835                        struct vbsf_inode_info *sf_new_i = VBSF_GET_INODE_INFO(pNewInode);
     836                        if (phHostFile) {
     837                            *phHostFile = pReq->Create.CreateParms.Handle;
     838                            pReq->Create.CreateParms.Handle = SHFL_HANDLE_NIL;
     839                        } else if (fStashHandle) {
     840                            sf_new_i->handle = pReq->Create.CreateParms.Handle;
     841                            pReq->Create.CreateParms.Handle = SHFL_HANDLE_NIL;
     842                        }
     843                        if (fDoLookup)
     844                            vbsf_d_add_inode(dentry, pNewInode);
     845                        path = NULL;
     846                    } else {
     847                        SFLOGFLOW(("%s vbsf_create_inode failed: -ENOMEM (path %s)\n", pszPrefix, rc, path->String.ach));
     848                        rc = -ENOMEM;
     849                    }
     850                } else if (pReq->Create.CreateParms.Result == SHFL_FILE_EXISTS) {
     851                    /*
     852                     * For atomic_open (at least), we should create an inode and
     853                     * convert the dentry from a negative to a positive one.
     854                     */
     855                    SFLOGFLOW(("%s SHFL_FILE_EXISTS for %s\n", pszPrefix, sf_parent_i->path->String.ach));
     856                    if (fDoLookup) {
     857                        struct inode *pNewInode = vbsf_create_inode(parent, dentry, path, &pReq->Create.CreateParms.Info,
     858                                                                    sf_g, false /*fInstantiate*/);
     859                        if (pNewInode)
     860                            vbsf_d_add_inode(dentry, pNewInode);
     861                        path = NULL;
     862                    }
     863                    rc = -EEXIST;
     864                } else if (pReq->Create.CreateParms.Result == SHFL_FILE_NOT_FOUND) {
     865                    SFLOGFLOW(("%s SHFL_FILE_NOT_FOUND for %s\n", pszPrefix, sf_parent_i->path->String.ach));
     866                    rc = -ENOENT;
     867                } else if (pReq->Create.CreateParms.Result == SHFL_PATH_NOT_FOUND) {
     868                    SFLOGFLOW(("%s SHFL_PATH_NOT_FOUND for %s\n", pszPrefix, sf_parent_i->path->String.ach));
     869                    rc = -ENOENT;
     870                } else {
     871                    AssertMsgFailed(("result=%d creating '%s'\n", pReq->Create.CreateParms.Result, sf_parent_i->path->String.ach));
     872                    rc = -EPERM;
     873                }
     874            } else {
     875                int const vrc = rc;
     876                rc = -RTErrConvertToErrno(vrc);
     877                SFLOGFLOW(("%s SHFL_FN_CREATE(%s) failed vrc=%Rrc rc=%d\n", pszPrefix, path->String.ach, vrc, rc));
     878            }
     879
     880            /* Cleanups. */
     881            if (pReq->Create.CreateParms.Handle != SHFL_HANDLE_NIL) {
     882                AssertCompile(RTASSERT_OFFSET_OF(VBOXSFCREATEREQ, CreateParms.Handle) > sizeof(VBOXSFCLOSEREQ)); /* no aliasing issues */
     883                int rc2 = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, pReq->Create.CreateParms.Handle);
     884                if (RT_FAILURE(rc2))
     885                    SFLOGFLOW(("%s VbglR0SfHostReqCloseSimple failed rc=%Rrc\n", pszPrefix, rc2));
     886            }
     887            VbglR0PhysHeapFree(pReq);
     888        } else
     889            rc = -ENOMEM;
     890        if (path)
     891            kfree(path);
     892    }
     893    return rc;
     894}
     895
     896
     897#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
     898/**
     899 * More atomic way of handling creation.
     900 *
     901 * Older kernels would first to a lookup that created the file, followed by
     902 * an open call.  We've got this horrid vbsf_inode_info::handle member because
     903 * of that approach.  The call combines the lookup and open.
     904 */
     905static int vbsf_inode_atomic_open(struct inode *pDirInode, struct dentry *dentry, struct file *file,  unsigned fOpen, umode_t fMode)
     906{
     907    SFLOGFLOW(("vbsf_inode_atomic_open: pDirInode=%p dentry=%p file=%p fOpen=%#x, fMode=%#x\n", pDirInode, dentry, file, fOpen, fMode));
     908    int rc;
     909
     910    /* Code assumes negative dentry. */
     911    Assert(dentry->d_inode == NULL);
     912
     913    /** @todo see if we can do this for non-create calls too, as it may save us a
     914     *        host call to revalidate the dentry. (Can't see anyone else doing
     915     *        this, so playing it safe for now.) */
     916    if (fOpen & O_CREAT) {
     917        /*
     918         * Prepare our file info structure.
     919         */
     920        struct vbsf_reg_info *sf_r = kmalloc(sizeof(*sf_r), GFP_KERNEL);
     921        if (sf_r) {
     922            bool     fCreated = false;
     923            uint32_t fCreateFlags;
     924
     925            RTListInit(&sf_r->Handle.Entry);
     926            sf_r->Handle.cRefs  = 1;
     927            sf_r->Handle.fFlags = !(fOpen & O_DIRECTORY)
     928                                 ? VBSF_HANDLE_F_FILE | VBSF_HANDLE_F_MAGIC
     929                                 : VBSF_HANDLE_F_DIR  | VBSF_HANDLE_F_MAGIC;
     930            sf_r->Handle.hHost  = SHFL_HANDLE_NIL;
     931
     932            /*
     933             * Try create it.
     934             */
     935            /* vbsf_create_worker uses the type from fMode, so match it up to O_DIRECTORY. */
     936            AssertMsg(!(fMode & S_IFMT) || (fMode & S_IFMT) == (fOpen & O_DIRECTORY ? S_IFDIR : S_IFREG), ("0%o\n", fMode));
     937            if (!(fOpen & O_DIRECTORY))
     938                fMode = (fMode & ~S_IFMT) | S_IFREG;
     939            else
     940                fMode = (fMode & ~S_IFMT) | S_IFDIR;
     941
     942            fCreateFlags = vbsf_linux_oflags_to_vbox(fOpen, &sf_r->Handle.fFlags, __FUNCTION__);
     943
     944            rc = vbsf_create_worker(pDirInode, dentry, fMode, fCreateFlags, false /*fStashHandle*/, true /*fDoLookup*/,
     945                                    &sf_r->Handle.hHost, &fCreated);
     946            if (rc == 0) {
     947                struct inode           *inode = dentry->d_inode;
     948                struct vbsf_inode_info *sf_i  = VBSF_GET_INODE_INFO(inode);
     949
     950                /*
     951                 * Set FMODE_CREATED according to the action taken by SHFL_CREATE
     952                 * and call finish_open() to do the remaining open() work.
     953                 */
     954                if (fCreated)
     955                    file->f_mode |= FMODE_CREATED;
     956                rc = finish_open(file, dentry, generic_file_open);
     957                if (rc == 0) {
     958                    /*
     959                     * Now that the file is fully opened, associate sf_r with it
     960                     * and link the handle to the inode.
     961                     */
     962                    vbsf_handle_append(sf_i, &sf_r->Handle);
     963                    file->private_data = sf_r;
     964                    SFLOGFLOW(("vbsf_inode_atomic_open: create succeeded; hHost=%#llx path='%s'\n",
     965                               rc, sf_r->Handle.hHost, sf_i->path->String.ach));
     966                    sf_r = NULL; /* don't free it */
     967                } else {
     968                    struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(pDirInode->i_sb);
     969                    SFLOGFLOW(("vbsf_inode_atomic_open: finish_open failed: %d (path='%s'\n", rc, sf_i->path->String.ach));
     970                    VbglR0SfHostReqCloseSimple(sf_g->map.root, sf_r->Handle.hHost);
     971                    sf_r->Handle.hHost = SHFL_HANDLE_NIL;
     972                }
     973            } else
     974                SFLOGFLOW(("vbsf_inode_atomic_open: vbsf_create_worker failed: %d\n", rc));
     975            if (sf_r)
     976                kfree(sf_r);
     977        } else {
     978            LogRelMaxFunc(64, ("could not allocate reg info\n"));
     979            rc = -ENOMEM;
     980        }
     981    }
     982    /*
     983     * Not creating anything.
     984     * Do we need to do a lookup or should we just fail?
     985     */
     986    else if (d_in_lookup(dentry)) {
     987        struct dentry *pResult = vbsf_inode_lookup(pDirInode, dentry, 0 /*fFlags*/);
     988        if (!IS_ERR(pResult))
     989            rc = finish_no_open(file, pResult);
     990        else
     991            rc = PTR_ERR(pResult);
     992        SFLOGFLOW(("vbsf_inode_atomic_open: open -> %d (%p)\n", rc, pResult));
    780993    } else {
    781         err = -ENOMEM;
    782         goto fail1;
    783     }
    784 
    785     RT_ZERO(pReq->Create.CreateParms);
    786     pReq->Create.CreateParms.Handle                  = SHFL_HANDLE_NIL;
    787     pReq->Create.CreateParms.CreateFlags             = SHFL_CF_ACT_CREATE_IF_NEW
    788                                                      | SHFL_CF_ACT_FAIL_IF_EXISTS
    789                                                      | SHFL_CF_ACCESS_READWRITE
    790                                                      | (fDirectory ? SHFL_CF_DIRECTORY : 0);
    791     pReq->Create.CreateParms.Info.Attr.fMode         = (fDirectory ? RTFS_TYPE_DIRECTORY : RTFS_TYPE_FILE)
    792                                                      | sf_access_permissions_to_vbox(mode);
    793     pReq->Create.CreateParms.Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING;
    794 
    795     LogFunc(("calling VbglR0SfHostReqCreate, folder %s, flags %#x\n", path->String.ach, pReq->Create.CreateParms.CreateFlags));
    796     rc = VbglR0SfHostReqCreate(sf_g->map.root, &pReq->Create);
    797     if (RT_FAILURE(rc)) {
    798         err = -RTErrConvertToErrno(rc);
    799         LogFunc(("(%d): SHFL_FN_CREATE(%s) failed rc=%Rrc err=%d\n", fDirectory, sf_parent_i->path->String.utf8, rc, err));
    800         goto fail2;
    801     }
    802 
    803     if (pReq->Create.CreateParms.Result != SHFL_FILE_CREATED) {
    804         err = -EPERM;
    805         LogFunc(("(%d): could not create file %s result=%d\n",
    806              fDirectory, sf_parent_i->path->String.utf8, pReq->Create.CreateParms.Result));
    807         goto fail2;
    808     }
    809 
    810     vbsf_dentry_chain_increase_parent_ttl(dentry);
    811 
    812     err = vbsf_inode_instantiate(parent, dentry, path, &pReq->Create.CreateParms.Info,
    813                                  fDirectory ? SHFL_HANDLE_NIL : pReq->Create.CreateParms.Handle);
    814     if (err) {
    815         LogFunc(("(%d): could not instantiate dentry for %s err=%d\n", fDirectory, path->String.utf8, err));
    816         goto fail3;
    817     }
    818 
    819     /*
    820      * Don't close this handle right now. We assume that the same file is
    821      * opened with vbsf_reg_open() and later closed with sf_reg_close(). Save
    822      * the handle in between. Does not apply to directories. True?
    823      */
    824     if (fDirectory) {
    825         AssertCompile(RTASSERT_OFFSET_OF(VBOXSFCREATEREQ, CreateParms.Handle) > sizeof(VBOXSFCLOSEREQ)); /* no aliasing issues */
    826         rc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, pReq->Create.CreateParms.Handle);
    827         if (RT_FAILURE(rc))
    828             LogFunc(("(%d): VbglR0SfHostReqClose failed rc=%Rrc\n", fDirectory, rc));
    829     }
    830 
    831     sf_parent_i->force_restat = 1;
    832     VbglR0PhysHeapFree(pReq);
    833     return 0;
    834 
    835  fail3:
    836     rc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, pReq->Create.CreateParms.Handle);
    837     if (RT_FAILURE(rc))
    838         LogFunc(("(%d): VbglR0SfHostReqCloseSimple failed rc=%Rrc\n", fDirectory, rc));
    839  fail2:
    840     VbglR0PhysHeapFree(pReq);
    841  fail1:
    842     kfree(path);
    843 
    844  fail0:
    845     return err;
    846 }
     994        SFLOGFLOW(("vbsf_inode_atomic_open: open -> -ENOENT\n"));
     995        rc = -ENOENT;
     996    }
     997    return rc;
     998}
     999#endif /* 3.6.0 */
     1000
    8471001
    8481002/**
     
    8691023 *        changed (investigate)... */
    8701024    TRACE();
    871     return vbsf_create_worker(parent, dentry, mode, 0 /*fDirectory*/);
     1025    AssertMsg(!(mode & S_IFMT) || (mode & S_IFMT) == S_IFREG, ("0%o\n", mode));
     1026    return vbsf_create_worker(parent, dentry, (mode & ~S_IFMT) | S_IFREG,
     1027                                SHFL_CF_ACT_CREATE_IF_NEW
     1028                              | SHFL_CF_ACT_FAIL_IF_EXISTS
     1029                              | SHFL_CF_ACCESS_READWRITE,
     1030                              true /*fStashHandle*/, false /*fDoLookup*/, NULL /*phHandle*/, NULL /*fCreated*/);
    8721031}
    8731032
     
    8871046{
    8881047    TRACE();
    889     return vbsf_create_worker(parent, dentry, mode, 1 /*fDirectory*/);
     1048    AssertMsg(!(mode & S_IFMT) || (mode & S_IFMT) == S_IFDIR, ("0%o\n", mode));
     1049    return vbsf_create_worker(parent, dentry, (mode & ~S_IFMT) | S_IFDIR,
     1050                                SHFL_CF_ACT_CREATE_IF_NEW
     1051                              | SHFL_CF_ACT_FAIL_IF_EXISTS
     1052                              | SHFL_CF_ACCESS_READWRITE
     1053                              | SHFL_CF_DIRECTORY,
     1054                              false /*fStashHandle*/, false /*fDoLookup*/, NULL /*phHandle*/, NULL /*fCreated*/);
    8901055}
    8911056
     
    9301095            } else if (rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND) {
    9311096                LogFunc(("(%d): VbglR0SfRemove(%s) failed rc=%Rrc; calling d_drop on %p\n",
    932                          fDirectory, path->String.utf8, rc, dentry));
     1097                         fDirectory, path->String.ach, rc, dentry));
    9331098                d_drop(dentry);
    9341099            } else {
    935                 LogFunc(("(%d): VbglR0SfRemove(%s) failed rc=%Rrc\n", fDirectory, path->String.utf8, rc));
     1100                LogFunc(("(%d): VbglR0SfRemove(%s) failed rc=%Rrc\n", fDirectory, path->String.ach, rc));
    9361101                err = -RTErrConvertToErrno(rc);
    9371102            }
     
    11101275struct inode_operations vbsf_dir_iops = {
    11111276    .lookup = vbsf_inode_lookup,
     1277#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
     1278    .atomic_open = vbsf_inode_atomic_open,
     1279#endif
    11121280    .create = vbsf_inode_create,
    11131281    .mkdir = vbsf_inode_mkdir,
  • trunk/src/VBox/Additions/linux/sharedfolders/regops.c

    r77631 r77704  
    18741874
    18751875/**
     1876 * Used by vbsf_reg_open() and vbsf_inode_atomic_open() to
     1877 *
     1878 * @returns shared folders create flags.
     1879 * @param   fLnxOpen    The linux O_XXX flags to convert.
     1880 * @param   pfHandle    Pointer to vbsf_handle::fFlags.
     1881 * @param   pszCaller   Caller, for logging purposes.
     1882 */
     1883uint32_t vbsf_linux_oflags_to_vbox(unsigned fLnxOpen, uint32_t *pfHandle, const char *pszCaller)
     1884{
     1885    uint32_t fVBoxFlags = SHFL_CF_ACCESS_DENYNONE;
     1886
     1887    /*
     1888     * Disposition.
     1889     */
     1890    if (fLnxOpen & O_CREAT) {
     1891        Log(("%s: O_CREAT set\n", pszCaller));
     1892        fVBoxFlags |= SHFL_CF_ACT_CREATE_IF_NEW;
     1893        if (fLnxOpen & O_EXCL) {
     1894            Log(("%s: O_EXCL set\n", pszCaller));
     1895            fVBoxFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS;
     1896        } else if (fLnxOpen & O_TRUNC) {
     1897            Log(("%s: O_TRUNC set\n", pszCaller));
     1898            fVBoxFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
     1899        } else
     1900            fVBoxFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS;
     1901    } else {
     1902        fVBoxFlags |= SHFL_CF_ACT_FAIL_IF_NEW;
     1903        if (fLnxOpen & O_TRUNC) {
     1904            Log(("%s: O_TRUNC set\n", pszCaller));
     1905            fVBoxFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
     1906        }
     1907    }
     1908
     1909    /*
     1910     * Access.
     1911     */
     1912    switch (fLnxOpen & O_ACCMODE) {
     1913        case O_RDONLY:
     1914            fVBoxFlags |= SHFL_CF_ACCESS_READ;
     1915            *pfHandle  |= VBSF_HANDLE_F_READ;
     1916            break;
     1917
     1918        case O_WRONLY:
     1919            fVBoxFlags |= SHFL_CF_ACCESS_WRITE;
     1920            *pfHandle  |= VBSF_HANDLE_F_WRITE;
     1921            break;
     1922
     1923        case O_RDWR:
     1924            fVBoxFlags |= SHFL_CF_ACCESS_READWRITE;
     1925            *pfHandle  |= VBSF_HANDLE_F_READ | VBSF_HANDLE_F_WRITE;
     1926            break;
     1927
     1928        default:
     1929            BUG();
     1930    }
     1931
     1932    if (fLnxOpen & O_APPEND) {
     1933        Log(("%s: O_APPEND set\n", pszCaller));
     1934        fVBoxFlags |= SHFL_CF_ACCESS_APPEND;
     1935        *pfHandle  |= VBSF_HANDLE_F_APPEND;
     1936    }
     1937
     1938    /*
     1939     * Only directories?
     1940     */
     1941    if (fLnxOpen & O_DIRECTORY) {
     1942        Log(("%s: O_DIRECTORY set\n", pszCaller));
     1943        fVBoxFlags |= SHFL_CF_DIRECTORY;
     1944    }
     1945
     1946    return fVBoxFlags;
     1947}
     1948
     1949
     1950/**
    18761951 * Open a regular file.
    18771952 *
     
    19392014     * to make the shared folders host service use our fMode parameter */
    19402015
    1941     if (file->f_flags & O_CREAT) {
    1942         LogFunc(("O_CREAT set\n"));
    1943         pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_CREATE_IF_NEW;
    1944         /* We ignore O_EXCL, as the Linux kernel seems to call create
    1945            beforehand itself, so O_EXCL should always fail. */
    1946         if (file->f_flags & O_TRUNC) {
    1947             LogFunc(("O_TRUNC set\n"));
    1948             pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
    1949         } else
    1950             pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS;
    1951     } else {
    1952         pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW;
    1953         if (file->f_flags & O_TRUNC) {
    1954             LogFunc(("O_TRUNC set\n"));
    1955             pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
    1956         }
    1957     }
    1958 
    1959     switch (file->f_flags & O_ACCMODE) {
    1960         case O_RDONLY:
    1961             pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_READ;
    1962             sf_r->Handle.fFlags |= VBSF_HANDLE_F_READ;
    1963             break;
    1964 
    1965         case O_WRONLY:
    1966             pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_WRITE;
    1967             sf_r->Handle.fFlags |= VBSF_HANDLE_F_WRITE;
    1968             break;
    1969 
    1970         case O_RDWR:
    1971             pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_READWRITE;
    1972             sf_r->Handle.fFlags |= VBSF_HANDLE_F_READ | VBSF_HANDLE_F_WRITE;
    1973             break;
    1974 
    1975         default:
    1976             BUG();
    1977     }
    1978 
    1979     if (file->f_flags & O_APPEND) {
    1980         LogFunc(("O_APPEND set\n"));
    1981         pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_APPEND;
    1982         sf_r->Handle.fFlags |= VBSF_HANDLE_F_APPEND;
    1983     }
    1984 
     2016    /* We ignore O_EXCL, as the Linux kernel seems to call create
     2017       beforehand itself, so O_EXCL should always fail. */
     2018    pReq->CreateParms.CreateFlags = vbsf_linux_oflags_to_vbox(file->f_flags & ~O_EXCL, &sf_r->Handle.fFlags, __FUNCTION__);
    19852019    pReq->CreateParms.Info.Attr.fMode = inode->i_mode;
    19862020    LogFunc(("vbsf_reg_open: calling VbglR0SfHostReqCreate, file %s, flags=%#x, %#x\n",
     
    20362070static int vbsf_reg_release(struct inode *inode, struct file *file)
    20372071{
    2038     struct vbsf_reg_info *sf_r;
    2039     struct vbsf_super_info *sf_g;
    20402072    struct vbsf_inode_info *sf_i = VBSF_GET_INODE_INFO(inode);
     2073    struct vbsf_reg_info   *sf_r = file->private_data;
    20412074
    20422075    SFLOGFLOW(("vbsf_reg_release: inode=%p file=%p\n", inode, file));
    2043     sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
    2044     sf_r = file->private_data;
    2045 
    2046     BUG_ON(!sf_g);
    2047     BUG_ON(!sf_r);
     2076    if (sf_r) {
     2077        struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
     2078        Assert(sf_g);
    20482079
    20492080#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
    2050     /* See the smbfs source (file.c). mmap in particular can cause data to be
    2051      * written to the file after it is closed, which we can't cope with.  We
    2052      * copy and paste the body of filemap_write_and_wait() here as it was not
    2053      * defined before 2.6.6 and not exported until quite a bit later. */
    2054     /* filemap_write_and_wait(inode->i_mapping); */
    2055     if (inode->i_mapping->nrpages
    2056         && filemap_fdatawrite(inode->i_mapping) != -EIO)
    2057         filemap_fdatawait(inode->i_mapping);
     2081        /* See the smbfs source (file.c). mmap in particular can cause data to be
     2082         * written to the file after it is closed, which we can't cope with.  We
     2083         * copy and paste the body of filemap_write_and_wait() here as it was not
     2084         * defined before 2.6.6 and not exported until quite a bit later. */
     2085        /* filemap_write_and_wait(inode->i_mapping); */
     2086        if (inode->i_mapping->nrpages
     2087            && filemap_fdatawrite(inode->i_mapping) != -EIO)
     2088            filemap_fdatawait(inode->i_mapping);
    20582089#endif
    20592090
    2060     /* Release sf_r, closing the handle if we're the last user. */
    2061     file->private_data = NULL;
    2062     vbsf_handle_release(&sf_r->Handle, sf_g, "vbsf_reg_release");
    2063 
    2064     sf_i->handle = SHFL_HANDLE_NIL;
     2091        /* Release sf_r, closing the handle if we're the last user. */
     2092        file->private_data = NULL;
     2093        vbsf_handle_release(&sf_r->Handle, sf_g, "vbsf_reg_release");
     2094
     2095        sf_i->handle = SHFL_HANDLE_NIL;
     2096    }
    20652097    return 0;
    20662098}
  • trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.h

    r77631 r77704  
    286286};
    287287
     288uint32_t vbsf_linux_oflags_to_vbox(unsigned fLnxOpen, uint32_t *pfHandle, const char *pszCaller);
     289
    288290
    289291/**
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette