Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 9383e745e23602bc45f9c92184feea59 > files > 94

gfs2-utils-0.1.62-28.el5.src.rpm

commit aa83b6f3b2606964e602bed3c6f467641f31891d
Author: Abhijith Das <adas@redhat.com>
Date:   Wed Mar 3 15:01:17 2010 -0600

    gfs2_quota: initialize fiemap flags and fix boundary conditions
    
    This patch initializes fiemap flags before calling
    the ioctl and also fixes gfs2_quota for some
    boundary conditions that prevent some quotas from
    being set/listed.
    
    rhbz#536902

diff --git a/gfs2/quota/check.c b/gfs2/quota/check.c
index f33aa17..59c287f 100644
--- a/gfs2/quota/check.c
+++ b/gfs2/quota/check.c
@@ -222,6 +222,7 @@ read_quota_file(struct gfs2_sbd *sdp, commandline_t *comline,
 	}
 	quota_file_size = statbuf.st_size;
 	/* First find the number of extents in the quota file */
+	fmap.fm_flags = 0;
 	fmap.fm_start = 0;
 	fmap.fm_length = (~0ULL);
 	error = ioctl(fd, FS_IOC_FIEMAP, &fmap);
@@ -235,6 +236,7 @@ read_quota_file(struct gfs2_sbd *sdp, commandline_t *comline,
 		fprintf(stderr, "malloc error (%d): %s\n", errno, strerror(errno));
 		goto out;
 	}
+	fmap2->fm_flags = 0;
 	fmap2->fm_start = 0;
 	fmap2->fm_length = (~0ULL);
 	fmap2->fm_extent_count = fmap.fm_mapped_extents;
@@ -264,6 +266,7 @@ read_quota_file(struct gfs2_sbd *sdp, commandline_t *comline,
 				}
 				gfs2_quota_in(&q, buf);
 				id = (offset / sizeof(struct gfs2_quota)) >> 1;
+				/* We want value in 512 byte blocks (1 << 9 = 512) */
 				q.qu_value <<= sdp->sd_sb.sb_bsize_shift - 9;
 
 				if (q.qu_value) {
@@ -274,7 +277,7 @@ read_quota_file(struct gfs2_sbd *sdp, commandline_t *comline,
 				}
 
 				offset += sizeof(struct gfs2_quota);
-			} while ((offset + sizeof(struct gfs2_quota)) < 
+			} while ((offset + sizeof(struct gfs2_quota)) <= 
 				 end);
 		}
 	}
diff --git a/gfs2/quota/main.c b/gfs2/quota/main.c
index e8b0fa2..36b6f2d 100644
--- a/gfs2/quota/main.c
+++ b/gfs2/quota/main.c
@@ -321,7 +321,7 @@ read_quota_internal(int fd, uint32_t id, int id_type, struct gfs2_quota *q)
 	if (error < 0)
 		die("failed to read from quota file: %s\n", strerror(errno));
 	if (error != sizeof(struct gfs2_quota))
-		die("Couldn't read %u bytes from quota file at offset %llu\n",
+		die("Couldn't read %lu bytes from quota file at offset %llu\n",
 		    sizeof(struct gfs2_quota), (unsigned long long)offset);
 	gfs2_quota_in(q, buf);
 }
@@ -360,8 +360,8 @@ do_reset(struct gfs2_sbd *sdp, commandline_t *comline)
 	if (!*comline->filesystem)
 		die("need a filesystem to work on\n");
 
-	printf("This operation will permanently erase all quota information. "
-	       "You will have to re-assign all quota limit/warn values. "
+	printf("This operation will permanently erase all quota information.\n"
+	       "You will have to re-assign all quota limit/warn values.\n"
 	       "Proceed [y/N]? ");
 	c = getchar();
 	if (c != 'y' && c != 'Y')
@@ -411,8 +411,9 @@ do_list(struct gfs2_sbd *sdp, commandline_t *comline)
 {
 	int fd;
 	struct gfs2_quota q;
-	uint32_t startid, endid;
-	int id_type;
+	char buf[sizeof(struct gfs2_quota)];
+	uint64_t offset;
+	uint32_t id, startid;
 	int pass = 0;
 	int error = 0;
 	char quota_file[BUF_SIZE];
@@ -447,6 +448,7 @@ do_list(struct gfs2_sbd *sdp, commandline_t *comline)
 	}
 	quota_file_size = statbuf.st_size;
 	/* First find the number of extents in the quota file */
+	fmap.fm_flags = 0;
 	fmap.fm_start = 0;
 	fmap.fm_length = (~0ULL);
 	error = ioctl(fd, FS_IOC_FIEMAP, &fmap);
@@ -460,6 +462,7 @@ do_list(struct gfs2_sbd *sdp, commandline_t *comline)
 		fprintf(stderr, "malloc error (%d): %s\n", errno, strerror(errno));
 		goto out;
 	}
+	fmap2->fm_flags = 0;
 	fmap2->fm_start = 0;
 	fmap2->fm_length = (~0ULL);
 	fmap2->fm_extent_count = fmap.fm_mapped_extents;
@@ -478,19 +481,26 @@ do_list(struct gfs2_sbd *sdp, commandline_t *comline)
 
 			end = end > quota_file_size ? quota_file_size : end;
 			startid = DIV_RU(fe->fe_logical, sizeof(struct gfs2_quota));
-			endid = end /(2 * sizeof(struct gfs2_quota));
 			if (startid % 2 != pass)
 				startid++;
