Changeset 5bcd5b7 in mainline
- Timestamp:
- 2013-07-29T14:36:57Z (11 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 4636a60
- Parents:
- 677745a
- Location:
- uspace
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/include/ipc/vfs.h
r677745a r5bcd5b7 95 95 VFS_OUT_UNMOUNTED, 96 96 VFS_OUT_GET_SIZE, 97 VFS_OUT_IS_EMPTY, 97 98 VFS_OUT_SYNC, 98 99 VFS_OUT_STAT, -
uspace/lib/fs/libfs.c
r677745a r5bcd5b7 259 259 } 260 260 261 static void vfs_out_is_empty(ipc_callid_t rid, ipc_call_t *req) 262 { 263 service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req); 264 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req); 265 int rc; 266 267 fs_node_t *node = NULL; 268 rc = libfs_ops->node_get(&node, service_id, index); 269 if (rc != EOK) { 270 async_answer_0(rid, rc); 271 } 272 if (node == NULL) { 273 async_answer_0(rid, EINVAL); 274 } 275 276 bool children = false; 277 rc = libfs_ops->has_children(&children, node); 278 libfs_ops->node_put(node); 279 280 if (rc != EOK) { 281 async_answer_0(rid, rc); 282 } 283 async_answer_0(rid, children ? ENOTEMPTY : EOK); 284 } 285 261 286 static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 262 287 { … … 322 347 case VFS_OUT_GET_SIZE: 323 348 vfs_out_get_size(callid, &call); 349 break; 350 case VFS_OUT_IS_EMPTY: 351 vfs_out_is_empty(callid, &call); 324 352 break; 325 353 default: -
uspace/srv/vfs/vfs.h
r677745a r5bcd5b7 100 100 * which may be associated with it. 101 101 */ 102 typedef struct {102 typedef struct _vfs_node { 103 103 VFS_TRIPLET; /**< Identity of the node. */ 104 104 … … 119 119 */ 120 120 fibril_rwlock_t contents_rwlock; 121 122 struct _vfs_node *mount; 121 123 } vfs_node_t; 122 124 … … 176 178 extern vfs_info_t *fs_handle_to_info(fs_handle_t); 177 179 178 extern int vfs_lookup_internal(vfs_ triplet_t *, char *, int, vfs_lookup_res_t *);179 extern int vfs_link_internal(vfs_ triplet_t *, char *, vfs_triplet_t *);180 extern int vfs_lookup_internal(vfs_node_t *, char *, int, vfs_lookup_res_t *); 181 extern int vfs_link_internal(vfs_node_t *, char *, vfs_triplet_t *); 180 182 181 183 extern bool vfs_nodes_init(void); 182 184 extern vfs_node_t *vfs_node_get(vfs_lookup_res_t *); 185 extern vfs_node_t *vfs_node_peek(vfs_lookup_res_t *result); 183 186 extern void vfs_node_put(vfs_node_t *); 184 187 extern void vfs_node_forget(vfs_node_t *); 185 188 extern unsigned vfs_nodes_refcount_sum_get(fs_handle_t, service_id_t); 186 189 187 int64_t vfs_node_get_size(vfs_node_t *node); 190 extern int64_t vfs_node_get_size(vfs_node_t *node); 191 extern bool vfs_node_has_children(vfs_node_t *node); 188 192 189 193 #define MAX_OPEN_FILES 128 -
uspace/srv/vfs/vfs_lookup.c
r677745a r5bcd5b7 153 153 } 154 154 155 int vfs_link_internal(vfs_ triplet_t *base, char *path, vfs_triplet_t *child)155 int vfs_link_internal(vfs_node_t *base, char *path, vfs_triplet_t *child) 156 156 { 157 157 assert(base != NULL); … … 173 173 path = npath; 174 174 175 vfs_triplet_t *triplet; 176 175 177 char *slash = _strrchr(path, '/'); 176 178 if (slash && slash != path) { … … 187 189 goto out; 188 190 } 189 base= &res.triplet;191 triplet = &res.triplet; 190 192 191 193 *slash = '/'; 192 194 } else { 195 if (base->mount != NULL) { 196 rc = EINVAL; 197 goto out; 198 } 199 193 200 memcpy(component, path + 1, str_size(path)); 194 } 195 196 if (base->fs_handle != child->fs_handle || base->service_id != child->service_id) { 201 triplet = (vfs_triplet_t *) base; 202 } 203 204 if (triplet->fs_handle != child->fs_handle || triplet->service_id != child->service_id) { 197 205 rc = EXDEV; 198 206 goto out; 199 207 } 200 208 201 async_exch_t *exch = vfs_exchange_grab( base->fs_handle);202 aid_t req = async_send_3(exch, VFS_OUT_LINK, base->service_id, base->index, child->index, NULL);209 async_exch_t *exch = vfs_exchange_grab(triplet->fs_handle); 210 aid_t req = async_send_3(exch, VFS_OUT_LINK, triplet->service_id, triplet->index, child->index, NULL); 203 211 204 212 rc = async_data_write_start(exch, component, str_size(component) + 1); … … 215 223 } 216 224 225 static int out_lookup(vfs_triplet_t *base, unsigned *pfirst, unsigned *plen, 226 int lflag, vfs_lookup_res_t *result) 227 { 228 assert(base); 229 assert(result); 230 231 sysarg_t rc; 232 ipc_call_t answer; 233 async_exch_t *exch = vfs_exchange_grab(base->fs_handle); 234 aid_t req = async_send_5(exch, VFS_OUT_LOOKUP, (sysarg_t) *pfirst, (sysarg_t) *plen, 235 (sysarg_t) base->service_id, (sysarg_t) base->index, (sysarg_t) lflag, &answer); 236 async_wait_for(req, &rc); 237 vfs_exchange_release(exch); 238 239 if ((int) rc < 0) { 240 return (int) rc; 241 } 242 243 unsigned last = *pfirst + *plen; 244 *pfirst = IPC_GET_ARG3(answer); 245 *plen = last - *pfirst; 246 247 result->triplet.fs_handle = (fs_handle_t) rc; 248 result->triplet.service_id = (service_id_t) IPC_GET_ARG1(answer); 249 result->triplet.index = (fs_index_t) IPC_GET_ARG2(answer); 250 result->size = (int64_t)(int32_t) IPC_GET_ARG4(answer); 251 result->type = IPC_GET_ARG5(answer); 252 return EOK; 253 } 254 217 255 /** Perform a path lookup. 218 256 * … … 227 265 * 228 266 */ 229 int vfs_lookup_internal(vfs_ triplet_t *base, char *path, int lflag, vfs_lookup_res_t *result)267 int vfs_lookup_internal(vfs_node_t *base, char *path, int lflag, vfs_lookup_res_t *result) 230 268 { 231 269 assert(base != NULL); 232 270 assert(path != NULL); 233 271 234 sysarg_t rc;235 236 if (!base->fs_handle) {237 rc = ENOENT;238 goto out;239 }240 241 272 size_t len; 273 int rc; 242 274 char *npath = canonify(path, &len); 243 275 if (!npath) { 276 DPRINTF("vfs_lookup_internal() can't canonify path: %s\n", path); 244 277 rc = EINVAL; 245 goto out;278 return rc; 246 279 } 247 280 path = npath; … … 254 287 rc = plb_insert_entry(&entry, path, &first, len); 255 288 if (rc != EOK) { 256 goto out; 257 } 258 259 ipc_call_t answer; 260 async_exch_t *exch = vfs_exchange_grab(base->fs_handle); 261 aid_t req = async_send_5(exch, VFS_OUT_LOOKUP, (sysarg_t) first, (sysarg_t) len, 262 (sysarg_t) base->service_id, (sysarg_t) base->index, (sysarg_t) lflag, &answer); 263 async_wait_for(req, &rc); 264 vfs_exchange_release(exch); 265 289 DPRINTF("vfs_lookup_internal() can't insert entry into PLB: %d\n", rc); 290 return rc; 291 } 292 293 size_t next = first; 294 size_t nlen = len; 295 296 vfs_lookup_res_t res; 297 298 /* Resolve path as long as there are mount points to cross. */ 299 while (nlen > 0) { 300 while (base->mount != NULL) { 301 if (lflag & L_DISABLE_MOUNTS) { 302 rc = EXDEV; 303 goto out; 304 } 305 306 base = base->mount; 307 } 308 309 rc = out_lookup((vfs_triplet_t *) base, &next, &nlen, lflag, &res); 310 if (rc != EOK) { 311 goto out; 312 } 313 314 if (nlen > 0) { 315 base = vfs_node_peek(&res); 316 if (base == NULL || base->mount == NULL) { 317 rc = ENOENT; 318 goto out; 319 } 320 if (lflag & L_DISABLE_MOUNTS) { 321 rc = EXDEV; 322 goto out; 323 } 324 } 325 } 326 327 assert(nlen == 0); 328 rc = EOK; 329 330 if (result != NULL) { 331 /* The found file may be a mount point. Try to cross it. */ 332 if (!(lflag & L_MP)) { 333 base = vfs_node_peek(&res); 334 if (base != NULL && base->mount != NULL) { 335 while (base->mount != NULL) { 336 base = base->mount; 337 } 338 339 result->triplet = *(vfs_triplet_t *)base; 340 result->type = base->type; 341 result->size = base->size; 342 goto out; 343 } 344 } 345 346 __builtin_memcpy(result, &res, sizeof(vfs_lookup_res_t)); 347 } 348 349 out: 266 350 plb_clear_entry(&entry, first, len); 267 268 if ((int) rc < 0) {269 goto out;270 }271 272 unsigned last = IPC_GET_ARG3(answer);273 if (last != first + len) {274 /* The path wasn't processed entirely. */275 rc = ENOENT;276 goto out;277 }278 279 if (!result) {280 rc = EOK;281 goto out;282 }283 284 result->triplet.fs_handle = (fs_handle_t) rc;285 result->triplet.service_id = (service_id_t) IPC_GET_ARG1(answer);286 result->triplet.index = (fs_index_t) IPC_GET_ARG2(answer);287 result->size = (int64_t)(int32_t) IPC_GET_ARG4(answer);288 result->type = IPC_GET_ARG5(answer);289 rc = EOK;290 291 out:292 351 DPRINTF("vfs_lookup_internal() with path '%s' returns %d\n", path, rc); 293 352 return rc; -
uspace/srv/vfs/vfs_node.c
r677745a r5bcd5b7 196 196 } 197 197 198 vfs_node_t *vfs_node_peek(vfs_lookup_res_t *result) 199 { 200 vfs_node_t *node = NULL; 201 202 fibril_mutex_lock(&nodes_mutex); 203 ht_link_t *tmp = hash_table_find(&nodes, &result->triplet); 204 if (tmp) { 205 node = hash_table_get_inst(tmp, vfs_node_t, nh_link); 206 } 207 fibril_mutex_unlock(&nodes_mutex); 208 209 return node; 210 } 211 198 212 /** Return VFS node when no longer needed by the caller. 199 213 * … … 317 331 } 318 332 333 bool vfs_node_has_children(vfs_node_t *node) 334 { 335 async_exch_t *exch = vfs_exchange_grab(node->fs_handle); 336 int rc = async_req_2_0(exch, VFS_OUT_IS_EMPTY, node->service_id, node->index); 337 vfs_exchange_release(exch); 338 return rc == ENOTEMPTY; 339 } 340 319 341 /** 320 342 * @} -
uspace/srv/vfs/vfs_ops.c
r677745a r5bcd5b7 70 70 vfs_node_t *root = NULL; 71 71 72 #if 0 73 static int vfs_attach_internal(vfs_node_t *mpoint, vfs_node_t *mountee) 74 { 75 assert(mpoint != NULL); 76 assert(mountee != NULL); 77 78 if (mpoint->mount != NULL) { 79 return EBUSY; 80 } 81 82 if (mpoint->type != VFS_NODE_DIRECTORY) { 83 return ENOTDIR; 84 } 85 86 if (vfs_node_has_children(mpoint)) { 87 return ENOTEMPTY; 88 } 89 90 mpoint->mount = mountee; 91 vfs_node_addref(mountee); 92 /* Add reference to make sure the node is not freed. Removed in detach_internal(). */ 93 vfs_node_addref(mpoint); 94 return EOK; 95 } 96 97 static int vfs_detach_internal(vfs_node_t *mpoint) 98 { 99 assert(mpoint != NULL); 100 101 if (mpoint->mount == NULL) { 102 return ENOENT; 103 } 104 vfs_node_put(mpoint->mount); 105 mpoint->mount = NULL; 106 vfs_node_put(mpoint); 107 } 108 #endif 109 72 110 static int vfs_mount_internal(ipc_callid_t rid, service_id_t service_id, 73 111 fs_handle_t fs_handle, char *mp, char *opts) … … 153 191 } 154 192 155 rc = vfs_lookup_internal( (vfs_triplet_t *)root, mp, L_DIRECTORY, &mp_res);193 rc = vfs_lookup_internal(root, mp, L_DIRECTORY, &mp_res); 156 194 if (rc != EOK) { 157 195 /* The lookup failed. */ … … 424 462 * Lookup the mounted root and instantiate it. 425 463 */ 426 rc = vfs_lookup_internal( (vfs_triplet_t *)root, mp, 0, &mr_res);464 rc = vfs_lookup_internal(root, mp, 0, &mr_res); 427 465 if (rc != EOK) { 428 466 fibril_rwlock_write_unlock(&namespace_rwlock); … … 487 525 */ 488 526 489 rc = vfs_lookup_internal( (vfs_triplet_t *)root, mp, L_MP, &mp_res);527 rc = vfs_lookup_internal(root, mp, L_MP, &mp_res); 490 528 if (rc != EOK) { 491 529 fibril_rwlock_write_unlock(&namespace_rwlock); … … 627 665 628 666 vfs_lookup_res_t lr; 629 rc = vfs_lookup_internal( (vfs_triplet_t *)parent_node, path, walk_lookup_flags(flags), &lr);667 rc = vfs_lookup_internal(parent_node, path, walk_lookup_flags(flags), &lr); 630 668 free(path); 631 669 … … 1050 1088 } 1051 1089 1090 static void out_destroy(vfs_triplet_t *file) 1091 { 1092 async_exch_t *exch = vfs_exchange_grab(file->fs_handle); 1093 async_msg_2(exch, VFS_OUT_DESTROY, 1094 (sysarg_t) file->service_id, (sysarg_t) file->index); 1095 vfs_exchange_release(exch); 1096 } 1097 1052 1098 void vfs_unlink2(ipc_callid_t rid, ipc_call_t *request) 1053 1099 { … … 1089 1135 1090 1136 vfs_lookup_res_t lr; 1091 rc = vfs_lookup_internal( (vfs_triplet_t *)parent_node, path, lflag, &lr);1137 rc = vfs_lookup_internal(parent_node, path, lflag, &lr); 1092 1138 if (rc != EOK) { 1093 1139 goto exit; … … 1104 1150 1105 1151 vfs_lookup_res_t lr; 1106 rc = vfs_lookup_internal( (vfs_triplet_t *)parent_node, path, lflag | L_UNLINK, &lr);1152 rc = vfs_lookup_internal(parent_node, path, lflag | L_UNLINK, &lr); 1107 1153 if (rc != EOK) { 1108 1154 goto exit; 1109 1155 } 1110 1156 1111 /* 1112 * The name has already been unlinked by vfs_lookup_internal(). 1113 * We have to get and put the VFS node to ensure that it is 1114 * VFS_OUT_DESTROY'ed after the last reference to it is dropped. 1115 */ 1116 vfs_node_put(vfs_node_get(&lr)); 1157 /* If the node is not held by anyone, try to destroy it. */ 1158 if (vfs_node_peek(&lr) == NULL) { 1159 out_destroy(&lr.triplet); 1160 } 1117 1161 1118 1162 exit: … … 1149 1193 } 1150 1194 1151 static int vfs_rename_internal(vfs_ triplet_t *base, char *old, char *new)1195 static int vfs_rename_internal(vfs_node_t *base, char *old, char *new) 1152 1196 { 1153 1197 assert(base != NULL); … … 1182 1226 } 1183 1227 1184 base = &base_lr.triplet;1228 base = vfs_node_get(&base_lr); 1185 1229 old[shared] = '/'; 1186 1230 old += shared; 1187 1231 new += shared; 1232 } else { 1233 vfs_node_addref(base); 1188 1234 } 1189 1235 … … 1193 1239 orig_unlinked = true; 1194 1240 } else if (rc != ENOENT) { 1241 vfs_node_put(base); 1195 1242 fibril_rwlock_write_unlock(&namespace_rwlock); 1196 1243 return rc; … … 1202 1249 vfs_link_internal(base, new, &new_lr_orig.triplet); 1203 1250 } 1251 vfs_node_put(base); 1204 1252 fibril_rwlock_write_unlock(&namespace_rwlock); 1205 1253 return rc; … … 1212 1260 vfs_link_internal(base, new, &new_lr_orig.triplet); 1213 1261 } 1262 vfs_node_put(base); 1214 1263 fibril_rwlock_write_unlock(&namespace_rwlock); 1215 1264 return rc; 1216 1265 } 1217 1266 1218 if (orig_unlinked) { 1219 vfs_node_put(vfs_node_get(&new_lr_orig)); 1220 } 1221 1267 /* If the node is not held by anyone, try to destroy it. */ 1268 if (orig_unlinked && vfs_node_peek(&new_lr_orig) == NULL) { 1269 out_destroy(&new_lr_orig.triplet); 1270 } 1271 1272 vfs_node_put(base); 1222 1273 fibril_rwlock_write_unlock(&namespace_rwlock); 1223 1274 return EOK; … … 1272 1323 } 1273 1324 1274 rc = vfs_rename_internal( (vfs_triplet_t *)base_node, oldc, newc);1325 rc = vfs_rename_internal(base_node, oldc, newc); 1275 1326 1276 1327 out:
Note:
See TracChangeset
for help on using the changeset viewer.