VirtualBox

Changeset 77526 in vbox


Ignore:
Timestamp:
Mar 1, 2019 12:15:29 PM (6 years ago)
Author:
vboxsync
Message:

linux/vboxsf: We don't use tabs and our indent size is 4 not 8. Makes this a heck lot easier to maintain. bugref:9172

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

Legend:

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

    r77525 r77526  
    4040 */
    4141static int sf_dir_open_worker(struct vbsf_super_info *sf_g, struct sf_dir_info *sf_d,
    42                               struct sf_inode_info *sf_i, const char *pszCaller)
     42                              struct sf_inode_info *sf_i, const char *pszCaller)
    4343{
    4444    int rc;
     
    4646    union SfDirOpenCloseReq
    4747    {
    48         VBOXSFCREATEREQ Create;
    49         VBOXSFCLOSEREQ  Close;
     48    VBOXSFCREATEREQ Create;
     49    VBOXSFCLOSEREQ  Close;
    5050    } *pReq;
    5151    SHFLCREATEPARMS *pCreateParms;
    5252
    5353    pReq = (union SfDirOpenCloseReq *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String)
    54                                                           + sf_i->path->u16Size);
     54                              + sf_i->path->u16Size);
    5555    if (pReq) {
    56             memcpy(&pReq->Create.StrPath, sf_i->path, SHFLSTRING_HEADER_SIZE + sf_i->path->u16Size);
    57             pCreateParms = &pReq->Create.CreateParms;
     56        memcpy(&pReq->Create.StrPath, sf_i->path, SHFLSTRING_HEADER_SIZE + sf_i->path->u16Size);
     57        pCreateParms = &pReq->Create.CreateParms;
    5858    } else {
    59             LogRelMaxFunc(64, ("failed to allocate %zu bytes for '%s' [caller: %s]\n",
    60                                RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + sf_i->path->u16Size,
    61                                sf_i->path->String.ach, pszCaller));
    62             return -ENOMEM;
     59        LogRelMaxFunc(64, ("failed to allocate %zu bytes for '%s' [caller: %s]\n",
     60                           RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + sf_i->path->u16Size,
     61                           sf_i->path->String.ach, pszCaller));
     62        return -ENOMEM;
    6363    }
    6464
     
    6666    pCreateParms->Handle = SHFL_HANDLE_NIL;
    6767    pCreateParms->CreateFlags = SHFL_CF_DIRECTORY
    68                               | SHFL_CF_ACT_OPEN_IF_EXISTS
    69                               | SHFL_CF_ACT_FAIL_IF_NEW
    70                               | SHFL_CF_ACCESS_READ;
     68                  | SHFL_CF_ACT_OPEN_IF_EXISTS
     69                  | SHFL_CF_ACT_FAIL_IF_NEW
     70                  | SHFL_CF_ACCESS_READ;
    7171
    7272    LogFunc(("calling VbglR0SfHostReqCreate on folder %s, flags %#x [caller: %s]\n",
    73              sf_i->path->String.utf8, pCreateParms->CreateFlags, pszCaller));
     73             sf_i->path->String.utf8, pCreateParms->CreateFlags, pszCaller));
    7474    rc = VbglR0SfHostReqCreate(sf_g->map.root, &pReq->Create);
    7575    if (RT_SUCCESS(rc)) {
    76             if (pCreateParms->Result == SHFL_FILE_EXISTS) {
    77 
    78                     /** @todo We could refresh the inode information here since SHFL_FN_CREATE
    79                      * returns updated object information. */
    80 
    81                     /** @todo Touch the dentries from here to the mount root since a successful
    82                      * open means that the whole path is valid.  I believe CIFS does this. */
    83 
    84                     /** @todo Reading all entries upon opening the directory doesn't seem like
    85                      * a good idea. */
    86                     sf_dir_info_empty(sf_d);
    87                     err = sf_dir_read_all(sf_g, sf_i, sf_d, pCreateParms->Handle);
    88             } else
    89                     err = -ENOENT;
    90 
    91             AssertCompile(RTASSERT_OFFSET_OF(VBOXSFCREATEREQ, CreateParms.Handle) > sizeof(VBOXSFCLOSEREQ)); /* no aliasing issues */
    92             if (pCreateParms->Handle != SHFL_HANDLE_NIL)
    93             {
    94                 rc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, pCreateParms->Handle);
    95                 if (RT_FAILURE(rc))
    96                         LogFunc(("VbglR0SfHostReqCloseSimple(%s) after err=%d failed rc=%Rrc caller=%s\n",
    97                                 sf_i->path->String.utf8, err, rc, pszCaller));
    98             }
     76        if (pCreateParms->Result == SHFL_FILE_EXISTS) {
     77
     78            /** @todo We could refresh the inode information here since SHFL_FN_CREATE
     79             * returns updated object information. */
     80
     81            /** @todo Touch the dentries from here to the mount root since a successful
     82             * open means that the whole path is valid.  I believe CIFS does this. */
     83
     84            /** @todo Reading all entries upon opening the directory doesn't seem like
     85             * a good idea. */
     86            sf_dir_info_empty(sf_d);
     87            err = sf_dir_read_all(sf_g, sf_i, sf_d, pCreateParms->Handle);
     88        } else
     89            err = -ENOENT;
     90
     91        AssertCompile(RTASSERT_OFFSET_OF(VBOXSFCREATEREQ, CreateParms.Handle) > sizeof(VBOXSFCLOSEREQ)); /* no aliasing issues */
     92        if (pCreateParms->Handle != SHFL_HANDLE_NIL)
     93        {
     94        rc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, pCreateParms->Handle);
     95        if (RT_FAILURE(rc))
     96            LogFunc(("VbglR0SfHostReqCloseSimple(%s) after err=%d failed rc=%Rrc caller=%s\n",
     97                    sf_i->path->String.utf8, err, rc, pszCaller));
     98        }
    9999    } else
    100             err = -EPERM;
     100        err = -EPERM;
    101101
    102102    VbglR0PhysHeapFree(pReq);
     
    113113static int sf_dir_open(struct inode *inode, struct file *file)
    114114{
    115         struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
    116         struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
    117         struct sf_dir_info *sf_d;
    118         int err;
    119 
    120         TRACE();
    121         BUG_ON(!sf_g);
    122         BUG_ON(!sf_i);
    123 
    124         if (file->private_data) {
    125                 LogFunc(("called on already opened directory '%s'!\n", sf_i->path->String.ach));
    126                 return 0;
    127         }
    128 
    129         sf_d = sf_dir_info_alloc();
    130         if (!sf_d) {
    131                 LogRelFunc(("could not allocate directory info for '%s'\n", sf_i->path->String.ach));
    132                 return -ENOMEM;
    133         }
    134 
    135         err = sf_dir_open_worker(sf_g, sf_d, sf_i, "sf_dir_open");
    136         if (!err)
    137                 file->private_data = sf_d;
    138         else
    139                 sf_dir_info_free(sf_d);
    140 
    141         return err;
     115    struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
     116    struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
     117    struct sf_dir_info *sf_d;
     118    int err;
     119
     120    TRACE();
     121    BUG_ON(!sf_g);
     122    BUG_ON(!sf_i);
     123
     124    if (file->private_data) {
     125        LogFunc(("called on already opened directory '%s'!\n", sf_i->path->String.ach));
     126        return 0;
     127    }
     128
     129    sf_d = sf_dir_info_alloc();
     130    if (!sf_d) {
     131        LogRelFunc(("could not allocate directory info for '%s'\n", sf_i->path->String.ach));
     132        return -ENOMEM;
     133    }
     134
     135    err = sf_dir_open_worker(sf_g, sf_d, sf_i, "sf_dir_open");
     136    if (!err)
     137        file->private_data = sf_d;
     138    else
     139        sf_dir_info_free(sf_d);
     140
     141    return err;
    142142}
    143143
     
    153153static int sf_dir_release(struct inode *inode, struct file *file)
    154154{
    155         TRACE();
    156 
    157         if (file->private_data)
    158                 sf_dir_info_free(file->private_data);
    159 
    160         return 0;
     155    TRACE();
     156
     157    if (file->private_data)
     158        sf_dir_info_free(file->private_data);
     159
     160    return 0;
    161161}
    162162
     
    168168static int sf_get_d_type(RTFMODE fMode)
    169169{
    170         int d_type;
    171         switch (fMode & RTFS_TYPE_MASK) {
    172         case RTFS_TYPE_FIFO:
    173                 d_type = DT_FIFO;
    174                 break;
    175         case RTFS_TYPE_DEV_CHAR:
    176                 d_type = DT_CHR;
    177                 break;
    178         case RTFS_TYPE_DIRECTORY:
    179                 d_type = DT_DIR;
    180                 break;
    181         case RTFS_TYPE_DEV_BLOCK:
    182                 d_type = DT_BLK;
    183                 break;
    184         case RTFS_TYPE_FILE:
    185                 d_type = DT_REG;
    186                 break;
    187         case RTFS_TYPE_SYMLINK:
    188                 d_type = DT_LNK;
    189                 break;
    190         case RTFS_TYPE_SOCKET:
    191                 d_type = DT_SOCK;
    192                 break;
    193         case RTFS_TYPE_WHITEOUT:
    194                 d_type = DT_WHT;
    195                 break;
    196         default:
    197                 d_type = DT_UNKNOWN;
    198                 break;
    199         }
    200         return d_type;
     170    int d_type;
     171    switch (fMode & RTFS_TYPE_MASK) {
     172    case RTFS_TYPE_FIFO:
     173        d_type = DT_FIFO;
     174        break;
     175    case RTFS_TYPE_DEV_CHAR:
     176        d_type = DT_CHR;
     177        break;
     178    case RTFS_TYPE_DIRECTORY:
     179        d_type = DT_DIR;
     180        break;
     181    case RTFS_TYPE_DEV_BLOCK:
     182        d_type = DT_BLK;
     183        break;
     184    case RTFS_TYPE_FILE:
     185        d_type = DT_REG;
     186        break;
     187    case RTFS_TYPE_SYMLINK:
     188        d_type = DT_LNK;
     189        break;
     190    case RTFS_TYPE_SOCKET:
     191        d_type = DT_SOCK;
     192        break;
     193    case RTFS_TYPE_WHITEOUT:
     194        d_type = DT_WHT;
     195        break;
     196    default:
     197        d_type = DT_UNKNOWN;
     198        break;
     199    }
     200    return d_type;
    201201}
    202202
     
    208208static int sf_getdent(struct file *dir, char d_name[NAME_MAX], int *d_type)
    209209{
    210         loff_t cur;
    211         struct vbsf_super_info *sf_g;
    212         struct sf_dir_info *sf_d;
    213         struct sf_inode_info *sf_i;
    214         struct inode *inode;
    215         struct list_head *pos, *list;
    216 
    217         TRACE();
    218 
    219         inode = GET_F_DENTRY(dir)->d_inode;
    220         sf_i = GET_INODE_INFO(inode);
    221         sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
    222         sf_d = dir->private_data;
    223 
    224         BUG_ON(!sf_g);
    225         BUG_ON(!sf_d);
    226         BUG_ON(!sf_i);
    227 
    228         if (sf_i->force_reread) {
    229                 int err = sf_dir_open_worker(sf_g, sf_d, sf_i, "sf_getdent");
    230                 if (!err) {
    231                         sf_i->force_reread = 0;
    232                 } else {
    233                         if (err == -ENOENT) {
    234                                 sf_dir_info_free(sf_d);
    235                                 dir->private_data = NULL;
    236                         }
    237                         return err;
    238                 }
    239         }
    240 
    241         cur = 0;
    242         list = &sf_d->info_list;
    243         list_for_each(pos, list) {
    244                 struct sf_dir_buf *b;
    245                 SHFLDIRINFO *info;
    246                 loff_t i;
    247 
    248                 b = list_entry(pos, struct sf_dir_buf, head);
    249                 if (dir->f_pos >= cur + b->cEntries) {
    250                         cur += b->cEntries;
    251                         continue;
    252                 }
    253 
    254                 for (i = 0, info = b->buf; i < dir->f_pos - cur; ++i) {
    255                         size_t size;
    256 
    257                         size = offsetof(SHFLDIRINFO, name.String)
    258                              + info->name.u16Size;
    259                         info = (SHFLDIRINFO *)((uintptr_t)info + size);
    260                 }
    261 
    262                 *d_type = sf_get_d_type(info->Info.Attr.fMode);
    263 
    264                 return sf_nlscpy(sf_g, d_name, NAME_MAX,
    265                                 info->name.String.utf8, info->name.u16Length);
    266         }
    267 
    268         return 1;
     210    loff_t cur;
     211    struct vbsf_super_info *sf_g;
     212    struct sf_dir_info *sf_d;
     213    struct sf_inode_info *sf_i;
     214    struct inode *inode;
     215    struct list_head *pos, *list;
     216
     217    TRACE();
     218
     219    inode = GET_F_DENTRY(dir)->d_inode;
     220    sf_i = GET_INODE_INFO(inode);
     221    sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
     222    sf_d = dir->private_data;
     223
     224    BUG_ON(!sf_g);
     225    BUG_ON(!sf_d);
     226    BUG_ON(!sf_i);
     227
     228    if (sf_i->force_reread) {
     229        int err = sf_dir_open_worker(sf_g, sf_d, sf_i, "sf_getdent");
     230        if (!err) {
     231            sf_i->force_reread = 0;
     232        } else {
     233            if (err == -ENOENT) {
     234                sf_dir_info_free(sf_d);
     235                dir->private_data = NULL;
     236            }
     237            return err;
     238        }
     239    }
     240
     241    cur = 0;
     242    list = &sf_d->info_list;
     243    list_for_each(pos, list) {
     244        struct sf_dir_buf *b;
     245        SHFLDIRINFO *info;
     246        loff_t i;
     247
     248        b = list_entry(pos, struct sf_dir_buf, head);
     249        if (dir->f_pos >= cur + b->cEntries) {
     250            cur += b->cEntries;
     251            continue;
     252        }
     253
     254        for (i = 0, info = b->buf; i < dir->f_pos - cur; ++i) {
     255            size_t size;
     256
     257            size = offsetof(SHFLDIRINFO, name.String)
     258                 + info->name.u16Size;
     259            info = (SHFLDIRINFO *)((uintptr_t)info + size);
     260        }
     261
     262        *d_type = sf_get_d_type(info->Info.Attr.fMode);
     263
     264        return sf_nlscpy(sf_g, d_name, NAME_MAX,
     265                info->name.String.utf8, info->name.u16Length);
     266    }
     267
     268    return 1;
    269269}
    270270
     
    298298#endif
    299299{
    300         TRACE();
    301         for (;;) {
    302                 int err;
    303                 ino_t fake_ino;
    304                 loff_t sanity;
    305                 char d_name[NAME_MAX];
    306                 int d_type = DT_UNKNOWN;
    307 
    308                 err = sf_getdent(dir, d_name, &d_type);
    309                 switch (err) {
    310                 case 1:
    311                         return 0;
    312 
    313                 case 0:
    314                         break;
    315 
    316                 case -1:
    317                 default:
    318                         /* skip erroneous entry and proceed */
    319                         LogFunc(("sf_getdent error %d\n", err));
    320                         dir->f_pos += 1;
     300    TRACE();
     301    for (;;) {
     302        int err;
     303        ino_t fake_ino;
     304        loff_t sanity;
     305        char d_name[NAME_MAX];
     306        int d_type = DT_UNKNOWN;
     307
     308        err = sf_getdent(dir, d_name, &d_type);
     309        switch (err) {
     310        case 1:
     311            return 0;
     312
     313        case 0:
     314            break;
     315
     316        case -1:
     317        default:
     318            /* skip erroneous entry and proceed */
     319            LogFunc(("sf_getdent error %d\n", err));
     320            dir->f_pos += 1;
    321321#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
    322                         ctx->pos += 1;
    323 #endif
    324                         continue;
    325                 }
    326 
    327                 /* d_name now contains a valid entry name */
     322            ctx->pos += 1;
     323#endif
     324            continue;
     325        }
     326
     327        /* d_name now contains a valid entry name */
    328328
    329329#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
    330                 sanity = ctx->pos + 0xbeef;
     330        sanity = ctx->pos + 0xbeef;
    331331#else
    332                 sanity = dir->f_pos + 0xbeef;
    333 #endif
    334                 fake_ino = sanity;
    335                 if (sanity - fake_ino) {
    336                         LogRelFunc(("can not compute ino\n"));
    337                         return -EINVAL;
    338                 }
     332        sanity = dir->f_pos + 0xbeef;
     333#endif
     334        fake_ino = sanity;
     335        if (sanity - fake_ino) {
     336            LogRelFunc(("can not compute ino\n"));
     337            return -EINVAL;
     338        }
    339339#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
    340                 if (!dir_emit(ctx, d_name, strlen(d_name), fake_ino, d_type)) {
    341                         LogFunc(("dir_emit failed\n"));
    342                         return 0;
    343                 }
     340        if (!dir_emit(ctx, d_name, strlen(d_name), fake_ino, d_type)) {
     341            LogFunc(("dir_emit failed\n"));
     342            return 0;
     343        }
    344344#else
    345                 err = filldir(opaque, d_name, strlen(d_name),
    346                               dir->f_pos, fake_ino, d_type);
    347                 if (err) {
    348                         LogFunc(("filldir returned error %d\n", err));
    349                         /* Rely on the fact that filldir returns error
    350                            only when it runs out of space in opaque */
    351                         return 0;
    352                 }
    353 #endif
    354 
    355                 dir->f_pos += 1;
     345        err = filldir(opaque, d_name, strlen(d_name),
     346                  dir->f_pos, fake_ino, d_type);
     347        if (err) {
     348            LogFunc(("filldir returned error %d\n", err));
     349            /* Rely on the fact that filldir returns error
     350               only when it runs out of space in opaque */
     351            return 0;
     352        }
     353#endif
     354
     355        dir->f_pos += 1;
    356356#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
    357                 ctx->pos += 1;
    358 #endif
    359         }
    360 
    361         BUG();
     357        ctx->pos += 1;
     358#endif
     359    }
     360
     361    BUG();
    362362}
    363363
    364364struct file_operations sf_dir_fops = {
    365         .open = sf_dir_open,
     365    .open = sf_dir_open,
    366366#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
    367         .iterate = sf_dir_iterate,
     367    .iterate = sf_dir_iterate,
    368368#else
    369         .readdir = sf_dir_read,
    370 #endif
    371         .release = sf_dir_release,
    372         .read = generic_read_dir
     369    .readdir = sf_dir_read,
     370#endif
     371    .release = sf_dir_release,
     372    .read = generic_read_dir
    373373#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
    374         , .llseek = generic_file_llseek
     374    , .llseek = generic_file_llseek
    375375#endif
    376376};
     
    382382 */
    383383static struct inode *sf_create_inode(struct inode *parent, struct dentry *dentry, PSHFLSTRING path,
    384                                      PSHFLFSOBJINFO pObjInfo, struct vbsf_super_info *sf_g, bool fInstantiate)
    385 {
    386         /*
    387         * Allocate memory for our additional inode info and create an inode.
    388         */
    389         struct sf_inode_info *sf_new_i = (struct sf_inode_info *)kmalloc(sizeof(*sf_new_i), GFP_KERNEL);
    390         if (sf_new_i) {
    391                 ino_t         iNodeNo = iunique(parent->i_sb, 1);
     384                                     PSHFLFSOBJINFO pObjInfo, struct vbsf_super_info *sf_g, bool fInstantiate)
     385{
     386    /*
     387    * Allocate memory for our additional inode info and create an inode.
     388    */
     389    struct sf_inode_info *sf_new_i = (struct sf_inode_info *)kmalloc(sizeof(*sf_new_i), GFP_KERNEL);
     390    if (sf_new_i) {
     391        ino_t         iNodeNo = iunique(parent->i_sb, 1);
    392392#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
    393                 struct inode *pInode  = iget_locked(parent->i_sb, iNodeNo);
     393        struct inode *pInode  = iget_locked(parent->i_sb, iNodeNo);
    394394#else
    395                 struct inode *pInode  = iget(parent->i_sb, iNodeNo);
    396 #endif
    397                 if (pInode) {
    398                         /*
    399                         * Initialize the two structures.
    400                         */
     395        struct inode *pInode  = iget(parent->i_sb, iNodeNo);
     396#endif
     397        if (pInode) {
     398            /*
     399            * Initialize the two structures.
     400            */
    401401#ifdef VBOX_STRICT
    402                         sf_new_i->u32Magic      = SF_INODE_INFO_MAGIC;
    403 #endif
    404                         sf_new_i->path          = path;
    405                         sf_new_i->force_reread  = 0;
    406                         sf_new_i->force_restat  = 0;
    407                         sf_new_i->ts_up_to_date = jiffies;
    408                         RTListInit(&sf_new_i->HandleList);
    409                         sf_new_i->handle        = SHFL_HANDLE_NIL;
    410 
    411                         SET_INODE_INFO(pInode, sf_new_i);
    412                         sf_init_inode(pInode, sf_new_i, pObjInfo, sf_g);
    413 
    414                         /*
    415                         * Before we unlock the new inode, we may need to call d_instantiate.
    416                         */
    417                         if (fInstantiate)
    418                                 d_instantiate(dentry, pInode);
     402            sf_new_i->u32Magic      = SF_INODE_INFO_MAGIC;
     403#endif
     404            sf_new_i->path          = path;
     405            sf_new_i->force_reread  = 0;
     406            sf_new_i->force_restat  = 0;
     407            sf_new_i->ts_up_to_date = jiffies;
     408            RTListInit(&sf_new_i->HandleList);
     409            sf_new_i->handle        = SHFL_HANDLE_NIL;
     410
     411            SET_INODE_INFO(pInode, sf_new_i);
     412            sf_init_inode(pInode, sf_new_i, pObjInfo, sf_g);
     413
     414            /*
     415            * Before we unlock the new inode, we may need to call d_instantiate.
     416            */
     417            if (fInstantiate)
     418                d_instantiate(dentry, pInode);
    419419#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
    420                         unlock_new_inode(pInode);
    421 #endif
    422                         return pInode;
    423 
    424                 }
    425                 LogFunc(("iget failed\n"));
    426                 kfree(sf_new_i);
    427         } else
    428                 LogRelFunc(("could not allocate memory for new inode info\n"));
    429         return NULL;
     420            unlock_new_inode(pInode);
     421#endif
     422            return pInode;
     423
     424        }
     425        LogFunc(("iget failed\n"));
     426        kfree(sf_new_i);
     427    } else
     428        LogRelFunc(("could not allocate memory for new inode info\n"));
     429    return NULL;
    430430}
    431431
     
    441441static struct dentry *sf_lookup(struct inode *parent, struct dentry *dentry
    442442#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
    443                                 , unsigned int flags
     443                                , unsigned int flags
    444444#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
    445                                 , struct nameidata *nd
    446 #endif
    447     )
    448 {
    449         struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(parent->i_sb);
    450         struct sf_inode_info   *sf_i = GET_INODE_INFO(parent);
    451         SHFLSTRING             *path;
    452         struct dentry          *dret;
    453         int                     rc;
     445                                , struct nameidata *nd
     446#endif
     447                                )
     448{
     449    struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(parent->i_sb);
     450    struct sf_inode_info   *sf_i = GET_INODE_INFO(parent);
     451    SHFLSTRING             *path;
     452    struct dentry          *dret;
     453    int                     rc;
    454454
    455455#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
    456         SFLOGFLOW(("sf_lookup: parent=%p dentry=%p flags=%#x\n", parent, dentry, flags));
     456    SFLOGFLOW(("sf_lookup: parent=%p dentry=%p flags=%#x\n", parent, dentry, flags));
    457457#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
    458         SFLOGFLOW(("sf_lookup: parent=%p dentry=%p nd=%p{.flags=%#x}\n", parent, dentry, nd, nd ? nd->flags : 0));
     458    SFLOGFLOW(("sf_lookup: parent=%p dentry=%p nd=%p{.flags=%#x}\n", parent, dentry, nd, nd ? nd->flags : 0));
    459459#else
    460         SFLOGFLOW(("sf_lookup: parent=%p dentry=%p\n", parent, dentry));
    461 #endif
    462 
    463         Assert(sf_g);
    464         Assert(sf_i && sf_i->u32Magic == SF_INODE_INFO_MAGIC);
    465 
    466         /*
    467          * Build the path.  We'll associate the path with dret's inode on success.
    468          */
    469         rc = sf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path);
    470         if (rc == 0) {
    471                 /*
    472                  * Do a lookup on the host side.
    473                  */
    474                 VBOXSFCREATEREQ *pReq = (VBOXSFCREATEREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq) + path->u16Size);
    475                 if (pReq) {
    476                         struct inode *pInode = NULL;
    477 
    478                         RT_ZERO(*pReq);
    479                         memcpy(&pReq->StrPath, path, SHFLSTRING_HEADER_SIZE + path->u16Size);
    480                         pReq->CreateParms.Handle = SHFL_HANDLE_NIL;
    481                         pReq->CreateParms.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;
    482 
    483                         LogFunc(("Calling VbglR0SfHostReqCreate on %s\n", path->String.utf8));
    484                         rc = VbglR0SfHostReqCreate(sf_g->map.root, pReq);
    485                         if (RT_SUCCESS(rc)) {
    486                                 if (pReq->CreateParms.Result == SHFL_FILE_EXISTS) {
    487                                         /*
    488                                          * Create an inode for the result.  Since this also confirms
    489                                          * the existence of all parent dentries, we increase their TTL.
    490                                          */
    491                                         pInode = sf_create_inode(parent, dentry, path, &pReq->CreateParms.Info,
    492                                                                  sf_g, false /*fInstantiate*/);
    493                                         if (rc == 0) {
    494                                                 path = NULL; /* given to the inode */
    495                                                 dret = dentry;
    496                                         } else
    497                                                 dret = (struct dentry *)ERR_PTR(-ENOMEM);
    498                                         sf_dentry_chain_increase_parent_ttl(dentry);
    499                                 } else if (   pReq->CreateParms.Result == SHFL_FILE_NOT_FOUND
    500                                            || pReq->CreateParms.Result == SHFL_PATH_NOT_FOUND /*this probably should happen*/) {
    501                                         dret = dentry;
    502                                 } else {
    503                                         AssertMsgFailed(("%d\n", pReq->CreateParms.Result));
    504                                         dret = (struct dentry *)ERR_PTR(-EPROTO);
    505                                 }
    506                         } else if (rc == VERR_INVALID_NAME) {
    507                                 dret = dentry; /* this can happen for names like 'foo*' on a Windows host */
    508                         } else {
    509                                 LogFunc(("VbglR0SfHostReqCreate failed on %s: %Rrc\n", path->String.utf8, rc));
    510                                 dret = (struct dentry *)ERR_PTR(-EPROTO);
    511                         }
    512                         VbglR0PhysHeapFree(pReq);
    513 
    514                         /*
    515                          * When dret is set to dentry we got something to insert,
    516                          * though it may be negative (pInode == NULL).
    517                          */
    518                         if (dret == dentry) {
    519                                 sf_dentry_set_update_jiffies(dentry, jiffies);
     460    SFLOGFLOW(("sf_lookup: parent=%p dentry=%p\n", parent, dentry));
     461#endif
     462
     463    Assert(sf_g);
     464    Assert(sf_i && sf_i->u32Magic == SF_INODE_INFO_MAGIC);
     465
     466    /*
     467     * Build the path.  We'll associate the path with dret's inode on success.
     468     */
     469    rc = sf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path);
     470    if (rc == 0) {
     471        /*
     472         * Do a lookup on the host side.
     473         */
     474        VBOXSFCREATEREQ *pReq = (VBOXSFCREATEREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq) + path->u16Size);
     475        if (pReq) {
     476            struct inode *pInode = NULL;
     477
     478            RT_ZERO(*pReq);
     479            memcpy(&pReq->StrPath, path, SHFLSTRING_HEADER_SIZE + path->u16Size);
     480            pReq->CreateParms.Handle = SHFL_HANDLE_NIL;
     481            pReq->CreateParms.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;
     482
     483            LogFunc(("Calling VbglR0SfHostReqCreate on %s\n", path->String.utf8));
     484            rc = VbglR0SfHostReqCreate(sf_g->map.root, pReq);
     485            if (RT_SUCCESS(rc)) {
     486                if (pReq->CreateParms.Result == SHFL_FILE_EXISTS) {
     487                    /*
     488                     * Create an inode for the result.  Since this also confirms
     489                     * the existence of all parent dentries, we increase their TTL.
     490                     */
     491                    pInode = sf_create_inode(parent, dentry, path, &pReq->CreateParms.Info, sf_g, false /*fInstantiate*/);
     492                    if (rc == 0) {
     493                        path = NULL; /* given to the inode */
     494                        dret = dentry;
     495                    } else
     496                        dret = (struct dentry *)ERR_PTR(-ENOMEM);
     497                    sf_dentry_chain_increase_parent_ttl(dentry);
     498                } else if (   pReq->CreateParms.Result == SHFL_FILE_NOT_FOUND
     499                       || pReq->CreateParms.Result == SHFL_PATH_NOT_FOUND /*this probably should happen*/) {
     500                    dret = dentry;
     501                } else {
     502                    AssertMsgFailed(("%d\n", pReq->CreateParms.Result));
     503                    dret = (struct dentry *)ERR_PTR(-EPROTO);
     504                }
     505            } else if (rc == VERR_INVALID_NAME) {
     506                dret = dentry; /* this can happen for names like 'foo*' on a Windows host */
     507            } else {
     508                LogFunc(("VbglR0SfHostReqCreate failed on %s: %Rrc\n", path->String.utf8, rc));
     509                dret = (struct dentry *)ERR_PTR(-EPROTO);
     510            }
     511            VbglR0PhysHeapFree(pReq);
     512
     513            /*
     514             * When dret is set to dentry we got something to insert,
     515             * though it may be negative (pInode == NULL).
     516             */
     517            if (dret == dentry) {
     518                sf_dentry_set_update_jiffies(dentry, jiffies);
    520519#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
    521                                 Assert(dentry->d_op == &sf_dentry_ops); /* (taken from the superblock) */
     520                Assert(dentry->d_op == &sf_dentry_ops); /* (taken from the superblock) */
    522521#else
    523                                 dentry->d_op = &sf_dentry_ops;
    524 #endif
    525                                 d_add(dentry, pInode);
    526                                 dret = NULL;
    527                         }
    528                 } else
    529                         dret = (struct dentry *)ERR_PTR(-ENOMEM);
    530                 if (path)
    531                         kfree(path);
    532         } else
    533                 dret = (struct dentry *)ERR_PTR(rc);
    534         return dret;
     522                dentry->d_op = &sf_dentry_ops;
     523#endif
     524                d_add(dentry, pInode);
     525                dret = NULL;
     526            }
     527        } else
     528            dret = (struct dentry *)ERR_PTR(-ENOMEM);
     529        if (path)
     530            kfree(path);
     531    } else
     532        dret = (struct dentry *)ERR_PTR(rc);
     533    return dret;
    535534}
    536535
     
    547546 * @returns 0 on success, Linux error code otherwise
    548547 */
    549 static int sf_instantiate(struct inode *parent, struct dentry *dentry,
    550                           PSHFLSTRING path, PSHFLFSOBJINFO info,
    551                           SHFLHANDLE handle)
    552 {
    553         struct vbsf_super_info *sf_g   = VBSF_GET_SUPER_INFO(parent->i_sb);
    554         struct inode           *pInode = sf_create_inode(parent, dentry, path, info, sf_g, true /*fInstantiate*/);
    555         if (pInode) {
    556                 /* Store this handle if we leave the handle open. */
    557                 struct sf_inode_info *sf_new_i = GET_INODE_INFO(pInode);
    558                 sf_new_i->handle = handle;
    559                 return 0;
    560         }
    561         return -ENOMEM;
     548static int sf_instantiate(struct inode *parent, struct dentry *dentry, PSHFLSTRING path, PSHFLFSOBJINFO info, SHFLHANDLE handle)
     549{
     550    struct vbsf_super_info *sf_g   = VBSF_GET_SUPER_INFO(parent->i_sb);
     551    struct inode           *pInode = sf_create_inode(parent, dentry, path, info, sf_g, true /*fInstantiate*/);
     552    if (pInode) {
     553        /* Store this handle if we leave the handle open. */
     554        struct sf_inode_info *sf_new_i = GET_INODE_INFO(pInode);
     555        sf_new_i->handle = handle;
     556        return 0;
     557    }
     558    return -ENOMEM;
    562559}
    563560
     
    571568 * @returns 0 on success, Linux error code otherwise
    572569 */
    573 static int sf_create_aux(struct inode *parent, struct dentry *dentry,
    574                          umode_t mode, int fDirectory)
    575 {
    576         int rc, err;
    577         struct sf_inode_info *sf_parent_i = GET_INODE_INFO(parent);
    578         struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(parent->i_sb);
    579         SHFLSTRING *path;
    580         union CreateAuxReq
    581         {
    582             VBOXSFCREATEREQ Create;
    583             VBOXSFCLOSEREQ  Close;
    584         } *pReq;
    585         SHFLCREATEPARMS *pCreateParms;
    586 
    587         TRACE();
    588         BUG_ON(!sf_parent_i);
    589         BUG_ON(!sf_g);
    590 
    591         err = sf_path_from_dentry(__func__, sf_g, sf_parent_i, dentry, &path);
    592         if (err)
    593                 goto fail0;
    594 
    595         /** @todo combine with sf_path_from_dentry? */
    596         pReq = (union CreateAuxReq *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + path->u16Size);
    597         if (pReq) {
    598                 memcpy(&pReq->Create.StrPath, path, SHFLSTRING_HEADER_SIZE + path->u16Size);
    599                 pCreateParms = &pReq->Create.CreateParms;
    600         } else {
    601                 err = -ENOMEM;
    602                 goto fail1;
    603         }
    604 
    605         RT_ZERO(*pCreateParms);
    606         pCreateParms->Handle = SHFL_HANDLE_NIL;
    607         pCreateParms->CreateFlags = SHFL_CF_ACT_CREATE_IF_NEW
    608                                   | SHFL_CF_ACT_FAIL_IF_EXISTS
    609                                   | SHFL_CF_ACCESS_READWRITE
    610                                   | (fDirectory ? SHFL_CF_DIRECTORY : 0);
    611         pCreateParms->Info.Attr.fMode = (fDirectory ? RTFS_TYPE_DIRECTORY : RTFS_TYPE_FILE)
    612                                       | (mode & S_IRWXUGO);
    613         pCreateParms->Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING;
    614 
    615         LogFunc(("calling VbglR0SfHostReqCreate, folder %s, flags %#x\n", path->String.ach, pCreateParms->CreateFlags));
    616         rc = VbglR0SfHostReqCreate(sf_g->map.root, &pReq->Create);
    617         if (RT_FAILURE(rc)) {
    618                 if (rc == VERR_WRITE_PROTECT) {
    619                         err = -EROFS;
    620                         goto fail2;
    621                 }
    622                 err = -EPROTO;
    623                 LogFunc(("(%d): SHFL_FN_CREATE(%s) failed rc=%Rrc\n",
    624                          fDirectory, sf_parent_i->path->String.utf8, rc));
    625                 goto fail2;
    626         }
    627 
    628         if (pCreateParms->Result != SHFL_FILE_CREATED) {
    629                 err = -EPERM;
    630                 LogFunc(("(%d): could not create file %s result=%d\n",
    631                          fDirectory, sf_parent_i->path->String.utf8, pCreateParms->Result));
    632                 goto fail2;
    633         }
    634 
    635         sf_dentry_chain_increase_parent_ttl(dentry);
    636 
    637         err = sf_instantiate(parent, dentry, path, &pCreateParms->Info,
    638                              fDirectory ? SHFL_HANDLE_NIL : pCreateParms->Handle);
    639         if (err) {
    640                 LogFunc(("(%d): could not instantiate dentry for %s err=%d\n", fDirectory, path->String.utf8, err));
    641                 goto fail3;
    642         }
    643 
    644         /*
    645          * Don't close this handle right now. We assume that the same file is
    646          * opened with sf_reg_open() and later closed with sf_reg_close(). Save
    647          * the handle in between. Does not apply to directories. True?
    648          */
    649         if (fDirectory) {
    650                 AssertCompile(RTASSERT_OFFSET_OF(VBOXSFCREATEREQ, CreateParms.Handle) > sizeof(VBOXSFCLOSEREQ)); /* no aliasing issues */
    651                 rc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, pCreateParms->Handle);
    652                 if (RT_FAILURE(rc))
    653                         LogFunc(("(%d): VbglR0SfHostReqClose failed rc=%Rrc\n", fDirectory, rc));
    654         }
    655 
    656         sf_parent_i->force_restat = 1;
    657         VbglR0PhysHeapFree(pReq);
    658         return 0;
     570static int sf_create_aux(struct inode *parent, struct dentry *dentry, umode_t mode, int fDirectory)
     571{
     572    int rc, err;
     573    struct sf_inode_info *sf_parent_i = GET_INODE_INFO(parent);
     574    struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(parent->i_sb);
     575    SHFLSTRING *path;
     576    union CreateAuxReq
     577    {
     578        VBOXSFCREATEREQ Create;
     579        VBOXSFCLOSEREQ  Close;
     580    } *pReq;
     581    SHFLCREATEPARMS *pCreateParms;
     582
     583    TRACE();
     584    BUG_ON(!sf_parent_i);
     585    BUG_ON(!sf_g);
     586
     587    err = sf_path_from_dentry(__func__, sf_g, sf_parent_i, dentry, &path);
     588    if (err)
     589        goto fail0;
     590
     591    /** @todo combine with sf_path_from_dentry? */
     592    pReq = (union CreateAuxReq *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + path->u16Size);
     593    if (pReq) {
     594        memcpy(&pReq->Create.StrPath, path, SHFLSTRING_HEADER_SIZE + path->u16Size);
     595        pCreateParms = &pReq->Create.CreateParms;
     596    } else {
     597        err = -ENOMEM;
     598        goto fail1;
     599    }
     600
     601    RT_ZERO(*pCreateParms);
     602    pCreateParms->Handle = SHFL_HANDLE_NIL;
     603    pCreateParms->CreateFlags = SHFL_CF_ACT_CREATE_IF_NEW
     604                              | SHFL_CF_ACT_FAIL_IF_EXISTS
     605                              | SHFL_CF_ACCESS_READWRITE
     606                              | (fDirectory ? SHFL_CF_DIRECTORY : 0);
     607    pCreateParms->Info.Attr.fMode = (fDirectory ? RTFS_TYPE_DIRECTORY : RTFS_TYPE_FILE)
     608                                  | (mode & S_IRWXUGO);
     609    pCreateParms->Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING;
     610
     611    LogFunc(("calling VbglR0SfHostReqCreate, folder %s, flags %#x\n", path->String.ach, pCreateParms->CreateFlags));
     612    rc = VbglR0SfHostReqCreate(sf_g->map.root, &pReq->Create);
     613    if (RT_FAILURE(rc)) {
     614        if (rc == VERR_WRITE_PROTECT) {
     615            err = -EROFS;
     616            goto fail2;
     617        }
     618        err = -EPROTO;
     619        LogFunc(("(%d): SHFL_FN_CREATE(%s) failed rc=%Rrc\n",
     620             fDirectory, sf_parent_i->path->String.utf8, rc));
     621        goto fail2;
     622    }
     623
     624    if (pCreateParms->Result != SHFL_FILE_CREATED) {
     625        err = -EPERM;
     626        LogFunc(("(%d): could not create file %s result=%d\n",
     627             fDirectory, sf_parent_i->path->String.utf8, pCreateParms->Result));
     628        goto fail2;
     629    }
     630
     631    sf_dentry_chain_increase_parent_ttl(dentry);
     632
     633    err = sf_instantiate(parent, dentry, path, &pCreateParms->Info,
     634                 fDirectory ? SHFL_HANDLE_NIL : pCreateParms->Handle);
     635    if (err) {
     636        LogFunc(("(%d): could not instantiate dentry for %s err=%d\n", fDirectory, path->String.utf8, err));
     637        goto fail3;
     638    }
     639
     640    /*
     641     * Don't close this handle right now. We assume that the same file is
     642     * opened with sf_reg_open() and later closed with sf_reg_close(). Save
     643     * the handle in between. Does not apply to directories. True?
     644     */
     645    if (fDirectory) {
     646        AssertCompile(RTASSERT_OFFSET_OF(VBOXSFCREATEREQ, CreateParms.Handle) > sizeof(VBOXSFCLOSEREQ)); /* no aliasing issues */
     647        rc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, pCreateParms->Handle);
     648        if (RT_FAILURE(rc))
     649            LogFunc(("(%d): VbglR0SfHostReqClose failed rc=%Rrc\n", fDirectory, rc));
     650    }
     651
     652    sf_parent_i->force_restat = 1;
     653    VbglR0PhysHeapFree(pReq);
     654    return 0;
    659655
    660656 fail3:
    661         rc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, pCreateParms->Handle);
    662         if (RT_FAILURE(rc))
    663                 LogFunc(("(%d): VbglR0SfHostReqCloseSimple failed rc=%Rrc\n", fDirectory, rc));
     657    rc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, pCreateParms->Handle);
     658    if (RT_FAILURE(rc))
     659        LogFunc(("(%d): VbglR0SfHostReqCloseSimple failed rc=%Rrc\n", fDirectory, rc));
    664660 fail2:
    665         VbglR0PhysHeapFree(pReq);
     661    VbglR0PhysHeapFree(pReq);
    666662 fail1:
    667         kfree(path);
     663    kfree(path);
    668664
    669665 fail0:
    670         return err;
     666    return err;
    671667}
    672668
     
    681677 */
    682678#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) || defined(DOXYGEN_RUNNING)
    683 static int sf_create(struct inode *parent, struct dentry *dentry, umode_t mode,
    684                      bool excl)
     679static int sf_create(struct inode *parent, struct dentry *dentry, umode_t mode, bool excl)
    685680#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
    686 static int sf_create(struct inode *parent, struct dentry *dentry, umode_t mode,
    687                      struct nameidata *nd)
     681static int sf_create(struct inode *parent, struct dentry *dentry, umode_t mode, struct nameidata *nd)
    688682#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
    689 static int sf_create(struct inode *parent, struct dentry *dentry, int mode,
    690                      struct nameidata *nd)
     683static int sf_create(struct inode *parent, struct dentry *dentry, int mode, struct nameidata *nd)
    691684#else
    692685static int sf_create(struct inode *parent, struct dentry *dentry, int mode)
     
    696689 *        2.6.0-3.5.999.  In 3.6.0 atomic_open was introduced and stuff
    697690 *        changed (investigate)... */
    698         TRACE();
    699         return sf_create_aux(parent, dentry, mode, 0 /*fDirectory*/);
     691    TRACE();
     692    return sf_create_aux(parent, dentry, mode, 0 /*fDirectory*/);
    700693}
    701694
     
    714707#endif
    715708{
    716         TRACE();
    717         return sf_create_aux(parent, dentry, mode, 1 /*fDirectory*/);
     709    TRACE();
     710    return sf_create_aux(parent, dentry, mode, 1 /*fDirectory*/);
    718711}
    719712
     
    726719 * @returns 0 on success, Linux error code otherwise
    727720 */
    728 static int sf_unlink_aux(struct inode *parent, struct dentry *dentry,
    729                          int fDirectory)
    730 {
    731         int rc, err;
    732         struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(parent->i_sb);
    733         struct sf_inode_info *sf_parent_i = GET_INODE_INFO(parent);
    734         SHFLSTRING *path;
    735 
    736         TRACE();
    737         BUG_ON(!sf_g);
    738 
    739         err = sf_path_from_dentry(__func__, sf_g, sf_parent_i, dentry, &path);
    740         if (!err) {
    741                 VBOXSFREMOVEREQ *pReq = (VBOXSFREMOVEREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFREMOVEREQ, StrPath.String)
    742                                                                                + path->u16Size);
    743                 if (pReq) {
    744                         memcpy(&pReq->StrPath, path, SHFLSTRING_HEADER_SIZE + path->u16Size);
    745                         uint32_t fFlags = fDirectory ? SHFL_REMOVE_DIR : SHFL_REMOVE_FILE;
    746                         if (dentry->d_inode && ((dentry->d_inode->i_mode & S_IFLNK) == S_IFLNK))
    747                                 fFlags |= SHFL_REMOVE_SYMLINK;
    748 
    749                         rc = VbglR0SfHostReqRemove(sf_g->map.root, pReq, fFlags);
    750 
    751                         if (dentry->d_inode) {
    752                                 struct sf_inode_info *sf_i = GET_INODE_INFO(dentry->d_inode);
    753                                 sf_i->force_restat = 1;
    754                                 sf_i->force_reread = 1;
    755                         }
    756 
    757                         if (RT_SUCCESS(rc)) {
    758                                 /* directory access/change time changed */
    759                                 sf_parent_i->force_restat = 1;
    760                                 /* directory content changed */
    761                                 sf_parent_i->force_reread = 1;
    762 
    763                                 err = 0;
    764                         } else if (rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND) {
    765                                 LogFunc(("(%d): VbglR0SfRemove(%s) failed rc=%Rrc; calling d_drop on %p\n",
    766                                          fDirectory, path->String.utf8, rc, dentry));
    767                                 d_drop(dentry);
    768                         } else {
    769                                 LogFunc(("(%d): VbglR0SfRemove(%s) failed rc=%Rrc\n", fDirectory, path->String.utf8, rc));
    770                                 err = -RTErrConvertToErrno(rc);
    771                         }
    772                         VbglR0PhysHeapFree(pReq);
    773                 } else
    774                         err = -ENOMEM;
    775                 kfree(path);
    776         }
    777         return err;
     721static int sf_unlink_aux(struct inode *parent, struct dentry *dentry, int fDirectory)
     722{
     723    int rc, err;
     724    struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(parent->i_sb);
     725    struct sf_inode_info *sf_parent_i = GET_INODE_INFO(parent);
     726    SHFLSTRING *path;
     727
     728    TRACE();
     729    BUG_ON(!sf_g);
     730
     731    err = sf_path_from_dentry(__func__, sf_g, sf_parent_i, dentry, &path);
     732    if (!err) {
     733        VBOXSFREMOVEREQ *pReq = (VBOXSFREMOVEREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFREMOVEREQ, StrPath.String)
     734                                           + path->u16Size);
     735        if (pReq) {
     736            memcpy(&pReq->StrPath, path, SHFLSTRING_HEADER_SIZE + path->u16Size);
     737            uint32_t fFlags = fDirectory ? SHFL_REMOVE_DIR : SHFL_REMOVE_FILE;
     738            if (dentry->d_inode && ((dentry->d_inode->i_mode & S_IFLNK) == S_IFLNK))
     739                fFlags |= SHFL_REMOVE_SYMLINK;
     740
     741            rc = VbglR0SfHostReqRemove(sf_g->map.root, pReq, fFlags);
     742
     743            if (dentry->d_inode) {
     744                struct sf_inode_info *sf_i = GET_INODE_INFO(dentry->d_inode);
     745                sf_i->force_restat = 1;
     746                sf_i->force_reread = 1;
     747            }
     748
     749            if (RT_SUCCESS(rc)) {
     750                /* directory access/change time changed */
     751                sf_parent_i->force_restat = 1;
     752                /* directory content changed */
     753                sf_parent_i->force_reread = 1;
     754
     755                err = 0;
     756            } else if (rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND) {
     757                LogFunc(("(%d): VbglR0SfRemove(%s) failed rc=%Rrc; calling d_drop on %p\n",
     758                         fDirectory, path->String.utf8, rc, dentry));
     759                d_drop(dentry);
     760            } else {
     761                LogFunc(("(%d): VbglR0SfRemove(%s) failed rc=%Rrc\n", fDirectory, path->String.utf8, rc));
     762                err = -RTErrConvertToErrno(rc);
     763            }
     764            VbglR0PhysHeapFree(pReq);
     765        } else
     766            err = -ENOMEM;
     767        kfree(path);
     768    }
     769    return err;
    778770}
    779771
     
    787779static int sf_unlink(struct inode *parent, struct dentry *dentry)
    788780{
    789         TRACE();
    790         return sf_unlink_aux(parent, dentry, 0 /*fDirectory*/);
     781    TRACE();
     782    return sf_unlink_aux(parent, dentry, 0 /*fDirectory*/);
    791783}
    792784
     
    800792static int sf_rmdir(struct inode *parent, struct dentry *dentry)
    801793{
    802         TRACE();
    803         return sf_unlink_aux(parent, dentry, 1 /*fDirectory*/);
     794    TRACE();
     795    return sf_unlink_aux(parent, dentry, 1 /*fDirectory*/);
    804796}
    805797
     
    815807 */
    816808static int sf_rename(struct inode *old_parent, struct dentry *old_dentry,
    817                      struct inode *new_parent, struct dentry *new_dentry
     809                     struct inode *new_parent, struct dentry *new_dentry
    818810#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
    819                      , unsigned flags
    820 #endif
    821     )
    822 {
    823         int err = 0, rc = VINF_SUCCESS;
    824         struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(old_parent->i_sb);
    825 
    826         TRACE();
     811                     , unsigned flags
     812#endif
     813                     )
     814{
     815    int err = 0, rc = VINF_SUCCESS;
     816    struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(old_parent->i_sb);
     817
     818    TRACE();
    827819
    828820#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
    829         if (flags) {
    830                 LogFunc(("rename with flags=%x\n", flags));
    831                 return -EINVAL;
    832         }
    833 #endif
    834 
    835         if (sf_g != VBSF_GET_SUPER_INFO(new_parent->i_sb)) {
    836                 LogFunc(("rename with different roots\n"));
    837                 err = -EINVAL;
    838         } else {
    839                 struct sf_inode_info *sf_old_i = GET_INODE_INFO(old_parent);
    840                 struct sf_inode_info *sf_new_i = GET_INODE_INFO(new_parent);
    841                 /* As we save the relative path inside the inode structure, we need to change
    842                    this if the rename is successful. */
    843                 struct sf_inode_info *sf_file_i =
    844                     GET_INODE_INFO(old_dentry->d_inode);
    845                 SHFLSTRING *old_path;
    846                 SHFLSTRING *new_path;
    847 
    848                 BUG_ON(!sf_old_i);
    849                 BUG_ON(!sf_new_i);
    850                 BUG_ON(!sf_file_i);
    851 
    852                 old_path = sf_file_i->path;
    853                 err = sf_path_from_dentry(__func__, sf_g, sf_new_i,
    854                                           new_dentry, &new_path);
    855                 if (err)
    856                         LogFunc(("failed to create new path\n"));
    857                 else {
    858                         VBOXSFRENAMEWITHSRCBUFREQ *pReq;
    859                         pReq = (VBOXSFRENAMEWITHSRCBUFREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFRENAMEWITHSRCBUFREQ,
    860                                                                                              StrDstPath.String)
    861                                                                                 + new_path->u16Size);
    862                         if (pReq) {
    863                                 memcpy(&pReq->StrDstPath, new_path, SHFLSTRING_HEADER_SIZE + new_path->u16Size);
    864                                 rc = VbglR0SfHostReqRenameWithSrcContig(sf_g->map.root, pReq,
    865                                                                         old_path, virt_to_phys(old_path),
    866                                                                         old_dentry->d_inode->i_mode & S_IFDIR ? SHFL_RENAME_DIR
    867                                                                         : SHFL_RENAME_FILE | SHFL_RENAME_REPLACE_IF_EXISTS);
    868                                 VbglR0PhysHeapFree(pReq);
    869                         } else
    870                                 rc = VERR_NO_MEMORY;
    871                         if (RT_SUCCESS(rc)) {
    872                                 kfree(old_path);
    873                                 sf_new_i->force_restat = 1;
    874                                 sf_old_i->force_restat = 1;     /* XXX: needed? */
    875 
    876                                 /* Set the new relative path in the inode. */
    877                                 sf_file_i->path = new_path;
    878 
    879                         } else {
    880                                 LogFunc(("VbglR0SfRename failed rc=%Rrc\n",
    881                                          rc));
    882                                 err = -RTErrConvertToErrno(rc);
    883                                 kfree(new_path);
    884                         }
    885                 }
    886         }
    887         return err;
     821    if (flags) {
     822        LogFunc(("rename with flags=%x\n", flags));
     823        return -EINVAL;
     824    }
     825#endif
     826
     827    if (sf_g != VBSF_GET_SUPER_INFO(new_parent->i_sb)) {
     828        LogFunc(("rename with different roots\n"));
     829        err = -EINVAL;
     830    } else {
     831        struct sf_inode_info *sf_old_i = GET_INODE_INFO(old_parent);
     832        struct sf_inode_info *sf_new_i = GET_INODE_INFO(new_parent);
     833        /* As we save the relative path inside the inode structure, we need to change
     834           this if the rename is successful. */
     835        struct sf_inode_info *sf_file_i = GET_INODE_INFO(old_dentry->d_inode);
     836        SHFLSTRING *old_path;
     837        SHFLSTRING *new_path;
     838
     839        BUG_ON(!sf_old_i);
     840        BUG_ON(!sf_new_i);
     841        BUG_ON(!sf_file_i);
     842
     843        old_path = sf_file_i->path;
     844        err = sf_path_from_dentry(__func__, sf_g, sf_new_i,
     845                      new_dentry, &new_path);
     846        if (err)
     847            LogFunc(("failed to create new path\n"));
     848        else {
     849            VBOXSFRENAMEWITHSRCBUFREQ *pReq;
     850            pReq = (VBOXSFRENAMEWITHSRCBUFREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFRENAMEWITHSRCBUFREQ,
     851                                                 StrDstPath.String)
     852                                        + new_path->u16Size);
     853            if (pReq) {
     854                memcpy(&pReq->StrDstPath, new_path, SHFLSTRING_HEADER_SIZE + new_path->u16Size);
     855                rc = VbglR0SfHostReqRenameWithSrcContig(sf_g->map.root, pReq,
     856                                    old_path, virt_to_phys(old_path),
     857                                    old_dentry->d_inode->i_mode & S_IFDIR ? SHFL_RENAME_DIR
     858                                    : SHFL_RENAME_FILE | SHFL_RENAME_REPLACE_IF_EXISTS);
     859                VbglR0PhysHeapFree(pReq);
     860            } else
     861                rc = VERR_NO_MEMORY;
     862            if (RT_SUCCESS(rc)) {
     863                kfree(old_path);
     864                sf_new_i->force_restat = 1;
     865                sf_old_i->force_restat = 1; /* XXX: needed? */
     866
     867                /* Set the new relative path in the inode. */
     868                sf_file_i->path = new_path;
     869
     870            } else {
     871                LogFunc(("VbglR0SfRename failed rc=%Rrc\n",
     872                     rc));
     873                err = -RTErrConvertToErrno(rc);
     874                kfree(new_path);
     875            }
     876        }
     877    }
     878    return err;
    888879}
    889880
    890881#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
    891 static int sf_symlink(struct inode *parent, struct dentry *dentry,
    892                       const char *symname)
    893 {
    894         int err;
    895         int rc;
    896         struct sf_inode_info *sf_i;
    897         struct vbsf_super_info *sf_g;
    898         SHFLSTRING *path, *ssymname;
    899         SHFLFSOBJINFO info;
    900         int symname_len = strlen(symname) + 1;
    901 
    902         TRACE();
    903         sf_g = VBSF_GET_SUPER_INFO(parent->i_sb);
    904         sf_i = GET_INODE_INFO(parent);
    905 
    906         BUG_ON(!sf_g);
    907         BUG_ON(!sf_i);
    908 
    909         err = sf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path);
    910         if (err)
    911                 goto fail0;
    912 
    913         ssymname =
    914             kmalloc(offsetof(SHFLSTRING, String.utf8) + symname_len,
    915                     GFP_KERNEL);
    916         if (!ssymname) {
    917                 LogRelFunc(("kmalloc failed, caller=sf_symlink\n"));
    918                 err = -ENOMEM;
    919                 goto fail1;
    920         }
    921 
    922         ssymname->u16Length = symname_len - 1;
    923         ssymname->u16Size = symname_len;
    924         memcpy(ssymname->String.utf8, symname, symname_len);
    925 
    926         rc = VbglR0SfSymlink(&client_handle, &sf_g->map, path, ssymname, &info);
    927         kfree(ssymname);
    928 
    929         if (RT_FAILURE(rc)) {
    930                 if (rc == VERR_WRITE_PROTECT) {
    931                         err = -EROFS;
    932                         goto fail1;
    933                 }
    934                 LogFunc(("VbglR0SfSymlink(%s) failed rc=%Rrc\n",
    935                          sf_i->path->String.utf8, rc));
    936                 err = -EPROTO;
    937                 goto fail1;
    938         }
    939 
    940         err = sf_instantiate(parent, dentry, path, &info, SHFL_HANDLE_NIL);
    941         if (err) {
    942                 LogFunc(("could not instantiate dentry for %s err=%d\n",
    943                          sf_i->path->String.utf8, err));
    944                 goto fail1;
    945         }
    946 
    947         sf_i->force_restat = 1;
    948         return 0;
     882static int sf_symlink(struct inode *parent, struct dentry *dentry, const char *symname)
     883{
     884    int err;
     885    int rc;
     886    struct sf_inode_info *sf_i;
     887    struct vbsf_super_info *sf_g;
     888    SHFLSTRING *path, *ssymname;
     889    SHFLFSOBJINFO info;
     890    int symname_len = strlen(symname) + 1;
     891
     892    TRACE();
     893    sf_g = VBSF_GET_SUPER_INFO(parent->i_sb);
     894    sf_i = GET_INODE_INFO(parent);
     895
     896    BUG_ON(!sf_g);
     897    BUG_ON(!sf_i);
     898
     899    err = sf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path);
     900    if (err)
     901        goto fail0;
     902
     903    ssymname =
     904        kmalloc(offsetof(SHFLSTRING, String.utf8) + symname_len,
     905            GFP_KERNEL);
     906    if (!ssymname) {
     907        LogRelFunc(("kmalloc failed, caller=sf_symlink\n"));
     908        err = -ENOMEM;
     909        goto fail1;
     910    }
     911
     912    ssymname->u16Length = symname_len - 1;
     913    ssymname->u16Size = symname_len;
     914    memcpy(ssymname->String.utf8, symname, symname_len);
     915
     916    rc = VbglR0SfSymlink(&client_handle, &sf_g->map, path, ssymname, &info);
     917    kfree(ssymname);
     918
     919    if (RT_FAILURE(rc)) {
     920        if (rc == VERR_WRITE_PROTECT) {
     921            err = -EROFS;
     922            goto fail1;
     923        }
     924        LogFunc(("VbglR0SfSymlink(%s) failed rc=%Rrc\n",
     925             sf_i->path->String.utf8, rc));
     926        err = -EPROTO;
     927        goto fail1;
     928    }
     929
     930    err = sf_instantiate(parent, dentry, path, &info, SHFL_HANDLE_NIL);
     931    if (err) {
     932        LogFunc(("could not instantiate dentry for %s err=%d\n",
     933             sf_i->path->String.utf8, err));
     934        goto fail1;
     935    }
     936
     937    sf_i->force_restat = 1;
     938    return 0;
    949939
    950940 fail1:
    951         kfree(path);
     941    kfree(path);
    952942 fail0:
    953         return err;
     943    return err;
    954944}
    955945#endif /* LINUX_VERSION_CODE >= 2.6.0 */
    956946
    957947struct inode_operations sf_dir_iops = {
    958         .lookup = sf_lookup,
    959         .create = sf_create,
    960         .mkdir = sf_mkdir,
    961         .rmdir = sf_rmdir,
    962         .unlink = sf_unlink,
    963         .rename = sf_rename,
     948    .lookup = sf_lookup,
     949    .create = sf_create,
     950    .mkdir = sf_mkdir,
     951    .rmdir = sf_rmdir,
     952    .unlink = sf_unlink,
     953    .rename = sf_rename,
    964954#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
    965         .revalidate = sf_inode_revalidate
     955    .revalidate = sf_inode_revalidate
    966956#else
    967         .getattr = sf_getattr,
    968         .setattr = sf_setattr,
    969         .symlink = sf_symlink
     957    .getattr = sf_getattr,
     958    .setattr = sf_setattr,
     959    .symlink = sf_symlink
    970960#endif
    971961};
     962
  • trunk/src/VBox/Additions/linux/sharedfolders/lnkops.c

    r77524 r77526  
    4242#  endif
    4343{
    44         struct inode *inode = dentry->d_inode;
    45         struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
    46         struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
    47         int error = -ENOMEM;
    48         char *path = (char *)get_zeroed_page(GFP_KERNEL);
    49         int rc;
     44    struct inode *inode = dentry->d_inode;
     45    struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
     46    struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
     47    int error = -ENOMEM;
     48    char *path = (char *)get_zeroed_page(GFP_KERNEL);
     49    int rc;
    5050
    51         if (path) {
    52                 error = 0;
    53                 rc = VbglR0SfReadLink(&client_handle, &sf_g->map, sf_i->path,
    54                                       PATH_MAX, path);
    55                 if (RT_FAILURE(rc)) {
    56                         LogFunc(("VbglR0SfReadLink failed, caller=%s, rc=%Rrc\n", __func__, rc));
    57                         free_page((unsigned long)path);
    58                         error = -EPROTO;
    59                 }
    60         }
     51    if (path) {
     52        error = 0;
     53        rc = VbglR0SfReadLink(&client_handle, &sf_g->map, sf_i->path,
     54                      PATH_MAX, path);
     55        if (RT_FAILURE(rc)) {
     56            LogFunc(("VbglR0SfReadLink failed, caller=%s, rc=%Rrc\n", __func__, rc));
     57            free_page((unsigned long)path);
     58            error = -EPROTO;
     59        }
     60    }
    6161#  if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
    62         return error ? ERR_PTR(error) : (*cookie = path);
     62    return error ? ERR_PTR(error) : (*cookie = path);
    6363#  else
    64         nd_set_link(nd, error ? ERR_PTR(error) : path);
     64    nd_set_link(nd, error ? ERR_PTR(error) : path);
    6565# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
    66         return NULL;
     66    return NULL;
    6767# else
    68         return 0;
     68    return 0;
    6969# endif
    7070#endif
     
    7474# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
    7575static void sf_put_link(struct dentry *dentry, struct nameidata *nd,
    76                         void *cookie)
     76            void *cookie)
    7777#else
    7878static void sf_put_link(struct dentry *dentry, struct nameidata *nd)
    7979#endif
    8080{
    81         char *page = nd_get_link(nd);
    82         if (!IS_ERR(page))
    83                 free_page((unsigned long)page);
     81    char *page = nd_get_link(nd);
     82    if (!IS_ERR(page))
     83        free_page((unsigned long)page);
    8484}
    8585#  endif
     
    8787# else  /* LINUX_VERSION_CODE >= 4.5.0 */
    8888static const char *sf_get_link(struct dentry *dentry, struct inode *inode,
    89                                struct delayed_call *done)
     89                               struct delayed_call *done)
    9090{
    91         struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
    92         struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
    93         char *path;
    94         int rc;
     91    struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
     92    struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
     93    char *path;
     94    int rc;
    9595
    96         if (!dentry)
    97                 return ERR_PTR(-ECHILD);
    98         path = kzalloc(PAGE_SIZE, GFP_KERNEL);
    99         if (!path)
    100                 return ERR_PTR(-ENOMEM);
    101         rc = VbglR0SfReadLink(&client_handle, &sf_g->map, sf_i->path, PATH_MAX,
    102                               path);
    103         if (RT_FAILURE(rc)) {
    104                 LogFunc(("VbglR0SfReadLink failed, caller=%s, rc=%Rrc\n",
    105                         __func__, rc));
    106                 kfree(path);
    107                 return ERR_PTR(-EPROTO);
    108         }
    109         set_delayed_call(done, kfree_link, path);
    110         return path;
     96    if (!dentry)
     97        return ERR_PTR(-ECHILD);
     98    path = kzalloc(PAGE_SIZE, GFP_KERNEL);
     99    if (!path)
     100        return ERR_PTR(-ENOMEM);
     101    rc = VbglR0SfReadLink(&client_handle, &sf_g->map, sf_i->path, PATH_MAX,
     102                  path);
     103    if (RT_FAILURE(rc)) {
     104        LogFunc(("VbglR0SfReadLink failed, caller=%s, rc=%Rrc\n",
     105            __func__, rc));
     106        kfree(path);
     107        return ERR_PTR(-EPROTO);
     108    }
     109    set_delayed_call(done, kfree_link, path);
     110    return path;
    111111}
    112112# endif /* LINUX_VERSION_CODE >= 4.5.0 */
     
    114114struct inode_operations sf_lnk_iops = {
    115115# if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
    116         .readlink = generic_readlink,
     116    .readlink = generic_readlink,
    117117# endif
    118118# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
    119         .get_link = sf_get_link
     119    .get_link = sf_get_link
    120120# elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
    121         .follow_link = sf_follow_link,
    122         .put_link = free_page_put_link,
     121    .follow_link = sf_follow_link,
     122    .put_link = free_page_put_link,
    123123# else
    124         .follow_link = sf_follow_link,
    125         .put_link = sf_put_link
     124    .follow_link = sf_follow_link,
     125    .put_link = sf_put_link
    126126# endif
    127127};
    128128
    129 #endif  /* LINUX_VERSION_CODE >= 2.6.8 */
     129#endif  /* LINUX_VERSION_CODE >= 2.6.8 */
  • trunk/src/VBox/Additions/linux/sharedfolders/regops.c

    r77524 r77526  
    6060void sf_handle_drop_chain(struct sf_inode_info *pInodeInfo)
    6161{
    62         struct sf_handle *pCur, *pNext;
    63         unsigned long     fSavedFlags;
    64         SFLOGFLOW(("sf_handle_drop_chain: %p\n", pInodeInfo));
    65         spin_lock_irqsave(&g_SfHandleLock, fSavedFlags);
    66 
    67         RTListForEachSafe(&pInodeInfo->HandleList, pCur, pNext, struct sf_handle, Entry) {
    68                 AssertMsg((pCur->fFlags & (SF_HANDLE_F_MAGIC_MASK | SF_HANDLE_F_ON_LIST)) == (SF_HANDLE_F_MAGIC | SF_HANDLE_F_ON_LIST),
    69                           ("%p %#x\n", pCur, pCur->fFlags));
    70                 pCur->fFlags |= SF_HANDLE_F_ON_LIST;
    71                 RTListNodeRemove(&pCur->Entry);
    72         }
    73 
    74         spin_unlock_irqrestore(&g_SfHandleLock, fSavedFlags);
     62    struct sf_handle *pCur, *pNext;
     63    unsigned long     fSavedFlags;
     64    SFLOGFLOW(("sf_handle_drop_chain: %p\n", pInodeInfo));
     65    spin_lock_irqsave(&g_SfHandleLock, fSavedFlags);
     66
     67    RTListForEachSafe(&pInodeInfo->HandleList, pCur, pNext, struct sf_handle, Entry) {
     68        AssertMsg((pCur->fFlags & (SF_HANDLE_F_MAGIC_MASK | SF_HANDLE_F_ON_LIST)) == (SF_HANDLE_F_MAGIC | SF_HANDLE_F_ON_LIST),
     69                  ("%p %#x\n", pCur, pCur->fFlags));
     70        pCur->fFlags |= SF_HANDLE_F_ON_LIST;
     71        RTListNodeRemove(&pCur->Entry);
     72    }
     73
     74    spin_unlock_irqrestore(&g_SfHandleLock, fSavedFlags);
    7575}
    7676
     
    8787struct sf_handle *sf_handle_find(struct sf_inode_info *pInodeInfo, uint32_t fFlagsSet, uint32_t fFlagsClear)
    8888{
    89         struct sf_handle *pCur;
    90         unsigned long     fSavedFlags;
    91         spin_lock_irqsave(&g_SfHandleLock, fSavedFlags);
    92 
    93         RTListForEach(&pInodeInfo->HandleList, pCur, struct sf_handle, Entry) {
    94                 AssertMsg((pCur->fFlags & (SF_HANDLE_F_MAGIC_MASK | SF_HANDLE_F_ON_LIST)) == (SF_HANDLE_F_MAGIC | SF_HANDLE_F_ON_LIST),
    95                           ("%p %#x\n", pCur, pCur->fFlags));
    96                 if ((pCur->fFlags & (fFlagsSet | fFlagsClear)) == fFlagsSet) {
    97                         uint32_t cRefs = ASMAtomicIncU32(&pCur->cRefs);
    98                         if (cRefs > 1) {
    99                                 spin_unlock_irqrestore(&g_SfHandleLock, fSavedFlags);
    100                                 SFLOGFLOW(("sf_handle_find: returns %p\n", pCur));
    101                                 return pCur;
    102                         }
    103                         /* Oops, already being closed (safe as it's only ever increased here). */
    104                         ASMAtomicDecU32(&pCur->cRefs);
    105                 }
    106         }
    107 
    108         spin_unlock_irqrestore(&g_SfHandleLock, fSavedFlags);
    109         SFLOGFLOW(("sf_handle_find: returns NULL!\n"));
    110         return NULL;
     89    struct sf_handle *pCur;
     90    unsigned long     fSavedFlags;
     91    spin_lock_irqsave(&g_SfHandleLock, fSavedFlags);
     92
     93    RTListForEach(&pInodeInfo->HandleList, pCur, struct sf_handle, Entry) {
     94        AssertMsg((pCur->fFlags & (SF_HANDLE_F_MAGIC_MASK | SF_HANDLE_F_ON_LIST)) == (SF_HANDLE_F_MAGIC | SF_HANDLE_F_ON_LIST),
     95                  ("%p %#x\n", pCur, pCur->fFlags));
     96        if ((pCur->fFlags & (fFlagsSet | fFlagsClear)) == fFlagsSet) {
     97            uint32_t cRefs = ASMAtomicIncU32(&pCur->cRefs);
     98            if (cRefs > 1) {
     99                spin_unlock_irqrestore(&g_SfHandleLock, fSavedFlags);
     100                SFLOGFLOW(("sf_handle_find: returns %p\n", pCur));
     101                return pCur;
     102            }
     103            /* Oops, already being closed (safe as it's only ever increased here). */
     104            ASMAtomicDecU32(&pCur->cRefs);
     105        }
     106    }
     107
     108    spin_unlock_irqrestore(&g_SfHandleLock, fSavedFlags);
     109    SFLOGFLOW(("sf_handle_find: returns NULL!\n"));
     110    return NULL;
    111111}
    112112
     
    118118 * @param   pHandle         The handle to release.
    119119 * @param   sf_g            The info structure for the shared folder associated
    120  *                          with the handle.
     120 *                  with the handle.
    121121 * @param   pszCaller       The caller name (for logging failures).
    122122 */
    123123uint32_t sf_handle_release_slow(struct sf_handle *pHandle, struct vbsf_super_info *sf_g, const char *pszCaller)
    124124{
    125         int rc;
    126         unsigned long fSavedFlags;
    127 
    128         SFLOGFLOW(("sf_handle_release_slow: %p (%s)\n", pHandle, pszCaller));
    129 
    130         /*
    131         * Remove from the list.
    132         */
    133         spin_lock_irqsave(&g_SfHandleLock, fSavedFlags);
    134 
    135         AssertMsg((pHandle->fFlags & SF_HANDLE_F_MAGIC_MASK) == SF_HANDLE_F_MAGIC, ("%p %#x\n", pHandle, pHandle->fFlags));
    136         Assert(pHandle->pInodeInfo);
    137         Assert(pHandle->pInodeInfo && pHandle->pInodeInfo->u32Magic == SF_INODE_INFO_MAGIC);
    138 
    139         if (pHandle->fFlags & SF_HANDLE_F_ON_LIST) {
    140                 pHandle->fFlags &= ~SF_HANDLE_F_ON_LIST;
    141                 RTListNodeRemove(&pHandle->Entry);
    142         }
    143 
    144         spin_unlock_irqrestore(&g_SfHandleLock, fSavedFlags);
    145 
    146         /*
    147         * Actually destroy it.
    148         */
    149         rc = VbglR0SfHostReqCloseSimple(sf_g->map.root, pHandle->hHost);
    150         if (RT_FAILURE(rc))
    151                 LogFunc(("Caller %s: VbglR0SfHostReqCloseSimple %#RX64 failed with rc=%Rrc\n", pszCaller, pHandle->hHost, rc));
    152         pHandle->hHost  = SHFL_HANDLE_NIL;
    153         pHandle->fFlags = SF_HANDLE_F_MAGIC_DEAD;
    154         kfree(pHandle);
    155         return 0;
     125    int rc;
     126    unsigned long fSavedFlags;
     127
     128    SFLOGFLOW(("sf_handle_release_slow: %p (%s)\n", pHandle, pszCaller));
     129
     130    /*
     131    * Remove from the list.
     132    */
     133    spin_lock_irqsave(&g_SfHandleLock, fSavedFlags);
     134
     135    AssertMsg((pHandle->fFlags & SF_HANDLE_F_MAGIC_MASK) == SF_HANDLE_F_MAGIC, ("%p %#x\n", pHandle, pHandle->fFlags));
     136    Assert(pHandle->pInodeInfo);
     137    Assert(pHandle->pInodeInfo && pHandle->pInodeInfo->u32Magic == SF_INODE_INFO_MAGIC);
     138
     139    if (pHandle->fFlags & SF_HANDLE_F_ON_LIST) {
     140        pHandle->fFlags &= ~SF_HANDLE_F_ON_LIST;
     141        RTListNodeRemove(&pHandle->Entry);
     142    }
     143
     144    spin_unlock_irqrestore(&g_SfHandleLock, fSavedFlags);
     145
     146    /*
     147    * Actually destroy it.
     148    */
     149    rc = VbglR0SfHostReqCloseSimple(sf_g->map.root, pHandle->hHost);
     150    if (RT_FAILURE(rc))
     151        LogFunc(("Caller %s: VbglR0SfHostReqCloseSimple %#RX64 failed with rc=%Rrc\n", pszCaller, pHandle->hHost, rc));
     152    pHandle->hHost  = SHFL_HANDLE_NIL;
     153    pHandle->fFlags = SF_HANDLE_F_MAGIC_DEAD;
     154    kfree(pHandle);
     155    return 0;
    156156}
    157157
     
    166166{
    167167#ifdef VBOX_STRICT
    168         struct sf_handle *pCur;
    169 #endif
    170         unsigned long fSavedFlags;
    171 
    172         SFLOGFLOW(("sf_handle_append: %p (to %p)\n", pHandle, pInodeInfo));
    173         AssertMsg((pHandle->fFlags & (SF_HANDLE_F_MAGIC_MASK | SF_HANDLE_F_ON_LIST)) == SF_HANDLE_F_MAGIC,
    174                   ("%p %#x\n", pHandle, pHandle->fFlags));
    175         Assert(pInodeInfo->u32Magic == SF_INODE_INFO_MAGIC);
    176 
    177         spin_lock_irqsave(&g_SfHandleLock, fSavedFlags);
    178 
    179         AssertMsg((pHandle->fFlags & (SF_HANDLE_F_MAGIC_MASK | SF_HANDLE_F_ON_LIST)) == SF_HANDLE_F_MAGIC,
    180                   ("%p %#x\n", pHandle, pHandle->fFlags));
     168    struct sf_handle *pCur;
     169#endif
     170    unsigned long fSavedFlags;
     171
     172    SFLOGFLOW(("sf_handle_append: %p (to %p)\n", pHandle, pInodeInfo));
     173    AssertMsg((pHandle->fFlags & (SF_HANDLE_F_MAGIC_MASK | SF_HANDLE_F_ON_LIST)) == SF_HANDLE_F_MAGIC,
     174          ("%p %#x\n", pHandle, pHandle->fFlags));
     175    Assert(pInodeInfo->u32Magic == SF_INODE_INFO_MAGIC);
     176
     177    spin_lock_irqsave(&g_SfHandleLock, fSavedFlags);
     178
     179    AssertMsg((pHandle->fFlags & (SF_HANDLE_F_MAGIC_MASK | SF_HANDLE_F_ON_LIST)) == SF_HANDLE_F_MAGIC,
     180          ("%p %#x\n", pHandle, pHandle->fFlags));
    181181#ifdef VBOX_STRICT
    182         RTListForEach(&pInodeInfo->HandleList, pCur, struct sf_handle, Entry) {
    183                 Assert(pCur != pHandle);
    184                 AssertMsg((pCur->fFlags & (SF_HANDLE_F_MAGIC_MASK | SF_HANDLE_F_ON_LIST)) == (SF_HANDLE_F_MAGIC | SF_HANDLE_F_ON_LIST),
    185                           ("%p %#x\n", pCur, pCur->fFlags));
    186         }
    187         pHandle->pInodeInfo = pInodeInfo;
    188 #endif
    189 
    190         pHandle->fFlags |= SF_HANDLE_F_ON_LIST;
    191         RTListAppend(&pInodeInfo->HandleList, &pHandle->Entry);
    192 
    193         spin_unlock_irqrestore(&g_SfHandleLock, fSavedFlags);
     182    RTListForEach(&pInodeInfo->HandleList, pCur, struct sf_handle, Entry) {
     183        Assert(pCur != pHandle);
     184        AssertMsg((pCur->fFlags & (SF_HANDLE_F_MAGIC_MASK | SF_HANDLE_F_ON_LIST)) == (SF_HANDLE_F_MAGIC | SF_HANDLE_F_ON_LIST),
     185              ("%p %#x\n", pCur, pCur->fFlags));
     186    }
     187    pHandle->pInodeInfo = pInodeInfo;
     188#endif
     189
     190    pHandle->fFlags |= SF_HANDLE_F_ON_LIST;
     191    RTListAppend(&pInodeInfo->HandleList, &pHandle->Entry);
     192
     193    spin_unlock_irqrestore(&g_SfHandleLock, fSavedFlags);
    194194}
    195195
     
    200200void free_pipebuf(struct page *kpage)
    201201{
    202         kunmap(kpage);
    203         __free_pages(kpage, 0);
     202    kunmap(kpage);
     203    __free_pages(kpage, 0);
    204204}
    205205
    206206void *sf_pipe_buf_map(struct pipe_inode_info *pipe,
    207                       struct pipe_buffer *pipe_buf, int atomic)
    208 {
    209         return 0;
     207              struct pipe_buffer *pipe_buf, int atomic)
     208{
     209    return 0;
    210210}
    211211
     
    215215
    216216void sf_pipe_buf_unmap(struct pipe_inode_info *pipe,
    217                        struct pipe_buffer *pipe_buf, void *map_data)
     217               struct pipe_buffer *pipe_buf, void *map_data)
    218218{
    219219}
    220220
    221221int sf_pipe_buf_steal(struct pipe_inode_info *pipe,
    222                       struct pipe_buffer *pipe_buf)
    223 {
    224         return 0;
     222              struct pipe_buffer *pipe_buf)
     223{
     224    return 0;
    225225}
    226226
    227227static void sf_pipe_buf_release(struct pipe_inode_info *pipe,
    228                                 struct pipe_buffer *pipe_buf)
    229 {
    230         free_pipebuf(pipe_buf->page);
     228                struct pipe_buffer *pipe_buf)
     229{
     230    free_pipebuf(pipe_buf->page);
    231231}
    232232
    233233int sf_pipe_buf_confirm(struct pipe_inode_info *info,
    234                         struct pipe_buffer *pipe_buf)
    235 {
    236         return 0;
     234            struct pipe_buffer *pipe_buf)
     235{
     236    return 0;
    237237}
    238238
    239239static struct pipe_buf_operations sf_pipe_buf_ops = {
    240         .can_merge = 0,
    241         .map = sf_pipe_buf_map,
    242         .unmap = sf_pipe_buf_unmap,
    243         .confirm = sf_pipe_buf_confirm,
    244         .release = sf_pipe_buf_release,
    245         .steal = sf_pipe_buf_steal,
    246         .get = sf_pipe_buf_get,
     240    .can_merge = 0,
     241    .map = sf_pipe_buf_map,
     242    .unmap = sf_pipe_buf_unmap,
     243    .confirm = sf_pipe_buf_confirm,
     244    .release = sf_pipe_buf_release,
     245    .steal = sf_pipe_buf_steal,
     246    .get = sf_pipe_buf_get,
    247247};
    248248
    249249static int sf_reg_read_aux(const char *caller, struct vbsf_super_info *sf_g,
    250                            struct sf_reg_info *sf_r, void *buf,
    251                            uint32_t * nread, uint64_t pos)
    252 {
    253         int rc = VbglR0SfRead(&client_handle, &sf_g->map, sf_r->Handle.hHost,
    254                               pos, nread, buf, false /* already locked? */ );
    255         if (RT_FAILURE(rc)) {
    256                 LogFunc(("VbglR0SfRead failed. caller=%s, rc=%Rrc\n", caller,
    257                         rc));
    258                 return -EPROTO;
    259         }
    260         return 0;
     250               struct sf_reg_info *sf_r, void *buf,
     251               uint32_t * nread, uint64_t pos)
     252{
     253    int rc = VbglR0SfRead(&client_handle, &sf_g->map, sf_r->Handle.hHost,
     254                  pos, nread, buf, false /* already locked? */ );
     255    if (RT_FAILURE(rc)) {
     256        LogFunc(("VbglR0SfRead failed. caller=%s, rc=%Rrc\n", caller,
     257            rc));
     258        return -EPROTO;
     259    }
     260    return 0;
    261261}
    262262
     
    266266ssize_t
    267267sf_splice_read(struct file *in, loff_t * poffset,
    268                struct pipe_inode_info *pipe, size_t len, unsigned int flags)
    269 {
    270         size_t bytes_remaining = len;
    271         loff_t orig_offset = *poffset;
    272         loff_t offset = orig_offset;
    273         struct inode *inode = GET_F_DENTRY(in)->d_inode;
    274         struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
    275         struct sf_reg_info *sf_r = in->private_data;
    276         ssize_t retval;
    277         struct page *kpage = 0;
    278         size_t nsent = 0;
     268           struct pipe_inode_info *pipe, size_t len, unsigned int flags)
     269{
     270    size_t bytes_remaining = len;
     271    loff_t orig_offset = *poffset;
     272    loff_t offset = orig_offset;
     273    struct inode *inode = GET_F_DENTRY(in)->d_inode;
     274    struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
     275    struct sf_reg_info *sf_r = in->private_data;
     276    ssize_t retval;
     277    struct page *kpage = 0;
     278    size_t nsent = 0;
    279279
    280280/** @todo rig up a FsPerf test for this code  */
    281         TRACE();
    282         if (!S_ISREG(inode->i_mode)) {
    283                 LogFunc(("read from non regular file %d\n", inode->i_mode));
    284                 return -EINVAL;
    285         }
    286         if (!len) {
    287                 return 0;
    288         }
    289 
    290         LOCK_PIPE(pipe);
    291 
    292         uint32_t req_size = 0;
    293         while (bytes_remaining > 0) {
    294                 kpage = alloc_page(GFP_KERNEL);
    295                 if (unlikely(kpage == NULL)) {
    296                         UNLOCK_PIPE(pipe);
    297                         return -ENOMEM;
    298                 }
    299                 req_size = 0;
    300                 uint32_t nread = req_size =
    301                     (uint32_t) min(bytes_remaining, (size_t) PAGE_SIZE);
    302                 uint32_t chunk = 0;
    303                 void *kbuf = kmap(kpage);
    304                 while (chunk < req_size) {
    305                         retval =
    306                             sf_reg_read_aux(__func__, sf_g, sf_r, kbuf + chunk,
    307                                             &nread, offset);
    308                         if (retval < 0)
    309                                 goto err;
    310                         if (nread == 0)
    311                                 break;
    312                         chunk += nread;
    313                         offset += nread;
    314                         nread = req_size - chunk;
    315                 }
    316                 if (!pipe->readers) {
    317                         send_sig(SIGPIPE, current, 0);
    318                         retval = -EPIPE;
    319                         goto err;
    320                 }
    321                 if (pipe->nrbufs < PIPE_BUFFERS) {
    322                         struct pipe_buffer *pipebuf =
    323                             pipe->bufs +
    324                             ((pipe->curbuf + pipe->nrbufs) & (PIPE_BUFFERS -
    325                                                               1));
    326                         pipebuf->page = kpage;
    327                         pipebuf->ops = &sf_pipe_buf_ops;
    328                         pipebuf->len = req_size;
    329                         pipebuf->offset = 0;
    330                         pipebuf->private = 0;
    331                         pipebuf->flags = 0;
    332                         pipe->nrbufs++;
    333                         nsent += req_size;
    334                         bytes_remaining -= req_size;
    335                         if (signal_pending(current))
    336                                 break;
    337                 } else {        /* pipe full */
    338 
    339                         if (flags & SPLICE_F_NONBLOCK) {
    340                                 retval = -EAGAIN;
    341                                 goto err;
    342                         }
    343                         free_pipebuf(kpage);
    344                         break;
    345                 }
    346         }
    347         UNLOCK_PIPE(pipe);
    348         if (!nsent && signal_pending(current))
    349                 return -ERESTARTSYS;
    350         *poffset += nsent;
    351         return offset - orig_offset;
     281    TRACE();
     282    if (!S_ISREG(inode->i_mode)) {
     283        LogFunc(("read from non regular file %d\n", inode->i_mode));
     284        return -EINVAL;
     285    }
     286    if (!len) {
     287        return 0;
     288    }
     289
     290    LOCK_PIPE(pipe);
     291
     292    uint32_t req_size = 0;
     293    while (bytes_remaining > 0) {
     294        kpage = alloc_page(GFP_KERNEL);
     295        if (unlikely(kpage == NULL)) {
     296            UNLOCK_PIPE(pipe);
     297            return -ENOMEM;
     298        }
     299        req_size = 0;
     300        uint32_t nread = req_size =
     301            (uint32_t) min(bytes_remaining, (size_t) PAGE_SIZE);
     302        uint32_t chunk = 0;
     303        void *kbuf = kmap(kpage);
     304        while (chunk < req_size) {
     305            retval =
     306                sf_reg_read_aux(__func__, sf_g, sf_r, kbuf + chunk,
     307                        &nread, offset);
     308            if (retval < 0)
     309                goto err;
     310            if (nread == 0)
     311                break;
     312            chunk += nread;
     313            offset += nread;
     314            nread = req_size - chunk;
     315        }
     316        if (!pipe->readers) {
     317            send_sig(SIGPIPE, current, 0);
     318            retval = -EPIPE;
     319            goto err;
     320        }
     321        if (pipe->nrbufs < PIPE_BUFFERS) {
     322            struct pipe_buffer *pipebuf =
     323                pipe->bufs +
     324                ((pipe->curbuf + pipe->nrbufs) & (PIPE_BUFFERS -
     325                                  1));
     326            pipebuf->page = kpage;
     327            pipebuf->ops = &sf_pipe_buf_ops;
     328            pipebuf->len = req_size;
     329            pipebuf->offset = 0;
     330            pipebuf->private = 0;
     331            pipebuf->flags = 0;
     332            pipe->nrbufs++;
     333            nsent += req_size;
     334            bytes_remaining -= req_size;
     335            if (signal_pending(current))
     336                break;
     337        } else {    /* pipe full */
     338
     339            if (flags & SPLICE_F_NONBLOCK) {
     340                retval = -EAGAIN;
     341                goto err;
     342            }
     343            free_pipebuf(kpage);
     344            break;
     345        }
     346    }
     347    UNLOCK_PIPE(pipe);
     348    if (!nsent && signal_pending(current))
     349        return -ERESTARTSYS;
     350    *poffset += nsent;
     351    return offset - orig_offset;
    352352
    353353 err:
    354         UNLOCK_PIPE(pipe);
    355         free_pipebuf(kpage);
    356         return retval;
     354    UNLOCK_PIPE(pipe);
     355    free_pipebuf(kpage);
     356    return retval;
    357357}
    358358
     
    365365    while (cPages-- > 0)
    366366    {
    367         struct page *pPage = papPages[cPages];
    368         if (fSetDirty && !PageReserved(pPage))
    369             SetPageDirty(pPage);
     367    struct page *pPage = papPages[cPages];
     368    if (fSetDirty && !PageReserved(pPage))
     369        SetPageDirty(pPage);
    370370#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
    371         put_page(pPage);
     371    put_page(pPage);
    372372#else
    373         page_cache_release(pPage);
     373    page_cache_release(pPage);
    374374#endif
    375375    }
     
    381381{
    382382# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
    383         ssize_t cPagesLocked = get_user_pages_unlocked(uPtrFrom, cPages, papPages,
    384                                                        fWrite ? FOLL_WRITE | FOLL_FORCE : FOLL_FORCE);
     383    ssize_t cPagesLocked = get_user_pages_unlocked(uPtrFrom, cPages, papPages,
     384                               fWrite ? FOLL_WRITE | FOLL_FORCE : FOLL_FORCE);
    385385# elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
    386         ssize_t cPagesLocked = get_user_pages_unlocked(uPtrFrom, cPages, fWrite, 1 /*force*/, papPages);
     386    ssize_t cPagesLocked = get_user_pages_unlocked(uPtrFrom, cPages, fWrite, 1 /*force*/, papPages);
    387387# elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
    388         ssize_t cPagesLocked = get_user_pages_unlocked(current, current->mm, uPtrFrom, cPages,
    389                                                        fWrite, 1 /*force*/, papPages);
     388    ssize_t cPagesLocked = get_user_pages_unlocked(current, current->mm, uPtrFrom, cPages,
     389                               fWrite, 1 /*force*/, papPages);
    390390# else
    391         struct task_struct *pTask = current;
    392         size_t cPagesLocked;
    393         down_read(&pTask->mm->mmap_sem);
    394         cPagesLocked = get_user_pages(current, current->mm, uPtrFrom, cPages, fWrite, 1 /*force*/, papPages, NULL);
    395         up_read(&pTask->mm->mmap_sem);
     391    struct task_struct *pTask = current;
     392    size_t cPagesLocked;
     393    down_read(&pTask->mm->mmap_sem);
     394    cPagesLocked = get_user_pages(current, current->mm, uPtrFrom, cPages, fWrite, 1 /*force*/, papPages, NULL);
     395    up_read(&pTask->mm->mmap_sem);
    396396# endif
    397         if (cPagesLocked == cPages)
    398             return 0;
    399         if (cPagesLocked < 0)
    400             return cPagesLocked;
    401 
    402         sf_unlock_user_pages(papPages, cPagesLocked, false /*fSetDirty*/);
    403 
    404         /* We could use uPtrFrom + cPagesLocked to get the correct status here... */
    405         return -EFAULT;
     397    if (cPagesLocked == cPages)
     398        return 0;
     399    if (cPagesLocked < 0)
     400        return cPagesLocked;
     401
     402    sf_unlock_user_pages(papPages, cPagesLocked, false /*fSetDirty*/);
     403
     404    /* We could use uPtrFrom + cPagesLocked to get the correct status here... */
     405    return -EFAULT;
    406406}
    407407
     
    416416{
    417417#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
    418         struct iovec    iov = { .iov_base = buf, .iov_len = size };
    419         struct iov_iter iter;
    420         struct kiocb    kiocb;
    421         ssize_t         cbRet;
    422 
    423         init_sync_kiocb(&kiocb, file);
    424         kiocb.ki_pos = *off;
    425         iov_iter_init(&iter, READ, &iov, 1, size);
    426 
    427         cbRet = generic_file_read_iter(&kiocb, &iter);
    428 
    429         *off = kiocb.ki_pos;
    430         return cbRet;
     418    struct iovec    iov = { .iov_base = buf, .iov_len = size };
     419    struct iov_iter iter;
     420    struct kiocb    kiocb;
     421    ssize_t         cbRet;
     422
     423    init_sync_kiocb(&kiocb, file);
     424    kiocb.ki_pos = *off;
     425    iov_iter_init(&iter, READ, &iov, 1, size);
     426
     427    cbRet = generic_file_read_iter(&kiocb, &iter);
     428
     429    *off = kiocb.ki_pos;
     430    return cbRet;
    431431
    432432#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
    433         struct iovec    iov = { .iov_base = buf, .iov_len = size };
    434         struct kiocb    kiocb;
    435         ssize_t         cbRet;
    436 
    437         init_sync_kiocb(&kiocb, file);
    438         kiocb.ki_pos = *off;
    439 
    440         cbRet = generic_file_aio_read(&kiocb, &iov, 1, *off);
    441         if (cbRet == -EIOCBQUEUED)
    442                 cbRet = wait_on_sync_kiocb(&kiocb);
    443 
    444         *off = kiocb.ki_pos;
    445         return cbRet;
     433    struct iovec    iov = { .iov_base = buf, .iov_len = size };
     434    struct kiocb    kiocb;
     435    ssize_t         cbRet;
     436
     437    init_sync_kiocb(&kiocb, file);
     438    kiocb.ki_pos = *off;
     439
     440    cbRet = generic_file_aio_read(&kiocb, &iov, 1, *off);
     441    if (cbRet == -EIOCBQUEUED)
     442        cbRet = wait_on_sync_kiocb(&kiocb);
     443
     444    *off = kiocb.ki_pos;
     445    return cbRet;
    446446
    447447#else /* 2.6.18 or earlier: */
    448         return generic_file_read(file, buf, size, off);
     448    return generic_file_read(file, buf, size, off);
    449449#endif
    450450}
     
    456456 */
    457457static ssize_t sf_reg_read_fallback(struct file *file, char /*__user*/ *buf, size_t size, loff_t *off,
    458                                     struct vbsf_super_info *sf_g, struct sf_reg_info *sf_r)
    459 {
    460         /*
    461         * Lock pages and execute the read, taking care not to pass the host
    462         * more than it can handle in one go or more than we care to allocate
    463         * page arrays for.  The latter limit is set at just short of 32KB due
    464         * to how the physical heap works.
    465         */
    466         struct page        *apPagesStack[16];
    467         struct page       **papPages     = &apPagesStack[0];
    468         struct page       **papPagesFree = NULL;
    469         VBOXSFREADPGLSTREQ *pReq;
    470         loff_t              offFile      = *off;
    471         ssize_t             cbRet        = -ENOMEM;
    472         size_t              cPages       = (((uintptr_t)buf & PAGE_OFFSET_MASK) + size + PAGE_OFFSET_MASK) >> PAGE_SHIFT;
    473         size_t              cMaxPages    = RT_MIN(RT_MAX(sf_g->cMaxIoPages, 1), cPages);
    474 
    475         pReq = (VBOXSFREADPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFREADPGLSTREQ, PgLst.aPages[cMaxPages]));
    476         while (!pReq && cMaxPages > 4) {
    477                 cMaxPages /= 2;
    478                 pReq = (VBOXSFREADPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFREADPGLSTREQ, PgLst.aPages[cMaxPages]));
    479         }
    480         if (pReq && cPages > RT_ELEMENTS(apPagesStack))
    481                 papPagesFree = papPages = kmalloc(cMaxPages * sizeof(sizeof(papPages[0])), GFP_KERNEL);
    482         if (pReq && papPages) {
    483                 cbRet = 0;
    484                 for (;;) {
    485                         /*
    486                         * Figure out how much to process now and lock the user pages.
    487                         */
    488                         int    rc;
    489                         size_t cbChunk = (uintptr_t)buf & PAGE_OFFSET_MASK;
    490                         pReq->PgLst.offFirstPage = (uint16_t)cbChunk;
    491                         cPages  = RT_ALIGN_Z(cbChunk + size, PAGE_SIZE) >> PAGE_SHIFT;
    492                         if (cPages <= cMaxPages)
    493                                 cbChunk = size;
    494                         else {
    495                                 cPages  = cMaxPages;
    496                                 cbChunk = (cMaxPages << PAGE_SHIFT) - cbChunk;
    497                         }
    498 
    499                         rc = sf_lock_user_pages((uintptr_t)buf, cPages, true /*fWrite*/, papPages);
    500                         if (rc == 0) {
    501                                 size_t iPage = cPages;
    502                                 while (iPage-- > 0)
    503                                         pReq->PgLst.aPages[iPage] = page_to_phys(papPages[iPage]);
    504                         } else {
    505                                 cbRet = rc;
    506                                 break;
    507                         }
    508 
    509                         /*
    510                         * Issue the request and unlock the pages.
    511                         */
    512                         rc = VbglR0SfHostReqReadPgLst(sf_g->map.root, pReq, sf_r->Handle.hHost, offFile, cbChunk, cPages);
    513 
    514                         sf_unlock_user_pages(papPages, cPages, true /*fSetDirty*/);
    515 
    516                         if (RT_SUCCESS(rc)) {
    517                                 /*
    518                                 * Success, advance position and buffer.
    519                                 */
    520                                 uint32_t cbActual = pReq->Parms.cb32Read.u.value32;
    521                                 AssertStmt(cbActual <= cbChunk, cbActual = cbChunk);
    522                                 cbRet   += cbActual;
    523                                 offFile += cbActual;
    524                                 buf      = (uint8_t *)buf + cbActual;
    525                                 size    -= cbActual;
    526 
    527                                 /*
    528                                 * Are we done already?  If so commit the new file offset.
    529                                 */
    530                                 if (!size || cbActual < cbChunk) {
    531                                         *off = offFile;
    532                                         break;
    533                                 }
    534                         } else if (rc == VERR_NO_MEMORY && cMaxPages > 4) {
    535                                 /*
    536                                 * The host probably doesn't have enough heap to handle the
    537                                 * request, reduce the page count and retry.
    538                                 */
    539                                 cMaxPages /= 4;
    540                                 Assert(cMaxPages > 0);
    541                         } else {
    542                                 /*
    543                                 * If we've successfully read stuff, return it rather than
    544                                 * the error.  (Not sure if this is such a great idea...)
    545                                 */
    546                                 if (cbRet > 0)
    547                                         *off = offFile;
    548                                 else
    549                                         cbRet = -EPROTO;
    550                                 break;
    551                         }
    552                 }
    553         }
    554         if (papPagesFree)
    555                 kfree(papPages);
    556         if (pReq)
    557                 VbglR0PhysHeapFree(pReq);
    558         return cbRet;
     458                                    struct vbsf_super_info *sf_g, struct sf_reg_info *sf_r)
     459{
     460    /*
     461    * Lock pages and execute the read, taking care not to pass the host
     462    * more than it can handle in one go or more than we care to allocate
     463    * page arrays for.  The latter limit is set at just short of 32KB due
     464    * to how the physical heap works.
     465    */
     466    struct page        *apPagesStack[16];
     467    struct page       **papPages     = &apPagesStack[0];
     468    struct page       **papPagesFree = NULL;
     469    VBOXSFREADPGLSTREQ *pReq;
     470    loff_t              offFile      = *off;
     471    ssize_t             cbRet        = -ENOMEM;
     472    size_t              cPages       = (((uintptr_t)buf & PAGE_OFFSET_MASK) + size + PAGE_OFFSET_MASK) >> PAGE_SHIFT;
     473    size_t              cMaxPages    = RT_MIN(RT_MAX(sf_g->cMaxIoPages, 1), cPages);
     474
     475    pReq = (VBOXSFREADPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFREADPGLSTREQ, PgLst.aPages[cMaxPages]));
     476    while (!pReq && cMaxPages > 4) {
     477        cMaxPages /= 2;
     478        pReq = (VBOXSFREADPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFREADPGLSTREQ, PgLst.aPages[cMaxPages]));
     479    }
     480    if (pReq && cPages > RT_ELEMENTS(apPagesStack))
     481        papPagesFree = papPages = kmalloc(cMaxPages * sizeof(sizeof(papPages[0])), GFP_KERNEL);
     482    if (pReq && papPages) {
     483        cbRet = 0;
     484        for (;;) {
     485            /*
     486            * Figure out how much to process now and lock the user pages.
     487            */
     488            int    rc;
     489            size_t cbChunk = (uintptr_t)buf & PAGE_OFFSET_MASK;
     490            pReq->PgLst.offFirstPage = (uint16_t)cbChunk;
     491            cPages  = RT_ALIGN_Z(cbChunk + size, PAGE_SIZE) >> PAGE_SHIFT;
     492            if (cPages <= cMaxPages)
     493                cbChunk = size;
     494            else {
     495                cPages  = cMaxPages;
     496                cbChunk = (cMaxPages << PAGE_SHIFT) - cbChunk;
     497            }
     498
     499            rc = sf_lock_user_pages((uintptr_t)buf, cPages, true /*fWrite*/, papPages);
     500            if (rc == 0) {
     501                size_t iPage = cPages;
     502                while (iPage-- > 0)
     503                    pReq->PgLst.aPages[iPage] = page_to_phys(papPages[iPage]);
     504            } else {
     505                cbRet = rc;
     506                break;
     507            }
     508
     509            /*
     510            * Issue the request and unlock the pages.
     511            */
     512            rc = VbglR0SfHostReqReadPgLst(sf_g->map.root, pReq, sf_r->Handle.hHost, offFile, cbChunk, cPages);
     513
     514            sf_unlock_user_pages(papPages, cPages, true /*fSetDirty*/);
     515
     516            if (RT_SUCCESS(rc)) {
     517                /*
     518                * Success, advance position and buffer.
     519                */
     520                uint32_t cbActual = pReq->Parms.cb32Read.u.value32;
     521                AssertStmt(cbActual <= cbChunk, cbActual = cbChunk);
     522                cbRet   += cbActual;
     523                offFile += cbActual;
     524                buf      = (uint8_t *)buf + cbActual;
     525                size    -= cbActual;
     526
     527                /*
     528                * Are we done already?  If so commit the new file offset.
     529                */
     530                if (!size || cbActual < cbChunk) {
     531                    *off = offFile;
     532                    break;
     533                }
     534            } else if (rc == VERR_NO_MEMORY && cMaxPages > 4) {
     535                /*
     536                * The host probably doesn't have enough heap to handle the
     537                * request, reduce the page count and retry.
     538                */
     539                cMaxPages /= 4;
     540                Assert(cMaxPages > 0);
     541            } else {
     542                /*
     543                * If we've successfully read stuff, return it rather than
     544                * the error.  (Not sure if this is such a great idea...)
     545                */
     546                if (cbRet > 0)
     547                    *off = offFile;
     548                else
     549                    cbRet = -EPROTO;
     550                break;
     551            }
     552        }
     553    }
     554    if (papPagesFree)
     555        kfree(papPages);
     556    if (pReq)
     557        VbglR0PhysHeapFree(pReq);
     558    return cbRet;
    559559}
    560560
     
    569569 * @returns the number of read bytes on success, Linux error code otherwise
    570570 */
    571 static ssize_t sf_reg_read(struct file *file, char /*__user*/ *buf, size_t size,
    572                            loff_t *off)
    573 {
    574         struct inode *inode = GET_F_DENTRY(file)->d_inode;
    575         struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
    576         struct sf_reg_info *sf_r = file->private_data;
    577         struct address_space *mapping = inode->i_mapping;
    578 
    579         SFLOGFLOW(("sf_reg_read: inode=%p file=%p buf=%p size=%#zx off=%#llx\n", inode, file, buf, size, *off));
    580 
    581         if (!S_ISREG(inode->i_mode)) {
    582                 LogFunc(("read from non regular file %d\n", inode->i_mode));
    583                 return -EINVAL;
    584         }
    585 
    586         /** @todo XXX Check read permission according to inode->i_mode! */
    587 
    588         if (!size)
    589                 return 0;
    590 
    591         /*
    592          * If there is a mapping and O_DIRECT isn't in effect, we must at a
    593          * heed dirty pages in the mapping and read from them.  For simplicity
    594          * though, we just do page cache reading when there are writable
    595          * mappings around with any kind of pages loaded.
    596          */
    597         if (   mapping
    598             && mapping->nrpages > 0
    599             && mapping_writably_mapped(mapping)
    600             && !(file->f_flags & O_DIRECT)
    601             && 1 /** @todo make this behaviour configurable */ )
    602                 return sf_reg_read_mapped(file, buf, size, off);
    603 
    604         /*
    605          * For small requests, try use an embedded buffer provided we get a heap block
    606          * that does not cross page boundraries (see host code).
    607          */
    608         if (size <= PAGE_SIZE / 4 * 3 - RT_UOFFSETOF(VBOXSFREADEMBEDDEDREQ, abData[0]) /* see allocator */) {
    609                 uint32_t const         cbReq = RT_UOFFSETOF(VBOXSFREADEMBEDDEDREQ, abData[0]) + size;
    610                 VBOXSFREADEMBEDDEDREQ *pReq  = (VBOXSFREADEMBEDDEDREQ *)VbglR0PhysHeapAlloc(cbReq);
    611                 if (   pReq
    612                     && (PAGE_SIZE - ((uintptr_t)pReq & PAGE_OFFSET_MASK)) >= cbReq) {
    613                         ssize_t cbRet;
    614                         int vrc = VbglR0SfHostReqReadEmbedded(sf_g->map.root, pReq, sf_r->Handle.hHost, *off, (uint32_t)size);
    615                         if (RT_SUCCESS(vrc)) {
    616                                 cbRet = pReq->Parms.cb32Read.u.value32;
    617                                 AssertStmt(cbRet <= (ssize_t)size, cbRet = size);
    618                                 if (copy_to_user(buf, pReq->abData, cbRet) == 0)
    619                                         *off += cbRet;
    620                                 else
    621                                         cbRet = -EFAULT;
    622                         } else
    623                                 cbRet = -EPROTO;
    624                         VbglR0PhysHeapFree(pReq);
    625                         return cbRet;
    626                 }
    627                 if (pReq)
    628                         VbglR0PhysHeapFree(pReq);
    629         }
     571static ssize_t sf_reg_read(struct file *file, char /*__user*/ *buf, size_t size, loff_t *off)
     572{
     573    struct inode *inode = GET_F_DENTRY(file)->d_inode;
     574    struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
     575    struct sf_reg_info *sf_r = file->private_data;
     576    struct address_space *mapping = inode->i_mapping;
     577
     578    SFLOGFLOW(("sf_reg_read: inode=%p file=%p buf=%p size=%#zx off=%#llx\n", inode, file, buf, size, *off));
     579
     580    if (!S_ISREG(inode->i_mode)) {
     581        LogFunc(("read from non regular file %d\n", inode->i_mode));
     582        return -EINVAL;
     583    }
     584
     585    /** @todo XXX Check read permission according to inode->i_mode! */
     586
     587    if (!size)
     588        return 0;
     589
     590    /*
     591     * If there is a mapping and O_DIRECT isn't in effect, we must at a
     592     * heed dirty pages in the mapping and read from them.  For simplicity
     593     * though, we just do page cache reading when there are writable
     594     * mappings around with any kind of pages loaded.
     595     */
     596    if (   mapping
     597        && mapping->nrpages > 0
     598        && mapping_writably_mapped(mapping)
     599        && !(file->f_flags & O_DIRECT)
     600        && 1 /** @todo make this behaviour configurable */ )
     601        return sf_reg_read_mapped(file, buf, size, off);
     602
     603    /*
     604     * For small requests, try use an embedded buffer provided we get a heap block
     605     * that does not cross page boundraries (see host code).
     606     */
     607    if (size <= PAGE_SIZE / 4 * 3 - RT_UOFFSETOF(VBOXSFREADEMBEDDEDREQ, abData[0]) /* see allocator */) {
     608        uint32_t const         cbReq = RT_UOFFSETOF(VBOXSFREADEMBEDDEDREQ, abData[0]) + size;
     609        VBOXSFREADEMBEDDEDREQ *pReq  = (VBOXSFREADEMBEDDEDREQ *)VbglR0PhysHeapAlloc(cbReq);
     610        if (   pReq
     611            && (PAGE_SIZE - ((uintptr_t)pReq & PAGE_OFFSET_MASK)) >= cbReq) {
     612            ssize_t cbRet;
     613            int vrc = VbglR0SfHostReqReadEmbedded(sf_g->map.root, pReq, sf_r->Handle.hHost, *off, (uint32_t)size);
     614            if (RT_SUCCESS(vrc)) {
     615                cbRet = pReq->Parms.cb32Read.u.value32;
     616                AssertStmt(cbRet <= (ssize_t)size, cbRet = size);
     617                if (copy_to_user(buf, pReq->abData, cbRet) == 0)
     618                    *off += cbRet;
     619                else
     620                    cbRet = -EFAULT;
     621            } else
     622                cbRet = -EPROTO;
     623            VbglR0PhysHeapFree(pReq);
     624            return cbRet;
     625        }
     626        if (pReq)
     627            VbglR0PhysHeapFree(pReq);
     628    }
    630629
    631630#if 0 /* Turns out this is slightly slower than locking the pages even for 4KB reads (4.19/amd64). */
    632         /*
    633         * For medium sized requests try use a bounce buffer.
    634         */
    635         if (size <= _64K /** @todo make this configurable? */) {
    636                 void *pvBounce = kmalloc(size, GFP_KERNEL);
    637                 if (pvBounce) {
    638                         VBOXSFREADPGLSTREQ *pReq = (VBOXSFREADPGLSTREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
    639                         if (pReq) {
    640                                 ssize_t cbRet;
    641                                 int vrc = VbglR0SfHostReqReadContig(sf_g->map.root, pReq, sf_r->Handle.hHost, *off,
    642                                                                     (uint32_t)size, pvBounce, virt_to_phys(pvBounce));
    643                                 if (RT_SUCCESS(vrc)) {
    644                                         cbRet = pReq->Parms.cb32Read.u.value32;
    645                                         AssertStmt(cbRet <= (ssize_t)size, cbRet = size);
    646                                         if (copy_to_user(buf, pvBounce, cbRet) == 0)
    647                                                 *off += cbRet;
    648                                         else
    649                                                 cbRet = -EFAULT;
    650                                 } else
    651                                         cbRet = -EPROTO;
    652                                 VbglR0PhysHeapFree(pReq);
    653                                 kfree(pvBounce);
    654                                 return cbRet;
    655                         }
    656                         kfree(pvBounce);
    657                 }
    658         }
    659 #endif
    660 
    661         return sf_reg_read_fallback(file, buf, size, off, sf_g, sf_r);
     631    /*
     632    * For medium sized requests try use a bounce buffer.
     633    */
     634    if (size <= _64K /** @todo make this configurable? */) {
     635        void *pvBounce = kmalloc(size, GFP_KERNEL);
     636        if (pvBounce) {
     637            VBOXSFREADPGLSTREQ *pReq = (VBOXSFREADPGLSTREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
     638            if (pReq) {
     639                ssize_t cbRet;
     640                int vrc = VbglR0SfHostReqReadContig(sf_g->map.root, pReq, sf_r->Handle.hHost, *off,
     641                                                    (uint32_t)size, pvBounce, virt_to_phys(pvBounce));
     642                if (RT_SUCCESS(vrc)) {
     643                    cbRet = pReq->Parms.cb32Read.u.value32;
     644                    AssertStmt(cbRet <= (ssize_t)size, cbRet = size);
     645                    if (copy_to_user(buf, pvBounce, cbRet) == 0)
     646                        *off += cbRet;
     647                    else
     648                        cbRet = -EFAULT;
     649                } else
     650                    cbRet = -EPROTO;
     651                VbglR0PhysHeapFree(pReq);
     652                kfree(pvBounce);
     653                return cbRet;
     654            }
     655            kfree(pvBounce);
     656        }
     657    }
     658#endif
     659
     660    return sf_reg_read_fallback(file, buf, size, off, sf_g, sf_r);
    662661}
    663662
     
    669668DECLINLINE(void) sf_reg_write_invalidate_mapping_range(struct address_space *mapping, loff_t offStart, loff_t offEnd)
    670669{
    671         /*
    672         * Only bother with this if the mapping has any pages in it.
    673         *
    674         * Note! According to the docs, the last parameter, end, is inclusive (we
    675         *       would have named it 'last' to indicate this).
    676         *
    677         * Note! The pre-2.6.12 function might not do enough to sure consistency
    678         *       when any of the pages in the range is already mapped.
    679         */
     670    /*
     671    * Only bother with this if the mapping has any pages in it.
     672    *
     673    * Note! According to the docs, the last parameter, end, is inclusive (we
     674    *       would have named it 'last' to indicate this).
     675    *
     676    * Note! The pre-2.6.12 function might not do enough to sure consistency
     677    *       when any of the pages in the range is already mapped.
     678    */
    680679# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12)
    681         if (mapping)
    682                 invalidate_inode_pages2_range(mapping, offStart >> PAGE_SHIFT, (offEnd - 1) >> PAGE_SHIFT);
     680    if (mapping)
     681        invalidate_inode_pages2_range(mapping, offStart >> PAGE_SHIFT, (offEnd - 1) >> PAGE_SHIFT);
    683682# elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 60)
    684         if (mapping && mapping->nrpages > 0)
    685                 invalidate_mapping_pages(mapping, offStart >> PAGE_SHIFT, (offEnd - 1) >> PAGE_SHIFT);
     683    if (mapping && mapping->nrpages > 0)
     684        invalidate_mapping_pages(mapping, offStart >> PAGE_SHIFT, (offEnd - 1) >> PAGE_SHIFT);
    686685# else
    687         /** @todo ... */
    688         RT_NOREF(mapping, offStart, offEnd);
     686    /** @todo ... */
     687    RT_NOREF(mapping, offStart, offEnd);
    689688# endif
    690689}
     
    696695 */
    697696static ssize_t sf_reg_write_fallback(struct file *file, const char /*__user*/ *buf, size_t size, loff_t *off, loff_t offFile,
    698                                      struct inode *inode, struct sf_inode_info *sf_i,
    699                                      struct vbsf_super_info *sf_g, struct sf_reg_info *sf_r)
    700 {
    701         /*
    702         * Lock pages and execute the write, taking care not to pass the host
    703         * more than it can handle in one go or more than we care to allocate
    704         * page arrays for.  The latter limit is set at just short of 32KB due
    705         * to how the physical heap works.
    706         */
    707         struct page         *apPagesStack[16];
    708         struct page        **papPages     = &apPagesStack[0];
    709         struct page        **papPagesFree = NULL;
    710         VBOXSFWRITEPGLSTREQ *pReq;
    711         ssize_t              cbRet        = -ENOMEM;
    712         size_t               cPages       = (((uintptr_t)buf & PAGE_OFFSET_MASK) + size + PAGE_OFFSET_MASK) >> PAGE_SHIFT;
    713         size_t               cMaxPages    = RT_MIN(RT_MAX(sf_g->cMaxIoPages, 1), cPages);
    714 
    715         pReq = (VBOXSFWRITEPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFWRITEPGLSTREQ, PgLst.aPages[cMaxPages]));
    716         while (!pReq && cMaxPages > 4) {
    717                 cMaxPages /= 2;
    718                 pReq = (VBOXSFWRITEPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFWRITEPGLSTREQ, PgLst.aPages[cMaxPages]));
    719         }
    720         if (pReq && cPages > RT_ELEMENTS(apPagesStack))
    721                 papPagesFree = papPages = kmalloc(cMaxPages * sizeof(sizeof(papPages[0])), GFP_KERNEL);
    722         if (pReq && papPages) {
    723                 cbRet = 0;
    724                 for (;;) {
    725                         /*
    726                         * Figure out how much to process now and lock the user pages.
    727                         */
    728                         int    rc;
    729                         size_t cbChunk = (uintptr_t)buf & PAGE_OFFSET_MASK;
    730                         pReq->PgLst.offFirstPage = (uint16_t)cbChunk;
    731                         cPages  = RT_ALIGN_Z(cbChunk + size, PAGE_SIZE) >> PAGE_SHIFT;
    732                         if (cPages <= cMaxPages)
    733                                 cbChunk = size;
    734                         else {
    735                                 cPages  = cMaxPages;
    736                                 cbChunk = (cMaxPages << PAGE_SHIFT) - cbChunk;
    737                         }
    738 
    739                         rc = sf_lock_user_pages((uintptr_t)buf, cPages, false /*fWrite*/, papPages);
    740                         if (rc == 0) {
    741                                 size_t iPage = cPages;
    742                                 while (iPage-- > 0)
    743                                         pReq->PgLst.aPages[iPage] = page_to_phys(papPages[iPage]);
    744                         } else {
    745                                 cbRet = rc;
    746                                 break;
    747                         }
    748 
    749                         /*
    750                         * Issue the request and unlock the pages.
    751                         */
    752                         rc = VbglR0SfHostReqWritePgLst(sf_g->map.root, pReq, sf_r->Handle.hHost, offFile, cbChunk, cPages);
    753 
    754                         sf_unlock_user_pages(papPages, cPages, false /*fSetDirty*/);
    755 
    756                         if (RT_SUCCESS(rc)) {
    757                                 /*
    758                                 * Success, advance position and buffer.
    759                                 */
    760                                 uint32_t cbActual = pReq->Parms.cb32Write.u.value32;
    761                                 AssertStmt(cbActual <= cbChunk, cbActual = cbChunk);
    762                                 cbRet   += cbActual;
    763                                 offFile += cbActual;
    764                                 buf      = (uint8_t *)buf + cbActual;
    765                                 size    -= cbActual;
    766                                 if (offFile > i_size_read(inode))
    767                                         i_size_write(inode, offFile);
    768                                 sf_reg_write_invalidate_mapping_range(inode->i_mapping, offFile - cbActual, offFile);
    769 
    770                                 /*
    771                                 * Are we done already?  If so commit the new file offset.
    772                                 */
    773                                 if (!size || cbActual < cbChunk) {
    774                                         *off = offFile;
    775                                         break;
    776                                 }
    777                         } else if (rc == VERR_NO_MEMORY && cMaxPages > 4) {
    778                                 /*
    779                                 * The host probably doesn't have enough heap to handle the
    780                                 * request, reduce the page count and retry.
    781                                 */
    782                                 cMaxPages /= 4;
    783                                 Assert(cMaxPages > 0);
    784                         } else {
    785                                 /*
    786                                 * If we've successfully written stuff, return it rather than
    787                                 * the error.  (Not sure if this is such a great idea...)
    788                                 */
    789                                 if (cbRet > 0)
    790                                         *off = offFile;
    791                                 else
    792                                         cbRet = -EPROTO;
    793                                 break;
    794                         }
    795                         sf_i->force_restat = 1; /* mtime (and size) may have changed */
    796                 }
    797         }
    798         if (papPagesFree)
    799                 kfree(papPages);
    800         if (pReq)
    801                 VbglR0PhysHeapFree(pReq);
    802         return cbRet;
     697                                     struct inode *inode, struct sf_inode_info *sf_i,
     698                                     struct vbsf_super_info *sf_g, struct sf_reg_info *sf_r)
     699{
     700    /*
     701    * Lock pages and execute the write, taking care not to pass the host
     702    * more than it can handle in one go or more than we care to allocate
     703    * page arrays for.  The latter limit is set at just short of 32KB due
     704    * to how the physical heap works.
     705    */
     706    struct page         *apPagesStack[16];
     707    struct page        **papPages     = &apPagesStack[0];
     708    struct page        **papPagesFree = NULL;
     709    VBOXSFWRITEPGLSTREQ *pReq;
     710    ssize_t              cbRet        = -ENOMEM;
     711    size_t               cPages       = (((uintptr_t)buf & PAGE_OFFSET_MASK) + size + PAGE_OFFSET_MASK) >> PAGE_SHIFT;
     712    size_t               cMaxPages    = RT_MIN(RT_MAX(sf_g->cMaxIoPages, 1), cPages);
     713
     714    pReq = (VBOXSFWRITEPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFWRITEPGLSTREQ, PgLst.aPages[cMaxPages]));
     715    while (!pReq && cMaxPages > 4) {
     716        cMaxPages /= 2;
     717        pReq = (VBOXSFWRITEPGLSTREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF_DYN(VBOXSFWRITEPGLSTREQ, PgLst.aPages[cMaxPages]));
     718    }
     719    if (pReq && cPages > RT_ELEMENTS(apPagesStack))
     720        papPagesFree = papPages = kmalloc(cMaxPages * sizeof(sizeof(papPages[0])), GFP_KERNEL);
     721    if (pReq && papPages) {
     722        cbRet = 0;
     723        for (;;) {
     724            /*
     725            * Figure out how much to process now and lock the user pages.
     726            */
     727            int    rc;
     728            size_t cbChunk = (uintptr_t)buf & PAGE_OFFSET_MASK;
     729            pReq->PgLst.offFirstPage = (uint16_t)cbChunk;
     730            cPages  = RT_ALIGN_Z(cbChunk + size, PAGE_SIZE) >> PAGE_SHIFT;
     731            if (cPages <= cMaxPages)
     732                cbChunk = size;
     733            else {
     734                cPages  = cMaxPages;
     735                cbChunk = (cMaxPages << PAGE_SHIFT) - cbChunk;
     736            }
     737
     738            rc = sf_lock_user_pages((uintptr_t)buf, cPages, false /*fWrite*/, papPages);
     739            if (rc == 0) {
     740                size_t iPage = cPages;
     741                while (iPage-- > 0)
     742                    pReq->PgLst.aPages[iPage] = page_to_phys(papPages[iPage]);
     743            } else {
     744                cbRet = rc;
     745                break;
     746            }
     747
     748            /*
     749            * Issue the request and unlock the pages.
     750            */
     751            rc = VbglR0SfHostReqWritePgLst(sf_g->map.root, pReq, sf_r->Handle.hHost, offFile, cbChunk, cPages);
     752
     753            sf_unlock_user_pages(papPages, cPages, false /*fSetDirty*/);
     754
     755            if (RT_SUCCESS(rc)) {
     756                /*
     757                * Success, advance position and buffer.
     758                */
     759                uint32_t cbActual = pReq->Parms.cb32Write.u.value32;
     760                AssertStmt(cbActual <= cbChunk, cbActual = cbChunk);
     761                cbRet   += cbActual;
     762                offFile += cbActual;
     763                buf      = (uint8_t *)buf + cbActual;
     764                size    -= cbActual;
     765                if (offFile > i_size_read(inode))
     766                    i_size_write(inode, offFile);
     767                sf_reg_write_invalidate_mapping_range(inode->i_mapping, offFile - cbActual, offFile);
     768
     769                /*
     770                * Are we done already?  If so commit the new file offset.
     771                */
     772                if (!size || cbActual < cbChunk) {
     773                    *off = offFile;
     774                    break;
     775                }
     776            } else if (rc == VERR_NO_MEMORY && cMaxPages > 4) {
     777                /*
     778                * The host probably doesn't have enough heap to handle the
     779                * request, reduce the page count and retry.
     780                */
     781                cMaxPages /= 4;
     782                Assert(cMaxPages > 0);
     783            } else {
     784                /*
     785                * If we've successfully written stuff, return it rather than
     786                * the error.  (Not sure if this is such a great idea...)
     787                */
     788                if (cbRet > 0)
     789                    *off = offFile;
     790                else
     791                    cbRet = -EPROTO;
     792                break;
     793            }
     794            sf_i->force_restat = 1; /* mtime (and size) may have changed */
     795        }
     796    }
     797    if (papPagesFree)
     798        kfree(papPages);
     799    if (pReq)
     800        VbglR0PhysHeapFree(pReq);
     801    return cbRet;
    803802}
    804803
     
    814813 */
    815814static ssize_t sf_reg_write(struct file *file, const char *buf, size_t size,
    816                             loff_t * off)
    817 {
    818         struct inode           *inode   = GET_F_DENTRY(file)->d_inode;
    819         struct sf_inode_info   *sf_i    = GET_INODE_INFO(inode);
    820         struct vbsf_super_info *sf_g    = VBSF_GET_SUPER_INFO(inode->i_sb);
    821         struct sf_reg_info     *sf_r    = file->private_data;
    822         struct address_space   *mapping = inode->i_mapping;
    823         loff_t                  pos;
    824 
    825         SFLOGFLOW(("sf_reg_write: inode=%p file=%p buf=%p size=%#zx off=%#llx\n", inode, file, buf, size, *off));
    826         BUG_ON(!sf_i);
    827         BUG_ON(!sf_g);
    828         BUG_ON(!sf_r);
    829 
    830         if (!S_ISREG(inode->i_mode)) {
    831                 LogFunc(("write to non regular file %d\n", inode->i_mode));
    832                 return -EINVAL;
    833         }
    834 
    835         pos = *off;
    836         /** @todo This should be handled by the host, it returning the new file
    837         *        offset when appending.  We may have an outdated i_size value here! */
    838         if (file->f_flags & O_APPEND)
    839                 pos = i_size_read(inode);
    840 
    841         /** @todo XXX Check write permission according to inode->i_mode! */
    842 
    843         if (!size) {
    844                 if (file->f_flags & O_APPEND)  /** @todo check if this is the consensus behavior... */
    845                         *off = pos;
    846                 return 0;
    847         }
    848 
    849         /*
    850         * If there are active writable mappings, coordinate with any
    851         * pending writes via those.
    852         */
    853         if (   mapping
    854             && mapping->nrpages > 0
    855             && mapping_writably_mapped(mapping)) {
     815                loff_t * off)
     816{
     817    struct inode           *inode   = GET_F_DENTRY(file)->d_inode;
     818    struct sf_inode_info   *sf_i    = GET_INODE_INFO(inode);
     819    struct vbsf_super_info *sf_g    = VBSF_GET_SUPER_INFO(inode->i_sb);
     820    struct sf_reg_info     *sf_r    = file->private_data;
     821    struct address_space   *mapping = inode->i_mapping;
     822    loff_t                  pos;
     823
     824    SFLOGFLOW(("sf_reg_write: inode=%p file=%p buf=%p size=%#zx off=%#llx\n", inode, file, buf, size, *off));
     825    BUG_ON(!sf_i);
     826    BUG_ON(!sf_g);
     827    BUG_ON(!sf_r);
     828
     829    if (!S_ISREG(inode->i_mode)) {
     830        LogFunc(("write to non regular file %d\n", inode->i_mode));
     831        return -EINVAL;
     832    }
     833
     834    pos = *off;
     835    /** @todo This should be handled by the host, it returning the new file
     836    *        offset when appending.  We may have an outdated i_size value here! */
     837    if (file->f_flags & O_APPEND)
     838        pos = i_size_read(inode);
     839
     840    /** @todo XXX Check write permission according to inode->i_mode! */
     841
     842    if (!size) {
     843        if (file->f_flags & O_APPEND)  /** @todo check if this is the consensus behavior... */
     844            *off = pos;
     845        return 0;
     846    }
     847
     848    /*
     849    * If there are active writable mappings, coordinate with any
     850    * pending writes via those.
     851    */
     852    if (   mapping
     853        && mapping->nrpages > 0
     854        && mapping_writably_mapped(mapping)) {
    856855#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
    857                 int err = filemap_fdatawait_range(mapping, pos, pos + size - 1);
    858                 if (err)
    859                         return err;
     856        int err = filemap_fdatawait_range(mapping, pos, pos + size - 1);
     857        if (err)
     858            return err;
    860859#else
    861                 /** @todo ...   */
    862 #endif
    863         }
    864 
    865         /*
    866         * For small requests, try use an embedded buffer provided we get a heap block
    867         * that does not cross page boundraries (see host code).
    868         */
    869         if (size <= PAGE_SIZE / 4 * 3 - RT_UOFFSETOF(VBOXSFWRITEEMBEDDEDREQ, abData[0]) /* see allocator */) {
    870                 uint32_t const          cbReq = RT_UOFFSETOF(VBOXSFWRITEEMBEDDEDREQ, abData[0]) + size;
    871                 VBOXSFWRITEEMBEDDEDREQ *pReq  = (VBOXSFWRITEEMBEDDEDREQ *)VbglR0PhysHeapAlloc(cbReq);
    872                 if (   pReq
    873                     && (PAGE_SIZE - ((uintptr_t)pReq & PAGE_OFFSET_MASK)) >= cbReq) {
    874                         ssize_t cbRet;
    875                         if (copy_from_user(pReq->abData, buf, size) == 0) {
    876                                 int vrc = VbglR0SfHostReqWriteEmbedded(sf_g->map.root, pReq, sf_r->Handle.hHost,
    877                                                                        pos, (uint32_t)size);
    878                                 if (RT_SUCCESS(vrc)) {
    879                                         cbRet = pReq->Parms.cb32Write.u.value32;
    880                                         AssertStmt(cbRet <= (ssize_t)size, cbRet = size);
    881                                         pos += cbRet;
    882                                         *off = pos;
    883                                         if (pos > i_size_read(inode))
    884                                                 i_size_write(inode, pos);
    885                                         sf_reg_write_invalidate_mapping_range(mapping, pos - cbRet, pos);
    886                                 } else
    887                                         cbRet = -EPROTO;
    888                                 sf_i->force_restat = 1; /* mtime (and size) may have changed */
    889                         } else
    890                                 cbRet = -EFAULT;
    891 
    892                         VbglR0PhysHeapFree(pReq);
    893                         return cbRet;
    894                 }
    895                 if (pReq)
    896                         VbglR0PhysHeapFree(pReq);
    897         }
     860        /** @todo ...   */
     861#endif
     862    }
     863
     864    /*
     865    * For small requests, try use an embedded buffer provided we get a heap block
     866    * that does not cross page boundraries (see host code).
     867    */
     868    if (size <= PAGE_SIZE / 4 * 3 - RT_UOFFSETOF(VBOXSFWRITEEMBEDDEDREQ, abData[0]) /* see allocator */) {
     869        uint32_t const          cbReq = RT_UOFFSETOF(VBOXSFWRITEEMBEDDEDREQ, abData[0]) + size;
     870        VBOXSFWRITEEMBEDDEDREQ *pReq  = (VBOXSFWRITEEMBEDDEDREQ *)VbglR0PhysHeapAlloc(cbReq);
     871        if (   pReq
     872            && (PAGE_SIZE - ((uintptr_t)pReq & PAGE_OFFSET_MASK)) >= cbReq) {
     873            ssize_t cbRet;
     874            if (copy_from_user(pReq->abData, buf, size) == 0) {
     875                int vrc = VbglR0SfHostReqWriteEmbedded(sf_g->map.root, pReq, sf_r->Handle.hHost,
     876                                       pos, (uint32_t)size);
     877                if (RT_SUCCESS(vrc)) {
     878                    cbRet = pReq->Parms.cb32Write.u.value32;
     879                    AssertStmt(cbRet <= (ssize_t)size, cbRet = size);
     880                    pos += cbRet;
     881                    *off = pos;
     882                    if (pos > i_size_read(inode))
     883                        i_size_write(inode, pos);
     884                    sf_reg_write_invalidate_mapping_range(mapping, pos - cbRet, pos);
     885                } else
     886                    cbRet = -EPROTO;
     887                sf_i->force_restat = 1; /* mtime (and size) may have changed */
     888            } else
     889                cbRet = -EFAULT;
     890
     891            VbglR0PhysHeapFree(pReq);
     892            return cbRet;
     893        }
     894        if (pReq)
     895            VbglR0PhysHeapFree(pReq);
     896    }
    898897
    899898#if 0 /* Turns out this is slightly slower than locking the pages even for 4KB reads (4.19/amd64). */
    900         /*
    901         * For medium sized requests try use a bounce buffer.
    902         */
    903         if (size <= _64K /** @todo make this configurable? */) {
    904                 void *pvBounce = kmalloc(size, GFP_KERNEL);
    905                 if (pvBounce) {
    906                         if (copy_from_user(pvBounce, buf, size) == 0) {
    907                                 VBOXSFWRITEPGLSTREQ *pReq = (VBOXSFWRITEPGLSTREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
    908                                 if (pReq) {
    909                                         ssize_t cbRet;
    910                                         int vrc = VbglR0SfHostReqWriteContig(sf_g->map.root, pReq, sf_r->handle, pos,
    911                                                                              (uint32_t)size, pvBounce, virt_to_phys(pvBounce));
    912                                         if (RT_SUCCESS(vrc)) {
    913                                                 cbRet = pReq->Parms.cb32Write.u.value32;
    914                                                 AssertStmt(cbRet <= (ssize_t)size, cbRet = size);
    915                                                 pos += cbRet;
    916                                                 *off = pos;
    917                                                 if (pos > i_size_read(inode))
    918                                                         i_size_write(inode, pos);
    919                                                 sf_reg_write_invalidate_mapping_range(mapping, pos - cbRet, pos);
    920                                         } else
    921                                                 cbRet = -EPROTO;
    922                                         sf_i->force_restat = 1; /* mtime (and size) may have changed */
    923                                         VbglR0PhysHeapFree(pReq);
    924                                         kfree(pvBounce);
    925                                         return cbRet;
    926                                 }
    927                                 kfree(pvBounce);
    928                         } else {
    929                                 kfree(pvBounce);
    930                                 return -EFAULT;
    931                         }
    932                 }
    933         }
    934 #endif
    935 
    936         return sf_reg_write_fallback(file, buf, size, off, pos, inode, sf_i, sf_g, sf_r);
     899    /*
     900    * For medium sized requests try use a bounce buffer.
     901    */
     902    if (size <= _64K /** @todo make this configurable? */) {
     903        void *pvBounce = kmalloc(size, GFP_KERNEL);
     904        if (pvBounce) {
     905            if (copy_from_user(pvBounce, buf, size) == 0) {
     906                VBOXSFWRITEPGLSTREQ *pReq = (VBOXSFWRITEPGLSTREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
     907                if (pReq) {
     908                    ssize_t cbRet;
     909                    int vrc = VbglR0SfHostReqWriteContig(sf_g->map.root, pReq, sf_r->handle, pos,
     910                                         (uint32_t)size, pvBounce, virt_to_phys(pvBounce));
     911                    if (RT_SUCCESS(vrc)) {
     912                        cbRet = pReq->Parms.cb32Write.u.value32;
     913                        AssertStmt(cbRet <= (ssize_t)size, cbRet = size);
     914                        pos += cbRet;
     915                        *off = pos;
     916                        if (pos > i_size_read(inode))
     917                            i_size_write(inode, pos);
     918                        sf_reg_write_invalidate_mapping_range(mapping, pos - cbRet, pos);
     919                    } else
     920                        cbRet = -EPROTO;
     921                    sf_i->force_restat = 1; /* mtime (and size) may have changed */
     922                    VbglR0PhysHeapFree(pReq);
     923                    kfree(pvBounce);
     924                    return cbRet;
     925                }
     926                kfree(pvBounce);
     927            } else {
     928                kfree(pvBounce);
     929                return -EFAULT;
     930            }
     931        }
     932    }
     933#endif
     934
     935    return sf_reg_write_fallback(file, buf, size, off, pos, inode, sf_i, sf_g, sf_r);
    937936}
    938937
     
    947946static int sf_reg_open(struct inode *inode, struct file *file)
    948947{
    949         int rc, rc_linux = 0;
    950         struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
    951         struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
    952         struct sf_reg_info *sf_r;
     948    int rc, rc_linux = 0;
     949    struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
     950    struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
     951    struct sf_reg_info *sf_r;
    953952#if   LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
    954         struct dentry *dentry = file_dentry(file);
     953    struct dentry *dentry = file_dentry(file);
    955954#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
    956         struct dentry *dentry = file->f_path.dentry;
     955    struct dentry *dentry = file->f_path.dentry;
    957956#else
    958         struct dentry *dentry = file->f_dentry;
    959 #endif
    960         VBOXSFCREATEREQ *pReq;
    961         SHFLCREATEPARMS *pCreateParms;  /* temp glue */
    962 
    963         SFLOGFLOW(("sf_reg_open: inode=%p file=%p flags=%#x %s\n",
    964                    inode, file, file->f_flags, sf_i ? sf_i->path->String.ach : NULL));
    965         BUG_ON(!sf_g);
    966         BUG_ON(!sf_i);
    967 
    968         sf_r = kmalloc(sizeof(*sf_r), GFP_KERNEL);
    969         if (!sf_r) {
    970                 LogRelFunc(("could not allocate reg info\n"));
    971                 return -ENOMEM;
    972         }
    973 
    974         RTListInit(&sf_r->Handle.Entry);
    975         sf_r->Handle.cRefs  = 1;
    976         sf_r->Handle.fFlags = SF_HANDLE_F_FILE | SF_HANDLE_F_MAGIC;
    977         sf_r->Handle.hHost  = SHFL_HANDLE_NIL;
    978 
    979         /* Already open? */
    980         if (sf_i->handle != SHFL_HANDLE_NIL) {
    981                 /*
    982                 * This inode was created with sf_create_aux(). Check the CreateFlags:
    983                 * O_CREAT, O_TRUNC: inherent true (file was just created). Not sure
    984                 * about the access flags (SHFL_CF_ACCESS_*).
    985                 */
    986                 sf_i->force_restat = 1;
    987                 sf_r->Handle.hHost = sf_i->handle;
    988                 sf_i->handle = SHFL_HANDLE_NIL;
    989                 file->private_data = sf_r;
    990 
    991                 sf_r->Handle.fFlags |= SF_HANDLE_F_READ | SF_HANDLE_F_WRITE; /** @todo check */
    992                 sf_handle_append(sf_i, &sf_r->Handle);
    993                 SFLOGFLOW(("sf_reg_open: returns 0 (#1) - sf_i=%p hHost=%#llx\n", sf_i, sf_r->Handle.hHost));
    994                 return 0;
    995         }
    996 
    997         pReq = (VBOXSFCREATEREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq) + sf_i->path->u16Size);
    998         if (!pReq) {
    999                 kfree(sf_r);
    1000                 LogRelFunc(("Failed to allocate a VBOXSFCREATEREQ buffer!\n"));
    1001                 return -ENOMEM;
    1002         }
    1003         memcpy(&pReq->StrPath, sf_i->path, SHFLSTRING_HEADER_SIZE + sf_i->path->u16Size);
    1004         RT_ZERO(pReq->CreateParms);
    1005         pCreateParms = &pReq->CreateParms;
    1006         pCreateParms->Handle = SHFL_HANDLE_NIL;
    1007 
    1008         /* We check the value of pCreateParms->Handle afterwards to find out if
    1009         * the call succeeded or failed, as the API does not seem to cleanly
    1010         * distinguish error and informational messages.
    1011         *
    1012         * Furthermore, we must set pCreateParms->Handle to SHFL_HANDLE_NIL to
    1013         * make the shared folders host service use our fMode parameter */
    1014 
    1015         if (file->f_flags & O_CREAT) {
    1016                 LogFunc(("O_CREAT set\n"));
    1017                 pCreateParms->CreateFlags |= SHFL_CF_ACT_CREATE_IF_NEW;
    1018                 /* We ignore O_EXCL, as the Linux kernel seems to call create
    1019                    beforehand itself, so O_EXCL should always fail. */
    1020                 if (file->f_flags & O_TRUNC) {
    1021                         LogFunc(("O_TRUNC set\n"));
    1022                         pCreateParms->CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
    1023                 } else
    1024                         pCreateParms->CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS;
    1025         } else {
    1026                 pCreateParms->CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW;
    1027                 if (file->f_flags & O_TRUNC) {
    1028                         LogFunc(("O_TRUNC set\n"));
    1029                         pCreateParms->CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
    1030                 }
    1031         }
    1032 
    1033         switch (file->f_flags & O_ACCMODE) {
    1034         case O_RDONLY:
    1035                 pCreateParms->CreateFlags |= SHFL_CF_ACCESS_READ;
    1036                 sf_r->Handle.fFlags |= SF_HANDLE_F_READ;
    1037                 break;
    1038 
    1039         case O_WRONLY:
    1040                 pCreateParms->CreateFlags |= SHFL_CF_ACCESS_WRITE;
    1041                 sf_r->Handle.fFlags |= SF_HANDLE_F_WRITE;
    1042                 break;
    1043 
    1044         case O_RDWR:
    1045                 pCreateParms->CreateFlags |= SHFL_CF_ACCESS_READWRITE;
    1046                 sf_r->Handle.fFlags |= SF_HANDLE_F_READ | SF_HANDLE_F_WRITE;
    1047                 break;
    1048 
    1049         default:
    1050                 BUG();
    1051         }
    1052 
    1053         if (file->f_flags & O_APPEND) {
    1054                 LogFunc(("O_APPEND set\n"));
    1055                 pCreateParms->CreateFlags |= SHFL_CF_ACCESS_APPEND;
    1056                 sf_r->Handle.fFlags |= SF_HANDLE_F_APPEND;
    1057         }
    1058 
    1059         pCreateParms->Info.Attr.fMode = inode->i_mode;
    1060         LogFunc(("sf_reg_open: calling VbglR0SfHostReqCreate, file %s, flags=%#x, %#x\n", sf_i->path->String.utf8, file->f_flags, pCreateParms->CreateFlags));
    1061         rc = VbglR0SfHostReqCreate(sf_g->map.root, pReq);
    1062         if (RT_FAILURE(rc)) {
    1063                 LogFunc(("VbglR0SfHostReqCreate failed flags=%d,%#x rc=%Rrc\n", file->f_flags, pCreateParms->CreateFlags, rc));
    1064                 kfree(sf_r);
    1065                 VbglR0PhysHeapFree(pReq);
    1066                 return -RTErrConvertToErrno(rc);
    1067         }
    1068 
    1069         if (pCreateParms->Handle != SHFL_HANDLE_NIL) {
    1070                 sf_dentry_chain_increase_ttl(dentry);
    1071                 rc_linux = 0;
    1072         } else {
    1073                 switch (pCreateParms->Result) {
    1074                 case SHFL_PATH_NOT_FOUND:
    1075                         rc_linux = -ENOENT;
    1076                         break;
    1077                 case SHFL_FILE_NOT_FOUND:
    1078                         /** @todo sf_dentry_increase_parent_ttl(file->f_dentry); if we can trust it.  */
    1079                         rc_linux = -ENOENT;
    1080                         break;
    1081                 case SHFL_FILE_EXISTS:
    1082                         sf_dentry_chain_increase_ttl(dentry);
    1083                         rc_linux = -EEXIST;
    1084                         break;
    1085                 default:
    1086                         sf_dentry_chain_increase_parent_ttl(dentry);
    1087                         rc_linux = 0;
    1088                         break;
    1089                 }
    1090         }
    1091 
    1092         sf_i->force_restat = 1; /** @todo Why?!? */
    1093         sf_r->Handle.hHost = pCreateParms->Handle;
    1094         file->private_data = sf_r;
    1095         sf_handle_append(sf_i, &sf_r->Handle);
    1096         VbglR0PhysHeapFree(pReq);
    1097         SFLOGFLOW(("sf_reg_open: returns 0 (#2) - sf_i=%p hHost=%#llx\n", sf_i, sf_r->Handle.hHost));
    1098         return rc_linux;
     957    struct dentry *dentry = file->f_dentry;
     958#endif
     959    VBOXSFCREATEREQ *pReq;
     960    SHFLCREATEPARMS *pCreateParms;  /* temp glue */
     961
     962    SFLOGFLOW(("sf_reg_open: inode=%p file=%p flags=%#x %s\n",
     963           inode, file, file->f_flags, sf_i ? sf_i->path->String.ach : NULL));
     964    BUG_ON(!sf_g);
     965    BUG_ON(!sf_i);
     966
     967    sf_r = kmalloc(sizeof(*sf_r), GFP_KERNEL);
     968    if (!sf_r) {
     969        LogRelFunc(("could not allocate reg info\n"));
     970        return -ENOMEM;
     971    }
     972
     973    RTListInit(&sf_r->Handle.Entry);
     974    sf_r->Handle.cRefs  = 1;
     975    sf_r->Handle.fFlags = SF_HANDLE_F_FILE | SF_HANDLE_F_MAGIC;
     976    sf_r->Handle.hHost  = SHFL_HANDLE_NIL;
     977
     978    /* Already open? */
     979    if (sf_i->handle != SHFL_HANDLE_NIL) {
     980        /*
     981        * This inode was created with sf_create_aux(). Check the CreateFlags:
     982        * O_CREAT, O_TRUNC: inherent true (file was just created). Not sure
     983        * about the access flags (SHFL_CF_ACCESS_*).
     984        */
     985        sf_i->force_restat = 1;
     986        sf_r->Handle.hHost = sf_i->handle;
     987        sf_i->handle = SHFL_HANDLE_NIL;
     988        file->private_data = sf_r;
     989
     990        sf_r->Handle.fFlags |= SF_HANDLE_F_READ | SF_HANDLE_F_WRITE; /** @todo check */
     991        sf_handle_append(sf_i, &sf_r->Handle);
     992        SFLOGFLOW(("sf_reg_open: returns 0 (#1) - sf_i=%p hHost=%#llx\n", sf_i, sf_r->Handle.hHost));
     993        return 0;
     994    }
     995
     996    pReq = (VBOXSFCREATEREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq) + sf_i->path->u16Size);
     997    if (!pReq) {
     998        kfree(sf_r);
     999        LogRelFunc(("Failed to allocate a VBOXSFCREATEREQ buffer!\n"));
     1000        return -ENOMEM;
     1001    }
     1002    memcpy(&pReq->StrPath, sf_i->path, SHFLSTRING_HEADER_SIZE + sf_i->path->u16Size);
     1003    RT_ZERO(pReq->CreateParms);
     1004    pCreateParms = &pReq->CreateParms;
     1005    pCreateParms->Handle = SHFL_HANDLE_NIL;
     1006
     1007    /* We check the value of pCreateParms->Handle afterwards to find out if
     1008    * the call succeeded or failed, as the API does not seem to cleanly
     1009    * distinguish error and informational messages.
     1010    *
     1011    * Furthermore, we must set pCreateParms->Handle to SHFL_HANDLE_NIL to
     1012    * make the shared folders host service use our fMode parameter */
     1013
     1014    if (file->f_flags & O_CREAT) {
     1015        LogFunc(("O_CREAT set\n"));
     1016        pCreateParms->CreateFlags |= SHFL_CF_ACT_CREATE_IF_NEW;
     1017        /* We ignore O_EXCL, as the Linux kernel seems to call create
     1018           beforehand itself, so O_EXCL should always fail. */
     1019        if (file->f_flags & O_TRUNC) {
     1020            LogFunc(("O_TRUNC set\n"));
     1021            pCreateParms->CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
     1022        } else
     1023            pCreateParms->CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS;
     1024    } else {
     1025        pCreateParms->CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW;
     1026        if (file->f_flags & O_TRUNC) {
     1027            LogFunc(("O_TRUNC set\n"));
     1028            pCreateParms->CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
     1029        }
     1030    }
     1031
     1032    switch (file->f_flags & O_ACCMODE) {
     1033    case O_RDONLY:
     1034        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_READ;
     1035        sf_r->Handle.fFlags |= SF_HANDLE_F_READ;
     1036        break;
     1037
     1038    case O_WRONLY:
     1039        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_WRITE;
     1040        sf_r->Handle.fFlags |= SF_HANDLE_F_WRITE;
     1041        break;
     1042
     1043    case O_RDWR:
     1044        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_READWRITE;
     1045        sf_r->Handle.fFlags |= SF_HANDLE_F_READ | SF_HANDLE_F_WRITE;
     1046        break;
     1047
     1048    default:
     1049        BUG();
     1050    }
     1051
     1052    if (file->f_flags & O_APPEND) {
     1053        LogFunc(("O_APPEND set\n"));
     1054        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_APPEND;
     1055        sf_r->Handle.fFlags |= SF_HANDLE_F_APPEND;
     1056    }
     1057
     1058    pCreateParms->Info.Attr.fMode = inode->i_mode;
     1059    LogFunc(("sf_reg_open: calling VbglR0SfHostReqCreate, file %s, flags=%#x, %#x\n", sf_i->path->String.utf8, file->f_flags, pCreateParms->CreateFlags));
     1060    rc = VbglR0SfHostReqCreate(sf_g->map.root, pReq);
     1061    if (RT_FAILURE(rc)) {
     1062        LogFunc(("VbglR0SfHostReqCreate failed flags=%d,%#x rc=%Rrc\n", file->f_flags, pCreateParms->CreateFlags, rc));
     1063        kfree(sf_r);
     1064        VbglR0PhysHeapFree(pReq);
     1065        return -RTErrConvertToErrno(rc);
     1066    }
     1067
     1068    if (pCreateParms->Handle != SHFL_HANDLE_NIL) {
     1069        sf_dentry_chain_increase_ttl(dentry);
     1070        rc_linux = 0;
     1071    } else {
     1072        switch (pCreateParms->Result) {
     1073        case SHFL_PATH_NOT_FOUND:
     1074            rc_linux = -ENOENT;
     1075            break;
     1076        case SHFL_FILE_NOT_FOUND:
     1077            /** @todo sf_dentry_increase_parent_ttl(file->f_dentry); if we can trust it.  */
     1078            rc_linux = -ENOENT;
     1079            break;
     1080        case SHFL_FILE_EXISTS:
     1081            sf_dentry_chain_increase_ttl(dentry);
     1082            rc_linux = -EEXIST;
     1083            break;
     1084        default:
     1085            sf_dentry_chain_increase_parent_ttl(dentry);
     1086            rc_linux = 0;
     1087            break;
     1088        }
     1089    }
     1090
     1091    sf_i->force_restat = 1; /** @todo Why?!? */
     1092    sf_r->Handle.hHost = pCreateParms->Handle;
     1093    file->private_data = sf_r;
     1094    sf_handle_append(sf_i, &sf_r->Handle);
     1095    VbglR0PhysHeapFree(pReq);
     1096    SFLOGFLOW(("sf_reg_open: returns 0 (#2) - sf_i=%p hHost=%#llx\n", sf_i, sf_r->Handle.hHost));
     1097    return rc_linux;
    10991098}
    11001099
     
    11091108static int sf_reg_release(struct inode *inode, struct file *file)
    11101109{
    1111         struct sf_reg_info *sf_r;
    1112         struct vbsf_super_info *sf_g;
    1113         struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
    1114 
    1115         SFLOGFLOW(("sf_reg_release: inode=%p file=%p\n", inode, file));
    1116         sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
    1117         sf_r = file->private_data;
    1118 
    1119         BUG_ON(!sf_g);
    1120         BUG_ON(!sf_r);
     1110    struct sf_reg_info *sf_r;
     1111    struct vbsf_super_info *sf_g;
     1112    struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
     1113
     1114    SFLOGFLOW(("sf_reg_release: inode=%p file=%p\n", inode, file));
     1115    sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
     1116    sf_r = file->private_data;
     1117
     1118    BUG_ON(!sf_g);
     1119    BUG_ON(!sf_r);
    11211120
    11221121#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
    1123         /* See the smbfs source (file.c). mmap in particular can cause data to be
    1124         * written to the file after it is closed, which we can't cope with.  We
    1125         * copy and paste the body of filemap_write_and_wait() here as it was not
    1126         * defined before 2.6.6 and not exported until quite a bit later. */
    1127         /* filemap_write_and_wait(inode->i_mapping); */
    1128         if (inode->i_mapping->nrpages
    1129             && filemap_fdatawrite(inode->i_mapping) != -EIO)
    1130                 filemap_fdatawait(inode->i_mapping);
    1131 #endif
    1132 
    1133         /* Release sf_r, closing the handle if we're the last user. */
    1134         file->private_data = NULL;
    1135         sf_handle_release(&sf_r->Handle, sf_g, "sf_reg_release");
    1136 
    1137         sf_i->handle = SHFL_HANDLE_NIL;
    1138         return 0;
     1122    /* See the smbfs source (file.c). mmap in particular can cause data to be
     1123    * written to the file after it is closed, which we can't cope with.  We
     1124    * copy and paste the body of filemap_write_and_wait() here as it was not
     1125    * defined before 2.6.6 and not exported until quite a bit later. */
     1126    /* filemap_write_and_wait(inode->i_mapping); */
     1127    if (inode->i_mapping->nrpages
     1128        && filemap_fdatawrite(inode->i_mapping) != -EIO)
     1129        filemap_fdatawait(inode->i_mapping);
     1130#endif
     1131
     1132    /* Release sf_r, closing the handle if we're the last user. */
     1133    file->private_data = NULL;
     1134    sf_handle_release(&sf_r->Handle, sf_g, "sf_reg_release");
     1135
     1136    sf_i->handle = SHFL_HANDLE_NIL;
     1137    return 0;
    11391138}
    11401139
     
    11501149static loff_t sf_reg_llseek(struct file *file, loff_t off, int whence)
    11511150{
    1152         SFLOGFLOW(("sf_reg_llseek: file=%p off=%lld whence=%d\n", file, off, whence));
    1153 
    1154         switch (whence) {
     1151    SFLOGFLOW(("sf_reg_llseek: file=%p off=%lld whence=%d\n", file, off, whence));
     1152
     1153    switch (whence) {
    11551154#ifdef SEEK_HOLE
    1156                 case SEEK_HOLE:
    1157                 case SEEK_DATA:
    1158 #endif
    1159                 case SEEK_END: {
    1160                         struct sf_reg_info *sf_r = file->private_data;
    1161                         int rc = sf_inode_revalidate_with_handle(GET_F_DENTRY(file), sf_r->Handle.hHost, true /*fForce*/,
    1162                                                                 false /*fInodeLocked*/);
    1163                         if (rc == 0)
    1164                                 break;
    1165                         return rc;
    1166                 }
    1167         }
     1155        case SEEK_HOLE:
     1156        case SEEK_DATA:
     1157#endif
     1158        case SEEK_END: {
     1159            struct sf_reg_info *sf_r = file->private_data;
     1160            int rc = sf_inode_revalidate_with_handle(GET_F_DENTRY(file), sf_r->Handle.hHost, true /*fForce*/,
     1161                                false /*fInodeLocked*/);
     1162            if (rc == 0)
     1163                break;
     1164            return rc;
     1165        }
     1166    }
    11681167
    11691168#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 8)
    1170         return generic_file_llseek(file, off, whence);
     1169    return generic_file_llseek(file, off, whence);
    11711170#else
    1172         return default_llseek(file, off, whence);
     1171    return default_llseek(file, off, whence);
    11731172#endif
    11741173}
     
    11861185{
    11871186# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
    1188         return __generic_file_fsync(file, start, end, datasync);
     1187    return __generic_file_fsync(file, start, end, datasync);
    11891188# else
    1190         return generic_file_fsync(file, start, end, datasync);
     1189    return generic_file_fsync(file, start, end, datasync);
    11911190# endif
    11921191}
     
    11941193static int sf_reg_fsync(struct file *file, int datasync)
    11951194{
    1196         return generic_file_fsync(file, datasync);
     1195    return generic_file_fsync(file, datasync);
    11971196}
    11981197#else /* < 2.6.35 */
     
    12001199{
    12011200# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
    1202         return simple_fsync(file, dentry, datasync);
     1201    return simple_fsync(file, dentry, datasync);
    12031202# else
    1204         int rc;
    1205         struct inode *inode = dentry->d_inode;
    1206         AssertReturn(inode, -EINVAL);
    1207 
    1208         /** @todo What about file_fsync()? (<= 2.5.11) */
     1203    int rc;
     1204    struct inode *inode = dentry->d_inode;
     1205    AssertReturn(inode, -EINVAL);
     1206
     1207    /** @todo What about file_fsync()? (<= 2.5.11) */
    12091208
    12101209#  if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 12)
    1211         rc = sync_mapping_buffers(inode->i_mapping);
    1212         if (   rc == 0
    1213             && (inode->i_state & I_DIRTY)
    1214             && ((inode->i_state & I_DIRTY_DATASYNC) || !datasync)
    1215            ) {
    1216                 struct writeback_control wbc = {
    1217                         .sync_mode = WB_SYNC_ALL,
    1218                         .nr_to_write = 0
    1219                 };
    1220                 rc = sync_inode(inode, &wbc);
    1221         }
     1210    rc = sync_mapping_buffers(inode->i_mapping);
     1211    if (   rc == 0
     1212        && (inode->i_state & I_DIRTY)
     1213        && ((inode->i_state & I_DIRTY_DATASYNC) || !datasync)
     1214       ) {
     1215        struct writeback_control wbc = {
     1216            .sync_mode = WB_SYNC_ALL,
     1217            .nr_to_write = 0
     1218        };
     1219        rc = sync_inode(inode, &wbc);
     1220    }
    12221221#  else  /* < 2.5.12 */
    1223         rc  = fsync_inode_buffers(inode);
     1222    rc  = fsync_inode_buffers(inode);
    12241223#   if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 10)
    1225         rc |= fsync_inode_data_buffers(inode);
     1224    rc |= fsync_inode_data_buffers(inode);
    12261225#   endif
    1227         /** @todo probably need to do more here... */
     1226    /** @todo probably need to do more here... */
    12281227#  endif /* < 2.5.12 */
    1229         return rc;
     1228    return rc;
    12301229# endif
    12311230}
     
    12341233
    12351234struct file_operations sf_reg_fops = {
    1236         .read = sf_reg_read,
    1237         .open = sf_reg_open,
    1238         .write = sf_reg_write,
    1239         .release = sf_reg_release,
    1240         .mmap = generic_file_mmap,
     1235    .read = sf_reg_read,
     1236    .open = sf_reg_open,
     1237    .write = sf_reg_write,
     1238    .release = sf_reg_release,
     1239    .mmap = generic_file_mmap,
    12411240#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
    12421241# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
     
    12441243 * cached.  Investigate. */
    12451244# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
    1246         .splice_read = sf_splice_read,
     1245    .splice_read = sf_splice_read,
    12471246# else
    1248         .sendfile = generic_file_sendfile,
     1247    .sendfile = generic_file_sendfile,
    12491248# endif
    1250         .aio_read = generic_file_aio_read,
    1251         .aio_write = generic_file_aio_write,
     1249    .aio_read = generic_file_aio_read,
     1250    .aio_write = generic_file_aio_write,
    12521251# endif
    12531252#endif
    1254         .llseek = sf_reg_llseek,
    1255         .fsync = sf_reg_fsync,
     1253    .llseek = sf_reg_llseek,
     1254    .fsync = sf_reg_fsync,
    12561255};
    12571256
    12581257struct inode_operations sf_reg_iops = {
    12591258#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
    1260         .revalidate = sf_inode_revalidate
     1259    .revalidate = sf_inode_revalidate
    12611260#else
    1262         .getattr = sf_getattr,
    1263         .setattr = sf_setattr
     1261    .getattr = sf_getattr,
     1262    .setattr = sf_setattr
    12641263#endif
    12651264};
     
    12751274static int sf_readpage(struct file *file, struct page *page)
    12761275{
    1277         struct inode *inode = GET_F_DENTRY(file)->d_inode;
    1278         int           err;
    1279 
    1280         SFLOGFLOW(("sf_readpage: inode=%p file=%p page=%p off=%#llx\n", inode, file, page, (uint64_t)page->index << PAGE_SHIFT));
    1281 
    1282         if (!is_bad_inode(inode)) {
    1283             VBOXSFREADPGLSTREQ *pReq = (VBOXSFREADPGLSTREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
    1284             if (pReq) {
    1285                     struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
    1286                     struct sf_reg_info     *sf_r = file->private_data;
    1287                     uint32_t                cbRead;
    1288                     int                     vrc;
    1289 
    1290                     pReq->PgLst.offFirstPage = 0;
    1291                     pReq->PgLst.aPages[0]    = page_to_phys(page);
    1292                     vrc = VbglR0SfHostReqReadPgLst(sf_g->map.root,
    1293                                                    pReq,
    1294                                                    sf_r->Handle.hHost,
    1295                                                    (uint64_t)page->index << PAGE_SHIFT,
    1296                                                    PAGE_SIZE,
    1297                                                    1 /*cPages*/);
    1298 
    1299                     cbRead = pReq->Parms.cb32Read.u.value32;
    1300                     AssertStmt(cbRead <= PAGE_SIZE, cbRead = PAGE_SIZE);
    1301                     VbglR0PhysHeapFree(pReq);
    1302 
    1303                     if (RT_SUCCESS(vrc)) {
    1304                             if (cbRead == PAGE_SIZE) {
    1305                                     /* likely */
    1306                             } else {
    1307                                     uint8_t *pbMapped = (uint8_t *)kmap(page);
    1308                                     RT_BZERO(&pbMapped[cbRead], PAGE_SIZE - cbRead);
    1309                                     kunmap(page);
    1310                                     /** @todo truncate the inode file size? */
    1311                             }
    1312 
    1313                             flush_dcache_page(page);
    1314                             SetPageUptodate(page);
    1315                             err = 0;
    1316                     } else
    1317                             err = -EPROTO;
    1318             } else
    1319                     err = -ENOMEM;
    1320         } else
    1321                 err = -EIO;
    1322         unlock_page(page);
    1323         return err;
     1276    struct inode *inode = GET_F_DENTRY(file)->d_inode;
     1277    int           err;
     1278
     1279    SFLOGFLOW(("sf_readpage: inode=%p file=%p page=%p off=%#llx\n", inode, file, page, (uint64_t)page->index << PAGE_SHIFT));
     1280
     1281    if (!is_bad_inode(inode)) {
     1282        VBOXSFREADPGLSTREQ *pReq = (VBOXSFREADPGLSTREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
     1283        if (pReq) {
     1284            struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
     1285            struct sf_reg_info     *sf_r = file->private_data;
     1286            uint32_t            cbRead;
     1287            int                     vrc;
     1288
     1289            pReq->PgLst.offFirstPage = 0;
     1290            pReq->PgLst.aPages[0]    = page_to_phys(page);
     1291            vrc = VbglR0SfHostReqReadPgLst(sf_g->map.root,
     1292                                           pReq,
     1293                                           sf_r->Handle.hHost,
     1294                                           (uint64_t)page->index << PAGE_SHIFT,
     1295                                           PAGE_SIZE,
     1296                                           1 /*cPages*/);
     1297
     1298            cbRead = pReq->Parms.cb32Read.u.value32;
     1299            AssertStmt(cbRead <= PAGE_SIZE, cbRead = PAGE_SIZE);
     1300            VbglR0PhysHeapFree(pReq);
     1301
     1302            if (RT_SUCCESS(vrc)) {
     1303                if (cbRead == PAGE_SIZE) {
     1304                    /* likely */
     1305                } else {
     1306                    uint8_t *pbMapped = (uint8_t *)kmap(page);
     1307                    RT_BZERO(&pbMapped[cbRead], PAGE_SIZE - cbRead);
     1308                    kunmap(page);
     1309                    /** @todo truncate the inode file size? */
     1310                }
     1311
     1312                flush_dcache_page(page);
     1313                SetPageUptodate(page);
     1314                err = 0;
     1315            } else
     1316                err = -EPROTO;
     1317        } else
     1318            err = -ENOMEM;
     1319    } else
     1320        err = -EIO;
     1321    unlock_page(page);
     1322    return err;
    13241323}
    13251324
     
    13331332static int sf_writepage(struct page *page, struct writeback_control *wbc)
    13341333{
    1335         struct address_space *mapping   = page->mapping;
    1336         struct inode         *inode     = mapping->host;
    1337         struct sf_inode_info *sf_i      = GET_INODE_INFO(inode);
    1338         struct sf_handle     *pHandle   = sf_handle_find(sf_i, SF_HANDLE_F_WRITE, SF_HANDLE_F_APPEND);
    1339         int                   err;
    1340 
    1341         SFLOGFLOW(("sf_writepage: inode=%p page=%p off=%#llx pHandle=%p (%#llx)\n",
    1342                    inode, page,(uint64_t)page->index << PAGE_SHIFT, pHandle, pHandle->hHost));
    1343 
    1344         if (pHandle) {
    1345                 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
    1346                 VBOXSFWRITEPGLSTREQ    *pReq = (VBOXSFWRITEPGLSTREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
    1347                 if (pReq) {
    1348                         uint64_t const cbFile    = i_size_read(inode);
    1349                         uint64_t const offInFile = (uint64_t)page->index << PAGE_SHIFT;
    1350                         uint32_t const cbToWrite = page->index != (cbFile >> PAGE_SHIFT) ? PAGE_SIZE
    1351                                                  : (uint32_t)cbFile & (uint32_t)PAGE_OFFSET_MASK;
    1352                         int            vrc;
    1353 
    1354                         pReq->PgLst.offFirstPage = 0;
    1355                         pReq->PgLst.aPages[0]    = page_to_phys(page);
    1356                         vrc = VbglR0SfHostReqWritePgLst(sf_g->map.root,
    1357                                                         pReq,
    1358                                                         pHandle->hHost,
    1359                                                         offInFile,
    1360                                                         cbToWrite,
    1361                                                         1 /*cPages*/);
    1362                         AssertMsgStmt(pReq->Parms.cb32Write.u.value32 == cbToWrite || RT_FAILURE(vrc), /* lazy bird */
    1363                                       ("%#x vs %#x\n", pReq->Parms.cb32Write, cbToWrite),
    1364                                       vrc = VERR_WRITE_ERROR);
    1365                         VbglR0PhysHeapFree(pReq);
    1366 
    1367                         if (RT_SUCCESS(vrc)) {
    1368                                 /* Update the inode if we've extended the file. */
    1369                                 /** @todo is this necessary given the cbToWrite calc above? */
    1370                                 uint64_t const offEndOfWrite = offInFile + cbToWrite;
    1371                                 if (   offEndOfWrite > cbFile
    1372                                     && offEndOfWrite > i_size_read(inode))
    1373                                         i_size_write(inode, offEndOfWrite);
    1374 
    1375                                 if (PageError(page))
    1376                                         ClearPageError(page);
    1377 
    1378                                 err = 0;
    1379                         } else {
    1380                                 ClearPageUptodate(page);
    1381                                 err = -EPROTO;
    1382                         }
    1383                 } else
    1384                         err = -ENOMEM;
    1385                 sf_handle_release(pHandle, sf_g, "sf_writepage");
    1386         } else {
    1387                 static uint64_t volatile s_cCalls = 0;
    1388                 if (s_cCalls++ < 16)
    1389                         printk("sf_writepage: no writable handle for %s..\n", sf_i->path->String.ach);
    1390                 err = -EPROTO;
    1391         }
    1392         unlock_page(page);
    1393         return err;
     1334    struct address_space *mapping   = page->mapping;
     1335    struct inode         *inode     = mapping->host;
     1336    struct sf_inode_info *sf_i      = GET_INODE_INFO(inode);
     1337    struct sf_handle     *pHandle   = sf_handle_find(sf_i, SF_HANDLE_F_WRITE, SF_HANDLE_F_APPEND);
     1338    int                   err;
     1339
     1340    SFLOGFLOW(("sf_writepage: inode=%p page=%p off=%#llx pHandle=%p (%#llx)\n",
     1341           inode, page,(uint64_t)page->index << PAGE_SHIFT, pHandle, pHandle->hHost));
     1342
     1343    if (pHandle) {
     1344        struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
     1345        VBOXSFWRITEPGLSTREQ    *pReq = (VBOXSFWRITEPGLSTREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
     1346        if (pReq) {
     1347            uint64_t const cbFile    = i_size_read(inode);
     1348            uint64_t const offInFile = (uint64_t)page->index << PAGE_SHIFT;
     1349            uint32_t const cbToWrite = page->index != (cbFile >> PAGE_SHIFT) ? PAGE_SIZE
     1350                                     : (uint32_t)cbFile & (uint32_t)PAGE_OFFSET_MASK;
     1351            int            vrc;
     1352
     1353            pReq->PgLst.offFirstPage = 0;
     1354            pReq->PgLst.aPages[0]    = page_to_phys(page);
     1355            vrc = VbglR0SfHostReqWritePgLst(sf_g->map.root,
     1356                            pReq,
     1357                            pHandle->hHost,
     1358                            offInFile,
     1359                            cbToWrite,
     1360                            1 /*cPages*/);
     1361            AssertMsgStmt(pReq->Parms.cb32Write.u.value32 == cbToWrite || RT_FAILURE(vrc), /* lazy bird */
     1362                      ("%#x vs %#x\n", pReq->Parms.cb32Write, cbToWrite),
     1363                      vrc = VERR_WRITE_ERROR);
     1364            VbglR0PhysHeapFree(pReq);
     1365
     1366            if (RT_SUCCESS(vrc)) {
     1367                /* Update the inode if we've extended the file. */
     1368                /** @todo is this necessary given the cbToWrite calc above? */
     1369                uint64_t const offEndOfWrite = offInFile + cbToWrite;
     1370                if (   offEndOfWrite > cbFile
     1371                    && offEndOfWrite > i_size_read(inode))
     1372                    i_size_write(inode, offEndOfWrite);
     1373
     1374                if (PageError(page))
     1375                    ClearPageError(page);
     1376
     1377                err = 0;
     1378            } else {
     1379                ClearPageUptodate(page);
     1380                err = -EPROTO;
     1381            }
     1382        } else
     1383            err = -ENOMEM;
     1384        sf_handle_release(pHandle, sf_g, "sf_writepage");
     1385    } else {
     1386        static uint64_t volatile s_cCalls = 0;
     1387        if (s_cCalls++ < 16)
     1388            printk("sf_writepage: no writable handle for %s..\n", sf_i->path->String.ach);
     1389        err = -EPROTO;
     1390    }
     1391    unlock_page(page);
     1392    return err;
    13941393}
    13951394
     
    13991398 */
    14001399int sf_write_begin(struct file *file, struct address_space *mapping, loff_t pos,
    1401                    unsigned len, unsigned flags, struct page **pagep,
    1402                    void **fsdata)
    1403 {
    1404         /** @todo r=bird: We shouldn't ever get here, should we?  Because we don't use
    1405         *        the page cache for any writes AFAIK.  We could just as well use
    1406         *        simple_write_begin & simple_write_end here if we think we really
    1407         *        need to have non-NULL function pointers in the table... */
    1408         static uint64_t volatile s_cCalls = 0;
    1409         if (s_cCalls++ < 16) {
    1410                 printk("vboxsf: Unexpected call to sf_write_begin(pos=%#llx len=%#x flags=%#x)! Please report.\n",
    1411                        (unsigned long long)pos, len, flags);
    1412                 RTLogBackdoorPrintf("vboxsf: Unexpected call to sf_write_begin(pos=%#llx len=%#x flags=%#x)!  Please report.\n",
    1413                                     (unsigned long long)pos, len, flags);
     1400           unsigned len, unsigned flags, struct page **pagep,
     1401           void **fsdata)
     1402{
     1403    /** @todo r=bird: We shouldn't ever get here, should we?  Because we don't use
     1404    *        the page cache for any writes AFAIK.  We could just as well use
     1405    *        simple_write_begin & simple_write_end here if we think we really
     1406    *        need to have non-NULL function pointers in the table... */
     1407    static uint64_t volatile s_cCalls = 0;
     1408    if (s_cCalls++ < 16) {
     1409        printk("vboxsf: Unexpected call to sf_write_begin(pos=%#llx len=%#x flags=%#x)! Please report.\n",
     1410               (unsigned long long)pos, len, flags);
     1411        RTLogBackdoorPrintf("vboxsf: Unexpected call to sf_write_begin(pos=%#llx len=%#x flags=%#x)!  Please report.\n",
     1412                    (unsigned long long)pos, len, flags);
    14141413#  ifdef WARN_ON
    1415                 WARN_ON(1);
     1414        WARN_ON(1);
    14161415#  endif
    1417         }
    1418         return simple_write_begin(file, mapping, pos, len, flags, pagep, fsdata);
    1419 }
    1420 # endif /* KERNEL_VERSION >= 2.6.24 */
     1416    }
     1417    return simple_write_begin(file, mapping, pos, len, flags, pagep, fsdata);
     1418}
     1419# endif /* KERNEL_VERSION >= 2.6.24 */
    14211420
    14221421# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 10)
     
    14451444#  endif
    14461445{
    1447         TRACE();
    1448         return -EINVAL;
     1446    TRACE();
     1447    return -EINVAL;
    14491448}
    14501449# endif
    14511450
    14521451struct address_space_operations sf_reg_aops = {
    1453         .readpage = sf_readpage,
    1454         .writepage = sf_writepage,
    1455         /** @todo Need .writepages if we want msync performance...  */
     1452    .readpage = sf_readpage,
     1453    .writepage = sf_writepage,
     1454    /** @todo Need .writepages if we want msync performance...  */
    14561455# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 12)
    1457         .set_page_dirty = __set_page_dirty_buffers,
     1456    .set_page_dirty = __set_page_dirty_buffers,
    14581457# endif
    14591458# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
    1460         .write_begin = sf_write_begin,
    1461         .write_end = simple_write_end,
     1459    .write_begin = sf_write_begin,
     1460    .write_end = simple_write_end,
    14621461# else
    1463         .prepare_write = simple_prepare_write,
    1464         .commit_write = simple_commit_write,
     1462    .prepare_write = simple_prepare_write,
     1463    .commit_write = simple_commit_write,
    14651464# endif
    14661465# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 10)
    1467         .direct_IO = sf_direct_IO,
     1466    .direct_IO = sf_direct_IO,
    14681467# endif
    14691468};
  • trunk/src/VBox/Additions/linux/sharedfolders/utils.c

    r77524 r77526  
    4343DECLINLINE(void) sf_ftime_from_timespec(time_t *pLinuxDst, PCRTTIMESPEC pVBoxSrc)
    4444{
    45         int64_t t = RTTimeSpecGetNano(pVBoxSrc);
    46         do_div(t, RT_NS_1SEC);
    47         *pLinuxDst = t;
    48 }
    49 #else   /* >= 2.6.0 */
     45    int64_t t = RTTimeSpecGetNano(pVBoxSrc);
     46    do_div(t, RT_NS_1SEC);
     47    *pLinuxDst = t;
     48}
     49#else   /* >= 2.6.0 */
    5050# if LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0)
    5151DECLINLINE(void) sf_ftime_from_timespec(struct timespec *pLinuxDst, PCRTTIMESPEC pVBoxSrc)
     
    5454# endif
    5555{
    56         int64_t t = RTTimeSpecGetNano(pVBoxSrc);
    57         pLinuxDst->tv_nsec = do_div(t, RT_NS_1SEC);
    58         pLinuxDst->tv_sec  = t;
    59 }
    60 #endif  /* >= 2.6.0 */
     56    int64_t t = RTTimeSpecGetNano(pVBoxSrc);
     57    pLinuxDst->tv_nsec = do_div(t, RT_NS_1SEC);
     58    pLinuxDst->tv_sec  = t;
     59}
     60#endif  /* >= 2.6.0 */
    6161
    6262
     
    6767DECLINLINE(void) sf_timespec_from_ftime(PRTTIMESPEC pVBoxDst, time_t *pLinuxSrc)
    6868{
    69         RTTimeSpecSetNano(pVBoxDst, RT_NS_1SEC_64 * *pLinuxSrc);
    70 }
    71 #else   /* >= 2.6.0 */
     69    RTTimeSpecSetNano(pVBoxDst, RT_NS_1SEC_64 * *pLinuxSrc);
     70}
     71#else   /* >= 2.6.0 */
    7272# if LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0)
    7373DECLINLINE(void) sf_timespec_from_ftime(PRTTIMESPEC pVBoxDst, struct timespec const *pLinuxSrc)
     
    7676# endif
    7777{
    78         RTTimeSpecSetNano(pVBoxDst, pLinuxSrc->tv_nsec + pLinuxSrc->tv_sec * (int64_t)RT_NS_1SEC);
    79 }
    80 #endif  /* >= 2.6.0 */
     78    RTTimeSpecSetNano(pVBoxDst, pLinuxSrc->tv_nsec + pLinuxSrc->tv_sec * (int64_t)RT_NS_1SEC);
     79}
     80#endif  /* >= 2.6.0 */
    8181
    8282
     
    8888DECLINLINE(int) sf_convert_access_perms(uint32_t fAttr)
    8989{
    90         /* Access bits should be the same: */
    91         AssertCompile(RTFS_UNIX_IRUSR == S_IRUSR);
    92         AssertCompile(RTFS_UNIX_IWUSR == S_IWUSR);
    93         AssertCompile(RTFS_UNIX_IXUSR == S_IXUSR);
    94         AssertCompile(RTFS_UNIX_IRGRP == S_IRGRP);
    95         AssertCompile(RTFS_UNIX_IWGRP == S_IWGRP);
    96         AssertCompile(RTFS_UNIX_IXGRP == S_IXGRP);
    97         AssertCompile(RTFS_UNIX_IROTH == S_IROTH);
    98         AssertCompile(RTFS_UNIX_IWOTH == S_IWOTH);
    99         AssertCompile(RTFS_UNIX_IXOTH == S_IXOTH);
    100 
    101         return fAttr & RTFS_UNIX_ALL_ACCESS_PERMS;
     90    /* Access bits should be the same: */
     91    AssertCompile(RTFS_UNIX_IRUSR == S_IRUSR);
     92    AssertCompile(RTFS_UNIX_IWUSR == S_IWUSR);
     93    AssertCompile(RTFS_UNIX_IXUSR == S_IXUSR);
     94    AssertCompile(RTFS_UNIX_IRGRP == S_IRGRP);
     95    AssertCompile(RTFS_UNIX_IWGRP == S_IWGRP);
     96    AssertCompile(RTFS_UNIX_IXGRP == S_IXGRP);
     97    AssertCompile(RTFS_UNIX_IROTH == S_IROTH);
     98    AssertCompile(RTFS_UNIX_IWOTH == S_IWOTH);
     99    AssertCompile(RTFS_UNIX_IXOTH == S_IXOTH);
     100
     101    return fAttr & RTFS_UNIX_ALL_ACCESS_PERMS;
    102102}
    103103
     
    108108DECLINLINE(int) sf_convert_file_mode(uint32_t fVBoxMode, int fFixedMode, int fClearMask, int fType)
    109109{
    110         int fLnxMode = sf_convert_access_perms(fVBoxMode);
    111         if (fFixedMode != ~0)
    112                 fLnxMode = fFixedMode & 0777;
    113         fLnxMode &= ~fClearMask;
    114         fLnxMode |= fType;
    115         return fLnxMode;
     110    int fLnxMode = sf_convert_access_perms(fVBoxMode);
     111    if (fFixedMode != ~0)
     112        fLnxMode = fFixedMode & 0777;
     113    fLnxMode &= ~fClearMask;
     114    fLnxMode |= fType;
     115    return fLnxMode;
    116116}
    117117
     
    122122void sf_init_inode(struct inode *inode, struct sf_inode_info *sf_i, PSHFLFSOBJINFO pObjInfo, struct vbsf_super_info *sf_g)
    123123{
    124         PCSHFLFSOBJATTR pAttr = &pObjInfo->Attr;
    125 
    126         TRACE();
    127 
    128         sf_i->ts_up_to_date = jiffies;
    129         sf_i->force_restat  = 0;
     124    PCSHFLFSOBJATTR pAttr = &pObjInfo->Attr;
     125
     126    TRACE();
     127
     128    sf_i->ts_up_to_date = jiffies;
     129    sf_i->force_restat  = 0;
    130130
    131131#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
    132         inode->i_mapping->a_ops = &sf_reg_aops;
     132    inode->i_mapping->a_ops = &sf_reg_aops;
    133133# if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19, 0)
    134         inode->i_mapping->backing_dev_info = &sf_g->bdi; /* This is needed for mmap. */
     134    inode->i_mapping->backing_dev_info = &sf_g->bdi; /* This is needed for mmap. */
    135135# endif
    136136#endif
    137         if (RTFS_IS_DIRECTORY(pAttr->fMode)) {
    138                 inode->i_mode = sf_convert_file_mode(pAttr->fMode, sf_g->dmode, sf_g->dmask, S_IFDIR);
    139                 inode->i_op = &sf_dir_iops;
    140                 inode->i_fop = &sf_dir_fops;
    141 
    142                 /* XXX: this probably should be set to the number of entries
    143                    in the directory plus two (. ..) */
    144                 set_nlink(inode, 1);
    145         }
     137    if (RTFS_IS_DIRECTORY(pAttr->fMode)) {
     138        inode->i_mode = sf_convert_file_mode(pAttr->fMode, sf_g->dmode, sf_g->dmask, S_IFDIR);
     139        inode->i_op = &sf_dir_iops;
     140        inode->i_fop = &sf_dir_fops;
     141
     142        /* XXX: this probably should be set to the number of entries
     143           in the directory plus two (. ..) */
     144        set_nlink(inode, 1);
     145    }
    146146#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
    147         else if (RTFS_IS_SYMLINK(pAttr->fMode)) {
    148                 /** @todo r=bird: Aren't System V symlinks w/o any mode mask? IIRC there is
    149                 *        no lchmod on Linux. */
    150                 inode->i_mode = sf_convert_file_mode(pAttr->fMode, sf_g->fmode, sf_g->fmask, S_IFLNK);
    151                 inode->i_op = &sf_lnk_iops;
    152                 set_nlink(inode, 1);
    153         }
    154 #endif
    155         else {
    156                 inode->i_mode = sf_convert_file_mode(pAttr->fMode, sf_g->fmode, sf_g->fmask, S_IFREG);
    157                 inode->i_op = &sf_reg_iops;
    158                 inode->i_fop = &sf_reg_fops;
    159                 set_nlink(inode, 1);
    160         }
     147    else if (RTFS_IS_SYMLINK(pAttr->fMode)) {
     148        /** @todo r=bird: Aren't System V symlinks w/o any mode mask? IIRC there is
     149        *        no lchmod on Linux. */
     150        inode->i_mode = sf_convert_file_mode(pAttr->fMode, sf_g->fmode, sf_g->fmask, S_IFLNK);
     151        inode->i_op = &sf_lnk_iops;
     152        set_nlink(inode, 1);
     153    }
     154#endif
     155    else {
     156        inode->i_mode = sf_convert_file_mode(pAttr->fMode, sf_g->fmode, sf_g->fmask, S_IFREG);
     157        inode->i_op = &sf_reg_iops;
     158        inode->i_fop = &sf_reg_fops;
     159        set_nlink(inode, 1);
     160    }
    161161
    162162#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
    163         inode->i_uid = make_kuid(current_user_ns(), sf_g->uid);
    164         inode->i_gid = make_kgid(current_user_ns(), sf_g->gid);
     163    inode->i_uid = make_kuid(current_user_ns(), sf_g->uid);
     164    inode->i_gid = make_kgid(current_user_ns(), sf_g->gid);
    165165#else
    166         inode->i_uid = sf_g->uid;
    167         inode->i_gid = sf_g->gid;
    168 #endif
    169 
    170         inode->i_size = pObjInfo->cbObject;
     166    inode->i_uid = sf_g->uid;
     167    inode->i_gid = sf_g->gid;
     168#endif
     169
     170    inode->i_size = pObjInfo->cbObject;
    171171#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) && !defined(KERNEL_FC6)
    172         inode->i_blksize = 4096;
     172    inode->i_blksize = 4096;
    173173#endif
    174174#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 11)
    175         inode->i_blkbits = 12;
    176 #endif
    177         /* i_blocks always in units of 512 bytes! */
    178         inode->i_blocks = (pObjInfo->cbAllocated + 511) / 512;
    179 
    180         sf_ftime_from_timespec(&inode->i_atime, &pObjInfo->AccessTime);
    181         sf_ftime_from_timespec(&inode->i_ctime, &pObjInfo->ChangeTime);
    182         sf_ftime_from_timespec(&inode->i_mtime, &pObjInfo->ModificationTime);
    183         sf_i->BirthTime = pObjInfo->BirthTime;
     175    inode->i_blkbits = 12;
     176#endif
     177    /* i_blocks always in units of 512 bytes! */
     178    inode->i_blocks = (pObjInfo->cbAllocated + 511) / 512;
     179
     180    sf_ftime_from_timespec(&inode->i_atime, &pObjInfo->AccessTime);
     181    sf_ftime_from_timespec(&inode->i_ctime, &pObjInfo->ChangeTime);
     182    sf_ftime_from_timespec(&inode->i_mtime, &pObjInfo->ModificationTime);
     183    sf_i->BirthTime = pObjInfo->BirthTime;
    184184}
    185185
     
    193193 */
    194194static void sf_update_inode(struct inode *pInode, struct sf_inode_info *pInodeInfo, PSHFLFSOBJINFO pObjInfo,
    195                             struct vbsf_super_info *sf_g, bool fInodeLocked)
    196 {
    197         PCSHFLFSOBJATTR pAttr = &pObjInfo->Attr;
    198         int fMode;
    199 
    200         TRACE();
     195                            struct vbsf_super_info *sf_g, bool fInodeLocked)
     196{
     197    PCSHFLFSOBJATTR pAttr = &pObjInfo->Attr;
     198    int fMode;
     199
     200    TRACE();
    201201
    202202#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
    203         if (!fInodeLocked)
    204                 inode_lock(pInode);
    205 #endif
    206 
    207         /*
    208         * Calc new mode mask and update it if it changed.
    209         */
    210         if (RTFS_IS_DIRECTORY(pAttr->fMode))
    211                 fMode = sf_convert_file_mode(pAttr->fMode, sf_g->dmode, sf_g->dmask, S_IFDIR);
     203    if (!fInodeLocked)
     204        inode_lock(pInode);
     205#endif
     206
     207    /*
     208    * Calc new mode mask and update it if it changed.
     209    */
     210    if (RTFS_IS_DIRECTORY(pAttr->fMode))
     211        fMode = sf_convert_file_mode(pAttr->fMode, sf_g->dmode, sf_g->dmask, S_IFDIR);
    212212#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
    213         else if (RTFS_IS_SYMLINK(pAttr->fMode))
    214                 /** @todo r=bird: Aren't System V symlinks w/o any mode mask? IIRC there is
    215                 *        no lchmod on Linux. */
    216                 fMode = sf_convert_file_mode(pAttr->fMode, sf_g->fmode, sf_g->fmask, S_IFLNK);
    217 #endif
    218         else
    219                 fMode = sf_convert_file_mode(pAttr->fMode, sf_g->fmode, sf_g->fmask, S_IFREG);
    220 
    221         if (fMode == pInode->i_mode) {
    222                 /* likely */
    223         } else {
    224                 if ((fMode & S_IFMT) == (pInode->i_mode & S_IFMT))
    225                         pInode->i_mode = fMode;
    226                 else {
    227                         SFLOGFLOW(("sf_update_inode: Changed from %o to %o (%s)\n",
    228                                    pInode->i_mode & S_IFMT, fMode & S_IFMT, pInodeInfo->path->String.ach));
    229                         /** @todo we probably need to be more drastic... */
    230                         sf_init_inode(pInode, pInodeInfo, pObjInfo, sf_g);
     213    else if (RTFS_IS_SYMLINK(pAttr->fMode))
     214        /** @todo r=bird: Aren't System V symlinks w/o any mode mask? IIRC there is
     215        *        no lchmod on Linux. */
     216        fMode = sf_convert_file_mode(pAttr->fMode, sf_g->fmode, sf_g->fmask, S_IFLNK);
     217#endif
     218    else
     219        fMode = sf_convert_file_mode(pAttr->fMode, sf_g->fmode, sf_g->fmask, S_IFREG);
     220
     221    if (fMode == pInode->i_mode) {
     222        /* likely */
     223    } else {
     224        if ((fMode & S_IFMT) == (pInode->i_mode & S_IFMT))
     225            pInode->i_mode = fMode;
     226        else {
     227            SFLOGFLOW(("sf_update_inode: Changed from %o to %o (%s)\n",
     228                   pInode->i_mode & S_IFMT, fMode & S_IFMT, pInodeInfo->path->String.ach));
     229            /** @todo we probably need to be more drastic... */
     230            sf_init_inode(pInode, pInodeInfo, pObjInfo, sf_g);
    231231
    232232#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
    233                         if (!fInodeLocked)
    234                                 inode_unlock(pInode);
    235 #endif
    236                         return;
    237                 }
    238         }
    239 
    240         /*
    241         * Update the sizes.
    242         * Note! i_blocks is always in units of 512 bytes!
    243         */
    244         pInode->i_blocks = (pObjInfo->cbAllocated + 511) / 512;
    245         i_size_write(pInode, pObjInfo->cbObject);
    246 
    247         /*
    248         * Update the timestamps.
    249         */
    250         sf_ftime_from_timespec(&pInode->i_atime, &pObjInfo->AccessTime);
    251         sf_ftime_from_timespec(&pInode->i_ctime, &pObjInfo->ChangeTime);
    252         sf_ftime_from_timespec(&pInode->i_mtime, &pObjInfo->ModificationTime);
    253         pInodeInfo->BirthTime = pObjInfo->BirthTime;
    254 
    255         /*
    256         * Mark it as up to date.
    257         */
    258         pInodeInfo->ts_up_to_date = jiffies;
    259         pInodeInfo->force_restat  = 0;
     233            if (!fInodeLocked)
     234                inode_unlock(pInode);
     235#endif
     236            return;
     237        }
     238    }
     239
     240    /*
     241    * Update the sizes.
     242    * Note! i_blocks is always in units of 512 bytes!
     243    */
     244    pInode->i_blocks = (pObjInfo->cbAllocated + 511) / 512;
     245    i_size_write(pInode, pObjInfo->cbObject);
     246
     247    /*
     248    * Update the timestamps.
     249    */
     250    sf_ftime_from_timespec(&pInode->i_atime, &pObjInfo->AccessTime);
     251    sf_ftime_from_timespec(&pInode->i_ctime, &pObjInfo->ChangeTime);
     252    sf_ftime_from_timespec(&pInode->i_mtime, &pObjInfo->ModificationTime);
     253    pInodeInfo->BirthTime = pObjInfo->BirthTime;
     254
     255    /*
     256    * Mark it as up to date.
     257    */
     258    pInodeInfo->ts_up_to_date = jiffies;
     259    pInodeInfo->force_restat  = 0;
    260260
    261261#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
    262         if (!fInodeLocked)
    263                 inode_unlock(pInode);
     262    if (!fInodeLocked)
     263        inode_unlock(pInode);
    264264#endif
    265265}
     
    268268/** @note Currently only used for the root directory during (re-)mount.  */
    269269int sf_stat(const char *caller, struct vbsf_super_info *sf_g,
    270             SHFLSTRING *path, PSHFLFSOBJINFO result, int ok_to_fail)
    271 {
    272         int rc;
    273         VBOXSFCREATEREQ *pReq;
    274         NOREF(caller);
    275 
    276         TRACE();
    277 
    278         pReq = (VBOXSFCREATEREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq) + path->u16Size);
    279         if (pReq) {
    280                 RT_ZERO(*pReq);
    281                 memcpy(&pReq->StrPath, path, SHFLSTRING_HEADER_SIZE + path->u16Size);
    282                 pReq->CreateParms.Handle = SHFL_HANDLE_NIL;
    283                 pReq->CreateParms.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;
    284 
    285                 LogFunc(("Calling VbglR0SfHostReqCreate on %s\n", path->String.utf8));
    286                 rc = VbglR0SfHostReqCreate(sf_g->map.root, pReq);
    287                 if (RT_SUCCESS(rc)) {
    288                         if (pReq->CreateParms.Result == SHFL_FILE_EXISTS) {
    289                                 *result = pReq->CreateParms.Info;
    290                                 rc = 0;
    291                         } else {
    292                                 if (!ok_to_fail)
    293                                         LogFunc(("VbglR0SfHostReqCreate on %s: file does not exist: %d (caller=%s)\n",
    294                                                 path->String.utf8, pReq->CreateParms.Result, caller));
    295                                 rc = -ENOENT;
    296                         }
    297                 } else if (rc == VERR_INVALID_NAME) {
    298                         rc = -ENOENT; /* this can happen for names like 'foo*' on a Windows host */
    299                 } else {
    300                         LogFunc(("VbglR0SfHostReqCreate failed on %s: %Rrc (caller=%s)\n", path->String.utf8, rc, caller));
    301                         rc = -EPROTO;
    302                 }
    303                 VbglR0PhysHeapFree(pReq);
    304         }
    305         else
    306                 rc = -ENOMEM;
    307         return rc;
     270            SHFLSTRING *path, PSHFLFSOBJINFO result, int ok_to_fail)
     271{
     272    int rc;
     273    VBOXSFCREATEREQ *pReq;
     274    NOREF(caller);
     275
     276    TRACE();
     277
     278    pReq = (VBOXSFCREATEREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq) + path->u16Size);
     279    if (pReq) {
     280        RT_ZERO(*pReq);
     281        memcpy(&pReq->StrPath, path, SHFLSTRING_HEADER_SIZE + path->u16Size);
     282        pReq->CreateParms.Handle = SHFL_HANDLE_NIL;
     283        pReq->CreateParms.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;
     284
     285        LogFunc(("Calling VbglR0SfHostReqCreate on %s\n", path->String.utf8));
     286        rc = VbglR0SfHostReqCreate(sf_g->map.root, pReq);
     287        if (RT_SUCCESS(rc)) {
     288            if (pReq->CreateParms.Result == SHFL_FILE_EXISTS) {
     289                *result = pReq->CreateParms.Info;
     290                rc = 0;
     291            } else {
     292                if (!ok_to_fail)
     293                    LogFunc(("VbglR0SfHostReqCreate on %s: file does not exist: %d (caller=%s)\n",
     294                        path->String.utf8, pReq->CreateParms.Result, caller));
     295                rc = -ENOENT;
     296            }
     297        } else if (rc == VERR_INVALID_NAME) {
     298            rc = -ENOENT; /* this can happen for names like 'foo*' on a Windows host */
     299        } else {
     300            LogFunc(("VbglR0SfHostReqCreate failed on %s: %Rrc (caller=%s)\n", path->String.utf8, rc, caller));
     301            rc = -EPROTO;
     302        }
     303        VbglR0PhysHeapFree(pReq);
     304    }
     305    else
     306        rc = -ENOMEM;
     307    return rc;
    308308}
    309309
     
    315315int sf_inode_revalidate_worker(struct dentry *dentry, bool fForced)
    316316{
    317         int rc;
    318         struct inode *pInode = dentry ? dentry->d_inode : NULL;
    319         if (pInode) {
    320                 struct sf_inode_info   *sf_i = GET_INODE_INFO(pInode);
    321                 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(pInode->i_sb);
    322                 AssertReturn(sf_i, -EINVAL);
    323                 AssertReturn(sf_g, -EINVAL);
    324 
    325                 /*
    326                 * Can we get away without any action here?
    327                 */
    328                 if (   !fForced
    329                     && !sf_i->force_restat
    330                     && jiffies - sf_i->ts_up_to_date < sf_g->ttl)
    331                         rc = 0;
    332                 else {
    333                         /*
    334                         * No, we have to query the file info from the host.
    335                         * Try get a handle we can query, any kind of handle will do here.
    336                         */
    337                         struct sf_handle *pHandle = sf_handle_find(sf_i, 0, 0);
    338                         if (pHandle) {
    339                                 /* Query thru pHandle. */
    340                                 VBOXSFOBJINFOREQ *pReq = (VBOXSFOBJINFOREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
    341                                 if (pReq) {
    342                                         RT_ZERO(*pReq);
    343                                         rc = VbglR0SfHostReqQueryObjInfo(sf_g->map.root, pReq, pHandle->hHost);
    344                                         if (RT_SUCCESS(rc)) {
    345                                                 /*
    346                                                 * Reset the TTL and copy the info over into the inode structure.
    347                                                 */
    348                                                 sf_update_inode(pInode, sf_i, &pReq->ObjInfo, sf_g, true /*fInodeLocked??*/);
    349                                         } else if (rc == VERR_INVALID_HANDLE) {
    350                                                 rc = -ENOENT; /* Restore.*/
    351                                         } else {
    352                                                 LogFunc(("VbglR0SfHostReqQueryObjInfo failed on %#RX64: %Rrc\n", pHandle->hHost, rc));
    353                                                 rc = -RTErrConvertToErrno(rc);
    354                                         }
    355                                         VbglR0PhysHeapFree(pReq);
    356                                 } else
    357                                         rc = -ENOMEM;
    358                                 sf_handle_release(pHandle, sf_g, "sf_inode_revalidate_worker");
    359 
    360                         } else {
    361                                 /* Query via path. */
    362                                 SHFLSTRING      *pPath = sf_i->path;
    363                                 VBOXSFCREATEREQ *pReq  = (VBOXSFCREATEREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq) + pPath->u16Size);
    364                                 if (pReq) {
    365                                         RT_ZERO(*pReq);
    366                                         memcpy(&pReq->StrPath, pPath, SHFLSTRING_HEADER_SIZE + pPath->u16Size);
    367                                         pReq->CreateParms.Handle      = SHFL_HANDLE_NIL;
    368                                         pReq->CreateParms.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;
    369 
    370                                         rc = VbglR0SfHostReqCreate(sf_g->map.root, pReq);
    371                                         if (RT_SUCCESS(rc)) {
    372                                                 if (pReq->CreateParms.Result == SHFL_FILE_EXISTS) {
    373                                                         /*
    374                                                         * Reset the TTL and copy the info over into the inode structure.
    375                                                         */
    376                                                         sf_update_inode(pInode, sf_i, &pReq->CreateParms.Info,
    377                                                                         sf_g, true /*fInodeLocked??*/);
    378                                                         rc = 0;
    379                                                 } else {
    380                                                         rc = -ENOENT;
    381                                                 }
    382                                         } else if (rc == VERR_INVALID_NAME) {
    383                                                 rc = -ENOENT; /* this can happen for names like 'foo*' on a Windows host */
    384                                         } else {
    385                                                 LogFunc(("VbglR0SfHostReqCreate failed on %s: %Rrc\n", pPath->String.ach, rc));
    386                                                 rc = -EPROTO;
    387                                         }
    388                                         VbglR0PhysHeapFree(pReq);
    389                                 }
    390                                 else
    391                                         rc = -ENOMEM;
    392                         }
    393                 }
    394         } else {
    395                 LogFunc(("no dentry(%p) or inode(%p)\n", dentry, pInode));
    396                 rc = -EINVAL;
    397         }
    398         return rc;
     317    int rc;
     318    struct inode *pInode = dentry ? dentry->d_inode : NULL;
     319    if (pInode) {
     320        struct sf_inode_info   *sf_i = GET_INODE_INFO(pInode);
     321        struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(pInode->i_sb);
     322        AssertReturn(sf_i, -EINVAL);
     323        AssertReturn(sf_g, -EINVAL);
     324
     325        /*
     326        * Can we get away without any action here?
     327        */
     328        if (   !fForced
     329            && !sf_i->force_restat
     330            && jiffies - sf_i->ts_up_to_date < sf_g->ttl)
     331            rc = 0;
     332        else {
     333            /*
     334            * No, we have to query the file info from the host.
     335            * Try get a handle we can query, any kind of handle will do here.
     336            */
     337            struct sf_handle *pHandle = sf_handle_find(sf_i, 0, 0);
     338            if (pHandle) {
     339                /* Query thru pHandle. */
     340                VBOXSFOBJINFOREQ *pReq = (VBOXSFOBJINFOREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
     341                if (pReq) {
     342                    RT_ZERO(*pReq);
     343                    rc = VbglR0SfHostReqQueryObjInfo(sf_g->map.root, pReq, pHandle->hHost);
     344                    if (RT_SUCCESS(rc)) {
     345                        /*
     346                        * Reset the TTL and copy the info over into the inode structure.
     347                        */
     348                        sf_update_inode(pInode, sf_i, &pReq->ObjInfo, sf_g, true /*fInodeLocked??*/);
     349                    } else if (rc == VERR_INVALID_HANDLE) {
     350                        rc = -ENOENT; /* Restore.*/
     351                    } else {
     352                        LogFunc(("VbglR0SfHostReqQueryObjInfo failed on %#RX64: %Rrc\n", pHandle->hHost, rc));
     353                        rc = -RTErrConvertToErrno(rc);
     354                    }
     355                    VbglR0PhysHeapFree(pReq);
     356                } else
     357                    rc = -ENOMEM;
     358                sf_handle_release(pHandle, sf_g, "sf_inode_revalidate_worker");
     359
     360            } else {
     361                /* Query via path. */
     362                SHFLSTRING      *pPath = sf_i->path;
     363                VBOXSFCREATEREQ *pReq  = (VBOXSFCREATEREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq) + pPath->u16Size);
     364                if (pReq) {
     365                    RT_ZERO(*pReq);
     366                    memcpy(&pReq->StrPath, pPath, SHFLSTRING_HEADER_SIZE + pPath->u16Size);
     367                    pReq->CreateParms.Handle      = SHFL_HANDLE_NIL;
     368                    pReq->CreateParms.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;
     369
     370                    rc = VbglR0SfHostReqCreate(sf_g->map.root, pReq);
     371                    if (RT_SUCCESS(rc)) {
     372                        if (pReq->CreateParms.Result == SHFL_FILE_EXISTS) {
     373                            /*
     374                            * Reset the TTL and copy the info over into the inode structure.
     375                            */
     376                            sf_update_inode(pInode, sf_i, &pReq->CreateParms.Info,
     377                                    sf_g, true /*fInodeLocked??*/);
     378                            rc = 0;
     379                        } else {
     380                            rc = -ENOENT;
     381                        }
     382                    } else if (rc == VERR_INVALID_NAME) {
     383                        rc = -ENOENT; /* this can happen for names like 'foo*' on a Windows host */
     384                    } else {
     385                        LogFunc(("VbglR0SfHostReqCreate failed on %s: %Rrc\n", pPath->String.ach, rc));
     386                        rc = -EPROTO;
     387                    }
     388                    VbglR0PhysHeapFree(pReq);
     389                }
     390                else
     391                    rc = -ENOMEM;
     392            }
     393        }
     394    } else {
     395        LogFunc(("no dentry(%p) or inode(%p)\n", dentry, pInode));
     396        rc = -EINVAL;
     397    }
     398    return rc;
    399399}
    400400
     
    421421int sf_inode_revalidate_with_handle(struct dentry *dentry, SHFLHANDLE hHostFile, bool fForced, bool fInodeLocked)
    422422{
    423         int err;
    424         struct inode *pInode = dentry ? dentry->d_inode : NULL;
    425         if (!pInode) {
    426                 LogFunc(("no dentry(%p) or inode(%p)\n", dentry, pInode));
    427                 err = -EINVAL;
    428         } else {
    429                 struct sf_inode_info   *sf_i = GET_INODE_INFO(pInode);
    430                 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(pInode->i_sb);
    431                 AssertReturn(sf_i, -EINVAL);
    432                 AssertReturn(sf_g, -EINVAL);
    433 
    434                 /*
    435                 * Can we get away without any action here?
    436                 */
    437                 if (   !fForced
    438                     && !sf_i->force_restat
    439                     && jiffies - sf_i->ts_up_to_date < sf_g->ttl)
    440                         err = 0;
    441                 else {
    442                         /*
    443                         * No, we have to query the file info from the host.
    444                         */
    445                         VBOXSFOBJINFOREQ *pReq = (VBOXSFOBJINFOREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
    446                         if (pReq) {
    447                                 RT_ZERO(*pReq);
    448                                 err = VbglR0SfHostReqQueryObjInfo(sf_g->map.root, pReq, hHostFile);
    449                                 if (RT_SUCCESS(err)) {
    450                                         /*
    451                                         * Reset the TTL and copy the info over into the inode structure.
    452                                         */
    453                                         sf_update_inode(pInode, sf_i, &pReq->ObjInfo, sf_g, fInodeLocked);
    454                                 } else {
    455                                         LogFunc(("VbglR0SfHostReqQueryObjInfo failed on %#RX64: %Rrc\n", hHostFile, err));
    456                                         err = -RTErrConvertToErrno(err);
    457                                 }
    458                                 VbglR0PhysHeapFree(pReq);
    459                         } else
    460                                 err = -ENOMEM;
    461                 }
    462         }
    463         return err;
     423    int err;
     424    struct inode *pInode = dentry ? dentry->d_inode : NULL;
     425    if (!pInode) {
     426        LogFunc(("no dentry(%p) or inode(%p)\n", dentry, pInode));
     427        err = -EINVAL;
     428    } else {
     429        struct sf_inode_info   *sf_i = GET_INODE_INFO(pInode);
     430        struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(pInode->i_sb);
     431        AssertReturn(sf_i, -EINVAL);
     432        AssertReturn(sf_g, -EINVAL);
     433
     434        /*
     435        * Can we get away without any action here?
     436        */
     437        if (   !fForced
     438            && !sf_i->force_restat
     439            && jiffies - sf_i->ts_up_to_date < sf_g->ttl)
     440            err = 0;
     441        else {
     442            /*
     443            * No, we have to query the file info from the host.
     444            */
     445            VBOXSFOBJINFOREQ *pReq = (VBOXSFOBJINFOREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
     446            if (pReq) {
     447                RT_ZERO(*pReq);
     448                err = VbglR0SfHostReqQueryObjInfo(sf_g->map.root, pReq, hHostFile);
     449                if (RT_SUCCESS(err)) {
     450                    /*
     451                    * Reset the TTL and copy the info over into the inode structure.
     452                    */
     453                    sf_update_inode(pInode, sf_i, &pReq->ObjInfo, sf_g, fInodeLocked);
     454                } else {
     455                    LogFunc(("VbglR0SfHostReqQueryObjInfo failed on %#RX64: %Rrc\n", hHostFile, err));
     456                    err = -RTErrConvertToErrno(err);
     457                }
     458                VbglR0PhysHeapFree(pReq);
     459            } else
     460                err = -ENOMEM;
     461        }
     462    }
     463    return err;
    464464}
    465465
     
    471471
    472472# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
    473 int sf_getattr(const struct path *path, struct kstat *kstat, u32 request_mask,
    474                unsigned int flags)
     473int sf_getattr(const struct path *path, struct kstat *kstat, u32 request_mask, unsigned int flags)
    475474# else
    476475int sf_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *kstat)
    477476# endif
    478477{
    479         int            rc;
     478    int            rc;
    480479# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
    481         struct dentry *dentry = path->dentry;
     480    struct dentry *dentry = path->dentry;
    482481# endif
    483482
    484483# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
    485         SFLOGFLOW(("sf_getattr: dentry=%p request_mask=%#x flags=%#x\n", dentry, request_mask, flags));
     484    SFLOGFLOW(("sf_getattr: dentry=%p request_mask=%#x flags=%#x\n", dentry, request_mask, flags));
    486485# else
    487         SFLOGFLOW(("sf_getattr: dentry=%p\n", dentry));
     486    SFLOGFLOW(("sf_getattr: dentry=%p\n", dentry));
    488487# endif
    489488
    490489# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
    491         /*
    492         * With the introduction of statx() userland can control whether we
    493         * update the inode information or not.
    494         */
    495         switch (flags & AT_STATX_SYNC_TYPE) {
    496                 default:
    497                         rc = sf_inode_revalidate_worker(dentry, false /*fForced*/);
    498                         break;
    499 
    500                 case AT_STATX_FORCE_SYNC:
    501                         rc = sf_inode_revalidate_worker(dentry, true /*fForced*/);
    502                         break;
    503 
    504                 case AT_STATX_DONT_SYNC:
    505                         rc = 0;
    506                         break;
    507         }
     490    /*
     491    * With the introduction of statx() userland can control whether we
     492    * update the inode information or not.
     493    */
     494    switch (flags & AT_STATX_SYNC_TYPE) {
     495        default:
     496            rc = sf_inode_revalidate_worker(dentry, false /*fForced*/);
     497            break;
     498
     499        case AT_STATX_FORCE_SYNC:
     500            rc = sf_inode_revalidate_worker(dentry, true /*fForced*/);
     501            break;
     502
     503        case AT_STATX_DONT_SYNC:
     504            rc = 0;
     505            break;
     506    }
    508507# else
    509         rc = sf_inode_revalidate_worker(dentry, false /*fForced*/);
     508    rc = sf_inode_revalidate_worker(dentry, false /*fForced*/);
    510509# endif
    511         if (rc == 0) {
    512                 /* Do generic filling in of info. */
    513                 generic_fillattr(dentry->d_inode, kstat);
    514 
    515                 /* Add birth time. */
     510    if (rc == 0) {
     511        /* Do generic filling in of info. */
     512        generic_fillattr(dentry->d_inode, kstat);
     513
     514        /* Add birth time. */
    516515#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
    517                 if (dentry->d_inode) {
    518                         struct sf_inode_info *pInodeInfo = GET_INODE_INFO(dentry->d_inode);
    519                         if (pInodeInfo) {
    520                                 sf_ftime_from_timespec(&kstat->btime, &pInodeInfo->BirthTime);
    521                                 kstat->result_mask |= STATX_BTIME;
    522                         }
    523                 }
    524 #endif
    525 
    526                 /*
    527                 * FsPerf shows the following numbers for sequential file access against
    528                 * a tmpfs folder on an AMD 1950X host running debian buster/sid:
    529                 *
    530                 * block size = r128600    ----- r128755 -----
    531                 *               reads      reads     writes
    532                 *    4096 KB = 2254 MB/s  4953 MB/s 3668 MB/s
    533                 *    2048 KB = 2368 MB/s  4908 MB/s 3541 MB/s
    534                 *    1024 KB = 2208 MB/s  4011 MB/s 3291 MB/s
    535                 *     512 KB = 1908 MB/s  3399 MB/s 2721 MB/s
    536                 *     256 KB = 1625 MB/s  2679 MB/s 2251 MB/s
    537                 *     128 KB = 1413 MB/s  1967 MB/s 1684 MB/s
    538                 *      64 KB = 1152 MB/s  1409 MB/s 1265 MB/s
    539                 *      32 KB =  726 MB/s   815 MB/s  783 MB/s
    540                 *      16 KB =             683 MB/s  475 MB/s
    541                 *       8 KB =             294 MB/s  286 MB/s
    542                 *       4 KB =  145 MB/s   156 MB/s  149 MB/s
    543                 *
    544                 */
    545                 if (S_ISREG(kstat->mode))
    546                         kstat->blksize = _1M;
    547                 else if (S_ISDIR(kstat->mode))
    548                         /** @todo this may need more tuning after we rewrite the directory handling. */
    549                         kstat->blksize = _16K;
    550         }
    551         return rc;
     516        if (dentry->d_inode) {
     517            struct sf_inode_info *pInodeInfo = GET_INODE_INFO(dentry->d_inode);
     518            if (pInodeInfo) {
     519                sf_ftime_from_timespec(&kstat->btime, &pInodeInfo->BirthTime);
     520                kstat->result_mask |= STATX_BTIME;
     521            }
     522        }
     523#endif
     524
     525        /*
     526        * FsPerf shows the following numbers for sequential file access against
     527        * a tmpfs folder on an AMD 1950X host running debian buster/sid:
     528        *
     529        * block size = r128600    ----- r128755 -----
     530        *               reads      reads     writes
     531        *    4096 KB = 2254 MB/s  4953 MB/s 3668 MB/s
     532        *    2048 KB = 2368 MB/s  4908 MB/s 3541 MB/s
     533        *    1024 KB = 2208 MB/s  4011 MB/s 3291 MB/s
     534        *     512 KB = 1908 MB/s  3399 MB/s 2721 MB/s
     535        *     256 KB = 1625 MB/s  2679 MB/s 2251 MB/s
     536        *     128 KB = 1413 MB/s  1967 MB/s 1684 MB/s
     537        *      64 KB = 1152 MB/s  1409 MB/s 1265 MB/s
     538        *      32 KB =  726 MB/s   815 MB/s  783 MB/s
     539        *      16 KB =             683 MB/s  475 MB/s
     540        *       8 KB =             294 MB/s  286 MB/s
     541        *       4 KB =  145 MB/s   156 MB/s  149 MB/s
     542        *
     543        */
     544        if (S_ISREG(kstat->mode))
     545            kstat->blksize = _1M;
     546        else if (S_ISDIR(kstat->mode))
     547            /** @todo this may need more tuning after we rewrite the directory handling. */
     548            kstat->blksize = _16K;
     549    }
     550    return rc;
    552551}
    553552
    554553int sf_setattr(struct dentry *dentry, struct iattr *iattr)
    555554{
    556         struct vbsf_super_info *sf_g;
    557         struct sf_inode_info *sf_i;
    558         union SetAttrReqs
    559         {
    560             VBOXSFCREATEREQ         Create;
    561             VBOXSFOBJINFOREQ        Info;
    562             VBOXSFSETFILESIZEREQ    SetSize;
    563             VBOXSFCLOSEREQ          Close;
    564         } *pReq;
    565         size_t cbReq;
    566         SHFLCREATEPARMS *pCreateParms;
    567         SHFLFSOBJINFO *pInfo;
    568         SHFLHANDLE hHostFile;
    569         int vrc;
    570         int err = 0;
    571 
    572         TRACE();
    573 
    574         sf_g = VBSF_GET_SUPER_INFO(dentry->d_inode->i_sb);
    575         sf_i = GET_INODE_INFO(dentry->d_inode);
    576         cbReq = RT_MAX(sizeof(pReq->Info), sizeof(pReq->Create) + SHFLSTRING_HEADER_SIZE + sf_i->path->u16Size);
    577         pReq = (union SetAttrReqs *)VbglR0PhysHeapAlloc(cbReq);
    578         if (!pReq) {
    579                 LogFunc(("Failed to allocate %#x byte request buffer!\n", cbReq));
    580                 return -ENOMEM;
    581         }
    582         pCreateParms = &pReq->Create.CreateParms;
    583         pInfo = &pReq->Info.ObjInfo;
    584 
    585         RT_ZERO(*pCreateParms);
    586         pCreateParms->Handle = SHFL_HANDLE_NIL;
    587         pCreateParms->CreateFlags = SHFL_CF_ACT_OPEN_IF_EXISTS
    588                                   | SHFL_CF_ACT_FAIL_IF_NEW
    589                                   | SHFL_CF_ACCESS_ATTR_WRITE;
    590 
    591         /* this is at least required for Posix hosts */
    592         if (iattr->ia_valid & ATTR_SIZE)
    593                 pCreateParms->CreateFlags |= SHFL_CF_ACCESS_WRITE;
    594 
    595         memcpy(&pReq->Create.StrPath, sf_i->path, SHFLSTRING_HEADER_SIZE + sf_i->path->u16Size);
    596         vrc = VbglR0SfHostReqCreate(sf_g->map.root, &pReq->Create);
    597         if (RT_SUCCESS(vrc)) {
    598                 hHostFile = pCreateParms->Handle;
    599         } else {
    600                 err = -RTErrConvertToErrno(vrc);
    601                 LogFunc(("VbglR0SfCreate(%s) failed vrc=%Rrc err=%d\n", sf_i->path->String.ach, vrc, err));
    602                 goto fail2;
    603         }
    604         if (pCreateParms->Result != SHFL_FILE_EXISTS) {
    605                 LogFunc(("file %s does not exist\n", sf_i->path->String.utf8));
    606                 err = -ENOENT;
    607                 goto fail1;
    608         }
    609 
    610         /* Setting the file size and setting the other attributes has to be
    611         * handled separately, see implementation of vbsfSetFSInfo() in
    612         * vbsf.cpp */
    613         if (iattr->ia_valid & (ATTR_MODE | ATTR_ATIME | ATTR_MTIME)) {
     555    struct vbsf_super_info *sf_g;
     556    struct sf_inode_info *sf_i;
     557    union SetAttrReqs
     558    {
     559        VBOXSFCREATEREQ         Create;
     560        VBOXSFOBJINFOREQ        Info;
     561        VBOXSFSETFILESIZEREQ    SetSize;
     562        VBOXSFCLOSEREQ          Close;
     563    } *pReq;
     564    size_t cbReq;
     565    SHFLCREATEPARMS *pCreateParms;
     566    SHFLFSOBJINFO *pInfo;
     567    SHFLHANDLE hHostFile;
     568    int vrc;
     569    int err = 0;
     570
     571    TRACE();
     572
     573    sf_g = VBSF_GET_SUPER_INFO(dentry->d_inode->i_sb);
     574    sf_i = GET_INODE_INFO(dentry->d_inode);
     575    cbReq = RT_MAX(sizeof(pReq->Info), sizeof(pReq->Create) + SHFLSTRING_HEADER_SIZE + sf_i->path->u16Size);
     576    pReq = (union SetAttrReqs *)VbglR0PhysHeapAlloc(cbReq);
     577    if (!pReq) {
     578        LogFunc(("Failed to allocate %#x byte request buffer!\n", cbReq));
     579        return -ENOMEM;
     580    }
     581    pCreateParms = &pReq->Create.CreateParms;
     582    pInfo = &pReq->Info.ObjInfo;
     583
     584    RT_ZERO(*pCreateParms);
     585    pCreateParms->Handle = SHFL_HANDLE_NIL;
     586    pCreateParms->CreateFlags = SHFL_CF_ACT_OPEN_IF_EXISTS
     587                              | SHFL_CF_ACT_FAIL_IF_NEW
     588                              | SHFL_CF_ACCESS_ATTR_WRITE;
     589
     590    /* this is at least required for Posix hosts */
     591    if (iattr->ia_valid & ATTR_SIZE)
     592        pCreateParms->CreateFlags |= SHFL_CF_ACCESS_WRITE;
     593
     594    memcpy(&pReq->Create.StrPath, sf_i->path, SHFLSTRING_HEADER_SIZE + sf_i->path->u16Size);
     595    vrc = VbglR0SfHostReqCreate(sf_g->map.root, &pReq->Create);
     596    if (RT_SUCCESS(vrc)) {
     597        hHostFile = pCreateParms->Handle;
     598    } else {
     599        err = -RTErrConvertToErrno(vrc);
     600        LogFunc(("VbglR0SfCreate(%s) failed vrc=%Rrc err=%d\n", sf_i->path->String.ach, vrc, err));
     601        goto fail2;
     602    }
     603    if (pCreateParms->Result != SHFL_FILE_EXISTS) {
     604        LogFunc(("file %s does not exist\n", sf_i->path->String.utf8));
     605        err = -ENOENT;
     606        goto fail1;
     607    }
     608
     609    /* Setting the file size and setting the other attributes has to be
     610    * handled separately, see implementation of vbsfSetFSInfo() in
     611    * vbsf.cpp */
     612    if (iattr->ia_valid & (ATTR_MODE | ATTR_ATIME | ATTR_MTIME)) {
    614613# define mode_set(r) ((iattr->ia_mode & (S_##r)) ? RTFS_UNIX_##r : 0)
    615614
    616                 RT_ZERO(*pInfo);
    617                 if (iattr->ia_valid & ATTR_MODE) {
    618                         pInfo->Attr.fMode = mode_set(IRUSR);
    619                         pInfo->Attr.fMode |= mode_set(IWUSR);
    620                         pInfo->Attr.fMode |= mode_set(IXUSR);
    621                         pInfo->Attr.fMode |= mode_set(IRGRP);
    622                         pInfo->Attr.fMode |= mode_set(IWGRP);
    623                         pInfo->Attr.fMode |= mode_set(IXGRP);
    624                         pInfo->Attr.fMode |= mode_set(IROTH);
    625                         pInfo->Attr.fMode |= mode_set(IWOTH);
    626                         pInfo->Attr.fMode |= mode_set(IXOTH);
    627 
    628                         if (iattr->ia_mode & S_IFDIR)
    629                                 pInfo->Attr.fMode |= RTFS_TYPE_DIRECTORY;
    630                         else
    631                                 pInfo->Attr.fMode |= RTFS_TYPE_FILE;
    632                 }
    633 
    634                 if (iattr->ia_valid & ATTR_ATIME)
    635                         sf_timespec_from_ftime(&pInfo->AccessTime,
    636                                                &iattr->ia_atime);
    637                 if (iattr->ia_valid & ATTR_MTIME)
    638                         sf_timespec_from_ftime(&pInfo->ModificationTime,
    639                                                &iattr->ia_mtime);
    640                 /* ignore ctime (inode change time) as it can't be set from userland anyway */
    641 
    642                 vrc = VbglR0SfHostReqSetObjInfo(sf_g->map.root, &pReq->Info, hHostFile);
    643                 if (RT_FAILURE(vrc)) {
    644                         err = -RTErrConvertToErrno(vrc);
    645                         LogFunc(("VbglR0SfHostReqSetObjInfo(%s) failed vrc=%Rrc err=%d\n", sf_i->path->String.ach, vrc, err));
    646                         goto fail1;
    647                 }
    648         }
    649 
    650         if (iattr->ia_valid & ATTR_SIZE) {
    651                 vrc = VbglR0SfHostReqSetFileSize(sf_g->map.root, &pReq->SetSize, hHostFile, iattr->ia_size);
    652                 /** @todo Implement fallback if host is < 6.0? */
    653                 if (RT_FAILURE(vrc)) {
    654                         err = -RTErrConvertToErrno(vrc);
    655                         LogFunc(("VbglR0SfHostReqSetFileSize(%s, %#llx) failed vrc=%Rrc err=%d\n",
    656                                  sf_i->path->String.ach, (unsigned long long)iattr->ia_size, vrc, err));
    657                         goto fail1;
    658                 }
    659         }
    660 
    661         vrc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, hHostFile);
    662         if (RT_FAILURE(vrc))
    663                 LogFunc(("VbglR0SfHostReqClose(%s [%#llx]) failed vrc=%Rrc\n", sf_i->path->String.utf8, hHostFile, vrc));
    664         VbglR0PhysHeapFree(pReq);
    665 
    666         /** @todo r=bird: I guess we're calling revalidate here to update the inode
    667          * info.  However, due to the TTL optimization this is not guarenteed to happen.
    668          *
    669          * Also, we already have accurate stat information on the file, either from the
    670          * SHFL_FN_CREATE call or from SHFL_FN_INFORMATION, so there is no need to do a
    671          * slow stat()-like operation to retrieve the information again.
    672          *
    673          * What's more, given that the SHFL_FN_CREATE call succeeded, we know that the
    674          * dentry and all its parent entries are valid and could touch their timestamps
    675          * extending their TTL (CIFS does that). */
    676         return sf_inode_revalidate_worker(dentry, true /*fForced*/);
     615        RT_ZERO(*pInfo);
     616        if (iattr->ia_valid & ATTR_MODE) {
     617/** @todo we've got code for this elsewhere...   */
     618            pInfo->Attr.fMode = mode_set(IRUSR);
     619            pInfo->Attr.fMode |= mode_set(IWUSR);
     620            pInfo->Attr.fMode |= mode_set(IXUSR);
     621            pInfo->Attr.fMode |= mode_set(IRGRP);
     622            pInfo->Attr.fMode |= mode_set(IWGRP);
     623            pInfo->Attr.fMode |= mode_set(IXGRP);
     624            pInfo->Attr.fMode |= mode_set(IROTH);
     625            pInfo->Attr.fMode |= mode_set(IWOTH);
     626            pInfo->Attr.fMode |= mode_set(IXOTH);
     627
     628            if (iattr->ia_mode & S_IFDIR)
     629                pInfo->Attr.fMode |= RTFS_TYPE_DIRECTORY;
     630            else
     631                pInfo->Attr.fMode |= RTFS_TYPE_FILE;
     632        }
     633
     634        if (iattr->ia_valid & ATTR_ATIME)
     635            sf_timespec_from_ftime(&pInfo->AccessTime, &iattr->ia_atime);
     636        if (iattr->ia_valid & ATTR_MTIME)
     637            sf_timespec_from_ftime(&pInfo->ModificationTime, &iattr->ia_mtime);
     638        /* ignore ctime (inode change time) as it can't be set from userland anyway */
     639
     640        vrc = VbglR0SfHostReqSetObjInfo(sf_g->map.root, &pReq->Info, hHostFile);
     641        if (RT_FAILURE(vrc)) {
     642            err = -RTErrConvertToErrno(vrc);
     643            LogFunc(("VbglR0SfHostReqSetObjInfo(%s) failed vrc=%Rrc err=%d\n", sf_i->path->String.ach, vrc, err));
     644            goto fail1;
     645        }
     646    }
     647
     648    if (iattr->ia_valid & ATTR_SIZE) {
     649        vrc = VbglR0SfHostReqSetFileSize(sf_g->map.root, &pReq->SetSize, hHostFile, iattr->ia_size);
     650        /** @todo Implement fallback if host is < 6.0? */
     651        if (RT_FAILURE(vrc)) {
     652            err = -RTErrConvertToErrno(vrc);
     653            LogFunc(("VbglR0SfHostReqSetFileSize(%s, %#llx) failed vrc=%Rrc err=%d\n",
     654                 sf_i->path->String.ach, (unsigned long long)iattr->ia_size, vrc, err));
     655            goto fail1;
     656        }
     657    }
     658
     659    vrc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, hHostFile);
     660    if (RT_FAILURE(vrc))
     661        LogFunc(("VbglR0SfHostReqClose(%s [%#llx]) failed vrc=%Rrc\n", sf_i->path->String.utf8, hHostFile, vrc));
     662    VbglR0PhysHeapFree(pReq);
     663
     664    /** @todo r=bird: I guess we're calling revalidate here to update the inode
     665     * info.  However, due to the TTL optimization this is not guarenteed to happen.
     666     *
     667     * Also, we already have accurate stat information on the file, either from the
     668     * SHFL_FN_CREATE call or from SHFL_FN_INFORMATION, so there is no need to do a
     669     * slow stat()-like operation to retrieve the information again.
     670     *
     671     * What's more, given that the SHFL_FN_CREATE call succeeded, we know that the
     672     * dentry and all its parent entries are valid and could touch their timestamps
     673     * extending their TTL (CIFS does that). */
     674    return sf_inode_revalidate_worker(dentry, true /*fForced*/);
    677675
    678676 fail1:
    679         vrc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, hHostFile);
    680         if (RT_FAILURE(vrc))
    681                 LogFunc(("VbglR0SfHostReqClose(%s [%#llx]) failed vrc=%Rrc; err=%d\n", sf_i->path->String.utf8, hHostFile, vrc, err));
     677    vrc = VbglR0SfHostReqClose(sf_g->map.root, &pReq->Close, hHostFile);
     678    if (RT_FAILURE(vrc))
     679        LogFunc(("VbglR0SfHostReqClose(%s [%#llx]) failed vrc=%Rrc; err=%d\n", sf_i->path->String.utf8, hHostFile, vrc, err));
    682680
    683681 fail2:
    684         VbglR0PhysHeapFree(pReq);
    685         return err;
     682    VbglR0PhysHeapFree(pReq);
     683    return err;
    686684}
    687685
     
    689687
    690688static int sf_make_path(const char *caller, struct sf_inode_info *sf_i,
    691                         const char *d_name, size_t d_len, SHFLSTRING ** result)
    692 {
    693         size_t path_len, shflstring_len;
    694         SHFLSTRING *tmp;
    695         uint16_t p_len;
    696         uint8_t *p_name;
    697         int fRoot = 0;
    698 
    699         TRACE();
    700         p_len = sf_i->path->u16Length;
    701         p_name = sf_i->path->String.utf8;
    702 
    703         if (p_len == 1 && *p_name == '/') {
    704                 path_len = d_len + 1;
    705                 fRoot = 1;
    706         } else {
    707                 /* lengths of constituents plus terminating zero plus slash  */
    708                 path_len = p_len + d_len + 2;
    709                 if (path_len > 0xffff) {
    710                         LogFunc(("path too long.  caller=%s, path_len=%zu\n",
    711                                 caller, path_len));
    712                         return -ENAMETOOLONG;
    713                 }
    714         }
    715 
    716         shflstring_len = offsetof(SHFLSTRING, String.utf8) + path_len;
    717         tmp = kmalloc(shflstring_len, GFP_KERNEL);
    718         if (!tmp) {
    719                 LogRelFunc(("kmalloc failed, caller=%s\n", caller));
    720                 return -ENOMEM;
    721         }
    722         tmp->u16Length = path_len - 1;
    723         tmp->u16Size = path_len;
    724 
    725         if (fRoot)
    726                 memcpy(&tmp->String.utf8[0], d_name, d_len + 1);
    727         else {
    728                 memcpy(&tmp->String.utf8[0], p_name, p_len);
    729                 tmp->String.utf8[p_len] = '/';
    730                 memcpy(&tmp->String.utf8[p_len + 1], d_name, d_len);
    731                 tmp->String.utf8[p_len + 1 + d_len] = '\0';
    732         }
    733 
    734         *result = tmp;
    735         return 0;
     689                        const char *d_name, size_t d_len, SHFLSTRING **result)
     690{
     691    size_t path_len, shflstring_len;
     692    SHFLSTRING *tmp;
     693    uint16_t p_len;
     694    uint8_t *p_name;
     695    int fRoot = 0;
     696
     697    TRACE();
     698    p_len = sf_i->path->u16Length;
     699    p_name = sf_i->path->String.utf8;
     700
     701    if (p_len == 1 && *p_name == '/') {
     702        path_len = d_len + 1;
     703        fRoot = 1;
     704    } else {
     705        /* lengths of constituents plus terminating zero plus slash  */
     706        path_len = p_len + d_len + 2;
     707        if (path_len > 0xffff) {
     708            LogFunc(("path too long.  caller=%s, path_len=%zu\n",
     709                caller, path_len));
     710            return -ENAMETOOLONG;
     711        }
     712    }
     713
     714    shflstring_len = offsetof(SHFLSTRING, String.utf8) + path_len;
     715    tmp = kmalloc(shflstring_len, GFP_KERNEL);
     716    if (!tmp) {
     717        LogRelFunc(("kmalloc failed, caller=%s\n", caller));
     718        return -ENOMEM;
     719    }
     720    tmp->u16Length = path_len - 1;
     721    tmp->u16Size = path_len;
     722
     723    if (fRoot)
     724        memcpy(&tmp->String.utf8[0], d_name, d_len + 1);
     725    else {
     726        memcpy(&tmp->String.utf8[0], p_name, p_len);
     727        tmp->String.utf8[p_len] = '/';
     728        memcpy(&tmp->String.utf8[p_len + 1], d_name, d_len);
     729        tmp->String.utf8[p_len + 1 + d_len] = '\0';
     730    }
     731
     732    *result = tmp;
     733    return 0;
    736734}
    737735
     
    742740 */
    743741int sf_path_from_dentry(const char *caller, struct vbsf_super_info *sf_g,
    744                         struct sf_inode_info *sf_i, struct dentry *dentry,
    745                         SHFLSTRING ** result)
    746 {
    747         int err;
    748         const char *d_name;
    749         size_t d_len;
    750         const char *name;
    751         size_t len = 0;
    752 
    753         TRACE();
    754         d_name = dentry->d_name.name;
    755         d_len = dentry->d_name.len;
    756 
    757         if (sf_g->nls) {
    758                 size_t in_len, i, out_bound_len;
    759                 const char *in;
    760                 char *out;
    761 
    762                 in = d_name;
    763                 in_len = d_len;
    764 
    765                 out_bound_len = PATH_MAX;
    766                 out = kmalloc(out_bound_len, GFP_KERNEL);
    767                 name = out;
    768 
    769                 for (i = 0; i < d_len; ++i) {
    770                         /* We renamed the linux kernel wchar_t type to linux_wchar_t in
    771                            the-linux-kernel.h, as it conflicts with the C++ type of that name. */
    772                         linux_wchar_t uni;
    773                         int nb;
    774 
    775                         nb = sf_g->nls->char2uni(in, in_len, &uni);
    776                         if (nb < 0) {
    777                                 LogFunc(("nls->char2uni failed %x %d\n",
    778                                         *in, in_len));
    779                                 err = -EINVAL;
    780                                 goto fail1;
    781                         }
    782                         in_len -= nb;
    783                         in += nb;
     742                        struct sf_inode_info *sf_i, struct dentry *dentry,
     743                        SHFLSTRING **result)
     744{
     745    int err;
     746    const char *d_name;
     747    size_t d_len;
     748    const char *name;
     749    size_t len = 0;
     750
     751    TRACE();
     752    d_name = dentry->d_name.name;
     753    d_len = dentry->d_name.len;
     754
     755    if (sf_g->nls) {
     756        size_t in_len, i, out_bound_len;
     757        const char *in;
     758        char *out;
     759
     760        in = d_name;
     761        in_len = d_len;
     762
     763        out_bound_len = PATH_MAX;
     764        out = kmalloc(out_bound_len, GFP_KERNEL);
     765        name = out;
     766
     767        for (i = 0; i < d_len; ++i) {
     768            /* We renamed the linux kernel wchar_t type to linux_wchar_t in
     769               the-linux-kernel.h, as it conflicts with the C++ type of that name. */
     770            linux_wchar_t uni;
     771            int nb;
     772
     773            nb = sf_g->nls->char2uni(in, in_len, &uni);
     774            if (nb < 0) {
     775                LogFunc(("nls->char2uni failed %x %d\n",
     776                    *in, in_len));
     777                err = -EINVAL;
     778                goto fail1;
     779            }
     780            in_len -= nb;
     781            in += nb;
    784782
    785783#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
    786                         nb = utf32_to_utf8(uni, out, out_bound_len);
     784            nb = utf32_to_utf8(uni, out, out_bound_len);
    787785#else
    788                         nb = utf8_wctomb(out, uni, out_bound_len);
    789 #endif
    790                         if (nb < 0) {
    791                                 LogFunc(("nls->uni2char failed %x %d\n",
    792                                         uni, out_bound_len));
    793                                 err = -EINVAL;
    794                                 goto fail1;
    795                         }
    796                         out_bound_len -= nb;
    797                         out += nb;
    798                         len += nb;
    799                 }
    800                 if (len >= PATH_MAX - 1) {
    801                         err = -ENAMETOOLONG;
    802                         goto fail1;
    803                 }
    804 
    805                 LogFunc(("result(%d) = %.*s\n", len, len, name));
    806                 *out = 0;
    807         } else {
    808                 name = d_name;
    809                 len = d_len;
    810         }
    811 
    812         err = sf_make_path(caller, sf_i, name, len, result);
    813         if (name != d_name)
    814                 kfree(name);
    815 
    816         return err;
     786            nb = utf8_wctomb(out, uni, out_bound_len);
     787#endif
     788            if (nb < 0) {
     789                LogFunc(("nls->uni2char failed %x %d\n",
     790                    uni, out_bound_len));
     791                err = -EINVAL;
     792                goto fail1;
     793            }
     794            out_bound_len -= nb;
     795            out += nb;
     796            len += nb;
     797        }
     798        if (len >= PATH_MAX - 1) {
     799            err = -ENAMETOOLONG;
     800            goto fail1;
     801        }
     802
     803        LogFunc(("result(%d) = %.*s\n", len, len, name));
     804        *out = 0;
     805    } else {
     806        name = d_name;
     807        len = d_len;
     808    }
     809
     810    err = sf_make_path(caller, sf_i, name, len, result);
     811    if (name != d_name)
     812        kfree(name);
     813
     814    return err;
    817815
    818816 fail1:
    819         kfree(name);
    820         return err;
     817    kfree(name);
     818    return err;
    821819}
    822820
    823821int sf_nlscpy(struct vbsf_super_info *sf_g,
    824               char *name, size_t name_bound_len,
    825               const unsigned char *utf8_name, size_t utf8_len)
    826 {
    827         if (sf_g->nls) {
    828                 const char *in;
    829                 char *out;
    830                 size_t out_len;
    831                 size_t out_bound_len;
    832                 size_t in_bound_len;
    833 
    834                 in = utf8_name;
    835                 in_bound_len = utf8_len;
    836 
    837                 out = name;
    838                 out_len = 0;
    839                 out_bound_len = name_bound_len;
    840 
    841                 while (in_bound_len) {
    842                         int nb;
     822              char *name, size_t name_bound_len,
     823              const unsigned char *utf8_name, size_t utf8_len)
     824{
     825    if (sf_g->nls) {
     826        const char *in;
     827        char *out;
     828        size_t out_len;
     829        size_t out_bound_len;
     830        size_t in_bound_len;
     831
     832        in = utf8_name;
     833        in_bound_len = utf8_len;
     834
     835        out = name;
     836        out_len = 0;
     837        out_bound_len = name_bound_len;
     838
     839        while (in_bound_len) {
     840            int nb;
    843841#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
    844                         unicode_t uni;
    845 
    846                         nb = utf8_to_utf32(in, in_bound_len, &uni);
     842            unicode_t uni;
     843
     844            nb = utf8_to_utf32(in, in_bound_len, &uni);
    847845#else
    848                         linux_wchar_t uni;
    849 
    850                         nb = utf8_mbtowc(&uni, in, in_bound_len);
    851 #endif
    852                         if (nb < 0) {
    853                                 LogFunc(("utf8_mbtowc failed(%s) %x:%d\n",
    854                                         (const char *)utf8_name, *in,
    855                                         in_bound_len));
    856                                 return -EINVAL;
    857                         }
    858                         in += nb;
    859                         in_bound_len -= nb;
    860 
    861                         nb = sf_g->nls->uni2char(uni, out, out_bound_len);
    862                         if (nb < 0) {
    863                                 LogFunc(("nls->uni2char failed(%s) %x:%d\n",
    864                                         utf8_name, uni, out_bound_len));
    865                                 return nb;
    866                         }
    867                         out += nb;
    868                         out_bound_len -= nb;
    869                         out_len += nb;
    870                 }
    871 
    872                 *out = 0;
    873         } else {
    874                 if (utf8_len + 1 > name_bound_len)
    875                         return -ENAMETOOLONG;
    876 
    877                 memcpy(name, utf8_name, utf8_len + 1);
    878         }
    879         return 0;
     846            linux_wchar_t uni;
     847
     848            nb = utf8_mbtowc(&uni, in, in_bound_len);
     849#endif
     850            if (nb < 0) {
     851                LogFunc(("utf8_mbtowc failed(%s) %x:%d\n",
     852                    (const char *)utf8_name, *in,
     853                    in_bound_len));
     854                return -EINVAL;
     855            }
     856            in += nb;
     857            in_bound_len -= nb;
     858
     859            nb = sf_g->nls->uni2char(uni, out, out_bound_len);
     860            if (nb < 0) {
     861                LogFunc(("nls->uni2char failed(%s) %x:%d\n",
     862                    utf8_name, uni, out_bound_len));
     863                return nb;
     864            }
     865            out += nb;
     866            out_bound_len -= nb;
     867            out_len += nb;
     868        }
     869
     870        *out = 0;
     871    } else {
     872        if (utf8_len + 1 > name_bound_len)
     873            return -ENAMETOOLONG;
     874
     875        memcpy(name, utf8_name, utf8_len + 1);
     876    }
     877    return 0;
    880878}
    881879
    882880static struct sf_dir_buf *sf_dir_buf_alloc(void)
    883881{
    884         struct sf_dir_buf *b;
    885 
    886         TRACE();
    887         b = kmalloc(sizeof(*b), GFP_KERNEL);
    888         if (!b) {
    889                 LogRelFunc(("could not alloc directory buffer\n"));
    890                 return NULL;
    891         }
    892         b->buf = kmalloc(DIR_BUFFER_SIZE, GFP_KERNEL);
    893         if (!b->buf) {
    894                 kfree(b);
    895                 LogRelFunc(("could not alloc directory buffer storage\n"));
    896                 return NULL;
    897         }
    898 
    899         INIT_LIST_HEAD(&b->head);
    900         b->cEntries = 0;
    901         b->cbUsed = 0;
    902         b->cbFree = DIR_BUFFER_SIZE;
    903         return b;
     882    struct sf_dir_buf *b;
     883
     884    TRACE();
     885    b = kmalloc(sizeof(*b), GFP_KERNEL);
     886    if (!b) {
     887        LogRelFunc(("could not alloc directory buffer\n"));
     888        return NULL;
     889    }
     890    b->buf = kmalloc(DIR_BUFFER_SIZE, GFP_KERNEL);
     891    if (!b->buf) {
     892        kfree(b);
     893        LogRelFunc(("could not alloc directory buffer storage\n"));
     894        return NULL;
     895    }
     896
     897    INIT_LIST_HEAD(&b->head);
     898    b->cEntries = 0;
     899    b->cbUsed = 0;
     900    b->cbFree = DIR_BUFFER_SIZE;
     901    return b;
    904902}
    905903
    906904static void sf_dir_buf_free(struct sf_dir_buf *b)
    907905{
    908         BUG_ON(!b || !b->buf);
    909 
    910         TRACE();
    911         list_del(&b->head);
    912         kfree(b->buf);
    913         kfree(b);
     906    BUG_ON(!b || !b->buf);
     907
     908    TRACE();
     909    list_del(&b->head);
     910    kfree(b->buf);
     911    kfree(b);
    914912}
    915913
     
    919917void sf_dir_info_free(struct sf_dir_info *p)
    920918{
    921         struct list_head *list, *pos, *tmp;
    922 
    923         TRACE();
    924         list = &p->info_list;
    925         list_for_each_safe(pos, tmp, list) {
    926                 struct sf_dir_buf *b;
    927 
    928                 b = list_entry(pos, struct sf_dir_buf, head);
    929                 sf_dir_buf_free(b);
    930         }
    931         kfree(p);
     919    struct list_head *list, *pos, *tmp;
     920
     921    TRACE();
     922    list = &p->info_list;
     923    list_for_each_safe(pos, tmp, list) {
     924        struct sf_dir_buf *b;
     925
     926        b = list_entry(pos, struct sf_dir_buf, head);
     927        sf_dir_buf_free(b);
     928    }
     929    kfree(p);
    932930}
    933931
     
    937935void sf_dir_info_empty(struct sf_dir_info *p)
    938936{
    939         struct list_head *list, *pos, *tmp;
    940         TRACE();
    941         list = &p->info_list;
    942         list_for_each_safe(pos, tmp, list) {
    943                 struct sf_dir_buf *b;
    944                 b = list_entry(pos, struct sf_dir_buf, head);
    945                 b->cEntries = 0;
    946                 b->cbUsed = 0;
    947                 b->cbFree = DIR_BUFFER_SIZE;
    948         }
     937    struct list_head *list, *pos, *tmp;
     938    TRACE();
     939    list = &p->info_list;
     940    list_for_each_safe(pos, tmp, list) {
     941        struct sf_dir_buf *b;
     942        b = list_entry(pos, struct sf_dir_buf, head);
     943        b->cEntries = 0;
     944        b->cbUsed = 0;
     945        b->cbFree = DIR_BUFFER_SIZE;
     946    }
    949947}
    950948
     
    954952struct sf_dir_info *sf_dir_info_alloc(void)
    955953{
    956         struct sf_dir_info *p;
    957 
    958         TRACE();
    959         p = kmalloc(sizeof(*p), GFP_KERNEL);
    960         if (!p) {
    961                 LogRelFunc(("could not alloc directory info\n"));
    962                 return NULL;
    963         }
    964 
    965         INIT_LIST_HEAD(&p->info_list);
    966         return p;
     954    struct sf_dir_info *p;
     955
     956    TRACE();
     957    p = kmalloc(sizeof(*p), GFP_KERNEL);
     958    if (!p) {
     959        LogRelFunc(("could not alloc directory info\n"));
     960        return NULL;
     961    }
     962
     963    INIT_LIST_HEAD(&p->info_list);
     964    return p;
    967965}
    968966
     
    972970static struct sf_dir_buf *sf_get_empty_dir_buf(struct sf_dir_info *sf_d)
    973971{
    974         struct list_head *list, *pos;
    975 
    976         list = &sf_d->info_list;
    977         list_for_each(pos, list) {
    978                 struct sf_dir_buf *b;
    979 
    980                 b = list_entry(pos, struct sf_dir_buf, head);
    981                 if (!b)
    982                         return NULL;
    983                 else {
    984                         if (b->cbUsed == 0)
    985                                 return b;
    986                 }
    987         }
    988 
    989         return NULL;
     972    struct list_head *list, *pos;
     973
     974    list = &sf_d->info_list;
     975    list_for_each(pos, list) {
     976        struct sf_dir_buf *b;
     977
     978        b = list_entry(pos, struct sf_dir_buf, head);
     979        if (!b)
     980            return NULL;
     981        else {
     982            if (b->cbUsed == 0)
     983                return b;
     984        }
     985    }
     986
     987    return NULL;
    990988}
    991989
     
    993991 *        cannot be healthy for like big directory and such... */
    994992int sf_dir_read_all(struct vbsf_super_info *sf_g, struct sf_inode_info *sf_i,
    995                     struct sf_dir_info *sf_d, SHFLHANDLE handle)
    996 {
    997         int err;
    998         SHFLSTRING *mask;
    999         VBOXSFLISTDIRREQ *pReq = NULL;
    1000 
    1001         TRACE();
    1002         err = sf_make_path(__func__, sf_i, "*", 1, &mask);
    1003         if (err)
    1004                 goto fail0;
    1005         pReq = (VBOXSFLISTDIRREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
    1006         if (!pReq)
    1007                 goto fail1;
    1008 
    1009         for (;;) {
    1010                 int rc;
    1011                 struct sf_dir_buf *b;
    1012 
    1013                 b = sf_get_empty_dir_buf(sf_d);
    1014                 if (!b) {
    1015                         b = sf_dir_buf_alloc();
    1016                         if (!b) {
    1017                                 err = -ENOMEM;
    1018                                 LogRelFunc(("could not alloc directory buffer\n"));
    1019                                 goto fail2;
    1020                         }
    1021                         list_add(&b->head, &sf_d->info_list);
    1022                 }
    1023 
    1024                 rc = VbglR0SfHostReqListDirContig2x(sf_g->map.root, pReq, handle, mask, virt_to_phys(mask),
    1025                                                     0 /*fFlags*/, b->buf, virt_to_phys(b->buf), b->cbFree);
    1026                 if (RT_SUCCESS(rc)) {
    1027                         b->cEntries += pReq->Parms.c32Entries.u.value32;
    1028                         b->cbFree   -= pReq->Parms.cb32Buffer.u.value32;
    1029                         b->cbUsed   += pReq->Parms.cb32Buffer.u.value32;
    1030                 } else if (rc == VERR_NO_MORE_FILES) {
    1031                         break;
    1032                 } else {
    1033                         err = -RTErrConvertToErrno(rc);
    1034                         LogFunc(("VbglR0SfHostReqListDirContig2x failed rc=%Rrc err=%d\n", rc, err));
    1035                         goto fail2;
    1036                 }
    1037         }
    1038         err = 0;
     993                    struct sf_dir_info *sf_d, SHFLHANDLE handle)
     994{
     995    int err;
     996    SHFLSTRING *mask;
     997    VBOXSFLISTDIRREQ *pReq = NULL;
     998
     999    TRACE();
     1000    err = sf_make_path(__func__, sf_i, "*", 1, &mask);
     1001    if (err)
     1002        goto fail0;
     1003    pReq = (VBOXSFLISTDIRREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
     1004    if (!pReq)
     1005        goto fail1;
     1006
     1007    for (;;) {
     1008        int rc;
     1009        struct sf_dir_buf *b;
     1010
     1011        b = sf_get_empty_dir_buf(sf_d);
     1012        if (!b) {
     1013            b = sf_dir_buf_alloc();
     1014            if (!b) {
     1015                err = -ENOMEM;
     1016                LogRelFunc(("could not alloc directory buffer\n"));
     1017                goto fail2;
     1018            }
     1019            list_add(&b->head, &sf_d->info_list);
     1020        }
     1021
     1022        rc = VbglR0SfHostReqListDirContig2x(sf_g->map.root, pReq, handle, mask, virt_to_phys(mask),
     1023                            0 /*fFlags*/, b->buf, virt_to_phys(b->buf), b->cbFree);
     1024        if (RT_SUCCESS(rc)) {
     1025            b->cEntries += pReq->Parms.c32Entries.u.value32;
     1026            b->cbFree   -= pReq->Parms.cb32Buffer.u.value32;
     1027            b->cbUsed   += pReq->Parms.cb32Buffer.u.value32;
     1028        } else if (rc == VERR_NO_MORE_FILES) {
     1029            break;
     1030        } else {
     1031            err = -RTErrConvertToErrno(rc);
     1032            LogFunc(("VbglR0SfHostReqListDirContig2x failed rc=%Rrc err=%d\n", rc, err));
     1033            goto fail2;
     1034        }
     1035    }
     1036    err = 0;
    10391037
    10401038 fail2:
    1041         VbglR0PhysHeapFree(pReq);
     1039    VbglR0PhysHeapFree(pReq);
    10421040 fail1:
    1043         kfree(mask);
     1041    kfree(mask);
    10441042
    10451043 fail0:
    1046         return err;
     1044    return err;
    10471045}
    10481046
     
    10631061{
    10641062#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
    1065         int const flags = nd ? nd->flags : 0;
    1066 #endif
    1067 
    1068         int rc;
    1069 
    1070         Assert(dentry);
    1071         SFLOGFLOW(("sf_dentry_revalidate: %p %#x %s\n", dentry, flags, dentry->d_inode ? GET_INODE_INFO(dentry->d_inode)->path->String.ach : "<negative>"));
    1072 
    1073         /*
    1074         * See Documentation/filesystems/vfs.txt why we skip LOOKUP_RCU.
    1075         *
    1076         * Also recommended: https://lwn.net/Articles/649115/
    1077          *                   https://lwn.net/Articles/649729/
    1078          *                   https://lwn.net/Articles/650786/
    1079         *
    1080         */
     1063    int const flags = nd ? nd->flags : 0;
     1064#endif
     1065
     1066    int rc;
     1067
     1068    Assert(dentry);
     1069    SFLOGFLOW(("sf_dentry_revalidate: %p %#x %s\n", dentry, flags, dentry->d_inode ? GET_INODE_INFO(dentry->d_inode)->path->String.ach : "<negative>"));
     1070
     1071    /*
     1072    * See Documentation/filesystems/vfs.txt why we skip LOOKUP_RCU.
     1073    *
     1074    * Also recommended: https://lwn.net/Articles/649115/
     1075     *                   https://lwn.net/Articles/649729/
     1076     *                   https://lwn.net/Articles/650786/
     1077    *
     1078    */
    10811079#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
    1082         if (flags & LOOKUP_RCU) {
    1083                 rc = -ECHILD;
    1084                 SFLOGFLOW(("sf_dentry_revalidate: RCU -> -ECHILD\n"));
    1085         } else
    1086 #endif
    1087         {
    1088                 /*
    1089                 * Do we have an inode or not?  If not it's probably a negative cache
    1090                 * entry, otherwise most likely a positive one.
    1091                 */
    1092                 struct inode *pInode = dentry->d_inode;
    1093                 if (pInode) {
    1094                         /*
    1095                         * Positive entry.
    1096                         *
    1097                         * Note! We're more aggressive here than other remote file systems,
    1098                         *       current (4.19) CIFS will for instance revalidate the inode
    1099                         *       and ignore the dentry timestamp for positive entries.
    1100                         */
    1101                         //struct sf_inode_info *sf_i = GET_INODE_INFO(pInode);
    1102                         unsigned long const     cJiffiesAge = sf_dentry_get_update_jiffies(dentry) - jiffies;
    1103                         struct vbsf_super_info *sf_g        = VBSF_GET_SUPER_INFO(dentry->d_sb);
    1104                         if (cJiffiesAge < sf_g->ttl) {
    1105                                 SFLOGFLOW(("sf_dentry_revalidate: age: %lu vs. TTL %lu -> 1\n", cJiffiesAge, sf_g->ttl));
    1106                                 rc = 1;
    1107                         } else if (!sf_inode_revalidate_worker(dentry, true /*fForced*/)) {
    1108                                 sf_dentry_set_update_jiffies(dentry, jiffies); /** @todo get jiffies from inode. */
    1109                                 SFLOGFLOW(("sf_dentry_revalidate: age: %lu vs. TTL %lu -> reval -> 1\n", cJiffiesAge, sf_g->ttl));
    1110                                 rc = 1;
    1111                         } else {
    1112                                 SFLOGFLOW(("sf_dentry_revalidate: age: %lu vs. TTL %lu -> reval -> 0\n", cJiffiesAge, sf_g->ttl));
    1113                                 rc = 0;
    1114                         }
    1115                 } else {
    1116                         /*
    1117                         * Negative entry.
    1118                         *
    1119                         * Invalidate dentries for open and renames here as we'll revalidate
    1120                         * these when taking the actual action (also good for case preservation
    1121                         * if we do case-insensitive mounts against windows + mac hosts at some
    1122                         * later point).
    1123                         */
     1080    if (flags & LOOKUP_RCU) {
     1081        rc = -ECHILD;
     1082        SFLOGFLOW(("sf_dentry_revalidate: RCU -> -ECHILD\n"));
     1083    } else
     1084#endif
     1085    {
     1086        /*
     1087        * Do we have an inode or not?  If not it's probably a negative cache
     1088        * entry, otherwise most likely a positive one.
     1089        */
     1090        struct inode *pInode = dentry->d_inode;
     1091        if (pInode) {
     1092            /*
     1093            * Positive entry.
     1094            *
     1095            * Note! We're more aggressive here than other remote file systems,
     1096            *       current (4.19) CIFS will for instance revalidate the inode
     1097            *       and ignore the dentry timestamp for positive entries.
     1098            */
     1099            //struct sf_inode_info *sf_i = GET_INODE_INFO(pInode);
     1100            unsigned long const     cJiffiesAge = sf_dentry_get_update_jiffies(dentry) - jiffies;
     1101            struct vbsf_super_info *sf_g        = VBSF_GET_SUPER_INFO(dentry->d_sb);
     1102            if (cJiffiesAge < sf_g->ttl) {
     1103                SFLOGFLOW(("sf_dentry_revalidate: age: %lu vs. TTL %lu -> 1\n", cJiffiesAge, sf_g->ttl));
     1104                rc = 1;
     1105            } else if (!sf_inode_revalidate_worker(dentry, true /*fForced*/)) {
     1106                sf_dentry_set_update_jiffies(dentry, jiffies); /** @todo get jiffies from inode. */
     1107                SFLOGFLOW(("sf_dentry_revalidate: age: %lu vs. TTL %lu -> reval -> 1\n", cJiffiesAge, sf_g->ttl));
     1108                rc = 1;
     1109            } else {
     1110                SFLOGFLOW(("sf_dentry_revalidate: age: %lu vs. TTL %lu -> reval -> 0\n", cJiffiesAge, sf_g->ttl));
     1111                rc = 0;
     1112            }
     1113        } else {
     1114            /*
     1115            * Negative entry.
     1116            *
     1117            * Invalidate dentries for open and renames here as we'll revalidate
     1118            * these when taking the actual action (also good for case preservation
     1119            * if we do case-insensitive mounts against windows + mac hosts at some
     1120            * later point).
     1121            */
    11241122#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
    1125                         if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
     1123            if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
    11261124#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 75)
    1127                         if (flags & LOOKUP_CREATE)
     1125            if (flags & LOOKUP_CREATE)
    11281126#else
    1129                         if (0)
    1130 #endif
    1131                         {
    1132                                 SFLOGFLOW(("sf_dentry_revalidate: negative: create or rename target -> 0\n"));
    1133                                 rc = 0;
    1134                         } else {
    1135                                 /* Can we skip revalidation based on TTL? */
    1136                                 unsigned long const     cJiffiesAge = sf_dentry_get_update_jiffies(dentry) - jiffies;
    1137                                 struct vbsf_super_info *sf_g        = VBSF_GET_SUPER_INFO(dentry->d_sb);
    1138                                 if (cJiffiesAge < sf_g->ttl) {
    1139                                         SFLOGFLOW(("sf_dentry_revalidate: negative: age: %lu vs. TTL %lu -> 1\n", cJiffiesAge, sf_g->ttl));
    1140                                         rc = 1;
    1141                                 } else {
    1142                                         /* We could revalidate it here, but we could instead just
    1143                                            have the caller kick it out. */
    1144                                         /** @todo stat the direntry and see if it exists now. */
    1145                                         SFLOGFLOW(("sf_dentry_revalidate: negative: age: %lu vs. TTL %lu -> 0\n", cJiffiesAge, sf_g->ttl));
    1146                                         rc = 0;
    1147                                 }
    1148                         }
    1149                 }
    1150         }
    1151         return rc;
     1127            if (0)
     1128#endif
     1129            {
     1130                SFLOGFLOW(("sf_dentry_revalidate: negative: create or rename target -> 0\n"));
     1131                rc = 0;
     1132            } else {
     1133                /* Can we skip revalidation based on TTL? */
     1134                unsigned long const     cJiffiesAge = sf_dentry_get_update_jiffies(dentry) - jiffies;
     1135                struct vbsf_super_info *sf_g        = VBSF_GET_SUPER_INFO(dentry->d_sb);
     1136                if (cJiffiesAge < sf_g->ttl) {
     1137                    SFLOGFLOW(("sf_dentry_revalidate: negative: age: %lu vs. TTL %lu -> 1\n", cJiffiesAge, sf_g->ttl));
     1138                    rc = 1;
     1139                } else {
     1140                    /* We could revalidate it here, but we could instead just
     1141                       have the caller kick it out. */
     1142                    /** @todo stat the direntry and see if it exists now. */
     1143                    SFLOGFLOW(("sf_dentry_revalidate: negative: age: %lu vs. TTL %lu -> 0\n", cJiffiesAge, sf_g->ttl));
     1144                    rc = 0;
     1145                }
     1146            }
     1147        }
     1148    }
     1149    return rc;
    11521150}
    11531151
     
    11611159# endif
    11621160{
    1163         SFLOGFLOW(("sf_dentry_delete: %p\n", pDirEntry));
    1164         return 0;
     1161    SFLOGFLOW(("sf_dentry_delete: %p\n", pDirEntry));
     1162    return 0;
    11651163}
    11661164
     
    11691167static int sf_dentry_init(struct dentry *pDirEntry)
    11701168{
    1171         SFLOGFLOW(("sf_dentry_init: %p\n", pDirEntry));
    1172         return 0;
     1169    SFLOGFLOW(("sf_dentry_init: %p\n", pDirEntry));
     1170    return 0;
    11731171}
    11741172# endif
     
    11821180 */
    11831181struct dentry_operations sf_dentry_ops = {
    1184         .d_revalidate = sf_dentry_revalidate,
     1182    .d_revalidate = sf_dentry_revalidate,
    11851183#ifdef SFLOG_ENABLED
    1186         .d_delete = sf_dentry_delete,
     1184    .d_delete = sf_dentry_delete,
    11871185# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
    1188         .d_init = sf_dentry_init,
     1186    .d_init = sf_dentry_init,
    11891187# endif
    11901188#endif
  • trunk/src/VBox/Additions/linux/sharedfolders/vbsfmount.h

    r77492 r77526  
    4545
    4646struct vbsf_mount_info_new {
    47         /**
    48         * The old version of the mount_info struct started with a
    49         * char name[MAX_HOST_NAME] field, where name cannot be '\0'.
    50         * So the new version of the mount_info struct starts with a
    51         * nullchar field which is always 0 so that we can detect and
    52         * reject the old structure being passed.
    53         */
    54         char nullchar;
    55         char signature[3];      /**< signature */
    56         int length;             /**< length of the whole structure */
    57         char name[MAX_HOST_NAME];       /**< share name */
    58         char nls_name[MAX_NLS_NAME];    /**< name of an I/O charset */
    59         int uid;                /**< user ID for all entries, default 0=root */
    60         int gid;                /**< group ID for all entries, default 0=root */
    61         int ttl;                /**< directory entry and inode time to live in milliseconds.
    62                                  * -1 for kernel default, 0 to disable caching.  */
    63         int dmode;              /**< mode for directories if != 0xffffffff */
    64         int fmode;              /**< mode for regular files if != 0xffffffff */
    65         int dmask;              /**< umask applied to directories */
    66         int fmask;              /**< umask applied to regular files */
    67         char tag[32];           /**< Mount tag for VBoxService automounter.  @since 6.0 */
    68         uint32_t cMaxIoPages;   /**< Max pages to read & write at a time.  @since 6.0.6 */
     47    /**
     48    * The old version of the mount_info struct started with a
     49    * char name[MAX_HOST_NAME] field, where name cannot be '\0'.
     50    * So the new version of the mount_info struct starts with a
     51    * nullchar field which is always 0 so that we can detect and
     52    * reject the old structure being passed.
     53    */
     54    char nullchar;
     55    char signature[3];          /**< signature */
     56    int length;                 /**< length of the whole structure */
     57    char name[MAX_HOST_NAME];   /**< share name */
     58    char nls_name[MAX_NLS_NAME];/**< name of an I/O charset */
     59    int uid;                    /**< user ID for all entries, default 0=root */
     60    int gid;                    /**< group ID for all entries, default 0=root */
     61    int ttl;                    /**< directory entry and inode time to live in milliseconds.
     62                                         * -1 for kernel default, 0 to disable caching.  */
     63    int dmode;                  /**< mode for directories if != 0xffffffff */
     64    int fmode;                  /**< mode for regular files if != 0xffffffff */
     65    int dmask;                  /**< umask applied to directories */
     66    int fmask;                  /**< umask applied to regular files */
     67    char tag[32];               /**< Mount tag for VBoxService automounter.  @since 6.0 */
     68    uint32_t cMaxIoPages;       /**< Max pages to read & write at a time.  @since 6.0.6 */
    6969};
    7070
    7171struct vbsf_mount_opts {
    72         int uid;
    73         int gid;
    74         int ttl;
    75         int dmode;
    76         int fmode;
    77         int dmask;
    78         int fmask;
    79         int ronly;
    80         int sloppy;
    81         int noexec;
    82         int nodev;
    83         int nosuid;
    84         int remount;
    85         char nls_name[MAX_NLS_NAME];
    86         char *convertcp;
    87         uint32_t cMaxIoPages;
     72    int uid;
     73    int gid;
     74    int ttl;
     75    int dmode;
     76    int fmode;
     77    int dmask;
     78    int fmask;
     79    int ronly;
     80    int sloppy;
     81    int noexec;
     82    int nodev;
     83    int nosuid;
     84    int remount;
     85    char nls_name[MAX_NLS_NAME];
     86    char *convertcp;
     87    uint32_t cMaxIoPages;
    8888};
    8989
    9090/** Completes the mount operation by adding the new mount point to mtab if required. */
    9191int vbsfmount_complete(const char *host_name, const char *mount_point,
    92                        unsigned long flags, struct vbsf_mount_opts *opts);
     92                       unsigned long flags, struct vbsf_mount_opts *opts);
    9393
    9494#endif /* !GA_INCLUDED_SRC_linux_sharedfolders_vbsfmount_h */
  • trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.c

    r77524 r77526  
    3737 * See also: http://us1.samba.org/samba/ftp/cifs-cvs/ols2006-fs-tutorial-smf.odp
    3838 */
     39
    3940
    4041/*********************************************************************************************************************************
     
    8182static void sf_super_info_copy_remount_options(struct vbsf_super_info *sf_g, struct vbsf_mount_info_new *info)
    8283{
    83         sf_g->ttl_msec = info->ttl;
    84         if (info->ttl > 0)
    85                 sf_g->ttl = msecs_to_jiffies(info->ttl);
    86         else if (info->ttl == 0 || info->ttl != -1)
    87                 sf_g->ttl = sf_g->ttl_msec = 0;
    88         else
    89                 sf_g->ttl = msecs_to_jiffies(VBSF_DEFAULT_TTL_MS);
    90 
    91         sf_g->uid = info->uid;
    92         sf_g->gid = info->gid;
    93 
    94         if ((unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, tag)) {
    95                 /* new fields */
    96                 sf_g->dmode = info->dmode;
    97                 sf_g->fmode = info->fmode;
    98                 sf_g->dmask = info->dmask;
    99                 sf_g->fmask = info->fmask;
    100         } else {
    101                 sf_g->dmode = ~0;
    102                 sf_g->fmode = ~0;
    103         }
    104 
    105         if ((unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, cMaxIoPages)) {
    106                 AssertCompile(sizeof(sf_g->tag) >= sizeof(info->tag));
    107                 memcpy(sf_g->tag, info->tag, sizeof(info->tag));
    108                 sf_g->tag[sizeof(sf_g->tag) - 1] = '\0';
    109         } else {
    110                 sf_g->tag[0] = '\0';
    111         }
    112 
    113         /* The max number of pages in an I/O request.  This must take into
    114            account that the physical heap generally grows in 64 KB chunks,
    115            so we should not try push that limit.   It also needs to take
    116            into account that the host will allocate temporary heap buffers
    117            for the I/O bytes we send/receive, so don't push the host heap
    118            too hard as we'd have to retry with smaller requests when this
    119            happens, which isn't too efficient. */
    120         sf_g->cMaxIoPages = RT_MIN(_16K / sizeof(RTGCPHYS64) /* => 8MB buffer */,
    121                                    VMMDEV_MAX_HGCM_DATA_SIZE >> PAGE_SHIFT);
    122         if (   (unsigned)info->length >= sizeof(struct vbsf_mount_info_new)
    123             && info->cMaxIoPages != 0) {
    124                 if (info->cMaxIoPages <= VMMDEV_MAX_HGCM_DATA_SIZE >> PAGE_SHIFT)
    125                         sf_g->cMaxIoPages = info->cMaxIoPages;
    126                 else
    127                         printk(KERN_WARNING "vboxsf: max I/O page count (%#x) is out of range, using default (%#x) instead.\n",
    128                                 info->cMaxIoPages, sf_g->cMaxIoPages);
    129         }
     84    sf_g->ttl_msec = info->ttl;
     85    if (info->ttl > 0)
     86        sf_g->ttl = msecs_to_jiffies(info->ttl);
     87    else if (info->ttl == 0 || info->ttl != -1)
     88        sf_g->ttl = sf_g->ttl_msec = 0;
     89    else
     90        sf_g->ttl = msecs_to_jiffies(VBSF_DEFAULT_TTL_MS);
     91
     92    sf_g->uid = info->uid;
     93    sf_g->gid = info->gid;
     94
     95    if ((unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, tag)) {
     96        /* new fields */
     97        sf_g->dmode = info->dmode;
     98        sf_g->fmode = info->fmode;
     99        sf_g->dmask = info->dmask;
     100        sf_g->fmask = info->fmask;
     101    } else {
     102        sf_g->dmode = ~0;
     103        sf_g->fmode = ~0;
     104    }
     105
     106    if ((unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, cMaxIoPages)) {
     107        AssertCompile(sizeof(sf_g->tag) >= sizeof(info->tag));
     108        memcpy(sf_g->tag, info->tag, sizeof(info->tag));
     109        sf_g->tag[sizeof(sf_g->tag) - 1] = '\0';
     110    } else {
     111        sf_g->tag[0] = '\0';
     112    }
     113
     114    /* The max number of pages in an I/O request.  This must take into
     115       account that the physical heap generally grows in 64 KB chunks,
     116       so we should not try push that limit.   It also needs to take
     117       into account that the host will allocate temporary heap buffers
     118       for the I/O bytes we send/receive, so don't push the host heap
     119       too hard as we'd have to retry with smaller requests when this
     120       happens, which isn't too efficient. */
     121    sf_g->cMaxIoPages = RT_MIN(_16K / sizeof(RTGCPHYS64) /* => 8MB buffer */,
     122                   VMMDEV_MAX_HGCM_DATA_SIZE >> PAGE_SHIFT);
     123    if (   (unsigned)info->length >= sizeof(struct vbsf_mount_info_new)
     124        && info->cMaxIoPages != 0) {
     125        if (info->cMaxIoPages <= VMMDEV_MAX_HGCM_DATA_SIZE >> PAGE_SHIFT)
     126            sf_g->cMaxIoPages = info->cMaxIoPages;
     127        else
     128            printk(KERN_WARNING "vboxsf: max I/O page count (%#x) is out of range, using default (%#x) instead.\n",
     129                    info->cMaxIoPages, sf_g->cMaxIoPages);
     130    }
    130131}
    131132
     
    133134static int sf_super_info_alloc(struct vbsf_mount_info_new *info, struct vbsf_super_info **sf_gp)
    134135{
    135         int err, rc;
    136         SHFLSTRING *str_name;
    137         size_t name_len, str_len;
    138         struct vbsf_super_info *sf_g;
    139 
    140         TRACE();
    141         sf_g = kmalloc(sizeof(*sf_g), GFP_KERNEL);
    142         if (!sf_g) {
    143                 err = -ENOMEM;
    144                 LogRelFunc(("could not allocate memory for super info\n"));
    145                 goto fail0;
    146         }
    147 
    148         RT_ZERO(*sf_g);
    149 
    150         if (info->nullchar != '\0'
    151             || info->signature[0] != VBSF_MOUNT_SIGNATURE_BYTE_0
    152             || info->signature[1] != VBSF_MOUNT_SIGNATURE_BYTE_1
    153             || info->signature[2] != VBSF_MOUNT_SIGNATURE_BYTE_2) {
    154                 err = -EINVAL;
    155                 goto fail1;
    156         }
    157 
    158         info->name[sizeof(info->name) - 1] = 0;
    159         info->nls_name[sizeof(info->nls_name) - 1] = 0;
    160 
    161         name_len = strlen(info->name);
    162         str_len = offsetof(SHFLSTRING, String.utf8) + name_len + 1;
    163         str_name = kmalloc(str_len, GFP_KERNEL);
    164         if (!str_name) {
    165                 err = -ENOMEM;
    166                 LogRelFunc(("could not allocate memory for host name\n"));
    167                 goto fail1;
    168         }
    169 
    170         str_name->u16Length = name_len;
    171         str_name->u16Size = name_len + 1;
    172         memcpy(str_name->String.utf8, info->name, name_len + 1);
     136    int err, rc;
     137    SHFLSTRING *str_name;
     138    size_t name_len, str_len;
     139    struct vbsf_super_info *sf_g;
     140
     141    TRACE();
     142    sf_g = kmalloc(sizeof(*sf_g), GFP_KERNEL);
     143    if (!sf_g) {
     144        err = -ENOMEM;
     145        LogRelFunc(("could not allocate memory for super info\n"));
     146        goto fail0;
     147    }
     148
     149    RT_ZERO(*sf_g);
     150
     151    if (info->nullchar != '\0'
     152        || info->signature[0] != VBSF_MOUNT_SIGNATURE_BYTE_0
     153        || info->signature[1] != VBSF_MOUNT_SIGNATURE_BYTE_1
     154        || info->signature[2] != VBSF_MOUNT_SIGNATURE_BYTE_2) {
     155        err = -EINVAL;
     156        goto fail1;
     157    }
     158
     159    info->name[sizeof(info->name) - 1] = 0;
     160    info->nls_name[sizeof(info->nls_name) - 1] = 0;
     161
     162    name_len = strlen(info->name);
     163    str_len = offsetof(SHFLSTRING, String.utf8) + name_len + 1;
     164    str_name = kmalloc(str_len, GFP_KERNEL);
     165    if (!str_name) {
     166        err = -ENOMEM;
     167        LogRelFunc(("could not allocate memory for host name\n"));
     168        goto fail1;
     169    }
     170
     171    str_name->u16Length = name_len;
     172    str_name->u16Size = name_len + 1;
     173    memcpy(str_name->String.utf8, info->name, name_len + 1);
    173174
    174175#define _IS_UTF8(_str)  (strcmp(_str, "utf8") == 0)
    175176#define _IS_EMPTY(_str) (strcmp(_str, "") == 0)
    176177
    177         /* Check if NLS charset is valid and not points to UTF8 table */
    178         if (info->nls_name[0]) {
    179                 if (_IS_UTF8(info->nls_name))
    180                         sf_g->nls = NULL;
    181                 else {
    182                         sf_g->nls = load_nls(info->nls_name);
    183                         if (!sf_g->nls) {
    184                                 err = -EINVAL;
    185                                 LogFunc(("failed to load nls %s\n",
    186                                         info->nls_name));
    187                                 kfree(str_name);
    188                                 goto fail1;
    189                         }
    190                 }
    191         } else {
     178    /* Check if NLS charset is valid and not points to UTF8 table */
     179    if (info->nls_name[0]) {
     180        if (_IS_UTF8(info->nls_name))
     181            sf_g->nls = NULL;
     182        else {
     183            sf_g->nls = load_nls(info->nls_name);
     184            if (!sf_g->nls) {
     185                err = -EINVAL;
     186                LogFunc(("failed to load nls %s\n",
     187                    info->nls_name));
     188                kfree(str_name);
     189                goto fail1;
     190            }
     191        }
     192    } else {
    192193#ifdef CONFIG_NLS_DEFAULT
    193                 /* If no NLS charset specified, try to load the default
    194                 * one if it's not points to UTF8. */
    195                 if (!_IS_UTF8(CONFIG_NLS_DEFAULT)
    196                     && !_IS_EMPTY(CONFIG_NLS_DEFAULT))
    197                         sf_g->nls = load_nls_default();
    198                 else
    199                         sf_g->nls = NULL;
     194        /* If no NLS charset specified, try to load the default
     195        * one if it's not points to UTF8. */
     196        if (!_IS_UTF8(CONFIG_NLS_DEFAULT)
     197            && !_IS_EMPTY(CONFIG_NLS_DEFAULT))
     198            sf_g->nls = load_nls_default();
     199        else
     200            sf_g->nls = NULL;
    200201#else
    201                 sf_g->nls = NULL;
    202 #endif
    203         }
     202        sf_g->nls = NULL;
     203#endif
     204    }
    204205
    205206#undef _IS_UTF8
    206207#undef _IS_EMPTY
    207208
    208         rc = VbglR0SfHostReqMapFolderWithContigSimple(str_name, virt_to_phys(str_name), RTPATH_DELIMITER,
    209                                                       true /*fCaseSensitive*/, &sf_g->map.root);
    210         kfree(str_name);
    211 
    212         if (RT_FAILURE(rc)) {
    213                 err = -EPROTO;
    214                 LogFunc(("SHFL_FN_MAP_FOLDER failed rc=%Rrc\n", rc));
    215                 goto fail2;
    216         }
    217 
    218         /* The rest is shared with remount. */
    219         sf_super_info_copy_remount_options(sf_g, info);
    220 
    221         *sf_gp = sf_g;
    222         return 0;
     209    rc = VbglR0SfHostReqMapFolderWithContigSimple(str_name, virt_to_phys(str_name), RTPATH_DELIMITER,
     210                              true /*fCaseSensitive*/, &sf_g->map.root);
     211    kfree(str_name);
     212
     213    if (RT_FAILURE(rc)) {
     214        err = -EPROTO;
     215        LogFunc(("SHFL_FN_MAP_FOLDER failed rc=%Rrc\n", rc));
     216        goto fail2;
     217    }
     218
     219    /* The rest is shared with remount. */
     220    sf_super_info_copy_remount_options(sf_g, info);
     221
     222    *sf_gp = sf_g;
     223    return 0;
    223224
    224225 fail2:
    225         if (sf_g->nls)
    226                 unload_nls(sf_g->nls);
     226    if (sf_g->nls)
     227        unload_nls(sf_g->nls);
    227228
    228229 fail1:
    229         kfree(sf_g);
     230    kfree(sf_g);
    230231
    231232 fail0:
    232         return err;
     233    return err;
    233234}
    234235
     
    236237static void sf_super_info_free(struct vbsf_super_info *sf_g)
    237238{
    238         int rc;
    239 
    240         TRACE();
    241         rc = VbglR0SfHostReqUnmapFolderSimple(sf_g->map.root);
    242         if (RT_FAILURE(rc))
    243                 LogFunc(("VbglR0SfHostReqUnmapFolderSimple failed rc=%Rrc\n", rc));
    244 
    245         if (sf_g->nls)
    246                 unload_nls(sf_g->nls);
    247 
    248         kfree(sf_g);
     239    int rc;
     240
     241    TRACE();
     242    rc = VbglR0SfHostReqUnmapFolderSimple(sf_g->map.root);
     243    if (RT_FAILURE(rc))
     244        LogFunc(("VbglR0SfHostReqUnmapFolderSimple failed rc=%Rrc\n", rc));
     245
     246    if (sf_g->nls)
     247        unload_nls(sf_g->nls);
     248
     249    kfree(sf_g);
    249250}
    250251
     
    255256static int sf_init_backing_dev(struct super_block *sb, struct vbsf_super_info *sf_g)
    256257{
    257         int rc = 0;
     258    int rc = 0;
    258259/** @todo this needs sorting out between 3.19 and 4.11   */
    259260#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) //&& LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19, 0)
    260         /* Each new shared folder map gets a new uint64_t identifier,
    261         * allocated in sequence.  We ASSUME the sequence will not wrap. */
     261    /* Each new shared folder map gets a new uint64_t identifier,
     262    * allocated in sequence.  We ASSUME the sequence will not wrap. */
    262263#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
    263         static uint64_t s_u64Sequence = 0;
    264         uint64_t u64CurrentSequence = ASMAtomicIncU64(&s_u64Sequence);
    265 #endif
    266         struct backing_dev_info *bdi;
     264    static uint64_t s_u64Sequence = 0;
     265    uint64_t u64CurrentSequence = ASMAtomicIncU64(&s_u64Sequence);
     266#endif
     267    struct backing_dev_info *bdi;
    267268
    268269#  if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
    269         rc = super_setup_bdi_name(sb, "vboxsf-%llu", (unsigned long long)u64CurrentSequence);
    270         if (!rc)
    271                 bdi = sb->s_bdi;
    272         else
    273                 return rc;
     270    rc = super_setup_bdi_name(sb, "vboxsf-%llu", (unsigned long long)u64CurrentSequence);
     271    if (!rc)
     272        bdi = sb->s_bdi;
     273    else
     274        return rc;
    274275#  else
    275         bdi = &sf_g->bdi;
     276    bdi = &sf_g->bdi;
    276277#  endif
    277278
    278         bdi->ra_pages = 0;                      /* No readahead */
     279    bdi->ra_pages = 0;                      /* No readahead */
    279280
    280281# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12)
    281         bdi->capabilities = 0
     282    bdi->capabilities = 0
    282283#  ifdef BDI_CAP_MAP_DIRECT
    283                           | BDI_CAP_MAP_DIRECT  /* MAP_SHARED */
     284                  | BDI_CAP_MAP_DIRECT  /* MAP_SHARED */
    284285#  endif
    285286#  ifdef BDI_CAP_MAP_COPY
    286                           | BDI_CAP_MAP_COPY    /* MAP_PRIVATE */
     287                      | BDI_CAP_MAP_COPY    /* MAP_PRIVATE */
    287288#  endif
    288289#  ifdef BDI_CAP_READ_MAP
    289                           | BDI_CAP_READ_MAP    /* can be mapped for reading */
     290                      | BDI_CAP_READ_MAP    /* can be mapped for reading */
    290291#  endif
    291292#  ifdef BDI_CAP_WRITE_MAP
    292                           | BDI_CAP_WRITE_MAP   /* can be mapped for writing */
     293                      | BDI_CAP_WRITE_MAP   /* can be mapped for writing */
    293294#  endif
    294295#  ifdef BDI_CAP_EXEC_MAP
    295                           | BDI_CAP_EXEC_MAP    /* can be mapped for execution */
     296                      | BDI_CAP_EXEC_MAP    /* can be mapped for execution */
    296297#  endif
    297298#  ifdef BDI_CAP_STRICTLIMIT
    298                           | BDI_CAP_STRICTLIMIT;
     299                      | BDI_CAP_STRICTLIMIT;
    299300#  endif
    300                           ;
     301              ;
    301302#  ifdef BDI_CAP_STRICTLIMIT
    302         /* Smalles possible amount of dirty pages: %1 of RAM */
    303         bdi_set_max_ratio(bdi, 1);
     303    /* Smalles possible amount of dirty pages: %1 of RAM */
     304    bdi_set_max_ratio(bdi, 1);
    304305#  endif
    305 # endif /* >= 2.6.12 */
     306# endif /* >= 2.6.12 */
    306307
    307308# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
    308         rc = bdi_init(&sf_g->bdi);
     309    rc = bdi_init(&sf_g->bdi);
    309310#  if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
    310         if (!rc)
    311                 rc = bdi_register(&sf_g->bdi, NULL, "vboxsf-%llu",
    312                                   (unsigned long long)u64CurrentSequence);
     311    if (!rc)
     312        rc = bdi_register(&sf_g->bdi, NULL, "vboxsf-%llu",
     313                  (unsigned long long)u64CurrentSequence);
    313314#  endif /* >= 2.6.26 */
    314 # endif  /* >= 2.6.24 */
     315# endif  /* >= 2.6.24 */
    315316#endif   /* >= 2.6.0 */
    316         return rc;
     317    return rc;
    317318}
    318319
     
    324325{
    325326#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19, 0)
    326         bdi_destroy(&sf_g->bdi);        /* includes bdi_unregister() */
     327    bdi_destroy(&sf_g->bdi);    /* includes bdi_unregister() */
    327328#endif
    328329}
     
    342343static int sf_read_super_aux(struct super_block *sb, void *data, int flags)
    343344{
    344         int err;
    345         struct dentry *droot;
    346         struct inode *iroot;
    347         struct sf_inode_info *sf_i;
    348         struct vbsf_super_info *sf_g;
    349         SHFLFSOBJINFO fsinfo;
    350         struct vbsf_mount_info_new *info;
    351         bool fInodePut = true;
    352 
    353         TRACE();
    354         if (!data) {
    355                 LogFunc(("no mount info specified\n"));
    356                 return -EINVAL;
    357         }
    358 
    359         info = data;
    360 
    361         if (flags & MS_REMOUNT) {
    362                 LogFunc(("remounting is not supported\n"));
    363                 return -ENOSYS;
    364         }
    365 
    366         err = sf_super_info_alloc(info, &sf_g);
    367         if (err)
    368                 goto fail0;
    369 
    370         sf_i = kmalloc(sizeof(*sf_i), GFP_KERNEL);
    371         if (!sf_i) {
    372                 err = -ENOMEM;
    373                 LogRelFunc(("could not allocate memory for root inode info\n"));
    374                 goto fail1;
    375         }
    376 
    377         sf_i->handle = SHFL_HANDLE_NIL;
    378         sf_i->path = kmalloc(sizeof(SHFLSTRING) + 1, GFP_KERNEL);
    379         if (!sf_i->path) {
    380                 err = -ENOMEM;
    381                 LogRelFunc(("could not allocate memory for root inode path\n"));
    382                 goto fail2;
    383         }
    384 
    385         sf_i->path->u16Length = 1;
    386         sf_i->path->u16Size = 2;
    387         sf_i->path->String.utf8[0] = '/';
    388         sf_i->path->String.utf8[1] = 0;
    389         sf_i->force_reread = 0;
    390         RTListInit(&sf_i->HandleList);
     345    int err;
     346    struct dentry *droot;
     347    struct inode *iroot;
     348    struct sf_inode_info *sf_i;
     349    struct vbsf_super_info *sf_g;
     350    SHFLFSOBJINFO fsinfo;
     351    struct vbsf_mount_info_new *info;
     352    bool fInodePut = true;
     353
     354    TRACE();
     355    if (!data) {
     356        LogFunc(("no mount info specified\n"));
     357        return -EINVAL;
     358    }
     359
     360    info = data;
     361
     362    if (flags & MS_REMOUNT) {
     363        LogFunc(("remounting is not supported\n"));
     364        return -ENOSYS;
     365    }
     366
     367    err = sf_super_info_alloc(info, &sf_g);
     368    if (err)
     369        goto fail0;
     370
     371    sf_i = kmalloc(sizeof(*sf_i), GFP_KERNEL);
     372    if (!sf_i) {
     373        err = -ENOMEM;
     374        LogRelFunc(("could not allocate memory for root inode info\n"));
     375        goto fail1;
     376    }
     377
     378    sf_i->handle = SHFL_HANDLE_NIL;
     379    sf_i->path = kmalloc(sizeof(SHFLSTRING) + 1, GFP_KERNEL);
     380    if (!sf_i->path) {
     381        err = -ENOMEM;
     382        LogRelFunc(("could not allocate memory for root inode path\n"));
     383        goto fail2;
     384    }
     385
     386    sf_i->path->u16Length = 1;
     387    sf_i->path->u16Size = 2;
     388    sf_i->path->String.utf8[0] = '/';
     389    sf_i->path->String.utf8[1] = 0;
     390    sf_i->force_reread = 0;
     391    RTListInit(&sf_i->HandleList);
    391392#ifdef VBOX_STRICT
    392         sf_i->u32Magic = SF_INODE_INFO_MAGIC;
    393 #endif
    394 
    395         err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
    396         if (err) {
    397                 LogFunc(("could not stat root of share\n"));
    398                 goto fail3;
    399         }
    400 
    401         sb->s_magic = 0xface;
    402         sb->s_blocksize = 1024;
     393    sf_i->u32Magic = SF_INODE_INFO_MAGIC;
     394#endif
     395
     396    err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
     397    if (err) {
     398        LogFunc(("could not stat root of share\n"));
     399        goto fail3;
     400    }
     401
     402    sb->s_magic = 0xface;
     403    sb->s_blocksize = 1024;
    403404#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 3)
    404         /* Required for seek/sendfile (see 'loff_t max' in fs/read_write.c / do_sendfile()). */
     405    /* Required for seek/sendfile (see 'loff_t max' in fs/read_write.c / do_sendfile()). */
    405406# if defined MAX_LFS_FILESIZE
    406         sb->s_maxbytes = MAX_LFS_FILESIZE;
     407    sb->s_maxbytes = MAX_LFS_FILESIZE;
    407408# elif BITS_PER_LONG == 32
    408         sb->s_maxbytes = (loff_t)ULONG_MAX << PAGE_SHIFT;
     409    sb->s_maxbytes = (loff_t)ULONG_MAX << PAGE_SHIFT;
    409410# else
    410         sb->s_maxbytes = INT64_MAX;
     411    sb->s_maxbytes = INT64_MAX;
    411412# endif
    412413#endif
    413         sb->s_op = &sf_super_ops;
     414    sb->s_op = &sf_super_ops;
    414415#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
    415         sb->s_d_op = &sf_dentry_ops;
     416    sb->s_d_op = &sf_dentry_ops;
    416417#endif
    417418
    418419#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
    419         iroot = iget_locked(sb, 0);
     420    iroot = iget_locked(sb, 0);
    420421#else
    421         iroot = iget(sb, 0);
    422 #endif
    423         if (!iroot) {
    424                 err = -ENOMEM;  /* XXX */
    425                 LogFunc(("could not get root inode\n"));
    426                 goto fail3;
    427         }
    428 
    429         if (sf_init_backing_dev(sb, sf_g)) {
    430                 err = -EINVAL;
    431                 LogFunc(("could not init bdi\n"));
     422    iroot = iget(sb, 0);
     423#endif
     424    if (!iroot) {
     425        err = -ENOMEM;  /* XXX */
     426        LogFunc(("could not get root inode\n"));
     427        goto fail3;
     428    }
     429
     430    if (sf_init_backing_dev(sb, sf_g)) {
     431        err = -EINVAL;
     432        LogFunc(("could not init bdi\n"));
    432433#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
    433                 unlock_new_inode(iroot);
    434 #endif
    435                 goto fail4;
    436         }
    437 
    438         sf_init_inode(iroot, sf_i, &fsinfo, sf_g);
    439         SET_INODE_INFO(iroot, sf_i);
     434        unlock_new_inode(iroot);
     435#endif
     436        goto fail4;
     437    }
     438
     439    sf_init_inode(iroot, sf_i, &fsinfo, sf_g);
     440    SET_INODE_INFO(iroot, sf_i);
    440441
    441442#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
    442         unlock_new_inode(iroot);
     443    unlock_new_inode(iroot);
    443444#endif
    444445
    445446#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
    446         droot = d_make_root(iroot);
     447    droot = d_make_root(iroot);
    447448#else
    448         droot = d_alloc_root(iroot);
    449 #endif
    450         if (!droot) {
    451                 err = -ENOMEM;  /* XXX */
    452                 LogFunc(("d_alloc_root failed\n"));
     449    droot = d_alloc_root(iroot);
     450#endif
     451    if (!droot) {
     452        err = -ENOMEM;  /* XXX */
     453        LogFunc(("d_alloc_root failed\n"));
    453454#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
    454                 fInodePut = false;
    455 #endif
    456                 goto fail5;
    457         }
    458 
    459         sb->s_root = droot;
    460         VBSF_SET_SUPER_INFO(sb, sf_g);
    461         return 0;
     455        fInodePut = false;
     456#endif
     457        goto fail5;
     458    }
     459
     460    sb->s_root = droot;
     461    VBSF_SET_SUPER_INFO(sb, sf_g);
     462    return 0;
    462463
    463464 fail5:
    464         sf_done_backing_dev(sb, sf_g);
     465    sf_done_backing_dev(sb, sf_g);
    465466
    466467 fail4:
    467         if (fInodePut)
    468                 iput(iroot);
     468    if (fInodePut)
     469        iput(iroot);
    469470
    470471 fail3:
    471         kfree(sf_i->path);
     472    kfree(sf_i->path);
    472473
    473474 fail2:
    474         kfree(sf_i);
     475    kfree(sf_i);
    475476
    476477 fail1:
    477         sf_super_info_free(sf_g);
     478    sf_super_info_free(sf_g);
    478479
    479480 fail0:
    480         return err;
     481    return err;
    481482}
    482483
     
    493494#endif
    494495{
    495         struct sf_inode_info *sf_i;
    496 
    497         TRACE();
    498 
    499         /*
    500         * Flush stuff.
    501         */
     496    struct sf_inode_info *sf_i;
     497
     498    TRACE();
     499
     500    /*
     501    * Flush stuff.
     502    */
    502503#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
    503         truncate_inode_pages(&inode->i_data, 0);
     504    truncate_inode_pages(&inode->i_data, 0);
    504505# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
    505         clear_inode(inode);
     506    clear_inode(inode);
    506507# else
    507         end_writeback(inode);
     508    end_writeback(inode);
    508509# endif
    509510#endif
    510         /*
    511         * Clean up our inode info.
    512         */
    513         sf_i = GET_INODE_INFO(inode);
    514         if (sf_i) {
    515                 SET_INODE_INFO(inode, NULL);
    516 
    517                 Assert(sf_i->u32Magic == SF_INODE_INFO_MAGIC);
    518                 BUG_ON(!sf_i->path);
    519                 kfree(sf_i->path);
    520                 sf_handle_drop_chain(sf_i);
     511    /*
     512    * Clean up our inode info.
     513    */
     514    sf_i = GET_INODE_INFO(inode);
     515    if (sf_i) {
     516        SET_INODE_INFO(inode, NULL);
     517
     518        Assert(sf_i->u32Magic == SF_INODE_INFO_MAGIC);
     519        BUG_ON(!sf_i->path);
     520        kfree(sf_i->path);
     521        sf_handle_drop_chain(sf_i);
    521522# ifdef VBOX_STRICT
    522                 sf_i->u32Magic = SF_INODE_INFO_MAGIC_DEAD;
     523        sf_i->u32Magic = SF_INODE_INFO_MAGIC_DEAD;
    523524# endif
    524                 kfree(sf_i);
    525         }
     525        kfree(sf_i);
     526    }
    526527}
    527528
     
    542543static void sf_put_super(struct super_block *sb)
    543544{
    544         struct vbsf_super_info *sf_g;
    545 
    546         sf_g = VBSF_GET_SUPER_INFO(sb);
    547         BUG_ON(!sf_g);
    548         sf_done_backing_dev(sb, sf_g);
    549         sf_super_info_free(sf_g);
     545    struct vbsf_super_info *sf_g;
     546
     547    sf_g = VBSF_GET_SUPER_INFO(sb);
     548    BUG_ON(!sf_g);
     549    sf_done_backing_dev(sb, sf_g);
     550    sf_super_info_free(sf_g);
    550551}
    551552
     
    563564{
    564565#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
    565         struct super_block *sb = dentry->d_inode->i_sb;
    566 #endif
    567         int rc;
    568         VBOXSFVOLINFOREQ *pReq = (VBOXSFVOLINFOREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
    569         if (pReq) {
    570                 SHFLVOLINFO            *pVolInfo = &pReq->VolInfo;
    571                 struct vbsf_super_info *sf_g     = VBSF_GET_SUPER_INFO(sb);
    572                 rc = VbglR0SfHostReqQueryVolInfo(sf_g->map.root, pReq, SHFL_HANDLE_ROOT);
    573                 if (RT_SUCCESS(rc)) {
    574                         stat->f_type   = NFS_SUPER_MAGIC; /** @todo vboxsf type? */
    575                         stat->f_bsize  = pVolInfo->ulBytesPerAllocationUnit;
     566    struct super_block *sb = dentry->d_inode->i_sb;
     567#endif
     568    int rc;
     569    VBOXSFVOLINFOREQ *pReq = (VBOXSFVOLINFOREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
     570    if (pReq) {
     571        SHFLVOLINFO            *pVolInfo = &pReq->VolInfo;
     572        struct vbsf_super_info *sf_g     = VBSF_GET_SUPER_INFO(sb);
     573        rc = VbglR0SfHostReqQueryVolInfo(sf_g->map.root, pReq, SHFL_HANDLE_ROOT);
     574        if (RT_SUCCESS(rc)) {
     575            stat->f_type   = NFS_SUPER_MAGIC; /** @todo vboxsf type? */
     576            stat->f_bsize  = pVolInfo->ulBytesPerAllocationUnit;
    576577#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 73)
    577                         stat->f_frsize = pVolInfo->ulBytesPerAllocationUnit;
    578 #endif
    579                         stat->f_blocks = pVolInfo->ullTotalAllocationBytes
    580                                        / pVolInfo->ulBytesPerAllocationUnit;
    581                         stat->f_bfree  = pVolInfo->ullAvailableAllocationBytes
    582                                        / pVolInfo->ulBytesPerAllocationUnit;
    583                         stat->f_bavail = pVolInfo->ullAvailableAllocationBytes
    584                                        / pVolInfo->ulBytesPerAllocationUnit;
    585                         stat->f_files  = 1000;
    586                         stat->f_ffree  = 1000; /* don't return 0 here since the guest may think
    587                                                 * that it is not possible to create any more files */
    588                         stat->f_fsid.val[0] = 0;
    589                         stat->f_fsid.val[1] = 0;
    590                         stat->f_namelen = 255;
     578            stat->f_frsize = pVolInfo->ulBytesPerAllocationUnit;
     579#endif
     580            stat->f_blocks = pVolInfo->ullTotalAllocationBytes
     581                       / pVolInfo->ulBytesPerAllocationUnit;
     582            stat->f_bfree  = pVolInfo->ullAvailableAllocationBytes
     583                       / pVolInfo->ulBytesPerAllocationUnit;
     584            stat->f_bavail = pVolInfo->ullAvailableAllocationBytes
     585                       / pVolInfo->ulBytesPerAllocationUnit;
     586            stat->f_files  = 1000;
     587            stat->f_ffree  = 1000; /* don't return 0 here since the guest may think
     588                        * that it is not possible to create any more files */
     589            stat->f_fsid.val[0] = 0;
     590            stat->f_fsid.val[1] = 0;
     591            stat->f_namelen = 255;
    591592#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
    592                         stat->f_flags = 0; /* not valid */
    593 #endif
    594                         RT_ZERO(stat->f_spare);
    595                         rc = 0;
    596                 } else
    597                         rc = -RTErrConvertToErrno(rc);
    598                 VbglR0PhysHeapFree(pReq);
    599         } else
    600                 rc = -ENOMEM;
    601         return rc;
     593            stat->f_flags = 0; /* not valid */
     594#endif
     595            RT_ZERO(stat->f_spare);
     596            rc = 0;
     597        } else
     598            rc = -RTErrConvertToErrno(rc);
     599        VbglR0PhysHeapFree(pReq);
     600    } else
     601        rc = -ENOMEM;
     602    return rc;
    602603}
    603604
     
    605606{
    606607#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 23)
    607         struct vbsf_super_info *sf_g;
    608         struct sf_inode_info *sf_i;
    609         struct inode *iroot;
    610         SHFLFSOBJINFO fsinfo;
    611         int err;
    612 
    613         sf_g = VBSF_GET_SUPER_INFO(sb);
    614         BUG_ON(!sf_g);
    615         if (data && data[0] != 0) {
    616                 struct vbsf_mount_info_new *info = (struct vbsf_mount_info_new *)data;
    617                 if (   info->nullchar == '\0'
    618                     && info->signature[0] == VBSF_MOUNT_SIGNATURE_BYTE_0
    619                     && info->signature[1] == VBSF_MOUNT_SIGNATURE_BYTE_1
    620                     && info->signature[2] == VBSF_MOUNT_SIGNATURE_BYTE_2) {
    621                         sf_super_info_copy_remount_options(sf_g, info);
    622                 }
    623         }
    624 
    625         iroot = ilookup(sb, 0);
    626         if (!iroot)
    627                 return -ENOSYS;
    628 
    629         sf_i = GET_INODE_INFO(iroot);
    630         err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
    631         BUG_ON(err != 0);
    632         sf_init_inode(iroot, sf_i, &fsinfo, sf_g);
    633         /*unlock_new_inode(iroot); */
    634         return 0;
     608    struct vbsf_super_info *sf_g;
     609    struct sf_inode_info *sf_i;
     610    struct inode *iroot;
     611    SHFLFSOBJINFO fsinfo;
     612    int err;
     613
     614    sf_g = VBSF_GET_SUPER_INFO(sb);
     615    BUG_ON(!sf_g);
     616    if (data && data[0] != 0) {
     617        struct vbsf_mount_info_new *info = (struct vbsf_mount_info_new *)data;
     618        if (   info->nullchar == '\0'
     619            && info->signature[0] == VBSF_MOUNT_SIGNATURE_BYTE_0
     620            && info->signature[1] == VBSF_MOUNT_SIGNATURE_BYTE_1
     621            && info->signature[2] == VBSF_MOUNT_SIGNATURE_BYTE_2) {
     622            sf_super_info_copy_remount_options(sf_g, info);
     623        }
     624    }
     625
     626    iroot = ilookup(sb, 0);
     627    if (!iroot)
     628        return -ENOSYS;
     629
     630    sf_i = GET_INODE_INFO(iroot);
     631    err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
     632    BUG_ON(err != 0);
     633    sf_init_inode(iroot, sf_i, &fsinfo, sf_g);
     634    /*unlock_new_inode(iroot); */
     635    return 0;
    635636#else  /* LINUX_VERSION_CODE < 2.4.23 */
    636         return -ENOSYS;
     637    return -ENOSYS;
    637638#endif /* LINUX_VERSION_CODE < 2.4.23 */
    638639}
     
    652653{
    653654#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
    654         struct super_block *sb = mnt->mnt_sb;
     655    struct super_block *sb = mnt->mnt_sb;
    655656#else
    656         struct super_block *sb = root->d_sb;
    657 #endif
    658         struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(sb);
    659         if (sf_g) {
    660                 seq_printf(m, ",uid=%u,gid=%u,ttl=%d,dmode=0%o,fmode=0%o,dmask=0%o,fmask=0%o,maxiopages=%u",
    661                            sf_g->uid, sf_g->gid, sf_g->ttl_msec, sf_g->dmode, sf_g->fmode, sf_g->dmask,
    662                            sf_g->fmask, sf_g->cMaxIoPages);
    663                 if (sf_g->tag[0] != '\0') {
    664                         seq_puts(m, ",tag=");
    665                         seq_escape(m, sf_g->tag, " \t\n\\");
    666                 }
    667         }
    668         return 0;
     657    struct super_block *sb = root->d_sb;
     658#endif
     659    struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(sb);
     660    if (sf_g) {
     661        seq_printf(m, ",uid=%u,gid=%u,ttl=%d,dmode=0%o,fmode=0%o,dmask=0%o,fmask=0%o,maxiopages=%u",
     662               sf_g->uid, sf_g->gid, sf_g->ttl_msec, sf_g->dmode, sf_g->fmode, sf_g->dmask,
     663               sf_g->fmask, sf_g->cMaxIoPages);
     664        if (sf_g->tag[0] != '\0') {
     665            seq_puts(m, ",tag=");
     666            seq_escape(m, sf_g->tag, " \t\n\\");
     667        }
     668    }
     669    return 0;
    669670}
    670671
     
    675676static struct super_operations sf_super_ops = {
    676677#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
    677         .clear_inode = sf_clear_inode,
     678    .clear_inode = sf_clear_inode,
    678679#else
    679         .evict_inode = sf_evict_inode,
     680    .evict_inode = sf_evict_inode,
    680681#endif
    681682#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
    682         .read_inode = sf_read_inode,
    683 #endif
    684         .put_super = sf_put_super,
    685         .statfs = sf_statfs,
    686         .remount_fs = sf_remount_fs,
    687         .show_options = sf_show_options
     683    .read_inode = sf_read_inode,
     684#endif
     685    .put_super = sf_put_super,
     686    .statfs = sf_statfs,
     687    .remount_fs = sf_remount_fs,
     688    .show_options = sf_show_options
    688689};
    689690
     
    697698static int sf_read_super_26(struct super_block *sb, void *data, int flags)
    698699{
    699         int err;
    700 
    701         TRACE();
    702         err = sf_read_super_aux(sb, data, flags);
    703         if (err)
    704                 printk(KERN_DEBUG "sf_read_super_aux err=%d\n", err);
    705 
    706         return err;
     700    int err;
     701
     702    TRACE();
     703    err = sf_read_super_aux(sb, data, flags);
     704    if (err)
     705        printk(KERN_DEBUG "sf_read_super_aux err=%d\n", err);
     706
     707    return err;
    707708}
    708709
    709710# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
    710711static struct super_block *sf_get_sb(struct file_system_type *fs_type,
    711                                      int flags, const char *dev_name,
    712                                      void *data)
    713 {
    714         TRACE();
    715         return get_sb_nodev(fs_type, flags, data, sf_read_super_26);
     712                     int flags, const char *dev_name,
     713                     void *data)
     714{
     715    TRACE();
     716    return get_sb_nodev(fs_type, flags, data, sf_read_super_26);
    716717}
    717718# elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
    718719static int sf_get_sb(struct file_system_type *fs_type, int flags,
    719                      const char *dev_name, void *data, struct vfsmount *mnt)
    720 {
    721         TRACE();
    722         return get_sb_nodev(fs_type, flags, data, sf_read_super_26, mnt);
     720             const char *dev_name, void *data, struct vfsmount *mnt)
     721{
     722    TRACE();
     723    return get_sb_nodev(fs_type, flags, data, sf_read_super_26, mnt);
    723724}
    724725# else /* LINUX_VERSION_CODE >= 2.6.39 */
    725726static struct dentry *sf_mount(struct file_system_type *fs_type, int flags,
    726                                const char *dev_name, void *data)
    727 {
    728         TRACE();
    729         return mount_nodev(fs_type, flags, data, sf_read_super_26);
     727                   const char *dev_name, void *data)
     728{
     729    TRACE();
     730    return mount_nodev(fs_type, flags, data, sf_read_super_26);
    730731}
    731732# endif /* LINUX_VERSION_CODE >= 2.6.39 */
    732733
    733734static struct file_system_type vboxsf_fs_type = {
    734         .owner = THIS_MODULE,
    735         .name = "vboxsf",
     735    .owner = THIS_MODULE,
     736    .name = "vboxsf",
    736737# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
    737         .get_sb = sf_get_sb,
     738    .get_sb = sf_get_sb,
    738739# else
    739         .mount = sf_mount,
     740    .mount = sf_mount,
    740741# endif
    741         .kill_sb = kill_anon_super
     742    .kill_sb = kill_anon_super
    742743};
    743744
     
    745746
    746747static struct super_block *sf_read_super_24(struct super_block *sb, void *data,
    747                                             int flags)
    748 {
    749         int err;
    750 
    751         TRACE();
    752         err = sf_read_super_aux(sb, data, flags);
    753         if (err) {
    754                 printk(KERN_DEBUG "sf_read_super_aux err=%d\n", err);
    755                 return NULL;
    756         }
    757 
    758         return sb;
     748                        int flags)
     749{
     750    int err;
     751
     752    TRACE();
     753    err = sf_read_super_aux(sb, data, flags);
     754    if (err) {
     755        printk(KERN_DEBUG "sf_read_super_aux err=%d\n", err);
     756        return NULL;
     757    }
     758
     759    return sb;
    759760}
    760761
     
    767768static int __init init(void)
    768769{
    769         int vrc;
    770         int rcRet = 0;
    771         int err;
    772 
    773         TRACE();
    774 
    775         if (sizeof(struct vbsf_mount_info_new) > PAGE_SIZE) {
    776                 printk(KERN_ERR
    777                        "Mount information structure is too large %lu\n"
    778                        "Must be less than or equal to %lu\n",
    779                        (unsigned long)sizeof(struct vbsf_mount_info_new),
    780                        (unsigned long)PAGE_SIZE);
    781                 return -EINVAL;
    782         }
    783 
    784         /** @todo Init order is wrong, file system reigstration is the very last
    785         *        thing we should do. */
    786         spin_lock_init(&g_SfHandleLock);
    787         err = register_filesystem(&vboxsf_fs_type);
    788         if (err) {
    789                 LogFunc(("register_filesystem err=%d\n", err));
    790                 return err;
    791         }
    792 
    793         vrc = VbglR0SfInit();
    794         if (RT_FAILURE(vrc)) {
    795                 LogRelFunc(("VbglR0SfInit failed, vrc=%Rrc\n", vrc));
    796                 rcRet = -EPROTO;
    797                 goto fail0;
    798         }
    799 
    800         vrc = VbglR0SfConnect(&client_handle);
    801         g_SfClient = client_handle; /* temporary */
    802         if (RT_FAILURE(vrc)) {
    803                 LogRelFunc(("VbglR0SfConnect failed, vrc=%Rrc\n", vrc));
    804                 rcRet = -EPROTO;
    805                 goto fail1;
    806         }
    807 
    808         vrc = VbglR0QueryHostFeatures(&g_fHostFeatures);
    809         if (RT_FAILURE(vrc))
    810         {
    811                 LogRelFunc(("VbglR0QueryHostFeatures failed: vrc=%Rrc (ignored)\n", vrc));
    812                 g_fHostFeatures = 0;
    813         }
    814         LogRelFunc(("g_fHostFeatures=%#x\n", g_fHostFeatures));
    815 
    816         vrc = VbglR0SfSetUtf8(&client_handle);
    817         if (RT_FAILURE(vrc)) {
    818                 LogRelFunc(("VbglR0SfSetUtf8 failed, vrc=%Rrc\n", vrc));
    819                 rcRet = -EPROTO;
    820                 goto fail2;
    821         }
     770    int vrc;
     771    int rcRet = 0;
     772    int err;
     773
     774    TRACE();
     775
     776    if (sizeof(struct vbsf_mount_info_new) > PAGE_SIZE) {
     777        printk(KERN_ERR
     778               "Mount information structure is too large %lu\n"
     779               "Must be less than or equal to %lu\n",
     780               (unsigned long)sizeof(struct vbsf_mount_info_new),
     781               (unsigned long)PAGE_SIZE);
     782        return -EINVAL;
     783    }
     784
     785    /** @todo Init order is wrong, file system reigstration is the very last
     786    *        thing we should do. */
     787    spin_lock_init(&g_SfHandleLock);
     788    err = register_filesystem(&vboxsf_fs_type);
     789    if (err) {
     790        LogFunc(("register_filesystem err=%d\n", err));
     791        return err;
     792    }
     793
     794    vrc = VbglR0SfInit();
     795    if (RT_FAILURE(vrc)) {
     796        LogRelFunc(("VbglR0SfInit failed, vrc=%Rrc\n", vrc));
     797        rcRet = -EPROTO;
     798        goto fail0;
     799    }
     800
     801    vrc = VbglR0SfConnect(&client_handle);
     802    g_SfClient = client_handle; /* temporary */
     803    if (RT_FAILURE(vrc)) {
     804        LogRelFunc(("VbglR0SfConnect failed, vrc=%Rrc\n", vrc));
     805        rcRet = -EPROTO;
     806        goto fail1;
     807    }
     808
     809    vrc = VbglR0QueryHostFeatures(&g_fHostFeatures);
     810    if (RT_FAILURE(vrc))
     811    {
     812        LogRelFunc(("VbglR0QueryHostFeatures failed: vrc=%Rrc (ignored)\n", vrc));
     813        g_fHostFeatures = 0;
     814    }
     815    LogRelFunc(("g_fHostFeatures=%#x\n", g_fHostFeatures));
     816
     817    vrc = VbglR0SfSetUtf8(&client_handle);
     818    if (RT_FAILURE(vrc)) {
     819        LogRelFunc(("VbglR0SfSetUtf8 failed, vrc=%Rrc\n", vrc));
     820        rcRet = -EPROTO;
     821        goto fail2;
     822    }
    822823#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
    823         if (!g_fFollowSymlinks) {
    824                 vrc = VbglR0SfSetSymlinks(&client_handle);
    825                 if (RT_FAILURE(vrc)) {
    826                         printk(KERN_WARNING
    827                                "vboxsf: Host unable to show symlinks, vrc=%d\n",
    828                                vrc);
    829                 }
    830         }
    831 #endif
    832 
    833         printk(KERN_DEBUG
    834                "vboxsf: Successfully loaded version " VBOX_VERSION_STRING
    835                " (interface " RT_XSTR(VMMDEV_VERSION) ")\n");
    836 
    837         return 0;
     824    if (!g_fFollowSymlinks) {
     825        vrc = VbglR0SfSetSymlinks(&client_handle);
     826        if (RT_FAILURE(vrc)) {
     827            printk(KERN_WARNING
     828                   "vboxsf: Host unable to show symlinks, vrc=%d\n",
     829                   vrc);
     830        }
     831    }
     832#endif
     833
     834    printk(KERN_DEBUG
     835           "vboxsf: Successfully loaded version " VBOX_VERSION_STRING
     836           " (interface " RT_XSTR(VMMDEV_VERSION) ")\n");
     837
     838    return 0;
    838839
    839840 fail2:
    840         VbglR0SfDisconnect(&client_handle);
    841         g_SfClient = client_handle; /* temporary */
     841    VbglR0SfDisconnect(&client_handle);
     842    g_SfClient = client_handle; /* temporary */
    842843
    843844 fail1:
    844         VbglR0SfTerm();
     845    VbglR0SfTerm();
    845846
    846847 fail0:
    847         unregister_filesystem(&vboxsf_fs_type);
    848         return rcRet;
     848    unregister_filesystem(&vboxsf_fs_type);
     849    return rcRet;
    849850}
    850851
    851852static void __exit fini(void)
    852853{
    853         TRACE();
    854 
    855         VbglR0SfDisconnect(&client_handle);
    856         g_SfClient = client_handle; /* temporary */
    857         VbglR0SfTerm();
    858         unregister_filesystem(&vboxsf_fs_type);
     854    TRACE();
     855
     856    VbglR0SfDisconnect(&client_handle);
     857    g_SfClient = client_handle; /* temporary */
     858    VbglR0SfTerm();
     859    unregister_filesystem(&vboxsf_fs_type);
    859860}
    860861
     
    866867module_param_named(follow_symlinks, g_fFollowSymlinks, int, 0);
    867868MODULE_PARM_DESC(follow_symlinks,
    868                 "Let host resolve symlinks rather than showing them");
     869        "Let host resolve symlinks rather than showing them");
    869870#endif
    870871
  • trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.h

    r77524 r77526  
    6363DECLINLINE(loff_t) i_size_read(struct inode *pInode)
    6464{
    65         AssertCompile(sizeof(loff_t) == sizeof(uint64_t));
    66         return ASMAtomicReadU64((uint64_t volatile *)&pInode->i_size);
     65    AssertCompile(sizeof(loff_t) == sizeof(uint64_t));
     66    return ASMAtomicReadU64((uint64_t volatile *)&pInode->i_size);
    6767}
    6868
    6969DECLINLINE(void) i_size_write(struct inode *pInode, loff_t cbNew)
    7070{
    71         AssertCompile(sizeof(pInode->i_size) == sizeof(uint64_t));
    72         ASMAtomicWriteU64((uint64_t volatile *)&pInode->i_size, cbNew);
     71    AssertCompile(sizeof(pInode->i_size) == sizeof(uint64_t));
     72    ASMAtomicWriteU64((uint64_t volatile *)&pInode->i_size, cbNew);
    7373}
    7474
     
    7878DECLINLINE(void) set_nlink(struct inode *pInode, unsigned int cLinks)
    7979{
    80         pInode->i_nlink = cLinks;
     80    pInode->i_nlink = cLinks;
    8181}
    8282#endif
     
    8989 */
    9090struct vbsf_super_info {
    91         VBGLSFMAP map;
    92         struct nls_table *nls;
    93         /** time-to-live value for direntry and inode info in jiffies.
    94         * Zero == disabled. */
    95         unsigned long ttl;
    96         /** The mount option value for /proc/mounts. */
    97         int ttl_msec;
    98         int uid;
    99         int gid;
    100         int dmode;
    101         int fmode;
    102         int dmask;
    103         int fmask;
    104         /** Maximum number of pages to allow in an I/O buffer with the host.
    105         * This applies to read and write operations.  */
    106         uint32_t cMaxIoPages;
    107         /** Mount tag for VBoxService automounter.  @since 6.0 */
    108         char tag[32];
     91    VBGLSFMAP map;
     92    struct nls_table *nls;
     93    /** time-to-live value for direntry and inode info in jiffies.
     94    * Zero == disabled. */
     95    unsigned long ttl;
     96    /** The mount option value for /proc/mounts. */
     97    int ttl_msec;
     98    int uid;
     99    int gid;
     100    int dmode;
     101    int fmode;
     102    int dmask;
     103    int fmask;
     104    /** Maximum number of pages to allow in an I/O buffer with the host.
     105    * This applies to read and write operations.  */
     106    uint32_t cMaxIoPages;
     107    /** Mount tag for VBoxService automounter.  @since 6.0 */
     108    char tag[32];
    109109#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
    110         /** The backing device info structure. */
    111         struct backing_dev_info bdi;
     110    /** The backing device info structure. */
     111    struct backing_dev_info bdi;
    112112#endif
    113113};
     
    131131 */
    132132struct sf_handle {
    133         /** List entry (head sf_inode_info::HandleList). */
    134         RTLISTNODE              Entry;
    135         /** Host file/whatever handle. */
    136         SHFLHANDLE              hHost;
    137         /** SF_HANDLE_F_XXX */
    138         uint32_t                fFlags;
    139         /** Reference counter.
    140         * Close the handle and free the structure when it reaches zero. */
    141         uint32_t volatile       cRefs;
     133    /** List entry (head sf_inode_info::HandleList). */
     134    RTLISTNODE              Entry;
     135    /** Host file/whatever handle. */
     136    SHFLHANDLE              hHost;
     137    /** SF_HANDLE_F_XXX */
     138    uint32_t                fFlags;
     139    /** Reference counter.
     140    * Close the handle and free the structure when it reaches zero. */
     141    uint32_t volatile       cRefs;
    142142#ifdef VBOX_STRICT
    143         /** For strictness checks. */
    144         struct sf_inode_info   *pInodeInfo;
     143    /** For strictness checks. */
     144    struct sf_inode_info   *pInodeInfo;
    145145#endif
    146146};
     
    154154#define SF_HANDLE_F_ON_LIST     UINT32_C(0x00000080)
    155155#define SF_HANDLE_F_MAGIC_MASK  UINT32_C(0xffffff00)
    156 #define SF_HANDLE_F_MAGIC       UINT32_C(0x75030700) /**< Maurice Ravel (1875-03-07). */
     156#define SF_HANDLE_F_MAGIC       UINT32_C(0x75030700) /**< Maurice Ravel (1875-03-07). */
    157157#define SF_HANDLE_F_MAGIC_DEAD  UINT32_C(0x19371228)
    158158/** @} */
     
    162162 */
    163163struct sf_inode_info {
    164         /** Which file */
    165         SHFLSTRING *path;
    166         /** Some information was changed, update data on next revalidate */
    167         bool force_restat;
    168         /** directory content changed, update the whole directory on next sf_getdent */
    169         bool force_reread;
    170         /** The timestamp (jiffies) where the inode info was last updated. */
    171         unsigned long           ts_up_to_date;
    172         /** The birth time. */
    173         RTTIMESPEC              BirthTime;
    174 
    175         /** handle valid if a file was created with sf_create_aux until it will
    176         * be opened with sf_reg_open()
    177         * @todo r=bird: figure this one out...  */
    178         SHFLHANDLE handle;
    179 
    180         /** List of open handles (struct sf_handle), protected by g_SfHandleLock. */
    181         RTLISTANCHOR            HandleList;
     164    /** Which file */
     165    SHFLSTRING *path;
     166    /** Some information was changed, update data on next revalidate */
     167    bool force_restat;
     168    /** directory content changed, update the whole directory on next sf_getdent */
     169    bool force_reread;
     170    /** The timestamp (jiffies) where the inode info was last updated. */
     171    unsigned long           ts_up_to_date;
     172    /** The birth time. */
     173    RTTIMESPEC              BirthTime;
     174
     175    /** handle valid if a file was created with sf_create_aux until it will
     176    * be opened with sf_reg_open()
     177    * @todo r=bird: figure this one out...  */
     178    SHFLHANDLE handle;
     179
     180    /** List of open handles (struct sf_handle), protected by g_SfHandleLock. */
     181    RTLISTANCHOR            HandleList;
    182182#ifdef VBOX_STRICT
    183         uint32_t                u32Magic;
     183    uint32_t                u32Magic;
    184184# define SF_INODE_INFO_MAGIC            UINT32_C(0x18620822) /**< Claude Debussy */
    185185# define SF_INODE_INFO_MAGIC_DEAD       UINT32_C(0x19180325)
     
    188188
    189189struct sf_dir_info {
    190         /** @todo sf_handle. */
    191         struct list_head info_list;
     190    /** @todo sf_handle. */
     191    struct list_head info_list;
    192192};
    193193
    194194struct sf_dir_buf {
    195         size_t cEntries;
    196         size_t cbFree;
    197         size_t cbUsed;
    198         void *buf;
    199         struct list_head head;
     195    size_t cEntries;
     196    size_t cbFree;
     197    size_t cbUsed;
     198    void *buf;
     199    struct list_head head;
    200200};
    201201
     
    204204 */
    205205struct sf_reg_info {
    206         /** Handle tracking structure. */
    207         struct sf_handle        Handle;
     206    /** Handle tracking structure. */
     207    struct sf_handle        Handle;
    208208};
    209209
     
    235235 * Increase the time-to-live of @a pDirEntry and all ancestors.
    236236 * @param   pDirEntry           The directory entry cache entry which ancestors
    237  *                              we should increase the TTL for.
     237 *                  we should increase the TTL for.
    238238 */
    239239DECLINLINE(void) sf_dentry_chain_increase_ttl(struct dentry *pDirEntry)
    240240{
    241241#ifdef VBOX_STRICT
    242         struct super_block * const pSuper = pDirEntry->d_sb;
    243 #endif
    244         unsigned long const        uToSet = jiffies;
    245         do {
    246                 Assert(pDirEntry->d_sb == pSuper);
    247                 sf_dentry_set_update_jiffies(pDirEntry, uToSet);
    248                 pDirEntry = pDirEntry->d_parent;
    249         } while (!IS_ROOT(pDirEntry));
     242    struct super_block * const pSuper = pDirEntry->d_sb;
     243#endif
     244    unsigned long const        uToSet = jiffies;
     245    do {
     246        Assert(pDirEntry->d_sb == pSuper);
     247        sf_dentry_set_update_jiffies(pDirEntry, uToSet);
     248        pDirEntry = pDirEntry->d_parent;
     249    } while (!IS_ROOT(pDirEntry));
    250250}
    251251
     
    253253 * Increase the time-to-live of all ancestors.
    254254 * @param   pDirEntry           The directory entry cache entry which ancestors
    255  *                              we should increase the TTL for.
     255 *                  we should increase the TTL for.
    256256 */
    257257DECLINLINE(void) sf_dentry_chain_increase_parent_ttl(struct dentry *pDirEntry)
    258258{
    259         Assert(!pDirEntry->d_parent || pDirEntry->d_parent->d_sb == pDirEntry->d_sb);
    260         pDirEntry = pDirEntry->d_parent;
    261         if (pDirEntry)
    262             sf_dentry_chain_increase_ttl(pDirEntry);
     259    Assert(!pDirEntry->d_parent || pDirEntry->d_parent->d_sb == pDirEntry->d_sb);
     260    pDirEntry = pDirEntry->d_parent;
     261    if (pDirEntry)
     262        sf_dentry_chain_increase_ttl(pDirEntry);
    263263}
    264264
     
    289289 * @param   pHandle         The handle to release.
    290290 * @param   sf_g            The info structure for the shared folder associated
    291  *                          with the handle.
     291 *                  with the handle.
    292292 * @param   pszCaller       The caller name (for logging failures).
    293293 */
    294294DECLINLINE(uint32_t) sf_handle_release(struct sf_handle *pHandle, struct vbsf_super_info *sf_g, const char *pszCaller)
    295295{
    296         uint32_t cRefs;
    297 
    298         Assert((pHandle->fFlags & SF_HANDLE_F_MAGIC_MASK) == SF_HANDLE_F_MAGIC);
    299         Assert(pHandle->pInodeInfo);
    300         Assert(pHandle->pInodeInfo && pHandle->pInodeInfo->u32Magic == SF_INODE_INFO_MAGIC);
    301 
    302         cRefs = ASMAtomicDecU32(&pHandle->cRefs);
    303         Assert(cRefs < _64M);
    304         if (cRefs)
    305                 return cRefs;
    306         return sf_handle_release_slow(pHandle, sf_g, pszCaller);
     296    uint32_t cRefs;
     297
     298    Assert((pHandle->fFlags & SF_HANDLE_F_MAGIC_MASK) == SF_HANDLE_F_MAGIC);
     299    Assert(pHandle->pInodeInfo);
     300    Assert(pHandle->pInodeInfo && pHandle->pInodeInfo->u32Magic == SF_INODE_INFO_MAGIC);
     301
     302    cRefs = ASMAtomicDecU32(&pHandle->cRefs);
     303    Assert(cRefs < _64M);
     304    if (cRefs)
     305        return cRefs;
     306    return sf_handle_release_slow(pHandle, sf_g, pszCaller);
    307307}
    308308
    309309extern void sf_init_inode(struct inode *inode, struct sf_inode_info *sf_i, PSHFLFSOBJINFO info, struct vbsf_super_info *sf_g);
    310310extern int sf_stat(const char *caller, struct vbsf_super_info *sf_g,
    311                    SHFLSTRING * path, PSHFLFSOBJINFO result, int ok_to_fail);
     311           SHFLSTRING * path, PSHFLFSOBJINFO result, int ok_to_fail);
    312312extern int sf_inode_revalidate(struct dentry *dentry);
    313313extern int sf_inode_revalidate_worker(struct dentry *dentry, bool fForced);
     
    316316# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
    317317extern int sf_getattr(const struct path *path, struct kstat *kstat,
    318                       u32 request_mask, unsigned int query_flags);
     318              u32 request_mask, unsigned int query_flags);
    319319# else
    320320extern int sf_getattr(struct vfsmount *mnt, struct dentry *dentry,
    321                       struct kstat *kstat);
     321              struct kstat *kstat);
    322322# endif
    323323extern int sf_setattr(struct dentry *dentry, struct iattr *iattr);
    324324#endif
    325325extern int sf_path_from_dentry(const char *caller, struct vbsf_super_info *sf_g,
    326                                struct sf_inode_info *sf_i,
    327                                struct dentry *dentry, SHFLSTRING ** result);
     326                   struct sf_inode_info *sf_i,
     327                   struct dentry *dentry, SHFLSTRING ** result);
    328328extern int sf_nlscpy(struct vbsf_super_info *sf_g, char *name,
    329                      size_t name_bound_len, const unsigned char *utf8_name,
    330                      size_t utf8_len);
     329             size_t name_bound_len, const unsigned char *utf8_name,
     330             size_t utf8_len);
    331331extern void sf_dir_info_free(struct sf_dir_info *p);
    332332extern void sf_dir_info_empty(struct sf_dir_info *p);
    333333extern struct sf_dir_info *sf_dir_info_alloc(void);
    334334extern int sf_dir_read_all(struct vbsf_super_info *sf_g,
    335                            struct sf_inode_info *sf_i, struct sf_dir_info *sf_d,
    336                            SHFLHANDLE handle);
     335               struct sf_inode_info *sf_i, struct sf_dir_info *sf_d,
     336               SHFLHANDLE handle);
    337337
    338338#ifdef __cplusplus
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