ocfs2: Increase max links count
authorMark Fasheh <mfasheh@suse.com>
Fri, 21 Nov 2008 01:54:57 +0000 (17:54 -0800)
committerMark Fasheh <mfasheh@suse.com>
Fri, 3 Apr 2009 18:39:16 +0000 (11:39 -0700)
Since we've now got a directory format capable of handling a large number of
entries, we can increase the maximum link count supported. This only gets
increased if the directory indexing feature is turned on.

Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Acked-by: Joel Becker <joel.becker@oracle.com>
fs/ocfs2/inode.c
fs/ocfs2/namei.c
fs/ocfs2/ocfs2.h
fs/ocfs2/ocfs2_fs.h

index d273c4a51a009e0d7915752588be8193c24dbbe2..f1f77b2f59472f3edaae8949b533bdc63b5bad2b 100644 (file)
@@ -276,7 +276,7 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
                     (unsigned long long)OCFS2_I(inode)->ip_blkno,
                     (unsigned long long)le64_to_cpu(fe->i_blkno));
 
-       inode->i_nlink = le16_to_cpu(fe->i_links_count);
+       inode->i_nlink = ocfs2_read_links_count(fe);
 
        if (fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL)) {
                OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SYSTEM_FILE;
@@ -1215,7 +1215,7 @@ int ocfs2_mark_inode_dirty(handle_t *handle,
        spin_unlock(&OCFS2_I(inode)->ip_lock);
 
        fe->i_size = cpu_to_le64(i_size_read(inode));
-       fe->i_links_count = cpu_to_le16(inode->i_nlink);
+       ocfs2_set_links_count(fe, inode->i_nlink);
        fe->i_uid = cpu_to_le32(inode->i_uid);
        fe->i_gid = cpu_to_le32(inode->i_gid);
        fe->i_mode = cpu_to_le16(inode->i_mode);
@@ -1252,7 +1252,7 @@ void ocfs2_refresh_inode(struct inode *inode,
        OCFS2_I(inode)->ip_dyn_features = le16_to_cpu(fe->i_dyn_features);
        ocfs2_set_inode_flags(inode);
        i_size_write(inode, le64_to_cpu(fe->i_size));
-       inode->i_nlink = le16_to_cpu(fe->i_links_count);
+       inode->i_nlink = ocfs2_read_links_count(fe);
        inode->i_uid = le32_to_cpu(fe->i_uid);
        inode->i_gid = le32_to_cpu(fe->i_gid);
        inode->i_mode = le16_to_cpu(fe->i_mode);
index f911edc8378bec3529464122444c30edbf865bec..67113cfddc9ba7be5d981adfa07b84359e3448f4 100644 (file)
@@ -255,13 +255,13 @@ static int ocfs2_mknod(struct inode *dir,
                return status;
        }
 
-       if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) {
+       if (S_ISDIR(mode) && (dir->i_nlink >= ocfs2_link_max(osb))) {
                status = -EMLINK;
                goto leave;
        }
 
        dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
-       if (!dirfe->i_links_count) {
+       if (!ocfs2_read_links_count(dirfe)) {
                /* can't make a file in a deleted directory. */
                status = -ENOENT;
                goto leave;
@@ -381,7 +381,7 @@ static int ocfs2_mknod(struct inode *dir,
                        mlog_errno(status);
                        goto leave;
                }
-               le16_add_cpu(&dirfe->i_links_count, 1);
+               ocfs2_add_links_count(dirfe, 1);
                status = ocfs2_journal_dirty(handle, parent_fe_bh);
                if (status < 0) {
                        mlog_errno(status);
@@ -529,7 +529,8 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
        fe->i_mode = cpu_to_le16(inode->i_mode);
        if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
                fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev));
-       fe->i_links_count = cpu_to_le16(inode->i_nlink);
+
+       ocfs2_set_links_count(fe, inode->i_nlink);
 
        fe->i_last_eb_blk = 0;
        strcpy(fe->i_signature, OCFS2_INODE_SIGNATURE);
@@ -668,7 +669,7 @@ static int ocfs2_link(struct dentry *old_dentry,
        }
 
        fe = (struct ocfs2_dinode *) fe_bh->b_data;
-       if (le16_to_cpu(fe->i_links_count) >= OCFS2_LINK_MAX) {
+       if (ocfs2_read_links_count(fe) >= ocfs2_link_max(osb)) {
                err = -EMLINK;
                goto out_unlock_inode;
        }
@@ -690,13 +691,13 @@ static int ocfs2_link(struct dentry *old_dentry,
 
        inc_nlink(inode);
        inode->i_ctime = CURRENT_TIME;
-       fe->i_links_count = cpu_to_le16(inode->i_nlink);
+       ocfs2_set_links_count(fe, inode->i_nlink);
        fe->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
        fe->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
 
        err = ocfs2_journal_dirty(handle, fe_bh);
        if (err < 0) {
-               le16_add_cpu(&fe->i_links_count, -1);
+               ocfs2_add_links_count(fe, -1);
                drop_nlink(inode);
                mlog_errno(err);
                goto out_commit;
@@ -706,7 +707,7 @@ static int ocfs2_link(struct dentry *old_dentry,
                              OCFS2_I(inode)->ip_blkno,
                              parent_fe_bh, &lookup);
        if (err) {
-               le16_add_cpu(&fe->i_links_count, -1);
+               ocfs2_add_links_count(fe, -1);
                drop_nlink(inode);
                mlog_errno(err);
                goto out_commit;
@@ -895,7 +896,7 @@ static int ocfs2_unlink(struct inode *dir,
        if (S_ISDIR(inode->i_mode))
                drop_nlink(inode);
        drop_nlink(inode);
-       fe->i_links_count = cpu_to_le16(inode->i_nlink);
+       ocfs2_set_links_count(fe, inode->i_nlink);
 
        status = ocfs2_journal_dirty(handle, fe_bh);
        if (status < 0) {
@@ -1139,7 +1140,7 @@ static int ocfs2_rename(struct inode *old_dir,
                }
 
                if (!new_inode && new_dir != old_dir &&
-                   new_dir->i_nlink >= OCFS2_LINK_MAX) {
+                   new_dir->i_nlink >= ocfs2_link_max(osb)) {
                        status = -EMLINK;
                        goto bail;
                }
@@ -1293,7 +1294,7 @@ static int ocfs2_rename(struct inode *old_dir,
                }
 
                if (S_ISDIR(new_inode->i_mode) ||
-                   (newfe->i_links_count == cpu_to_le16(1))){
+                   (ocfs2_read_links_count(newfe) == 1)) {
                        status = ocfs2_orphan_add(osb, handle, new_inode,
                                                  newfe, orphan_name,
                                                  &orphan_insert, orphan_dir);
@@ -1313,9 +1314,9 @@ static int ocfs2_rename(struct inode *old_dir,
                new_dir->i_version++;
 
                if (S_ISDIR(new_inode->i_mode))
-                       newfe->i_links_count = 0;
+                       ocfs2_set_links_count(newfe, 0);
                else
-                       le16_add_cpu(&newfe->i_links_count, -1);
+                       ocfs2_add_links_count(newfe, -1);
 
                status = ocfs2_journal_dirty(handle, newfe_bh);
                if (status < 0) {
@@ -1409,14 +1410,13 @@ static int ocfs2_rename(struct inode *old_dir,
                } else {
                        struct ocfs2_dinode *fe;
                        status = ocfs2_journal_access_di(handle, old_dir,
-                                                        old_dir_bh,
-                                                        OCFS2_JOURNAL_ACCESS_WRITE);
+                                                     old_dir_bh,
+                                                     OCFS2_JOURNAL_ACCESS_WRITE);
                        fe = (struct ocfs2_dinode *) old_dir_bh->b_data;
-                       fe->i_links_count = cpu_to_le16(old_dir->i_nlink);
+                       ocfs2_set_links_count(fe, old_dir->i_nlink);
                        status = ocfs2_journal_dirty(handle, old_dir_bh);
                }
        }
-
        ocfs2_dentry_move(old_dentry, new_dentry, old_dir, new_dir);
        status = 0;
 bail:
@@ -1614,7 +1614,7 @@ static int ocfs2_symlink(struct inode *dir,
        }
 
        dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
-       if (!dirfe->i_links_count) {
+       if (!ocfs2_read_links_count(dirfe)) {
                /* can't make a file in a deleted directory. */
                status = -ENOENT;
                goto bail;
@@ -1932,8 +1932,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
         * underneath us... */
        orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data;
        if (S_ISDIR(inode->i_mode))
-               le16_add_cpu(&orphan_fe->i_links_count, 1);
-       orphan_dir_inode->i_nlink = le16_to_cpu(orphan_fe->i_links_count);
+               ocfs2_add_links_count(orphan_fe, 1);
+       orphan_dir_inode->i_nlink = ocfs2_read_links_count(orphan_fe);
 
        status = ocfs2_journal_dirty(handle, orphan_dir_bh);
        if (status < 0) {
@@ -2016,8 +2016,8 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
        /* do the i_nlink dance! :) */
        orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data;
        if (S_ISDIR(inode->i_mode))
-               le16_add_cpu(&orphan_fe->i_links_count, -1);
-       orphan_dir_inode->i_nlink = le16_to_cpu(orphan_fe->i_links_count);
+               ocfs2_add_links_count(orphan_fe, -1);
+       orphan_dir_inode->i_nlink = ocfs2_read_links_count(orphan_fe);
 
        status = ocfs2_journal_dirty(handle, orphan_dir_bh);
        if (status < 0) {
index 3749c32c2fc49ca76ec9a94b5defee0d1579bb0b..fa3c6d3f0bd2d5a52fb41b1da91226fa1ecdc48b 100644 (file)
@@ -408,6 +408,44 @@ static inline int ocfs2_supports_indexed_dirs(struct ocfs2_super *osb)
        return 0;
 }
 
+static inline unsigned int ocfs2_link_max(struct ocfs2_super *osb)
+{
+       if (ocfs2_supports_indexed_dirs(osb))
+               return OCFS2_DX_LINK_MAX;
+       return OCFS2_LINK_MAX;
+}
+
+static inline unsigned int ocfs2_read_links_count(struct ocfs2_dinode *di)
+{
+       u32 nlink = le16_to_cpu(di->i_links_count);
+       u32 hi = le16_to_cpu(di->i_links_count_hi);
+
+       if (di->i_dyn_features & cpu_to_le16(OCFS2_INDEXED_DIR_FL))
+               nlink |= (hi << OCFS2_LINKS_HI_SHIFT);
+
+       return nlink;
+}
+
+static inline void ocfs2_set_links_count(struct ocfs2_dinode *di, u32 nlink)
+{
+       u16 lo, hi;
+
+       lo = nlink;
+       hi = nlink >> OCFS2_LINKS_HI_SHIFT;
+
+       di->i_links_count = cpu_to_le16(lo);
+       di->i_links_count_hi = cpu_to_le16(hi);
+}
+
+static inline void ocfs2_add_links_count(struct ocfs2_dinode *di, int n)
+{
+       u32 links = ocfs2_read_links_count(di);
+
+       links += n;
+
+       ocfs2_set_links_count(di, links);
+}
+
 /* set / clear functions because cluster events can make these happen
  * in parallel so we want the transitions to be atomic. this also
  * means that any future flags osb_flags must be protected by spinlock
index d549b1799a61561786fa706b2a734e5b67a8d466..43da76eff9ae64a6c3e51b8fa551c04b4941f26f 100644 (file)
@@ -419,6 +419,8 @@ static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = {
 #define OCFS2_DIR_MIN_REC_LEN  OCFS2_DIR_REC_LEN(1)
 
 #define OCFS2_LINK_MAX         32000
+#define        OCFS2_DX_LINK_MAX       ((1U << 31) - 1U)
+#define        OCFS2_LINKS_HI_SHIFT    16
 
 #define S_SHIFT                        12
 static unsigned char ocfs2_type_by_mode[S_IFMT >> S_SHIFT] = {
@@ -686,7 +688,7 @@ struct ocfs2_dinode {
                                           belongs to */
        __le16 i_suballoc_bit;          /* Bit offset in suballocator
                                           block group */
-/*10*/ __le16 i_reserved0;
+/*10*/ __le16 i_links_count_hi;        /* High 16 bits of links count */
        __le16 i_xattr_inline_size;
        __le32 i_clusters;              /* Cluster count */
        __le32 i_uid;                   /* Owner UID */