Includes MDS statfs method.
Includes fixes for sgid directories on MDS.
void ptlrpc_stop_all_threads(struct ptlrpc_service *svc);
int ptlrpc_start_thread(struct obd_device *dev, struct ptlrpc_service *svc,
char *name);
-int rpc_unregister_service(struct ptlrpc_service *service);
+int ptlrpc_unregister_service(struct ptlrpc_service *service);
struct ptlrpc_svc_data {
char *name;
out_thread:
ptlrpc_stop_all_threads(ldlm->ldlm_service);
- rpc_unregister_service(ldlm->ldlm_service);
- OBD_FREE(ldlm->ldlm_service, sizeof(*ldlm->ldlm_service));
+ ptlrpc_unregister_service(ldlm->ldlm_service);
out_dec:
MOD_DEC_USE_COUNT;
return rc;
ENTRY;
ptlrpc_stop_all_threads(ldlm->ldlm_service);
- rpc_unregister_service(ldlm->ldlm_service);
-
- if (!list_empty(&ldlm->ldlm_service->srv_reqs)) {
- // XXX reply with errors and clean up
- CERROR("Request list not empty!\n");
- }
-
- OBD_FREE(ldlm->ldlm_service, sizeof(*ldlm->ldlm_service));
+ ptlrpc_unregister_service(ldlm->ldlm_service);
if (mds_reint_p != NULL)
inter_module_put("mds_reint");
modulefs_DATA = mds.o mds_extN.o # mds_ext2.o mds_ext3.o
EXTRA_PROGRAMS = mds mds_extN # mds_ext2 mds_ext3
-LINX=mds_updates.c simple.c
+LINX=mds_updates.c simple.c ll_pack.c
+ll_pack.c:
+ test -e ll_pack.c || ln -sf $(top_srcdir)/lib/ll_pack.c
+
mds_updates.c:
test -e mds_updates.c || ln -sf $(top_srcdir)/lib/mds_updates.c
struct ptlrpc_request *req);
static int mds_cleanup(struct obd_device * obddev);
+/* Assumes caller has already pushed into the kernel filesystem context */
static int mds_sendpage(struct ptlrpc_request *req, struct file *file,
__u64 offset)
{
int rc = 0;
- mm_segment_t oldfs = get_fs();
+ struct mds_obd *mds = &req->rq_obd->u.mds;
struct ptlrpc_bulk_desc *desc;
struct ptlrpc_bulk_page *bulk;
char *buf;
if (buf == NULL)
GOTO(cleanup_bulk, rc = -ENOMEM);
- set_fs(KERNEL_DS);
- rc = mds_fs_readpage(&req->rq_obd->u.mds, file, buf, PAGE_SIZE,
- (loff_t *)&offset);
- set_fs(oldfs);
+ rc = mds_fs_readpage(mds, file, buf, PAGE_SIZE, (loff_t *)&offset);
if (rc != PAGE_SIZE)
GOTO(cleanup_buf, rc = -EIO);
static int mds_getattr_name(int offset, struct ptlrpc_request *req)
{
struct mds_obd *mds = &req->rq_obd->u.mds;
+ struct obd_run_ctxt saved;
struct mds_body *body;
struct dentry *de = NULL, *dchild = NULL;
struct inode *dir;
if (offset)
offset = 1;
+ push_ctxt(&saved, &mds->mds_ctxt);
de = mds_fid2dentry(mds, &body->fid1, NULL);
if (IS_ERR(de)) {
LBUG();
ldlm_lock_decref(lock, lock_mode);
out_create_de:
l_dput(de);
- out_pre_de:
+out_pre_de:
req->rq_status = rc;
+ pop_ctxt(&saved);
return 0;
}
static int mds_getattr(int offset, struct ptlrpc_request *req)
{
struct mds_obd *mds = &req->rq_obd->u.mds;
+ struct obd_run_ctxt saved;
struct dentry *de;
struct inode *inode;
struct mds_body *body;
ENTRY;
body = lustre_msg_buf(req->rq_reqmsg, offset);
+ push_ctxt(&saved, &mds->mds_ctxt);
de = mds_fid2dentry(mds, &body->fid1, NULL);
if (IS_ERR(de)) {
- req->rq_status = -ENOENT;
- RETURN(-ENOENT);
+ GOTO(out_pop, rc = -ENOENT);
}
inode = de->d_inode;
&req->rq_repmsg);
if (rc || OBD_FAIL_CHECK(OBD_FAIL_MDS_GETATTR_PACK)) {
CERROR("mds: out of memory\n");
- req->rq_status = -ENOMEM;
- GOTO(out, rc = -ENOMEM);
+ GOTO(out, rc);
}
if (body->valid & OBD_MD_LINKNAME) {
char *tmp = lustre_msg_buf(req->rq_repmsg, 1);
- mm_segment_t oldfs;
- oldfs = get_fs();
- set_fs(KERNEL_DS);
rc = inode->i_op->readlink(de, tmp, size[1]);
- set_fs(oldfs);
if (rc < 0) {
- req->rq_status = rc;
CERROR("readlink failed: %d\n", rc);
GOTO(out, rc);
}
rc = mds_fs_get_obdo(mds, inode,
lustre_msg_buf(req->rq_repmsg, 1));
if (rc < 0) {
- req->rq_status = rc;
CERROR("mds_fs_get_obdo failed: %d\n", rc);
GOTO(out, rc);
}
}
- out:
+out:
l_dput(de);
- RETURN(rc);
+out_pop:
+ pop_ctxt(&saved);
+ req->rq_status = rc;
+ RETURN(0);
+}
+
+static int mds_statfs(struct ptlrpc_request *req)
+{
+ struct mds_obd *mds = &req->rq_obd->u.mds;
+ struct obd_statfs *osfs;
+ struct statfs sfs;
+ int rc, size = sizeof(*osfs);
+ ENTRY;
+
+ rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen,
+ &req->rq_repmsg);
+ if (rc || OBD_FAIL_CHECK(OBD_FAIL_MDS_STATFS_PACK)) {
+ CERROR("mds: statfs lustre_pack_msg failed: rc = %d\n", rc);
+ GOTO(out, rc);
+ }
+
+ rc = vfs_statfs(mds->mds_sb, &sfs);
+ if (rc) {
+ CERROR("mds: statfs failed: rc %d\n", rc);
+ GOTO(out, rc);
+ }
+ osfs = lustre_msg_buf(req->rq_repmsg, 0);
+ memset(osfs, 0, size);
+ /* FIXME: hack until the MDS gets the OST data, next month */
+ sfs.f_blocks = -1;
+ sfs.f_bfree = -1;
+ sfs.f_bavail = -1;
+ obd_statfs_pack(osfs, &sfs);
+
+out:
+ req->rq_status = rc;
+ RETURN(0);
}
static int mds_open(struct ptlrpc_request *req)
body = lustre_msg_buf(req->rq_reqmsg, 0);
/* was this animal open already? */
+ /* XXX we chould only check on re-open, or do a refcount... */
list_for_each(tmp, &mci->mci_open_head) {
struct mds_file_data *fd;
fd = list_entry(tmp, struct mds_file_data, mfd_list);
struct dentry *de;
struct file *file;
struct mds_body *body;
+ struct obd_run_ctxt saved;
int rc, size = sizeof(*body);
ENTRY;
rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen, &req->rq_repmsg);
if (rc || OBD_FAIL_CHECK(OBD_FAIL_MDS_READPAGE_PACK)) {
CERROR("mds: out of memory\n");
- req->rq_status = -ENOMEM;
- RETURN(0);
+ GOTO(out, rc = -ENOMEM);
}
body = lustre_msg_buf(req->rq_reqmsg, 0);
+ push_ctxt(&saved, &mds->mds_ctxt);
de = mds_fid2dentry(mds, &body->fid1, &mnt);
- if (IS_ERR(de)) {
- req->rq_status = PTR_ERR(de);
- RETURN(0);
- }
+ if (IS_ERR(de))
+ GOTO(out_pop, rc = PTR_ERR(de));
CDEBUG(D_INODE, "ino %ld\n", de->d_inode->i_ino);
file = dentry_open(de, mnt, O_RDONLY | O_LARGEFILE);
/* note: in case of an error, dentry_open puts dentry */
- if (IS_ERR(file)) {
- req->rq_status = PTR_ERR(file);
- RETURN(0);
- }
+ if (IS_ERR(file))
+ GOTO(out_pop, rc = PTR_ERR(file));
/* to make this asynchronous make sure that the handling function
doesn't send a reply when this function completes. Instead a
rc = mds_sendpage(req, file, body->size);
filp_close(file, 0);
+out_pop:
+ pop_ctxt(&saved);
+out:
req->rq_status = rc;
RETURN(0);
}
rc = mds_getattr(0, req);
break;
+ case MDS_STATFS:
+ CDEBUG(D_INODE, "statfs\n");
+ OBD_FAIL_RETURN(OBD_FAIL_MDS_STATFS_NET, 0);
+ rc = mds_statfs(req);
+ break;
+
case MDS_READPAGE:
CDEBUG(D_INODE, "readpage\n");
OBD_FAIL_RETURN(OBD_FAIL_MDS_READPAGE_NET, 0);
GOTO(err_put, rc);
}
- mds->mds_service = ptlrpc_init_svc(64 * 1024,
- MDS_REQUEST_PORTAL, MDC_REPLY_PORTAL, "self", mds_handle);
+ mds->mds_service = ptlrpc_init_svc(64 * 1024, MDS_REQUEST_PORTAL,
+ MDC_REPLY_PORTAL, "self",mds_handle);
if (!mds->mds_service) {
CERROR("failed to start service\n");
GOTO(err_fs, rc = -EINVAL);
err_thread:
ptlrpc_stop_all_threads(mds->mds_service);
err_svc:
- rpc_unregister_service(mds->mds_service);
- OBD_FREE(mds->mds_service, sizeof(*mds->mds_service));
+ ptlrpc_unregister_service(mds->mds_service);
err_fs:
mds_fs_cleanup(mds);
err_put:
}
ptlrpc_stop_all_threads(mds->mds_service);
- rpc_unregister_service(mds->mds_service);
- if (!list_empty(&mds->mds_service->srv_reqs)) {
- // XXX reply with errors and clean up
- CERROR("Request list not empty!\n");
- }
- OBD_FREE(mds->mds_service, sizeof(*mds->mds_service));
+ ptlrpc_unregister_service(mds->mds_service);
sb = mds->mds_sb;
if (!mds->mds_sb)
mds->mds_fsops = fs_ops;
mds->mds_vfsmnt = mnt;
+
+ OBD_SET_CTXT_MAGIC(&mds->mds_ctxt);
mds->mds_ctxt.pwdmnt = mnt;
mds->mds_ctxt.pwd = mnt->mnt_root;
mds->mds_ctxt.fs = KERNEL_DS;
return NULL;
}
+/* Assumes caller has already pushed us into the kernel context. */
int mds_update_last_rcvd(struct mds_obd *mds, void *handle,
struct ptlrpc_request *req)
{
/* get from req->rq_connection-> or req->rq_client */
- struct obd_run_ctxt saved;
struct mds_client_info *mci;
loff_t off;
int rc;
mci->mci_mcd->mcd_last_xid = cpu_to_le64(req->rq_xid);
mds_fs_set_last_rcvd(mds, handle);
- push_ctxt(&saved, &mds->mds_ctxt);
rc = lustre_fwrite(mds->mds_rcvd_filp, (char *)mci->mci_mcd,
sizeof(*mci->mci_mcd), &off);
- pop_ctxt(&saved);
CDEBUG(D_INODE, "wrote trans #%Ld for client '%s' at #%d: rc = %d\n",
mds->mds_last_rcvd, mci->mci_mcd->mcd_uuid, mci->mci_off, rc);
// store new value and last committed value in req struct
OBD_FAIL_WRITE(OBD_FAIL_MDS_REINT_CREATE_WRITE, dir->i_sb->s_dev);
+ if (dir->i_mode & S_ISGID) {
+ rec->ur_gid = dir->i_gid;
+ if (S_ISDIR(rec->ur_mode))
+ rec->ur_mode |= S_ISGID;
+ }
+
switch (type) {
case S_IFREG: {
handle = mds_fs_start(mds, dir, MDS_FSOP_CREATE);
struct obdo *obdo;
obdo = lustre_msg_buf(req->rq_reqmsg, 2);
rc = mds_fs_set_obdo(mds, inode, handle, obdo);
- if (rc)
- CERROR("error %d setting objid for %ld\n",
+ if (rc) {
+ CERROR("error %d setting obdo for %ld\n",
rc, inode->i_ino);
+ GOTO(out_create_unlink, rc);
+ }
}
iattr.ia_atime = rec->ur_time;
l_dput(de);
req->rq_status = rc;
return 0;
+
+out_create_unlink:
+ /* Destroy the file we just created. This should not need extra
+ * journal credits, as we have already modified all of the blocks
+ * needed in order to create the file in the first place.
+ */
+ switch(type) {
+ case S_IFDIR:
+ err = vfs_rmdir(dir, dchild);
+ if (err)
+ CERROR("failed rmdir in error path: rc = %d\n", err);
+ break;
+ default:
+ err = vfs_unlink(dir, dchild);
+ if (err)
+ CERROR("failed unlink in error path: rc = %d\n", err);
+ }
+
+ goto out_create_commit;
}
static int mds_reint_unlink(struct mds_update_record *rec, int offset,
int mds_reint_rec(struct mds_update_record *rec, int offset,
struct ptlrpc_request *req)
{
+ struct mds_obd *mds = &req->rq_obd->u.mds;
+ struct obd_run_ctxt saved;
+
int rc;
if (rec->ur_opcode < 1 || rec->ur_opcode > REINT_MAX) {
RETURN(rc);
}
+ push_ctxt(&saved, &mds->mds_ctxt);
rc = reinters[rec->ur_opcode](rec, offset, req);
+ pop_ctxt(&saved);
return rc;
}
{
struct ost_body *body = lustre_msg_buf(req->rq_reqmsg, 0);
- if (body->data == OBD_BRW_READ)
- return ost_brw_read(obddev, req);
- else
+ if (body->data & OBD_BRW_WRITE)
return ost_brw_write(obddev, req);
+ else
+ return ost_brw_read(obddev, req);
}
static int ost_handle(struct obd_device *obddev, struct ptlrpc_service *svc,
if (obddev->obd_namespace == NULL)
LBUG();
- ost->ost_service = ptlrpc_init_svc(64 * 1024,
- OST_REQUEST_PORTAL, OSC_REPLY_PORTAL,
- "self", ost_handle);
+ ost->ost_service = ptlrpc_init_svc(64 * 1024, OST_REQUEST_PORTAL,
+ OSC_REPLY_PORTAL, "self",ost_handle);
if (!ost->ost_service) {
CERROR("failed to start service\n");
GOTO(error_disc, err = -EINVAL);
}
ptlrpc_stop_all_threads(ost->ost_service);
- rpc_unregister_service(ost->ost_service);
-
- if (!list_empty(&ost->ost_service->srv_reqs)) {
- // XXX reply with errors and clean up
- CERROR("Request list not empty!\n");
- }
- OBD_FREE(ost->ost_service, sizeof(*ost->ost_service));
+ ptlrpc_unregister_service(ost->ost_service);
err = obd_disconnect(&ost->ost_conn);
if (err) {
RETURN(0);
err_svc:
- rpc_unregister_service(recovd->recovd_service);
+ ptlrpc_unregister_service(recovd->recovd_service);
err_recovd:
recovd_cleanup(recovd);
err_free:
LBUG();
ptlrpc_stop_all_threads(recovd->recovd_service);
- rpc_unregister_service(recovd->recovd_service);
- if (!list_empty(&recovd->recovd_service->srv_reqs)) {
- // XXX reply with errors and clean up
- CERROR("Request list not empty!\n");
- }
-
- OBD_FREE(recovd->recovd_service, sizeof(*recovd->recovd_service));
+ ptlrpc_unregister_service(recovd->recovd_service);
ptlrpc_cleanup_client(recovd->recovd_client);
OBD_FREE(recovd->recovd_client, sizeof(*recovd->recovd_client));
MOD_DEC_USE_COUNT;
EXPORT_SYMBOL(ptlrpc_init_svc);
EXPORT_SYMBOL(ptlrpc_stop_all_threads);
EXPORT_SYMBOL(ptlrpc_start_thread);
-EXPORT_SYMBOL(rpc_unregister_service);
+EXPORT_SYMBOL(ptlrpc_unregister_service);
/* pack_generic.c */
EXPORT_SYMBOL(lustre_pack_msg);
err = kportal_uuid_to_peer(uuid, &service->srv_self);
if (err) {
CERROR("cannot get peer for uuid '%s'", uuid);
- GOTO(err_free, NULL);
+ OBD_FREE(service, sizeof(*service));
+ RETURN(NULL);
}
service->srv_ring_length = RPC_RING_LENGTH;
if (rc != PTL_OK) {
CERROR("PtlEQAlloc failed: %d\n", rc);
LBUG();
- GOTO(err_free, NULL);
+ OBD_FREE(service, sizeof(*service));
+ RETURN(NULL);
}
for (i = 0; i < service->srv_ring_length; i++) {
RETURN(service);
err_ring:
service->srv_ring_length = i;
- rpc_unregister_service(service); // XXX verify this is right
- PtlEQFree(service->srv_eq_h);
-err_free:
- OBD_FREE(service, sizeof(*service));
+ ptlrpc_unregister_service(service);
return NULL;
}
RETURN(0);
}
-int rpc_unregister_service(struct ptlrpc_service *service)
+int ptlrpc_unregister_service(struct ptlrpc_service *service)
{
int rc, i;
if (rc)
CERROR("PtlEQFree failed: %d\n", rc);
+ if (!list_empty(&service->srv_reqs)) {
+ // XXX reply with errors and clean up
+ CERROR("Request list not empty!\n");
+ }
+
+ OBD_FREE(service, sizeof(*service));
return 0;
}