Whamcloud - gitweb
LU-2760 ldiskfs: update rhel6.3 series to handle mkdir errors
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / rhel6.3 / ext4_data_in_dirent.patch
index 75e5634..72c2395 100644 (file)
@@ -7,11 +7,9 @@ is present.
 make use of dentry->d_fsdata to pass fid to ext4. so no
 changes in ext4_add_entry() interface required.
 
-Index: linux-stage/fs/ext4/dir.c
-===================================================================
---- linux-stage.orig/fs/ext4/dir.c
-+++ linux-stage/fs/ext4/dir.c
-@@ -53,11 +53,18 @@ const struct file_operations ext4_dir_op
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -37,11 +37,18 @@ static int ext4_dx_readdir(struct file *
  
  static unsigned char get_dtype(struct super_block *sb, int filetype)
  {
@@ -31,8 +29,8 @@ Index: linux-stage/fs/ext4/dir.c
 +
  }
  
-@@ -70,11 +77,11 @@ int ext4_check_dir_entry(const char *fun
+ /**
+@@ -73,11 +80,11 @@ int ext4_check_dir_entry(const char *fun
        const int rlen = ext4_rec_len_from_disk(de->rec_len,
                                                dir->i_sb->s_blocksize);
  
@@ -44,9 +42,9 @@ Index: linux-stage/fs/ext4/dir.c
 -      else if (unlikely(rlen < EXT4_DIR_REC_LEN(de->name_len)))
 +      else if (unlikely(rlen < EXT4_DIR_REC_LEN(de)))
                error_msg = "rec_len is too small for name_len";
-       else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
+       else if (unlikely(((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize))
                error_msg = "directory entry across blocks";
-@@ -182,7 +189,7 @@ revalidate:
+@@ -181,7 +188,7 @@ revalidate:
                                 * failure will be detected in the
                                 * dirent test below. */
                                if (ext4_rec_len_from_disk(de->rec_len,
@@ -55,7 +53,7 @@ Index: linux-stage/fs/ext4/dir.c
                                        break;
                                i += ext4_rec_len_from_disk(de->rec_len,
                                                            sb->s_blocksize);
-@@ -345,12 +352,17 @@ int ext4_htree_store_dirent(struct file 
+@@ -457,12 +464,17 @@ int ext4_htree_store_dirent(struct file
        struct fname *fname, *new_fn;
        struct dir_private_info *info;
        int len;
@@ -74,7 +72,7 @@ Index: linux-stage/fs/ext4/dir.c
        new_fn = kzalloc(len, GFP_KERNEL);
        if (!new_fn)
                return -ENOMEM;
-@@ -359,7 +371,7 @@ int ext4_htree_store_dirent(struct file 
+@@ -471,7 +483,7 @@ int ext4_htree_store_dirent(struct file
        new_fn->inode = le32_to_cpu(dirent->inode);
        new_fn->name_len = dirent->name_len;
        new_fn->file_type = dirent->file_type;
@@ -83,11 +81,9 @@ Index: linux-stage/fs/ext4/dir.c
        new_fn->name[dirent->name_len] = 0;
  
        while (*p) {
-Index: linux-stage/fs/ext4/ext4.h
-===================================================================
---- linux-stage.orig/fs/ext4/ext4.h
-+++ linux-stage/fs/ext4/ext4.h
-@@ -1267,6 +1267,7 @@ EXT4_INODE_BIT_FNS(state, state_flags)
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1294,6 +1294,7 @@ EXT4_INODE_BIT_FNS(state, state_flags)
  #define EXT4_FEATURE_INCOMPAT_64BIT           0x0080
  #define EXT4_FEATURE_INCOMPAT_MMP               0x0100
  #define EXT4_FEATURE_INCOMPAT_FLEX_BG         0x0200
@@ -95,7 +91,7 @@ Index: linux-stage/fs/ext4/ext4.h
  
  #define EXT4_FEATURE_COMPAT_SUPP      EXT2_FEATURE_COMPAT_EXT_ATTR
  #define EXT4_FEATURE_INCOMPAT_SUPP    (EXT4_FEATURE_INCOMPAT_FILETYPE| \
-@@ -1275,7 +1276,9 @@ EXT4_INODE_BIT_FNS(state, state_flags)
+@@ -1302,7 +1303,9 @@ EXT4_INODE_BIT_FNS(state, state_flags)
                                         EXT4_FEATURE_INCOMPAT_EXTENTS| \
                                         EXT4_FEATURE_INCOMPAT_64BIT| \
                                         EXT4_FEATURE_INCOMPAT_FLEX_BG| \
@@ -106,7 +102,7 @@ Index: linux-stage/fs/ext4/ext4.h
  #define EXT4_FEATURE_RO_COMPAT_SUPP   (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
                                         EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
                                         EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \
-@@ -1357,6 +1360,43 @@ struct ext4_dir_entry_2 {
+@@ -1388,6 +1391,43 @@ struct ext4_dir_entry_2 {
  #define EXT4_FT_SYMLINK               7
  
  #define EXT4_FT_MAX           8
@@ -150,7 +146,7 @@ Index: linux-stage/fs/ext4/ext4.h
  
  /*
   * EXT4_DIR_PAD defines the directory entries boundaries
-@@ -1365,8 +1405,11 @@ struct ext4_dir_entry_2 {
+@@ -1396,8 +1436,11 @@ struct ext4_dir_entry_2 {
   */
  #define EXT4_DIR_PAD                  4
  #define EXT4_DIR_ROUND                        (EXT4_DIR_PAD - 1)
@@ -163,7 +159,7 @@ Index: linux-stage/fs/ext4/ext4.h
  #define EXT4_MAX_REC_LEN              ((1<<16)-1)
  
  static inline unsigned int
-@@ -1726,7 +1769,7 @@ extern struct buffer_head * ext4_find_en
+@@ -1791,7 +1834,7 @@ extern struct buffer_head * ext4_find_en
                                            struct ext4_dir_entry_2 ** res_dir);
  #define ll_ext4_find_entry(inode, dentry, res_dir) ext4_find_entry(inode, &(dentry)->d_name, res_dir)
  extern int ext4_add_dot_dotdot(handle_t *handle, struct inode *dir,
@@ -172,7 +168,7 @@ Index: linux-stage/fs/ext4/ext4.h
  extern struct buffer_head *ext4_append(handle_t *handle,
                                       struct inode *inode,
                                       ext4_lblk_t *block, int *err);
-@@ -2069,6 +2112,28 @@ extern wait_queue_head_t aio_wq[];
+@@ -2143,6 +2186,28 @@ extern wait_queue_head_t aio_wq[];
  #define to_aio_wq(v) (&aio_wq[((unsigned long)v) % WQ_HASH_SZ])
  extern void ext4_aio_wait(struct inode *inode);
  
@@ -201,10 +197,8 @@ Index: linux-stage/fs/ext4/ext4.h
  #endif        /* __KERNEL__ */
  
  #endif        /* _EXT4_H */
-Index: linux-stage/fs/ext4/namei.c
-===================================================================
---- linux-stage.orig/fs/ext4/namei.c
-+++ linux-stage/fs/ext4/namei.c
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
 @@ -169,7 +169,8 @@ static unsigned dx_get_count(struct dx_e
  static unsigned dx_get_limit(struct dx_entry *entries);
  static void dx_set_count(struct dx_entry *entries, unsigned value);
@@ -215,7 +209,7 @@ Index: linux-stage/fs/ext4/namei.c
  static unsigned dx_node_limit(struct inode *dir);
  static struct dx_frame *dx_probe(const struct qstr *d_name,
                                 struct inode *dir,
-@@ -212,11 +213,12 @@ ext4_next_entry(struct ext4_dir_entry_2 
+@@ -212,11 +213,12 @@ ext4_next_entry(struct ext4_dir_entry_2
   */
  struct dx_root_info * dx_get_dx_info(struct ext4_dir_entry_2 *de)
  {
@@ -260,7 +254,7 @@ Index: linux-stage/fs/ext4/namei.c
        return entry_space / sizeof(struct dx_entry);
  }
  
-@@ -317,7 +326,7 @@ static struct stats dx_show_leaf(struct 
+@@ -317,7 +326,7 @@ static struct stats dx_show_leaf(struct
                                printk(":%x.%u ", h.hash,
                                       ((char *) de - base));
                        }
@@ -375,7 +369,7 @@ Index: linux-stage/fs/ext4/namei.c
  
        /* Initialize as for dx_probe */
        hinfo.hash_version = dx_info->hash_version;
-@@ -1511,6 +1534,8 @@ static int ext4_update_dotdot(handle_t *
+@@ -1523,6 +1546,8 @@ static int ext4_update_dotdot(handle_t *
        struct buffer_head * dir_block;
        struct ext4_dir_entry_2 * de;
        int len, journal = 0, err = 0;
@@ -384,7 +378,7 @@ Index: linux-stage/fs/ext4/namei.c
  
        if (IS_ERR(handle))
                return PTR_ERR(handle);
-@@ -1526,19 +1551,24 @@ static int ext4_update_dotdot(handle_t *
+@@ -1538,19 +1563,24 @@ static int ext4_update_dotdot(handle_t *
        /* the first item must be "." */
        assert(de->name_len == 1 && de->name[0] == '.');
        len = le16_to_cpu(de->rec_len);
@@ -414,14 +408,14 @@ Index: linux-stage/fs/ext4/namei.c
        de = (struct ext4_dir_entry_2 *)
                        ((char *) de + le16_to_cpu(de->rec_len));
        if (!journal) {
-@@ -1552,10 +1582,15 @@ static int ext4_update_dotdot(handle_t *
+@@ -1564,10 +1594,15 @@ static int ext4_update_dotdot(handle_t *
        if (len > 0)
                de->rec_len = cpu_to_le16(len);
        else
 -              assert(le16_to_cpu(de->rec_len) >= EXT4_DIR_REC_LEN(2));
 +              assert(le16_to_cpu(de->rec_len) >= __EXT4_DIR_REC_LEN(2));
-       de->name_len = 2;
-       strcpy (de->name, "..");
+       de->name_len = 2;
+       strcpy (de->name, "..");
 -      ext4_set_de_type(dir->i_sb, de, S_IFDIR);
 +      if (data != NULL && ext4_get_dirent_data_len(de) >= dlen) {
 +              de->name[2] = 0;
@@ -432,7 +426,7 @@ Index: linux-stage/fs/ext4/namei.c
  
  out_journal:
        if (journal) {
-@@ -1978,12 +2013,13 @@ retry:
+@@ -1989,12 +2024,13 @@ retry:
  /* Initialize @inode as a subdirectory of @dir, and add the
   * "." and ".." entries into the first directory block. */
  int ext4_add_dot_dotdot(handle_t *handle, struct inode * dir,
@@ -448,20 +442,7 @@ Index: linux-stage/fs/ext4/namei.c
  
        if (IS_ERR(handle))
                return PTR_ERR(handle);
-@@ -1996,28 +2032,40 @@ int ext4_add_dot_dotdot(handle_t *handle
-       inode->i_fop = &ext4_dir_operations;
-       inode->i_size = EXT4_I(inode)->i_disksize = inode->i_sb->s_blocksize;
-       dir_block = ext4_bread(handle, inode, 0, 1, &err);
--      if (!dir_block) {
--              clear_nlink(inode);
--              ext4_mark_inode_dirty(handle, inode);
--              iput (inode);
-+      if (!dir_block)
-               goto get_out;
--      }
-+
-       BUFFER_TRACE(dir_block, "get_write_access");
-       ext4_journal_get_write_access(handle, dir_block);
+@@ -2015,17 +2051,32 @@ int ext4_add_dot_dotdot(handle_t *handle
        de = (struct ext4_dir_entry_2 *) dir_block->b_data;
        de->inode = cpu_to_le32(inode->i_ino);
        de->name_len = 1;
@@ -496,22 +477,17 @@ Index: linux-stage/fs/ext4/namei.c
 +      }
        inode->i_nlink = 2;
        BUFFER_TRACE(dir_block, "call ext4_handle_dirty_metadata");
-       ext4_handle_dirty_metadata(handle, dir, dir_block);
-@@ -2054,9 +2102,12 @@ retry:
+       err = ext4_handle_dirty_metadata(handle, inode, dir_block);
+@@ -2064,7 +2115,7 @@ retry:
        if (IS_ERR(inode))
                goto out_stop;
  
 -      err = ext4_add_dot_dotdot(handle, dir, inode);
 +      err = ext4_add_dot_dotdot(handle, dir, inode, NULL, NULL);
-       if (err) {
-+              clear_nlink(inode);
-               unlock_new_inode(inode);
-+              ext4_mark_inode_dirty(handle, inode);
-+              iput (inode);
-               goto out_stop;
-       }
+       if (err)
+               goto out_clear_inode;
  
-@@ -2092,7 +2143,7 @@ static int empty_dir(struct inode *inode
+@@ -2103,7 +2154,7 @@ static int empty_dir(struct inode *inode
        int err = 0;
  
        sb = inode->i_sb;