Changes in uspace/srv/vfs/vfs_file.c [6639ae1:19f857a] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/vfs/vfs_file.c
r6639ae1 r19f857a 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 static bool vfs_files_init(void) 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); 65 bool vfs_files_init(void) 66 { 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 *)); 66 } 67 fibril_mutex_unlock(&VFS_DATA->lock); 71 memset(files, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *)); 72 } 68 73 return true; 69 74 } 70 75 71 76 /** Cleanup the table of open files. */ 72 staticvoid vfs_files_done(void)77 void vfs_files_done(void) 73 78 { 74 79 int i; 75 80 76 if (! FILES)81 if (!files) 77 82 return; 78 83 79 84 for (i = 0; i < MAX_OPEN_FILES; i++) { 80 if ( FILES[i]) {81 (void) vfs_close_internal( FILES[i]);85 if (files[i]) { 86 (void) vfs_close_internal(files[i]); 82 87 (void) vfs_fd_free(i); 83 88 } 84 89 } 85 90 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 count 113 * 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 count 125 * 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 reference 134 * to the underlying VFS node. 135 */ 136 vfs_node_delref(file->node); 137 free(file); 138 } 139 } 140 91 free(files); 92 } 141 93 142 94 /** Allocate a file descriptor. … … 159 111 i = 0; 160 112 161 fibril_mutex_lock(&VFS_DATA->lock);162 113 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); 114 if (!files[i]) { 115 files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t)); 116 if (!files[i]) 167 117 return ENOMEM; 168 }169 118 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); 119 memset(files[i], 0, sizeof(vfs_file_t)); 120 fibril_mutex_initialize(&files[i]->lock); 121 vfs_file_addref(files[i]); 174 122 return (int) i; 175 123 } … … 187 135 } 188 136 } 189 fibril_mutex_unlock(&VFS_DATA->lock);190 137 191 138 return EMFILE; … … 203 150 if (!vfs_files_init()) 204 151 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); 152 153 if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (files[fd] == NULL)) 209 154 return EBADF; 210 } 211 212 vfs_file_delref(FILES[fd]); 213 FILES[fd] = NULL; 214 fibril_mutex_unlock(&VFS_DATA->lock); 155 156 vfs_file_delref(files[fd]); 157 files[fd] = NULL; 215 158 216 159 return EOK; … … 230 173 if (!vfs_files_init()) 231 174 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); 175 176 if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (files[fd] != NULL)) 236 177 return EINVAL; 237 } 238 239 FILES[fd] = file; 240 vfs_file_addref(FILES[fd]); 241 fibril_mutex_unlock(&VFS_DATA->lock); 178 179 files[fd] = file; 180 vfs_file_addref(files[fd]); 242 181 243 182 return EOK; 244 183 } 245 184 185 /** Increment reference count of VFS file structure. 186 * 187 * @param file File structure that will have reference count 188 * incremented. 189 */ 190 void vfs_file_addref(vfs_file_t *file) 191 { 192 /* 193 * File structures are per-connection, so no-one, except the current 194 * fibril, should have a reference to them. This is the reason we don't 195 * do any synchronization here. 196 */ 197 file->refcnt++; 198 } 199 200 /** Decrement reference count of VFS file structure. 201 * 202 * @param file File structure that will have reference count 203 * decremented. 204 */ 205 void vfs_file_delref(vfs_file_t *file) 206 { 207 if (file->refcnt-- == 1) { 208 /* 209 * Lost the last reference to a file, need to drop our reference 210 * to the underlying VFS node. 211 */ 212 vfs_node_delref(file->node); 213 free(file); 214 } 215 } 216 246 217 /** Find VFS file structure for a given file descriptor. 247 218 * … … 255 226 return NULL; 256 227 257 fibril_mutex_lock(&VFS_DATA->lock); 258 if ((fd >= 0) && (fd < MAX_OPEN_FILES)) { 259 vfs_file_t *file = FILES[fd]; 260 if (file != NULL) { 261 vfs_file_addref(file); 262 fibril_mutex_unlock(&VFS_DATA->lock); 263 return file; 264 } 265 } 266 fibril_mutex_unlock(&VFS_DATA->lock); 228 if ((fd >= 0) && (fd < MAX_OPEN_FILES)) 229 return files[fd]; 267 230 268 231 return NULL; 269 }270 271 /** Stop using a file structure.272 *273 * @param file VFS file structure.274 */275 void vfs_file_put(vfs_file_t *file)276 {277 fibril_mutex_lock(&VFS_DATA->lock);278 vfs_file_delref(file);279 fibril_mutex_unlock(&VFS_DATA->lock);280 232 } 281 233
Note:
See TracChangeset
for help on using the changeset viewer.