tbd Cluster File Systems, Inc. <info@clusterfs.com>
* version 1.2.0
* bug fixes
- - reduce journal credits needed for BRW writes (2370)
- - orphan handling to avoid losing space on client/server crashes
- - ptlrpcd can be blocked, stopping ALL progress (2477)
- - recovery for initial connections (2355)
- - orphan recovery problems in b_eq (1934)
- - block all file creations until orphan recovery completes (1901)
- - client remove rq_connection from request struct (2423)
- - conf-sanity test_5, proper cleanup in umount log not availale (2640)
- - recovery timer race (2670)
- - mdc_close recovey bug (2532)
+ - reduce journal credits needed for BRW writes (2370)
+ - orphan handling to avoid losing space on client/server crashes
+ - ptlrpcd can be blocked, stopping ALL progress (2477)
+ - recovery for initial connections (2355)
+ - orphan recovery problems in b_eq (1934)
+ - block all file creations until orphan recovery completes (1901)
+ - client remove rq_connection from request struct (2423)
+ - conf-sanity test_5, proper cleanup in umount log not availale (2640)
+ - recovery timer race (2670)
+ - mdc_close recovey bug (2532)
+
+2004-02-06 Cluster File Systems, Inc. <info@clusterfs.com>
+ * version 1.0.4
+ * kernel patches
+ - fix for failed assertion in iopen_connect_dentry (1792,2517)
+
2004-01-27 Cluster File Systems, Inc. <info@clusterfs.com>
* version 1.0.3
inode->u.ext3_i.i_state = EXT3_STATE_NEW;
- err = ext3_mark_inode_dirty(handle, inode);
- if (err) goto fail;
-+ err = ext3_get_inode_loc_new(inode, &iloc, 1);
-+ if (err) goto fail;
-+ BUFFER_TRACE(iloc->bh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, iloc.bh);
-+ if (err) {
-+ brelse(iloc.bh);
-+ iloc.bh = NULL;
-+ goto fail;
-+ }
-+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
-+ if (err) goto fail;
-+
++ err = ext3_get_inode_loc_new(inode, &iloc, 1);
++ if (err) goto fail;
++ BUFFER_TRACE(iloc->bh, "get_write_access");
++ err = ext3_journal_get_write_access(handle, iloc.bh);
++ if (err) {
++ brelse(iloc.bh);
++ iloc.bh = NULL;
++ goto fail;
++ }
++ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
++ if (err) goto fail;
++
+
unlock_super (sb);
-
-int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
+#define NUM_INODE_PREREAD 16
-+
++
+/*
-+ * ext3_get_inode_loc returns with an extra refcount against the inode's
-+ * underlying buffer_head on success. If this is for a new inode allocation
-+ * (new is non-zero) then we may be able to optimize away the read if there
-+ * are no other in-use inodes in this inode table block. If we need to do
-+ * a read, then read in a whole chunk of blocks to avoid blocking again soon
-+ * if we are doing lots of creates/updates.
-+ */
++ * ext3_get_inode_loc returns with an extra refcount against the inode's
++ * underlying buffer_head on success. If this is for a new inode allocation
++ * (new is non-zero) then we may be able to optimize away the read if there
++ * are no other in-use inodes in this inode table block. If we need to do
++ * a read, then read in a whole chunk of blocks to avoid blocking again soon
++ * if we are doing lots of creates/updates.
++ */
+int ext3_get_inode_loc_new(struct inode *inode, struct ext3_iloc *iloc, int new)
{
- struct buffer_head *bh = 0;
-+ struct buffer_head *bh[NUM_INODE_PREREAD];
++ struct buffer_head *bh[NUM_INODE_PREREAD];
unsigned long block;
unsigned long block_group;
unsigned long group_desc;
}
- gdp = (struct ext3_group_desc *) bh->b_data;
-+ gdp = (struct ext3_group_desc *)(inode->i_sb->u.ext3_sb.s_group_desc[group_desc]->b_data);
++ gdp = (struct ext3_group_desc *)(inode->i_sb->u.ext3_sb.s_group_desc[group_desc]->b_data);
/*
* Figure out the offset within the block group inode table
*/
- goto bad_inode;
- }
- offset &= (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
-+ (offset * EXT3_INODE_SIZE(inode->i_sb) >> EXT3_BLOCK_SIZE_BITS(inode->i_sb));
++ (offset * EXT3_INODE_SIZE(inode->i_sb) >> EXT3_BLOCK_SIZE_BITS(inode->i_sb));
- iloc->bh = bh;
- iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset);
-+ bh[0] = sb_getblk(inode->i_sb, block);
-+ if (buffer_uptodate(bh[0]))
-+ goto done;
-+
-+ /* If we don't really need to read this block, and it isn't already
-+ * in memory, then we just zero it out. Otherwise, we keep the
-+ * current block contents (deleted inode data) for posterity.
-+ */
-+ if (new && !ext3_itable_block_used(inode->i_sb, block_group, offset)) {
-+ lock_buffer(bh[0]);
-+ memset(bh[0]->b_data, 0, bh[0]->b_size);
-+ mark_buffer_uptodate(bh[0], 1);
-+ unlock_buffer(bh[0]);
-+ } else {
-+ unsigned long block_end, itable_end;
-+ int count = 1;
-+
-+ itable_end = le32_to_cpu(gdp[desc].bg_inode_table) +
-+ inode->i_sb->u.ext3_sb.s_itb_per_group;
-+ block_end = block + NUM_INODE_PREREAD;
-+ if (block_end > itable_end)
-+ block_end = itable_end;
-+
-+ for (++block; block < block_end; block++) {
-+ bh[count] = sb_getblk(inode->i_sb, block);
-+ if (count && (buffer_uptodate(bh[count]) ||
-+ buffer_locked(bh[count]))) {
-+ __brelse(bh[count]);
-+ } else
-+ count++;
-+ }
-+
-+ ll_rw_block(READ, count, bh);
-+
-+ /* Release all but the block we actually need (bh[0]) */
-+ while (--count > 0)
-+ __brelse(bh[count]);
-+
-+ wait_on_buffer(bh[0]);
-+ if (!buffer_uptodate(bh[0])) {
-+ ext3_error(inode->i_sb, __FUNCTION__,
-+ "unable to read inode block - "
-+ "inode=%lu, block=%lu", inode->i_ino,
-+ bh[0]->b_blocknr);
-+ goto bad_inode;
-+ }
-+ }
-+ done:
-+ offset = (offset * EXT3_INODE_SIZE(inode->i_sb)) & (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
-+
-+ iloc->bh = bh[0];
-+ iloc->raw_inode = (struct ext3_inode *)(bh[0]->b_data + offset);
++ bh[0] = sb_getblk(inode->i_sb, block);
++ if (buffer_uptodate(bh[0]))
++ goto done;
++
++ /* If we don't really need to read this block, and it isn't already
++ * in memory, then we just zero it out. Otherwise, we keep the
++ * current block contents (deleted inode data) for posterity.
++ */
++ if (new && !ext3_itable_block_used(inode->i_sb, block_group, offset)) {
++ lock_buffer(bh[0]);
++ memset(bh[0]->b_data, 0, bh[0]->b_size);
++ mark_buffer_uptodate(bh[0], 1);
++ unlock_buffer(bh[0]);
++ } else {
++ unsigned long block_end, itable_end;
++ int count = 1;
++
++ itable_end = le32_to_cpu(gdp[desc].bg_inode_table) +
++ inode->i_sb->u.ext3_sb.s_itb_per_group;
++ block_end = block + NUM_INODE_PREREAD;
++ if (block_end > itable_end)
++ block_end = itable_end;
++
++ for (++block; block < block_end; block++) {
++ bh[count] = sb_getblk(inode->i_sb, block);
++ if (count && (buffer_uptodate(bh[count]) ||
++ buffer_locked(bh[count]))) {
++ __brelse(bh[count]);
++ } else
++ count++;
++ }
++
++ ll_rw_block(READ, count, bh);
++
++ /* Release all but the block we actually need (bh[0]) */
++ while (--count > 0)
++ __brelse(bh[count]);
++
++ wait_on_buffer(bh[0]);
++ if (!buffer_uptodate(bh[0])) {
++ ext3_error(inode->i_sb, __FUNCTION__,
++ "unable to read inode block - "
++ "inode=%lu, block=%lu", inode->i_ino,
++ bh[0]->b_blocknr);
++ goto bad_inode;
++ }
++ }
++done:
++ offset = (offset * EXT3_INODE_SIZE(inode->i_sb)) & (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
++
++ iloc->bh = bh[0];
++ iloc->raw_inode = (struct ext3_inode *)(bh[0]->b_data + offset);
iloc->block_group = block_group;
return 0;
+int ext3_get_inode_loc(struct inode *inode, struct ext3_iloc *iloc)
+{
-+ return ext3_get_inode_loc_new(inode, iloc, 0);
++ return ext3_get_inode_loc_new(inode, iloc, 0);
+}
-+
++
void ext3_read_inode(struct inode * inode)
{
struct ext3_iloc iloc;
ei->i_state = EXT3_STATE_NEW;
- err = ext3_mark_inode_dirty(handle, inode);
- if (err) goto fail;
-+ err = ext3_get_inode_loc_new(inode, &iloc, 1);
-+ if (err) goto fail;
-+ BUFFER_TRACE(iloc->bh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, iloc.bh);
-+ if (err) {
-+ brelse(iloc.bh);
-+ iloc.bh = NULL;
-+ goto fail;
-+ }
-+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
-+ if (err) goto fail;
++ err = ext3_get_inode_loc_new(inode, &iloc, 1);
++ if (err) goto fail;
++ BUFFER_TRACE(iloc->bh, "get_write_access");
++ err = ext3_journal_get_write_access(handle, iloc.bh);
++ if (err) {
++ brelse(iloc.bh);
++ iloc.bh = NULL;
++ goto fail;
++ }
++ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
++ if (err) goto fail;
+
+
-
-int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
+#define NUM_INODE_PREREAD 16
-+
++
+/*
-+ * ext3_get_inode_loc returns with an extra refcount against the inode's
-+ * underlying buffer_head on success. If this is for a new inode allocation
-+ * (new is non-zero) then we may be able to optimize away the read if there
-+ * are no other in-use inodes in this inode table block. If we need to do
-+ * a read, then read in a whole chunk of blocks to avoid blocking again soon
-+ * if we are doing lots of creates/updates.
-+ */
++ * ext3_get_inode_loc returns with an extra refcount against the inode's
++ * underlying buffer_head on success. If this is for a new inode allocation
++ * (new is non-zero) then we may be able to optimize away the read if there
++ * are no other in-use inodes in this inode table block. If we need to do
++ * a read, then read in a whole chunk of blocks to avoid blocking again soon
++ * if we are doing lots of creates/updates.
++ */
+int ext3_get_inode_loc_new(struct inode *inode, struct ext3_iloc *iloc, int new)
{
struct super_block *sb = inode->i_sb;
struct ext3_sb_info *sbi = EXT3_SB(sb);
- struct buffer_head *bh = 0;
-+ struct buffer_head *bh[NUM_INODE_PREREAD];
++ struct buffer_head *bh[NUM_INODE_PREREAD];
unsigned long block;
unsigned long block_group;
unsigned long group_desc;
}
- gdp = (struct ext3_group_desc *) bh->b_data;
-+ gdp = (struct ext3_group_desc *)(sbi->s_group_desc[group_desc]->b_data);
++ gdp = (struct ext3_group_desc *)(sbi->s_group_desc[group_desc]->b_data);
/*
* Figure out the offset within the block group inode table
*/
- goto bad_inode;
- }
- offset &= (EXT3_BLOCK_SIZE(sb) - 1);
-+ (offset * EXT3_INODE_SIZE(sb) >> EXT3_BLOCK_SIZE_BITS(sb));
++ (offset * EXT3_INODE_SIZE(sb) >> EXT3_BLOCK_SIZE_BITS(sb));
- iloc->bh = bh;
- iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset);
-+ bh[0] = sb_getblk(inode->i_sb, block);
-+ if (buffer_uptodate(bh[0]))
-+ goto done;
++ bh[0] = sb_getblk(inode->i_sb, block);
++ if (buffer_uptodate(bh[0]))
++ goto done;
+
-+ /* If we don't really need to read this block, and it isn't already
-+ * in memory, then we just zero it out. Otherwise, we keep the
-+ * current block contents (deleted inode data) for posterity.
-+ */
-+ if (new && !ext3_itable_block_used(inode->i_sb, block_group, offset)) {
-+ lock_buffer(bh[0]);
-+ memset(bh[0]->b_data, 0, bh[0]->b_size);
-+ mark_buffer_uptodate(bh[0], 1);
-+ unlock_buffer(bh[0]);
-+ } else {
-+ unsigned long block_end, itable_end;
-+ int count = 1;
++ /* If we don't really need to read this block, and it isn't already
++ * in memory, then we just zero it out. Otherwise, we keep the
++ * current block contents (deleted inode data) for posterity.
++ */
++ if (new && !ext3_itable_block_used(inode->i_sb, block_group, offset)) {
++ lock_buffer(bh[0]);
++ memset(bh[0]->b_data, 0, bh[0]->b_size);
++ mark_buffer_uptodate(bh[0], 1);
++ unlock_buffer(bh[0]);
++ } else {
++ unsigned long block_end, itable_end;
++ int count = 1;
+
-+ itable_end = le32_to_cpu(gdp[desc].bg_inode_table) +
-+ inode->i_sb->u.ext3_sb.s_itb_per_group;
-+ block_end = block + NUM_INODE_PREREAD;
-+ if (block_end > itable_end)
-+ block_end = itable_end;
++ itable_end = le32_to_cpu(gdp[desc].bg_inode_table) +
++ inode->i_sb->u.ext3_sb.s_itb_per_group;
++ block_end = block + NUM_INODE_PREREAD;
++ if (block_end > itable_end)
++ block_end = itable_end;
+
-+ for (++block; block < block_end; block++) {
-+ bh[count] = sb_getblk(inode->i_sb, block);
-+ if (count && (buffer_uptodate(bh[count]) ||
-+ buffer_locked(bh[count]))) {
-+ __brelse(bh[count]);
-+ } else
-+ count++;
-+ }
++ for (++block; block < block_end; block++) {
++ bh[count] = sb_getblk(inode->i_sb, block);
++ if (count && (buffer_uptodate(bh[count]) ||
++ buffer_locked(bh[count]))) {
++ __brelse(bh[count]);
++ } else
++ count++;
++ }
+
-+ ll_rw_block(READ, count, bh);
++ ll_rw_block(READ, count, bh);
+
-+ /* Release all but the block we actually need (bh[0]) */
-+ while (--count > 0)
-+ __brelse(bh[count]);
++ /* Release all but the block we actually need (bh[0]) */
++ while (--count > 0)
++ __brelse(bh[count]);
+
-+ wait_on_buffer(bh[0]);
-+ if (!buffer_uptodate(bh[0])) {
-+ ext3_error(inode->i_sb, __FUNCTION__,
-+ "unable to read inode block - "
-+ "inode=%lu, block=%lu", inode->i_ino,
-+ bh[0]->b_blocknr);
-+ goto bad_inode;
-+ }
-+ }
-+ done:
-+ offset = (offset * EXT3_INODE_SIZE(inode->i_sb)) & (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
-+
-+ iloc->bh = bh[0];
-+ iloc->raw_inode = (struct ext3_inode *)(bh[0]->b_data + offset);
++ wait_on_buffer(bh[0]);
++ if (!buffer_uptodate(bh[0])) {
++ ext3_error(inode->i_sb, __FUNCTION__,
++ "unable to read inode block - "
++ "inode=%lu, block=%lu", inode->i_ino,
++ bh[0]->b_blocknr);
++ goto bad_inode;
++ }
++ }
++ done:
++ offset = (offset * EXT3_INODE_SIZE(inode->i_sb)) & (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
++
++ iloc->bh = bh[0];
++ iloc->raw_inode = (struct ext3_inode *)(bh[0]->b_data + offset);
iloc->block_group = block_group;
return 0;
+int ext3_get_inode_loc(struct inode *inode, struct ext3_iloc *iloc)
+{
-+ return ext3_get_inode_loc_new(inode, iloc, 0);
++ return ext3_get_inode_loc_new(inode, iloc, 0);
+}
+
void ext3_read_inode(struct inode * inode)
inode->u.ext3_i.i_state = EXT3_STATE_NEW;
- err = ext3_mark_inode_dirty(handle, inode);
- if (err) goto fail;
-+ err = ext3_get_inode_loc_new(inode, &iloc, 1);
-+ if (err) goto fail;
-+ BUFFER_TRACE(iloc->bh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, iloc.bh);
-+ if (err) {
-+ brelse(iloc.bh);
-+ iloc.bh = NULL;
-+ goto fail;
-+ }
-+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
-+ if (err) goto fail;
++ err = ext3_get_inode_loc_new(inode, &iloc, 1);
++ if (err) goto fail;
++ BUFFER_TRACE(iloc->bh, "get_write_access");
++ err = ext3_journal_get_write_access(handle, iloc.bh);
++ if (err) {
++ brelse(iloc.bh);
++ iloc.bh = NULL;
++ goto fail;
++ }
++ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
++ if (err) goto fail;
+
+
-
-int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
+#define NUM_INODE_PREREAD 16
-+
++
+/*
-+ * ext3_get_inode_loc returns with an extra refcount against the inode's
-+ * underlying buffer_head on success. If this is for a new inode allocation
-+ * (new is non-zero) then we may be able to optimize away the read if there
-+ * are no other in-use inodes in this inode table block. If we need to do
-+ * a read, then read in a whole chunk of blocks to avoid blocking again soon
-+ * if we are doing lots of creates/updates.
-+ */
++ * ext3_get_inode_loc returns with an extra refcount against the inode's
++ * underlying buffer_head on success. If this is for a new inode allocation
++ * (new is non-zero) then we may be able to optimize away the read if there
++ * are no other in-use inodes in this inode table block. If we need to do
++ * a read, then read in a whole chunk of blocks to avoid blocking again soon
++ * if we are doing lots of creates/updates.
++ */
+int ext3_get_inode_loc_new(struct inode *inode, struct ext3_iloc *iloc, int new)
{
- struct buffer_head *bh = 0;
-+ struct buffer_head *bh[NUM_INODE_PREREAD];
++ struct buffer_head *bh[NUM_INODE_PREREAD];
unsigned long block;
unsigned long block_group;
unsigned long group_desc;
}
- gdp = (struct ext3_group_desc *) bh->b_data;
-+ gdp = (struct ext3_group_desc *)(inode->i_sb->u.ext3_sb.s_group_desc[group_desc]->b_data);
++ gdp = (struct ext3_group_desc *)(inode->i_sb->u.ext3_sb.s_group_desc[group_desc]->b_data);
/*
* Figure out the offset within the block group inode table
*/
- goto bad_inode;
- }
- offset &= (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
-+ (offset * EXT3_INODE_SIZE(inode->i_sb) >> EXT3_BLOCK_SIZE_BITS(inode->i_sb));
++ (offset * EXT3_INODE_SIZE(inode->i_sb) >> EXT3_BLOCK_SIZE_BITS(inode->i_sb));
- iloc->bh = bh;
- iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset);
-+ bh[0] = sb_getblk(inode->i_sb, block);
-+ if (buffer_uptodate(bh[0]))
-+ goto done;
++ bh[0] = sb_getblk(inode->i_sb, block);
++ if (buffer_uptodate(bh[0]))
++ goto done;
+
-+ /* If we don't really need to read this block, and it isn't already
-+ * in memory, then we just zero it out. Otherwise, we keep the
-+ * current block contents (deleted inode data) for posterity.
-+ */
-+ if (new && !ext3_itable_block_used(inode->i_sb, block_group, offset)) {
-+ lock_buffer(bh[0]);
-+ memset(bh[0]->b_data, 0, bh[0]->b_size);
-+ mark_buffer_uptodate(bh[0], 1);
-+ unlock_buffer(bh[0]);
-+ } else {
-+ unsigned long block_end, itable_end;
-+ int count = 1;
++ /* If we don't really need to read this block, and it isn't already
++ * in memory, then we just zero it out. Otherwise, we keep the
++ * current block contents (deleted inode data) for posterity.
++ */
++ if (new && !ext3_itable_block_used(inode->i_sb, block_group, offset)) {
++ lock_buffer(bh[0]);
++ memset(bh[0]->b_data, 0, bh[0]->b_size);
++ mark_buffer_uptodate(bh[0], 1);
++ unlock_buffer(bh[0]);
++ } else {
++ unsigned long block_end, itable_end;
++ int count = 1;
+
-+ itable_end = le32_to_cpu(gdp[desc].bg_inode_table) +
-+ inode->i_sb->u.ext3_sb.s_itb_per_group;
-+ block_end = block + NUM_INODE_PREREAD;
-+ if (block_end > itable_end)
-+ block_end = itable_end;
++ itable_end = le32_to_cpu(gdp[desc].bg_inode_table) +
++ inode->i_sb->u.ext3_sb.s_itb_per_group;
++ block_end = block + NUM_INODE_PREREAD;
++ if (block_end > itable_end)
++ block_end = itable_end;
+
-+ for (++block; block < block_end; block++) {
-+ bh[count] = sb_getblk(inode->i_sb, block);
-+ if (count && (buffer_uptodate(bh[count]) ||
-+ buffer_locked(bh[count]))) {
-+ __brelse(bh[count]);
-+ } else
-+ count++;
-+ }
++ for (++block; block < block_end; block++) {
++ bh[count] = sb_getblk(inode->i_sb, block);
++ if (count && (buffer_uptodate(bh[count]) ||
++ buffer_locked(bh[count]))) {
++ __brelse(bh[count]);
++ } else
++ count++;
++ }
+
-+ ll_rw_block(READ, count, bh);
++ ll_rw_block(READ, count, bh);
+
-+ /* Release all but the block we actually need (bh[0]) */
-+ while (--count > 0)
-+ __brelse(bh[count]);
++ /* Release all but the block we actually need (bh[0]) */
++ while (--count > 0)
++ __brelse(bh[count]);
+
-+ wait_on_buffer(bh[0]);
-+ if (!buffer_uptodate(bh[0])) {
-+ ext3_error(inode->i_sb, __FUNCTION__,
-+ "unable to read inode block - "
-+ "inode=%lu, block=%lu", inode->i_ino,
-+ bh[0]->b_blocknr);
-+ goto bad_inode;
-+ }
-+ }
-+ done:
-+ offset = (offset * EXT3_INODE_SIZE(inode->i_sb)) & (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
-+
-+ iloc->bh = bh[0];
-+ iloc->raw_inode = (struct ext3_inode *)(bh[0]->b_data + offset);
++ wait_on_buffer(bh[0]);
++ if (!buffer_uptodate(bh[0])) {
++ ext3_error(inode->i_sb, __FUNCTION__,
++ "unable to read inode block - "
++ "inode=%lu, block=%lu", inode->i_ino,
++ bh[0]->b_blocknr);
++ goto bad_inode;
++ }
++ }
++ done:
++ offset = (offset * EXT3_INODE_SIZE(inode->i_sb)) & (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
++
++ iloc->bh = bh[0];
++ iloc->raw_inode = (struct ext3_inode *)(bh[0]->b_data + offset);
iloc->block_group = block_group;
return 0;
+int ext3_get_inode_loc(struct inode *inode, struct ext3_iloc *iloc)
+{
-+ return ext3_get_inode_loc_new(inode, iloc, 0);
++ return ext3_get_inode_loc_new(inode, iloc, 0);
+}
+
void ext3_read_inode(struct inode * inode)
sb=n Use alternate superblock at this location.
-+iopen Makes an invisible pseudo-directory called
++iopen Makes an invisible pseudo-directory called
+ __iopen__ available in the root directory
+ of the filesystem. Allows open-by-inode-
+ number. i.e., inode 3145 can be accessed
+ if (ext3_iopen_get_inode(inode))
+ return;
-+
++
if(ext3_get_inode_loc(inode, &iloc))
goto bad_inode;
bh = iloc.bh;
--- /dev/null 2003-01-30 03:24:37.000000000 -0700
+++ linux-2.4.18-p4smp-braam/fs/ext3/iopen.c 2003-07-09 17:13:02.000000000 -0600
-@@ -0,0 +1,259 @@
+@@ -0,0 +1,258 @@
+/*
+ * linux/fs/ext3/iopen.c
+ *
+ * Special support for open by inode number
+ *
+ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
-+ *
++ *
+ * This file may be redistributed under the terms of the GNU General
+ * Public License.
+ *
+ struct list_head *lp;
+ struct dentry *alternate;
+ char buf[IOPEN_NAME_LEN];
-+
++
+ if (dentry->d_name.len >= IOPEN_NAME_LEN)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ return ERR_PTR(-ENOENT);
+ }
+
++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
++ assert(list_empty(&dentry->d_hash)); /* d_rehash */
++
+ /* preferrably return a connected dentry */
+ spin_lock(&dcache_lock);
+ list_for_each(lp, &inode->i_dentry) {
+ }
+
+ if (!list_empty(&inode->i_dentry)) {
-+ alternate = list_entry(inode->i_dentry.next,
++ alternate = list_entry(inode->i_dentry.next,
+ struct dentry, d_alias);
+ dget_locked(alternate);
+ alternate->d_vfs_flags |= DCACHE_REFERENCED;
+ return alternate;
+ }
+ dentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
++
++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */
++ dentry->d_inode = inode;
++
++ __d_rehash(dentry, 0); /* d_rehash */
+ spin_unlock(&dcache_lock);
+
-+ d_add(dentry, inode);
+ return NULL;
+}
+
+{
+ const unsigned char *old_name, *new_name;
+
-+ memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN);
++ memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN);
+ old_name = target->d_name.name;
+ new_name = dentry->d_name.name;
+ if (old_name == target->d_iname)
+
+/* This function is spliced into ext3_lookup and does the move of a
+ * disconnected dentry (if it exists) to a connected dentry.
++ * Caller must hold dcache_lock.
+ */
+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode)
+{
+ struct list_head *lp;
+
+ /* preferrably return a connected dentry */
-+ spin_lock(&dcache_lock);
-+ /* verify this dentry is really new */
-+ assert(!de->d_inode);
-+ assert(list_empty(&de->d_subdirs));
-+ assert(list_empty(&de->d_alias));
-+
-+
+ list_for_each(lp, &inode->i_dentry) {
+ tmp = list_entry(lp, struct dentry, d_alias);
+ if (tmp->d_flags & DCACHE_NFSD_DISCONNECTED) {
+ }
+ }
+
-+ if (!goal) {
-+ spin_unlock(&dcache_lock);
-+ return NULL;
-+ }
++ if (!goal)
++ return NULL;
+
+ /* Move the goal to the de hash queue - like d_move() */
+ goal->d_flags &= ~DCACHE_NFSD_DISCONNECTED;
-+ list_del(&goal->d_hash);
-+ list_add(&goal->d_hash, &de->d_hash);
++ list_del_init(&goal->d_hash);
+
+ list_del(&goal->d_child);
+ list_del(&de->d_child);
+ /* And add them back to the (new) parent lists */
+ list_add(&goal->d_child, &goal->d_parent->d_subdirs);
+ list_add(&de->d_child, &de->d_parent->d_subdirs);
-+ spin_unlock(&dcache_lock);
++ __d_rehash(goal, 0);
+
+ return goal;
+}
+
+ inode = iget(dir->i_sb, EXT3_BAD_INO);
+
-+ if (!inode)
++ if (!inode)
+ return 0;
+ d_add(dentry, inode);
+ return 1;
+ inode->u.ext3_i.i_dtime = 0;
+ inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size
+ * (for stat), not the fs block
-+ * size */
++ * size */
+ inode->i_blocks = 0;
+ inode->i_version = 1;
+ inode->i_generation = 0;
+}
--- /dev/null 2003-01-30 03:24:37.000000000 -0700
+++ linux-2.4.18-p4smp-braam/fs/ext3/iopen.h 2003-07-09 17:13:02.000000000 -0600
-@@ -0,0 +1,13 @@
+@@ -0,0 +1,15 @@
+/*
+ * iopen.h
+ *
+ * Special support for opening files by inode number.
-+ *
++ *
+ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
-+ *
++ *
+ * This file may be redistributed under the terms of the GNU General
+ * Public License.
+ */
+
+extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry);
+extern int ext3_iopen_get_inode(struct inode *inode);
++extern struct dentry *iopen_connect_dentry(struct dentry *de,
++ struct inode *inode);
--- linux-2.4.18-p4smp/fs/ext3/namei.c~iopen-2.4.18 2003-07-09 13:32:38.000000000 -0600
+++ linux-2.4.18-p4smp-braam/fs/ext3/namei.c 2003-07-09 17:13:02.000000000 -0600
@@ -34,6 +34,7 @@
/*
* define how far ahead to read directories while searching them.
-@@ -703,16 +704,21 @@ cleanup_and_exit:
- return NULL;
- }
- #endif
-+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode);
-
- static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry)
- {
+@@ -709,10 +710,14 @@ cleanup_and_exit:
struct inode * inode;
struct ext3_dir_entry_2 * de;
struct buffer_head * bh;
bh = ext3_find_entry(dentry, &de);
inode = NULL;
if (bh) {
-@@ -723,6 +729,12 @@ static struct dentry *ext3_lookup(struct
+@@ -723,7 +729,28 @@ static struct dentry *ext3_lookup(struct
if (!inode)
return ERR_PTR(-EACCES);
}
+- d_add(dentry, inode);
++
++ /* verify this dentry is really new */
++ assert(!dentry->d_inode);
++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
++ assert(list_empty(&dentry->d_hash)); /* d_rehash */
++ assert(list_empty(&dentry->d_subdirs));
+
++ spin_lock(&dcache_lock);
+ if (inode && (alternate = iopen_connect_dentry(dentry, inode))) {
++ spin_unlock(&dcache_lock);
+ iput(inode);
+ return alternate;
+ }
+
- d_add(dentry, inode);
++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++ if (inode) /* d_instantiate */
++ list_add(&dentry->d_alias, &inode->i_dentry);
++ dentry->d_inode = inode;
++
++ __d_rehash(dentry, 0); /* d_rehash */
++ spin_unlock(&dcache_lock);
++
return NULL;
}
+
--- linux-2.4.18-p4smp/fs/ext3/super.c~iopen-2.4.18 2003-07-09 13:32:38.000000000 -0600
+++ linux-2.4.18-p4smp-braam/fs/ext3/super.c 2003-07-09 17:13:02.000000000 -0600
-@@ -831,6 +831,17 @@ static int parse_options (char * options
+@@ -831,6 +831,18 @@ static int parse_options (char * options
|| !strcmp (this_char, "quota")
|| !strcmp (this_char, "usrquota"))
/* Don't do anything ;-) */ ;
+ else if (!strcmp (this_char, "iopen")) {
+ set_opt (sbi->s_mount_opt, IOPEN);
+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
-+ } else if (!strcmp (this_char, "noiopen")) {
++ }
++ else if (!strcmp (this_char, "noiopen")) {
+ clear_opt (sbi->s_mount_opt, IOPEN);
+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
+ }
sb=n Use alternate superblock at this location.
-+iopen Makes an invisible pseudo-directory called
++iopen Makes an invisible pseudo-directory called
+ __iopen__ available in the root directory
+ of the filesystem. Allows open-by-inode-
+ number. i.e., inode 3145 can be accessed
+ if (ext3_iopen_get_inode(inode))
+ return;
-+
++
if(ext3_get_inode_loc(inode, &iloc))
goto bad_inode;
bh = iloc.bh;
--- /dev/null 2003-01-30 03:24:37.000000000 -0700
+++ linux-2.4.18-p4smp-braam/fs/ext3/iopen.c 2003-07-09 17:13:02.000000000 -0600
-@@ -0,0 +1,259 @@
+@@ -0,0 +1,258 @@
+/*
+ * linux/fs/ext3/iopen.c
+ *
+ * Special support for open by inode number
+ *
+ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
-+ *
++ *
+ * This file may be redistributed under the terms of the GNU General
+ * Public License.
+ *
+ struct list_head *lp;
+ struct dentry *alternate;
+ char buf[IOPEN_NAME_LEN];
-+
++
+ if (dentry->d_name.len >= IOPEN_NAME_LEN)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ return ERR_PTR(-ENOENT);
+ }
+
++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
++ assert(list_empty(&dentry->d_hash)); /* d_rehash */
++
+ /* preferrably return a connected dentry */
+ spin_lock(&dcache_lock);
+ list_for_each(lp, &inode->i_dentry) {
+ }
+
+ if (!list_empty(&inode->i_dentry)) {
-+ alternate = list_entry(inode->i_dentry.next,
++ alternate = list_entry(inode->i_dentry.next,
+ struct dentry, d_alias);
+ dget_locked(alternate);
+ alternate->d_vfs_flags |= DCACHE_REFERENCED;
+ return alternate;
+ }
+ dentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
++
++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */
++ dentry->d_inode = inode;
++
++ __d_rehash(dentry, 0); /* d_rehash */
+ spin_unlock(&dcache_lock);
+
-+ d_add(dentry, inode);
+ return NULL;
+}
+
+{
+ const unsigned char *old_name, *new_name;
+
-+ memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN);
++ memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN);
+ old_name = target->d_name.name;
+ new_name = dentry->d_name.name;
+ if (old_name == target->d_iname)
+
+/* This function is spliced into ext3_lookup and does the move of a
+ * disconnected dentry (if it exists) to a connected dentry.
++ * Caller must hold dcache_lock.
+ */
+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode)
+{
+ struct list_head *lp;
+
+ /* preferrably return a connected dentry */
-+ spin_lock(&dcache_lock);
-+ /* verify this dentry is really new */
-+ assert(!de->d_inode);
-+ assert(list_empty(&de->d_subdirs));
-+ assert(list_empty(&de->d_alias));
-+
-+
+ list_for_each(lp, &inode->i_dentry) {
+ tmp = list_entry(lp, struct dentry, d_alias);
+ if (tmp->d_flags & DCACHE_NFSD_DISCONNECTED) {
+ }
+ }
+
-+ if (!goal) {
-+ spin_unlock(&dcache_lock);
-+ return NULL;
-+ }
++ if (!goal)
++ return NULL;
+
+ /* Move the goal to the de hash queue - like d_move() */
+ goal->d_flags &= ~DCACHE_NFSD_DISCONNECTED;
+ list_add(&goal->d_child, &goal->d_parent->d_subdirs);
+ list_add(&de->d_child, &de->d_parent->d_subdirs);
+ __d_rehash(goal, 0);
-+ spin_unlock(&dcache_lock);
+
+ return goal;
+}
+
+ inode = iget(dir->i_sb, EXT3_BAD_INO);
+
-+ if (!inode)
++ if (!inode)
+ return 0;
+ d_add(dentry, inode);
+ return 1;
+ inode->u.ext3_i.i_dtime = 0;
+ inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size
+ * (for stat), not the fs block
-+ * size */
++ * size */
+ inode->i_blocks = 0;
+ inode->i_version = 1;
+ inode->i_generation = 0;
+}
--- /dev/null 2003-01-30 03:24:37.000000000 -0700
+++ linux-2.4.18-p4smp-braam/fs/ext3/iopen.h 2003-07-09 17:13:02.000000000 -0600
-@@ -0,0 +1,13 @@
+@@ -0,0 +1,15 @@
+/*
+ * iopen.h
+ *
+ * Special support for opening files by inode number.
-+ *
++ *
+ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
-+ *
++ *
+ * This file may be redistributed under the terms of the GNU General
+ * Public License.
+ */
+
+extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry);
+extern int ext3_iopen_get_inode(struct inode *inode);
++extern struct dentry *iopen_connect_dentry(struct dentry *de,
++ struct inode *inode);
--- linux-2.4.18-p4smp/fs/ext3/namei.c~iopen-2.4.18 2003-07-09 13:32:38.000000000 -0600
+++ linux-2.4.18-p4smp-braam/fs/ext3/namei.c 2003-07-09 17:13:02.000000000 -0600
@@ -34,6 +34,7 @@
/*
* define how far ahead to read directories while searching them.
-@@ -703,16 +704,21 @@ cleanup_and_exit:
- brelse (bh_use[ra_ptr]);
- return ret;
- }
-+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode);
-
- static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry)
- {
+@@ -703,10 +704,14 @@ cleanup_and_exit:
struct inode * inode;
struct ext3_dir_entry_2 * de;
struct buffer_head * bh;
bh = ext3_find_entry(dentry, &de);
inode = NULL;
if (bh) {
-@@ -723,6 +729,12 @@ static struct dentry *ext3_lookup(struct
+@@ -723,7 +729,28 @@ static struct dentry *ext3_lookup(struct
if (!inode)
return ERR_PTR(-EACCES);
}
+- d_add(dentry, inode);
++
++ /* verify this dentry is really new */
++ assert(!dentry->d_inode);
++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
++ assert(list_empty(&dentry->d_hash)); /* d_rehash */
++ assert(list_empty(&dentry->d_subdirs));
+
++ spin_lock(&dcache_lock);
+ if (inode && (alternate = iopen_connect_dentry(dentry, inode))) {
++ spin_unlock(&dcache_lock);
+ iput(inode);
+ return alternate;
+ }
+
- d_add(dentry, inode);
++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++ if (inode) /* d_instantiate */
++ list_add(&dentry->d_alias, &inode->i_dentry);
++ dentry->d_inode = inode;
++
++ __d_rehash(dentry, 0); /* d_rehash */
++ spin_unlock(&dcache_lock);
++
return NULL;
}
+
--- linux-2.4.18-p4smp/fs/ext3/super.c~iopen-2.4.18 2003-07-09 13:32:38.000000000 -0600
+++ linux-2.4.18-p4smp-braam/fs/ext3/super.c 2003-07-09 17:13:02.000000000 -0600
-@@ -831,6 +831,17 @@ static int parse_options (char * options
+@@ -831,6 +831,18 @@ static int parse_options (char * options
|| !strcmp (this_char, "quota")
|| !strcmp (this_char, "usrquota"))
/* Don't do anything ;-) */ ;
+ else if (!strcmp (this_char, "iopen")) {
+ set_opt (sbi->s_mount_opt, IOPEN);
+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
-+ } else if (!strcmp (this_char, "noiopen")) {
++ }
++ else if (!strcmp (this_char, "noiopen")) {
+ clear_opt (sbi->s_mount_opt, IOPEN);
+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
+ }
sb=n Use alternate superblock at this location.
-+iopen Makes an invisible pseudo-directory called
++iopen Makes an invisible pseudo-directory called
+ __iopen__ available in the root directory
+ of the filesystem. Allows open-by-inode-
+ number. i.e., inode 3145 can be accessed
+ if (ext3_iopen_get_inode(inode))
+ return;
-+
++
if(ext3_get_inode_loc(inode, &iloc))
goto bad_inode;
bh = iloc.bh;
===================================================================
--- linux-2.4.19.SuSE.orig/fs/ext3/iopen.c Sun Nov 16 01:27:31 2003
+++ linux-2.4.19.SuSE/fs/ext3/iopen.c Sun Nov 16 01:27:31 2003
-@@ -0,0 +1,259 @@
+@@ -0,0 +1,258 @@
+/*
+ * linux/fs/ext3/iopen.c
+ *
+ * Special support for open by inode number
+ *
+ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
-+ *
++ *
+ * This file may be redistributed under the terms of the GNU General
+ * Public License.
-+ *
++ *
+ *
+ * Invariants:
+ * - there is only ever a single DCACHE_NFSD_DISCONNECTED dentry alias
+ struct list_head *lp;
+ struct dentry *alternate;
+ char buf[IOPEN_NAME_LEN];
-+
++
+ if (dentry->d_name.len >= IOPEN_NAME_LEN)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ return ERR_PTR(-ENOENT);
+ }
+
++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
++ assert(list_empty(&dentry->d_hash)); /* d_rehash */
++
+ /* preferrably return a connected dentry */
+ spin_lock(&dcache_lock);
+ list_for_each(lp, &inode->i_dentry) {
+ }
+
+ if (!list_empty(&inode->i_dentry)) {
-+ alternate = list_entry(inode->i_dentry.next,
++ alternate = list_entry(inode->i_dentry.next,
+ struct dentry, d_alias);
+ dget_locked(alternate);
+ alternate->d_vfs_flags |= DCACHE_REFERENCED;
+ return alternate;
+ }
+ dentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
++
++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */
++ dentry->d_inode = inode;
++
++ __d_rehash(dentry, 0); /* d_rehash */
+ spin_unlock(&dcache_lock);
+
-+ d_add(dentry, inode);
+ return NULL;
+}
+
+{
+ const unsigned char *old_name, *new_name;
+
-+ memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN);
++ memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN);
+ old_name = target->d_name.name;
+ new_name = dentry->d_name.name;
+ if (old_name == target->d_iname)
+
+/* This function is spliced into ext3_lookup and does the move of a
+ * disconnected dentry (if it exists) to a connected dentry.
++ * Caller must hold dcache_lock.
+ */
+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode)
+{
+ struct list_head *lp;
+
+ /* preferrably return a connected dentry */
-+ spin_lock(&dcache_lock);
-+ /* verify this dentry is really new */
-+ assert(!de->d_inode);
-+ assert(list_empty(&de->d_subdirs));
-+ assert(list_empty(&de->d_alias));
-+
-+
+ list_for_each(lp, &inode->i_dentry) {
+ tmp = list_entry(lp, struct dentry, d_alias);
+ if (tmp->d_flags & DCACHE_NFSD_DISCONNECTED) {
+ }
+ }
+
-+ if (!goal) {
-+ spin_unlock(&dcache_lock);
-+ return NULL;
-+ }
++ if (!goal)
++ return NULL;
+
+ /* Move the goal to the de hash queue - like d_move() */
+ goal->d_flags &= ~DCACHE_NFSD_DISCONNECTED;
+ list_add(&goal->d_child, &goal->d_parent->d_subdirs);
+ list_add(&de->d_child, &de->d_parent->d_subdirs);
+ __d_rehash(goal, 0);
-+ spin_unlock(&dcache_lock);
+
+ return goal;
+}
+
+ inode = iget(dir->i_sb, EXT3_BAD_INO);
+
-+ if (!inode)
++ if (!inode)
+ return 0;
+ d_add(dentry, inode);
+ return 1;
+ inode->u.ext3_i.i_dtime = 0;
+ inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size
+ * (for stat), not the fs block
-+ * size */
++ * size */
+ inode->i_blocks = 0;
+ inode->i_version = 1;
+ inode->i_generation = 0;
===================================================================
--- linux-2.4.19.SuSE.orig/fs/ext3/iopen.h Sun Nov 16 01:27:31 2003
+++ linux-2.4.19.SuSE/fs/ext3/iopen.h Sun Nov 16 01:27:31 2003
-@@ -0,0 +1,13 @@
+@@ -0,0 +1,15 @@
+/*
+ * iopen.h
+ *
+ * Special support for opening files by inode number.
-+ *
++ *
+ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
-+ *
++ *
+ * This file may be redistributed under the terms of the GNU General
+ * Public License.
+ */
+
+extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry);
+extern int ext3_iopen_get_inode(struct inode *inode);
++extern struct dentry *iopen_connect_dentry(struct dentry *de,
++ struct inode *inode);
Index: linux-2.4.19.SuSE/fs/ext3/namei.c
===================================================================
--- linux-2.4.19.SuSE.orig/fs/ext3/namei.c Sun Nov 16 01:23:20 2003
/*
* define how far ahead to read directories while searching them.
-@@ -922,16 +922,21 @@
- return NULL;
- }
- #endif
-+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode);
-
- static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry)
- {
+@@ -922,10 +922,14 @@
struct inode * inode;
struct ext3_dir_entry_2 * de;
struct buffer_head * bh;
bh = ext3_find_entry(dentry, &de);
inode = NULL;
if (bh) {
-@@ -943,6 +948,12 @@
+@@ -943,7 +948,28 @@
return ERR_PTR(-EACCES);
}
}
+- d_add(dentry, inode);
++
++ /* verify this dentry is really new */
++ assert(!dentry->d_inode);
++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
++ assert(list_empty(&dentry->d_hash)); /* d_rehash */
++ assert(list_empty(&dentry->d_subdirs));
+
++ spin_lock(&dcache_lock);
+ if (inode && (alternate = iopen_connect_dentry(dentry, inode))) {
++ spin_unlock(&dcache_lock);
+ iput(inode);
+ return alternate;
+ }
+
- d_add(dentry, inode);
++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++ if (inode) /* d_instantiate */
++ list_add(&dentry->d_alias, &inode->i_dentry);
++ dentry->d_inode = inode;
++
++ __d_rehash(dentry, 0); /* d_rehash */
++ spin_unlock(&dcache_lock);
++
return NULL;
}
+
Index: linux-2.4.19.SuSE/fs/ext3/super.c
===================================================================
--- linux-2.4.19.SuSE.orig/fs/ext3/super.c Sun Nov 16 01:19:22 2003
+++ linux-2.4.19.SuSE/fs/ext3/super.c Sun Nov 16 01:27:31 2003
-@@ -864,6 +864,17 @@
+@@ -864,6 +864,18 @@
|| !strcmp (this_char, "quota")
|| !strcmp (this_char, "usrquota"))
/* Don't do anything ;-) */ ;
+ else if (!strcmp (this_char, "iopen")) {
+ set_opt (sbi->s_mount_opt, IOPEN);
+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
-+ } else if (!strcmp (this_char, "noiopen")) {
++ }
++ else if (!strcmp (this_char, "noiopen")) {
+ clear_opt (sbi->s_mount_opt, IOPEN);
+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
+ }
include/linux/ext3_fs.h | 2
8 files changed, 318 insertions(+), 2 deletions(-)
---- linux/Documentation/filesystems/ext2.txt~iopen-2.4.20 Wed Jul 11 15:44:45 2001
-+++ linux-mmonroe/Documentation/filesystems/ext2.txt Thu Jul 10 12:28:54 2003
-@@ -35,6 +35,22 @@ resgid=n The group ID which may use th
+Index: linux-2.4.22-uml/Documentation/filesystems/ext2.txt
+===================================================================
+--- linux-2.4.22-uml.orig/Documentation/filesystems/ext2.txt 2001-07-11 16:44:45.000000000 -0600
++++ linux-2.4.22-uml/Documentation/filesystems/ext2.txt 2004-01-30 14:18:10.000000000 -0700
+@@ -35,6 +35,22 @@
sb=n Use alternate superblock at this location.
-+iopen Makes an invisible pseudo-directory called
++iopen Makes an invisible pseudo-directory called
+ __iopen__ available in the root directory
+ of the filesystem. Allows open-by-inode-
+ number. i.e., inode 3145 can be accessed
grpquota,noquota,quota,usrquota Quota options are silently ignored by ext2.
---- linux/fs/ext3/Makefile~iopen-2.4.20 Thu Jul 10 12:28:44 2003
-+++ linux-mmonroe/fs/ext3/Makefile Thu Jul 10 12:28:54 2003
-@@ -11,7 +11,7 @@ O_TARGET := ext3.o
+Index: linux-2.4.22-uml/fs/ext3/Makefile
+===================================================================
+--- linux-2.4.22-uml.orig/fs/ext3/Makefile 2004-01-30 14:17:58.000000000 -0700
++++ linux-2.4.22-uml/fs/ext3/Makefile 2004-01-30 14:18:10.000000000 -0700
+@@ -11,7 +11,7 @@
export-objs := ext3-exports.o
ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o
obj-m := $(O_TARGET)
---- linux/fs/ext3/inode.c~iopen-2.4.20 Thu Jul 10 12:28:46 2003
-+++ linux-mmonroe/fs/ext3/inode.c Thu Jul 10 12:28:54 2003
+Index: linux-2.4.22-uml/fs/ext3/inode.c
+===================================================================
+--- linux-2.4.22-uml.orig/fs/ext3/inode.c 2004-01-30 14:17:59.000000000 -0700
++++ linux-2.4.22-uml/fs/ext3/inode.c 2004-01-30 14:18:10.000000000 -0700
@@ -31,6 +31,7 @@
#include <linux/highuid.h>
#include <linux/quotaops.h>
/*
* SEARCH_FROM_ZERO forces each block allocation to search from the start
-@@ -2253,6 +2254,9 @@ void ext3_read_inode(struct inode * inod
+@@ -2153,6 +2154,9 @@
struct buffer_head *bh;
int block;
+ if (ext3_iopen_get_inode(inode))
+ return;
-+
++
if(ext3_get_inode_loc(inode, &iloc))
goto bad_inode;
bh = iloc.bh;
---- /dev/null Tue Jan 28 04:00:01 2003
-+++ linux-mmonroe/fs/ext3/iopen.c Thu Jul 10 12:28:54 2003
-@@ -0,0 +1,259 @@
+Index: linux-2.4.22-uml/fs/ext3/iopen.c
+===================================================================
+--- linux-2.4.22-uml.orig/fs/ext3/iopen.c 2004-01-30 14:18:10.000000000 -0700
++++ linux-2.4.22-uml/fs/ext3/iopen.c 2004-01-30 14:18:10.000000000 -0700
+@@ -0,0 +1,258 @@
+/*
+ * linux/fs/ext3/iopen.c
+ *
+ * Special support for open by inode number
+ *
+ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
-+ *
++ *
+ * This file may be redistributed under the terms of the GNU General
+ * Public License.
-+ *
++ *
+ *
+ * Invariants:
+ * - there is only ever a single DCACHE_NFSD_DISCONNECTED dentry alias
+ struct list_head *lp;
+ struct dentry *alternate;
+ char buf[IOPEN_NAME_LEN];
-+
++
+ if (dentry->d_name.len >= IOPEN_NAME_LEN)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ return ERR_PTR(-ENOENT);
+ }
+
++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
++ assert(list_empty(&dentry->d_hash)); /* d_rehash */
++
+ /* preferrably return a connected dentry */
+ spin_lock(&dcache_lock);
+ list_for_each(lp, &inode->i_dentry) {
+ }
+
+ if (!list_empty(&inode->i_dentry)) {
-+ alternate = list_entry(inode->i_dentry.next,
++ alternate = list_entry(inode->i_dentry.next,
+ struct dentry, d_alias);
+ dget_locked(alternate);
+ alternate->d_vfs_flags |= DCACHE_REFERENCED;
+ return alternate;
+ }
+ dentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
++
++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */
++ dentry->d_inode = inode;
++
++ __d_rehash(dentry, 0); /* d_rehash */
+ spin_unlock(&dcache_lock);
+
-+ d_add(dentry, inode);
+ return NULL;
+}
+
+{
+ const unsigned char *old_name, *new_name;
+
-+ memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN);
++ memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN);
+ old_name = target->d_name.name;
+ new_name = dentry->d_name.name;
+ if (old_name == target->d_iname)
+
+/* This function is spliced into ext3_lookup and does the move of a
+ * disconnected dentry (if it exists) to a connected dentry.
++ * Caller must hold dcache_lock.
+ */
+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode)
+{
+ struct list_head *lp;
+
+ /* preferrably return a connected dentry */
-+ spin_lock(&dcache_lock);
-+ /* verify this dentry is really new */
-+ assert(!de->d_inode);
-+ assert(list_empty(&de->d_subdirs));
-+ assert(list_empty(&de->d_alias));
-+
-+
+ list_for_each(lp, &inode->i_dentry) {
+ tmp = list_entry(lp, struct dentry, d_alias);
+ if (tmp->d_flags & DCACHE_NFSD_DISCONNECTED) {
+ }
+ }
+
-+ if (!goal) {
-+ spin_unlock(&dcache_lock);
-+ return NULL;
-+ }
++ if (!goal)
++ return NULL;
+
+ /* Move the goal to the de hash queue - like d_move() */
+ goal->d_flags &= ~DCACHE_NFSD_DISCONNECTED;
+ list_add(&goal->d_child, &goal->d_parent->d_subdirs);
+ list_add(&de->d_child, &de->d_parent->d_subdirs);
+ __d_rehash(goal, 0);
-+ spin_unlock(&dcache_lock);
+
+ return goal;
+}
+
+ inode = iget(dir->i_sb, EXT3_BAD_INO);
+
-+ if (!inode)
++ if (!inode)
+ return 0;
+ d_add(dentry, inode);
+ return 1;
+ inode->u.ext3_i.i_dtime = 0;
+ inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size
+ * (for stat), not the fs block
-+ * size */
++ * size */
+ inode->i_blocks = 0;
+ inode->i_version = 1;
+ inode->i_generation = 0;
+
+ return 1;
+}
---- /dev/null Tue Jan 28 04:00:01 2003
-+++ linux-mmonroe/fs/ext3/iopen.h Thu Jul 10 12:28:54 2003
-@@ -0,0 +1,13 @@
+Index: linux-2.4.22-uml/fs/ext3/iopen.h
+===================================================================
+--- linux-2.4.22-uml.orig/fs/ext3/iopen.h 2004-01-30 14:18:10.000000000 -0700
++++ linux-2.4.22-uml/fs/ext3/iopen.h 2004-01-30 14:18:10.000000000 -0700
+@@ -0,0 +1,15 @@
+/*
+ * iopen.h
+ *
+ * Special support for opening files by inode number.
-+ *
++ *
+ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
-+ *
++ *
+ * This file may be redistributed under the terms of the GNU General
+ * Public License.
+ */
+
+extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry);
+extern int ext3_iopen_get_inode(struct inode *inode);
---- linux/fs/ext3/namei.c~iopen-2.4.20 Thu Jul 10 12:28:46 2003
-+++ linux-mmonroe/fs/ext3/namei.c Thu Jul 10 12:28:54 2003
++extern struct dentry *iopen_connect_dentry(struct dentry *de,
++ struct inode *inode);
+Index: linux-2.4.22-uml/fs/ext3/namei.c
+===================================================================
+--- linux-2.4.22-uml.orig/fs/ext3/namei.c 2004-01-30 14:17:59.000000000 -0700
++++ linux-2.4.22-uml/fs/ext3/namei.c 2004-01-30 14:19:44.000000000 -0700
@@ -35,7 +35,7 @@
#include <linux/string.h>
#include <linux/locks.h>
/*
* define how far ahead to read directories while searching them.
-@@ -921,16 +921,21 @@ errout:
- return NULL;
- }
- #endif
-+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode);
-
- static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry)
- {
+@@ -927,10 +927,14 @@
struct inode * inode;
struct ext3_dir_entry_2 * de;
struct buffer_head * bh;
bh = ext3_find_entry(dentry, &de);
inode = NULL;
if (bh) {
-@@ -942,6 +947,12 @@ static struct dentry *ext3_lookup(struct
+@@ -942,7 +946,28 @@
return ERR_PTR(-EACCES);
}
}
+- d_add(dentry, inode);
++
++ /* verify this dentry is really new */
++ assert(!dentry->d_inode);
++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
++ assert(list_empty(&dentry->d_hash)); /* d_rehash */
++ assert(list_empty(&dentry->d_subdirs));
+
++ spin_lock(&dcache_lock);
+ if (inode && (alternate = iopen_connect_dentry(dentry, inode))) {
++ spin_unlock(&dcache_lock);
+ iput(inode);
+ return alternate;
+ }
+
- d_add(dentry, inode);
++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++ if (inode) /* d_instantiate */
++ list_add(&dentry->d_alias, &inode->i_dentry);
++ dentry->d_inode = inode;
++
++ __d_rehash(dentry, 0); /* d_rehash */
++ spin_unlock(&dcache_lock);
++
return NULL;
}
---- linux/fs/ext3/super.c~iopen-2.4.20 Thu Jul 10 12:28:45 2003
-+++ linux-mmonroe/fs/ext3/super.c Thu Jul 10 12:28:54 2003
-@@ -835,6 +835,17 @@ static int parse_options (char * options
+
+Index: linux-2.4.22-uml/fs/ext3/super.c
+===================================================================
+--- linux-2.4.22-uml.orig/fs/ext3/super.c Sun Nov 16 01:19:22 2003
++++ linux-2.4.22-uml/fs/ext3/super.c Sun Nov 16 01:27:31 2003
+@@ -839,6 +839,18 @@
|| !strcmp (this_char, "quota")
|| !strcmp (this_char, "usrquota"))
/* Don't do anything ;-) */ ;
+ else if (!strcmp (this_char, "iopen")) {
+ set_opt (sbi->s_mount_opt, IOPEN);
+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
-+ } else if (!strcmp (this_char, "noiopen")) {
++ }
++ else if (!strcmp (this_char, "noiopen")) {
+ clear_opt (sbi->s_mount_opt, IOPEN);
+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
+ }
else if (!strcmp (this_char, "journal")) {
/* @@@ FIXME */
/* Eventually we will want to be able to create
---- linux/include/linux/ext3_fs.h~iopen-2.4.20 Thu Jul 10 12:28:46 2003
-+++ linux-mmonroe/include/linux/ext3_fs.h Thu Jul 10 12:30:12 2003
-@@ -322,6 +322,8 @@ struct ext3_inode {
+Index: linux-2.4.22-uml/include/linux/ext3_fs.h
+===================================================================
+--- linux-2.4.22-uml.orig/include/linux/ext3_fs.h 2004-01-30 14:17:59.000000000 -0700
++++ linux-2.4.22-uml/include/linux/ext3_fs.h 2004-01-30 14:18:10.000000000 -0700
+@@ -322,6 +322,8 @@
#define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */
#define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
#define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
#define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
-
-_
sb=n Use alternate superblock at this location.
-+iopen Makes an invisible pseudo-directory called
++iopen Makes an invisible pseudo-directory called
+ __iopen__ available in the root directory
+ of the filesystem. Allows open-by-inode-
+ number. i.e., inode 3145 can be accessed
+ if (ext3_iopen_get_inode(inode))
+ return;
-+
++
if(ext3_get_inode_loc(inode, &iloc))
goto bad_inode;
bh = iloc.bh;
===================================================================
--- linux-2.4.21-chaos.orig/fs/ext3/iopen.c 2003-01-30 13:24:37.000000000 +0300
+++ linux-2.4.21-chaos/fs/ext3/iopen.c 2003-12-12 16:19:05.000000000 +0300
-@@ -0,0 +1,259 @@
+@@ -0,0 +1,258 @@
+/*
+ * linux/fs/ext3/iopen.c
+ *
+ * Special support for open by inode number
+ *
+ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
-+ *
++ *
+ * This file may be redistributed under the terms of the GNU General
+ * Public License.
-+ *
++ *
+ *
+ * Invariants:
+ * - there is only ever a single DCACHE_NFSD_DISCONNECTED dentry alias
+ struct list_head *lp;
+ struct dentry *alternate;
+ char buf[IOPEN_NAME_LEN];
-+
++
+ if (dentry->d_name.len >= IOPEN_NAME_LEN)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ return ERR_PTR(-ENOENT);
+ }
+
++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
++ assert(list_empty(&dentry->d_hash)); /* d_rehash */
++
+ /* preferrably return a connected dentry */
+ spin_lock(&dcache_lock);
+ list_for_each(lp, &inode->i_dentry) {
+ }
+
+ if (!list_empty(&inode->i_dentry)) {
-+ alternate = list_entry(inode->i_dentry.next,
++ alternate = list_entry(inode->i_dentry.next,
+ struct dentry, d_alias);
+ dget_locked(alternate);
+ alternate->d_vfs_flags |= DCACHE_REFERENCED;
+ return alternate;
+ }
+ dentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
++
++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */
++ dentry->d_inode = inode;
++
++ __d_rehash(dentry, 0); /* d_rehash */
+ spin_unlock(&dcache_lock);
+
-+ d_add(dentry, inode);
+ return NULL;
+}
+
+{
+ const unsigned char *old_name, *new_name;
+
-+ memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN);
++ memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN);
+ old_name = target->d_name.name;
+ new_name = dentry->d_name.name;
+ if (old_name == target->d_iname)
+
+/* This function is spliced into ext3_lookup and does the move of a
+ * disconnected dentry (if it exists) to a connected dentry.
++ * Caller must hold dcache_lock.
+ */
+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode)
+{
+ struct list_head *lp;
+
+ /* preferrably return a connected dentry */
-+ spin_lock(&dcache_lock);
-+ /* verify this dentry is really new */
-+ assert(!de->d_inode);
-+ assert(list_empty(&de->d_subdirs));
-+ assert(list_empty(&de->d_alias));
-+
-+
+ list_for_each(lp, &inode->i_dentry) {
+ tmp = list_entry(lp, struct dentry, d_alias);
+ if (tmp->d_flags & DCACHE_NFSD_DISCONNECTED) {
+ }
+ }
+
-+ if (!goal) {
-+ spin_unlock(&dcache_lock);
-+ return NULL;
-+ }
++ if (!goal)
++ return NULL;
+
+ /* Move the goal to the de hash queue - like d_move() */
+ goal->d_flags &= ~DCACHE_NFSD_DISCONNECTED;
+ list_add(&goal->d_child, &goal->d_parent->d_subdirs);
+ list_add(&de->d_child, &de->d_parent->d_subdirs);
+ __d_rehash(goal, 0);
-+ spin_unlock(&dcache_lock);
+
+ return goal;
+}
+
+ inode = iget(dir->i_sb, EXT3_BAD_INO);
+
-+ if (!inode)
++ if (!inode)
+ return 0;
+ d_add(dentry, inode);
+ return 1;
+ inode->u.ext3_i.i_dtime = 0;
+ inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size
+ * (for stat), not the fs block
-+ * size */
++ * size */
+ inode->i_blocks = 0;
+ inode->i_version = 1;
+ inode->i_generation = 0;
===================================================================
--- linux-2.4.21-chaos.orig/fs/ext3/iopen.h 2003-01-30 13:24:37.000000000 +0300
+++ linux-2.4.21-chaos/fs/ext3/iopen.h 2003-12-12 16:19:05.000000000 +0300
-@@ -0,0 +1,13 @@
+@@ -0,0 +1,15 @@
+/*
+ * iopen.h
+ *
+ * Special support for opening files by inode number.
-+ *
++ *
+ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
-+ *
++ *
+ * This file may be redistributed under the terms of the GNU General
+ * Public License.
+ */
+
+extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry);
+extern int ext3_iopen_get_inode(struct inode *inode);
++extern struct dentry *iopen_connect_dentry(struct dentry *de,
++ struct inode *inode);
Index: linux-2.4.21-chaos/fs/ext3/namei.c
===================================================================
--- linux-2.4.21-chaos.orig/fs/ext3/namei.c 2003-12-12 16:18:59.000000000 +0300
/*
* define how far ahead to read directories while searching them.
-@@ -922,16 +922,21 @@
- return NULL;
- }
- #endif
-+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode);
-
- static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry)
- {
+@@ -922,10 +922,14 @@
struct inode * inode;
struct ext3_dir_entry_2 * de;
struct buffer_head * bh;
bh = ext3_find_entry(dentry, &de);
inode = NULL;
if (bh) {
-@@ -943,6 +948,12 @@
+@@ -943,7 +948,28 @@
return ERR_PTR(-EACCES);
}
}
+- d_add(dentry, inode);
++
++ /* verify this dentry is really new */
++ assert(!dentry->d_inode);
++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
++ assert(list_empty(&dentry->d_hash)); /* d_rehash */
++ assert(list_empty(&dentry->d_subdirs));
+
++ spin_lock(&dcache_lock);
+ if (inode && (alternate = iopen_connect_dentry(dentry, inode))) {
++ spin_unlock(&dcache_lock);
+ iput(inode);
+ return alternate;
+ }
+
- d_add(dentry, inode);
++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++ if (inode) /* d_instantiate */
++ list_add(&dentry->d_alias, &inode->i_dentry);
++ dentry->d_inode = inode;
++
++ __d_rehash(dentry, 0); /* d_rehash */
++ spin_unlock(&dcache_lock);
++
return NULL;
}
+
Index: linux-2.4.21-chaos/fs/ext3/super.c
===================================================================
--- linux-2.4.21-chaos.orig/fs/ext3/super.c 2003-12-12 16:18:51.000000000 +0300
+++ linux-2.4.21-chaos/fs/ext3/super.c 2003-12-12 16:19:05.000000000 +0300
-@@ -890,6 +890,17 @@
+@@ -890,6 +890,18 @@
|| !strcmp (this_char, "quota")
|| !strcmp (this_char, "usrquota"))
/* Don't do anything ;-) */ ;
+ else if (!strcmp (this_char, "iopen")) {
+ set_opt (sbi->s_mount_opt, IOPEN);
+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
-+ } else if (!strcmp (this_char, "noiopen")) {
++ }
++ else if (!strcmp (this_char, "noiopen")) {
+ clear_opt (sbi->s_mount_opt, IOPEN);
+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
+ }
{
struct dentry * result;
struct inode *dir = parent->d_inode;
-+ int counter = 0;
++ int counter = 0;
+again:
-+ counter++;
++ counter++;
down(&dir->i_sem);
/*
* First re-do the cached lookup just in case it was created
+ if (!result->d_op->d_revalidate_it(result, flags, it) &&
+ !d_invalidate(result)) {
+ dput(result);
-+ if (counter > 10)
-+ result = ERR_PTR(-ESTALE);
-+ if (!IS_ERR(result))
-+ goto again;
++ if (counter > 10)
++ result = ERR_PTR(-ESTALE);
++ if (!IS_ERR(result))
++ goto again;
+ }
}
return result;
{
struct inode * inode = dentry->d_inode;
- if (inode->i_op && inode->i_op->revalidate)
-+ if (!inode)
-+ return -ENOENT;
++ if (!inode)
++ return -ENOENT;
+ if (inode->i_op && inode->i_op->revalidate_it)
+ return inode->i_op->revalidate_it(dentry, it);
+ else if (inode->i_op && inode->i_op->revalidate)
+ &dentry->d_name, 0, NULL);
+ d_invalidate(dentry);
+ dput(dentry);
-+ if (IS_ERR(new)) {
-+ err = PTR_ERR(new);
-+ break;
-+ }
-+ nd->dentry = new;
++ if (IS_ERR(new)) {
++ err = PTR_ERR(new);
++ break;
++ }
++ nd->dentry = new;
+ }
+ } else
+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
{
struct inode * inode = dentry->d_inode;
- if (inode->i_op && inode->i_op->revalidate)
-+ if (!inode)
-+ return -ENOENT;
++ if (!inode)
++ return -ENOENT;
+ if (inode->i_op && inode->i_op->revalidate_it)
+ return inode->i_op->revalidate_it(dentry, it);
+ else if (inode->i_op && inode->i_op->revalidate)
+ &dentry->d_name, 0, NULL);
+ d_invalidate(dentry);
+ dput(dentry);
-+ if (IS_ERR(new)) {
-+ err = PTR_ERR(new);
-+ break;
-+ }
-+ nd->dentry = new;
++ if (IS_ERR(new)) {
++ err = PTR_ERR(new);
++ break;
++ }
++ nd->dentry = new;
+ }
+ } else
if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
{
struct inode * inode = dentry->d_inode;
- if (inode->i_op && inode->i_op->revalidate)
-+ if (!inode)
-+ return -ENOENT;
++ if (!inode)
++ return -ENOENT;
+ if (inode->i_op && inode->i_op->revalidate_it)
+ return inode->i_op->revalidate_it(dentry, it);
+ else if (inode->i_op && inode->i_op->revalidate)
+ &dentry->d_name, 0, NULL);
+ d_invalidate(dentry);
+ dput(dentry);
-+ if (IS_ERR(new)) {
-+ err = PTR_ERR(new);
-+ break;
-+ }
-+ nd->dentry = new;
++ if (IS_ERR(new)) {
++ err = PTR_ERR(new);
++ break;
++ }
++ nd->dentry = new;
+ }
+ } else
if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
{
struct inode * inode = dentry->d_inode;
- if (inode->i_op && inode->i_op->revalidate)
-+ if (!inode)
-+ return -ENOENT;
++ if (!inode)
++ return -ENOENT;
+ if (inode->i_op && inode->i_op->revalidate_it)
+ return inode->i_op->revalidate_it(dentry, it);
+ else if (inode->i_op && inode->i_op->revalidate)
{
struct inode * inode = dentry->d_inode;
- if (inode->i_op && inode->i_op->revalidate)
-+ if (!inode)
-+ return -ENOENT;
++ if (!inode)
++ return -ENOENT;
+ if (inode->i_op && inode->i_op->revalidate_it)
+ return inode->i_op->revalidate_it(dentry, it);
+ else if (inode->i_op && inode->i_op->revalidate)
{
struct inode * inode = dentry->d_inode;
- if (inode->i_op && inode->i_op->revalidate)
-+ if (!inode)
-+ return -ENOENT;
++ if (!inode)
++ return -ENOENT;
+ if (inode->i_op && inode->i_op->revalidate_it)
+ return inode->i_op->revalidate_it(dentry, it);
+ else if (inode->i_op && inode->i_op->revalidate)
{
struct inode * inode = dentry->d_inode;
- if (inode->i_op && inode->i_op->revalidate)
-+ if (!inode)
-+ return -ENOENT;
++ if (!inode)
++ return -ENOENT;
+ if (inode->i_op && inode->i_op->revalidate_it)
+ return inode->i_op->revalidate_it(dentry, it);
+ else if (inode->i_op && inode->i_op->revalidate)
{
struct inode * inode = dentry->d_inode;
- if (inode->i_op && inode->i_op->revalidate)
-+ if (!inode)
-+ return -ENOENT;
++ if (!inode)
++ return -ENOENT;
+ if (inode->i_op && inode->i_op->revalidate_it)
+ return inode->i_op->revalidate_it(dentry, it);
+ else if (inode->i_op && inode->i_op->revalidate)
{
struct dentry * result;
struct inode *dir = parent->d_inode;
-+ int counter = 0;
++ int counter = 0;
+again:
-+ counter++;
++ counter++;
down(&dir->i_sem);
/*
* First re-do the cached lookup just in case it was created
if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) {
dput(result);
- result = ERR_PTR(-ENOENT);
-+ if (counter > 10)
-+ result = ERR_PTR(-ESTALE);
-+ if (!IS_ERR(result))
-+ goto again;
++ if (counter > 10)
++ result = ERR_PTR(-ESTALE);
++ if (!IS_ERR(result))
++ goto again;
}
}
return result;
{
struct dentry * result;
struct inode *dir = parent->d_inode;
-+ int counter = 0;
++ int counter = 0;
+again:
-+ counter++;
++ counter++;
down(&dir->i_sem);
/*
* First re-do the cached lookup just in case it was created
if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) {
dput(result);
- result = ERR_PTR(-ENOENT);
-+ if (counter > 10)
-+ result = ERR_PTR(-ESTALE);
-+ if (!IS_ERR(result))
-+ goto again;
++ if (counter > 10)
++ result = ERR_PTR(-ESTALE);
++ if (!IS_ERR(result))
++ goto again;
}
}
return result;
{
struct dentry * result;
struct inode *dir = parent->d_inode;
-+ int counter = 0;
++ int counter = 0;
+again:
-+ counter++;
++ counter++;
down(&dir->i_sem);
/*
* First re-do the cached lookup just in case it was created
if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) {
dput(result);
- result = ERR_PTR(-ENOENT);
-+ if (counter > 10)
-+ result = ERR_PTR(-ESTALE);
-+ if (!IS_ERR(result))
-+ goto again;
++ if (counter > 10)
++ result = ERR_PTR(-ESTALE);
++ if (!IS_ERR(result))
++ goto again;
}
}
return result;