| 1 | /* |
|---|
| 2 | * (C) 2001 Clemson University and The University of Chicago |
|---|
| 3 | * |
|---|
| 4 | * See COPYING in top-level directory. |
|---|
| 5 | */ |
|---|
| 6 | |
|---|
| 7 | /* pvfs2-tio |
|---|
| 8 | * Threaded I/O benchmark to exercise the aio code paths on server. |
|---|
| 9 | */ |
|---|
| 10 | #include <stdio.h> |
|---|
| 11 | #include <stdlib.h> |
|---|
| 12 | #include <unistd.h> |
|---|
| 13 | #include <limits.h> |
|---|
| 14 | #include <string.h> |
|---|
| 15 | #include <sys/types.h> |
|---|
| 16 | #include <sys/stat.h> |
|---|
| 17 | #include <fcntl.h> |
|---|
| 18 | #include <libgen.h> |
|---|
| 19 | #include <getopt.h> |
|---|
| 20 | #include <pthread.h> |
|---|
| 21 | #include <aio.h> |
|---|
| 22 | |
|---|
| 23 | #define __PINT_REQPROTO_ENCODE_FUNCS_C |
|---|
| 24 | #include "pvfs2.h" |
|---|
| 25 | #include "str-utils.h" |
|---|
| 26 | #include "pint-sysint-utils.h" |
|---|
| 27 | #include "pint-util.h" |
|---|
| 28 | #include "pvfs2-internal.h" |
|---|
| 29 | #include "quicklist.h" |
|---|
| 30 | #include "quickhash.h" |
|---|
| 31 | |
|---|
| 32 | struct options |
|---|
| 33 | { |
|---|
| 34 | char *srcfile; |
|---|
| 35 | int num_io; |
|---|
| 36 | }; |
|---|
| 37 | |
|---|
| 38 | enum object_type { |
|---|
| 39 | UNIX_FILE, |
|---|
| 40 | PVFS2_FILE |
|---|
| 41 | }; |
|---|
| 42 | |
|---|
| 43 | typedef struct pvfs2_file_object_s { |
|---|
| 44 | PVFS_fs_id fs_id; |
|---|
| 45 | PVFS_object_ref ref; |
|---|
| 46 | char pvfs2_path[PVFS_NAME_MAX]; |
|---|
| 47 | char user_path[PVFS_NAME_MAX]; |
|---|
| 48 | PVFS_sys_attr attr; |
|---|
| 49 | PVFS_permissions perms; |
|---|
| 50 | } pvfs2_file_object; |
|---|
| 51 | |
|---|
| 52 | typedef struct unix_file_object_s { |
|---|
| 53 | int fd; |
|---|
| 54 | int mode; |
|---|
| 55 | char path[NAME_MAX]; |
|---|
| 56 | PVFS_fs_id fs_id; |
|---|
| 57 | } unix_file_object; |
|---|
| 58 | |
|---|
| 59 | typedef struct file_object_s { |
|---|
| 60 | int fs_type; |
|---|
| 61 | union { |
|---|
| 62 | unix_file_object ufs; |
|---|
| 63 | pvfs2_file_object pvfs2; |
|---|
| 64 | } u; |
|---|
| 65 | } file_object; |
|---|
| 66 | |
|---|
| 67 | |
|---|
| 68 | static struct options* parse_args(int argc, char* argv[]); |
|---|
| 69 | static void usage(int argc, char** argv); |
|---|
| 70 | static int resolve_filename(file_object *obj, char *filename); |
|---|
| 71 | static int generic_open(file_object *obj, PVFS_credentials *credentials); |
|---|
| 72 | |
|---|
| 73 | static file_object src; |
|---|
| 74 | static char buf[2097152]; |
|---|
| 75 | |
|---|
| 76 | typedef struct { |
|---|
| 77 | int index; |
|---|
| 78 | PVFS_id_gen_t tag; |
|---|
| 79 | PVFS_sys_op_id op_id; |
|---|
| 80 | PVFS_Request file_req; |
|---|
| 81 | PVFS_Request mem_req; |
|---|
| 82 | PVFS_sysresp_io resp_io; |
|---|
| 83 | file_object *src; |
|---|
| 84 | char *buffer; |
|---|
| 85 | int64_t offset; |
|---|
| 86 | int64_t count; |
|---|
| 87 | PVFS_credentials credentials; |
|---|
| 88 | struct aiocb acb; |
|---|
| 89 | struct qlist_head hash_link; |
|---|
| 90 | } io_request; |
|---|
| 91 | |
|---|
| 92 | static PVFS_error post_generic_write(io_request *req); |
|---|
| 93 | static PVFS_error post_generic_read(io_request *req); |
|---|
| 94 | #define NUM_IO 5 |
|---|
| 95 | |
|---|
| 96 | io_request vfs_request[NUM_IO]; |
|---|
| 97 | /* this hashtable is used to keep track of operations in progress */ |
|---|
| 98 | #define DEFAULT_OPS_IN_PROGRESS_HTABLE_SIZE 67 |
|---|
| 99 | static int hash_key(void *key, int table_size); |
|---|
| 100 | static int hash_key_compare(void *key, struct qlist_head *link); |
|---|
| 101 | static struct qhash_table *s_ops_in_progress_table = NULL; |
|---|
| 102 | |
|---|
| 103 | static int hash_key(void *key, int table_size) |
|---|
| 104 | { |
|---|
| 105 | PVFS_id_gen_t tag = *((PVFS_id_gen_t *)key); |
|---|
| 106 | return (tag % table_size); |
|---|
| 107 | } |
|---|
| 108 | |
|---|
| 109 | static int hash_key_compare(void *key, struct qlist_head *link) |
|---|
| 110 | { |
|---|
| 111 | io_request *vfs_request = NULL; |
|---|
| 112 | PVFS_id_gen_t tag = *((PVFS_id_gen_t *)key); |
|---|
| 113 | |
|---|
| 114 | vfs_request = qlist_entry(link, io_request, hash_link); |
|---|
| 115 | assert(vfs_request); |
|---|
| 116 | |
|---|
| 117 | return ((vfs_request->tag == tag) ? 1 : 0); |
|---|
| 118 | } |
|---|
| 119 | |
|---|
| 120 | static int initialize_ops_in_progress_table(void) |
|---|
| 121 | { |
|---|
| 122 | if (!s_ops_in_progress_table) |
|---|
| 123 | { |
|---|
| 124 | s_ops_in_progress_table = qhash_init( |
|---|
| 125 | hash_key_compare, hash_key, |
|---|
| 126 | DEFAULT_OPS_IN_PROGRESS_HTABLE_SIZE); |
|---|
| 127 | } |
|---|
| 128 | return (s_ops_in_progress_table ? 0 : -PVFS_ENOMEM); |
|---|
| 129 | } |
|---|
| 130 | |
|---|
| 131 | static void finalize_ops_in_progress_table(void) |
|---|
| 132 | { |
|---|
| 133 | int i = 0; |
|---|
| 134 | struct qlist_head *hash_link = NULL; |
|---|
| 135 | |
|---|
| 136 | if (s_ops_in_progress_table) |
|---|
| 137 | { |
|---|
| 138 | for(i = 0; i < s_ops_in_progress_table->table_size; i++) |
|---|
| 139 | { |
|---|
| 140 | do |
|---|
| 141 | { |
|---|
| 142 | hash_link = qhash_search_and_remove_at_index( |
|---|
| 143 | s_ops_in_progress_table, i); |
|---|
| 144 | |
|---|
| 145 | } while(hash_link); |
|---|
| 146 | } |
|---|
| 147 | qhash_finalize(s_ops_in_progress_table); |
|---|
| 148 | s_ops_in_progress_table = NULL; |
|---|
| 149 | } |
|---|
| 150 | } |
|---|
| 151 | |
|---|
| 152 | static PVFS_error remove_op_from_op_in_progress_table( |
|---|
| 153 | io_request *vfs_request) |
|---|
| 154 | { |
|---|
| 155 | PVFS_error ret = -PVFS_EINVAL; |
|---|
| 156 | struct qlist_head *hash_link = NULL; |
|---|
| 157 | io_request *tmp_vfs_request = NULL; |
|---|
| 158 | |
|---|
| 159 | if (vfs_request) |
|---|
| 160 | { |
|---|
| 161 | hash_link = qhash_search_and_remove( |
|---|
| 162 | s_ops_in_progress_table, (void *)(&vfs_request->tag)); |
|---|
| 163 | if (hash_link) |
|---|
| 164 | { |
|---|
| 165 | tmp_vfs_request = qhash_entry( |
|---|
| 166 | hash_link, io_request, hash_link); |
|---|
| 167 | assert(tmp_vfs_request); |
|---|
| 168 | assert(tmp_vfs_request == vfs_request); |
|---|
| 169 | ret = 0; |
|---|
| 170 | } |
|---|
| 171 | } |
|---|
| 172 | return ret; |
|---|
| 173 | } |
|---|
| 174 | |
|---|
| 175 | static PVFS_error add_op_to_op_in_progress_table( |
|---|
| 176 | io_request *vfs_request) |
|---|
| 177 | { |
|---|
| 178 | PVFS_error ret = -PVFS_EINVAL; |
|---|
| 179 | |
|---|
| 180 | if (vfs_request) |
|---|
| 181 | { |
|---|
| 182 | qhash_add(s_ops_in_progress_table, |
|---|
| 183 | (void *)(&vfs_request->tag), |
|---|
| 184 | &vfs_request->hash_link); |
|---|
| 185 | ret = 0; |
|---|
| 186 | } |
|---|
| 187 | return ret; |
|---|
| 188 | } |
|---|
| 189 | static long tag = 100; |
|---|
| 190 | |
|---|
| 191 | static void post_op(io_request *req) |
|---|
| 192 | { |
|---|
| 193 | static int off_count = 0; |
|---|
| 194 | int rd_wr = 1; |
|---|
| 195 | req->offset = (off_count++ * 2097152); |
|---|
| 196 | req->tag = tag++; |
|---|
| 197 | req->src = &src; |
|---|
| 198 | req->buffer = buf; |
|---|
| 199 | req->count = 2097152; |
|---|
| 200 | PVFS_util_gen_credentials(&req->credentials); |
|---|
| 201 | if (rd_wr == 0) |
|---|
| 202 | post_generic_read(req); |
|---|
| 203 | else |
|---|
| 204 | post_generic_write(req); |
|---|
| 205 | add_op_to_op_in_progress_table(req); |
|---|
| 206 | } |
|---|
| 207 | |
|---|
| 208 | #define MAX_OPS 64 |
|---|
| 209 | |
|---|
| 210 | static void do_pvfs_io(int num_io) |
|---|
| 211 | { |
|---|
| 212 | PVFS_error ret; |
|---|
| 213 | int i, count = num_io; |
|---|
| 214 | io_request *all_request[MAX_OPS], *req; |
|---|
| 215 | PVFS_sys_op_id op_id_array[MAX_OPS]; |
|---|
| 216 | int error_code_array[MAX_OPS], op_count = 0; |
|---|
| 217 | PVFS_size total = 0; |
|---|
| 218 | |
|---|
| 219 | printf("doing %d I/O 5 at a time\n", num_io); |
|---|
| 220 | for (i = 0; i < NUM_IO; i++) { |
|---|
| 221 | vfs_request[i].index = i; |
|---|
| 222 | } |
|---|
| 223 | |
|---|
| 224 | for (i = 0; i < NUM_IO; i++) { |
|---|
| 225 | post_op(&vfs_request[i]); |
|---|
| 226 | } |
|---|
| 227 | while (1) |
|---|
| 228 | { |
|---|
| 229 | op_count = MAX_OPS; |
|---|
| 230 | memset(error_code_array, 0, MAX_OPS * sizeof(int)); |
|---|
| 231 | memset(all_request, 0, MAX_OPS * sizeof(io_request *)); |
|---|
| 232 | ret = PVFS_sys_testsome( |
|---|
| 233 | op_id_array, &op_count, (void *) all_request, |
|---|
| 234 | error_code_array, 10); |
|---|
| 235 | for (i = 0; i < op_count; i++) |
|---|
| 236 | { |
|---|
| 237 | req = all_request[i]; |
|---|
| 238 | if (req->op_id != op_id_array[i]) |
|---|
| 239 | continue; |
|---|
| 240 | if (req->resp_io.total_completed != 2097152) |
|---|
| 241 | { |
|---|
| 242 | fprintf(stderr, "Short I/O\n"); |
|---|
| 243 | } |
|---|
| 244 | total += req->resp_io.total_completed; |
|---|
| 245 | ret = remove_op_from_op_in_progress_table(req); |
|---|
| 246 | if (ret) |
|---|
| 247 | { |
|---|
| 248 | PVFS_perror_gossip("Failed to remove op in progress from table\n", ret); |
|---|
| 249 | } |
|---|
| 250 | count--; |
|---|
| 251 | if (count > 0) |
|---|
| 252 | post_op(req); |
|---|
| 253 | } |
|---|
| 254 | if (count <= 0) |
|---|
| 255 | break; |
|---|
| 256 | } |
|---|
| 257 | printf("Total I/O staged %Ld\n", lld(total)); |
|---|
| 258 | return; |
|---|
| 259 | } |
|---|
| 260 | |
|---|
| 261 | static void do_unix_io(int num_io) |
|---|
| 262 | { |
|---|
| 263 | int count; |
|---|
| 264 | long ret; |
|---|
| 265 | int status[NUM_IO]; |
|---|
| 266 | int flag, i; |
|---|
| 267 | |
|---|
| 268 | count = num_io; |
|---|
| 269 | ret = 0; |
|---|
| 270 | flag = -1; |
|---|
| 271 | |
|---|
| 272 | for (i = 0; i < NUM_IO; i++) { |
|---|
| 273 | vfs_request[i].index = i; |
|---|
| 274 | } |
|---|
| 275 | for (i = 0; i < NUM_IO; i++) { |
|---|
| 276 | status[i] = EINPROGRESS; |
|---|
| 277 | post_op(&vfs_request[i]); |
|---|
| 278 | } |
|---|
| 279 | while (1) |
|---|
| 280 | { |
|---|
| 281 | long ret1; |
|---|
| 282 | flag = -1; |
|---|
| 283 | for (i = 0; i < NUM_IO; i++) |
|---|
| 284 | { |
|---|
| 285 | if (status[i] == EINPROGRESS) |
|---|
| 286 | { |
|---|
| 287 | ret1 = aio_error(&vfs_request[i].acb); |
|---|
| 288 | if (ret1 != 0) |
|---|
| 289 | { |
|---|
| 290 | /* if op in progress, we have to skip it */ |
|---|
| 291 | if (ret1 == EINPROGRESS) |
|---|
| 292 | { |
|---|
| 293 | /* we have not completed */ |
|---|
| 294 | flag = 1; |
|---|
| 295 | continue; |
|---|
| 296 | } |
|---|
| 297 | else |
|---|
| 298 | { |
|---|
| 299 | printf("I/O on %d failed: %s\n", i, strerror(errno)); |
|---|
| 300 | status[i] = -1; |
|---|
| 301 | } |
|---|
| 302 | } |
|---|
| 303 | else |
|---|
| 304 | { |
|---|
| 305 | /* we have completed */ |
|---|
| 306 | ret += aio_return(&vfs_request[i].acb); |
|---|
| 307 | if (flag < 0) |
|---|
| 308 | { |
|---|
| 309 | flag = 0; |
|---|
| 310 | } |
|---|
| 311 | remove_op_from_op_in_progress_table(&vfs_request[i]); |
|---|
| 312 | count--; |
|---|
| 313 | if (count > 0) |
|---|
| 314 | { |
|---|
| 315 | status[i] = EINPROGRESS; |
|---|
| 316 | post_op(&vfs_request[i]); |
|---|
| 317 | } |
|---|
| 318 | } |
|---|
| 319 | } |
|---|
| 320 | } |
|---|
| 321 | if (count <= 0) |
|---|
| 322 | break; |
|---|
| 323 | } |
|---|
| 324 | return; |
|---|
| 325 | } |
|---|
| 326 | |
|---|
| 327 | static void do_io(int num_io) |
|---|
| 328 | { |
|---|
| 329 | if(src.fs_type == UNIX_FILE) |
|---|
| 330 | do_unix_io(num_io); |
|---|
| 331 | else |
|---|
| 332 | do_pvfs_io(num_io); |
|---|
| 333 | return; |
|---|
| 334 | } |
|---|
| 335 | |
|---|
| 336 | int main(int argc, char ** argv) |
|---|
| 337 | { |
|---|
| 338 | struct options* user_opts = NULL; |
|---|
| 339 | int64_t ret; |
|---|
| 340 | PVFS_credentials credentials; |
|---|
| 341 | |
|---|
| 342 | initialize_ops_in_progress_table(); |
|---|
| 343 | user_opts = parse_args(argc, argv); |
|---|
| 344 | if (!user_opts) |
|---|
| 345 | { |
|---|
| 346 | fprintf(stderr, "Error, failed to parse command line arguments\n"); |
|---|
| 347 | return(-1); |
|---|
| 348 | } |
|---|
| 349 | |
|---|
| 350 | ret = PVFS_util_init_defaults(); |
|---|
| 351 | if (ret < 0) |
|---|
| 352 | { |
|---|
| 353 | PVFS_perror("PVFS_util_init_defaults", ret); |
|---|
| 354 | return(-1); |
|---|
| 355 | } |
|---|
| 356 | memset(&src, 0, sizeof(src)); |
|---|
| 357 | |
|---|
| 358 | resolve_filename(&src, user_opts->srcfile); |
|---|
| 359 | |
|---|
| 360 | PVFS_util_gen_credentials(&credentials); |
|---|
| 361 | |
|---|
| 362 | ret = generic_open(&src, &credentials); |
|---|
| 363 | if (ret < 0) |
|---|
| 364 | { |
|---|
| 365 | fprintf(stderr, "Could not open %s\n", user_opts->srcfile); |
|---|
| 366 | goto main_out; |
|---|
| 367 | } |
|---|
| 368 | |
|---|
| 369 | do_io(user_opts->num_io); |
|---|
| 370 | main_out: |
|---|
| 371 | PVFS_sys_finalize(); |
|---|
| 372 | finalize_ops_in_progress_table(); |
|---|
| 373 | free(user_opts); |
|---|
| 374 | return(ret); |
|---|
| 375 | } |
|---|
| 376 | |
|---|
| 377 | /* parse_args() |
|---|
| 378 | * |
|---|
| 379 | * parses command line arguments |
|---|
| 380 | * |
|---|
| 381 | * returns pointer to options structure on success, NULL on failure |
|---|
| 382 | */ |
|---|
| 383 | static struct options* parse_args(int argc, char* argv[]) |
|---|
| 384 | { |
|---|
| 385 | char flags[] = "f:i:"; |
|---|
| 386 | int one_opt = 0; |
|---|
| 387 | |
|---|
| 388 | struct options* tmp_opts = NULL; |
|---|
| 389 | |
|---|
| 390 | /* create storage for the command line options */ |
|---|
| 391 | tmp_opts = (struct options*)malloc(sizeof(struct options)); |
|---|
| 392 | if(!tmp_opts){ |
|---|
| 393 | return(NULL); |
|---|
| 394 | } |
|---|
| 395 | memset(tmp_opts, 0, sizeof(struct options)); |
|---|
| 396 | tmp_opts->num_io = 10000; |
|---|
| 397 | |
|---|
| 398 | /* look at command line arguments */ |
|---|
| 399 | while((one_opt = getopt(argc, argv, flags)) != EOF) |
|---|
| 400 | { |
|---|
| 401 | switch(one_opt) { |
|---|
| 402 | case 'i': |
|---|
| 403 | tmp_opts->num_io = atoi(optarg); |
|---|
| 404 | break; |
|---|
| 405 | case('f'): |
|---|
| 406 | tmp_opts->srcfile = optarg; |
|---|
| 407 | break; |
|---|
| 408 | case('?'): |
|---|
| 409 | usage(argc, argv); |
|---|
| 410 | exit(EXIT_FAILURE); |
|---|
| 411 | } |
|---|
| 412 | } |
|---|
| 413 | if (tmp_opts->srcfile == NULL) |
|---|
| 414 | { |
|---|
| 415 | usage(argc, argv); |
|---|
| 416 | exit(EXIT_FAILURE); |
|---|
| 417 | } |
|---|
| 418 | return(tmp_opts); |
|---|
| 419 | } |
|---|
| 420 | |
|---|
| 421 | static void usage(int argc, char** argv) |
|---|
| 422 | { |
|---|
| 423 | fprintf(stderr, |
|---|
| 424 | "Usage: %s ARGS \n", argv[0]); |
|---|
| 425 | fprintf(stderr, "Where ARGS is one or more of" |
|---|
| 426 | "\n-f <file name>\t\t\tPVFS2 file pathname" |
|---|
| 427 | "\n-v\t\t\t\tprint version number and exit\n"); |
|---|
| 428 | return; |
|---|
| 429 | } |
|---|
| 430 | |
|---|
| 431 | /* resolve_filename: |
|---|
| 432 | * given 'filename', find the PVFS2 fs_id and relative pvfs_path. In case of |
|---|
| 433 | * error, assume 'filename' is a unix file. |
|---|
| 434 | */ |
|---|
| 435 | static int resolve_filename(file_object *obj, char *filename) |
|---|
| 436 | { |
|---|
| 437 | int ret; |
|---|
| 438 | |
|---|
| 439 | ret = PVFS_util_resolve(filename, &(obj->u.pvfs2.fs_id), |
|---|
| 440 | obj->u.pvfs2.pvfs2_path, PVFS_NAME_MAX); |
|---|
| 441 | if (ret < 0) |
|---|
| 442 | { |
|---|
| 443 | obj->fs_type = UNIX_FILE; |
|---|
| 444 | strncpy(obj->u.ufs.path, filename, NAME_MAX); |
|---|
| 445 | } else { |
|---|
| 446 | obj->fs_type = PVFS2_FILE; |
|---|
| 447 | strncpy(obj->u.pvfs2.user_path, filename, PVFS_NAME_MAX); |
|---|
| 448 | } |
|---|
| 449 | return 0; |
|---|
| 450 | } |
|---|
| 451 | |
|---|
| 452 | /* generic_open: |
|---|
| 453 | * given a file_object, perform the apropriate open calls. |
|---|
| 454 | */ |
|---|
| 455 | static int generic_open(file_object *obj, PVFS_credentials *credentials) |
|---|
| 456 | { |
|---|
| 457 | struct stat stat_buf; |
|---|
| 458 | PVFS_sysresp_lookup resp_lookup; |
|---|
| 459 | PVFS_sysresp_getattr resp_getattr; |
|---|
| 460 | PVFS_object_ref ref; |
|---|
| 461 | int ret = -1; |
|---|
| 462 | |
|---|
| 463 | if (obj->fs_type == UNIX_FILE) |
|---|
| 464 | { |
|---|
| 465 | PINT_statfs_t statfsbuf; |
|---|
| 466 | memset(&stat_buf, 0, sizeof(struct stat)); |
|---|
| 467 | |
|---|
| 468 | stat(obj->u.ufs.path, &stat_buf); |
|---|
| 469 | if (!S_ISREG(stat_buf.st_mode)) |
|---|
| 470 | { |
|---|
| 471 | fprintf(stderr, "Not a file!\n"); |
|---|
| 472 | return(-1); |
|---|
| 473 | } |
|---|
| 474 | obj->u.ufs.fd = open(obj->u.ufs.path, O_RDWR); |
|---|
| 475 | obj->u.ufs.mode = (int)stat_buf.st_mode; |
|---|
| 476 | if (obj->u.ufs.fd < 0) |
|---|
| 477 | { |
|---|
| 478 | perror("open"); |
|---|
| 479 | fprintf(stderr, "could not open %s\n", obj->u.ufs.path); |
|---|
| 480 | return (-1); |
|---|
| 481 | } |
|---|
| 482 | if (PINT_statfs_fd_lookup(obj->u.ufs.fd, &statfsbuf) < 0) |
|---|
| 483 | { |
|---|
| 484 | perror("fstatfs:"); |
|---|
| 485 | fprintf(stderr, "could not fstatfs %s\n", obj->u.ufs.path); |
|---|
| 486 | } |
|---|
| 487 | memcpy(&obj->u.ufs.fs_id, &PINT_statfs_fsid(&statfsbuf), |
|---|
| 488 | sizeof(PINT_statfs_fsid(&statfsbuf))); |
|---|
| 489 | return 0; |
|---|
| 490 | } |
|---|
| 491 | else |
|---|
| 492 | { |
|---|
| 493 | memset(&resp_lookup, 0, sizeof(PVFS_sysresp_lookup)); |
|---|
| 494 | ret = PVFS_sys_lookup(obj->u.pvfs2.fs_id, |
|---|
| 495 | (char *) obj->u.pvfs2.pvfs2_path, |
|---|
| 496 | credentials, |
|---|
| 497 | &resp_lookup, |
|---|
| 498 | PVFS2_LOOKUP_LINK_FOLLOW, NULL); |
|---|
| 499 | if (ret < 0) |
|---|
| 500 | { |
|---|
| 501 | PVFS_perror("PVFS_sys_lookup", ret); |
|---|
| 502 | return (-1); |
|---|
| 503 | } |
|---|
| 504 | ref.handle = resp_lookup.ref.handle; |
|---|
| 505 | ref.fs_id = resp_lookup.ref.fs_id; |
|---|
| 506 | |
|---|
| 507 | memset(&resp_getattr, 0, sizeof(PVFS_sysresp_getattr)); |
|---|
| 508 | ret = PVFS_sys_getattr(ref, PVFS_ATTR_SYS_ALL, |
|---|
| 509 | credentials, &resp_getattr, NULL); |
|---|
| 510 | if (ret) |
|---|
| 511 | { |
|---|
| 512 | fprintf(stderr, "Failed to do pvfs2 getattr on %s\n", |
|---|
| 513 | obj->u.pvfs2.pvfs2_path); |
|---|
| 514 | return -1; |
|---|
| 515 | } |
|---|
| 516 | |
|---|
| 517 | if (resp_getattr.attr.objtype != PVFS_TYPE_METAFILE) |
|---|
| 518 | { |
|---|
| 519 | fprintf(stderr, "Not a meta file!\n"); |
|---|
| 520 | return -1; |
|---|
| 521 | } |
|---|
| 522 | obj->u.pvfs2.perms = resp_getattr.attr.perms; |
|---|
| 523 | memcpy(&obj->u.pvfs2.attr, &resp_getattr.attr, |
|---|
| 524 | sizeof(PVFS_sys_attr)); |
|---|
| 525 | obj->u.pvfs2.attr.mask = PVFS_ATTR_SYS_ALL_SETABLE; |
|---|
| 526 | obj->u.pvfs2.ref = ref; |
|---|
| 527 | } |
|---|
| 528 | return 0; |
|---|
| 529 | } |
|---|
| 530 | |
|---|
| 531 | /* read 'count' bytes from a (unix or pvfs2) file 'src', placing the result in |
|---|
| 532 | * 'buffer' */ |
|---|
| 533 | static PVFS_error post_generic_read(io_request *req) |
|---|
| 534 | { |
|---|
| 535 | if(req->src->fs_type == UNIX_FILE) |
|---|
| 536 | { |
|---|
| 537 | req->acb.aio_fildes = req->src->u.ufs.fd; |
|---|
| 538 | req->acb.aio_lio_opcode = LIO_READ; |
|---|
| 539 | req->acb.aio_reqprio = 0; |
|---|
| 540 | req->acb.aio_offset = req->offset; |
|---|
| 541 | req->acb.aio_buf = req->buffer; |
|---|
| 542 | req->acb.aio_nbytes = req->count; |
|---|
| 543 | req->acb.aio_sigevent.sigev_notify = SIGEV_NONE; |
|---|
| 544 | return (aio_read(&req->acb)); |
|---|
| 545 | } |
|---|
| 546 | else |
|---|
| 547 | { |
|---|
| 548 | PVFS_error ret; |
|---|
| 549 | req->file_req = PVFS_BYTE; |
|---|
| 550 | ret = PVFS_Request_contiguous(req->count, PVFS_BYTE, &req->mem_req); |
|---|
| 551 | if (ret < 0) |
|---|
| 552 | { |
|---|
| 553 | fprintf(stderr, "Error: PVFS_Request_contiguous failure\n"); |
|---|
| 554 | return (ret); |
|---|
| 555 | } |
|---|
| 556 | ret = PVFS_isys_io(req->src->u.pvfs2.ref, req->file_req, req->offset, |
|---|
| 557 | req->buffer, req->mem_req, &req->credentials, &req->resp_io, |
|---|
| 558 | PVFS_IO_READ, &req->op_id, NULL, req); |
|---|
| 559 | if (ret != 0) |
|---|
| 560 | { |
|---|
| 561 | PVFS_perror("PVFS_isys_io", ret); |
|---|
| 562 | PVFS_Request_free(&req->mem_req); |
|---|
| 563 | return ret; |
|---|
| 564 | } |
|---|
| 565 | return 0; |
|---|
| 566 | } |
|---|
| 567 | } |
|---|
| 568 | |
|---|
| 569 | /* write 'count' bytes to a (unix or pvfs2) file 'src', taking the result from |
|---|
| 570 | * 'buffer' */ |
|---|
| 571 | static PVFS_error post_generic_write(io_request *req) |
|---|
| 572 | { |
|---|
| 573 | if(req->src->fs_type == UNIX_FILE) |
|---|
| 574 | { |
|---|
| 575 | req->acb.aio_fildes = req->src->u.ufs.fd; |
|---|
| 576 | req->acb.aio_lio_opcode = LIO_WRITE; |
|---|
| 577 | req->acb.aio_reqprio = 0; |
|---|
| 578 | req->acb.aio_offset = req->offset; |
|---|
| 579 | req->acb.aio_buf = req->buffer; |
|---|
| 580 | req->acb.aio_nbytes = req->count; |
|---|
| 581 | req->acb.aio_sigevent.sigev_notify = SIGEV_NONE; |
|---|
| 582 | return (aio_write(&req->acb)); |
|---|
| 583 | } |
|---|
| 584 | else |
|---|
| 585 | { |
|---|
| 586 | PVFS_error ret; |
|---|
| 587 | req->file_req = PVFS_BYTE; |
|---|
| 588 | ret = PVFS_Request_contiguous(req->count, PVFS_BYTE, &req->mem_req); |
|---|
| 589 | if (ret < 0) |
|---|
| 590 | { |
|---|
| 591 | fprintf(stderr, "Error: PVFS_Request_contiguous failure\n"); |
|---|
| 592 | return (ret); |
|---|
| 593 | } |
|---|
| 594 | ret = PVFS_isys_io(req->src->u.pvfs2.ref, req->file_req, req->offset, |
|---|
| 595 | req->buffer, req->mem_req, &req->credentials, &req->resp_io, |
|---|
| 596 | PVFS_IO_WRITE, &req->op_id, NULL, req); |
|---|
| 597 | if (ret != 0) |
|---|
| 598 | { |
|---|
| 599 | PVFS_perror("PVFS_isys_io", ret); |
|---|
| 600 | PVFS_Request_free(&req->mem_req); |
|---|
| 601 | return ret; |
|---|
| 602 | } |
|---|
| 603 | return 0; |
|---|
| 604 | } |
|---|
| 605 | } |
|---|
| 606 | |
|---|
| 607 | /* |
|---|
| 608 | * Local variables: |
|---|
| 609 | * c-indent-level: 4 |
|---|
| 610 | * c-basic-offset: 4 |
|---|
| 611 | * End: |
|---|
| 612 | * |
|---|
| 613 | * vim: ts=8 sts=4 sw=4 expandtab |
|---|
| 614 | */ |
|---|