VirtualBox

source: vbox/trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.h@ 77536

Last change on this file since 77536 was 77536, checked in by vboxsync, 6 years ago

linux/vboxsf: Early version of non-buffered directories (disabled). bugref:9172

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.2 KB
Line 
1/* $Id: vfsmod.h 77536 2019-03-02 05:04:45Z vboxsync $ */
2/** @file
3 * vboxsf - Linux Shared Folders VFS, internal header.
4 */
5
6/*
7 * Copyright (C) 2006-2019 Oracle Corporation
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
16 * conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31#ifndef GA_INCLUDED_SRC_linux_sharedfolders_vfsmod_h
32#define GA_INCLUDED_SRC_linux_sharedfolders_vfsmod_h
33#ifndef RT_WITHOUT_PRAGMA_ONCE
34# pragma once
35#endif
36
37#if 0 /* Enables strict checks. */
38# define RT_STRICT
39# define VBOX_STRICT
40#endif
41#define VBSF_BUFFER_DIRS /* till I've fully tested the other code */
42
43#define LOG_GROUP LOG_GROUP_SHARED_FOLDERS
44#include "the-linux-kernel.h"
45#include <iprt/list.h>
46#include <iprt/asm.h>
47#include <VBox/log.h>
48
49#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
50# include <linux/backing-dev.h>
51#endif
52
53#include <VBox/VBoxGuestLibSharedFolders.h>
54#include <VBox/VBoxGuestLibSharedFoldersInline.h>
55#include <iprt/asm.h>
56#include "vbsfmount.h"
57
58
59/*
60 * inode compatibility glue.
61 */
62#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
63
64DECLINLINE(loff_t) i_size_read(struct inode *pInode)
65{
66 AssertCompile(sizeof(loff_t) == sizeof(uint64_t));
67 return ASMAtomicReadU64((uint64_t volatile *)&pInode->i_size);
68}
69
70DECLINLINE(void) i_size_write(struct inode *pInode, loff_t cbNew)
71{
72 AssertCompile(sizeof(pInode->i_size) == sizeof(uint64_t));
73 ASMAtomicWriteU64((uint64_t volatile *)&pInode->i_size, cbNew);
74}
75
76#endif /* < 2.6.0 */
77
78#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
79DECLINLINE(void) set_nlink(struct inode *pInode, unsigned int cLinks)
80{
81 pInode->i_nlink = cLinks;
82}
83#endif
84
85
86/* global variables */
87extern VBGLSFCLIENT g_SfClient;
88extern spinlock_t g_SfHandleLock;
89
90extern struct inode_operations vbsf_dir_iops;
91extern struct inode_operations vbsf_lnk_iops;
92extern struct inode_operations vbsf_reg_iops;
93extern struct file_operations vbsf_dir_fops;
94extern struct file_operations vbsf_reg_fops;
95extern struct dentry_operations vbsf_dentry_ops;
96extern struct address_space_operations vbsf_reg_aops;
97
98
99/**
100 * VBox specific per-mount (shared folder) information.
101 */
102struct vbsf_super_info {
103 VBGLSFMAP map;
104 struct nls_table *nls;
105 /** Set if the NLS table is UTF-8. */
106 bool fNlsIsUtf8;
107 /** time-to-live value for direntry and inode info in jiffies.
108 * Zero == disabled. */
109 unsigned long ttl;
110 /** The mount option value for /proc/mounts. */
111 int ttl_msec;
112 int uid;
113 int gid;
114 int dmode;
115 int fmode;
116 int dmask;
117 int fmask;
118 /** Maximum number of pages to allow in an I/O buffer with the host.
119 * This applies to read and write operations. */
120 uint32_t cMaxIoPages;
121 /** Mount tag for VBoxService automounter. @since 6.0 */
122 char tag[32];
123#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
124 /** The backing device info structure. */
125 struct backing_dev_info bdi;
126#endif
127};
128
129/* Following casts are here to prevent assignment of void * to
130 pointers of arbitrary type */
131#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
132# define VBSF_GET_SUPER_INFO(sb) ((struct vbsf_super_info *)(sb)->u.generic_sbp)
133# define VBSF_SET_SUPER_INFO(sb, sf_g) do { (sb)->u.generic_sbp = sf_g; } while (0)
134#else
135# define VBSF_GET_SUPER_INFO(sb) ((struct vbsf_super_info *)(sb)->s_fs_info)
136# define VBSF_SET_SUPER_INFO(sb, sf_g) do { (sb)->s_fs_info = sf_g;} while (0)
137#endif
138
139
140/**
141 * For associating inodes with host handles.
142 *
143 * This is necessary for address_space_operations::vbsf_writepage and allows
144 * optimizing stat, lookups and other operations on open files and directories.
145 */
146struct vbsf_handle {
147 /** List entry (head vbsf_inode_info::HandleList). */
148 RTLISTNODE Entry;
149 /** Host file/whatever handle. */
150 SHFLHANDLE hHost;
151 /** VBSF_HANDLE_F_XXX */
152 uint32_t fFlags;
153 /** Reference counter.
154 * Close the handle and free the structure when it reaches zero. */
155 uint32_t volatile cRefs;
156#ifdef VBOX_STRICT
157 /** For strictness checks. */
158 struct vbsf_inode_info *pInodeInfo;
159#endif
160};
161
162/** @name VBSF_HANDLE_F_XXX - Handle summary flags (vbsf_handle::fFlags).
163 * @{ */
164#define VBSF_HANDLE_F_READ UINT32_C(0x00000001)
165#define VBSF_HANDLE_F_WRITE UINT32_C(0x00000002)
166#define VBSF_HANDLE_F_APPEND UINT32_C(0x00000004)
167#define VBSF_HANDLE_F_FILE UINT32_C(0x00000010)
168#define VBSF_HANDLE_F_DIR UINT32_C(0x00000020)
169#define vbSF_HANDLE_F_ON_LIST UINT32_C(0x00000080)
170#define VBSF_HANDLE_F_MAGIC_MASK UINT32_C(0xffffff00)
171#define VBSF_HANDLE_F_MAGIC UINT32_C(0x75030700) /**< Maurice Ravel (1875-03-07). */
172#define VBSF_HANDLE_F_MAGIC_DEAD UINT32_C(0x19371228)
173/** @} */
174
175
176/**
177 * VBox specific per-inode information.
178 */
179struct vbsf_inode_info {
180 /** Which file */
181 SHFLSTRING *path;
182 /** Some information was changed, update data on next revalidate */
183 bool force_restat;
184#ifdef VBSF_BUFFER_DIRS
185 /** Directory content changed, update the whole directory on next vbsf_getdent */
186 bool force_reread;
187#endif
188 /** The timestamp (jiffies) where the inode info was last updated. */
189 unsigned long ts_up_to_date;
190 /** The birth time. */
191 RTTIMESPEC BirthTime;
192
193 /** handle valid if a file was created with vbsf_create_worker until it will
194 * be opened with vbsf_reg_open()
195 * @todo r=bird: figure this one out... */
196 SHFLHANDLE handle;
197
198 /** List of open handles (struct vbsf_handle), protected by g_SfHandleLock. */
199 RTLISTANCHOR HandleList;
200#ifdef VBOX_STRICT
201 uint32_t u32Magic;
202# define SF_INODE_INFO_MAGIC UINT32_C(0x18620822) /**< Claude Debussy */
203# define SF_INODE_INFO_MAGIC_DEAD UINT32_C(0x19180325)
204#endif
205};
206
207#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) || defined(KERNEL_FC6)
208/* FC6 kernel 2.6.18, vanilla kernel 2.6.19+ */
209# define VBSF_GET_INODE_INFO(i) ((struct vbsf_inode_info *) (i)->i_private)
210# define VBSF_SET_INODE_INFO(i, sf_i) (i)->i_private = sf_i
211#else
212/* vanilla kernel up to 2.6.18 */
213# define VBSF_GET_INODE_INFO(i) ((struct vbsf_inode_info *) (i)->u.generic_ip)
214# define VBSF_SET_INODE_INFO(i, sf_i) (i)->u.generic_ip = sf_i
215#endif
216
217extern void vbsf_init_inode(struct inode *inode, struct vbsf_inode_info *sf_i, PSHFLFSOBJINFO info, struct vbsf_super_info *sf_g);
218extern void vbsf_update_inode(struct inode *pInode, struct vbsf_inode_info *pInodeInfo, PSHFLFSOBJINFO pObjInfo,
219 struct vbsf_super_info *sf_g, bool fInodeLocked);
220extern int vbsf_inode_revalidate(struct dentry *dentry);
221extern int vbsf_inode_revalidate_worker(struct dentry *dentry, bool fForced);
222extern int vbsf_inode_revalidate_with_handle(struct dentry *dentry, SHFLHANDLE hHostFile, bool fForced, bool fInodeLocked);
223#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
224# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
225extern int vbsf_inode_getattr(const struct path *path, struct kstat *kstat, u32 request_mask, unsigned int query_flags);
226# else
227extern int vbsf_inode_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *kstat);
228# endif
229extern int vbsf_inode_setattr(struct dentry *dentry, struct iattr *iattr);
230#endif
231
232
233extern void vbsf_handle_drop_chain(struct vbsf_inode_info *pInodeInfo);
234extern struct vbsf_handle *vbsf_handle_find(struct vbsf_inode_info *pInodeInfo, uint32_t fFlagsSet, uint32_t fFlagsClear);
235extern uint32_t vbsf_handle_release_slow(struct vbsf_handle *pHandle, struct vbsf_super_info *sf_g, const char *pszCaller);
236extern void vbsf_handle_append(struct vbsf_inode_info *pInodeInfo, struct vbsf_handle *pHandle);
237
238/**
239 * Releases a handle.
240 *
241 * @returns New reference count.
242 * @param pHandle The handle to release.
243 * @param sf_g The info structure for the shared folder associated
244 * with the handle.
245 * @param pszCaller The caller name (for logging failures).
246 */
247DECLINLINE(uint32_t) vbsf_handle_release(struct vbsf_handle *pHandle, struct vbsf_super_info *sf_g, const char *pszCaller)
248{
249 uint32_t cRefs;
250
251 Assert((pHandle->fFlags & VBSF_HANDLE_F_MAGIC_MASK) == VBSF_HANDLE_F_MAGIC);
252 Assert(pHandle->pInodeInfo);
253 Assert(pHandle->pInodeInfo && pHandle->pInodeInfo->u32Magic == SF_INODE_INFO_MAGIC);
254
255 cRefs = ASMAtomicDecU32(&pHandle->cRefs);
256 Assert(cRefs < _64M);
257 if (cRefs)
258 return cRefs;
259 return vbsf_handle_release_slow(pHandle, sf_g, pszCaller);
260}
261
262
263/**
264 * VBox specific information for a regular file.
265 */
266struct vbsf_reg_info {
267 /** Handle tracking structure.
268 * @note Must be first! */
269 struct vbsf_handle Handle;
270};
271
272
273/**
274 * VBox specific information for an open directory.
275 */
276struct vbsf_dir_info {
277#ifndef VBSF_BUFFER_DIRS
278 /** Handle tracking structure.
279 * @note Must be first! */
280 struct vbsf_handle Handle;
281 /** A magic number (VBSF_DIR_INFO_MAGIC). */
282 uint32_t u32Magic;
283 /** Size of the buffer for directory entries. */
284 uint32_t cbBuf;
285 /** Buffer for directory entries on the physical heap. */
286 PSHFLDIRINFO pBuf;
287 /** Number of valid bytes in the buffer. */
288 uint32_t cbValid;
289 /** Number of entries left in the buffer. */
290 uint32_t cEntriesLeft;
291 /** The position of the next entry. Incremented by one for each entry. */
292 loff_t offPos;
293 /** The next entry. */
294 PSHFLDIRINFO pEntry;
295#else
296 /** List of vbsf_dir_buf. */
297 struct list_head info_list;
298#endif
299};
300
301/** Magic number for vbsf_dir_info::u32Magic (Robert Anson Heinlein). */
302#define VBSF_DIR_INFO_MAGIC UINT32_C(0x19070707)
303/** Value of vbsf_dir_info::u32Magic when freed. */
304#define VBSF_DIR_INFO_MAGIC_DEAD UINT32_C(0x19880508)
305
306
307#ifdef VBSF_BUFFER_DIRS
308# define DIR_BUFFER_SIZE (16*_1K)
309struct vbsf_dir_buf {
310 size_t cEntries;
311 size_t cbFree;
312 size_t cbUsed;
313 void *buf;
314 struct list_head head;
315};
316#endif
317
318#ifdef VBSF_BUFFER_DIRS
319extern void vbsf_dir_info_free(struct vbsf_dir_info *p);
320extern void vbsf_dir_info_empty(struct vbsf_dir_info *p);
321extern struct vbsf_dir_info *vbsf_dir_info_alloc(void);
322extern int vbsf_dir_read_all(struct vbsf_super_info *sf_g, struct vbsf_inode_info *sf_i,
323 struct vbsf_dir_info *sf_d, SHFLHANDLE handle);
324#endif
325
326
327/**
328 * Sets the update-jiffies value for a dentry.
329 *
330 * This is used together with vbsf_super_info::ttl to reduce re-validation of
331 * dentry structures while walking.
332 *
333 * This used to be living in d_time, but since 4.9.0 that seems to have become
334 * unfashionable and d_fsdata is now used to for this purpose. We do this all
335 * the way back, since d_time seems only to have been used by the file system
336 * specific code (at least going back to 2.4.0).
337 */
338DECLINLINE(void) vbsf_dentry_set_update_jiffies(struct dentry *pDirEntry, unsigned long uToSet)
339{
340 pDirEntry->d_fsdata = (void *)uToSet;
341}
342
343/**
344 * Get the update-jiffies value for a dentry.
345 */
346DECLINLINE(unsigned long) vbsf_dentry_get_update_jiffies(struct dentry *pDirEntry)
347{
348 return (unsigned long)pDirEntry->d_fsdata;
349}
350
351/**
352 * Increase the time-to-live of @a pDirEntry and all ancestors.
353 * @param pDirEntry The directory entry cache entry which ancestors
354 * we should increase the TTL for.
355 */
356DECLINLINE(void) vbsf_dentry_chain_increase_ttl(struct dentry *pDirEntry)
357{
358#ifdef VBOX_STRICT
359 struct super_block * const pSuper = pDirEntry->d_sb;
360#endif
361 unsigned long const uToSet = jiffies;
362 do {
363 Assert(pDirEntry->d_sb == pSuper);
364 vbsf_dentry_set_update_jiffies(pDirEntry, uToSet);
365 pDirEntry = pDirEntry->d_parent;
366 } while (!IS_ROOT(pDirEntry));
367}
368
369/**
370 * Increase the time-to-live of all ancestors.
371 * @param pDirEntry The directory entry cache entry which ancestors
372 * we should increase the TTL for.
373 */
374DECLINLINE(void) vbsf_dentry_chain_increase_parent_ttl(struct dentry *pDirEntry)
375{
376 Assert(!pDirEntry->d_parent || pDirEntry->d_parent->d_sb == pDirEntry->d_sb);
377 pDirEntry = pDirEntry->d_parent;
378 if (pDirEntry)
379 vbsf_dentry_chain_increase_ttl(pDirEntry);
380}
381
382/** Macro for getting the dentry for a struct file. */
383#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
384# define VBSF_GET_F_DENTRY(f) file_dentry(f)
385#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
386# define VBSF_GET_F_DENTRY(f) (f->f_path.dentry)
387#else
388# define VBSF_GET_F_DENTRY(f) (f->f_dentry)
389#endif
390
391extern int vbsf_stat(const char *caller, struct vbsf_super_info *sf_g, SHFLSTRING * path, PSHFLFSOBJINFO result, int ok_to_fail);
392extern int vbsf_path_from_dentry(const char *caller, struct vbsf_super_info *sf_g, struct vbsf_inode_info *sf_i,
393 struct dentry *dentry, SHFLSTRING ** result);
394extern int vbsf_nlscpy(struct vbsf_super_info *sf_g, char *name, size_t name_bound_len,
395 const unsigned char *utf8_name, size_t utf8_len);
396
397
398#if 1
399# define TRACE() LogFunc(("tracepoint\n"))
400# define SFLOGFLOW(aArgs) Log(aArgs)
401# ifdef LOG_ENABLED
402# define SFLOG_ENABLED 1
403# endif
404#else
405# define TRACE() RTLogBackdoorPrintf("%s: tracepoint\n", __FUNCTION__)
406# define SFLOGFLOW(aArgs) RTLogBackdoorPrintf aArgs
407# define SFLOG_ENABLED 1
408#endif
409
410#endif /* !GA_INCLUDED_SRC_linux_sharedfolders_vfsmod_h */
Note: See TracBrowser for help on using the repository browser.

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