3 * vboxsf -- VirtualBox Guest Additions for Linux:
5 * Mainly conversion from/to VirtualBox/Linux data structures
9 * Copyright (C) 2006-2016 Oracle Corporation
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
22 #include <linux/nfs_fs.h>
23 #include <linux/vfs.h>
25 /* #define USE_VMALLOC */
28 * sf_reg_aops and sf_backing_dev_info are just quick implementations to make
29 * sendfile work. For more information have a look at
31 * http://us1.samba.org/samba/ftp/cifs-cvs/ols2006-fs-tutorial-smf.odp
33 * and the sample implementation
35 * http://pserver.samba.org/samba/ftp/cifs-cvs/samplefs.tar.gz
38 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
39 static void sf_ftime_from_timespec(time_t *time
, RTTIMESPEC
*ts
)
41 int64_t t
= RTTimeSpecGetNano(ts
);
43 do_div(t
, 1000000000);
47 static void sf_timespec_from_ftime(RTTIMESPEC
*ts
, time_t *time
)
49 int64_t t
= 1000000000 * *time
;
50 RTTimeSpecSetNano(ts
, t
);
53 static void sf_ftime_from_timespec(struct timespec
*tv
, RTTIMESPEC
*ts
)
55 int64_t t
= RTTimeSpecGetNano(ts
);
58 nsec
= do_div(t
, 1000000000);
63 static void sf_timespec_from_ftime(RTTIMESPEC
*ts
, struct timespec
*tv
)
65 int64_t t
= (int64_t)tv
->tv_nsec
+ (int64_t)tv
->tv_sec
* 1000000000;
66 RTTimeSpecSetNano(ts
, t
);
70 /* set [inode] attributes based on [info], uid/gid based on [sf_g] */
71 void sf_init_inode(struct sf_glob_info
*sf_g
, struct inode
*inode
,
81 #define mode_set(r) attr->fMode & (RTFS_UNIX_##r) ? (S_##r) : 0;
82 mode
= mode_set(ISUID
);
83 mode
|= mode_set(ISGID
);
85 mode
|= mode_set(IRUSR
);
86 mode
|= mode_set(IWUSR
);
87 mode
|= mode_set(IXUSR
);
89 mode
|= mode_set(IRGRP
);
90 mode
|= mode_set(IWGRP
);
91 mode
|= mode_set(IXGRP
);
93 mode
|= mode_set(IROTH
);
94 mode
|= mode_set(IWOTH
);
95 mode
|= mode_set(IXOTH
);
99 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
100 inode
->i_mapping
->a_ops
= &sf_reg_aops
;
101 # if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19, 0)
102 /* XXX Was this ever necessary? */
103 inode
->i_mapping
->backing_dev_info
= &sf_g
->bdi
;
107 if (RTFS_IS_DIRECTORY(attr
->fMode
))
109 inode
->i_mode
= sf_g
->dmode
!= ~0 ? (sf_g
->dmode
& 0777) : mode
;
110 inode
->i_mode
&= ~sf_g
->dmask
;
111 inode
->i_mode
|= S_IFDIR
;
112 inode
->i_op
= &sf_dir_iops
;
113 inode
->i_fop
= &sf_dir_fops
;
114 /* XXX: this probably should be set to the number of entries
115 in the directory plus two (. ..) */
116 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
122 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
123 else if (RTFS_IS_SYMLINK(attr
->fMode
))
125 inode
->i_mode
= sf_g
->fmode
!= ~0 ? (sf_g
->fmode
& 0777): mode
;
126 inode
->i_mode
&= ~sf_g
->fmask
;
127 inode
->i_mode
|= S_IFLNK
;
128 inode
->i_op
= &sf_lnk_iops
;
129 # if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
138 inode
->i_mode
= sf_g
->fmode
!= ~0 ? (sf_g
->fmode
& 0777): mode
;
139 inode
->i_mode
&= ~sf_g
->fmask
;
140 inode
->i_mode
|= S_IFREG
;
141 inode
->i_op
= &sf_reg_iops
;
142 inode
->i_fop
= &sf_reg_fops
;
143 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
150 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
151 inode
->i_uid
= make_kuid(current_user_ns(), sf_g
->uid
);
152 inode
->i_gid
= make_kgid(current_user_ns(), sf_g
->gid
);
154 inode
->i_uid
= sf_g
->uid
;
155 inode
->i_gid
= sf_g
->gid
;
158 inode
->i_size
= info
->cbObject
;
159 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) && !defined(KERNEL_FC6)
160 inode
->i_blksize
= 4096;
162 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 11)
163 inode
->i_blkbits
= 12;
165 /* i_blocks always in units of 512 bytes! */
166 inode
->i_blocks
= (info
->cbAllocated
+ 511) / 512;
168 sf_ftime_from_timespec(&inode
->i_atime
, &info
->AccessTime
);
169 sf_ftime_from_timespec(&inode
->i_ctime
, &info
->ChangeTime
);
170 sf_ftime_from_timespec(&inode
->i_mtime
, &info
->ModificationTime
);
173 int sf_stat(const char *caller
, struct sf_glob_info
*sf_g
,
174 SHFLSTRING
*path
, PSHFLFSOBJINFO result
, int ok_to_fail
)
177 SHFLCREATEPARMS params
;
183 params
.Handle
= SHFL_HANDLE_NIL
;
184 params
.CreateFlags
= SHFL_CF_LOOKUP
| SHFL_CF_ACT_FAIL_IF_NEW
;
185 LogFunc(("sf_stat: calling VbglR0SfCreate, file %s, flags %#x\n",
186 path
->String
.utf8
, params
.CreateFlags
));
187 rc
= VbglR0SfCreate(&client_handle
, &sf_g
->map
, path
, ¶ms
);
188 if (rc
== VERR_INVALID_NAME
)
190 /* this can happen for names like 'foo*' on a Windows host */
195 LogFunc(("VbglR0SfCreate(%s) failed. caller=%s, rc=%Rrc\n",
196 path
->String
.utf8
, rc
, caller
));
199 if (params
.Result
!= SHFL_FILE_EXISTS
)
202 LogFunc(("VbglR0SfCreate(%s) file does not exist. caller=%s, result=%d\n",
203 path
->String
.utf8
, params
.Result
, caller
));
207 *result
= params
.Info
;
211 /* this is called directly as iop on 2.4, indirectly as dop
212 [sf_dentry_revalidate] on 2.4/2.6, indirectly as iop through
213 [sf_getattr] on 2.6. the job is to find out whether dentry/inode is
214 still valid. the test is failed if [dentry] does not have an inode
215 or [sf_stat] is unsuccessful, otherwise we return success and
216 update inode attributes */
217 int sf_inode_revalidate(struct dentry
*dentry
)
220 struct sf_glob_info
*sf_g
;
221 struct sf_inode_info
*sf_i
;
225 if (!dentry
|| !dentry
->d_inode
)
227 LogFunc(("no dentry(%p) or inode(%p)\n", dentry
, dentry
->d_inode
));
231 sf_g
= GET_GLOB_INFO(dentry
->d_inode
->i_sb
);
232 sf_i
= GET_INODE_INFO(dentry
->d_inode
);
235 printk("%s called by %p:%p\n",
236 sf_i
->path
->String
.utf8
,
237 __builtin_return_address (0),
238 __builtin_return_address (1));
244 if (!sf_i
->force_restat
)
246 if (jiffies
- dentry
->d_time
< sf_g
->ttl
)
250 err
= sf_stat(__func__
, sf_g
, sf_i
->path
, &info
, 1);
254 dentry
->d_time
= jiffies
;
255 sf_init_inode(sf_g
, dentry
->d_inode
, &info
);
259 /* this is called during name resolution/lookup to check if the
260 [dentry] in the cache is still valid. the job is handled by
261 [sf_inode_revalidate] */
263 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
264 sf_dentry_revalidate(struct dentry
*dentry
, unsigned flags
)
265 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
266 sf_dentry_revalidate(struct dentry
*dentry
, struct nameidata
*nd
)
268 sf_dentry_revalidate(struct dentry
*dentry
, int flags
)
273 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
274 if (flags
& LOOKUP_RCU
)
276 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
277 /* see Documentation/filesystems/vfs.txt */
278 if (nd
&& nd
->flags
& LOOKUP_RCU
)
282 if (sf_inode_revalidate(dentry
))
288 /* on 2.6 this is a proxy for [sf_inode_revalidate] which (as a side
289 effect) updates inode attributes for [dentry] (given that [dentry]
290 has inode at all) from these new attributes we derive [kstat] via
291 [generic_fillattr] */
292 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
293 # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
294 int sf_getattr(const struct path
*path
, struct kstat
*kstat
, u32 request_mask
, unsigned int flags
)
296 int sf_getattr(struct vfsmount
*mnt
, struct dentry
*dentry
, struct kstat
*kstat
)
300 # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
301 struct dentry
*dentry
= path
->dentry
;
305 err
= sf_inode_revalidate(dentry
);
309 generic_fillattr(dentry
->d_inode
, kstat
);
313 int sf_setattr(struct dentry
*dentry
, struct iattr
*iattr
)
315 struct sf_glob_info
*sf_g
;
316 struct sf_inode_info
*sf_i
;
317 SHFLCREATEPARMS params
;
324 sf_g
= GET_GLOB_INFO(dentry
->d_inode
->i_sb
);
325 sf_i
= GET_INODE_INFO(dentry
->d_inode
);
329 params
.Handle
= SHFL_HANDLE_NIL
;
330 params
.CreateFlags
= SHFL_CF_ACT_OPEN_IF_EXISTS
331 | SHFL_CF_ACT_FAIL_IF_NEW
332 | SHFL_CF_ACCESS_ATTR_WRITE
;
334 /* this is at least required for Posix hosts */
335 if (iattr
->ia_valid
& ATTR_SIZE
)
336 params
.CreateFlags
|= SHFL_CF_ACCESS_WRITE
;
338 rc
= VbglR0SfCreate(&client_handle
, &sf_g
->map
, sf_i
->path
, ¶ms
);
341 LogFunc(("VbglR0SfCreate(%s) failed rc=%Rrc\n",
342 sf_i
->path
->String
.utf8
, rc
));
343 err
= -RTErrConvertToErrno(rc
);
346 if (params
.Result
!= SHFL_FILE_EXISTS
)
348 LogFunc(("file %s does not exist\n", sf_i
->path
->String
.utf8
));
353 /* Setting the file size and setting the other attributes has to be
354 * handled separately, see implementation of vbsfSetFSInfo() in
356 if (iattr
->ia_valid
& (ATTR_MODE
| ATTR_ATIME
| ATTR_MTIME
))
358 #define mode_set(r) ((iattr->ia_mode & (S_##r)) ? RTFS_UNIX_##r : 0)
361 if (iattr
->ia_valid
& ATTR_MODE
)
363 info
.Attr
.fMode
= mode_set(ISUID
);
364 info
.Attr
.fMode
|= mode_set(ISGID
);
365 info
.Attr
.fMode
|= mode_set(IRUSR
);
366 info
.Attr
.fMode
|= mode_set(IWUSR
);
367 info
.Attr
.fMode
|= mode_set(IXUSR
);
368 info
.Attr
.fMode
|= mode_set(IRGRP
);
369 info
.Attr
.fMode
|= mode_set(IWGRP
);
370 info
.Attr
.fMode
|= mode_set(IXGRP
);
371 info
.Attr
.fMode
|= mode_set(IROTH
);
372 info
.Attr
.fMode
|= mode_set(IWOTH
);
373 info
.Attr
.fMode
|= mode_set(IXOTH
);
375 if (iattr
->ia_mode
& S_IFDIR
)
376 info
.Attr
.fMode
|= RTFS_TYPE_DIRECTORY
;
378 info
.Attr
.fMode
|= RTFS_TYPE_FILE
;
381 if (iattr
->ia_valid
& ATTR_ATIME
)
382 sf_timespec_from_ftime(&info
.AccessTime
, &iattr
->ia_atime
);
383 if (iattr
->ia_valid
& ATTR_MTIME
)
384 sf_timespec_from_ftime(&info
.ModificationTime
, &iattr
->ia_mtime
);
385 /* ignore ctime (inode change time) as it can't be set from userland anyway */
387 cbBuffer
= sizeof(info
);
388 rc
= VbglR0SfFsInfo(&client_handle
, &sf_g
->map
, params
.Handle
,
389 SHFL_INFO_SET
| SHFL_INFO_FILE
, &cbBuffer
,
390 (PSHFLDIRINFO
)&info
);
393 LogFunc(("VbglR0SfFsInfo(%s, FILE) failed rc=%Rrc\n",
394 sf_i
->path
->String
.utf8
, rc
));
395 err
= -RTErrConvertToErrno(rc
);
400 if (iattr
->ia_valid
& ATTR_SIZE
)
403 info
.cbObject
= iattr
->ia_size
;
404 cbBuffer
= sizeof(info
);
405 rc
= VbglR0SfFsInfo(&client_handle
, &sf_g
->map
, params
.Handle
,
406 SHFL_INFO_SET
| SHFL_INFO_SIZE
, &cbBuffer
,
407 (PSHFLDIRINFO
)&info
);
410 LogFunc(("VbglR0SfFsInfo(%s, SIZE) failed rc=%Rrc\n",
411 sf_i
->path
->String
.utf8
, rc
));
412 err
= -RTErrConvertToErrno(rc
);
417 rc
= VbglR0SfClose(&client_handle
, &sf_g
->map
, params
.Handle
);
419 LogFunc(("VbglR0SfClose(%s) failed rc=%Rrc\n", sf_i
->path
->String
.utf8
, rc
));
421 return sf_inode_revalidate(dentry
);
424 rc
= VbglR0SfClose(&client_handle
, &sf_g
->map
, params
.Handle
);
426 LogFunc(("VbglR0SfClose(%s) failed rc=%Rrc\n", sf_i
->path
->String
.utf8
, rc
));
431 #endif /* >= 2.6.0 */
433 static int sf_make_path(const char *caller
, struct sf_inode_info
*sf_i
,
434 const char *d_name
, size_t d_len
, SHFLSTRING
**result
)
436 size_t path_len
, shflstring_len
;
443 p_len
= sf_i
->path
->u16Length
;
444 p_name
= sf_i
->path
->String
.utf8
;
446 if (p_len
== 1 && *p_name
== '/')
448 path_len
= d_len
+ 1;
453 /* lengths of constituents plus terminating zero plus slash */
454 path_len
= p_len
+ d_len
+ 2;
455 if (path_len
> 0xffff)
457 LogFunc(("path too long. caller=%s, path_len=%zu\n", caller
, path_len
));
458 return -ENAMETOOLONG
;
462 shflstring_len
= offsetof(SHFLSTRING
, String
.utf8
) + path_len
;
463 tmp
= kmalloc(shflstring_len
, GFP_KERNEL
);
466 LogRelFunc(("kmalloc failed, caller=%s\n", caller
));
469 tmp
->u16Length
= path_len
- 1;
470 tmp
->u16Size
= path_len
;
473 memcpy(&tmp
->String
.utf8
[0], d_name
, d_len
+ 1);
476 memcpy(&tmp
->String
.utf8
[0], p_name
, p_len
);
477 tmp
->String
.utf8
[p_len
] = '/';
478 memcpy(&tmp
->String
.utf8
[p_len
+ 1], d_name
, d_len
);
479 tmp
->String
.utf8
[p_len
+ 1 + d_len
] = '\0';
487 * [dentry] contains string encoded in coding system that corresponds
488 * to [sf_g]->nls, we must convert it to UTF8 here and pass down to
489 * [sf_make_path] which will allocate SHFLSTRING and fill it in
491 int sf_path_from_dentry(const char *caller
, struct sf_glob_info
*sf_g
,
492 struct sf_inode_info
*sf_i
, struct dentry
*dentry
,
502 d_name
= dentry
->d_name
.name
;
503 d_len
= dentry
->d_name
.len
;
507 size_t in_len
, i
, out_bound_len
;
514 out_bound_len
= PATH_MAX
;
515 out
= kmalloc(out_bound_len
, GFP_KERNEL
);
518 for (i
= 0; i
< d_len
; ++i
)
520 /* We renamed the linux kernel wchar_t type to linux_wchar_t in
521 the-linux-kernel.h, as it conflicts with the C++ type of that name. */
525 nb
= sf_g
->nls
->char2uni(in
, in_len
, &uni
);
528 LogFunc(("nls->char2uni failed %x %d\n",
536 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
537 nb
= utf32_to_utf8(uni
, out
, out_bound_len
);
539 nb
= utf8_wctomb(out
, uni
, out_bound_len
);
543 LogFunc(("nls->uni2char failed %x %d\n",
544 uni
, out_bound_len
));
552 if (len
>= PATH_MAX
- 1)
558 LogFunc(("result(%d) = %.*s\n", len
, len
, name
));
567 err
= sf_make_path(caller
, sf_i
, name
, len
, result
);
578 int sf_nlscpy(struct sf_glob_info
*sf_g
,
579 char *name
, size_t name_bound_len
,
580 const unsigned char *utf8_name
, size_t utf8_len
)
587 size_t out_bound_len
;
591 in_bound_len
= utf8_len
;
595 out_bound_len
= name_bound_len
;
600 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
603 nb
= utf8_to_utf32(in
, in_bound_len
, &uni
);
607 nb
= utf8_mbtowc(&uni
, in
, in_bound_len
);
611 LogFunc(("utf8_mbtowc failed(%s) %x:%d\n",
612 (const char *) utf8_name
, *in
, in_bound_len
));
618 nb
= sf_g
->nls
->uni2char(uni
, out
, out_bound_len
);
621 LogFunc(("nls->uni2char failed(%s) %x:%d\n",
622 utf8_name
, uni
, out_bound_len
));
634 if (utf8_len
+ 1 > name_bound_len
)
635 return -ENAMETOOLONG
;
637 memcpy(name
, utf8_name
, utf8_len
+ 1);
642 static struct sf_dir_buf
*sf_dir_buf_alloc(void)
644 struct sf_dir_buf
*b
;
647 b
= kmalloc(sizeof(*b
), GFP_KERNEL
);
650 LogRelFunc(("could not alloc directory buffer\n"));
655 b
->buf
= vmalloc(DIR_BUFFER_SIZE
);
657 b
->buf
= kmalloc(DIR_BUFFER_SIZE
, GFP_KERNEL
);
662 LogRelFunc(("could not alloc directory buffer storage\n"));
666 INIT_LIST_HEAD(&b
->head
);
669 b
->cbFree
= DIR_BUFFER_SIZE
;
673 static void sf_dir_buf_free(struct sf_dir_buf
*b
)
675 BUG_ON(!b
|| !b
->buf
);
688 * Free the directory buffer.
690 void sf_dir_info_free(struct sf_dir_info
*p
)
692 struct list_head
*list
, *pos
, *tmp
;
695 list
= &p
->info_list
;
696 list_for_each_safe(pos
, tmp
, list
)
698 struct sf_dir_buf
*b
;
700 b
= list_entry(pos
, struct sf_dir_buf
, head
);
707 * Empty (but not free) the directory buffer.
709 void sf_dir_info_empty(struct sf_dir_info
*p
)
711 struct list_head
*list
, *pos
, *tmp
;
713 list
= &p
->info_list
;
714 list_for_each_safe(pos
, tmp
, list
)
716 struct sf_dir_buf
*b
;
717 b
= list_entry(pos
, struct sf_dir_buf
, head
);
720 b
->cbFree
= DIR_BUFFER_SIZE
;
725 * Create a new directory buffer descriptor.
727 struct sf_dir_info
*sf_dir_info_alloc(void)
729 struct sf_dir_info
*p
;
732 p
= kmalloc(sizeof(*p
), GFP_KERNEL
);
735 LogRelFunc(("could not alloc directory info\n"));
739 INIT_LIST_HEAD(&p
->info_list
);
744 * Search for an empty directory content buffer.
746 static struct sf_dir_buf
*sf_get_empty_dir_buf(struct sf_dir_info
*sf_d
)
748 struct list_head
*list
, *pos
;
750 list
= &sf_d
->info_list
;
751 list_for_each(pos
, list
)
753 struct sf_dir_buf
*b
;
755 b
= list_entry(pos
, struct sf_dir_buf
, head
);
768 int sf_dir_read_all(struct sf_glob_info
*sf_g
, struct sf_inode_info
*sf_i
,
769 struct sf_dir_info
*sf_d
, SHFLHANDLE handle
)
773 struct sf_dir_buf
*b
;
776 err
= sf_make_path(__func__
, sf_i
, "*", 1, &mask
);
787 b
= sf_get_empty_dir_buf(sf_d
);
790 b
= sf_dir_buf_alloc();
794 LogRelFunc(("could not alloc directory buffer\n"));
797 list_add(&b
->head
, &sf_d
->info_list
);
803 rc
= VbglR0SfDirInfo(&client_handle
, &sf_g
->map
, handle
, mask
,
804 0, 0, &cbSize
, buf
, &cEntries
);
809 case VERR_NO_MORE_FILES
:
811 case VERR_NO_TRANSLATION
:
812 LogFunc(("host could not translate entry\n"));
816 err
= -RTErrConvertToErrno(rc
);
817 LogFunc(("VbglR0SfDirInfo failed rc=%Rrc\n", rc
));
821 b
->cEntries
+= cEntries
;
837 int sf_get_volume_info(struct super_block
*sb
, STRUCT_STATFS
*stat
)
839 struct sf_glob_info
*sf_g
;
840 SHFLVOLINFO SHFLVolumeInfo
;
844 sf_g
= GET_GLOB_INFO(sb
);
845 cbBuffer
= sizeof(SHFLVolumeInfo
);
846 rc
= VbglR0SfFsInfo(&client_handle
, &sf_g
->map
, 0, SHFL_INFO_GET
| SHFL_INFO_VOLUME
,
847 &cbBuffer
, (PSHFLDIRINFO
)&SHFLVolumeInfo
);
849 return -RTErrConvertToErrno(rc
);
851 stat
->f_type
= NFS_SUPER_MAGIC
; /* XXX vboxsf type? */
852 stat
->f_bsize
= SHFLVolumeInfo
.ulBytesPerAllocationUnit
;
853 stat
->f_blocks
= SHFLVolumeInfo
.ullTotalAllocationBytes
854 / SHFLVolumeInfo
.ulBytesPerAllocationUnit
;
855 stat
->f_bfree
= SHFLVolumeInfo
.ullAvailableAllocationBytes
856 / SHFLVolumeInfo
.ulBytesPerAllocationUnit
;
857 stat
->f_bavail
= SHFLVolumeInfo
.ullAvailableAllocationBytes
858 / SHFLVolumeInfo
.ulBytesPerAllocationUnit
;
859 stat
->f_files
= 1000;
860 stat
->f_ffree
= 1000; /* don't return 0 here since the guest may think
861 * that it is not possible to create any more files */
862 stat
->f_fsid
.val
[0] = 0;
863 stat
->f_fsid
.val
[1] = 0;
864 stat
->f_namelen
= 255;
868 struct dentry_operations sf_dentry_ops
=
870 .d_revalidate
= sf_dentry_revalidate
873 int sf_init_backing_dev(struct sf_glob_info
*sf_g
)
876 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19, 0)
877 /* Each new shared folder map gets a new uint64_t identifier,
878 * allocated in sequence. We ASSUME the sequence will not wrap. */
879 static uint64_t s_u64Sequence
= 0;
880 uint64_t u64CurrentSequence
= ASMAtomicIncU64(&s_u64Sequence
);
882 sf_g
->bdi
.ra_pages
= 0; /* No readahead */
883 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12)
884 sf_g
->bdi
.capabilities
= BDI_CAP_MAP_DIRECT
/* MAP_SHARED */
885 | BDI_CAP_MAP_COPY
/* MAP_PRIVATE */
886 | BDI_CAP_READ_MAP
/* can be mapped for reading */
887 | BDI_CAP_WRITE_MAP
/* can be mapped for writing */
888 | BDI_CAP_EXEC_MAP
; /* can be mapped for execution */
889 # endif /* >= 2.6.12 */
890 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
891 rc
= bdi_init(&sf_g
->bdi
);
892 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
894 rc
= bdi_register(&sf_g
->bdi
, NULL
, "vboxsf-%llu",
895 (unsigned long long)u64CurrentSequence
);
896 # endif /* >= 2.6.26 */
897 # endif /* >= 2.6.24 */
898 #endif /* >= 2.6.0 && <= 3.19.0 */
902 void sf_done_backing_dev(struct sf_glob_info
*sf_g
)
904 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19, 0)
905 bdi_destroy(&sf_g
->bdi
); /* includes bdi_unregister() */