Changes in uspace/srv/vfs/vfs_file.c [6639ae1:e2ab36f1] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/vfs/vfs_file.c
r6639ae1 re2ab36f1 43 43 #include <fibril.h> 44 44 #include <fibril_synch.h> 45 #include <adt/list.h> 46 #include <task.h> 45 47 #include "vfs.h" 46 48 47 #define VFS_DATA ((vfs_client_data_t *) async_ client_data_get())49 #define VFS_DATA ((vfs_client_data_t *) async_get_client_data()) 48 50 #define FILES (VFS_DATA->files) 49 51 50 52 typedef struct { 51 53 fibril_mutex_t lock; 54 fibril_condvar_t cv; 55 list_t passed_handles; 52 56 vfs_file_t **files; 53 57 } vfs_client_data_t; 54 58 59 typedef struct { 60 link_t link; 61 int handle; 62 } vfs_boxed_handle_t; 63 64 static int _vfs_fd_free(vfs_client_data_t *, int); 65 55 66 /** Initialize the table of open files. */ 56 static bool vfs_files_init(v oid)57 { 58 fibril_mutex_lock(& VFS_DATA->lock);59 if (! FILES) {60 FILES= malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *));61 if (! FILES) {62 fibril_mutex_unlock(& VFS_DATA->lock);67 static bool vfs_files_init(vfs_client_data_t *vfs_data) 68 { 69 fibril_mutex_lock(&vfs_data->lock); 70 if (!vfs_data->files) { 71 vfs_data->files = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *)); 72 if (!vfs_data->files) { 73 fibril_mutex_unlock(&vfs_data->lock); 63 74 return false; 64 75 } 65 memset( FILES, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));66 } 67 fibril_mutex_unlock(& VFS_DATA->lock);76 memset(vfs_data->files, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *)); 77 } 78 fibril_mutex_unlock(&vfs_data->lock); 68 79 return true; 69 80 } 70 81 71 82 /** Cleanup the table of open files. */ 72 static void vfs_files_done(v oid)83 static void vfs_files_done(vfs_client_data_t *vfs_data) 73 84 { 74 85 int i; 75 86 76 if (! FILES)87 if (!vfs_data->files) 77 88 return; 78 89 79 90 for (i = 0; i < MAX_OPEN_FILES; i++) { 80 if (FILES[i]) { 81 (void) vfs_close_internal(FILES[i]); 82 (void) vfs_fd_free(i); 83 } 84 } 85 86 free(FILES); 91 if (vfs_data->files[i]) 92 (void) _vfs_fd_free(vfs_data, i); 93 } 94 95 free(vfs_data->files); 96 97 while (!list_empty(&vfs_data->passed_handles)) { 98 link_t *lnk; 99 vfs_boxed_handle_t *bh; 100 101 lnk = list_first(&vfs_data->passed_handles); 102 list_remove(lnk); 103 104 bh = list_get_instance(lnk, vfs_boxed_handle_t, link); 105 free(bh); 106 } 87 107 } 88 108 … … 94 114 if (vfs_data) { 95 115 fibril_mutex_initialize(&vfs_data->lock); 116 fibril_condvar_initialize(&vfs_data->cv); 117 list_initialize(&vfs_data->passed_handles); 96 118 vfs_data->files = NULL; 97 119 } … … 104 126 vfs_client_data_t *vfs_data = (vfs_client_data_t *) data; 105 127 106 vfs_files_done( );128 vfs_files_done(vfs_data); 107 129 free(vfs_data); 130 } 131 132 /** Close the file in the endpoint FS server. */ 133 static int vfs_file_close_remote(vfs_file_t *file) 134 { 135 assert(!file->refcnt); 136 137 async_exch_t *exch = vfs_exchange_grab(file->node->fs_handle); 138 139 ipc_call_t answer; 140 aid_t msg = async_send_2(exch, VFS_OUT_CLOSE, file->node->service_id, 141 file->node->index, &answer); 142 143 vfs_exchange_release(exch); 144 145 sysarg_t rc; 146 async_wait_for(msg, &rc); 147 148 return IPC_GET_ARG1(answer); 108 149 } 109 150 … … 113 154 * incremented. 114 155 */ 115 static void vfs_file_addref(vfs_ file_t *file)116 { 117 assert(fibril_mutex_is_locked(& VFS_DATA->lock));156 static void vfs_file_addref(vfs_client_data_t *vfs_data, vfs_file_t *file) 157 { 158 assert(fibril_mutex_is_locked(&vfs_data->lock)); 118 159 119 160 file->refcnt++; … … 125 166 * decremented. 126 167 */ 127 static void vfs_file_delref(vfs_file_t *file) 128 { 129 assert(fibril_mutex_is_locked(&VFS_DATA->lock)); 168 static int vfs_file_delref(vfs_client_data_t *vfs_data, vfs_file_t *file) 169 { 170 int rc = EOK; 171 172 assert(fibril_mutex_is_locked(&vfs_data->lock)); 130 173 131 174 if (file->refcnt-- == 1) { 132 175 /* 133 * Lost the last reference to a file, need to drop our reference134 * to the underlying VFS node.176 * Lost the last reference to a file, need to close it in the 177 * endpoint FS and drop our reference to the underlying VFS node. 135 178 */ 179 rc = vfs_file_close_remote(file); 136 180 vfs_node_delref(file->node); 137 181 free(file); 138 182 } 139 } 140 141 142 /** Allocate a file descriptor. 143 * 144 * @param desc If true, look for an available file descriptor 145 * in a descending order. 146 * 147 * @return First available file descriptor or a negative error 148 * code. 149 */ 150 int vfs_fd_alloc(bool desc) 151 { 152 if (!vfs_files_init()) 183 184 return rc; 185 } 186 187 static int _vfs_fd_alloc(vfs_client_data_t *vfs_data, bool desc) 188 { 189 if (!vfs_files_init(vfs_data)) 153 190 return ENOMEM; 154 191 … … 159 196 i = 0; 160 197 161 fibril_mutex_lock(& VFS_DATA->lock);198 fibril_mutex_lock(&vfs_data->lock); 162 199 while (true) { 163 if (! FILES[i]) {164 FILES[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));165 if (! FILES[i]) {166 fibril_mutex_unlock(& VFS_DATA->lock);200 if (!vfs_data->files[i]) { 201 vfs_data->files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t)); 202 if (!vfs_data->files[i]) { 203 fibril_mutex_unlock(&vfs_data->lock); 167 204 return ENOMEM; 168 205 } 169 206 170 memset( FILES[i], 0, sizeof(vfs_file_t));171 fibril_mutex_initialize(& FILES[i]->lock);172 vfs_file_addref( FILES[i]);173 fibril_mutex_unlock(& VFS_DATA->lock);207 memset(vfs_data->files[i], 0, sizeof(vfs_file_t)); 208 fibril_mutex_initialize(&vfs_data->files[i]->lock); 209 vfs_file_addref(vfs_data, vfs_data->files[i]); 210 fibril_mutex_unlock(&vfs_data->lock); 174 211 return (int) i; 175 212 } … … 187 224 } 188 225 } 189 fibril_mutex_unlock(& VFS_DATA->lock);226 fibril_mutex_unlock(&vfs_data->lock); 190 227 191 228 return EMFILE; 229 } 230 231 /** Allocate a file descriptor. 232 * 233 * @param desc If true, look for an available file descriptor 234 * in a descending order. 235 * 236 * @return First available file descriptor or a negative error 237 * code. 238 */ 239 int vfs_fd_alloc(bool desc) 240 { 241 return _vfs_fd_alloc(VFS_DATA, desc); 242 } 243 244 static int _vfs_fd_free(vfs_client_data_t *vfs_data, int fd) 245 { 246 int rc; 247 248 if (!vfs_files_init(vfs_data)) 249 return ENOMEM; 250 251 fibril_mutex_lock(&vfs_data->lock); 252 if ((fd < 0) || (fd >= MAX_OPEN_FILES) || !vfs_data->files[fd]) { 253 fibril_mutex_unlock(&vfs_data->lock); 254 return EBADF; 255 } 256 257 rc = vfs_file_delref(vfs_data, vfs_data->files[fd]); 258 vfs_data->files[fd] = NULL; 259 fibril_mutex_unlock(&vfs_data->lock); 260 261 return rc; 192 262 } 193 263 … … 201 271 int vfs_fd_free(int fd) 202 272 { 203 if (!vfs_files_init()) 204 return ENOMEM; 205 206 fibril_mutex_lock(&VFS_DATA->lock); 207 if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (FILES[fd] == NULL)) { 208 fibril_mutex_unlock(&VFS_DATA->lock); 209 return EBADF; 210 } 211 212 vfs_file_delref(FILES[fd]); 213 FILES[fd] = NULL; 214 fibril_mutex_unlock(&VFS_DATA->lock); 215 216 return EOK; 273 return _vfs_fd_free(VFS_DATA, fd); 217 274 } 218 275 … … 228 285 int vfs_fd_assign(vfs_file_t *file, int fd) 229 286 { 230 if (!vfs_files_init( ))287 if (!vfs_files_init(VFS_DATA)) 231 288 return ENOMEM; 232 289 … … 238 295 239 296 FILES[fd] = file; 240 vfs_file_addref( FILES[fd]);297 vfs_file_addref(VFS_DATA, FILES[fd]); 241 298 fibril_mutex_unlock(&VFS_DATA->lock); 242 299 … … 244 301 } 245 302 246 /** Find VFS file structure for a given file descriptor. 247 * 248 * @param fd File descriptor. 249 * 250 * @return VFS file structure corresponding to fd. 251 */ 252 vfs_file_t *vfs_file_get(int fd) 253 { 254 if (!vfs_files_init()) 303 static vfs_file_t *_vfs_file_get(vfs_client_data_t *vfs_data, int fd) 304 { 305 if (!vfs_files_init(vfs_data)) 255 306 return NULL; 256 307 257 fibril_mutex_lock(& VFS_DATA->lock);308 fibril_mutex_lock(&vfs_data->lock); 258 309 if ((fd >= 0) && (fd < MAX_OPEN_FILES)) { 259 vfs_file_t *file = FILES[fd];310 vfs_file_t *file = vfs_data->files[fd]; 260 311 if (file != NULL) { 261 vfs_file_addref( file);262 fibril_mutex_unlock(& VFS_DATA->lock);312 vfs_file_addref(vfs_data, file); 313 fibril_mutex_unlock(&vfs_data->lock); 263 314 return file; 264 315 } 265 316 } 266 fibril_mutex_unlock(& VFS_DATA->lock);317 fibril_mutex_unlock(&vfs_data->lock); 267 318 268 319 return NULL; 269 320 } 270 321 322 /** Find VFS file structure for a given file descriptor. 323 * 324 * @param fd File descriptor. 325 * 326 * @return VFS file structure corresponding to fd. 327 */ 328 vfs_file_t *vfs_file_get(int fd) 329 { 330 return _vfs_file_get(VFS_DATA, fd); 331 } 332 333 static void _vfs_file_put(vfs_client_data_t *vfs_data, vfs_file_t *file) 334 { 335 fibril_mutex_lock(&vfs_data->lock); 336 vfs_file_delref(vfs_data, file); 337 fibril_mutex_unlock(&vfs_data->lock); 338 } 339 271 340 /** Stop using a file structure. 272 341 * … … 275 344 void vfs_file_put(vfs_file_t *file) 276 345 { 277 fibril_mutex_lock(&VFS_DATA->lock); 278 vfs_file_delref(file); 279 fibril_mutex_unlock(&VFS_DATA->lock); 346 _vfs_file_put(VFS_DATA, file); 347 } 348 349 void vfs_pass_handle(task_id_t donor_id, task_id_t acceptor_id, int donor_fd) 350 { 351 vfs_client_data_t *donor_data = NULL; 352 vfs_client_data_t *acceptor_data = NULL; 353 vfs_file_t *donor_file = NULL; 354 vfs_file_t *acceptor_file = NULL; 355 vfs_boxed_handle_t *bh; 356 int acceptor_fd; 357 358 acceptor_data = async_get_client_data_by_id(acceptor_id); 359 if (!acceptor_data) 360 return; 361 362 bh = malloc(sizeof(vfs_boxed_handle_t)); 363 assert(bh); 364 365 link_initialize(&bh->link); 366 bh->handle = -1; 367 368 donor_data = async_get_client_data_by_id(donor_id); 369 if (!donor_data) 370 goto out; 371 372 donor_file = _vfs_file_get(donor_data, donor_fd); 373 if (!donor_file) 374 goto out; 375 376 acceptor_fd = _vfs_fd_alloc(acceptor_data, false); 377 if (acceptor_fd < 0) 378 goto out; 379 380 bh->handle = acceptor_fd; 381 382 /* 383 * Add a new reference to the underlying VFS node. 384 */ 385 vfs_node_addref(donor_file->node); 386 (void) vfs_open_node_remote(donor_file->node); 387 388 acceptor_file = _vfs_file_get(acceptor_data, acceptor_fd); 389 assert(acceptor_file); 390 391 /* 392 * Inherit attributes from the donor. 393 */ 394 acceptor_file->node = donor_file->node; 395 acceptor_file->append = donor_file->append; 396 acceptor_file->pos = donor_file->pos; 397 398 out: 399 fibril_mutex_lock(&acceptor_data->lock); 400 list_append(&bh->link, &acceptor_data->passed_handles); 401 fibril_condvar_broadcast(&acceptor_data->cv); 402 fibril_mutex_unlock(&acceptor_data->lock); 403 404 if (donor_data) 405 async_put_client_data_by_id(donor_id); 406 if (acceptor_data) 407 async_put_client_data_by_id(acceptor_id); 408 if (donor_file) 409 _vfs_file_put(donor_data, donor_file); 410 if (acceptor_file) 411 _vfs_file_put(acceptor_data, acceptor_file); 412 413 } 414 415 int vfs_wait_handle_internal(void) 416 { 417 vfs_client_data_t *vfs_data = VFS_DATA; 418 int fd; 419 420 fibril_mutex_lock(&vfs_data->lock); 421 while (list_empty(&vfs_data->passed_handles)) 422 fibril_condvar_wait(&vfs_data->cv, &vfs_data->lock); 423 link_t *lnk = list_first(&vfs_data->passed_handles); 424 list_remove(lnk); 425 fibril_mutex_unlock(&vfs_data->lock); 426 427 vfs_boxed_handle_t *bh = list_get_instance(lnk, vfs_boxed_handle_t, link); 428 fd = bh->handle; 429 free(bh); 430 431 return fd; 280 432 } 281 433
Note:
See TracChangeset
for help on using the changeset viewer.