Exemplo n.º 1
0
int
test_mount(int argc, char *argv[])
{
	const unsigned iterations = 2000;
	const unsigned alignments = 10;

	const char *cmd_filename = "/fs/microsd/mount_test_cmds.txt";


	/* check if microSD card is mounted */
	struct stat buffer;

	if (stat("/fs/microsd/", &buffer)) {
		warnx("no microSD card mounted, aborting file test");
		return 1;
	}

	/* list directory */
	DIR		*d;
	struct dirent	*dir;
	d = opendir("/fs/microsd");

	if (d) {

		while ((dir = readdir(d)) != NULL) {
			//printf("%s\n", dir->d_name);
		}

		closedir(d);

		warnx("directory listing ok (FS mounted and readable)");

	} else {
		/* failed opening dir */
		warnx("FAILED LISTING MICROSD ROOT DIRECTORY");

		if (stat(cmd_filename, &buffer) == OK) {
			(void)unlink(cmd_filename);
		}

		return 1;
	}

	/* read current test status from file, write test instructions for next round */

	/* initial values */
	int it_left_fsync = fsync_tries;
	int it_left_abort = abort_tries;

	int cmd_fd;

	if (stat(cmd_filename, &buffer) == OK) {

		/* command file exists, read off state */
		cmd_fd = open(cmd_filename, O_RDWR | O_NONBLOCK);
		char buf[64];
		int ret = read(cmd_fd, buf, sizeof(buf));

		if (ret > 0) {
			int count = 0;
			ret = sscanf(buf, "TEST: %u %u %n", &it_left_fsync, &it_left_abort, &count);

		} else {
			buf[0] = '\0';
		}

		if (it_left_fsync > fsync_tries) {
			it_left_fsync = fsync_tries;
		}

		if (it_left_abort > abort_tries) {
			it_left_abort = abort_tries;
		}

		warnx("Iterations left: #%d / #%d of %d / %d\n(%s)", it_left_fsync, it_left_abort,
		      fsync_tries, abort_tries, buf);

		int it_left_fsync_prev = it_left_fsync;

		/* now write again what to do next */
		if (it_left_fsync > 0) {
			it_left_fsync--;
		}

		if (it_left_fsync == 0 && it_left_abort > 0) {

			it_left_abort--;

			/* announce mode switch */
			if (it_left_fsync_prev != it_left_fsync && it_left_fsync == 0) {
				warnx("\n SUCCESSFULLY PASSED FSYNC'ED WRITES, CONTINUTING WITHOUT FSYNC");
				fsync(fileno(stdout));
				fsync(fileno(stderr));
				usleep(20000);
			}

		}

		if (it_left_abort == 0) {
			(void)unlink(cmd_filename);
			return 0;
		}

	} else {

		/* this must be the first iteration, do something */
		cmd_fd = open(cmd_filename, O_TRUNC | O_WRONLY | O_CREAT);

		warnx("First iteration of file test\n");
	}

	char buf[64];
	(void)sprintf(buf, "TEST: %d %d ", it_left_fsync, it_left_abort);
	lseek(cmd_fd, 0, SEEK_SET);
	write(cmd_fd, buf, strlen(buf) + 1);
	fsync(cmd_fd);

	/* perform tests for a range of chunk sizes */
	unsigned chunk_sizes[] = {32, 64, 128, 256, 512, 600, 1200};

	for (unsigned c = 0; c < (sizeof(chunk_sizes) / sizeof(chunk_sizes[0])); c++) {

		printf("\n\n====== FILE TEST: %u bytes chunks (%s) ======\n", chunk_sizes[c],
		       (it_left_fsync > 0) ? "FSYNC" : "NO FSYNC");
		printf("unpower the system immediately (within 0.5s) when the hash (#) sign appears\n");
		fsync(fileno(stdout));
		fsync(fileno(stderr));
		usleep(50000);

		for (unsigned a = 0; a < alignments; a++) {

			printf(".");

			uint8_t write_buf[chunk_sizes[c] + alignments] __attribute__((aligned(64)));

			/* fill write buffer with known values */
			for (unsigned i = 0; i < sizeof(write_buf); i++) {
				/* this will wrap, but we just need a known value with spacing */
				write_buf[i] = i + 11;
			}

			uint8_t read_buf[chunk_sizes[c] + alignments] __attribute__((aligned(64)));

			int fd = open("/fs/microsd/testfile", O_TRUNC | O_WRONLY | O_CREAT);

			for (unsigned i = 0; i < iterations; i++) {

				int wret = write(fd, write_buf + a, chunk_sizes[c]);

				if (wret != (int)chunk_sizes[c]) {
					warn("WRITE ERROR!");

					if ((0x3 & (uintptr_t)(write_buf + a))) {
						warnx("memory is unaligned, align shift: %d", a);
					}

					return 1;

				}

				if (it_left_fsync > 0) {
					fsync(fd);

				} else {
					printf("#");
					fsync(fileno(stdout));
					fsync(fileno(stderr));
				}
			}

			if (it_left_fsync > 0) {
				printf("#");
			}

			printf(".");
			fsync(fileno(stdout));
			fsync(fileno(stderr));
			usleep(200000);

			close(fd);
			fd = open("/fs/microsd/testfile", O_RDONLY);

			/* read back data for validation */
			for (unsigned i = 0; i < iterations; i++) {
				int rret = read(fd, read_buf, chunk_sizes[c]);

				if (rret != (int)chunk_sizes[c]) {
					warnx("READ ERROR!");
					return 1;
				}

				/* compare value */
				bool compare_ok = true;

				for (unsigned j = 0; j < chunk_sizes[c]; j++) {
					if (read_buf[j] != write_buf[j + a]) {
						warnx("COMPARISON ERROR: byte %d, align shift: %d", j, a);
						compare_ok = false;
						break;
					}
				}

				if (!compare_ok) {
					warnx("ABORTING FURTHER COMPARISON DUE TO ERROR");
					return 1;
				}

			}

			int ret = unlink("/fs/microsd/testfile");
			close(fd);

			if (ret) {
				warnx("UNLINKING FILE FAILED");
				return 1;
			}

		}
	}

	fsync(fileno(stdout));
	fsync(fileno(stderr));
	usleep(20000);



	/* we always reboot for the next test if we get here */
	warnx("Iteration done, rebooting..");
	fsync(fileno(stdout));
	fsync(fileno(stderr));
	usleep(50000);
	px4_systemreset(false);

	/* never going to get here */
	return 0;
}
Exemplo n.º 2
0
int
deliver(int fd, char *name, int lockfile)
{
	struct stat sb, fsb;
	struct passwd *pw;
	int mbfd=-1, rval=1, lfd=-1;
	char biffmsg[100], buf[8*1024], path[MAXPATHLEN];
	off_t curoff;
	size_t off;
	ssize_t nr, nw;

	/*
	 * Disallow delivery to unknown names -- special mailboxes can be
	 * handled in the sendmail aliases file.
	 */
	if (!(pw = getpwnam(name))) {
		merr(NOTFATAL, "unknown name: %s", name);
		return(1);
	}

	(void)snprintf(path, sizeof path, "%s/%s", _PATH_MAILDIR, name);

	if (lockfile) {
		lfd = getlock(name, pw);
		if (lfd == -1)
			return (1);
	}

	/* after this point, always exit via bad to remove lockfile */
retry:
	if (lstat(path, &sb)) {
		if (errno != ENOENT) {
			merr(NOTFATAL, "%s: %s", path, strerror(errno));
			goto bad;
		}
		if ((mbfd = open(path, O_APPEND|O_CREAT|O_EXCL|O_WRONLY|O_EXLOCK,
		    S_IRUSR|S_IWUSR)) < 0) {
			if (errno == EEXIST) {
				/* file appeared since lstat */
				goto retry;
			} else {
				merr(NOTFATAL, "%s: %s", path, strerror(errno));
				goto bad;
			}
		}
		/*
		 * Set the owner and group.  Historically, binmail repeated
		 * this at each mail delivery.  We no longer do this, assuming
		 * that if the ownership or permissions were changed there
		 * was a reason for doing so.
		 */
		if (fchown(mbfd, pw->pw_uid, pw->pw_gid) < 0) {
			merr(NOTFATAL, "chown %u:%u: %s",
			    pw->pw_uid, pw->pw_gid, name);
			goto bad;
		}
	} else {
		if (sb.st_nlink != 1 || !S_ISREG(sb.st_mode)) {
			merr(NOTFATAL, "%s: linked or special file", path);
			goto bad;
		}
		if ((mbfd = open(path, O_APPEND|O_WRONLY|O_EXLOCK,
		    S_IRUSR|S_IWUSR)) < 0) {
			merr(NOTFATAL, "%s: %s", path, strerror(errno));
			goto bad;
		}
		if (fstat(mbfd, &fsb)) {
			/* relating error to path may be bad style */
			merr(NOTFATAL, "%s: %s", path, strerror(errno));
			goto bad;
		}
		if (sb.st_dev != fsb.st_dev || sb.st_ino != fsb.st_ino) {
			merr(NOTFATAL, "%s: changed after open", path);
			goto bad;
		}
		/* paranoia? */
		if (fsb.st_nlink != 1 || !S_ISREG(fsb.st_mode)) {
			merr(NOTFATAL, "%s: linked or special file", path);
			goto bad;
		}
	}

	curoff = lseek(mbfd, 0, SEEK_END);
	(void)snprintf(biffmsg, sizeof biffmsg, "%s@%qd\n", name, curoff);
	if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
		merr(NOTFATAL, "temporary file: %s", strerror(errno));
		goto bad;
	}

	while ((nr = read(fd, buf, sizeof(buf))) > 0)
		for (off = 0; off < nr;  off += nw)
			if ((nw = write(mbfd, buf + off, nr - off)) < 0) {
				merr(NOTFATAL, "%s: %s", path, strerror(errno));
				(void)ftruncate(mbfd, curoff);
				goto bad;
			}

	if (nr == 0) {
		rval = 0;
	} else {
		(void)ftruncate(mbfd, curoff);
		merr(FATAL, "temporary file: %s", strerror(errno));
	}

bad:
	if (lfd != -1) {
		rellock();
		close(lfd);
	}

	if (mbfd != -1) {
		(void)fsync(mbfd);		/* Don't wait for update. */
		(void)close(mbfd);		/* Implicit unlock. */
	}

	if (!rval)
		notifybiff(biffmsg);
	return(rval);
}
Exemplo n.º 3
0
void write_perf_test1(off64_t kilo64,long long reclen ,long long *data1,long long *data2)
{
	double starttime1;
	double writetime[2];
	double walltime[2], cputime[2];
	double qtime_start,qtime_stop;
	double hist_time;
	double compute_val = (double)0;
	long long i,j;
	off64_t numrecs64,traj_offset;
	off64_t lock_offset=0;
	long long Index = 0;
	long long file_flags = 0;
	long long traj_size;
	unsigned long long writerate[2];
	off64_t filebytes64;
	int ltest;
	char *maddr;
	char *wmaddr,*free_addr;
	char *pbuff;
	char *nbuff;
	int fd,wval;
	int notruncate = 1;
	unsigned long w_traj_ops_completed=0;
	unsigned long w_traj_bytes_completed=0;
	char *filename = "/mnt/ramdisk/test1";

	int test_foo;

	nbuff=wmaddr=free_addr=0;
	traj_offset=0;
	test_foo=0;
	hist_time=qtime_start=qtime_stop=0;
	maddr=0;
	pbuff=mainbuffer;
	numrecs64 = (kilo64*1024)/reclen;
	filebytes64 = numrecs64*reclen;

	fd = 0;
	file_flags = O_RDWR;

/* Sanity check */
/* Some filesystems do not behave correctly and fail
 * when this sequence is performned. This is a very
 * bad thing. It breaks many applications and lurks
 * around quietly. This code should never get
 * triggered, but in the case of running iozone on
 * an NFS client, the filesystem type on the server
 * that is being exported can cause this failure.
 * If this failure happens, then the NFS client is
 * going to going to have problems, but the acutal
 * problem is the filesystem on the NFS server.
 * It's not NFS, it's the local filesystem on the
 * NFS server that is not correctly permitting
 * the sequence to function.
 */
/* _SUA_ Services for Unix Applications, under Windows
    does not have a truncate, so this must be skipped */
        if((fd = open(filename, (int)O_CREAT|O_RDWR,0))<0)
        {
                printf("\nCan not open temp file: %s\n",
                        filename);
                perror("open");
                exit(44);
        }
		if(!notruncate)
		{
			wval=ftruncate(fd,0);
			if(wval < 0)
			{
				printf("\n\nSanity check failed. Do not deploy this filesystem in a production environment !\n");
				exit(44);
			}
			close(fd);

		}
/* Sanity check */

	ltest=3;

	for( j=0; j<ltest; j++)
	{
		if(j==0)
		{
			if(!notruncate)
			{
	  	   		if((fd = creat(filename, 0640))<0)
	  	   		{
					printf("\nCan not create temp file: %s\n", 
						filename);
					perror("creat");
					exit(42);
	  	   		}
			}
		}
		if(fd) 
			close(fd);

	  	 if((fd = open(filename, (int)file_flags,0))<0)
	  	 {
			printf("\nCan not open temp file: %s\n", 
				filename);
			perror("open");
			exit(44);
	  	 }

		wval=fsync(fd);
		if(wval==-1){
			perror("fsync");
		}
		pbuff=mainbuffer;
		starttime1 = time_so_far();

		compute_val=(double)0;
		w_traj_ops_completed=0;
		w_traj_bytes_completed=0;

		for(i=0; i<numrecs64; i++){
			    wval=write(fd, pbuff, (size_t ) reclen);
			    if(wval != reclen)
			    {
#ifdef NO_PRINT_LLD
			    	printf("\nError writing block %ld, fd= %d\n", i,
					 fd);
#else
			    	printf("\nError writing block %lld, fd= %d\n", i,
					 fd);
#endif
			    	if(wval == -1)
					perror("write");
			    }
			w_traj_ops_completed++;
			w_traj_bytes_completed+=reclen;
		}

		writetime[j] = ((time_so_far() - starttime1))
			-compute_val;
		if(writetime[j] < (double).000001) 
		{
			writetime[j]=(double).000001;
		}
		wval=close(fd);
		if(wval==-1){
			perror("close");
		}
	}

	filebytes64=w_traj_bytes_completed;
		
        for(j=0;j<ltest;j++)
        {
                  writerate[j] = 
                    (unsigned long long) ((double) filebytes64 / writetime[j]);
		  printf("%s: ltest %d writerate %llu\n", __func__, j, writerate[j]);
	}

}
Exemplo n.º 4
0
pid_t
cyon_store_write(void)
{
	pid_t			pid;
	u_int8_t		*buf;
	struct store_header	header;
	int			fd, ret;
	u_int32_t		len, blen;
	u_char			hash[SHA_DIGEST_LENGTH];
	char			fpath[MAXPATHLEN], tpath[MAXPATHLEN];

	if (rnode == NULL || store_modified == 0 || store_nopersist) {
		cyon_log(LOG_NOTICE, "store is clean, not writing");
		return (CYON_RESULT_OK);
	}

	/*
	 * The write lock protects us from getting new entries in the log
	 * so it is safe to reopen the logs after the fork.
	 */
	cyon_store_lock(1);

	pid = fork();
	if (pid == -1) {
		cyon_store_unlock();
		cyon_log(LOG_NOTICE,
		    "store write not started (fork: %s)", errno_s);
		return (CYON_RESULT_ERROR);
	}

	if (pid != 0) {
		store_modified = 0;
		if (!cyon_readonly_mode)
			cyon_storelog_reopen(1);
		cyon_store_unlock();
		cyon_log(LOG_NOTICE, "store write started (%d)", pid);
		return (pid);
	}

	if (!cyon_readonly_mode)
		close(lfd);

	snprintf(fpath, sizeof(fpath), CYON_STORE_FILE, storepath, storename);
	snprintf(tpath, sizeof(tpath), CYON_STORE_TMPFILE,
	    storepath, storename);

	fd = open(tpath, O_CREAT | O_TRUNC | O_WRONLY, 0700);
	if (fd == -1)
		fatal("open(%s): %s", tpath, errno_s);

	memset(&header, 0, sizeof(header));
	if (store_passphrase != NULL)
		header.flags |= STORE_HAS_PASSPHRASE;

	len = 0;
	blen = 128 * 1024 * 1024;
	buf = cyon_malloc(blen);

	memcpy(buf, &header, sizeof(header));
	len += sizeof(header);

	if (header.flags & STORE_HAS_PASSPHRASE) {
		memcpy(buf + len, store_passphrase, SHA256_DIGEST_LENGTH);
		len += SHA256_DIGEST_LENGTH;
	}

	SHA_Init(&shactx);
	cyon_store_writenode(fd, rnode, buf, blen, &len, NULL);
	if (len > 0)
		cyon_atomic_write(fd, buf, len, &shactx);
	cyon_mem_free(buf);
	SHA_Final(hash, &shactx);
	cyon_atomic_write(fd, hash, SHA_DIGEST_LENGTH, NULL);

	for (;;) {
		ret = fsync(fd);
		if (ret == -1 && errno == EINTR)
			continue;
		if (ret == -1)
			fatal("store write failed %s", errno_s);
		break;
	}

	close(fd);

	if (rename(tpath, fpath) == -1)
		fatal("cannot move store into place: %s", errno_s);

	exit(0);
}
Exemplo n.º 5
0
/* Read the request from a client socket.
 */
