Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'staging-5.4-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging

Pull IIO fixes and staging driver from Greg KH:
"Here is a mix of a number of IIO driver fixes for 5.4-rc7, and a whole
new staging driver.

The IIO fixes resolve some reported issues, all are tiny.

The staging driver addition is the vboxsf filesystem, which is the
VirtualBox guest shared folder code. Hans has been trying to get
filesystem reviewers to review the code for many months now, and
Christoph finally said to just merge it in staging now as it is
stand-alone and the filesystem people can review it easier over time
that way.

I know it's late for this big of an addition, but it is stand-alone.

The code has been in linux-next for a while, long enough to pick up a
few tiny fixes for it already so people are looking at it.

All of these have been in linux-next with no reported issues"

* tag 'staging-5.4-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging:
staging: Fix error return code in vboxsf_fill_super()
staging: vboxsf: fix dereference of pointer dentry before it is null checked
staging: vboxsf: Remove unused including <linux/version.h>
staging: Add VirtualBox guest shared folder (vboxsf) support
iio: adc: stm32-adc: fix stopping dma
iio: imu: inv_mpu6050: fix no data on MPU6050
iio: srf04: fix wrong limitation in distance measuring
iio: imu: adis16480: make sure provided frequency is positive

+3324 -20
+6
MAINTAINERS
··· 17339 17339 F: include/uapi/linux/vbox*.h 17340 17340 F: drivers/virt/vboxguest/ 17341 17341 17342 + VIRTUAL BOX SHARED FOLDER VFS DRIVER: 17343 + M: Hans de Goede <hdegoede@redhat.com> 17344 + L: linux-fsdevel@vger.kernel.org 17345 + S: Maintained 17346 + F: drivers/staging/vboxsf/* 17347 + 17342 17348 VIRTUAL SERIO DEVICE DRIVER 17343 17349 M: Stephen Chandler Paul <thatslyude@gmail.com> 17344 17350 S: Maintained
+2 -2
drivers/iio/adc/stm32-adc.c
··· 1399 1399 cookie = dmaengine_submit(desc); 1400 1400 ret = dma_submit_error(cookie); 1401 1401 if (ret) { 1402 - dmaengine_terminate_all(adc->dma_chan); 1402 + dmaengine_terminate_sync(adc->dma_chan); 1403 1403 return ret; 1404 1404 } 1405 1405 ··· 1477 1477 stm32_adc_conv_irq_disable(adc); 1478 1478 1479 1479 if (adc->dma_chan) 1480 - dmaengine_terminate_all(adc->dma_chan); 1480 + dmaengine_terminate_sync(adc->dma_chan); 1481 1481 1482 1482 if (stm32_adc_set_trig(indio_dev, NULL)) 1483 1483 dev_err(&indio_dev->dev, "Can't clear trigger\n");
+4 -1
drivers/iio/imu/adis16480.c
··· 317 317 struct adis16480 *st = iio_priv(indio_dev); 318 318 unsigned int t, reg; 319 319 320 + if (val < 0 || val2 < 0) 321 + return -EINVAL; 322 + 320 323 t = val * 1000 + val2 / 1000; 321 - if (t <= 0) 324 + if (t == 0) 322 325 return -EINVAL; 323 326 324 327 /*
+9
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
··· 114 114 .name = "MPU6050", 115 115 .reg = &reg_set_6050, 116 116 .config = &chip_config_6050, 117 + .fifo_size = 1024, 117 118 }, 118 119 { 119 120 .whoami = INV_MPU6500_WHOAMI_VALUE, 120 121 .name = "MPU6500", 121 122 .reg = &reg_set_6500, 122 123 .config = &chip_config_6050, 124 + .fifo_size = 512, 123 125 }, 124 126 { 125 127 .whoami = INV_MPU6515_WHOAMI_VALUE, 126 128 .name = "MPU6515", 127 129 .reg = &reg_set_6500, 128 130 .config = &chip_config_6050, 131 + .fifo_size = 512, 129 132 }, 130 133 { 131 134 .whoami = INV_MPU6000_WHOAMI_VALUE, 132 135 .name = "MPU6000", 133 136 .reg = &reg_set_6050, 134 137 .config = &chip_config_6050, 138 + .fifo_size = 1024, 135 139 }, 136 140 { 137 141 .whoami = INV_MPU9150_WHOAMI_VALUE, 138 142 .name = "MPU9150", 139 143 .reg = &reg_set_6050, 140 144 .config = &chip_config_6050, 145 + .fifo_size = 1024, 141 146 }, 142 147 { 143 148 .whoami = INV_MPU9250_WHOAMI_VALUE, 144 149 .name = "MPU9250", 145 150 .reg = &reg_set_6500, 146 151 .config = &chip_config_6050, 152 + .fifo_size = 512, 147 153 }, 148 154 { 149 155 .whoami = INV_MPU9255_WHOAMI_VALUE, 150 156 .name = "MPU9255", 151 157 .reg = &reg_set_6500, 152 158 .config = &chip_config_6050, 159 + .fifo_size = 512, 153 160 }, 154 161 { 155 162 .whoami = INV_ICM20608_WHOAMI_VALUE, 156 163 .name = "ICM20608", 157 164 .reg = &reg_set_6500, 158 165 .config = &chip_config_6050, 166 + .fifo_size = 512, 159 167 }, 160 168 { 161 169 .whoami = INV_ICM20602_WHOAMI_VALUE, 162 170 .name = "ICM20602", 163 171 .reg = &reg_set_icm20602, 164 172 .config = &chip_config_6050, 173 + .fifo_size = 1008, 165 174 }, 166 175 }; 167 176
+2
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
··· 100 100 * @name: name of the chip. 101 101 * @reg: register map of the chip. 102 102 * @config: configuration of the chip. 103 + * @fifo_size: size of the FIFO in bytes. 103 104 */ 104 105 struct inv_mpu6050_hw { 105 106 u8 whoami; 106 107 u8 *name; 107 108 const struct inv_mpu6050_reg_map *reg; 108 109 const struct inv_mpu6050_chip_config *config; 110 + size_t fifo_size; 109 111 }; 110 112 111 113 /*
+12 -3
drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
··· 180 180 "failed to ack interrupt\n"); 181 181 goto flush_fifo; 182 182 } 183 - /* handle fifo overflow by reseting fifo */ 184 - if (int_status & INV_MPU6050_BIT_FIFO_OVERFLOW_INT) 185 - goto flush_fifo; 186 183 if (!(int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT)) { 187 184 dev_warn(regmap_get_device(st->map), 188 185 "spurious interrupt with status 0x%x\n", int_status); ··· 208 211 if (result) 209 212 goto end_session; 210 213 fifo_count = get_unaligned_be16(&data[0]); 214 + 215 + /* 216 + * Handle fifo overflow by resetting fifo. 217 + * Reset if there is only 3 data set free remaining to mitigate 218 + * possible delay between reading fifo count and fifo data. 219 + */ 220 + nb = 3 * bytes_per_datum; 221 + if (fifo_count >= st->hw->fifo_size - nb) { 222 + dev_warn(regmap_get_device(st->map), "fifo overflow reset\n"); 223 + goto flush_fifo; 224 + } 225 + 211 226 /* compute and process all complete datum */ 212 227 nb = fifo_count / bytes_per_datum; 213 228 inv_mpu6050_update_period(st, pf->timestamp, nb);
+15 -14
drivers/iio/proximity/srf04.c
··· 110 110 udelay(data->cfg->trigger_pulse_us); 111 111 gpiod_set_value(data->gpiod_trig, 0); 112 112 113 - /* it cannot take more than 20 ms */ 113 + /* it should not take more than 20 ms until echo is rising */ 114 114 ret = wait_for_completion_killable_timeout(&data->rising, HZ/50); 115 115 if (ret < 0) { 116 116 mutex_unlock(&data->lock); ··· 120 120 return -ETIMEDOUT; 121 121 } 122 122 123 - ret = wait_for_completion_killable_timeout(&data->falling, HZ/50); 123 + /* it cannot take more than 50 ms until echo is falling */ 124 + ret = wait_for_completion_killable_timeout(&data->falling, HZ/20); 124 125 if (ret < 0) { 125 126 mutex_unlock(&data->lock); 126 127 return ret; ··· 136 135 137 136 dt_ns = ktime_to_ns(ktime_dt); 138 137 /* 139 - * measuring more than 3 meters is beyond the capabilities of 140 - * the sensor 138 + * measuring more than 6,45 meters is beyond the capabilities of 139 + * the supported sensors 141 140 * ==> filter out invalid results for not measuring echos of 142 141 * another us sensor 143 142 * 144 143 * formula: 145 - * distance 3 m 146 - * time = ---------- = --------- = 9404389 ns 147 - * speed 319 m/s 144 + * distance 6,45 * 2 m 145 + * time = ---------- = ------------ = 40438871 ns 146 + * speed 319 m/s 148 147 * 149 148 * using a minimum speed at -20 °C of 319 m/s 150 149 */ 151 - if (dt_ns > 9404389) 150 + if (dt_ns > 40438871) 152 151 return -EIO; 153 152 154 153 time_ns = dt_ns; ··· 160 159 * with Temp in °C 161 160 * and speed in m/s 162 161 * 163 - * use 343 m/s as ultrasonic speed at 20 °C here in absence of the 162 + * use 343,5 m/s as ultrasonic speed at 20 °C here in absence of the 164 163 * temperature 165 164 * 166 165 * therefore: 167 - * time 343 168 - * distance = ------ * ----- 169 - * 10^6 2 166 + * time 343,5 time * 106 167 + * distance = ------ * ------- = ------------ 168 + * 10^6 2 617176 170 169 * with time in ns 171 170 * and distance in mm (one way) 172 171 * 173 - * because we limit to 3 meters the multiplication with 343 just 172 + * because we limit to 6,45 meters the multiplication with 106 just 174 173 * fits into 32 bit 175 174 */ 176 - distance_mm = time_ns * 343 / 2000000; 175 + distance_mm = time_ns * 106 / 617176; 177 176 178 177 return distance_mm; 179 178 }
+2
drivers/staging/Kconfig
··· 125 125 126 126 source "drivers/staging/qlge/Kconfig" 127 127 128 + source "drivers/staging/vboxsf/Kconfig" 129 + 128 130 endif # STAGING
+1
drivers/staging/Makefile
··· 53 53 obj-$(CONFIG_USB_WUSB) += wusbcore/ 54 54 obj-$(CONFIG_EXFAT_FS) += exfat/ 55 55 obj-$(CONFIG_QLGE) += qlge/ 56 + obj-$(CONFIG_VBOXSF_FS) += vboxsf/
+10
drivers/staging/vboxsf/Kconfig
··· 1 + config VBOXSF_FS 2 + tristate "VirtualBox guest shared folder (vboxsf) support" 3 + depends on X86 && VBOXGUEST 4 + select NLS 5 + help 6 + VirtualBox hosts can share folders with guests, this driver 7 + implements the Linux-guest side of this allowing folders exported 8 + by the host to be mounted under Linux. 9 + 10 + If you want to use shared folders in VirtualBox guests, answer Y or M.
+5
drivers/staging/vboxsf/Makefile
··· 1 + # SPDX-License-Identifier: MIT 2 + 3 + obj-$(CONFIG_VBOXSF_FS) += vboxsf.o 4 + 5 + vboxsf-y := dir.o file.o utils.o vboxsf_wrappers.o super.o
+7
drivers/staging/vboxsf/TODO
··· 1 + TODO: 2 + - Find a file-system developer to review this and give their Reviewed-By 3 + - Address any items coming up during review 4 + - Move to fs/vboxfs 5 + 6 + Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org> 7 + and Hans de Goede <hdegoede@redhat.com>
+418
drivers/staging/vboxsf/dir.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * VirtualBox Guest Shared Folders support: Directory inode and file operations 4 + * 5 + * Copyright (C) 2006-2018 Oracle Corporation 6 + */ 7 + 8 + #include <linux/namei.h> 9 + #include <linux/vbox_utils.h> 10 + #include "vfsmod.h" 11 + 12 + static int vboxsf_dir_open(struct inode *inode, struct file *file) 13 + { 14 + struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb); 15 + struct shfl_createparms params = {}; 16 + struct vboxsf_dir_info *sf_d; 17 + int err; 18 + 19 + sf_d = vboxsf_dir_info_alloc(); 20 + if (!sf_d) 21 + return -ENOMEM; 22 + 23 + params.handle = SHFL_HANDLE_NIL; 24 + params.create_flags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_OPEN_IF_EXISTS | 25 + SHFL_CF_ACT_FAIL_IF_NEW | SHFL_CF_ACCESS_READ; 26 + 27 + err = vboxsf_create_at_dentry(file_dentry(file), &params); 28 + if (err) 29 + goto err_free_dir_info; 30 + 31 + if (params.result != SHFL_FILE_EXISTS) { 32 + err = -ENOENT; 33 + goto err_close; 34 + } 35 + 36 + err = vboxsf_dir_read_all(sbi, sf_d, params.handle); 37 + if (err) 38 + goto err_close; 39 + 40 + vboxsf_close(sbi->root, params.handle); 41 + file->private_data = sf_d; 42 + return 0; 43 + 44 + err_close: 45 + vboxsf_close(sbi->root, params.handle); 46 + err_free_dir_info: 47 + vboxsf_dir_info_free(sf_d); 48 + return err; 49 + } 50 + 51 + static int vboxsf_dir_release(struct inode *inode, struct file *file) 52 + { 53 + if (file->private_data) 54 + vboxsf_dir_info_free(file->private_data); 55 + 56 + return 0; 57 + } 58 + 59 + static unsigned int vboxsf_get_d_type(u32 mode) 60 + { 61 + unsigned int d_type; 62 + 63 + switch (mode & SHFL_TYPE_MASK) { 64 + case SHFL_TYPE_FIFO: 65 + d_type = DT_FIFO; 66 + break; 67 + case SHFL_TYPE_DEV_CHAR: 68 + d_type = DT_CHR; 69 + break; 70 + case SHFL_TYPE_DIRECTORY: 71 + d_type = DT_DIR; 72 + break; 73 + case SHFL_TYPE_DEV_BLOCK: 74 + d_type = DT_BLK; 75 + break; 76 + case SHFL_TYPE_FILE: 77 + d_type = DT_REG; 78 + break; 79 + case SHFL_TYPE_SYMLINK: 80 + d_type = DT_LNK; 81 + break; 82 + case SHFL_TYPE_SOCKET: 83 + d_type = DT_SOCK; 84 + break; 85 + case SHFL_TYPE_WHITEOUT: 86 + d_type = DT_WHT; 87 + break; 88 + default: 89 + d_type = DT_UNKNOWN; 90 + break; 91 + } 92 + return d_type; 93 + } 94 + 95 + static bool vboxsf_dir_emit(struct file *dir, struct dir_context *ctx) 96 + { 97 + struct vboxsf_sbi *sbi = VBOXSF_SBI(file_inode(dir)->i_sb); 98 + struct vboxsf_dir_info *sf_d = dir->private_data; 99 + struct shfl_dirinfo *info; 100 + struct vboxsf_dir_buf *b; 101 + unsigned int d_type; 102 + loff_t i, cur = 0; 103 + ino_t fake_ino; 104 + size_t size; 105 + int err; 106 + 107 + list_for_each_entry(b, &sf_d->info_list, head) { 108 + try_next_entry: 109 + if (ctx->pos >= cur + b->entries) { 110 + cur += b->entries; 111 + continue; 112 + } 113 + 114 + /* 115 + * Note the vboxsf_dir_info objects we are iterating over here 116 + * are variable sized, so the info pointer may end up being 117 + * unaligned. This is how we get the data from the host. 118 + * Since vboxsf is only supported on x86 machines this is not 119 + * a problem. 120 + */ 121 + for (i = 0, info = b->buf; i < ctx->pos - cur; i++) { 122 + size = offsetof(struct shfl_dirinfo, name.string) + 123 + info->name.size; 124 + info = (struct shfl_dirinfo *)((uintptr_t)info + size); 125 + } 126 + 127 + /* Info now points to the right entry, emit it. */ 128 + d_type = vboxsf_get_d_type(info->info.attr.mode); 129 + 130 + /* 131 + * On 32 bit systems pos is 64 signed, while ino is 32 bit 132 + * unsigned so fake_ino may overflow, check for this. 133 + */ 134 + if ((ino_t)(ctx->pos + 1) != (u64)(ctx->pos + 1)) { 135 + vbg_err("vboxsf: fake ino overflow, truncating dir\n"); 136 + return false; 137 + } 138 + fake_ino = ctx->pos + 1; 139 + 140 + if (sbi->nls) { 141 + char d_name[NAME_MAX]; 142 + 143 + err = vboxsf_nlscpy(sbi, d_name, NAME_MAX, 144 + info->name.string.utf8, 145 + info->name.length); 146 + if (err) { 147 + /* skip erroneous entry and proceed */ 148 + ctx->pos += 1; 149 + goto try_next_entry; 150 + } 151 + 152 + return dir_emit(ctx, d_name, strlen(d_name), 153 + fake_ino, d_type); 154 + } 155 + 156 + return dir_emit(ctx, info->name.string.utf8, info->name.length, 157 + fake_ino, d_type); 158 + } 159 + 160 + return false; 161 + } 162 + 163 + static int vboxsf_dir_iterate(struct file *dir, struct dir_context *ctx) 164 + { 165 + bool keep_iterating; 166 + 167 + for (keep_iterating = true; keep_iterating; ctx->pos += 1) 168 + keep_iterating = vboxsf_dir_emit(dir, ctx); 169 + 170 + return 0; 171 + } 172 + 173 + const struct file_operations vboxsf_dir_fops = { 174 + .open = vboxsf_dir_open, 175 + .iterate = vboxsf_dir_iterate, 176 + .release = vboxsf_dir_release, 177 + .read = generic_read_dir, 178 + .llseek = generic_file_llseek, 179 + }; 180 + 181 + /* 182 + * This is called during name resolution/lookup to check if the @dentry in 183 + * the cache is still valid. the job is handled by vboxsf_inode_revalidate. 184 + */ 185 + static int vboxsf_dentry_revalidate(struct dentry *dentry, unsigned int flags) 186 + { 187 + if (flags & LOOKUP_RCU) 188 + return -ECHILD; 189 + 190 + if (d_really_is_positive(dentry)) 191 + return vboxsf_inode_revalidate(dentry) == 0; 192 + else 193 + return vboxsf_stat_dentry(dentry, NULL) == -ENOENT; 194 + } 195 + 196 + const struct dentry_operations vboxsf_dentry_ops = { 197 + .d_revalidate = vboxsf_dentry_revalidate 198 + }; 199 + 200 + /* iops */ 201 + 202 + static struct dentry *vboxsf_dir_lookup(struct inode *parent, 203 + struct dentry *dentry, 204 + unsigned int flags) 205 + { 206 + struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); 207 + struct shfl_fsobjinfo fsinfo; 208 + struct inode *inode; 209 + int err; 210 + 211 + dentry->d_time = jiffies; 212 + 213 + err = vboxsf_stat_dentry(dentry, &fsinfo); 214 + if (err) { 215 + inode = (err == -ENOENT) ? NULL : ERR_PTR(err); 216 + } else { 217 + inode = vboxsf_new_inode(parent->i_sb); 218 + if (!IS_ERR(inode)) 219 + vboxsf_init_inode(sbi, inode, &fsinfo); 220 + } 221 + 222 + return d_splice_alias(inode, dentry); 223 + } 224 + 225 + static int vboxsf_dir_instantiate(struct inode *parent, struct dentry *dentry, 226 + struct shfl_fsobjinfo *info) 227 + { 228 + struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); 229 + struct vboxsf_inode *sf_i; 230 + struct inode *inode; 231 + 232 + inode = vboxsf_new_inode(parent->i_sb); 233 + if (IS_ERR(inode)) 234 + return PTR_ERR(inode); 235 + 236 + sf_i = VBOXSF_I(inode); 237 + /* The host may have given us different attr then requested */ 238 + sf_i->force_restat = 1; 239 + vboxsf_init_inode(sbi, inode, info); 240 + 241 + d_instantiate(dentry, inode); 242 + 243 + return 0; 244 + } 245 + 246 + static int vboxsf_dir_create(struct inode *parent, struct dentry *dentry, 247 + umode_t mode, int is_dir) 248 + { 249 + struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent); 250 + struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); 251 + struct shfl_createparms params = {}; 252 + int err; 253 + 254 + params.handle = SHFL_HANDLE_NIL; 255 + params.create_flags = SHFL_CF_ACT_CREATE_IF_NEW | 256 + SHFL_CF_ACT_FAIL_IF_EXISTS | 257 + SHFL_CF_ACCESS_READWRITE | 258 + (is_dir ? SHFL_CF_DIRECTORY : 0); 259 + params.info.attr.mode = (mode & 0777) | 260 + (is_dir ? SHFL_TYPE_DIRECTORY : SHFL_TYPE_FILE); 261 + params.info.attr.additional = SHFLFSOBJATTRADD_NOTHING; 262 + 263 + err = vboxsf_create_at_dentry(dentry, &params); 264 + if (err) 265 + return err; 266 + 267 + if (params.result != SHFL_FILE_CREATED) 268 + return -EPERM; 269 + 270 + vboxsf_close(sbi->root, params.handle); 271 + 272 + err = vboxsf_dir_instantiate(parent, dentry, &params.info); 273 + if (err) 274 + return err; 275 + 276 + /* parent directory access/change time changed */ 277 + sf_parent_i->force_restat = 1; 278 + 279 + return 0; 280 + } 281 + 282 + static int vboxsf_dir_mkfile(struct inode *parent, struct dentry *dentry, 283 + umode_t mode, bool excl) 284 + { 285 + return vboxsf_dir_create(parent, dentry, mode, 0); 286 + } 287 + 288 + static int vboxsf_dir_mkdir(struct inode *parent, struct dentry *dentry, 289 + umode_t mode) 290 + { 291 + return vboxsf_dir_create(parent, dentry, mode, 1); 292 + } 293 + 294 + static int vboxsf_dir_unlink(struct inode *parent, struct dentry *dentry) 295 + { 296 + struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); 297 + struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent); 298 + struct inode *inode = d_inode(dentry); 299 + struct shfl_string *path; 300 + u32 flags; 301 + int err; 302 + 303 + if (S_ISDIR(inode->i_mode)) 304 + flags = SHFL_REMOVE_DIR; 305 + else 306 + flags = SHFL_REMOVE_FILE; 307 + 308 + if (S_ISLNK(inode->i_mode)) 309 + flags |= SHFL_REMOVE_SYMLINK; 310 + 311 + path = vboxsf_path_from_dentry(sbi, dentry); 312 + if (IS_ERR(path)) 313 + return PTR_ERR(path); 314 + 315 + err = vboxsf_remove(sbi->root, path, flags); 316 + __putname(path); 317 + if (err) 318 + return err; 319 + 320 + /* parent directory access/change time changed */ 321 + sf_parent_i->force_restat = 1; 322 + 323 + return 0; 324 + } 325 + 326 + static int vboxsf_dir_rename(struct inode *old_parent, 327 + struct dentry *old_dentry, 328 + struct inode *new_parent, 329 + struct dentry *new_dentry, 330 + unsigned int flags) 331 + { 332 + struct vboxsf_sbi *sbi = VBOXSF_SBI(old_parent->i_sb); 333 + struct vboxsf_inode *sf_old_parent_i = VBOXSF_I(old_parent); 334 + struct vboxsf_inode *sf_new_parent_i = VBOXSF_I(new_parent); 335 + u32 shfl_flags = SHFL_RENAME_FILE | SHFL_RENAME_REPLACE_IF_EXISTS; 336 + struct shfl_string *old_path, *new_path; 337 + int err; 338 + 339 + if (flags) 340 + return -EINVAL; 341 + 342 + old_path = vboxsf_path_from_dentry(sbi, old_dentry); 343 + if (IS_ERR(old_path)) 344 + return PTR_ERR(old_path); 345 + 346 + new_path = vboxsf_path_from_dentry(sbi, new_dentry); 347 + if (IS_ERR(new_path)) { 348 + err = PTR_ERR(new_path); 349 + goto err_put_old_path; 350 + } 351 + 352 + if (d_inode(old_dentry)->i_mode & S_IFDIR) 353 + shfl_flags = 0; 354 + 355 + err = vboxsf_rename(sbi->root, old_path, new_path, shfl_flags); 356 + if (err == 0) { 357 + /* parent directories access/change time changed */ 358 + sf_new_parent_i->force_restat = 1; 359 + sf_old_parent_i->force_restat = 1; 360 + } 361 + 362 + __putname(new_path); 363 + err_put_old_path: 364 + __putname(old_path); 365 + return err; 366 + } 367 + 368 + static int vboxsf_dir_symlink(struct inode *parent, struct dentry *dentry, 369 + const char *symname) 370 + { 371 + struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent); 372 + struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); 373 + int symname_size = strlen(symname) + 1; 374 + struct shfl_string *path, *ssymname; 375 + struct shfl_fsobjinfo info; 376 + int err; 377 + 378 + path = vboxsf_path_from_dentry(sbi, dentry); 379 + if (IS_ERR(path)) 380 + return PTR_ERR(path); 381 + 382 + ssymname = kmalloc(SHFLSTRING_HEADER_SIZE + symname_size, GFP_KERNEL); 383 + if (!ssymname) { 384 + __putname(path); 385 + return -ENOMEM; 386 + } 387 + ssymname->length = symname_size - 1; 388 + ssymname->size = symname_size; 389 + memcpy(ssymname->string.utf8, symname, symname_size); 390 + 391 + err = vboxsf_symlink(sbi->root, path, ssymname, &info); 392 + kfree(ssymname); 393 + __putname(path); 394 + if (err) { 395 + /* -EROFS means symlinks are note support -> -EPERM */ 396 + return (err == -EROFS) ? -EPERM : err; 397 + } 398 + 399 + err = vboxsf_dir_instantiate(parent, dentry, &info); 400 + if (err) 401 + return err; 402 + 403 + /* parent directory access/change time changed */ 404 + sf_parent_i->force_restat = 1; 405 + return 0; 406 + } 407 + 408 + const struct inode_operations vboxsf_dir_iops = { 409 + .lookup = vboxsf_dir_lookup, 410 + .create = vboxsf_dir_mkfile, 411 + .mkdir = vboxsf_dir_mkdir, 412 + .rmdir = vboxsf_dir_unlink, 413 + .unlink = vboxsf_dir_unlink, 414 + .rename = vboxsf_dir_rename, 415 + .symlink = vboxsf_dir_symlink, 416 + .getattr = vboxsf_getattr, 417 + .setattr = vboxsf_setattr, 418 + };
+370
drivers/staging/vboxsf/file.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * VirtualBox Guest Shared Folders support: Regular file inode and file ops. 4 + * 5 + * Copyright (C) 2006-2018 Oracle Corporation 6 + */ 7 + 8 + #include <linux/mm.h> 9 + #include <linux/page-flags.h> 10 + #include <linux/pagemap.h> 11 + #include <linux/highmem.h> 12 + #include <linux/sizes.h> 13 + #include "vfsmod.h" 14 + 15 + struct vboxsf_handle { 16 + u64 handle; 17 + u32 root; 18 + u32 access_flags; 19 + struct kref refcount; 20 + struct list_head head; 21 + }; 22 + 23 + static int vboxsf_file_open(struct inode *inode, struct file *file) 24 + { 25 + struct vboxsf_inode *sf_i = VBOXSF_I(inode); 26 + struct shfl_createparms params = {}; 27 + struct vboxsf_handle *sf_handle; 28 + u32 access_flags = 0; 29 + int err; 30 + 31 + sf_handle = kmalloc(sizeof(*sf_handle), GFP_KERNEL); 32 + if (!sf_handle) 33 + return -ENOMEM; 34 + 35 + /* 36 + * We check the value of params.handle afterwards to find out if 37 + * the call succeeded or failed, as the API does not seem to cleanly 38 + * distinguish error and informational messages. 39 + * 40 + * Furthermore, we must set params.handle to SHFL_HANDLE_NIL to 41 + * make the shared folders host service use our mode parameter. 42 + */ 43 + params.handle = SHFL_HANDLE_NIL; 44 + if (file->f_flags & O_CREAT) { 45 + params.create_flags |= SHFL_CF_ACT_CREATE_IF_NEW; 46 + /* 47 + * We ignore O_EXCL, as the Linux kernel seems to call create 48 + * beforehand itself, so O_EXCL should always fail. 49 + */ 50 + if (file->f_flags & O_TRUNC) 51 + params.create_flags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; 52 + else 53 + params.create_flags |= SHFL_CF_ACT_OPEN_IF_EXISTS; 54 + } else { 55 + params.create_flags |= SHFL_CF_ACT_FAIL_IF_NEW; 56 + if (file->f_flags & O_TRUNC) 57 + params.create_flags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; 58 + } 59 + 60 + switch (file->f_flags & O_ACCMODE) { 61 + case O_RDONLY: 62 + access_flags |= SHFL_CF_ACCESS_READ; 63 + break; 64 + 65 + case O_WRONLY: 66 + access_flags |= SHFL_CF_ACCESS_WRITE; 67 + break; 68 + 69 + case O_RDWR: 70 + access_flags |= SHFL_CF_ACCESS_READWRITE; 71 + break; 72 + 73 + default: 74 + WARN_ON(1); 75 + } 76 + 77 + if (file->f_flags & O_APPEND) 78 + access_flags |= SHFL_CF_ACCESS_APPEND; 79 + 80 + params.create_flags |= access_flags; 81 + params.info.attr.mode = inode->i_mode; 82 + 83 + err = vboxsf_create_at_dentry(file_dentry(file), &params); 84 + if (err == 0 && params.handle == SHFL_HANDLE_NIL) 85 + err = (params.result == SHFL_FILE_EXISTS) ? -EEXIST : -ENOENT; 86 + if (err) { 87 + kfree(sf_handle); 88 + return err; 89 + } 90 + 91 + /* the host may have given us different attr then requested */ 92 + sf_i->force_restat = 1; 93 + 94 + /* init our handle struct and add it to the inode's handles list */ 95 + sf_handle->handle = params.handle; 96 + sf_handle->root = VBOXSF_SBI(inode->i_sb)->root; 97 + sf_handle->access_flags = access_flags; 98 + kref_init(&sf_handle->refcount); 99 + 100 + mutex_lock(&sf_i->handle_list_mutex); 101 + list_add(&sf_handle->head, &sf_i->handle_list); 102 + mutex_unlock(&sf_i->handle_list_mutex); 103 + 104 + file->private_data = sf_handle; 105 + return 0; 106 + } 107 + 108 + static void vboxsf_handle_release(struct kref *refcount) 109 + { 110 + struct vboxsf_handle *sf_handle = 111 + container_of(refcount, struct vboxsf_handle, refcount); 112 + 113 + vboxsf_close(sf_handle->root, sf_handle->handle); 114 + kfree(sf_handle); 115 + } 116 + 117 + static int vboxsf_file_release(struct inode *inode, struct file *file) 118 + { 119 + struct vboxsf_inode *sf_i = VBOXSF_I(inode); 120 + struct vboxsf_handle *sf_handle = file->private_data; 121 + 122 + /* 123 + * When a file is closed on our (the guest) side, we want any subsequent 124 + * accesses done on the host side to see all changes done from our side. 125 + */ 126 + filemap_write_and_wait(inode->i_mapping); 127 + 128 + mutex_lock(&sf_i->handle_list_mutex); 129 + list_del(&sf_handle->head); 130 + mutex_unlock(&sf_i->handle_list_mutex); 131 + 132 + kref_put(&sf_handle->refcount, vboxsf_handle_release); 133 + return 0; 134 + } 135 + 136 + /* 137 + * Write back dirty pages now, because there may not be any suitable 138 + * open files later 139 + */ 140 + static void vboxsf_vma_close(struct vm_area_struct *vma) 141 + { 142 + filemap_write_and_wait(vma->vm_file->f_mapping); 143 + } 144 + 145 + static const struct vm_operations_struct vboxsf_file_vm_ops = { 146 + .close = vboxsf_vma_close, 147 + .fault = filemap_fault, 148 + .map_pages = filemap_map_pages, 149 + }; 150 + 151 + static int vboxsf_file_mmap(struct file *file, struct vm_area_struct *vma) 152 + { 153 + int err; 154 + 155 + err = generic_file_mmap(file, vma); 156 + if (!err) 157 + vma->vm_ops = &vboxsf_file_vm_ops; 158 + 159 + return err; 160 + } 161 + 162 + /* 163 + * Note that since we are accessing files on the host's filesystem, files 164 + * may always be changed underneath us by the host! 165 + * 166 + * The vboxsf API between the guest and the host does not offer any functions 167 + * to deal with this. There is no inode-generation to check for changes, no 168 + * events / callback on changes and no way to lock files. 169 + * 170 + * To avoid returning stale data when a file gets *opened* on our (the guest) 171 + * side, we do a "stat" on the host side, then compare the mtime with the 172 + * last known mtime and invalidate the page-cache if they differ. 173 + * This is done from vboxsf_inode_revalidate(). 174 + * 175 + * When reads are done through the read_iter fop, it is possible to do 176 + * further cache revalidation then, there are 3 options to deal with this: 177 + * 178 + * 1) Rely solely on the revalidation done at open time 179 + * 2) Do another "stat" and compare mtime again. Unfortunately the vboxsf 180 + * host API does not allow stat on handles, so we would need to use 181 + * file->f_path.dentry and the stat will then fail if the file was unlinked 182 + * or renamed (and there is no thing like NFS' silly-rename). So we get: 183 + * 2a) "stat" and compare mtime, on stat failure invalidate the cache 184 + * 2b) "stat" and compare mtime, on stat failure do nothing 185 + * 3) Simply always call invalidate_inode_pages2_range on the range of the read 186 + * 187 + * Currently we are keeping things KISS and using option 1. this allows 188 + * directly using generic_file_read_iter without wrapping it. 189 + * 190 + * This means that only data written on the host side before open() on 191 + * the guest side is guaranteed to be seen by the guest. If necessary 192 + * we may provide other read-cache strategies in the future and make this 193 + * configurable through a mount option. 194 + */ 195 + const struct file_operations vboxsf_reg_fops = { 196 + .llseek = generic_file_llseek, 197 + .read_iter = generic_file_read_iter, 198 + .write_iter = generic_file_write_iter, 199 + .mmap = vboxsf_file_mmap, 200 + .open = vboxsf_file_open, 201 + .release = vboxsf_file_release, 202 + .fsync = noop_fsync, 203 + .splice_read = generic_file_splice_read, 204 + }; 205 + 206 + const struct inode_operations vboxsf_reg_iops = { 207 + .getattr = vboxsf_getattr, 208 + .setattr = vboxsf_setattr 209 + }; 210 + 211 + static int vboxsf_readpage(struct file *file, struct page *page) 212 + { 213 + struct vboxsf_handle *sf_handle = file->private_data; 214 + loff_t off = page_offset(page); 215 + u32 nread = PAGE_SIZE; 216 + u8 *buf; 217 + int err; 218 + 219 + buf = kmap(page); 220 + 221 + err = vboxsf_read(sf_handle->root, sf_handle->handle, off, &nread, buf); 222 + if (err == 0) { 223 + memset(&buf[nread], 0, PAGE_SIZE - nread); 224 + flush_dcache_page(page); 225 + SetPageUptodate(page); 226 + } else { 227 + SetPageError(page); 228 + } 229 + 230 + kunmap(page); 231 + unlock_page(page); 232 + return err; 233 + } 234 + 235 + static struct vboxsf_handle *vboxsf_get_write_handle(struct vboxsf_inode *sf_i) 236 + { 237 + struct vboxsf_handle *h, *sf_handle = NULL; 238 + 239 + mutex_lock(&sf_i->handle_list_mutex); 240 + list_for_each_entry(h, &sf_i->handle_list, head) { 241 + if (h->access_flags == SHFL_CF_ACCESS_WRITE || 242 + h->access_flags == SHFL_CF_ACCESS_READWRITE) { 243 + kref_get(&h->refcount); 244 + sf_handle = h; 245 + break; 246 + } 247 + } 248 + mutex_unlock(&sf_i->handle_list_mutex); 249 + 250 + return sf_handle; 251 + } 252 + 253 + static int vboxsf_writepage(struct page *page, struct writeback_control *wbc) 254 + { 255 + struct inode *inode = page->mapping->host; 256 + struct vboxsf_inode *sf_i = VBOXSF_I(inode); 257 + struct vboxsf_handle *sf_handle; 258 + loff_t off = page_offset(page); 259 + loff_t size = i_size_read(inode); 260 + u32 nwrite = PAGE_SIZE; 261 + u8 *buf; 262 + int err; 263 + 264 + if (off + PAGE_SIZE > size) 265 + nwrite = size & ~PAGE_MASK; 266 + 267 + sf_handle = vboxsf_get_write_handle(sf_i); 268 + if (!sf_handle) 269 + return -EBADF; 270 + 271 + buf = kmap(page); 272 + err = vboxsf_write(sf_handle->root, sf_handle->handle, 273 + off, &nwrite, buf); 274 + kunmap(page); 275 + 276 + kref_put(&sf_handle->refcount, vboxsf_handle_release); 277 + 278 + if (err == 0) { 279 + ClearPageError(page); 280 + /* mtime changed */ 281 + sf_i->force_restat = 1; 282 + } else { 283 + ClearPageUptodate(page); 284 + } 285 + 286 + unlock_page(page); 287 + return err; 288 + } 289 + 290 + static int vboxsf_write_end(struct file *file, struct address_space *mapping, 291 + loff_t pos, unsigned int len, unsigned int copied, 292 + struct page *page, void *fsdata) 293 + { 294 + struct inode *inode = mapping->host; 295 + struct vboxsf_handle *sf_handle = file->private_data; 296 + unsigned int from = pos & ~PAGE_MASK; 297 + u32 nwritten = len; 298 + u8 *buf; 299 + int err; 300 + 301 + buf = kmap(page); 302 + err = vboxsf_write(sf_handle->root, sf_handle->handle, 303 + pos, &nwritten, buf + from); 304 + kunmap(page); 305 + 306 + if (err) { 307 + nwritten = 0; 308 + goto out; 309 + } 310 + 311 + /* mtime changed */ 312 + VBOXSF_I(inode)->force_restat = 1; 313 + 314 + if (!PageUptodate(page) && nwritten == PAGE_SIZE) 315 + SetPageUptodate(page); 316 + 317 + pos += nwritten; 318 + if (pos > inode->i_size) 319 + i_size_write(inode, pos); 320 + 321 + out: 322 + unlock_page(page); 323 + put_page(page); 324 + 325 + return nwritten; 326 + } 327 + 328 + const struct address_space_operations vboxsf_reg_aops = { 329 + .readpage = vboxsf_readpage, 330 + .writepage = vboxsf_writepage, 331 + .set_page_dirty = __set_page_dirty_nobuffers, 332 + .write_begin = simple_write_begin, 333 + .write_end = vboxsf_write_end, 334 + }; 335 + 336 + static const char *vboxsf_get_link(struct dentry *dentry, struct inode *inode, 337 + struct delayed_call *done) 338 + { 339 + struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb); 340 + struct shfl_string *path; 341 + char *link; 342 + int err; 343 + 344 + if (!dentry) 345 + return ERR_PTR(-ECHILD); 346 + 347 + path = vboxsf_path_from_dentry(sbi, dentry); 348 + if (IS_ERR(path)) 349 + return (char *)path; 350 + 351 + link = kzalloc(PATH_MAX, GFP_KERNEL); 352 + if (!link) { 353 + __putname(path); 354 + return ERR_PTR(-ENOMEM); 355 + } 356 + 357 + err = vboxsf_readlink(sbi->root, path, PATH_MAX, link); 358 + __putname(path); 359 + if (err) { 360 + kfree(link); 361 + return ERR_PTR(err); 362 + } 363 + 364 + set_delayed_call(done, kfree_link, link); 365 + return link; 366 + } 367 + 368 + const struct inode_operations vboxsf_lnk_iops = { 369 + .get_link = vboxsf_get_link 370 + };
+901
drivers/staging/vboxsf/shfl_hostintf.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * VirtualBox Shared Folders: host interface definition. 4 + * 5 + * Copyright (C) 2006-2018 Oracle Corporation 6 + */ 7 + 8 + #ifndef SHFL_HOSTINTF_H 9 + #define SHFL_HOSTINTF_H 10 + 11 + #include <linux/vbox_vmmdev_types.h> 12 + 13 + /* The max in/out buffer size for a FN_READ or FN_WRITE call */ 14 + #define SHFL_MAX_RW_COUNT (16 * SZ_1M) 15 + 16 + /* 17 + * Structures shared between guest and the service 18 + * can be relocated and use offsets to point to variable 19 + * length parts. 20 + * 21 + * Shared folders protocol works with handles. 22 + * Before doing any action on a file system object, 23 + * one have to obtain the object handle via a SHFL_FN_CREATE 24 + * request. A handle must be closed with SHFL_FN_CLOSE. 25 + */ 26 + 27 + enum { 28 + SHFL_FN_QUERY_MAPPINGS = 1, /* Query mappings changes. */ 29 + SHFL_FN_QUERY_MAP_NAME = 2, /* Query map name. */ 30 + SHFL_FN_CREATE = 3, /* Open/create object. */ 31 + SHFL_FN_CLOSE = 4, /* Close object handle. */ 32 + SHFL_FN_READ = 5, /* Read object content. */ 33 + SHFL_FN_WRITE = 6, /* Write new object content. */ 34 + SHFL_FN_LOCK = 7, /* Lock/unlock a range in the object. */ 35 + SHFL_FN_LIST = 8, /* List object content. */ 36 + SHFL_FN_INFORMATION = 9, /* Query/set object information. */ 37 + /* Note function number 10 is not used! */ 38 + SHFL_FN_REMOVE = 11, /* Remove object */ 39 + SHFL_FN_MAP_FOLDER_OLD = 12, /* Map folder (legacy) */ 40 + SHFL_FN_UNMAP_FOLDER = 13, /* Unmap folder */ 41 + SHFL_FN_RENAME = 14, /* Rename object */ 42 + SHFL_FN_FLUSH = 15, /* Flush file */ 43 + SHFL_FN_SET_UTF8 = 16, /* Select UTF8 filename encoding */ 44 + SHFL_FN_MAP_FOLDER = 17, /* Map folder */ 45 + SHFL_FN_READLINK = 18, /* Read symlink dest (as of VBox 4.0) */ 46 + SHFL_FN_SYMLINK = 19, /* Create symlink (as of VBox 4.0) */ 47 + SHFL_FN_SET_SYMLINKS = 20, /* Ask host to show symlinks (4.0+) */ 48 + }; 49 + 50 + /* Root handles for a mapping are of type u32, Root handles are unique. */ 51 + #define SHFL_ROOT_NIL UINT_MAX 52 + 53 + /* Shared folders handle for an opened object are of type u64. */ 54 + #define SHFL_HANDLE_NIL ULLONG_MAX 55 + 56 + /* Hardcoded maximum length (in chars) of a shared folder name. */ 57 + #define SHFL_MAX_LEN (256) 58 + /* Hardcoded maximum number of shared folder mapping available to the guest. */ 59 + #define SHFL_MAX_MAPPINGS (64) 60 + 61 + /** Shared folder string buffer structure. */ 62 + struct shfl_string { 63 + /** Allocated size of the string member in bytes. */ 64 + u16 size; 65 + 66 + /** Length of string without trailing nul in bytes. */ 67 + u16 length; 68 + 69 + /** UTF-8 or UTF-16 string. Nul terminated. */ 70 + union { 71 + u8 utf8[2]; 72 + u16 utf16[1]; 73 + u16 ucs2[1]; /* misnomer, use utf16. */ 74 + } string; 75 + }; 76 + VMMDEV_ASSERT_SIZE(shfl_string, 6); 77 + 78 + /* The size of shfl_string w/o the string part. */ 79 + #define SHFLSTRING_HEADER_SIZE 4 80 + 81 + /* Calculate size of the string. */ 82 + static inline u32 shfl_string_buf_size(const struct shfl_string *string) 83 + { 84 + return string ? SHFLSTRING_HEADER_SIZE + string->size : 0; 85 + } 86 + 87 + /* Set user id on execution (S_ISUID). */ 88 + #define SHFL_UNIX_ISUID 0004000U 89 + /* Set group id on execution (S_ISGID). */ 90 + #define SHFL_UNIX_ISGID 0002000U 91 + /* Sticky bit (S_ISVTX / S_ISTXT). */ 92 + #define SHFL_UNIX_ISTXT 0001000U 93 + 94 + /* Owner readable (S_IRUSR). */ 95 + #define SHFL_UNIX_IRUSR 0000400U 96 + /* Owner writable (S_IWUSR). */ 97 + #define SHFL_UNIX_IWUSR 0000200U 98 + /* Owner executable (S_IXUSR). */ 99 + #define SHFL_UNIX_IXUSR 0000100U 100 + 101 + /* Group readable (S_IRGRP). */ 102 + #define SHFL_UNIX_IRGRP 0000040U 103 + /* Group writable (S_IWGRP). */ 104 + #define SHFL_UNIX_IWGRP 0000020U 105 + /* Group executable (S_IXGRP). */ 106 + #define SHFL_UNIX_IXGRP 0000010U 107 + 108 + /* Other readable (S_IROTH). */ 109 + #define SHFL_UNIX_IROTH 0000004U 110 + /* Other writable (S_IWOTH). */ 111 + #define SHFL_UNIX_IWOTH 0000002U 112 + /* Other executable (S_IXOTH). */ 113 + #define SHFL_UNIX_IXOTH 0000001U 114 + 115 + /* Named pipe (fifo) (S_IFIFO). */ 116 + #define SHFL_TYPE_FIFO 0010000U 117 + /* Character device (S_IFCHR). */ 118 + #define SHFL_TYPE_DEV_CHAR 0020000U 119 + /* Directory (S_IFDIR). */ 120 + #define SHFL_TYPE_DIRECTORY 0040000U 121 + /* Block device (S_IFBLK). */ 122 + #define SHFL_TYPE_DEV_BLOCK 0060000U 123 + /* Regular file (S_IFREG). */ 124 + #define SHFL_TYPE_FILE 0100000U 125 + /* Symbolic link (S_IFLNK). */ 126 + #define SHFL_TYPE_SYMLINK 0120000U 127 + /* Socket (S_IFSOCK). */ 128 + #define SHFL_TYPE_SOCKET 0140000U 129 + /* Whiteout (S_IFWHT). */ 130 + #define SHFL_TYPE_WHITEOUT 0160000U 131 + /* Type mask (S_IFMT). */ 132 + #define SHFL_TYPE_MASK 0170000U 133 + 134 + /* Checks the mode flags indicate a directory (S_ISDIR). */ 135 + #define SHFL_IS_DIRECTORY(m) (((m) & SHFL_TYPE_MASK) == SHFL_TYPE_DIRECTORY) 136 + /* Checks the mode flags indicate a symbolic link (S_ISLNK). */ 137 + #define SHFL_IS_SYMLINK(m) (((m) & SHFL_TYPE_MASK) == SHFL_TYPE_SYMLINK) 138 + 139 + /** The available additional information in a shfl_fsobjattr object. */ 140 + enum shfl_fsobjattr_add { 141 + /** No additional information is available / requested. */ 142 + SHFLFSOBJATTRADD_NOTHING = 1, 143 + /** 144 + * The additional unix attributes (shfl_fsobjattr::u::unix_attr) are 145 + * available / requested. 146 + */ 147 + SHFLFSOBJATTRADD_UNIX, 148 + /** 149 + * The additional extended attribute size (shfl_fsobjattr::u::size) is 150 + * available / requested. 151 + */ 152 + SHFLFSOBJATTRADD_EASIZE, 153 + /** 154 + * The last valid item (inclusive). 155 + * The valid range is SHFLFSOBJATTRADD_NOTHING thru 156 + * SHFLFSOBJATTRADD_LAST. 157 + */ 158 + SHFLFSOBJATTRADD_LAST = SHFLFSOBJATTRADD_EASIZE, 159 + 160 + /** The usual 32-bit hack. */ 161 + SHFLFSOBJATTRADD_32BIT_SIZE_HACK = 0x7fffffff 162 + }; 163 + 164 + /** 165 + * Additional unix Attributes, these are available when 166 + * shfl_fsobjattr.additional == SHFLFSOBJATTRADD_UNIX. 167 + */ 168 + struct shfl_fsobjattr_unix { 169 + /** 170 + * The user owning the filesystem object (st_uid). 171 + * This field is ~0U if not supported. 172 + */ 173 + u32 uid; 174 + 175 + /** 176 + * The group the filesystem object is assigned (st_gid). 177 + * This field is ~0U if not supported. 178 + */ 179 + u32 gid; 180 + 181 + /** 182 + * Number of hard links to this filesystem object (st_nlink). 183 + * This field is 1 if the filesystem doesn't support hardlinking or 184 + * the information isn't available. 185 + */ 186 + u32 hardlinks; 187 + 188 + /** 189 + * The device number of the device which this filesystem object resides 190 + * on (st_dev). This field is 0 if this information is not available. 191 + */ 192 + u32 inode_id_device; 193 + 194 + /** 195 + * The unique identifier (within the filesystem) of this filesystem 196 + * object (st_ino). Together with inode_id_device, this field can be 197 + * used as a OS wide unique id, when both their values are not 0. 198 + * This field is 0 if the information is not available. 199 + */ 200 + u64 inode_id; 201 + 202 + /** 203 + * User flags (st_flags). 204 + * This field is 0 if this information is not available. 205 + */ 206 + u32 flags; 207 + 208 + /** 209 + * The current generation number (st_gen). 210 + * This field is 0 if this information is not available. 211 + */ 212 + u32 generation_id; 213 + 214 + /** 215 + * The device number of a char. or block device type object (st_rdev). 216 + * This field is 0 if the file isn't a char. or block device or when 217 + * the OS doesn't use the major+minor device idenfication scheme. 218 + */ 219 + u32 device; 220 + } __packed; 221 + 222 + /** Extended attribute size. */ 223 + struct shfl_fsobjattr_easize { 224 + /** Size of EAs. */ 225 + s64 cb; 226 + } __packed; 227 + 228 + /** Shared folder filesystem object attributes. */ 229 + struct shfl_fsobjattr { 230 + /** Mode flags (st_mode). SHFL_UNIX_*, SHFL_TYPE_*, and SHFL_DOS_*. */ 231 + u32 mode; 232 + 233 + /** The additional attributes available. */ 234 + enum shfl_fsobjattr_add additional; 235 + 236 + /** 237 + * Additional attributes. 238 + * 239 + * Unless explicitly specified to an API, the API can provide additional 240 + * data as it is provided by the underlying OS. 241 + */ 242 + union { 243 + struct shfl_fsobjattr_unix unix_attr; 244 + struct shfl_fsobjattr_easize size; 245 + } __packed u; 246 + } __packed; 247 + VMMDEV_ASSERT_SIZE(shfl_fsobjattr, 44); 248 + 249 + struct shfl_timespec { 250 + s64 ns_relative_to_unix_epoch; 251 + }; 252 + 253 + /** Filesystem object information structure. */ 254 + struct shfl_fsobjinfo { 255 + /** 256 + * Logical size (st_size). 257 + * For normal files this is the size of the file. 258 + * For symbolic links, this is the length of the path name contained 259 + * in the symbolic link. 260 + * For other objects this fields needs to be specified. 261 + */ 262 + s64 size; 263 + 264 + /** Disk allocation size (st_blocks * DEV_BSIZE). */ 265 + s64 allocated; 266 + 267 + /** Time of last access (st_atime). */ 268 + struct shfl_timespec access_time; 269 + 270 + /** Time of last data modification (st_mtime). */ 271 + struct shfl_timespec modification_time; 272 + 273 + /** 274 + * Time of last status change (st_ctime). 275 + * If not available this is set to modification_time. 276 + */ 277 + struct shfl_timespec change_time; 278 + 279 + /** 280 + * Time of file birth (st_birthtime). 281 + * If not available this is set to change_time. 282 + */ 283 + struct shfl_timespec birth_time; 284 + 285 + /** Attributes. */ 286 + struct shfl_fsobjattr attr; 287 + 288 + } __packed; 289 + VMMDEV_ASSERT_SIZE(shfl_fsobjinfo, 92); 290 + 291 + /** 292 + * result of an open/create request. 293 + * Along with handle value the result code 294 + * identifies what has happened while 295 + * trying to open the object. 296 + */ 297 + enum shfl_create_result { 298 + SHFL_NO_RESULT, 299 + /** Specified path does not exist. */ 300 + SHFL_PATH_NOT_FOUND, 301 + /** Path to file exists, but the last component does not. */ 302 + SHFL_FILE_NOT_FOUND, 303 + /** File already exists and either has been opened or not. */ 304 + SHFL_FILE_EXISTS, 305 + /** New file was created. */ 306 + SHFL_FILE_CREATED, 307 + /** Existing file was replaced or overwritten. */ 308 + SHFL_FILE_REPLACED 309 + }; 310 + 311 + /* No flags. Initialization value. */ 312 + #define SHFL_CF_NONE (0x00000000) 313 + 314 + /* 315 + * Only lookup the object, do not return a handle. When this is set all other 316 + * flags are ignored. 317 + */ 318 + #define SHFL_CF_LOOKUP (0x00000001) 319 + 320 + /* 321 + * Open parent directory of specified object. 322 + * Useful for the corresponding Windows FSD flag 323 + * and for opening paths like \\dir\\*.* to search the 'dir'. 324 + */ 325 + #define SHFL_CF_OPEN_TARGET_DIRECTORY (0x00000002) 326 + 327 + /* Create/open a directory. */ 328 + #define SHFL_CF_DIRECTORY (0x00000004) 329 + 330 + /* 331 + * Open/create action to do if object exists 332 + * and if the object does not exists. 333 + * REPLACE file means atomically DELETE and CREATE. 334 + * OVERWRITE file means truncating the file to 0 and 335 + * setting new size. 336 + * When opening an existing directory REPLACE and OVERWRITE 337 + * actions are considered invalid, and cause returning 338 + * FILE_EXISTS with NIL handle. 339 + */ 340 + #define SHFL_CF_ACT_MASK_IF_EXISTS (0x000000f0) 341 + #define SHFL_CF_ACT_MASK_IF_NEW (0x00000f00) 342 + 343 + /* What to do if object exists. */ 344 + #define SHFL_CF_ACT_OPEN_IF_EXISTS (0x00000000) 345 + #define SHFL_CF_ACT_FAIL_IF_EXISTS (0x00000010) 346 + #define SHFL_CF_ACT_REPLACE_IF_EXISTS (0x00000020) 347 + #define SHFL_CF_ACT_OVERWRITE_IF_EXISTS (0x00000030) 348 + 349 + /* What to do if object does not exist. */ 350 + #define SHFL_CF_ACT_CREATE_IF_NEW (0x00000000) 351 + #define SHFL_CF_ACT_FAIL_IF_NEW (0x00000100) 352 + 353 + /* Read/write requested access for the object. */ 354 + #define SHFL_CF_ACCESS_MASK_RW (0x00003000) 355 + 356 + /* No access requested. */ 357 + #define SHFL_CF_ACCESS_NONE (0x00000000) 358 + /* Read access requested. */ 359 + #define SHFL_CF_ACCESS_READ (0x00001000) 360 + /* Write access requested. */ 361 + #define SHFL_CF_ACCESS_WRITE (0x00002000) 362 + /* Read/Write access requested. */ 363 + #define SHFL_CF_ACCESS_READWRITE (0x00003000) 364 + 365 + /* Requested share access for the object. */ 366 + #define SHFL_CF_ACCESS_MASK_DENY (0x0000c000) 367 + 368 + /* Allow any access. */ 369 + #define SHFL_CF_ACCESS_DENYNONE (0x00000000) 370 + /* Do not allow read. */ 371 + #define SHFL_CF_ACCESS_DENYREAD (0x00004000) 372 + /* Do not allow write. */ 373 + #define SHFL_CF_ACCESS_DENYWRITE (0x00008000) 374 + /* Do not allow access. */ 375 + #define SHFL_CF_ACCESS_DENYALL (0x0000c000) 376 + 377 + /* Requested access to attributes of the object. */ 378 + #define SHFL_CF_ACCESS_MASK_ATTR (0x00030000) 379 + 380 + /* No access requested. */ 381 + #define SHFL_CF_ACCESS_ATTR_NONE (0x00000000) 382 + /* Read access requested. */ 383 + #define SHFL_CF_ACCESS_ATTR_READ (0x00010000) 384 + /* Write access requested. */ 385 + #define SHFL_CF_ACCESS_ATTR_WRITE (0x00020000) 386 + /* Read/Write access requested. */ 387 + #define SHFL_CF_ACCESS_ATTR_READWRITE (0x00030000) 388 + 389 + /* 390 + * The file is opened in append mode. 391 + * Ignored if SHFL_CF_ACCESS_WRITE is not set. 392 + */ 393 + #define SHFL_CF_ACCESS_APPEND (0x00040000) 394 + 395 + /** Create parameters buffer struct for SHFL_FN_CREATE call */ 396 + struct shfl_createparms { 397 + /** Returned handle of opened object. */ 398 + u64 handle; 399 + 400 + /** Returned result of the operation */ 401 + enum shfl_create_result result; 402 + 403 + /** SHFL_CF_* */ 404 + u32 create_flags; 405 + 406 + /** 407 + * Attributes of object to create and 408 + * returned actual attributes of opened/created object. 409 + */ 410 + struct shfl_fsobjinfo info; 411 + } __packed; 412 + 413 + /** Shared Folder directory information */ 414 + struct shfl_dirinfo { 415 + /** Full information about the object. */ 416 + struct shfl_fsobjinfo info; 417 + /** 418 + * The length of the short field (number of UTF16 chars). 419 + * It is 16-bit for reasons of alignment. 420 + */ 421 + u16 short_name_len; 422 + /** 423 + * The short name for 8.3 compatibility. 424 + * Empty string if not available. 425 + */ 426 + u16 short_name[14]; 427 + struct shfl_string name; 428 + }; 429 + 430 + /** Shared folder filesystem properties. */ 431 + struct shfl_fsproperties { 432 + /** 433 + * The maximum size of a filesystem object name. 434 + * This does not include the '\\0'. 435 + */ 436 + u32 max_component_len; 437 + 438 + /** 439 + * True if the filesystem is remote. 440 + * False if the filesystem is local. 441 + */ 442 + bool remote; 443 + 444 + /** 445 + * True if the filesystem is case sensitive. 446 + * False if the filesystem is case insensitive. 447 + */ 448 + bool case_sensitive; 449 + 450 + /** 451 + * True if the filesystem is mounted read only. 452 + * False if the filesystem is mounted read write. 453 + */ 454 + bool read_only; 455 + 456 + /** 457 + * True if the filesystem can encode unicode object names. 458 + * False if it can't. 459 + */ 460 + bool supports_unicode; 461 + 462 + /** 463 + * True if the filesystem is compresses. 464 + * False if it isn't or we don't know. 465 + */ 466 + bool compressed; 467 + 468 + /** 469 + * True if the filesystem compresses of individual files. 470 + * False if it doesn't or we don't know. 471 + */ 472 + bool file_compression; 473 + }; 474 + VMMDEV_ASSERT_SIZE(shfl_fsproperties, 12); 475 + 476 + struct shfl_volinfo { 477 + s64 total_allocation_bytes; 478 + s64 available_allocation_bytes; 479 + u32 bytes_per_allocation_unit; 480 + u32 bytes_per_sector; 481 + u32 serial; 482 + struct shfl_fsproperties properties; 483 + }; 484 + 485 + 486 + /** SHFL_FN_MAP_FOLDER Parameters structure. */ 487 + struct shfl_map_folder { 488 + /** 489 + * pointer, in: 490 + * Points to struct shfl_string buffer. 491 + */ 492 + struct vmmdev_hgcm_function_parameter path; 493 + 494 + /** 495 + * pointer, out: SHFLROOT (u32) 496 + * Root handle of the mapping which name is queried. 497 + */ 498 + struct vmmdev_hgcm_function_parameter root; 499 + 500 + /** 501 + * pointer, in: UTF16 502 + * Path delimiter 503 + */ 504 + struct vmmdev_hgcm_function_parameter delimiter; 505 + 506 + /** 507 + * pointer, in: SHFLROOT (u32) 508 + * Case senstive flag 509 + */ 510 + struct vmmdev_hgcm_function_parameter case_sensitive; 511 + 512 + }; 513 + 514 + /* Number of parameters */ 515 + #define SHFL_CPARMS_MAP_FOLDER (4) 516 + 517 + 518 + /** SHFL_FN_UNMAP_FOLDER Parameters structure. */ 519 + struct shfl_unmap_folder { 520 + /** 521 + * pointer, in: SHFLROOT (u32) 522 + * Root handle of the mapping which name is queried. 523 + */ 524 + struct vmmdev_hgcm_function_parameter root; 525 + 526 + }; 527 + 528 + /* Number of parameters */ 529 + #define SHFL_CPARMS_UNMAP_FOLDER (1) 530 + 531 + 532 + /** SHFL_FN_CREATE Parameters structure. */ 533 + struct shfl_create { 534 + /** 535 + * pointer, in: SHFLROOT (u32) 536 + * Root handle of the mapping which name is queried. 537 + */ 538 + struct vmmdev_hgcm_function_parameter root; 539 + 540 + /** 541 + * pointer, in: 542 + * Points to struct shfl_string buffer. 543 + */ 544 + struct vmmdev_hgcm_function_parameter path; 545 + 546 + /** 547 + * pointer, in/out: 548 + * Points to struct shfl_createparms buffer. 549 + */ 550 + struct vmmdev_hgcm_function_parameter parms; 551 + 552 + }; 553 + 554 + /* Number of parameters */ 555 + #define SHFL_CPARMS_CREATE (3) 556 + 557 + 558 + /** SHFL_FN_CLOSE Parameters structure. */ 559 + struct shfl_close { 560 + /** 561 + * pointer, in: SHFLROOT (u32) 562 + * Root handle of the mapping which name is queried. 563 + */ 564 + struct vmmdev_hgcm_function_parameter root; 565 + 566 + /** 567 + * value64, in: 568 + * SHFLHANDLE (u64) of object to close. 569 + */ 570 + struct vmmdev_hgcm_function_parameter handle; 571 + 572 + }; 573 + 574 + /* Number of parameters */ 575 + #define SHFL_CPARMS_CLOSE (2) 576 + 577 + 578 + /** SHFL_FN_READ Parameters structure. */ 579 + struct shfl_read { 580 + /** 581 + * pointer, in: SHFLROOT (u32) 582 + * Root handle of the mapping which name is queried. 583 + */ 584 + struct vmmdev_hgcm_function_parameter root; 585 + 586 + /** 587 + * value64, in: 588 + * SHFLHANDLE (u64) of object to read from. 589 + */ 590 + struct vmmdev_hgcm_function_parameter handle; 591 + 592 + /** 593 + * value64, in: 594 + * Offset to read from. 595 + */ 596 + struct vmmdev_hgcm_function_parameter offset; 597 + 598 + /** 599 + * value64, in/out: 600 + * Bytes to read/How many were read. 601 + */ 602 + struct vmmdev_hgcm_function_parameter cb; 603 + 604 + /** 605 + * pointer, out: 606 + * Buffer to place data to. 607 + */ 608 + struct vmmdev_hgcm_function_parameter buffer; 609 + 610 + }; 611 + 612 + /* Number of parameters */ 613 + #define SHFL_CPARMS_READ (5) 614 + 615 + 616 + /** SHFL_FN_WRITE Parameters structure. */ 617 + struct shfl_write { 618 + /** 619 + * pointer, in: SHFLROOT (u32) 620 + * Root handle of the mapping which name is queried. 621 + */ 622 + struct vmmdev_hgcm_function_parameter root; 623 + 624 + /** 625 + * value64, in: 626 + * SHFLHANDLE (u64) of object to write to. 627 + */ 628 + struct vmmdev_hgcm_function_parameter handle; 629 + 630 + /** 631 + * value64, in: 632 + * Offset to write to. 633 + */ 634 + struct vmmdev_hgcm_function_parameter offset; 635 + 636 + /** 637 + * value64, in/out: 638 + * Bytes to write/How many were written. 639 + */ 640 + struct vmmdev_hgcm_function_parameter cb; 641 + 642 + /** 643 + * pointer, in: 644 + * Data to write. 645 + */ 646 + struct vmmdev_hgcm_function_parameter buffer; 647 + 648 + }; 649 + 650 + /* Number of parameters */ 651 + #define SHFL_CPARMS_WRITE (5) 652 + 653 + 654 + /* 655 + * SHFL_FN_LIST 656 + * Listing information includes variable length RTDIRENTRY[EX] structures. 657 + */ 658 + 659 + #define SHFL_LIST_NONE 0 660 + #define SHFL_LIST_RETURN_ONE 1 661 + 662 + /** SHFL_FN_LIST Parameters structure. */ 663 + struct shfl_list { 664 + /** 665 + * pointer, in: SHFLROOT (u32) 666 + * Root handle of the mapping which name is queried. 667 + */ 668 + struct vmmdev_hgcm_function_parameter root; 669 + 670 + /** 671 + * value64, in: 672 + * SHFLHANDLE (u64) of object to be listed. 673 + */ 674 + struct vmmdev_hgcm_function_parameter handle; 675 + 676 + /** 677 + * value32, in: 678 + * List flags SHFL_LIST_*. 679 + */ 680 + struct vmmdev_hgcm_function_parameter flags; 681 + 682 + /** 683 + * value32, in/out: 684 + * Bytes to be used for listing information/How many bytes were used. 685 + */ 686 + struct vmmdev_hgcm_function_parameter cb; 687 + 688 + /** 689 + * pointer, in/optional 690 + * Points to struct shfl_string buffer that specifies a search path. 691 + */ 692 + struct vmmdev_hgcm_function_parameter path; 693 + 694 + /** 695 + * pointer, out: 696 + * Buffer to place listing information to. (struct shfl_dirinfo) 697 + */ 698 + struct vmmdev_hgcm_function_parameter buffer; 699 + 700 + /** 701 + * value32, in/out: 702 + * Indicates a key where the listing must be resumed. 703 + * in: 0 means start from begin of object. 704 + * out: 0 means listing completed. 705 + */ 706 + struct vmmdev_hgcm_function_parameter resume_point; 707 + 708 + /** 709 + * pointer, out: 710 + * Number of files returned 711 + */ 712 + struct vmmdev_hgcm_function_parameter file_count; 713 + }; 714 + 715 + /* Number of parameters */ 716 + #define SHFL_CPARMS_LIST (8) 717 + 718 + 719 + /** SHFL_FN_READLINK Parameters structure. */ 720 + struct shfl_readLink { 721 + /** 722 + * pointer, in: SHFLROOT (u32) 723 + * Root handle of the mapping which name is queried. 724 + */ 725 + struct vmmdev_hgcm_function_parameter root; 726 + 727 + /** 728 + * pointer, in: 729 + * Points to struct shfl_string buffer. 730 + */ 731 + struct vmmdev_hgcm_function_parameter path; 732 + 733 + /** 734 + * pointer, out: 735 + * Buffer to place data to. 736 + */ 737 + struct vmmdev_hgcm_function_parameter buffer; 738 + 739 + }; 740 + 741 + /* Number of parameters */ 742 + #define SHFL_CPARMS_READLINK (3) 743 + 744 + 745 + /* SHFL_FN_INFORMATION */ 746 + 747 + /* Mask of Set/Get bit. */ 748 + #define SHFL_INFO_MODE_MASK (0x1) 749 + /* Get information */ 750 + #define SHFL_INFO_GET (0x0) 751 + /* Set information */ 752 + #define SHFL_INFO_SET (0x1) 753 + 754 + /* Get name of the object. */ 755 + #define SHFL_INFO_NAME (0x2) 756 + /* Set size of object (extend/trucate); only applies to file objects */ 757 + #define SHFL_INFO_SIZE (0x4) 758 + /* Get/Set file object info. */ 759 + #define SHFL_INFO_FILE (0x8) 760 + /* Get volume information. */ 761 + #define SHFL_INFO_VOLUME (0x10) 762 + 763 + /** SHFL_FN_INFORMATION Parameters structure. */ 764 + struct shfl_information { 765 + /** 766 + * pointer, in: SHFLROOT (u32) 767 + * Root handle of the mapping which name is queried. 768 + */ 769 + struct vmmdev_hgcm_function_parameter root; 770 + 771 + /** 772 + * value64, in: 773 + * SHFLHANDLE (u64) of object to be listed. 774 + */ 775 + struct vmmdev_hgcm_function_parameter handle; 776 + 777 + /** 778 + * value32, in: 779 + * SHFL_INFO_* 780 + */ 781 + struct vmmdev_hgcm_function_parameter flags; 782 + 783 + /** 784 + * value32, in/out: 785 + * Bytes to be used for information/How many bytes were used. 786 + */ 787 + struct vmmdev_hgcm_function_parameter cb; 788 + 789 + /** 790 + * pointer, in/out: 791 + * Information to be set/get (shfl_fsobjinfo or shfl_string). Do not 792 + * forget to set the shfl_fsobjinfo::attr::additional for a get 793 + * operation as well. 794 + */ 795 + struct vmmdev_hgcm_function_parameter info; 796 + 797 + }; 798 + 799 + /* Number of parameters */ 800 + #define SHFL_CPARMS_INFORMATION (5) 801 + 802 + 803 + /* SHFL_FN_REMOVE */ 804 + 805 + #define SHFL_REMOVE_FILE (0x1) 806 + #define SHFL_REMOVE_DIR (0x2) 807 + #define SHFL_REMOVE_SYMLINK (0x4) 808 + 809 + /** SHFL_FN_REMOVE Parameters structure. */ 810 + struct shfl_remove { 811 + /** 812 + * pointer, in: SHFLROOT (u32) 813 + * Root handle of the mapping which name is queried. 814 + */ 815 + struct vmmdev_hgcm_function_parameter root; 816 + 817 + /** 818 + * pointer, in: 819 + * Points to struct shfl_string buffer. 820 + */ 821 + struct vmmdev_hgcm_function_parameter path; 822 + 823 + /** 824 + * value32, in: 825 + * remove flags (file/directory) 826 + */ 827 + struct vmmdev_hgcm_function_parameter flags; 828 + 829 + }; 830 + 831 + #define SHFL_CPARMS_REMOVE (3) 832 + 833 + 834 + /* SHFL_FN_RENAME */ 835 + 836 + #define SHFL_RENAME_FILE (0x1) 837 + #define SHFL_RENAME_DIR (0x2) 838 + #define SHFL_RENAME_REPLACE_IF_EXISTS (0x4) 839 + 840 + /** SHFL_FN_RENAME Parameters structure. */ 841 + struct shfl_rename { 842 + /** 843 + * pointer, in: SHFLROOT (u32) 844 + * Root handle of the mapping which name is queried. 845 + */ 846 + struct vmmdev_hgcm_function_parameter root; 847 + 848 + /** 849 + * pointer, in: 850 + * Points to struct shfl_string src. 851 + */ 852 + struct vmmdev_hgcm_function_parameter src; 853 + 854 + /** 855 + * pointer, in: 856 + * Points to struct shfl_string dest. 857 + */ 858 + struct vmmdev_hgcm_function_parameter dest; 859 + 860 + /** 861 + * value32, in: 862 + * rename flags (file/directory) 863 + */ 864 + struct vmmdev_hgcm_function_parameter flags; 865 + 866 + }; 867 + 868 + #define SHFL_CPARMS_RENAME (4) 869 + 870 + 871 + /** SHFL_FN_SYMLINK Parameters structure. */ 872 + struct shfl_symlink { 873 + /** 874 + * pointer, in: SHFLROOT (u32) 875 + * Root handle of the mapping which name is queried. 876 + */ 877 + struct vmmdev_hgcm_function_parameter root; 878 + 879 + /** 880 + * pointer, in: 881 + * Points to struct shfl_string of path for the new symlink. 882 + */ 883 + struct vmmdev_hgcm_function_parameter new_path; 884 + 885 + /** 886 + * pointer, in: 887 + * Points to struct shfl_string of destination for symlink. 888 + */ 889 + struct vmmdev_hgcm_function_parameter old_path; 890 + 891 + /** 892 + * pointer, out: 893 + * Information about created symlink. 894 + */ 895 + struct vmmdev_hgcm_function_parameter info; 896 + 897 + }; 898 + 899 + #define SHFL_CPARMS_SYMLINK (4) 900 + 901 + #endif
+501
drivers/staging/vboxsf/super.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * VirtualBox Guest Shared Folders support: Virtual File System. 4 + * 5 + * Module initialization/finalization 6 + * File system registration/deregistration 7 + * Superblock reading 8 + * Few utility functions 9 + * 10 + * Copyright (C) 2006-2018 Oracle Corporation 11 + */ 12 + 13 + #include <linux/idr.h> 14 + #include <linux/fs_parser.h> 15 + #include <linux/magic.h> 16 + #include <linux/module.h> 17 + #include <linux/nls.h> 18 + #include <linux/statfs.h> 19 + #include <linux/vbox_utils.h> 20 + #include "vfsmod.h" 21 + 22 + #define VBOXSF_SUPER_MAGIC 0x786f4256 /* 'VBox' little endian */ 23 + 24 + #define VBSF_MOUNT_SIGNATURE_BYTE_0 ('\000') 25 + #define VBSF_MOUNT_SIGNATURE_BYTE_1 ('\377') 26 + #define VBSF_MOUNT_SIGNATURE_BYTE_2 ('\376') 27 + #define VBSF_MOUNT_SIGNATURE_BYTE_3 ('\375') 28 + 29 + static int follow_symlinks; 30 + module_param(follow_symlinks, int, 0444); 31 + MODULE_PARM_DESC(follow_symlinks, 32 + "Let host resolve symlinks rather than showing them"); 33 + 34 + static DEFINE_IDA(vboxsf_bdi_ida); 35 + static DEFINE_MUTEX(vboxsf_setup_mutex); 36 + static bool vboxsf_setup_done; 37 + static struct super_operations vboxsf_super_ops; /* forward declaration */ 38 + static struct kmem_cache *vboxsf_inode_cachep; 39 + 40 + static char * const vboxsf_default_nls = CONFIG_NLS_DEFAULT; 41 + 42 + enum { opt_nls, opt_uid, opt_gid, opt_ttl, opt_dmode, opt_fmode, 43 + opt_dmask, opt_fmask }; 44 + 45 + static const struct fs_parameter_spec vboxsf_param_specs[] = { 46 + fsparam_string ("nls", opt_nls), 47 + fsparam_u32 ("uid", opt_uid), 48 + fsparam_u32 ("gid", opt_gid), 49 + fsparam_u32 ("ttl", opt_ttl), 50 + fsparam_u32oct ("dmode", opt_dmode), 51 + fsparam_u32oct ("fmode", opt_fmode), 52 + fsparam_u32oct ("dmask", opt_dmask), 53 + fsparam_u32oct ("fmask", opt_fmask), 54 + {} 55 + }; 56 + 57 + static const struct fs_parameter_description vboxsf_fs_parameters = { 58 + .name = "vboxsf", 59 + .specs = vboxsf_param_specs, 60 + }; 61 + 62 + static int vboxsf_parse_param(struct fs_context *fc, struct fs_parameter *param) 63 + { 64 + struct vboxsf_fs_context *ctx = fc->fs_private; 65 + struct fs_parse_result result; 66 + kuid_t uid; 67 + kgid_t gid; 68 + int opt; 69 + 70 + opt = fs_parse(fc, &vboxsf_fs_parameters, param, &result); 71 + if (opt < 0) 72 + return opt; 73 + 74 + switch (opt) { 75 + case opt_nls: 76 + if (fc->purpose != FS_CONTEXT_FOR_MOUNT) { 77 + vbg_err("vboxsf: Cannot reconfigure nls option\n"); 78 + return -EINVAL; 79 + } 80 + ctx->nls_name = param->string; 81 + param->string = NULL; 82 + break; 83 + case opt_uid: 84 + uid = make_kuid(current_user_ns(), result.uint_32); 85 + if (!uid_valid(uid)) 86 + return -EINVAL; 87 + ctx->o.uid = uid; 88 + break; 89 + case opt_gid: 90 + gid = make_kgid(current_user_ns(), result.uint_32); 91 + if (!gid_valid(gid)) 92 + return -EINVAL; 93 + ctx->o.gid = gid; 94 + break; 95 + case opt_ttl: 96 + ctx->o.ttl = msecs_to_jiffies(result.uint_32); 97 + break; 98 + case opt_dmode: 99 + if (result.uint_32 & ~0777) 100 + return -EINVAL; 101 + ctx->o.dmode = result.uint_32; 102 + ctx->o.dmode_set = true; 103 + break; 104 + case opt_fmode: 105 + if (result.uint_32 & ~0777) 106 + return -EINVAL; 107 + ctx->o.fmode = result.uint_32; 108 + ctx->o.fmode_set = true; 109 + break; 110 + case opt_dmask: 111 + if (result.uint_32 & ~07777) 112 + return -EINVAL; 113 + ctx->o.dmask = result.uint_32; 114 + break; 115 + case opt_fmask: 116 + if (result.uint_32 & ~07777) 117 + return -EINVAL; 118 + ctx->o.fmask = result.uint_32; 119 + break; 120 + default: 121 + return -EINVAL; 122 + } 123 + 124 + return 0; 125 + } 126 + 127 + static int vboxsf_fill_super(struct super_block *sb, struct fs_context *fc) 128 + { 129 + struct vboxsf_fs_context *ctx = fc->fs_private; 130 + struct shfl_string *folder_name, root_path; 131 + struct vboxsf_sbi *sbi; 132 + struct dentry *droot; 133 + struct inode *iroot; 134 + char *nls_name; 135 + size_t size; 136 + int err; 137 + 138 + if (!fc->source) 139 + return -EINVAL; 140 + 141 + sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); 142 + if (!sbi) 143 + return -ENOMEM; 144 + 145 + sbi->o = ctx->o; 146 + idr_init(&sbi->ino_idr); 147 + spin_lock_init(&sbi->ino_idr_lock); 148 + sbi->next_generation = 1; 149 + sbi->bdi_id = -1; 150 + 151 + /* Load nls if not utf8 */ 152 + nls_name = ctx->nls_name ? ctx->nls_name : vboxsf_default_nls; 153 + if (strcmp(nls_name, "utf8") != 0) { 154 + if (nls_name == vboxsf_default_nls) 155 + sbi->nls = load_nls_default(); 156 + else 157 + sbi->nls = load_nls(nls_name); 158 + 159 + if (!sbi->nls) { 160 + vbg_err("vboxsf: Count not load '%s' nls\n", nls_name); 161 + err = -EINVAL; 162 + goto fail_free; 163 + } 164 + } 165 + 166 + sbi->bdi_id = ida_simple_get(&vboxsf_bdi_ida, 0, 0, GFP_KERNEL); 167 + if (sbi->bdi_id < 0) { 168 + err = sbi->bdi_id; 169 + goto fail_free; 170 + } 171 + 172 + err = super_setup_bdi_name(sb, "vboxsf-%s.%d", fc->source, sbi->bdi_id); 173 + if (err) 174 + goto fail_free; 175 + 176 + /* Turn source into a shfl_string and map the folder */ 177 + size = strlen(fc->source) + 1; 178 + folder_name = kmalloc(SHFLSTRING_HEADER_SIZE + size, GFP_KERNEL); 179 + if (!folder_name) { 180 + err = -ENOMEM; 181 + goto fail_free; 182 + } 183 + folder_name->size = size; 184 + folder_name->length = size - 1; 185 + strlcpy(folder_name->string.utf8, fc->source, size); 186 + err = vboxsf_map_folder(folder_name, &sbi->root); 187 + kfree(folder_name); 188 + if (err) { 189 + vbg_err("vboxsf: Host rejected mount of '%s' with error %d\n", 190 + fc->source, err); 191 + goto fail_free; 192 + } 193 + 194 + root_path.length = 1; 195 + root_path.size = 2; 196 + root_path.string.utf8[0] = '/'; 197 + root_path.string.utf8[1] = 0; 198 + err = vboxsf_stat(sbi, &root_path, &sbi->root_info); 199 + if (err) 200 + goto fail_unmap; 201 + 202 + sb->s_magic = VBOXSF_SUPER_MAGIC; 203 + sb->s_blocksize = 1024; 204 + sb->s_maxbytes = MAX_LFS_FILESIZE; 205 + sb->s_op = &vboxsf_super_ops; 206 + sb->s_d_op = &vboxsf_dentry_ops; 207 + 208 + iroot = iget_locked(sb, 0); 209 + if (!iroot) { 210 + err = -ENOMEM; 211 + goto fail_unmap; 212 + } 213 + vboxsf_init_inode(sbi, iroot, &sbi->root_info); 214 + unlock_new_inode(iroot); 215 + 216 + droot = d_make_root(iroot); 217 + if (!droot) { 218 + err = -ENOMEM; 219 + goto fail_unmap; 220 + } 221 + 222 + sb->s_root = droot; 223 + sb->s_fs_info = sbi; 224 + return 0; 225 + 226 + fail_unmap: 227 + vboxsf_unmap_folder(sbi->root); 228 + fail_free: 229 + if (sbi->bdi_id >= 0) 230 + ida_simple_remove(&vboxsf_bdi_ida, sbi->bdi_id); 231 + if (sbi->nls) 232 + unload_nls(sbi->nls); 233 + idr_destroy(&sbi->ino_idr); 234 + kfree(sbi); 235 + return err; 236 + } 237 + 238 + static void vboxsf_inode_init_once(void *data) 239 + { 240 + struct vboxsf_inode *sf_i = data; 241 + 242 + mutex_init(&sf_i->handle_list_mutex); 243 + inode_init_once(&sf_i->vfs_inode); 244 + } 245 + 246 + static struct inode *vboxsf_alloc_inode(struct super_block *sb) 247 + { 248 + struct vboxsf_inode *sf_i; 249 + 250 + sf_i = kmem_cache_alloc(vboxsf_inode_cachep, GFP_NOFS); 251 + if (!sf_i) 252 + return NULL; 253 + 254 + sf_i->force_restat = 0; 255 + INIT_LIST_HEAD(&sf_i->handle_list); 256 + 257 + return &sf_i->vfs_inode; 258 + } 259 + 260 + static void vboxsf_free_inode(struct inode *inode) 261 + { 262 + struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb); 263 + unsigned long flags; 264 + 265 + spin_lock_irqsave(&sbi->ino_idr_lock, flags); 266 + idr_remove(&sbi->ino_idr, inode->i_ino); 267 + spin_unlock_irqrestore(&sbi->ino_idr_lock, flags); 268 + kmem_cache_free(vboxsf_inode_cachep, VBOXSF_I(inode)); 269 + } 270 + 271 + static void vboxsf_put_super(struct super_block *sb) 272 + { 273 + struct vboxsf_sbi *sbi = VBOXSF_SBI(sb); 274 + 275 + vboxsf_unmap_folder(sbi->root); 276 + if (sbi->bdi_id >= 0) 277 + ida_simple_remove(&vboxsf_bdi_ida, sbi->bdi_id); 278 + if (sbi->nls) 279 + unload_nls(sbi->nls); 280 + 281 + /* 282 + * vboxsf_free_inode uses the idr, make sure all delayed rcu free 283 + * inodes are flushed. 284 + */ 285 + rcu_barrier(); 286 + idr_destroy(&sbi->ino_idr); 287 + kfree(sbi); 288 + } 289 + 290 + static int vboxsf_statfs(struct dentry *dentry, struct kstatfs *stat) 291 + { 292 + struct super_block *sb = dentry->d_sb; 293 + struct shfl_volinfo shfl_volinfo; 294 + struct vboxsf_sbi *sbi; 295 + u32 buf_len; 296 + int err; 297 + 298 + sbi = VBOXSF_SBI(sb); 299 + buf_len = sizeof(shfl_volinfo); 300 + err = vboxsf_fsinfo(sbi->root, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME, 301 + &buf_len, &shfl_volinfo); 302 + if (err) 303 + return err; 304 + 305 + stat->f_type = VBOXSF_SUPER_MAGIC; 306 + stat->f_bsize = shfl_volinfo.bytes_per_allocation_unit; 307 + 308 + do_div(shfl_volinfo.total_allocation_bytes, 309 + shfl_volinfo.bytes_per_allocation_unit); 310 + stat->f_blocks = shfl_volinfo.total_allocation_bytes; 311 + 312 + do_div(shfl_volinfo.available_allocation_bytes, 313 + shfl_volinfo.bytes_per_allocation_unit); 314 + stat->f_bfree = shfl_volinfo.available_allocation_bytes; 315 + stat->f_bavail = shfl_volinfo.available_allocation_bytes; 316 + 317 + stat->f_files = 1000; 318 + /* 319 + * Don't return 0 here since the guest may then think that it is not 320 + * possible to create any more files. 321 + */ 322 + stat->f_ffree = 1000000; 323 + stat->f_fsid.val[0] = 0; 324 + stat->f_fsid.val[1] = 0; 325 + stat->f_namelen = 255; 326 + return 0; 327 + } 328 + 329 + static struct super_operations vboxsf_super_ops = { 330 + .alloc_inode = vboxsf_alloc_inode, 331 + .free_inode = vboxsf_free_inode, 332 + .put_super = vboxsf_put_super, 333 + .statfs = vboxsf_statfs, 334 + }; 335 + 336 + static int vboxsf_setup(void) 337 + { 338 + int err; 339 + 340 + mutex_lock(&vboxsf_setup_mutex); 341 + 342 + if (vboxsf_setup_done) 343 + goto success; 344 + 345 + vboxsf_inode_cachep = 346 + kmem_cache_create("vboxsf_inode_cache", 347 + sizeof(struct vboxsf_inode), 0, 348 + (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD | 349 + SLAB_ACCOUNT), 350 + vboxsf_inode_init_once); 351 + if (!vboxsf_inode_cachep) { 352 + err = -ENOMEM; 353 + goto fail_nomem; 354 + } 355 + 356 + err = vboxsf_connect(); 357 + if (err) { 358 + vbg_err("vboxsf: err %d connecting to guest PCI-device\n", err); 359 + vbg_err("vboxsf: make sure you are inside a VirtualBox VM\n"); 360 + vbg_err("vboxsf: and check dmesg for vboxguest errors\n"); 361 + goto fail_free_cache; 362 + } 363 + 364 + err = vboxsf_set_utf8(); 365 + if (err) { 366 + vbg_err("vboxsf_setutf8 error %d\n", err); 367 + goto fail_disconnect; 368 + } 369 + 370 + if (!follow_symlinks) { 371 + err = vboxsf_set_symlinks(); 372 + if (err) 373 + vbg_warn("vboxsf: Unable to show symlinks: %d\n", err); 374 + } 375 + 376 + vboxsf_setup_done = true; 377 + success: 378 + mutex_unlock(&vboxsf_setup_mutex); 379 + return 0; 380 + 381 + fail_disconnect: 382 + vboxsf_disconnect(); 383 + fail_free_cache: 384 + kmem_cache_destroy(vboxsf_inode_cachep); 385 + fail_nomem: 386 + mutex_unlock(&vboxsf_setup_mutex); 387 + return err; 388 + } 389 + 390 + static int vboxsf_parse_monolithic(struct fs_context *fc, void *data) 391 + { 392 + char *options = data; 393 + 394 + if (options && options[0] == VBSF_MOUNT_SIGNATURE_BYTE_0 && 395 + options[1] == VBSF_MOUNT_SIGNATURE_BYTE_1 && 396 + options[2] == VBSF_MOUNT_SIGNATURE_BYTE_2 && 397 + options[3] == VBSF_MOUNT_SIGNATURE_BYTE_3) { 398 + vbg_err("vboxsf: Old binary mount data not supported, remove obsolete mount.vboxsf and/or update your VBoxService.\n"); 399 + return -EINVAL; 400 + } 401 + 402 + return generic_parse_monolithic(fc, data); 403 + } 404 + 405 + static int vboxsf_get_tree(struct fs_context *fc) 406 + { 407 + int err; 408 + 409 + err = vboxsf_setup(); 410 + if (err) 411 + return err; 412 + 413 + return vfs_get_super(fc, vfs_get_independent_super, vboxsf_fill_super); 414 + } 415 + 416 + static int vboxsf_reconfigure(struct fs_context *fc) 417 + { 418 + struct vboxsf_sbi *sbi = VBOXSF_SBI(fc->root->d_sb); 419 + struct vboxsf_fs_context *ctx = fc->fs_private; 420 + struct inode *iroot; 421 + 422 + iroot = ilookup(fc->root->d_sb, 0); 423 + if (!iroot) 424 + return -ENOENT; 425 + 426 + /* Apply changed options to the root inode */ 427 + sbi->o = ctx->o; 428 + vboxsf_init_inode(sbi, iroot, &sbi->root_info); 429 + 430 + return 0; 431 + } 432 + 433 + static void vboxsf_free_fc(struct fs_context *fc) 434 + { 435 + struct vboxsf_fs_context *ctx = fc->fs_private; 436 + 437 + kfree(ctx->nls_name); 438 + kfree(ctx); 439 + } 440 + 441 + static const struct fs_context_operations vboxsf_context_ops = { 442 + .free = vboxsf_free_fc, 443 + .parse_param = vboxsf_parse_param, 444 + .parse_monolithic = vboxsf_parse_monolithic, 445 + .get_tree = vboxsf_get_tree, 446 + .reconfigure = vboxsf_reconfigure, 447 + }; 448 + 449 + static int vboxsf_init_fs_context(struct fs_context *fc) 450 + { 451 + struct vboxsf_fs_context *ctx; 452 + 453 + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 454 + if (!ctx) 455 + return -ENOMEM; 456 + 457 + current_uid_gid(&ctx->o.uid, &ctx->o.gid); 458 + 459 + fc->fs_private = ctx; 460 + fc->ops = &vboxsf_context_ops; 461 + return 0; 462 + } 463 + 464 + static struct file_system_type vboxsf_fs_type = { 465 + .owner = THIS_MODULE, 466 + .name = "vboxsf", 467 + .init_fs_context = vboxsf_init_fs_context, 468 + .parameters = &vboxsf_fs_parameters, 469 + .kill_sb = kill_anon_super 470 + }; 471 + 472 + /* Module initialization/finalization handlers */ 473 + static int __init vboxsf_init(void) 474 + { 475 + return register_filesystem(&vboxsf_fs_type); 476 + } 477 + 478 + static void __exit vboxsf_fini(void) 479 + { 480 + unregister_filesystem(&vboxsf_fs_type); 481 + 482 + mutex_lock(&vboxsf_setup_mutex); 483 + if (vboxsf_setup_done) { 484 + vboxsf_disconnect(); 485 + /* 486 + * Make sure all delayed rcu free inodes are flushed 487 + * before we destroy the cache. 488 + */ 489 + rcu_barrier(); 490 + kmem_cache_destroy(vboxsf_inode_cachep); 491 + } 492 + mutex_unlock(&vboxsf_setup_mutex); 493 + } 494 + 495 + module_init(vboxsf_init); 496 + module_exit(vboxsf_fini); 497 + 498 + MODULE_DESCRIPTION("Oracle VM VirtualBox Module for Host File System Access"); 499 + MODULE_AUTHOR("Oracle Corporation"); 500 + MODULE_LICENSE("GPL v2"); 501 + MODULE_ALIAS_FS("vboxsf");
+551
drivers/staging/vboxsf/utils.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * VirtualBox Guest Shared Folders support: Utility functions. 4 + * Mainly conversion from/to VirtualBox/Linux data structures. 5 + * 6 + * Copyright (C) 2006-2018 Oracle Corporation 7 + */ 8 + 9 + #include <linux/namei.h> 10 + #include <linux/nls.h> 11 + #include <linux/sizes.h> 12 + #include <linux/vfs.h> 13 + #include "vfsmod.h" 14 + 15 + struct inode *vboxsf_new_inode(struct super_block *sb) 16 + { 17 + struct vboxsf_sbi *sbi = VBOXSF_SBI(sb); 18 + struct inode *inode; 19 + unsigned long flags; 20 + int cursor, ret; 21 + u32 gen; 22 + 23 + inode = new_inode(sb); 24 + if (!inode) 25 + return ERR_PTR(-ENOMEM); 26 + 27 + idr_preload(GFP_KERNEL); 28 + spin_lock_irqsave(&sbi->ino_idr_lock, flags); 29 + cursor = idr_get_cursor(&sbi->ino_idr); 30 + ret = idr_alloc_cyclic(&sbi->ino_idr, inode, 1, 0, GFP_ATOMIC); 31 + if (ret >= 0 && ret < cursor) 32 + sbi->next_generation++; 33 + gen = sbi->next_generation; 34 + spin_unlock_irqrestore(&sbi->ino_idr_lock, flags); 35 + idr_preload_end(); 36 + 37 + if (ret < 0) { 38 + iput(inode); 39 + return ERR_PTR(ret); 40 + } 41 + 42 + inode->i_ino = ret; 43 + inode->i_generation = gen; 44 + return inode; 45 + } 46 + 47 + /* set [inode] attributes based on [info], uid/gid based on [sbi] */ 48 + void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode, 49 + const struct shfl_fsobjinfo *info) 50 + { 51 + const struct shfl_fsobjattr *attr; 52 + s64 allocated; 53 + int mode; 54 + 55 + attr = &info->attr; 56 + 57 + #define mode_set(r) ((attr->mode & (SHFL_UNIX_##r)) ? (S_##r) : 0) 58 + 59 + mode = mode_set(IRUSR); 60 + mode |= mode_set(IWUSR); 61 + mode |= mode_set(IXUSR); 62 + 63 + mode |= mode_set(IRGRP); 64 + mode |= mode_set(IWGRP); 65 + mode |= mode_set(IXGRP); 66 + 67 + mode |= mode_set(IROTH); 68 + mode |= mode_set(IWOTH); 69 + mode |= mode_set(IXOTH); 70 + 71 + #undef mode_set 72 + 73 + /* We use the host-side values for these */ 74 + inode->i_flags |= S_NOATIME | S_NOCMTIME; 75 + inode->i_mapping->a_ops = &vboxsf_reg_aops; 76 + 77 + if (SHFL_IS_DIRECTORY(attr->mode)) { 78 + inode->i_mode = sbi->o.dmode_set ? sbi->o.dmode : mode; 79 + inode->i_mode &= ~sbi->o.dmask; 80 + inode->i_mode |= S_IFDIR; 81 + inode->i_op = &vboxsf_dir_iops; 82 + inode->i_fop = &vboxsf_dir_fops; 83 + /* 84 + * XXX: this probably should be set to the number of entries 85 + * in the directory plus two (. ..) 86 + */ 87 + set_nlink(inode, 1); 88 + } else if (SHFL_IS_SYMLINK(attr->mode)) { 89 + inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode; 90 + inode->i_mode &= ~sbi->o.fmask; 91 + inode->i_mode |= S_IFLNK; 92 + inode->i_op = &vboxsf_lnk_iops; 93 + set_nlink(inode, 1); 94 + } else { 95 + inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode; 96 + inode->i_mode &= ~sbi->o.fmask; 97 + inode->i_mode |= S_IFREG; 98 + inode->i_op = &vboxsf_reg_iops; 99 + inode->i_fop = &vboxsf_reg_fops; 100 + set_nlink(inode, 1); 101 + } 102 + 103 + inode->i_uid = sbi->o.uid; 104 + inode->i_gid = sbi->o.gid; 105 + 106 + inode->i_size = info->size; 107 + inode->i_blkbits = 12; 108 + /* i_blocks always in units of 512 bytes! */ 109 + allocated = info->allocated + 511; 110 + do_div(allocated, 512); 111 + inode->i_blocks = allocated; 112 + 113 + inode->i_atime = ns_to_timespec64( 114 + info->access_time.ns_relative_to_unix_epoch); 115 + inode->i_ctime = ns_to_timespec64( 116 + info->change_time.ns_relative_to_unix_epoch); 117 + inode->i_mtime = ns_to_timespec64( 118 + info->modification_time.ns_relative_to_unix_epoch); 119 + } 120 + 121 + int vboxsf_create_at_dentry(struct dentry *dentry, 122 + struct shfl_createparms *params) 123 + { 124 + struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb); 125 + struct shfl_string *path; 126 + int err; 127 + 128 + path = vboxsf_path_from_dentry(sbi, dentry); 129 + if (IS_ERR(path)) 130 + return PTR_ERR(path); 131 + 132 + err = vboxsf_create(sbi->root, path, params); 133 + __putname(path); 134 + 135 + return err; 136 + } 137 + 138 + int vboxsf_stat(struct vboxsf_sbi *sbi, struct shfl_string *path, 139 + struct shfl_fsobjinfo *info) 140 + { 141 + struct shfl_createparms params = {}; 142 + int err; 143 + 144 + params.handle = SHFL_HANDLE_NIL; 145 + params.create_flags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW; 146 + 147 + err = vboxsf_create(sbi->root, path, &params); 148 + if (err) 149 + return err; 150 + 151 + if (params.result != SHFL_FILE_EXISTS) 152 + return -ENOENT; 153 + 154 + if (info) 155 + *info = params.info; 156 + 157 + return 0; 158 + } 159 + 160 + int vboxsf_stat_dentry(struct dentry *dentry, struct shfl_fsobjinfo *info) 161 + { 162 + struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb); 163 + struct shfl_string *path; 164 + int err; 165 + 166 + path = vboxsf_path_from_dentry(sbi, dentry); 167 + if (IS_ERR(path)) 168 + return PTR_ERR(path); 169 + 170 + err = vboxsf_stat(sbi, path, info); 171 + __putname(path); 172 + return err; 173 + } 174 + 175 + int vboxsf_inode_revalidate(struct dentry *dentry) 176 + { 177 + struct vboxsf_sbi *sbi; 178 + struct vboxsf_inode *sf_i; 179 + struct shfl_fsobjinfo info; 180 + struct timespec64 prev_mtime; 181 + struct inode *inode; 182 + int err; 183 + 184 + if (!dentry || !d_really_is_positive(dentry)) 185 + return -EINVAL; 186 + 187 + inode = d_inode(dentry); 188 + prev_mtime = inode->i_mtime; 189 + sf_i = VBOXSF_I(inode); 190 + sbi = VBOXSF_SBI(dentry->d_sb); 191 + if (!sf_i->force_restat) { 192 + if (time_before(jiffies, dentry->d_time + sbi->o.ttl)) 193 + return 0; 194 + } 195 + 196 + err = vboxsf_stat_dentry(dentry, &info); 197 + if (err) 198 + return err; 199 + 200 + dentry->d_time = jiffies; 201 + sf_i->force_restat = 0; 202 + vboxsf_init_inode(sbi, inode, &info); 203 + 204 + /* 205 + * If the file was changed on the host side we need to invalidate the 206 + * page-cache for it. Note this also gets triggered by our own writes, 207 + * this is unavoidable. 208 + */ 209 + if (timespec64_compare(&inode->i_mtime, &prev_mtime) > 0) 210 + invalidate_inode_pages2(inode->i_mapping); 211 + 212 + return 0; 213 + } 214 + 215 + int vboxsf_getattr(const struct path *path, struct kstat *kstat, 216 + u32 request_mask, unsigned int flags) 217 + { 218 + int err; 219 + struct dentry *dentry = path->dentry; 220 + struct inode *inode = d_inode(dentry); 221 + struct vboxsf_inode *sf_i = VBOXSF_I(inode); 222 + 223 + switch (flags & AT_STATX_SYNC_TYPE) { 224 + case AT_STATX_DONT_SYNC: 225 + err = 0; 226 + break; 227 + case AT_STATX_FORCE_SYNC: 228 + sf_i->force_restat = 1; 229 + /* fall-through */ 230 + default: 231 + err = vboxsf_inode_revalidate(dentry); 232 + } 233 + if (err) 234 + return err; 235 + 236 + generic_fillattr(d_inode(dentry), kstat); 237 + return 0; 238 + } 239 + 240 + int vboxsf_setattr(struct dentry *dentry, struct iattr *iattr) 241 + { 242 + struct vboxsf_inode *sf_i = VBOXSF_I(d_inode(dentry)); 243 + struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb); 244 + struct shfl_createparms params = {}; 245 + struct shfl_fsobjinfo info = {}; 246 + u32 buf_len; 247 + int err; 248 + 249 + params.handle = SHFL_HANDLE_NIL; 250 + params.create_flags = SHFL_CF_ACT_OPEN_IF_EXISTS | 251 + SHFL_CF_ACT_FAIL_IF_NEW | 252 + SHFL_CF_ACCESS_ATTR_WRITE; 253 + 254 + /* this is at least required for Posix hosts */ 255 + if (iattr->ia_valid & ATTR_SIZE) 256 + params.create_flags |= SHFL_CF_ACCESS_WRITE; 257 + 258 + err = vboxsf_create_at_dentry(dentry, &params); 259 + if (err || params.result != SHFL_FILE_EXISTS) 260 + return err ? err : -ENOENT; 261 + 262 + #define mode_set(r) ((iattr->ia_mode & (S_##r)) ? SHFL_UNIX_##r : 0) 263 + 264 + /* 265 + * Setting the file size and setting the other attributes has to 266 + * be handled separately. 267 + */ 268 + if (iattr->ia_valid & (ATTR_MODE | ATTR_ATIME | ATTR_MTIME)) { 269 + if (iattr->ia_valid & ATTR_MODE) { 270 + info.attr.mode = mode_set(IRUSR); 271 + info.attr.mode |= mode_set(IWUSR); 272 + info.attr.mode |= mode_set(IXUSR); 273 + info.attr.mode |= mode_set(IRGRP); 274 + info.attr.mode |= mode_set(IWGRP); 275 + info.attr.mode |= mode_set(IXGRP); 276 + info.attr.mode |= mode_set(IROTH); 277 + info.attr.mode |= mode_set(IWOTH); 278 + info.attr.mode |= mode_set(IXOTH); 279 + 280 + if (iattr->ia_mode & S_IFDIR) 281 + info.attr.mode |= SHFL_TYPE_DIRECTORY; 282 + else 283 + info.attr.mode |= SHFL_TYPE_FILE; 284 + } 285 + 286 + if (iattr->ia_valid & ATTR_ATIME) 287 + info.access_time.ns_relative_to_unix_epoch = 288 + timespec64_to_ns(&iattr->ia_atime); 289 + 290 + if (iattr->ia_valid & ATTR_MTIME) 291 + info.modification_time.ns_relative_to_unix_epoch = 292 + timespec64_to_ns(&iattr->ia_mtime); 293 + 294 + /* 295 + * Ignore ctime (inode change time) as it can't be set 296 + * from userland anyway. 297 + */ 298 + 299 + buf_len = sizeof(info); 300 + err = vboxsf_fsinfo(sbi->root, params.handle, 301 + SHFL_INFO_SET | SHFL_INFO_FILE, &buf_len, 302 + &info); 303 + if (err) { 304 + vboxsf_close(sbi->root, params.handle); 305 + return err; 306 + } 307 + 308 + /* the host may have given us different attr then requested */ 309 + sf_i->force_restat = 1; 310 + } 311 + 312 + #undef mode_set 313 + 314 + if (iattr->ia_valid & ATTR_SIZE) { 315 + memset(&info, 0, sizeof(info)); 316 + info.size = iattr->ia_size; 317 + buf_len = sizeof(info); 318 + err = vboxsf_fsinfo(sbi->root, params.handle, 319 + SHFL_INFO_SET | SHFL_INFO_SIZE, &buf_len, 320 + &info); 321 + if (err) { 322 + vboxsf_close(sbi->root, params.handle); 323 + return err; 324 + } 325 + 326 + /* the host may have given us different attr then requested */ 327 + sf_i->force_restat = 1; 328 + } 329 + 330 + vboxsf_close(sbi->root, params.handle); 331 + 332 + /* Update the inode with what the host has actually given us. */ 333 + if (sf_i->force_restat) 334 + vboxsf_inode_revalidate(dentry); 335 + 336 + return 0; 337 + } 338 + 339 + /* 340 + * [dentry] contains string encoded in coding system that corresponds 341 + * to [sbi]->nls, we must convert it to UTF8 here. 342 + * Returns a shfl_string allocated through __getname (must be freed using 343 + * __putname), or an ERR_PTR on error. 344 + */ 345 + struct shfl_string *vboxsf_path_from_dentry(struct vboxsf_sbi *sbi, 346 + struct dentry *dentry) 347 + { 348 + struct shfl_string *shfl_path; 349 + int path_len, out_len, nb; 350 + char *buf, *path; 351 + wchar_t uni; 352 + u8 *out; 353 + 354 + buf = __getname(); 355 + if (!buf) 356 + return ERR_PTR(-ENOMEM); 357 + 358 + path = dentry_path_raw(dentry, buf, PATH_MAX); 359 + if (IS_ERR(path)) { 360 + __putname(buf); 361 + return (struct shfl_string *)path; 362 + } 363 + path_len = strlen(path); 364 + 365 + if (sbi->nls) { 366 + shfl_path = __getname(); 367 + if (!shfl_path) { 368 + __putname(buf); 369 + return ERR_PTR(-ENOMEM); 370 + } 371 + 372 + out = shfl_path->string.utf8; 373 + out_len = PATH_MAX - SHFLSTRING_HEADER_SIZE - 1; 374 + 375 + while (path_len) { 376 + nb = sbi->nls->char2uni(path, path_len, &uni); 377 + if (nb < 0) { 378 + __putname(shfl_path); 379 + __putname(buf); 380 + return ERR_PTR(-EINVAL); 381 + } 382 + path += nb; 383 + path_len -= nb; 384 + 385 + nb = utf32_to_utf8(uni, out, out_len); 386 + if (nb < 0) { 387 + __putname(shfl_path); 388 + __putname(buf); 389 + return ERR_PTR(-ENAMETOOLONG); 390 + } 391 + out += nb; 392 + out_len -= nb; 393 + } 394 + *out = 0; 395 + shfl_path->length = out - shfl_path->string.utf8; 396 + shfl_path->size = shfl_path->length + 1; 397 + __putname(buf); 398 + } else { 399 + if ((SHFLSTRING_HEADER_SIZE + path_len + 1) > PATH_MAX) { 400 + __putname(buf); 401 + return ERR_PTR(-ENAMETOOLONG); 402 + } 403 + /* 404 + * dentry_path stores the name at the end of buf, but the 405 + * shfl_string string we return must be properly aligned. 406 + */ 407 + shfl_path = (struct shfl_string *)buf; 408 + memmove(shfl_path->string.utf8, path, path_len); 409 + shfl_path->string.utf8[path_len] = 0; 410 + shfl_path->length = path_len; 411 + shfl_path->size = path_len + 1; 412 + } 413 + 414 + return shfl_path; 415 + } 416 + 417 + int vboxsf_nlscpy(struct vboxsf_sbi *sbi, char *name, size_t name_bound_len, 418 + const unsigned char *utf8_name, size_t utf8_len) 419 + { 420 + const char *in; 421 + char *out; 422 + size_t out_len; 423 + size_t out_bound_len; 424 + size_t in_bound_len; 425 + 426 + in = utf8_name; 427 + in_bound_len = utf8_len; 428 + 429 + out = name; 430 + out_len = 0; 431 + /* Reserve space for terminating 0 */ 432 + out_bound_len = name_bound_len - 1; 433 + 434 + while (in_bound_len) { 435 + int nb; 436 + unicode_t uni; 437 + 438 + nb = utf8_to_utf32(in, in_bound_len, &uni); 439 + if (nb < 0) 440 + return -EINVAL; 441 + 442 + in += nb; 443 + in_bound_len -= nb; 444 + 445 + nb = sbi->nls->uni2char(uni, out, out_bound_len); 446 + if (nb < 0) 447 + return nb; 448 + 449 + out += nb; 450 + out_bound_len -= nb; 451 + out_len += nb; 452 + } 453 + 454 + *out = 0; 455 + 456 + return 0; 457 + } 458 + 459 + static struct vboxsf_dir_buf *vboxsf_dir_buf_alloc(struct list_head *list) 460 + { 461 + struct vboxsf_dir_buf *b; 462 + 463 + b = kmalloc(sizeof(*b), GFP_KERNEL); 464 + if (!b) 465 + return NULL; 466 + 467 + b->buf = kmalloc(DIR_BUFFER_SIZE, GFP_KERNEL); 468 + if (!b->buf) { 469 + kfree(b); 470 + return NULL; 471 + } 472 + 473 + b->entries = 0; 474 + b->used = 0; 475 + b->free = DIR_BUFFER_SIZE; 476 + list_add(&b->head, list); 477 + 478 + return b; 479 + } 480 + 481 + static void vboxsf_dir_buf_free(struct vboxsf_dir_buf *b) 482 + { 483 + list_del(&b->head); 484 + kfree(b->buf); 485 + kfree(b); 486 + } 487 + 488 + struct vboxsf_dir_info *vboxsf_dir_info_alloc(void) 489 + { 490 + struct vboxsf_dir_info *p; 491 + 492 + p = kmalloc(sizeof(*p), GFP_KERNEL); 493 + if (!p) 494 + return NULL; 495 + 496 + INIT_LIST_HEAD(&p->info_list); 497 + return p; 498 + } 499 + 500 + void vboxsf_dir_info_free(struct vboxsf_dir_info *p) 501 + { 502 + struct list_head *list, *pos, *tmp; 503 + 504 + list = &p->info_list; 505 + list_for_each_safe(pos, tmp, list) { 506 + struct vboxsf_dir_buf *b; 507 + 508 + b = list_entry(pos, struct vboxsf_dir_buf, head); 509 + vboxsf_dir_buf_free(b); 510 + } 511 + kfree(p); 512 + } 513 + 514 + int vboxsf_dir_read_all(struct vboxsf_sbi *sbi, struct vboxsf_dir_info *sf_d, 515 + u64 handle) 516 + { 517 + struct vboxsf_dir_buf *b; 518 + u32 entries, size; 519 + int err = 0; 520 + void *buf; 521 + 522 + /* vboxsf_dirinfo returns 1 on end of dir */ 523 + while (err == 0) { 524 + b = vboxsf_dir_buf_alloc(&sf_d->info_list); 525 + if (!b) { 526 + err = -ENOMEM; 527 + break; 528 + } 529 + 530 + buf = b->buf; 531 + size = b->free; 532 + 533 + err = vboxsf_dirinfo(sbi->root, handle, NULL, 0, 0, 534 + &size, buf, &entries); 535 + if (err < 0) 536 + break; 537 + 538 + b->entries += entries; 539 + b->free -= size; 540 + b->used += size; 541 + } 542 + 543 + if (b && b->used == 0) 544 + vboxsf_dir_buf_free(b); 545 + 546 + /* -EILSEQ means the host could not translate a filename, ignore */ 547 + if (err > 0 || err == -EILSEQ) 548 + err = 0; 549 + 550 + return err; 551 + }
+371
drivers/staging/vboxsf/vboxsf_wrappers.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Wrapper functions for the shfl host calls. 4 + * 5 + * Copyright (C) 2006-2018 Oracle Corporation 6 + */ 7 + 8 + #include <linux/mm.h> 9 + #include <linux/slab.h> 10 + #include <linux/vbox_err.h> 11 + #include <linux/vbox_utils.h> 12 + #include "vfsmod.h" 13 + 14 + #define SHFL_REQUEST \ 15 + (VMMDEV_REQUESTOR_KERNEL | VMMDEV_REQUESTOR_USR_DRV_OTHER | \ 16 + VMMDEV_REQUESTOR_CON_DONT_KNOW | VMMDEV_REQUESTOR_TRUST_NOT_GIVEN) 17 + 18 + static u32 vboxsf_client_id; 19 + 20 + int vboxsf_connect(void) 21 + { 22 + struct vbg_dev *gdev; 23 + struct vmmdev_hgcm_service_location loc; 24 + int err, vbox_status; 25 + 26 + loc.type = VMMDEV_HGCM_LOC_LOCALHOST_EXISTING; 27 + strcpy(loc.u.localhost.service_name, "VBoxSharedFolders"); 28 + 29 + gdev = vbg_get_gdev(); 30 + if (IS_ERR(gdev)) 31 + return -ENODEV; /* No guest-device */ 32 + 33 + err = vbg_hgcm_connect(gdev, SHFL_REQUEST, &loc, 34 + &vboxsf_client_id, &vbox_status); 35 + vbg_put_gdev(gdev); 36 + 37 + return err ? err : vbg_status_code_to_errno(vbox_status); 38 + } 39 + 40 + void vboxsf_disconnect(void) 41 + { 42 + struct vbg_dev *gdev; 43 + int vbox_status; 44 + 45 + gdev = vbg_get_gdev(); 46 + if (IS_ERR(gdev)) 47 + return; /* guest-device is gone, already disconnected */ 48 + 49 + vbg_hgcm_disconnect(gdev, SHFL_REQUEST, vboxsf_client_id, &vbox_status); 50 + vbg_put_gdev(gdev); 51 + } 52 + 53 + static int vboxsf_call(u32 function, void *parms, u32 parm_count, int *status) 54 + { 55 + struct vbg_dev *gdev; 56 + int err, vbox_status; 57 + 58 + gdev = vbg_get_gdev(); 59 + if (IS_ERR(gdev)) 60 + return -ESHUTDOWN; /* guest-dev removed underneath us */ 61 + 62 + err = vbg_hgcm_call(gdev, SHFL_REQUEST, vboxsf_client_id, function, 63 + U32_MAX, parms, parm_count, &vbox_status); 64 + vbg_put_gdev(gdev); 65 + 66 + if (err < 0) 67 + return err; 68 + 69 + if (status) 70 + *status = vbox_status; 71 + 72 + return vbg_status_code_to_errno(vbox_status); 73 + } 74 + 75 + int vboxsf_map_folder(struct shfl_string *folder_name, u32 *root) 76 + { 77 + struct shfl_map_folder parms; 78 + int err, status; 79 + 80 + parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; 81 + parms.path.u.pointer.size = shfl_string_buf_size(folder_name); 82 + parms.path.u.pointer.u.linear_addr = (uintptr_t)folder_name; 83 + 84 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 85 + parms.root.u.value32 = 0; 86 + 87 + parms.delimiter.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 88 + parms.delimiter.u.value32 = '/'; 89 + 90 + parms.case_sensitive.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 91 + parms.case_sensitive.u.value32 = 1; 92 + 93 + err = vboxsf_call(SHFL_FN_MAP_FOLDER, &parms, SHFL_CPARMS_MAP_FOLDER, 94 + &status); 95 + if (err == -ENOSYS && status == VERR_NOT_IMPLEMENTED) 96 + vbg_err("%s: Error host is too old\n", __func__); 97 + 98 + *root = parms.root.u.value32; 99 + return err; 100 + } 101 + 102 + int vboxsf_unmap_folder(u32 root) 103 + { 104 + struct shfl_unmap_folder parms; 105 + 106 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 107 + parms.root.u.value32 = root; 108 + 109 + return vboxsf_call(SHFL_FN_UNMAP_FOLDER, &parms, 110 + SHFL_CPARMS_UNMAP_FOLDER, NULL); 111 + } 112 + 113 + /** 114 + * vboxsf_create - Create a new file or folder 115 + * @root: Root of the shared folder in which to create the file 116 + * @parsed_path: The path of the file or folder relative to the shared folder 117 + * @param: create_parms Parameters for file/folder creation. 118 + * 119 + * Create a new file or folder or open an existing one in a shared folder. 120 + * Note this function always returns 0 / success unless an exceptional condition 121 + * occurs - out of memory, invalid arguments, etc. If the file or folder could 122 + * not be opened or created, create_parms->handle will be set to 123 + * SHFL_HANDLE_NIL on return. In this case the value in create_parms->result 124 + * provides information as to why (e.g. SHFL_FILE_EXISTS), create_parms->result 125 + * is also set on success as additional information. 126 + * 127 + * Returns: 128 + * 0 or negative errno value. 129 + */ 130 + int vboxsf_create(u32 root, struct shfl_string *parsed_path, 131 + struct shfl_createparms *create_parms) 132 + { 133 + struct shfl_create parms; 134 + 135 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 136 + parms.root.u.value32 = root; 137 + 138 + parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; 139 + parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); 140 + parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; 141 + 142 + parms.parms.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; 143 + parms.parms.u.pointer.size = sizeof(struct shfl_createparms); 144 + parms.parms.u.pointer.u.linear_addr = (uintptr_t)create_parms; 145 + 146 + return vboxsf_call(SHFL_FN_CREATE, &parms, SHFL_CPARMS_CREATE, NULL); 147 + } 148 + 149 + int vboxsf_close(u32 root, u64 handle) 150 + { 151 + struct shfl_close parms; 152 + 153 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 154 + parms.root.u.value32 = root; 155 + 156 + parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; 157 + parms.handle.u.value64 = handle; 158 + 159 + return vboxsf_call(SHFL_FN_CLOSE, &parms, SHFL_CPARMS_CLOSE, NULL); 160 + } 161 + 162 + int vboxsf_remove(u32 root, struct shfl_string *parsed_path, u32 flags) 163 + { 164 + struct shfl_remove parms; 165 + 166 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 167 + parms.root.u.value32 = root; 168 + 169 + parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; 170 + parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); 171 + parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; 172 + 173 + parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 174 + parms.flags.u.value32 = flags; 175 + 176 + return vboxsf_call(SHFL_FN_REMOVE, &parms, SHFL_CPARMS_REMOVE, NULL); 177 + } 178 + 179 + int vboxsf_rename(u32 root, struct shfl_string *src_path, 180 + struct shfl_string *dest_path, u32 flags) 181 + { 182 + struct shfl_rename parms; 183 + 184 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 185 + parms.root.u.value32 = root; 186 + 187 + parms.src.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; 188 + parms.src.u.pointer.size = shfl_string_buf_size(src_path); 189 + parms.src.u.pointer.u.linear_addr = (uintptr_t)src_path; 190 + 191 + parms.dest.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; 192 + parms.dest.u.pointer.size = shfl_string_buf_size(dest_path); 193 + parms.dest.u.pointer.u.linear_addr = (uintptr_t)dest_path; 194 + 195 + parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 196 + parms.flags.u.value32 = flags; 197 + 198 + return vboxsf_call(SHFL_FN_RENAME, &parms, SHFL_CPARMS_RENAME, NULL); 199 + } 200 + 201 + int vboxsf_read(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf) 202 + { 203 + struct shfl_read parms; 204 + int err; 205 + 206 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 207 + parms.root.u.value32 = root; 208 + 209 + parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; 210 + parms.handle.u.value64 = handle; 211 + parms.offset.type = VMMDEV_HGCM_PARM_TYPE_64BIT; 212 + parms.offset.u.value64 = offset; 213 + parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 214 + parms.cb.u.value32 = *buf_len; 215 + parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; 216 + parms.buffer.u.pointer.size = *buf_len; 217 + parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; 218 + 219 + err = vboxsf_call(SHFL_FN_READ, &parms, SHFL_CPARMS_READ, NULL); 220 + 221 + *buf_len = parms.cb.u.value32; 222 + return err; 223 + } 224 + 225 + int vboxsf_write(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf) 226 + { 227 + struct shfl_write parms; 228 + int err; 229 + 230 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 231 + parms.root.u.value32 = root; 232 + 233 + parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; 234 + parms.handle.u.value64 = handle; 235 + parms.offset.type = VMMDEV_HGCM_PARM_TYPE_64BIT; 236 + parms.offset.u.value64 = offset; 237 + parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 238 + parms.cb.u.value32 = *buf_len; 239 + parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; 240 + parms.buffer.u.pointer.size = *buf_len; 241 + parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; 242 + 243 + err = vboxsf_call(SHFL_FN_WRITE, &parms, SHFL_CPARMS_WRITE, NULL); 244 + 245 + *buf_len = parms.cb.u.value32; 246 + return err; 247 + } 248 + 249 + /* Returns 0 on success, 1 on end-of-dir, negative errno otherwise */ 250 + int vboxsf_dirinfo(u32 root, u64 handle, 251 + struct shfl_string *parsed_path, u32 flags, u32 index, 252 + u32 *buf_len, struct shfl_dirinfo *buf, u32 *file_count) 253 + { 254 + struct shfl_list parms; 255 + int err, status; 256 + 257 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 258 + parms.root.u.value32 = root; 259 + 260 + parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; 261 + parms.handle.u.value64 = handle; 262 + parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 263 + parms.flags.u.value32 = flags; 264 + parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 265 + parms.cb.u.value32 = *buf_len; 266 + if (parsed_path) { 267 + parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; 268 + parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); 269 + parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; 270 + } else { 271 + parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_IN; 272 + parms.path.u.pointer.size = 0; 273 + parms.path.u.pointer.u.linear_addr = 0; 274 + } 275 + 276 + parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; 277 + parms.buffer.u.pointer.size = *buf_len; 278 + parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; 279 + 280 + parms.resume_point.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 281 + parms.resume_point.u.value32 = index; 282 + parms.file_count.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 283 + parms.file_count.u.value32 = 0; /* out parameter only */ 284 + 285 + err = vboxsf_call(SHFL_FN_LIST, &parms, SHFL_CPARMS_LIST, &status); 286 + if (err == -ENODATA && status == VERR_NO_MORE_FILES) 287 + err = 1; 288 + 289 + *buf_len = parms.cb.u.value32; 290 + *file_count = parms.file_count.u.value32; 291 + return err; 292 + } 293 + 294 + int vboxsf_fsinfo(u32 root, u64 handle, u32 flags, 295 + u32 *buf_len, void *buf) 296 + { 297 + struct shfl_information parms; 298 + int err; 299 + 300 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 301 + parms.root.u.value32 = root; 302 + 303 + parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; 304 + parms.handle.u.value64 = handle; 305 + parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 306 + parms.flags.u.value32 = flags; 307 + parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 308 + parms.cb.u.value32 = *buf_len; 309 + parms.info.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; 310 + parms.info.u.pointer.size = *buf_len; 311 + parms.info.u.pointer.u.linear_addr = (uintptr_t)buf; 312 + 313 + err = vboxsf_call(SHFL_FN_INFORMATION, &parms, SHFL_CPARMS_INFORMATION, 314 + NULL); 315 + 316 + *buf_len = parms.cb.u.value32; 317 + return err; 318 + } 319 + 320 + int vboxsf_readlink(u32 root, struct shfl_string *parsed_path, 321 + u32 buf_len, u8 *buf) 322 + { 323 + struct shfl_readLink parms; 324 + 325 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 326 + parms.root.u.value32 = root; 327 + 328 + parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; 329 + parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); 330 + parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; 331 + 332 + parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; 333 + parms.buffer.u.pointer.size = buf_len; 334 + parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; 335 + 336 + return vboxsf_call(SHFL_FN_READLINK, &parms, SHFL_CPARMS_READLINK, 337 + NULL); 338 + } 339 + 340 + int vboxsf_symlink(u32 root, struct shfl_string *new_path, 341 + struct shfl_string *old_path, struct shfl_fsobjinfo *buf) 342 + { 343 + struct shfl_symlink parms; 344 + 345 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 346 + parms.root.u.value32 = root; 347 + 348 + parms.new_path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; 349 + parms.new_path.u.pointer.size = shfl_string_buf_size(new_path); 350 + parms.new_path.u.pointer.u.linear_addr = (uintptr_t)new_path; 351 + 352 + parms.old_path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; 353 + parms.old_path.u.pointer.size = shfl_string_buf_size(old_path); 354 + parms.old_path.u.pointer.u.linear_addr = (uintptr_t)old_path; 355 + 356 + parms.info.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; 357 + parms.info.u.pointer.size = sizeof(struct shfl_fsobjinfo); 358 + parms.info.u.pointer.u.linear_addr = (uintptr_t)buf; 359 + 360 + return vboxsf_call(SHFL_FN_SYMLINK, &parms, SHFL_CPARMS_SYMLINK, NULL); 361 + } 362 + 363 + int vboxsf_set_utf8(void) 364 + { 365 + return vboxsf_call(SHFL_FN_SET_UTF8, NULL, 0, NULL); 366 + } 367 + 368 + int vboxsf_set_symlinks(void) 369 + { 370 + return vboxsf_call(SHFL_FN_SET_SYMLINKS, NULL, 0, NULL); 371 + }
+137
drivers/staging/vboxsf/vfsmod.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * VirtualBox Guest Shared Folders support: module header. 4 + * 5 + * Copyright (C) 2006-2018 Oracle Corporation 6 + */ 7 + 8 + #ifndef VFSMOD_H 9 + #define VFSMOD_H 10 + 11 + #include <linux/backing-dev.h> 12 + #include <linux/idr.h> 13 + #include "shfl_hostintf.h" 14 + 15 + #define DIR_BUFFER_SIZE SZ_16K 16 + 17 + /* The cast is to prevent assignment of void * to pointers of arbitrary type */ 18 + #define VBOXSF_SBI(sb) ((struct vboxsf_sbi *)(sb)->s_fs_info) 19 + #define VBOXSF_I(i) container_of(i, struct vboxsf_inode, vfs_inode) 20 + 21 + struct vboxsf_options { 22 + unsigned long ttl; 23 + kuid_t uid; 24 + kgid_t gid; 25 + bool dmode_set; 26 + bool fmode_set; 27 + umode_t dmode; 28 + umode_t fmode; 29 + umode_t dmask; 30 + umode_t fmask; 31 + }; 32 + 33 + struct vboxsf_fs_context { 34 + struct vboxsf_options o; 35 + char *nls_name; 36 + }; 37 + 38 + /* per-shared folder information */ 39 + struct vboxsf_sbi { 40 + struct vboxsf_options o; 41 + struct shfl_fsobjinfo root_info; 42 + struct idr ino_idr; 43 + spinlock_t ino_idr_lock; /* This protects ino_idr */ 44 + struct nls_table *nls; 45 + u32 next_generation; 46 + u32 root; 47 + int bdi_id; 48 + }; 49 + 50 + /* per-inode information */ 51 + struct vboxsf_inode { 52 + /* some information was changed, update data on next revalidate */ 53 + int force_restat; 54 + /* list of open handles for this inode + lock protecting it */ 55 + struct list_head handle_list; 56 + /* This mutex protects handle_list accesses */ 57 + struct mutex handle_list_mutex; 58 + /* The VFS inode struct */ 59 + struct inode vfs_inode; 60 + }; 61 + 62 + struct vboxsf_dir_info { 63 + struct list_head info_list; 64 + }; 65 + 66 + struct vboxsf_dir_buf { 67 + size_t entries; 68 + size_t free; 69 + size_t used; 70 + void *buf; 71 + struct list_head head; 72 + }; 73 + 74 + /* globals */ 75 + extern const struct inode_operations vboxsf_dir_iops; 76 + extern const struct inode_operations vboxsf_lnk_iops; 77 + extern const struct inode_operations vboxsf_reg_iops; 78 + extern const struct file_operations vboxsf_dir_fops; 79 + extern const struct file_operations vboxsf_reg_fops; 80 + extern const struct address_space_operations vboxsf_reg_aops; 81 + extern const struct dentry_operations vboxsf_dentry_ops; 82 + 83 + /* from utils.c */ 84 + struct inode *vboxsf_new_inode(struct super_block *sb); 85 + void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode, 86 + const struct shfl_fsobjinfo *info); 87 + int vboxsf_create_at_dentry(struct dentry *dentry, 88 + struct shfl_createparms *params); 89 + int vboxsf_stat(struct vboxsf_sbi *sbi, struct shfl_string *path, 90 + struct shfl_fsobjinfo *info); 91 + int vboxsf_stat_dentry(struct dentry *dentry, struct shfl_fsobjinfo *info); 92 + int vboxsf_inode_revalidate(struct dentry *dentry); 93 + int vboxsf_getattr(const struct path *path, struct kstat *kstat, 94 + u32 request_mask, unsigned int query_flags); 95 + int vboxsf_setattr(struct dentry *dentry, struct iattr *iattr); 96 + struct shfl_string *vboxsf_path_from_dentry(struct vboxsf_sbi *sbi, 97 + struct dentry *dentry); 98 + int vboxsf_nlscpy(struct vboxsf_sbi *sbi, char *name, size_t name_bound_len, 99 + const unsigned char *utf8_name, size_t utf8_len); 100 + struct vboxsf_dir_info *vboxsf_dir_info_alloc(void); 101 + void vboxsf_dir_info_free(struct vboxsf_dir_info *p); 102 + int vboxsf_dir_read_all(struct vboxsf_sbi *sbi, struct vboxsf_dir_info *sf_d, 103 + u64 handle); 104 + 105 + /* from vboxsf_wrappers.c */ 106 + int vboxsf_connect(void); 107 + void vboxsf_disconnect(void); 108 + 109 + int vboxsf_create(u32 root, struct shfl_string *parsed_path, 110 + struct shfl_createparms *create_parms); 111 + 112 + int vboxsf_close(u32 root, u64 handle); 113 + int vboxsf_remove(u32 root, struct shfl_string *parsed_path, u32 flags); 114 + int vboxsf_rename(u32 root, struct shfl_string *src_path, 115 + struct shfl_string *dest_path, u32 flags); 116 + 117 + int vboxsf_read(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf); 118 + int vboxsf_write(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf); 119 + 120 + int vboxsf_dirinfo(u32 root, u64 handle, 121 + struct shfl_string *parsed_path, u32 flags, u32 index, 122 + u32 *buf_len, struct shfl_dirinfo *buf, u32 *file_count); 123 + int vboxsf_fsinfo(u32 root, u64 handle, u32 flags, 124 + u32 *buf_len, void *buf); 125 + 126 + int vboxsf_map_folder(struct shfl_string *folder_name, u32 *root); 127 + int vboxsf_unmap_folder(u32 root); 128 + 129 + int vboxsf_readlink(u32 root, struct shfl_string *parsed_path, 130 + u32 buf_len, u8 *buf); 131 + int vboxsf_symlink(u32 root, struct shfl_string *new_path, 132 + struct shfl_string *old_path, struct shfl_fsobjinfo *buf); 133 + 134 + int vboxsf_set_utf8(void); 135 + int vboxsf_set_symlinks(void); 136 + 137 + #endif