* allocate nbytes of diskspace for file fp * this allows the filesystem to make smarter allocation decisions and gives a * fast exit on not enough free space * returns -1 and raises exception on no space, ignores all other errors */
| 34 | * returns -1 and raises exception on no space, ignores all other errors |
| 35 | */ |
| 36 | static int |
| 37 | npy_fallocate(npy_intp nbytes, FILE * fp) |
| 38 | { |
| 39 | /* |
| 40 | * unknown behavior on non-linux so don't try it |
| 41 | * we don't want explicit zeroing to happen |
| 42 | */ |
| 43 | #if defined(HAVE_FALLOCATE) && defined(__linux__) |
| 44 | int r; |
| 45 | /* small files not worth the system call */ |
| 46 | if (nbytes < 16 * 1024 * 1024) { |
| 47 | return 0; |
| 48 | } |
| 49 | |
| 50 | /* btrfs can take a while to allocate making release worthwhile */ |
| 51 | NPY_BEGIN_ALLOW_THREADS; |
| 52 | /* |
| 53 | * flush in case there might be some unexpected interactions between the |
| 54 | * fallocate call and unwritten data in the descriptor |
| 55 | */ |
| 56 | fflush(fp); |
| 57 | /* |
| 58 | * the flag "1" (=FALLOC_FL_KEEP_SIZE) is needed for the case of files |
| 59 | * opened in append mode (issue #8329) |
| 60 | */ |
| 61 | r = fallocate(fileno(fp), 1, npy_ftell(fp), nbytes); |
| 62 | NPY_END_ALLOW_THREADS; |
| 63 | |
| 64 | /* |
| 65 | * early exit on no space, other errors will also get found during fwrite |
| 66 | */ |
| 67 | if (r == -1 && errno == ENOSPC) { |
| 68 | PyErr_Format(PyExc_OSError, "Not enough free space to write " |
| 69 | "%"NPY_INTP_FMT" bytes", nbytes); |
| 70 | return -1; |
| 71 | } |
| 72 | #endif |
| 73 | return 0; |
| 74 | } |
| 75 | |
| 76 | /* |
| 77 | * Converts a subarray of 'self' into lists, with starting data pointer |