// File: /workspace/github_c_makefile_star2_O3/Tarsnap[P]kivaloo/lbs/storage.c
// Function: storage_write
int
storage_write(struct storage_state * S,
    uint64_t blkno, uint64_t nblks, uint8_t * buf)
{
	struct file_state fs_new;
	struct file_state * fs;
	int newfile;
	uint64_t fnum;
	char * s = NULL;	/* free(NULL) simplifies error path. */

	/* Sanity checks.  We must have nblks * S->blocklen <= SIZE_MAX. */
	assert((nblks != 0) && (S->blocklen != 0));
	assert(nblks <= SIZE_MAX / S->blocklen);

	/* Pick up a write lock. */
	if (storage_util_writelock(S))
		goto err0;

	/* Sanity-check the write position. */
	if (blkno != S->nextblk) {
		warn0("Attempt to append data with wrong blkno");
		warn0("(%016" PRIx64 ", should be %016" PRIx64 ")",
		    blkno, S->nextblk);
		goto err2;
	}

	/* Get a pointer to the last file (or NULL if no files exist). */
	fs = elasticqueue_get(S->files, elasticqueue_getlen(S->files) - 1);

	/**
	 * Figure out if we should continue appending to the last file, or
	 * create a new file.  We start a new file if either of the following
	 * conditions apply:
	 * 1. We have no files yet.
	 * 2. The last file is more than 1/16 of the total stored data.
	 * 3. Adding to the last file will result in the file having too
	 *    many blocks.
	 */
	if (fs == NULL)
		newfile = 1;
	else if (fs->len > (S->nextblk - S->minblk) / 16)
		newfile = 1;
	else if (fs->len + nblks > S->maxnblks)
		newfile = 1;
	else
		newfile = 0;

	/* If we're creating a new file, add a new file_state to the queue. */
	if (newfile) {
		fs_new.start = blkno;
		fs_new.len = 0;
		fs = &fs_new;
		if (elasticqueue_add(S->files, fs))
			goto err2;
	}

	/* Record which file we're appending to. */
	fnum = fs->start;

	/* Release the lock. */
	if (storage_util_unlock(S))
		goto err0;

	/* Write the block(s) to the end of the file. */
	if ((s = storage_util_mkpath(S, fnum)) == NULL)
		goto err0;
	if (disk_write(s, newfile, (size_t)(S->blocklen * nblks), buf,
	    S->nosync)) {
		goto err1;
	}
	free(s);

	/* Make sure any file creation is flushed to disk. */
	if ((newfile) && (S->nosync == 0)) {
		if (disk_syncdir(S->storagedir))
			goto err0;
	}

	/* Pick up a write lock. */
	if (storage_util_writelock(S))
		goto err0;

	/*
	 * Get a pointer to the last file.  We must do this here since the
	 * queue may have been modified while we didn't have a lock.
	 */
	fs = elasticqueue_get(S->files, elasticqueue_getlen(S->files) - 1);

	/* Adjust block count. */
	fs->len += nblks;

	/* Adjust next-block-to-write value. */
	S->nextblk += nblks;

	/* Release the lock. */
	if (storage_util_unlock(S))
		goto err0;

	/* Success! */
	return (0);

err2:
	storage_util_unlock(S);
err1:
	free(s);
err0:
	/* Failure! */
	return (-1);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
testq %rdx, %rdx
je 0x5209
movq %rdi, %rbx
movq 0x8(%rdi), %rax
testq %rax, %rax
je 0x5209
movq %rdx, %r14
mulq %rdx
jo 0x5228
movq %rcx, %r15
movq %rsi, %r12
movq %rbx, %rdi
callq 0x5708
testl %eax, %eax
jne 0x5143
cmpq %r12, 0x70(%rbx)
jne 0x50fe
movq 0x60(%rbx), %r13
movq %r13, %rdi
callq 0x5d90
leaq -0x1(%rax), %rsi
movq %r13, %rdi
callq 0x5d95
testq %rax, %rax
je 0x50ce
movq %rax, %r13
movq 0x8(%rax), %rax
movq 0x70(%rbx), %rcx
subq 0x68(%rbx), %rcx
shrq $0x4, %rcx
cmpq %rcx, %rax
ja 0x50ce
addq %r14, %rax
cmpq 0x10(%rbx), %rax
jbe 0x5157
leaq 0x8(%rsp), %r13
movq %r12, (%r13)
movq $0x0, 0x8(%r13)
movq 0x60(%rbx), %rdi
movq %r13, %rsi
callq 0x5cd9
testl %eax, %eax
jne 0x5130
movl $0x1, %ebp
movl $0x0, 0x4(%rsp)
jmp 0x515f
leaq 0x89de(%rip), %rdi      # 0xdae3
xorl %ebp, %ebp
xorl %eax, %eax
callq 0xadf7
callq 0x20a0
movq %rax, %r14
movl %ebp, (%rax)
movq 0x70(%rbx), %rdx
leaq 0x89e8(%rip), %rdi      # 0xdb0b
movq %r12, %rsi
xorl %eax, %eax
callq 0xadf7
movl %ebp, (%r14)
movq %rbx, %rdi
callq 0x5744
xorl %r12d, %r12d
movq %r12, %rdi
callq 0x2040
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movb $0x1, %al
movl %eax, 0x4(%rsp)
xorl %ebp, %ebp
movq (%r13), %r12
movq %rbx, %rdi
callq 0x5744
testl %eax, %eax
jne 0x5143
movq %rbx, %rdi
movq %r12, %rsi
callq 0x5780
testq %rax, %rax
je 0x5143
movq %rax, %r12
movq 0x8(%rbx), %rdx
imulq %r14, %rdx
movl 0x20(%rbx), %r8d
movq %rax, %rdi
movl %ebp, %esi
movq %r15, %rcx
callq 0x5aeb
testl %eax, %eax
jne 0x513b
movq %r12, %rdi
callq 0x2040
cmpb $0x0, 0x4(%rsp)
jne 0x51b4
cmpl $0x0, 0x20(%rbx)
je 0x51f7
movq %rbx, %rdi
callq 0x5708
testl %eax, %eax
jne 0x5143
movq 0x60(%rbx), %r15
movq %r15, %rdi
callq 0x5d90
leaq -0x1(%rax), %rsi
movq %r15, %rdi
callq 0x5d95
addq %r14, 0x8(%rax)
addq %r14, 0x70(%rbx)
movq %rbx, %rdi
callq 0x5744
testl %eax, %eax
jne 0x5143
xorl %eax, %eax
jmp 0x5148
movq (%rbx), %rdi
callq 0x57e8
testl %eax, %eax
jne 0x5143
jmp 0x51b4
leaq 0x8847(%rip), %rdi      # 0xda57
leaq 0x86e4(%rip), %rsi      # 0xd8fb
leaq 0x885c(%rip), %rcx      # 0xda7a
movl $0x12c, %edx            # imm = 0x12C
callq 0x2220
leaq 0x8894(%rip), %rdi      # 0xdac3
leaq 0x86c5(%rip), %rsi      # 0xd8fb
leaq 0x883d(%rip), %rcx      # 0xda7a
movl $0x12d, %edx            # imm = 0x12D
callq 0x2220