struct mds_fs_operations {
void *(* fs_start)(struct inode *inode, int op);
int (* fs_commit)(struct inode *inode, void *handle);
- int (* fs_setattr)(struct inode *inode, void *handle,
+ int (* fs_setattr)(struct dentry *dentry, void *handle,
struct iattr *iattr);
int (* fs_set_objid)(struct inode *inode, void *handle, obd_id id);
void (* fs_get_objid)(struct inode *inode, obd_id *id);
void (* cl_delete_inode)(struct inode *inode);
};
-#define MDS_FSOP_UNLINK 1
-#define MDS_FSOP_RMDIR 2
+#define MDS_FSOP_UNLINK 1
+#define MDS_FSOP_RMDIR 2
+#define MDS_FSOP_RENAME 3
+#define MDS_FSOP_CREATE 4
+#define MDS_FSOP_MKDIR 5
+#define MDS_FSOP_SYMLINK 6
+#define MDS_FSOP_MKNOD 7
static inline void *mds_fs_start(struct mds_obd *mds, struct inode *inode,
int op)
return mds->mds_fsops->fs_commit(inode, handle);
}
-static inline int mds_fs_setattr(struct mds_obd *mds, struct inode *inode,
+static inline int mds_fs_setattr(struct mds_obd *mds, struct dentry *dentry,
void *handle, struct iattr *iattr)
{
- return mds->mds_fsops->fs_setattr(inode, handle, iattr);
+ return mds->mds_fsops->fs_setattr(dentry, handle, iattr);
}
static inline int mds_fs_set_objid(struct mds_obd *mds, struct inode *inode,
push_ctxt(&saved, &mds->mds_ctxt);
err = simple_mkdir(current->fs->pwd, "ROOT", 0700);
err = simple_mkdir(current->fs->pwd, "FH", 0700);
+ pop_ctxt(&saved);
+
/*
* Replace the client filesystem delete_inode method with our own,
* so that we can clear the object ID before the inode is deleted.
struct obd_ioctl_data* data = buf;
struct mds_obd *mds = &obddev->u.mds;
struct vfsmount *mnt;
- int err;
+ int err = 0;
ENTRY;
#ifdef CONFIG_DEV_RDONLY
static void *mds_ext2_start(struct inode *inode, int nblocks)
{
- return 0;
+ return (void *)1;
}
static int mds_ext2_stop(struct inode *inode, void *handle)
return 0;
}
-static int mds_ext2_setattr(struct inode *inode, void *handle,
+static int mds_ext2_setattr(struct dentry *dentry, void *handle,
struct iattr *iattr)
{
+ struct inode *inode = dentry->d_inode;
+
/* 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.
}
}
- return 0;
+ if (inode->i_op->setattr)
+ return inode->i_op->setattr(dentry, iattr);
+ else
+ return inode_setattr(inode, iattr);
}
/*
* We don't currently need any additional blocks for rmdir and
* unlink transactions because we are storing the OST oa_id inside
* the inode (which we will be changing anyways as part of this
- * transaction). When we store the oa_id in an EA (which may be
- * in an external block) we need to increase nblocks by 1.
+ * transaction).
*/
static void *mds_ext3_start(struct inode *inode, int op)
{
- int nblocks = 0;
+ /* For updates to the last recieved file */
+ int nblocks = EXT3_DATA_TRANS_BLOCKS;
switch(op) {
case MDS_FSOP_RMDIR:
- case MDS_FSOP_UNLINK: nblocks = EXT3_DELETE_TRANS_BLOCKS; break;
+ case MDS_FSOP_UNLINK:
+ nblocks += EXT3_DELETE_TRANS_BLOCKS; break;
+ case MDS_FSOP_RENAME:
+ nblocks += EXT3_DATA_TRANS_BLOCKS;
+ case MDS_FSOP_CREATE:
+ // FIXME: when we store oa_id in an EA we need more blocks
+ // nblocks += 0;
+ case MDS_FSOP_MKDIR:
+ case MDS_FSOP_SYMLINK:
+ /* Create new directory or symlink (more data blocks) */
+ nblocks += 2;
+ case MDS_FSOP_MKNOD:
+ /* Change parent directory + setattr on new inode */
+ nblocks += EXT3_DATA_TRANS_BLOCKS + 3;
}
return journal_start(EXT3_JOURNAL(inode), nblocks);
return journal_stop((handle_t *)handle);
}
-static int mds_ext3_setattr(struct inode *inode, void *handle,
+static int mds_ext3_setattr(struct dentry *dentry, void *handle,
struct iattr *iattr)
{
+ struct inode *inode = dentry->d_inode;
+
/* 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.
}
}
- return 0;
+ if (inode->i_op->setattr)
+ return inode->i_op->setattr(dentry, iattr);
+ else
+ return inode_setattr(inode, iattr);
}
/*
* FIXME: nasty hack - store the object id in the first two
* direct block spots. This should be done with EAs...
+ * Note also that this does not currently mark the inode
+ * dirty (it currently is used with other operations that
+ * subsequently also mark the inode dirty).
*/
#define EXT3_OBJID_FL 0x40000000
static int mds_ext3_set_objid(struct inode *inode, void *handle, obd_id id)
static int mds_reint_setattr(struct mds_update_record *rec, struct ptlrpc_request *req)
{
- struct dentry *de;
- struct inode *inode;
struct mds_obd *mds = &req->rq_obd->u.mds;
+ struct dentry *de;
de = mds_fid2dentry(mds, rec->ur_fid1, NULL);
if (IS_ERR(de) || OBD_FAIL_CHECK(OBD_FAIL_MDS_REINT_SETATTR)) {
RETURN(0);
}
- inode = de->d_inode;
- CDEBUG(D_INODE, "ino %ld\n", inode->i_ino);
+ CDEBUG(D_INODE, "ino %ld\n", de->d_inode->i_ino);
- mds_fs_setattr(mds, inode, NULL, &rec->ur_iattr);
+ OBD_FAIL_WRITE(OBD_FAIL_MDS_REINT_SETATTR_WRITE,
+ de->d_inode->i_sb->s_dev);
- OBD_FAIL_WRITE(OBD_FAIL_MDS_REINT_SETATTR_WRITE, inode->i_sb->s_dev);
-
- if (inode->i_op->setattr)
- req->rq_rephdr->status = inode->i_op->setattr(de, &rec->ur_iattr);
- else
- req->rq_rephdr->status = inode_setattr(inode, &rec->ur_iattr);
+ req->rq_rephdr->status = mds_fs_setattr(mds, de, NULL, &rec->ur_iattr);
l_dput(de);
RETURN(0);
struct mds_obd *mds = &req->rq_obd->u.mds;
struct dentry *dchild = NULL;
struct inode *dir;
+ void *handle;
int rc = 0;
ENTRY;
switch (type) {
case S_IFREG: {
+ handle = mds_fs_start(mds, dir, MDS_FSOP_CREATE);
+ if (!handle)
+ GOTO(out_reint_create, PTR_ERR(handle));
rc = vfs_create(dir, dchild, rec->ur_mode);
EXIT;
break;
}
case S_IFDIR: {
+ handle = mds_fs_start(mds, dir, MDS_FSOP_MKDIR);
+ if (!handle)
+ GOTO(out_reint_create, PTR_ERR(handle));
rc = vfs_mkdir(dir, dchild, rec->ur_mode);
EXIT;
break;
}
case S_IFLNK: {
+ handle = mds_fs_start(mds, dir, MDS_FSOP_SYMLINK);
+ if (!handle)
+ GOTO(out_reint_create, PTR_ERR(handle));
rc = vfs_symlink(dir, dchild, rec->ur_tgt);
EXIT;
break;
case S_IFIFO:
case S_IFSOCK: {
int rdev = rec->ur_id;
+ handle = mds_fs_start(mds, dir, MDS_FSOP_MKNOD);
+ if (!handle)
+ GOTO(out_reint_create, PTR_ERR(handle));
rc = vfs_mknod(dir, dchild, rec->ur_mode, rdev);
EXIT;
break;
}
}
- if (!rc) {
- if (type == S_IFREG)
- rc = mds_fs_set_objid(mds, dchild->d_inode,
- NULL, rec->ur_id);
- dchild->d_inode->i_atime = rec->ur_time;
- dchild->d_inode->i_ctime = rec->ur_time;
- dchild->d_inode->i_mtime = rec->ur_time;
- dchild->d_inode->i_uid = rec->ur_uid;
- dchild->d_inode->i_gid = rec->ur_gid;
- rep->ino = dchild->d_inode->i_ino;
- rep->generation = dchild->d_inode->i_generation;
- } else {
+ if (rc) {
CERROR("error during create: %d\n", rc);
LBUG();
+ GOTO(out_reint_commit, rc);
+ } else {
+ struct iattr iattr;
+ struct inode *inode = dchild->d_inode;
+
+ if (type == S_IFREG) {
+ rc = mds_fs_set_objid(mds, inode, handle, rec->ur_id);
+ if (rc)
+ CERROR("error setting objid for %ld\n",
+ inode->i_ino);
+ }
+
+ iattr.ia_atime = rec->ur_time;
+ iattr.ia_ctime = rec->ur_time;
+ iattr.ia_mtime = rec->ur_time;
+ iattr.ia_uid = rec->ur_uid;
+ iattr.ia_gid = rec->ur_gid;
+ iattr.ia_valid = ATTR_UID | ATTR_GID | ATTR_ATIME |
+ ATTR_MTIME | ATTR_CTIME;
+
+ rc = mds_fs_setattr(mds, dchild, handle, &iattr);
+
+ rep->ino = inode->i_ino;
+ rep->generation = inode->i_generation;
}
+out_reint_commit:
+ rc = mds_fs_commit(mds, dir, handle);
+
out_reint_create:
req->rq_rephdr->status = rc;
l_dput(dchild);