From: Johann Lombardi Date: Thu, 2 Feb 2012 13:21:22 +0000 (+0100) Subject: LU-787 clio: ftruncate shouldn't block when grouplock is hold X-Git-Tag: 2.2.51~37 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=1f0cf69eb0346e5c07a5383a1182e28fe0137925 LU-787 clio: ftruncate shouldn't block when grouplock is hold Pass the file descriptor used by ftruncate to the CLIO stack so that ccc_io_one_lock_index() can use the group lock when appropriate (i.e. when LL_FILE_GROUP_LOCKED is set). This patch also adds a regression test for this issue. Signed-off-by: Johann Lombardi Signed-off-by: Jacques-Charles Lafoucriere Change-Id: I81828cc63bb40586cc1155a58c00e3dab1100ec3 Reviewed-on: http://review.whamcloud.com/2081 Tested-by: Hudson Tested-by: Maloo Reviewed-by: Jinshan Xiong Reviewed-by: Oleg Drokin --- diff --git a/lustre/include/liblustre.h b/lustre/include/liblustre.h index cac6320..b551641 100644 --- a/lustre/include/liblustre.h +++ b/lustre/include/liblustre.h @@ -195,6 +195,7 @@ void cfs_get_random_bytes(void *ptr, int size); #define ATTR_BLOCKS 0x4000 #define ATTR_KILL_SUID 0 #define ATTR_KILL_SGID 0 +#define ATTR_FILE 0 struct iattr { unsigned int ia_valid; diff --git a/lustre/lclient/lcommon_cl.c b/lustre/lclient/lcommon_cl.c index 95607a5..e767c02 100644 --- a/lustre/lclient/lcommon_cl.c +++ b/lustre/lclient/lcommon_cl.c @@ -1033,10 +1033,18 @@ int cl_setattr_ost(struct inode *inode, const struct iattr *attr, io->u.ci_setattr.sa_valid = attr->ia_valid; io->u.ci_setattr.sa_capa = capa; - if (cl_io_init(env, io, CIT_SETATTR, io->ci_obj) == 0) + if (cl_io_init(env, io, CIT_SETATTR, io->ci_obj) == 0) { + struct ccc_io *cio = ccc_env_io(env); + + if (attr->ia_valid & ATTR_FILE) + /* populate the file descriptor for ftruncate to honor + * group lock - see LU-787 */ + cio->cui_fd = cl_iattr2fd(inode, attr); + result = cl_io_loop(env, io); - else + } else { result = io->ci_result; + } cl_io_fini(env, io); cl_env_put(env, &refcheck); RETURN(result); diff --git a/lustre/liblustre/llite_lib.h b/lustre/liblustre/llite_lib.h index aaece89..9062bf9 100644 --- a/lustre/liblustre/llite_lib.h +++ b/lustre/liblustre/llite_lib.h @@ -404,6 +404,12 @@ static inline struct slp_io *slp_env_io(const struct lu_env *env) #define cl_isize_write(inode,kms) do{llu_i2stat(inode)->st_size = kms;}while(0) #define cl_isize_write_nolock(inode,kms) cl_isize_write(inode,kms) +static inline struct ll_file_data *cl_iattr2fd(struct inode *inode, + const struct iattr *attr) +{ + return llu_i2info(inode)->lli_file_data; +} + static inline void cl_isize_lock(struct inode *inode, int lsmlock) { } diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 4d35abe..1386bbe 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -1347,6 +1347,13 @@ void ll_iocontrol_unregister(void *magic); #define cl_inode_mode(inode) ((inode)->i_mode) #define cl_i2sbi ll_i2sbi +static inline struct ll_file_data *cl_iattr2fd(struct inode *inode, + const struct iattr *attr) +{ + LASSERT(attr->ia_valid & ATTR_FILE); + return LUSTRE_FPRIVATE(attr->ia_file); +} + static inline void cl_isize_lock(struct inode *inode, int lsmlock) { ll_inode_size_lock(inode, lsmlock); diff --git a/lustre/tests/multiop.c b/lustre/tests/multiop.c index b42bfb8..7e0dbfe 100755 --- a/lustre/tests/multiop.c +++ b/lustre/tests/multiop.c @@ -68,6 +68,8 @@ char usage[] = " d mkdir\n" " D open(O_DIRECTORY)\n" " f statfs\n" +" G gid get grouplock\n" +" g gid put grouplock\n" " L link\n" " l symlink\n" " m mknod\n" @@ -194,6 +196,7 @@ int main(int argc, char **argv) int flags; int save_errno; int verbose = 0; + int gid = 0; if (argc < 3) { fprintf(stderr, usage, argv[0]); @@ -257,6 +260,22 @@ int main(int argc, char **argv) exit(save_errno); } break; + case 'G': + gid = atoi(commands+1); + if (ioctl(fd, LL_IOC_GROUP_LOCK, gid) == -1) { + save_errno = errno; + perror("ioctl(GROUP_LOCK)"); + exit(save_errno); + } + break; + case 'g': + gid = atoi(commands+1); + if (ioctl(fd, LL_IOC_GROUP_UNLOCK, gid) == -1) { + save_errno = errno; + perror("ioctl(GROUP_UNLOCK)"); + exit(save_errno); + } + break; case 'l': newfile = POP_ARG(); if (!newfile) diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index d0cb980..205dd7e 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -2061,6 +2061,25 @@ test_34g() { } run_test 34g "truncate long file ===============================" +test_34h() { + local gid=10 + local sz=1000 + + dd if=/dev/zero of=$DIR/$tfile bs=1M count=10 || error + multiop $DIR/$tfile OG${gid}T${sz}g${gid}c & + MULTIPID=$! + sleep 2 + + if [[ `ps h -o comm -p $MULTIPID` == "multiop" ]]; then + error "Multiop blocked on ftruncate, pid=$MULTIPID" + kill -9 $MULTIPID + fi + wait $MULTIPID + local nsz=`stat -c %s $DIR/$tfile` + [[ $nsz == $sz ]] || error "New size wrong $nsz != $sz" +} +run_test 34h "ftruncate file under grouplock should not block" + test_35a() { cp /bin/sh $DIR/f35a chmod 444 $DIR/f35a