diff options
author | Mark Fasheh <mfasheh@suse.com> | 2008-11-20 20:54:57 -0500 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-04-03 14:39:16 -0400 |
commit | 198a1ca3b735986542c538e38b9499ffcaed7005 (patch) | |
tree | 3b02034534c4640e72623088a59d1e942c38e7c3 /fs/ocfs2 | |
parent | e7c17e43090afe558c40bfb66637744c27bd2aeb (diff) |
ocfs2: Increase max links count
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>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/inode.c | 6 | ||||
-rw-r--r-- | fs/ocfs2/namei.c | 44 | ||||
-rw-r--r-- | fs/ocfs2/ocfs2.h | 38 | ||||
-rw-r--r-- | fs/ocfs2/ocfs2_fs.h | 4 |
4 files changed, 66 insertions, 26 deletions
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index d273c4a51a0..f1f77b2f594 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
@@ -276,7 +276,7 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, | |||
276 | (unsigned long long)OCFS2_I(inode)->ip_blkno, | 276 | (unsigned long long)OCFS2_I(inode)->ip_blkno, |
277 | (unsigned long long)le64_to_cpu(fe->i_blkno)); | 277 | (unsigned long long)le64_to_cpu(fe->i_blkno)); |
278 | 278 | ||
279 | inode->i_nlink = le16_to_cpu(fe->i_links_count); | 279 | inode->i_nlink = ocfs2_read_links_count(fe); |
280 | 280 | ||
281 | if (fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL)) { | 281 | if (fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL)) { |
282 | OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SYSTEM_FILE; | 282 | OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SYSTEM_FILE; |
@@ -1215,7 +1215,7 @@ int ocfs2_mark_inode_dirty(handle_t *handle, | |||
1215 | spin_unlock(&OCFS2_I(inode)->ip_lock); | 1215 | spin_unlock(&OCFS2_I(inode)->ip_lock); |
1216 | 1216 | ||
1217 | fe->i_size = cpu_to_le64(i_size_read(inode)); | 1217 | fe->i_size = cpu_to_le64(i_size_read(inode)); |
1218 | fe->i_links_count = cpu_to_le16(inode->i_nlink); | 1218 | ocfs2_set_links_count(fe, inode->i_nlink); |
1219 | fe->i_uid = cpu_to_le32(inode->i_uid); | 1219 | fe->i_uid = cpu_to_le32(inode->i_uid); |
1220 | fe->i_gid = cpu_to_le32(inode->i_gid); | 1220 | fe->i_gid = cpu_to_le32(inode->i_gid); |
1221 | fe->i_mode = cpu_to_le16(inode->i_mode); | 1221 | fe->i_mode = cpu_to_le16(inode->i_mode); |
@@ -1252,7 +1252,7 @@ void ocfs2_refresh_inode(struct inode *inode, | |||
1252 | OCFS2_I(inode)->ip_dyn_features = le16_to_cpu(fe->i_dyn_features); | 1252 | OCFS2_I(inode)->ip_dyn_features = le16_to_cpu(fe->i_dyn_features); |
1253 | ocfs2_set_inode_flags(inode); | 1253 | ocfs2_set_inode_flags(inode); |
1254 | i_size_write(inode, le64_to_cpu(fe->i_size)); | 1254 | i_size_write(inode, le64_to_cpu(fe->i_size)); |
1255 | inode->i_nlink = le16_to_cpu(fe->i_links_count); | 1255 | inode->i_nlink = ocfs2_read_links_count(fe); |
1256 | inode->i_uid = le32_to_cpu(fe->i_uid); | 1256 | inode->i_uid = le32_to_cpu(fe->i_uid); |
1257 | inode->i_gid = le32_to_cpu(fe->i_gid); | 1257 | inode->i_gid = le32_to_cpu(fe->i_gid); |
1258 | inode->i_mode = le16_to_cpu(fe->i_mode); | 1258 | inode->i_mode = le16_to_cpu(fe->i_mode); |
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index f911edc8378..67113cfddc9 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -255,13 +255,13 @@ static int ocfs2_mknod(struct inode *dir, | |||
255 | return status; | 255 | return status; |
256 | } | 256 | } |
257 | 257 | ||
258 | if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) { | 258 | if (S_ISDIR(mode) && (dir->i_nlink >= ocfs2_link_max(osb))) { |
259 | status = -EMLINK; | 259 | status = -EMLINK; |
260 | goto leave; | 260 | goto leave; |
261 | } | 261 | } |
262 | 262 | ||
263 | dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data; | 263 | dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data; |
264 | if (!dirfe->i_links_count) { | 264 | if (!ocfs2_read_links_count(dirfe)) { |
265 | /* can't make a file in a deleted directory. */ | 265 | /* can't make a file in a deleted directory. */ |
266 | status = -ENOENT; | 266 | status = -ENOENT; |
267 | goto leave; | 267 | goto leave; |
@@ -381,7 +381,7 @@ static int ocfs2_mknod(struct inode *dir, | |||
381 | mlog_errno(status); | 381 | mlog_errno(status); |
382 | goto leave; | 382 | goto leave; |
383 | } | 383 | } |
384 | le16_add_cpu(&dirfe->i_links_count, 1); | 384 | ocfs2_add_links_count(dirfe, 1); |
385 | status = ocfs2_journal_dirty(handle, parent_fe_bh); | 385 | status = ocfs2_journal_dirty(handle, parent_fe_bh); |
386 | if (status < 0) { | 386 | if (status < 0) { |
387 | mlog_errno(status); | 387 | mlog_errno(status); |
@@ -529,7 +529,8 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, | |||
529 | fe->i_mode = cpu_to_le16(inode->i_mode); | 529 | fe->i_mode = cpu_to_le16(inode->i_mode); |
530 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) | 530 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) |
531 | fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev)); | 531 | fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev)); |
532 | fe->i_links_count = cpu_to_le16(inode->i_nlink); | 532 | |
533 | ocfs2_set_links_count(fe, inode->i_nlink); | ||
533 | 534 | ||
534 | fe->i_last_eb_blk = 0; | 535 | fe->i_last_eb_blk = 0; |
535 | strcpy(fe->i_signature, OCFS2_INODE_SIGNATURE); | 536 | strcpy(fe->i_signature, OCFS2_INODE_SIGNATURE); |
@@ -668,7 +669,7 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
668 | } | 669 | } |
669 | 670 | ||
670 | fe = (struct ocfs2_dinode *) fe_bh->b_data; | 671 | fe = (struct ocfs2_dinode *) fe_bh->b_data; |
671 | if (le16_to_cpu(fe->i_links_count) >= OCFS2_LINK_MAX) { | 672 | if (ocfs2_read_links_count(fe) >= ocfs2_link_max(osb)) { |
672 | err = -EMLINK; | 673 | err = -EMLINK; |
673 | goto out_unlock_inode; | 674 | goto out_unlock_inode; |
674 | } | 675 | } |
@@ -690,13 +691,13 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
690 | 691 | ||
691 | inc_nlink(inode); | 692 | inc_nlink(inode); |
692 | inode->i_ctime = CURRENT_TIME; | 693 | inode->i_ctime = CURRENT_TIME; |
693 | fe->i_links_count = cpu_to_le16(inode->i_nlink); | 694 | ocfs2_set_links_count(fe, inode->i_nlink); |
694 | fe->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec); | 695 | fe->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec); |
695 | fe->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); | 696 | fe->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); |
696 | 697 | ||
697 | err = ocfs2_journal_dirty(handle, fe_bh); | 698 | err = ocfs2_journal_dirty(handle, fe_bh); |
698 | if (err < 0) { | 699 | if (err < 0) { |
699 | le16_add_cpu(&fe->i_links_count, -1); | 700 | ocfs2_add_links_count(fe, -1); |
700 | drop_nlink(inode); | 701 | drop_nlink(inode); |
701 | mlog_errno(err); | 702 | mlog_errno(err); |
702 | goto out_commit; | 703 | goto out_commit; |
@@ -706,7 +707,7 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
706 | OCFS2_I(inode)->ip_blkno, | 707 | OCFS2_I(inode)->ip_blkno, |
707 | parent_fe_bh, &lookup); | 708 | parent_fe_bh, &lookup); |
708 | if (err) { | 709 | if (err) { |
709 | le16_add_cpu(&fe->i_links_count, -1); | 710 | ocfs2_add_links_count(fe, -1); |
710 | drop_nlink(inode); | 711 | drop_nlink(inode); |
711 | mlog_errno(err); | 712 | mlog_errno(err); |
712 | goto out_commit; | 713 | goto out_commit; |
@@ -895,7 +896,7 @@ static int ocfs2_unlink(struct inode *dir, | |||
895 | if (S_ISDIR(inode->i_mode)) | 896 | if (S_ISDIR(inode->i_mode)) |
896 | drop_nlink(inode); | 897 | drop_nlink(inode); |
897 | drop_nlink(inode); | 898 | drop_nlink(inode); |
898 | fe->i_links_count = cpu_to_le16(inode->i_nlink); | 899 | ocfs2_set_links_count(fe, inode->i_nlink); |
899 | 900 | ||
900 | status = ocfs2_journal_dirty(handle, fe_bh); | 901 | status = ocfs2_journal_dirty(handle, fe_bh); |
901 | if (status < 0) { | 902 | if (status < 0) { |
@@ -1139,7 +1140,7 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1139 | } | 1140 | } |
1140 | 1141 | ||
1141 | if (!new_inode && new_dir != old_dir && | 1142 | if (!new_inode && new_dir != old_dir && |
1142 | new_dir->i_nlink >= OCFS2_LINK_MAX) { | 1143 | new_dir->i_nlink >= ocfs2_link_max(osb)) { |
1143 | status = -EMLINK; | 1144 | status = -EMLINK; |
1144 | goto bail; | 1145 | goto bail; |
1145 | } | 1146 | } |
@@ -1293,7 +1294,7 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1293 | } | 1294 | } |
1294 | 1295 | ||
1295 | if (S_ISDIR(new_inode->i_mode) || | 1296 | if (S_ISDIR(new_inode->i_mode) || |
1296 | (newfe->i_links_count == cpu_to_le16(1))){ | 1297 | (ocfs2_read_links_count(newfe) == 1)) { |
1297 | status = ocfs2_orphan_add(osb, handle, new_inode, | 1298 | status = ocfs2_orphan_add(osb, handle, new_inode, |
1298 | newfe, orphan_name, | 1299 | newfe, orphan_name, |
1299 | &orphan_insert, orphan_dir); | 1300 | &orphan_insert, orphan_dir); |
@@ -1313,9 +1314,9 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1313 | new_dir->i_version++; | 1314 | new_dir->i_version++; |
1314 | 1315 | ||
1315 | if (S_ISDIR(new_inode->i_mode)) | 1316 | if (S_ISDIR(new_inode->i_mode)) |
1316 | newfe->i_links_count = 0; | 1317 | ocfs2_set_links_count(newfe, 0); |
1317 | else | 1318 | else |
1318 | le16_add_cpu(&newfe->i_links_count, -1); | 1319 | ocfs2_add_links_count(newfe, -1); |
1319 | 1320 | ||
1320 | status = ocfs2_journal_dirty(handle, newfe_bh); | 1321 | status = ocfs2_journal_dirty(handle, newfe_bh); |
1321 | if (status < 0) { | 1322 | if (status < 0) { |
@@ -1409,14 +1410,13 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1409 | } else { | 1410 | } else { |
1410 | struct ocfs2_dinode *fe; | 1411 | struct ocfs2_dinode *fe; |
1411 | status = ocfs2_journal_access_di(handle, old_dir, | 1412 | status = ocfs2_journal_access_di(handle, old_dir, |
1412 | old_dir_bh, | 1413 | old_dir_bh, |
1413 | OCFS2_JOURNAL_ACCESS_WRITE); | 1414 | OCFS2_JOURNAL_ACCESS_WRITE); |
1414 | fe = (struct ocfs2_dinode *) old_dir_bh->b_data; | 1415 | fe = (struct ocfs2_dinode *) old_dir_bh->b_data; |
1415 | fe->i_links_count = cpu_to_le16(old_dir->i_nlink); | 1416 | ocfs2_set_links_count(fe, old_dir->i_nlink); |
1416 | status = ocfs2_journal_dirty(handle, old_dir_bh); | 1417 | status = ocfs2_journal_dirty(handle, old_dir_bh); |
1417 | } | 1418 | } |
1418 | } | 1419 | } |
1419 | |||
1420 | ocfs2_dentry_move(old_dentry, new_dentry, old_dir, new_dir); | 1420 | ocfs2_dentry_move(old_dentry, new_dentry, old_dir, new_dir); |
1421 | status = 0; | 1421 | status = 0; |
1422 | bail: | 1422 | bail: |
@@ -1614,7 +1614,7 @@ static int ocfs2_symlink(struct inode *dir, | |||
1614 | } | 1614 | } |
1615 | 1615 | ||
1616 | dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data; | 1616 | dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data; |
1617 | if (!dirfe->i_links_count) { | 1617 | if (!ocfs2_read_links_count(dirfe)) { |
1618 | /* can't make a file in a deleted directory. */ | 1618 | /* can't make a file in a deleted directory. */ |
1619 | status = -ENOENT; | 1619 | status = -ENOENT; |
1620 | goto bail; | 1620 | goto bail; |
@@ -1932,8 +1932,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, | |||
1932 | * underneath us... */ | 1932 | * underneath us... */ |
1933 | orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data; | 1933 | orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data; |
1934 | if (S_ISDIR(inode->i_mode)) | 1934 | if (S_ISDIR(inode->i_mode)) |
1935 | le16_add_cpu(&orphan_fe->i_links_count, 1); | 1935 | ocfs2_add_links_count(orphan_fe, 1); |
1936 | orphan_dir_inode->i_nlink = le16_to_cpu(orphan_fe->i_links_count); | 1936 | orphan_dir_inode->i_nlink = ocfs2_read_links_count(orphan_fe); |
1937 | 1937 | ||
1938 | status = ocfs2_journal_dirty(handle, orphan_dir_bh); | 1938 | status = ocfs2_journal_dirty(handle, orphan_dir_bh); |
1939 | if (status < 0) { | 1939 | if (status < 0) { |
@@ -2016,8 +2016,8 @@ int ocfs2_orphan_del(struct ocfs2_super *osb, | |||
2016 | /* do the i_nlink dance! :) */ | 2016 | /* do the i_nlink dance! :) */ |
2017 | orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data; | 2017 | orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data; |
2018 | if (S_ISDIR(inode->i_mode)) | 2018 | if (S_ISDIR(inode->i_mode)) |
2019 | le16_add_cpu(&orphan_fe->i_links_count, -1); | 2019 | ocfs2_add_links_count(orphan_fe, -1); |
2020 | orphan_dir_inode->i_nlink = le16_to_cpu(orphan_fe->i_links_count); | 2020 | orphan_dir_inode->i_nlink = ocfs2_read_links_count(orphan_fe); |
2021 | 2021 | ||
2022 | status = ocfs2_journal_dirty(handle, orphan_dir_bh); | 2022 | status = ocfs2_journal_dirty(handle, orphan_dir_bh); |
2023 | if (status < 0) { | 2023 | if (status < 0) { |
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 3749c32c2fc..fa3c6d3f0bd 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
@@ -408,6 +408,44 @@ static inline int ocfs2_supports_indexed_dirs(struct ocfs2_super *osb) | |||
408 | return 0; | 408 | return 0; |
409 | } | 409 | } |
410 | 410 | ||
411 | static inline unsigned int ocfs2_link_max(struct ocfs2_super *osb) | ||
412 | { | ||
413 | if (ocfs2_supports_indexed_dirs(osb)) | ||
414 | return OCFS2_DX_LINK_MAX; | ||
415 | return OCFS2_LINK_MAX; | ||
416 | } | ||
417 | |||
418 | static inline unsigned int ocfs2_read_links_count(struct ocfs2_dinode *di) | ||
419 | { | ||
420 | u32 nlink = le16_to_cpu(di->i_links_count); | ||
421 | u32 hi = le16_to_cpu(di->i_links_count_hi); | ||
422 | |||
423 | if (di->i_dyn_features & cpu_to_le16(OCFS2_INDEXED_DIR_FL)) | ||
424 | nlink |= (hi << OCFS2_LINKS_HI_SHIFT); | ||
425 | |||
426 | return nlink; | ||
427 | } | ||
428 | |||
429 | static inline void ocfs2_set_links_count(struct ocfs2_dinode *di, u32 nlink) | ||
430 | { | ||
431 | u16 lo, hi; | ||
432 | |||
433 | lo = nlink; | ||
434 | hi = nlink >> OCFS2_LINKS_HI_SHIFT; | ||
435 | |||
436 | di->i_links_count = cpu_to_le16(lo); | ||
437 | di->i_links_count_hi = cpu_to_le16(hi); | ||
438 | } | ||
439 | |||
440 | static inline void ocfs2_add_links_count(struct ocfs2_dinode *di, int n) | ||
441 | { | ||
442 | u32 links = ocfs2_read_links_count(di); | ||
443 | |||
444 | links += n; | ||
445 | |||
446 | ocfs2_set_links_count(di, links); | ||
447 | } | ||
448 | |||
411 | /* set / clear functions because cluster events can make these happen | 449 | /* set / clear functions because cluster events can make these happen |
412 | * in parallel so we want the transitions to be atomic. this also | 450 | * in parallel so we want the transitions to be atomic. this also |
413 | * means that any future flags osb_flags must be protected by spinlock | 451 | * means that any future flags osb_flags must be protected by spinlock |
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index d549b1799a6..43da76eff9a 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h | |||
@@ -419,6 +419,8 @@ static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = { | |||
419 | #define OCFS2_DIR_MIN_REC_LEN OCFS2_DIR_REC_LEN(1) | 419 | #define OCFS2_DIR_MIN_REC_LEN OCFS2_DIR_REC_LEN(1) |
420 | 420 | ||
421 | #define OCFS2_LINK_MAX 32000 | 421 | #define OCFS2_LINK_MAX 32000 |
422 | #define OCFS2_DX_LINK_MAX ((1U << 31) - 1U) | ||
423 | #define OCFS2_LINKS_HI_SHIFT 16 | ||
422 | 424 | ||
423 | #define S_SHIFT 12 | 425 | #define S_SHIFT 12 |
424 | static unsigned char ocfs2_type_by_mode[S_IFMT >> S_SHIFT] = { | 426 | static unsigned char ocfs2_type_by_mode[S_IFMT >> S_SHIFT] = { |
@@ -686,7 +688,7 @@ struct ocfs2_dinode { | |||
686 | belongs to */ | 688 | belongs to */ |
687 | __le16 i_suballoc_bit; /* Bit offset in suballocator | 689 | __le16 i_suballoc_bit; /* Bit offset in suballocator |
688 | block group */ | 690 | block group */ |
689 | /*10*/ __le16 i_reserved0; | 691 | /*10*/ __le16 i_links_count_hi; /* High 16 bits of links count */ |
690 | __le16 i_xattr_inline_size; | 692 | __le16 i_xattr_inline_size; |
691 | __le32 i_clusters; /* Cluster count */ | 693 | __le32 i_clusters; /* Cluster count */ |
692 | __le32 i_uid; /* Owner UID */ | 694 | __le32 i_uid; /* Owner UID */ |