int fetch_request(t_session *session) {
	char *new_reqbuf, *strstart, *strend;
	long max_request_size, bytes_read, header_length = -1, content_length = -1;
	int result = 200, write_bytes, poll_result;
	time_t deadline;
	struct pollfd poll_data;
	bool keep_reading = true, store_on_disk = false;
	int upload_handle = -1;

	if (session->request_limit == false) {
		deadline = session->time + NO_REQUEST_LIMIT_TIME;
		max_request_size = NO_REQUEST_LIMIT_SIZE;
	} else if (session->kept_alive == 0) {
		deadline = session->time + session->binding->time_for_1st_request;
		max_request_size = session->binding->max_request_size;
	} else {
		deadline = session->time + session->binding->time_for_request;
		max_request_size = session->binding->max_request_size;
	}

	do {
		/* Check if requestbuffer contains a complete request.
		 */
		if (session->request != NULL) {
			if (header_length == -1) {
				if ((strstart = strstr(session->request, "\r\n\r\n")) != NULL) {
					*(strstart + 2) = '\0';
					header_length = strstart + 4 - session->request;
					session->header_length = header_length;

					determine_request_method(session);
					store_on_disk = (session->request_method == PUT) && session->binding->enable_alter;

					if (store_on_disk) {
	 					if ((session->uploaded_file = (char*)malloc(session->config->upload_directory_len + 15)) != NULL) {
							strcpy(session->uploaded_file, session->config->upload_directory);
							strcpy(session->uploaded_file + session->config->upload_directory_len, "/upload_XXXXXX");
							if ((upload_handle = mkstemp(session->uploaded_file)) == -1) {
								free(session->uploaded_file);
								session->uploaded_file = NULL;
							}
						}
						if (session->uploaded_file == NULL) {
							log_error(session, "can't create temporary file for PUT request");
							result = 500;
							break;
						}

						session->uploaded_size = session->bytes_in_buffer - header_length;
						if (write_buffer(upload_handle, session->request + header_length, session->uploaded_size) == -1) {
							result = 500;
							break;
						}
						session->bytes_in_buffer = header_length;
					}

				}
			}
			if (header_length != -1) {
				if (content_length == -1) {
					if ((strstart = strcasestr(session->request, hs_conlen)) != NULL) {
						strstart += 16;
						if ((strend = strstr(strstart, "\r\n")) != NULL) {
							*strend = '\0';
							content_length = str2int(strstart);
							*strend = '\r';
							if ((content_length < 0) || (INT_MAX - content_length - 2 <= header_length)) {
								result = 500;
								break;
							}

							if (store_on_disk) {
								/* Write to file on disk
								 */
								session->content_length = 0;
								if (content_length > session->binding->max_upload_size) {
									result = 413;
									break;
								}

								session->buffer_size = header_length + REQUEST_BUFFER_CHUNK;
								if ((new_reqbuf = (char*)realloc(session->request, session->buffer_size + 1)) != NULL) {
									session->request = new_reqbuf;
								} else {
									session->error_cause = ec_SOCKET_READ_ERROR;
									result = -1;
									break;
								}
							} else {
								/* Read into memory
								 */
								session->content_length = content_length;
								if (header_length + content_length > max_request_size) {
									session->error_cause = ec_MAX_REQUESTSIZE;
									result = -1;
									break;
								}

								if (header_length + content_length > session->buffer_size) {
									session->buffer_size = header_length + content_length;
									if ((new_reqbuf = (char*)realloc(session->request, session->buffer_size + 1)) != NULL) {
										session->request = new_reqbuf;
									} else {
										session->error_cause = ec_SOCKET_READ_ERROR;
										result = -1;
										break;
									}
								}
							}
						}
					} else {
						session->content_length = 0;
						if (store_on_disk) {
							result = 411;
						}
						break;
					}
				}

				if (content_length > -1) {
					if (store_on_disk) {
						if (session->uploaded_size == content_length) {
							/* Received a complete PUT request */
							break;
						}
					} else {
						if (session->bytes_in_buffer >= header_length + content_length) {
							/* Received a complete request */
							break;
						}
					}
				}
			}
		}

#ifdef ENABLE_SSL
		poll_result = session->binding->use_ssl ? ssl_pending(&(session->ssl_context)) : 0;

		if (poll_result == 0) {
#endif
			poll_data.fd = session->client_socket;
			poll_data.events = POLL_EVENT_BITS;
			poll_result = poll(&poll_data, 1, 1000);
#ifdef ENABLE_SSL
		}
#endif

		switch (poll_result) {
			case -1:
				if (errno != EINTR) {
					session->error_cause = ec_SOCKET_READ_ERROR;
					result = -1;
					keep_reading = false;
				}
				break;
			case 0:
				if (session->force_quit) {
					session->error_cause = ec_FORCE_QUIT;
					result = -1;
					keep_reading = false;
				} else if (time(NULL) > deadline) {
					session->error_cause = ec_TIMEOUT;
					result = -1;
					keep_reading = false;
				}
				break;
			default:
				if ((content_length == -1) && ((session->buffer_size - session->bytes_in_buffer) < 256)) {
					session->buffer_size += REQUEST_BUFFER_CHUNK;
					if ((new_reqbuf = (char*)realloc(session->request, session->buffer_size + 1)) != NULL) {
						session->request = new_reqbuf;
					} else {
						session->error_cause = ec_SOCKET_READ_ERROR;
						result = -1;
						keep_reading = false;
						break;
					}
				}

				/* Read from socket.
				 */
#ifdef ENABLE_SSL
				if (session->binding->use_ssl) {
					bytes_read = ssl_receive(&(session->ssl_context), session->request + session->bytes_in_buffer,
									session->buffer_size - session->bytes_in_buffer);
				} else
#endif
					bytes_read = recv(session->client_socket, session->request + session->bytes_in_buffer,
									session->buffer_size - session->bytes_in_buffer, 0);

				switch (bytes_read) {
					case -1:
						if (errno != EINTR) {
							session->error_cause = ec_SOCKET_READ_ERROR;
							result = -1;
							keep_reading = false;
						}
						break;
					case 0:
						session->error_cause = ec_CLIENT_DISCONNECTED;
						result = -1;
						keep_reading = false;
						break;
					default:
						if (store_on_disk) {
							/* Write to file on disk
							 */
							write_bytes = bytes_read;
							if (session->uploaded_size + bytes_read > content_length) {
								write_bytes -= ((session->uploaded_size + bytes_read) - content_length);
							}
							if (write_buffer(upload_handle, session->request + header_length, write_bytes) == -1) {
								result = 500;
								keep_reading = false;
								break;
							}
							if ((session->uploaded_size += write_bytes) > session->binding->max_upload_size) {
								keep_reading = false;
								result = 413;
								break;
							}
							if (write_bytes < bytes_read) {
								memmove(session->request + header_length, session->request + header_length + write_bytes, bytes_read - write_bytes);
								session->bytes_in_buffer += bytes_read - write_bytes;
								keep_reading = false;
							}
						} else {
							/* Read into memory
							 */
							session->bytes_in_buffer += bytes_read;
							*(session->request + session->bytes_in_buffer) = '\0';

							if (session->bytes_in_buffer > max_request_size) {
								keep_reading = false;
								session->error_cause = ec_MAX_REQUESTSIZE;
								result = -1;
								break;
							}
						}
				}
		}
	} while (keep_reading);

	if (upload_handle != -1) {
		fsync(upload_handle);
		close(upload_handle);
	}

#ifdef ENABLE_TOMAHAWK
	increment_transfer(TRANSFER_RECEIVED, header_length + content_length);
#endif

	return result;
}
Exemplo n.º 6
0
void gds_rundown(void)
{
	boolean_t		cancelled_dbsync_timer, cancelled_timer, have_standalone_access, ipc_deleted, skip_database_rundown;
	boolean_t		is_cur_process_ss_initiator, remove_shm, vermismatch, we_are_last_user, we_are_last_writer, is_mm;
	now_t			now;	/* for GET_CUR_TIME macro */
	char			*time_ptr, time_str[CTIME_BEFORE_NL + 2]; /* for GET_CUR_TIME macro */
	gd_region		*reg;
	int			save_errno, status, rc;
	int4			semval, ftok_semval, sopcnt, ftok_sopcnt;
	short			crash_count;
	sm_long_t		munmap_len;
	sgmnt_addrs		*csa;
	sgmnt_data_ptr_t	csd;
	struct shmid_ds		shm_buf;
	struct sembuf		sop[2], ftok_sop[2];
	uint4           	jnl_status;
	unix_db_info		*udi;
	jnl_private_control	*jpc;
	jnl_buffer_ptr_t	jbp;
	shm_snapshot_t		*ss_shm_ptr;
	uint4			ss_pid, onln_rlbk_pid, holder_pid;
	boolean_t		was_crit;

	jnl_status = 0;
	reg = gv_cur_region;			/* Local copy */

	/* early out for cluster regions
	 * to avoid tripping the assert below.
	 * Note:
	 *	This early out is consistent with VMS.  It has been
	 *	noted that all of the gtcm assignments
	 *      to gv_cur_region should use the TP_CHANGE_REG
	 *	macro.  This would also avoid the assert problem
	 *	and should be done eventually.
	 */
	if (dba_cm == reg->dyn.addr->acc_meth)
		return;

	udi = FILE_INFO(reg);
	csa = &udi->s_addrs;
	csd = csa->hdr;
	assert(csa == cs_addrs && csd == cs_data);
	if ((reg->open) && (dba_usr == csd->acc_meth))
	{
		change_reg();
		gvusr_rundown();
		return;
	}
	ESTABLISH(gds_rundown_ch);
	assert(reg->open);			/* if we failed to open, dbinit_ch should have taken care of proper clean up */
	assert(!reg->opening);			/* see comment above */
	switch(csd->acc_meth)
	{	/* Pass mm and bg through */
		case dba_bg:
			is_mm = FALSE;
			break;
		case dba_mm:
			is_mm = TRUE;
			break;
		case dba_usr:
			assert(FALSE);
		default:
			REVERT;
			return;
	}
	assert(!csa->hold_onto_crit || (csa->now_crit && jgbl.onlnrlbk));
	/* If we are online rollback, we should already be holding crit and should release it only at the end of this module. This
	 * is usually done by noting down csa->now_crit in a local variable (was_crit) and using it whenever we are about to
	 * grab_crit. But, there are instances (like mupip_set_journal.c) where we grab_crit but invoke gds_rundown without any
	 * preceeding rel_crit. Such code relies on the fact that gds_rundown does rel_crit unconditionally (to get locks to a known
	 * state). So, augment csa->now_crit with jgbl.onlnrlbk to track if we can rel_crit unconditionally or not in gds_rundown.
	 */
	was_crit = (csa->now_crit && jgbl.onlnrlbk);
	/* Cancel any pending flush timer for this region by this task */
	cancelled_timer = FALSE;
	cancelled_dbsync_timer = FALSE;
	CANCEL_DB_TIMERS(reg, csa, cancelled_timer, cancelled_dbsync_timer);
	we_are_last_user = FALSE;
	if (!csa->persistent_freeze)
		region_freeze(reg, FALSE, FALSE, FALSE);
	if (!was_crit)
	{
		rel_crit(reg);		/* get locks to known state */
		mutex_cleanup(reg);
	}
	DEFER_INTERRUPTS(INTRPT_IN_GDS_RUNDOWN);
	/* If the process has standalone access, it has udi->grabbed_access_sem set to TRUE at this point. Note that down
	 * in a local variable as the udi->grabbed_access_sem is set to TRUE even for non-standalone access below and hence
	 * we can't rely on that later to determine if the process had standalone access or not when it entered this function.
	 * We need to guarantee that none else access database file header when semid/shmid fields are reset.
	 * We already have created ftok semaphore in db_init or, mu_rndwn_file and did not remove it.
	 * So just lock it. We do it in blocking mode.
	 */
	have_standalone_access = udi->grabbed_access_sem; /* process holds standalone access */
	/* The only process that can invoke gds_rundown while holding access control semaphore is RECOVER/ROLLBACK. All the others
	 * (like MUPIP SET -FILE/MUPIP EXTEND would have invoked db_ipcs_reset() before invoking gds_rundown (from
	 * mupip_exit_handler). The only exception is when these processes encounter a terminate signal and they reach
	 * mupip_exit_handler while holding access control semaphore. Assert accordingly.
	 */
	assert(!have_standalone_access || mupip_jnl_recover || process_exiting);
	/* If we have standalone access, then ensure that a concurrent online rollback cannot be running at the same time as it
	 * needs the access control lock as well. The only expection is we are online rollback and currently running down.
	 */
	onln_rlbk_pid = csa->nl->onln_rlbk_pid;
	assert(!have_standalone_access || mupip_jnl_recover || !onln_rlbk_pid || !is_proc_alive(onln_rlbk_pid, 0));
	skip_database_rundown = FALSE;
	if (!have_standalone_access)
	{
		/* We need to guarantee that no one else access database file header when semid/shmid fields are reset.
		 * We already have created ftok semaphore in db_init or mu_rndwn_file and did not remove it.  So just
		 * lock it. We do it in blocking mode.
		 */
		if (!ftok_sem_lock(reg, FALSE, FALSE))
			rts_error(VARLSTCNT(4) ERR_DBFILERR, 2, DB_LEN_STR(reg));
		FTOK_TRACE(csa, csa->ti->curr_tn, ftok_ops_lock, process_id);
		sop[0].sem_num = 0; sop[0].sem_op = 0;	/* Wait for 0 */
		sop[1].sem_num = 0; sop[1].sem_op = 1;	/* Lock */
		sopcnt = 2;
		sop[0].sem_flg = sop[1].sem_flg = SEM_UNDO | IPC_NOWAIT; /* Don't wait the first time thru */
		SEMOP(udi->semid, sop, sopcnt, status, NO_WAIT);
		if (-1 == status)			/* We couldn't get it in one shot -- see if we already have it */
		{
			save_errno = errno;
			holder_pid = semctl(udi->semid, 0, GETPID);
			if (holder_pid == process_id)
			{
				send_msg(VARLSTCNT(5) MAKE_MSG_INFO(ERR_CRITSEMFAIL), 2,
					DB_LEN_STR(reg),
					ERR_RNDWNSEMFAIL);
				REVERT;
				ENABLE_INTERRUPTS(INTRPT_IN_GDS_RUNDOWN);
				return;			/* Already in rundown for this region */
			}
			if (EAGAIN != save_errno)
			{
				assert(FALSE);
				rts_error(VARLSTCNT(9) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg),
					ERR_TEXT, 2, RTS_ERROR_TEXT("gds_rundown first semop/semctl"), save_errno);
			}
			/* Before attempting again in the blocking mode, see if the holding process is an online rollback.
			 * If so, it is likely we won't get the access control semaphore anytime soon. In that case, we
			 * are better off skipping rundown and continuing with sanity cleanup and exit.
			 */
			skip_database_rundown = (onln_rlbk_pid || csd->file_corrupt);
			if (!skip_database_rundown)
			{
				sop[0].sem_flg = sop[1].sem_flg = SEM_UNDO;	/* Try again - blocking this time */
				SEMOP(udi->semid, sop, 2, status, FORCED_WAIT);
				if (-1 == status)			/* We couldn't get it at all.. */
					rts_error(VARLSTCNT(5) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg), errno);
			}
		}
		udi->grabbed_access_sem = !skip_database_rundown;
	} /* else we we hold the access control semaphore and therefore have standalone access. We do not release it now - we
	   * release it later in mupip_exit_handler.c. Since we already hold the access control semaphore, we don't need the
	   * ftok semaphore and trying it could cause deadlock
	   */
	/* At this point we are guaranteed no one else is doing a db_init/rundown as we hold the access control semaphore */
	assert(csa->ref_cnt);	/* decrement private ref_cnt before shared ref_cnt decrement. */
	csa->ref_cnt--;		/* Currently journaling logic in gds_rundown() in VMS relies on this order to detect last writer */
	assert(!csa->ref_cnt);
	--csa->nl->ref_cnt;
	if (memcmp(csa->nl->now_running, gtm_release_name, gtm_release_name_len + 1))
	{	/* VERMISMATCH condition. Possible only if DSE */
		assert(dse_running);
		vermismatch = TRUE;
	} else
		vermismatch = FALSE;
	if (-1 == shmctl(udi->shmid, IPC_STAT, &shm_buf))
	{
		save_errno = errno;
		rts_error(VARLSTCNT(9) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg),
			ERR_TEXT, 2, RTS_ERROR_TEXT("gds_rundown shmctl"), save_errno);
	} else
		we_are_last_user =  (1 == shm_buf.shm_nattch) && !vermismatch;
	assert(!have_standalone_access || we_are_last_user || jgbl.onlnrlbk); /* recover => one user except ONLINE ROLLBACK */
	if (-1 == (semval = semctl(udi->semid, 1, GETVAL)))
		rts_error(VARLSTCNT(5) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg), errno);
	we_are_last_writer = (1 == semval) && (FALSE == reg->read_only) && !vermismatch;/* There's one writer left and I am it */
	assert(!we_are_last_writer || !skip_database_rundown);
	assert(!we_are_last_user || !skip_database_rundown);
	assert(!(have_standalone_access && !reg->read_only) || we_are_last_writer
			|| jgbl.onlnrlbk); /* recover + R/W region => one writer except ONLINE ROLLBACK */
	if (!have_standalone_access && (-1 == (ftok_semval = semctl(udi->ftok_semid, 1, GETVAL))))
		rts_error(VARLSTCNT(5) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg), errno);
	if (NULL != csa->ss_ctx)
		ss_destroy_context(csa->ss_ctx);
	/* SS_MULTI: If multiple snapshots are supported, then we have to run through each of the snapshots */
	assert(1 == MAX_SNAPSHOTS);
	ss_shm_ptr = (shm_snapshot_ptr_t)SS_GETSTARTPTR(csa);
	ss_pid = ss_shm_ptr->ss_info.ss_pid;
	is_cur_process_ss_initiator = (process_id == ss_pid);
	if (ss_pid && (is_cur_process_ss_initiator || we_are_last_user))
	{
		/* Try getting snapshot crit latch. If we don't get latch, we won't hang for eternity and will skip
		 * doing the orphaned snapshot cleanup. It will be cleaned up eventually either by subsequent MUPIP
		 * INTEG or by a MUPIP RUNDOWN.
		 */
		if (ss_get_lock_nowait(reg) && (ss_pid == ss_shm_ptr->ss_info.ss_pid)
			&& (is_cur_process_ss_initiator || !is_proc_alive(ss_pid, 0)))
		{
			ss_release(NULL);
			ss_release_lock(reg);
		}
	}
	/* If csa->nl->donotflush_dbjnl is set, it means mupip recover/rollback was interrupted and therefore we need not flush
	 * shared memory contents to disk as they might be in an inconsistent state. Moreover, any more flushing will only cause
	 * future rollback to undo more journal records (PBLKs). In this case, we will go ahead and remove shared memory (without
	 * flushing the contents) in this routine. A reissue of the recover/rollback command will restore the database to a
	 * consistent state.
	 */
	if (!csa->nl->donotflush_dbjnl && !reg->read_only && !vermismatch)
	{	/* If we had an orphaned block and were interrupted, set wc_blocked so we can invoke wcs_recover. Do it ONLY
		 * if there is NO concurrent online rollback running (as we need crit to set wc_blocked)
		 */
		if (csa->wbuf_dqd)
		{	/* If we had an orphaned block and were interrupted, mupip_exit_handler will invoke secshr_db_clnup which
			 * will clear this field and so we should never come to gds_rundown with a non-zero wbuf_dqd. The only
			 * exception is if we are recover/rollback in which case gds_rundown (from mur_close_files) is invoked
			 * BEFORE secshr_db_clnup in mur_close_files.
			 * Note: It is NOT possible for online rollback to reach here with wbuf_dqd being non-zero. This is because
			 * the moment we apply the first PBLK, we stop all interrupts and hence can never be interrupted in
			 * wcs_wtstart or wcs_get_space. Assert accordingly.
			 */
			assert(mupip_jnl_recover && !jgbl.onlnrlbk && !skip_database_rundown);
			if (!was_crit)
				grab_crit(reg);
			SET_TRACEABLE_VAR(csd->wc_blocked, TRUE);
			BG_TRACE_PRO_ANY(csa, wcb_gds_rundown);
                        send_msg(VARLSTCNT(8) ERR_WCBLOCKED, 6, LEN_AND_LIT("wcb_gds_rundown"),
                                process_id, &csa->ti->curr_tn, DB_LEN_STR(reg));
			csa->wbuf_dqd = 0;
			wcs_recover(reg);
			if (is_mm)
			{
				assert(FALSE);
				csd = csa->hdr;
			}
			BG_TRACE_PRO_ANY(csa, lost_block_recovery);
			if (!was_crit)
				rel_crit(reg);
		}
		if (JNL_ENABLED(csd) && IS_GTCM_GNP_SERVER_IMAGE)
			originator_prc_vec = NULL;
		/* If we are the last writing user, then everything must be flushed */
		if (we_are_last_writer)
		{	/* Time to flush out all of our buffers */
			if (is_mm)
			{
				if (csa->total_blks != csa->ti->total_blks)	/* do remap if file had been extended */
				{
					if (!was_crit)
						grab_crit(reg);
					wcs_mm_recover(reg);
					csd = csa->hdr;
					if (!was_crit)
						rel_crit(reg);
				}
				csa->nl->remove_shm = TRUE;
			}
			if (csd->wc_blocked && jgbl.onlnrlbk)
			{	/* if the last update done by online rollback was not committed in the normal code-path but was
				 * completed by secshr_db_clnup, wc_blocked will be set to TRUE. But, since online rollback never
				 * invokes grab_crit (since csa->hold_onto_crit is set to TRUE), wcs_recover is never invoked. This
				 * could result in the last update never getting flushed to the disk and if online rollback happened
				 * to be the last writer then the shared memory will be flushed and removed and the last update will
				 * be lost. So, force wcs_recover if we find ourselves in such a situation. But, wc_blocked is
				 * possible only if phase1 or phase2 errors are induced using white box test cases
				 */
				assert(WB_COMMIT_ERR_ENABLED);
				wcs_recover(reg);
			}
			/* Note WCSFLU_SYNC_EPOCH ensures the epoch is synced to the journal and indirectly
			 * also ensures that the db is fsynced. We don't want to use it in the calls to
			 * wcs_flu() from t_end() and tp_tend() since we can defer it to out-of-crit there.
			 * In this case, since we are running down, we don't have any such option.
			 */
			csa->nl->remove_shm = wcs_flu(WCSFLU_FLUSH_HDR | WCSFLU_WRITE_EPOCH | WCSFLU_SYNC_EPOCH);
			/* Since we_are_last_writer, we should be guaranteed that wcs_flu() did not change csd, (in
			 * case of MM for potential file extension), even if it did a grab_crit().  Therefore, make
			 * sure that's true.
			 */
			assert(csd == csa->hdr);
			assert(0 == memcmp(csd->label, GDS_LABEL, GDS_LABEL_SZ - 1));
		} else if (((cancelled_timer && (0 > csa->nl->wcs_timers)) || cancelled_dbsync_timer) && !skip_database_rundown)
		{	/* cancelled pending db or jnl flush timers - flush database and journal buffers to disk */
			if (!was_crit)
				grab_crit(reg);
			/* we need to sync the epoch as the fact that there is no active pending flush timer implies
			 * there will be noone else who will flush the dirty buffers and EPOCH to disk in a timely fashion
			 */
			wcs_flu(WCSFLU_FLUSH_HDR | WCSFLU_WRITE_EPOCH | WCSFLU_SYNC_EPOCH);
			if (!was_crit)
				rel_crit(reg);
			assert((dba_mm == cs_data->acc_meth) || (csd == cs_data));
			csd = cs_data;	/* In case this is MM and wcs_flu() remapped an extended database, reset csd */
		}
		/* Do rundown journal processing after buffer flushes since they require jnl to be open */
		if (JNL_ENABLED(csd))
		{	/* the following tp_change_reg() is not needed due to the assert csa == cs_addrs at the beginning
			 * of gds_rundown(), but just to be safe. To be removed by 2002!! --- nars -- 2001/04/25.
			 */
			tp_change_reg();	/* call this because jnl_ensure_open checks cs_addrs rather than gv_cur_region */
			jpc = csa->jnl;
			jbp = jpc->jnl_buff;
			if (jbp->fsync_in_prog_latch.u.parts.latch_pid == process_id)
                        {
                                assert(FALSE);
                                COMPSWAP_UNLOCK(&jbp->fsync_in_prog_latch, process_id, 0, LOCK_AVAILABLE, 0);
                        }
                        if (jbp->io_in_prog_latch.u.parts.latch_pid == process_id)
                        {
                                assert(FALSE);
                                COMPSWAP_UNLOCK(&jbp->io_in_prog_latch, process_id, 0, LOCK_AVAILABLE, 0);
                        }
			if ((((NOJNL != jpc->channel) && !JNL_FILE_SWITCHED(jpc))
				|| we_are_last_writer && (0 != csa->nl->jnl_file.u.inode)) && !skip_database_rundown)
			{	/* We need to close the journal file cleanly if we have the latest generation journal file open
				 *	or if we are the last writer and the journal file is open in shared memory (not necessarily
				 *	by ourselves e.g. the only process that opened the journal got shot abnormally)
				 * Note: we should not infer anything from the shared memory value of csa->nl->jnl_file.u.inode
				 * 	if we are not the last writer as it can be concurrently updated.
				 */
				if (!was_crit)
					grab_crit(reg);
				if (JNL_ENABLED(csd))
				{
					SET_GBL_JREC_TIME; /* jnl_ensure_open/jnl_put_jrt_pini/pfin/jnl_file_close all need it */
					/* Before writing to jnlfile, adjust jgbl.gbl_jrec_time if needed to maintain time order
					 * of jnl records. This needs to be done BEFORE the jnl_ensure_open as that could write
					 * journal records (if it decides to switch to a new journal file).
					 */
					ADJUST_GBL_JREC_TIME(jgbl, jbp);
					jnl_status = jnl_ensure_open();
					if (0 == jnl_status)
					{	/* If we_are_last_writer, we would have already done a wcs_flu() which would
						 * have written an epoch record and we are guaranteed no further updates
						 * since we are the last writer. So, just close the journal.
						 * Although we assert pini_addr should be non-zero for last_writer, we
						 * play it safe in PRO and write a PINI record if not written already.
						 */
						assert(!jbp->before_images || is_mm
								|| !we_are_last_writer || 0 != jpc->pini_addr);
						if (we_are_last_writer && 0 == jpc->pini_addr)
							jnl_put_jrt_pini(csa);
						if (0 != jpc->pini_addr)
							jnl_put_jrt_pfin(csa);
						/* If not the last writer and no pending flush timer left, do jnl flush now */
						if (!we_are_last_writer && (0 > csa->nl->wcs_timers))
						{
							if (SS_NORMAL == (jnl_status = jnl_flush(reg)))
							{
								assert(jbp->freeaddr == jbp->dskaddr);
								jnl_fsync(reg, jbp->dskaddr);
								assert(jbp->fsync_dskaddr == jbp->dskaddr);
							} else
							{
								send_msg(VARLSTCNT(9) ERR_JNLFLUSH, 2, JNL_LEN_STR(csd),
									ERR_TEXT, 2,
									RTS_ERROR_TEXT("Error with journal flush in gds_rundown"),
									jnl_status);
								assert(NOJNL == jpc->channel);/* jnl file lost has been triggered */
								/* In this routine, all code that follows from here on does not
								 * assume anything about the journaling characteristics of this
								 * database so it is safe to continue execution even though
								 * journaling got closed in the middle.
								 */
							}
						}
						jnl_file_close(reg, we_are_last_writer, FALSE);
					} else
						send_msg(VARLSTCNT(6) jnl_status, 4, JNL_LEN_STR(csd), DB_LEN_STR(reg));
				}
				if (!was_crit)
					rel_crit(reg);
			}
		}
		if (we_are_last_writer)			/* Flush the fileheader last and harden the file to disk */
		{
			if (!was_crit)
				grab_crit(reg);			/* To satisfy crit requirement in fileheader_sync() */
			memset(csd->machine_name, 0, MAX_MCNAMELEN); /* clear the machine_name field */
			if (!have_standalone_access && we_are_last_user)
			{	/* mupip_exit_handler will do this after mur_close_file */
				csd->semid = INVALID_SEMID;
				csd->shmid = INVALID_SHMID;
				csd->gt_sem_ctime.ctime = 0;
				csd->gt_shm_ctime.ctime = 0;
			}
			fileheader_sync(reg);
			if (!was_crit)
				rel_crit(reg);
			if (FALSE == is_mm)
			{
				if (-1 == fsync(udi->fd))		/* Sync it all */
				{
					rts_error(VARLSTCNT(9) ERR_DBFILERR, 2, DB_LEN_STR(reg),
						  ERR_TEXT, 2, RTS_ERROR_TEXT("Error during file sync at close"), errno);
				}
			} else
			{	/* Now do final MM file sync before exit */
#				if !defined(TARGETED_MSYNC) && !defined(NO_MSYNC)
				if (-1 == fsync(udi->fd))		/* Sync it all */
				{
					rts_error(VARLSTCNT(9) ERR_DBFILERR, 2, DB_LEN_STR(reg),
						  ERR_TEXT, 2, RTS_ERROR_TEXT("Error during file sync at close"), errno);
				}
#				else
				if (-1 == msync((caddr_t)csa->db_addrs[0], (size_t)(csa->db_addrs[1] - csa->db_addrs[0]), MS_SYNC))
				{
					rts_error(VARLSTCNT(9) ERR_DBFILERR, 2, DB_LEN_STR(reg),
						  ERR_TEXT, 2, RTS_ERROR_TEXT("Error during file msync at close"), errno);
				}
#				endif
			}
                }
	} /* end if (!reg->read_only && !csa->nl->donotflush_dbjnl) */
	/* We had cancelled all db timers at start of rundown. In case as part of rundown (wcs_flu above), we had started
	 * any timers, cancel them BEFORE setting reg->open to FALSE (assert in wcs_clean_dbsync relies on this).
	 */
	CANCEL_DB_TIMERS(reg, csa, cancelled_timer, cancelled_dbsync_timer);
	if (reg->read_only && we_are_last_user && !have_standalone_access)
	{	/* mupip_exit_handler will do this after mur_close_file */
		db_ipcs.semid = INVALID_SEMID;
		db_ipcs.shmid = INVALID_SHMID;
		db_ipcs.gt_sem_ctime = 0;
		db_ipcs.gt_shm_ctime = 0;
		db_ipcs.fn_len = reg->dyn.addr->fname_len;
		memcpy(db_ipcs.fn, reg->dyn.addr->fname, reg->dyn.addr->fname_len);
		db_ipcs.fn[reg->dyn.addr->fname_len] = 0;
 		/* request gtmsecshr to flush. read_only cannot flush itself */
		if (0 != send_mesg2gtmsecshr(FLUSH_DB_IPCS_INFO, 0, (char *)NULL, 0))
			rts_error(VARLSTCNT(8) ERR_DBFILERR, 2, DB_LEN_STR(reg),
				  ERR_TEXT, 2, RTS_ERROR_TEXT("gtmsecshr failed to update database file header"));
	}
	/* Done with file now, close it */
	CLOSEFILE_RESET(udi->fd, rc);	/* resets "udi->fd" to FD_INVALID */
	if (-1 == rc)
	{
		rts_error(VARLSTCNT(9) ERR_DBFILERR, 2, DB_LEN_STR(reg),
			  ERR_TEXT, 2, LEN_AND_LIT("Error during file close"), errno);
	}
	/* Unmap storage if mm mode but only the part that is not the fileheader (so shows up in dumps) */
	if (is_mm)
	{
		munmap_len = (sm_long_t)((csa->db_addrs[1] - csa->db_addrs[0]) - ROUND_UP(SIZEOF_FILE_HDR(csa->hdr),
											 MSYNC_ADDR_INCS));
		if (munmap_len > 0)
		{
			munmap((caddr_t)(csa->db_addrs[0] + ROUND_UP(SIZEOF_FILE_HDR(csa->hdr), MSYNC_ADDR_INCS)),
			       (size_t)(munmap_len));
#			ifdef DEBUG_DB64
			rel_mmseg((caddr_t)csa->db_addrs[0]);
#			endif
		}
	}
	/* If we had skipped flushing journal and database buffers due to a concurrent online rollback, increment the counter
	 * indicating that in the shared memory so that online rollback can report the # of such processes when it shuts down.
	 */
	if (skip_database_rundown) /* indicates flushing was skipped */
		csa->nl->dbrndwn_skip_cnt++;
	/* If we are online rollback, report the # of processes that skipped rundown because we were holding the access control
	 * semaphore
	 */
	if (jgbl.onlnrlbk && csa->nl->dbrndwn_skip_cnt)
	{
		send_msg(VARLSTCNT(3) ERR_RNDWNSKIPCNT, 1, csa->nl->dbrndwn_skip_cnt);
		csa->nl->dbrndwn_skip_cnt = 0;
	}
	/* Detach our shared memory while still under lock so reference counts will be correct for the next process to run down
	 * this region. In the process also get the remove_shm status from node_local before detaching.
	 * If csa->nl->donotflush_dbjnl is TRUE, it means we can safely remove shared memory without compromising data
	 * integrity as a reissue of recover will restore the database to a consistent state.
	 */
	remove_shm = !vermismatch && (csa->nl->remove_shm || csa->nl->donotflush_dbjnl);
	rel_crit(reg); /* Since we are about to detach from the shared memory, release crit and reset onln_rlbk_pid */
	if (jgbl.onlnrlbk)
	{	/* We are done with online rollback on this region Indicate to other processes by setting the onln_rlbk_pid to 0 */
		csa->hold_onto_crit = FALSE;
		csa->nl->onln_rlbk_pid = 0;
	}
	status = shmdt((caddr_t)csa->nl);
	csa->nl = NULL; /* dereferencing nl after detach is not right, so we set it to NULL so that we can test before dereference*/
	if (-1 == status)
		send_msg(VARLSTCNT(9) ERR_DBFILERR, 2, DB_LEN_STR(reg), ERR_TEXT, 2, LEN_AND_LIT("Error during shmdt"), errno);
	REMOVE_CSA_FROM_CSADDRSLIST(csa);	/* remove "csa" from list of open regions (cs_addrs_list) */
	reg->open = FALSE;
	/* If file is still not in good shape, die here and now before we get rid of our storage */
	assertpro(0 == csa->wbuf_dqd);
	ipc_deleted = FALSE;
	/* If we are the very last user, remove shared storage id and the semaphores */
	if (we_are_last_user)
	{	/* remove shared storage, only if last writer to rundown did a successful wcs_flu() */
		assert(!vermismatch);
		if (remove_shm)
		{
			ipc_deleted = TRUE;
			if (0 != shm_rmid(udi->shmid))
				rts_error(VARLSTCNT(8) ERR_DBFILERR, 2, DB_LEN_STR(reg),
					ERR_TEXT, 2, RTS_ERROR_TEXT("Unable to remove shared memory"));
		} else if (is_src_server || is_updproc)
		{
			gtm_putmsg(VARLSTCNT(6) ERR_DBRNDWNWRN, 4, DB_LEN_STR(reg), process_id, process_id);
			send_msg(VARLSTCNT(6) ERR_DBRNDWNWRN, 4, DB_LEN_STR(reg), process_id, process_id);
		} else
			send_msg(VARLSTCNT(6) ERR_DBRNDWNWRN, 4, DB_LEN_STR(reg), process_id, process_id);
		/* mupip recover/rollback don't release the semaphore here, but do it later in db_ipcs_reset (invoked from
		 * mur_close_files())
		 */
		if (!have_standalone_access)
		{
			if (0 != sem_rmid(udi->semid))
				rts_error(VARLSTCNT(8) ERR_DBFILERR, 2, DB_LEN_STR(reg),
					ERR_TEXT, 2, RTS_ERROR_TEXT("Unable to remove semaphore"));
			udi->grabbed_access_sem = FALSE;
		}
	} else
	{
		assert(!have_standalone_access || jgbl.onlnrlbk);
		if (!jgbl.onlnrlbk)
		{ 	/* If we were writing, get rid of our writer access count semaphore */
			if (!reg->read_only)
				if (0 != (save_errno = do_semop(udi->semid, 1, -1, SEM_UNDO)))
					rts_error(VARLSTCNT(9) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg),
						ERR_TEXT, 2, RTS_ERROR_TEXT("gds_rundown write semaphore release"), save_errno);
			/* Now remove the rundown lock */
			if (!skip_database_rundown)
			{	/* Do it only if we skipped getting the access control semaphore above */
				if (0 != (save_errno = do_semop(udi->semid, 0, -1, SEM_UNDO)))
					rts_error(VARLSTCNT(9) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg),
						ERR_TEXT, 2, RTS_ERROR_TEXT("gds_rundown rundown semaphore release"), save_errno);
				udi->grabbed_access_sem = FALSE;
			}
		} /* else access control semaphore will be released in db_ipcs_reset */
	}
	if (!have_standalone_access)
	{
		if (!ftok_sem_release(reg, !have_standalone_access, FALSE))
				rts_error(VARLSTCNT(4) ERR_DBFILERR, 2, DB_LEN_STR(reg));
		FTOK_TRACE(csa, csa->ti->curr_tn, ftok_ops_release, process_id);
	}
	ENABLE_INTERRUPTS(INTRPT_IN_GDS_RUNDOWN);
	if (!ipc_deleted)
	{
		GET_CUR_TIME;
		if (is_src_server)
			gtm_putmsg(VARLSTCNT(8) ERR_IPCNOTDEL, 6, CTIME_BEFORE_NL, time_ptr,
				LEN_AND_LIT("Source server"), REG_LEN_STR(reg));
		if (is_updproc)
			gtm_putmsg(VARLSTCNT(8) ERR_IPCNOTDEL, 6, CTIME_BEFORE_NL, time_ptr,
				LEN_AND_LIT("Update process"), REG_LEN_STR(reg));
		if (mupip_jnl_recover && (!jgbl.onlnrlbk || !we_are_last_user))
		{
			gtm_putmsg(VARLSTCNT(8) ERR_IPCNOTDEL, 6, CTIME_BEFORE_NL, time_ptr,
				LEN_AND_LIT("Mupip journal process"), REG_LEN_STR(reg));
			send_msg(VARLSTCNT(8) ERR_IPCNOTDEL, 6, CTIME_BEFORE_NL, time_ptr,
				LEN_AND_LIT("Mupip journal process"), REG_LEN_STR(reg));
		}
	}
	REVERT;
}
static
int
copy_file(
    const char *file,
    const char *copy)
{
    int fd1, fd2, retval;
    char *buf;
    struct stat info;
    kern_return_t ret;

    fd1 = open(file, O_RDONLY, 0666);
    if (fd1 < 0) {
        perror("open");
        return -1;
    }
    if (fstat(fd1, &info) < 0) {
        perror("fstat");
        return -1;
    }
    if (info.st_size < 0 || (info.st_mode & S_IFMT) != S_IFREG) {
        return -1;
    }
    if ((ret = map_fd(fd1, 0, (vm_offset_t *)&buf, TRUE, info.st_size)) !=
	KERN_SUCCESS) {
        mach_error("map_fd", ret);
        return -1;
    }
    fd2 = open(copy, O_WRONLY | O_CREAT, 0666);
    if (fd2 < 0) {
        perror("open");
        return -1;
    }
    retval = write(fd2, buf, info.st_size);
    if (retval < 0) {
        perror("write");
        return retval;
    }
    retval = fsync(fd2);
    if (retval < 0) {
        perror("fsync");
        return retval;
    }
    retval = close(fd2);
    if (retval < 0) {
        perror("close");
        return retval;
    }
    retval = close(fd1);
    if (retval < 0) {
        perror("close");
        return retval;
    }
    ret = vm_deallocate(mach_task_self(), (vm_offset_t)buf,
			(vm_size_t)info.st_size);
    if (ret != KERN_SUCCESS) {
        mach_error("vm_deallocate", ret);
        return ret;
    }
    return 0;
}
Exemplo n.º 8
0
static void dotest(int testers, int me, int fd)
{
	char *bits, *hold_bits;
	char val;
	int count, collide, chunk, whenmisc, xfr, i;

	/* Stuff for the readv call */
	struct	iovec	r_iovec[MAXIOVCNT];
	int	r_ioveclen;

	/* Stuff for the writev call */
	struct	iovec	val_iovec[MAXIOVCNT];

	struct	iovec	zero_iovec[MAXIOVCNT];
	int	w_ioveclen;

	nchunks = max_size / csize;
	if ((bits = malloc((nchunks+7) / 8)) == NULL) {
		tst_resm(TBROK, "\tmalloc failed(bits)");
		tst_exit();
	}
	if ((hold_bits = malloc((nchunks+7) / 8)) == NULL) {
		tst_resm(TBROK, "\tmalloc failed(hlod_bits)");
		tst_exit();
	}

	/*Allocate memory for the iovec buffers and init the iovec arrays
	 */
	r_ioveclen = w_ioveclen = csize / MAXIOVCNT;

		/* Please note that the above statement implies that csize
		 * be evenly divisible by MAXIOVCNT.
		 */

	for (i = 0; i < MAXIOVCNT; i++) {
		if ((r_iovec[i].iov_base = calloc(r_ioveclen, 1)) == NULL) {
			tst_resm(TFAIL, "\tmalloc failed(r_iovec[i].iov_base)");
			tst_exit();
		}
		r_iovec[i].iov_len = r_ioveclen;

		/* Allocate unused memory areas between all the buffers to
		 * make things more diffult for the OS.
		 */

		if (malloc((i+1)*8) == NULL) {
			tst_resm(TBROK, "\tmalloc failed((i+1)*8)");
			tst_exit();
		}
		if ((val_iovec[i].iov_base = calloc(w_ioveclen, 1)) == NULL) {
			tst_resm(TBROK, "\tmalloc failed(val_iovec[i]");
			exit(1);
		}
		val_iovec[i].iov_len = w_ioveclen;
	
		if (malloc((i+1)*8) == NULL) {
			tst_resm(TBROK, "\tmalloc failed((i+1)*8)");
			tst_exit();
		}
		if ((zero_iovec[i].iov_base = calloc(w_ioveclen, 1)) == NULL) {
			tst_resm(TBROK, "\tmalloc failed(zero_iover)");
			tst_exit();
		}
		zero_iovec[i].iov_len = w_ioveclen;

		if (malloc((i+1)*8) == NULL) {
			tst_resm(TBROK, "\tmalloc failed((i+1)*8)");
			tst_exit();
		}
	}
	/*
	 * No init sectors; allow file to be sparse.
	 */
	val = (64/testers) * me + 1;

	/*
	 * For each iteration:
	 *	zap bits array
	 *	loop
	 *		pick random chunk, read it. 
	 *		if corresponding bit off {
	 *			verify = 0. (sparse file)
	 *			++count;
	 *		} else
	 *			verify = val.
	 *		write "val" on it.
	 *		repeat unitl count = nchunks.
	 *	++val.
         */

	 srand(getpid());
	 if (misc_intvl)
	 	whenmisc = NEXTMISC;

	 while (iterations-- > 0) {
		for (i = 0; i < NMISC; i++)
			misc_cnt[i] = 0;
		ftruncate(fd,0);
		file_max = 0;
		memset(bits, 0, (nchunks+7) / 8);
		memset(hold_bits, 0, (nchunks+7) / 8);

		/* Have to fill the val and zero iov buffers in a different manner
		 */
		for (i = 0; i < MAXIOVCNT; i++) {
			memset(val_iovec[i].iov_base,val,val_iovec[i].iov_len);
			memset(zero_iovec[i].iov_base,0,zero_iovec[i].iov_len);

		}
		count = 0;
		collide = 0;
		while (count < nchunks) {
			chunk = rand() % nchunks;
			/*
			 * Read it.
			 */
			if (lseek64(fd, CHUNK(chunk), 0) < 0) {
				tst_resm(TFAIL, "\tTest[%d]: lseek64(0) fail at %Lx, errno = %d.",
					me, CHUNK(chunk), errno);
				tst_exit();
			}
			if ((xfr = readv(fd, &r_iovec[0], MAXIOVCNT)) < 0) {
				tst_resm(TFAIL, "\tTest[%d]: readv fail at %Lx, errno = %d.",
					me, CHUNK(chunk), errno);
				tst_exit();
			}
			/*
			 * If chunk beyond EOF just write on it.
			 * Else if bit off, haven't seen it yet.
			 * Else, have.  Verify values.
			 */
			if (CHUNK(chunk) >= file_max) {
				bits[chunk/8] |= (1<<(chunk%8));
				++count;
			} else if ((bits[chunk/8] & (1<<(chunk%8))) == 0) {
				if (xfr != csize) {
					tst_resm(TFAIL, "\tTest[%d]: xfr=%d != %d, zero read.",
						me, xfr, csize);
					tst_exit();
				}
				for (i = 0; i < MAXIOVCNT; i++) {
					if (memcmp(r_iovec[i].iov_base, zero_iovec[i].iov_base, r_iovec[i].iov_len)) {
						tst_resm(TFAIL,
					  	"\tTest[%d] bad verify @ 0x%Lx for val %d count %d xfr %d file_max 0x%x, should be 0.",
							me, CHUNK(chunk), val, count, xfr, file_max);
						tst_resm(TINFO, "\tTest[%d]: last_trunc = 0x%x.",
							me, last_trunc);
						sync();
						ft_dumpiov(&r_iovec[i]);
						ft_dumpbits(bits, (nchunks+7)/8);
						ft_orbits(hold_bits, bits, (nchunks+7)/8);
						tst_resm(TINFO, "\tHold ");
						ft_dumpbits(hold_bits, (nchunks+7)/8);
						tst_exit();
					}
				}
				bits[chunk/8] |= (1<<(chunk%8));
				++count;
			} else {
				if (xfr != csize) {
					tst_resm(TFAIL, "\tTest[%d]: xfr=%d != %d, val read.",
						me, xfr, csize);
					tst_exit();
				}
				++collide;
				for (i = 0; i < MAXIOVCNT; i++) {
					if (memcmp(r_iovec[i].iov_base, val_iovec[i].iov_base, r_iovec[i].iov_len)) {
						tst_resm(TFAIL, "\tTest[%d] bad verify @ 0x%Lx for val %d count %d xfr %d file_max 0x%x.",
							me, CHUNK(chunk), val, count, xfr, file_max);
						tst_resm(TINFO, "\tTest[%d]: last_trunc = 0x%x.",
							me, last_trunc);
						sync();
						ft_dumpiov(&r_iovec[i]);
						ft_dumpbits(bits, (nchunks+7)/8);
						ft_orbits(hold_bits, bits, (nchunks+7)/8);
						tst_resm(TINFO, "\tHold ");
						ft_dumpbits(hold_bits, (nchunks+7)/8);
						tst_exit();
					}
				}
			}
			/*
			 * Writev it.
			 */
			if (lseek64(fd, -((off64_t)xfr), 1) <  0) {
				tst_resm(TFAIL, "\tTest[%d]: lseek64(1) fail at %Lx, errno = %d.",
					me, CHUNK(chunk), errno);
				tst_exit();
			}
			if ((xfr = writev(fd, &val_iovec[0], MAXIOVCNT)) < csize) {
				if (errno == ENOSPC) {
					tst_resm(TFAIL, "\tTest[%d]: no space, exiting.", me);
					fsync(fd);
					tst_exit();
				}
				tst_resm(TFAIL, "\tTest[%d]: writev fail at %Lx xfr %d, errno = %d.",
					me, CHUNK(chunk), xfr, errno);
				tst_exit();
			}
			if (CHUNK(chunk) + csize > file_max)
				file_max = CHUNK(chunk) + csize;
			/*
			 * If hit "misc" interval, do it.
			 */
			if (misc_intvl && --whenmisc <= 0) {
				ft_orbits(hold_bits, bits, (nchunks+7)/8);
				domisc(me, fd, bits);
				whenmisc = NEXTMISC;
			}
			if (count + collide > 2 * nchunks)
				break;
		}

		/*
		 * End of iteration, maybe before doing all chunks.
		 */
		fsync(fd);
		++misc_cnt[m_fsync];
		//tst_resm(TINFO, "\tTest{%d} val %d done, count = %d, collide = {%d}",
		//		me, val, count, collide);
		//for(i = 0; i < NMISC; i++)
		//	tst_resm(TINFO, "\t\tTest{%d}: {%d} %s's.", me, misc_cnt[i], m_str[i]);
		++val;
	}
}
Exemplo n.º 9
0
void
x_vpx_enc_run(unsigned char *pixels, int w, int h, int sock,
    struct sockaddr_in *cli)
{
  size_t len = 0;
  int p1x = 0;
  int p1y = 0;
  void *dat;
  vpx_codec_ctx_t _encoder;
  vpx_codec_ctx_t _decoder;
  vpx_image_t raw_yuv;
  const vpx_codec_cx_pkt_t *pkt;
  int frame_cnt = 0;
  int flags = 0;
  vpx_codec_iter_t iter;
  int outfd;
  int infd;
  int mem_fdmap;

