VirtualBox

Changeset 87014 in vbox for trunk/src/VBox/Additions/linux


Ignore:
Timestamp:
Nov 27, 2020 9:18:18 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
141587
Message:

linux/vboxsf: Add support for parsing string-based mount options using the Linux Filesystem Mount API aka fs_context (kernel versions >= 5.1.0) bugref:9816

File:
1 edited

Legend:

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

    r86897 r87014  
    5858#include <VBox/err.h>
    5959#include <iprt/path.h>
     60#if RTLNX_VER_MIN(5,1,0)
     61# include <linux/fs_context.h>
     62# include <linux/fs_parser.h>
     63#endif
    6064
    6165
     
    216220    *sf_gp = NULL; /* (old gcc maybe used initialized) */
    217221
     222#if RTLNX_VER_MAX(5,1,0)
    218223    /*
    219224     * Validate info.
     
    227232        return -EINVAL;
    228233    }
     234#endif
    229235    name_len = RTStrNLen(info->name, sizeof(info->name));
    230236    if (name_len >= sizeof(info->name)) {
     
    545551
    546552/**
    547  * This is called by vbsf_read_super_24() and vbsf_read_super_26() when vfs mounts
    548  * the fs and wants to read super_block.
     553 * This is called by vbsf_read_super_24(), vbsf_read_super_26(), and
     554 * vbsf_get_tree() when vfs mounts the fs and wants to read the super_block.
    549555 *
    550556 * Calls vbsf_super_info_alloc_and_map_it() to map the folder and allocate super
     
    555561 * Should respect @a flags.
    556562 */
     563#if RTLNX_VER_MIN(5,1,0)
     564static int vbsf_read_super_aux(struct super_block *sb, struct fs_context *fc)
     565#else
    557566static int vbsf_read_super_aux(struct super_block *sb, void *data, int flags)
     567#endif
    558568{
    559569    int rc;
     
    561571
    562572    TRACE();
     573#if RTLNX_VER_MAX(5,1,0)
    563574    if (!data) {
    564575        SFLOGRELBOTH(("vboxsf: No mount data. Is mount.vboxsf installed (typically in /sbin)?\n"));
     
    570581        return -ENOSYS;
    571582    }
     583#endif
    572584
    573585    /*
    574586     * Create our super info structure and map the shared folder.
    575587     */
     588#if RTLNX_VER_MIN(5,1,0)
     589    struct vbsf_mount_info_new *info = fc->fs_private;
     590    rc = vbsf_super_info_alloc_and_map_it(info, &pSuperInfo);
     591#else
    576592    rc = vbsf_super_info_alloc_and_map_it((struct vbsf_mount_info_new *)data, &pSuperInfo);
     593#endif
    577594    if (rc == 0) {
    578595        /*
     
    744761}
    745762
     763#if RTLNX_VER_MIN(5,1,0)
     764static int vbsf_remount_fs(struct super_block *sb,
     765                           struct vbsf_mount_info_new *info)
     766#else
    746767static int vbsf_remount_fs(struct super_block *sb, int *flags, char *data)
     768#endif
    747769{
    748770#if RTLNX_VER_MIN(2,4,23)
    749     struct vbsf_super_info *pSuperInfo = pSuperInfo = VBSF_GET_SUPER_INFO(sb);
     771    struct vbsf_super_info *pSuperInfo = VBSF_GET_SUPER_INFO(sb);
    750772    struct vbsf_inode_info *sf_i;
    751773    struct inode *iroot;
     
    754776    Assert(pSuperInfo);
    755777
     778# if RTLNX_VER_MIN(5,1,0)
     779    vbsf_super_info_copy_remount_options(pSuperInfo, info);
     780# else
    756781    if (data && data[0] != 0) {
    757782        struct vbsf_mount_info_new *info = (struct vbsf_mount_info_new *)data;
     
    763788        }
    764789    }
     790# endif
    765791
    766792    /* '.' and '..' entries are st_ino == 0 so root is #1 */
     
    856882    .put_super    = vbsf_put_super,
    857883    .statfs       = vbsf_statfs,
     884#if RTLNX_VER_MAX(5,1,0)
    858885    .remount_fs   = vbsf_remount_fs,
     886#endif
    859887    .show_options = vbsf_show_options
    860888};
     
    866894*********************************************************************************************************************************/
    867895
    868 #if RTLNX_VER_MIN(2,5,4)
     896#if RTLNX_VER_RANGE(2,5,4,  5,1,0)
    869897
    870898static int vbsf_read_super_26(struct super_block *sb, void *data, int flags)
     
    879907    return err;
    880908}
    881 
    882 # if RTLNX_VER_MIN(2,6,39)
     909#endif
     910
     911#if RTLNX_VER_RANGE(2,6,39,  5,1,0)
    883912static struct dentry *sf_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
    884913{
     
    886915    return mount_nodev(fs_type, flags, data, vbsf_read_super_26);
    887916}
    888 # elif RTLNX_VER_MIN(2,6,18)
     917#elif RTLNX_VER_RANGE(2,6,18,  2,6,39)
    889918static int vbsf_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt)
    890919{
     
    892921    return get_sb_nodev(fs_type, flags, data, vbsf_read_super_26, mnt);
    893922}
    894 # else /* < 2.6.18 */
     923#elif RTLNX_VER_MAX(2,6,18) /* < 2.6.18 */
    895924static struct super_block *vbsf_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
    896925{
     
    898927    return get_sb_nodev(fs_type, flags, data, vbsf_read_super_26);
    899928}
     929#endif
     930
     931#if RTLNX_VER_MAX(2,5,4)  /* < 2.5.4 */
     932
     933static struct super_block *vbsf_read_super_24(struct super_block *sb, void *data, int flags)
     934{
     935    int err;
     936
     937    TRACE();
     938    err = vbsf_read_super_aux(sb, data, flags);
     939    if (err) {
     940        printk(KERN_DEBUG "vbsf_read_super_aux err=%d\n", err);
     941        return NULL;
     942    }
     943
     944    return sb;
     945}
     946
     947static DECLARE_FSTYPE(g_vboxsf_fs_type, "vboxsf", vbsf_read_super_24, 0);
     948
     949#endif /* < 2.5.4 */
     950
     951#if RTLNX_VER_MIN(5,1,0)
     952
     953/**
     954 * The following section of code uses the Linux filesystem mount API (also
     955 * known as the "filesystem context API") to parse string-based mount options.
     956 * The API is described here:
     957 * https://www.kernel.org/doc/Documentation/filesystems/mount_api.txt
     958 */
     959enum vbsf_cache_modes {
     960    VBSF_CACHE_DEFAULT,
     961    VBSF_CACHE_NONE,
     962    VBSF_CACHE_STRICT,
     963    VBSF_CACHE_READ,
     964    VBSF_CACHE_RW
     965};
     966
     967static const struct constant_table vbsf_param_cache_mode[] = {
     968        { "default",      VBSF_CACHE_DEFAULT },
     969        { "none",         VBSF_CACHE_NONE },
     970        { "strict",       VBSF_CACHE_STRICT },
     971        { "read",         VBSF_CACHE_READ },
     972        { "readwrite",    VBSF_CACHE_RW },
     973        {}
     974};
     975
     976enum {
     977    Opt_iocharset,  /* nls_name[] */
     978    Opt_nls,        /* alias for iocharset */
     979    Opt_uid,
     980    Opt_gid,
     981    Opt_ttl,
     982    Opt_dmode,
     983    Opt_fmode,
     984    Opt_dmask,
     985    Opt_fmask,
     986    Opt_umask,
     987    Opt_maxiopages,
     988    Opt_dirbuf,
     989    Opt_dcachettl,
     990    Opt_inodettl,
     991    Opt_cachemode,  /* enum vbsf_cache_mode */
     992    Opt_tag
     993};
     994
     995# if RTLNX_VER_MAX(5,6,0)
     996static const struct fs_parameter_spec vbsf_fs_specs[] = {
     997# else
     998static const struct fs_parameter_spec vbsf_fs_parameters[] = {
    900999# endif
    901 
     1000    fsparam_string("iocharset",   Opt_iocharset),
     1001    fsparam_string("nls",         Opt_nls),
     1002    fsparam_u32   ("uid",         Opt_uid),
     1003    fsparam_u32   ("gid",         Opt_gid),
     1004    fsparam_u32   ("ttl",         Opt_ttl),
     1005    fsparam_u32oct("dmode",       Opt_dmode),
     1006    fsparam_u32oct("fmode",       Opt_fmode),
     1007    fsparam_u32oct("dmask",       Opt_dmask),
     1008    fsparam_u32oct("fmask",       Opt_fmask),
     1009    fsparam_u32oct("umask",       Opt_umask),
     1010    fsparam_u32   ("maxiopages",  Opt_maxiopages),
     1011    fsparam_u32   ("dirbuf",      Opt_dirbuf),
     1012    fsparam_u32   ("dcachettl",   Opt_dcachettl),
     1013    fsparam_u32   ("inodettl",    Opt_inodettl),
     1014# if RTLNX_VER_MAX(5,6,0)
     1015    fsparam_enum  ("cache",       Opt_cachemode),
     1016# else
     1017    fsparam_enum  ("cache",       Opt_cachemode, vbsf_param_cache_mode),
     1018# endif
     1019    fsparam_string("tag",         Opt_tag),
     1020    {}
     1021};
     1022
     1023# if RTLNX_VER_MAX(5,6,0)
     1024static const struct fs_parameter_enum vbsf_fs_enums[] = {
     1025    { Opt_cachemode,    "default",      VBSF_CACHE_DEFAULT },
     1026    { Opt_cachemode,    "none",         VBSF_CACHE_NONE },
     1027    { Opt_cachemode,    "strict",       VBSF_CACHE_STRICT },
     1028    { Opt_cachemode,    "read",         VBSF_CACHE_READ },
     1029    { Opt_cachemode,    "readwrite",    VBSF_CACHE_RW },
     1030    {}
     1031};
     1032
     1033static const struct fs_parameter_description vbsf_fs_parameters = {
     1034    .name       = "vboxsf",
     1035    .specs      = vbsf_fs_specs,
     1036    .enums      = vbsf_fs_enums
     1037};
     1038# endif
     1039
     1040/**
     1041 * Parse the (string-based) mount options passed in as -o foo,bar=123,etc.
     1042 */
     1043static int vbsf_parse_param(struct fs_context *fc, struct fs_parameter *param)
     1044{
     1045    struct fs_parse_result result;
     1046    struct vbsf_mount_info_new *info = fc->fs_private;
     1047    int opt;
     1048
     1049# if RTLNX_VER_MAX(5,6,0)
     1050    opt = fs_parse(fc, &vbsf_fs_parameters, param, &result);
     1051# else
     1052    opt = fs_parse(fc, vbsf_fs_parameters, param, &result);
     1053# endif
     1054    if (opt < 0)
     1055        return opt;
     1056
     1057    switch (opt) {
     1058    case Opt_iocharset:
     1059    case Opt_nls:
     1060        strlcpy(info->nls_name, param->string, sizeof(info->nls_name));
     1061        break;
     1062    case Opt_uid:
     1063        info->uid = result.uint_32;
     1064        break;
     1065    case Opt_gid:
     1066        info->gid = result.uint_32;
     1067        break;
     1068    case Opt_ttl:
     1069        info->ttl = result.uint_32;
     1070        break;
     1071    case Opt_dmode:
     1072        if (result.uint_32 & ~0777)
     1073            return invalf(fc, "Invalid dmode specified: '%o'", result.uint_32);
     1074        info->dmode = result.uint_32;
     1075        break;
     1076    case Opt_fmode:
     1077        if (result.uint_32 & ~0777)
     1078            return invalf(fc, "Invalid fmode specified: '%o'", result.uint_32);
     1079        info->fmode = result.uint_32;
     1080        break;
     1081    case Opt_dmask:
     1082        if (result.uint_32 & ~07777)
     1083            return invalf(fc, "Invalid dmask specified: '%o'", result.uint_32);
     1084        info->dmask = result.uint_32;
     1085        break;
     1086    case Opt_fmask:
     1087        if (result.uint_32 & ~07777)
     1088            return invalf(fc, "Invalid fmask specified: '%o'", result.uint_32);
     1089        info->fmask = result.uint_32;
     1090        break;
     1091    case Opt_umask:
     1092        if (result.uint_32 & ~07777)
     1093            return invalf(fc, "Invalid umask specified: '%o'", result.uint_32);
     1094        info->dmask = info->fmask = result.uint_32;
     1095        break;
     1096    case Opt_maxiopages:
     1097        info->cMaxIoPages = result.uint_32;
     1098        break;
     1099    case Opt_dirbuf:
     1100        info->cbDirBuf = result.uint_32;
     1101        break;
     1102    case Opt_dcachettl:
     1103        info->msDirCacheTTL = result.uint_32;
     1104        break;
     1105    case Opt_inodettl:
     1106        info->msInodeTTL = result.uint_32;
     1107        break;
     1108    case Opt_cachemode:
     1109        if (result.uint_32 == VBSF_CACHE_DEFAULT || result.uint_32 == VBSF_CACHE_STRICT)
     1110            info->enmCacheMode = kVbsfCacheMode_Strict;
     1111        else if (result.uint_32 == VBSF_CACHE_NONE)
     1112            info->enmCacheMode = kVbsfCacheMode_None;
     1113        else if (result.uint_32 == VBSF_CACHE_READ)
     1114            info->enmCacheMode = kVbsfCacheMode_Read;
     1115        else if (result.uint_32 == VBSF_CACHE_RW)
     1116            info->enmCacheMode = kVbsfCacheMode_ReadWrite;
     1117        else
     1118            printk(KERN_WARNING "vboxsf: cache mode (%u) is out of range, using default instead.\n", result.uint_32);
     1119        break;
     1120    case Opt_tag:
     1121        strlcpy(info->szTag, param->string, sizeof(info->szTag));
     1122        break;
     1123    default:
     1124        return invalf(fc, "Invalid mount option: '%s'", param->key);
     1125    }
     1126
     1127    return 0;
     1128}
     1129
     1130/**
     1131 * Parse the mount options provided whether by the mount.vboxsf utility
     1132 * which supplies the mount information as a page of data or else as a
     1133 * string in the following format: key[=val][,key[=val]]*.
     1134 */
     1135static int vbsf_parse_monolithic(struct fs_context *fc, void *data)
     1136{
     1137    struct vbsf_mount_info_new *info = fc->fs_private;
     1138
     1139    if (data) {
     1140        struct vbsf_mount_info_new *mount_opts =
     1141            (struct vbsf_mount_info_new *)data;
     1142        if (mount_opts->nullchar == '\0'
     1143            && mount_opts->signature[0] == VBSF_MOUNT_SIGNATURE_BYTE_0
     1144            && mount_opts->signature[1] == VBSF_MOUNT_SIGNATURE_BYTE_1
     1145            && mount_opts->signature[2] == VBSF_MOUNT_SIGNATURE_BYTE_2) {
     1146            memcpy(info, mount_opts, sizeof(struct vbsf_mount_info_new));
     1147        } else {
     1148            /* this will call vbsf_parse_param() */
     1149            return generic_parse_monolithic(fc, data);
     1150        }
     1151    }
     1152
     1153    return 0;
     1154}
     1155
     1156/**
     1157 * Clean up the filesystem-specific part of the filesystem context.
     1158 */
     1159static void vbsf_free_ctx(struct fs_context *fc)
     1160{
     1161    struct vbsf_mount_info_new *info = fc->fs_private;
     1162
     1163    if (info) {
     1164        kfree(info);
     1165        fc->fs_private = NULL;
     1166    }
     1167}
     1168
     1169/**
     1170 * Create the mountable root and superblock which can then be used later for
     1171 * mounting the shared folder.  The superblock is populated by
     1172 * vbsf_read_super_aux() which also sets up the shared folder mapping and the
     1173 * related paperwork in preparation for mounting the shared folder.
     1174 */
     1175static int vbsf_get_tree(struct fs_context *fc)
     1176{
     1177    struct vbsf_mount_info_new *info = fc->fs_private;
     1178
     1179    if (!fc->source) {
     1180        SFLOGRELBOTH(("vboxsf: No shared folder specified\n"));
     1181        return invalf(fc, "vboxsf: No shared folder specified");
     1182    }
     1183
     1184    /* fc->source (the shared folder name) is set after vbsf_init_fs_ctx() */
     1185    strlcpy(info->name, fc->source, sizeof(info->name));
     1186
     1187# if RTLNX_VER_MAX(5,3,0)
     1188    return vfs_get_super(fc, vfs_get_independent_super, vbsf_read_super_aux);
     1189# else
     1190    return get_tree_nodev(fc, vbsf_read_super_aux);
     1191# endif
     1192}
     1193
     1194/**
     1195 * Reconfigures the superblock based on the mount information stored in the
     1196 * filesystem context.  Called via '-o remount' (aka mount(2) with MS_REMOUNT)
     1197 * and is the equivalent of .fs_remount.
     1198 */
     1199static int vbsf_reconfigure(struct fs_context *fc)
     1200{
     1201    struct vbsf_mount_info_new *info = fc->fs_private;
     1202    struct super_block *sb = fc->root->d_sb;
     1203
     1204    return vbsf_remount_fs(sb, info);
     1205}
     1206
     1207static const struct fs_context_operations vbsf_context_ops = {
     1208    .parse_param         = vbsf_parse_param,
     1209    .parse_monolithic    = vbsf_parse_monolithic,
     1210    .free                = vbsf_free_ctx,
     1211    .get_tree            = vbsf_get_tree,
     1212    .reconfigure         = vbsf_reconfigure
     1213};
     1214
     1215/**
     1216 * Set up the filesystem mount context.
     1217 */
     1218static int vbsf_init_fs_context(struct fs_context *fc)
     1219{
     1220    struct vbsf_mount_info_new *info = fc->fs_private;
     1221
     1222    info = kzalloc(sizeof(*info), GFP_KERNEL);
     1223    if (!info) {
     1224        SFLOGRELBOTH(("vboxsf: Could not allocate memory for mount options\n"));
     1225        return -ENOMEM;
     1226    }
     1227
     1228    /* set default values for the mount information structure */
     1229    info->ttl = info->msDirCacheTTL = info->msInodeTTL = -1;
     1230    info->dmode = info->fmode = ~0U;
     1231    info->enmCacheMode = kVbsfCacheMode_Strict;
     1232    info->length = sizeof(struct vbsf_mount_info_new);
     1233
     1234    fc->fs_private = info;
     1235    fc->ops = &vbsf_context_ops;
     1236
     1237    return 0;
     1238}
     1239#endif /* >= 5.1.0 */
     1240
     1241
     1242#if RTLNX_VER_MIN(2,5,4)
    9021243/**
    9031244 * File system registration structure.
     
    9061247    .owner = THIS_MODULE,
    9071248    .name = "vboxsf",
    908 # if RTLNX_VER_MIN(2,6,39)
     1249# if RTLNX_VER_MIN(5,1,0)
     1250    .init_fs_context = vbsf_init_fs_context,
     1251#  if RTLNX_VER_MAX(5,6,0)
     1252    .parameters = &vbsf_fs_parameters,
     1253#  else
     1254    .parameters = vbsf_fs_parameters,
     1255#  endif
     1256# elif RTLNX_VER_MIN(2,6,39)
    9091257    .mount = sf_mount,
    9101258# else
     
    9131261    .kill_sb = kill_anon_super
    9141262};
    915 
    916 #else  /* < 2.5.4 */
    917 
    918 static struct super_block *vbsf_read_super_24(struct super_block *sb, void *data, int flags)
    919 {
    920     int err;
    921 
    922     TRACE();
    923     err = vbsf_read_super_aux(sb, data, flags);
    924     if (err) {
    925         printk(KERN_DEBUG "vbsf_read_super_aux err=%d\n", err);
    926         return NULL;
    927     }
    928 
    929     return sb;
    930 }
    931 
    932 static DECLARE_FSTYPE(g_vboxsf_fs_type, "vboxsf", vbsf_read_super_24, 0);
    933 
    934 #endif /* < 2.5.4 */
    935 
     1263#endif /* >= 2.5.4 */
    9361264
    9371265
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