From 00ff7c94cff6fea25da417f6160ec5883c3d0877 Mon Sep 17 00:00:00 2001 From: adilger Date: Fri, 29 Mar 2002 06:58:54 +0000 Subject: [PATCH] Add in a delete_inode method for use when the inode is finally unlinked, so that we can clear out the objid if necessary. Since delete_inode is handled by a callback from the VFS when n_link == 0 (and we don't want to introduce race conditions by checking this at unlink time), we replace the client delete_inode method with a filesystem-specific MDS delete_inode call, and then call the client delete_inode method from within our MDS delete_inode operation. --- lustre/mds/mds_ext2.c | 13 ++++++ lustre/mds/mds_ext3.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 124 insertions(+), 6 deletions(-) diff --git a/lustre/mds/mds_ext2.c b/lustre/mds/mds_ext2.c index 4649322..f2a24b2 100644 --- a/lustre/mds/mds_ext2.c +++ b/lustre/mds/mds_ext2.c @@ -76,6 +76,17 @@ static ssize_t mds_ext2_readpage(struct file *file, char *buf, size_t count, return generic_file_read(file, buf, count, offset); } +struct mds_fs_operations mds_ext2_fs_ops; + +void mds_ext2_delete_inode(struct inode * inode) +{ + if (!S_ISDIR(inode->i_mode)) + mds_ext2_set_objid(inode, NULL, 0); + + if (mds_ext2_fs_ops.cl_delete_inode) + mds_ext2_fs_ops.cl_delete_inode(inode); +} + struct mds_fs_operations mds_ext2_fs_ops = { fs_start: mds_ext2_start, fs_commit: mds_ext2_stop, @@ -83,4 +94,6 @@ struct mds_fs_operations mds_ext2_fs_ops = { fs_set_objid: mds_ext2_set_objid, fs_get_objid: mds_ext2_get_objid, fs_readpage: mds_ext2_readpage, + fs_delete_inode:mds_ext2_delete_inode, + cl_delete_inode:NULL, }; diff --git a/lustre/mds/mds_ext3.c b/lustre/mds/mds_ext3.c index 7f14e30..de62b4f 100644 --- a/lustre/mds/mds_ext3.c +++ b/lustre/mds/mds_ext3.c @@ -33,19 +33,124 @@ static void *mds_ext3_start(struct inode *inode, int op) int nblocks = 0; switch(op) { - case MDS_JOP_RMDIR: - case MDS_JOP_UNLINK: nblocks = EXT3_DELETE_TRANS_BLOCKS; break; + case MDS_FSOP_RMDIR: + case MDS_FSOP_UNLINK: nblocks = EXT3_DELETE_TRANS_BLOCKS; break; } return journal_start(EXT3_JOURNAL(inode), nblocks); } -static int mds_ext3_stop(void *handle, struct inode *inode) +static int mds_ext3_commit(struct inode *inode, void *handle) { return journal_stop((handle_t *)handle); } -struct mds_journal_operations mds_ext3_journal_ops = { - tr_start: mds_ext3_start, - tr_commit: mds_ext3_stop, +static int mds_ext3_setattr(struct inode *inode, void *handle, + struct iattr *iattr) +{ + /* a _really_ horrible hack to avoid removing the data stored + in the block pointers; this data is the object id + this will go into an extended attribute at some point. + */ + if ( iattr->ia_valid & ATTR_SIZE ) { + /* ATTR_SIZE would invoke truncate: clear it */ + iattr->ia_valid &= ~ATTR_SIZE; + inode->i_size = iattr->ia_size; + + /* an _even_more_ horrible hack to make this hack work with + * ext3. This is because ext3 keeps a separate inode size + * until the inode is committed to ensure consistency. This + * will also go away with the move to EAs. + */ + EXT3_I(inode)->i_disksize = inode->i_size; + + /* make sure _something_ gets set - so new inode + goes to disk (probably won't work over XFS */ + if (!iattr->ia_valid & ATTR_MODE) { + iattr->ia_valid |= ATTR_MODE; + iattr->ia_mode = inode->i_mode; + } + } + + return 0; +} + +/* + * FIXME: nasty hack - store the object id in the first two + * direct block spots. This should be done with EAs... + */ +static int mds_ext3_set_objid(struct inode *inode, void *handle, obd_id id) +{ + memcpy(&EXT3_I(inode)->i_data, &id, sizeof(id)); + + return 0; +} + +static void mds_ext3_get_objid(struct inode *inode, obd_id *id) +{ + memcpy(id, &EXT3_I(inode)->i_data, sizeof(*id)); +} + +static ssize_t mds_ext3_readpage(struct file *file, char *buf, size_t count, + loff_t *offset) +{ + struct inode *inode = file->f_dentry->d_inode; + int rc = 0; + + if (S_ISREG(inode->i_mode)) + rc = file->f_op->read(file, buf, count, offset); + else { + struct buffer_head *bh; + + /* FIXME: this assumes the blocksize == count, but the calling + * function will detect this as an error for now */ + bh = ext3_bread(NULL, inode, + *offset >> inode->i_sb->s_blocksize_bits, + 0, &rc); + + if (bh) { + memcpy(buf, bh->b_data, inode->i_blksize); + brelse(bh); + rc = inode->i_blksize; + } + } + + return rc; +} + +struct mds_fs_operations mds_ext3_fs_ops; + +void mds_ext3_delete_inode(struct inode * inode) +{ + void *handle; + + if (!S_ISDIR(inode->i_mode)) { + handle = mds_ext3_start(inode, MDS_FSOP_UNLINK); + + if (!IS_ERR(handle)) { + CERROR("unable to start transaction"); + EXIT; + return; + } + if (mds_ext3_set_objid(inode, handle, 0)) + CERROR("error clearing objid on %ld\n", inode->i_ino); + + if (mds_ext3_fs_ops.cl_delete_inode) + mds_ext3_fs_ops.cl_delete_inode(inode); + + if (mds_ext3_commit(inode, handle)) + CERROR("error closing handle on %ld\n", inode->i_ino); + } else if (mds_ext3_fs_ops.cl_delete_inode) + mds_ext3_fs_ops.cl_delete_inode(inode); +} + +struct mds_fs_operations mds_ext3_fs_ops = { + fs_start: mds_ext3_start, + fs_commit: mds_ext3_commit, + fs_setattr: mds_ext3_setattr, + fs_set_objid: mds_ext3_set_objid, + fs_get_objid: mds_ext3_get_objid, + fs_readpage: mds_ext3_readpage, + fs_delete_inode:mds_ext3_delete_inode, + cl_delete_inode:NULL, }; -- 1.8.3.1