Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
80f3fda9
Commit
80f3fda9
authored
May 02, 2016
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
server: Add support for maintaining a client-side directory cache.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
fcf0829b
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
172 additions
and
2 deletions
+172
-2
server_protocol.h
include/wine/server_protocol.h
+19
-1
change.c
server/change.c
+121
-1
process.c
server/process.c
+2
-0
process.h
server/process.h
+1
-0
protocol.def
server/protocol.def
+9
-0
request.h
server/request.h
+6
-0
trace.c
server/trace.c
+14
-0
No files found.
include/wine/server_protocol.h
View file @
80f3fda9
...
...
@@ -1452,6 +1452,21 @@ enum server_fd_type
struct
get_directory_cache_entry_request
{
struct
request_header
__header
;
obj_handle_t
handle
;
};
struct
get_directory_cache_entry_reply
{
struct
reply_header
__header
;
int
entry
;
/* VARARG(free,ints); */
char
__pad_12
[
4
];
};
struct
flush_request
{
struct
request_header
__header
;
...
...
@@ -5401,6 +5416,7 @@ enum request
REQ_alloc_file_handle
,
REQ_get_handle_unix_name
,
REQ_get_handle_fd
,
REQ_get_directory_cache_entry
,
REQ_flush
,
REQ_lock_file
,
REQ_unlock_file
,
...
...
@@ -5679,6 +5695,7 @@ union generic_request
struct
alloc_file_handle_request
alloc_file_handle_request
;
struct
get_handle_unix_name_request
get_handle_unix_name_request
;
struct
get_handle_fd_request
get_handle_fd_request
;
struct
get_directory_cache_entry_request
get_directory_cache_entry_request
;
struct
flush_request
flush_request
;
struct
lock_file_request
lock_file_request
;
struct
unlock_file_request
unlock_file_request
;
...
...
@@ -5955,6 +5972,7 @@ union generic_reply
struct
alloc_file_handle_reply
alloc_file_handle_reply
;
struct
get_handle_unix_name_reply
get_handle_unix_name_reply
;
struct
get_handle_fd_reply
get_handle_fd_reply
;
struct
get_directory_cache_entry_reply
get_directory_cache_entry_reply
;
struct
flush_reply
flush_reply
;
struct
lock_file_reply
lock_file_reply
;
struct
unlock_file_reply
unlock_file_reply
;
...
...
@@ -6184,6 +6202,6 @@ union generic_reply
struct
terminate_job_reply
terminate_job_reply
;
};
#define SERVER_PROTOCOL_VERSION 50
2
#define SERVER_PROTOCOL_VERSION 50
3
#endif
/* __WINE_WINE_SERVER_PROTOCOL_H */
server/change.c
View file @
80f3fda9
...
...
@@ -141,6 +141,8 @@ struct dir
struct
list
change_records
;
/* data for the change */
struct
list
in_entry
;
/* entry in the inode dirs list */
struct
inode
*
inode
;
/* inode of the associated directory */
struct
process
*
client_process
;
/* client process that has a cache for this directory */
int
client_entry
;
/* entry in client process cache */
};
static
struct
fd
*
dir_get_fd
(
struct
object
*
obj
);
...
...
@@ -149,6 +151,7 @@ static int dir_set_sd( struct object *obj, const struct security_descriptor *sd,
unsigned
int
set_info
);
static
void
dir_dump
(
struct
object
*
obj
,
int
verbose
);
static
struct
object_type
*
dir_get_type
(
struct
object
*
obj
);
static
int
dir_close_handle
(
struct
object
*
obj
,
struct
process
*
process
,
obj_handle_t
handle
);
static
void
dir_destroy
(
struct
object
*
obj
);
static
const
struct
object_ops
dir_ops
=
...
...
@@ -169,7 +172,7 @@ static const struct object_ops dir_ops =
no_link_name
,
/* link_name */
NULL
,
/* unlink_name */
no_open_file
,
/* open_file */
fd_close_handle
,
/* close_handle */
dir_close_handle
,
/* close_handle */
dir_destroy
/* destroy */
};
...
...
@@ -192,6 +195,86 @@ static const struct fd_ops dir_fd_ops =
static
struct
list
change_list
=
LIST_INIT
(
change_list
);
/* per-process structure to keep track of cache entries on the client size */
struct
dir_cache
{
unsigned
int
size
;
unsigned
int
count
;
unsigned
char
state
[
1
];
};
enum
dir_cache_state
{
DIR_CACHE_STATE_FREE
,
DIR_CACHE_STATE_INUSE
,
DIR_CACHE_STATE_RELEASED
};
/* return an array of cache entries that can be freed on the client side */
static
int
*
get_free_dir_cache_entries
(
struct
process
*
process
,
data_size_t
*
size
)
{
int
*
ret
;
struct
dir_cache
*
cache
=
process
->
dir_cache
;
unsigned
int
i
,
j
,
count
;
if
(
!
cache
)
return
NULL
;
for
(
i
=
count
=
0
;
i
<
cache
->
count
&&
count
<
*
size
/
sizeof
(
*
ret
);
i
++
)
if
(
cache
->
state
[
i
]
==
DIR_CACHE_STATE_RELEASED
)
count
++
;
if
(
!
count
)
return
NULL
;
if
((
ret
=
malloc
(
count
*
sizeof
(
*
ret
)
)))
{
for
(
i
=
j
=
0
;
j
<
count
;
i
++
)
{
if
(
cache
->
state
[
i
]
!=
DIR_CACHE_STATE_RELEASED
)
continue
;
cache
->
state
[
i
]
=
DIR_CACHE_STATE_FREE
;
ret
[
j
++
]
=
i
;
}
*
size
=
count
*
sizeof
(
*
ret
);
}
return
ret
;
}
/* allocate a new client-side directory cache entry */
static
int
alloc_dir_cache_entry
(
struct
dir
*
dir
,
struct
process
*
process
)
{
unsigned
int
i
=
0
;
struct
dir_cache
*
cache
=
process
->
dir_cache
;
if
(
cache
)
for
(
i
=
0
;
i
<
cache
->
count
;
i
++
)
if
(
cache
->
state
[
i
]
==
DIR_CACHE_STATE_FREE
)
goto
found
;
if
(
!
cache
||
cache
->
count
==
cache
->
size
)
{
unsigned
int
size
=
cache
?
cache
->
size
*
2
:
256
;
if
(
!
(
cache
=
realloc
(
cache
,
offsetof
(
struct
dir_cache
,
state
[
size
]
))))
{
set_error
(
STATUS_NO_MEMORY
);
return
-
1
;
}
process
->
dir_cache
=
cache
;
cache
->
size
=
size
;
}
cache
->
count
=
i
+
1
;
found:
cache
->
state
[
i
]
=
DIR_CACHE_STATE_INUSE
;
return
i
;
}
/* release a directory cache entry; it will be freed on the client side on the next cache request */
static
void
release_dir_cache_entry
(
struct
dir
*
dir
)
{
struct
dir_cache
*
cache
;
if
(
!
dir
->
client_process
)
return
;
cache
=
dir
->
client_process
->
dir_cache
;
cache
->
state
[
dir
->
client_entry
]
=
DIR_CACHE_STATE_RELEASED
;
release_object
(
dir
->
client_process
);
dir
->
client_process
=
NULL
;
}
static
void
dnotify_adjust_changes
(
struct
dir
*
dir
)
{
#if defined(F_SETSIG) && defined(F_NOTIFY)
...
...
@@ -385,6 +468,15 @@ static struct change_record *get_first_change_record( struct dir *dir )
return
LIST_ENTRY
(
ptr
,
struct
change_record
,
entry
);
}
static
int
dir_close_handle
(
struct
object
*
obj
,
struct
process
*
process
,
obj_handle_t
handle
)
{
struct
dir
*
dir
=
(
struct
dir
*
)
obj
;
if
(
!
fd_close_handle
(
obj
,
process
,
handle
))
return
0
;
if
(
obj
->
handle_count
==
1
)
release_dir_cache_entry
(
dir
);
/* closing last handle, release cache */
return
1
;
/* ok to close */
}
static
void
dir_destroy
(
struct
object
*
obj
)
{
struct
change_record
*
record
;
...
...
@@ -402,6 +494,7 @@ static void dir_destroy( struct object *obj )
while
((
record
=
get_first_change_record
(
dir
)))
free
(
record
);
release_dir_cache_entry
(
dir
);
release_object
(
dir
->
fd
);
if
(
inotify_fd
&&
list_empty
(
&
change_list
))
...
...
@@ -1104,6 +1197,7 @@ struct object *create_dir_obj( struct fd *fd, unsigned int access, mode_t mode )
dir
->
fd
=
fd
;
dir
->
mode
=
mode
;
dir
->
uid
=
~
(
uid_t
)
0
;
dir
->
client_process
=
NULL
;
set_fd_user
(
fd
,
&
dir_fd_ops
,
&
dir
->
obj
);
dir_add_to_existing_notify
(
dir
);
...
...
@@ -1111,6 +1205,32 @@ struct object *create_dir_obj( struct fd *fd, unsigned int access, mode_t mode )
return
&
dir
->
obj
;
}
/* retrieve (or allocate) the client-side directory cache entry */
DECL_HANDLER
(
get_directory_cache_entry
)
{
struct
dir
*
dir
;
int
*
free_entries
;
data_size_t
free_size
;
if
(
!
(
dir
=
get_dir_obj
(
current
->
process
,
req
->
handle
,
0
)))
return
;
if
(
!
dir
->
client_process
)
{
if
((
dir
->
client_entry
=
alloc_dir_cache_entry
(
dir
,
current
->
process
))
==
-
1
)
goto
done
;
dir
->
client_process
=
(
struct
process
*
)
grab_object
(
current
->
process
);
}
if
(
dir
->
client_process
==
current
->
process
)
reply
->
entry
=
dir
->
client_entry
;
else
set_error
(
STATUS_SHARING_VIOLATION
);
done
:
/* allow freeing entries even on failure */
free_size
=
get_reply_max_size
();
free_entries
=
get_free_dir_cache_entries
(
current
->
process
,
&
free_size
);
if
(
free_entries
)
set_reply_data_ptr
(
free_entries
,
free_size
);
release_object
(
dir
);
}
/* enable change notifications for a directory */
DECL_HANDLER
(
read_directory_changes
)
{
...
...
server/process.c
View file @
80f3fda9
...
...
@@ -526,6 +526,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit
process
->
idle_event
=
NULL
;
process
->
peb
=
0
;
process
->
ldt_copy
=
0
;
process
->
dir_cache
=
NULL
;
process
->
winstation
=
0
;
process
->
desktop
=
0
;
process
->
token
=
NULL
;
...
...
@@ -630,6 +631,7 @@ static void process_destroy( struct object *obj )
if
(
process
->
idle_event
)
release_object
(
process
->
idle_event
);
if
(
process
->
id
)
free_ptid
(
process
->
id
);
if
(
process
->
token
)
release_object
(
process
->
token
);
free
(
process
->
dir_cache
);
}
/* dump a process on stdout for debugging purposes */
...
...
server/process.h
View file @
80f3fda9
...
...
@@ -90,6 +90,7 @@ struct process
struct
list
dlls
;
/* list of loaded dlls */
client_ptr_t
peb
;
/* PEB address in client address space */
client_ptr_t
ldt_copy
;
/* pointer to LDT copy in client addr space */
struct
dir_cache
*
dir_cache
;
/* map of client-side directory cache */
unsigned
int
trace_data
;
/* opaque data used by the process tracing mechanism */
struct
list
rawinput_devices
;
/* list of registered rawinput devices */
const
struct
rawinput_device
*
rawinput_mouse
;
/* rawinput mouse device, if any */
...
...
server/protocol.def
View file @
80f3fda9
...
...
@@ -1200,6 +1200,15 @@ enum server_fd_type
};
/* Retrieve (or allocate) the client-side directory cache entry */
@REQ(get_directory_cache_entry)
obj_handle_t handle; /* handle to the directory */
@REPLY
int entry; /* cache entry on the client side */
VARARG(free,ints); /* entries that can be freed */
@END
/* Flush a file buffers */
@REQ(flush)
int blocking; /* whether it's a blocking flush */
...
...
server/request.h
View file @
80f3fda9
...
...
@@ -156,6 +156,7 @@ DECL_HANDLER(open_file_object);
DECL_HANDLER
(
alloc_file_handle
);
DECL_HANDLER
(
get_handle_unix_name
);
DECL_HANDLER
(
get_handle_fd
);
DECL_HANDLER
(
get_directory_cache_entry
);
DECL_HANDLER
(
flush
);
DECL_HANDLER
(
lock_file
);
DECL_HANDLER
(
unlock_file
);
...
...
@@ -433,6 +434,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(
req_handler
)
req_alloc_file_handle
,
(
req_handler
)
req_get_handle_unix_name
,
(
req_handler
)
req_get_handle_fd
,
(
req_handler
)
req_get_directory_cache_entry
,
(
req_handler
)
req_flush
,
(
req_handler
)
req_lock_file
,
(
req_handler
)
req_unlock_file
,
...
...
@@ -975,6 +977,10 @@ C_ASSERT( FIELD_OFFSET(struct get_handle_fd_reply, cacheable) == 12 );
C_ASSERT
(
FIELD_OFFSET
(
struct
get_handle_fd_reply
,
access
)
==
16
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_handle_fd_reply
,
options
)
==
20
);
C_ASSERT
(
sizeof
(
struct
get_handle_fd_reply
)
==
24
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_directory_cache_entry_request
,
handle
)
==
12
);
C_ASSERT
(
sizeof
(
struct
get_directory_cache_entry_request
)
==
16
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_directory_cache_entry_reply
,
entry
)
==
8
);
C_ASSERT
(
sizeof
(
struct
get_directory_cache_entry_reply
)
==
16
);
C_ASSERT
(
FIELD_OFFSET
(
struct
flush_request
,
blocking
)
==
12
);
C_ASSERT
(
FIELD_OFFSET
(
struct
flush_request
,
async
)
==
16
);
C_ASSERT
(
sizeof
(
struct
flush_request
)
==
56
);
...
...
server/trace.c
View file @
80f3fda9
...
...
@@ -1717,6 +1717,17 @@ static void dump_get_handle_fd_reply( const struct get_handle_fd_reply *req )
fprintf
(
stderr
,
", options=%08x"
,
req
->
options
);
}
static
void
dump_get_directory_cache_entry_request
(
const
struct
get_directory_cache_entry_request
*
req
)
{
fprintf
(
stderr
,
" handle=%04x"
,
req
->
handle
);
}
static
void
dump_get_directory_cache_entry_reply
(
const
struct
get_directory_cache_entry_reply
*
req
)
{
fprintf
(
stderr
,
" entry=%d"
,
req
->
entry
);
dump_varargs_ints
(
", free="
,
cur_size
);
}
static
void
dump_flush_request
(
const
struct
flush_request
*
req
)
{
fprintf
(
stderr
,
" blocking=%d"
,
req
->
blocking
);
...
...
@@ -4344,6 +4355,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
dump_alloc_file_handle_request
,
(
dump_func
)
dump_get_handle_unix_name_request
,
(
dump_func
)
dump_get_handle_fd_request
,
(
dump_func
)
dump_get_directory_cache_entry_request
,
(
dump_func
)
dump_flush_request
,
(
dump_func
)
dump_lock_file_request
,
(
dump_func
)
dump_unlock_file_request
,
...
...
@@ -4618,6 +4630,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
dump_alloc_file_handle_reply
,
(
dump_func
)
dump_get_handle_unix_name_reply
,
(
dump_func
)
dump_get_handle_fd_reply
,
(
dump_func
)
dump_get_directory_cache_entry_reply
,
(
dump_func
)
dump_flush_reply
,
(
dump_func
)
dump_lock_file_reply
,
NULL
,
...
...
@@ -4892,6 +4905,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"alloc_file_handle"
,
"get_handle_unix_name"
,
"get_handle_fd"
,
"get_directory_cache_entry"
,
"flush"
,
"lock_file"
,
"unlock_file"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment