In ll_file_io_generic() use the position returned in the kiocb to set
the returned file position. This ensures that the file position is set
correctly after an appending write. Add sanity test_23d() to check
that calling lseek() for the current offset returns the correct value
in this situation.
Lustre-change: https://review.whamcloud.com/32641
Signed-off-by: John L. Hammond <john.hammond@intel.com>
Change-Id: Ic76ce49db6e87d5294e18546d5b75a12793aa99c
Reviewed-on: https://review.whamcloud.com/32661
Reviewed-by: Jinshan Xiong <jinshan.xiong@gmail.com>
Tested-by: Jenkins
Reviewed-by: John L. Hammond <jhammond@whamcloud.com>
if (args->via_io_subtype == IO_NORMAL) {
iov_iter_advance(args->u.normal.via_iter, io->ci_nob);
if (args->via_io_subtype == IO_NORMAL) {
iov_iter_advance(args->u.normal.via_iter, io->ci_nob);
+
+ /* CLIO is too complicated. See LU-11069. */
+ if (cl_io_is_append(io))
+ pos = io->u.ci_rw.rw_iocb.ki_pos;
+ else
+ pos += io->ci_nob;
+
args->u.normal.via_iocb->ki_pos = pos;
#ifdef HAVE_KIOCB_KI_LEFT
args->u.normal.via_iocb->ki_left = count;
args->u.normal.via_iocb->ki_pos = pos;
#ifdef HAVE_KIOCB_KI_LEFT
args->u.normal.via_iocb->ki_left = count;
" N rename filename to path\n"
" o open(O_RDONLY)\n"
" O open(O_CREAT|O_RDWR)\n"
" N rename filename to path\n"
" o open(O_RDONLY)\n"
" O open(O_CREAT|O_RDWR)\n"
+" p print return value of last command\n"
" r[num] read [optional length]\n"
" R reference entire mmap-ed region\n"
" s stat\n"
" r[num] read [optional length]\n"
" R reference entire mmap-ed region\n"
" s stat\n"
" W write entire mmap-ed region\n"
" y fsync\n"
" Y fdatasync\n"
" W write entire mmap-ed region\n"
" y fsync\n"
" Y fdatasync\n"
-" z[num] seek [optional position, default 0]\n"
+" z[num] lseek(SEEK_SET) [optional offset, default 0]\n"
+" Z[num] lseek(SEEK_CUR) [optional offset, default 0]\n"
" _ wait for signal\n";
void usr1_handler(int unused)
" _ wait for signal\n";
void usr1_handler(int unused)
struct statfs stfs;
size_t mmap_len = 0, i;
unsigned char *mmap_ptr = NULL, junk = 0;
struct statfs stfs;
size_t mmap_len = 0, i;
unsigned char *mmap_ptr = NULL, junk = 0;
int flags;
int save_errno;
int verbose = 0;
int flags;
int save_errno;
int verbose = 0;
struct timespec ts;
struct lov_user_md_v3 lum;
__u64 dv;
struct timespec ts;
struct lov_user_md_v3 lum;
__u64 dv;
+ long long rc = 0;
+ long long last_rc;
if (argc < 3) {
fprintf(stderr, usage, argv[0]);
if (argc < 3) {
fprintf(stderr, usage, argv[0]);
fname = argv[1];
for (commands = argv[2]; *commands; commands++) {
fname = argv[1];
for (commands = argv[2]; *commands; commands++) {
+ /* XXX Most commands return 0 or we exit so we only
+ * update rc where really needed. */
+ last_rc = rc;
+ rc = 0;
+
switch (*commands) {
case '_':
if (verbose) {
switch (*commands) {
case '_':
if (verbose) {
- if (fgetxattr(fd, XATTR, NULL, 0) == -1) {
+ rc = fgetxattr(fd, XATTR, NULL, 0);
+ if (rc < 0) {
save_errno = errno;
perror("fgetxattr");
exit(save_errno);
save_errno = errno;
perror("fgetxattr");
exit(save_errno);
perror("create stripe file");
exit(save_errno);
}
perror("create stripe file");
exit(save_errno);
}
break;
case 'd':
if (mkdir(fname, 0755) == -1) {
break;
case 'd':
if (mkdir(fname, 0755) == -1) {
perror("open(O_DIRECTORY)");
exit(save_errno);
}
perror("open(O_DIRECTORY)");
exit(save_errno);
}
break;
case 'e':
commands++;
break;
case 'e':
commands++;
str = "read";
else if (rc == LL_LEASE_WRLCK)
str = "write";
str = "read";
else if (rc == LL_LEASE_WRLCK)
str = "write";
- fprintf(stdout, "%s lease(%d) released.\n",
+ fprintf(stdout, "%s lease(%lld) released.\n",
str, rc);
} else if (rc == 0) {
fprintf(stdout, "lease already broken.\n");
str, rc);
} else if (rc == 0) {
fprintf(stdout, "lease already broken.\n");
str = "read";
else if (rc == LL_LEASE_WRLCK)
str = "write";
str = "read";
else if (rc == LL_LEASE_WRLCK)
str = "write";
- fprintf(stdout, "%s lease(%d) has applied.\n",
+ fprintf(stdout, "%s lease(%lld) has applied.\n",
str, rc);
if (*commands == '-')
errx(-1, "expect lease to not exist");
str, rc);
if (*commands == '-')
errx(-1, "expect lease to not exist");
rc = llapi_fd2fid(fd, &fid);
if (rc != 0)
fprintf(stderr,
rc = llapi_fd2fid(fd, &fid);
if (rc != 0)
fprintf(stderr,
- "llapi_path/fd2fid() on %d, rc=%d\n",
+ "llapi_path/fd2fid() on %d, rc=%lld\n",
fd, rc);
else
printf(DFID"\n", PFID(&fid));
fd, rc);
else
printf(DFID"\n", PFID(&fid));
perror("create stripe file");
exit(save_errno);
}
perror("create stripe file");
exit(save_errno);
}
break;
case 'j':
if (flock(fd, LOCK_EX) == -1)
break;
case 'j':
if (flock(fd, LOCK_EX) == -1)
perror("open(O_RDWR|O_CREAT)");
exit(save_errno);
}
perror("open(O_RDWR|O_CREAT)");
exit(save_errno);
}
break;
case 'o':
len = get_flags(commands+1, &flags);
break;
case 'o':
len = get_flags(commands+1, &flags);
perror("open");
exit(save_errno);
}
perror("open");
exit(save_errno);
}
+ case 'p':
+ printf("%lld\n", last_rc);
+ break;
case 'r':
len = atoi(commands+1);
if (len <= 0)
case 'r':
len = atoi(commands+1);
if (len <= 0)
exit(save_errno);
}
if (rc < len) {
exit(save_errno);
}
if (rc < len) {
- fprintf(stderr, "short read: %u/%u\n",
+ fprintf(stderr, "short read: %lld/%u\n",
rc, len);
if (rc == 0)
exit(ENODATA);
}
len -= rc;
if (verbose >= 2)
rc, len);
if (rc == 0)
exit(ENODATA);
}
len -= rc;
if (verbose >= 2)
- printf("%.*s\n", rc, buf_align);
+ printf("%.*s\n", (int)rc, buf_align);
perror("llapi_create_volatile");
exit(fd);
}
perror("llapi_create_volatile");
exit(fd);
}
break;
case 'w':
len = atoi(commands+1);
break;
case 'w':
len = atoi(commands+1);
exit(save_errno);
}
if (rc < len)
exit(save_errno);
}
if (rc < len)
- fprintf(stderr, "short write: %u/%u\n",
+ fprintf(stderr, "short write: %lld/%u\n",
rc = llapi_get_data_version(fd, &dv, 0);
if (rc) {
fprintf(stderr, "cannot get file data version"
rc = llapi_get_data_version(fd, &dv, 0);
if (rc) {
fprintf(stderr, "cannot get file data version"
exit(-rc);
}
printf("dataversion is %ju\n", (uintmax_t)dv);
exit(-rc);
}
printf("dataversion is %ju\n", (uintmax_t)dv);
exit(save_errno);
}
break;
exit(save_errno);
}
break;
- case 'z':
- len = atoi(commands+1);
- if (lseek(fd, len, SEEK_SET) == -1) {
- save_errno = errno;
- perror("lseek");
- exit(save_errno);
- }
- break;
+ case 'z': {
+ off_t off;
+
+ len = atoi(commands + 1);
+ off = lseek(fd, len, SEEK_SET);
+ if (off == (off_t)-1) {
+ save_errno = errno;
+ perror("lseek");
+ exit(save_errno);
+ }
+
+ rc = off;
+ break;
+ }
+ case 'Z': {
+ off_t off;
+
+ len = atoi(commands + 1);
+ off = lseek(fd, len, SEEK_CUR);
+ if (off == (off_t)-1) {
+ save_errno = errno;
+ perror("lseek");
+ exit(save_errno);
+ }
+
+ rc = off;
+ break;
+ }
case '-':
case '0':
case '1':
case '-':
case '0':
case '1':
}
run_test 23b "O_APPEND check =========================="
}
run_test 23b "O_APPEND check =========================="
+# LU-11069 file offset is correct after appending writes
+test_23d() {
+ local file=$DIR/$tfile
+ local offset
+
+ echo CentaurHauls > $file
+ offset=$($MULTIOP $file oO_WRONLY:O_APPEND:w13Zp)
+ if ((offset != 26)); then
+ error "wrong offset, expected 26, got '$offset'"
+ fi
+}
+run_test 23d "file offset is correct after appending writes"
+
# rename sanity
test_24a() {
echo '-- same directory rename'
# rename sanity
test_24a() {
echo '-- same directory rename'