Whamcloud - gitweb
LU-787 clio: ftruncate shouldn't block when grouplock is hold
authorJohann Lombardi <johann@whamcloud.com>
Thu, 2 Feb 2012 13:21:22 +0000 (14:21 +0100)
committerOleg Drokin <green@whamcloud.com>
Thu, 29 Mar 2012 03:37:21 +0000 (23:37 -0400)
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 <johann@whamcloud.com>
Signed-off-by: Jacques-Charles Lafoucriere <jacques-charles.lafoucriere@cea.fr>
Change-Id: I81828cc63bb40586cc1155a58c00e3dab1100ec3
Reviewed-on: http://review.whamcloud.com/2081
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Jinshan Xiong <jinshan.xiong@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/liblustre.h
lustre/lclient/lcommon_cl.c
lustre/liblustre/llite_lib.h
lustre/llite/llite_internal.h
lustre/tests/multiop.c
lustre/tests/sanity.sh

index cac6320..b551641 100644 (file)
@@ -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;
index 95607a5..e767c02 100644 (file)
@@ -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);
index aaece89..9062bf9 100644 (file)
@@ -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)
 {
 }
index 4d35abe..1386bbe 100644 (file)
@@ -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);
index b42bfb8..7e0dbfe 100755 (executable)
@@ -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)
index d0cb980..205dd7e 100644 (file)
@@ -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