Changes in uspace/srv/vfs/vfs_file.c [4fe94c66:553492be] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/vfs/vfs_file.c
r4fe94c66 r553492be 38 38 #include <errno.h> 39 39 #include <stdlib.h> 40 #include <str .h>40 #include <string.h> 41 41 #include <assert.h> 42 42 #include <bool.h> 43 43 #include <fibril.h> 44 #include <fibril_sync h.h>44 #include <fibril_sync.h> 45 45 #include "vfs.h" 46 46 47 #define VFS_DATA ((vfs_client_data_t *) async_client_data_get()) 48 #define FILES (VFS_DATA->files) 49 50 typedef struct { 51 fibril_mutex_t lock; 52 vfs_file_t **files; 53 } vfs_client_data_t; 47 /** 48 * This is a per-connection table of open files. 49 * Our assumption is that each client opens only one connection and therefore 50 * there is one table of open files per task. However, this may not be the case 51 * and the client can open more connections to VFS. In that case, there will be 52 * several tables and several file handle name spaces per task. Besides of this, 53 * the functionality will stay unchanged. So unless the client knows what it is 54 * doing, it should open one connection to VFS only. 55 * 56 * Allocation of the open files table is deferred until the client makes the 57 * first VFS_OPEN operation. 58 * 59 * This resource being per-connection and, in the first place, per-fibril, we 60 * don't need to protect it by a mutex. 61 */ 62 fibril_local vfs_file_t **files = NULL; 54 63 55 64 /** Initialize the table of open files. */ 56 staticbool vfs_files_init(void)65 bool vfs_files_init(void) 57 66 { 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 if (!files) { 68 files = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *)); 69 if (!files) 63 70 return false; 64 } 65 memset(FILES, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *)); 71 memset(files, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *)); 66 72 } 67 fibril_mutex_unlock(&VFS_DATA->lock);68 73 return true; 69 74 } 70 75 71 /** Cleanup the table of open files. */72 static void vfs_files_done(void)73 {74 int i;75 76 if (!FILES)77 return;78 79 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);87 }88 89 void *vfs_client_data_create(void)90 {91 vfs_client_data_t *vfs_data;92 93 vfs_data = malloc(sizeof(vfs_client_data_t));94 if (vfs_data) {95 fibril_mutex_initialize(&vfs_data->lock);96 vfs_data->files = NULL;97 }98 99 return vfs_data;100 }101 102 void vfs_client_data_destroy(void *data)103 {104 vfs_client_data_t *vfs_data = (vfs_client_data_t *) data;105 106 vfs_files_done();107 free(vfs_data);108 }109 110 /** Increment reference count of VFS file structure.111 *112 * @param file File structure that will have reference count113 * incremented.114 */115 static void vfs_file_addref(vfs_file_t *file)116 {117 assert(fibril_mutex_is_locked(&VFS_DATA->lock));118 119 file->refcnt++;120 }121 122 /** Decrement reference count of VFS file structure.123 *124 * @param file File structure that will have reference count125 * decremented.126 */127 static void vfs_file_delref(vfs_file_t *file)128 {129 assert(fibril_mutex_is_locked(&VFS_DATA->lock));130 131 if (file->refcnt-- == 1) {132 /*133 * Lost the last reference to a file, need to drop our reference134 * to the underlying VFS node.135 */136 vfs_node_delref(file->node);137 free(file);138 }139 }140 141 142 76 /** Allocate a file descriptor. 143 77 * 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. 78 * @return First available file descriptor or a negative error 79 * code. 149 80 */ 150 int vfs_fd_alloc( bool desc)81 int vfs_fd_alloc(void) 151 82 { 152 83 if (!vfs_files_init()) … … 154 85 155 86 unsigned int i; 156 if (desc) 157 i = MAX_OPEN_FILES - 1; 158 else 159 i = 0; 160 161 fibril_mutex_lock(&VFS_DATA->lock); 162 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); 87 for (i = 0; i < MAX_OPEN_FILES; i++) { 88 if (!files[i]) { 89 files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t)); 90 if (!files[i]) 167 91 return ENOMEM; 168 }169 92 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); 93 memset(files[i], 0, sizeof(vfs_file_t)); 94 fibril_mutex_initialize(&files[i]->lock); 95 vfs_file_addref(files[i]); 174 96 return (int) i; 175 97 } 176 177 if (desc) {178 if (i == 0)179 break;180 181 i--;182 } else {183 if (i == MAX_OPEN_FILES - 1)184 break;185 186 i++;187 }188 98 } 189 fibril_mutex_unlock(&VFS_DATA->lock);190 99 191 100 return EMFILE; … … 203 112 if (!vfs_files_init()) 204 113 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); 114 115 if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (files[fd] == NULL)) 209 116 return EBADF; 210 }211 117 212 vfs_file_delref(FILES[fd]); 213 FILES[fd] = NULL; 214 fibril_mutex_unlock(&VFS_DATA->lock); 118 vfs_file_delref(files[fd]); 119 files[fd] = NULL; 215 120 216 121 return EOK; 217 122 } 218 123 219 /** Assign a file to a file descriptor.124 /** Increment reference count of VFS file structure. 220 125 * 221 * @param file File to assign. 222 * @param fd File descriptor to assign to. 126 * @param file File structure that will have reference count 127 * incremented. 128 */ 129 void vfs_file_addref(vfs_file_t *file) 130 { 131 /* 132 * File structures are per-connection, so no-one, except the current 133 * fibril, should have a reference to them. This is the reason we don't 134 * do any synchronization here. 135 */ 136 file->refcnt++; 137 } 138 139 /** Decrement reference count of VFS file structure. 223 140 * 224 * @return EOK on success or EINVAL if fd is an invalid or already 225 * used file descriptor. 226 * 141 * @param file File structure that will have reference count 142 * decremented. 227 143 */ 228 int vfs_fd_assign(vfs_file_t *file, int fd)144 void vfs_file_delref(vfs_file_t *file) 229 145 { 230 if ( !vfs_files_init())231 return ENOMEM;232 233 fibril_mutex_lock(&VFS_DATA->lock);234 if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (FILES[fd] != NULL)) {235 fibril_mutex_unlock(&VFS_DATA->lock);236 return EINVAL;146 if (file->refcnt-- == 1) { 147 /* 148 * Lost the last reference to a file, need to drop our reference 149 * to the underlying VFS node. 150 */ 151 vfs_node_delref(file->node); 152 free(file); 237 153 } 238 239 FILES[fd] = file;240 vfs_file_addref(FILES[fd]);241 fibril_mutex_unlock(&VFS_DATA->lock);242 243 return EOK;244 154 } 245 155 … … 255 165 return NULL; 256 166 257 fibril_mutex_lock(&VFS_DATA->lock); 258 if ((fd >= 0) && (fd < MAX_OPEN_FILES)) { 259 vfs_file_t *file = FILES[fd]; 260 vfs_file_addref(file); 261 fibril_mutex_unlock(&VFS_DATA->lock); 262 return file; 263 } 264 fibril_mutex_unlock(&VFS_DATA->lock); 167 if ((fd >= 0) && (fd < MAX_OPEN_FILES)) 168 return files[fd]; 265 169 266 170 return NULL; 267 }268 269 /** Stop using a file structure.270 *271 * @param file VFS file structure.272 */273 void vfs_file_put(vfs_file_t *file)274 {275 fibril_mutex_lock(&VFS_DATA->lock);276 vfs_file_delref(file);277 fibril_mutex_unlock(&VFS_DATA->lock);278 171 } 279 172
Note:
See TracChangeset
for help on using the changeset viewer.