-
-			startid = DIV_RU(startid, 2);
-			id_type = pass == 0 ? GQ_ID_USER : GQ_ID_GROUP;
+			offset = startid * sizeof(struct gfs2_quota);
 			do {
-				read_quota_internal(fd, startid, id_type, &q);
+				memset(buf, 0, sizeof(struct gfs2_quota));
+				/* read hidden quota file here */
+				lseek(fd, offset, SEEK_SET);
+				error = read(fd, buf, sizeof(struct gfs2_quota));
+				if (error < 0) {
+					fprintf(stderr, "read error (%d): %s\n",
+						errno, strerror(errno));
+					goto fmap2_free;
+				}
+				gfs2_quota_in(&q, buf);
+				id = (offset / sizeof(struct gfs2_quota)) >> 1;
 				if (q.qu_limit || q.qu_warn || q.qu_value)
-					print_quota(comline, (pass) ? FALSE : TRUE, startid,
+					print_quota(comline, (pass) ? FALSE : TRUE, id,
 						    &q, &sdp->sd_sb);
-				startid++;
-			} while (startid < endid);
+				offset += 2 * sizeof(struct gfs2_quota);
+			} while (offset < end);
 		}
 		if (!pass) {
 			pass = 1;
@@ -666,10 +676,10 @@ do_set(struct gfs2_sbd *sdp, commandline_t *comline)
 	int fd;
 	uint64_t offset;
 	uint64_t new_value;
-	int error;
 	char quota_file[BUF_SIZE];
 	char id_str[16];
 	struct stat stat_buf;
+	struct gfs2_quota q;
 	char *fs;
 	
 	if (!*comline->filesystem)
@@ -685,7 +695,7 @@ do_set(struct gfs2_sbd *sdp, commandline_t *comline)
 	strcpy(quota_file, sdp->metafs_path);
 	strcat(quota_file, "/quota");
 
-	fd = open(quota_file, O_WRONLY);
+	fd = open(quota_file, O_RDWR);
 	if (fd < 0) {
 		close(sdp->metafs_fd);
 		cleanup_metafs(sdp);
@@ -735,76 +745,22 @@ do_set(struct gfs2_sbd *sdp, commandline_t *comline)
 		goto out;
 	}
 
-	new_value = cpu_to_be64(new_value);
-	/*
-	 * Hack to force writing the entire gfs2_quota structure to 
-	 * the quota file instead of just the limit or warn values.
-	 * This is because of a bug in gfs2 which doesn't extend 
-	 * the quotafile appropriately to write the usage value of a 
-	 * given id. For instance, if you write a limit value (8 bytes) 
-	 * for userid x at offset 2*x, gfs2 will not extend the file and write 
-	 * 8 bytes at offset (2*x + 16) when it has to update the usage 
-	 * value for id x. Therefore, we extend the quota file to 
-	 * a struct gfs2_quota boundary. i.e. The size of the quota file
-	 * will always be a multiple of sizeof(struct gfs2_quota)
-	 */
+	memset(&q, 0, sizeof(struct gfs2_quota));
 	if (fstat(fd, &stat_buf)) {
 		fprintf(stderr, "stat failed: %s\n", strerror(errno));
 		goto out;
 	}
-	if (stat_buf.st_size < (offset + sizeof(struct gfs2_quota))) {
-		struct gfs2_quota tmp;
-		memset((void*)(&tmp), 0, sizeof(struct gfs2_quota));
-		switch (comline->operation) {
-		case GQ_OP_LIMIT:
-			tmp.qu_limit = new_value; break;
-		case GQ_OP_WARN:
-			tmp.qu_warn = new_value; break;
-		}
-		
-		lseek(fd, offset, SEEK_SET);
-		error = write(fd, (void*)(&tmp), sizeof(struct gfs2_quota));
-		if (error != sizeof(struct gfs2_quota)) {
-			fprintf(stderr, "can't write quota file (%d): %s\n", 
-				error, strerror(errno));
-			goto out;
-		}
-		/* Also, if the id type is USER, append another empty 
-		 * struct gfs2_quota for the GROUP with the same id
-		 */
-		if (comline->id_type == GQ_ID_USER) {
-			memset((void*)(&tmp), 0, sizeof(struct gfs2_quota));
-			error = write(fd, (void*)(&tmp), sizeof(struct gfs2_quota));
-			if (error != sizeof(struct gfs2_quota)) {
-				fprintf(stderr, "can't write quota file (%d): %s\n", 
-					error, strerror(errno));
-				goto out;
-			}
-		}
-	} else {
-		switch (comline->operation) {
-		case GQ_OP_LIMIT:
-			offset += (unsigned long)(&((struct gfs2_quota *) NULL)->qu_limit);
-			break;
-			
-		case GQ_OP_WARN:
-			offset += (unsigned long)(&((struct gfs2_quota *) NULL)->qu_warn);
-			break;
-			
-		default:
-			fprintf(stderr, "invalid operation\n");
-			goto out;
-		};
+	if (stat_buf.st_size >= (offset + sizeof(struct gfs2_quota)))
+		read_quota_internal(fd, comline->id, comline->id_type, &q);
 
-		lseek(fd, offset, SEEK_SET);
-		error = write(fd, (char*)&new_value, sizeof(uint64_t));
-		if (error != sizeof(uint64_t)) {
-			fprintf(stderr, "can't write quota file (%d): %s\n",
-				error, strerror(errno));
-			goto out;
-		}
+	switch (comline->operation) {
+	case GQ_OP_LIMIT:
+		q.qu_limit = new_value; break;
+	case GQ_OP_WARN:
+		q.qu_warn = new_value; break;
 	}
 
+	write_quota_internal(fd, comline->id, comline->id_type, &q);
 	fs = mp2fsname(comline->filesystem);
 	sprintf(id_str, "%d", comline->id);
 	set_sysfs(fs, comline->id_type == GQ_ID_USER ?