From: Greg Farnum Date: Fri, 24 Sep 2010 00:13:05 +0000 (-0700) Subject: mds: Implement op CEPH_MDS_OP_SETDIRLAYOUT. X-Git-Tag: v0.22~69^2~8 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=42c7ed44c0b67a9f5dc8a6e07324fe08cfb5a6e8;p=ceph.git mds: Implement op CEPH_MDS_OP_SETDIRLAYOUT. Implement handler functions, add to inode projection machinery, etc. --- diff --git a/src/include/ceph_fs.h b/src/include/ceph_fs.h index ba122f3794f5..83953f77dde7 100644 --- a/src/include/ceph_fs.h +++ b/src/include/ceph_fs.h @@ -305,6 +305,7 @@ enum { CEPH_MDS_OP_SETATTR = 0x01108, CEPH_MDS_OP_SETFILELOCK= 0x01109, CEPH_MDS_OP_GETFILELOCK= 0x00110, + CEPH_MDS_OP_SETDIRLAYOUT=0x0110a, CEPH_MDS_OP_MKNOD = 0x01201, CEPH_MDS_OP_LINK = 0x01202, diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index bb5c9d18b927..bdc5aebbd227 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -227,6 +227,7 @@ inode_t *CInode::project_inode(map *px) projected_nodes.push_back(new projected_inode_t(new inode_t(inode))); if (px) *px = xattrs; + projected_nodes.back()->dir_layout = default_layout; } else { projected_nodes.push_back(new projected_inode_t( new inode_t(*projected_nodes.back()->inode))); @@ -252,6 +253,11 @@ void CInode::pop_and_dirty_projected_inode(LogSegment *ls) delete px; } + if (projected_nodes.front()->dir_layout != default_layout) { + delete default_layout; + default_layout = projected_nodes.front()->dir_layout; + } + if (projected_nodes.front()->snapnode) pop_projected_snaprealm(projected_nodes.front()->snapnode); diff --git a/src/mds/CInode.h b/src/mds/CInode.h index f775b967af92..30774e2bbe7c 100644 --- a/src/mds/CInode.h +++ b/src/mds/CInode.h @@ -232,6 +232,7 @@ public: inode_t *inode; map *xattrs; sr_t *snapnode; + default_file_layout *dir_layout; projected_inode_t() : inode(NULL), xattrs(NULL), snapnode(NULL) {} projected_inode_t(inode_t *in, sr_t *sn) : inode(in), xattrs(NULL), snapnode(sn) {} @@ -243,6 +244,26 @@ public: inode_t *project_inode(map *px=0); void pop_and_dirty_projected_inode(LogSegment *ls); + projected_inode_t *get_projected_node() { + if (projected_nodes.empty()) + return NULL; + else + return projected_nodes.back(); + } + + ceph_file_layout *get_projected_dir_layout() { + if (!inode.is_dir()) return NULL; + if (projected_nodes.empty()) { + if (default_layout) + return &default_layout->layout; + else + return NULL; + } + else if (projected_nodes.back()->dir_layout) + return &projected_nodes.back()->dir_layout->layout; + else return NULL; + } + version_t get_projected_version() { if (projected_nodes.empty()) return inode.version; diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 279d9f01247e..41c2cf30fd18 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -1147,6 +1147,9 @@ void Server::dispatch_client_request(MDRequest *mdr) case CEPH_MDS_OP_SETLAYOUT: handle_client_setlayout(mdr); break; + case CEPH_MDS_OP_SETDIRLAYOUT: + handle_client_setdirlayout(mdr); + break; case CEPH_MDS_OP_SETXATTR: handle_client_setxattr(mdr); break; @@ -2959,6 +2962,69 @@ void Server::handle_client_setlayout(MDRequest *mdr) journal_and_reply(mdr, cur, 0, le, new C_MDS_inode_update_finish(mds, mdr, cur)); } +void Server::handle_client_setdirlayout(MDRequest *mdr) +{ + MClientRequest *req = mdr->client_request; + set rdlocks, wrlocks, xlocks; + CInode *cur = rdlock_path_pin_ref(mdr, 0, rdlocks, true); + if (!cur) return; + + if (mdr->snapid != CEPH_NOSNAP) { + reply_request(mdr, -EROFS); + return; + } + + if (!cur->is_dir()) { + reply_request(mdr, -ENOTDIR); + return; + } + + xlocks.insert(&cur->policylock); + if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks)) + return; + + // validate layout + default_file_layout *layout = new default_file_layout; + if (cur->get_projected_dir_layout()) + layout->layout = *cur->get_projected_dir_layout(); + else + layout->layout = g_default_file_layout; + + if (req->head.args.setlayout.layout.fl_object_size > 0) + layout->layout.fl_object_size = req->head.args.setlayout.layout.fl_object_size; + if (req->head.args.setlayout.layout.fl_stripe_unit > 0) + layout->layout.fl_stripe_unit = req->head.args.setlayout.layout.fl_stripe_unit; + if (req->head.args.setlayout.layout.fl_stripe_count > 0) + layout->layout.fl_stripe_count=req->head.args.setlayout.layout.fl_stripe_count; + if (req->head.args.setlayout.layout.fl_cas_hash > 0) + layout->layout.fl_cas_hash = req->head.args.setlayout.layout.fl_cas_hash; + if (req->head.args.setlayout.layout.fl_object_stripe_unit > 0) + layout->layout.fl_object_stripe_unit = req->head.args.setlayout.layout.fl_object_stripe_unit; + if (req->head.args.setlayout.layout.fl_pg_preferred > 0) + layout->layout.fl_pg_preferred = req->head.args.setlayout.layout.fl_pg_preferred; + if (req->head.args.setlayout.layout.fl_pg_pool > 0) + layout->layout.fl_pg_pool = req->head.args.setlayout.layout.fl_pg_pool; + if (!ceph_file_layout_is_valid(&layout->layout)) { + dout(10) << "bad layout" << dendl; + reply_request(mdr, -EINVAL); + return; + } + + cur->project_inode(); + cur->get_projected_node()->dir_layout = layout; + cur->get_projected_inode()->version = cur->pre_dirty(); + + // log + wait + mdr->ls = mdlog->get_current_segment(); + EUpdate *le = new EUpdate(mdlog, "setlayout"); + mdlog->start_entry(le); + le->metablob.add_client_req(req->get_reqid(), req->get_oldest_client_tid()); + mdcache->predirty_journal_parents(mdr, &le->metablob, cur, 0, PREDIRTY_PRIMARY, false); + mdcache->journal_dirty_inode(mdr, &le->metablob, cur); + + journal_and_reply(mdr, cur, 0, le, new C_MDS_inode_update_finish(mds, mdr, cur)); +} + diff --git a/src/mds/Server.h b/src/mds/Server.h index 444339de7dd1..61dbbd860c5f 100644 --- a/src/mds/Server.h +++ b/src/mds/Server.h @@ -141,6 +141,7 @@ public: void handle_client_setattr(MDRequest *mdr); void handle_client_setlayout(MDRequest *mdr); + void handle_client_setdirlayout(MDRequest *mdr); void handle_client_setxattr(MDRequest *mdr); void handle_client_removexattr(MDRequest *mdr);