  memset(&_encoder, 0, sizeof(_encoder));
  x_vpx_encoder_init(&_encoder, 1, w, h);

  memset(&_decoder, 0, sizeof(_decoder));
  x_vpx_decoder_init(&_decoder, 1);

  vpx_img_alloc(&raw_yuv, VPX_IMG_FMT_YV12, w, h, 0);
  memset(raw_yuv.planes[VPX_PLANE_Y], 0, raw_yuv.stride[VPX_PLANE_Y]
      * raw_yuv.d_h / 2);

  //  outfd = _P(open)("x_vp8_out.yuv",_P(O_CREAT) | _P(O_RDWR));
  infd = _P(open)("x_camera_in.yuv", _P(O_RDONLY));

  for (;;)
    {
#if 0
      raw_yuv.planes[VPX_PLANE_Y][p1y * w + p1x] = 0x0;
      p1x++;
      if (p1x > w)
        {
          p1x = 0;
          p1y++;
          if (p1y > h)
          p1y = 0;
        }
      raw_yuv.planes[VPX_PLANE_Y][p1y * w + p1x] = 0xff;
#endif
      //		int rbytes;
      //		int bufsiz = ycbcr[0].width*ycbcr[0].height
      //			+ ycbcr[1].width*ycbcr[1].height + ycbcr[2].width*ycbcr[2].height;

      /* read luminance */
      x_read(infd, raw_yuv.planes[VPX_PLANE_Y], raw_yuv.w * raw_yuv.h);
      /* read chroma U */
      x_read(infd, raw_yuv.planes[VPX_PLANE_U], (raw_yuv.w * raw_yuv.h) >> 2);
      /* read chroma V */
      x_read(infd, raw_yuv.planes[VPX_PLANE_V], (raw_yuv.w * raw_yuv.h) >> 2);

      //	x_vp8_write_frame(outfd,&raw_yuv);

      if (vpx_codec_encode(&_encoder, &raw_yuv, frame_cnt, 1, flags,
          VPX_DL_REALTIME ))
        {
          die_codec(&_encoder, "vpx_codec_enc_init()");
        }
      iter = NULL;
      while ((pkt = vpx_codec_get_cx_data(&_encoder, &iter)))
        {
          switch (pkt->kind)
            {
          case VPX_CODEC_CX_FRAME_PKT:
            // __decode_vp8_pkt(&_decoder, pkt->data.frame.buf, pkt->data.frame.sz, outfd);
            x_vp8_rtp_send((int) sock, (void *) pkt->data.frame.buf,
                (int) pkt->data.frame.sz, (struct sockaddr *) cli,
                (int) sizeof(*cli), seqno * 90);

            break;
          default:
            break;
            }
          x_write(1, (pkt->kind == VPX_CODEC_CX_FRAME_PKT)
              && (pkt->data.frame.flags & VPX_FRAME_IS_KEY) ? "K" : (pkt->kind
              == VPX_CODEC_CX_FRAME_PKT) && (pkt->data.frame.flags
              & VPX_FRAME_IS_INVISIBLE) ? "I" : (pkt->kind
              == VPX_CODEC_CX_FRAME_PKT) && (pkt->data.frame.flags
              & VPX_FRAME_IS_DROPPABLE) ? "D" : (pkt->kind
              == VPX_CODEC_CX_FRAME_PKT) && (pkt->data.frame.flags & 0x3) ? "B"
              : ".", 1);
#ifndef WIN32
          fsync(1);
#endif
        }
      frame_cnt++;
#ifdef WIN32
      Sleep(20);
#else
      usleep(56000);
#endif
    }
}
Exemplo n.º 10
0
void GenerateJson()
{
    char tmp[256];
    static char* buff = NULL;

    miniemc::EmcController* pCtrl = miniemc::EmcController::Instance();
    if( pCtrl->GetInitState() == miniemc::EmcController::lsLoaded )
    {
        if( !buff )
            buff = (char*) malloc(32768);
        strcpy(buff, "{\n \"positions\":[");
        /*
         * Append Positions
         */
        for(int i = 0; i <  pCtrl->GetAxisNumber(); i++)
        {
               char name = pCtrl->GetAxisName( i );
               sprintf(buff+strlen(buff), "%.4f", pCtrl->GetAxisPosition(name) );
               if( i != pCtrl->GetAxisNumber() -1 )
                        strcat(buff, ",");
        }
        /*
         * Append feedrate
         */

        strcat(buff, "],\n\"feed\":");
        sprintf( buff+ strlen(buff), "%.2f,\n", pCtrl->GetVelocity() );
        /*
         * Append Relative/Absolute position type
         */
         sprintf( buff+ strlen(buff), "\"pos_abs\":%s,\n", pCtrl->IsPositionAbsolute() ? "true" : "false" );
         /*
          * Append Limits overrided or not flag
          */
          sprintf( buff+ strlen(buff), "\"limit_over\":%s,\n", pCtrl->IsLimitsOverrided() ? "true" : "false" );
        // Active modal G-code
        memset(tmp, 0 , sizeof(tmp) );
        pCtrl->GetActiveCodes(tmp);
        sprintf( buff+ strlen(buff), "\"active_codes\": \"%s\",\n", tmp );
        //Current offsets
        //miniemc::Coord coord = pCtrl->GetCurrentOffset();
        miniemc::Coord coord = pCtrl->GetCurrentOrigin();
        sprintf( buff+ strlen(buff), "\"offsets\":[%.3f,%.3f,%.3f,%.3f,%.3f,%.3f],\n", coord.GetPosIndex(0),  coord.GetPosIndex(1),
                coord.GetPosIndex(2), coord.GetPosIndex(3), coord.GetPosIndex(4), coord.GetPosIndex(5) );
        //Controller state, see enum miniemc::EmcController::ecState
        sprintf( buff+ strlen(buff), "\"ctrl_state\":%d,\n", pCtrl->GetControllerState() );
        // Controller mode , see miniemc::EmcController::eCtlMode
        sprintf( buff+ strlen(buff), "\"ctrl_mode\":%d,\n", pCtrl->GetControllerMode() );
        // Interpretter state
        sprintf( buff+ strlen(buff), "\"interp_state\":%d,\n", pCtrl->GetInterpState() );
        // Is machine in position ?
        sprintf( buff+ strlen(buff), "\"inpos\":%s,\n", pCtrl->IsInpos() ? "true" : "false" );
        // Is spindle on ?
        sprintf( buff+ strlen(buff), "\"spindle_on\":%s,\n", pCtrl->IsSpindleOn() ? "true" : "false" );
        // Get infos
        if(pCtrl->GetErrorCount(miniemc::EmcController::elInfo) > 0 )
        {
            strcat(buff, "\"info\": [");
            while(pCtrl->GetErrorCount(miniemc::EmcController::elInfo))
            {
                sprintf( buff+ strlen(buff), "\"%s\"", pCtrl->GetNextError(miniemc::EmcController::elInfo).c_str() );
                if(pCtrl->GetErrorCount(miniemc::EmcController::elInfo) )
                {
                    strcat(buff, ",");
                }
            }
            strcat(buff, "],\n");
        }

         // Get warnings
        if(pCtrl->GetErrorCount(miniemc::EmcController::elWarning) > 0 )
        {
            strcat(buff, "\"warn\": [");
            while(pCtrl->GetErrorCount(miniemc::EmcController::elWarning))
            {
                sprintf( buff+ strlen(buff), "\"%s\"", pCtrl->GetNextError(miniemc::EmcController::elWarning).c_str() );
                if(pCtrl->GetErrorCount(miniemc::EmcController::elWarning) )
                {
                    strcat(buff, ",");
                }
            }
            strcat(buff, "],\n");
        }

         // Get errorss
        if(pCtrl->GetErrorCount(miniemc::EmcController::elError) > 0 )
        {
            strcat(buff, "\"errors\": [");
            while(pCtrl->GetErrorCount(miniemc::EmcController::elError))
            {
                sprintf( buff+ strlen(buff), "\"%s\"", pCtrl->GetNextError(miniemc::EmcController::elError).c_str() );
                if(pCtrl->GetErrorCount(miniemc::EmcController::elError) )
                {
                    strcat(buff, ",");
                }
            }
            strcat(buff, "],\n");
        }
        sprintf( buff+ strlen(buff), "\"last_program\":\"%s\",\n", pCtrl->GetLastFileName() );
        // Get num lines per context
        sprintf( buff+ strlen(buff), "\"context_size\":%d,\n", pCtrl->GetNumLinesPerContext() );
        // Get current context index
        sprintf( buff+ strlen(buff), "\"context_index\":%d,\n", pCtrl->GetActualContextIndex() );
        // Offset with actual context
        sprintf( buff+ strlen(buff), "\"context_offset\":%d,\n", pCtrl->GetCurrPosInContext() );
        // Context changed flag
        sprintf( buff+ strlen(buff), "\"context_changed\":%s\n", pCtrl->isContextChanged() ? "true" : "false" );
        strcat(buff, "}");

        /*
         * Write to disk
         */
        int fd = open("/tmp/emc_dynamic.json", O_WRONLY | O_TRUNC | O_SYNC | O_CREAT);
        if( fd >= 0)
        {
            write(fd, buff, strlen(buff));
            fsync(fd);
            close(fd);
        } else
        {
            fprintf(stderr, "can't open /tmp/emc_dynamic.json for write!");
        }
    }
}
Exemplo n.º 11
0
int fdatasync(int filedes) {
    return fsync(filedes);
}
/**************************************************************************
 * private functions
 **************************************************************************/
