Whamcloud - gitweb
Branch b1_8
authorjohann <johann>
Thu, 12 Nov 2009 09:54:21 +0000 (09:54 +0000)
committerjohann <johann>
Thu, 12 Nov 2009 09:54:21 +0000 (09:54 +0000)
b=20892
i=shadow
i=yangsheng

Take inode semaphores instead of the bkl before calling vfs_rename.

lustre/ChangeLog
lustre/autoconf/lustre-core.m4
lustre/include/linux/lustre_compat25.h
lustre/mds/mds_fs.c
lustre/mds/mds_reint.c

index d4ead2c..bcb2892 100644 (file)
@@ -215,9 +215,15 @@ Severity   : normal
 Bugzilla   : 19128
 Description: Out or order replies might be lost on replay
 Details    : In ptlrpc_retain_replayable_request if we cannot find retained
-             request with tid smaller then one currently being added, add it
+            request with tid smaller then one currently being added, add it
             to the start, not end of the list.
 
+Severity   : major
+Bugzilla   : 20892
+Description: bad entry in directory xxx: inode out of bounds
+Details    : fix locking issue in the rename path which could race with any
+            other operations updating the same directory.
+
 -------------------------------------------------------------------------------
 2009-10-16 Sun Microsystems, Inc.
        * version 1.8.1.1
index d7fd26c..7c31a43 100644 (file)
@@ -1684,23 +1684,6 @@ LB_LINUX_TRY_COMPILE([
 ])
 ])
 
-# 2.6.17 super_block use s_vfs_rename_mutex instead of s_vfs_rename_sem
-AC_DEFUN([LC_VFS_RENAME_MUTEX],
-[AC_MSG_CHECKING([super_block has s_vfs_rename_mutex])
-LB_LINUX_TRY_COMPILE([
-        #include <linux/fs.h>
-],[
-        struct super_block sb;
-        mutex_lock(&sb.s_vfs_rename_mutex);
-],[
-        AC_DEFINE(HAVE_VFS_RENAME_MUTEX, 1,
-                [super_block has s_vfs_rename_mutex])
-        AC_MSG_RESULT([yes])
-],[
-        AC_MSG_RESULT([no])
-])
-])
-
 #
 # LC_PROG_LINUX
 #
index 7311cf3..9ffd18a 100644 (file)
@@ -626,14 +626,5 @@ static inline int ll_quota_off(struct super_block *sb, int off, int remount)
 #else
 #define ll_update_time(file) inode_update_time(file->f_mapping->host, 1)
 #endif
-
-#ifdef HAVE_VFS_RENAME_MUTEX
-#define VFS_RENAME_LOCK(inode) mutex_lock(&((inode)->i_sb->s_vfs_rename_mutex))
-#define VFS_RENAME_UNLOCK(inode) mutex_unlock(&((inode)->i_sb->s_vfs_rename_mutex))
-#else
-#define VFS_RENAME_LOCK(inode) down(&((inode)->i_sb->s_vfs_rename_sem))
-#define VFS_RENAME_UNLOCK(inode) up(&((inode)->i_sb->s_vfs_rename_sem))
-#endif
-
 #endif /* __KERNEL__ */
 #endif /* _COMPAT25_H */
index 2a2b2e4..d551891 100644 (file)
@@ -1025,10 +1025,8 @@ int mds_obd_create(struct obd_export *exp, struct obdo *oa,
         if (IS_ERR(handle))
                 GOTO(out_dput2, rc = PTR_ERR(handle));
 
-        lock_kernel();
         rc = ll_vfs_rename(parent_inode, dchild, mds->mds_vfsmnt,
                            parent_inode, new_child, mds->mds_vfsmnt);
-        unlock_kernel();
         if (rc)
                 CERROR("error renaming new object "LPU64":%u: rc %d\n",
                        oa->o_id, oa->o_generation, rc);
index 6df7730..eca8297 100644 (file)
@@ -2536,6 +2536,7 @@ static int mds_reint_rename(struct mds_update_record *rec, int offset,
         struct dentry *de_tgtdir = NULL;
         struct dentry *de_old = NULL;
         struct dentry *de_new = NULL;
+        struct dentry *trap;
         struct inode *old_inode = NULL, *new_inode = NULL;
         struct inode *inodes[PTLRPC_NUM_VERSIONS] = { NULL };
         struct mds_obd *mds = mds_req2mds(req);
@@ -2650,11 +2651,6 @@ no_unlink:
         OBD_FAIL_WRITE(obd, OBD_FAIL_MDS_REINT_RENAME_WRITE,
                        de_srcdir->d_inode->i_sb);
 
-        /* Check if we are moving old entry into its child. 2.6 does not
-           check for this in vfs_rename() anymore */
-        if (is_subdir(de_new, de_old))
-                GOTO(cleanup, rc = -EINVAL);
-
         lmm = lustre_msg_buf(req->rq_repmsg, offset + 1, 0);
         /* check that lmm size is not 0 */
         sz = lustre_msg_buflen(req->rq_repmsg, offset + 1) > 0 ?
@@ -2665,14 +2661,25 @@ no_unlink:
         if (IS_ERR(handle))
                 GOTO(cleanup, rc = PTR_ERR(handle));
 
-        VFS_RENAME_LOCK(de_srcdir->d_inode);
+        trap = lock_rename(de_tgtdir, de_srcdir);
+        /* source should not be ancestor of target */
+        if (de_old == trap) {
+                unlock_rename(de_tgtdir, de_srcdir);
+                GOTO(cleanup, rc = -EINVAL);
+        }
+        /* target should not be an ancestor of source */
+        if (de_new == trap) {
+                unlock_rename(de_tgtdir, de_srcdir);
+                GOTO(cleanup, rc = -ENOTEMPTY);
+        }
+
         de_old->d_fsdata = req;
         de_new->d_fsdata = req;
 
-        rc = ll_vfs_rename(de_srcdir->d_inode, de_old, mds->mds_vfsmnt, 
+        rc = ll_vfs_rename(de_srcdir->d_inode, de_old, mds->mds_vfsmnt,
                            de_tgtdir->d_inode, de_new, mds->mds_vfsmnt);
 
-        VFS_RENAME_UNLOCK(de_srcdir->d_inode);
+        unlock_rename(de_tgtdir, de_srcdir);
 
         if (rc == 0) {
                 struct iattr iattr;