Changeset 5126f80 in mainline for uspace/srv/vfs/vfs_ops.c
- Timestamp:
- 2017-03-08T11:42:17Z (8 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0d35511
- Parents:
- a737667e
- git-author:
- Jiri Zarevucky <zarevucky.jiri@…> (2017-03-08 11:42:17)
- git-committer:
- Jakub Jermar <jakub@…> (2017-03-08 11:42:17)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/vfs/vfs_ops.c
ra737667e r5126f80 68 68 FIBRIL_RWLOCK_INITIALIZE(namespace_rwlock); 69 69 70 vfs_node_t *root = NULL;71 72 70 static int vfs_connect_internal(service_id_t service_id, unsigned flags, unsigned instance, 73 71 char *options, char *fsname, vfs_node_t **root) 74 72 { 75 73 fs_handle_t fs_handle = 0; … … 79 77 fs_handle = fs_name_to_handle(instance, fsname, false); 80 78 81 if (fs_handle != 0 || !(flags & IPC_FLAG_BLOCKING)) {79 if (fs_handle != 0 || !(flags & VFS_MOUNT_BLOCKING)) { 82 80 break; 83 81 } … … 123 121 } 124 122 125 static int vfs_mount_internal(service_id_t service_id, unsigned flags, unsigned instance,126 char *opts, char *fs_name, char *mp)127 {128 /* Resolve the path to the mountpoint. */129 130 if (root == NULL) {131 /* We still don't have the root file system mounted. */132 if (str_cmp(mp, "/") != 0) {133 /*134 * We can't resolve this without the root filesystem135 * being mounted first.136 */137 return ENOENT;138 }139 140 return vfs_connect_internal(service_id, flags, instance, opts, fs_name, &root);141 }142 143 /* We already have the root FS. */144 if (str_cmp(mp, "/") == 0) {145 /* Trying to mount root FS over root FS */146 return EBUSY;147 }148 149 vfs_lookup_res_t mp_res;150 int rc = vfs_lookup_internal(root, mp, L_DIRECTORY, &mp_res);151 if (rc != EOK) {152 /* The lookup failed. */153 return rc;154 }155 156 vfs_node_t *mp_node;157 mp_node = vfs_node_get(&mp_res);158 if (!mp_node) {159 return ENOMEM;160 }161 162 if (mp_node->mount != NULL) {163 return EBUSY;164 }165 166 if (mp_node->type != VFS_NODE_DIRECTORY) {167 printf("%s node not a directory, type=%d\n", mp, mp_node->type);168 return ENOTDIR;169 }170 171 if (vfs_node_has_children(mp_node)) {172 return ENOTEMPTY;173 }174 175 vfs_node_t *mountee;176 177 rc = vfs_connect_internal(service_id, flags, instance, opts, fs_name, &mountee);178 if (rc != EOK) {179 vfs_node_put(mp_node);180 return ENOMEM;181 }182 183 mp_node->mount = mountee;184 /* The two references to nodes are held by the mount so that they cannot be freed.185 * They are removed in detach_internal().186 */187 return EOK;188 }189 190 123 void vfs_mount_srv(ipc_callid_t rid, ipc_call_t *request) 191 124 { 125 int mpfd = IPC_GET_ARG1(*request); 126 192 127 /* 193 128 * We expect the library to do the device-name to device-handle … … 195 130 * in the request. 196 131 */ 197 service_id_t service_id = (service_id_t) IPC_GET_ARG 1(*request);132 service_id_t service_id = (service_id_t) IPC_GET_ARG2(*request); 198 133 199 134 /* 200 135 * Mount flags are passed as ARG2. 201 136 */ 202 unsigned int flags = (unsigned int) IPC_GET_ARG 2(*request);137 unsigned int flags = (unsigned int) IPC_GET_ARG3(*request); 203 138 204 139 /* 205 140 * Instance number is passed as ARG3. 206 141 */ 207 unsigned int instance = IPC_GET_ARG3(*request); 208 209 /* We want the client to send us the mount point. */ 210 char *mp; 211 int rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN, 142 unsigned int instance = IPC_GET_ARG4(*request); 143 144 char *opts = NULL; 145 char *fs_name = NULL; 146 vfs_file_t *mp = NULL; 147 vfs_file_t *file = NULL; 148 int fd = -1; 149 mtab_ent_t *mtab_ent = NULL; 150 151 /* Now we expect to receive the mount options. */ 152 int rc = async_data_write_accept((void **) &opts, true, 0, MAX_MNTOPTS_LEN, 212 153 0, NULL); 213 154 if (rc != EOK) { 214 async_answer_0(rid, rc); 215 return; 216 } 217 218 /* Now we expect to receive the mount options. */ 219 char *opts; 220 rc = async_data_write_accept((void **) &opts, true, 0, MAX_MNTOPTS_LEN, 221 0, NULL); 222 if (rc != EOK) { 223 async_answer_0(rid, rc); 224 free(mp); 225 return; 155 async_data_write_void(rc); 156 goto out; 226 157 } 227 158 … … 230 161 * system. 231 162 */ 232 char *fs_name;233 163 rc = async_data_write_accept((void **) &fs_name, true, 0, 234 164 FS_NAME_MAXLEN, 0, NULL); 235 165 if (rc != EOK) { 236 async_answer_0(rid, rc); 237 free(mp); 238 free(opts); 239 return; 166 goto out; 167 } 168 169 if (!(flags & VFS_MOUNT_CONNECT_ONLY)) { 170 mp = vfs_file_get(mpfd); 171 if (mp == NULL) { 172 rc = EBADF; 173 goto out; 174 } 175 176 if (mp->node->mount != NULL) { 177 rc = EBUSY; 178 goto out; 179 } 180 181 if (mp->node->type != VFS_NODE_DIRECTORY) { 182 rc = ENOTDIR; 183 goto out; 184 } 185 186 if (vfs_node_has_children(mp->node)) { 187 rc = ENOTEMPTY; 188 goto out; 189 } 190 } 191 192 if (!(flags & VFS_MOUNT_NO_REF)) { 193 fd = vfs_fd_alloc(&file, false); 194 if (fd < 0) { 195 rc = fd; 196 goto out; 197 } 240 198 } 241 199 242 200 /* Add the filesystem info to the list of mounted filesystems */ 243 mtab_ent _t *mtab_ent= malloc(sizeof(mtab_ent_t));201 mtab_ent = malloc(sizeof(mtab_ent_t)); 244 202 if (!mtab_ent) { 245 async_answer_0(rid, ENOMEM); 246 free(mp); 247 free(fs_name); 248 free(opts); 249 return; 250 } 251 252 /* Mount the filesystem. */ 203 rc = ENOMEM; 204 goto out; 205 } 206 207 vfs_node_t *root = NULL; 208 253 209 fibril_rwlock_write_lock(&namespace_rwlock); 254 rc = vfs_mount_internal(service_id, flags, instance, opts, fs_name, mp); 210 211 rc = vfs_connect_internal(service_id, flags, instance, opts, fs_name, &root); 212 if (rc == EOK && !(flags & VFS_MOUNT_CONNECT_ONLY)) { 213 vfs_node_addref(mp->node); 214 vfs_node_addref(root); 215 mp->node->mount = root; 216 } 217 255 218 fibril_rwlock_write_unlock(&namespace_rwlock); 256 219 220 if (rc != EOK) { 221 goto out; 222 } 223 224 225 if (flags & VFS_MOUNT_NO_REF) { 226 vfs_node_delref(root); 227 } else { 228 assert(file != NULL); 229 230 file->node = root; 231 file->permissions = MODE_READ | MODE_WRITE | MODE_APPEND; 232 file->open_read = false; 233 file->open_write = false; 234 } 235 257 236 /* Add the filesystem info to the list of mounted filesystems */ 258 237 if (rc == EOK) { 259 str_cpy(mtab_ent->mp, MAX_PATH_LEN, mp);238 str_cpy(mtab_ent->mp, MAX_PATH_LEN, "fixme"); 260 239 str_cpy(mtab_ent->fs_name, FS_NAME_MAXLEN, fs_name); 261 240 str_cpy(mtab_ent->opts, MAX_MNTOPTS_LEN, opts); … … 269 248 mtab_size++; 270 249 fibril_mutex_unlock(&mtab_list_lock); 271 } 272 273 async_answer_0(rid, rc); 274 275 free(mp); 276 free(fs_name); 277 free(opts); 250 } 251 252 rc = EOK; 253 254 out: 255 async_answer_1(rid, rc, rc == EOK ? fd : 0); 256 257 if (opts) { 258 free(opts); 259 } 260 if (fs_name) { 261 free(fs_name); 262 } 263 if (mp) { 264 vfs_file_put(mp); 265 } 266 if (file) { 267 vfs_file_put(file); 268 } 269 if (rc != EOK && fd >= 0) { 270 vfs_fd_free(fd); 271 } 278 272 } 279 273 280 274 void vfs_unmount_srv(ipc_callid_t rid, ipc_call_t *request) 281 275 { 282 /* 283 * Receive the mount point path. 284 */ 285 char *mp; 286 int rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN, 287 0, NULL); 288 if (rc != EOK) 289 async_answer_0(rid, rc); 290 291 /* 292 * Taking the namespace lock will do two things for us. First, it will 293 * prevent races with other lookup operations. Second, it will stop new 294 * references to already existing VFS nodes and creation of new VFS 295 * nodes. This is because new references are added as a result of some 296 * lookup operation or at least of some operation which is protected by 297 * the namespace lock. 298 */ 276 int mpfd = IPC_GET_ARG1(*request); 277 278 vfs_file_t *mp = vfs_file_get(mpfd); 279 if (mp == NULL) { 280 async_answer_0(rid, EBADF); 281 return; 282 } 283 284 if (mp->node->mount == NULL) { 285 async_answer_0(rid, ENOENT); 286 vfs_file_put(mp); 287 return; 288 } 289 299 290 fibril_rwlock_write_lock(&namespace_rwlock); 300 301 if (str_cmp(mp, "/") == 0) {302 free(mp);303 304 /*305 * Unmounting the root file system.306 *307 * In this case, there is no mount point node and we send308 * VFS_OUT_UNMOUNTED directly to the mounted file system.309 */310 311 if (!root) {312 fibril_rwlock_write_unlock(&namespace_rwlock);313 async_answer_0(rid, ENOENT);314 return;315 }316 317 /*318 * Count the total number of references for the mounted file system. We319 * are expecting at least one, which we got when the file system was mounted.320 * If we find more, it means that321 * the file system cannot be gracefully unmounted at the moment because322 * someone is working with it.323 */324 if (vfs_nodes_refcount_sum_get(root->fs_handle, root->service_id) != 1) {325 fibril_rwlock_write_unlock(&namespace_rwlock);326 async_answer_0(rid, EBUSY);327 return;328 }329 330 async_exch_t *exch = vfs_exchange_grab(root->fs_handle);331 rc = async_req_1_0(exch, VFS_OUT_UNMOUNTED, root->service_id);332 vfs_exchange_release(exch);333 334 fibril_rwlock_write_unlock(&namespace_rwlock);335 if (rc == EOK) {336 vfs_node_forget(root);337 root = NULL;338 }339 async_answer_0(rid, rc);340 return;341 }342 343 /*344 * Lookup the mounted root and instantiate it.345 */346 vfs_lookup_res_t mp_res;347 rc = vfs_lookup_internal(root, mp, L_MP, &mp_res);348 if (rc != EOK) {349 fibril_rwlock_write_unlock(&namespace_rwlock);350 free(mp);351 async_answer_0(rid, rc);352 return;353 }354 vfs_node_t *mp_node = vfs_node_get(&mp_res);355 if (!mp_node) {356 fibril_rwlock_write_unlock(&namespace_rwlock);357 free(mp);358 async_answer_0(rid, ENOMEM);359 return;360 }361 362 if (mp_node->mount == NULL) {363 fibril_rwlock_write_unlock(&namespace_rwlock);364 vfs_node_put(mp_node);365 free(mp);366 async_answer_0(rid, ENOENT);367 return;368 }369 291 370 292 /* 371 293 * Count the total number of references for the mounted file system. We 372 * are expecting at least one, which we got when the file system was mounted.294 * are expecting at least one, which is held by the mount point. 373 295 * If we find more, it means that 374 296 * the file system cannot be gracefully unmounted at the moment because 375 297 * someone is working with it. 376 298 */ 377 if (vfs_nodes_refcount_sum_get(mp_node->mount->fs_handle, mp_node->mount->service_id) != 1) { 299 if (vfs_nodes_refcount_sum_get(mp->node->mount->fs_handle, mp->node->mount->service_id) != 1) { 300 async_answer_0(rid, EBUSY); 301 vfs_file_put(mp); 378 302 fibril_rwlock_write_unlock(&namespace_rwlock); 379 vfs_node_put(mp_node); 380 free(mp); 381 async_answer_0(rid, EBUSY); 382 return; 383 } 384 385 /* Unmount the filesystem. */ 386 async_exch_t *exch = vfs_exchange_grab(mp_node->mount->fs_handle); 387 rc = async_req_1_0(exch, VFS_OUT_UNMOUNTED, mp_node->mount->service_id); 303 return; 304 } 305 306 async_exch_t *exch = vfs_exchange_grab(mp->node->mount->fs_handle); 307 int rc = async_req_1_0(exch, VFS_OUT_UNMOUNTED, mp->node->mount->service_id); 388 308 vfs_exchange_release(exch); 389 309 390 vfs_node_forget(mp_node->mount); 391 mp_node->mount = NULL; 392 393 vfs_node_put(mp_node); 310 if (rc != EOK) { 311 async_answer_0(rid, rc); 312 vfs_file_put(mp); 313 fibril_rwlock_write_unlock(&namespace_rwlock); 314 return; 315 } 316 317 vfs_node_forget(mp->node->mount); 318 vfs_node_put(mp->node); 319 mp->node->mount = NULL; 320 394 321 fibril_rwlock_write_unlock(&namespace_rwlock); 395 322 … … 398 325 399 326 list_foreach(mtab_list, link, mtab_ent_t, mtab_ent) { 400 if (str_cmp(mtab_ent->mp, mp) == 0) { 327 // FIXME: mp name 328 if (str_cmp(mtab_ent->mp, "fixme") == 0) { 401 329 list_remove(&mtab_ent->link); 402 330 mtab_size--; … … 408 336 assert(found); 409 337 fibril_mutex_unlock(&mtab_list_lock); 410 411 free(mp); 412 338 339 vfs_file_put(mp); 413 340 async_answer_0(rid, EOK); 414 return;415 341 } 416 342 … … 448 374 if (flags&WALK_DIRECTORY) { 449 375 lflags |= L_DIRECTORY; 376 } 377 if (flags&WALK_MOUNT_POINT) { 378 lflags |= L_MP; 450 379 } 451 380 return lflags; … … 470 399 471 400 /* Lookup the file structure corresponding to the file descriptor. */ 472 vfs_file_t *parent = NULL; 473 vfs_node_t *parent_node = root; 474 // TODO: Client-side root. 475 if (parentfd != -1) { 476 parent = vfs_file_get(parentfd); 477 if (!parent) { 478 free(path); 479 async_answer_0(rid, EBADF); 480 return; 481 } 482 parent_node = parent->node; 401 vfs_file_t *parent = vfs_file_get(parentfd); 402 if (!parent) { 403 free(path); 404 async_answer_0(rid, EBADF); 405 return; 483 406 } 484 407 … … 486 409 487 410 vfs_lookup_res_t lr; 488 rc = vfs_lookup_internal(parent _node, path, walk_lookup_flags(flags), &lr);411 rc = vfs_lookup_internal(parent->node, path, walk_lookup_flags(flags), &lr); 489 412 free(path); 490 413 … … 963 886 vfs_file_t *parent = NULL; 964 887 vfs_file_t *expect = NULL; 965 vfs_node_t *parent_node = root;966 888 967 889 int parentfd = IPC_GET_ARG1(*request); … … 974 896 return; 975 897 } 898 if (parentfd == expectfd) { 899 async_answer_0(rid, EINVAL); 900 return; 901 } 976 902 977 903 fibril_rwlock_write_lock(&namespace_rwlock); … … 980 906 981 907 /* Files are retrieved in order of file descriptors, to prevent deadlock. */ 982 if (parentfd >= 0 && parentfd< expectfd) {908 if (parentfd < expectfd) { 983 909 parent = vfs_file_get(parentfd); 984 910 if (!parent) { 985 rc = E NOENT;911 rc = EBADF; 986 912 goto exit; 987 913 } … … 996 922 } 997 923 998 if (parentfd > = 0 && parentfd >=expectfd) {924 if (parentfd > expectfd) { 999 925 parent = vfs_file_get(parentfd); 1000 926 if (!parent) { 1001 rc = E NOENT;927 rc = EBADF; 1002 928 goto exit; 1003 929 } 1004 930 } 1005 931 1006 if (parent) { 1007 parent_node = parent->node; 1008 } 932 assert(parent != NULL); 1009 933 1010 934 if (expectfd >= 0) { 1011 935 vfs_lookup_res_t lr; 1012 rc = vfs_lookup_internal(parent _node, path, lflag, &lr);936 rc = vfs_lookup_internal(parent->node, path, lflag, &lr); 1013 937 if (rc != EOK) { 1014 938 goto exit; … … 1026 950 1027 951 vfs_lookup_res_t lr; 1028 rc = vfs_lookup_internal(parent _node, path, lflag | L_UNLINK, &lr);952 rc = vfs_lookup_internal(parent->node, path, lflag | L_UNLINK, &lr); 1029 953 if (rc != EOK) { 1030 954 goto exit; … … 1188 1112 1189 1113 /* Lookup the file structure corresponding to the file descriptor. */ 1190 vfs_node_t *base_node = root; 1191 // TODO: Client-side root. 1192 if (basefd != -1) { 1193 base = vfs_file_get(basefd); 1194 if (!base) { 1195 rc = EBADF; 1196 goto out; 1197 } 1198 base_node = base->node; 1199 } 1200 1201 rc = vfs_rename_internal(base_node, oldc, newc); 1114 base = vfs_file_get(basefd); 1115 if (!base) { 1116 rc = EBADF; 1117 goto out; 1118 } 1119 1120 rc = vfs_rename_internal(base->node, oldc, newc); 1202 1121 1203 1122 out: … … 1358 1277 /* Lookup the file structure corresponding to fd. */ 1359 1278 vfs_file_t *oldfile = vfs_file_get(oldfd); 1360 if ( !oldfile) {1279 if (oldfile == NULL) { 1361 1280 async_answer_0(rid, EBADF); 1362 1281 return; … … 1365 1284 vfs_file_t *newfile; 1366 1285 int newfd = vfs_fd_alloc(&newfile, desc); 1286 async_answer_0(rid, newfd); 1287 1367 1288 if (newfd < 0) { 1368 async_answer_0(rid, newfd);1369 1289 vfs_file_put(oldfile); 1370 1290 return; … … 1379 1299 vfs_file_put(oldfile); 1380 1300 vfs_file_put(newfile); 1381 1382 async_answer_0(rid, newfd);1383 1301 } 1384 1302
Note:
See TracChangeset
for help on using the changeset viewer.