static int
_commitLocalBuffer(const char *iRODSPath, struct fuse_file_info *fi, lazyUploadFileInfo_t *lazyUploadFileInfo) {
    int status;
    int desc;
    char bufferPath[MAX_NAME_LEN];
    int descInx;

    status = _getBufferPath(iRODSPath, bufferPath);
    if(status < 0) {
        rodsLog (LOG_DEBUG, "_upload: failed to get Buffered lazy upload file path - %s", iRODSPath);
        return status;
    }

    // close local buffer file handle
    if(lazyUploadFileInfo->localHandle < 0) {
        rodsLog (LOG_DEBUG, "_commitLocalBuffer: wrong file descriptor - %s, %d", iRODSPath, lazyUploadFileInfo->localHandle);
        return -EBADF;
    }

    // no write but requested flush
    if(lazyUploadFileInfo->curOffset == 0) {
        return 0;
    }

    fsync(lazyUploadFileInfo->localHandle);
    close(lazyUploadFileInfo->localHandle);
    lazyUploadFileInfo->localHandle = -1;

    rodsLog (LOG_DEBUG, "_commitLocalBuffer: upload - %s", iRODSPath);
    
    if(lazyUploadFileInfo->commitCount == 0) {
        // put and reopen iRODS file
        dataObjInp_t dataObjInp;
        int fd;
        pathCache_t *tmpPathCache = NULL;
        iFuseConn_t *iFuseConn = NULL;
        iFuseDesc_t *desc = NULL;
        struct stat stbuf;
        char objPath[MAX_NAME_LEN];

        descInx = GET_IFUSE_DESC_INDEX(fi);

        rodsLog (LOG_DEBUG, "_commitLocalBuffer: closing existing iRODS file handle - %s - %d", iRODSPath, descInx);

        status = ifuseClose (&IFuseDesc[descInx]);
        if (status < 0) {
            int myError;
            if ((myError = getErrno (status)) > 0) {
                return (-myError);
            } else {
                return -ENOENT;
            }
        }

        // put
        rodsLog (LOG_DEBUG, "_commitLocalBuffer: uploading buffered file - %s", iRODSPath);

        status = _upload(iRODSPath);
        if(status != 0) {
            rodsLog (LOG_DEBUG, "_commitLocalBuffer: upload error - %s, %d", iRODSPath, status);
            return status;
        }

        // reopen file
        rodsLog (LOG_DEBUG, "_commitLocalBuffer: reopening iRODS file handle - %s", iRODSPath);

        memset (&dataObjInp, 0, sizeof (dataObjInp));
        //dataObjInp.openFlags = lazyUploadFileInfo->accmode;
        dataObjInp.openFlags = O_RDWR | O_APPEND;

        status = parseRodsPathStr ((char *) iRODSPath, LazyUploadRodsEnv, objPath);
        rstrcpy(dataObjInp.objPath, objPath, MAX_NAME_LEN);
        if (status < 0) {
            rodsLogError (LOG_ERROR, status, "_commitLocalBuffer: parseRodsPathStr of %s error", iRODSPath);
            /* use ENOTDIR for this type of error */
            return -ENOTDIR;
        }

        iFuseConn = getAndUseConnByPath((char *) iRODSPath, &status);
        /* status = getAndUseIFuseConn(&iFuseConn); */
        if(status < 0) {
            rodsLogError (LOG_ERROR, status, "_commitLocalBuffer: cannot get connection for %s error", iRODSPath);
            /* use ENOTDIR for this type of error */
            return -ENOTDIR;
        }

        status = _irodsGetattr (iFuseConn, iRODSPath, &stbuf);

        fd = rcDataObjOpen (iFuseConn->conn, &dataObjInp);
        unuseIFuseConn (iFuseConn);

        if (fd < 0) {
            rodsLogError (LOG_ERROR, status, "_commitLocalBuffer: rcDataObjOpen of %s error, status = %d", iRODSPath, fd);
            return -ENOENT;
        }

		fileCache_t *fileCache = addFileCache(fd, objPath, (char *) iRODSPath, NULL, stbuf.st_mode, stbuf.st_size, NO_FILE_CACHE);
        matchAndLockPathCache(pctable, (char *) iRODSPath, &tmpPathCache);
        if(tmpPathCache == NULL) {
            pathExist(pctable, (char *) iRODSPath, fileCache, &stbuf, NULL);
        } else {
			_addFileCacheForPath(tmpPathCache, fileCache);
            UNLOCK_STRUCT(*tmpPathCache);
        }

        desc = newIFuseDesc (objPath, (char *) iRODSPath, fileCache, &status);
        if (desc == NULL) {
            rodsLogError (LOG_ERROR, status, "_commitLocalBuffer: allocIFuseDesc of %s error", iRODSPath);
            return -ENOENT;
        }

        SET_IFUSE_DESC_INDEX(fi, desc->index);
        rodsLog (LOG_DEBUG, "_commitLocalBuffer: created new file handle - %s - %d", iRODSPath, desc->index);

    } else {
        // append
        int localDesc = open (bufferPath, O_RDONLY, 0755);
        char *buffer = (char*)malloc(FUSE_LAZY_UPLOAD_MEM_BUFFER_SIZE);
        int grandTotalReadLen = 0;

        if(localDesc < 0) {
            rodsLog (LOG_DEBUG, "_commitLocalBuffer: file descriptor error - %s, %d", iRODSPath, localDesc);
            return -ENOENT;
        }

        descInx = GET_IFUSE_DESC_INDEX(fi);

        if (checkFuseDesc (descInx) < 0) {
            return -EBADF;
        }

        status = 0;
        while(grandTotalReadLen < lazyUploadFileInfo->curOffset) {
            int totalReadLen = 0;
            int totalWriteLen = 0;

            while(totalReadLen < FUSE_LAZY_UPLOAD_MEM_BUFFER_SIZE) {
                int readLen = read(localDesc, buffer + totalReadLen, FUSE_LAZY_UPLOAD_MEM_BUFFER_SIZE - totalReadLen);
                if(readLen > 0) {
                    totalReadLen += readLen;
                } else if(readLen == 0) {
                    // EOF
                    break;
                } else if(readLen < 0) {
                    rodsLog (LOG_DEBUG, "_commitLocalBuffer: buffered file read error - %s, %d", iRODSPath, localDesc);
                    status = getErrno (readLen);
                    break;
                }
            }

            if(status >= 0) {
                while(totalWriteLen < totalReadLen) {
                    int writeLen = _ifuseWrite (&IFuseDesc[descInx], buffer + totalWriteLen, totalReadLen - totalWriteLen, lazyUploadFileInfo->curLocalOffsetStart + totalWriteLen);
                    if(writeLen > 0) {
                        totalWriteLen += writeLen;
                    } else if(writeLen == 0) {
                        // EOF
                        break;
                    } else if(writeLen < 0) {
                        rodsLog (LOG_DEBUG, "_commitLocalBuffer: iRODS file write error - %s", iRODSPath);
                        status = getErrno (writeLen);
                        break;
                    }
                }
            }

            grandTotalReadLen += totalReadLen;
        }

        unlockDesc (descInx);

        free(buffer);
        close(localDesc);
    }

    rodsLog (LOG_DEBUG, "_commitLocalBuffer: reset local buffered file - %s", iRODSPath);

    // reset local buffer file
    desc = open (bufferPath, O_RDWR|O_CREAT|O_TRUNC, 0755);
    lazyUploadFileInfo->localHandle = desc;
    lazyUploadFileInfo->commitCount++;
    lazyUploadFileInfo->curLocalOffsetStart += lazyUploadFileInfo->curOffset;
    lazyUploadFileInfo->curOffset = 0;
    return (0);
}
Exemplo n.º 13
0
static int handle_decrypt(int stdout_fd, const char *password)
{
    DIR *d;
    struct dirent *de;
    char buff[256];
    int res = -1;
    static const char *default_password = "******";

    if(cryptfs_check_footer() < 0)
    {
        ERROR("cryptfs_check_footer failed!");
        return -1;
    }

    int pwtype = cryptfs_get_password_type();
    if(pwtype < 0)
    {
        ERROR("cryptfs_get_password_type failed!");
        return -1;
    }
    else if (pwtype == CRYPT_TYPE_DEFAULT)
        password = default_password;

    if(password)
    {
        if(cryptfs_check_passwd(password) < 0)
        {
            ERROR("cryptfs_check_passwd failed!");
            return -1;
        }
    }
    else
    {
        switch(pw_ui_run(pwtype))
        {
            default:
            case ENCMNT_UIRES_ERROR:
                ERROR("pw_ui_run() failed!\n");
                return -1;
            case ENCMNT_UIRES_BOOT_INTERNAL:
                INFO("Wants to boot internal!\n");
                write(stdout_fd, ENCMNT_BOOT_INTERNAL_OUTPUT, strlen(ENCMNT_BOOT_INTERNAL_OUTPUT));
                fsync(stdout_fd);
                return 0;
            case ENCMNT_UIRES_BOOT_RECOVERY:
                INFO("Wants to boot recoveryl!\n");
                write(stdout_fd, ENCMNT_BOOT_RECOVERY_OUTPUT, strlen(ENCMNT_BOOT_RECOVERY_OUTPUT));
                fsync(stdout_fd);
                return 0;
            case ENCMNT_UIRES_PASS_OK:
                break;
        }
    }

    d = opendir("/dev/block/");
    if(!d)
    {
        ERROR("Failed to open /dev/block, wth? %s", strerror(errno));
        return -1;
    }

    // find the block device
    while((de = readdir(d)))
    {
        if(de->d_type == DT_BLK && strncmp(de->d_name, "dm-", 3) == 0)
        {
            snprintf(buff, sizeof(buff), "/dev/block/%s\n", de->d_name);
            INFO("Found block device %s\n", buff);
            write(stdout_fd, buff, strlen(buff));
            fsync(stdout_fd);
            res = 0;
            break;
        }
    }

    closedir(d);
    return res;
}
Exemplo n.º 14
0
static void file_flush( struct fd *fd, struct event **event )
{
    int unix_fd = get_unix_fd( fd );
    if (unix_fd != -1 && fsync( unix_fd ) == -1) file_set_error();
}
Exemplo n.º 15
0
static int GenerateTarget(FileContents* source_file,
                          const Value* source_patch_value,
                          FileContents* copy_file,
                          const Value* copy_patch_value,
                          const char* source_filename,
                          const char* target_filename,
                          const uint8_t target_sha1[SHA_DIGEST_SIZE],
                          size_t target_size,
                          const Value* bonus_data) {
    int retry = 1;
    SHA_CTX ctx;
    int output;
    MemorySinkInfo msi;
    FileContents* source_to_use;
    char* outname;
    int made_copy = 0;

    // assume that target_filename (eg "/system/app/Foo.apk") is located
    // on the same filesystem as its top-level directory ("/system").
    // We need something that exists for calling statfs().
    char target_fs[strlen(target_filename)+1];
    char* slash = strchr(target_filename+1, '/');
    if (slash != NULL) {
        int count = slash - target_filename;
        strncpy(target_fs, target_filename, count);
        target_fs[count] = '\0';
    } else {
        strcpy(target_fs, target_filename);
    }

    do {
        // Is there enough room in the target filesystem to hold the patched
        // file?

        if (strncmp(target_filename, "MTD:", 4) == 0 ||
            strncmp(target_filename, "EMMC:", 5) == 0) {
            // If the target is a partition, we're actually going to
            // write the output to /tmp and then copy it to the
            // partition.  statfs() always returns 0 blocks free for
            // /tmp, so instead we'll just assume that /tmp has enough
            // space to hold the file.

            // We still write the original source to cache, in case
            // the partition write is interrupted.
            if (source_patch_value != NULL) { //wschen 2013-05-24 must check the source is complete
            if (MakeFreeSpaceOnCache(source_file->size) < 0) {
                printf("not enough free space on /cache\n");
                return 1;
            }
            if (SaveFileContents(CACHE_TEMP_SOURCE, source_file) < 0) {
                printf("failed to back up source file\n");
                return 1;
            }
            }
            made_copy = 1;
            retry = 0;
        } else {
            int enough_space = 0;
            if (retry > 0) {
                size_t free_space = FreeSpaceForFile(target_fs);
                enough_space =
                    (free_space > (256 << 10)) &&          // 256k (two-block) minimum
                    (free_space > (target_size * 3 / 2));  // 50% margin of error
                if (!enough_space) {
                    printf("target %ld bytes; free space %ld bytes; retry %d; enough %d\n",
                           (long)target_size, (long)free_space, retry, enough_space);
                }
            }

            if (!enough_space) {
                retry = 0;
            }

            if (!enough_space && source_patch_value != NULL) {
                // Using the original source, but not enough free space.  First
                // copy the source file to cache, then delete it from the original
                // location.

                if (strncmp(source_filename, "MTD:", 4) == 0 ||
                    strncmp(source_filename, "EMMC:", 5) == 0) {
                    // It's impossible to free space on the target filesystem by
                    // deleting the source if the source is a partition.  If
                    // we're ever in a state where we need to do this, fail.
                    printf("not enough free space for target but source "
                           "is partition\n");
                    return 1;
                }

                if (MakeFreeSpaceOnCache(source_file->size) < 0) {
                    printf("not enough free space on /cache\n");
                    return 1;
                }

                if (SaveFileContents(CACHE_TEMP_SOURCE, source_file) < 0) {
                    printf("failed to back up source file\n");
                    return 1;
                }
                made_copy = 1;
                unlink(source_filename);

                size_t free_space = FreeSpaceForFile(target_fs);
                printf("(now %ld bytes free for target) ", (long)free_space);
            }

#if 1 //wschen 2013-05-24 still backup file to cache

            if (enough_space && (source_patch_value != NULL)) {
                if (strncmp(source_filename, "MTD:", 4) && strncmp(source_filename, "EMMC:", 5)) {
                    if (MakeFreeSpaceOnCache(source_file->size) == 0) {
                        if (SaveFileContents(CACHE_TEMP_SOURCE, source_file) == 0) {
                            made_copy = 1;
                        }
                    }
                }
            }
#endif
        }

        const Value* patch;
        if (source_patch_value != NULL) {
            source_to_use = source_file;
            patch = source_patch_value;
        } else {
            source_to_use = copy_file;
            patch = copy_patch_value;
        }

        if (patch->type != VAL_BLOB) {
            printf("patch is not a blob\n");
            return 1;
        }

#if 1 //wschen 2013-05-23

        if (patch->data == NULL) {
            printf("patch data is invalid\n");
            return 1;
        }
#endif

        SinkFn sink = NULL;
        void* token = NULL;
        output = -1;
        outname = NULL;
        if (strncmp(target_filename, "MTD:", 4) == 0 ||
            strncmp(target_filename, "EMMC:", 5) == 0) {
            // We store the decoded output in memory.
            msi.buffer = malloc(target_size);
            if (msi.buffer == NULL) {
                printf("failed to alloc %ld bytes for output\n",
                       (long)target_size);
                return 1;
            }
            msi.pos = 0;
            msi.size = target_size;
            sink = MemorySink;
            token = &msi;
        } else {
            // We write the decoded output to "<tgt-file>.patch".
            outname = (char*)malloc(strlen(target_filename) + 10);
            strcpy(outname, target_filename);
            strcat(outname, ".patch");

            output = open(outname, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC,
                S_IRUSR | S_IWUSR);
            if (output < 0) {
                printf("failed to open output file %s: %s\n",
                       outname, strerror(errno));
                return 1;
            }
            sink = FileSink;
            token = &output;
        }

        char* header = patch->data;
        ssize_t header_bytes_read = patch->size;

        SHA_init(&ctx);

        int result;

        if (header_bytes_read >= 8 &&
            memcmp(header, "BSDIFF40", 8) == 0) {
            result = ApplyBSDiffPatch(source_to_use->data, source_to_use->size,
                                      patch, 0, sink, token, &ctx);
        } else if (header_bytes_read >= 8 &&
                   memcmp(header, "IMGDIFF2", 8) == 0) {
            result = ApplyImagePatch(source_to_use->data, source_to_use->size,
                                     patch, sink, token, &ctx, bonus_data);
        } else {
            printf("Unknown patch file format\n");
            return 1;
        }

        if (output >= 0) {
            if (fsync(output) != 0) {
                printf("failed to fsync file \"%s\" (%s)\n", outname, strerror(errno));
                result = 1;
            }
            if (close(output) != 0) {
                printf("failed to close file \"%s\" (%s)\n", outname, strerror(errno));
                result = 1;
            }
        }

        if (result != 0) {
            if (retry == 0) {
                printf("applying patch failed\n");
                return result != 0;
            } else {
                printf("applying patch failed; retrying\n");
            }
            if (outname != NULL) {
                unlink(outname);
            }
        } else {
            // succeeded; no need to retry
            break;
        }
    } while (retry-- > 0);

    const uint8_t* current_target_sha1 = SHA_final(&ctx);
    if (memcmp(current_target_sha1, target_sha1, SHA_DIGEST_SIZE) != 0) {
        printf("patch did not produce expected sha1\n");
        return 1;
    } else {
        printf("now ");
        print_short_sha1(target_sha1);
        putchar('\n');
    }

    if (output < 0) {
        // Copy the temp file to the partition.
        if (WriteToPartition(msi.buffer, msi.pos, target_filename) != 0) {
            printf("write of patched data to %s failed\n", target_filename);
            return 1;
        }
        free(msi.buffer);
    } else {
        // Give the .patch file the same owner, group, and mode of the
        // original source file.
        if (chmod(outname, source_to_use->st.st_mode) != 0) {
            printf("chmod of \"%s\" failed: %s\n", outname, strerror(errno));
            return 1;
        }
        if (chown(outname, source_to_use->st.st_uid,
                  source_to_use->st.st_gid) != 0) {
            printf("chown of \"%s\" failed: %s\n", outname, strerror(errno));
            return 1;
        }

        // Finally, rename the .patch file to replace the target file.
        if (rename(outname, target_filename) != 0) {
            printf("rename of .patch to \"%s\" failed: %s\n",
                   target_filename, strerror(errno));
            return 1;
        }
    }

    // If this run of applypatch created the copy, and we're here, we
    // can delete it.
    if (made_copy) unlink(CACHE_TEMP_SOURCE);

#if 1 //wschen 2013-05-23
    sync();
#endif

    // Success!
    return 0;
}
Exemplo n.º 16
0
static void test_corruption(const char *filename, uint32_t write_chunk, uint32_t write_size, uint16_t flags)
{
	printf("Testing on %s with write_chunk=%u write_size=%u\n",
	       filename, (unsigned)write_chunk, (unsigned)write_size);

	uint32_t ofs = 0;
	int fd = open(filename, O_CREAT | O_RDWR | O_TRUNC, PX4_O_MODE_666);

	if (fd == -1) {
		perror(filename);
		exit(1);
	}

	// create a file of size write_size, in write_chunk blocks
	uint8_t counter = 0;

	while (ofs < write_size) {
		uint8_t buffer[write_chunk];

		for (uint16_t j = 0; j < write_chunk; j++) {
			buffer[j] = get_value(ofs);
			ofs++;
		}

		if (write(fd, buffer, sizeof(buffer)) != (int)sizeof(buffer)) {
			printf("write failed at offset %u\n", ofs);
			exit(1);
		}

		if (flags & FLAG_FSYNC) {
			fsync(fd);
		}

		if (counter % 100 == 0) {
			printf("write ofs=%u\r", ofs);
		}

		counter++;
	}

	close(fd);

	printf("write ofs=%u\n", ofs);

	// read and check
	fd = open(filename, O_RDONLY);

	if (fd == -1) {
		perror(filename);
		exit(1);
	}

	counter = 0;
	ofs = 0;

	while (ofs < write_size) {
		uint8_t buffer[write_chunk];

		if (counter % 100 == 0) {
			printf("read ofs=%u\r", ofs);
		}

		counter++;

		if (read(fd, buffer, sizeof(buffer)) != (int)sizeof(buffer)) {
			printf("read failed at offset %u\n", ofs);
			close(fd);
			return;
		}

		for (uint16_t j = 0; j < write_chunk; j++) {
			if (buffer[j] != get_value(ofs)) {
				printf("corruption at ofs=%u got %u\n", ofs, buffer[j]);
				close(fd);
				return;
			}

			ofs++;
		}

		if (flags & FLAG_LSEEK) {
			lseek(fd, 0, SEEK_CUR);
		}
	}

	printf("read ofs=%u\n", ofs);
	close(fd);
	unlink(filename);
	printf("All OK\n");
}
Exemplo n.º 17
0
    int main(int argc, char* argv[], char *envp[] ) {
        cout << "hello" << endl;

        FILE *f = fopen("/data/db/temptest", "a");

        if ( f == 0 ) {
            cout << "can't open file\n";
            return 1;
        }

        {
            Timer t;
            for ( int i = 0; i < 50000; i++ )
                fwrite("abc", 3, 1, f);
            cout << "small writes: " << t.millis() << "ms" << endl;
        }

        {
            Timer t;
            for ( int i = 0; i < 10000; i++ ) {
                fwrite("abc", 3, 1, f);
                fflush(f);
                fsync( fileno( f ) );
            }
            int ms = t.millis();
            cout << "flush: " << ms << "ms, " << ms / 10000.0 << "ms/request" << endl;
        }

        {
            Timer t;
            for ( int i = 0; i < 500; i++ ) {
                fwrite("abc", 3, 1, f);
                fflush(f);
                fsync( fileno( f ) );
                sleepmillis(2);
            }
            int ms = t.millis() - 500 * 2;
            cout << "flush with sleeps: " << ms << "ms, " << ms / 500.0 << "ms/request" << endl;
        }

        char buf[8192];
        for ( int pass = 0; pass < 2; pass++ ) {
            cout << "pass " << pass << endl;
            {
                Timer t;
                int n = 500;
                for ( int i = 0; i < n; i++ ) {
                    if ( pass == 0 )
                        fwrite("abc", 3, 1, f);
                    else
                        fwrite(buf, 8192, 1, f);
                    buf[0]++;
                    fflush(f);
                    fullsync(fileno(f));
                }
                int ms = t.millis();
                cout << "fullsync: " << ms << "ms, " << ms / ((double) n) << "ms/request" << endl;
            }

            {
                Timer t;
                for ( int i = 0; i < 500; i++ ) {
                    if ( pass == 0 )
                        fwrite("abc", 3, 1, f);
                    else
                        fwrite(buf, 8192, 1, f);
                    buf[0]++;
                    fflush(f);
                    fullsync(fileno(f));
                    sleepmillis(2);
                }
                int ms = t.millis() - 2 * 500;
                cout << "fullsync with sleeps: " << ms << "ms, " << ms / 500.0 << "ms/request" << endl;
            }
        }

        // without growing
        {
            fclose(f);
            /* try from beginning of the file, where we aren't appending and changing the file length,
               to see if this is faster as the directory entry then doesn't have to be flushed (if noatime in effect).
            */
            f = fopen("/data/db/temptest", "r+");
            Timer t;
            int n = 500;
            for ( int i = 0; i < n; i++ ) {
                fwrite("xyz", 3, 1, f);
                fflush(f);
                fullsync(fileno(f));
            }
            int ms = t.millis();
            cout << "fullsync without growing: " << ms << "ms, " << ms / ((double) n) << "ms/request" << endl;
        }

        // without growing, with delay
        {
            fclose(f);
            /* try from beginning of the file, where we aren't appending and changing the file length,
               to see if this is faster as the directory entry then doesn't have to be flushed (if noatime in effect).
            */
            f = fopen("/data/db/temptest", "r+");
            Timer t;
            int n = 500;
            for ( int i = 0; i < n; i++ ) {
                fwrite("xyz", 3, 1, f);
                fflush(f);
                fullsync(fileno(f));
                sleepmillis(2);
            }
            int ms = t.millis() - 2 * 500;
            cout << "fullsync without growing with sleeps: " << ms << "ms, " << ms / ((double) n) << "ms/request" << endl;
        }

        return 0;
    }
Exemplo n.º 18
0
static int trunk_binlog_merge_file(int old_fd)
{
	int result;
	int tmp_fd;
	int bytes;
	char binlog_filename[MAX_PATH_SIZE];
	char tmp_filename[MAX_PATH_SIZE];
	char buff[64 * 1024];

	get_trunk_binlog_filename(binlog_filename);
	sprintf(tmp_filename, "%s.tmp", binlog_filename);
	tmp_fd = open(tmp_filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
	if (tmp_fd < 0)
	{
		result = errno != 0 ? errno : EACCES;
		logError("file: "__FILE__", line: %d, " \
			"open file \"%s\" fail, " \
			"errno: %d, error info: %s", \
			__LINE__, tmp_filename, result, STRERROR(result));
		return result;
	}

	while ((bytes=fc_safe_read(old_fd, buff, sizeof(buff))) > 0)
	{
		if (fc_safe_write(tmp_fd, buff, bytes) != bytes)
		{
			result = errno != 0 ? errno : EACCES;
			logError("file: "__FILE__", line: %d, " \
				"write to file \"%s\" fail, " \
				"errno: %d, error info: %s", \
				__LINE__, tmp_filename,
				result, STRERROR(result));
			close(tmp_fd);
			return result;
		}
	}

	if (access(binlog_filename, F_OK) == 0)
	{
		int binlog_fd;
		if ((binlog_fd=trunk_binlog_open_read(binlog_filename,
			false)) < 0)
		{
			close(tmp_fd);
			return errno != 0 ? errno : EPERM;
		}

		while ((bytes=fc_safe_read(binlog_fd, buff, sizeof(buff))) > 0)
		{
			if (fc_safe_write(tmp_fd, buff, bytes) != bytes)
			{
				result = errno != 0 ? errno : EACCES;
				logError("file: "__FILE__", line: %d, " \
					"write to file \"%s\" fail, " \
					"errno: %d, error info: %s", \
					__LINE__, tmp_filename,
					result, STRERROR(result));
				close(tmp_fd);
				close(binlog_fd);
				return result;
			}
		}
		close(binlog_fd);
	}

	if (fsync(tmp_fd) != 0)
	{
		result = errno != 0 ? errno : EIO;
		logError("file: "__FILE__", line: %d, " \
			"sync file \"%s\" fail, " \
			"errno: %d, error info: %s",  \
			__LINE__, tmp_filename, \
			errno, STRERROR(errno));
		close(tmp_fd);
		return result;
	}
	close(tmp_fd);

	if (rename(tmp_filename, binlog_filename) != 0)
	{
		result = errno != 0 ? errno : EPERM;
		logError("file: "__FILE__", line: %d, " \
			"rename %s to %s fail, " \
			"errno: %d, error info: %s",
			__LINE__, tmp_filename, binlog_filename,
			result, STRERROR(result));
		return result;
	}

	return 0;
}
Exemplo n.º 19
0
bool TextBuffer::save (const QString &filename)
{
  // codec must be set!
  Q_ASSERT (m_textCodec);

  /**
   * construct correct filter device and try to open
   */
  QIODevice *file = KFilterDev::deviceForFile (filename, m_mimeTypeForFilterDev, false);
  if (!file->open (QIODevice::WriteOnly)) {
    delete file;
    return false;
  }

  /**
   * construct stream + disable Unicode headers
   */
  QTextStream stream (file);
  stream.setCodec (QTextCodec::codecForName("UTF-16"));

  // set the correct codec
  stream.setCodec (m_textCodec);

  // generate byte order mark?
  stream.setGenerateByteOrderMark (generateByteOrderMark());

  // our loved eol string ;)
  QString eol = "\n"; //m_doc->config()->eolString ();
  if (endOfLineMode() == eolDos)
    eol = QString ("\r\n");
  else if (endOfLineMode() == eolMac)
    eol = QString ("\r");

  // just dump the lines out ;)
  for (int i = 0; i < m_lines; ++i)
  {
    // get line to save
    Kate::TextLine textline = line (i);

    // strip trailing spaces
    if (m_removeTrailingSpaces)
    {
      int lastChar = textline->lastChar();
      if (lastChar > -1)
      {
        stream << textline->text().left (lastChar+1);
      }
    }
    else // simple, dump the line
      stream << textline->text();

    // append correct end of line string
    if ((i+1) < m_lines)
      stream << eol;
  }

  // flush stream
  stream.flush ();

  // close and delete file
  file->close ();
  delete file;

#ifndef Q_OS_WIN
  // ensure that the file is written to disk
  // we crete new qfile, as the above might be wrapper around compression
  QFile syncFile (filename);
  syncFile.open (QIODevice::ReadOnly);

#ifdef HAVE_FDATASYNC
  fdatasync (syncFile.handle());
#else
  fsync (syncFile.handle());
#endif
#endif

  // did save work?
  bool ok = stream.status() == QTextStream::Ok;

  // remember this revision as last saved if we had success!
  if (ok)
    m_history.setLastSavedRevision ();

  // report CODEC + ERRORS
  kDebug (13020) << "Saved file " << filename << "with codec" << m_textCodec->name()
    << (ok ? "without" : "with") << "errors";

  if (ok)
    markModifiedLinesAsSaved();

  // emit signal on success
  if (ok)
    emit saved (filename);

  // return success or not
  return ok;
}
Exemplo n.º 20
0
int
commonio_close(struct commonio_db *db)
{
	char buf[1024];
	int errors = 0;
	struct stat sb;

	if (!db->isopen) {
		errno = EINVAL;
		return 0;
	}
	db->isopen = 0;

	if (!db->changed || db->readonly) {
		fclose(db->fp);
		db->fp = NULL;
		goto success;
	}

	memzero(&sb, sizeof sb);
	if (db->fp) {
		if (fstat(fileno(db->fp), &sb)) {
			fclose(db->fp);
			db->fp = NULL;
			goto fail;
		}

		/*
		 * Create backup file.
		 */
		snprintf(buf, sizeof buf, "%s-", db->filename);

		if (create_backup(buf, db->fp))
			errors++;

		if (fclose(db->fp))
			errors++;

		if (errors) {
			db->fp = NULL;
			goto fail;
		}
	} else {
		/*
		 * Default permissions for new [g]shadow files.
		 * (passwd and group always exist...)
		 */
		sb.st_mode = 0400;
		sb.st_uid = 0;
		sb.st_gid = 0;
	}

	snprintf(buf, sizeof buf, "%s+", db->filename);

	db->fp = fopen_set_perms(buf, "w", &sb);
	if (!db->fp)
		goto fail;

	if (write_all(db))
		errors++;

	if (fflush(db->fp))
		errors++;
#ifdef HAVE_FSYNC
	if (fsync(fileno(db->fp)))
		errors++;
#else
	sync();
#endif
	if (fclose(db->fp))
		errors++;

	db->fp = NULL;

	if (errors) {
		unlink(buf);
		goto fail;
	}

	if (rename(buf, db->filename))
		goto fail;

	nscd_need_reload = 1;

success:
	free_linked_list(db);
	return 1;

fail:
	free_linked_list(db);
	return 0;
}
Exemplo n.º 21
0
/* Save mbox changes. */
int
fetch_mbox_save(struct account *a, struct fetch_mbox_mbox *fmbox)
{
	struct fetch_mbox_data	*data = a->data;
	struct fetch_mbox_mail	*aux, *this;
	char			 path[MAXPATHLEN], saved[MAXPATHLEN], c;
	int			 fd;
	ssize_t			 n;
	struct iovec		 iov[2];

	log_debug2("%s: %s: saving mbox: %u kept, %u total",
	    a->name, fmbox->path, fmbox->reference, fmbox->total);
	fd = -1;

	/*
	 * If the reference count is 0, no mails were kept, so the mbox can
	 * just be truncated.
	 */
	if (fmbox->reference == 0) {
		if (fmbox->total != 0 && ftruncate(fmbox->fd, 0) != 0)
			goto error;
		goto free_all;
	}

	/* If all the mails were kept, do nothing. */
	if (fmbox->reference == fmbox->total)
		goto free_all;

	/*
	 * Otherwise, things get complicated. data->kept is a list of all the
	 * mails (struct fetch_mbox_mail) which were kept for ALL mailboxes.
	 * There is no guarantee it is ordered by offset. Rather than try to be
	 * clever and save disk space, just create a new mbox and copy all the
	 * kept mails into it.
	 */
	if (ppath(path, sizeof path, "%s.XXXXXXXXXX", fmbox->path) != 0)
		goto error;
	if (ppath(saved, sizeof saved, "%s.XXXXXXXXXX", fmbox->path) != 0)
		goto error;
	if ((fd = mkstemp(path)) == -1)
		goto error;

	aux = TAILQ_FIRST(&data->kept);
	while (aux != NULL) {
		this = aux;
		aux = TAILQ_NEXT(aux, entry);

		if (this->fmbox != fmbox)
			continue;

		log_debug2("%s: writing message from %zu, size %zu",
		    a->name, this->off, this->size);
		c = '\n';
		iov[0].iov_base = fmbox->base + this->off;
		iov[0].iov_len = this->size;
		iov[1].iov_base = &c;
		iov[1].iov_len = 1;
		if ((n = writev(fd, iov, 2)) < 0)
			goto error;
		if ((size_t) n != this->size + 1) {
			errno = EIO;
			goto error;
		}

		fetch_mbox_free(this);
		TAILQ_REMOVE(&data->kept, this, entry);
	}

	if (fsync(fd) != 0)
		goto error;
	close(fd);

	/*
	 * Do the replacement dance: create a backup copy of the mbox, remove
	 * the mbox, link in the temporary file, unlink the temporary file,
	 * then unlink the backup mbox. We don't try to recover if anything
	 * fails on the grounds that it could just make things worse, just
	 * die and let the user sort it out.
	 */
	if (link(fmbox->path, saved) != 0)
		goto error;
	if (unlink(fmbox->path) != 0)
		goto error;
	if (link(path, fmbox->path) != 0)
		goto error;
	if (unlink(path) != 0)
		goto error;
	if (unlink(saved) != 0)
		goto error;

free_all:
	aux = TAILQ_FIRST(&data->kept);
	while (aux != NULL) {
		this = aux;
		aux = TAILQ_NEXT(aux, entry);

		if (this->fmbox == fmbox)
			fetch_mbox_free(this);
	}

	if (fmbox->reference != 0)
		fatalx("dangling reference");

	return (0);

error:
	if (fd != -1) {
		close(fd);
		unlink(path);
	}
	log_warn("%s: %s", a->name, fmbox->path);
	return (-1);
}
Exemplo n.º 22
0
int
run_file_tests(char *testfile)
{
    int ret = -1;
    struct stat buf;

    assert(testfile);
    fprintf(stdout, "Testing creat");
    ret = creat(testfile, S_IRWXU);
    check_err(ret, "creat", 2);

    fprintf(stdout, "Testing close");
    ret = close(ret);
    check_err(ret, "close", 2);

    fprintf(stdout, "Testing open");
    ret = open(testfile, O_RDONLY);
    check_err(ret, "open", 2);

    fprintf(stdout, "Testing read");
    ret = read(0, NULL, 0);
    check_err(ret, "read", 2);

    fprintf(stdout, "Testing readv");
    ret = readv(0, NULL, 0);
    check_err(ret, "readv", 2);

    fprintf(stdout, "Testing pread");
    ret = pread(0, NULL, 0, 0);
    check_err(ret, "pread", 2);

    fprintf(stdout, "Testing write");
    ret = write(0, NULL, 0);
    check_err(ret, "write", 2);

    fprintf(stdout, "Testing writev");
    ret = writev(0, NULL, 0);
    check_err(ret, "writev", 2);

    fprintf(stdout, "Testing pwrite");
    ret = pwrite(0, NULL, 0, 0);
    check_err(ret, "pwrite", 2);

    fprintf(stdout, "Testing lseek");
    ret = lseek(0, 0, 0);
    check_err(ret, "lseek", 2);

    fprintf(stdout, "Testing dup");
    ret = dup(0);
    check_err(ret, "dup", 2);

    fprintf(stdout, "Testing dup2");
    ret = dup2(0, 0);
    check_err(ret, "dup2", 2);

    fprintf(stdout, "Testing fchmod");
    ret = fchmod(0, 0);
    check_err(ret, "fchmod", 2);

    fprintf(stdout, "Testing fchown");
    ret = fchown(0, 0, 0);
    check_err(ret, "fchown", 2);

    fprintf(stdout, "Testing fsync");
    ret = fsync(0);
    check_err(ret, "fsync", 2);

    fprintf(stdout, "Testing ftruncate");
    ret = ftruncate(0, 0);
    check_err(ret, "ftruncate", 1);

    fprintf(stdout, "Testing fstat");
    ret = fstat(0, &buf);
    check_err(ret, "fstat", 1);

    fprintf(stdout, "Testing sendfile");
    ret = sendfile(0, 0, NULL, 0);
    check_err(ret, "sendfile", 1);

    fprintf(stdout, "Testing fcntl");
    ret = fcntl(0, 0, NULL);
    check_err(ret, "fcntl", 2);

    fprintf(stdout, "Testing close");
    ret = close(ret);
    check_err(ret, "close", 2);

    fprintf(stdout, "Testing remove");
    ret = remove(testfile);
    check_err(ret, "remove", 2);

    return ret;
}
Exemplo n.º 23
0
axStatus axFile::flush () {
	int b = fsync( h_ );
	if( b != 0 ) return axStatus_Std::File_error;
	return 0;
}
Exemplo n.º 24
0
gboolean
crm_add_logfile(const char *filename)
{
    struct stat parent;
    int fd = 0, rc = 0;
    FILE *logfile = NULL;
    char *parent_dir = NULL;
    char *filename_cp;

    static gboolean have_logfile = FALSE;

    if (filename == NULL && have_logfile == FALSE) {
        filename = "/var/log/pacemaker.log";
    }

    if (filename == NULL) {
        return FALSE;           /* Nothing to do */
    }

    filename_cp = strdup(filename);

    /* Check the parent directory and attempt to open */
    parent_dir = dirname(filename_cp);
    rc = stat(parent_dir, &parent);

    if (rc != 0) {
        crm_err("Directory '%s' does not exist: logging to '%s' is disabled", parent_dir, filename);
        free(filename_cp);
        return FALSE;

    } else if (parent.st_uid == geteuid() && (parent.st_mode & (S_IRUSR | S_IWUSR))) {
        /* all good - user */
        logfile = fopen(filename, "a");

    } else if (parent.st_gid == getegid() && (parent.st_mode & S_IXGRP)) {
        /* all good - group */
        logfile = fopen(filename, "a");

    } else {
        crm_err
            ("We (uid=%u, gid=%u) do not have permission to access '%s': logging to '%s' is disabled",
             geteuid(), getegid(), parent_dir, filename);
        free(filename_cp);
        return FALSE;
    }
    free(filename_cp);
    filename_cp = NULL;

    /* Check/Set permissions if we're root */
    if (logfile && geteuid() == 0) {
        struct stat st;
        uid_t pcmk_uid = 0;
        gid_t pcmk_gid = 0;
        gboolean fix = FALSE;
        int logfd = fileno(logfile);

        rc = fstat(logfd, &st);
        if (rc < 0) {
            crm_perror(LOG_WARNING, "Cannot stat %s", filename);
            fclose(logfile);
            return FALSE;
        }

        crm_user_lookup(CRM_DAEMON_USER, &pcmk_uid, &pcmk_gid);
        if (st.st_gid != pcmk_gid) {
            /* Wrong group */
            fix = TRUE;
        } else if ((st.st_mode & S_IRWXG) != (S_IRGRP | S_IWGRP)) {
            /* Not read/writable by the correct group */
            fix = TRUE;
        }

        if (fix) {
            rc = fchown(logfd, pcmk_uid, pcmk_gid);
            if (rc < 0) {
                crm_warn("Cannot change the ownership of %s to user %s and gid %d",
                         filename, CRM_DAEMON_USER, pcmk_gid);
            }

            rc = fchmod(logfd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
            if (rc < 0) {
                crm_warn("Cannot change the mode of %s to rw-rw----", filename);
            }

            fprintf(logfile, "Set r/w permissions for uid=%d, gid=%d on %s\n",
                    pcmk_uid, pcmk_gid, filename);
            if (fflush(logfile) < 0 || fsync(logfd) < 0) {
                crm_err("Couldn't write out logfile: %s", filename);
            }
        }
    }
    if (logfile) {
        fclose(logfile);
    }

    /* Now open with libqb */
    fd = qb_log_file_open(filename);

    if (fd < 0) {
        crm_perror(LOG_WARNING, "Couldn't send additional logging to %s", filename);
        return FALSE;
    }

    crm_notice("Additional logging available in %s", filename);
    qb_log_ctl(fd, QB_LOG_CONF_ENABLED, QB_TRUE);

    /* Enable callsites */
    crm_update_callsites();
    have_logfile = TRUE;
    return TRUE;
}
Exemplo n.º 25
0
/**
 * \brief Measures the time to write once to a file.
 *
 * Only one process is active. It writes once to a file.
 *
 * Remark:<br>
 * With the <tt>O_DIRECT</tt> flag set, cache effects are minimized, because I/O
 * is done directly to/from user space buffers. The operation system's page
 * cache is bypassed. Under Linux 2.6 alignment to 512-byte boundaries is
 * required for buffer and file offset. Thus the following parameters should be
 * set in a SKaMPI input file:
 * - <tt>set_send_buffert_alignment (512)</tt>
 * - <tt>set_recv_buffert_alignment (512)</tt>
 * - <tt>switch_buffer_cycling_off ()</tt><br>
 *
 * <tt>O_DIRECT</tt> is only relevant if the POSIX-API is used for I/O.
 * 
 * For more information please refer to the <tt>open ()</tt> man pages.
 *
 * \param[in] size        size of memory buffer, i.e. number of <tt>MPI_BYTE</tt>s
 * \param[in] api         POSIX-API or MPI-API for I/O accesses
 * \param[in] create_flag write into existing file (FALSE) or create it (TRUE)
 * \param[in] directio_flag open file with <tt>O_DIRECT</tt> flag to minimize
 *                          cache effects
 *
 * \return    measured time 
 */
double measure_MPI_IO_write_file_once (int size, char *api, int create_flag, int directio_flag){
  double     start_time = 1.0, end_time = 0.0;
  int        open_flags;
  char       *error_string;
  
  if (get_measurement_rank () == 0){
    if (strcmp (api, POSIX_API) == 0){

      if (directio_flag != 0)
	open_flags = O_WRONLY | O_DIRECT;
      else
	open_flags = O_WRONLY;

      errno = 0;

      if (create_flag == 0){	/* open existing file */

	if ((io_fd = open (io_filename, open_flags)) < 0){
	  error_string = strerror (errno);
	  error_with_abort (errno,
			    "\nmeasure_MPI_IO_write_file_once (int %d, char * %s, int %d, int %d) failed."
			    "\nCannot open local file (write only mode)."
			    "\nError: %s\n",
			    size, api, create_flag, directio_flag, error_string);
	}
      }
      else {			/* open nonexisting file and create it */
	
	if ((io_fd = open (io_filename, open_flags|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0){
	  error_string = strerror (errno);
	  error_with_abort (errno,
			   "\nmeasure_MPI_IO_write_file_once (int %d, char * %s, int %d, int %d) failed."
			   "\nCannot open local file (write only mode)."
			   "\nError: %s\n",
			    size, api, create_flag, directio_flag, error_string);
	}
      }

      start_time = start_synchronization ();
      write (io_fd, get_send_buffer (), size);
      fsync (io_fd);
      end_time = MPI_Wtime ();

      close (io_fd);

    }
    else{ 			/* if strcmp (api, POSIX_API) != 0 */

      if (create_flag == 0){

	MPI_File_open (MPI_COMM_SELF, io_filename, MPI_MODE_WRONLY, MPI_INFO_NULL, &io_fh);
      }
      else{ 			/* if create_flag != 0*/

	MPI_File_open (MPI_COMM_SELF, io_filename, MPI_MODE_WRONLY|MPI_MODE_CREATE, MPI_INFO_NULL, &io_fh);
      }
      
      MPI_File_set_view (io_fh, (MPI_Offset)0, 
			MPI_BYTE, MPI_BYTE,
			"native", MPI_INFO_NULL);

      start_time = start_synchronization ();
      MPI_File_write (io_fh, get_send_buffer (), size, MPI_BYTE, MPI_STATUS_IGNORE);
      MPI_File_sync (io_fh);
      end_time = MPI_Wtime ();
      
      MPI_File_close (&io_fh);
    }
  }
  else if (get_measurement_rank () != 0) {
    start_synchronization ();
  }
  stop_synchronization ();

  if (get_measurement_rank () == 0)
    return end_time - start_time;
  else
    return -1.0;
}
  virtual int run(int checkpoint) override {
    int local_checkpoint = 0;

    //Open file foo
    const int fd_foo = open(foo_path.c_str(), O_RDWR);
    if (fd_foo < 0) {
      return -1;
    }

    // system("stat /mnt/snapshot/foo");


    /*-------------------Variant 1 ---------------------------*/
    //unaligned offset and size less than  a page
    //Fallocate from off 17000 of length 3000
    if(fallocate(fd_foo, FALLOC_FL_KEEP_SIZE ,17000, 3000) < 0){
      close(fd_foo);
      return -2;
    }

    //fsync file_foo
    int res = fsync(fd_foo);
    if (res < 0){
      close(fd_foo);
      return -3;
    }

    // Make a user checkpoint here. Checkpoint must be 1 beyond this point
    // Beyond this point, the effect of falloc must be visible
    if (Checkpoint() < 0){
      close(fd_foo);
      return -4;
    }
    local_checkpoint += 1;
    if (local_checkpoint == checkpoint) {
      return 0;
    }

    //Expected output if checkpoint = 1 : Size = 16K, blocks == 40  (32 + 8)
    // system("stat /mnt/snapshot/foo");



    /*-------------------Variant 2 ---------------------------*/
    //aligned offset and size less than  a page
    //Fallocate from off 24K of length 3000
    if(fallocate(fd_foo, FALLOC_FL_KEEP_SIZE ,24576, 3000) < 0){
      close(fd_foo);
      return -2;
    }

    //fsync file_foo
    res = fsync(fd_foo);
    if (res < 0){
      close(fd_foo);
      return -3;
    }

    // Make a user checkpoint here. Checkpoint must be 2 beyond this point
    // Beyond this point, the effect of falloc must be visible
    if (Checkpoint() < 0){
      close(fd_foo);
      return -4;
    }
    local_checkpoint += 1;
    if (local_checkpoint == checkpoint) {
      return 0;
    }
    //Expected output if checkpoint = 2: size = 16K, blocks == 48 (40 + 8)
    // system("stat /mnt/snapshot/foo");


    /*-------------------Variant 3 ---------------------------*/
    //Aligned offset and size > a page
    //Fallocate from off 32K of length 8192
    if(fallocate(fd_foo, FALLOC_FL_KEEP_SIZE , 32768, 8192) < 0){
      close(fd_foo);
      return -2;
    }

    //fsync file_foo
    res = fsync(fd_foo);
    if (res < 0){
      close(fd_foo);
      return -3;
    }
    // Make a user checkpoint here. Checkpoint must be 3 beyond this point
    // Beyond this point, the effect of falloc must be visible
    if (Checkpoint() < 0){
      close(fd_foo);
      return -4;
    }
    local_checkpoint += 1;
    if (local_checkpoint == checkpoint) {
      return 0;
    }
    //Expected output if checkpoint = 3: size = 16K, blocks == 64 (48 + 16)
    // system("stat /mnt/snapshot/foo");


    /*-------------------Variant 4 ---------------------------*/
    //unaligned offset and size less than  a page
    //Fzero from off 42000 of length 3000
    if(fallocate(fd_foo, FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE ,42000, 3000) < 0){
      close(fd_foo);
      return -2;
    }

    //fsync file_foo
    res = fsync(fd_foo);
    if (res < 0){
      close(fd_foo);
      return -3;
    }

    // Make a user checkpoint here. Checkpoint must be 4 beyond this point
    // Beyond this point, the effect of falloc must be visible
    if (Checkpoint() < 0){
      close(fd_foo);
      return -4;
    }
    local_checkpoint += 1;
    if (local_checkpoint == checkpoint) {
      return 0;
    }
    //Expected output if checkpoint = 4 : Size = 16K, blocks == 72  (64 + 8)
    // system("stat /mnt/snapshot/foo");



    /*-------------------Variant 5 ---------------------------*/
    //aligned offset and size less than  a page
    //Fzero from off 48K of length 3000
    if(fallocate(fd_foo, FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE ,49152, 3000) < 0){
      close(fd_foo);
      return -2;
    }

    //fsync file_foo
    res = fsync(fd_foo);
    if (res < 0){
      close(fd_foo);
      return -3;
    }

    // Make a user checkpoint here. Checkpoint must be 5 beyond this point
    // Beyond this point, the effect of falloc must be visible
    if (Checkpoint() < 0){
      close(fd_foo);
      return -4;
    }
    local_checkpoint += 1;
    if (local_checkpoint == checkpoint) {
      return 0;
    }
    //Expected output if checkpoint = 5: size = 16K, blocks == 80 (72 + 8)
    // system("stat /mnt/snapshot/foo");


    /*-------------------Variant 6 ---------------------------*/
    //Aligned offset and size > a page
    //Fzero from off 52K of length 8192
    if(fallocate(fd_foo, FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE , 53248, 8192) < 0){
      close(fd_foo);
      return -2;
    }

    //fsync file_foo
    res = fsync(fd_foo);
    if (res < 0){
      close(fd_foo);
      return -3;
    }

    // Make a user checkpoint here. Checkpoint must be 6 beyond this point
    // Beyond this point, the effect of falloc must be visible
    if (Checkpoint() < 0){
      close(fd_foo);
      return -4;
    }
    local_checkpoint += 1;
    if (local_checkpoint == checkpoint) {
      return 1;
    }
    //Expected output if checkpoint = 6: size = 16K, blocks == 96 (80 + 16)
    // system("stat /mnt/snapshot/foo");






    //Close open files  
    close(fd_foo);

    return 0;
  }
Exemplo n.º 27
0
int main(int argc, char *argv[]) {
  int fd,pos_io;
  char s[taille_bloc+1]; // +1 pour pouvoir ajouter le caractère '\0' de fin de chaine
  long nb_char=0;
  long taille_nombre;
  long nb_char_ecrits_total=0;
  long nb_char_lus_total=0;
  int i;
  long nb_nombre;
  int nb_max=100;
  char *device_name;
  char str_nombre[100];
  int retval;
  unsigned int taille;
  char rep='n';
  long nb_car_a_lire;
  int bad=0, nb_ecrits;

  

  if (argc != 2) {
    fprintf(stderr, "usage : %s <nom du dev>\n", argv[0]);
    return 1;
  }
  device_name = argv[1];
  printf("device name =%s\n", device_name);

  if ((fd = open(device_name,O_RDWR)) <0) {
    printf("Erreur à l'ouverture du device %s",device_name);
    exit(-1);
  } 
  printf("Ouverture de %s terminée\n",device_name);
  
  
  printf("Test taille\n");
  retval = ioctl(fd,BLKGETSIZE,&taille);
  if (retval !=0) 
    printf("Erreur dans le ioctl BLKGETSIZE, taille =%d\n",taille);
  else printf("Ioctl BLKGETSIZE, taille =%d\n",taille);
  
  
  printf("Test d'écriture et de lecture\nEntrez le nombre d'entier à écrire : ");
  scanf("%ld",&nb_nombre);
  printf("Voulez-vous un affichage de ce qui est écrit et de ce qui est relu ? (o/n) : ");
  scanf("\n%c",&rep);

  printf("\n");

  printf("Ecriture de la chaine 1 2 3 4 ... %ld sur %s\n",nb_nombre,device_name);

  pos_io=lseek(fd,0,SEEK_SET);
  
  for (i=1;i<=nb_nombre;i++) {
    taille_nombre=sprintf(str_nombre,"%ld ",i);
    nb_ecrits = write(fd,str_nombre,taille_nombre);
    if (nb_ecrits != taille_nombre) {
      fprintf(stderr,"erreur à l'écriture de '%s', return = %d\n", 
	      str_nombre,
	      nb_ecrits);
    }
    nb_char_ecrits_total+=taille_nombre;
    str_nombre[taille_nombre]='\0';
    if (rep=='o') printf("%s",str_nombre);
  }
  if (rep=='o') printf(".\n");

  printf("Ecriture terminée : %ld caractères écrits\n",nb_char_ecrits_total);

  printf("\n");
  printf("Test de lecture : par blocs de %ld caractères\n",taille_bloc);
  lseek(fd,0,SEEK_SET);
  for (i=0;i<nb_char_ecrits_total;i+=taille_bloc) {

    if (i+taille_bloc>nb_char_ecrits_total) 
      nb_car_a_lire=nb_char_ecrits_total-i;
    else nb_car_a_lire=taille_bloc;

    nb_char=read(fd,s,nb_car_a_lire); 
    nb_char_lus_total+=nb_char;
    s[nb_char]='\0';
    if (rep=='o') printf("%s",s);
  }
  if (rep=='o') printf(".\n");
  printf("Lecture terminée : %ld caractères lus\n",nb_char_lus_total);
 
  printf("\n");
  printf("fsync du fichier\n");
  retval = fsync(fd);
  if (retval == 0) 
    printf("fsync ok\n");
  else 
    fprintf(stderr, "erreur fsync\n");

  printf("\n");
  printf("Test de lecture : lecture des %ld entiers et vérif que chaque entier est correct\n",nb_nombre);
  lseek(fd,0,SEEK_SET);
  for (i=1;i<nb_nombre;i++) {
    taille_nombre=sprintf(str_nombre,"%ld ",i);
    nb_char=read(fd,s,taille_nombre);
    if (nb_char!=taille_nombre) {
      printf("Erreur dans la lecture du nombre %ld : "
	     "taille voulue = %ld, taille lue = %ld\n",
	     i,taille_nombre,nb_char);
      bad=1;
    }
    else {
      s[nb_char]='\0';
      str_nombre[nb_char]='\0';
      if (strcmp(s,str_nombre)!=0) {
	printf("Erreur dans la lecture du nombre %ld : "
	       "str voulue = <%s>, str obtenue = <%s>\n",
	       i,str_nombre,s);
	bad=1;
      }
    }
    if (bad) break;
  }
  
  printf("Lecture de contrôle terminée : ");
  if (bad == 0) printf("** SUCCES ! **\n");  else printf("** ECHEC ! **\n");

  printf("\n");

  printf("Fermeture du fichier\n");
  if (close(fd) !=0) {
    printf("Erreur détectée à la fermeture");
  }

  printf("Fin du programme\n");
  return(0);
}
Exemplo n.º 28
0
// Write a memory buffer to 'target' partition, a string of the form
// "MTD:<partition>[:...]" or "EMMC:<partition_device>:".  Return 0 on
// success.
int WriteToPartition(unsigned char* data, size_t len,
                        const char* target) {
    char* copy = strdup(target);
    const char* magic = strtok(copy, ":");

    enum PartitionType type;
    if (strcmp(magic, "MTD") == 0) {
        type = MTD;
    } else if (strcmp(magic, "EMMC") == 0) {
        type = EMMC;
    } else {
        printf("WriteToPartition called with bad target (%s)\n", target);
        return -1;
    }

    const char* partition = strtok(NULL, ":");

    if (partition == NULL) {
        printf("bad partition target name \"%s\"\n", target);
#if 1
        free(copy);
#endif
        return -1;

    }

    char *dev_path = get_partition_path(partition);
    partition = dev_path;

    switch (type) {
        case MTD:
            if (!mtd_partitions_scanned) {
                mtd_scan_partitions();
                mtd_partitions_scanned = 1;
            }

            const MtdPartition* mtd = mtd_find_partition_by_name(partition);
            if (mtd == NULL) {
                printf("mtd partition \"%s\" not found for writing\n",
                       partition);
#if 1
                free(copy);
                free(partition);
#endif
                return -1;
            }

            MtdWriteContext* ctx = mtd_write_partition(mtd);
            if (ctx == NULL) {
                printf("failed to init mtd partition \"%s\" for writing\n",
                       partition);
#if 1
                free(copy);
                free(partition);
#endif
                return -1;
            }

            size_t written = mtd_write_data(ctx, (char*)data, len);
            if (written != len) {
                printf("only wrote %zu of %zu bytes to MTD %s\n",
                       written, len, partition);
                mtd_write_close(ctx);
#if 1
                free(copy);
                free(partition);
#endif
                return -1;
            }

            if (mtd_erase_blocks(ctx, -1) < 0) {
                printf("error finishing mtd write of %s\n", partition);
                mtd_write_close(ctx);
#if 1
                free(copy);
                free(partition);
#endif
                return -1;
            }

            if (mtd_write_close(ctx)) {
                printf("error closing mtd write of %s\n", partition);
#if 1
                free(copy);
                free(partition);
#endif
                return -1;
            }
            break;

        case EMMC:
        {
            size_t start = 0;
            int success = 0;
            int fd = open(partition, O_RDWR | O_SYNC);
            if (fd < 0) {
                printf("failed to open %s: %s\n", partition, strerror(errno));
                return -1;
            }
            int attempt;

            for (attempt = 0; attempt < 2; ++attempt) {
                if (TEMP_FAILURE_RETRY(lseek(fd, start, SEEK_SET)) == -1) {
                    printf("failed seek on %s: %s\n",
                           partition, strerror(errno));
                    close(fd);
                    return -1;
                }
                while (start < len) {
                    size_t to_write = len - start;
                    if (to_write > 1<<20) to_write = 1<<20;

                    ssize_t written = TEMP_FAILURE_RETRY(write(fd, data+start, to_write));
                    if (written == -1) {
                        printf("failed write writing to %s: %s\n", partition, strerror(errno));
                        close(fd);
                        return -1;
                    }
                    start += written;
                }
                if (fsync(fd) != 0) {
                   printf("failed to sync to %s (%s)\n",
                          partition, strerror(errno));
                    close(fd);
                   return -1;
                }
                if (close(fd) != 0) {
                   printf("failed to close %s (%s)\n",
                          partition, strerror(errno));
                   return -1;
                }
                fd = open(partition, O_RDONLY);
                if (fd < 0) {
                   printf("failed to reopen %s for verify (%s)\n",
                          partition, strerror(errno));
                   return -1;
                }

                // drop caches so our subsequent verification read
                // won't just be reading the cache.
                sync();
                int dc = open("/proc/sys/vm/drop_caches", O_WRONLY);
                if (TEMP_FAILURE_RETRY(write(dc, "3\n", 2)) == -1) {
                    printf("write to /proc/sys/vm/drop_caches failed: %s\n", strerror(errno));
                } else {
                    printf("  caches dropped\n");
                }
                close(dc);
                sleep(1);

                // verify
                if (TEMP_FAILURE_RETRY(lseek(fd, 0, SEEK_SET)) == -1) {
                    printf("failed to seek back to beginning of %s: %s\n",
                           partition, strerror(errno));
                    close(fd);
                    return -1;
                }
                unsigned char buffer[4096];
                start = len;
                size_t p;
                for (p = 0; p < len; p += sizeof(buffer)) {
                    size_t to_read = len - p;
                    if (to_read > sizeof(buffer)) to_read = sizeof(buffer);

                    size_t so_far = 0;
                    while (so_far < to_read) {
                        ssize_t read_count =
                                TEMP_FAILURE_RETRY(read(fd, buffer+so_far, to_read-so_far));
                        if (read_count == -1) {
                            printf("verify read error %s at %zu: %s\n",
                                   partition, p, strerror(errno));
                            close(fd);
                            return -1;
                        }
                        if ((size_t)read_count < to_read) {
                            printf("short verify read %s at %zu: %zd %zu %s\n",
                                   partition, p, read_count, to_read, strerror(errno));
                        }
                        so_far += read_count;
                    }

                    if (memcmp(buffer, data+p, to_read)) {
                        printf("verification failed starting at %zu\n", p);
                        start = p;
                        break;
                    }
                }

                if (start == len) {
                    printf("verification read succeeded (attempt %d)\n", attempt+1);
                    success = true;
                    break;
                }
            }

            if (!success) {
                printf("failed to verify after all attempts\n");
                close(fd);
                return -1;
            }

            if (close(fd) != 0) {
                printf("error closing %s (%s)\n", partition, strerror(errno));
                return -1;
            }
            sync();
            break;
        }
    }

    free(copy);
    return 0;
}
Exemplo n.º 29
0
void 
read_perf_test(unsigned long kilo64,long long reclen,long long *data1,long long *data2)
{
	double starttime2;
	double compute_val = (double)0;
	double readtime[2];
	double walltime[2], cputime[2];
	long long j;
	long long traj_size;
	unsigned long i,numrecs64,traj_offset;
	unsigned long lock_offset=0;
	long long Index = 0;
	unsigned long long readrate[2];
	unsigned long filebytes64;
	volatile char *buffer1;
	char *nbuff;
	int fd,open_flags;
	int test_foo,ltest;
	long wval;
	double qtime_start,qtime_stop;
	double hist_time;
	unsigned long r_traj_ops_completed=0;
	unsigned long r_traj_bytes_completed=0;
	long long *gc=0;
	char *filename = "/mnt/ramdisk/test1";
	size_t len = reclen;
	struct timespec start, end;
	long long time;

	hist_time=qtime_start=qtime_stop=0;
	traj_offset=0;
	test_foo=0;

	numrecs64 = (kilo64*1024)/reclen;

	open_flags = O_RDONLY;
	
	filebytes64 = numrecs64*reclen;
	fd = 0;

//	mainbuffer = (char *)malloc(4 * 1024 * 4096);

	/* 
	 * begin real testing
	 */
	ltest=3;
	printf("%s: filename %s, test %d, reclen %lld, numrecs64 %llu, filebytes64 %llu\n", __func__, filename, ltest, reclen, numrecs64, filebytes64);


//	fd = open(filename, open_flags,0640);

	for( j=0; j<ltest; j++ )
	{

//		lseek(fd,0,SEEK_SET);
		if((fd = open(filename, open_flags,0))<0)
		{
			printf("\nCan not open temporary file %s for read\n",filename);
			perror("open");
			exit(58);
		}

		printf("fd: %d, reclen %lu\n", fd, reclen);
		  fsync(fd);

		/* 
		 *  Need to prime the instruction cache & TLB
		 */
		nbuff=mainbuffer;
//		read(fd, (void *)nbuff, (size_t)reclen);
//		if(fetchon)
//			fetchit(nbuff,reclen);

		if(read(fd, (void *)nbuff, 4096) != reclen)
		{
#ifdef _64BIT_ARCH_
			printf("\nError reading block %d %llx\n", 0,
				(unsigned long long)nbuff);
#else
			printf("\nError reading block %d %lx\n", 0,
				(long)nbuff);
#endif
			perror("read");
			exit(60);
		}
		lseek(fd,0,SEEK_SET);

		nbuff=mainbuffer;

		starttime2 = time_so_far();

		compute_val=(double)0;
		r_traj_ops_completed=0;
		r_traj_bytes_completed=0;

		clock_gettime(CLOCK_MONOTONIC, &start);
		for(i=0; i<numrecs64; i++) 
		{
			    wval=read((int)fd, (void*)nbuff, 4096);
			    if(wval != reclen)
			    {
				printf("\nError reading block %lld %llx\n", i,
					(unsigned long long)nbuff);
				perror("read");
				exit(61);
			    }
		
		
			r_traj_ops_completed++;
			r_traj_bytes_completed+=reclen;
		}
		
		clock_gettime(CLOCK_MONOTONIC, &end);
		time = (end.tv_sec - start.tv_sec) * 1e9 + (end.tv_nsec - start.tv_nsec);
		printf("%lld ns\n", time);
		readtime[j] = ((time_so_far() - starttime2))-compute_val;
		if(readtime[j] < (double).000001) 
		{
			readtime[j]= (double)0.000001;
		}

		fsync(fd);
		close(fd);
	}

	filebytes64=r_traj_bytes_completed;
	printf("%s: completed %llu\n", __func__, filebytes64);

        for(j=0;j<ltest;j++)
        {
                  readrate[j] = 
                  (unsigned long long) ((double) filebytes64 / readtime[j]);
		  printf("%s: ltest %d readrate %llu\n", __func__, j, readrate[j]);
			
	}

}
Exemplo n.º 30
0
/// Synchronizes the file's data and status with the disk.
void fstream::sync (void)
{
    if (fsync (m_fd))
	set_and_throw (badbit | failbit, "sync");
}