Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / client / Client.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7  *
8  * This is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License version 2.1, as published by the Free Software
11  * Foundation.  See file COPYING.
12  *
13  */
14
15
16 // unix-ey fs stuff
17 #include <unistd.h>
18 #include <sys/types.h>
19 #include <time.h>
20 #include <utime.h>
21 #include <sys/stat.h>
22 #include <sys/param.h>
23 #include <fcntl.h>
24 #include <sys/file.h>
25 #include <sys/utsname.h>
26 #include <sys/uio.h>
27
28 #include <boost/lexical_cast.hpp>
29 #include <boost/fusion/include/std_pair.hpp>
30
31 #if defined(__FreeBSD__)
32 #define XATTR_CREATE    0x1
33 #define XATTR_REPLACE   0x2
34 #else
35 #include <sys/xattr.h>
36 #endif
37
38 #if defined(__linux__)
39 #include <linux/falloc.h>
40 #endif
41
42 #include <sys/statvfs.h>
43
44 #include "common/config.h"
45 #include "common/version.h"
46
47 // ceph stuff
48 #include "messages/MClientSession.h"
49 #include "messages/MClientReconnect.h"
50 #include "messages/MClientRequest.h"
51 #include "messages/MClientRequestForward.h"
52 #include "messages/MClientReply.h"
53 #include "messages/MClientCaps.h"
54 #include "messages/MClientLease.h"
55 #include "messages/MClientSnap.h"
56 #include "messages/MCommandReply.h"
57 #include "messages/MOSDMap.h"
58 #include "messages/MClientQuota.h"
59 #include "messages/MClientCapRelease.h"
60 #include "messages/MMDSMap.h"
61 #include "messages/MFSMap.h"
62 #include "messages/MFSMapUser.h"
63
64 #include "mon/MonClient.h"
65
66 #include "mds/flock.h"
67 #include "osd/OSDMap.h"
68 #include "osdc/Filer.h"
69
70 #include "common/Cond.h"
71 #include "common/Mutex.h"
72 #include "common/perf_counters.h"
73 #include "common/admin_socket.h"
74 #include "common/errno.h"
75 #include "include/str_list.h"
76
77 #define dout_subsys ceph_subsys_client
78
79 #include "include/lru.h"
80 #include "include/compat.h"
81 #include "include/stringify.h"
82
83 #include "Client.h"
84 #include "Inode.h"
85 #include "Dentry.h"
86 #include "Dir.h"
87 #include "ClientSnapRealm.h"
88 #include "Fh.h"
89 #include "MetaSession.h"
90 #include "MetaRequest.h"
91 #include "ObjecterWriteback.h"
92 #include "posix_acl.h"
93
94 #include "include/assert.h"
95 #include "include/stat.h"
96
97 #include "include/cephfs/ceph_statx.h"
98
99 #if HAVE_GETGROUPLIST
100 #include <grp.h>
101 #include <pwd.h>
102 #include <unistd.h>
103 #endif
104
105 #undef dout_prefix
106 #define dout_prefix *_dout << "client." << whoami << " "
107
108 #define  tout(cct)       if (!cct->_conf->client_trace.empty()) traceout
109
110 // FreeBSD fails to define this
111 #ifndef O_DSYNC
112 #define O_DSYNC 0x0
113 #endif
114 // Darwin fails to define this
115 #ifndef O_RSYNC
116 #define O_RSYNC 0x0
117 #endif
118
119 #ifndef O_DIRECT
120 #define O_DIRECT 0x0
121 #endif
122
123 #define DEBUG_GETATTR_CAPS (CEPH_CAP_XATTR_SHARED)
124
125 void client_flush_set_callback(void *p, ObjectCacher::ObjectSet *oset)
126 {
127   Client *client = static_cast<Client*>(p);
128   client->flush_set_callback(oset);
129 }
130
131
132 // -------------
133
134 Client::CommandHook::CommandHook(Client *client) :
135   m_client(client)
136 {
137 }
138
139 bool Client::CommandHook::call(std::string command, cmdmap_t& cmdmap,
140                                std::string format, bufferlist& out)
141 {
142   Formatter *f = Formatter::create(format);
143   f->open_object_section("result");
144   m_client->client_lock.Lock();
145   if (command == "mds_requests")
146     m_client->dump_mds_requests(f);
147   else if (command == "mds_sessions")
148     m_client->dump_mds_sessions(f);
149   else if (command == "dump_cache")
150     m_client->dump_cache(f);
151   else if (command == "kick_stale_sessions")
152     m_client->_kick_stale_sessions();
153   else if (command == "status")
154     m_client->dump_status(f);
155   else
156     assert(0 == "bad command registered");
157   m_client->client_lock.Unlock();
158   f->close_section();
159   f->flush(out);
160   delete f;
161   return true;
162 }
163
164
165 // -------------
166
167 dir_result_t::dir_result_t(Inode *in, const UserPerm& perms)
168   : inode(in), offset(0), next_offset(2),
169     release_count(0), ordered_count(0), cache_index(0), start_shared_gen(0),
170     perms(perms)
171   { }
172
173 void Client::_reset_faked_inos()
174 {
175   ino_t start = 1024;
176   free_faked_inos.clear();
177   free_faked_inos.insert(start, (uint32_t)-1 - start + 1);
178   last_used_faked_ino = 0;
179   _use_faked_inos = sizeof(ino_t) < 8 || cct->_conf->client_use_faked_inos;
180 }
181
182 void Client::_assign_faked_ino(Inode *in)
183 {
184   interval_set<ino_t>::const_iterator it = free_faked_inos.lower_bound(last_used_faked_ino + 1);
185   if (it == free_faked_inos.end() && last_used_faked_ino > 0) {
186     last_used_faked_ino = 0;
187     it = free_faked_inos.lower_bound(last_used_faked_ino + 1);
188   }
189   assert(it != free_faked_inos.end());
190   if (last_used_faked_ino < it.get_start()) {
191     assert(it.get_len() > 0);
192     last_used_faked_ino = it.get_start();
193   } else {
194     ++last_used_faked_ino;
195     assert(it.get_start() + it.get_len() > last_used_faked_ino);
196   }
197   in->faked_ino = last_used_faked_ino;
198   free_faked_inos.erase(in->faked_ino);
199   faked_ino_map[in->faked_ino] = in->vino();
200 }
201
202 void Client::_release_faked_ino(Inode *in)
203 {
204   free_faked_inos.insert(in->faked_ino);
205   faked_ino_map.erase(in->faked_ino);
206 }
207
208 vinodeno_t Client::_map_faked_ino(ino_t ino)
209 {
210   vinodeno_t vino;
211   if (ino == 1)
212     vino = root->vino();
213   else if (faked_ino_map.count(ino))
214     vino = faked_ino_map[ino];
215   else
216     vino = vinodeno_t(0, CEPH_NOSNAP);
217   ldout(cct, 10) << "map_faked_ino " << ino << " -> " << vino << dendl;
218   return vino;
219 }
220
221 vinodeno_t Client::map_faked_ino(ino_t ino)
222 {
223   Mutex::Locker lock(client_lock);
224   return _map_faked_ino(ino);
225 }
226
227 // cons/des
228
229 Client::Client(Messenger *m, MonClient *mc, Objecter *objecter_)
230   : Dispatcher(m->cct),
231     m_command_hook(this),
232     timer(m->cct, client_lock),
233     callback_handle(NULL),
234     switch_interrupt_cb(NULL),
235     remount_cb(NULL),
236     ino_invalidate_cb(NULL),
237     dentry_invalidate_cb(NULL),
238     getgroups_cb(NULL),
239     umask_cb(NULL),
240     can_invalidate_dentries(false),
241     require_remount(false),
242     async_ino_invalidator(m->cct),
243     async_dentry_invalidator(m->cct),
244     interrupt_finisher(m->cct),
245     remount_finisher(m->cct),
246     objecter_finisher(m->cct),
247     tick_event(NULL),
248     messenger(m), monclient(mc),
249     objecter(objecter_),
250     whoami(mc->get_global_id()), cap_epoch_barrier(0),
251     last_tid(0), oldest_tid(0), last_flush_tid(1),
252     initialized(false),
253     mounted(false), unmounting(false), blacklisted(false),
254     local_osd(-1), local_osd_epoch(0),
255     unsafe_sync_write(0),
256     client_lock("Client::client_lock")
257 {
258   _reset_faked_inos();
259   //
260   root = 0;
261
262   num_flushing_caps = 0;
263
264   _dir_vxattrs_name_size = _vxattrs_calcu_name_size(_dir_vxattrs);
265   _file_vxattrs_name_size = _vxattrs_calcu_name_size(_file_vxattrs);
266
267   user_id = cct->_conf->client_mount_uid;
268   group_id = cct->_conf->client_mount_gid;
269
270   acl_type = NO_ACL;
271   if (cct->_conf->client_acl_type == "posix_acl")
272     acl_type = POSIX_ACL;
273
274   lru.lru_set_midpoint(cct->_conf->client_cache_mid);
275
276   // file handles
277   free_fd_set.insert(10, 1<<30);
278
279   mdsmap.reset(new MDSMap);
280
281   // osd interfaces
282   writeback_handler.reset(new ObjecterWriteback(objecter, &objecter_finisher,
283                                             &client_lock));
284   objectcacher.reset(new ObjectCacher(cct, "libcephfs", *writeback_handler, client_lock,
285                                   client_flush_set_callback,    // all commit callback
286                                   (void*)this,
287                                   cct->_conf->client_oc_size,
288                                   cct->_conf->client_oc_max_objects,
289                                   cct->_conf->client_oc_max_dirty,
290                                   cct->_conf->client_oc_target_dirty,
291                                   cct->_conf->client_oc_max_dirty_age,
292                                   true));
293   objecter_finisher.start();
294   filer.reset(new Filer(objecter, &objecter_finisher));
295   objecter->enable_blacklist_events();
296 }
297
298
299 Client::~Client()
300 {
301   assert(!client_lock.is_locked());
302
303   // It is necessary to hold client_lock, because any inode destruction
304   // may call into ObjectCacher, which asserts that it's lock (which is
305   // client_lock) is held.
306   client_lock.Lock();
307   tear_down_cache();
308   client_lock.Unlock();
309 }
310
311 void Client::tear_down_cache()
312 {
313   // fd's
314   for (ceph::unordered_map<int, Fh*>::iterator it = fd_map.begin();
315        it != fd_map.end();
316        ++it) {
317     Fh *fh = it->second;
318     ldout(cct, 1) << "tear_down_cache forcing close of fh " << it->first << " ino " << fh->inode->ino << dendl;
319     _release_fh(fh);
320   }
321   fd_map.clear();
322
323   while (!opened_dirs.empty()) {
324     dir_result_t *dirp = *opened_dirs.begin();
325     ldout(cct, 1) << "tear_down_cache forcing close of dir " << dirp << " ino " << dirp->inode->ino << dendl;
326     _closedir(dirp);
327   }
328
329   // caps!
330   // *** FIXME ***
331
332   // empty lru
333   trim_cache();
334   assert(lru.lru_get_size() == 0);
335
336   // close root ino
337   assert(inode_map.size() <= 1 + root_parents.size());
338   if (root && inode_map.size() == 1 + root_parents.size()) {
339     delete root;
340     root = 0;
341     root_ancestor = 0;
342     while (!root_parents.empty())
343       root_parents.erase(root_parents.begin());
344     inode_map.clear();
345     _reset_faked_inos();
346   }
347
348   assert(inode_map.empty());
349 }
350
351 inodeno_t Client::get_root_ino()
352 {
353   Mutex::Locker l(client_lock);
354   if (use_faked_inos())
355     return root->faked_ino;
356   else
357     return root->ino;
358 }
359
360 Inode *Client::get_root()
361 {
362   Mutex::Locker l(client_lock);
363   root->ll_get();
364   return root;
365 }
366
367
368 // debug crapola
369
370 void Client::dump_inode(Formatter *f, Inode *in, set<Inode*>& did, bool disconnected)
371 {
372   filepath path;
373   in->make_long_path(path);
374   ldout(cct, 1) << "dump_inode: "
375                 << (disconnected ? "DISCONNECTED ":"")
376                 << "inode " << in->ino
377                 << " " << path
378                 << " ref " << in->get_num_ref()
379                 << *in << dendl;
380
381   if (f) {
382     f->open_object_section("inode");
383     f->dump_stream("path") << path;
384     if (disconnected)
385       f->dump_int("disconnected", 1);
386     in->dump(f);
387     f->close_section();
388   }
389
390   did.insert(in);
391   if (in->dir) {
392     ldout(cct, 1) << "  dir " << in->dir << " size " << in->dir->dentries.size() << dendl;
393     for (ceph::unordered_map<string, Dentry*>::iterator it = in->dir->dentries.begin();
394          it != in->dir->dentries.end();
395          ++it) {
396       ldout(cct, 1) << "   " << in->ino << " dn " << it->first << " " << it->second << " ref " << it->second->ref << dendl;
397       if (f) {
398         f->open_object_section("dentry");
399         it->second->dump(f);
400         f->close_section();
401       } 
402       if (it->second->inode)
403         dump_inode(f, it->second->inode.get(), did, false);
404     }
405   }
406 }
407
408 void Client::dump_cache(Formatter *f)
409 {
410   set<Inode*> did;
411
412   ldout(cct, 1) << "dump_cache" << dendl;
413
414   if (f)
415     f->open_array_section("cache");
416
417   if (root)
418     dump_inode(f, root, did, true);
419
420   // make a second pass to catch anything disconnected
421   for (ceph::unordered_map<vinodeno_t, Inode*>::iterator it = inode_map.begin();
422        it != inode_map.end();
423        ++it) {
424     if (did.count(it->second))
425       continue;
426     dump_inode(f, it->second, did, true);
427   }
428
429   if (f)
430     f->close_section();
431 }
432
433 void Client::dump_status(Formatter *f)
434 {
435   assert(client_lock.is_locked_by_me());
436
437   ldout(cct, 1) << __func__ << dendl;
438
439   const epoch_t osd_epoch
440     = objecter->with_osdmap(std::mem_fn(&OSDMap::get_epoch));
441
442   if (f) {
443     f->open_object_section("metadata");
444     for (const auto& kv : metadata)
445       f->dump_string(kv.first.c_str(), kv.second);
446     f->close_section();
447
448     f->dump_int("dentry_count", lru.lru_get_size());
449     f->dump_int("dentry_pinned_count", lru.lru_get_num_pinned());
450     f->dump_int("id", get_nodeid().v);
451     f->dump_int("inode_count", inode_map.size());
452     f->dump_int("mds_epoch", mdsmap->get_epoch());
453     f->dump_int("osd_epoch", osd_epoch);
454     f->dump_int("osd_epoch_barrier", cap_epoch_barrier);
455   }
456 }
457
458 int Client::init()
459 {
460   timer.init();
461   objectcacher->start();
462
463   client_lock.Lock();
464   assert(!initialized);
465
466   messenger->add_dispatcher_tail(this);
467   client_lock.Unlock();
468
469   _finish_init();
470   return 0;
471 }
472
473 void Client::_finish_init()
474 {
475   client_lock.Lock();
476   // logger
477   PerfCountersBuilder plb(cct, "client", l_c_first, l_c_last);
478   plb.add_time_avg(l_c_reply, "reply", "Latency of receiving a reply on metadata request");
479   plb.add_time_avg(l_c_lat, "lat", "Latency of processing a metadata request");
480   plb.add_time_avg(l_c_wrlat, "wrlat", "Latency of a file data write operation");
481   logger.reset(plb.create_perf_counters());
482   cct->get_perfcounters_collection()->add(logger.get());
483
484   client_lock.Unlock();
485
486   cct->_conf->add_observer(this);
487
488   AdminSocket* admin_socket = cct->get_admin_socket();
489   int ret = admin_socket->register_command("mds_requests",
490                                            "mds_requests",
491                                            &m_command_hook,
492                                            "show in-progress mds requests");
493   if (ret < 0) {
494     lderr(cct) << "error registering admin socket command: "
495                << cpp_strerror(-ret) << dendl;
496   }
497   ret = admin_socket->register_command("mds_sessions",
498                                        "mds_sessions",
499                                        &m_command_hook,
500                                        "show mds session state");
501   if (ret < 0) {
502     lderr(cct) << "error registering admin socket command: "
503                << cpp_strerror(-ret) << dendl;
504   }
505   ret = admin_socket->register_command("dump_cache",
506                                        "dump_cache",
507                                        &m_command_hook,
508                                        "show in-memory metadata cache contents");
509   if (ret < 0) {
510     lderr(cct) << "error registering admin socket command: "
511                << cpp_strerror(-ret) << dendl;
512   }
513   ret = admin_socket->register_command("kick_stale_sessions",
514                                        "kick_stale_sessions",
515                                        &m_command_hook,
516                                        "kick sessions that were remote reset");
517   if (ret < 0) {
518     lderr(cct) << "error registering admin socket command: "
519                << cpp_strerror(-ret) << dendl;
520   }
521   ret = admin_socket->register_command("status",
522                                        "status",
523                                        &m_command_hook,
524                                        "show overall client status");
525   if (ret < 0) {
526     lderr(cct) << "error registering admin socket command: "
527                << cpp_strerror(-ret) << dendl;
528   }
529
530   client_lock.Lock();
531   initialized = true;
532   client_lock.Unlock();
533 }
534
535 void Client::shutdown() 
536 {
537   ldout(cct, 1) << "shutdown" << dendl;
538
539   // If we were not mounted, but were being used for sending
540   // MDS commands, we may have sessions that need closing.
541   client_lock.Lock();
542   _close_sessions();
543   client_lock.Unlock();
544
545   cct->_conf->remove_observer(this);
546
547   AdminSocket* admin_socket = cct->get_admin_socket();
548   admin_socket->unregister_command("mds_requests");
549   admin_socket->unregister_command("mds_sessions");
550   admin_socket->unregister_command("dump_cache");
551   admin_socket->unregister_command("kick_stale_sessions");
552   admin_socket->unregister_command("status");
553
554   if (ino_invalidate_cb) {
555     ldout(cct, 10) << "shutdown stopping cache invalidator finisher" << dendl;
556     async_ino_invalidator.wait_for_empty();
557     async_ino_invalidator.stop();
558   }
559
560   if (dentry_invalidate_cb) {
561     ldout(cct, 10) << "shutdown stopping dentry invalidator finisher" << dendl;
562     async_dentry_invalidator.wait_for_empty();
563     async_dentry_invalidator.stop();
564   }
565
566   if (switch_interrupt_cb) {
567     ldout(cct, 10) << "shutdown stopping interrupt finisher" << dendl;
568     interrupt_finisher.wait_for_empty();
569     interrupt_finisher.stop();
570   }
571
572   if (remount_cb) {
573     ldout(cct, 10) << "shutdown stopping remount finisher" << dendl;
574     remount_finisher.wait_for_empty();
575     remount_finisher.stop();
576   }
577
578   objectcacher->stop();  // outside of client_lock! this does a join.
579
580   client_lock.Lock();
581   assert(initialized);
582   initialized = false;
583   timer.shutdown();
584   client_lock.Unlock();
585
586   objecter_finisher.wait_for_empty();
587   objecter_finisher.stop();
588
589   if (logger) {
590     cct->get_perfcounters_collection()->remove(logger.get());
591     logger.reset();
592   }
593 }
594
595
596 // ===================
597 // metadata cache stuff
598
599 void Client::trim_cache(bool trim_kernel_dcache)
600 {
601   uint64_t max = cct->_conf->client_cache_size;
602   ldout(cct, 20) << "trim_cache size " << lru.lru_get_size() << " max " << max << dendl;
603   unsigned last = 0;
604   while (lru.lru_get_size() != last) {
605     last = lru.lru_get_size();
606
607     if (!unmounting && lru.lru_get_size() <= max)  break;
608
609     // trim!
610     Dentry *dn = static_cast<Dentry*>(lru.lru_get_next_expire());
611     if (!dn)
612       break;  // done
613     
614     trim_dentry(dn);
615   }
616
617   if (trim_kernel_dcache && lru.lru_get_size() > max)
618     _invalidate_kernel_dcache();
619
620   // hose root?
621   if (lru.lru_get_size() == 0 && root && root->get_num_ref() == 0 && inode_map.size() == 1 + root_parents.size()) {
622     ldout(cct, 15) << "trim_cache trimmed root " << root << dendl;
623     delete root;
624     root = 0;
625     root_ancestor = 0;
626     while (!root_parents.empty())
627       root_parents.erase(root_parents.begin());
628     inode_map.clear();
629     _reset_faked_inos();
630   }
631 }
632
633 void Client::trim_cache_for_reconnect(MetaSession *s)
634 {
635   mds_rank_t mds = s->mds_num;
636   ldout(cct, 20) << "trim_cache_for_reconnect mds." << mds << dendl;
637
638   int trimmed = 0;
639   list<Dentry*> skipped;
640   while (lru.lru_get_size() > 0) {
641     Dentry *dn = static_cast<Dentry*>(lru.lru_expire());
642     if (!dn)
643       break;
644
645     if ((dn->inode && dn->inode->caps.count(mds)) ||
646         dn->dir->parent_inode->caps.count(mds)) {
647       trim_dentry(dn);
648       trimmed++;
649     } else
650       skipped.push_back(dn);
651   }
652
653   for(list<Dentry*>::iterator p = skipped.begin(); p != skipped.end(); ++p)
654     lru.lru_insert_mid(*p);
655
656   ldout(cct, 20) << "trim_cache_for_reconnect mds." << mds
657                  << " trimmed " << trimmed << " dentries" << dendl;
658
659   if (s->caps.size() > 0)
660     _invalidate_kernel_dcache();
661 }
662
663 void Client::trim_dentry(Dentry *dn)
664 {
665   ldout(cct, 15) << "trim_dentry unlinking dn " << dn->name 
666                  << " in dir " << hex << dn->dir->parent_inode->ino 
667                  << dendl;
668   if (dn->inode) {
669     Inode *diri = dn->dir->parent_inode;
670     diri->dir_release_count++;
671     clear_dir_complete_and_ordered(diri, true);
672   }
673   unlink(dn, false, false);  // drop dir, drop dentry
674 }
675
676
677 void Client::update_inode_file_bits(Inode *in,
678                                     uint64_t truncate_seq, uint64_t truncate_size,
679                                     uint64_t size, uint64_t change_attr,
680                                     uint64_t time_warp_seq, utime_t ctime,
681                                     utime_t mtime,
682                                     utime_t atime,
683                                     version_t inline_version,
684                                     bufferlist& inline_data,
685                                     int issued)
686 {
687   bool warn = false;
688   ldout(cct, 10) << "update_inode_file_bits " << *in << " " << ccap_string(issued)
689            << " mtime " << mtime << dendl;
690   ldout(cct, 25) << "truncate_seq: mds " << truncate_seq <<  " local "
691            << in->truncate_seq << " time_warp_seq: mds " << time_warp_seq
692            << " local " << in->time_warp_seq << dendl;
693   uint64_t prior_size = in->size;
694
695   if (inline_version > in->inline_version) {
696     in->inline_data = inline_data;
697     in->inline_version = inline_version;
698   }
699
700   /* always take a newer change attr */
701   if (change_attr > in->change_attr)
702     in->change_attr = change_attr;
703
704   if (truncate_seq > in->truncate_seq ||
705       (truncate_seq == in->truncate_seq && size > in->size)) {
706     ldout(cct, 10) << "size " << in->size << " -> " << size << dendl;
707     in->size = size;
708     in->reported_size = size;
709     if (truncate_seq != in->truncate_seq) {
710       ldout(cct, 10) << "truncate_seq " << in->truncate_seq << " -> "
711                << truncate_seq << dendl;
712       in->truncate_seq = truncate_seq;
713       in->oset.truncate_seq = truncate_seq;
714
715       // truncate cached file data
716       if (prior_size > size) {
717         _invalidate_inode_cache(in, truncate_size, prior_size - truncate_size);
718       }
719     }
720
721     // truncate inline data
722     if (in->inline_version < CEPH_INLINE_NONE) {
723       uint32_t len = in->inline_data.length();
724       if (size < len)
725         in->inline_data.splice(size, len - size);
726     }
727   }
728   if (truncate_seq >= in->truncate_seq &&
729       in->truncate_size != truncate_size) {
730     if (in->is_file()) {
731       ldout(cct, 10) << "truncate_size " << in->truncate_size << " -> "
732                << truncate_size << dendl;
733       in->truncate_size = truncate_size;
734       in->oset.truncate_size = truncate_size;
735     } else {
736       ldout(cct, 0) << "Hmmm, truncate_seq && truncate_size changed on non-file inode!" << dendl;
737     }
738   }
739   
740   // be careful with size, mtime, atime
741   if (issued & (CEPH_CAP_FILE_EXCL|
742                 CEPH_CAP_FILE_WR|
743                 CEPH_CAP_FILE_BUFFER|
744                 CEPH_CAP_AUTH_EXCL|
745                 CEPH_CAP_XATTR_EXCL)) {
746     ldout(cct, 30) << "Yay have enough caps to look at our times" << dendl;
747     if (ctime > in->ctime) 
748       in->ctime = ctime;
749     if (time_warp_seq > in->time_warp_seq) {
750       ldout(cct, 10) << "mds time_warp_seq " << time_warp_seq << " on inode " << *in
751                << " is higher than local time_warp_seq "
752                << in->time_warp_seq << dendl;
753       //the mds updated times, so take those!
754       in->mtime = mtime;
755       in->atime = atime;
756       in->time_warp_seq = time_warp_seq;
757     } else if (time_warp_seq == in->time_warp_seq) {
758       //take max times
759       if (mtime > in->mtime)
760         in->mtime = mtime;
761       if (atime > in->atime)
762         in->atime = atime;
763     } else if (issued & CEPH_CAP_FILE_EXCL) {
764       //ignore mds values as we have a higher seq
765     } else warn = true;
766   } else {
767     ldout(cct, 30) << "Don't have enough caps, just taking mds' time values" << dendl;
768     if (time_warp_seq >= in->time_warp_seq) {
769       in->ctime = ctime;
770       in->mtime = mtime;
771       in->atime = atime;
772       in->time_warp_seq = time_warp_seq;
773     } else warn = true;
774   }
775   if (warn) {
776     ldout(cct, 0) << "WARNING: " << *in << " mds time_warp_seq "
777             << time_warp_seq << " is lower than local time_warp_seq "
778             << in->time_warp_seq
779             << dendl;
780   }
781 }
782
783 void Client::_fragmap_remove_non_leaves(Inode *in)
784 {
785   for (map<frag_t,int>::iterator p = in->fragmap.begin(); p != in->fragmap.end(); )
786     if (!in->dirfragtree.is_leaf(p->first))
787       in->fragmap.erase(p++);
788     else
789       ++p;
790 }
791
792 void Client::_fragmap_remove_stopped_mds(Inode *in, mds_rank_t mds)
793 {
794   for (auto p = in->fragmap.begin(); p != in->fragmap.end(); )
795     if (p->second == mds)
796       in->fragmap.erase(p++);
797     else
798       ++p;
799 }
800
801 Inode * Client::add_update_inode(InodeStat *st, utime_t from,
802                                  MetaSession *session,
803                                  const UserPerm& request_perms)
804 {
805   Inode *in;
806   bool was_new = false;
807   if (inode_map.count(st->vino)) {
808     in = inode_map[st->vino];
809     ldout(cct, 12) << "add_update_inode had " << *in << " caps " << ccap_string(st->cap.caps) << dendl;
810   } else {
811     in = new Inode(this, st->vino, &st->layout);
812     inode_map[st->vino] = in;
813
814     if (use_faked_inos())
815       _assign_faked_ino(in);
816
817     if (!root) {
818       root = in;
819       root_ancestor = in;
820       cwd = root;
821     } else if (!mounted) {
822       root_parents[root_ancestor] = in;
823       root_ancestor = in;
824     }
825
826     // immutable bits
827     in->ino = st->vino.ino;
828     in->snapid = st->vino.snapid;
829     in->mode = st->mode & S_IFMT;
830     was_new = true;
831   }
832
833   in->rdev = st->rdev;
834   if (in->is_symlink())
835     in->symlink = st->symlink;
836
837   if (was_new)
838     ldout(cct, 12) << "add_update_inode adding " << *in << " caps " << ccap_string(st->cap.caps) << dendl;
839
840   if (!st->cap.caps)
841     return in;   // as with readdir returning indoes in different snaprealms (no caps!)
842
843   // only update inode if mds info is strictly newer, or it is the same and projected (odd).
844   bool updating_inode = false;
845   int issued = 0;
846   if (st->version == 0 ||
847       (in->version & ~1) < st->version) {
848     updating_inode = true;
849
850     int implemented = 0;
851     issued = in->caps_issued(&implemented) | in->caps_dirty();
852     issued |= implemented;
853
854     in->version = st->version;
855
856     if ((issued & CEPH_CAP_AUTH_EXCL) == 0) {
857       in->mode = st->mode;
858       in->uid = st->uid;
859       in->gid = st->gid;
860       in->btime = st->btime;
861     }
862
863     if ((issued & CEPH_CAP_LINK_EXCL) == 0) {
864       in->nlink = st->nlink;
865     }
866
867     in->dirstat = st->dirstat;
868     in->rstat = st->rstat;
869     in->quota = st->quota;
870     in->layout = st->layout;
871
872     if (in->is_dir()) {
873       in->dir_layout = st->dir_layout;
874       ldout(cct, 20) << " dir hash is " << (int)in->dir_layout.dl_dir_hash << dendl;
875     }
876
877     update_inode_file_bits(in, st->truncate_seq, st->truncate_size, st->size,
878                            st->change_attr, st->time_warp_seq, st->ctime,
879                            st->mtime, st->atime, st->inline_version,
880                            st->inline_data, issued);
881   } else if (st->inline_version > in->inline_version) {
882     in->inline_data = st->inline_data;
883     in->inline_version = st->inline_version;
884   }
885
886   if ((in->xattr_version  == 0 || !(issued & CEPH_CAP_XATTR_EXCL)) &&
887       st->xattrbl.length() &&
888       st->xattr_version > in->xattr_version) {
889     bufferlist::iterator p = st->xattrbl.begin();
890     ::decode(in->xattrs, p);
891     in->xattr_version = st->xattr_version;
892   }
893
894   // move me if/when version reflects fragtree changes.
895   if (in->dirfragtree != st->dirfragtree) {
896     in->dirfragtree = st->dirfragtree;
897     _fragmap_remove_non_leaves(in);
898   }
899
900   if (in->snapid == CEPH_NOSNAP) {
901     add_update_cap(in, session, st->cap.cap_id, st->cap.caps, st->cap.seq,
902                    st->cap.mseq, inodeno_t(st->cap.realm), st->cap.flags,
903                    request_perms);
904     if (in->auth_cap && in->auth_cap->session == session)
905       in->max_size = st->max_size;
906   } else
907     in->snap_caps |= st->cap.caps;
908
909   // setting I_COMPLETE needs to happen after adding the cap
910   if (updating_inode &&
911       in->is_dir() &&
912       (st->cap.caps & CEPH_CAP_FILE_SHARED) &&
913       (issued & CEPH_CAP_FILE_EXCL) == 0 &&
914       in->dirstat.nfiles == 0 &&
915       in->dirstat.nsubdirs == 0) {
916     ldout(cct, 10) << " marking (I_COMPLETE|I_DIR_ORDERED) on empty dir " << *in << dendl;
917     in->flags |= I_COMPLETE | I_DIR_ORDERED;
918     if (in->dir) {
919       ldout(cct, 10) << " dir is open on empty dir " << in->ino << " with "
920                      << in->dir->dentries.size() << " entries, marking all dentries null" << dendl;
921       in->dir->readdir_cache.clear();
922       for (auto p = in->dir->dentries.begin();
923            p != in->dir->dentries.end();
924            ++p) {
925         unlink(p->second, true, true);  // keep dir, keep dentry
926       }
927       if (in->dir->dentries.empty())
928         close_dir(in->dir);
929     }
930   }
931
932   return in;
933 }
934
935
936 /*
937  * insert_dentry_inode - insert + link a single dentry + inode into the metadata cache.
938  */
939 Dentry *Client::insert_dentry_inode(Dir *dir, const string& dname, LeaseStat *dlease, 
940                                     Inode *in, utime_t from, MetaSession *session,
941                                     Dentry *old_dentry)
942 {
943   Dentry *dn = NULL;
944   if (dir->dentries.count(dname))
945     dn = dir->dentries[dname];
946
947   ldout(cct, 12) << "insert_dentry_inode '" << dname << "' vino " << in->vino()
948                  << " in dir " << dir->parent_inode->vino() << " dn " << dn
949                  << dendl;
950
951   if (dn && dn->inode) {
952     if (dn->inode->vino() == in->vino()) {
953       touch_dn(dn);
954       ldout(cct, 12) << " had dentry " << dname
955                << " with correct vino " << dn->inode->vino()
956                << dendl;
957     } else {
958       ldout(cct, 12) << " had dentry " << dname
959                << " with WRONG vino " << dn->inode->vino()
960                << dendl;
961       unlink(dn, true, true);  // keep dir, keep dentry
962     }
963   }
964   
965   if (!dn || !dn->inode) {
966     InodeRef tmp_ref(in);
967     if (old_dentry) {
968       if (old_dentry->dir != dir) {
969         Inode *old_diri = old_dentry->dir->parent_inode;
970         old_diri->dir_ordered_count++;
971         clear_dir_complete_and_ordered(old_diri, false);
972       }
973       unlink(old_dentry, dir == old_dentry->dir, false);  // drop dentry, keep dir open if its the same dir
974     }
975     Inode *diri = dir->parent_inode;
976     diri->dir_ordered_count++;
977     clear_dir_complete_and_ordered(diri, false);
978     dn = link(dir, dname, in, dn);
979   }
980
981   update_dentry_lease(dn, dlease, from, session);
982   return dn;
983 }
984
985 void Client::update_dentry_lease(Dentry *dn, LeaseStat *dlease, utime_t from, MetaSession *session)
986 {
987   utime_t dttl = from;
988   dttl += (float)dlease->duration_ms / 1000.0;
989   
990   assert(dn);
991
992   if (dlease->mask & CEPH_LOCK_DN) {
993     if (dttl > dn->lease_ttl) {
994       ldout(cct, 10) << "got dentry lease on " << dn->name
995                << " dur " << dlease->duration_ms << "ms ttl " << dttl << dendl;
996       dn->lease_ttl = dttl;
997       dn->lease_mds = session->mds_num;
998       dn->lease_seq = dlease->seq;
999       dn->lease_gen = session->cap_gen;
1000     }
1001   }
1002   dn->cap_shared_gen = dn->dir->parent_inode->shared_gen;
1003 }
1004
1005
1006 /*
1007  * update MDS location cache for a single inode
1008  */
1009 void Client::update_dir_dist(Inode *in, DirStat *dst)
1010 {
1011   // auth
1012   ldout(cct, 20) << "got dirfrag map for " << in->ino << " frag " << dst->frag << " to mds " << dst->auth << dendl;
1013   if (dst->auth >= 0) {
1014     in->fragmap[dst->frag] = dst->auth;
1015   } else {
1016     in->fragmap.erase(dst->frag);
1017   }
1018   if (!in->dirfragtree.is_leaf(dst->frag)) {
1019     in->dirfragtree.force_to_leaf(cct, dst->frag);
1020     _fragmap_remove_non_leaves(in);
1021   }
1022
1023   // replicated
1024   in->dir_replicated = !dst->dist.empty();  // FIXME that's just one frag!
1025   
1026   // dist
1027   /*
1028   if (!st->dirfrag_dist.empty()) {   // FIXME
1029     set<int> dist = st->dirfrag_dist.begin()->second;
1030     if (dist.empty() && !in->dir_contacts.empty())
1031       ldout(cct, 9) << "lost dist spec for " << in->ino 
1032               << " " << dist << dendl;
1033     if (!dist.empty() && in->dir_contacts.empty()) 
1034       ldout(cct, 9) << "got dist spec for " << in->ino 
1035               << " " << dist << dendl;
1036     in->dir_contacts = dist;
1037   }
1038   */
1039 }
1040
1041 void Client::clear_dir_complete_and_ordered(Inode *diri, bool complete)
1042 {
1043   if (diri->flags & I_COMPLETE) {
1044     if (complete) {
1045       ldout(cct, 10) << " clearing (I_COMPLETE|I_DIR_ORDERED) on " << *diri << dendl;
1046       diri->flags &= ~(I_COMPLETE | I_DIR_ORDERED);
1047     } else {
1048       if (diri->flags & I_DIR_ORDERED) {
1049         ldout(cct, 10) << " clearing I_DIR_ORDERED on " << *diri << dendl;
1050         diri->flags &= ~I_DIR_ORDERED;
1051       }
1052     }
1053     if (diri->dir)
1054       diri->dir->readdir_cache.clear();
1055   }
1056 }
1057
1058 /*
1059  * insert results from readdir or lssnap into the metadata cache.
1060  */
1061 void Client::insert_readdir_results(MetaRequest *request, MetaSession *session, Inode *diri) {
1062
1063   MClientReply *reply = request->reply;
1064   ConnectionRef con = request->reply->get_connection();
1065   uint64_t features = con->get_features();
1066
1067   dir_result_t *dirp = request->dirp;
1068   assert(dirp);
1069
1070   // the extra buffer list is only set for readdir and lssnap replies
1071   bufferlist::iterator p = reply->get_extra_bl().begin();
1072   if (!p.end()) {
1073     // snapdir?
1074     if (request->head.op == CEPH_MDS_OP_LSSNAP) {
1075       assert(diri);
1076       diri = open_snapdir(diri);
1077     }
1078
1079     // only open dir if we're actually adding stuff to it!
1080     Dir *dir = diri->open_dir();
1081     assert(dir);
1082
1083     // dirstat
1084     DirStat dst(p);
1085     __u32 numdn;
1086     __u16 flags;
1087     ::decode(numdn, p);
1088     ::decode(flags, p);
1089
1090     bool end = ((unsigned)flags & CEPH_READDIR_FRAG_END);
1091     bool hash_order = ((unsigned)flags & CEPH_READDIR_HASH_ORDER);
1092
1093     frag_t fg = (unsigned)request->head.args.readdir.frag;
1094     unsigned readdir_offset = dirp->next_offset;
1095     string readdir_start = dirp->last_name;
1096     assert(!readdir_start.empty() || readdir_offset == 2);
1097
1098     unsigned last_hash = 0;
1099     if (hash_order) {
1100       if (!readdir_start.empty()) {
1101         last_hash = ceph_frag_value(diri->hash_dentry_name(readdir_start));
1102       } else if (flags & CEPH_READDIR_OFFSET_HASH) {
1103         /* mds understands offset_hash */
1104         last_hash = (unsigned)request->head.args.readdir.offset_hash;
1105       }
1106     }
1107
1108     if (fg != dst.frag) {
1109       ldout(cct, 10) << "insert_trace got new frag " << fg << " -> " << dst.frag << dendl;
1110       fg = dst.frag;
1111       if (!hash_order) {
1112         readdir_offset = 2;
1113         readdir_start.clear();
1114         dirp->offset = dir_result_t::make_fpos(fg, readdir_offset, false);
1115       }
1116     }
1117
1118     ldout(cct, 10) << __func__ << " " << numdn << " readdir items, end=" << end
1119                    << ", hash_order=" << hash_order
1120                    << ", readdir_start " << readdir_start
1121                    << ", last_hash " << last_hash
1122                    << ", next_offset " << readdir_offset << dendl;
1123
1124     if (diri->snapid != CEPH_SNAPDIR &&
1125         fg.is_leftmost() && readdir_offset == 2 &&
1126         !(hash_order && last_hash)) {
1127       dirp->release_count = diri->dir_release_count;
1128       dirp->ordered_count = diri->dir_ordered_count;
1129       dirp->start_shared_gen = diri->shared_gen;
1130       dirp->cache_index = 0;
1131     }
1132
1133     dirp->buffer_frag = fg;
1134
1135     _readdir_drop_dirp_buffer(dirp);
1136     dirp->buffer.reserve(numdn);
1137
1138     string dname;
1139     LeaseStat dlease;
1140     for (unsigned i=0; i<numdn; i++) {
1141       ::decode(dname, p);
1142       ::decode(dlease, p);
1143       InodeStat ist(p, features);
1144
1145       ldout(cct, 15) << "" << i << ": '" << dname << "'" << dendl;
1146
1147       Inode *in = add_update_inode(&ist, request->sent_stamp, session,
1148                                    request->perms);
1149       Dentry *dn;
1150       if (diri->dir->dentries.count(dname)) {
1151         Dentry *olddn = diri->dir->dentries[dname];
1152         if (olddn->inode != in) {
1153           // replace incorrect dentry
1154           unlink(olddn, true, true);  // keep dir, dentry
1155           dn = link(dir, dname, in, olddn);
1156           assert(dn == olddn);
1157         } else {
1158           // keep existing dn
1159           dn = olddn;
1160           touch_dn(dn);
1161         }
1162       } else {
1163         // new dn
1164         dn = link(dir, dname, in, NULL);
1165       }
1166
1167       update_dentry_lease(dn, &dlease, request->sent_stamp, session);
1168       if (hash_order) {
1169         unsigned hash = ceph_frag_value(diri->hash_dentry_name(dname));
1170         if (hash != last_hash)
1171           readdir_offset = 2;
1172         last_hash = hash;
1173         dn->offset = dir_result_t::make_fpos(hash, readdir_offset++, true);
1174       } else {
1175         dn->offset = dir_result_t::make_fpos(fg, readdir_offset++, false);
1176       }
1177       // add to readdir cache
1178       if (dirp->release_count == diri->dir_release_count &&
1179           dirp->ordered_count == diri->dir_ordered_count &&
1180           dirp->start_shared_gen == diri->shared_gen) {
1181         if (dirp->cache_index == dir->readdir_cache.size()) {
1182           if (i == 0) {
1183             assert(!dirp->inode->is_complete_and_ordered());
1184             dir->readdir_cache.reserve(dirp->cache_index + numdn);
1185           }
1186           dir->readdir_cache.push_back(dn);
1187         } else if (dirp->cache_index < dir->readdir_cache.size()) {
1188           if (dirp->inode->is_complete_and_ordered())
1189             assert(dir->readdir_cache[dirp->cache_index] == dn);
1190           else
1191             dir->readdir_cache[dirp->cache_index] = dn;
1192         } else {
1193           assert(0 == "unexpected readdir buffer idx");
1194         }
1195         dirp->cache_index++;
1196       }
1197       // add to cached result list
1198       dirp->buffer.push_back(dir_result_t::dentry(dn->offset, dname, in));
1199       ldout(cct, 15) << __func__ << "  " << hex << dn->offset << dec << ": '" << dname << "' -> " << in->ino << dendl;
1200     }
1201
1202     if (numdn > 0)
1203       dirp->last_name = dname;
1204     if (end)
1205       dirp->next_offset = 2;
1206     else
1207       dirp->next_offset = readdir_offset;
1208
1209     if (dir->is_empty())
1210       close_dir(dir);
1211   }
1212 }
1213
1214 /** insert_trace
1215  *
1216  * insert a trace from a MDS reply into the cache.
1217  */
1218 Inode* Client::insert_trace(MetaRequest *request, MetaSession *session)
1219 {
1220   MClientReply *reply = request->reply;
1221   int op = request->get_op();
1222
1223   ldout(cct, 10) << "insert_trace from " << request->sent_stamp << " mds." << session->mds_num
1224            << " is_target=" << (int)reply->head.is_target
1225            << " is_dentry=" << (int)reply->head.is_dentry
1226            << dendl;
1227
1228   bufferlist::iterator p = reply->get_trace_bl().begin();
1229   if (request->got_unsafe) {
1230     ldout(cct, 10) << "insert_trace -- already got unsafe; ignoring" << dendl;
1231     assert(p.end());
1232     return NULL;
1233   }
1234
1235   if (p.end()) {
1236     ldout(cct, 10) << "insert_trace -- no trace" << dendl;
1237
1238     Dentry *d = request->dentry();
1239     if (d) {
1240       Inode *diri = d->dir->parent_inode;
1241       diri->dir_release_count++;
1242       clear_dir_complete_and_ordered(diri, true);
1243     }
1244
1245     if (d && reply->get_result() == 0) {
1246       if (op == CEPH_MDS_OP_RENAME) {
1247         // rename
1248         Dentry *od = request->old_dentry();
1249         ldout(cct, 10) << " unlinking rename src dn " << od << " for traceless reply" << dendl;
1250         assert(od);
1251         unlink(od, true, true);  // keep dir, dentry
1252       } else if (op == CEPH_MDS_OP_RMDIR ||
1253                  op == CEPH_MDS_OP_UNLINK) {
1254         // unlink, rmdir
1255         ldout(cct, 10) << " unlinking unlink/rmdir dn " << d << " for traceless reply" << dendl;
1256         unlink(d, true, true);  // keep dir, dentry
1257       }
1258     }
1259     return NULL;
1260   }
1261
1262   ConnectionRef con = request->reply->get_connection();
1263   uint64_t features = con->get_features();
1264   ldout(cct, 10) << " features 0x" << hex << features << dec << dendl;
1265
1266   // snap trace
1267   SnapRealm *realm = NULL;
1268   if (reply->snapbl.length())
1269     update_snap_trace(reply->snapbl, &realm);
1270
1271   ldout(cct, 10) << " hrm " 
1272            << " is_target=" << (int)reply->head.is_target
1273            << " is_dentry=" << (int)reply->head.is_dentry
1274            << dendl;
1275
1276   InodeStat dirst;
1277   DirStat dst;
1278   string dname;
1279   LeaseStat dlease;
1280   InodeStat ist;
1281
1282   if (reply->head.is_dentry) {
1283     dirst.decode(p, features);
1284     dst.decode(p);
1285     ::decode(dname, p);
1286     ::decode(dlease, p);
1287   }
1288
1289   Inode *in = 0;
1290   if (reply->head.is_target) {
1291     ist.decode(p, features);
1292     if (cct->_conf->client_debug_getattr_caps) {
1293       unsigned wanted = 0;
1294       if (op == CEPH_MDS_OP_GETATTR || op == CEPH_MDS_OP_LOOKUP)
1295         wanted = request->head.args.getattr.mask;
1296       else if (op == CEPH_MDS_OP_OPEN || op == CEPH_MDS_OP_CREATE)
1297         wanted = request->head.args.open.mask;
1298
1299       if ((wanted & CEPH_CAP_XATTR_SHARED) &&
1300           !(ist.xattr_version > 0 && ist.xattrbl.length() > 0))
1301           assert(0 == "MDS reply does not contain xattrs");
1302     }
1303
1304     in = add_update_inode(&ist, request->sent_stamp, session,
1305                           request->perms);
1306   }
1307
1308   Inode *diri = NULL;
1309   if (reply->head.is_dentry) {
1310     diri = add_update_inode(&dirst, request->sent_stamp, session,
1311                             request->perms);
1312     update_dir_dist(diri, &dst);  // dir stat info is attached to ..
1313
1314     if (in) {
1315       Dir *dir = diri->open_dir();
1316       insert_dentry_inode(dir, dname, &dlease, in, request->sent_stamp, session,
1317                           (op == CEPH_MDS_OP_RENAME) ? request->old_dentry() : NULL);
1318     } else {
1319       Dentry *dn = NULL;
1320       if (diri->dir && diri->dir->dentries.count(dname)) {
1321         dn = diri->dir->dentries[dname];
1322         if (dn->inode) {
1323           diri->dir_ordered_count++;
1324           clear_dir_complete_and_ordered(diri, false);
1325           unlink(dn, true, true);  // keep dir, dentry
1326         }
1327       }
1328       if (dlease.duration_ms > 0) {
1329         if (!dn) {
1330           Dir *dir = diri->open_dir();
1331           dn = link(dir, dname, NULL, NULL);
1332         }
1333         update_dentry_lease(dn, &dlease, request->sent_stamp, session);
1334       }
1335     }
1336   } else if (op == CEPH_MDS_OP_LOOKUPSNAP ||
1337              op == CEPH_MDS_OP_MKSNAP) {
1338     ldout(cct, 10) << " faking snap lookup weirdness" << dendl;
1339     // fake it for snap lookup
1340     vinodeno_t vino = ist.vino;
1341     vino.snapid = CEPH_SNAPDIR;
1342     assert(inode_map.count(vino));
1343     diri = inode_map[vino];
1344     
1345     string dname = request->path.last_dentry();
1346     
1347     LeaseStat dlease;
1348     dlease.duration_ms = 0;
1349
1350     if (in) {
1351       Dir *dir = diri->open_dir();
1352       insert_dentry_inode(dir, dname, &dlease, in, request->sent_stamp, session);
1353     } else {
1354       if (diri->dir && diri->dir->dentries.count(dname)) {
1355         Dentry *dn = diri->dir->dentries[dname];
1356         if (dn->inode)
1357           unlink(dn, true, true);  // keep dir, dentry
1358       }
1359     }
1360   }
1361
1362   if (in) {
1363     if (op == CEPH_MDS_OP_READDIR ||
1364         op == CEPH_MDS_OP_LSSNAP) {
1365       insert_readdir_results(request, session, in);
1366     } else if (op == CEPH_MDS_OP_LOOKUPNAME) {
1367       // hack: return parent inode instead
1368       in = diri;
1369     }
1370
1371     if (request->dentry() == NULL && in != request->inode()) {
1372       // pin the target inode if its parent dentry is not pinned
1373       request->set_other_inode(in);
1374     }
1375   }
1376
1377   if (realm)
1378     put_snap_realm(realm);
1379
1380   request->target = in;
1381   return in;
1382 }
1383
1384 // -------
1385
1386 mds_rank_t Client::choose_target_mds(MetaRequest *req, Inode** phash_diri)
1387 {
1388   mds_rank_t mds = MDS_RANK_NONE;
1389   __u32 hash = 0;
1390   bool is_hash = false;
1391
1392   Inode *in = NULL;
1393   Dentry *de = NULL;
1394   Cap *cap = NULL;
1395
1396   if (req->resend_mds >= 0) {
1397     mds = req->resend_mds;
1398     req->resend_mds = -1;
1399     ldout(cct, 10) << "choose_target_mds resend_mds specified as mds." << mds << dendl;
1400     goto out;
1401   }
1402
1403   if (cct->_conf->client_use_random_mds)
1404     goto random_mds;
1405
1406   in = req->inode();
1407   de = req->dentry();
1408   if (in) {
1409     ldout(cct, 20) << "choose_target_mds starting with req->inode " << *in << dendl;
1410     if (req->path.depth()) {
1411       hash = in->hash_dentry_name(req->path[0]);
1412       ldout(cct, 20) << "choose_target_mds inode dir hash is " << (int)in->dir_layout.dl_dir_hash
1413                << " on " << req->path[0]
1414                << " => " << hash << dendl;
1415       is_hash = true;
1416     }
1417   } else if (de) {
1418     if (de->inode) {
1419       in = de->inode.get();
1420       ldout(cct, 20) << "choose_target_mds starting with req->dentry inode " << *in << dendl;
1421     } else {
1422       in = de->dir->parent_inode;
1423       hash = in->hash_dentry_name(de->name);
1424       ldout(cct, 20) << "choose_target_mds dentry dir hash is " << (int)in->dir_layout.dl_dir_hash
1425                << " on " << de->name
1426                << " => " << hash << dendl;
1427       is_hash = true;
1428     }
1429   }
1430   if (in) {
1431     if (in->snapid != CEPH_NOSNAP) {
1432       ldout(cct, 10) << "choose_target_mds " << *in << " is snapped, using nonsnap parent" << dendl;
1433       while (in->snapid != CEPH_NOSNAP) {
1434         if (in->snapid == CEPH_SNAPDIR)
1435           in = in->snapdir_parent.get();
1436         else if (!in->dn_set.empty())
1437           /* In most cases there will only be one dentry, so getting it
1438            * will be the correct action. If there are multiple hard links,
1439            * I think the MDS should be able to redirect as needed*/
1440           in = in->get_first_parent()->dir->parent_inode;
1441         else {
1442           ldout(cct, 10) << "got unlinked inode, can't look at parent" << dendl;
1443           break;
1444         }
1445       }
1446       is_hash = false;
1447     }
1448   
1449     ldout(cct, 20) << "choose_target_mds " << *in << " is_hash=" << is_hash
1450              << " hash=" << hash << dendl;
1451   
1452     if (is_hash && S_ISDIR(in->mode) && !in->fragmap.empty()) {
1453       frag_t fg = in->dirfragtree[hash];
1454       if (in->fragmap.count(fg)) {
1455         mds = in->fragmap[fg];
1456         if (phash_diri)
1457           *phash_diri = in;
1458         ldout(cct, 10) << "choose_target_mds from dirfragtree hash" << dendl;
1459         goto out;
1460       }
1461     }
1462   
1463     if (req->auth_is_best())
1464       cap = in->auth_cap;
1465     if (!cap && !in->caps.empty())
1466       cap = in->caps.begin()->second;
1467     if (!cap)
1468       goto random_mds;
1469     mds = cap->session->mds_num;
1470     ldout(cct, 10) << "choose_target_mds from caps on inode " << *in << dendl;
1471   
1472     goto out;
1473   }
1474
1475 random_mds:
1476   if (mds < 0) {
1477     mds = _get_random_up_mds();
1478     ldout(cct, 10) << "did not get mds through better means, so chose random mds " << mds << dendl;
1479   }
1480
1481 out:
1482   ldout(cct, 20) << "mds is " << mds << dendl;
1483   return mds;
1484 }
1485
1486
1487 void Client::connect_mds_targets(mds_rank_t mds)
1488 {
1489   ldout(cct, 10) << "connect_mds_targets for mds." << mds << dendl;
1490   assert(mds_sessions.count(mds));
1491   const MDSMap::mds_info_t& info = mdsmap->get_mds_info(mds);
1492   for (set<mds_rank_t>::const_iterator q = info.export_targets.begin();
1493        q != info.export_targets.end();
1494        ++q) {
1495     if (mds_sessions.count(*q) == 0 &&
1496         mdsmap->is_clientreplay_or_active_or_stopping(*q)) {
1497       ldout(cct, 10) << "check_mds_sessions opening mds." << mds
1498                      << " export target mds." << *q << dendl;
1499       _open_mds_session(*q);
1500     }
1501   }
1502 }
1503
1504 void Client::dump_mds_sessions(Formatter *f)
1505 {
1506   f->dump_int("id", get_nodeid().v);
1507   f->open_array_section("sessions");
1508   for (map<mds_rank_t,MetaSession*>::const_iterator p = mds_sessions.begin(); p != mds_sessions.end(); ++p) {
1509     f->open_object_section("session");
1510     p->second->dump(f);
1511     f->close_section();
1512   }
1513   f->close_section();
1514   f->dump_int("mdsmap_epoch", mdsmap->get_epoch());
1515 }
1516 void Client::dump_mds_requests(Formatter *f)
1517 {
1518   for (map<ceph_tid_t, MetaRequest*>::iterator p = mds_requests.begin();
1519        p != mds_requests.end();
1520        ++p) {
1521     f->open_object_section("request");
1522     p->second->dump(f);
1523     f->close_section();
1524   }
1525 }
1526
1527 int Client::verify_reply_trace(int r,
1528                                MetaRequest *request, MClientReply *reply,
1529                                InodeRef *ptarget, bool *pcreated,
1530                                const UserPerm& perms)
1531 {
1532   // check whether this request actually did the create, and set created flag
1533   bufferlist extra_bl;
1534   inodeno_t created_ino;
1535   bool got_created_ino = false;
1536   ceph::unordered_map<vinodeno_t, Inode*>::iterator p;
1537
1538   extra_bl.claim(reply->get_extra_bl());
1539   if (extra_bl.length() >= 8) {
1540     // if the extra bufferlist has a buffer, we assume its the created inode
1541     // and that this request to create succeeded in actually creating
1542     // the inode (won the race with other create requests)
1543     ::decode(created_ino, extra_bl);
1544     got_created_ino = true;
1545     ldout(cct, 10) << "make_request created ino " << created_ino << dendl;
1546   }
1547
1548   if (pcreated)
1549     *pcreated = got_created_ino;
1550
1551   if (request->target) {
1552     *ptarget = request->target;
1553     ldout(cct, 20) << "make_request target is " << *ptarget->get() << dendl;
1554   } else {
1555     if (got_created_ino && (p = inode_map.find(vinodeno_t(created_ino, CEPH_NOSNAP))) != inode_map.end()) {
1556       (*ptarget) = p->second;
1557       ldout(cct, 20) << "make_request created, target is " << *ptarget->get() << dendl;
1558     } else {
1559       // we got a traceless reply, and need to look up what we just
1560       // created.  for now, do this by name.  someday, do this by the
1561       // ino... which we know!  FIXME.
1562       InodeRef target;
1563       Dentry *d = request->dentry();
1564       if (d) {
1565         if (d->dir) {
1566           ldout(cct, 10) << "make_request got traceless reply, looking up #"
1567                          << d->dir->parent_inode->ino << "/" << d->name
1568                          << " got_ino " << got_created_ino
1569                          << " ino " << created_ino
1570                          << dendl;
1571           r = _do_lookup(d->dir->parent_inode, d->name, request->regetattr_mask,
1572                          &target, perms);
1573         } else {
1574           // if the dentry is not linked, just do our best. see #5021.
1575           assert(0 == "how did this happen?  i want logs!");
1576         }
1577       } else {
1578         Inode *in = request->inode();
1579         ldout(cct, 10) << "make_request got traceless reply, forcing getattr on #"
1580                        << in->ino << dendl;
1581         r = _getattr(in, request->regetattr_mask, perms, true);
1582         target = in;
1583       }
1584       if (r >= 0) {
1585         // verify ino returned in reply and trace_dist are the same
1586         if (got_created_ino &&
1587             created_ino.val != target->ino.val) {
1588           ldout(cct, 5) << "create got ino " << created_ino << " but then failed on lookup; EINTR?" << dendl;
1589           r = -EINTR;
1590         }
1591         if (ptarget)
1592           ptarget->swap(target);
1593       }
1594     }
1595   }
1596
1597   return r;
1598 }
1599
1600
1601 /**
1602  * make a request
1603  *
1604  * Blocking helper to make an MDS request.
1605  *
1606  * If the ptarget flag is set, behavior changes slightly: the caller
1607  * expects to get a pointer to the inode we are creating or operating
1608  * on.  As a result, we will follow up any traceless mutation reply
1609  * with a getattr or lookup to transparently handle a traceless reply
1610  * from the MDS (as when the MDS restarts and the client has to replay
1611  * a request).
1612  *
1613  * @param request the MetaRequest to execute
1614  * @param perms The user uid/gid to execute as (eventually, full group lists?)
1615  * @param ptarget [optional] address to store a pointer to the target inode we want to create or operate on
1616  * @param pcreated [optional; required if ptarget] where to store a bool of whether our create atomically created a file
1617  * @param use_mds [optional] prefer a specific mds (-1 for default)
1618  * @param pdirbl [optional; disallowed if ptarget] where to pass extra reply payload to the caller
1619  */
1620 int Client::make_request(MetaRequest *request,
1621                          const UserPerm& perms,
1622                          InodeRef *ptarget, bool *pcreated,
1623                          mds_rank_t use_mds,
1624                          bufferlist *pdirbl)
1625 {
1626   int r = 0;
1627
1628   // assign a unique tid
1629   ceph_tid_t tid = ++last_tid;
1630   request->set_tid(tid);
1631
1632   // and timestamp
1633   request->op_stamp = ceph_clock_now();
1634
1635   // make note
1636   mds_requests[tid] = request->get();
1637   if (oldest_tid == 0 && request->get_op() != CEPH_MDS_OP_SETFILELOCK)
1638     oldest_tid = tid;
1639
1640   request->set_caller_perms(perms);
1641
1642   if (cct->_conf->client_inject_fixed_oldest_tid) {
1643     ldout(cct, 20) << __func__ << " injecting fixed oldest_client_tid(1)" << dendl;
1644     request->set_oldest_client_tid(1);
1645   } else {
1646     request->set_oldest_client_tid(oldest_tid);
1647   }
1648
1649   // hack target mds?
1650   if (use_mds >= 0)
1651     request->resend_mds = use_mds;
1652
1653   while (1) {
1654     if (request->aborted())
1655       break;
1656
1657     if (blacklisted) {
1658       request->abort(-EBLACKLISTED);
1659       break;
1660     }
1661
1662     // set up wait cond
1663     Cond caller_cond;
1664     request->caller_cond = &caller_cond;
1665
1666     // choose mds
1667     Inode *hash_diri = NULL;
1668     mds_rank_t mds = choose_target_mds(request, &hash_diri);
1669     int mds_state = (mds == MDS_RANK_NONE) ? MDSMap::STATE_NULL : mdsmap->get_state(mds);
1670     if (mds_state != MDSMap::STATE_ACTIVE && mds_state != MDSMap::STATE_STOPPING) {
1671       if (mds_state == MDSMap::STATE_NULL && mds >= mdsmap->get_max_mds()) {
1672         if (hash_diri) {
1673           ldout(cct, 10) << " target mds." << mds << " has stopped, remove it from fragmap" << dendl;
1674           _fragmap_remove_stopped_mds(hash_diri, mds);
1675         } else {
1676           ldout(cct, 10) << " target mds." << mds << " has stopped, trying a random mds" << dendl;
1677           request->resend_mds = _get_random_up_mds();
1678         }
1679       } else {
1680         ldout(cct, 10) << " target mds." << mds << " not active, waiting for new mdsmap" << dendl;
1681         wait_on_list(waiting_for_mdsmap);
1682       }
1683       continue;
1684     }
1685
1686     // open a session?
1687     MetaSession *session = NULL;
1688     if (!have_open_session(mds)) {
1689       session = _get_or_open_mds_session(mds);
1690
1691       // wait
1692       if (session->state == MetaSession::STATE_OPENING) {
1693         ldout(cct, 10) << "waiting for session to mds." << mds << " to open" << dendl;
1694         wait_on_context_list(session->waiting_for_open);
1695         // Abort requests on REJECT from MDS
1696         if (rejected_by_mds.count(mds)) {
1697           request->abort(-EPERM);
1698           break;
1699         }
1700         continue;
1701       }
1702
1703       if (!have_open_session(mds))
1704         continue;
1705     } else {
1706       session = mds_sessions[mds];
1707     }
1708
1709     // send request.
1710     send_request(request, session);
1711
1712     // wait for signal
1713     ldout(cct, 20) << "awaiting reply|forward|kick on " << &caller_cond << dendl;
1714     request->kick = false;
1715     while (!request->reply &&         // reply
1716            request->resend_mds < 0 && // forward
1717            !request->kick)
1718       caller_cond.Wait(client_lock);
1719     request->caller_cond = NULL;
1720
1721     // did we get a reply?
1722     if (request->reply) 
1723       break;
1724   }
1725
1726   if (!request->reply) {
1727     assert(request->aborted());
1728     assert(!request->got_unsafe);
1729     r = request->get_abort_code();
1730     request->item.remove_myself();
1731     unregister_request(request);
1732     put_request(request); // ours
1733     return r;
1734   }
1735
1736   // got it!
1737   MClientReply *reply = request->reply;
1738   request->reply = NULL;
1739   r = reply->get_result();
1740   if (r >= 0)
1741     request->success = true;
1742
1743   // kick dispatcher (we've got it!)
1744   assert(request->dispatch_cond);
1745   request->dispatch_cond->Signal();
1746   ldout(cct, 20) << "sendrecv kickback on tid " << tid << " " << request->dispatch_cond << dendl;
1747   request->dispatch_cond = 0;
1748   
1749   if (r >= 0 && ptarget)
1750     r = verify_reply_trace(r, request, reply, ptarget, pcreated, perms);
1751
1752   if (pdirbl)
1753     pdirbl->claim(reply->get_extra_bl());
1754
1755   // -- log times --
1756   utime_t lat = ceph_clock_now();
1757   lat -= request->sent_stamp;
1758   ldout(cct, 20) << "lat " << lat << dendl;
1759   logger->tinc(l_c_lat, lat);
1760   logger->tinc(l_c_reply, lat);
1761
1762   put_request(request);
1763
1764   reply->put();
1765   return r;
1766 }
1767
1768 void Client::unregister_request(MetaRequest *req)
1769 {
1770   mds_requests.erase(req->tid);
1771   if (req->tid == oldest_tid) {
1772     map<ceph_tid_t, MetaRequest*>::iterator p = mds_requests.upper_bound(oldest_tid);
1773     while (true) {
1774       if (p == mds_requests.end()) {
1775         oldest_tid = 0;
1776         break;
1777       }
1778       if (p->second->get_op() != CEPH_MDS_OP_SETFILELOCK) {
1779         oldest_tid = p->first;
1780         break;
1781       }
1782       ++p;
1783     }
1784   }
1785   put_request(req);
1786 }
1787
1788 void Client::put_request(MetaRequest *request)
1789 {
1790   if (request->_put()) {
1791     int op = -1;
1792     if (request->success)
1793       op = request->get_op();
1794     InodeRef other_in;
1795     request->take_other_inode(&other_in);
1796     delete request;
1797
1798     if (other_in &&
1799         (op == CEPH_MDS_OP_RMDIR ||
1800          op == CEPH_MDS_OP_RENAME ||
1801          op == CEPH_MDS_OP_RMSNAP)) {
1802       _try_to_trim_inode(other_in.get(), false);
1803     }
1804   }
1805 }
1806
1807 int Client::encode_inode_release(Inode *in, MetaRequest *req,
1808                          mds_rank_t mds, int drop,
1809                          int unless, int force)
1810 {
1811   ldout(cct, 20) << "encode_inode_release enter(in:" << *in << ", req:" << req
1812            << " mds:" << mds << ", drop:" << drop << ", unless:" << unless
1813            << ", have:" << ", force:" << force << ")" << dendl;
1814   int released = 0;
1815   if (in->caps.count(mds)) {
1816     Cap *caps = in->caps[mds];
1817     drop &= ~(in->dirty_caps | get_caps_used(in));
1818     if ((drop & caps->issued) &&
1819         !(unless & caps->issued)) {
1820       ldout(cct, 25) << "Dropping caps. Initial " << ccap_string(caps->issued) << dendl;
1821       caps->issued &= ~drop;
1822       caps->implemented &= ~drop;
1823       released = 1;
1824       ldout(cct, 25) << "Now have: " << ccap_string(caps->issued) << dendl;
1825     } else {
1826       released = force;
1827     }
1828     if (released) {
1829       ceph_mds_request_release rel;
1830       rel.ino = in->ino;
1831       rel.cap_id = caps->cap_id;
1832       rel.seq = caps->seq;
1833       rel.issue_seq = caps->issue_seq;
1834       rel.mseq = caps->mseq;
1835       rel.caps = caps->implemented;
1836       rel.wanted = caps->wanted;
1837       rel.dname_len = 0;
1838       rel.dname_seq = 0;
1839       req->cap_releases.push_back(MClientRequest::Release(rel,""));
1840     }
1841   }
1842   ldout(cct, 25) << "encode_inode_release exit(in:" << *in << ") released:"
1843            << released << dendl;
1844   return released;
1845 }
1846
1847 void Client::encode_dentry_release(Dentry *dn, MetaRequest *req,
1848                            mds_rank_t mds, int drop, int unless)
1849 {
1850   ldout(cct, 20) << "encode_dentry_release enter(dn:"
1851            << dn << ")" << dendl;
1852   int released = 0;
1853   if (dn->dir)
1854     released = encode_inode_release(dn->dir->parent_inode, req,
1855                                     mds, drop, unless, 1);
1856   if (released && dn->lease_mds == mds) {
1857     ldout(cct, 25) << "preemptively releasing dn to mds" << dendl;
1858     MClientRequest::Release& rel = req->cap_releases.back();
1859     rel.item.dname_len = dn->name.length();
1860     rel.item.dname_seq = dn->lease_seq;
1861     rel.dname = dn->name;
1862   }
1863   ldout(cct, 25) << "encode_dentry_release exit(dn:"
1864            << dn << ")" << dendl;
1865 }
1866
1867
1868 /*
1869  * This requires the MClientRequest *request member to be set.
1870  * It will error out horribly without one.
1871  * Additionally, if you set any *drop member, you'd better have
1872  * set the corresponding dentry!
1873  */
1874 void Client::encode_cap_releases(MetaRequest *req, mds_rank_t mds)
1875 {
1876   ldout(cct, 20) << "encode_cap_releases enter (req: "
1877                  << req << ", mds: " << mds << ")" << dendl;
1878   if (req->inode_drop && req->inode())
1879     encode_inode_release(req->inode(), req,
1880                          mds, req->inode_drop,
1881                          req->inode_unless);
1882   
1883   if (req->old_inode_drop && req->old_inode())
1884     encode_inode_release(req->old_inode(), req,
1885                          mds, req->old_inode_drop,
1886                          req->old_inode_unless);
1887   if (req->other_inode_drop && req->other_inode())
1888     encode_inode_release(req->other_inode(), req,
1889                          mds, req->other_inode_drop,
1890                          req->other_inode_unless);
1891   
1892   if (req->dentry_drop && req->dentry())
1893     encode_dentry_release(req->dentry(), req,
1894                           mds, req->dentry_drop,
1895                           req->dentry_unless);
1896   
1897   if (req->old_dentry_drop && req->old_dentry())
1898     encode_dentry_release(req->old_dentry(), req,
1899                           mds, req->old_dentry_drop,
1900                           req->old_dentry_unless);
1901   ldout(cct, 25) << "encode_cap_releases exit (req: "
1902            << req << ", mds " << mds <<dendl;
1903 }
1904
1905 bool Client::have_open_session(mds_rank_t mds)
1906 {
1907   return
1908     mds_sessions.count(mds) &&
1909     (mds_sessions[mds]->state == MetaSession::STATE_OPEN ||
1910      mds_sessions[mds]->state == MetaSession::STATE_STALE);
1911 }
1912
1913 MetaSession *Client::_get_mds_session(mds_rank_t mds, Connection *con)
1914 {
1915   if (mds_sessions.count(mds) == 0)
1916     return NULL;
1917   MetaSession *s = mds_sessions[mds];
1918   if (s->con != con)
1919     return NULL;
1920   return s;
1921 }
1922
1923 MetaSession *Client::_get_or_open_mds_session(mds_rank_t mds)
1924 {
1925   if (mds_sessions.count(mds))
1926     return mds_sessions[mds];
1927   return _open_mds_session(mds);
1928 }
1929
1930 /**
1931  * Populate a map of strings with client-identifying metadata,
1932  * such as the hostname.  Call this once at initialization.
1933  */
1934 void Client::populate_metadata(const std::string &mount_root)
1935 {
1936   // Hostname
1937   struct utsname u;
1938   int r = uname(&u);
1939   if (r >= 0) {
1940     metadata["hostname"] = u.nodename;
1941     ldout(cct, 20) << __func__ << " read hostname '" << u.nodename << "'" << dendl;
1942   } else {
1943     ldout(cct, 1) << __func__ << " failed to read hostname (" << cpp_strerror(r) << ")" << dendl;
1944   }
1945
1946   metadata["pid"] = stringify(getpid());
1947
1948   // Ceph entity id (the '0' in "client.0")
1949   metadata["entity_id"] = cct->_conf->name.get_id();
1950
1951   // Our mount position
1952   if (!mount_root.empty()) {
1953     metadata["root"] = mount_root;
1954   }
1955
1956   // Ceph version
1957   metadata["ceph_version"] = pretty_version_to_str();
1958   metadata["ceph_sha1"] = git_version_to_str();
1959
1960   // Apply any metadata from the user's configured overrides
1961   std::vector<std::string> tokens;
1962   get_str_vec(cct->_conf->client_metadata, ",", tokens);
1963   for (const auto &i : tokens) {
1964     auto eqpos = i.find("=");
1965     // Throw out anything that isn't of the form "<str>=<str>"
1966     if (eqpos == 0 || eqpos == std::string::npos || eqpos == i.size()) {
1967       lderr(cct) << "Invalid metadata keyval pair: '" << i << "'" << dendl;
1968       continue;
1969     }
1970     metadata[i.substr(0, eqpos)] = i.substr(eqpos + 1);
1971   }
1972 }
1973
1974 /**
1975  * Optionally add or override client metadata fields.
1976  */
1977 void Client::update_metadata(std::string const &k, std::string const &v)
1978 {
1979   Mutex::Locker l(client_lock);
1980   assert(initialized);
1981
1982   if (metadata.count(k)) {
1983     ldout(cct, 1) << __func__ << " warning, overriding metadata field '" << k
1984       << "' from '" << metadata[k] << "' to '" << v << "'" << dendl;
1985   }
1986
1987   metadata[k] = v;
1988 }
1989
1990 MetaSession *Client::_open_mds_session(mds_rank_t mds)
1991 {
1992   ldout(cct, 10) << "_open_mds_session mds." << mds << dendl;
1993   assert(mds_sessions.count(mds) == 0);
1994   MetaSession *session = new MetaSession;
1995   session->mds_num = mds;
1996   session->seq = 0;
1997   session->inst = mdsmap->get_inst(mds);
1998   session->con = messenger->get_connection(session->inst);
1999   session->state = MetaSession::STATE_OPENING;
2000   session->mds_state = MDSMap::STATE_NULL;
2001   mds_sessions[mds] = session;
2002
2003   // Maybe skip sending a request to open if this MDS daemon
2004   // has previously sent us a REJECT.
2005   if (rejected_by_mds.count(mds)) {
2006     if (rejected_by_mds[mds] == session->inst) {
2007       ldout(cct, 4) << "_open_mds_session mds." << mds << " skipping "
2008                        "because we were rejected" << dendl;
2009       return session;
2010     } else {
2011       ldout(cct, 4) << "_open_mds_session mds." << mds << " old inst "
2012                        "rejected us, trying with new inst" << dendl;
2013       rejected_by_mds.erase(mds);
2014     }
2015   }
2016
2017   MClientSession *m = new MClientSession(CEPH_SESSION_REQUEST_OPEN);
2018   m->client_meta = metadata;
2019   session->con->send_message(m);
2020   return session;
2021 }
2022
2023 void Client::_close_mds_session(MetaSession *s)
2024 {
2025   ldout(cct, 2) << "_close_mds_session mds." << s->mds_num << " seq " << s->seq << dendl;
2026   s->state = MetaSession::STATE_CLOSING;
2027   s->con->send_message(new MClientSession(CEPH_SESSION_REQUEST_CLOSE, s->seq));
2028 }
2029
2030 void Client::_closed_mds_session(MetaSession *s)
2031 {
2032   s->state = MetaSession::STATE_CLOSED;
2033   s->con->mark_down();
2034   signal_context_list(s->waiting_for_open);
2035   mount_cond.Signal();
2036   remove_session_caps(s);
2037   kick_requests_closed(s);
2038   mds_sessions.erase(s->mds_num);
2039   delete s;
2040 }
2041
2042 void Client::handle_client_session(MClientSession *m) 
2043 {
2044   mds_rank_t from = mds_rank_t(m->get_source().num());
2045   ldout(cct, 10) << "handle_client_session " << *m << " from mds." << from << dendl;
2046
2047   MetaSession *session = _get_mds_session(from, m->get_connection().get());
2048   if (!session) {
2049     ldout(cct, 10) << " discarding session message from sessionless mds " << m->get_source_inst() << dendl;
2050     m->put();
2051     return;
2052   }
2053
2054   switch (m->get_op()) {
2055   case CEPH_SESSION_OPEN:
2056     renew_caps(session);
2057     session->state = MetaSession::STATE_OPEN;
2058     if (unmounting)
2059       mount_cond.Signal();
2060     else
2061       connect_mds_targets(from);
2062     signal_context_list(session->waiting_for_open);
2063     break;
2064
2065   case CEPH_SESSION_CLOSE:
2066     _closed_mds_session(session);
2067     break;
2068
2069   case CEPH_SESSION_RENEWCAPS:
2070     if (session->cap_renew_seq == m->get_seq()) {
2071       session->cap_ttl =
2072         session->last_cap_renew_request + mdsmap->get_session_timeout();
2073       wake_inode_waiters(session);
2074     }
2075     break;
2076
2077   case CEPH_SESSION_STALE:
2078     renew_caps(session);
2079     break;
2080
2081   case CEPH_SESSION_RECALL_STATE:
2082     trim_caps(session, m->get_max_caps());
2083     break;
2084
2085   case CEPH_SESSION_FLUSHMSG:
2086     session->con->send_message(new MClientSession(CEPH_SESSION_FLUSHMSG_ACK, m->get_seq()));
2087     break;
2088
2089   case CEPH_SESSION_FORCE_RO:
2090     force_session_readonly(session);
2091     break;
2092
2093   case CEPH_SESSION_REJECT:
2094     rejected_by_mds[session->mds_num] = session->inst;
2095     _closed_mds_session(session);
2096
2097     break;
2098
2099   default:
2100     ceph_abort();
2101   }
2102
2103   m->put();
2104 }
2105
2106 bool Client::_any_stale_sessions() const
2107 {
2108   assert(client_lock.is_locked_by_me());
2109
2110   for (const auto &i : mds_sessions) {
2111     if (i.second->state == MetaSession::STATE_STALE) {
2112       return true;
2113     }
2114   }
2115
2116   return false;
2117 }
2118
2119 void Client::_kick_stale_sessions()
2120 {
2121   ldout(cct, 1) << "kick_stale_sessions" << dendl;
2122
2123   for (map<mds_rank_t,MetaSession*>::iterator p = mds_sessions.begin();
2124        p != mds_sessions.end(); ) {
2125     MetaSession *s = p->second;
2126     ++p;
2127     if (s->state == MetaSession::STATE_STALE)
2128       _closed_mds_session(s);
2129   }
2130 }
2131
2132 void Client::send_request(MetaRequest *request, MetaSession *session,
2133                           bool drop_cap_releases)
2134 {
2135   // make the request
2136   mds_rank_t mds = session->mds_num;
2137   ldout(cct, 10) << "send_request rebuilding request " << request->get_tid()
2138                  << " for mds." << mds << dendl;
2139   MClientRequest *r = build_client_request(request);
2140   if (request->dentry()) {
2141     r->set_dentry_wanted();
2142   }
2143   if (request->got_unsafe) {
2144     r->set_replayed_op();
2145     if (request->target)
2146       r->head.ino = request->target->ino;
2147   } else {
2148     encode_cap_releases(request, mds);
2149     if (drop_cap_releases) // we haven't send cap reconnect yet, drop cap releases
2150       request->cap_releases.clear();
2151     else
2152       r->releases.swap(request->cap_releases);
2153   }
2154   r->set_mdsmap_epoch(mdsmap->get_epoch());
2155   if (r->head.op == CEPH_MDS_OP_SETXATTR) {
2156     objecter->with_osdmap([r](const OSDMap& o) {
2157         r->set_osdmap_epoch(o.get_epoch());
2158       });
2159   }
2160
2161   if (request->mds == -1) {
2162     request->sent_stamp = ceph_clock_now();
2163     ldout(cct, 20) << "send_request set sent_stamp to " << request->sent_stamp << dendl;
2164   }
2165   request->mds = mds;
2166
2167   Inode *in = request->inode();
2168   if (in && in->caps.count(mds))
2169     request->sent_on_mseq = in->caps[mds]->mseq;
2170
2171   session->requests.push_back(&request->item);
2172
2173   ldout(cct, 10) << "send_request " << *r << " to mds." << mds << dendl;
2174   session->con->send_message(r);
2175 }
2176
2177 MClientRequest* Client::build_client_request(MetaRequest *request)
2178 {
2179   MClientRequest *req = new MClientRequest(request->get_op());
2180   req->set_tid(request->tid);
2181   req->set_stamp(request->op_stamp);
2182   memcpy(&req->head, &request->head, sizeof(ceph_mds_request_head));
2183
2184   // if the filepath's haven't been set, set them!
2185   if (request->path.empty()) {
2186     Inode *in = request->inode();
2187     Dentry *de = request->dentry();
2188     if (in)
2189       in->make_nosnap_relative_path(request->path);
2190     else if (de) {
2191       if (de->inode)
2192         de->inode->make_nosnap_relative_path(request->path);
2193       else if (de->dir) {
2194         de->dir->parent_inode->make_nosnap_relative_path(request->path);
2195         request->path.push_dentry(de->name);
2196       }
2197       else ldout(cct, 1) << "Warning -- unable to construct a filepath!"
2198                    << " No path, inode, or appropriately-endowed dentry given!"
2199                    << dendl;
2200     } else ldout(cct, 1) << "Warning -- unable to construct a filepath!"
2201                    << " No path, inode, or dentry given!"
2202                    << dendl;
2203   }
2204   req->set_filepath(request->get_filepath());
2205   req->set_filepath2(request->get_filepath2());
2206   req->set_data(request->data);
2207   req->set_retry_attempt(request->retry_attempt++);
2208   req->head.num_fwd = request->num_fwd;
2209   const gid_t *_gids;
2210   int gid_count = request->perms.get_gids(&_gids);
2211   req->set_gid_list(gid_count, _gids);
2212   return req;
2213 }
2214
2215
2216
2217 void Client::handle_client_request_forward(MClientRequestForward *fwd)
2218 {
2219   mds_rank_t mds = mds_rank_t(fwd->get_source().num());
2220   MetaSession *session = _get_mds_session(mds, fwd->get_connection().get());
2221   if (!session) {
2222     fwd->put();
2223     return;
2224   }
2225   ceph_tid_t tid = fwd->get_tid();
2226
2227   if (mds_requests.count(tid) == 0) {
2228     ldout(cct, 10) << "handle_client_request_forward no pending request on tid " << tid << dendl;
2229     fwd->put();
2230     return;
2231   }
2232
2233   MetaRequest *request = mds_requests[tid];
2234   assert(request);
2235
2236   // reset retry counter
2237   request->retry_attempt = 0;
2238
2239   // request not forwarded, or dest mds has no session.
2240   // resend.
2241   ldout(cct, 10) << "handle_client_request tid " << tid
2242            << " fwd " << fwd->get_num_fwd() 
2243            << " to mds." << fwd->get_dest_mds() 
2244            << ", resending to " << fwd->get_dest_mds()
2245            << dendl;
2246   
2247   request->mds = -1;
2248   request->item.remove_myself();
2249   request->num_fwd = fwd->get_num_fwd();
2250   request->resend_mds = fwd->get_dest_mds();
2251   request->caller_cond->Signal();
2252
2253   fwd->put();
2254 }
2255
2256 bool Client::is_dir_operation(MetaRequest *req)
2257 {
2258   int op = req->get_op();
2259   if (op == CEPH_MDS_OP_MKNOD || op == CEPH_MDS_OP_LINK ||
2260       op == CEPH_MDS_OP_UNLINK || op == CEPH_MDS_OP_RENAME ||
2261       op == CEPH_MDS_OP_MKDIR || op == CEPH_MDS_OP_RMDIR ||
2262       op == CEPH_MDS_OP_SYMLINK || op == CEPH_MDS_OP_CREATE)
2263     return true;
2264   return false;
2265 }
2266
2267 void Client::handle_client_reply(MClientReply *reply)
2268 {
2269   mds_rank_t mds_num = mds_rank_t(reply->get_source().num());
2270   MetaSession *session = _get_mds_session(mds_num, reply->get_connection().get());
2271   if (!session) {
2272     reply->put();
2273     return;
2274   }
2275
2276   ceph_tid_t tid = reply->get_tid();
2277   bool is_safe = reply->is_safe();
2278
2279   if (mds_requests.count(tid) == 0) {
2280     lderr(cct) << "handle_client_reply no pending request on tid " << tid
2281                << " safe is:" << is_safe << dendl;
2282     reply->put();
2283     return;
2284   }
2285   MetaRequest *request = mds_requests.at(tid);
2286
2287   ldout(cct, 20) << "handle_client_reply got a reply. Safe:" << is_safe
2288                  << " tid " << tid << dendl;
2289
2290   if (request->got_unsafe && !is_safe) {
2291     //duplicate response
2292     ldout(cct, 0) << "got a duplicate reply on tid " << tid << " from mds "
2293             << mds_num << " safe:" << is_safe << dendl;
2294     reply->put();
2295     return;
2296   }
2297
2298   if (-ESTALE == reply->get_result()) { // see if we can get to proper MDS
2299     ldout(cct, 20) << "got ESTALE on tid " << request->tid
2300                    << " from mds." << request->mds << dendl;
2301     request->send_to_auth = true;
2302     request->resend_mds = choose_target_mds(request);
2303     Inode *in = request->inode();
2304     if (request->resend_mds >= 0 &&
2305         request->resend_mds == request->mds &&
2306         (in == NULL ||
2307          in->caps.count(request->resend_mds) == 0 ||
2308          request->sent_on_mseq == in->caps[request->resend_mds]->mseq)) {
2309       // have to return ESTALE
2310     } else {
2311       request->caller_cond->Signal();
2312       reply->put();
2313       return;
2314     }
2315     ldout(cct, 20) << "have to return ESTALE" << dendl;
2316   }
2317   
2318   assert(request->reply == NULL);
2319   request->reply = reply;
2320   insert_trace(request, session);
2321
2322   // Handle unsafe reply
2323   if (!is_safe) {
2324     request->got_unsafe = true;
2325     session->unsafe_requests.push_back(&request->unsafe_item);
2326     if (is_dir_operation(request)) {
2327       Inode *dir = request->inode();
2328       assert(dir);
2329       dir->unsafe_ops.push_back(&request->unsafe_dir_item);
2330     }
2331     if (request->target) {
2332       InodeRef &in = request->target;
2333       in->unsafe_ops.push_back(&request->unsafe_target_item);
2334     }
2335   }
2336
2337   // Only signal the caller once (on the first reply):
2338   // Either its an unsafe reply, or its a safe reply and no unsafe reply was sent.
2339   if (!is_safe || !request->got_unsafe) {
2340     Cond cond;
2341     request->dispatch_cond = &cond;
2342
2343     // wake up waiter
2344     ldout(cct, 20) << "handle_client_reply signalling caller " << (void*)request->caller_cond << dendl;
2345     request->caller_cond->Signal();
2346
2347     // wake for kick back
2348     while (request->dispatch_cond) {
2349       ldout(cct, 20) << "handle_client_reply awaiting kickback on tid " << tid << " " << &cond << dendl;
2350       cond.Wait(client_lock);
2351     }
2352   }
2353
2354   if (is_safe) {
2355     // the filesystem change is committed to disk
2356     // we're done, clean up
2357     if (request->got_unsafe) {
2358       request->unsafe_item.remove_myself();
2359       request->unsafe_dir_item.remove_myself();
2360       request->unsafe_target_item.remove_myself();
2361       signal_cond_list(request->waitfor_safe);
2362     }
2363     request->item.remove_myself();
2364     unregister_request(request);
2365   }
2366   if (unmounting)
2367     mount_cond.Signal();
2368 }
2369
2370 void Client::_handle_full_flag(int64_t pool)
2371 {
2372   ldout(cct, 1) << __func__ << ": FULL: cancelling outstanding operations "
2373     << "on " << pool << dendl;
2374   // Cancel all outstanding ops in this pool with -ENOSPC: it is necessary
2375   // to do this rather than blocking, because otherwise when we fill up we
2376   // potentially lock caps forever on files with dirty pages, and we need
2377   // to be able to release those caps to the MDS so that it can delete files
2378   // and free up space.
2379   epoch_t cancelled_epoch = objecter->op_cancel_writes(-ENOSPC, pool);
2380
2381   // For all inodes with layouts in this pool and a pending flush write op
2382   // (i.e. one of the ones we will cancel), we've got to purge_set their data
2383   // from ObjectCacher so that it doesn't re-issue the write in response to
2384   // the ENOSPC error.
2385   // Fortunately since we're cancelling everything in a given pool, we don't
2386   // need to know which ops belong to which ObjectSet, we can just blow all
2387   // the un-flushed cached data away and mark any dirty inodes' async_err
2388   // field with -ENOSPC as long as we're sure all the ops we cancelled were
2389   // affecting this pool, and all the objectsets we're purging were also
2390   // in this pool.
2391   for (unordered_map<vinodeno_t,Inode*>::iterator i = inode_map.begin();
2392        i != inode_map.end(); ++i)
2393   {
2394     Inode *inode = i->second;
2395     if (inode->oset.dirty_or_tx
2396         && (pool == -1 || inode->layout.pool_id == pool)) {
2397       ldout(cct, 4) << __func__ << ": FULL: inode 0x" << std::hex << i->first << std::dec
2398         << " has dirty objects, purging and setting ENOSPC" << dendl;
2399       objectcacher->purge_set(&inode->oset);
2400       inode->set_async_err(-ENOSPC);
2401     }
2402   }
2403
2404   if (cancelled_epoch != (epoch_t)-1) {
2405     set_cap_epoch_barrier(cancelled_epoch);
2406   }
2407 }
2408
2409 void Client::handle_osd_map(MOSDMap *m)
2410 {
2411   std::set<entity_addr_t> new_blacklists;
2412   objecter->consume_blacklist_events(&new_blacklists);
2413
2414   const auto myaddr = messenger->get_myaddr();
2415   if (!blacklisted && new_blacklists.count(myaddr)) {
2416     auto epoch = objecter->with_osdmap([](const OSDMap &o){
2417         return o.get_epoch();
2418         });
2419     lderr(cct) << "I was blacklisted at osd epoch " << epoch << dendl;
2420     blacklisted = true;
2421     for (std::map<ceph_tid_t, MetaRequest*>::iterator p = mds_requests.begin();
2422          p != mds_requests.end(); ) {
2423       auto req = p->second;
2424       ++p;
2425       req->abort(-EBLACKLISTED);
2426       if (req->caller_cond) {
2427         req->kick = true;
2428         req->caller_cond->Signal();
2429       }
2430     }
2431
2432     // Progress aborts on any requests that were on this waitlist.  Any
2433     // requests that were on a waiting_for_open session waitlist
2434     // will get kicked during close session below.
2435     signal_cond_list(waiting_for_mdsmap);
2436
2437     // Force-close all sessions: assume this is not abandoning any state
2438     // on the MDS side because the MDS will have seen the blacklist too.
2439     while(!mds_sessions.empty()) {
2440       auto i = mds_sessions.begin();
2441       auto session = i->second;
2442       _closed_mds_session(session);
2443     }
2444
2445     // Since we know all our OSD ops will fail, cancel them all preemtively,
2446     // so that on an unhealthy cluster we can umount promptly even if e.g.
2447     // some PGs were inaccessible.
2448     objecter->op_cancel_writes(-EBLACKLISTED);
2449
2450   } else if (blacklisted) {
2451     // Handle case where we were blacklisted but no longer are
2452     blacklisted = objecter->with_osdmap([myaddr](const OSDMap &o){
2453         return o.is_blacklisted(myaddr);});
2454   }
2455
2456   if (objecter->osdmap_full_flag()) {
2457     _handle_full_flag(-1);
2458   } else {
2459     // Accumulate local list of full pools so that I can drop
2460     // the objecter lock before re-entering objecter in
2461     // cancel_writes
2462     std::vector<int64_t> full_pools;
2463
2464     objecter->with_osdmap([&full_pools](const OSDMap &o) {
2465         for (const auto& kv : o.get_pools()) {
2466           if (kv.second.has_flag(pg_pool_t::FLAG_FULL)) {
2467             full_pools.push_back(kv.first);
2468           }
2469         }
2470       });
2471
2472     for (auto p : full_pools)
2473       _handle_full_flag(p);
2474
2475     // Subscribe to subsequent maps to watch for the full flag going
2476     // away.  For the global full flag objecter does this for us, but
2477     // it pays no attention to the per-pool full flag so in this branch
2478     // we do it ourselves.
2479     if (!full_pools.empty()) {
2480       objecter->maybe_request_map();
2481     }
2482   }
2483
2484   m->put();
2485 }
2486
2487
2488 // ------------------------
2489 // incoming messages
2490
2491
2492 bool Client::ms_dispatch(Message *m)
2493 {
2494   Mutex::Locker l(client_lock);
2495   if (!initialized) {
2496     ldout(cct, 10) << "inactive, discarding " << *m << dendl;
2497     m->put();
2498     return true;
2499   }
2500
2501   switch (m->get_type()) {
2502     // mounting and mds sessions
2503   case CEPH_MSG_MDS_MAP:
2504     handle_mds_map(static_cast<MMDSMap*>(m));
2505     break;
2506   case CEPH_MSG_FS_MAP:
2507     handle_fs_map(static_cast<MFSMap*>(m));
2508     break;
2509   case CEPH_MSG_FS_MAP_USER:
2510     handle_fs_map_user(static_cast<MFSMapUser*>(m));
2511     break;
2512   case CEPH_MSG_CLIENT_SESSION:
2513     handle_client_session(static_cast<MClientSession*>(m));
2514     break;
2515
2516   case CEPH_MSG_OSD_MAP:
2517     handle_osd_map(static_cast<MOSDMap*>(m));
2518     break;
2519
2520     // requests
2521   case CEPH_MSG_CLIENT_REQUEST_FORWARD:
2522     handle_client_request_forward(static_cast<MClientRequestForward*>(m));
2523     break;
2524   case CEPH_MSG_CLIENT_REPLY:
2525     handle_client_reply(static_cast<MClientReply*>(m));
2526     break;
2527
2528   case CEPH_MSG_CLIENT_SNAP:
2529     handle_snap(static_cast<MClientSnap*>(m));
2530     break;
2531   case CEPH_MSG_CLIENT_CAPS:
2532     handle_caps(static_cast<MClientCaps*>(m));
2533     break;
2534   case CEPH_MSG_CLIENT_LEASE:
2535     handle_lease(static_cast<MClientLease*>(m));
2536     break;
2537   case MSG_COMMAND_REPLY:
2538     if (m->get_source().type() == CEPH_ENTITY_TYPE_MDS) {
2539       handle_command_reply(static_cast<MCommandReply*>(m));
2540     } else {
2541       return false;
2542     }
2543     break;
2544   case CEPH_MSG_CLIENT_QUOTA:
2545     handle_quota(static_cast<MClientQuota*>(m));
2546     break;
2547
2548   default:
2549     return false;
2550   }
2551
2552   // unmounting?
2553   if (unmounting) {
2554     ldout(cct, 10) << "unmounting: trim pass, size was " << lru.lru_get_size() 
2555              << "+" << inode_map.size() << dendl;
2556     long unsigned size = lru.lru_get_size() + inode_map.size();
2557     trim_cache();
2558     if (size < lru.lru_get_size() + inode_map.size()) {
2559       ldout(cct, 10) << "unmounting: trim pass, cache shrank, poking unmount()" << dendl;
2560       mount_cond.Signal();
2561     } else {
2562       ldout(cct, 10) << "unmounting: trim pass, size still " << lru.lru_get_size() 
2563                << "+" << inode_map.size() << dendl;
2564     }
2565   }
2566
2567   return true;
2568 }
2569
2570 void Client::handle_fs_map(MFSMap *m)
2571 {
2572   fsmap.reset(new FSMap(m->get_fsmap()));
2573   m->put();
2574
2575   signal_cond_list(waiting_for_fsmap);
2576
2577   monclient->sub_got("fsmap", fsmap->get_epoch());
2578 }
2579
2580 void Client::handle_fs_map_user(MFSMapUser *m)
2581 {
2582   fsmap_user.reset(new FSMapUser);
2583   *fsmap_user = m->get_fsmap();
2584   m->put();
2585
2586   monclient->sub_got("fsmap.user", fsmap_user->get_epoch());
2587   signal_cond_list(waiting_for_fsmap);
2588 }
2589
2590 void Client::handle_mds_map(MMDSMap* m)
2591 {
2592   if (m->get_epoch() <= mdsmap->get_epoch()) {
2593     ldout(cct, 1) << "handle_mds_map epoch " << m->get_epoch()
2594                   << " is identical to or older than our "
2595                   << mdsmap->get_epoch() << dendl;
2596     m->put();
2597     return;
2598   }  
2599
2600   ldout(cct, 1) << "handle_mds_map epoch " << m->get_epoch() << dendl;
2601
2602   std::unique_ptr<MDSMap> oldmap(new MDSMap);
2603   oldmap.swap(mdsmap);
2604
2605   mdsmap->decode(m->get_encoded());
2606
2607   // Cancel any commands for missing or laggy GIDs
2608   std::list<ceph_tid_t> cancel_ops;
2609   auto &commands = command_table.get_commands();
2610   for (const auto &i : commands) {
2611     auto &op = i.second;
2612     const mds_gid_t op_mds_gid = op.mds_gid;
2613     if (mdsmap->is_dne_gid(op_mds_gid) || mdsmap->is_laggy_gid(op_mds_gid)) {
2614       ldout(cct, 1) << __func__ << ": cancelling command op " << i.first << dendl;
2615       cancel_ops.push_back(i.first);
2616       if (op.outs) {
2617         std::ostringstream ss;
2618         ss << "MDS " << op_mds_gid << " went away";
2619         *(op.outs) = ss.str();
2620       }
2621       op.con->mark_down();
2622       if (op.on_finish) {
2623         op.on_finish->complete(-ETIMEDOUT);
2624       }
2625     }
2626   }
2627
2628   for (std::list<ceph_tid_t>::iterator i = cancel_ops.begin();
2629        i != cancel_ops.end(); ++i) {
2630     command_table.erase(*i);
2631   }
2632
2633   // reset session
2634   for (map<mds_rank_t,MetaSession*>::iterator p = mds_sessions.begin();
2635        p != mds_sessions.end(); ) {
2636     mds_rank_t mds = p->first;
2637     MetaSession *session = p->second;
2638     ++p;
2639
2640     int oldstate = oldmap->get_state(mds);
2641     int newstate = mdsmap->get_state(mds);
2642     if (!mdsmap->is_up(mds)) {
2643       session->con->mark_down();
2644     } else if (mdsmap->get_inst(mds) != session->inst) {
2645       session->con->mark_down();
2646       session->inst = mdsmap->get_inst(mds);
2647       // When new MDS starts to take over, notify kernel to trim unused entries
2648       // in its dcache/icache. Hopefully, the kernel will release some unused
2649       // inodes before the new MDS enters reconnect state.
2650       trim_cache_for_reconnect(session);
2651     } else if (oldstate == newstate)
2652       continue;  // no change
2653     
2654     session->mds_state = newstate;
2655     if (newstate == MDSMap::STATE_RECONNECT) {
2656       session->con = messenger->get_connection(session->inst);
2657       send_reconnect(session);
2658     } else if (newstate >= MDSMap::STATE_ACTIVE) {
2659       if (oldstate < MDSMap::STATE_ACTIVE) {
2660         // kick new requests
2661         kick_requests(session);
2662         kick_flushing_caps(session);
2663         signal_context_list(session->waiting_for_open);
2664         kick_maxsize_requests(session);
2665         wake_inode_waiters(session);
2666       }
2667       connect_mds_targets(mds);
2668     } else if (newstate == MDSMap::STATE_NULL &&
2669                mds >= mdsmap->get_max_mds()) {
2670       _closed_mds_session(session);
2671     }
2672   }
2673
2674   // kick any waiting threads
2675   signal_cond_list(waiting_for_mdsmap);
2676
2677   m->put();
2678
2679   monclient->sub_got("mdsmap", mdsmap->get_epoch());
2680 }
2681
2682 void Client::send_reconnect(MetaSession *session)
2683 {
2684   mds_rank_t mds = session->mds_num;
2685   ldout(cct, 10) << "send_reconnect to mds." << mds << dendl;
2686
2687   // trim unused caps to reduce MDS's cache rejoin time
2688   trim_cache_for_reconnect(session);
2689
2690   session->readonly = false;
2691
2692   if (session->release) {
2693     session->release->put();
2694     session->release = NULL;
2695   }
2696
2697   // reset my cap seq number
2698   session->seq = 0;
2699   //connect to the mds' offload targets
2700   connect_mds_targets(mds);
2701   //make sure unsafe requests get saved
2702   resend_unsafe_requests(session);
2703
2704   MClientReconnect *m = new MClientReconnect;
2705
2706   // i have an open session.
2707   ceph::unordered_set<inodeno_t> did_snaprealm;
2708   for (ceph::unordered_map<vinodeno_t, Inode*>::iterator p = inode_map.begin();
2709        p != inode_map.end();
2710        ++p) {
2711     Inode *in = p->second;
2712     if (in->caps.count(mds)) {
2713       ldout(cct, 10) << " caps on " << p->first
2714                << " " << ccap_string(in->caps[mds]->issued)
2715                << " wants " << ccap_string(in->caps_wanted())
2716                << dendl;
2717       filepath path;
2718       in->make_long_path(path);
2719       ldout(cct, 10) << "    path " << path << dendl;
2720
2721       bufferlist flockbl;
2722       _encode_filelocks(in, flockbl);
2723
2724       Cap *cap = in->caps[mds];
2725       cap->seq = 0;  // reset seq.
2726       cap->issue_seq = 0;  // reset seq.
2727       cap->mseq = 0;  // reset seq.
2728       cap->issued = cap->implemented;
2729
2730       snapid_t snap_follows = 0;
2731       if (!in->cap_snaps.empty())
2732         snap_follows = in->cap_snaps.begin()->first;
2733
2734       m->add_cap(p->first.ino, 
2735                  cap->cap_id,
2736                  path.get_ino(), path.get_path(),   // ino
2737                  in->caps_wanted(), // wanted
2738                  cap->issued,     // issued
2739                  in->snaprealm->ino,
2740                  snap_follows,
2741                  flockbl);
2742
2743       if (did_snaprealm.count(in->snaprealm->ino) == 0) {
2744         ldout(cct, 10) << " snaprealm " << *in->snaprealm << dendl;
2745         m->add_snaprealm(in->snaprealm->ino, in->snaprealm->seq, in->snaprealm->parent);
2746         did_snaprealm.insert(in->snaprealm->ino);
2747       }
2748     }
2749   }
2750
2751   early_kick_flushing_caps(session);
2752
2753   session->con->send_message(m);
2754
2755   mount_cond.Signal();
2756 }
2757
2758
2759 void Client::kick_requests(MetaSession *session)
2760 {
2761   ldout(cct, 10) << "kick_requests for mds." << session->mds_num << dendl;
2762   for (map<ceph_tid_t, MetaRequest*>::iterator p = mds_requests.begin();
2763        p != mds_requests.end();
2764        ++p) {
2765     MetaRequest *req = p->second;
2766     if (req->got_unsafe)
2767       continue;
2768     if (req->aborted()) {
2769       if (req->caller_cond) {
2770         req->kick = true;
2771         req->caller_cond->Signal();
2772       }
2773       continue;
2774     }
2775     if (req->retry_attempt > 0)
2776       continue; // new requests only
2777     if (req->mds == session->mds_num) {
2778       send_request(p->second, session);
2779     }
2780   }
2781 }
2782
2783 void Client::resend_unsafe_requests(MetaSession *session)
2784 {
2785   for (xlist<MetaRequest*>::iterator iter = session->unsafe_requests.begin();
2786        !iter.end();
2787        ++iter)
2788     send_request(*iter, session);
2789
2790   // also re-send old requests when MDS enters reconnect stage. So that MDS can
2791   // process completed requests in clientreplay stage.
2792   for (map<ceph_tid_t, MetaRequest*>::iterator p = mds_requests.begin();
2793        p != mds_requests.end();
2794        ++p) {
2795     MetaRequest *req = p->second;
2796     if (req->got_unsafe)
2797       continue;
2798     if (req->aborted())
2799       continue;
2800     if (req->retry_attempt == 0)
2801       continue; // old requests only
2802     if (req->mds == session->mds_num)
2803       send_request(req, session, true);
2804   }
2805 }
2806
2807 void Client::wait_unsafe_requests()
2808 {
2809   list<MetaRequest*> last_unsafe_reqs;
2810   for (map<mds_rank_t,MetaSession*>::iterator p = mds_sessions.begin();
2811        p != mds_sessions.end();
2812        ++p) {
2813     MetaSession *s = p->second;
2814     if (!s->unsafe_requests.empty()) {
2815       MetaRequest *req = s->unsafe_requests.back();
2816       req->get();
2817       last_unsafe_reqs.push_back(req);
2818     }
2819   }
2820
2821   for (list<MetaRequest*>::iterator p = last_unsafe_reqs.begin();
2822        p != last_unsafe_reqs.end();
2823        ++p) {
2824     MetaRequest *req = *p;
2825     if (req->unsafe_item.is_on_list())
2826       wait_on_list(req->waitfor_safe);
2827     put_request(req);
2828   }
2829 }
2830
2831 void Client::kick_requests_closed(MetaSession *session)
2832 {
2833   ldout(cct, 10) << "kick_requests_closed for mds." << session->mds_num << dendl;
2834   for (map<ceph_tid_t, MetaRequest*>::iterator p = mds_requests.begin();
2835        p != mds_requests.end(); ) {
2836     MetaRequest *req = p->second;
2837     ++p;
2838     if (req->mds == session->mds_num) {
2839       if (req->caller_cond) {
2840         req->kick = true;
2841         req->caller_cond->Signal();
2842       }
2843       req->item.remove_myself();
2844       if (req->got_unsafe) {
2845         lderr(cct) << "kick_requests_closed removing unsafe request " << req->get_tid() << dendl;
2846         req->unsafe_item.remove_myself();
2847         req->unsafe_dir_item.remove_myself();
2848         req->unsafe_target_item.remove_myself();
2849         signal_cond_list(req->waitfor_safe);
2850         unregister_request(req);
2851       }
2852     }
2853   }
2854   assert(session->requests.empty());
2855   assert(session->unsafe_requests.empty());
2856 }
2857
2858
2859
2860
2861 /************
2862  * leases
2863  */
2864
2865 void Client::got_mds_push(MetaSession *s)
2866 {
2867   s->seq++;
2868   ldout(cct, 10) << " mds." << s->mds_num << " seq now " << s->seq << dendl;
2869   if (s->state == MetaSession::STATE_CLOSING) {
2870     s->con->send_message(new MClientSession(CEPH_SESSION_REQUEST_CLOSE, s->seq));
2871   }
2872 }
2873
2874 void Client::handle_lease(MClientLease *m)
2875 {
2876   ldout(cct, 10) << "handle_lease " << *m << dendl;
2877
2878   assert(m->get_action() == CEPH_MDS_LEASE_REVOKE);
2879
2880   mds_rank_t mds = mds_rank_t(m->get_source().num());
2881   MetaSession *session = _get_mds_session(mds, m->get_connection().get());
2882   if (!session) {
2883     m->put();
2884     return;
2885   }
2886
2887   got_mds_push(session);
2888
2889   ceph_seq_t seq = m->get_seq();
2890
2891   Inode *in;
2892   vinodeno_t vino(m->get_ino(), CEPH_NOSNAP);
2893   if (inode_map.count(vino) == 0) {
2894     ldout(cct, 10) << " don't have vino " << vino << dendl;
2895     goto revoke;
2896   }
2897   in = inode_map[vino];
2898
2899   if (m->get_mask() & CEPH_LOCK_DN) {
2900     if (!in->dir || in->dir->dentries.count(m->dname) == 0) {
2901       ldout(cct, 10) << " don't have dir|dentry " << m->get_ino() << "/" << m->dname <<dendl;
2902       goto revoke;
2903     }
2904     Dentry *dn = in->dir->dentries[m->dname];
2905     ldout(cct, 10) << " revoked DN lease on " << dn << dendl;
2906     dn->lease_mds = -1;
2907   }
2908
2909  revoke:
2910   m->get_connection()->send_message(
2911     new MClientLease(
2912       CEPH_MDS_LEASE_RELEASE, seq,
2913       m->get_mask(), m->get_ino(), m->get_first(), m->get_last(), m->dname));
2914   m->put();
2915 }
2916
2917 void Client::put_inode(Inode *in, int n)
2918 {
2919   ldout(cct, 10) << "put_inode on " << *in << dendl;
2920   int left = in->_put(n);
2921   if (left == 0) {
2922     // release any caps
2923     remove_all_caps(in);
2924
2925     ldout(cct, 10) << "put_inode deleting " << *in << dendl;
2926     bool unclean = objectcacher->release_set(&in->oset);
2927     assert(!unclean);
2928     inode_map.erase(in->vino());
2929     if (use_faked_inos())
2930       _release_faked_ino(in);
2931
2932     if (in == root) {
2933       root = 0;
2934       root_ancestor = 0;
2935       while (!root_parents.empty())
2936         root_parents.erase(root_parents.begin());
2937     }
2938
2939     delete in;
2940   }
2941 }
2942
2943 void Client::close_dir(Dir *dir)
2944 {
2945   Inode *in = dir->parent_inode;
2946   ldout(cct, 15) << "close_dir dir " << dir << " on " << in << dendl;
2947   assert(dir->is_empty());
2948   assert(in->dir == dir);
2949   assert(in->dn_set.size() < 2);     // dirs can't be hard-linked
2950   if (!in->dn_set.empty())
2951     in->get_first_parent()->put();   // unpin dentry
2952   
2953   delete in->dir;
2954   in->dir = 0;
2955   put_inode(in);               // unpin inode
2956 }
2957
2958   /**
2959    * Don't call this with in==NULL, use get_or_create for that
2960    * leave dn set to default NULL unless you're trying to add
2961    * a new inode to a pre-created Dentry
2962    */
2963 Dentry* Client::link(Dir *dir, const string& name, Inode *in, Dentry *dn)
2964 {
2965   if (!dn) {
2966     // create a new Dentry
2967     dn = new Dentry;
2968     dn->name = name;
2969     
2970     // link to dir
2971     dn->dir = dir;
2972     dir->dentries[dn->name] = dn;
2973     lru.lru_insert_mid(dn);    // mid or top?
2974
2975     ldout(cct, 15) << "link dir " << dir->parent_inode << " '" << name << "' to inode " << in
2976                    << " dn " << dn << " (new dn)" << dendl;
2977   } else {
2978     ldout(cct, 15) << "link dir " << dir->parent_inode << " '" << name << "' to inode " << in
2979                    << " dn " << dn << " (old dn)" << dendl;
2980   }
2981
2982   if (in) {    // link to inode
2983     dn->inode = in;
2984     if (in->is_dir()) {
2985       if (in->dir)
2986         dn->get(); // dir -> dn pin
2987       if (in->ll_ref)
2988         dn->get(); // ll_ref -> dn pin
2989     }
2990
2991     assert(in->dn_set.count(dn) == 0);
2992
2993     // only one parent for directories!
2994     if (in->is_dir() && !in->dn_set.empty()) {
2995       Dentry *olddn = in->get_first_parent();
2996       assert(olddn->dir != dir || olddn->name != name);
2997       Inode *old_diri = olddn->dir->parent_inode;
2998       old_diri->dir_release_count++;
2999       clear_dir_complete_and_ordered(old_diri, true);
3000       unlink(olddn, true, true);  // keep dir, dentry
3001     }
3002
3003     in->dn_set.insert(dn);
3004
3005     ldout(cct, 20) << "link  inode " << in << " parents now " << in->dn_set << dendl; 
3006   }
3007   
3008   return dn;
3009 }
3010
3011 void Client::unlink(Dentry *dn, bool keepdir, bool keepdentry)
3012 {
3013   InodeRef in;
3014   in.swap(dn->inode);
3015   ldout(cct, 15) << "unlink dir " << dn->dir->parent_inode << " '" << dn->name << "' dn " << dn
3016                  << " inode " << dn->inode << dendl;
3017
3018   // unlink from inode
3019   if (in) {
3020     if (in->is_dir()) {
3021       if (in->dir)
3022         dn->put(); // dir -> dn pin
3023       if (in->ll_ref)
3024         dn->put(); // ll_ref -> dn pin
3025     }
3026     dn->inode = 0;
3027     assert(in->dn_set.count(dn));
3028     in->dn_set.erase(dn);
3029     ldout(cct, 20) << "unlink  inode " << in << " parents now " << in->dn_set << dendl; 
3030   }
3031
3032   if (keepdentry) {
3033     dn->lease_mds = -1;
3034   } else {
3035     ldout(cct, 15) << "unlink  removing '" << dn->name << "' dn " << dn << dendl;
3036
3037     // unlink from dir
3038     dn->dir->dentries.erase(dn->name);
3039     if (dn->dir->is_empty() && !keepdir)
3040       close_dir(dn->dir);
3041     dn->dir = 0;
3042
3043     // delete den
3044     lru.lru_remove(dn);
3045     dn->put();
3046   }
3047 }
3048
3049 /**
3050  * For asynchronous flushes, check for errors from the IO and
3051  * update the inode if necessary
3052  */
3053 class C_Client_FlushComplete : public Context {
3054 private:
3055   Client *client;
3056   InodeRef inode;
3057 public:
3058   C_Client_FlushComplete(Client *c, Inode *in) : client(c), inode(in) { }
3059   void finish(int r) override {
3060     assert(client->client_lock.is_locked_by_me());
3061     if (r != 0) {
3062       client_t const whoami = client->whoami;  // For the benefit of ldout prefix
3063       ldout(client->cct, 1) << "I/O error from flush on inode " << inode
3064         << " 0x" << std::hex << inode->ino << std::dec
3065         << ": " << r << "(" << cpp_strerror(r) << ")" << dendl;
3066       inode->set_async_err(r);
3067     }
3068   }
3069 };
3070
3071
3072 /****
3073  * caps
3074  */
3075
3076 void Client::get_cap_ref(Inode *in, int cap)
3077 {
3078   if ((cap & CEPH_CAP_FILE_BUFFER) &&
3079       in->cap_refs[CEPH_CAP_FILE_BUFFER] == 0) {
3080     ldout(cct, 5) << "get_cap_ref got first FILE_BUFFER ref on " << *in << dendl;
3081     in->get();
3082   }
3083   if ((cap & CEPH_CAP_FILE_CACHE) &&
3084       in->cap_refs[CEPH_CAP_FILE_CACHE] == 0) {
3085     ldout(cct, 5) << "get_cap_ref got first FILE_CACHE ref on " << *in << dendl;
3086     in->get();
3087   }
3088   in->get_cap_ref(cap);
3089 }
3090
3091 void Client::put_cap_ref(Inode *in, int cap)
3092 {
3093   int last = in->put_cap_ref(cap);
3094   if (last) {
3095     int put_nref = 0;
3096     int drop = last & ~in->caps_issued();
3097     if (in->snapid == CEPH_NOSNAP) {
3098       if ((last & CEPH_CAP_FILE_WR) &&
3099           !in->cap_snaps.empty() &&
3100           in->cap_snaps.rbegin()->second.writing) {
3101         ldout(cct, 10) << "put_cap_ref finishing pending cap_snap on " << *in << dendl;
3102         in->cap_snaps.rbegin()->second.writing = 0;
3103         finish_cap_snap(in, in->cap_snaps.rbegin()->second, get_caps_used(in));
3104         signal_cond_list(in->waitfor_caps);  // wake up blocked sync writers
3105       }
3106       if (last & CEPH_CAP_FILE_BUFFER) {
3107         for (auto &p : in->cap_snaps)
3108           p.second.dirty_data = 0;
3109         signal_cond_list(in->waitfor_commit);
3110         ldout(cct, 5) << "put_cap_ref dropped last FILE_BUFFER ref on " << *in << dendl;
3111         ++put_nref;
3112       }
3113     }
3114     if (last & CEPH_CAP_FILE_CACHE) {
3115       ldout(cct, 5) << "put_cap_ref dropped last FILE_CACHE ref on " << *in << dendl;
3116       ++put_nref;
3117     }
3118     if (drop)
3119       check_caps(in, 0);
3120     if (put_nref)
3121       put_inode(in, put_nref);
3122   }
3123 }
3124
3125 int Client::get_caps(Inode *in, int need, int want, int *phave, loff_t endoff)
3126 {
3127   int r = check_pool_perm(in, need);
3128   if (r < 0)
3129     return r;
3130
3131   while (1) {
3132     int file_wanted = in->caps_file_wanted();
3133     if ((file_wanted & need) != need) {
3134       ldout(cct, 10) << "get_caps " << *in << " need " << ccap_string(need)
3135                      << " file_wanted " << ccap_string(file_wanted) << ", EBADF "
3136                      << dendl;
3137       return -EBADF;
3138     }
3139
3140     int implemented;
3141     int have = in->caps_issued(&implemented);
3142
3143     bool waitfor_caps = false;
3144     bool waitfor_commit = false;
3145
3146     if (have & need & CEPH_CAP_FILE_WR) {
3147       if (endoff > 0 &&
3148           (endoff >= (loff_t)in->max_size ||
3149            endoff > (loff_t)(in->size << 1)) &&
3150           endoff > (loff_t)in->wanted_max_size) {
3151         ldout(cct, 10) << "wanted_max_size " << in->wanted_max_size << " -> " << endoff << dendl;
3152         in->wanted_max_size = endoff;
3153         check_caps(in, 0);
3154       }
3155
3156       if (endoff >= 0 && endoff > (loff_t)in->max_size) {
3157         ldout(cct, 10) << "waiting on max_size, endoff " << endoff << " max_size " << in->max_size << " on " << *in << dendl;
3158         waitfor_caps = true;
3159       }
3160       if (!in->cap_snaps.empty()) {
3161         if (in->cap_snaps.rbegin()->second.writing) {
3162           ldout(cct, 10) << "waiting on cap_snap write to complete" << dendl;
3163           waitfor_caps = true;
3164         }
3165         for (auto &p : in->cap_snaps) {
3166           if (p.second.dirty_data) {
3167             waitfor_commit = true;
3168             break;
3169           }
3170         }
3171         if (waitfor_commit) {
3172           _flush(in, new C_Client_FlushComplete(this, in));
3173           ldout(cct, 10) << "waiting for WRBUFFER to get dropped" << dendl;
3174         }
3175       }
3176     }
3177
3178     if (!waitfor_caps && !waitfor_commit) {
3179       if ((have & need) == need) {
3180         int revoking = implemented & ~have;
3181         ldout(cct, 10) << "get_caps " << *in << " have " << ccap_string(have)
3182                  << " need " << ccap_string(need) << " want " << ccap_string(want)
3183                  << " revoking " << ccap_string(revoking)
3184                  << dendl;
3185         if ((revoking & want) == 0) {
3186           *phave = need | (have & want);
3187           in->get_cap_ref(need);
3188           return 0;
3189         }
3190       }
3191       ldout(cct, 10) << "waiting for caps " << *in << " need " << ccap_string(need) << " want " << ccap_string(want) << dendl;
3192       waitfor_caps = true;
3193     }
3194
3195     if ((need & CEPH_CAP_FILE_WR) && in->auth_cap &&
3196         in->auth_cap->session->readonly)
3197       return -EROFS;
3198
3199     if (in->flags & I_CAP_DROPPED) {
3200       int mds_wanted = in->caps_mds_wanted();
3201       if ((mds_wanted & need) != need) {
3202         int ret = _renew_caps(in);
3203         if (ret < 0)
3204           return ret;
3205         continue;
3206       }
3207       if ((mds_wanted & file_wanted) ==
3208           (file_wanted & (CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR))) {
3209         in->flags &= ~I_CAP_DROPPED;
3210       }
3211     }
3212
3213     if (waitfor_caps)
3214       wait_on_list(in->waitfor_caps);
3215     else if (waitfor_commit)
3216       wait_on_list(in->waitfor_commit);
3217   }
3218 }
3219
3220 int Client::get_caps_used(Inode *in)
3221 {
3222   unsigned used = in->caps_used();
3223   if (!(used & CEPH_CAP_FILE_CACHE) &&
3224       !objectcacher->set_is_empty(&in->oset))
3225     used |= CEPH_CAP_FILE_CACHE;
3226   return used;
3227 }
3228
3229 void Client::cap_delay_requeue(Inode *in)
3230 {
3231   ldout(cct, 10) << "cap_delay_requeue on " << *in << dendl;
3232   in->hold_caps_until = ceph_clock_now();
3233   in->hold_caps_until += cct->_conf->client_caps_release_delay;
3234   delayed_caps.push_back(&in->cap_item);
3235 }
3236
3237 void Client::send_cap(Inode *in, MetaSession *session, Cap *cap,
3238                       bool sync, int used, int want, int retain,
3239                       int flush, ceph_tid_t flush_tid)
3240 {
3241   int held = cap->issued | cap->implemented;
3242   int revoking = cap->implemented & ~cap->issued;
3243   retain &= ~revoking;
3244   int dropping = cap->issued & ~retain;
3245   int op = CEPH_CAP_OP_UPDATE;
3246
3247   ldout(cct, 10) << "send_cap " << *in
3248            << " mds." << session->mds_num << " seq " << cap->seq
3249            << (sync ? " sync " : " async ")
3250            << " used " << ccap_string(used)
3251            << " want " << ccap_string(want)
3252            << " flush " << ccap_string(flush)
3253            << " retain " << ccap_string(retain)
3254            << " held "<< ccap_string(held)
3255            << " revoking " << ccap_string(revoking)
3256            << " dropping " << ccap_string(dropping)
3257            << dendl;
3258
3259   if (cct->_conf->client_inject_release_failure && revoking) {
3260     const int would_have_issued = cap->issued & retain;
3261     const int would_have_implemented = cap->implemented & (cap->issued | used);
3262     // Simulated bug:
3263     //  - tell the server we think issued is whatever they issued plus whatever we implemented
3264     //  - leave what we have implemented in place
3265     ldout(cct, 20) << __func__ << " injecting failure to release caps" << dendl;
3266     cap->issued = cap->issued | cap->implemented;
3267
3268     // Make an exception for revoking xattr caps: we are injecting
3269     // failure to release other caps, but allow xattr because client
3270     // will block on xattr ops if it can't release these to MDS (#9800)
3271     const int xattr_mask = CEPH_CAP_XATTR_SHARED | CEPH_CAP_XATTR_EXCL;
3272     cap->issued ^= xattr_mask & revoking;
3273     cap->implemented ^= xattr_mask & revoking;
3274
3275     ldout(cct, 20) << __func__ << " issued " << ccap_string(cap->issued) << " vs " << ccap_string(would_have_issued) << dendl;
3276     ldout(cct, 20) << __func__ << " implemented " << ccap_string(cap->implemented) << " vs " << ccap_string(would_have_implemented) << dendl;
3277   } else {
3278     // Normal behaviour
3279     cap->issued &= retain;
3280     cap->implemented &= cap->issued | used;
3281   }
3282
3283   snapid_t follows = 0;
3284
3285   if (flush)
3286     follows = in->snaprealm->get_snap_context().seq;
3287   
3288   MClientCaps *m = new MClientCaps(op,
3289                                    in->ino,
3290                                    0,
3291                                    cap->cap_id, cap->seq,
3292                                    cap->implemented,
3293                                    want,
3294                                    flush,
3295                                    cap->mseq,
3296                                    cap_epoch_barrier);
3297   m->caller_uid = in->cap_dirtier_uid;
3298   m->caller_gid = in->cap_dirtier_gid;
3299
3300   m->head.issue_seq = cap->issue_seq;
3301   m->set_tid(flush_tid);
3302
3303   m->head.uid = in->uid;
3304   m->head.gid = in->gid;
3305   m->head.mode = in->mode;
3306   
3307   m->head.nlink = in->nlink;
3308   
3309   if (flush & CEPH_CAP_XATTR_EXCL) {
3310     ::encode(in->xattrs, m->xattrbl);
3311     m->head.xattr_version = in->xattr_version;
3312   }
3313   
3314   m->size = in->size;
3315   m->max_size = in->max_size;
3316   m->truncate_seq = in->truncate_seq;
3317   m->truncate_size = in->truncate_size;
3318   m->mtime = in->mtime;
3319   m->atime = in->atime;
3320   m->ctime = in->ctime;
3321   m->btime = in->btime;
3322   m->time_warp_seq = in->time_warp_seq;
3323   m->change_attr = in->change_attr;
3324   if (sync)
3325     m->flags |= CLIENT_CAPS_SYNC;
3326     
3327   if (flush & CEPH_CAP_FILE_WR) {
3328     m->inline_version = in->inline_version;
3329     m->inline_data = in->inline_data;
3330   }
3331
3332   in->reported_size = in->size;
3333   m->set_snap_follows(follows);
3334   cap->wanted = want;
3335   if (cap == in->auth_cap) {
3336     m->set_max_size(in->wanted_max_size);
3337     in->requested_max_size = in->wanted_max_size;
3338     ldout(cct, 15) << "auth cap, setting max_size = " << in->requested_max_size << dendl;
3339   }
3340
3341   if (!session->flushing_caps_tids.empty())
3342     m->set_oldest_flush_tid(*session->flushing_caps_tids.begin());
3343
3344   session->con->send_message(m);
3345 }
3346
3347 static bool is_max_size_approaching(Inode *in)
3348 {
3349   /* mds will adjust max size according to the reported size */
3350   if (in->flushing_caps & CEPH_CAP_FILE_WR)
3351     return false;
3352   if (in->size >= in->max_size)
3353     return true;
3354   /* half of previous max_size increment has been used */
3355   if (in->max_size > in->reported_size &&
3356       (in->size << 1) >= in->max_size + in->reported_size)
3357     return true;
3358   return false;
3359 }
3360
3361 /**
3362  * check_caps
3363  *
3364  * Examine currently used and wanted versus held caps. Release, flush or ack
3365  * revoked caps to the MDS as appropriate.
3366  *
3367  * @param in the inode to check
3368  * @param flags flags to apply to cap check
3369  */
3370 void Client::check_caps(Inode *in, unsigned flags)
3371 {
3372   unsigned wanted = in->caps_wanted();
3373   unsigned used = get_caps_used(in);
3374   unsigned cap_used;
3375
3376   if (in->is_dir() && (in->flags & I_COMPLETE)) {
3377     // we do this here because we don't want to drop to Fs (and then
3378     // drop the Fs if we do a create!) if that alone makes us send lookups
3379     // to the MDS. Doing it in in->caps_wanted() has knock-on effects elsewhere
3380     wanted |= CEPH_CAP_FILE_EXCL;
3381   }
3382
3383   int implemented;
3384   int issued = in->caps_issued(&implemented);
3385   int revoking = implemented & ~issued;
3386
3387   int retain = wanted | used | CEPH_CAP_PIN;
3388   if (!unmounting) {
3389     if (wanted)
3390       retain |= CEPH_CAP_ANY;
3391     else
3392       retain |= CEPH_CAP_ANY_SHARED;
3393   }
3394
3395   ldout(cct, 10) << "check_caps on " << *in
3396            << " wanted " << ccap_string(wanted)
3397            << " used " << ccap_string(used)
3398            << " issued " << ccap_string(issued)
3399            << " revoking " << ccap_string(revoking)
3400            << " flags=" << flags
3401            << dendl;
3402
3403   if (in->snapid != CEPH_NOSNAP)
3404     return; //snap caps last forever, can't write
3405
3406   if (in->caps.empty())
3407     return;   // guard if at end of func
3408
3409   if ((revoking & (CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO)) &&
3410       (used & CEPH_CAP_FILE_CACHE) && !(used & CEPH_CAP_FILE_BUFFER))
3411     _release(in);
3412
3413   if (!in->cap_snaps.empty())
3414     flush_snaps(in);
3415
3416   if (flags & CHECK_CAPS_NODELAY)
3417     in->hold_caps_until = utime_t();
3418   else
3419     cap_delay_requeue(in);
3420
3421   utime_t now = ceph_clock_now();
3422
3423   map<mds_rank_t, Cap*>::iterator it = in->caps.begin();
3424   while (it != in->caps.end()) {
3425     mds_rank_t mds = it->first;
3426     Cap *cap = it->second;
3427     ++it;
3428
3429     MetaSession *session = mds_sessions[mds];
3430     assert(session);
3431
3432     cap_used = used;
3433     if (in->auth_cap && cap != in->auth_cap)
3434       cap_used &= ~in->auth_cap->issued;
3435
3436     revoking = cap->implemented & ~cap->issued;
3437     
3438     ldout(cct, 10) << " cap mds." << mds
3439              << " issued " << ccap_string(cap->issued)
3440              << " implemented " << ccap_string(cap->implemented)
3441              << " revoking " << ccap_string(revoking) << dendl;
3442
3443     if (in->wanted_max_size > in->max_size &&
3444         in->wanted_max_size > in->requested_max_size &&
3445         cap == in->auth_cap)
3446       goto ack;
3447
3448     /* approaching file_max? */
3449     if ((cap->issued & CEPH_CAP_FILE_WR) &&
3450         cap == in->auth_cap &&
3451         is_max_size_approaching(in)) {
3452       ldout(cct, 10) << "size " << in->size << " approaching max_size " << in->max_size
3453                      << ", reported " << in->reported_size << dendl;
3454       goto ack;
3455     }
3456
3457     /* completed revocation? */
3458     if (revoking && (revoking & cap_used) == 0) {
3459       ldout(cct, 10) << "completed revocation of " << ccap_string(cap->implemented & ~cap->issued) << dendl;
3460       goto ack;
3461     }
3462
3463     /* want more caps from mds? */
3464     if (wanted & ~(cap->wanted | cap->issued))
3465       goto ack;
3466
3467     if (!revoking && unmounting && (cap_used == 0))
3468       goto ack;
3469
3470     if (wanted == cap->wanted &&         // mds knows what we want.
3471         ((cap->issued & ~retain) == 0) &&// and we don't have anything we wouldn't like
3472         !in->dirty_caps)                 // and we have no dirty caps
3473       continue;
3474
3475     if (now < in->hold_caps_until) {
3476       ldout(cct, 10) << "delaying cap release" << dendl;
3477       continue;
3478     }
3479
3480   ack:
3481     // re-send old cap/snapcap flushes first.
3482     if (session->mds_state >= MDSMap::STATE_RECONNECT &&
3483         session->mds_state < MDSMap::STATE_ACTIVE &&
3484         session->early_flushing_caps.count(in) == 0) {
3485       ldout(cct, 20) << " reflushing caps (check_caps) on " << *in
3486                      << " to mds." << session->mds_num << dendl;
3487       session->early_flushing_caps.insert(in);
3488       if (in->cap_snaps.size())
3489         flush_snaps(in, true);
3490       if (in->flushing_caps)
3491         flush_caps(in, session, flags & CHECK_CAPS_SYNCHRONOUS);
3492     }
3493
3494     int flushing;
3495     ceph_tid_t flush_tid;
3496     if (in->auth_cap == cap && in->dirty_caps) {
3497       flushing = mark_caps_flushing(in, &flush_tid);
3498     } else {
3499       flushing = 0;
3500       flush_tid = 0;
3501     }
3502
3503     send_cap(in, session, cap, flags & CHECK_CAPS_SYNCHRONOUS, cap_used, wanted,
3504              retain, flushing, flush_tid);
3505   }
3506 }
3507
3508
3509 void Client::queue_cap_snap(Inode *in, SnapContext& old_snapc)
3510 {
3511   int used = get_caps_used(in);
3512   int dirty = in->caps_dirty();
3513   ldout(cct, 10) << "queue_cap_snap " << *in << " snapc " << old_snapc << " used " << ccap_string(used) << dendl;
3514
3515   if (in->cap_snaps.size() &&
3516       in->cap_snaps.rbegin()->second.writing) {
3517     ldout(cct, 10) << "queue_cap_snap already have pending cap_snap on " << *in << dendl;
3518     return;
3519   } else if (in->caps_dirty() ||
3520             (used & CEPH_CAP_FILE_WR) ||
3521              (dirty & CEPH_CAP_ANY_WR)) {
3522     const auto &capsnapem = in->cap_snaps.emplace(std::piecewise_construct, std::make_tuple(old_snapc.seq), std::make_tuple(in));
3523     assert(capsnapem.second == true); /* element inserted */
3524     CapSnap &capsnap = capsnapem.first->second;
3525     capsnap.context = old_snapc;
3526     capsnap.issued = in->caps_issued();
3527     capsnap.dirty = in->caps_dirty();
3528     
3529     capsnap.dirty_data = (used & CEPH_CAP_FILE_BUFFER);
3530     
3531     capsnap.uid = in->uid;
3532     capsnap.gid = in->gid;
3533     capsnap.mode = in->mode;
3534     capsnap.btime = in->btime;
3535     capsnap.xattrs = in->xattrs;
3536     capsnap.xattr_version = in->xattr_version;
3537  
3538     if (used & CEPH_CAP_FILE_WR) {
3539       ldout(cct, 10) << "queue_cap_snap WR used on " << *in << dendl;
3540       capsnap.writing = 1;
3541     } else {
3542       finish_cap_snap(in, capsnap, used);
3543     }
3544   } else {
3545     ldout(cct, 10) << "queue_cap_snap not dirty|writing on " << *in << dendl;
3546   }
3547 }
3548
3549 void Client::finish_cap_snap(Inode *in, CapSnap &capsnap, int used)
3550 {
3551   ldout(cct, 10) << "finish_cap_snap " << *in << " capsnap " << (void *)&capsnap << " used " << ccap_string(used) << dendl;
3552   capsnap.size = in->size;
3553   capsnap.mtime = in->mtime;
3554   capsnap.atime = in->atime;
3555   capsnap.ctime = in->ctime;
3556   capsnap.time_warp_seq = in->time_warp_seq;
3557   capsnap.change_attr = in->change_attr;
3558
3559   capsnap.dirty |= in->caps_dirty();
3560
3561   if (capsnap.dirty & CEPH_CAP_FILE_WR) {
3562     capsnap.inline_data = in->inline_data;
3563     capsnap.inline_version = in->inline_version;
3564   }
3565
3566   if (used & CEPH_CAP_FILE_BUFFER) {
3567     ldout(cct, 10) << "finish_cap_snap " << *in << " cap_snap " << &capsnap << " used " << used
3568              << " WRBUFFER, delaying" << dendl;
3569   } else {
3570     capsnap.dirty_data = 0;
3571     flush_snaps(in);
3572   }
3573 }
3574
3575 void Client::_flushed_cap_snap(Inode *in, snapid_t seq)
3576 {
3577   ldout(cct, 10) << "_flushed_cap_snap seq " << seq << " on " << *in << dendl;
3578   in->cap_snaps.at(seq).dirty_data = 0;
3579   flush_snaps(in);
3580 }
3581
3582 void Client::flush_snaps(Inode *in, bool all_again)
3583 {
3584   ldout(cct, 10) << "flush_snaps on " << *in << " all_again " << all_again << dendl;
3585   assert(in->cap_snaps.size());
3586
3587   // pick auth mds
3588   assert(in->auth_cap);
3589   MetaSession *session = in->auth_cap->session;
3590   int mseq = in->auth_cap->mseq;
3591
3592   for (auto &p : in->cap_snaps) {
3593     CapSnap &capsnap = p.second;
3594     if (!all_again) {
3595       // only flush once per session
3596       if (capsnap.flush_tid > 0)
3597         continue;
3598     }
3599
3600     ldout(cct, 10) << "flush_snaps mds." << session->mds_num
3601              << " follows " << p.first
3602              << " size " << capsnap.size
3603              << " mtime " << capsnap.mtime
3604              << " dirty_data=" << capsnap.dirty_data
3605              << " writing=" << capsnap.writing
3606              << " on " << *in << dendl;
3607     if (capsnap.dirty_data || capsnap.writing)
3608       continue;
3609     
3610     if (capsnap.flush_tid == 0) {
3611       capsnap.flush_tid = ++last_flush_tid;
3612       if (!in->flushing_cap_item.is_on_list())
3613         session->flushing_caps.push_back(&in->flushing_cap_item);
3614       session->flushing_caps_tids.insert(capsnap.flush_tid);
3615     }
3616
3617     MClientCaps *m = new MClientCaps(CEPH_CAP_OP_FLUSHSNAP, in->ino, in->snaprealm->ino, 0, mseq,
3618                                      cap_epoch_barrier);
3619     if (user_id >= 0)
3620       m->caller_uid = user_id;
3621     if (group_id >= 0)
3622       m->caller_gid = group_id;
3623
3624     m->set_client_tid(capsnap.flush_tid);
3625     m->head.snap_follows = p.first;
3626
3627     m->head.caps = capsnap.issued;
3628     m->head.dirty = capsnap.dirty;
3629
3630     m->head.uid = capsnap.uid;
3631     m->head.gid = capsnap.gid;
3632     m->head.mode = capsnap.mode;
3633     m->btime = capsnap.btime;
3634
3635     m->size = capsnap.size;
3636
3637     m->head.xattr_version = capsnap.xattr_version;
3638     ::encode(capsnap.xattrs, m->xattrbl);
3639
3640     m->ctime = capsnap.ctime;
3641     m->btime = capsnap.btime;
3642     m->mtime = capsnap.mtime;
3643     m->atime = capsnap.atime;
3644     m->time_warp_seq = capsnap.time_warp_seq;
3645     m->change_attr = capsnap.change_attr;
3646
3647     if (capsnap.dirty & CEPH_CAP_FILE_WR) {
3648       m->inline_version = in->inline_version;
3649       m->inline_data = in->inline_data;
3650     }
3651
3652     assert(!session->flushing_caps_tids.empty());
3653     m->set_oldest_flush_tid(*session->flushing_caps_tids.begin());
3654
3655     session->con->send_message(m);
3656   }
3657 }
3658
3659
3660
3661 void Client::wait_on_list(list<Cond*>& ls)
3662 {
3663   Cond cond;
3664   ls.push_back(&cond);
3665   cond.Wait(client_lock);
3666   ls.remove(&cond);
3667 }
3668
3669 void Client::signal_cond_list(list<Cond*>& ls)
3670 {
3671   for (list<Cond*>::iterator it = ls.begin(); it != ls.end(); ++it)
3672     (*it)->Signal();
3673 }
3674
3675 void Client::wait_on_context_list(list<Context*>& ls)
3676 {
3677   Cond cond;
3678   bool done = false;
3679   int r;
3680   ls.push_back(new C_Cond(&cond, &done, &r));
3681   while (!done)
3682     cond.Wait(client_lock);
3683 }
3684
3685 void Client::signal_context_list(list<Context*>& ls)
3686 {
3687   while (!ls.empty()) {
3688     ls.front()->complete(0);
3689     ls.pop_front();
3690   }
3691 }
3692
3693 void Client::wake_inode_waiters(MetaSession *s)
3694 {
3695   xlist<Cap*>::iterator iter = s->caps.begin();
3696   while (!iter.end()){
3697     signal_cond_list((*iter)->inode->waitfor_caps);
3698     ++iter;
3699   }
3700 }
3701
3702
3703 // flush dirty data (from objectcache)
3704
3705 class C_Client_CacheInvalidate : public Context  {
3706 private:
3707   Client *client;
3708   vinodeno_t ino;
3709   int64_t offset, length;
3710 public:
3711   C_Client_CacheInvalidate(Client *c, Inode *in, int64_t off, int64_t len) :
3712     client(c), offset(off), length(len) {
3713     if (client->use_faked_inos())
3714       ino = vinodeno_t(in->faked_ino, CEPH_NOSNAP);
3715     else
3716       ino = in->vino();
3717   }
3718   void finish(int r) override {
3719     // _async_invalidate takes the lock when it needs to, call this back from outside of lock.
3720     assert(!client->client_lock.is_locked_by_me());
3721     client->_async_invalidate(ino, offset, length);
3722   }
3723 };
3724
3725 void Client::_async_invalidate(vinodeno_t ino, int64_t off, int64_t len)
3726 {
3727   if (unmounting)
3728     return;
3729   ldout(cct, 10) << "_async_invalidate " << ino << " " << off << "~" << len << dendl;
3730   ino_invalidate_cb(callback_handle, ino, off, len);
3731 }
3732
3733 void Client::_schedule_invalidate_callback(Inode *in, int64_t off, int64_t len) {
3734
3735   if (ino_invalidate_cb)
3736     // we queue the invalidate, which calls the callback and decrements the ref
3737     async_ino_invalidator.queue(new C_Client_CacheInvalidate(this, in, off, len));
3738 }
3739
3740 void Client::_invalidate_inode_cache(Inode *in)
3741 {
3742   ldout(cct, 10) << "_invalidate_inode_cache " << *in << dendl;
3743
3744   // invalidate our userspace inode cache
3745   if (cct->_conf->client_oc)
3746     objectcacher->release_set(&in->oset);
3747
3748   _schedule_invalidate_callback(in, 0, 0);
3749 }
3750
3751 void Client::_invalidate_inode_cache(Inode *in, int64_t off, int64_t len)
3752 {
3753   ldout(cct, 10) << "_invalidate_inode_cache " << *in << " " << off << "~" << len << dendl;
3754
3755   // invalidate our userspace inode cache
3756   if (cct->_conf->client_oc) {
3757     vector<ObjectExtent> ls;
3758     Striper::file_to_extents(cct, in->ino, &in->layout, off, len, in->truncate_size, ls);
3759     objectcacher->discard_set(&in->oset, ls);
3760   }
3761
3762   _schedule_invalidate_callback(in, off, len);
3763 }
3764
3765 bool Client::_release(Inode *in)
3766 {
3767   ldout(cct, 20) << "_release " << *in << dendl;
3768   if (in->cap_refs[CEPH_CAP_FILE_CACHE] == 0) {
3769     _invalidate_inode_cache(in);
3770     return true;
3771   }
3772   return false;
3773 }
3774
3775 bool Client::_flush(Inode *in, Context *onfinish)
3776 {
3777   ldout(cct, 10) << "_flush " << *in << dendl;
3778
3779   if (!in->oset.dirty_or_tx) {
3780     ldout(cct, 10) << " nothing to flush" << dendl;
3781     onfinish->complete(0);
3782     return true;
3783   }
3784
3785   if (objecter->osdmap_pool_full(in->layout.pool_id)) {
3786     ldout(cct, 1) << __func__ << ": FULL, purging for ENOSPC" << dendl;
3787     objectcacher->purge_set(&in->oset);
3788     if (onfinish) {
3789       onfinish->complete(-ENOSPC);
3790     }
3791     return true;
3792   }
3793
3794   return objectcacher->flush_set(&in->oset, onfinish);
3795 }
3796
3797 void Client::_flush_range(Inode *in, int64_t offset, uint64_t size)
3798 {
3799   assert(client_lock.is_locked());
3800   if (!in->oset.dirty_or_tx) {
3801     ldout(cct, 10) << " nothing to flush" << dendl;
3802     return;
3803   }
3804
3805   Mutex flock("Client::_flush_range flock");
3806   Cond cond;
3807   bool safe = false;
3808   Context *onflush = new C_SafeCond(&flock, &cond, &safe);
3809   bool ret = objectcacher->file_flush(&in->oset, &in->layout, in->snaprealm->get_snap_context(),
3810                                       offset, size, onflush);
3811   if (!ret) {
3812     // wait for flush
3813     client_lock.Unlock();
3814     flock.Lock();
3815     while (!safe)
3816       cond.Wait(flock);
3817     flock.Unlock();
3818     client_lock.Lock();
3819   }
3820 }
3821
3822 void Client::flush_set_callback(ObjectCacher::ObjectSet *oset)
3823 {
3824   //  Mutex::Locker l(client_lock);
3825   assert(client_lock.is_locked());   // will be called via dispatch() -> objecter -> ...
3826   Inode *in = static_cast<Inode *>(oset->parent);
3827   assert(in);
3828   _flushed(in);
3829 }
3830
3831 void Client::_flushed(Inode *in)
3832 {
3833   ldout(cct, 10) << "_flushed " << *in << dendl;
3834
3835   put_cap_ref(in, CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_BUFFER);
3836 }
3837
3838
3839
3840 // checks common to add_update_cap, handle_cap_grant
3841 void Client::check_cap_issue(Inode *in, Cap *cap, unsigned issued)
3842 {
3843   unsigned had = in->caps_issued();
3844
3845   if ((issued & CEPH_CAP_FILE_CACHE) &&
3846       !(had & CEPH_CAP_FILE_CACHE))
3847     in->cache_gen++;
3848
3849   if ((issued & CEPH_CAP_FILE_SHARED) &&
3850       !(had & CEPH_CAP_FILE_SHARED)) {
3851     in->shared_gen++;
3852
3853     if (in->is_dir())
3854       clear_dir_complete_and_ordered(in, true);
3855   }
3856 }
3857
3858 void Client::add_update_cap(Inode *in, MetaSession *mds_session, uint64_t cap_id,
3859                             unsigned issued, unsigned seq, unsigned mseq, inodeno_t realm,
3860                             int flags, const UserPerm& cap_perms)
3861 {
3862   Cap *cap = 0;
3863   mds_rank_t mds = mds_session->mds_num;
3864   if (in->caps.count(mds)) {
3865     cap = in->caps[mds];
3866
3867     /*
3868      * auth mds of the inode changed. we received the cap export
3869      * message, but still haven't received the cap import message.
3870      * handle_cap_export() updated the new auth MDS' cap.
3871      *
3872      * "ceph_seq_cmp(seq, cap->seq) <= 0" means we are processing
3873      * a message that was send before the cap import message. So
3874      * don't remove caps.
3875      */
3876     if (ceph_seq_cmp(seq, cap->seq) <= 0) {
3877       assert(cap == in->auth_cap);
3878       assert(cap->cap_id == cap_id);
3879       seq = cap->seq;
3880       mseq = cap->mseq;
3881       issued |= cap->issued;
3882       flags |= CEPH_CAP_FLAG_AUTH;
3883     }
3884   } else {
3885     mds_session->num_caps++;
3886     if (!in->is_any_caps()) {
3887       assert(in->snaprealm == 0);
3888       in->snaprealm = get_snap_realm(realm);
3889       in->snaprealm->inodes_with_caps.push_back(&in->snaprealm_item);
3890       ldout(cct, 15) << "add_update_cap first one, opened snaprealm " << in->snaprealm << dendl;
3891     }
3892     in->caps[mds] = cap = new Cap;
3893
3894     mds_session->caps.push_back(&cap->cap_item);
3895     cap->session = mds_session;
3896     cap->inode = in;
3897     cap->gen = mds_session->cap_gen;
3898     cap_list.push_back(&in->cap_item);
3899   }
3900
3901   check_cap_issue(in, cap, issued);
3902
3903   if (flags & CEPH_CAP_FLAG_AUTH) {
3904     if (in->auth_cap != cap &&
3905         (!in->auth_cap || ceph_seq_cmp(in->auth_cap->mseq, mseq) < 0)) {
3906       if (in->auth_cap && in->flushing_cap_item.is_on_list()) {
3907         ldout(cct, 10) << "add_update_cap changing auth cap: "
3908                        << "add myself to new auth MDS' flushing caps list" << dendl;
3909         adjust_session_flushing_caps(in, in->auth_cap->session, mds_session);
3910       }
3911       in->auth_cap = cap;
3912     }
3913   }
3914
3915   unsigned old_caps = cap->issued;
3916   cap->cap_id = cap_id;
3917   cap->issued |= issued;
3918   cap->implemented |= issued;
3919   cap->seq = seq;
3920   cap->issue_seq = seq;
3921   cap->mseq = mseq;
3922   cap->latest_perms = cap_perms;
3923   ldout(cct, 10) << "add_update_cap issued " << ccap_string(old_caps) << " -> " << ccap_string(cap->issued)
3924            << " from mds." << mds
3925            << " on " << *in
3926            << dendl;
3927
3928   if ((issued & ~old_caps) && in->auth_cap == cap) {
3929     // non-auth MDS is revoking the newly grant caps ?
3930     for (map<mds_rank_t,Cap*>::iterator it = in->caps.begin(); it != in->caps.end(); ++it) {
3931       if (it->second == cap)
3932         continue;
3933       if (it->second->implemented & ~it->second->issued & issued) {
3934         check_caps(in, CHECK_CAPS_NODELAY);
3935         break;
3936       }
3937     }
3938   }
3939
3940   if (issued & ~old_caps)
3941     signal_cond_list(in->waitfor_caps);
3942 }
3943
3944 void Client::remove_cap(Cap *cap, bool queue_release)
3945 {
3946   Inode *in = cap->inode;
3947   MetaSession *session = cap->session;
3948   mds_rank_t mds = cap->session->mds_num;
3949
3950   ldout(cct, 10) << "remove_cap mds." << mds << " on " << *in << dendl;
3951   
3952   if (queue_release) {
3953     session->enqueue_cap_release(
3954       in->ino,
3955       cap->cap_id,
3956       cap->issue_seq,
3957       cap->mseq,
3958       cap_epoch_barrier);
3959   }
3960
3961   if (in->auth_cap == cap) {
3962     if (in->flushing_cap_item.is_on_list()) {
3963       ldout(cct, 10) << " removing myself from flushing_cap list" << dendl;
3964       in->flushing_cap_item.remove_myself();
3965     }
3966     in->auth_cap = NULL;
3967   }
3968   assert(in->caps.count(mds));
3969   in->caps.erase(mds);
3970
3971   cap->cap_item.remove_myself();
3972   delete cap;
3973   cap = nullptr;
3974
3975   if (!in->is_any_caps()) {
3976     ldout(cct, 15) << "remove_cap last one, closing snaprealm " << in->snaprealm << dendl;
3977     in->snaprealm_item.remove_myself();
3978     put_snap_realm(in->snaprealm);
3979     in->snaprealm = 0;
3980   }
3981 }
3982
3983 void Client::remove_all_caps(Inode *in)
3984 {
3985   while (!in->caps.empty())
3986     remove_cap(in->caps.begin()->second, true);
3987 }
3988
3989 void Client::remove_session_caps(MetaSession *s)
3990 {
3991   ldout(cct, 10) << "remove_session_caps mds." << s->mds_num << dendl;
3992
3993   while (s->caps.size()) {
3994     Cap *cap = *s->caps.begin();
3995     Inode *in = cap->inode;
3996     bool dirty_caps = false, cap_snaps = false;
3997     if (in->auth_cap == cap) {
3998       cap_snaps = !in->cap_snaps.empty();
3999       dirty_caps = in->dirty_caps | in->flushing_caps;
4000       in->wanted_max_size = 0;
4001       in->requested_max_size = 0;
4002       in->flags |= I_CAP_DROPPED;
4003     }
4004     remove_cap(cap, false);
4005     signal_cond_list(in->waitfor_caps);
4006     if (cap_snaps) {
4007       InodeRef tmp_ref(in);
4008       in->cap_snaps.clear();
4009     }
4010     if (dirty_caps) {
4011       lderr(cct) << "remove_session_caps still has dirty|flushing caps on " << *in << dendl;
4012       if (in->flushing_caps) {
4013         num_flushing_caps--;
4014         in->flushing_cap_tids.clear();
4015       }
4016       in->flushing_caps = 0;
4017       in->dirty_caps = 0;
4018       put_inode(in);
4019     }
4020   }
4021   s->flushing_caps_tids.clear();
4022   sync_cond.Signal();
4023 }
4024
4025 class C_Client_Remount : public Context  {
4026 private:
4027   Client *client;
4028 public:
4029   explicit C_Client_Remount(Client *c) : client(c) {}
4030   void finish(int r) override {
4031     assert (r == 0);
4032     r = client->remount_cb(client->callback_handle);
4033     if (r != 0) {
4034       client_t whoami = client->get_nodeid();
4035       lderr(client->cct) << "tried to remount (to trim kernel dentries) and got error "
4036                          << r << dendl;
4037       if (client->require_remount && !client->unmounting) {
4038         assert(0 == "failed to remount for kernel dentry trimming");
4039       }
4040     }
4041   }
4042 };
4043
4044 void Client::_invalidate_kernel_dcache()
4045 {
4046   if (unmounting)
4047     return;
4048   if (can_invalidate_dentries && dentry_invalidate_cb && root->dir) {
4049     for (ceph::unordered_map<string, Dentry*>::iterator p = root->dir->dentries.begin();
4050          p != root->dir->dentries.end();
4051          ++p) {
4052       if (p->second->inode)
4053         _schedule_invalidate_dentry_callback(p->second, false);
4054     }
4055   } else if (remount_cb) {
4056     // Hacky:
4057     // when remounting a file system, linux kernel trims all unused dentries in the fs
4058     remount_finisher.queue(new C_Client_Remount(this));
4059   }
4060 }
4061
4062 void Client::trim_caps(MetaSession *s, int max)
4063 {
4064   mds_rank_t mds = s->mds_num;
4065   int caps_size = s->caps.size();
4066   ldout(cct, 10) << "trim_caps mds." << mds << " max " << max 
4067     << " caps " << caps_size << dendl;
4068
4069   int trimmed = 0;
4070   xlist<Cap*>::iterator p = s->caps.begin();
4071   while ((caps_size - trimmed) > max && !p.end()) {
4072     Cap *cap = *p;
4073     Inode *in = cap->inode;
4074
4075     // Increment p early because it will be invalidated if cap
4076     // is deleted inside remove_cap
4077     ++p;
4078
4079     if (in->caps.size() > 1 && cap != in->auth_cap) {
4080       int mine = cap->issued | cap->implemented;
4081       int oissued = in->auth_cap ? in->auth_cap->issued : 0;
4082       // disposable non-auth cap
4083       if (!(get_caps_used(in) & ~oissued & mine)) {
4084         ldout(cct, 20) << " removing unused, unneeded non-auth cap on " << *in << dendl;
4085         remove_cap(cap, true);
4086         trimmed++;
4087       }
4088     } else {
4089       ldout(cct, 20) << " trying to trim dentries for " << *in << dendl;
4090       bool all = true;
4091       set<Dentry*>::iterator q = in->dn_set.begin();
4092       InodeRef tmp_ref(in);
4093       while (q != in->dn_set.end()) {
4094         Dentry *dn = *q++;
4095         if (dn->lru_is_expireable()) {
4096           if (can_invalidate_dentries &&
4097               dn->dir->parent_inode->ino == MDS_INO_ROOT) {
4098             // Only issue one of these per DN for inodes in root: handle
4099             // others more efficiently by calling for root-child DNs at
4100             // the end of this function.
4101             _schedule_invalidate_dentry_callback(dn, true);
4102           }
4103           trim_dentry(dn);
4104         } else {
4105           ldout(cct, 20) << "  not expirable: " << dn->name << dendl;
4106           all = false;
4107         }
4108       }
4109       if (all && in->ino != MDS_INO_ROOT) {
4110         ldout(cct, 20) << __func__ << " counting as trimmed: " << *in << dendl;
4111         trimmed++;
4112       }
4113     }
4114   }
4115
4116   if (s->caps.size() > max)
4117     _invalidate_kernel_dcache();
4118 }
4119
4120 void Client::force_session_readonly(MetaSession *s)
4121 {
4122   s->readonly = true;
4123   for (xlist<Cap*>::iterator p = s->caps.begin(); !p.end(); ++p) {
4124     Inode *in = (*p)->inode;
4125     if (in->caps_wanted() & CEPH_CAP_FILE_WR)
4126       signal_cond_list(in->waitfor_caps);
4127   }
4128 }
4129
4130 void Client::mark_caps_dirty(Inode *in, int caps)
4131 {
4132   ldout(cct, 10) << "mark_caps_dirty " << *in << " " << ccap_string(in->dirty_caps) << " -> "
4133            << ccap_string(in->dirty_caps | caps) << dendl;
4134   if (caps && !in->caps_dirty())
4135     in->get();
4136   in->dirty_caps |= caps;
4137 }
4138
4139 int Client::mark_caps_flushing(Inode *in, ceph_tid_t* ptid)
4140 {
4141   MetaSession *session = in->auth_cap->session;
4142
4143   int flushing = in->dirty_caps;
4144   assert(flushing);
4145
4146   ceph_tid_t flush_tid = ++last_flush_tid;
4147   in->flushing_cap_tids[flush_tid] = flushing;
4148
4149   if (!in->flushing_caps) {
4150     ldout(cct, 10) << "mark_caps_flushing " << ccap_string(flushing) << " " << *in << dendl;
4151     num_flushing_caps++;
4152   } else {
4153     ldout(cct, 10) << "mark_caps_flushing (more) " << ccap_string(flushing) << " " << *in << dendl;
4154   }
4155
4156   in->flushing_caps |= flushing;
4157   in->dirty_caps = 0;
4158  
4159   if (!in->flushing_cap_item.is_on_list())
4160     session->flushing_caps.push_back(&in->flushing_cap_item);
4161   session->flushing_caps_tids.insert(flush_tid);
4162
4163   *ptid = flush_tid;
4164   return flushing;
4165 }
4166
4167 void Client::adjust_session_flushing_caps(Inode *in, MetaSession *old_s,  MetaSession *new_s)
4168 {
4169   for (auto &p : in->cap_snaps) {
4170     CapSnap &capsnap = p.second;
4171     if (capsnap.flush_tid > 0) {
4172       old_s->flushing_caps_tids.erase(capsnap.flush_tid);
4173       new_s->flushing_caps_tids.insert(capsnap.flush_tid);
4174     }
4175   }
4176   for (map<ceph_tid_t, int>::iterator it = in->flushing_cap_tids.begin();
4177        it != in->flushing_cap_tids.end();
4178        ++it) {
4179     old_s->flushing_caps_tids.erase(it->first);
4180     new_s->flushing_caps_tids.insert(it->first);
4181   }
4182   new_s->flushing_caps.push_back(&in->flushing_cap_item);
4183 }
4184
4185 /*
4186  * Flush all caps back to the MDS. Because the callers generally wait on the
4187  * result of this function (syncfs and umount cases), we set
4188  * CHECK_CAPS_SYNCHRONOUS on the last check_caps call.
4189  */
4190 void Client::flush_caps_sync()
4191 {
4192   ldout(cct, 10) << __func__ << dendl;
4193   xlist<Inode*>::iterator p = delayed_caps.begin();
4194   while (!p.end()) {
4195     unsigned flags = CHECK_CAPS_NODELAY;
4196     Inode *in = *p;
4197
4198     ++p;
4199     delayed_caps.pop_front();
4200     if (p.end() && cap_list.empty())
4201       flags |= CHECK_CAPS_SYNCHRONOUS;
4202     check_caps(in, flags);
4203   }
4204
4205   // other caps, too
4206   p = cap_list.begin();
4207   while (!p.end()) {
4208     unsigned flags = CHECK_CAPS_NODELAY;
4209     Inode *in = *p;
4210
4211     ++p;
4212     if (p.end())
4213       flags |= CHECK_CAPS_SYNCHRONOUS;
4214     check_caps(in, flags);
4215   }
4216 }
4217
4218 void Client::flush_caps(Inode *in, MetaSession *session, bool sync)
4219 {
4220   ldout(cct, 10) << "flush_caps " << in << " mds." << session->mds_num << dendl;
4221   Cap *cap = in->auth_cap;
4222   assert(cap->session == session);
4223
4224   for (map<ceph_tid_t,int>::iterator p = in->flushing_cap_tids.begin();
4225        p != in->flushing_cap_tids.end();
4226        ++p) {
4227     bool req_sync = false;
4228
4229     /* If this is a synchronous request, then flush the journal on last one */
4230     if (sync && (p->first == in->flushing_cap_tids.rbegin()->first))
4231       req_sync = true;
4232
4233     send_cap(in, session, cap, req_sync,
4234              (get_caps_used(in) | in->caps_dirty()),
4235              in->caps_wanted(), (cap->issued | cap->implemented),
4236              p->second, p->first);
4237   }
4238 }
4239
4240 void Client::wait_sync_caps(Inode *in, ceph_tid_t want)
4241 {
4242   while (in->flushing_caps) {
4243     map<ceph_tid_t, int>::iterator it = in->flushing_cap_tids.begin();
4244     assert(it != in->flushing_cap_tids.end());
4245     if (it->first > want)
4246       break;
4247     ldout(cct, 10) << "wait_sync_caps on " << *in << " flushing "
4248                    << ccap_string(it->second) << " want " << want
4249                    << " last " << it->first << dendl;
4250     wait_on_list(in->waitfor_caps);
4251   }
4252 }
4253
4254 void Client::wait_sync_caps(ceph_tid_t want)
4255 {
4256  retry:
4257   ldout(cct, 10) << "wait_sync_caps want " << want  << " (last is " << last_flush_tid << ", "
4258            << num_flushing_caps << " total flushing)" << dendl;
4259   for (map<mds_rank_t,MetaSession*>::iterator p = mds_sessions.begin();
4260        p != mds_sessions.end();
4261        ++p) {
4262     MetaSession *s = p->second;
4263     if (s->flushing_caps_tids.empty())
4264         continue;
4265     ceph_tid_t oldest_tid = *s->flushing_caps_tids.begin();
4266     if (oldest_tid <= want) {
4267       ldout(cct, 10) << " waiting on mds." << p->first << " tid " << oldest_tid
4268                      << " (want " << want << ")" << dendl;
4269       sync_cond.Wait(client_lock);
4270       goto retry;
4271     }
4272   }
4273 }
4274
4275 void Client::kick_flushing_caps(MetaSession *session)
4276 {
4277   mds_rank_t mds = session->mds_num;
4278   ldout(cct, 10) << "kick_flushing_caps mds." << mds << dendl;
4279
4280   for (xlist<Inode*>::iterator p = session->flushing_caps.begin(); !p.end(); ++p) {
4281     Inode *in = *p;
4282     if (session->early_flushing_caps.count(in))
4283       continue;
4284     ldout(cct, 20) << " reflushing caps on " << *in << " to mds." << mds << dendl;
4285     if (in->cap_snaps.size())
4286       flush_snaps(in, true);
4287     if (in->flushing_caps)
4288       flush_caps(in, session);
4289   }
4290
4291   session->early_flushing_caps.clear();
4292 }
4293
4294 void Client::early_kick_flushing_caps(MetaSession *session)
4295 {
4296   session->early_flushing_caps.clear();
4297
4298   for (xlist<Inode*>::iterator p = session->flushing_caps.begin(); !p.end(); ++p) {
4299     Inode *in = *p;
4300     assert(in->auth_cap);
4301
4302     // if flushing caps were revoked, we re-send the cap flush in client reconnect
4303     // stage. This guarantees that MDS processes the cap flush message before issuing
4304     // the flushing caps to other client.
4305     if ((in->flushing_caps & in->auth_cap->issued) == in->flushing_caps)
4306       continue;
4307
4308     ldout(cct, 20) << " reflushing caps (early_kick) on " << *in
4309                    << " to mds." << session->mds_num << dendl;
4310
4311     session->early_flushing_caps.insert(in);
4312
4313     if (in->cap_snaps.size())
4314       flush_snaps(in, true);
4315     if (in->flushing_caps)
4316       flush_caps(in, session);
4317
4318   }
4319 }
4320
4321 void Client::kick_maxsize_requests(MetaSession *session)
4322 {
4323   xlist<Cap*>::iterator iter = session->caps.begin();
4324   while (!iter.end()){
4325     (*iter)->inode->requested_max_size = 0;
4326     (*iter)->inode->wanted_max_size = 0;
4327     signal_cond_list((*iter)->inode->waitfor_caps);
4328     ++iter;
4329   }
4330 }
4331
4332 void SnapRealm::build_snap_context()
4333 {
4334   set<snapid_t> snaps;
4335   snapid_t max_seq = seq;
4336   
4337   // start with prior_parents?
4338   for (unsigned i=0; i<prior_parent_snaps.size(); i++)
4339     snaps.insert(prior_parent_snaps[i]);
4340
4341   // current parent's snaps
4342   if (pparent) {
4343     const SnapContext& psnapc = pparent->get_snap_context();
4344     for (unsigned i=0; i<psnapc.snaps.size(); i++)
4345       if (psnapc.snaps[i] >= parent_since)
4346         snaps.insert(psnapc.snaps[i]);
4347     if (psnapc.seq > max_seq)
4348       max_seq = psnapc.seq;
4349   }
4350
4351   // my snaps
4352   for (unsigned i=0; i<my_snaps.size(); i++)
4353     snaps.insert(my_snaps[i]);
4354
4355   // ok!
4356   cached_snap_context.seq = max_seq;
4357   cached_snap_context.snaps.resize(0);
4358   cached_snap_context.snaps.reserve(snaps.size());
4359   for (set<snapid_t>::reverse_iterator p = snaps.rbegin(); p != snaps.rend(); ++p)
4360     cached_snap_context.snaps.push_back(*p);
4361 }
4362
4363 void Client::invalidate_snaprealm_and_children(SnapRealm *realm)
4364 {
4365   list<SnapRealm*> q;
4366   q.push_back(realm);
4367
4368   while (!q.empty()) {
4369     realm = q.front();
4370     q.pop_front();
4371
4372     ldout(cct, 10) << "invalidate_snaprealm_and_children " << *realm << dendl;
4373     realm->invalidate_cache();
4374
4375     for (set<SnapRealm*>::iterator p = realm->pchildren.begin();
4376          p != realm->pchildren.end(); 
4377          ++p)
4378       q.push_back(*p);
4379   }
4380 }
4381
4382 SnapRealm *Client::get_snap_realm(inodeno_t r)
4383 {
4384   SnapRealm *realm = snap_realms[r];
4385   if (!realm)
4386     snap_realms[r] = realm = new SnapRealm(r);
4387   ldout(cct, 20) << "get_snap_realm " << r << " " << realm << " " << realm->nref << " -> " << (realm->nref + 1) << dendl;
4388   realm->nref++;
4389   return realm;
4390 }
4391
4392 SnapRealm *Client::get_snap_realm_maybe(inodeno_t r)
4393 {
4394   if (snap_realms.count(r) == 0) {
4395     ldout(cct, 20) << "get_snap_realm_maybe " << r << " fail" << dendl;
4396     return NULL;
4397   }
4398   SnapRealm *realm = snap_realms[r];
4399   ldout(cct, 20) << "get_snap_realm_maybe " << r << " " << realm << " " << realm->nref << " -> " << (realm->nref + 1) << dendl;
4400   realm->nref++;
4401   return realm;
4402 }
4403
4404 void Client::put_snap_realm(SnapRealm *realm)
4405 {
4406   ldout(cct, 20) << "put_snap_realm " << realm->ino << " " << realm
4407                  << " " << realm->nref << " -> " << (realm->nref - 1) << dendl;
4408   if (--realm->nref == 0) {
4409     snap_realms.erase(realm->ino);
4410     if (realm->pparent) {
4411       realm->pparent->pchildren.erase(realm);
4412       put_snap_realm(realm->pparent);
4413     }
4414     delete realm;
4415   }
4416 }
4417
4418 bool Client::adjust_realm_parent(SnapRealm *realm, inodeno_t parent)
4419 {
4420   if (realm->parent != parent) {
4421     ldout(cct, 10) << "adjust_realm_parent " << *realm
4422              << " " << realm->parent << " -> " << parent << dendl;
4423     realm->parent = parent;
4424     if (realm->pparent) {
4425       realm->pparent->pchildren.erase(realm);
4426       put_snap_realm(realm->pparent);
4427     }
4428     realm->pparent = get_snap_realm(parent);
4429     realm->pparent->pchildren.insert(realm);
4430     return true;
4431   }
4432   return false;
4433 }
4434
4435 static bool has_new_snaps(const SnapContext& old_snapc,
4436                           const SnapContext& new_snapc)
4437 {
4438   return !new_snapc.snaps.empty() && new_snapc.snaps[0] > old_snapc.seq;
4439 }
4440
4441
4442 void Client::update_snap_trace(bufferlist& bl, SnapRealm **realm_ret, bool flush)
4443 {
4444   SnapRealm *first_realm = NULL;
4445   ldout(cct, 10) << "update_snap_trace len " << bl.length() << dendl;
4446
4447   map<SnapRealm*, SnapContext> dirty_realms;
4448
4449   bufferlist::iterator p = bl.begin();
4450   while (!p.end()) {
4451     SnapRealmInfo info;
4452     ::decode(info, p);
4453     SnapRealm *realm = get_snap_realm(info.ino());
4454
4455     bool invalidate = false;
4456
4457     if (info.seq() > realm->seq) {
4458       ldout(cct, 10) << "update_snap_trace " << *realm << " seq " << info.seq() << " > " << realm->seq
4459                << dendl;
4460
4461       if (flush) {
4462         // writeback any dirty caps _before_ updating snap list (i.e. with old snap info)
4463         //  flush me + children
4464         list<SnapRealm*> q;
4465         q.push_back(realm);
4466         while (!q.empty()) {
4467           SnapRealm *realm = q.front();
4468           q.pop_front();
4469
4470           for (set<SnapRealm*>::iterator p = realm->pchildren.begin(); 
4471                p != realm->pchildren.end();
4472                ++p)
4473             q.push_back(*p);
4474
4475           if (dirty_realms.count(realm) == 0) {
4476             realm->nref++;
4477             dirty_realms[realm] = realm->get_snap_context();
4478           }
4479         }
4480       }
4481
4482       // update
4483       realm->seq = info.seq();
4484       realm->created = info.created();
4485       realm->parent_since = info.parent_since();
4486       realm->prior_parent_snaps = info.prior_parent_snaps;
4487       realm->my_snaps = info.my_snaps;
4488       invalidate = true;
4489     }
4490
4491     // _always_ verify parent
4492     if (adjust_realm_parent(realm, info.parent()))
4493       invalidate = true;
4494
4495     if (invalidate) {
4496       invalidate_snaprealm_and_children(realm);
4497       ldout(cct, 15) << "update_snap_trace " << *realm << " self|parent updated" << dendl;
4498       ldout(cct, 15) << "  snapc " << realm->get_snap_context() << dendl;
4499     } else {
4500       ldout(cct, 10) << "update_snap_trace " << *realm << " seq " << info.seq()
4501                << " <= " << realm->seq << " and same parent, SKIPPING" << dendl;
4502     }
4503         
4504     if (!first_realm)
4505       first_realm = realm;
4506     else
4507       put_snap_realm(realm);
4508   }
4509
4510   for (map<SnapRealm*, SnapContext>::iterator q = dirty_realms.begin();
4511        q != dirty_realms.end();
4512        ++q) {
4513     SnapRealm *realm = q->first;
4514     // if there are new snaps ?
4515     if (has_new_snaps(q->second, realm->get_snap_context())) { 
4516       ldout(cct, 10) << " flushing caps on " << *realm << dendl;
4517       xlist<Inode*>::iterator r = realm->inodes_with_caps.begin();
4518       while (!r.end()) {
4519         Inode *in = *r;
4520         ++r;
4521         queue_cap_snap(in, q->second);
4522       }
4523     } else {
4524       ldout(cct, 10) << " no new snap on " << *realm << dendl;
4525     }
4526     put_snap_realm(realm);
4527   }
4528
4529   if (realm_ret)
4530     *realm_ret = first_realm;
4531   else
4532     put_snap_realm(first_realm);
4533 }
4534
4535 void Client::handle_snap(MClientSnap *m)
4536 {
4537   ldout(cct, 10) << "handle_snap " << *m << dendl;
4538   mds_rank_t mds = mds_rank_t(m->get_source().num());
4539   MetaSession *session = _get_mds_session(mds, m->get_connection().get());
4540   if (!session) {
4541     m->put();
4542     return;
4543   }
4544
4545   got_mds_push(session);
4546
4547   map<Inode*, SnapContext> to_move;
4548   SnapRealm *realm = 0;
4549
4550   if (m->head.op == CEPH_SNAP_OP_SPLIT) {
4551     assert(m->head.split);
4552     SnapRealmInfo info;
4553     bufferlist::iterator p = m->bl.begin();    
4554     ::decode(info, p);
4555     assert(info.ino() == m->head.split);
4556     
4557     // flush, then move, ino's.
4558     realm = get_snap_realm(info.ino());
4559     ldout(cct, 10) << " splitting off " << *realm << dendl;
4560     for (vector<inodeno_t>::iterator p = m->split_inos.begin();
4561          p != m->split_inos.end();
4562          ++p) {
4563       vinodeno_t vino(*p, CEPH_NOSNAP);
4564       if (inode_map.count(vino)) {
4565         Inode *in = inode_map[vino];
4566         if (!in->snaprealm || in->snaprealm == realm)
4567           continue;
4568         if (in->snaprealm->created > info.created()) {
4569           ldout(cct, 10) << " NOT moving " << *in << " from _newer_ realm " 
4570                    << *in->snaprealm << dendl;
4571           continue;
4572         }
4573         ldout(cct, 10) << " moving " << *in << " from " << *in->snaprealm << dendl;
4574
4575
4576         in->snaprealm_item.remove_myself();
4577         to_move[in] = in->snaprealm->get_snap_context();
4578         put_snap_realm(in->snaprealm);
4579       }
4580     }
4581
4582     // move child snaprealms, too
4583     for (vector<inodeno_t>::iterator p = m->split_realms.begin();
4584          p != m->split_realms.end();
4585          ++p) {
4586       ldout(cct, 10) << "adjusting snaprealm " << *p << " parent" << dendl;
4587       SnapRealm *child = get_snap_realm_maybe(*p);
4588       if (!child)
4589         continue;
4590       adjust_realm_parent(child, realm->ino);
4591       put_snap_realm(child);
4592     }
4593   }
4594
4595   update_snap_trace(m->bl, NULL, m->head.op != CEPH_SNAP_OP_DESTROY);
4596
4597   if (realm) {
4598     for (auto p = to_move.begin(); p != to_move.end(); ++p) {
4599       Inode *in = p->first;
4600       in->snaprealm = realm;
4601       realm->inodes_with_caps.push_back(&in->snaprealm_item);
4602       realm->nref++;
4603       // queue for snap writeback
4604       if (has_new_snaps(p->second, realm->get_snap_context()))
4605         queue_cap_snap(in, p->second);
4606     }
4607     put_snap_realm(realm);
4608   }
4609
4610   m->put();
4611 }
4612
4613 void Client::handle_quota(MClientQuota *m)
4614 {
4615   mds_rank_t mds = mds_rank_t(m->get_source().num());
4616   MetaSession *session = _get_mds_session(mds, m->get_connection().get());
4617   if (!session) {
4618     m->put();
4619     return;
4620   }
4621
4622   got_mds_push(session);
4623
4624   ldout(cct, 10) << "handle_quota " << *m << " from mds." << mds << dendl;
4625
4626   vinodeno_t vino(m->ino, CEPH_NOSNAP);
4627   if (inode_map.count(vino)) {
4628     Inode *in = NULL;
4629     in = inode_map[vino];
4630
4631     if (in) {
4632       in->quota = m->quota;
4633       in->rstat = m->rstat;
4634     }
4635   }
4636
4637   m->put();
4638 }
4639
4640 void Client::handle_caps(MClientCaps *m)
4641 {
4642   mds_rank_t mds = mds_rank_t(m->get_source().num());
4643   MetaSession *session = _get_mds_session(mds, m->get_connection().get());
4644   if (!session) {
4645     m->put();
4646     return;
4647   }
4648
4649   if (m->osd_epoch_barrier && !objecter->have_map(m->osd_epoch_barrier)) {
4650     // Pause RADOS operations until we see the required epoch
4651     objecter->set_epoch_barrier(m->osd_epoch_barrier);
4652   }
4653
4654   if (m->osd_epoch_barrier > cap_epoch_barrier) {
4655     // Record the barrier so that we will transmit it to MDS when releasing
4656     set_cap_epoch_barrier(m->osd_epoch_barrier);
4657   }
4658
4659   got_mds_push(session);
4660
4661   m->clear_payload();  // for if/when we send back to MDS
4662
4663   Inode *in = 0;
4664   vinodeno_t vino(m->get_ino(), CEPH_NOSNAP);
4665   if (inode_map.count(vino))
4666     in = inode_map[vino];
4667   if (!in) {
4668     if (m->get_op() == CEPH_CAP_OP_IMPORT) {
4669       ldout(cct, 5) << "handle_caps don't have vino " << vino << " on IMPORT, immediately releasing" << dendl;
4670       session->enqueue_cap_release(
4671         m->get_ino(),
4672         m->get_cap_id(),
4673         m->get_seq(),
4674         m->get_mseq(),
4675         cap_epoch_barrier);
4676     } else {
4677       ldout(cct, 5) << "handle_caps don't have vino " << vino << ", dropping" << dendl;
4678     }
4679     m->put();
4680
4681     // in case the mds is waiting on e.g. a revocation
4682     flush_cap_releases();
4683     return;
4684   }
4685
4686   switch (m->get_op()) {
4687   case CEPH_CAP_OP_EXPORT:
4688     return handle_cap_export(session, in, m);
4689   case CEPH_CAP_OP_FLUSHSNAP_ACK:
4690     return handle_cap_flushsnap_ack(session, in, m);
4691   case CEPH_CAP_OP_IMPORT:
4692     handle_cap_import(session, in, m);
4693   }
4694
4695   if (in->caps.count(mds) == 0) {
4696     ldout(cct, 5) << "handle_caps don't have " << *in << " cap on mds." << mds << dendl;
4697     m->put();
4698     return;
4699   }
4700
4701   Cap *cap = in->caps[mds];
4702
4703   switch (m->get_op()) {
4704   case CEPH_CAP_OP_TRUNC: return handle_cap_trunc(session, in, m);
4705   case CEPH_CAP_OP_IMPORT:
4706   case CEPH_CAP_OP_REVOKE:
4707   case CEPH_CAP_OP_GRANT: return handle_cap_grant(session, in, cap, m);
4708   case CEPH_CAP_OP_FLUSH_ACK: return handle_cap_flush_ack(session, in, cap, m);
4709   default:
4710     m->put();
4711   }
4712 }
4713
4714 void Client::handle_cap_import(MetaSession *session, Inode *in, MClientCaps *m)
4715 {
4716   mds_rank_t mds = session->mds_num;
4717
4718   ldout(cct, 5) << "handle_cap_import ino " << m->get_ino() << " mseq " << m->get_mseq()
4719                 << " IMPORT from mds." << mds << dendl;
4720
4721   const mds_rank_t peer_mds = mds_rank_t(m->peer.mds);
4722   Cap *cap = NULL;
4723   UserPerm cap_perms;
4724   if (m->peer.cap_id && in->caps.count(peer_mds)) {
4725     cap = in->caps[peer_mds];
4726     if (cap) {
4727       cap_perms = cap->latest_perms;
4728     }
4729   }
4730
4731   // add/update it
4732   SnapRealm *realm = NULL;
4733   update_snap_trace(m->snapbl, &realm);
4734
4735   add_update_cap(in, session, m->get_cap_id(),
4736                  m->get_caps(), m->get_seq(), m->get_mseq(), m->get_realm(),
4737                  CEPH_CAP_FLAG_AUTH, cap_perms);
4738   
4739   if (cap && cap->cap_id == m->peer.cap_id) {
4740       remove_cap(cap, (m->peer.flags & CEPH_CAP_FLAG_RELEASE));
4741   }
4742
4743   if (realm)
4744     put_snap_realm(realm);
4745   
4746   if (in->auth_cap && in->auth_cap->session->mds_num == mds) {
4747     // reflush any/all caps (if we are now the auth_cap)
4748     if (in->cap_snaps.size())
4749       flush_snaps(in, true);
4750     if (in->flushing_caps)
4751       flush_caps(in, session);
4752   }
4753 }
4754
4755 void Client::handle_cap_export(MetaSession *session, Inode *in, MClientCaps *m)
4756 {
4757   mds_rank_t mds = session->mds_num;
4758
4759   ldout(cct, 5) << "handle_cap_export ino " << m->get_ino() << " mseq " << m->get_mseq()
4760                 << " EXPORT from mds." << mds << dendl;
4761
4762   Cap *cap = NULL;
4763   if (in->caps.count(mds))
4764     cap = in->caps[mds];
4765
4766   const mds_rank_t peer_mds = mds_rank_t(m->peer.mds);
4767
4768   if (cap && cap->cap_id == m->get_cap_id()) {
4769     if (m->peer.cap_id) {
4770       MetaSession *tsession = _get_or_open_mds_session(peer_mds);
4771       if (in->caps.count(peer_mds)) {
4772         Cap *tcap = in->caps[peer_mds];
4773         if (tcap->cap_id == m->peer.cap_id &&
4774             ceph_seq_cmp(tcap->seq, m->peer.seq) < 0) {
4775           tcap->cap_id = m->peer.cap_id;
4776           tcap->seq = m->peer.seq - 1;
4777           tcap->issue_seq = tcap->seq;
4778           tcap->mseq = m->peer.mseq;
4779           tcap->issued |= cap->issued;
4780           tcap->implemented |= cap->issued;
4781           if (cap == in->auth_cap)
4782             in->auth_cap = tcap;
4783           if (in->auth_cap == tcap && in->flushing_cap_item.is_on_list())
4784             adjust_session_flushing_caps(in, session, tsession);
4785         }
4786       } else {
4787         add_update_cap(in, tsession, m->peer.cap_id, cap->issued,
4788                        m->peer.seq - 1, m->peer.mseq, (uint64_t)-1,
4789                        cap == in->auth_cap ? CEPH_CAP_FLAG_AUTH : 0,
4790                        cap->latest_perms);
4791       }
4792     } else {
4793       if (cap == in->auth_cap)
4794         in->flags |= I_CAP_DROPPED;
4795     }
4796
4797     remove_cap(cap, false);
4798   }
4799
4800   m->put();
4801 }
4802
4803 void Client::handle_cap_trunc(MetaSession *session, Inode *in, MClientCaps *m)
4804 {
4805   mds_rank_t mds = session->mds_num;
4806   assert(in->caps[mds]);
4807
4808   ldout(cct, 10) << "handle_cap_trunc on ino " << *in
4809            << " size " << in->size << " -> " << m->get_size()
4810            << dendl;
4811   
4812   int implemented = 0;
4813   int issued = in->caps_issued(&implemented) | in->caps_dirty();
4814   issued |= implemented;
4815   update_inode_file_bits(in, m->get_truncate_seq(), m->get_truncate_size(),
4816                          m->get_size(), m->get_change_attr(), m->get_time_warp_seq(),
4817                          m->get_ctime(), m->get_mtime(), m->get_atime(),
4818                          m->inline_version, m->inline_data, issued);
4819   m->put();
4820 }
4821
4822 void Client::handle_cap_flush_ack(MetaSession *session, Inode *in, Cap *cap, MClientCaps *m)
4823 {
4824   ceph_tid_t flush_ack_tid = m->get_client_tid();
4825   int dirty = m->get_dirty();
4826   int cleaned = 0;
4827   int flushed = 0;
4828
4829   for (map<ceph_tid_t, int>::iterator it = in->flushing_cap_tids.begin();
4830        it != in->flushing_cap_tids.end(); ) {
4831     if (it->first == flush_ack_tid)
4832       cleaned = it->second;
4833     if (it->first <= flush_ack_tid) {
4834       session->flushing_caps_tids.erase(it->first);
4835       in->flushing_cap_tids.erase(it++);
4836       ++flushed;
4837       continue;
4838     }
4839     cleaned &= ~it->second;
4840     if (!cleaned)
4841       break;
4842     ++it;
4843   }
4844
4845   ldout(cct, 5) << "handle_cap_flush_ack mds." << session->mds_num
4846           << " cleaned " << ccap_string(cleaned) << " on " << *in
4847           << " with " << ccap_string(dirty) << dendl;
4848
4849   if (flushed) {
4850     signal_cond_list(in->waitfor_caps);
4851     if (session->flushing_caps_tids.empty() ||
4852         *session->flushing_caps_tids.begin() > flush_ack_tid)
4853       sync_cond.Signal();
4854   }
4855
4856   if (!dirty) {
4857     in->cap_dirtier_uid = -1;
4858     in->cap_dirtier_gid = -1;
4859   }
4860
4861   if (!cleaned) {
4862     ldout(cct, 10) << " tid " << m->get_client_tid() << " != any cap bit tids" << dendl;
4863   } else {
4864     if (in->flushing_caps) {
4865       ldout(cct, 5) << "  flushing_caps " << ccap_string(in->flushing_caps)
4866               << " -> " << ccap_string(in->flushing_caps & ~cleaned) << dendl;
4867       in->flushing_caps &= ~cleaned;
4868       if (in->flushing_caps == 0) {
4869         ldout(cct, 10) << " " << *in << " !flushing" << dendl;
4870         num_flushing_caps--;
4871         if (in->cap_snaps.empty())
4872           in->flushing_cap_item.remove_myself();
4873       }
4874       if (!in->caps_dirty())
4875         put_inode(in);
4876     }
4877   }
4878   
4879   m->put();
4880 }
4881
4882
4883 void Client::handle_cap_flushsnap_ack(MetaSession *session, Inode *in, MClientCaps *m)
4884 {
4885   mds_rank_t mds = session->mds_num;
4886   assert(in->caps[mds]);
4887   snapid_t follows = m->get_snap_follows();
4888
4889   if (in->cap_snaps.count(follows)) {
4890     CapSnap &capsnap = in->cap_snaps.at(follows);
4891     if (m->get_client_tid() != capsnap.flush_tid) {
4892       ldout(cct, 10) << " tid " << m->get_client_tid() << " != " << capsnap.flush_tid << dendl;
4893     } else {
4894       ldout(cct, 5) << "handle_cap_flushedsnap mds." << mds << " flushed snap follows " << follows
4895               << " on " << *in << dendl;
4896       InodeRef tmp_ref;
4897       if (in->get_num_ref() == 1)
4898         tmp_ref = in; // make sure inode not get freed while erasing item from in->cap_snaps
4899       if (in->flushing_caps == 0 && in->cap_snaps.empty())
4900         in->flushing_cap_item.remove_myself();
4901       session->flushing_caps_tids.erase(capsnap.flush_tid);
4902       in->cap_snaps.erase(follows);
4903     }
4904   } else {
4905     ldout(cct, 5) << "handle_cap_flushedsnap DUP(?) mds." << mds << " flushed snap follows " << follows
4906             << " on " << *in << dendl;
4907     // we may not have it if we send multiple FLUSHSNAP requests and (got multiple FLUSHEDSNAPs back)
4908   }
4909
4910   m->put();
4911 }
4912
4913 class C_Client_DentryInvalidate : public Context  {
4914 private:
4915   Client *client;
4916   vinodeno_t dirino;
4917   vinodeno_t ino;
4918   string name;
4919 public:
4920   C_Client_DentryInvalidate(Client *c, Dentry *dn, bool del) :
4921     client(c), name(dn->name) {
4922       if (client->use_faked_inos()) {
4923         dirino.ino = dn->dir->parent_inode->faked_ino;
4924         if (del)
4925           ino.ino = dn->inode->faked_ino;
4926       } else {
4927         dirino = dn->dir->parent_inode->vino();
4928         if (del)
4929           ino = dn->inode->vino();
4930       }
4931       if (!del)
4932         ino.ino = inodeno_t();
4933   }
4934   void finish(int r) override {
4935     // _async_dentry_invalidate is responsible for its own locking
4936     assert(!client->client_lock.is_locked_by_me());
4937     client->_async_dentry_invalidate(dirino, ino, name);
4938   }
4939 };
4940
4941 void Client::_async_dentry_invalidate(vinodeno_t dirino, vinodeno_t ino, string& name)
4942 {
4943   if (unmounting)
4944     return;
4945   ldout(cct, 10) << "_async_dentry_invalidate '" << name << "' ino " << ino
4946                  << " in dir " << dirino << dendl;
4947   dentry_invalidate_cb(callback_handle, dirino, ino, name);
4948 }
4949
4950 void Client::_schedule_invalidate_dentry_callback(Dentry *dn, bool del)
4951 {
4952   if (dentry_invalidate_cb && dn->inode->ll_ref > 0)
4953     async_dentry_invalidator.queue(new C_Client_DentryInvalidate(this, dn, del));
4954 }
4955
4956 void Client::_try_to_trim_inode(Inode *in, bool sched_inval)
4957 {
4958   int ref = in->get_num_ref();
4959
4960   if (in->dir && !in->dir->dentries.empty()) {
4961     for (auto p = in->dir->dentries.begin();
4962          p != in->dir->dentries.end(); ) {
4963       Dentry *dn = p->second;
4964       ++p;
4965       /* rmsnap removes whole subtree, need trim inodes recursively.
4966        * we don't need to invalidate dentries recursively. because
4967        * invalidating a directory dentry effectively invalidate
4968        * whole subtree */
4969       if (in->snapid != CEPH_NOSNAP && dn->inode && dn->inode->is_dir())
4970         _try_to_trim_inode(dn->inode.get(), false);
4971
4972       if (dn->lru_is_expireable())
4973         unlink(dn, true, false);  // keep dir, drop dentry
4974     }
4975     if (in->dir->dentries.empty()) {
4976       close_dir(in->dir);
4977       --ref;
4978     }
4979   }
4980
4981   if (ref > 0 && (in->flags & I_SNAPDIR_OPEN)) {
4982     InodeRef snapdir = open_snapdir(in);
4983     _try_to_trim_inode(snapdir.get(), false);
4984     --ref;
4985   }
4986
4987   if (ref > 0 && in->ll_ref > 0 && sched_inval) {
4988     set<Dentry*>::iterator q = in->dn_set.begin();
4989     while (q != in->dn_set.end()) {
4990       Dentry *dn = *q++;
4991       // FIXME: we play lots of unlink/link tricks when handling MDS replies,
4992       //        so in->dn_set doesn't always reflect the state of kernel's dcache.
4993       _schedule_invalidate_dentry_callback(dn, true);
4994       unlink(dn, true, true);
4995     }
4996   }
4997 }
4998
4999 void Client::handle_cap_grant(MetaSession *session, Inode *in, Cap *cap, MClientCaps *m)
5000 {
5001   mds_rank_t mds = session->mds_num;
5002   int used = get_caps_used(in);
5003   int wanted = in->caps_wanted();
5004
5005   const int old_caps = cap->issued;
5006   const int new_caps = m->get_caps();
5007   ldout(cct, 5) << "handle_cap_grant on in " << m->get_ino() 
5008                 << " mds." << mds << " seq " << m->get_seq()
5009                 << " caps now " << ccap_string(new_caps)
5010                 << " was " << ccap_string(old_caps) << dendl;
5011   cap->seq = m->get_seq();
5012
5013   in->layout = m->get_layout();
5014
5015   // update inode
5016   int implemented = 0;
5017   int issued = in->caps_issued(&implemented) | in->caps_dirty();
5018   issued |= implemented;
5019
5020   if ((issued & CEPH_CAP_AUTH_EXCL) == 0) {
5021     in->mode = m->head.mode;
5022     in->uid = m->head.uid;
5023     in->gid = m->head.gid;
5024     in->btime = m->btime;
5025   }
5026   bool deleted_inode = false;
5027   if ((issued & CEPH_CAP_LINK_EXCL) == 0) {
5028     in->nlink = m->head.nlink;
5029     if (in->nlink == 0 &&
5030         (new_caps & (CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL)))
5031       deleted_inode = true;
5032   }
5033   if ((issued & CEPH_CAP_XATTR_EXCL) == 0 &&
5034       m->xattrbl.length() &&
5035       m->head.xattr_version > in->xattr_version) {
5036     bufferlist::iterator p = m->xattrbl.begin();
5037     ::decode(in->xattrs, p);
5038     in->xattr_version = m->head.xattr_version;
5039   }
5040   update_inode_file_bits(in, m->get_truncate_seq(), m->get_truncate_size(), m->get_size(),
5041                          m->get_change_attr(), m->get_time_warp_seq(), m->get_ctime(),
5042                          m->get_mtime(), m->get_atime(),
5043                          m->inline_version, m->inline_data, issued);
5044
5045   // max_size
5046   if (cap == in->auth_cap &&
5047       m->get_max_size() != in->max_size) {
5048     ldout(cct, 10) << "max_size " << in->max_size << " -> " << m->get_max_size() << dendl;
5049     in->max_size = m->get_max_size();
5050     if (in->max_size > in->wanted_max_size) {
5051       in->wanted_max_size = 0;
5052       in->requested_max_size = 0;
5053     }
5054   }
5055
5056   bool check = false;
5057   if (m->get_op() == CEPH_CAP_OP_IMPORT && m->get_wanted() != wanted)
5058     check = true;
5059
5060   check_cap_issue(in, cap, new_caps);
5061
5062   // update caps
5063   if (old_caps & ~new_caps) { 
5064     ldout(cct, 10) << "  revocation of " << ccap_string(~new_caps & old_caps) << dendl;
5065     cap->issued = new_caps;
5066     cap->implemented |= new_caps;
5067
5068     if (((used & ~new_caps) & CEPH_CAP_FILE_BUFFER)
5069         && !_flush(in, new C_Client_FlushComplete(this, in))) {
5070       // waitin' for flush
5071     } else if ((old_caps & ~new_caps) & CEPH_CAP_FILE_CACHE) {
5072       if (_release(in))
5073         check = true;
5074     } else {
5075       cap->wanted = 0; // don't let check_caps skip sending a response to MDS
5076       check = true;
5077     }
5078
5079   } else if (old_caps == new_caps) {
5080     ldout(cct, 10) << "  caps unchanged at " << ccap_string(old_caps) << dendl;
5081   } else {
5082     ldout(cct, 10) << "  grant, new caps are " << ccap_string(new_caps & ~old_caps) << dendl;
5083     cap->issued = new_caps;
5084     cap->implemented |= new_caps;
5085
5086     if (cap == in->auth_cap) {
5087       // non-auth MDS is revoking the newly grant caps ?
5088       for (map<mds_rank_t, Cap*>::iterator it = in->caps.begin(); it != in->caps.end(); ++it) {
5089         if (it->second == cap)
5090           continue;
5091         if (it->second->implemented & ~it->second->issued & new_caps) {
5092           check = true;
5093           break;
5094         }
5095       }
5096     }
5097   }
5098
5099   if (check)
5100     check_caps(in, 0);
5101
5102   // wake up waiters
5103   if (new_caps)
5104     signal_cond_list(in->waitfor_caps);
5105
5106   // may drop inode's last ref
5107   if (deleted_inode)
5108     _try_to_trim_inode(in, true);
5109
5110   m->put();
5111 }
5112
5113 int Client::_getgrouplist(gid_t** sgids, uid_t uid, gid_t gid)
5114 {
5115   // cppcheck-suppress variableScope
5116   int sgid_count;
5117   gid_t *sgid_buf;
5118
5119   if (getgroups_cb) {
5120     sgid_count = getgroups_cb(callback_handle, &sgid_buf);
5121     if (sgid_count > 0) {
5122       *sgids = sgid_buf;
5123       return sgid_count;
5124     }
5125   }
5126
5127 #if HAVE_GETGROUPLIST
5128   struct passwd *pw;
5129   pw = getpwuid(uid);
5130   if (pw == NULL) {
5131     ldout(cct, 3) << "getting user entry failed" << dendl;
5132     return -errno;
5133   }
5134   //use PAM to get the group list
5135   // initial number of group entries, defaults to posix standard of 16
5136   // PAM implementations may provide more than 16 groups....
5137   sgid_count = 16;
5138   sgid_buf = (gid_t*)malloc(sgid_count * sizeof(gid_t));
5139   if (sgid_buf == NULL) {
5140     ldout(cct, 3) << "allocating group memory failed" << dendl;
5141     return -ENOMEM;
5142   }
5143
5144   while (1) {
5145 #if defined(__APPLE__)
5146     if (getgrouplist(pw->pw_name, gid, (int*)sgid_buf, &sgid_count) == -1) {
5147 #else
5148     if (getgrouplist(pw->pw_name, gid, sgid_buf, &sgid_count) == -1) {
5149 #endif
5150       // we need to resize the group list and try again
5151       void *_realloc = NULL;
5152       if ((_realloc = realloc(sgid_buf, sgid_count * sizeof(gid_t))) == NULL) {
5153         ldout(cct, 3) << "allocating group memory failed" << dendl;
5154         free(sgid_buf);
5155         return -ENOMEM;
5156       }
5157       sgid_buf = (gid_t*)_realloc;
5158       continue;
5159     }
5160     // list was successfully retrieved
5161     break;
5162   }
5163   *sgids = sgid_buf;
5164   return sgid_count;
5165 #else
5166   return 0;
5167 #endif
5168 }
5169
5170 int Client::inode_permission(Inode *in, const UserPerm& perms, unsigned want)
5171 {
5172   if (perms.uid() == 0)
5173     return 0;
5174   
5175   if (perms.uid() != in->uid && (in->mode & S_IRWXG)) {
5176     int ret = _posix_acl_permission(in, perms, want);
5177     if (ret != -EAGAIN)
5178       return ret;
5179   }
5180
5181   // check permissions before doing anything else
5182   if (!in->check_mode(perms, want))
5183     return -EACCES;
5184   return 0;
5185 }
5186
5187 int Client::xattr_permission(Inode *in, const char *name, unsigned want,
5188                              const UserPerm& perms)
5189 {
5190   int r = _getattr_for_perm(in, perms);
5191   if (r < 0)
5192     goto out;
5193
5194   r = 0;
5195   if (strncmp(name, "system.", 7) == 0) {
5196     if ((want & MAY_WRITE) && (perms.uid() != 0 && perms.uid() != in->uid))
5197       r = -EPERM;
5198   } else {
5199     r = inode_permission(in, perms, want);
5200   }
5201 out:
5202   ldout(cct, 3) << __func__ << " " << in << " = " << r <<  dendl;
5203   return r;
5204 }
5205
5206 ostream& operator<<(ostream &out, const UserPerm& perm) {
5207   out << "UserPerm(uid: " << perm.uid() << ", gid: " << perm.gid() << ")";
5208   return out;
5209 }
5210
5211 int Client::may_setattr(Inode *in, struct ceph_statx *stx, int mask,
5212                         const UserPerm& perms)
5213 {
5214   ldout(cct, 20) << __func__ << " " << *in << "; " << perms << dendl;
5215   int r = _getattr_for_perm(in, perms);
5216   if (r < 0)
5217     goto out;
5218
5219   if (mask & CEPH_SETATTR_SIZE) {
5220     r = inode_permission(in, perms, MAY_WRITE);
5221     if (r < 0)
5222       goto out;
5223   }
5224
5225   r = -EPERM;
5226   if (mask & CEPH_SETATTR_UID) {
5227     if (perms.uid() != 0 && (perms.uid() != in->uid || stx->stx_uid != in->uid))
5228       goto out;
5229   }
5230   if (mask & CEPH_SETATTR_GID) {
5231     if (perms.uid() != 0 && (perms.uid() != in->uid ||
5232                (!perms.gid_in_groups(stx->stx_gid) && stx->stx_gid != in->gid)))
5233       goto out;
5234   }
5235
5236   if (mask & CEPH_SETATTR_MODE) {
5237     if (perms.uid() != 0 && perms.uid() != in->uid)
5238       goto out;
5239
5240     gid_t i_gid = (mask & CEPH_SETATTR_GID) ? stx->stx_gid : in->gid;
5241     if (perms.uid() != 0 && !perms.gid_in_groups(i_gid))
5242       stx->stx_mode &= ~S_ISGID;
5243   }
5244
5245   if (mask & (CEPH_SETATTR_CTIME | CEPH_SETATTR_BTIME |
5246               CEPH_SETATTR_MTIME | CEPH_SETATTR_ATIME)) {
5247     if (perms.uid() != 0 && perms.uid() != in->uid) {
5248       int check_mask = CEPH_SETATTR_CTIME | CEPH_SETATTR_BTIME;
5249       if (!(mask & CEPH_SETATTR_MTIME_NOW))
5250         check_mask |= CEPH_SETATTR_MTIME;
5251       if (!(mask & CEPH_SETATTR_ATIME_NOW))
5252         check_mask |= CEPH_SETATTR_ATIME;
5253       if (check_mask & mask) {
5254         goto out;
5255       } else {
5256         r = inode_permission(in, perms, MAY_WRITE);
5257         if (r < 0)
5258           goto out;
5259       }
5260     }
5261   }
5262   r = 0;
5263 out:
5264   ldout(cct, 3) << __func__ << " " << in << " = " << r <<  dendl;
5265   return r;
5266 }
5267
5268 int Client::may_open(Inode *in, int flags, const UserPerm& perms)
5269 {
5270   ldout(cct, 20) << __func__ << " " << *in << "; " << perms << dendl;
5271   unsigned want = 0;
5272
5273   if ((flags & O_ACCMODE) == O_WRONLY)
5274     want = MAY_WRITE;
5275   else if ((flags & O_ACCMODE) == O_RDWR)
5276     want = MAY_READ | MAY_WRITE;
5277   else if ((flags & O_ACCMODE) == O_RDONLY)
5278     want = MAY_READ;
5279   if (flags & O_TRUNC)
5280     want |= MAY_WRITE;
5281
5282   int r = 0;
5283   switch (in->mode & S_IFMT) {
5284     case S_IFLNK:
5285       r = -ELOOP;
5286       goto out;
5287     case S_IFDIR:
5288       if (want & MAY_WRITE) {
5289         r = -EISDIR;
5290         goto out;
5291       }
5292       break;
5293   }
5294
5295   r = _getattr_for_perm(in, perms);
5296   if (r < 0)
5297     goto out;
5298
5299   r = inode_permission(in, perms, want);
5300 out:
5301   ldout(cct, 3) << __func__ << " " << in << " = " << r <<  dendl;
5302   return r;
5303 }
5304
5305 int Client::may_lookup(Inode *dir, const UserPerm& perms)
5306 {
5307   ldout(cct, 20) << __func__ << " " << *dir << "; " << perms << dendl;
5308   int r = _getattr_for_perm(dir, perms);
5309   if (r < 0)
5310     goto out;
5311
5312   r = inode_permission(dir, perms, MAY_EXEC);
5313 out:
5314   ldout(cct, 3) << __func__ << " " << dir << " = " << r <<  dendl;
5315   return r;
5316 }
5317
5318 int Client::may_create(Inode *dir, const UserPerm& perms)
5319 {
5320   ldout(cct, 20) << __func__ << " " << *dir << "; " << perms << dendl;
5321   int r = _getattr_for_perm(dir, perms);
5322   if (r < 0)
5323     goto out;
5324
5325   r = inode_permission(dir, perms, MAY_EXEC | MAY_WRITE);
5326 out:
5327   ldout(cct, 3) << __func__ << " " << dir << " = " << r <<  dendl;
5328   return r;
5329 }
5330
5331 int Client::may_delete(Inode *dir, const char *name, const UserPerm& perms)
5332 {
5333   ldout(cct, 20) << __func__ << " " << *dir << "; " << "; name " << name << "; " << perms << dendl;
5334   int r = _getattr_for_perm(dir, perms);
5335   if (r < 0)
5336     goto out;
5337
5338   r = inode_permission(dir, perms, MAY_EXEC | MAY_WRITE);
5339   if (r < 0)
5340     goto out;
5341
5342   /* 'name == NULL' means rmsnap */
5343   if (perms.uid() != 0 && name && (dir->mode & S_ISVTX)) {
5344     InodeRef otherin;
5345     r = _lookup(dir, name, CEPH_CAP_AUTH_SHARED, &otherin, perms);
5346     if (r < 0)
5347       goto out;
5348     if (dir->uid != perms.uid() && otherin->uid != perms.uid())
5349       r = -EPERM;
5350   }
5351 out:
5352   ldout(cct, 3) << __func__ << " " << dir << " = " << r <<  dendl;
5353   return r;
5354 }
5355
5356 int Client::may_hardlink(Inode *in, const UserPerm& perms)
5357 {
5358   ldout(cct, 20) << __func__ << " " << *in << "; " << perms << dendl;
5359   int r = _getattr_for_perm(in, perms);
5360   if (r < 0)
5361     goto out;
5362
5363   if (perms.uid() == 0 || perms.uid() == in->uid) {
5364     r = 0;
5365     goto out;
5366   }
5367
5368   r = -EPERM;
5369   if (!S_ISREG(in->mode))
5370     goto out;
5371
5372   if (in->mode & S_ISUID)
5373     goto out;
5374
5375   if ((in->mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))
5376     goto out;
5377
5378   r = inode_permission(in, perms, MAY_READ | MAY_WRITE);
5379 out:
5380   ldout(cct, 3) << __func__ << " " << in << " = " << r <<  dendl;
5381   return r;
5382 }
5383
5384 int Client::_getattr_for_perm(Inode *in, const UserPerm& perms)
5385 {
5386   int mask = CEPH_STAT_CAP_MODE;
5387   bool force = false;
5388   if (acl_type != NO_ACL) {
5389     mask |= CEPH_STAT_CAP_XATTR;
5390     force = in->xattr_version == 0;
5391   }
5392   return _getattr(in, mask, perms, force);
5393 }
5394
5395 vinodeno_t Client::_get_vino(Inode *in)
5396 {
5397   /* The caller must hold the client lock */
5398   return vinodeno_t(in->ino, in->snapid);
5399 }
5400
5401 inodeno_t Client::_get_inodeno(Inode *in)
5402 {
5403   /* The caller must hold the client lock */
5404   return in->ino;
5405 }
5406
5407
5408 /**
5409  * Resolve an MDS spec to a list of MDS daemon GIDs.
5410  *
5411  * The spec is a string representing a GID, rank, filesystem:rank, or name/id.
5412  * It may be '*' in which case it matches all GIDs.
5413  *
5414  * If no error is returned, the `targets` vector will be populated with at least
5415  * one MDS.
5416  */
5417 int Client::resolve_mds(
5418     const std::string &mds_spec,
5419     std::vector<mds_gid_t> *targets)
5420 {
5421   assert(fsmap);
5422   assert(targets != nullptr);
5423
5424   mds_role_t role;
5425   std::stringstream ss;
5426   int role_r = fsmap->parse_role(mds_spec, &role, ss);
5427   if (role_r == 0) {
5428     // We got a role, resolve it to a GID
5429     ldout(cct, 10) << __func__ << ": resolved '" << mds_spec << "' to role '"
5430       << role << "'" << dendl;
5431     targets->push_back(
5432         fsmap->get_filesystem(role.fscid)->mds_map.get_info(role.rank).global_id);
5433     return 0;
5434   }
5435
5436   std::string strtol_err;
5437   long long rank_or_gid = strict_strtoll(mds_spec.c_str(), 10, &strtol_err);
5438   if (strtol_err.empty()) {
5439     // It is a possible GID
5440     const mds_gid_t mds_gid = mds_gid_t(rank_or_gid);
5441     if (fsmap->gid_exists(mds_gid)) {
5442       ldout(cct, 10) << __func__ << ": validated GID " << mds_gid << dendl;
5443       targets->push_back(mds_gid);
5444     } else {
5445       lderr(cct) << __func__ << ": GID " << mds_gid << " not in MDS map"
5446                  << dendl;
5447       return -ENOENT;
5448     }
5449   } else if (mds_spec == "*") {
5450     // It is a wildcard: use all MDSs
5451     const auto mds_info = fsmap->get_mds_info();
5452
5453     if (mds_info.empty()) {
5454       lderr(cct) << __func__ << ": * passed but no MDS daemons found" << dendl;
5455       return -ENOENT;
5456     }
5457
5458     for (const auto i : mds_info) {
5459       targets->push_back(i.first);
5460     }
5461   } else {
5462     // It did not parse as an integer, it is not a wildcard, it must be a name
5463     const mds_gid_t mds_gid = fsmap->find_mds_gid_by_name(mds_spec);
5464     if (mds_gid == 0) {
5465       lderr(cct) << "MDS ID '" << mds_spec << "' not found" << dendl;
5466
5467       lderr(cct) << "FSMap: " << *fsmap << dendl;
5468
5469       return -ENOENT;
5470     } else {
5471       ldout(cct, 10) << __func__ << ": resolved ID '" << mds_spec
5472                      << "' to GID " << mds_gid << dendl;
5473       targets->push_back(mds_gid);
5474     }
5475   }
5476
5477   return 0;
5478 }
5479
5480
5481 /**
5482  * Authenticate with mon and establish global ID
5483  */
5484 int Client::authenticate()
5485 {
5486   assert(client_lock.is_locked_by_me());
5487
5488   if (monclient->is_authenticated()) {
5489     return 0;
5490   }
5491
5492   client_lock.Unlock();
5493   int r = monclient->authenticate(cct->_conf->client_mount_timeout);
5494   client_lock.Lock();
5495   if (r < 0) {
5496     return r;
5497   }
5498
5499   whoami = monclient->get_global_id();
5500   messenger->set_myname(entity_name_t::CLIENT(whoami.v));
5501
5502   return 0;
5503 }
5504
5505 int Client::fetch_fsmap(bool user)
5506 {
5507   int r;
5508   // Retrieve FSMap to enable looking up daemon addresses.  We need FSMap
5509   // rather than MDSMap because no one MDSMap contains all the daemons, and
5510   // a `tell` can address any daemon.
5511   version_t fsmap_latest;
5512   do {
5513     C_SaferCond cond;
5514     monclient->get_version("fsmap", &fsmap_latest, NULL, &cond);
5515     client_lock.Unlock();
5516     r = cond.wait();
5517     client_lock.Lock();
5518   } while (r == -EAGAIN);
5519
5520   if (r < 0) {
5521     lderr(cct) << "Failed to learn FSMap version: " << cpp_strerror(r) << dendl;
5522     return r;
5523   }
5524
5525   ldout(cct, 10) << __func__ << " learned FSMap version " << fsmap_latest << dendl;
5526
5527   if (user) {
5528     if (!fsmap_user || fsmap_user->get_epoch() < fsmap_latest) {
5529       monclient->sub_want("fsmap.user", fsmap_latest, CEPH_SUBSCRIBE_ONETIME);
5530       monclient->renew_subs();
5531       wait_on_list(waiting_for_fsmap);
5532     }
5533     assert(fsmap_user);
5534     assert(fsmap_user->get_epoch() >= fsmap_latest);
5535   } else {
5536     if (!fsmap || fsmap->get_epoch() < fsmap_latest) {
5537       monclient->sub_want("fsmap", fsmap_latest, CEPH_SUBSCRIBE_ONETIME);
5538       monclient->renew_subs();
5539       wait_on_list(waiting_for_fsmap);
5540     }
5541     assert(fsmap);
5542     assert(fsmap->get_epoch() >= fsmap_latest);
5543   }
5544   ldout(cct, 10) << __func__ << " finished waiting for FSMap version "
5545                  << fsmap_latest << dendl;
5546   return 0;
5547 }
5548
5549 /**
5550  *
5551  * @mds_spec one of ID, rank, GID, "*"
5552  *
5553  */
5554 int Client::mds_command(
5555     const std::string &mds_spec,
5556     const vector<string>& cmd,
5557     const bufferlist& inbl,
5558     bufferlist *outbl,
5559     string *outs,
5560     Context *onfinish)
5561 {
5562   Mutex::Locker lock(client_lock);
5563
5564   if (!initialized)
5565     return -ENOTCONN;
5566
5567   int r;
5568   r = authenticate();
5569   if (r < 0) {
5570     return r;
5571   }
5572
5573   r = fetch_fsmap(false);
5574   if (r < 0) {
5575     return r;
5576   }
5577
5578   // Look up MDS target(s) of the command
5579   std::vector<mds_gid_t> targets;
5580   r = resolve_mds(mds_spec, &targets);
5581   if (r < 0) {
5582     return r;
5583   }
5584
5585   // If daemons are laggy, we won't send them commands.  If all
5586   // are laggy then we fail.
5587   std::vector<mds_gid_t> non_laggy;
5588   for (const auto gid : targets) {
5589     const auto info = fsmap->get_info_gid(gid);
5590     if (!info.laggy()) {
5591       non_laggy.push_back(gid);
5592     }
5593   }
5594   if (non_laggy.size() == 0) {
5595     *outs = "All targeted MDS daemons are laggy";
5596     return -ENOENT;
5597   }
5598
5599   if (metadata.empty()) {
5600     // We are called on an unmounted client, so metadata
5601     // won't be initialized yet.
5602     populate_metadata("");
5603   }
5604
5605   // Send commands to targets
5606   C_GatherBuilder gather(cct, onfinish);
5607   for (const auto target_gid : non_laggy) {
5608     const auto info = fsmap->get_info_gid(target_gid);
5609
5610     // Open a connection to the target MDS
5611     entity_inst_t inst = info.get_inst();
5612     ConnectionRef conn = messenger->get_connection(inst);
5613
5614     // Generate MDSCommandOp state
5615     auto &op = command_table.start_command();
5616
5617     op.on_finish = gather.new_sub();
5618     op.cmd = cmd;
5619     op.outbl = outbl;
5620     op.outs = outs;
5621     op.inbl = inbl;
5622     op.mds_gid = target_gid;
5623     op.con = conn;
5624
5625     ldout(cct, 4) << __func__ << ": new command op to " << target_gid
5626       << " tid=" << op.tid << cmd << dendl;
5627
5628     // Construct and send MCommand
5629     MCommand *m = op.get_message(monclient->get_fsid());
5630     conn->send_message(m);
5631   }
5632   gather.activate();
5633
5634   return 0;
5635 }
5636
5637 void Client::handle_command_reply(MCommandReply *m)
5638 {
5639   ceph_tid_t const tid = m->get_tid();
5640
5641   ldout(cct, 10) << __func__ << ": tid=" << m->get_tid() << dendl;
5642
5643   if (!command_table.exists(tid)) {
5644     ldout(cct, 1) << __func__ << ": unknown tid " << tid << ", dropping" << dendl;
5645     m->put();
5646     return;
5647   }
5648
5649   auto &op = command_table.get_command(tid);
5650   if (op.outbl) {
5651     op.outbl->claim(m->get_data());
5652   }
5653   if (op.outs) {
5654     *op.outs = m->rs;
5655   }
5656
5657   if (op.on_finish) {
5658     op.on_finish->complete(m->r);
5659   }
5660
5661   command_table.erase(tid);
5662
5663   m->put();
5664 }
5665
5666 // -------------------
5667 // MOUNT
5668
5669 int Client::mount(const std::string &mount_root, const UserPerm& perms,
5670                   bool require_mds)
5671 {
5672   Mutex::Locker lock(client_lock);
5673
5674   if (mounted) {
5675     ldout(cct, 5) << "already mounted" << dendl;
5676     return 0;
5677   }
5678
5679   int r = authenticate();
5680   if (r < 0) {
5681     lderr(cct) << "authentication failed: " << cpp_strerror(r) << dendl;
5682     return r;
5683   }
5684
5685   std::string want = "mdsmap";
5686   const auto &mds_ns = cct->_conf->client_mds_namespace;
5687   if (!mds_ns.empty()) {
5688     r = fetch_fsmap(true);
5689     if (r < 0)
5690       return r;
5691     fs_cluster_id_t cid = fsmap_user->get_fs_cid(mds_ns);
5692     if (cid == FS_CLUSTER_ID_NONE)
5693       return -ENOENT;
5694
5695     std::ostringstream oss;
5696     oss << want << "." << cid;
5697     want = oss.str();
5698   }
5699   ldout(cct, 10) << "Subscribing to map '" << want << "'" << dendl;
5700
5701   monclient->sub_want(want, 0, 0);
5702   monclient->renew_subs();
5703
5704   tick(); // start tick
5705   
5706   if (require_mds) {
5707     while (1) {
5708       auto availability = mdsmap->is_cluster_available();
5709       if (availability == MDSMap::STUCK_UNAVAILABLE) {
5710         // Error out
5711         ldout(cct, 10) << "mds cluster unavailable: epoch=" << mdsmap->get_epoch() << dendl;
5712         return CEPH_FUSE_NO_MDS_UP;
5713       } else if (availability == MDSMap::AVAILABLE) {
5714         // Continue to mount
5715         break;
5716       } else if (availability == MDSMap::TRANSIENT_UNAVAILABLE) {
5717         // Else, wait.  MDSMonitor will update the map to bring
5718         // us to a conclusion eventually.
5719         wait_on_list(waiting_for_mdsmap);
5720       } else {
5721         // Unexpected value!
5722         ceph_abort();
5723       }
5724     }
5725   }
5726
5727   populate_metadata(mount_root.empty() ? "/" : mount_root);
5728
5729   filepath fp(CEPH_INO_ROOT);
5730   if (!mount_root.empty()) {
5731     fp = filepath(mount_root.c_str());
5732   }
5733   while (true) {
5734     MetaRequest *req = new MetaRequest(CEPH_MDS_OP_GETATTR);
5735     req->set_filepath(fp);
5736     req->head.args.getattr.mask = CEPH_STAT_CAP_INODE_ALL;
5737     int res = make_request(req, perms);
5738     if (res < 0) {
5739       if (res == -EACCES && root) {
5740         ldout(cct, 1) << __func__ << " EACCES on parent of mount point; quotas may not work" << dendl;
5741         break;
5742       }
5743       return res;
5744     }
5745
5746     if (fp.depth())
5747       fp.pop_dentry();
5748     else
5749       break;
5750   }
5751
5752   assert(root);
5753   _ll_get(root);
5754
5755   mounted = true;
5756
5757   // trace?
5758   if (!cct->_conf->client_trace.empty()) {
5759     traceout.open(cct->_conf->client_trace.c_str());
5760     if (traceout.is_open()) {
5761       ldout(cct, 1) << "opened trace file '" << cct->_conf->client_trace << "'" << dendl;
5762     } else {
5763       ldout(cct, 1) << "FAILED to open trace file '" << cct->_conf->client_trace << "'" << dendl;
5764     }
5765   }
5766
5767   /*
5768   ldout(cct, 3) << "op: // client trace data structs" << dendl;
5769   ldout(cct, 3) << "op: struct stat st;" << dendl;
5770   ldout(cct, 3) << "op: struct utimbuf utim;" << dendl;
5771   ldout(cct, 3) << "op: int readlinkbuf_len = 1000;" << dendl;
5772   ldout(cct, 3) << "op: char readlinkbuf[readlinkbuf_len];" << dendl;
5773   ldout(cct, 3) << "op: map<string, inode_t*> dir_contents;" << dendl;
5774   ldout(cct, 3) << "op: map<int, int> open_files;" << dendl;
5775   ldout(cct, 3) << "op: int fd;" << dendl;
5776   */
5777   return 0;
5778 }
5779
5780 // UNMOUNT
5781
5782 void Client::_close_sessions()
5783 {
5784   while (!mds_sessions.empty()) {
5785     // send session closes!
5786     for (map<mds_rank_t,MetaSession*>::iterator p = mds_sessions.begin();
5787         p != mds_sessions.end();
5788         ++p) {
5789       if (p->second->state != MetaSession::STATE_CLOSING) {
5790         _close_mds_session(p->second);
5791       }
5792     }
5793
5794     // wait for sessions to close
5795     ldout(cct, 2) << "waiting for " << mds_sessions.size() << " mds sessions to close" << dendl;
5796     mount_cond.Wait(client_lock);
5797   }
5798 }
5799
5800 void Client::flush_mdlog_sync()
5801 {
5802   if (mds_requests.empty()) 
5803     return;
5804   for (map<mds_rank_t,MetaSession*>::iterator p = mds_sessions.begin();
5805        p != mds_sessions.end();
5806        ++p) {
5807     MetaSession *s = p->second;
5808     flush_mdlog(s);
5809   }
5810 }
5811
5812 void Client::flush_mdlog(MetaSession *session)
5813 {
5814   // Only send this to Luminous or newer MDS daemons, older daemons
5815   // will crash if they see an unknown CEPH_SESSION_* value in this msg.
5816   const uint64_t features = session->con->get_features();
5817   if (HAVE_FEATURE(features, SERVER_LUMINOUS)) {
5818     MClientSession *m = new MClientSession(CEPH_SESSION_REQUEST_FLUSH_MDLOG);
5819     session->con->send_message(m);
5820   }
5821 }
5822
5823
5824 void Client::unmount()
5825 {
5826   Mutex::Locker lock(client_lock);
5827
5828   if (unmounting)
5829     return;
5830
5831   ldout(cct, 2) << "unmounting" << dendl;
5832   unmounting = true;
5833
5834   flush_mdlog_sync(); // flush the mdlog for pending requests, if any
5835   while (!mds_requests.empty()) {
5836     ldout(cct, 10) << "waiting on " << mds_requests.size() << " requests" << dendl;
5837     mount_cond.Wait(client_lock);
5838   }
5839
5840   if (tick_event)
5841     timer.cancel_event(tick_event);
5842   tick_event = 0;
5843
5844   cwd.reset();
5845
5846   // clean up any unclosed files
5847   while (!fd_map.empty()) {
5848     Fh *fh = fd_map.begin()->second;
5849     fd_map.erase(fd_map.begin());
5850     ldout(cct, 0) << " destroyed lost open file " << fh << " on " << *fh->inode << dendl;
5851     _release_fh(fh);
5852   }
5853   
5854   while (!ll_unclosed_fh_set.empty()) {
5855     set<Fh*>::iterator it = ll_unclosed_fh_set.begin();
5856     Fh *fh = *it;
5857     ll_unclosed_fh_set.erase(fh);
5858     ldout(cct, 0) << " destroyed lost open file " << fh << " on " << *(fh->inode) << dendl;
5859     _release_fh(fh);
5860   }
5861
5862   while (!opened_dirs.empty()) {
5863     dir_result_t *dirp = *opened_dirs.begin();
5864     ldout(cct, 0) << " destroyed lost open dir " << dirp << " on " << *dirp->inode << dendl;
5865     _closedir(dirp);
5866   }
5867
5868   _ll_drop_pins();
5869
5870   if (blacklisted) {
5871     ldout(cct, 0) << " skipping clean shutdown, we are blacklisted" << dendl;
5872
5873     if (cct->_conf->client_oc) {
5874       // Purge all cached data so that ObjectCacher doesn't get hung up
5875       // trying to flush it.  ObjectCacher's behaviour on EBLACKLISTED
5876       // is to just leave things marked dirty
5877       // (http://tracker.ceph.com/issues/9105)
5878       for (const auto &i : inode_map) {
5879         objectcacher->purge_set(&(i.second->oset));
5880       }
5881     }
5882
5883     mounted = false;
5884     return;
5885   }
5886
5887   while (unsafe_sync_write > 0) {
5888     ldout(cct, 0) << unsafe_sync_write << " unsafe_sync_writes, waiting"  << dendl;
5889     mount_cond.Wait(client_lock);
5890   }
5891
5892   if (cct->_conf->client_oc) {
5893     // flush/release all buffered data
5894     ceph::unordered_map<vinodeno_t, Inode*>::iterator next;
5895     for (ceph::unordered_map<vinodeno_t, Inode*>::iterator p = inode_map.begin();
5896          p != inode_map.end();
5897          p = next) {
5898       next = p;
5899       ++next;
5900       Inode *in = p->second;
5901       if (!in) {
5902         ldout(cct, 0) << "null inode_map entry ino " << p->first << dendl;
5903         assert(in);
5904       }
5905       if (!in->caps.empty()) {
5906         InodeRef tmp_ref(in);
5907         _release(in);
5908         _flush(in, new C_Client_FlushComplete(this, in));
5909       }
5910     }
5911   }
5912
5913   flush_caps_sync();
5914   wait_sync_caps(last_flush_tid);
5915
5916   // empty lru cache
5917   trim_cache();
5918
5919   while (lru.lru_get_size() > 0 ||
5920          !inode_map.empty()) {
5921     ldout(cct, 2) << "cache still has " << lru.lru_get_size()
5922             << "+" << inode_map.size() << " items"
5923             << ", waiting (for caps to release?)"
5924             << dendl;
5925     utime_t until = ceph_clock_now() + utime_t(5, 0);
5926     int r = mount_cond.WaitUntil(client_lock, until);
5927     if (r == ETIMEDOUT) {
5928       dump_cache(NULL);
5929     }
5930   }
5931   assert(lru.lru_get_size() == 0);
5932   assert(inode_map.empty());
5933
5934   // stop tracing
5935   if (!cct->_conf->client_trace.empty()) {
5936     ldout(cct, 1) << "closing trace file '" << cct->_conf->client_trace << "'" << dendl;
5937     traceout.close();
5938   }
5939
5940   _close_sessions();
5941
5942   mounted = false;
5943
5944   ldout(cct, 2) << "unmounted." << dendl;
5945 }
5946
5947 void Client::flush_cap_releases()
5948 {
5949   // send any cap releases
5950   for (map<mds_rank_t,MetaSession*>::iterator p = mds_sessions.begin();
5951        p != mds_sessions.end();
5952        ++p) {
5953     if (p->second->release && mdsmap->is_clientreplay_or_active_or_stopping(
5954           p->first)) {
5955       if (cct->_conf->client_inject_release_failure) {
5956         ldout(cct, 20) << __func__ << " injecting failure to send cap release message" << dendl;
5957         p->second->release->put();
5958       } else {
5959         p->second->con->send_message(p->second->release);
5960       }
5961       p->second->release = 0;
5962     }
5963   }
5964 }
5965
5966 void Client::tick()
5967 {
5968   if (cct->_conf->client_debug_inject_tick_delay > 0) {
5969     sleep(cct->_conf->client_debug_inject_tick_delay);
5970     assert(0 == cct->_conf->set_val("client_debug_inject_tick_delay", "0"));
5971     cct->_conf->apply_changes(NULL);
5972   }
5973
5974   ldout(cct, 21) << "tick" << dendl;
5975   tick_event = timer.add_event_after(
5976     cct->_conf->client_tick_interval,
5977     new FunctionContext([this](int) {
5978         // Called back via Timer, which takes client_lock for us
5979         assert(client_lock.is_locked_by_me());
5980         tick();
5981       }));
5982   utime_t now = ceph_clock_now();
5983
5984   if (!mounted && !mds_requests.empty()) {
5985     MetaRequest *req = mds_requests.begin()->second;
5986     if (req->op_stamp + cct->_conf->client_mount_timeout < now) {
5987       req->abort(-ETIMEDOUT);
5988       if (req->caller_cond) {
5989         req->kick = true;
5990         req->caller_cond->Signal();
5991       }
5992       signal_cond_list(waiting_for_mdsmap);
5993       for (map<mds_rank_t,MetaSession*>::iterator p = mds_sessions.begin();
5994            p != mds_sessions.end();
5995           ++p)
5996         signal_context_list(p->second->waiting_for_open);
5997     }
5998   }
5999
6000   if (mdsmap->get_epoch()) {
6001     // renew caps?
6002     utime_t el = now - last_cap_renew;
6003     if (el > mdsmap->get_session_timeout() / 3.0)
6004       renew_caps();
6005
6006     flush_cap_releases();
6007   }
6008
6009   // delayed caps
6010   xlist<Inode*>::iterator p = delayed_caps.begin();
6011   while (!p.end()) {
6012     Inode *in = *p;
6013     ++p;
6014     if (in->hold_caps_until > now)
6015       break;
6016     delayed_caps.pop_front();
6017     cap_list.push_back(&in->cap_item);
6018     check_caps(in, CHECK_CAPS_NODELAY);
6019   }
6020
6021   trim_cache(true);
6022 }
6023
6024 void Client::renew_caps()
6025 {
6026   ldout(cct, 10) << "renew_caps()" << dendl;
6027   last_cap_renew = ceph_clock_now();
6028
6029   for (map<mds_rank_t,MetaSession*>::iterator p = mds_sessions.begin();
6030        p != mds_sessions.end();
6031        ++p) {
6032     ldout(cct, 15) << "renew_caps requesting from mds." << p->first << dendl;
6033     if (mdsmap->get_state(p->first) >= MDSMap::STATE_REJOIN)
6034       renew_caps(p->second);
6035   }
6036 }
6037
6038 void Client::renew_caps(MetaSession *session)
6039 {
6040   ldout(cct, 10) << "renew_caps mds." << session->mds_num << dendl;
6041   session->last_cap_renew_request = ceph_clock_now();
6042   uint64_t seq = ++session->cap_renew_seq;
6043   session->con->send_message(new MClientSession(CEPH_SESSION_REQUEST_RENEWCAPS, seq));
6044 }
6045
6046
6047 // ===============================================================
6048 // high level (POSIXy) interface
6049
6050 int Client::_do_lookup(Inode *dir, const string& name, int mask,
6051                        InodeRef *target, const UserPerm& perms)
6052 {
6053   int op = dir->snapid == CEPH_SNAPDIR ? CEPH_MDS_OP_LOOKUPSNAP : CEPH_MDS_OP_LOOKUP;
6054   MetaRequest *req = new MetaRequest(op);
6055   filepath path;
6056   dir->make_nosnap_relative_path(path);
6057   path.push_dentry(name);
6058   req->set_filepath(path);
6059   req->set_inode(dir);
6060   if (cct->_conf->client_debug_getattr_caps && op == CEPH_MDS_OP_LOOKUP)
6061       mask |= DEBUG_GETATTR_CAPS;
6062   req->head.args.getattr.mask = mask;
6063
6064   ldout(cct, 10) << "_do_lookup on " << path << dendl;
6065
6066   int r = make_request(req, perms, target);
6067   ldout(cct, 10) << "_do_lookup res is " << r << dendl;
6068   return r;
6069 }
6070
6071 int Client::_lookup(Inode *dir, const string& dname, int mask, InodeRef *target,
6072                     const UserPerm& perms)
6073 {
6074   int r = 0;
6075   Dentry *dn = NULL;
6076
6077   if (!dir->is_dir()) {
6078     r = -ENOTDIR;
6079     goto done;
6080   }
6081
6082   if (dname == "..") {
6083     if (dir->dn_set.empty())
6084       *target = dir;
6085     else
6086       *target = dir->get_first_parent()->dir->parent_inode; //dirs can't be hard-linked
6087     goto done;
6088   }
6089
6090   if (dname == ".") {
6091     *target = dir;
6092     goto done;
6093   }
6094
6095   if (dname.length() > NAME_MAX) {
6096     r = -ENAMETOOLONG;
6097     goto done;
6098   }
6099
6100   if (dname == cct->_conf->client_snapdir &&
6101       dir->snapid == CEPH_NOSNAP) {
6102     *target = open_snapdir(dir);
6103     goto done;
6104   }
6105
6106   if (dir->dir &&
6107       dir->dir->dentries.count(dname)) {
6108     dn = dir->dir->dentries[dname];
6109
6110     ldout(cct, 20) << "_lookup have dn " << dname << " mds." << dn->lease_mds << " ttl " << dn->lease_ttl
6111              << " seq " << dn->lease_seq
6112              << dendl;
6113
6114     if (!dn->inode || dn->inode->caps_issued_mask(mask)) {
6115       // is dn lease valid?
6116       utime_t now = ceph_clock_now();
6117       if (dn->lease_mds >= 0 &&
6118           dn->lease_ttl > now &&
6119           mds_sessions.count(dn->lease_mds)) {
6120         MetaSession *s = mds_sessions[dn->lease_mds];
6121         if (s->cap_ttl > now &&
6122             s->cap_gen == dn->lease_gen) {
6123           // touch this mds's dir cap too, even though we don't _explicitly_ use it here, to
6124           // make trim_caps() behave.
6125           dir->try_touch_cap(dn->lease_mds);
6126           goto hit_dn;
6127         }
6128         ldout(cct, 20) << " bad lease, cap_ttl " << s->cap_ttl << ", cap_gen " << s->cap_gen
6129                        << " vs lease_gen " << dn->lease_gen << dendl;
6130       }
6131       // dir lease?
6132       if (dir->caps_issued_mask(CEPH_CAP_FILE_SHARED)) {
6133         if (dn->cap_shared_gen == dir->shared_gen &&
6134             (!dn->inode || dn->inode->caps_issued_mask(mask)))
6135               goto hit_dn;
6136         if (!dn->inode && (dir->flags & I_COMPLETE)) {
6137           ldout(cct, 10) << "_lookup concluded ENOENT locally for "
6138                          << *dir << " dn '" << dname << "'" << dendl;
6139           return -ENOENT;
6140         }
6141       }
6142     } else {
6143       ldout(cct, 20) << " no cap on " << dn->inode->vino() << dendl;
6144     }
6145   } else {
6146     // can we conclude ENOENT locally?
6147     if (dir->caps_issued_mask(CEPH_CAP_FILE_SHARED) &&
6148         (dir->flags & I_COMPLETE)) {
6149       ldout(cct, 10) << "_lookup concluded ENOENT locally for " << *dir << " dn '" << dname << "'" << dendl;
6150       return -ENOENT;
6151     }
6152   }
6153
6154   r = _do_lookup(dir, dname, mask, target, perms);
6155   goto done;
6156
6157  hit_dn:
6158   if (dn->inode) {
6159     *target = dn->inode;
6160   } else {
6161     r = -ENOENT;
6162   }
6163   touch_dn(dn);
6164
6165  done:
6166   if (r < 0)
6167     ldout(cct, 10) << "_lookup " << *dir << " " << dname << " = " << r << dendl;
6168   else
6169     ldout(cct, 10) << "_lookup " << *dir << " " << dname << " = " << **target << dendl;
6170   return r;
6171 }
6172
6173 int Client::get_or_create(Inode *dir, const char* name,
6174                           Dentry **pdn, bool expect_null)
6175 {
6176   // lookup
6177   ldout(cct, 20) << "get_or_create " << *dir << " name " << name << dendl;
6178   dir->open_dir();
6179   if (dir->dir->dentries.count(name)) {
6180     Dentry *dn = dir->dir->dentries[name];
6181     
6182     // is dn lease valid?
6183     utime_t now = ceph_clock_now();
6184     if (dn->inode &&
6185         dn->lease_mds >= 0 &&
6186         dn->lease_ttl > now &&
6187         mds_sessions.count(dn->lease_mds)) {
6188       MetaSession *s = mds_sessions[dn->lease_mds];
6189       if (s->cap_ttl > now &&
6190           s->cap_gen == dn->lease_gen) {
6191         if (expect_null)
6192           return -EEXIST;
6193       }
6194     }
6195     *pdn = dn;
6196   } else {
6197     // otherwise link up a new one
6198     *pdn = link(dir->dir, name, NULL, NULL);
6199   }
6200
6201   // success
6202   return 0;
6203 }
6204
6205 int Client::path_walk(const filepath& origpath, InodeRef *end,
6206                       const UserPerm& perms, bool followsym, int mask)
6207 {
6208   filepath path = origpath;
6209   InodeRef cur;
6210   if (origpath.absolute())
6211     cur = root;
6212   else
6213     cur = cwd;
6214   assert(cur);
6215
6216   ldout(cct, 10) << "path_walk " << path << dendl;
6217
6218   int symlinks = 0;
6219
6220   unsigned i=0;
6221   while (i < path.depth() && cur) {
6222     int caps = 0;
6223     const string &dname = path[i];
6224     ldout(cct, 10) << " " << i << " " << *cur << " " << dname << dendl;
6225     ldout(cct, 20) << "  (path is " << path << ")" << dendl;
6226     InodeRef next;
6227     if (cct->_conf->client_permissions) {
6228       int r = may_lookup(cur.get(), perms);
6229       if (r < 0)
6230         return r;
6231       caps = CEPH_CAP_AUTH_SHARED;
6232     }
6233
6234     /* Get extra requested caps on the last component */
6235     if (i == (path.depth() - 1))
6236       caps |= mask;
6237     int r = _lookup(cur.get(), dname, caps, &next, perms);
6238     if (r < 0)
6239       return r;
6240     // only follow trailing symlink if followsym.  always follow
6241     // 'directory' symlinks.
6242     if (next && next->is_symlink()) {
6243       symlinks++;
6244       ldout(cct, 20) << " symlink count " << symlinks << ", value is '" << next->symlink << "'" << dendl;
6245       if (symlinks > MAXSYMLINKS) {
6246         return -ELOOP;
6247       }
6248
6249       if (i < path.depth() - 1) {
6250         // dir symlink
6251         // replace consumed components of path with symlink dir target
6252         filepath resolved(next->symlink.c_str());
6253         resolved.append(path.postfixpath(i + 1));
6254         path = resolved;
6255         i = 0;
6256         if (next->symlink[0] == '/') {
6257           cur = root;
6258         }
6259         continue;
6260       } else if (followsym) {
6261         if (next->symlink[0] == '/') {
6262           path = next->symlink.c_str();
6263           i = 0;
6264           // reset position
6265           cur = root;
6266         } else {
6267           filepath more(next->symlink.c_str());
6268           // we need to remove the symlink component from off of the path
6269           // before adding the target that the symlink points to.  remain
6270           // at the same position in the path.
6271           path.pop_dentry();
6272           path.append(more);
6273         }
6274         continue;
6275       }
6276     }
6277     cur.swap(next);
6278     i++;
6279   }
6280   if (!cur)
6281     return -ENOENT;
6282   if (end)
6283     end->swap(cur);
6284   return 0;
6285 }
6286
6287
6288 // namespace ops
6289
6290 int Client::link(const char *relexisting, const char *relpath, const UserPerm& perm)
6291 {
6292   Mutex::Locker lock(client_lock);
6293   tout(cct) << "link" << std::endl;
6294   tout(cct) << relexisting << std::endl;
6295   tout(cct) << relpath << std::endl;
6296
6297   if (unmounting)
6298     return -ENOTCONN;
6299
6300   filepath existing(relexisting);
6301
6302   InodeRef in, dir;
6303   int r = path_walk(existing, &in, perm, true);
6304   if (r < 0)
6305     return r;
6306   if (std::string(relpath) == "/") {
6307     r = -EEXIST;
6308     return r;
6309   }
6310   filepath path(relpath);
6311   string name = path.last_dentry();
6312   path.pop_dentry();
6313
6314   r = path_walk(path, &dir, perm, true);
6315   if (r < 0)
6316     return r;
6317   if (cct->_conf->client_permissions) {
6318     if (S_ISDIR(in->mode)) {
6319       r = -EPERM;
6320       return r;
6321     }
6322     r = may_hardlink(in.get(), perm);
6323     if (r < 0)
6324       return r;
6325     r = may_create(dir.get(), perm);
6326     if (r < 0)
6327       return r;
6328   }
6329   r = _link(in.get(), dir.get(), name.c_str(), perm);
6330   return r;
6331 }
6332
6333 int Client::unlink(const char *relpath, const UserPerm& perm)
6334 {
6335   Mutex::Locker lock(client_lock);
6336   tout(cct) << "unlink" << std::endl;
6337   tout(cct) << relpath << std::endl;
6338
6339   if (unmounting)
6340     return -ENOTCONN;
6341
6342   if (std::string(relpath) == "/")
6343     return -EISDIR;
6344
6345   filepath path(relpath);
6346   string name = path.last_dentry();
6347   path.pop_dentry();
6348   InodeRef dir;
6349   int r = path_walk(path, &dir, perm);
6350   if (r < 0)
6351     return r;
6352   if (cct->_conf->client_permissions) {
6353     r = may_delete(dir.get(), name.c_str(), perm);
6354     if (r < 0)
6355       return r;
6356   }
6357   return _unlink(dir.get(), name.c_str(), perm);
6358 }
6359
6360 int Client::rename(const char *relfrom, const char *relto, const UserPerm& perm)
6361 {
6362   Mutex::Locker lock(client_lock);
6363   tout(cct) << "rename" << std::endl;
6364   tout(cct) << relfrom << std::endl;
6365   tout(cct) << relto << std::endl;
6366
6367   if (unmounting)
6368     return -ENOTCONN;
6369
6370   if (std::string(relfrom) == "/" || std::string(relto) == "/")
6371     return -EBUSY;
6372
6373   filepath from(relfrom);
6374   filepath to(relto);
6375   string fromname = from.last_dentry();
6376   from.pop_dentry();
6377   string toname = to.last_dentry();
6378   to.pop_dentry();
6379
6380   InodeRef fromdir, todir;
6381   int r = path_walk(from, &fromdir, perm);
6382   if (r < 0)
6383     goto out;
6384   r = path_walk(to, &todir, perm);
6385   if (r < 0)
6386     goto out;
6387
6388   if (cct->_conf->client_permissions) {
6389     int r = may_delete(fromdir.get(), fromname.c_str(), perm);
6390     if (r < 0)
6391       return r;
6392     r = may_delete(todir.get(), toname.c_str(), perm);
6393     if (r < 0 && r != -ENOENT)
6394       return r;
6395   }
6396   r = _rename(fromdir.get(), fromname.c_str(), todir.get(), toname.c_str(), perm);
6397 out:
6398   return r;
6399 }
6400
6401 // dirs
6402
6403 int Client::mkdir(const char *relpath, mode_t mode, const UserPerm& perm)
6404 {
6405   Mutex::Locker lock(client_lock);
6406   tout(cct) << "mkdir" << std::endl;
6407   tout(cct) << relpath << std::endl;
6408   tout(cct) << mode << std::endl;
6409   ldout(cct, 10) << "mkdir: " << relpath << dendl;
6410
6411   if (unmounting)
6412     return -ENOTCONN;
6413
6414   if (std::string(relpath) == "/")
6415     return -EEXIST;
6416
6417   filepath path(relpath);
6418   string name = path.last_dentry();
6419   path.pop_dentry();
6420   InodeRef dir;
6421   int r = path_walk(path, &dir, perm);
6422   if (r < 0)
6423     return r;
6424   if (cct->_conf->client_permissions) {
6425     r = may_create(dir.get(), perm);
6426     if (r < 0)
6427       return r;
6428   }
6429   return _mkdir(dir.get(), name.c_str(), mode, perm);
6430 }
6431
6432 int Client::mkdirs(const char *relpath, mode_t mode, const UserPerm& perms)
6433 {
6434   Mutex::Locker lock(client_lock);
6435   ldout(cct, 10) << "Client::mkdirs " << relpath << dendl;
6436   tout(cct) << "mkdirs" << std::endl;
6437   tout(cct) << relpath << std::endl;
6438   tout(cct) << mode << std::endl;
6439
6440   if (unmounting)
6441     return -ENOTCONN;
6442
6443   //get through existing parts of path
6444   filepath path(relpath);
6445   unsigned int i;
6446   int r = 0, caps = 0;
6447   InodeRef cur, next;
6448   cur = cwd;
6449   for (i=0; i<path.depth(); ++i) {
6450     if (cct->_conf->client_permissions) {
6451       r = may_lookup(cur.get(), perms);
6452       if (r < 0)
6453         break;
6454       caps = CEPH_CAP_AUTH_SHARED;
6455     }
6456     r = _lookup(cur.get(), path[i].c_str(), caps, &next, perms);
6457     if (r < 0)
6458       break;
6459     cur.swap(next);
6460   }
6461   //check that we have work left to do
6462   if (i==path.depth()) return -EEXIST;
6463   if (r!=-ENOENT) return r;
6464   ldout(cct, 20) << "mkdirs got through " << i << " directories on path " << relpath << dendl;
6465   //make new directory at each level
6466   for (; i<path.depth(); ++i) {
6467     if (cct->_conf->client_permissions) {
6468       r = may_create(cur.get(), perms);
6469       if (r < 0)
6470         return r;
6471     }
6472     //make new dir
6473     r = _mkdir(cur.get(), path[i].c_str(), mode, perms, &next);
6474     
6475     //check proper creation/existence
6476     if(-EEXIST == r && i < path.depth() - 1) {
6477       r = _lookup(cur.get(), path[i].c_str(), CEPH_CAP_AUTH_SHARED, &next, perms);
6478     }   
6479     if (r < 0) 
6480       return r;
6481     //move to new dir and continue
6482     cur.swap(next);
6483     ldout(cct, 20) << "mkdirs: successfully created directory "
6484                    << filepath(cur->ino).get_path() << dendl;
6485   }
6486   return 0;
6487 }
6488
6489 int Client::rmdir(const char *relpath, const UserPerm& perms)
6490 {
6491   Mutex::Locker lock(client_lock);
6492   tout(cct) << "rmdir" << std::endl;
6493   tout(cct) << relpath << std::endl;
6494
6495   if (unmounting)
6496     return -ENOTCONN;
6497
6498   if (std::string(relpath) == "/")
6499     return -EBUSY;
6500
6501   filepath path(relpath);
6502   string name = path.last_dentry();
6503   path.pop_dentry();
6504   InodeRef dir;
6505   int r = path_walk(path, &dir, perms);
6506   if (r < 0)
6507     return r;
6508   if (cct->_conf->client_permissions) {
6509     int r = may_delete(dir.get(), name.c_str(), perms);
6510     if (r < 0)
6511       return r;
6512   }
6513   return _rmdir(dir.get(), name.c_str(), perms);
6514 }
6515
6516 int Client::mknod(const char *relpath, mode_t mode, const UserPerm& perms, dev_t rdev) 
6517
6518   Mutex::Locker lock(client_lock);
6519   tout(cct) << "mknod" << std::endl;
6520   tout(cct) << relpath << std::endl;
6521   tout(cct) << mode << std::endl;
6522   tout(cct) << rdev << std::endl;
6523
6524   if (unmounting)
6525     return -ENOTCONN;
6526
6527   if (std::string(relpath) == "/")
6528     return -EEXIST;
6529
6530   filepath path(relpath);
6531   string name = path.last_dentry();
6532   path.pop_dentry();
6533   InodeRef dir;
6534   int r = path_walk(path, &dir, perms);
6535   if (r < 0)
6536     return r;
6537   if (cct->_conf->client_permissions) {
6538     int r = may_create(dir.get(), perms);
6539     if (r < 0)
6540       return r;
6541   }
6542   return _mknod(dir.get(), name.c_str(), mode, rdev, perms);
6543 }
6544
6545 // symlinks
6546   
6547 int Client::symlink(const char *target, const char *relpath, const UserPerm& perms)
6548 {
6549   Mutex::Locker lock(client_lock);
6550   tout(cct) << "symlink" << std::endl;
6551   tout(cct) << target << std::endl;
6552   tout(cct) << relpath << std::endl;
6553
6554   if (unmounting)
6555     return -ENOTCONN;
6556
6557   if (std::string(relpath) == "/")
6558     return -EEXIST;
6559
6560   filepath path(relpath);
6561   string name = path.last_dentry();
6562   path.pop_dentry();
6563   InodeRef dir;
6564   int r = path_walk(path, &dir, perms);
6565   if (r < 0)
6566     return r;
6567   if (cct->_conf->client_permissions) {
6568     int r = may_create(dir.get(), perms);
6569     if (r < 0)
6570       return r;
6571   }
6572   return _symlink(dir.get(), name.c_str(), target, perms);
6573 }
6574
6575 int Client::readlink(const char *relpath, char *buf, loff_t size, const UserPerm& perms)
6576 {
6577   Mutex::Locker lock(client_lock);
6578   tout(cct) << "readlink" << std::endl;
6579   tout(cct) << relpath << std::endl;
6580
6581   if (unmounting)
6582     return -ENOTCONN;
6583
6584   filepath path(relpath);
6585   InodeRef in;
6586   int r = path_walk(path, &in, perms, false);
6587   if (r < 0)
6588     return r;
6589
6590   return _readlink(in.get(), buf, size);
6591 }
6592
6593 int Client::_readlink(Inode *in, char *buf, size_t size)
6594 {
6595   if (!in->is_symlink())
6596     return -EINVAL;
6597
6598   // copy into buf (at most size bytes)
6599   int r = in->symlink.length();
6600   if (r > (int)size)
6601     r = size;
6602   memcpy(buf, in->symlink.c_str(), r);
6603   return r;
6604 }
6605
6606
6607 // inode stuff
6608
6609 int Client::_getattr(Inode *in, int mask, const UserPerm& perms, bool force)
6610 {
6611   bool yes = in->caps_issued_mask(mask);
6612
6613   ldout(cct, 10) << "_getattr mask " << ccap_string(mask) << " issued=" << yes << dendl;
6614   if (yes && !force)
6615     return 0;
6616
6617   MetaRequest *req = new MetaRequest(CEPH_MDS_OP_GETATTR);
6618   filepath path;
6619   in->make_nosnap_relative_path(path);
6620   req->set_filepath(path);
6621   req->set_inode(in);
6622   req->head.args.getattr.mask = mask;
6623   
6624   int res = make_request(req, perms);
6625   ldout(cct, 10) << "_getattr result=" << res << dendl;
6626   return res;
6627 }
6628
6629 int Client::_do_setattr(Inode *in, struct ceph_statx *stx, int mask,
6630                         const UserPerm& perms, InodeRef *inp)
6631 {
6632   int issued = in->caps_issued();
6633
6634   ldout(cct, 10) << "_setattr mask " << mask << " issued " <<
6635     ccap_string(issued) << dendl;
6636
6637   if (in->snapid != CEPH_NOSNAP) {
6638     return -EROFS;
6639   }
6640   if ((mask & CEPH_SETATTR_SIZE) &&
6641       (unsigned long)stx->stx_size > in->size &&
6642       is_quota_bytes_exceeded(in, (unsigned long)stx->stx_size - in->size,
6643                               perms)) {
6644     return -EDQUOT;
6645   }
6646
6647   // make the change locally?
6648   if ((in->cap_dirtier_uid >= 0 && perms.uid() != in->cap_dirtier_uid) ||
6649       (in->cap_dirtier_gid >= 0 && perms.gid() != in->cap_dirtier_gid)) {
6650     ldout(cct, 10) << __func__ << " caller " << perms.uid() << ":" << perms.gid()
6651                    << " != cap dirtier " << in->cap_dirtier_uid << ":"
6652                    << in->cap_dirtier_gid << ", forcing sync setattr"
6653                    << dendl;
6654     /*
6655      * This works because we implicitly flush the caps as part of the
6656      * request, so the cap update check will happen with the writeback
6657      * cap context, and then the setattr check will happen with the
6658      * caller's context.
6659      *
6660      * In reality this pattern is likely pretty rare (different users
6661      * setattr'ing the same file).  If that turns out not to be the
6662      * case later, we can build a more complex pipelined cap writeback
6663      * infrastructure...
6664      */
6665     if (!mask)
6666       mask |= CEPH_SETATTR_CTIME;
6667     goto force_request;
6668   }
6669
6670   if (!mask) {
6671     // caller just needs us to bump the ctime
6672     in->ctime = ceph_clock_now();
6673     in->cap_dirtier_uid = perms.uid();
6674     in->cap_dirtier_gid = perms.gid();
6675     if (issued & CEPH_CAP_AUTH_EXCL)
6676       mark_caps_dirty(in, CEPH_CAP_AUTH_EXCL);
6677     else if (issued & CEPH_CAP_FILE_EXCL)
6678       mark_caps_dirty(in, CEPH_CAP_FILE_EXCL);
6679     else if (issued & CEPH_CAP_XATTR_EXCL)
6680       mark_caps_dirty(in, CEPH_CAP_XATTR_EXCL);
6681     else
6682       mask |= CEPH_SETATTR_CTIME;
6683   }
6684
6685   if (in->caps_issued_mask(CEPH_CAP_AUTH_EXCL)) {
6686     bool kill_sguid = mask & (CEPH_SETATTR_SIZE|CEPH_SETATTR_KILL_SGUID);
6687
6688     mask &= ~CEPH_SETATTR_KILL_SGUID;
6689
6690     if (mask & CEPH_SETATTR_UID) {
6691       in->ctime = ceph_clock_now();
6692       in->cap_dirtier_uid = perms.uid();
6693       in->cap_dirtier_gid = perms.gid();
6694       in->uid = stx->stx_uid;
6695       mark_caps_dirty(in, CEPH_CAP_AUTH_EXCL);
6696       mask &= ~CEPH_SETATTR_UID;
6697       kill_sguid = true;
6698       ldout(cct,10) << "changing uid to " << stx->stx_uid << dendl;
6699     }
6700     if (mask & CEPH_SETATTR_GID) {
6701       in->ctime = ceph_clock_now();
6702       in->cap_dirtier_uid = perms.uid();
6703       in->cap_dirtier_gid = perms.gid();
6704       in->gid = stx->stx_gid;
6705       mark_caps_dirty(in, CEPH_CAP_AUTH_EXCL);
6706       mask &= ~CEPH_SETATTR_GID;
6707       kill_sguid = true;
6708       ldout(cct,10) << "changing gid to " << stx->stx_gid << dendl;
6709     }
6710
6711     if (mask & CEPH_SETATTR_MODE) {
6712       in->ctime = ceph_clock_now();
6713       in->cap_dirtier_uid = perms.uid();
6714       in->cap_dirtier_gid = perms.gid();
6715       in->mode = (in->mode & ~07777) | (stx->stx_mode & 07777);
6716       mark_caps_dirty(in, CEPH_CAP_AUTH_EXCL);
6717       mask &= ~CEPH_SETATTR_MODE;
6718       ldout(cct,10) << "changing mode to " << stx->stx_mode << dendl;
6719     } else if (kill_sguid && S_ISREG(in->mode) && (in->mode & (S_IXUSR|S_IXGRP|S_IXOTH))) {
6720       /* Must squash the any setuid/setgid bits with an ownership change */
6721       in->mode &= ~(S_ISUID|S_ISGID);
6722       mark_caps_dirty(in, CEPH_CAP_AUTH_EXCL);
6723     }
6724
6725     if (mask & CEPH_SETATTR_BTIME) {
6726       in->ctime = ceph_clock_now();
6727       in->cap_dirtier_uid = perms.uid();
6728       in->cap_dirtier_gid = perms.gid();
6729       in->btime = utime_t(stx->stx_btime);
6730       mark_caps_dirty(in, CEPH_CAP_AUTH_EXCL);
6731       mask &= ~CEPH_SETATTR_BTIME;
6732       ldout(cct,10) << "changing btime to " << in->btime << dendl;
6733     }
6734   } else if (mask & CEPH_SETATTR_SIZE) {
6735     /* If we don't have Ax, then we must ask the server to clear them on truncate */
6736     mask |= CEPH_SETATTR_KILL_SGUID;
6737   }
6738
6739   if (in->caps_issued_mask(CEPH_CAP_FILE_EXCL)) {
6740     if (mask & (CEPH_SETATTR_MTIME|CEPH_SETATTR_ATIME)) {
6741       if (mask & CEPH_SETATTR_MTIME)
6742         in->mtime = utime_t(stx->stx_mtime);
6743       if (mask & CEPH_SETATTR_ATIME)
6744         in->atime = utime_t(stx->stx_atime);
6745       in->ctime = ceph_clock_now();
6746       in->cap_dirtier_uid = perms.uid();
6747       in->cap_dirtier_gid = perms.gid();
6748       in->time_warp_seq++;
6749       mark_caps_dirty(in, CEPH_CAP_FILE_EXCL);
6750       mask &= ~(CEPH_SETATTR_MTIME|CEPH_SETATTR_ATIME);
6751     }
6752   }
6753   if (!mask) {
6754     in->change_attr++;
6755     return 0;
6756   }
6757
6758 force_request:
6759   MetaRequest *req = new MetaRequest(CEPH_MDS_OP_SETATTR);
6760
6761   filepath path;
6762
6763   in->make_nosnap_relative_path(path);
6764   req->set_filepath(path);
6765   req->set_inode(in);
6766
6767   if (mask & CEPH_SETATTR_KILL_SGUID) {
6768     req->inode_drop |= CEPH_CAP_AUTH_SHARED;
6769   }
6770   if (mask & CEPH_SETATTR_MODE) {
6771     req->head.args.setattr.mode = stx->stx_mode;
6772     req->inode_drop |= CEPH_CAP_AUTH_SHARED;
6773     ldout(cct,10) << "changing mode to " << stx->stx_mode << dendl;
6774   }
6775   if (mask & CEPH_SETATTR_UID) {
6776     req->head.args.setattr.uid = stx->stx_uid;
6777     req->inode_drop |= CEPH_CAP_AUTH_SHARED;
6778     ldout(cct,10) << "changing uid to " << stx->stx_uid << dendl;
6779   }
6780   if (mask & CEPH_SETATTR_GID) {
6781     req->head.args.setattr.gid = stx->stx_gid;
6782     req->inode_drop |= CEPH_CAP_AUTH_SHARED;
6783     ldout(cct,10) << "changing gid to " << stx->stx_gid << dendl;
6784   }
6785   if (mask & CEPH_SETATTR_BTIME) {
6786     req->head.args.setattr.btime = utime_t(stx->stx_btime);
6787     req->inode_drop |= CEPH_CAP_AUTH_SHARED;
6788   }
6789   if (mask & CEPH_SETATTR_MTIME) {
6790     req->head.args.setattr.mtime = utime_t(stx->stx_mtime);
6791     req->inode_drop |= CEPH_CAP_AUTH_SHARED | CEPH_CAP_FILE_RD |
6792       CEPH_CAP_FILE_WR;
6793   }
6794   if (mask & CEPH_SETATTR_ATIME) {
6795     req->head.args.setattr.atime = utime_t(stx->stx_atime);
6796     req->inode_drop |= CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_RD |
6797       CEPH_CAP_FILE_WR;
6798   }
6799   if (mask & CEPH_SETATTR_SIZE) {
6800     if ((unsigned long)stx->stx_size < mdsmap->get_max_filesize()) {
6801       req->head.args.setattr.size = stx->stx_size;
6802       ldout(cct,10) << "changing size to " << stx->stx_size << dendl;
6803     } else { //too big!
6804       put_request(req);
6805       ldout(cct,10) << "unable to set size to " << stx->stx_size << ". Too large!" << dendl;
6806       return -EFBIG;
6807     }
6808     req->inode_drop |= CEPH_CAP_AUTH_SHARED | CEPH_CAP_FILE_RD |
6809       CEPH_CAP_FILE_WR;
6810   }
6811   req->head.args.setattr.mask = mask;
6812
6813   req->regetattr_mask = mask;
6814
6815   int res = make_request(req, perms, inp);
6816   ldout(cct, 10) << "_setattr result=" << res << dendl;
6817   return res;
6818 }
6819
6820 /* Note that we only care about attrs that setattr cares about */
6821 void Client::stat_to_statx(struct stat *st, struct ceph_statx *stx)
6822 {
6823   stx->stx_size = st->st_size;
6824   stx->stx_mode = st->st_mode;
6825   stx->stx_uid = st->st_uid;
6826   stx->stx_gid = st->st_gid;
6827   stx->stx_mtime = st->st_mtim;
6828   stx->stx_atime = st->st_atim;
6829 }
6830
6831 int Client::__setattrx(Inode *in, struct ceph_statx *stx, int mask,
6832                        const UserPerm& perms, InodeRef *inp)
6833 {
6834   int ret = _do_setattr(in, stx, mask, perms, inp);
6835   if (ret < 0)
6836    return ret;
6837   if (mask & CEPH_SETATTR_MODE)
6838     ret = _posix_acl_chmod(in, stx->stx_mode, perms);
6839   return ret;
6840 }
6841
6842 int Client::_setattrx(InodeRef &in, struct ceph_statx *stx, int mask,
6843                       const UserPerm& perms)
6844 {
6845   mask &= (CEPH_SETATTR_MODE | CEPH_SETATTR_UID |
6846            CEPH_SETATTR_GID | CEPH_SETATTR_MTIME |
6847            CEPH_SETATTR_ATIME | CEPH_SETATTR_SIZE |
6848            CEPH_SETATTR_CTIME | CEPH_SETATTR_BTIME);
6849   if (cct->_conf->client_permissions) {
6850     int r = may_setattr(in.get(), stx, mask, perms);
6851     if (r < 0)
6852       return r;
6853   }
6854   return __setattrx(in.get(), stx, mask, perms);
6855 }
6856
6857 int Client::_setattr(InodeRef &in, struct stat *attr, int mask,
6858                      const UserPerm& perms)
6859 {
6860   struct ceph_statx stx;
6861
6862   stat_to_statx(attr, &stx);
6863   mask &= ~CEPH_SETATTR_BTIME;
6864
6865   if ((mask & CEPH_SETATTR_UID) && attr->st_uid == static_cast<uid_t>(-1)) {
6866     mask &= ~CEPH_SETATTR_UID;
6867   }
6868   if ((mask & CEPH_SETATTR_GID) && attr->st_gid == static_cast<uid_t>(-1)) {
6869     mask &= ~CEPH_SETATTR_GID;
6870   }
6871
6872   return _setattrx(in, &stx, mask, perms);
6873 }
6874
6875 int Client::setattr(const char *relpath, struct stat *attr, int mask,
6876                     const UserPerm& perms)
6877 {
6878   Mutex::Locker lock(client_lock);
6879   tout(cct) << "setattr" << std::endl;
6880   tout(cct) << relpath << std::endl;
6881   tout(cct) << mask  << std::endl;
6882
6883   if (unmounting)
6884     return -ENOTCONN;
6885
6886   filepath path(relpath);
6887   InodeRef in;
6888   int r = path_walk(path, &in, perms);
6889   if (r < 0)
6890     return r;
6891   return _setattr(in, attr, mask, perms);
6892 }
6893
6894 int Client::setattrx(const char *relpath, struct ceph_statx *stx, int mask,
6895                      const UserPerm& perms, int flags)
6896 {
6897   Mutex::Locker lock(client_lock);
6898   tout(cct) << "setattrx" << std::endl;
6899   tout(cct) << relpath << std::endl;
6900   tout(cct) << mask  << std::endl;
6901
6902   if (unmounting)
6903     return -ENOTCONN;
6904
6905   filepath path(relpath);
6906   InodeRef in;
6907   int r = path_walk(path, &in, perms, !(flags & AT_SYMLINK_NOFOLLOW));
6908   if (r < 0)
6909     return r;
6910   return _setattrx(in, stx, mask, perms);
6911 }
6912
6913 int Client::fsetattr(int fd, struct stat *attr, int mask, const UserPerm& perms)
6914 {
6915   Mutex::Locker lock(client_lock);
6916   tout(cct) << "fsetattr" << std::endl;
6917   tout(cct) << fd << std::endl;
6918   tout(cct) << mask  << std::endl;
6919
6920   if (unmounting)
6921     return -ENOTCONN;
6922
6923   Fh *f = get_filehandle(fd);
6924   if (!f)
6925     return -EBADF;
6926 #if defined(__linux__) && defined(O_PATH)
6927   if (f->flags & O_PATH)
6928     return -EBADF;
6929 #endif
6930   return _setattr(f->inode, attr, mask, perms);
6931 }
6932
6933 int Client::fsetattrx(int fd, struct ceph_statx *stx, int mask, const UserPerm& perms)
6934 {
6935   Mutex::Locker lock(client_lock);
6936   tout(cct) << "fsetattr" << std::endl;
6937   tout(cct) << fd << std::endl;
6938   tout(cct) << mask  << std::endl;
6939
6940   if (unmounting)
6941     return -ENOTCONN;
6942
6943   Fh *f = get_filehandle(fd);
6944   if (!f)
6945     return -EBADF;
6946 #if defined(__linux__) && defined(O_PATH)
6947   if (f->flags & O_PATH)
6948     return -EBADF;
6949 #endif
6950   return _setattrx(f->inode, stx, mask, perms);
6951 }
6952
6953 int Client::stat(const char *relpath, struct stat *stbuf, const UserPerm& perms,
6954                  frag_info_t *dirstat, int mask)
6955 {
6956   ldout(cct, 3) << "stat enter (relpath " << relpath << " mask " << mask << ")" << dendl;
6957   Mutex::Locker lock(client_lock);
6958   tout(cct) << "stat" << std::endl;
6959   tout(cct) << relpath << std::endl;
6960
6961   if (unmounting)
6962     return -ENOTCONN;
6963
6964   filepath path(relpath);
6965   InodeRef in;
6966   int r = path_walk(path, &in, perms, true, mask);
6967   if (r < 0)
6968     return r;
6969   r = _getattr(in, mask, perms);
6970   if (r < 0) {
6971     ldout(cct, 3) << "stat exit on error!" << dendl;
6972     return r;
6973   }
6974   fill_stat(in, stbuf, dirstat);
6975   ldout(cct, 3) << "stat exit (relpath " << relpath << " mask " << mask << ")" << dendl;
6976   return r;
6977 }
6978
6979 unsigned Client::statx_to_mask(unsigned int flags, unsigned int want)
6980 {
6981   unsigned mask = 0;
6982
6983   /* if NO_ATTR_SYNC is set, then we don't need any -- just use what's in cache */
6984   if (flags & AT_NO_ATTR_SYNC)
6985     goto out;
6986
6987   /* Always set PIN to distinguish from AT_NO_ATTR_SYNC case */
6988   mask |= CEPH_CAP_PIN;
6989   if (want & (CEPH_STATX_MODE|CEPH_STATX_UID|CEPH_STATX_GID|CEPH_STATX_BTIME|CEPH_STATX_CTIME|CEPH_STATX_VERSION))
6990     mask |= CEPH_CAP_AUTH_SHARED;
6991   if (want & (CEPH_STATX_NLINK|CEPH_STATX_CTIME|CEPH_STATX_VERSION))
6992     mask |= CEPH_CAP_LINK_SHARED;
6993   if (want & (CEPH_STATX_ATIME|CEPH_STATX_MTIME|CEPH_STATX_CTIME|CEPH_STATX_SIZE|CEPH_STATX_BLOCKS|CEPH_STATX_VERSION))
6994     mask |= CEPH_CAP_FILE_SHARED;
6995   if (want & (CEPH_STATX_VERSION|CEPH_STATX_CTIME))
6996     mask |= CEPH_CAP_XATTR_SHARED;
6997 out:
6998   return mask;
6999 }
7000
7001 int Client::statx(const char *relpath, struct ceph_statx *stx,
7002                   const UserPerm& perms,
7003                   unsigned int want, unsigned int flags)
7004 {
7005   ldout(cct, 3) << "statx enter (relpath " << relpath << " want " << want << ")" << dendl;
7006   Mutex::Locker lock(client_lock);
7007   tout(cct) << "statx" << std::endl;
7008   tout(cct) << relpath << std::endl;
7009
7010   if (unmounting)
7011     return -ENOTCONN;
7012
7013   filepath path(relpath);
7014   InodeRef in;
7015
7016   unsigned mask = statx_to_mask(flags, want);
7017
7018   int r = path_walk(path, &in, perms, !(flags & AT_SYMLINK_NOFOLLOW), mask);
7019   if (r < 0)
7020     return r;
7021
7022   r = _getattr(in, mask, perms);
7023   if (r < 0) {
7024     ldout(cct, 3) << "statx exit on error!" << dendl;
7025     return r;
7026   }
7027
7028   fill_statx(in, mask, stx);
7029   ldout(cct, 3) << "statx exit (relpath " << relpath << " mask " << stx->stx_mask << ")" << dendl;
7030   return r;
7031 }
7032
7033 int Client::lstat(const char *relpath, struct stat *stbuf,
7034                   const UserPerm& perms, frag_info_t *dirstat, int mask)
7035 {
7036   ldout(cct, 3) << "lstat enter (relpath " << relpath << " mask " << mask << ")" << dendl;
7037   Mutex::Locker lock(client_lock);
7038   tout(cct) << "lstat" << std::endl;
7039   tout(cct) << relpath << std::endl;
7040
7041   if (unmounting)
7042     return -ENOTCONN;
7043
7044   filepath path(relpath);
7045   InodeRef in;
7046   // don't follow symlinks
7047   int r = path_walk(path, &in, perms, false, mask);
7048   if (r < 0)
7049     return r;
7050   r = _getattr(in, mask, perms);
7051   if (r < 0) {
7052     ldout(cct, 3) << "lstat exit on error!" << dendl;
7053     return r;
7054   }
7055   fill_stat(in, stbuf, dirstat);
7056   ldout(cct, 3) << "lstat exit (relpath " << relpath << " mask " << mask << ")" << dendl;
7057   return r;
7058 }
7059
7060 int Client::fill_stat(Inode *in, struct stat *st, frag_info_t *dirstat, nest_info_t *rstat)
7061 {
7062   ldout(cct, 10) << "fill_stat on " << in->ino << " snap/dev" << in->snapid
7063            << " mode 0" << oct << in->mode << dec
7064            << " mtime " << in->mtime << " ctime " << in->ctime << dendl;
7065   memset(st, 0, sizeof(struct stat));
7066   if (use_faked_inos())
7067     st->st_ino = in->faked_ino;
7068   else
7069     st->st_ino = in->ino;
7070   st->st_dev = in->snapid;
7071   st->st_mode = in->mode;
7072   st->st_rdev = in->rdev;
7073   st->st_nlink = in->nlink;
7074   st->st_uid = in->uid;
7075   st->st_gid = in->gid;
7076   if (in->ctime > in->mtime) {
7077     stat_set_ctime_sec(st, in->ctime.sec());
7078     stat_set_ctime_nsec(st, in->ctime.nsec());
7079   } else {
7080     stat_set_ctime_sec(st, in->mtime.sec());
7081     stat_set_ctime_nsec(st, in->mtime.nsec());
7082   }
7083   stat_set_atime_sec(st, in->atime.sec());
7084   stat_set_atime_nsec(st, in->atime.nsec());
7085   stat_set_mtime_sec(st, in->mtime.sec());
7086   stat_set_mtime_nsec(st, in->mtime.nsec());
7087   if (in->is_dir()) {
7088     if (cct->_conf->client_dirsize_rbytes)
7089       st->st_size = in->rstat.rbytes;
7090     else
7091       st->st_size = in->dirstat.size();
7092     st->st_blocks = 1;
7093   } else {
7094     st->st_size = in->size;
7095     st->st_blocks = (in->size + 511) >> 9;
7096   }
7097   st->st_blksize = MAX(in->layout.stripe_unit, 4096);
7098
7099   if (dirstat)
7100     *dirstat = in->dirstat;
7101   if (rstat)
7102     *rstat = in->rstat;
7103
7104   return in->caps_issued();
7105 }
7106
7107 void Client::fill_statx(Inode *in, unsigned int mask, struct ceph_statx *stx)
7108 {
7109   ldout(cct, 10) << "fill_statx on " << in->ino << " snap/dev" << in->snapid
7110            << " mode 0" << oct << in->mode << dec
7111            << " mtime " << in->mtime << " ctime " << in->ctime << dendl;
7112   memset(stx, 0, sizeof(struct ceph_statx));
7113
7114   /*
7115    * If mask is 0, then the caller set AT_NO_ATTR_SYNC. Reset the mask
7116    * so that all bits are set.
7117    */
7118   if (!mask)
7119     mask = ~0;
7120
7121   /* These are always considered to be available */
7122   stx->stx_dev = in->snapid;
7123   stx->stx_blksize = MAX(in->layout.stripe_unit, 4096);
7124
7125   /* Type bits are always set, even when CEPH_STATX_MODE is not */
7126   stx->stx_mode = S_IFMT & in->mode;
7127   stx->stx_ino = use_faked_inos() ? in->faked_ino : (ino_t)in->ino;
7128   stx->stx_rdev = in->rdev;
7129   stx->stx_mask |= (CEPH_STATX_INO|CEPH_STATX_RDEV);
7130
7131   if (mask & CEPH_CAP_AUTH_SHARED) {
7132     stx->stx_uid = in->uid;
7133     stx->stx_gid = in->gid;
7134     stx->stx_mode = in->mode;
7135     in->btime.to_timespec(&stx->stx_btime);
7136     stx->stx_mask |= (CEPH_STATX_MODE|CEPH_STATX_UID|CEPH_STATX_GID|CEPH_STATX_BTIME);
7137   }
7138
7139   if (mask & CEPH_CAP_LINK_SHARED) {
7140     stx->stx_nlink = in->nlink;
7141     stx->stx_mask |= CEPH_STATX_NLINK;
7142   }
7143
7144   if (mask & CEPH_CAP_FILE_SHARED) {
7145
7146     in->atime.to_timespec(&stx->stx_atime);
7147     in->mtime.to_timespec(&stx->stx_mtime);
7148
7149     if (in->is_dir()) {
7150       if (cct->_conf->client_dirsize_rbytes)
7151         stx->stx_size = in->rstat.rbytes;
7152       else
7153         stx->stx_size = in->dirstat.size();
7154       stx->stx_blocks = 1;
7155     } else {
7156       stx->stx_size = in->size;
7157       stx->stx_blocks = (in->size + 511) >> 9;
7158     }
7159     stx->stx_mask |= (CEPH_STATX_ATIME|CEPH_STATX_MTIME|
7160                       CEPH_STATX_SIZE|CEPH_STATX_BLOCKS);
7161   }
7162
7163   /* Change time and change_attr both require all shared caps to view */
7164   if ((mask & CEPH_STAT_CAP_INODE_ALL) == CEPH_STAT_CAP_INODE_ALL) {
7165     stx->stx_version = in->change_attr;
7166     if (in->ctime > in->mtime)
7167       in->ctime.to_timespec(&stx->stx_ctime);
7168     else
7169       in->mtime.to_timespec(&stx->stx_ctime);
7170     stx->stx_mask |= (CEPH_STATX_CTIME|CEPH_STATX_VERSION);
7171   }
7172
7173 }
7174
7175 void Client::touch_dn(Dentry *dn)
7176 {
7177   lru.lru_touch(dn);
7178 }
7179
7180 int Client::chmod(const char *relpath, mode_t mode, const UserPerm& perms)
7181 {
7182   Mutex::Locker lock(client_lock);
7183   tout(cct) << "chmod" << std::endl;
7184   tout(cct) << relpath << std::endl;
7185   tout(cct) << mode << std::endl;
7186
7187   if (unmounting)
7188     return -ENOTCONN;
7189
7190   filepath path(relpath);
7191   InodeRef in;
7192   int r = path_walk(path, &in, perms);
7193   if (r < 0)
7194     return r;
7195   struct stat attr;
7196   attr.st_mode = mode;
7197   return _setattr(in, &attr, CEPH_SETATTR_MODE, perms);
7198 }
7199
7200 int Client::fchmod(int fd, mode_t mode, const UserPerm& perms)
7201 {
7202   Mutex::Locker lock(client_lock);
7203   tout(cct) << "fchmod" << std::endl;
7204   tout(cct) << fd << std::endl;
7205   tout(cct) << mode << std::endl;
7206
7207   if (unmounting)
7208     return -ENOTCONN;
7209
7210   Fh *f = get_filehandle(fd);
7211   if (!f)
7212     return -EBADF;
7213 #if defined(__linux__) && defined(O_PATH)
7214   if (f->flags & O_PATH)
7215     return -EBADF;
7216 #endif
7217   struct stat attr;
7218   attr.st_mode = mode;
7219   return _setattr(f->inode, &attr, CEPH_SETATTR_MODE, perms);
7220 }
7221
7222 int Client::lchmod(const char *relpath, mode_t mode, const UserPerm& perms)
7223 {
7224   Mutex::Locker lock(client_lock);
7225   tout(cct) << "lchmod" << std::endl;
7226   tout(cct) << relpath << std::endl;
7227   tout(cct) << mode << std::endl;
7228
7229   if (unmounting)
7230     return -ENOTCONN;
7231
7232   filepath path(relpath);
7233   InodeRef in;
7234   // don't follow symlinks
7235   int r = path_walk(path, &in, perms, false);
7236   if (r < 0)
7237     return r;
7238   struct stat attr;
7239   attr.st_mode = mode;
7240   return _setattr(in, &attr, CEPH_SETATTR_MODE, perms);
7241 }
7242
7243 int Client::chown(const char *relpath, uid_t new_uid, gid_t new_gid,
7244                   const UserPerm& perms)
7245 {
7246   Mutex::Locker lock(client_lock);
7247   tout(cct) << "chown" << std::endl;
7248   tout(cct) << relpath << std::endl;
7249   tout(cct) << new_uid << std::endl;
7250   tout(cct) << new_gid << std::endl;
7251
7252   if (unmounting)
7253     return -ENOTCONN;
7254
7255   filepath path(relpath);
7256   InodeRef in;
7257   int r = path_walk(path, &in, perms);
7258   if (r < 0)
7259     return r;
7260   struct stat attr;
7261   attr.st_uid = new_uid;
7262   attr.st_gid = new_gid;
7263   return _setattr(in, &attr, CEPH_SETATTR_UID|CEPH_SETATTR_GID, perms);
7264 }
7265
7266 int Client::fchown(int fd, uid_t new_uid, gid_t new_gid, const UserPerm& perms)
7267 {
7268   Mutex::Locker lock(client_lock);
7269   tout(cct) << "fchown" << std::endl;
7270   tout(cct) << fd << std::endl;
7271   tout(cct) << new_uid << std::endl;
7272   tout(cct) << new_gid << std::endl;
7273
7274   if (unmounting)
7275     return -ENOTCONN;
7276
7277   Fh *f = get_filehandle(fd);
7278   if (!f)
7279     return -EBADF;
7280 #if defined(__linux__) && defined(O_PATH)
7281   if (f->flags & O_PATH)
7282     return -EBADF;
7283 #endif
7284   struct stat attr;
7285   attr.st_uid = new_uid;
7286   attr.st_gid = new_gid;
7287   int mask = 0;
7288   if (new_uid != static_cast<uid_t>(-1)) mask |= CEPH_SETATTR_UID;
7289   if (new_gid != static_cast<gid_t>(-1)) mask |= CEPH_SETATTR_GID;
7290   return _setattr(f->inode, &attr, mask, perms);
7291 }
7292
7293 int Client::lchown(const char *relpath, uid_t new_uid, gid_t new_gid,
7294                    const UserPerm& perms)
7295 {
7296   Mutex::Locker lock(client_lock);
7297   tout(cct) << "lchown" << std::endl;
7298   tout(cct) << relpath << std::endl;
7299   tout(cct) << new_uid << std::endl;
7300   tout(cct) << new_gid << std::endl;
7301
7302   if (unmounting)
7303     return -ENOTCONN;
7304
7305   filepath path(relpath);
7306   InodeRef in;
7307   // don't follow symlinks
7308   int r = path_walk(path, &in, perms, false);
7309   if (r < 0)
7310     return r;
7311   struct stat attr;
7312   attr.st_uid = new_uid;
7313   attr.st_gid = new_gid;
7314   int mask = 0;
7315   if (new_uid != static_cast<uid_t>(-1)) mask |= CEPH_SETATTR_UID;
7316   if (new_gid != static_cast<gid_t>(-1)) mask |= CEPH_SETATTR_GID;
7317   return _setattr(in, &attr, mask, perms);
7318 }
7319
7320 int Client::utime(const char *relpath, struct utimbuf *buf,
7321                   const UserPerm& perms)
7322 {
7323   Mutex::Locker lock(client_lock);
7324   tout(cct) << "utime" << std::endl;
7325   tout(cct) << relpath << std::endl;
7326   tout(cct) << buf->modtime << std::endl;
7327   tout(cct) << buf->actime << std::endl;
7328
7329   if (unmounting)
7330     return -ENOTCONN;
7331
7332   filepath path(relpath);
7333   InodeRef in;
7334   int r = path_walk(path, &in, perms);
7335   if (r < 0)
7336     return r;
7337   struct stat attr;
7338   stat_set_mtime_sec(&attr, buf->modtime);
7339   stat_set_mtime_nsec(&attr, 0);
7340   stat_set_atime_sec(&attr, buf->actime);
7341   stat_set_atime_nsec(&attr, 0);
7342   return _setattr(in, &attr, CEPH_SETATTR_MTIME|CEPH_SETATTR_ATIME, perms);
7343 }
7344
7345 int Client::lutime(const char *relpath, struct utimbuf *buf,
7346                    const UserPerm& perms)
7347 {
7348   Mutex::Locker lock(client_lock);
7349   tout(cct) << "lutime" << std::endl;
7350   tout(cct) << relpath << std::endl;
7351   tout(cct) << buf->modtime << std::endl;
7352   tout(cct) << buf->actime << std::endl;
7353
7354   if (unmounting)
7355     return -ENOTCONN;
7356
7357   filepath path(relpath);
7358   InodeRef in;
7359   // don't follow symlinks
7360   int r = path_walk(path, &in, perms, false);
7361   if (r < 0)
7362     return r;
7363   struct stat attr;
7364   stat_set_mtime_sec(&attr, buf->modtime);
7365   stat_set_mtime_nsec(&attr, 0);
7366   stat_set_atime_sec(&attr, buf->actime);
7367   stat_set_atime_nsec(&attr, 0);
7368   return _setattr(in, &attr, CEPH_SETATTR_MTIME|CEPH_SETATTR_ATIME, perms);
7369 }
7370
7371 int Client::flock(int fd, int operation, uint64_t owner)
7372 {
7373   Mutex::Locker lock(client_lock);
7374   tout(cct) << "flock" << std::endl;
7375   tout(cct) << fd << std::endl;
7376   tout(cct) << operation << std::endl;
7377   tout(cct) << owner << std::endl;
7378
7379   if (unmounting)
7380     return -ENOTCONN;
7381
7382   Fh *f = get_filehandle(fd);
7383   if (!f)
7384     return -EBADF;
7385
7386   return _flock(f, operation, owner);
7387 }
7388
7389 int Client::opendir(const char *relpath, dir_result_t **dirpp, const UserPerm& perms)
7390 {
7391   Mutex::Locker lock(client_lock);
7392   tout(cct) << "opendir" << std::endl;
7393   tout(cct) << relpath << std::endl;
7394
7395   if (unmounting)
7396     return -ENOTCONN;
7397
7398   filepath path(relpath);
7399   InodeRef in;
7400   int r = path_walk(path, &in, perms, true);
7401   if (r < 0)
7402     return r;
7403   if (cct->_conf->client_permissions) {
7404     int r = may_open(in.get(), O_RDONLY, perms);
7405     if (r < 0)
7406       return r;
7407   }
7408   r = _opendir(in.get(), dirpp, perms);
7409   /* if ENOTDIR, dirpp will be an uninitialized point and it's very dangerous to access its value */
7410   if (r != -ENOTDIR)
7411       tout(cct) << (unsigned long)*dirpp << std::endl;
7412   return r;
7413 }
7414
7415 int Client::_opendir(Inode *in, dir_result_t **dirpp, const UserPerm& perms)
7416 {
7417   if (!in->is_dir())
7418     return -ENOTDIR;
7419   *dirpp = new dir_result_t(in, perms);
7420   opened_dirs.insert(*dirpp);
7421   ldout(cct, 3) << "_opendir(" << in->ino << ") = " << 0 << " (" << *dirpp << ")" << dendl;
7422   return 0;
7423 }
7424
7425
7426 int Client::closedir(dir_result_t *dir) 
7427 {
7428   Mutex::Locker lock(client_lock);
7429   tout(cct) << "closedir" << std::endl;
7430   tout(cct) << (unsigned long)dir << std::endl;
7431
7432   ldout(cct, 3) << "closedir(" << dir << ") = 0" << dendl;
7433   _closedir(dir);
7434   return 0;
7435 }
7436
7437 void Client::_closedir(dir_result_t *dirp)
7438 {
7439   ldout(cct, 10) << "_closedir(" << dirp << ")" << dendl;
7440   if (dirp->inode) {
7441     ldout(cct, 10) << "_closedir detaching inode " << dirp->inode << dendl;
7442     dirp->inode.reset();
7443   }
7444   _readdir_drop_dirp_buffer(dirp);
7445   opened_dirs.erase(dirp);
7446   delete dirp;
7447 }
7448
7449 void Client::rewinddir(dir_result_t *dirp)
7450 {
7451   Mutex::Locker lock(client_lock);
7452   ldout(cct, 3) << "rewinddir(" << dirp << ")" << dendl;
7453
7454   if (unmounting)
7455     return;
7456
7457   dir_result_t *d = static_cast<dir_result_t*>(dirp);
7458   _readdir_drop_dirp_buffer(d);
7459   d->reset();
7460 }
7461  
7462 loff_t Client::telldir(dir_result_t *dirp)
7463 {
7464   dir_result_t *d = static_cast<dir_result_t*>(dirp);
7465   ldout(cct, 3) << "telldir(" << dirp << ") = " << d->offset << dendl;
7466   return d->offset;
7467 }
7468
7469 void Client::seekdir(dir_result_t *dirp, loff_t offset)
7470 {
7471   Mutex::Locker lock(client_lock);
7472
7473   ldout(cct, 3) << "seekdir(" << dirp << ", " << offset << ")" << dendl;
7474
7475   if (unmounting)
7476     return;
7477
7478   if (offset == dirp->offset)
7479     return;
7480
7481   if (offset > dirp->offset)
7482     dirp->release_count = 0;   // bump if we do a forward seek
7483   else
7484     dirp->ordered_count = 0;   // disable filling readdir cache
7485
7486   if (dirp->hash_order()) {
7487     if (dirp->offset > offset) {
7488       _readdir_drop_dirp_buffer(dirp);
7489       dirp->reset();
7490     }
7491   } else {
7492     if (offset == 0 ||
7493         dirp->buffer_frag != frag_t(dir_result_t::fpos_high(offset)) ||
7494         dirp->offset_low() > dir_result_t::fpos_low(offset))  {
7495       _readdir_drop_dirp_buffer(dirp);
7496       dirp->reset();
7497     }
7498   }
7499
7500   dirp->offset = offset;
7501 }
7502
7503
7504 //struct dirent {
7505 //  ino_t          d_ino;       /* inode number */
7506 //  off_t          d_off;       /* offset to the next dirent */
7507 //  unsigned short d_reclen;    /* length of this record */
7508 //  unsigned char  d_type;      /* type of file */
7509 //  char           d_name[256]; /* filename */
7510 //};
7511 void Client::fill_dirent(struct dirent *de, const char *name, int type, uint64_t ino, loff_t next_off)
7512 {
7513   strncpy(de->d_name, name, 255);
7514   de->d_name[255] = '\0';
7515 #ifndef __CYGWIN__
7516   de->d_ino = ino;
7517 #if !defined(DARWIN) && !defined(__FreeBSD__)
7518   de->d_off = next_off;
7519 #endif
7520   de->d_reclen = 1;
7521   de->d_type = IFTODT(type);
7522   ldout(cct, 10) << "fill_dirent '" << de->d_name << "' -> " << inodeno_t(de->d_ino)
7523            << " type " << (int)de->d_type << " w/ next_off " << hex << next_off << dec << dendl;
7524 #endif
7525 }
7526
7527 void Client::_readdir_next_frag(dir_result_t *dirp)
7528 {
7529   frag_t fg = dirp->buffer_frag;
7530
7531   if (fg.is_rightmost()) {
7532     ldout(cct, 10) << "_readdir_next_frag advance from " << fg << " to END" << dendl;
7533     dirp->set_end();
7534     return;
7535   }
7536
7537   // advance
7538   fg = fg.next();
7539   ldout(cct, 10) << "_readdir_next_frag advance from " << dirp->buffer_frag << " to " << fg << dendl;
7540
7541   if (dirp->hash_order()) {
7542     // keep last_name
7543     int64_t new_offset = dir_result_t::make_fpos(fg.value(), 2, true);
7544     if (dirp->offset < new_offset) // don't decrease offset
7545       dirp->offset = new_offset;
7546   } else {
7547     dirp->last_name.clear();
7548     dirp->offset = dir_result_t::make_fpos(fg, 2, false);
7549     _readdir_rechoose_frag(dirp);
7550   }
7551 }
7552
7553 void Client::_readdir_rechoose_frag(dir_result_t *dirp)
7554 {
7555   assert(dirp->inode);
7556
7557   if (dirp->hash_order())
7558     return;
7559
7560   frag_t cur = frag_t(dirp->offset_high());
7561   frag_t fg = dirp->inode->dirfragtree[cur.value()];
7562   if (fg != cur) {
7563     ldout(cct, 10) << "_readdir_rechoose_frag frag " << cur << " maps to " << fg << dendl;
7564     dirp->offset = dir_result_t::make_fpos(fg, 2, false);
7565     dirp->last_name.clear();
7566     dirp->next_offset = 2;
7567   }
7568 }
7569
7570 void Client::_readdir_drop_dirp_buffer(dir_result_t *dirp)
7571 {
7572   ldout(cct, 10) << "_readdir_drop_dirp_buffer " << dirp << dendl;
7573   dirp->buffer.clear();
7574 }
7575
7576 int Client::_readdir_get_frag(dir_result_t *dirp)
7577 {
7578   assert(dirp);
7579   assert(dirp->inode);
7580
7581   // get the current frag.
7582   frag_t fg;
7583   if (dirp->hash_order())
7584     fg = dirp->inode->dirfragtree[dirp->offset_high()];
7585   else
7586     fg = frag_t(dirp->offset_high());
7587   
7588   ldout(cct, 10) << "_readdir_get_frag " << dirp << " on " << dirp->inode->ino << " fg " << fg
7589                  << " offset " << hex << dirp->offset << dec << dendl;
7590
7591   int op = CEPH_MDS_OP_READDIR;
7592   if (dirp->inode && dirp->inode->snapid == CEPH_SNAPDIR)
7593     op = CEPH_MDS_OP_LSSNAP;
7594
7595   InodeRef& diri = dirp->inode;
7596
7597   MetaRequest *req = new MetaRequest(op);
7598   filepath path;
7599   diri->make_nosnap_relative_path(path);
7600   req->set_filepath(path); 
7601   req->set_inode(diri.get());
7602   req->head.args.readdir.frag = fg;
7603   req->head.args.readdir.flags = CEPH_READDIR_REPLY_BITFLAGS;
7604   if (dirp->last_name.length()) {
7605     req->path2.set_path(dirp->last_name.c_str());
7606   } else if (dirp->hash_order()) {
7607     req->head.args.readdir.offset_hash = dirp->offset_high();
7608   }
7609   req->dirp = dirp;
7610   
7611   bufferlist dirbl;
7612   int res = make_request(req, dirp->perms, NULL, NULL, -1, &dirbl);
7613   
7614   if (res == -EAGAIN) {
7615     ldout(cct, 10) << "_readdir_get_frag got EAGAIN, retrying" << dendl;
7616     _readdir_rechoose_frag(dirp);
7617     return _readdir_get_frag(dirp);
7618   }
7619
7620   if (res == 0) {
7621     ldout(cct, 10) << "_readdir_get_frag " << dirp << " got frag " << dirp->buffer_frag
7622                    << " size " << dirp->buffer.size() << dendl;
7623   } else {
7624     ldout(cct, 10) << "_readdir_get_frag got error " << res << ", setting end flag" << dendl;
7625     dirp->set_end();
7626   }
7627
7628   return res;
7629 }
7630
7631 struct dentry_off_lt {
7632   bool operator()(const Dentry* dn, int64_t off) const {
7633     return dir_result_t::fpos_cmp(dn->offset, off) < 0;
7634   }
7635 };
7636
7637 int Client::_readdir_cache_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p,
7638                               int caps, bool getref)
7639 {
7640   assert(client_lock.is_locked());
7641   ldout(cct, 10) << "_readdir_cache_cb " << dirp << " on " << dirp->inode->ino
7642            << " last_name " << dirp->last_name << " offset " << hex << dirp->offset << dec
7643            << dendl;
7644   Dir *dir = dirp->inode->dir;
7645
7646   if (!dir) {
7647     ldout(cct, 10) << " dir is empty" << dendl;
7648     dirp->set_end();
7649     return 0;
7650   }
7651
7652   vector<Dentry*>::iterator pd = std::lower_bound(dir->readdir_cache.begin(),
7653                                                   dir->readdir_cache.end(),
7654                                                   dirp->offset, dentry_off_lt());
7655
7656   string dn_name;
7657   while (true) {
7658     if (!dirp->inode->is_complete_and_ordered())
7659       return -EAGAIN;
7660     if (pd == dir->readdir_cache.end())
7661       break;
7662     Dentry *dn = *pd;
7663     if (dn->inode == NULL) {
7664       ldout(cct, 15) << " skipping null '" << dn->name << "'" << dendl;
7665       ++pd;
7666       continue;
7667     }
7668     if (dn->cap_shared_gen != dir->parent_inode->shared_gen) {
7669       ldout(cct, 15) << " skipping mismatch shared gen '" << dn->name << "'" << dendl;
7670       ++pd;
7671       continue;
7672     }
7673
7674     int r = _getattr(dn->inode, caps, dirp->perms);
7675     if (r < 0)
7676       return r;
7677
7678     struct ceph_statx stx;
7679     struct dirent de;
7680     fill_statx(dn->inode, caps, &stx);
7681
7682     uint64_t next_off = dn->offset + 1;
7683     ++pd;
7684     if (pd == dir->readdir_cache.end())
7685       next_off = dir_result_t::END;
7686
7687     Inode *in = NULL;
7688     fill_dirent(&de, dn->name.c_str(), stx.stx_mode, stx.stx_ino, next_off);
7689     if (getref) {
7690       in = dn->inode.get();
7691       _ll_get(in);
7692     }
7693
7694     dn_name = dn->name; // fill in name while we have lock
7695
7696     client_lock.Unlock();
7697     r = cb(p, &de, &stx, next_off, in);  // _next_ offset
7698     client_lock.Lock();
7699     ldout(cct, 15) << " de " << de.d_name << " off " << hex << dn->offset << dec
7700                    << " = " << r << dendl;
7701     if (r < 0) {
7702       return r;
7703     }
7704
7705     dirp->offset = next_off;
7706     if (dirp->at_end())
7707       dirp->next_offset = 2;
7708     else
7709       dirp->next_offset = dirp->offset_low();
7710     dirp->last_name = dn_name; // we successfully returned this one; update!
7711     if (r > 0)
7712       return r;
7713   }
7714
7715   ldout(cct, 10) << "_readdir_cache_cb " << dirp << " on " << dirp->inode->ino << " at end" << dendl;
7716   dirp->set_end();
7717   return 0;
7718 }
7719
7720 int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p,
7721                          unsigned want, unsigned flags, bool getref)
7722 {
7723   int caps = statx_to_mask(flags, want);
7724
7725   Mutex::Locker lock(client_lock);
7726
7727   if (unmounting)
7728     return -ENOTCONN;
7729
7730   dir_result_t *dirp = static_cast<dir_result_t*>(d);
7731
7732   ldout(cct, 10) << "readdir_r_cb " << *dirp->inode << " offset " << hex << dirp->offset
7733                  << dec << " at_end=" << dirp->at_end()
7734                  << " hash_order=" << dirp->hash_order() << dendl;
7735
7736   struct dirent de;
7737   struct ceph_statx stx;
7738   memset(&de, 0, sizeof(de));
7739   memset(&stx, 0, sizeof(stx));
7740
7741   InodeRef& diri = dirp->inode;
7742
7743   if (dirp->at_end())
7744     return 0;
7745
7746   if (dirp->offset == 0) {
7747     ldout(cct, 15) << " including ." << dendl;
7748     assert(diri->dn_set.size() < 2); // can't have multiple hard-links to a dir
7749     uint64_t next_off = 1;
7750
7751     int r;
7752     r = _getattr(diri, caps, dirp->perms);
7753     if (r < 0)
7754       return r;
7755
7756     fill_statx(diri, caps, &stx);
7757     fill_dirent(&de, ".", S_IFDIR, stx.stx_ino, next_off);
7758
7759     Inode *inode = NULL;
7760     if (getref) {
7761       inode = diri.get();
7762       _ll_get(inode);
7763     }
7764
7765     client_lock.Unlock();
7766     r = cb(p, &de, &stx, next_off, inode);
7767     client_lock.Lock();
7768     if (r < 0)
7769       return r;
7770
7771     dirp->offset = next_off;
7772     if (r > 0)
7773       return r;
7774   }
7775   if (dirp->offset == 1) {
7776     ldout(cct, 15) << " including .." << dendl;
7777     uint64_t next_off = 2;
7778     InodeRef in;
7779     if (diri->dn_set.empty())
7780       in = diri;
7781     else
7782       in = diri->get_first_parent()->inode;
7783
7784     int r;
7785     r = _getattr(diri, caps, dirp->perms);
7786     if (r < 0)
7787       return r;
7788
7789     fill_statx(in, caps, &stx);
7790     fill_dirent(&de, "..", S_IFDIR, stx.stx_ino, next_off);
7791
7792     Inode *inode = NULL;
7793     if (getref) {
7794       inode = in.get();
7795       _ll_get(inode);
7796     }
7797
7798     client_lock.Unlock();
7799     r = cb(p, &de, &stx, next_off, inode);
7800     client_lock.Lock();
7801     if (r < 0)
7802       return r;
7803
7804     dirp->offset = next_off;
7805     if (r > 0)
7806       return r;
7807   }
7808
7809   // can we read from our cache?
7810   ldout(cct, 10) << "offset " << hex << dirp->offset << dec
7811            << " snapid " << dirp->inode->snapid << " (complete && ordered) "
7812            << dirp->inode->is_complete_and_ordered()
7813            << " issued " << ccap_string(dirp->inode->caps_issued())
7814            << dendl;
7815   if (dirp->inode->snapid != CEPH_SNAPDIR &&
7816       dirp->inode->is_complete_and_ordered() &&
7817       dirp->inode->caps_issued_mask(CEPH_CAP_FILE_SHARED)) {
7818     int err = _readdir_cache_cb(dirp, cb, p, caps, getref);
7819     if (err != -EAGAIN)
7820       return err;
7821   }
7822
7823   while (1) {
7824     if (dirp->at_end())
7825       return 0;
7826
7827     bool check_caps = true;
7828     if (!dirp->is_cached()) {
7829       int r = _readdir_get_frag(dirp);
7830       if (r)
7831         return r;
7832       // _readdir_get_frag () may updates dirp->offset if the replied dirfrag is
7833       // different than the requested one. (our dirfragtree was outdated)
7834       check_caps = false;
7835     }
7836     frag_t fg = dirp->buffer_frag;
7837
7838     ldout(cct, 10) << "frag " << fg << " buffer size " << dirp->buffer.size()
7839                    << " offset " << hex << dirp->offset << dendl;
7840
7841     for (auto it = std::lower_bound(dirp->buffer.begin(), dirp->buffer.end(),
7842                                     dirp->offset, dir_result_t::dentry_off_lt());
7843          it != dirp->buffer.end();
7844          ++it) {
7845       dir_result_t::dentry &entry = *it;
7846
7847       uint64_t next_off = entry.offset + 1;
7848
7849       int r;
7850       if (check_caps) {
7851         r = _getattr(entry.inode, caps, dirp->perms);
7852         if (r < 0)
7853           return r;
7854       }
7855
7856       fill_statx(entry.inode, caps, &stx);
7857       fill_dirent(&de, entry.name.c_str(), stx.stx_mode, stx.stx_ino, next_off);
7858
7859       Inode *inode = NULL;
7860       if (getref) {
7861         inode = entry.inode.get();
7862         _ll_get(inode);
7863       }
7864
7865       client_lock.Unlock();
7866       r = cb(p, &de, &stx, next_off, inode);  // _next_ offset
7867       client_lock.Lock();
7868
7869       ldout(cct, 15) << " de " << de.d_name << " off " << hex << next_off - 1 << dec
7870                      << " = " << r << dendl;
7871       if (r < 0)
7872         return r;
7873
7874       dirp->offset = next_off;
7875       if (r > 0)
7876         return r;
7877     }
7878
7879     if (dirp->next_offset > 2) {
7880       ldout(cct, 10) << " fetching next chunk of this frag" << dendl;
7881       _readdir_drop_dirp_buffer(dirp);
7882       continue;  // more!
7883     }
7884
7885     if (!fg.is_rightmost()) {
7886       // next frag!
7887       _readdir_next_frag(dirp);
7888       continue;
7889     }
7890
7891     if (diri->shared_gen == dirp->start_shared_gen &&
7892         diri->dir_release_count == dirp->release_count) {
7893       if (diri->dir_ordered_count == dirp->ordered_count) {
7894         ldout(cct, 10) << " marking (I_COMPLETE|I_DIR_ORDERED) on " << *diri << dendl;
7895         if (diri->dir) {
7896           assert(diri->dir->readdir_cache.size() >= dirp->cache_index);
7897           diri->dir->readdir_cache.resize(dirp->cache_index);
7898         }
7899         diri->flags |= I_COMPLETE | I_DIR_ORDERED;
7900       } else {
7901         ldout(cct, 10) << " marking I_COMPLETE on " << *diri << dendl;
7902         diri->flags |= I_COMPLETE;
7903       }
7904     }
7905
7906     dirp->set_end();
7907     return 0;
7908   }
7909   ceph_abort();
7910   return 0;
7911 }
7912
7913
7914 int Client::readdir_r(dir_result_t *d, struct dirent *de)
7915 {  
7916   return readdirplus_r(d, de, 0, 0, 0, NULL);
7917 }
7918
7919 /*
7920  * readdirplus_r
7921  *
7922  * returns
7923  *  1 if we got a dirent
7924  *  0 for end of directory
7925  * <0 on error
7926  */
7927
7928 struct single_readdir {
7929   struct dirent *de;
7930   struct ceph_statx *stx;
7931   Inode *inode;
7932   bool full;
7933 };
7934
7935 static int _readdir_single_dirent_cb(void *p, struct dirent *de,
7936                                      struct ceph_statx *stx, off_t off,
7937                                      Inode *in)
7938 {
7939   single_readdir *c = static_cast<single_readdir *>(p);
7940
7941   if (c->full)
7942     return -1;  // already filled this dirent
7943
7944   *c->de = *de;
7945   if (c->stx)
7946     *c->stx = *stx;
7947   c->inode = in;
7948   c->full = true;
7949   return 1;
7950 }
7951
7952 struct dirent *Client::readdir(dir_result_t *d)
7953 {
7954   int ret;
7955   static struct dirent de;
7956   single_readdir sr;
7957   sr.de = &de;
7958   sr.stx = NULL;
7959   sr.inode = NULL;
7960   sr.full = false;
7961
7962   // our callback fills the dirent and sets sr.full=true on first
7963   // call, and returns -1 the second time around.
7964   ret = readdir_r_cb(d, _readdir_single_dirent_cb, (void *)&sr);
7965   if (ret < -1) {
7966     errno = -ret;  // this sucks.
7967     return (dirent *) NULL;
7968   }
7969   if (sr.full) {
7970     return &de;
7971   }
7972   return (dirent *) NULL;
7973 }
7974
7975 int Client::readdirplus_r(dir_result_t *d, struct dirent *de,
7976                           struct ceph_statx *stx, unsigned want,
7977                           unsigned flags, Inode **out)
7978 {  
7979   single_readdir sr;
7980   sr.de = de;
7981   sr.stx = stx;
7982   sr.inode = NULL;
7983   sr.full = false;
7984
7985   // our callback fills the dirent and sets sr.full=true on first
7986   // call, and returns -1 the second time around.
7987   int r = readdir_r_cb(d, _readdir_single_dirent_cb, (void *)&sr, want, flags, out);
7988   if (r < -1)
7989     return r;
7990   if (out)
7991     *out = sr.inode;
7992   if (sr.full)
7993     return 1;
7994   return 0;
7995 }
7996
7997
7998 /* getdents */
7999 struct getdents_result {
8000   char *buf;
8001   int buflen;
8002   int pos;
8003   bool fullent;
8004 };
8005
8006 static int _readdir_getdent_cb(void *p, struct dirent *de,
8007                                struct ceph_statx *stx, off_t off, Inode *in)
8008 {
8009   struct getdents_result *c = static_cast<getdents_result *>(p);
8010
8011   int dlen;
8012   if (c->fullent)
8013     dlen = sizeof(*de);
8014   else
8015     dlen = strlen(de->d_name) + 1;
8016
8017   if (c->pos + dlen > c->buflen)
8018     return -1;  // doesn't fit
8019
8020   if (c->fullent) {
8021     memcpy(c->buf + c->pos, de, sizeof(*de));
8022   } else {
8023     memcpy(c->buf + c->pos, de->d_name, dlen);
8024   }
8025   c->pos += dlen;
8026   return 0;
8027 }
8028
8029 int Client::_getdents(dir_result_t *dir, char *buf, int buflen, bool fullent)
8030 {
8031   getdents_result gr;
8032   gr.buf = buf;
8033   gr.buflen = buflen;
8034   gr.fullent = fullent;
8035   gr.pos = 0;
8036
8037   int r = readdir_r_cb(dir, _readdir_getdent_cb, (void *)&gr);
8038
8039   if (r < 0) { // some error
8040     if (r == -1) { // buffer ran out of space
8041       if (gr.pos) { // but we got some entries already!
8042         return gr.pos;
8043       } // or we need a larger buffer
8044       return -ERANGE;
8045     } else { // actual error, return it
8046       return r;
8047     }
8048   }
8049   return gr.pos;
8050 }
8051
8052
8053 /* getdir */
8054 struct getdir_result {
8055   list<string> *contents;
8056   int num;
8057 };
8058
8059 static int _getdir_cb(void *p, struct dirent *de, struct ceph_statx *stx, off_t off, Inode *in)
8060 {
8061   getdir_result *r = static_cast<getdir_result *>(p);
8062
8063   r->contents->push_back(de->d_name);
8064   r->num++;
8065   return 0;
8066 }
8067
8068 int Client::getdir(const char *relpath, list<string>& contents,
8069                    const UserPerm& perms)
8070 {
8071   ldout(cct, 3) << "getdir(" << relpath << ")" << dendl;
8072   {
8073     Mutex::Locker lock(client_lock);
8074     tout(cct) << "getdir" << std::endl;
8075     tout(cct) << relpath << std::endl;
8076   }
8077
8078   dir_result_t *d;
8079   int r = opendir(relpath, &d, perms);
8080   if (r < 0)
8081     return r;
8082
8083   getdir_result gr;
8084   gr.contents = &contents;
8085   gr.num = 0;
8086   r = readdir_r_cb(d, _getdir_cb, (void *)&gr);
8087
8088   closedir(d);
8089
8090   if (r < 0)
8091     return r;
8092   return gr.num;
8093 }
8094
8095
8096 /****** file i/o **********/
8097 int Client::open(const char *relpath, int flags, const UserPerm& perms,
8098                  mode_t mode, int stripe_unit, int stripe_count,
8099                  int object_size, const char *data_pool)
8100 {
8101   ldout(cct, 3) << "open enter(" << relpath << ", " << ceph_flags_sys2wire(flags) << "," << mode << ")" << dendl;
8102   Mutex::Locker lock(client_lock);
8103   tout(cct) << "open" << std::endl;
8104   tout(cct) << relpath << std::endl;
8105   tout(cct) << ceph_flags_sys2wire(flags) << std::endl;
8106
8107   if (unmounting)
8108     return -ENOTCONN;
8109
8110   Fh *fh = NULL;
8111
8112 #if defined(__linux__) && defined(O_PATH)
8113   /* When the O_PATH is being specified, others flags than O_DIRECTORY
8114    * and O_NOFOLLOW are ignored. Please refer do_entry_open() function
8115    * in kernel (fs/open.c). */
8116   if (flags & O_PATH)
8117     flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH;
8118 #endif
8119
8120   filepath path(relpath);
8121   InodeRef in;
8122   bool created = false;
8123   /* O_CREATE with O_EXCL enforces O_NOFOLLOW. */
8124   bool followsym = !((flags & O_NOFOLLOW) || ((flags & O_CREAT) && (flags & O_EXCL)));
8125   int r = path_walk(path, &in, perms, followsym, ceph_caps_for_mode(mode));
8126
8127   if (r == 0 && (flags & O_CREAT) && (flags & O_EXCL))
8128     return -EEXIST;
8129
8130 #if defined(__linux__) && defined(O_PATH)
8131   if (r == 0 && in->is_symlink() && (flags & O_NOFOLLOW) && !(flags & O_PATH))
8132 #else
8133   if (r == 0 && in->is_symlink() && (flags & O_NOFOLLOW))
8134 #endif
8135     return -ELOOP;
8136
8137   if (r == -ENOENT && (flags & O_CREAT)) {
8138     filepath dirpath = path;
8139     string dname = dirpath.last_dentry();
8140     dirpath.pop_dentry();
8141     InodeRef dir;
8142     r = path_walk(dirpath, &dir, perms, true,
8143                   cct->_conf->client_permissions ? CEPH_CAP_AUTH_SHARED : 0);
8144     if (r < 0)
8145       goto out;
8146     if (cct->_conf->client_permissions) {
8147       r = may_create(dir.get(), perms);
8148       if (r < 0)
8149         goto out;
8150     }
8151     r = _create(dir.get(), dname.c_str(), flags, mode, &in, &fh, stripe_unit,
8152                 stripe_count, object_size, data_pool, &created, perms);
8153   }
8154   if (r < 0)
8155     goto out;
8156
8157   if (!created) {
8158     // posix says we can only check permissions of existing files
8159     if (cct->_conf->client_permissions) {
8160       r = may_open(in.get(), flags, perms);
8161       if (r < 0)
8162         goto out;
8163     }
8164   }
8165
8166   if (!fh)
8167     r = _open(in.get(), flags, mode, &fh, perms);
8168   if (r >= 0) {
8169     // allocate a integer file descriptor
8170     assert(fh);
8171     r = get_fd();
8172     assert(fd_map.count(r) == 0);
8173     fd_map[r] = fh;
8174   }
8175   
8176  out:
8177   tout(cct) << r << std::endl;
8178   ldout(cct, 3) << "open exit(" << path << ", " << ceph_flags_sys2wire(flags) << ") = " << r << dendl;
8179   return r;
8180 }
8181
8182 int Client::open(const char *relpath, int flags, const UserPerm& perms, mode_t mode)
8183 {
8184   /* Use default file striping parameters */
8185   return open(relpath, flags, perms, mode, 0, 0, 0, NULL);
8186 }
8187
8188 int Client::lookup_hash(inodeno_t ino, inodeno_t dirino, const char *name,
8189                         const UserPerm& perms)
8190 {
8191   Mutex::Locker lock(client_lock);
8192   ldout(cct, 3) << "lookup_hash enter(" << ino << ", #" << dirino << "/" << name << ")" << dendl;
8193
8194   if (unmounting)
8195     return -ENOTCONN;
8196
8197   MetaRequest *req = new MetaRequest(CEPH_MDS_OP_LOOKUPHASH);
8198   filepath path(ino);
8199   req->set_filepath(path);
8200
8201   uint32_t h = ceph_str_hash(CEPH_STR_HASH_RJENKINS, name, strlen(name));
8202   char f[30];
8203   sprintf(f, "%u", h);
8204   filepath path2(dirino);
8205   path2.push_dentry(string(f));
8206   req->set_filepath2(path2);
8207
8208   int r = make_request(req, perms, NULL, NULL,
8209                        rand() % mdsmap->get_num_in_mds());
8210   ldout(cct, 3) << "lookup_hash exit(" << ino << ", #" << dirino << "/" << name << ") = " << r << dendl;
8211   return r;
8212 }
8213
8214
8215 /**
8216  * Load inode into local cache.
8217  *
8218  * If inode pointer is non-NULL, and take a reference on
8219  * the resulting Inode object in one operation, so that caller
8220  * can safely assume inode will still be there after return.
8221  */
8222 int Client::lookup_ino(inodeno_t ino, const UserPerm& perms, Inode **inode)
8223 {
8224   Mutex::Locker lock(client_lock);
8225   ldout(cct, 3) << "lookup_ino enter(" << ino << ")" << dendl;
8226
8227   if (unmounting)
8228     return -ENOTCONN;
8229
8230   MetaRequest *req = new MetaRequest(CEPH_MDS_OP_LOOKUPINO);
8231   filepath path(ino);
8232   req->set_filepath(path);
8233
8234   int r = make_request(req, perms, NULL, NULL, rand() % mdsmap->get_num_in_mds());
8235   if (r == 0 && inode != NULL) {
8236     vinodeno_t vino(ino, CEPH_NOSNAP);
8237     unordered_map<vinodeno_t,Inode*>::iterator p = inode_map.find(vino);
8238     assert(p != inode_map.end());
8239     *inode = p->second;
8240     _ll_get(*inode);
8241   }
8242   ldout(cct, 3) << "lookup_ino exit(" << ino << ") = " << r << dendl;
8243   return r;
8244 }
8245
8246
8247
8248 /**
8249  * Find the parent inode of `ino` and insert it into
8250  * our cache.  Conditionally also set `parent` to a referenced
8251  * Inode* if caller provides non-NULL value.
8252  */
8253 int Client::lookup_parent(Inode *ino, const UserPerm& perms, Inode **parent)
8254 {
8255   Mutex::Locker lock(client_lock);
8256   ldout(cct, 3) << "lookup_parent enter(" << ino->ino << ")" << dendl;
8257
8258   if (unmounting)
8259     return -ENOTCONN;
8260
8261   if (!ino->dn_set.empty()) {
8262     // if we exposed the parent here, we'd need to check permissions,
8263     // but right now we just rely on the MDS doing so in make_request
8264     ldout(cct, 3) << "lookup_parent dentry already present" << dendl;
8265     return 0;
8266   }
8267   
8268   if (ino->is_root()) {
8269     *parent = NULL;
8270     ldout(cct, 3) << "ino is root, no parent" << dendl;
8271     return -EINVAL;
8272   }
8273
8274   MetaRequest *req = new MetaRequest(CEPH_MDS_OP_LOOKUPPARENT);
8275   filepath path(ino->ino);
8276   req->set_filepath(path);
8277
8278   InodeRef target;
8279   int r = make_request(req, perms, &target, NULL, rand() % mdsmap->get_num_in_mds());
8280   // Give caller a reference to the parent ino if they provided a pointer.
8281   if (parent != NULL) {
8282     if (r == 0) {
8283       *parent = target.get();
8284       _ll_get(*parent);
8285       ldout(cct, 3) << "lookup_parent found parent " << (*parent)->ino << dendl;
8286     } else {
8287       *parent = NULL;
8288     }
8289   }
8290   ldout(cct, 3) << "lookup_parent exit(" << ino->ino << ") = " << r << dendl;
8291   return r;
8292 }
8293
8294
8295 /**
8296  * Populate the parent dentry for `ino`, provided it is
8297  * a child of `parent`.
8298  */
8299 int Client::lookup_name(Inode *ino, Inode *parent, const UserPerm& perms)
8300 {
8301   assert(parent->is_dir());
8302
8303   Mutex::Locker lock(client_lock);
8304   ldout(cct, 3) << "lookup_name enter(" << ino->ino << ")" << dendl;
8305
8306   if (unmounting)
8307     return -ENOTCONN;
8308
8309   MetaRequest *req = new MetaRequest(CEPH_MDS_OP_LOOKUPNAME);
8310   req->set_filepath2(filepath(parent->ino));
8311   req->set_filepath(filepath(ino->ino));
8312   req->set_inode(ino);
8313
8314   int r = make_request(req, perms, NULL, NULL, rand() % mdsmap->get_num_in_mds());
8315   ldout(cct, 3) << "lookup_name exit(" << ino->ino << ") = " << r << dendl;
8316   return r;
8317 }
8318
8319
8320  Fh *Client::_create_fh(Inode *in, int flags, int cmode, const UserPerm& perms)
8321 {
8322   assert(in);
8323   Fh *f = new Fh(in);
8324   f->mode = cmode;
8325   f->flags = flags;
8326
8327   // inode
8328   f->actor_perms = perms;
8329
8330   ldout(cct, 10) << "_create_fh " << in->ino << " mode " << cmode << dendl;
8331
8332   if (in->snapid != CEPH_NOSNAP) {
8333     in->snap_cap_refs++;
8334     ldout(cct, 5) << "open success, fh is " << f << " combined IMMUTABLE SNAP caps " 
8335             << ccap_string(in->caps_issued()) << dendl;
8336   }
8337
8338   const md_config_t *conf = cct->_conf;
8339   f->readahead.set_trigger_requests(1);
8340   f->readahead.set_min_readahead_size(conf->client_readahead_min);
8341   uint64_t max_readahead = Readahead::NO_LIMIT;
8342   if (conf->client_readahead_max_bytes) {
8343     max_readahead = MIN(max_readahead, (uint64_t)conf->client_readahead_max_bytes);
8344   }
8345   if (conf->client_readahead_max_periods) {
8346     max_readahead = MIN(max_readahead, in->layout.get_period()*(uint64_t)conf->client_readahead_max_periods);
8347   }
8348   f->readahead.set_max_readahead_size(max_readahead);
8349   vector<uint64_t> alignments;
8350   alignments.push_back(in->layout.get_period());
8351   alignments.push_back(in->layout.stripe_unit);
8352   f->readahead.set_alignments(alignments);
8353
8354   return f;
8355 }
8356
8357 int Client::_release_fh(Fh *f)
8358 {
8359   //ldout(cct, 3) << "op: client->close(open_files[ " << fh << " ]);" << dendl;
8360   //ldout(cct, 3) << "op: open_files.erase( " << fh << " );" << dendl;
8361   Inode *in = f->inode.get();
8362   ldout(cct, 5) << "_release_fh " << f << " mode " << f->mode << " on " << *in << dendl;
8363
8364   if (in->snapid == CEPH_NOSNAP) {
8365     if (in->put_open_ref(f->mode)) {
8366       _flush(in, new C_Client_FlushComplete(this, in));
8367       check_caps(in, 0);
8368     }
8369   } else {
8370     assert(in->snap_cap_refs > 0);
8371     in->snap_cap_refs--;
8372   }
8373
8374   _release_filelocks(f);
8375
8376   // Finally, read any async err (i.e. from flushes)
8377   int err = f->take_async_err();
8378   if (err != 0) {
8379     ldout(cct, 1) << "_release_fh " << f << " on inode " << *in << " caught async_err = "
8380                   << cpp_strerror(err) << dendl;
8381   } else {
8382     ldout(cct, 10) << "_release_fh " << f << " on inode " << *in << " no async_err state" << dendl;
8383   }
8384
8385   _put_fh(f);
8386
8387   return err;
8388 }
8389
8390 void Client::_put_fh(Fh *f)
8391 {
8392   int left = f->put();
8393   if (!left) {
8394     delete f;
8395   }
8396 }
8397
8398 int Client::_open(Inode *in, int flags, mode_t mode, Fh **fhp,
8399                   const UserPerm& perms)
8400 {
8401   if (in->snapid != CEPH_NOSNAP &&
8402       (flags & (O_WRONLY | O_RDWR | O_CREAT | O_TRUNC | O_APPEND))) {
8403     return -EROFS;
8404   }
8405
8406   // use normalized flags to generate cmode
8407   int cmode = ceph_flags_to_mode(ceph_flags_sys2wire(flags));
8408   if (cmode < 0)
8409     return -EINVAL;
8410   int want = ceph_caps_for_mode(cmode);
8411   int result = 0;
8412
8413   in->get_open_ref(cmode);  // make note of pending open, since it effects _wanted_ caps.
8414
8415   if ((flags & O_TRUNC) == 0 &&
8416       in->caps_issued_mask(want)) {
8417     // update wanted?
8418     check_caps(in, CHECK_CAPS_NODELAY);
8419   } else {
8420     MetaRequest *req = new MetaRequest(CEPH_MDS_OP_OPEN);
8421     filepath path;
8422     in->make_nosnap_relative_path(path);
8423     req->set_filepath(path);
8424     req->head.args.open.flags = ceph_flags_sys2wire(flags & ~O_CREAT);
8425     req->head.args.open.mode = mode;
8426     req->head.args.open.pool = -1;
8427     if (cct->_conf->client_debug_getattr_caps)
8428       req->head.args.open.mask = DEBUG_GETATTR_CAPS;
8429     else
8430       req->head.args.open.mask = 0;
8431     req->head.args.open.old_size = in->size;   // for O_TRUNC
8432     req->set_inode(in);
8433     result = make_request(req, perms);
8434   }
8435
8436   // success?
8437   if (result >= 0) {
8438     if (fhp)
8439       *fhp = _create_fh(in, flags, cmode, perms);
8440   } else {
8441     in->put_open_ref(cmode);
8442   }
8443
8444   trim_cache();
8445
8446   return result;
8447 }
8448
8449 int Client::_renew_caps(Inode *in)
8450 {
8451   int wanted = in->caps_file_wanted();
8452   if (in->is_any_caps() &&
8453       ((wanted & CEPH_CAP_ANY_WR) == 0 || in->auth_cap)) {
8454     check_caps(in, CHECK_CAPS_NODELAY);
8455     return 0;
8456   }
8457
8458   int flags = 0;
8459   if ((wanted & CEPH_CAP_FILE_RD) && (wanted & CEPH_CAP_FILE_WR))
8460     flags = O_RDWR;
8461   else if (wanted & CEPH_CAP_FILE_RD)
8462     flags = O_RDONLY;
8463   else if (wanted & CEPH_CAP_FILE_WR)
8464     flags = O_WRONLY;
8465
8466   MetaRequest *req = new MetaRequest(CEPH_MDS_OP_OPEN);
8467   filepath path;
8468   in->make_nosnap_relative_path(path);
8469   req->set_filepath(path);
8470   req->head.args.open.flags = flags;
8471   req->head.args.open.pool = -1;
8472   if (cct->_conf->client_debug_getattr_caps)
8473     req->head.args.open.mask = DEBUG_GETATTR_CAPS;
8474   else
8475     req->head.args.open.mask = 0;
8476   req->set_inode(in);
8477
8478   // duplicate in case Cap goes away; not sure if that race is a concern?
8479   const UserPerm *pperm = in->get_best_perms();
8480   UserPerm perms;
8481   if (pperm != NULL)
8482     perms = *pperm;
8483   int ret = make_request(req, perms);
8484   return ret;
8485 }
8486
8487 int Client::close(int fd)
8488 {
8489   ldout(cct, 3) << "close enter(" << fd << ")" << dendl;
8490   Mutex::Locker lock(client_lock);
8491   tout(cct) << "close" << std::endl;
8492   tout(cct) << fd << std::endl;
8493
8494   if (unmounting)
8495     return -ENOTCONN;
8496
8497   Fh *fh = get_filehandle(fd);
8498   if (!fh)
8499     return -EBADF;
8500   int err = _release_fh(fh);
8501   fd_map.erase(fd);
8502   put_fd(fd);
8503   ldout(cct, 3) << "close exit(" << fd << ")" << dendl;
8504   return err;
8505 }
8506
8507
8508 // ------------
8509 // read, write
8510
8511 loff_t Client::lseek(int fd, loff_t offset, int whence)
8512 {
8513   Mutex::Locker lock(client_lock);
8514   tout(cct) << "lseek" << std::endl;
8515   tout(cct) << fd << std::endl;
8516   tout(cct) << offset << std::endl;
8517   tout(cct) << whence << std::endl;
8518
8519   if (unmounting)
8520     return -ENOTCONN;
8521
8522   Fh *f = get_filehandle(fd);
8523   if (!f)
8524     return -EBADF;
8525 #if defined(__linux__) && defined(O_PATH)
8526   if (f->flags & O_PATH)
8527     return -EBADF;
8528 #endif
8529   return _lseek(f, offset, whence);
8530 }
8531
8532 loff_t Client::_lseek(Fh *f, loff_t offset, int whence)
8533 {
8534   Inode *in = f->inode.get();
8535   int r;
8536
8537   switch (whence) {
8538   case SEEK_SET:
8539     f->pos = offset;
8540     break;
8541
8542   case SEEK_CUR:
8543     f->pos += offset;
8544     break;
8545
8546   case SEEK_END:
8547     r = _getattr(in, CEPH_STAT_CAP_SIZE, f->actor_perms);
8548     if (r < 0)
8549       return r;
8550     f->pos = in->size + offset;
8551     break;
8552
8553   default:
8554     ceph_abort();
8555   }
8556
8557   ldout(cct, 3) << "_lseek(" << f << ", " << offset << ", " << whence << ") = " << f->pos << dendl;
8558   return f->pos;
8559 }
8560
8561
8562 void Client::lock_fh_pos(Fh *f)
8563 {
8564   ldout(cct, 10) << "lock_fh_pos " << f << dendl;
8565
8566   if (f->pos_locked || !f->pos_waiters.empty()) {
8567     Cond cond;
8568     f->pos_waiters.push_back(&cond);
8569     ldout(cct, 10) << "lock_fh_pos BLOCKING on " << f << dendl;
8570     while (f->pos_locked || f->pos_waiters.front() != &cond)
8571       cond.Wait(client_lock);
8572     ldout(cct, 10) << "lock_fh_pos UNBLOCKING on " << f << dendl;
8573     assert(f->pos_waiters.front() == &cond);
8574     f->pos_waiters.pop_front();
8575   }
8576
8577   f->pos_locked = true;
8578 }
8579
8580 void Client::unlock_fh_pos(Fh *f)
8581 {
8582   ldout(cct, 10) << "unlock_fh_pos " << f << dendl;
8583   f->pos_locked = false;
8584 }
8585
8586 int Client::uninline_data(Inode *in, Context *onfinish)
8587 {
8588   if (!in->inline_data.length()) {
8589     onfinish->complete(0);
8590     return 0;
8591   }
8592
8593   char oid_buf[32];
8594   snprintf(oid_buf, sizeof(oid_buf), "%llx.00000000", (long long unsigned)in->ino);
8595   object_t oid = oid_buf;
8596
8597   ObjectOperation create_ops;
8598   create_ops.create(false);
8599
8600   objecter->mutate(oid,
8601                    OSDMap::file_to_object_locator(in->layout),
8602                    create_ops,
8603                    in->snaprealm->get_snap_context(),
8604                    ceph::real_clock::now(),
8605                    0,
8606                    NULL);
8607
8608   bufferlist inline_version_bl;
8609   ::encode(in->inline_version, inline_version_bl);
8610
8611   ObjectOperation uninline_ops;
8612   uninline_ops.cmpxattr("inline_version",
8613                         CEPH_OSD_CMPXATTR_OP_GT,
8614                         CEPH_OSD_CMPXATTR_MODE_U64,
8615                         inline_version_bl);
8616   bufferlist inline_data = in->inline_data;
8617   uninline_ops.write(0, inline_data, in->truncate_size, in->truncate_seq);
8618   uninline_ops.setxattr("inline_version", stringify(in->inline_version));
8619
8620   objecter->mutate(oid,
8621                    OSDMap::file_to_object_locator(in->layout),
8622                    uninline_ops,
8623                    in->snaprealm->get_snap_context(),
8624                    ceph::real_clock::now(),
8625                    0,
8626                    onfinish);
8627
8628   return 0;
8629 }
8630
8631 //
8632
8633 // blocking osd interface
8634
8635 int Client::read(int fd, char *buf, loff_t size, loff_t offset)
8636 {
8637   Mutex::Locker lock(client_lock);
8638   tout(cct) << "read" << std::endl;
8639   tout(cct) << fd << std::endl;
8640   tout(cct) << size << std::endl;
8641   tout(cct) << offset << std::endl;
8642
8643   if (unmounting)
8644     return -ENOTCONN;
8645
8646   Fh *f = get_filehandle(fd);
8647   if (!f)
8648     return -EBADF;
8649 #if defined(__linux__) && defined(O_PATH)
8650   if (f->flags & O_PATH)
8651     return -EBADF;
8652 #endif
8653   bufferlist bl;
8654   int r = _read(f, offset, size, &bl);
8655   ldout(cct, 3) << "read(" << fd << ", " << (void*)buf << ", " << size << ", " << offset << ") = " << r << dendl;
8656   if (r >= 0) {
8657     bl.copy(0, bl.length(), buf);
8658     r = bl.length();
8659   }
8660   return r;
8661 }
8662
8663 int Client::preadv(int fd, const struct iovec *iov, int iovcnt, loff_t offset)
8664 {
8665   if (iovcnt < 0)
8666     return -EINVAL;
8667   return _preadv_pwritev(fd, iov, iovcnt, offset, false);
8668 }
8669
8670 int Client::_read(Fh *f, int64_t offset, uint64_t size, bufferlist *bl)
8671 {
8672   const md_config_t *conf = cct->_conf;
8673   Inode *in = f->inode.get();
8674
8675   if ((f->mode & CEPH_FILE_MODE_RD) == 0)
8676     return -EBADF;
8677   //bool lazy = f->mode == CEPH_FILE_MODE_LAZY;
8678
8679   bool movepos = false;
8680   if (offset < 0) {
8681     lock_fh_pos(f);
8682     offset = f->pos;
8683     movepos = true;
8684   }
8685   loff_t start_pos = offset;
8686
8687   if (in->inline_version == 0) {
8688     int r = _getattr(in, CEPH_STAT_CAP_INLINE_DATA, f->actor_perms, true);
8689     if (r < 0) {
8690       if (movepos)
8691         unlock_fh_pos(f);
8692       return r;
8693     }
8694     assert(in->inline_version > 0);
8695   }
8696
8697 retry:
8698   int have;
8699   int r = get_caps(in, CEPH_CAP_FILE_RD, CEPH_CAP_FILE_CACHE, &have, -1);
8700   if (r < 0) {
8701     if (movepos)
8702         unlock_fh_pos(f);
8703     return r;
8704   }
8705   if (f->flags & O_DIRECT)
8706     have &= ~CEPH_CAP_FILE_CACHE;
8707
8708   Mutex uninline_flock("Client::_read_uninline_data flock");
8709   Cond uninline_cond;
8710   bool uninline_done = false;
8711   int uninline_ret = 0;
8712   Context *onuninline = NULL;
8713
8714   if (in->inline_version < CEPH_INLINE_NONE) {
8715     if (!(have & CEPH_CAP_FILE_CACHE)) {
8716       onuninline = new C_SafeCond(&uninline_flock,
8717                                   &uninline_cond,
8718                                   &uninline_done,
8719                                   &uninline_ret);
8720       uninline_data(in, onuninline);
8721     } else {
8722       uint32_t len = in->inline_data.length();
8723
8724       uint64_t endoff = offset + size;
8725       if (endoff > in->size)
8726         endoff = in->size;
8727
8728       if (offset < len) {
8729         if (endoff <= len) {
8730           bl->substr_of(in->inline_data, offset, endoff - offset);
8731         } else {
8732           bl->substr_of(in->inline_data, offset, len - offset);
8733           bl->append_zero(endoff - len);
8734         }
8735       } else if ((uint64_t)offset < endoff) {
8736         bl->append_zero(endoff - offset);
8737       }
8738
8739       goto success;
8740     }
8741   }
8742
8743   if (!conf->client_debug_force_sync_read &&
8744       (conf->client_oc && (have & CEPH_CAP_FILE_CACHE))) {
8745
8746     if (f->flags & O_RSYNC) {
8747       _flush_range(in, offset, size);
8748     }
8749     r = _read_async(f, offset, size, bl);
8750     if (r < 0)
8751       goto done;
8752   } else {
8753     if (f->flags & O_DIRECT)
8754       _flush_range(in, offset, size);
8755
8756     bool checkeof = false;
8757     r = _read_sync(f, offset, size, bl, &checkeof);
8758     if (r < 0)
8759       goto done;
8760     if (checkeof) {
8761       offset += r;
8762       size -= r;
8763
8764       put_cap_ref(in, CEPH_CAP_FILE_RD);
8765       have = 0;
8766       // reverify size
8767       r = _getattr(in, CEPH_STAT_CAP_SIZE, f->actor_perms);
8768       if (r < 0)
8769         goto done;
8770
8771       // eof?  short read.
8772       if ((uint64_t)offset < in->size)
8773         goto retry;
8774     }
8775   }
8776
8777 success:
8778   if (movepos) {
8779     // adjust fd pos
8780     f->pos = start_pos + bl->length();
8781     unlock_fh_pos(f);
8782   }
8783
8784 done:
8785   // done!
8786
8787   if (onuninline) {
8788     client_lock.Unlock();
8789     uninline_flock.Lock();
8790     while (!uninline_done)
8791       uninline_cond.Wait(uninline_flock);
8792     uninline_flock.Unlock();
8793     client_lock.Lock();
8794
8795     if (uninline_ret >= 0 || uninline_ret == -ECANCELED) {
8796       in->inline_data.clear();
8797       in->inline_version = CEPH_INLINE_NONE;
8798       mark_caps_dirty(in, CEPH_CAP_FILE_WR);
8799       check_caps(in, 0);
8800     } else
8801       r = uninline_ret;
8802   }
8803
8804   if (have)
8805     put_cap_ref(in, CEPH_CAP_FILE_RD);
8806   if (r < 0) {
8807     if (movepos)
8808         unlock_fh_pos(f);
8809     return r;
8810   } else
8811     return bl->length();
8812 }
8813
8814 Client::C_Readahead::C_Readahead(Client *c, Fh *f) :
8815     client(c), f(f) {
8816   f->get();
8817   f->readahead.inc_pending();
8818 }
8819
8820 Client::C_Readahead::~C_Readahead() {
8821   f->readahead.dec_pending();
8822   client->_put_fh(f);
8823 }
8824
8825 void Client::C_Readahead::finish(int r) {
8826   lgeneric_subdout(client->cct, client, 20) << "client." << client->get_nodeid() << " " << "C_Readahead on " << f->inode << dendl;
8827   client->put_cap_ref(f->inode.get(), CEPH_CAP_FILE_RD | CEPH_CAP_FILE_CACHE);
8828 }
8829
8830 int Client::_read_async(Fh *f, uint64_t off, uint64_t len, bufferlist *bl)
8831 {
8832   const md_config_t *conf = cct->_conf;
8833   Inode *in = f->inode.get();
8834
8835   ldout(cct, 10) << "_read_async " << *in << " " << off << "~" << len << dendl;
8836
8837   // trim read based on file size?
8838   if (off >= in->size)
8839     return 0;
8840   if (len == 0)
8841     return 0;
8842   if (off + len > in->size) {
8843     len = in->size - off;    
8844   }
8845
8846   ldout(cct, 10) << " min_bytes=" << f->readahead.get_min_readahead_size()
8847                  << " max_bytes=" << f->readahead.get_max_readahead_size()
8848                  << " max_periods=" << conf->client_readahead_max_periods << dendl;
8849
8850   // read (and possibly block)
8851   int r, rvalue = 0;
8852   Mutex flock("Client::_read_async flock");
8853   Cond cond;
8854   bool done = false;
8855   Context *onfinish = new C_SafeCond(&flock, &cond, &done, &rvalue);
8856   r = objectcacher->file_read(&in->oset, &in->layout, in->snapid,
8857                               off, len, bl, 0, onfinish);
8858   if (r == 0) {
8859     get_cap_ref(in, CEPH_CAP_FILE_CACHE);
8860     client_lock.Unlock();
8861     flock.Lock();
8862     while (!done)
8863       cond.Wait(flock);
8864     flock.Unlock();
8865     client_lock.Lock();
8866     put_cap_ref(in, CEPH_CAP_FILE_CACHE);
8867     r = rvalue;
8868   } else {
8869     // it was cached.
8870     delete onfinish;
8871   }
8872
8873   if(f->readahead.get_min_readahead_size() > 0) {
8874     pair<uint64_t, uint64_t> readahead_extent = f->readahead.update(off, len, in->size);
8875     if (readahead_extent.second > 0) {
8876       ldout(cct, 20) << "readahead " << readahead_extent.first << "~" << readahead_extent.second
8877                      << " (caller wants " << off << "~" << len << ")" << dendl;
8878       Context *onfinish2 = new C_Readahead(this, f);
8879       int r2 = objectcacher->file_read(&in->oset, &in->layout, in->snapid,
8880                                        readahead_extent.first, readahead_extent.second,
8881                                        NULL, 0, onfinish2);
8882       if (r2 == 0) {
8883         ldout(cct, 20) << "readahead initiated, c " << onfinish2 << dendl;
8884         get_cap_ref(in, CEPH_CAP_FILE_RD | CEPH_CAP_FILE_CACHE);
8885       } else {
8886         ldout(cct, 20) << "readahead was no-op, already cached" << dendl;
8887         delete onfinish2;
8888       }
8889     }
8890   }
8891
8892   return r;
8893 }
8894
8895 int Client::_read_sync(Fh *f, uint64_t off, uint64_t len, bufferlist *bl,
8896                        bool *checkeof)
8897 {
8898   Inode *in = f->inode.get();
8899   uint64_t pos = off;
8900   int left = len;
8901   int read = 0;
8902
8903   ldout(cct, 10) << "_read_sync " << *in << " " << off << "~" << len << dendl;
8904
8905   Mutex flock("Client::_read_sync flock");
8906   Cond cond;
8907   while (left > 0) {
8908     int r = 0;
8909     bool done = false;
8910     Context *onfinish = new C_SafeCond(&flock, &cond, &done, &r);
8911     bufferlist tbl;
8912
8913     int wanted = left;
8914     filer->read_trunc(in->ino, &in->layout, in->snapid,
8915                       pos, left, &tbl, 0,
8916                       in->truncate_size, in->truncate_seq,
8917                       onfinish);
8918     client_lock.Unlock();
8919     flock.Lock();
8920     while (!done)
8921       cond.Wait(flock);
8922     flock.Unlock();
8923     client_lock.Lock();
8924
8925     // if we get ENOENT from OSD, assume 0 bytes returned
8926     if (r == -ENOENT)
8927       r = 0;
8928     if (r < 0)
8929       return r;
8930     if (tbl.length()) {
8931       r = tbl.length();
8932
8933       read += r;
8934       pos += r;
8935       left -= r;
8936       bl->claim_append(tbl);
8937     }
8938     // short read?
8939     if (r >= 0 && r < wanted) {
8940       if (pos < in->size) {
8941         // zero up to known EOF
8942         int64_t some = in->size - pos;
8943         if (some > left)
8944           some = left;
8945         bufferptr z(some);
8946         z.zero();
8947         bl->push_back(z);
8948         read += some;
8949         pos += some;
8950         left -= some;
8951         if (left == 0)
8952           return read;
8953       }
8954
8955       *checkeof = true;
8956       return read;
8957     }
8958   }
8959   return read;
8960 }
8961
8962
8963 /*
8964  * we keep count of uncommitted sync writes on the inode, so that
8965  * fsync can DDRT.
8966  */
8967 void Client::_sync_write_commit(Inode *in)
8968 {
8969   assert(unsafe_sync_write > 0);
8970   unsafe_sync_write--;
8971
8972   put_cap_ref(in, CEPH_CAP_FILE_BUFFER);
8973
8974   ldout(cct, 15) << "sync_write_commit unsafe_sync_write = " << unsafe_sync_write << dendl;
8975   if (unsafe_sync_write == 0 && unmounting) {
8976     ldout(cct, 10) << "sync_write_commit -- no more unsafe writes, unmount can proceed" << dendl;
8977     mount_cond.Signal();
8978   }
8979 }
8980
8981 int Client::write(int fd, const char *buf, loff_t size, loff_t offset) 
8982 {
8983   Mutex::Locker lock(client_lock);
8984   tout(cct) << "write" << std::endl;
8985   tout(cct) << fd << std::endl;
8986   tout(cct) << size << std::endl;
8987   tout(cct) << offset << std::endl;
8988
8989   if (unmounting)
8990     return -ENOTCONN;
8991
8992   Fh *fh = get_filehandle(fd);
8993   if (!fh)
8994     return -EBADF;
8995 #if defined(__linux__) && defined(O_PATH)
8996   if (fh->flags & O_PATH)
8997     return -EBADF;
8998 #endif
8999   int r = _write(fh, offset, size, buf, NULL, 0);
9000   ldout(cct, 3) << "write(" << fd << ", \"...\", " << size << ", " << offset << ") = " << r << dendl;
9001   return r;
9002 }
9003
9004 int Client::pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset)
9005 {
9006   if (iovcnt < 0)
9007     return -EINVAL;
9008   return _preadv_pwritev(fd, iov, iovcnt, offset, true);
9009 }
9010
9011 int Client::_preadv_pwritev(int fd, const struct iovec *iov, unsigned iovcnt, int64_t offset, bool write)
9012 {
9013     Mutex::Locker lock(client_lock);
9014     tout(cct) << fd << std::endl;
9015     tout(cct) << offset << std::endl;
9016
9017     if (unmounting)
9018      return -ENOTCONN;
9019
9020     Fh *fh = get_filehandle(fd);
9021     if (!fh)
9022         return -EBADF;
9023 #if defined(__linux__) && defined(O_PATH)
9024     if (fh->flags & O_PATH)
9025         return -EBADF;
9026 #endif
9027     loff_t totallen = 0;
9028     for (unsigned i = 0; i < iovcnt; i++) {
9029         totallen += iov[i].iov_len;
9030     }
9031     if (write) {
9032         int w = _write(fh, offset, totallen, NULL, iov, iovcnt);
9033         ldout(cct, 3) << "pwritev(" << fd << ", \"...\", " << totallen << ", " << offset << ") = " << w << dendl;
9034         return w;
9035     } else {
9036         bufferlist bl;
9037         int r = _read(fh, offset, totallen, &bl);
9038         ldout(cct, 3) << "preadv(" << fd << ", " <<  offset << ") = " << r << dendl;
9039         if (r <= 0)
9040           return r;
9041
9042         int bufoff = 0;
9043         for (unsigned j = 0, resid = r; j < iovcnt && resid > 0; j++) {
9044                /*
9045                 * This piece of code aims to handle the case that bufferlist does not have enough data 
9046                 * to fill in the iov 
9047                 */
9048                if (resid < iov[j].iov_len) {
9049                     bl.copy(bufoff, resid, (char *)iov[j].iov_base);
9050                     break;
9051                } else {
9052                     bl.copy(bufoff, iov[j].iov_len, (char *)iov[j].iov_base);
9053                }
9054                resid -= iov[j].iov_len;
9055                bufoff += iov[j].iov_len;
9056         }
9057         return r;  
9058     }
9059 }
9060
9061 int Client::_write(Fh *f, int64_t offset, uint64_t size, const char *buf,
9062                   const struct iovec *iov, int iovcnt)
9063 {
9064   if ((uint64_t)(offset+size) > mdsmap->get_max_filesize()) //too large!
9065     return -EFBIG;
9066
9067   //ldout(cct, 7) << "write fh " << fh << " size " << size << " offset " << offset << dendl;
9068   Inode *in = f->inode.get();
9069
9070   if (objecter->osdmap_pool_full(in->layout.pool_id)) {
9071     return -ENOSPC;
9072   }
9073
9074   assert(in->snapid == CEPH_NOSNAP);
9075
9076   // was Fh opened as writeable?
9077   if ((f->mode & CEPH_FILE_MODE_WR) == 0)
9078     return -EBADF;
9079
9080   // check quota
9081   uint64_t endoff = offset + size;
9082   if (endoff > in->size && is_quota_bytes_exceeded(in, endoff - in->size,
9083                                                    f->actor_perms)) {
9084     return -EDQUOT;
9085   }
9086
9087   // use/adjust fd pos?
9088   if (offset < 0) {
9089     lock_fh_pos(f);
9090     /*
9091      * FIXME: this is racy in that we may block _after_ this point waiting for caps, and size may
9092      * change out from under us.
9093      */
9094     if (f->flags & O_APPEND) {
9095       int r = _lseek(f, 0, SEEK_END);
9096       if (r < 0) {
9097         unlock_fh_pos(f);
9098         return r;
9099       }
9100     }
9101     offset = f->pos;
9102     f->pos = offset+size;
9103     unlock_fh_pos(f);
9104   }
9105
9106   //bool lazy = f->mode == CEPH_FILE_MODE_LAZY;
9107
9108   ldout(cct, 10) << "cur file size is " << in->size << dendl;
9109
9110   // time it.
9111   utime_t start = ceph_clock_now();
9112
9113   if (in->inline_version == 0) {
9114     int r = _getattr(in, CEPH_STAT_CAP_INLINE_DATA, f->actor_perms, true);
9115     if (r < 0)
9116       return r;
9117     assert(in->inline_version > 0);
9118   }
9119
9120   // copy into fresh buffer (since our write may be resub, async)
9121   bufferlist bl;
9122   if (buf) {
9123     if (size > 0)
9124       bl.append(buf, size);
9125   } else if (iov){
9126     for (int i = 0; i < iovcnt; i++) {
9127       if (iov[i].iov_len > 0) {
9128         bl.append((const char *)iov[i].iov_base, iov[i].iov_len);
9129       }
9130     }
9131   }
9132
9133   utime_t lat;
9134   uint64_t totalwritten;
9135   int have;
9136   int r = get_caps(in, CEPH_CAP_FILE_WR|CEPH_CAP_AUTH_SHARED,
9137                     CEPH_CAP_FILE_BUFFER, &have, endoff);
9138   if (r < 0)
9139     return r;
9140
9141   /* clear the setuid/setgid bits, if any */
9142   if (unlikely(in->mode & (S_ISUID|S_ISGID)) && size > 0) {
9143     struct ceph_statx stx = { 0 };
9144
9145     put_cap_ref(in, CEPH_CAP_AUTH_SHARED);
9146     r = __setattrx(in, &stx, CEPH_SETATTR_KILL_SGUID, f->actor_perms);
9147     if (r < 0)
9148       return r;
9149   } else {
9150     put_cap_ref(in, CEPH_CAP_AUTH_SHARED);
9151   }
9152
9153   if (f->flags & O_DIRECT)
9154     have &= ~CEPH_CAP_FILE_BUFFER;
9155
9156   ldout(cct, 10) << " snaprealm " << *in->snaprealm << dendl;
9157
9158   Mutex uninline_flock("Client::_write_uninline_data flock");
9159   Cond uninline_cond;
9160   bool uninline_done = false;
9161   int uninline_ret = 0;
9162   Context *onuninline = NULL;
9163
9164   if (in->inline_version < CEPH_INLINE_NONE) {
9165     if (endoff > cct->_conf->client_max_inline_size ||
9166         endoff > CEPH_INLINE_MAX_SIZE ||
9167         !(have & CEPH_CAP_FILE_BUFFER)) {
9168       onuninline = new C_SafeCond(&uninline_flock,
9169                                   &uninline_cond,
9170                                   &uninline_done,
9171                                   &uninline_ret);
9172       uninline_data(in, onuninline);
9173     } else {
9174       get_cap_ref(in, CEPH_CAP_FILE_BUFFER);
9175
9176       uint32_t len = in->inline_data.length();
9177
9178       if (endoff < len)
9179         in->inline_data.copy(endoff, len - endoff, bl);
9180
9181       if (offset < len)
9182         in->inline_data.splice(offset, len - offset);
9183       else if (offset > len)
9184         in->inline_data.append_zero(offset - len);
9185
9186       in->inline_data.append(bl);
9187       in->inline_version++;
9188
9189       put_cap_ref(in, CEPH_CAP_FILE_BUFFER);
9190
9191       goto success;
9192     }
9193   }
9194
9195   if (cct->_conf->client_oc && (have & CEPH_CAP_FILE_BUFFER)) {
9196     // do buffered write
9197     if (!in->oset.dirty_or_tx)
9198       get_cap_ref(in, CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_BUFFER);
9199
9200     get_cap_ref(in, CEPH_CAP_FILE_BUFFER);
9201
9202     // async, caching, non-blocking.
9203     r = objectcacher->file_write(&in->oset, &in->layout,
9204                                  in->snaprealm->get_snap_context(),
9205                                  offset, size, bl, ceph::real_clock::now(),
9206                                  0);
9207     put_cap_ref(in, CEPH_CAP_FILE_BUFFER);
9208
9209     if (r < 0)
9210       goto done;
9211
9212     // flush cached write if O_SYNC is set on file fh
9213     // O_DSYNC == O_SYNC on linux < 2.6.33
9214     // O_SYNC = __O_SYNC | O_DSYNC on linux >= 2.6.33
9215     if ((f->flags & O_SYNC) || (f->flags & O_DSYNC)) {
9216       _flush_range(in, offset, size);
9217     }
9218   } else {
9219     if (f->flags & O_DIRECT)
9220       _flush_range(in, offset, size);
9221
9222     // simple, non-atomic sync write
9223     Mutex flock("Client::_write flock");
9224     Cond cond;
9225     bool done = false;
9226     Context *onfinish = new C_SafeCond(&flock, &cond, &done);
9227
9228     unsafe_sync_write++;
9229     get_cap_ref(in, CEPH_CAP_FILE_BUFFER);  // released by onsafe callback
9230
9231     filer->write_trunc(in->ino, &in->layout, in->snaprealm->get_snap_context(),
9232                        offset, size, bl, ceph::real_clock::now(), 0,
9233                        in->truncate_size, in->truncate_seq,
9234                        onfinish);
9235     client_lock.Unlock();
9236     flock.Lock();
9237
9238     while (!done)
9239       cond.Wait(flock);
9240     flock.Unlock();
9241     client_lock.Lock();
9242     _sync_write_commit(in);
9243   }
9244
9245   // if we get here, write was successful, update client metadata
9246 success:
9247   // time
9248   lat = ceph_clock_now();
9249   lat -= start;
9250   logger->tinc(l_c_wrlat, lat);
9251
9252   totalwritten = size;
9253   r = (int)totalwritten;
9254
9255   // extend file?
9256   if (totalwritten + offset > in->size) {
9257     in->size = totalwritten + offset;
9258     mark_caps_dirty(in, CEPH_CAP_FILE_WR);
9259
9260     if (is_quota_bytes_approaching(in, f->actor_perms)) {
9261       check_caps(in, CHECK_CAPS_NODELAY);
9262     } else if (is_max_size_approaching(in)) {
9263       check_caps(in, 0);
9264     }
9265
9266     ldout(cct, 7) << "wrote to " << totalwritten+offset << ", extending file size" << dendl;
9267   } else {
9268     ldout(cct, 7) << "wrote to " << totalwritten+offset << ", leaving file size at " << in->size << dendl;
9269   }
9270
9271   // mtime
9272   in->mtime = ceph_clock_now();
9273   in->change_attr++;
9274   mark_caps_dirty(in, CEPH_CAP_FILE_WR);
9275
9276 done:
9277
9278   if (onuninline) {
9279     client_lock.Unlock();
9280     uninline_flock.Lock();
9281     while (!uninline_done)
9282       uninline_cond.Wait(uninline_flock);
9283     uninline_flock.Unlock();
9284     client_lock.Lock();
9285
9286     if (uninline_ret >= 0 || uninline_ret == -ECANCELED) {
9287       in->inline_data.clear();
9288       in->inline_version = CEPH_INLINE_NONE;
9289       mark_caps_dirty(in, CEPH_CAP_FILE_WR);
9290       check_caps(in, 0);
9291     } else
9292       r = uninline_ret;
9293   }
9294
9295   put_cap_ref(in, CEPH_CAP_FILE_WR);
9296   return r;
9297 }
9298
9299 int Client::_flush(Fh *f)
9300 {
9301   Inode *in = f->inode.get();
9302   int err = f->take_async_err();
9303   if (err != 0) {
9304     ldout(cct, 1) << __func__ << ": " << f << " on inode " << *in << " caught async_err = "
9305                   << cpp_strerror(err) << dendl;
9306   } else {
9307     ldout(cct, 10) << __func__ << ": " << f << " on inode " << *in << " no async_err state" << dendl;
9308   }
9309
9310   return err;
9311 }
9312
9313 int Client::truncate(const char *relpath, loff_t length, const UserPerm& perms) 
9314 {
9315   struct ceph_statx stx;
9316   stx.stx_size = length;
9317   return setattrx(relpath, &stx, CEPH_SETATTR_SIZE, perms);
9318 }
9319
9320 int Client::ftruncate(int fd, loff_t length, const UserPerm& perms) 
9321 {
9322   Mutex::Locker lock(client_lock);
9323   tout(cct) << "ftruncate" << std::endl;
9324   tout(cct) << fd << std::endl;
9325   tout(cct) << length << std::endl;
9326
9327   if (unmounting)
9328     return -ENOTCONN;
9329
9330   Fh *f = get_filehandle(fd);
9331   if (!f)
9332     return -EBADF;
9333 #if defined(__linux__) && defined(O_PATH)
9334   if (f->flags & O_PATH)
9335     return -EBADF;
9336 #endif
9337   struct stat attr;
9338   attr.st_size = length;
9339   return _setattr(f->inode, &attr, CEPH_SETATTR_SIZE, perms);
9340 }
9341
9342 int Client::fsync(int fd, bool syncdataonly) 
9343 {
9344   Mutex::Locker lock(client_lock);
9345   tout(cct) << "fsync" << std::endl;
9346   tout(cct) << fd << std::endl;
9347   tout(cct) << syncdataonly << std::endl;
9348
9349   if (unmounting)
9350     return -ENOTCONN;
9351
9352   Fh *f = get_filehandle(fd);
9353   if (!f)
9354     return -EBADF;
9355 #if defined(__linux__) && defined(O_PATH)
9356   if (f->flags & O_PATH)
9357     return -EBADF;
9358 #endif
9359   int r = _fsync(f, syncdataonly);
9360   if (r == 0) {
9361     // The IOs in this fsync were okay, but maybe something happened
9362     // in the background that we shoudl be reporting?
9363     r = f->take_async_err();
9364     ldout(cct, 3) << "fsync(" << fd << ", " << syncdataonly
9365                   << ") = 0, async_err = " << r << dendl;
9366   } else {
9367     // Assume that an error we encountered during fsync, even reported
9368     // synchronously, would also have applied the error to the Fh, and we
9369     // should clear it here to avoid returning the same error again on next
9370     // call.
9371     ldout(cct, 3) << "fsync(" << fd << ", " << syncdataonly << ") = "
9372                   << r << dendl;
9373     f->take_async_err();
9374   }
9375   return r;
9376 }
9377
9378 int Client::_fsync(Inode *in, bool syncdataonly)
9379 {
9380   int r = 0;
9381   Mutex lock("Client::_fsync::lock");
9382   Cond cond;
9383   bool done = false;
9384   C_SafeCond *object_cacher_completion = NULL;
9385   ceph_tid_t flush_tid = 0;
9386   InodeRef tmp_ref;
9387
9388   ldout(cct, 3) << "_fsync on " << *in << " " << (syncdataonly ? "(dataonly)":"(data+metadata)") << dendl;
9389   
9390   if (cct->_conf->client_oc) {
9391     object_cacher_completion = new C_SafeCond(&lock, &cond, &done, &r);
9392     tmp_ref = in; // take a reference; C_SafeCond doesn't and _flush won't either
9393     _flush(in, object_cacher_completion);
9394     ldout(cct, 15) << "using return-valued form of _fsync" << dendl;
9395   }
9396   
9397   if (!syncdataonly && in->dirty_caps) {
9398     check_caps(in, CHECK_CAPS_NODELAY|CHECK_CAPS_SYNCHRONOUS);
9399     if (in->flushing_caps)
9400       flush_tid = last_flush_tid;
9401   } else ldout(cct, 10) << "no metadata needs to commit" << dendl;
9402
9403   if (!syncdataonly && !in->unsafe_ops.empty()) {
9404     MetaRequest *req = in->unsafe_ops.back();
9405     ldout(cct, 15) << "waiting on unsafe requests, last tid " << req->get_tid() <<  dendl;
9406
9407     req->get();
9408     wait_on_list(req->waitfor_safe);
9409     put_request(req);
9410   }
9411
9412   if (object_cacher_completion) { // wait on a real reply instead of guessing
9413     client_lock.Unlock();
9414     lock.Lock();
9415     ldout(cct, 15) << "waiting on data to flush" << dendl;
9416     while (!done)
9417       cond.Wait(lock);
9418     lock.Unlock();
9419     client_lock.Lock();
9420     ldout(cct, 15) << "got " << r << " from flush writeback" << dendl;
9421   } else {
9422     // FIXME: this can starve
9423     while (in->cap_refs[CEPH_CAP_FILE_BUFFER] > 0) {
9424       ldout(cct, 10) << "ino " << in->ino << " has " << in->cap_refs[CEPH_CAP_FILE_BUFFER]
9425                      << " uncommitted, waiting" << dendl;
9426       wait_on_list(in->waitfor_commit);
9427     }
9428   }
9429
9430   if (!r) {
9431     if (flush_tid > 0)
9432       wait_sync_caps(in, flush_tid);
9433
9434     ldout(cct, 10) << "ino " << in->ino << " has no uncommitted writes" << dendl;
9435   } else {
9436     ldout(cct, 1) << "ino " << in->ino << " failed to commit to disk! "
9437                   << cpp_strerror(-r) << dendl;
9438   }
9439
9440   return r;
9441 }
9442
9443 int Client::_fsync(Fh *f, bool syncdataonly)
9444 {
9445   ldout(cct, 3) << "_fsync(" << f << ", " << (syncdataonly ? "dataonly)":"data+metadata)") << dendl;
9446   return _fsync(f->inode.get(), syncdataonly);
9447 }
9448
9449 int Client::fstat(int fd, struct stat *stbuf, const UserPerm& perms, int mask)
9450 {
9451   Mutex::Locker lock(client_lock);
9452   tout(cct) << "fstat mask " << hex << mask << dec << std::endl;
9453   tout(cct) << fd << std::endl;
9454
9455   if (unmounting)
9456     return -ENOTCONN;
9457
9458   Fh *f = get_filehandle(fd);
9459   if (!f)
9460     return -EBADF;
9461   int r = _getattr(f->inode, mask, perms);
9462   if (r < 0)
9463     return r;
9464   fill_stat(f->inode, stbuf, NULL);
9465   ldout(cct, 3) << "fstat(" << fd << ", " << stbuf << ") = " << r << dendl;
9466   return r;
9467 }
9468
9469 int Client::fstatx(int fd, struct ceph_statx *stx, const UserPerm& perms,
9470                    unsigned int want, unsigned int flags)
9471 {
9472   Mutex::Locker lock(client_lock);
9473   tout(cct) << "fstatx flags " << hex << flags << " want " << want << dec << std::endl;
9474   tout(cct) << fd << std::endl;
9475
9476   if (unmounting)
9477     return -ENOTCONN;
9478
9479   Fh *f = get_filehandle(fd);
9480   if (!f)
9481     return -EBADF;
9482
9483   unsigned mask = statx_to_mask(flags, want);
9484
9485   int r = 0;
9486   if (mask && !f->inode->caps_issued_mask(mask)) {
9487     r = _getattr(f->inode, mask, perms);
9488     if (r < 0) {
9489       ldout(cct, 3) << "fstatx exit on error!" << dendl;
9490       return r;
9491     }
9492   }
9493
9494   fill_statx(f->inode, mask, stx);
9495   ldout(cct, 3) << "fstatx(" << fd << ", " << stx << ") = " << r << dendl;
9496   return r;
9497 }
9498
9499 // not written yet, but i want to link!
9500
9501 int Client::chdir(const char *relpath, std::string &new_cwd,
9502                   const UserPerm& perms)
9503 {
9504   Mutex::Locker lock(client_lock);
9505   tout(cct) << "chdir" << std::endl;
9506   tout(cct) << relpath << std::endl;
9507
9508   if (unmounting)
9509     return -ENOTCONN;
9510
9511   filepath path(relpath);
9512   InodeRef in;
9513   int r = path_walk(path, &in, perms);
9514   if (r < 0)
9515     return r;
9516   if (cwd != in)
9517     cwd.swap(in);
9518   ldout(cct, 3) << "chdir(" << relpath << ")  cwd now " << cwd->ino << dendl;
9519
9520   _getcwd(new_cwd, perms);
9521   return 0;
9522 }
9523
9524 void Client::_getcwd(string& dir, const UserPerm& perms)
9525 {
9526   filepath path;
9527   ldout(cct, 10) << "getcwd " << *cwd << dendl;
9528
9529   Inode *in = cwd.get();
9530   while (in != root) {
9531     assert(in->dn_set.size() < 2); // dirs can't be hard-linked
9532
9533     // A cwd or ancester is unlinked
9534     if (in->dn_set.empty()) {
9535       return;
9536     }
9537
9538     Dentry *dn = in->get_first_parent();
9539
9540
9541     if (!dn) {
9542       // look it up
9543       ldout(cct, 10) << "getcwd looking up parent for " << *in << dendl;
9544       MetaRequest *req = new MetaRequest(CEPH_MDS_OP_LOOKUPNAME);
9545       filepath path(in->ino);
9546       req->set_filepath(path);
9547       req->set_inode(in);
9548       int res = make_request(req, perms);
9549       if (res < 0)
9550         break;
9551
9552       // start over
9553       path = filepath();
9554       in = cwd.get();
9555       continue;
9556     }
9557     path.push_front_dentry(dn->name);
9558     in = dn->dir->parent_inode;
9559   }
9560   dir = "/";
9561   dir += path.get_path();
9562 }
9563
9564 void Client::getcwd(string& dir, const UserPerm& perms)
9565 {
9566   Mutex::Locker l(client_lock);
9567   if (!unmounting)
9568     _getcwd(dir, perms);
9569 }
9570
9571 int Client::statfs(const char *path, struct statvfs *stbuf,
9572                    const UserPerm& perms)
9573 {
9574   Mutex::Locker l(client_lock);
9575   tout(cct) << "statfs" << std::endl;
9576
9577   if (unmounting)
9578     return -ENOTCONN;
9579
9580   ceph_statfs stats;
9581   C_SaferCond cond;
9582
9583   const vector<int64_t> &data_pools = mdsmap->get_data_pools();
9584   if (data_pools.size() == 1) {
9585     objecter->get_fs_stats(stats, data_pools[0], &cond);
9586   } else {
9587     objecter->get_fs_stats(stats, boost::optional<int64_t>(), &cond);
9588   }
9589
9590   client_lock.Unlock();
9591   int rval = cond.wait();
9592   client_lock.Lock();
9593
9594   if (rval < 0) {
9595     ldout(cct, 1) << "underlying call to statfs returned error: "
9596                   << cpp_strerror(rval)
9597                   << dendl;
9598     return rval;
9599   }
9600
9601   memset(stbuf, 0, sizeof(*stbuf));
9602
9603   /*
9604    * we're going to set a block size of 4MB so we can represent larger
9605    * FSes without overflowing. Additionally convert the space
9606    * measurements from KB to bytes while making them in terms of
9607    * blocks.  We use 4MB only because it is big enough, and because it
9608    * actually *is* the (ceph) default block size.
9609    */
9610   const int CEPH_BLOCK_SHIFT = 22;
9611   stbuf->f_frsize = 1 << CEPH_BLOCK_SHIFT;
9612   stbuf->f_bsize = 1 << CEPH_BLOCK_SHIFT;
9613   stbuf->f_files = stats.num_objects;
9614   stbuf->f_ffree = -1;
9615   stbuf->f_favail = -1;
9616   stbuf->f_fsid = -1;       // ??
9617   stbuf->f_flag = 0;        // ??
9618   stbuf->f_namemax = NAME_MAX;
9619
9620   // Usually quota_root will == root_ancestor, but if the mount root has no
9621   // quota but we can see a parent of it that does have a quota, we'll
9622   // respect that one instead.
9623   assert(root != nullptr);
9624   Inode *quota_root = root->quota.is_enable() ? root : get_quota_root(root, perms);
9625
9626   // get_quota_root should always give us something
9627   // because client quotas are always enabled
9628   assert(quota_root != nullptr);
9629
9630   if (quota_root && cct->_conf->client_quota_df && quota_root->quota.max_bytes) {
9631
9632     // Skip the getattr if any sessions are stale, as we don't want to
9633     // block `df` if this client has e.g. been evicted, or if the MDS cluster
9634     // is unhealthy.
9635     if (!_any_stale_sessions()) {
9636       int r = _getattr(quota_root, 0, perms, true);
9637       if (r != 0) {
9638         // Ignore return value: error getting latest inode metadata is not a good
9639         // reason to break "df".
9640         lderr(cct) << "Error in getattr on quota root 0x"
9641                    << std::hex << quota_root->ino << std::dec
9642                    << " statfs result may be outdated" << dendl;
9643       }
9644     }
9645
9646     // Special case: if there is a size quota set on the Inode acting
9647     // as the root for this client mount, then report the quota status
9648     // as the filesystem statistics.
9649     const fsblkcnt_t total = quota_root->quota.max_bytes >> CEPH_BLOCK_SHIFT;
9650     const fsblkcnt_t used = quota_root->rstat.rbytes >> CEPH_BLOCK_SHIFT;
9651     // It is possible for a quota to be exceeded: arithmetic here must
9652     // handle case where used > total.
9653     const fsblkcnt_t free = total > used ? total - used : 0;
9654
9655     stbuf->f_blocks = total;
9656     stbuf->f_bfree = free;
9657     stbuf->f_bavail = free;
9658   } else {
9659     // General case: report the cluster statistics returned from RADOS. Because
9660     // multiple pools may be used without one filesystem namespace via
9661     // layouts, this is the most correct thing we can do.
9662     stbuf->f_blocks = stats.kb >> (CEPH_BLOCK_SHIFT - 10);
9663     stbuf->f_bfree = stats.kb_avail >> (CEPH_BLOCK_SHIFT - 10);
9664     stbuf->f_bavail = stats.kb_avail >> (CEPH_BLOCK_SHIFT - 10);
9665   }
9666
9667   return rval;
9668 }
9669
9670 int Client::_do_filelock(Inode *in, Fh *fh, int lock_type, int op, int sleep,
9671                          struct flock *fl, uint64_t owner, bool removing)
9672 {
9673   ldout(cct, 10) << "_do_filelock ino " << in->ino
9674                  << (lock_type == CEPH_LOCK_FCNTL ? " fcntl" : " flock")
9675                  << " type " << fl->l_type << " owner " << owner
9676                  << " " << fl->l_start << "~" << fl->l_len << dendl;
9677
9678   int lock_cmd;
9679   if (F_RDLCK == fl->l_type)
9680     lock_cmd = CEPH_LOCK_SHARED;
9681   else if (F_WRLCK == fl->l_type)
9682     lock_cmd = CEPH_LOCK_EXCL;
9683   else if (F_UNLCK == fl->l_type)
9684     lock_cmd = CEPH_LOCK_UNLOCK;
9685   else
9686     return -EIO;
9687
9688   if (op != CEPH_MDS_OP_SETFILELOCK || lock_cmd == CEPH_LOCK_UNLOCK)
9689     sleep = 0;
9690
9691   /*
9692    * Set the most significant bit, so that MDS knows the 'owner'
9693    * is sufficient to identify the owner of lock. (old code uses
9694    * both 'owner' and 'pid')
9695    */
9696   owner |= (1ULL << 63);
9697
9698   MetaRequest *req = new MetaRequest(op);
9699   filepath path;
9700   in->make_nosnap_relative_path(path);
9701   req->set_filepath(path);
9702   req->set_inode(in);
9703
9704   req->head.args.filelock_change.rule = lock_type;
9705   req->head.args.filelock_change.type = lock_cmd;
9706   req->head.args.filelock_change.owner = owner;
9707   req->head.args.filelock_change.pid = fl->l_pid;
9708   req->head.args.filelock_change.start = fl->l_start;
9709   req->head.args.filelock_change.length = fl->l_len;
9710   req->head.args.filelock_change.wait = sleep;
9711
9712   int ret;
9713   bufferlist bl;
9714
9715   if (sleep && switch_interrupt_cb) {
9716     // enable interrupt
9717     switch_interrupt_cb(callback_handle, req->get());
9718     ret = make_request(req, fh->actor_perms, NULL, NULL, -1, &bl);
9719     // disable interrupt
9720     switch_interrupt_cb(callback_handle, NULL);
9721     if (ret == 0 && req->aborted()) {
9722       // effect of this lock request has been revoked by the 'lock intr' request
9723       ret = req->get_abort_code();
9724     }
9725     put_request(req);
9726   } else {
9727     ret = make_request(req, fh->actor_perms, NULL, NULL, -1, &bl);
9728   }
9729
9730   if (ret == 0) {
9731     if (op == CEPH_MDS_OP_GETFILELOCK) {
9732       ceph_filelock filelock;
9733       bufferlist::iterator p = bl.begin();
9734       ::decode(filelock, p);
9735
9736       if (CEPH_LOCK_SHARED == filelock.type)
9737         fl->l_type = F_RDLCK;
9738       else if (CEPH_LOCK_EXCL == filelock.type)
9739         fl->l_type = F_WRLCK;
9740       else
9741         fl->l_type = F_UNLCK;
9742
9743       fl->l_whence = SEEK_SET;
9744       fl->l_start = filelock.start;
9745       fl->l_len = filelock.length;
9746       fl->l_pid = filelock.pid;
9747     } else if (op == CEPH_MDS_OP_SETFILELOCK) {
9748       ceph_lock_state_t *lock_state;
9749       if (lock_type == CEPH_LOCK_FCNTL) {
9750         if (!in->fcntl_locks)
9751           in->fcntl_locks = new ceph_lock_state_t(cct, CEPH_LOCK_FCNTL);
9752         lock_state = in->fcntl_locks;
9753       } else if (lock_type == CEPH_LOCK_FLOCK) {
9754         if (!in->flock_locks)
9755           in->flock_locks = new ceph_lock_state_t(cct, CEPH_LOCK_FLOCK);
9756         lock_state = in->flock_locks;
9757       } else {
9758         ceph_abort();
9759         return -EINVAL;
9760       }
9761       _update_lock_state(fl, owner, lock_state);
9762
9763       if (!removing) {
9764         if (lock_type == CEPH_LOCK_FCNTL) {
9765           if (!fh->fcntl_locks)
9766             fh->fcntl_locks = new ceph_lock_state_t(cct, CEPH_LOCK_FCNTL);
9767           lock_state = fh->fcntl_locks;
9768         } else {
9769           if (!fh->flock_locks)
9770             fh->flock_locks = new ceph_lock_state_t(cct, CEPH_LOCK_FLOCK);
9771           lock_state = fh->flock_locks;
9772         }
9773         _update_lock_state(fl, owner, lock_state);
9774       }
9775     } else
9776       ceph_abort();
9777   }
9778   return ret;
9779 }
9780
9781 int Client::_interrupt_filelock(MetaRequest *req)
9782 {
9783   // Set abort code, but do not kick. The abort code prevents the request
9784   // from being re-sent.
9785   req->abort(-EINTR);
9786   if (req->mds < 0)
9787     return 0; // haven't sent the request
9788
9789   Inode *in = req->inode();
9790
9791   int lock_type;
9792   if (req->head.args.filelock_change.rule == CEPH_LOCK_FLOCK)
9793     lock_type = CEPH_LOCK_FLOCK_INTR;
9794   else if (req->head.args.filelock_change.rule == CEPH_LOCK_FCNTL)
9795     lock_type = CEPH_LOCK_FCNTL_INTR;
9796   else {
9797     ceph_abort();
9798     return -EINVAL;
9799   }
9800
9801   MetaRequest *intr_req = new MetaRequest(CEPH_MDS_OP_SETFILELOCK);
9802   filepath path;
9803   in->make_nosnap_relative_path(path);
9804   intr_req->set_filepath(path);
9805   intr_req->set_inode(in);
9806   intr_req->head.args.filelock_change = req->head.args.filelock_change;
9807   intr_req->head.args.filelock_change.rule = lock_type;
9808   intr_req->head.args.filelock_change.type = CEPH_LOCK_UNLOCK;
9809
9810   UserPerm perms(req->get_uid(), req->get_gid());
9811   return make_request(intr_req, perms, NULL, NULL, -1);
9812 }
9813
9814 void Client::_encode_filelocks(Inode *in, bufferlist& bl)
9815 {
9816   if (!in->fcntl_locks && !in->flock_locks)
9817     return;
9818
9819   unsigned nr_fcntl_locks = in->fcntl_locks ? in->fcntl_locks->held_locks.size() : 0;
9820   ::encode(nr_fcntl_locks, bl);
9821   if (nr_fcntl_locks) {
9822     ceph_lock_state_t* lock_state = in->fcntl_locks;
9823     for(multimap<uint64_t, ceph_filelock>::iterator p = lock_state->held_locks.begin();
9824         p != lock_state->held_locks.end();
9825         ++p)
9826       ::encode(p->second, bl);
9827   }
9828
9829   unsigned nr_flock_locks = in->flock_locks ? in->flock_locks->held_locks.size() : 0;
9830   ::encode(nr_flock_locks, bl);
9831   if (nr_flock_locks) {
9832     ceph_lock_state_t* lock_state = in->flock_locks;
9833     for(multimap<uint64_t, ceph_filelock>::iterator p = lock_state->held_locks.begin();
9834         p != lock_state->held_locks.end();
9835         ++p)
9836       ::encode(p->second, bl);
9837   }
9838
9839   ldout(cct, 10) << "_encode_filelocks ino " << in->ino << ", " << nr_fcntl_locks
9840                  << " fcntl locks, " << nr_flock_locks << " flock locks" <<  dendl;
9841 }
9842
9843 void Client::_release_filelocks(Fh *fh)
9844 {
9845   if (!fh->fcntl_locks && !fh->flock_locks)
9846     return;
9847
9848   Inode *in = fh->inode.get();
9849   ldout(cct, 10) << "_release_filelocks " << fh << " ino " << in->ino << dendl;
9850
9851   list<pair<int, ceph_filelock> > to_release;
9852
9853   if (fh->fcntl_locks) {
9854     ceph_lock_state_t* lock_state = fh->fcntl_locks;
9855     for(multimap<uint64_t, ceph_filelock>::iterator p = lock_state->held_locks.begin();
9856         p != lock_state->held_locks.end();
9857         ++p)
9858       to_release.push_back(pair<int, ceph_filelock>(CEPH_LOCK_FCNTL, p->second));
9859     delete fh->fcntl_locks;
9860   }
9861   if (fh->flock_locks) {
9862     ceph_lock_state_t* lock_state = fh->flock_locks;
9863     for(multimap<uint64_t, ceph_filelock>::iterator p = lock_state->held_locks.begin();
9864         p != lock_state->held_locks.end();
9865         ++p)
9866       to_release.push_back(pair<int, ceph_filelock>(CEPH_LOCK_FLOCK, p->second));
9867     delete fh->flock_locks;
9868   }
9869
9870   if (to_release.empty())
9871     return;
9872
9873   struct flock fl;
9874   memset(&fl, 0, sizeof(fl));
9875   fl.l_whence = SEEK_SET;
9876   fl.l_type = F_UNLCK;
9877
9878   for (list<pair<int, ceph_filelock> >::iterator p = to_release.begin();
9879        p != to_release.end();
9880        ++p) {
9881     fl.l_start = p->second.start;
9882     fl.l_len = p->second.length;
9883     fl.l_pid = p->second.pid;
9884     _do_filelock(in, fh, p->first, CEPH_MDS_OP_SETFILELOCK, 0, &fl,
9885                  p->second.owner, true);
9886   }
9887 }
9888
9889 void Client::_update_lock_state(struct flock *fl, uint64_t owner,
9890                                 ceph_lock_state_t *lock_state)
9891 {
9892   int lock_cmd;
9893   if (F_RDLCK == fl->l_type)
9894     lock_cmd = CEPH_LOCK_SHARED;
9895   else if (F_WRLCK == fl->l_type)
9896     lock_cmd = CEPH_LOCK_EXCL;
9897   else
9898     lock_cmd = CEPH_LOCK_UNLOCK;;
9899
9900   ceph_filelock filelock;
9901   filelock.start = fl->l_start;
9902   filelock.length = fl->l_len;
9903   filelock.client = 0;
9904   // see comment in _do_filelock()
9905   filelock.owner = owner | (1ULL << 63);
9906   filelock.pid = fl->l_pid;
9907   filelock.type = lock_cmd;
9908
9909   if (filelock.type == CEPH_LOCK_UNLOCK) {
9910     list<ceph_filelock> activated_locks;
9911     lock_state->remove_lock(filelock, activated_locks);
9912   } else {
9913     bool r = lock_state->add_lock(filelock, false, false, NULL);
9914     assert(r);
9915   }
9916 }
9917
9918 int Client::_getlk(Fh *fh, struct flock *fl, uint64_t owner)
9919 {
9920   Inode *in = fh->inode.get();
9921   ldout(cct, 10) << "_getlk " << fh << " ino " << in->ino << dendl;
9922   int ret = _do_filelock(in, fh, CEPH_LOCK_FCNTL, CEPH_MDS_OP_GETFILELOCK, 0, fl, owner);
9923   return ret;
9924 }
9925
9926 int Client::_setlk(Fh *fh, struct flock *fl, uint64_t owner, int sleep)
9927 {
9928   Inode *in = fh->inode.get();
9929   ldout(cct, 10) << "_setlk " << fh << " ino " << in->ino << dendl;
9930   int ret =  _do_filelock(in, fh, CEPH_LOCK_FCNTL, CEPH_MDS_OP_SETFILELOCK, sleep, fl, owner);
9931   ldout(cct, 10) << "_setlk " << fh << " ino " << in->ino << " result=" << ret << dendl;
9932   return ret;
9933 }
9934
9935 int Client::_flock(Fh *fh, int cmd, uint64_t owner)
9936 {
9937   Inode *in = fh->inode.get();
9938   ldout(cct, 10) << "_flock " << fh << " ino " << in->ino << dendl;
9939
9940   int sleep = !(cmd & LOCK_NB);
9941   cmd &= ~LOCK_NB;
9942
9943   int type;
9944   switch (cmd) {
9945     case LOCK_SH:
9946       type = F_RDLCK;
9947       break;
9948     case LOCK_EX:
9949       type = F_WRLCK;
9950       break;
9951     case LOCK_UN:
9952       type = F_UNLCK;
9953       break;
9954     default:
9955       return -EINVAL;
9956   }
9957
9958   struct flock fl;
9959   memset(&fl, 0, sizeof(fl));
9960   fl.l_type = type;
9961   fl.l_whence = SEEK_SET;
9962
9963   int ret =  _do_filelock(in, fh, CEPH_LOCK_FLOCK, CEPH_MDS_OP_SETFILELOCK, sleep, &fl, owner);
9964   ldout(cct, 10) << "_flock " << fh << " ino " << in->ino << " result=" << ret << dendl;
9965   return ret;
9966 }
9967
9968 int Client::ll_statfs(Inode *in, struct statvfs *stbuf, const UserPerm& perms)
9969 {
9970   /* Since the only thing this does is wrap a call to statfs, and
9971      statfs takes a lock, it doesn't seem we have a need to split it
9972      out. */
9973   return statfs(0, stbuf, perms);
9974 }
9975
9976 void Client::ll_register_callbacks(struct client_callback_args *args)
9977 {
9978   if (!args)
9979     return;
9980   Mutex::Locker l(client_lock);
9981   ldout(cct, 10) << "ll_register_callbacks cb " << args->handle
9982                  << " invalidate_ino_cb " << args->ino_cb
9983                  << " invalidate_dentry_cb " << args->dentry_cb
9984                  << " getgroups_cb" << args->getgroups_cb
9985                  << " switch_interrupt_cb " << args->switch_intr_cb
9986                  << " remount_cb " << args->remount_cb
9987                  << dendl;
9988   callback_handle = args->handle;
9989   if (args->ino_cb) {
9990     ino_invalidate_cb = args->ino_cb;
9991     async_ino_invalidator.start();
9992   }
9993   if (args->dentry_cb) {
9994     dentry_invalidate_cb = args->dentry_cb;
9995     async_dentry_invalidator.start();
9996   }
9997   if (args->switch_intr_cb) {
9998     switch_interrupt_cb = args->switch_intr_cb;
9999     interrupt_finisher.start();
10000   }
10001   if (args->remount_cb) {
10002     remount_cb = args->remount_cb;
10003     remount_finisher.start();
10004   }
10005   getgroups_cb = args->getgroups_cb;
10006   umask_cb = args->umask_cb;
10007 }
10008
10009 int Client::test_dentry_handling(bool can_invalidate)
10010 {
10011   int r = 0;
10012
10013   can_invalidate_dentries = can_invalidate;
10014
10015   if (can_invalidate_dentries) {
10016     assert(dentry_invalidate_cb);
10017     ldout(cct, 1) << "using dentry_invalidate_cb" << dendl;
10018   } else if (remount_cb) {
10019     ldout(cct, 1) << "using remount_cb" << dendl;
10020     int s = remount_cb(callback_handle);
10021     if (s) {
10022       lderr(cct) << "Failed to invoke remount, needed to ensure kernel dcache consistency"
10023                  << dendl;
10024     }
10025     if (cct->_conf->client_die_on_failed_remount) {
10026       require_remount = true;
10027       r = s;
10028     }
10029   } else {
10030     lderr(cct) << "no method to invalidate kernel dentry cache; expect issues!" << dendl;
10031     if (cct->_conf->client_die_on_failed_remount)
10032       ceph_abort();
10033   }
10034   return r;
10035 }
10036
10037 int Client::_sync_fs()
10038 {
10039   ldout(cct, 10) << "_sync_fs" << dendl;
10040
10041   // flush file data
10042   Mutex lock("Client::_fsync::lock");
10043   Cond cond;
10044   bool flush_done = false;
10045   if (cct->_conf->client_oc)
10046     objectcacher->flush_all(new C_SafeCond(&lock, &cond, &flush_done));
10047   else
10048     flush_done = true;
10049
10050   // flush caps
10051   flush_caps_sync();
10052   ceph_tid_t flush_tid = last_flush_tid;
10053
10054   // wait for unsafe mds requests
10055   wait_unsafe_requests();
10056
10057   wait_sync_caps(flush_tid);
10058
10059   if (!flush_done) {
10060     client_lock.Unlock();
10061     lock.Lock();
10062     ldout(cct, 15) << "waiting on data to flush" << dendl;
10063     while (!flush_done)
10064       cond.Wait(lock);
10065     lock.Unlock();
10066     client_lock.Lock();
10067   }
10068
10069   return 0;
10070 }
10071
10072 int Client::sync_fs()
10073 {
10074   Mutex::Locker l(client_lock);
10075
10076   if (unmounting)
10077     return -ENOTCONN;
10078
10079   return _sync_fs();
10080 }
10081
10082 int64_t Client::drop_caches()
10083 {
10084   Mutex::Locker l(client_lock);
10085   return objectcacher->release_all();
10086 }
10087
10088
10089 int Client::lazyio_propogate(int fd, loff_t offset, size_t count)
10090 {
10091   Mutex::Locker l(client_lock);
10092   ldout(cct, 3) << "op: client->lazyio_propogate(" << fd
10093           << ", " << offset << ", " << count << ")" << dendl;
10094   
10095   Fh *f = get_filehandle(fd);
10096   if (!f)
10097     return -EBADF;
10098
10099   // for now
10100   _fsync(f, true);
10101
10102   return 0;
10103 }
10104
10105 int Client::lazyio_synchronize(int fd, loff_t offset, size_t count)
10106 {
10107   Mutex::Locker l(client_lock);
10108   ldout(cct, 3) << "op: client->lazyio_synchronize(" << fd
10109           << ", " << offset << ", " << count << ")" << dendl;
10110   
10111   Fh *f = get_filehandle(fd);
10112   if (!f)
10113     return -EBADF;
10114   Inode *in = f->inode.get();
10115   
10116   _fsync(f, true);
10117   if (_release(in))
10118     check_caps(in, 0);
10119   return 0;
10120 }
10121
10122
10123 // =============================
10124 // snaps
10125
10126 int Client::mksnap(const char *relpath, const char *name, const UserPerm& perm)
10127 {
10128   Mutex::Locker l(client_lock);
10129
10130   if (unmounting)
10131     return -ENOTCONN;
10132
10133   filepath path(relpath);
10134   InodeRef in;
10135   int r = path_walk(path, &in, perm);
10136   if (r < 0)
10137     return r;
10138   if (cct->_conf->client_permissions) {
10139     r = may_create(in.get(), perm);
10140     if (r < 0)
10141       return r;
10142   }
10143   Inode *snapdir = open_snapdir(in.get());
10144   return _mkdir(snapdir, name, 0, perm);
10145 }
10146
10147 int Client::rmsnap(const char *relpath, const char *name, const UserPerm& perms)
10148 {
10149   Mutex::Locker l(client_lock);
10150
10151   if (unmounting)
10152     return -ENOTCONN;
10153
10154   filepath path(relpath);
10155   InodeRef in;
10156   int r = path_walk(path, &in, perms);
10157   if (r < 0)
10158     return r;
10159   if (cct->_conf->client_permissions) {
10160     r = may_delete(in.get(), NULL, perms);
10161     if (r < 0)
10162       return r;
10163   }
10164   Inode *snapdir = open_snapdir(in.get());
10165   return _rmdir(snapdir, name, perms);
10166 }
10167
10168 // =============================
10169 // expose caps
10170
10171 int Client::get_caps_issued(int fd) {
10172
10173   Mutex::Locker lock(client_lock);
10174
10175   if (unmounting)
10176     return -ENOTCONN;
10177
10178   Fh *f = get_filehandle(fd);
10179   if (!f)
10180     return -EBADF;
10181
10182   return f->inode->caps_issued();
10183 }
10184
10185 int Client::get_caps_issued(const char *path, const UserPerm& perms)
10186 {
10187   Mutex::Locker lock(client_lock);
10188
10189   if (unmounting)
10190     return -ENOTCONN;
10191
10192   filepath p(path);
10193   InodeRef in;
10194   int r = path_walk(p, &in, perms, true);
10195   if (r < 0)
10196     return r;
10197   return in->caps_issued();
10198 }
10199
10200 // =========================================
10201 // low level
10202
10203 Inode *Client::open_snapdir(Inode *diri)
10204 {
10205   Inode *in;
10206   vinodeno_t vino(diri->ino, CEPH_SNAPDIR);
10207   if (!inode_map.count(vino)) {
10208     in = new Inode(this, vino, &diri->layout);
10209
10210     in->ino = diri->ino;
10211     in->snapid = CEPH_SNAPDIR;
10212     in->mode = diri->mode;
10213     in->uid = diri->uid;
10214     in->gid = diri->gid;
10215     in->mtime = diri->mtime;
10216     in->ctime = diri->ctime;
10217     in->btime = diri->btime;
10218     in->size = diri->size;
10219     in->change_attr = diri->change_attr;
10220
10221     in->dirfragtree.clear();
10222     in->snapdir_parent = diri;
10223     diri->flags |= I_SNAPDIR_OPEN;
10224     inode_map[vino] = in;
10225     if (use_faked_inos())
10226       _assign_faked_ino(in);
10227     ldout(cct, 10) << "open_snapdir created snapshot inode " << *in << dendl;
10228   } else {
10229     in = inode_map[vino];
10230     ldout(cct, 10) << "open_snapdir had snapshot inode " << *in << dendl;
10231   }
10232   return in;
10233 }
10234
10235 int Client::ll_lookup(Inode *parent, const char *name, struct stat *attr,
10236                       Inode **out, const UserPerm& perms)
10237 {
10238   Mutex::Locker lock(client_lock);
10239   vinodeno_t vparent = _get_vino(parent);
10240   ldout(cct, 3) << "ll_lookup " << vparent << " " << name << dendl;
10241   tout(cct) << "ll_lookup" << std::endl;
10242   tout(cct) << name << std::endl;
10243
10244   if (unmounting)
10245     return -ENOTCONN;
10246
10247   int r = 0;
10248   if (!cct->_conf->fuse_default_permissions) {
10249     r = may_lookup(parent, perms);
10250     if (r < 0)
10251       return r;
10252   }
10253
10254   string dname(name);
10255   InodeRef in;
10256
10257   r = _lookup(parent, dname, CEPH_STAT_CAP_INODE_ALL, &in, perms);
10258   if (r < 0) {
10259     attr->st_ino = 0;
10260     goto out;
10261   }
10262
10263   assert(in);
10264   fill_stat(in, attr);
10265   _ll_get(in.get());
10266
10267  out:
10268   ldout(cct, 3) << "ll_lookup " << vparent << " " << name
10269           << " -> " << r << " (" << hex << attr->st_ino << dec << ")" << dendl;
10270   tout(cct) << attr->st_ino << std::endl;
10271   *out = in.get();
10272   return r;
10273 }
10274
10275 int Client::ll_lookupx(Inode *parent, const char *name, Inode **out,
10276                        struct ceph_statx *stx, unsigned want, unsigned flags,
10277                        const UserPerm& perms)
10278 {
10279   Mutex::Locker lock(client_lock);
10280   vinodeno_t vparent = _get_vino(parent);
10281   ldout(cct, 3) << "ll_lookupx " << vparent << " " << name << dendl;
10282   tout(cct) << "ll_lookupx" << std::endl;
10283   tout(cct) << name << std::endl;
10284
10285   if (unmounting)
10286     return -ENOTCONN;
10287
10288   int r = 0;
10289   if (!cct->_conf->fuse_default_permissions) {
10290     r = may_lookup(parent, perms);
10291     if (r < 0)
10292       return r;
10293   }
10294
10295   string dname(name);
10296   InodeRef in;
10297
10298   unsigned mask = statx_to_mask(flags, want);
10299   r = _lookup(parent, dname, mask, &in, perms);
10300   if (r < 0) {
10301     stx->stx_ino = 0;
10302     stx->stx_mask = 0;
10303   } else {
10304     assert(in);
10305     fill_statx(in, mask, stx);
10306     _ll_get(in.get());
10307   }
10308
10309   ldout(cct, 3) << "ll_lookupx " << vparent << " " << name
10310           << " -> " << r << " (" << hex << stx->stx_ino << dec << ")" << dendl;
10311   tout(cct) << stx->stx_ino << std::endl;
10312   *out = in.get();
10313   return r;
10314 }
10315
10316 int Client::ll_walk(const char* name, Inode **out, struct ceph_statx *stx,
10317                     unsigned int want, unsigned int flags, const UserPerm& perms)
10318 {
10319   Mutex::Locker lock(client_lock);
10320
10321   if (unmounting)
10322     return -ENOTCONN;
10323
10324   filepath fp(name, 0);
10325   InodeRef in;
10326   int rc;
10327   unsigned mask = statx_to_mask(flags, want);
10328
10329   ldout(cct, 3) << "ll_walk" << name << dendl;
10330   tout(cct) << "ll_walk" << std::endl;
10331   tout(cct) << name << std::endl;
10332
10333   rc = path_walk(fp, &in, perms, !(flags & AT_SYMLINK_NOFOLLOW), mask);
10334   if (rc < 0) {
10335     /* zero out mask, just in case... */
10336     stx->stx_mask = 0;
10337     stx->stx_ino = 0;
10338     *out = NULL;
10339     return rc;
10340   } else {
10341     assert(in);
10342     fill_statx(in, mask, stx);
10343     _ll_get(in.get());
10344     *out = in.get();
10345     return 0;
10346   }
10347 }
10348
10349 void Client::_ll_get(Inode *in)
10350 {
10351   if (in->ll_ref == 0) {
10352     in->get();
10353     if (in->is_dir() && !in->dn_set.empty()) {
10354       assert(in->dn_set.size() == 1); // dirs can't be hard-linked
10355       in->get_first_parent()->get(); // pin dentry
10356     }
10357   }
10358   in->ll_get();
10359   ldout(cct, 20) << "_ll_get " << in << " " << in->ino << " -> " << in->ll_ref << dendl;
10360 }
10361
10362 int Client::_ll_put(Inode *in, int num)
10363 {
10364   in->ll_put(num);
10365   ldout(cct, 20) << "_ll_put " << in << " " << in->ino << " " << num << " -> " << in->ll_ref << dendl;
10366   if (in->ll_ref == 0) {
10367     if (in->is_dir() && !in->dn_set.empty()) {
10368       assert(in->dn_set.size() == 1); // dirs can't be hard-linked
10369       in->get_first_parent()->put(); // unpin dentry
10370     }
10371     put_inode(in);
10372     return 0;
10373   } else {
10374     return in->ll_ref;
10375   }
10376 }
10377
10378 void Client::_ll_drop_pins()
10379 {
10380   ldout(cct, 10) << "_ll_drop_pins" << dendl;
10381   ceph::unordered_map<vinodeno_t, Inode*>::iterator next;
10382   for (ceph::unordered_map<vinodeno_t, Inode*>::iterator it = inode_map.begin();
10383        it != inode_map.end();
10384        it = next) {
10385     Inode *in = it->second;
10386     next = it;
10387     ++next;
10388     if (in->ll_ref)
10389       _ll_put(in, in->ll_ref);
10390   }
10391 }
10392
10393 bool Client::ll_forget(Inode *in, int count)
10394 {
10395   Mutex::Locker lock(client_lock);
10396   inodeno_t ino = _get_inodeno(in);
10397
10398   ldout(cct, 3) << "ll_forget " << ino << " " << count << dendl;
10399   tout(cct) << "ll_forget" << std::endl;
10400   tout(cct) << ino.val << std::endl;
10401   tout(cct) << count << std::endl;
10402
10403   // Ignore forget if we're no longer mounted
10404   if (unmounting)
10405     return true;
10406
10407   if (ino == 1) return true;  // ignore forget on root.
10408
10409   bool last = false;
10410   if (in->ll_ref < count) {
10411     ldout(cct, 1) << "WARNING: ll_forget on " << ino << " " << count
10412                   << ", which only has ll_ref=" << in->ll_ref << dendl;
10413     _ll_put(in, in->ll_ref);
10414     last = true;
10415   } else {
10416     if (_ll_put(in, count) == 0)
10417       last = true;
10418   }
10419
10420   return last;
10421 }
10422
10423 bool Client::ll_put(Inode *in)
10424 {
10425   /* ll_forget already takes the lock */
10426   return ll_forget(in, 1);
10427 }
10428
10429 snapid_t Client::ll_get_snapid(Inode *in)
10430 {
10431   Mutex::Locker lock(client_lock);
10432   return in->snapid;
10433 }
10434
10435 Inode *Client::ll_get_inode(ino_t ino)
10436 {
10437   Mutex::Locker lock(client_lock);
10438
10439   if (unmounting)
10440     return NULL;
10441
10442   vinodeno_t vino = _map_faked_ino(ino);
10443   unordered_map<vinodeno_t,Inode*>::iterator p = inode_map.find(vino);
10444   if (p == inode_map.end())
10445     return NULL;
10446   Inode *in = p->second;
10447   _ll_get(in);
10448   return in;
10449 }
10450
10451 Inode *Client::ll_get_inode(vinodeno_t vino)
10452 {
10453   Mutex::Locker lock(client_lock);
10454
10455   if (unmounting)
10456     return NULL;
10457
10458   unordered_map<vinodeno_t,Inode*>::iterator p = inode_map.find(vino);
10459   if (p == inode_map.end())
10460     return NULL;
10461   Inode *in = p->second;
10462   _ll_get(in);
10463   return in;
10464 }
10465
10466 int Client::_ll_getattr(Inode *in, int caps, const UserPerm& perms)
10467 {
10468   vinodeno_t vino = _get_vino(in);
10469
10470   ldout(cct, 3) << "ll_getattr " << vino << dendl;
10471   tout(cct) << "ll_getattr" << std::endl;
10472   tout(cct) << vino.ino.val << std::endl;
10473
10474   if (vino.snapid < CEPH_NOSNAP)
10475     return 0;
10476   else
10477     return _getattr(in, caps, perms);
10478 }
10479
10480 int Client::ll_getattr(Inode *in, struct stat *attr, const UserPerm& perms)
10481 {
10482   Mutex::Locker lock(client_lock);
10483
10484   if (unmounting)
10485     return -ENOTCONN;
10486
10487   int res = _ll_getattr(in, CEPH_STAT_CAP_INODE_ALL, perms);
10488
10489   if (res == 0)
10490     fill_stat(in, attr);
10491   ldout(cct, 3) << "ll_getattr " << _get_vino(in) << " = " << res << dendl;
10492   return res;
10493 }
10494
10495 int Client::ll_getattrx(Inode *in, struct ceph_statx *stx, unsigned int want,
10496                         unsigned int flags, const UserPerm& perms)
10497 {
10498   Mutex::Locker lock(client_lock);
10499
10500   if (unmounting)
10501     return -ENOTCONN;
10502
10503   int res = 0;
10504   unsigned mask = statx_to_mask(flags, want);
10505
10506   if (mask && !in->caps_issued_mask(mask))
10507     res = _ll_getattr(in, mask, perms);
10508
10509   if (res == 0)
10510     fill_statx(in, mask, stx);
10511   ldout(cct, 3) << "ll_getattrx " << _get_vino(in) << " = " << res << dendl;
10512   return res;
10513 }
10514
10515 int Client::_ll_setattrx(Inode *in, struct ceph_statx *stx, int mask,
10516                          const UserPerm& perms, InodeRef *inp)
10517 {
10518   vinodeno_t vino = _get_vino(in);
10519
10520   ldout(cct, 3) << "ll_setattrx " << vino << " mask " << hex << mask << dec
10521                 << dendl;
10522   tout(cct) << "ll_setattrx" << std::endl;
10523   tout(cct) << vino.ino.val << std::endl;
10524   tout(cct) << stx->stx_mode << std::endl;
10525   tout(cct) << stx->stx_uid << std::endl;
10526   tout(cct) << stx->stx_gid << std::endl;
10527   tout(cct) << stx->stx_size << std::endl;
10528   tout(cct) << stx->stx_mtime << std::endl;
10529   tout(cct) << stx->stx_atime << std::endl;
10530   tout(cct) << stx->stx_btime << std::endl;
10531   tout(cct) << mask << std::endl;
10532
10533   if (!cct->_conf->fuse_default_permissions) {
10534     int res = may_setattr(in, stx, mask, perms);
10535     if (res < 0)
10536       return res;
10537   }
10538
10539   mask &= ~(CEPH_SETATTR_MTIME_NOW | CEPH_SETATTR_ATIME_NOW);
10540
10541   return __setattrx(in, stx, mask, perms, inp);
10542 }
10543
10544 int Client::ll_setattrx(Inode *in, struct ceph_statx *stx, int mask,
10545                         const UserPerm& perms)
10546 {
10547   Mutex::Locker lock(client_lock);
10548
10549   if (unmounting)
10550     return -ENOTCONN;
10551
10552   InodeRef target(in);
10553   int res = _ll_setattrx(in, stx, mask, perms, &target);
10554   if (res == 0) {
10555     assert(in == target.get());
10556     fill_statx(in, in->caps_issued(), stx);
10557   }
10558
10559   ldout(cct, 3) << "ll_setattrx " << _get_vino(in) << " = " << res << dendl;
10560   return res;
10561 }
10562
10563 int Client::ll_setattr(Inode *in, struct stat *attr, int mask,
10564                        const UserPerm& perms)
10565 {
10566   struct ceph_statx stx;
10567   stat_to_statx(attr, &stx);
10568
10569   Mutex::Locker lock(client_lock);
10570
10571   if (unmounting)
10572     return -ENOTCONN;
10573
10574   InodeRef target(in);
10575   int res = _ll_setattrx(in, &stx, mask, perms, &target);
10576   if (res == 0) {
10577     assert(in == target.get());
10578     fill_stat(in, attr);
10579   }
10580
10581   ldout(cct, 3) << "ll_setattr " << _get_vino(in) << " = " << res << dendl;
10582   return res;
10583 }
10584
10585
10586 // ----------
10587 // xattrs
10588
10589 int Client::getxattr(const char *path, const char *name, void *value, size_t size,
10590                      const UserPerm& perms)
10591 {
10592   Mutex::Locker lock(client_lock);
10593
10594   if (unmounting)
10595     return -ENOTCONN;
10596
10597   InodeRef in;
10598   int r = Client::path_walk(path, &in, perms, true, CEPH_STAT_CAP_XATTR);
10599   if (r < 0)
10600     return r;
10601   return _getxattr(in, name, value, size, perms);
10602 }
10603
10604 int Client::lgetxattr(const char *path, const char *name, void *value, size_t size,
10605                       const UserPerm& perms)
10606 {
10607   Mutex::Locker lock(client_lock);
10608
10609   if (unmounting)
10610     return -ENOTCONN;
10611
10612   InodeRef in;
10613   int r = Client::path_walk(path, &in, perms, false, CEPH_STAT_CAP_XATTR);
10614   if (r < 0)
10615     return r;
10616   return _getxattr(in, name, value, size, perms);
10617 }
10618
10619 int Client::fgetxattr(int fd, const char *name, void *value, size_t size,
10620                       const UserPerm& perms)
10621 {
10622   Mutex::Locker lock(client_lock);
10623
10624   if (unmounting)
10625     return -ENOTCONN;
10626
10627   Fh *f = get_filehandle(fd);
10628   if (!f)
10629     return -EBADF;
10630   return _getxattr(f->inode, name, value, size, perms);
10631 }
10632
10633 int Client::listxattr(const char *path, char *list, size_t size,
10634                       const UserPerm& perms)
10635 {
10636   Mutex::Locker lock(client_lock);
10637
10638   if (unmounting)
10639     return -ENOTCONN;
10640
10641   InodeRef in;
10642   int r = Client::path_walk(path, &in, perms, true, CEPH_STAT_CAP_XATTR);
10643   if (r < 0)
10644     return r;
10645   return Client::_listxattr(in.get(), list, size, perms);
10646 }
10647
10648 int Client::llistxattr(const char *path, char *list, size_t size,
10649                        const UserPerm& perms)
10650 {
10651   Mutex::Locker lock(client_lock);
10652
10653   if (unmounting)
10654     return -ENOTCONN;
10655
10656   InodeRef in;
10657   int r = Client::path_walk(path, &in, perms, false, CEPH_STAT_CAP_XATTR);
10658   if (r < 0)
10659     return r;
10660   return Client::_listxattr(in.get(), list, size, perms);
10661 }
10662
10663 int Client::flistxattr(int fd, char *list, size_t size, const UserPerm& perms)
10664 {
10665   Mutex::Locker lock(client_lock);
10666
10667   if (unmounting)
10668     return -ENOTCONN;
10669
10670   Fh *f = get_filehandle(fd);
10671   if (!f)
10672     return -EBADF;
10673   return Client::_listxattr(f->inode.get(), list, size, perms);
10674 }
10675
10676 int Client::removexattr(const char *path, const char *name,
10677                         const UserPerm& perms)
10678 {
10679   Mutex::Locker lock(client_lock);
10680
10681   if (unmounting)
10682     return -ENOTCONN;
10683
10684   InodeRef in;
10685   int r = Client::path_walk(path, &in, perms, true);
10686   if (r < 0)
10687     return r;
10688   return _removexattr(in, name, perms);
10689 }
10690
10691 int Client::lremovexattr(const char *path, const char *name,
10692                          const UserPerm& perms)
10693 {
10694   Mutex::Locker lock(client_lock);
10695
10696   if (unmounting)
10697     return -ENOTCONN;
10698
10699   InodeRef in;
10700   int r = Client::path_walk(path, &in, perms, false);
10701   if (r < 0)
10702     return r;
10703   return _removexattr(in, name, perms);
10704 }
10705
10706 int Client::fremovexattr(int fd, const char *name, const UserPerm& perms)
10707 {
10708   Mutex::Locker lock(client_lock);
10709
10710   if (unmounting)
10711     return -ENOTCONN;
10712
10713   Fh *f = get_filehandle(fd);
10714   if (!f)
10715     return -EBADF;
10716   return _removexattr(f->inode, name, perms);
10717 }
10718
10719 int Client::setxattr(const char *path, const char *name, const void *value,
10720                      size_t size, int flags, const UserPerm& perms)
10721 {
10722   _setxattr_maybe_wait_for_osdmap(name, value, size);
10723
10724   Mutex::Locker lock(client_lock);
10725
10726   if (unmounting)
10727     return -ENOTCONN;
10728
10729   InodeRef in;
10730   int r = Client::path_walk(path, &in, perms, true);
10731   if (r < 0)
10732     return r;
10733   return _setxattr(in, name, value, size, flags, perms);
10734 }
10735
10736 int Client::lsetxattr(const char *path, const char *name, const void *value,
10737                       size_t size, int flags, const UserPerm& perms)
10738 {
10739   _setxattr_maybe_wait_for_osdmap(name, value, size);
10740
10741   Mutex::Locker lock(client_lock);
10742
10743   if (unmounting)
10744     return -ENOTCONN;
10745
10746   InodeRef in;
10747   int r = Client::path_walk(path, &in, perms, false);
10748   if (r < 0)
10749     return r;
10750   return _setxattr(in, name, value, size, flags, perms);
10751 }
10752
10753 int Client::fsetxattr(int fd, const char *name, const void *value, size_t size,
10754                       int flags, const UserPerm& perms)
10755 {
10756   _setxattr_maybe_wait_for_osdmap(name, value, size);
10757
10758   Mutex::Locker lock(client_lock);
10759
10760   if (unmounting)
10761     return -ENOTCONN;
10762
10763   Fh *f = get_filehandle(fd);
10764   if (!f)
10765     return -EBADF;
10766   return _setxattr(f->inode, name, value, size, flags, perms);
10767 }
10768
10769 int Client::_getxattr(Inode *in, const char *name, void *value, size_t size,
10770                       const UserPerm& perms)
10771 {
10772   int r;
10773
10774   const VXattr *vxattr = _match_vxattr(in, name);
10775   if (vxattr) {
10776     r = -ENODATA;
10777
10778     // Do a force getattr to get the latest quota before returning
10779     // a value to userspace.
10780     r = _getattr(in, 0, perms, true);
10781     if (r != 0) {
10782       // Error from getattr!
10783       return r;
10784     }
10785
10786     // call pointer-to-member function
10787     char buf[256];
10788     if (!(vxattr->exists_cb && !(this->*(vxattr->exists_cb))(in))) {
10789       r = (this->*(vxattr->getxattr_cb))(in, buf, sizeof(buf));
10790     } else {
10791       r = -ENODATA;
10792     }
10793
10794     if (size != 0) {
10795       if (r > (int)size) {
10796         r = -ERANGE;
10797       } else if (r > 0) {
10798         memcpy(value, buf, r);
10799       }
10800     }
10801     goto out;
10802   }
10803
10804   if (acl_type == NO_ACL && !strncmp(name, "system.", 7)) {
10805     r = -EOPNOTSUPP;
10806     goto out;
10807   }
10808
10809   r = _getattr(in, CEPH_STAT_CAP_XATTR, perms, in->xattr_version == 0);
10810   if (r == 0) {
10811     string n(name);
10812     r = -ENODATA;
10813    if (in->xattrs.count(n)) {
10814       r = in->xattrs[n].length();
10815       if (r > 0 && size != 0) {
10816         if (size >= (unsigned)r)
10817           memcpy(value, in->xattrs[n].c_str(), r);
10818         else
10819           r = -ERANGE;
10820       }
10821     }
10822   }
10823  out:
10824   ldout(cct, 3) << "_getxattr(" << in->ino << ", \"" << name << "\", " << size << ") = " << r << dendl;
10825   return r;
10826 }
10827
10828 int Client::_getxattr(InodeRef &in, const char *name, void *value, size_t size,
10829                       const UserPerm& perms)
10830 {
10831   if (cct->_conf->client_permissions) {
10832     int r = xattr_permission(in.get(), name, MAY_READ, perms);
10833     if (r < 0)
10834       return r;
10835   }
10836   return _getxattr(in.get(), name, value, size, perms);
10837 }
10838
10839 int Client::ll_getxattr(Inode *in, const char *name, void *value,
10840                         size_t size, const UserPerm& perms)
10841 {
10842   Mutex::Locker lock(client_lock);
10843
10844   if (unmounting)
10845     return -ENOTCONN;
10846
10847   vinodeno_t vino = _get_vino(in);
10848
10849   ldout(cct, 3) << "ll_getxattr " << vino << " " << name << " size " << size << dendl;
10850   tout(cct) << "ll_getxattr" << std::endl;
10851   tout(cct) << vino.ino.val << std::endl;
10852   tout(cct) << name << std::endl;
10853
10854   if (!cct->_conf->fuse_default_permissions) {
10855     int r = xattr_permission(in, name, MAY_READ, perms);
10856     if (r < 0)
10857       return r;
10858   }
10859
10860   return _getxattr(in, name, value, size, perms);
10861 }
10862
10863 int Client::_listxattr(Inode *in, char *name, size_t size,
10864                        const UserPerm& perms)
10865 {
10866   int r = _getattr(in, CEPH_STAT_CAP_XATTR, perms, in->xattr_version == 0);
10867   if (r == 0) {
10868     for (map<string,bufferptr>::iterator p = in->xattrs.begin();
10869          p != in->xattrs.end();
10870          ++p)
10871       r += p->first.length() + 1;
10872
10873     const VXattr *vxattrs = _get_vxattrs(in);
10874     r += _vxattrs_name_size(vxattrs);
10875
10876     if (size != 0) {
10877       if (size >= (unsigned)r) {
10878         for (map<string,bufferptr>::iterator p = in->xattrs.begin();
10879              p != in->xattrs.end();
10880              ++p) {
10881           memcpy(name, p->first.c_str(), p->first.length());
10882           name += p->first.length();
10883           *name = '\0';
10884           name++;
10885         }
10886         if (vxattrs) {
10887           for (int i = 0; !vxattrs[i].name.empty(); i++) {
10888             const VXattr& vxattr = vxattrs[i];
10889             if (vxattr.hidden)
10890               continue;
10891             // call pointer-to-member function
10892             if(vxattr.exists_cb && !(this->*(vxattr.exists_cb))(in))
10893               continue;
10894             memcpy(name, vxattr.name.c_str(), vxattr.name.length());
10895             name += vxattr.name.length();
10896             *name = '\0';
10897             name++;
10898           }
10899         }
10900       } else
10901         r = -ERANGE;
10902     }
10903   }
10904   ldout(cct, 3) << "_listxattr(" << in->ino << ", " << size << ") = " << r << dendl;
10905   return r;
10906 }
10907
10908 int Client::ll_listxattr(Inode *in, char *names, size_t size,
10909                          const UserPerm& perms)
10910 {
10911   Mutex::Locker lock(client_lock);
10912
10913   if (unmounting)
10914     return -ENOTCONN;
10915
10916   vinodeno_t vino = _get_vino(in);
10917
10918   ldout(cct, 3) << "ll_listxattr " << vino << " size " << size << dendl;
10919   tout(cct) << "ll_listxattr" << std::endl;
10920   tout(cct) << vino.ino.val << std::endl;
10921   tout(cct) << size << std::endl;
10922
10923   return _listxattr(in, names, size, perms);
10924 }
10925
10926 int Client::_do_setxattr(Inode *in, const char *name, const void *value,
10927                          size_t size, int flags, const UserPerm& perms)
10928 {
10929
10930   int xattr_flags = 0;
10931   if (!value)
10932     xattr_flags |= CEPH_XATTR_REMOVE;
10933   if (flags & XATTR_CREATE)
10934     xattr_flags |= CEPH_XATTR_CREATE;
10935   if (flags & XATTR_REPLACE)
10936     xattr_flags |= CEPH_XATTR_REPLACE;
10937
10938   MetaRequest *req = new MetaRequest(CEPH_MDS_OP_SETXATTR);
10939   filepath path;
10940   in->make_nosnap_relative_path(path);
10941   req->set_filepath(path);
10942   req->set_string2(name);
10943   req->set_inode(in);
10944   req->head.args.setxattr.flags = xattr_flags;
10945
10946   bufferlist bl;
10947   bl.append((const char*)value, size);
10948   req->set_data(bl);
10949
10950   int res = make_request(req, perms);
10951
10952   trim_cache();
10953   ldout(cct, 3) << "_setxattr(" << in->ino << ", \"" << name << "\") = " <<
10954     res << dendl;
10955   return res;
10956 }
10957
10958 int Client::_setxattr(Inode *in, const char *name, const void *value,
10959                       size_t size, int flags, const UserPerm& perms)
10960 {
10961   if (in->snapid != CEPH_NOSNAP) {
10962     return -EROFS;
10963   }
10964
10965   bool posix_acl_xattr = false;
10966   if (acl_type == POSIX_ACL)
10967     posix_acl_xattr = !strncmp(name, "system.", 7);
10968
10969   if (strncmp(name, "user.", 5) &&
10970       strncmp(name, "security.", 9) &&
10971       strncmp(name, "trusted.", 8) &&
10972       strncmp(name, "ceph.", 5) &&
10973       !posix_acl_xattr)
10974     return -EOPNOTSUPP;
10975
10976   if (posix_acl_xattr) {
10977     if (!strcmp(name, ACL_EA_ACCESS)) {
10978       mode_t new_mode = in->mode;
10979       if (value) {
10980         int ret = posix_acl_equiv_mode(value, size, &new_mode);
10981         if (ret < 0)
10982           return ret;
10983         if (ret == 0) {
10984           value = NULL;
10985           size = 0;
10986         }
10987         if (new_mode != in->mode) {
10988           struct ceph_statx stx;
10989           stx.stx_mode = new_mode;
10990           ret = _do_setattr(in, &stx, CEPH_SETATTR_MODE, perms, NULL);
10991           if (ret < 0)
10992             return ret;
10993         }
10994       }
10995     } else if (!strcmp(name, ACL_EA_DEFAULT)) {
10996       if (value) {
10997         if (!S_ISDIR(in->mode))
10998           return -EACCES;
10999         int ret = posix_acl_check(value, size);
11000         if (ret < 0)
11001           return -EINVAL;
11002         if (ret == 0) {
11003           value = NULL;
11004           size = 0;
11005         }
11006       }
11007     } else {
11008       return -EOPNOTSUPP;
11009     }
11010   } else {
11011     const VXattr *vxattr = _match_vxattr(in, name);
11012     if (vxattr && vxattr->readonly)
11013       return -EOPNOTSUPP;
11014   }
11015
11016   return _do_setxattr(in, name, value, size, flags, perms);
11017 }
11018
11019 int Client::_setxattr(InodeRef &in, const char *name, const void *value,
11020                       size_t size, int flags, const UserPerm& perms)
11021 {
11022   if (cct->_conf->client_permissions) {
11023     int r = xattr_permission(in.get(), name, MAY_WRITE, perms);
11024     if (r < 0)
11025       return r;
11026   }
11027   return _setxattr(in.get(), name, value, size, flags, perms);
11028 }
11029
11030 int Client::_setxattr_check_data_pool(string& name, string& value, const OSDMap *osdmap)
11031 {
11032   string tmp;
11033   if (name == "layout") {
11034     string::iterator begin = value.begin();
11035     string::iterator end = value.end();
11036     keys_and_values<string::iterator> p;    // create instance of parser
11037     std::map<string, string> m;             // map to receive results
11038     if (!qi::parse(begin, end, p, m)) {     // returns true if successful
11039       return -EINVAL;
11040     }
11041     if (begin != end)
11042       return -EINVAL;
11043     for (map<string,string>::iterator q = m.begin(); q != m.end(); ++q) {
11044       if (q->first == "pool") {
11045         tmp = q->second;
11046         break;
11047       }
11048     }
11049   } else if (name == "layout.pool") {
11050     tmp = value;
11051   }
11052
11053   if (tmp.length()) {
11054     int64_t pool;
11055     try {
11056       pool = boost::lexical_cast<unsigned>(tmp);
11057       if (!osdmap->have_pg_pool(pool))
11058         return -ENOENT;
11059     } catch (boost::bad_lexical_cast const&) {
11060       pool = osdmap->lookup_pg_pool_name(tmp);
11061       if (pool < 0) {
11062         return -ENOENT;
11063       }
11064     }
11065   }
11066
11067   return 0;
11068 }
11069
11070 void Client::_setxattr_maybe_wait_for_osdmap(const char *name, const void *value, size_t size)
11071 {
11072   // For setting pool of layout, MetaRequest need osdmap epoch.
11073   // There is a race which create a new data pool but client and mds both don't have.
11074   // Make client got the latest osdmap which make mds quickly judge whether get newer osdmap.
11075   if (strcmp(name, "ceph.file.layout.pool") == 0 || strcmp(name, "ceph.dir.layout.pool") == 0 ||
11076       strcmp(name, "ceph.file.layout") == 0 || strcmp(name, "ceph.dir.layout") == 0) {
11077     string rest(strstr(name, "layout"));
11078     string v((const char*)value, size);
11079     int r = objecter->with_osdmap([&](const OSDMap& o) {
11080       return _setxattr_check_data_pool(rest, v, &o);
11081     });
11082
11083     if (r == -ENOENT) {
11084       C_SaferCond ctx;
11085       objecter->wait_for_latest_osdmap(&ctx);
11086       ctx.wait();
11087     }
11088   }
11089 }
11090
11091 int Client::ll_setxattr(Inode *in, const char *name, const void *value,
11092                         size_t size, int flags, const UserPerm& perms)
11093 {
11094   _setxattr_maybe_wait_for_osdmap(name, value, size);
11095
11096   Mutex::Locker lock(client_lock);
11097
11098   if (unmounting)
11099     return -ENOTCONN;
11100
11101   vinodeno_t vino = _get_vino(in);
11102
11103   ldout(cct, 3) << "ll_setxattr " << vino << " " << name << " size " << size << dendl;
11104   tout(cct) << "ll_setxattr" << std::endl;
11105   tout(cct) << vino.ino.val << std::endl;
11106   tout(cct) << name << std::endl;
11107
11108   if (!cct->_conf->fuse_default_permissions) {
11109     int r = xattr_permission(in, name, MAY_WRITE, perms);
11110     if (r < 0)
11111       return r;
11112   }
11113   return _setxattr(in, name, value, size, flags, perms);
11114 }
11115
11116 int Client::_removexattr(Inode *in, const char *name, const UserPerm& perms)
11117 {
11118   if (in->snapid != CEPH_NOSNAP) {
11119     return -EROFS;
11120   }
11121
11122   // same xattrs supported by kernel client
11123   if (strncmp(name, "user.", 5) &&
11124       strncmp(name, "system.", 7) &&
11125       strncmp(name, "security.", 9) &&
11126       strncmp(name, "trusted.", 8) &&
11127       strncmp(name, "ceph.", 5))
11128     return -EOPNOTSUPP;
11129
11130   const VXattr *vxattr = _match_vxattr(in, name);
11131   if (vxattr && vxattr->readonly)
11132     return -EOPNOTSUPP;
11133
11134   MetaRequest *req = new MetaRequest(CEPH_MDS_OP_RMXATTR);
11135   filepath path;
11136   in->make_nosnap_relative_path(path);
11137   req->set_filepath(path);
11138   req->set_filepath2(name);
11139   req->set_inode(in);
11140  
11141   int res = make_request(req, perms);
11142
11143   trim_cache();
11144   ldout(cct, 3) << "_removexattr(" << in->ino << ", \"" << name << "\") = " << res << dendl;
11145   return res;
11146 }
11147
11148 int Client::_removexattr(InodeRef &in, const char *name, const UserPerm& perms)
11149 {
11150   if (cct->_conf->client_permissions) {
11151     int r = xattr_permission(in.get(), name, MAY_WRITE, perms);
11152     if (r < 0)
11153       return r;
11154   }
11155   return _removexattr(in.get(), name, perms);
11156 }
11157
11158 int Client::ll_removexattr(Inode *in, const char *name, const UserPerm& perms)
11159 {
11160   Mutex::Locker lock(client_lock);
11161
11162   if (unmounting)
11163     return -ENOTCONN;
11164
11165   vinodeno_t vino = _get_vino(in);
11166
11167   ldout(cct, 3) << "ll_removexattr " << vino << " " << name << dendl;
11168   tout(cct) << "ll_removexattr" << std::endl;
11169   tout(cct) << vino.ino.val << std::endl;
11170   tout(cct) << name << std::endl;
11171
11172   if (!cct->_conf->fuse_default_permissions) {
11173     int r = xattr_permission(in, name, MAY_WRITE, perms);
11174     if (r < 0)
11175       return r;
11176   }
11177
11178   return _removexattr(in, name, perms);
11179 }
11180
11181 bool Client::_vxattrcb_quota_exists(Inode *in)
11182 {
11183   return in->quota.is_enable();
11184 }
11185 size_t Client::_vxattrcb_quota(Inode *in, char *val, size_t size)
11186 {
11187   return snprintf(val, size,
11188                   "max_bytes=%lld max_files=%lld",
11189                   (long long int)in->quota.max_bytes,
11190                   (long long int)in->quota.max_files);
11191 }
11192 size_t Client::_vxattrcb_quota_max_bytes(Inode *in, char *val, size_t size)
11193 {
11194   return snprintf(val, size, "%lld", (long long int)in->quota.max_bytes);
11195 }
11196 size_t Client::_vxattrcb_quota_max_files(Inode *in, char *val, size_t size)
11197 {
11198   return snprintf(val, size, "%lld", (long long int)in->quota.max_files);
11199 }
11200
11201 bool Client::_vxattrcb_layout_exists(Inode *in)
11202 {
11203   return in->layout != file_layout_t();
11204 }
11205 size_t Client::_vxattrcb_layout(Inode *in, char *val, size_t size)
11206 {
11207   int r = snprintf(val, size,
11208       "stripe_unit=%lld stripe_count=%lld object_size=%lld pool=",
11209       (unsigned long long)in->layout.stripe_unit,
11210       (unsigned long long)in->layout.stripe_count,
11211       (unsigned long long)in->layout.object_size);
11212   objecter->with_osdmap([&](const OSDMap& o) {
11213       if (o.have_pg_pool(in->layout.pool_id))
11214         r += snprintf(val + r, size - r, "%s",
11215                       o.get_pool_name(in->layout.pool_id).c_str());
11216       else
11217         r += snprintf(val + r, size - r, "%" PRIu64,
11218                       (uint64_t)in->layout.pool_id);
11219     });
11220   if (in->layout.pool_ns.length())
11221     r += snprintf(val + r, size - r, " pool_namespace=%s",
11222                   in->layout.pool_ns.c_str());
11223   return r;
11224 }
11225 size_t Client::_vxattrcb_layout_stripe_unit(Inode *in, char *val, size_t size)
11226 {
11227   return snprintf(val, size, "%lld", (unsigned long long)in->layout.stripe_unit);
11228 }
11229 size_t Client::_vxattrcb_layout_stripe_count(Inode *in, char *val, size_t size)
11230 {
11231   return snprintf(val, size, "%lld", (unsigned long long)in->layout.stripe_count);
11232 }
11233 size_t Client::_vxattrcb_layout_object_size(Inode *in, char *val, size_t size)
11234 {
11235   return snprintf(val, size, "%lld", (unsigned long long)in->layout.object_size);
11236 }
11237 size_t Client::_vxattrcb_layout_pool(Inode *in, char *val, size_t size)
11238 {
11239   size_t r;
11240   objecter->with_osdmap([&](const OSDMap& o) {
11241       if (o.have_pg_pool(in->layout.pool_id))
11242         r = snprintf(val, size, "%s", o.get_pool_name(
11243                        in->layout.pool_id).c_str());
11244       else
11245         r = snprintf(val, size, "%" PRIu64, (uint64_t)in->layout.pool_id);
11246     });
11247   return r;
11248 }
11249 size_t Client::_vxattrcb_layout_pool_namespace(Inode *in, char *val, size_t size)
11250 {
11251   return snprintf(val, size, "%s", in->layout.pool_ns.c_str());
11252 }
11253 size_t Client::_vxattrcb_dir_entries(Inode *in, char *val, size_t size)
11254 {
11255   return snprintf(val, size, "%lld", (unsigned long long)(in->dirstat.nfiles + in->dirstat.nsubdirs));
11256 }
11257 size_t Client::_vxattrcb_dir_files(Inode *in, char *val, size_t size)
11258 {
11259   return snprintf(val, size, "%lld", (unsigned long long)in->dirstat.nfiles);
11260 }
11261 size_t Client::_vxattrcb_dir_subdirs(Inode *in, char *val, size_t size)
11262 {
11263   return snprintf(val, size, "%lld", (unsigned long long)in->dirstat.nsubdirs);
11264 }
11265 size_t Client::_vxattrcb_dir_rentries(Inode *in, char *val, size_t size)
11266 {
11267   return snprintf(val, size, "%lld", (unsigned long long)(in->rstat.rfiles + in->rstat.rsubdirs));
11268 }
11269 size_t Client::_vxattrcb_dir_rfiles(Inode *in, char *val, size_t size)
11270 {
11271   return snprintf(val, size, "%lld", (unsigned long long)in->rstat.rfiles);
11272 }
11273 size_t Client::_vxattrcb_dir_rsubdirs(Inode *in, char *val, size_t size)
11274 {
11275   return snprintf(val, size, "%lld", (unsigned long long)in->rstat.rsubdirs);
11276 }
11277 size_t Client::_vxattrcb_dir_rbytes(Inode *in, char *val, size_t size)
11278 {
11279   return snprintf(val, size, "%lld", (unsigned long long)in->rstat.rbytes);
11280 }
11281 size_t Client::_vxattrcb_dir_rctime(Inode *in, char *val, size_t size)
11282 {
11283   return snprintf(val, size, "%ld.09%ld", (long)in->rstat.rctime.sec(),
11284       (long)in->rstat.rctime.nsec());
11285 }
11286
11287 #define CEPH_XATTR_NAME(_type, _name) "ceph." #_type "." #_name
11288 #define CEPH_XATTR_NAME2(_type, _name, _name2) "ceph." #_type "." #_name "." #_name2
11289
11290 #define XATTR_NAME_CEPH(_type, _name)                           \
11291 {                                                               \
11292   name: CEPH_XATTR_NAME(_type, _name),                          \
11293   getxattr_cb: &Client::_vxattrcb_ ## _type ## _ ## _name,      \
11294   readonly: true,                                               \
11295   hidden: false,                                                \
11296   exists_cb: NULL,                                              \
11297 }
11298 #define XATTR_LAYOUT_FIELD(_type, _name, _field)                \
11299 {                                                               \
11300   name: CEPH_XATTR_NAME2(_type, _name, _field),                 \
11301   getxattr_cb: &Client::_vxattrcb_ ## _name ## _ ## _field,     \
11302   readonly: false,                                              \
11303   hidden: true,                                                 \
11304   exists_cb: &Client::_vxattrcb_layout_exists,                  \
11305 }
11306 #define XATTR_QUOTA_FIELD(_type, _name)                         \
11307 {                                                               \
11308   name: CEPH_XATTR_NAME(_type, _name),                          \
11309   getxattr_cb: &Client::_vxattrcb_ ## _type ## _ ## _name,      \
11310   readonly: false,                                              \
11311   hidden: true,                                                 \
11312   exists_cb: &Client::_vxattrcb_quota_exists,                   \
11313 }
11314
11315 const Client::VXattr Client::_dir_vxattrs[] = {
11316   {
11317     name: "ceph.dir.layout",
11318     getxattr_cb: &Client::_vxattrcb_layout,
11319     readonly: false,
11320     hidden: true,
11321     exists_cb: &Client::_vxattrcb_layout_exists,
11322   },
11323   XATTR_LAYOUT_FIELD(dir, layout, stripe_unit),
11324   XATTR_LAYOUT_FIELD(dir, layout, stripe_count),
11325   XATTR_LAYOUT_FIELD(dir, layout, object_size),
11326   XATTR_LAYOUT_FIELD(dir, layout, pool),
11327   XATTR_LAYOUT_FIELD(dir, layout, pool_namespace),
11328   XATTR_NAME_CEPH(dir, entries),
11329   XATTR_NAME_CEPH(dir, files),
11330   XATTR_NAME_CEPH(dir, subdirs),
11331   XATTR_NAME_CEPH(dir, rentries),
11332   XATTR_NAME_CEPH(dir, rfiles),
11333   XATTR_NAME_CEPH(dir, rsubdirs),
11334   XATTR_NAME_CEPH(dir, rbytes),
11335   XATTR_NAME_CEPH(dir, rctime),
11336   {
11337     name: "ceph.quota",
11338     getxattr_cb: &Client::_vxattrcb_quota,
11339     readonly: false,
11340     hidden: true,
11341     exists_cb: &Client::_vxattrcb_quota_exists,
11342   },
11343   XATTR_QUOTA_FIELD(quota, max_bytes),
11344   XATTR_QUOTA_FIELD(quota, max_files),
11345   { name: "" }     /* Required table terminator */
11346 };
11347
11348 const Client::VXattr Client::_file_vxattrs[] = {
11349   {
11350     name: "ceph.file.layout",
11351     getxattr_cb: &Client::_vxattrcb_layout,
11352     readonly: false,
11353     hidden: true,
11354     exists_cb: &Client::_vxattrcb_layout_exists,
11355   },
11356   XATTR_LAYOUT_FIELD(file, layout, stripe_unit),
11357   XATTR_LAYOUT_FIELD(file, layout, stripe_count),
11358   XATTR_LAYOUT_FIELD(file, layout, object_size),
11359   XATTR_LAYOUT_FIELD(file, layout, pool),
11360   XATTR_LAYOUT_FIELD(file, layout, pool_namespace),
11361   { name: "" }     /* Required table terminator */
11362 };
11363
11364 const Client::VXattr *Client::_get_vxattrs(Inode *in)
11365 {
11366   if (in->is_dir())
11367     return _dir_vxattrs;
11368   else if (in->is_file())
11369     return _file_vxattrs;
11370   return NULL;
11371 }
11372
11373 const Client::VXattr *Client::_match_vxattr(Inode *in, const char *name)
11374 {
11375   if (strncmp(name, "ceph.", 5) == 0) {
11376     const VXattr *vxattr = _get_vxattrs(in);
11377     if (vxattr) {
11378       while (!vxattr->name.empty()) {
11379         if (vxattr->name == name)
11380           return vxattr;
11381         vxattr++;
11382       }
11383     }
11384   }
11385   return NULL;
11386 }
11387
11388 size_t Client::_vxattrs_calcu_name_size(const VXattr *vxattr)
11389 {
11390   size_t len = 0;
11391   while (!vxattr->name.empty()) {
11392     if (!vxattr->hidden)
11393       len += vxattr->name.length() + 1;
11394     vxattr++;
11395   }
11396   return len;
11397 }
11398
11399 int Client::ll_readlink(Inode *in, char *buf, size_t buflen, const UserPerm& perms)
11400 {
11401   Mutex::Locker lock(client_lock);
11402
11403   if (unmounting)
11404     return -ENOTCONN;
11405
11406   vinodeno_t vino = _get_vino(in);
11407
11408   ldout(cct, 3) << "ll_readlink " << vino << dendl;
11409   tout(cct) << "ll_readlink" << std::endl;
11410   tout(cct) << vino.ino.val << std::endl;
11411
11412   set<Dentry*>::iterator dn = in->dn_set.begin();
11413   while (dn != in->dn_set.end()) {
11414     touch_dn(*dn);
11415     ++dn;
11416   }
11417
11418   int r = _readlink(in, buf, buflen); // FIXME: no permission checking!
11419   ldout(cct, 3) << "ll_readlink " << vino << " = " << r << dendl;
11420   return r;
11421 }
11422
11423 int Client::_mknod(Inode *dir, const char *name, mode_t mode, dev_t rdev,
11424                    const UserPerm& perms, InodeRef *inp)
11425 {
11426   ldout(cct, 3) << "_mknod(" << dir->ino << " " << name << ", 0" << oct
11427                 << mode << dec << ", " << rdev << ", uid " << perms.uid()
11428                 << ", gid " << perms.gid() << ")" << dendl;
11429
11430   if (strlen(name) > NAME_MAX)
11431     return -ENAMETOOLONG;
11432
11433   if (dir->snapid != CEPH_NOSNAP) {
11434     return -EROFS;
11435   }
11436   if (is_quota_files_exceeded(dir, perms)) {
11437     return -EDQUOT;
11438   }
11439
11440   MetaRequest *req = new MetaRequest(CEPH_MDS_OP_MKNOD);
11441
11442   filepath path;
11443   dir->make_nosnap_relative_path(path);
11444   path.push_dentry(name);
11445   req->set_filepath(path); 
11446   req->set_inode(dir);
11447   req->head.args.mknod.rdev = rdev;
11448   req->dentry_drop = CEPH_CAP_FILE_SHARED;
11449   req->dentry_unless = CEPH_CAP_FILE_EXCL;
11450
11451   bufferlist xattrs_bl;
11452   int res = _posix_acl_create(dir, &mode, xattrs_bl, perms);
11453   if (res < 0)
11454     goto fail;
11455   req->head.args.mknod.mode = mode;
11456   if (xattrs_bl.length() > 0)
11457     req->set_data(xattrs_bl);
11458
11459   Dentry *de;
11460   res = get_or_create(dir, name, &de);
11461   if (res < 0)
11462     goto fail;
11463   req->set_dentry(de);
11464
11465   res = make_request(req, perms, inp);
11466
11467   trim_cache();
11468
11469   ldout(cct, 3) << "mknod(" << path << ", 0" << oct << mode << dec << ") = " << res << dendl;
11470   return res;
11471
11472  fail:
11473   put_request(req);
11474   return res;
11475 }
11476
11477 int Client::ll_mknod(Inode *parent, const char *name, mode_t mode,
11478                      dev_t rdev, struct stat *attr, Inode **out,
11479                      const UserPerm& perms)
11480 {
11481   Mutex::Locker lock(client_lock);
11482
11483   if (unmounting)
11484     return -ENOTCONN;
11485
11486   vinodeno_t vparent = _get_vino(parent);
11487
11488   ldout(cct, 3) << "ll_mknod " << vparent << " " << name << dendl;
11489   tout(cct) << "ll_mknod" << std::endl;
11490   tout(cct) << vparent.ino.val << std::endl;
11491   tout(cct) << name << std::endl;
11492   tout(cct) << mode << std::endl;
11493   tout(cct) << rdev << std::endl;
11494
11495   if (!cct->_conf->fuse_default_permissions) {
11496     int r = may_create(parent, perms);
11497     if (r < 0)
11498       return r;
11499   }
11500
11501   InodeRef in;
11502   int r = _mknod(parent, name, mode, rdev, perms, &in);
11503   if (r == 0) {
11504     fill_stat(in, attr);
11505     _ll_get(in.get());
11506   }
11507   tout(cct) << attr->st_ino << std::endl;
11508   ldout(cct, 3) << "ll_mknod " << vparent << " " << name
11509           << " = " << r << " (" << hex << attr->st_ino << dec << ")" << dendl;
11510   *out = in.get();
11511   return r;
11512 }
11513
11514 int Client::ll_mknodx(Inode *parent, const char *name, mode_t mode,
11515                       dev_t rdev, Inode **out,
11516                       struct ceph_statx *stx, unsigned want, unsigned flags,
11517                       const UserPerm& perms)
11518 {
11519   unsigned caps = statx_to_mask(flags, want);
11520   Mutex::Locker lock(client_lock);
11521
11522   if (unmounting)
11523     return -ENOTCONN;
11524
11525   vinodeno_t vparent = _get_vino(parent);
11526
11527   ldout(cct, 3) << "ll_mknodx " << vparent << " " << name << dendl;
11528   tout(cct) << "ll_mknodx" << std::endl;
11529   tout(cct) << vparent.ino.val << std::endl;
11530   tout(cct) << name << std::endl;
11531   tout(cct) << mode << std::endl;
11532   tout(cct) << rdev << std::endl;
11533
11534   if (!cct->_conf->fuse_default_permissions) {
11535     int r = may_create(parent, perms);
11536     if (r < 0)
11537       return r;
11538   }
11539
11540   InodeRef in;
11541   int r = _mknod(parent, name, mode, rdev, perms, &in);
11542   if (r == 0) {
11543     fill_statx(in, caps, stx);
11544     _ll_get(in.get());
11545   }
11546   tout(cct) << stx->stx_ino << std::endl;
11547   ldout(cct, 3) << "ll_mknodx " << vparent << " " << name
11548           << " = " << r << " (" << hex << stx->stx_ino << dec << ")" << dendl;
11549   *out = in.get();
11550   return r;
11551 }
11552
11553 int Client::_create(Inode *dir, const char *name, int flags, mode_t mode,
11554                     InodeRef *inp, Fh **fhp, int stripe_unit, int stripe_count,
11555                     int object_size, const char *data_pool, bool *created,
11556                     const UserPerm& perms)
11557 {
11558   ldout(cct, 3) << "_create(" << dir->ino << " " << name << ", 0" << oct <<
11559     mode << dec << ")" << dendl;
11560
11561   if (strlen(name) > NAME_MAX)
11562     return -ENAMETOOLONG;
11563   if (dir->snapid != CEPH_NOSNAP) {
11564     return -EROFS;
11565   }
11566   if (is_quota_files_exceeded(dir, perms)) {
11567     return -EDQUOT;
11568   }
11569
11570   // use normalized flags to generate cmode
11571   int cmode = ceph_flags_to_mode(ceph_flags_sys2wire(flags));
11572   if (cmode < 0)
11573     return -EINVAL;
11574
11575   int64_t pool_id = -1;
11576   if (data_pool && *data_pool) {
11577     pool_id = objecter->with_osdmap(
11578       std::mem_fn(&OSDMap::lookup_pg_pool_name), data_pool);
11579     if (pool_id < 0)
11580       return -EINVAL;
11581     if (pool_id > 0xffffffffll)
11582       return -ERANGE;  // bummer!
11583   }
11584
11585   MetaRequest *req = new MetaRequest(CEPH_MDS_OP_CREATE);
11586
11587   filepath path;
11588   dir->make_nosnap_relative_path(path);
11589   path.push_dentry(name);
11590   req->set_filepath(path);
11591   req->set_inode(dir);
11592   req->head.args.open.flags = ceph_flags_sys2wire(flags | O_CREAT);
11593
11594   req->head.args.open.stripe_unit = stripe_unit;
11595   req->head.args.open.stripe_count = stripe_count;
11596   req->head.args.open.object_size = object_size;
11597   if (cct->_conf->client_debug_getattr_caps)
11598     req->head.args.open.mask = DEBUG_GETATTR_CAPS;
11599   else
11600     req->head.args.open.mask = 0;
11601   req->head.args.open.pool = pool_id;
11602   req->dentry_drop = CEPH_CAP_FILE_SHARED;
11603   req->dentry_unless = CEPH_CAP_FILE_EXCL;
11604
11605   mode |= S_IFREG;
11606   bufferlist xattrs_bl;
11607   int res = _posix_acl_create(dir, &mode, xattrs_bl, perms);
11608   if (res < 0)
11609     goto fail;
11610   req->head.args.open.mode = mode;
11611   if (xattrs_bl.length() > 0)
11612     req->set_data(xattrs_bl);
11613
11614   Dentry *de;
11615   res = get_or_create(dir, name, &de);
11616   if (res < 0)
11617     goto fail;
11618   req->set_dentry(de);
11619
11620   res = make_request(req, perms, inp, created);
11621   if (res < 0) {
11622     goto reply_error;
11623   }
11624
11625   /* If the caller passed a value in fhp, do the open */
11626   if(fhp) {
11627     (*inp)->get_open_ref(cmode);
11628     *fhp = _create_fh(inp->get(), flags, cmode, perms);
11629   }
11630
11631  reply_error:
11632   trim_cache();
11633
11634   ldout(cct, 3) << "create(" << path << ", 0" << oct << mode << dec 
11635                 << " layout " << stripe_unit
11636                 << ' ' << stripe_count
11637                 << ' ' << object_size
11638                 <<") = " << res << dendl;
11639   return res;
11640
11641  fail:
11642   put_request(req);
11643   return res;
11644 }
11645
11646
11647 int Client::_mkdir(Inode *dir, const char *name, mode_t mode, const UserPerm& perm,
11648                    InodeRef *inp)
11649 {
11650   ldout(cct, 3) << "_mkdir(" << dir->ino << " " << name << ", 0" << oct
11651                 << mode << dec << ", uid " << perm.uid()
11652                 << ", gid " << perm.gid() << ")" << dendl;
11653
11654   if (strlen(name) > NAME_MAX)
11655     return -ENAMETOOLONG;
11656
11657   if (dir->snapid != CEPH_NOSNAP && dir->snapid != CEPH_SNAPDIR) {
11658     return -EROFS;
11659   }
11660   if (is_quota_files_exceeded(dir, perm)) {
11661     return -EDQUOT;
11662   }
11663   MetaRequest *req = new MetaRequest(dir->snapid == CEPH_SNAPDIR ?
11664                                      CEPH_MDS_OP_MKSNAP : CEPH_MDS_OP_MKDIR);
11665
11666   filepath path;
11667   dir->make_nosnap_relative_path(path);
11668   path.push_dentry(name);
11669   req->set_filepath(path);
11670   req->set_inode(dir);
11671   req->dentry_drop = CEPH_CAP_FILE_SHARED;
11672   req->dentry_unless = CEPH_CAP_FILE_EXCL;
11673
11674   mode |= S_IFDIR;
11675   bufferlist xattrs_bl;
11676   int res = _posix_acl_create(dir, &mode, xattrs_bl, perm);
11677   if (res < 0)
11678     goto fail;
11679   req->head.args.mkdir.mode = mode;
11680   if (xattrs_bl.length() > 0)
11681     req->set_data(xattrs_bl);
11682
11683   Dentry *de;
11684   res = get_or_create(dir, name, &de);
11685   if (res < 0)
11686     goto fail;
11687   req->set_dentry(de);
11688   
11689   ldout(cct, 10) << "_mkdir: making request" << dendl;
11690   res = make_request(req, perm, inp);
11691   ldout(cct, 10) << "_mkdir result is " << res << dendl;
11692
11693   trim_cache();
11694
11695   ldout(cct, 3) << "_mkdir(" << path << ", 0" << oct << mode << dec << ") = " << res << dendl;
11696   return res;
11697
11698  fail:
11699   put_request(req);
11700   return res;
11701 }
11702
11703 int Client::ll_mkdir(Inode *parent, const char *name, mode_t mode,
11704                      struct stat *attr, Inode **out, const UserPerm& perm)
11705 {
11706   Mutex::Locker lock(client_lock);
11707
11708   if (unmounting)
11709     return -ENOTCONN;
11710
11711   vinodeno_t vparent = _get_vino(parent);
11712
11713   ldout(cct, 3) << "ll_mkdir " << vparent << " " << name << dendl;
11714   tout(cct) << "ll_mkdir" << std::endl;
11715   tout(cct) << vparent.ino.val << std::endl;
11716   tout(cct) << name << std::endl;
11717   tout(cct) << mode << std::endl;
11718
11719   if (!cct->_conf->fuse_default_permissions) {
11720     int r = may_create(parent, perm);
11721     if (r < 0)
11722       return r;
11723   }
11724
11725   InodeRef in;
11726   int r = _mkdir(parent, name, mode, perm, &in);
11727   if (r == 0) {
11728     fill_stat(in, attr);
11729     _ll_get(in.get());
11730   }
11731   tout(cct) << attr->st_ino << std::endl;
11732   ldout(cct, 3) << "ll_mkdir " << vparent << " " << name
11733           << " = " << r << " (" << hex << attr->st_ino << dec << ")" << dendl;
11734   *out = in.get();
11735   return r;
11736 }
11737
11738 int Client::ll_mkdirx(Inode *parent, const char *name, mode_t mode, Inode **out,
11739                       struct ceph_statx *stx, unsigned want, unsigned flags,
11740                       const UserPerm& perms)
11741 {
11742   Mutex::Locker lock(client_lock);
11743
11744   if (unmounting)
11745     return -ENOTCONN;
11746
11747   vinodeno_t vparent = _get_vino(parent);
11748
11749   ldout(cct, 3) << "ll_mkdirx " << vparent << " " << name << dendl;
11750   tout(cct) << "ll_mkdirx" << std::endl;
11751   tout(cct) << vparent.ino.val << std::endl;
11752   tout(cct) << name << std::endl;
11753   tout(cct) << mode << std::endl;
11754
11755   if (!cct->_conf->fuse_default_permissions) {
11756     int r = may_create(parent, perms);
11757     if (r < 0)
11758       return r;
11759   }
11760
11761   InodeRef in;
11762   int r = _mkdir(parent, name, mode, perms, &in);
11763   if (r == 0) {
11764     fill_statx(in, statx_to_mask(flags, want), stx);
11765     _ll_get(in.get());
11766   } else {
11767     stx->stx_ino = 0;
11768     stx->stx_mask = 0;
11769   }
11770   tout(cct) << stx->stx_ino << std::endl;
11771   ldout(cct, 3) << "ll_mkdirx " << vparent << " " << name
11772           << " = " << r << " (" << hex << stx->stx_ino << dec << ")" << dendl;
11773   *out = in.get();
11774   return r;
11775 }
11776
11777 int Client::_symlink(Inode *dir, const char *name, const char *target,
11778                      const UserPerm& perms, InodeRef *inp)
11779 {
11780   ldout(cct, 3) << "_symlink(" << dir->ino << " " << name << ", " << target
11781                 << ", uid " << perms.uid() << ", gid " << perms.gid() << ")"
11782                 << dendl;
11783
11784   if (strlen(name) > NAME_MAX)
11785     return -ENAMETOOLONG;
11786
11787   if (dir->snapid != CEPH_NOSNAP) {
11788     return -EROFS;
11789   }
11790   if (is_quota_files_exceeded(dir, perms)) {
11791     return -EDQUOT;
11792   }
11793
11794   MetaRequest *req = new MetaRequest(CEPH_MDS_OP_SYMLINK);
11795
11796   filepath path;
11797   dir->make_nosnap_relative_path(path);
11798   path.push_dentry(name);
11799   req->set_filepath(path);
11800   req->set_inode(dir);
11801   req->set_string2(target); 
11802   req->dentry_drop = CEPH_CAP_FILE_SHARED;
11803   req->dentry_unless = CEPH_CAP_FILE_EXCL;
11804
11805   Dentry *de;
11806   int res = get_or_create(dir, name, &de);
11807   if (res < 0)
11808     goto fail;
11809   req->set_dentry(de);
11810
11811   res = make_request(req, perms, inp);
11812
11813   trim_cache();
11814   ldout(cct, 3) << "_symlink(\"" << path << "\", \"" << target << "\") = " <<
11815     res << dendl;
11816   return res;
11817
11818  fail:
11819   put_request(req);
11820   return res;
11821 }
11822
11823 int Client::ll_symlink(Inode *parent, const char *name, const char *value,
11824                        struct stat *attr, Inode **out, const UserPerm& perms)
11825 {
11826   Mutex::Locker lock(client_lock);
11827
11828   if (unmounting)
11829     return -ENOTCONN;
11830
11831   vinodeno_t vparent = _get_vino(parent);
11832
11833   ldout(cct, 3) << "ll_symlink " << vparent << " " << name << " -> " << value
11834                 << dendl;
11835   tout(cct) << "ll_symlink" << std::endl;
11836   tout(cct) << vparent.ino.val << std::endl;
11837   tout(cct) << name << std::endl;
11838   tout(cct) << value << std::endl;
11839
11840   if (!cct->_conf->fuse_default_permissions) {
11841     int r = may_create(parent, perms);
11842     if (r < 0)
11843       return r;
11844   }
11845
11846   InodeRef in;
11847   int r = _symlink(parent, name, value, perms, &in);
11848   if (r == 0) {
11849     fill_stat(in, attr);
11850     _ll_get(in.get());
11851   }
11852   tout(cct) << attr->st_ino << std::endl;
11853   ldout(cct, 3) << "ll_symlink " << vparent << " " << name
11854           << " = " << r << " (" << hex << attr->st_ino << dec << ")" << dendl;
11855   *out = in.get();
11856   return r;
11857 }
11858
11859 int Client::ll_symlinkx(Inode *parent, const char *name, const char *value,
11860                         Inode **out, struct ceph_statx *stx, unsigned want,
11861                         unsigned flags, const UserPerm& perms)
11862 {
11863   Mutex::Locker lock(client_lock);
11864
11865   if (unmounting)
11866     return -ENOTCONN;
11867
11868   vinodeno_t vparent = _get_vino(parent);
11869
11870   ldout(cct, 3) << "ll_symlinkx " << vparent << " " << name << " -> " << value
11871                 << dendl;
11872   tout(cct) << "ll_symlinkx" << std::endl;
11873   tout(cct) << vparent.ino.val << std::endl;
11874   tout(cct) << name << std::endl;
11875   tout(cct) << value << std::endl;
11876
11877   if (!cct->_conf->fuse_default_permissions) {
11878     int r = may_create(parent, perms);
11879     if (r < 0)
11880       return r;
11881   }
11882
11883   InodeRef in;
11884   int r = _symlink(parent, name, value, perms, &in);
11885   if (r == 0) {
11886     fill_statx(in, statx_to_mask(flags, want), stx);
11887     _ll_get(in.get());
11888   }
11889   tout(cct) << stx->stx_ino << std::endl;
11890   ldout(cct, 3) << "ll_symlinkx " << vparent << " " << name
11891           << " = " << r << " (" << hex << stx->stx_ino << dec << ")" << dendl;
11892   *out = in.get();
11893   return r;
11894 }
11895
11896 int Client::_unlink(Inode *dir, const char *name, const UserPerm& perm)
11897 {
11898   ldout(cct, 3) << "_unlink(" << dir->ino << " " << name
11899                 << " uid " << perm.uid() << " gid " << perm.gid()
11900                 << ")" << dendl;
11901
11902   if (dir->snapid != CEPH_NOSNAP) {
11903     return -EROFS;
11904   }
11905
11906   MetaRequest *req = new MetaRequest(CEPH_MDS_OP_UNLINK);
11907
11908   filepath path;
11909   dir->make_nosnap_relative_path(path);
11910   path.push_dentry(name);
11911   req->set_filepath(path);
11912
11913   InodeRef otherin;
11914
11915   Dentry *de;
11916   int res = get_or_create(dir, name, &de);
11917   if (res < 0)
11918     goto fail;
11919   req->set_dentry(de);
11920   req->dentry_drop = CEPH_CAP_FILE_SHARED;
11921   req->dentry_unless = CEPH_CAP_FILE_EXCL;
11922
11923   res = _lookup(dir, name, 0, &otherin, perm);
11924   if (res < 0)
11925     goto fail;
11926   req->set_other_inode(otherin.get());
11927   req->other_inode_drop = CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL;
11928
11929   req->set_inode(dir);
11930
11931   res = make_request(req, perm);
11932
11933   trim_cache();
11934   ldout(cct, 3) << "unlink(" << path << ") = " << res << dendl;
11935   return res;
11936
11937  fail:
11938   put_request(req);
11939   return res;
11940 }
11941
11942 int Client::ll_unlink(Inode *in, const char *name, const UserPerm& perm)
11943 {
11944   Mutex::Locker lock(client_lock);
11945
11946   if (unmounting)
11947     return -ENOTCONN;
11948
11949   vinodeno_t vino = _get_vino(in);
11950
11951   ldout(cct, 3) << "ll_unlink " << vino << " " << name << dendl;
11952   tout(cct) << "ll_unlink" << std::endl;
11953   tout(cct) << vino.ino.val << std::endl;
11954   tout(cct) << name << std::endl;
11955
11956   if (!cct->_conf->fuse_default_permissions) {
11957     int r = may_delete(in, name, perm);
11958     if (r < 0)
11959       return r;
11960   }
11961   return _unlink(in, name, perm);
11962 }
11963
11964 int Client::_rmdir(Inode *dir, const char *name, const UserPerm& perms)
11965 {
11966   ldout(cct, 3) << "_rmdir(" << dir->ino << " " << name << " uid "
11967                 << perms.uid() << " gid " << perms.gid() << ")" << dendl;
11968
11969   if (dir->snapid != CEPH_NOSNAP && dir->snapid != CEPH_SNAPDIR) {
11970     return -EROFS;
11971   }
11972
11973   MetaRequest *req = new MetaRequest(dir->snapid == CEPH_SNAPDIR ? CEPH_MDS_OP_RMSNAP:CEPH_MDS_OP_RMDIR);
11974   filepath path;
11975   dir->make_nosnap_relative_path(path);
11976   path.push_dentry(name);
11977   req->set_filepath(path);
11978
11979   req->dentry_drop = CEPH_CAP_FILE_SHARED;
11980   req->dentry_unless = CEPH_CAP_FILE_EXCL;
11981   req->other_inode_drop = CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL;
11982
11983   InodeRef in;
11984
11985   Dentry *de;
11986   int res = get_or_create(dir, name, &de);
11987   if (res < 0)
11988     goto fail;
11989   res = _lookup(dir, name, 0, &in, perms);
11990   if (res < 0)
11991     goto fail;
11992   if (req->get_op() == CEPH_MDS_OP_RMDIR) {
11993     req->set_inode(dir);
11994     req->set_dentry(de);
11995     req->set_other_inode(in.get());
11996   } else {
11997     unlink(de, true, true);
11998     req->set_other_inode(in.get());
11999   }
12000
12001   res = make_request(req, perms);
12002
12003   trim_cache();
12004   ldout(cct, 3) << "rmdir(" << path << ") = " << res << dendl;
12005   return res;
12006
12007  fail:
12008   put_request(req);
12009   return res;
12010 }
12011
12012 int Client::ll_rmdir(Inode *in, const char *name, const UserPerm& perms)
12013 {
12014   Mutex::Locker lock(client_lock);
12015
12016   if (unmounting)
12017     return -ENOTCONN;
12018
12019   vinodeno_t vino = _get_vino(in);
12020
12021   ldout(cct, 3) << "ll_rmdir " << vino << " " << name << dendl;
12022   tout(cct) << "ll_rmdir" << std::endl;
12023   tout(cct) << vino.ino.val << std::endl;
12024   tout(cct) << name << std::endl;
12025
12026   if (!cct->_conf->fuse_default_permissions) {
12027     int r = may_delete(in, name, perms);
12028     if (r < 0)
12029       return r;
12030   }
12031
12032   return _rmdir(in, name, perms);
12033 }
12034
12035 int Client::_rename(Inode *fromdir, const char *fromname, Inode *todir, const char *toname, const UserPerm& perm)
12036 {
12037   ldout(cct, 3) << "_rename(" << fromdir->ino << " " << fromname << " to "
12038                 << todir->ino << " " << toname
12039                 << " uid " << perm.uid() << " gid " << perm.gid() << ")"
12040                 << dendl;
12041
12042   if (fromdir->snapid != todir->snapid)
12043     return -EXDEV;
12044
12045   int op = CEPH_MDS_OP_RENAME;
12046   if (fromdir->snapid != CEPH_NOSNAP) {
12047     if (fromdir == todir && fromdir->snapid == CEPH_SNAPDIR)
12048       op = CEPH_MDS_OP_RENAMESNAP;
12049     else
12050       return -EROFS;
12051   }
12052   if (fromdir != todir) {
12053     Inode *fromdir_root =
12054       fromdir->quota.is_enable() ? fromdir : get_quota_root(fromdir, perm);
12055     Inode *todir_root =
12056       todir->quota.is_enable() ? todir : get_quota_root(todir, perm);
12057     if (fromdir_root != todir_root) {
12058       return -EXDEV;
12059     }
12060   }
12061
12062   InodeRef target;
12063   MetaRequest *req = new MetaRequest(op);
12064
12065   filepath from;
12066   fromdir->make_nosnap_relative_path(from);
12067   from.push_dentry(fromname);
12068   filepath to;
12069   todir->make_nosnap_relative_path(to);
12070   to.push_dentry(toname);
12071   req->set_filepath(to);
12072   req->set_filepath2(from);
12073
12074   Dentry *oldde;
12075   int res = get_or_create(fromdir, fromname, &oldde);
12076   if (res < 0)
12077     goto fail;
12078   Dentry *de;
12079   res = get_or_create(todir, toname, &de);
12080   if (res < 0)
12081     goto fail;
12082
12083   if (op == CEPH_MDS_OP_RENAME) {
12084     req->set_old_dentry(oldde);
12085     req->old_dentry_drop = CEPH_CAP_FILE_SHARED;
12086     req->old_dentry_unless = CEPH_CAP_FILE_EXCL;
12087
12088     req->set_dentry(de);
12089     req->dentry_drop = CEPH_CAP_FILE_SHARED;
12090     req->dentry_unless = CEPH_CAP_FILE_EXCL;
12091
12092     InodeRef oldin, otherin;
12093     res = _lookup(fromdir, fromname, 0, &oldin, perm);
12094     if (res < 0)
12095       goto fail;
12096     req->set_old_inode(oldin.get());
12097     req->old_inode_drop = CEPH_CAP_LINK_SHARED;
12098
12099     res = _lookup(todir, toname, 0, &otherin, perm);
12100     if (res != 0 && res != -ENOENT) {
12101       goto fail;
12102     } else if (res == 0) {
12103       req->set_other_inode(otherin.get());
12104       req->other_inode_drop = CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL;
12105     }
12106
12107     req->set_inode(todir);
12108   } else {
12109     // renamesnap reply contains no tracedn, so we need to invalidate
12110     // dentry manually
12111     unlink(oldde, true, true);
12112     unlink(de, true, true);
12113   }
12114
12115   res = make_request(req, perm, &target);
12116   ldout(cct, 10) << "rename result is " << res << dendl;
12117
12118   // renamed item from our cache
12119
12120   trim_cache();
12121   ldout(cct, 3) << "_rename(" << from << ", " << to << ") = " << res << dendl;
12122   return res;
12123
12124  fail:
12125   put_request(req);
12126   return res;
12127 }
12128
12129 int Client::ll_rename(Inode *parent, const char *name, Inode *newparent,
12130                       const char *newname, const UserPerm& perm)
12131 {
12132   Mutex::Locker lock(client_lock);
12133
12134   if (unmounting)
12135     return -ENOTCONN;
12136
12137   vinodeno_t vparent = _get_vino(parent);
12138   vinodeno_t vnewparent = _get_vino(newparent);
12139
12140   ldout(cct, 3) << "ll_rename " << vparent << " " << name << " to "
12141           << vnewparent << " " << newname << dendl;
12142   tout(cct) << "ll_rename" << std::endl;
12143   tout(cct) << vparent.ino.val << std::endl;
12144   tout(cct) << name << std::endl;
12145   tout(cct) << vnewparent.ino.val << std::endl;
12146   tout(cct) << newname << std::endl;
12147
12148   if (!cct->_conf->fuse_default_permissions) {
12149     int r = may_delete(parent, name, perm);
12150     if (r < 0)
12151       return r;
12152     r = may_delete(newparent, newname, perm);
12153     if (r < 0 && r != -ENOENT)
12154       return r;
12155   }
12156
12157   return _rename(parent, name, newparent, newname, perm);
12158 }
12159
12160 int Client::_link(Inode *in, Inode *dir, const char *newname, const UserPerm& perm, InodeRef *inp)
12161 {
12162   ldout(cct, 3) << "_link(" << in->ino << " to " << dir->ino << " " << newname
12163                 << " uid " << perm.uid() << " gid " << perm.gid() << ")" << dendl;
12164
12165   if (strlen(newname) > NAME_MAX)
12166     return -ENAMETOOLONG;
12167
12168   if (in->snapid != CEPH_NOSNAP || dir->snapid != CEPH_NOSNAP) {
12169     return -EROFS;
12170   }
12171   if (is_quota_files_exceeded(dir, perm)) {
12172     return -EDQUOT;
12173   }
12174
12175   MetaRequest *req = new MetaRequest(CEPH_MDS_OP_LINK);
12176
12177   filepath path(newname, dir->ino);
12178   req->set_filepath(path);
12179   filepath existing(in->ino);
12180   req->set_filepath2(existing);
12181
12182   req->set_inode(dir);
12183   req->inode_drop = CEPH_CAP_FILE_SHARED;
12184   req->inode_unless = CEPH_CAP_FILE_EXCL;
12185
12186   Dentry *de;
12187   int res = get_or_create(dir, newname, &de);
12188   if (res < 0)
12189     goto fail;
12190   req->set_dentry(de);
12191   
12192   res = make_request(req, perm, inp);
12193   ldout(cct, 10) << "link result is " << res << dendl;
12194
12195   trim_cache();
12196   ldout(cct, 3) << "link(" << existing << ", " << path << ") = " << res << dendl;
12197   return res;
12198
12199  fail:
12200   put_request(req);
12201   return res;
12202 }
12203
12204 int Client::ll_link(Inode *in, Inode *newparent, const char *newname,
12205                     const UserPerm& perm)
12206 {
12207   Mutex::Locker lock(client_lock);
12208
12209   if (unmounting)
12210     return -ENOTCONN;
12211
12212   vinodeno_t vino = _get_vino(in);
12213   vinodeno_t vnewparent = _get_vino(newparent);
12214
12215   ldout(cct, 3) << "ll_link " << vino << " to " << vnewparent << " " <<
12216     newname << dendl;
12217   tout(cct) << "ll_link" << std::endl;
12218   tout(cct) << vino.ino.val << std::endl;
12219   tout(cct) << vnewparent << std::endl;
12220   tout(cct) << newname << std::endl;
12221
12222   int r = 0;
12223   InodeRef target;
12224
12225   if (!cct->_conf->fuse_default_permissions) {
12226     if (S_ISDIR(in->mode))
12227       return -EPERM;
12228
12229     r = may_hardlink(in, perm);
12230     if (r < 0)
12231       return r;
12232
12233     r = may_create(newparent, perm);
12234     if (r < 0)
12235       return r;
12236   }
12237
12238   return _link(in, newparent, newname, perm, &target);
12239 }
12240
12241 int Client::ll_num_osds(void)
12242 {
12243   Mutex::Locker lock(client_lock);
12244   return objecter->with_osdmap(std::mem_fn(&OSDMap::get_num_osds));
12245 }
12246
12247 int Client::ll_osdaddr(int osd, uint32_t *addr)
12248 {
12249   Mutex::Locker lock(client_lock);
12250
12251   entity_addr_t g;
12252   bool exists = objecter->with_osdmap([&](const OSDMap& o) {
12253       if (!o.exists(osd))
12254         return false;
12255       g = o.get_addr(osd);
12256       return true;
12257     });
12258   if (!exists)
12259     return -1;
12260   uint32_t nb_addr = (g.in4_addr()).sin_addr.s_addr;
12261   *addr = ntohl(nb_addr);
12262   return 0;
12263 }
12264
12265 uint32_t Client::ll_stripe_unit(Inode *in)
12266 {
12267   Mutex::Locker lock(client_lock);
12268   return in->layout.stripe_unit;
12269 }
12270
12271 uint64_t Client::ll_snap_seq(Inode *in)
12272 {
12273   Mutex::Locker lock(client_lock);
12274   return in->snaprealm->seq;
12275 }
12276
12277 int Client::ll_file_layout(Inode *in, file_layout_t *layout)
12278 {
12279   Mutex::Locker lock(client_lock);
12280   *layout = in->layout;
12281   return 0;
12282 }
12283
12284 int Client::ll_file_layout(Fh *fh, file_layout_t *layout)
12285 {
12286   return ll_file_layout(fh->inode.get(), layout);
12287 }
12288
12289 /* Currently we cannot take advantage of redundancy in reads, since we
12290    would have to go through all possible placement groups (a
12291    potentially quite large number determined by a hash), and use CRUSH
12292    to calculate the appropriate set of OSDs for each placement group,
12293    then index into that.  An array with one entry per OSD is much more
12294    tractable and works for demonstration purposes. */
12295
12296 int Client::ll_get_stripe_osd(Inode *in, uint64_t blockno,
12297                               file_layout_t* layout)
12298 {
12299   Mutex::Locker lock(client_lock);
12300
12301   inodeno_t ino = ll_get_inodeno(in);
12302   uint32_t object_size = layout->object_size;
12303   uint32_t su = layout->stripe_unit;
12304   uint32_t stripe_count = layout->stripe_count;
12305   uint64_t stripes_per_object = object_size / su;
12306
12307   uint64_t stripeno = blockno / stripe_count;    // which horizontal stripe        (Y)
12308   uint64_t stripepos = blockno % stripe_count;   // which object in the object set (X)
12309   uint64_t objectsetno = stripeno / stripes_per_object;       // which object set
12310   uint64_t objectno = objectsetno * stripe_count + stripepos;  // object id
12311
12312   object_t oid = file_object_t(ino, objectno);
12313   return objecter->with_osdmap([&](const OSDMap& o) {
12314       ceph_object_layout olayout =
12315         o.file_to_object_layout(oid, *layout);
12316       pg_t pg = (pg_t)olayout.ol_pgid;
12317       vector<int> osds;
12318       int primary;
12319       o.pg_to_acting_osds(pg, &osds, &primary);
12320       return primary;
12321     });
12322 }
12323
12324 /* Return the offset of the block, internal to the object */
12325
12326 uint64_t Client::ll_get_internal_offset(Inode *in, uint64_t blockno)
12327 {
12328   Mutex::Locker lock(client_lock);
12329   file_layout_t *layout=&(in->layout);
12330   uint32_t object_size = layout->object_size;
12331   uint32_t su = layout->stripe_unit;
12332   uint64_t stripes_per_object = object_size / su;
12333
12334   return (blockno % stripes_per_object) * su;
12335 }
12336
12337 int Client::ll_opendir(Inode *in, int flags, dir_result_t** dirpp,
12338                        const UserPerm& perms)
12339 {
12340   Mutex::Locker lock(client_lock);
12341
12342   if (unmounting)
12343     return -ENOTCONN;
12344
12345   vinodeno_t vino = _get_vino(in);
12346
12347   ldout(cct, 3) << "ll_opendir " << vino << dendl;
12348   tout(cct) << "ll_opendir" << std::endl;
12349   tout(cct) << vino.ino.val << std::endl;
12350
12351   if (!cct->_conf->fuse_default_permissions) {
12352     int r = may_open(in, flags, perms);
12353     if (r < 0)
12354       return r;
12355   }
12356
12357   int r = _opendir(in, dirpp, perms);
12358   tout(cct) << (unsigned long)*dirpp << std::endl;
12359
12360   ldout(cct, 3) << "ll_opendir " << vino << " = " << r << " (" << *dirpp << ")"
12361                 << dendl;
12362   return r;
12363 }
12364
12365 int Client::ll_releasedir(dir_result_t *dirp)
12366 {
12367   Mutex::Locker lock(client_lock);
12368   ldout(cct, 3) << "ll_releasedir " << dirp << dendl;
12369   tout(cct) << "ll_releasedir" << std::endl;
12370   tout(cct) << (unsigned long)dirp << std::endl;
12371
12372   if (unmounting)
12373     return -ENOTCONN;
12374
12375   _closedir(dirp);
12376   return 0;
12377 }
12378
12379 int Client::ll_fsyncdir(dir_result_t *dirp)
12380 {
12381   Mutex::Locker lock(client_lock);
12382   ldout(cct, 3) << "ll_fsyncdir " << dirp << dendl;
12383   tout(cct) << "ll_fsyncdir" << std::endl;
12384   tout(cct) << (unsigned long)dirp << std::endl;
12385
12386   if (unmounting)
12387     return -ENOTCONN;
12388
12389   return _fsync(dirp->inode.get(), false);
12390 }
12391
12392 int Client::ll_open(Inode *in, int flags, Fh **fhp, const UserPerm& perms)
12393 {
12394   assert(!(flags & O_CREAT));
12395
12396   Mutex::Locker lock(client_lock);
12397
12398   if (unmounting)
12399     return -ENOTCONN;
12400
12401   vinodeno_t vino = _get_vino(in);
12402
12403   ldout(cct, 3) << "ll_open " << vino << " " << ceph_flags_sys2wire(flags) << dendl;
12404   tout(cct) << "ll_open" << std::endl;
12405   tout(cct) << vino.ino.val << std::endl;
12406   tout(cct) << ceph_flags_sys2wire(flags) << std::endl;
12407
12408   int r;
12409   if (!cct->_conf->fuse_default_permissions) {
12410     r = may_open(in, flags, perms);
12411     if (r < 0)
12412       goto out;
12413   }
12414
12415   r = _open(in, flags, 0, fhp /* may be NULL */, perms);
12416
12417  out:
12418   Fh *fhptr = fhp ? *fhp : NULL;
12419   if (fhptr) {
12420     ll_unclosed_fh_set.insert(fhptr);
12421   }
12422   tout(cct) << (unsigned long)fhptr << std::endl;
12423   ldout(cct, 3) << "ll_open " << vino << " " << ceph_flags_sys2wire(flags) <<
12424       " = " << r << " (" << fhptr << ")" << dendl;
12425   return r;
12426 }
12427
12428 int Client::_ll_create(Inode *parent, const char *name, mode_t mode,
12429                       int flags, InodeRef *in, int caps, Fh **fhp,
12430                       const UserPerm& perms)
12431 {
12432   *fhp = NULL;
12433
12434   vinodeno_t vparent = _get_vino(parent);
12435
12436   ldout(cct, 3) << "_ll_create " << vparent << " " << name << " 0" << oct <<
12437     mode << dec << " " << ceph_flags_sys2wire(flags) << ", uid " << perms.uid()
12438                 << ", gid " << perms.gid() << dendl;
12439   tout(cct) << "ll_create" << std::endl;
12440   tout(cct) << vparent.ino.val << std::endl;
12441   tout(cct) << name << std::endl;
12442   tout(cct) << mode << std::endl;
12443   tout(cct) << ceph_flags_sys2wire(flags) << std::endl;
12444
12445   bool created = false;
12446   int r = _lookup(parent, name, caps, in, perms);
12447
12448   if (r == 0 && (flags & O_CREAT) && (flags & O_EXCL))
12449     return -EEXIST;
12450
12451   if (r == -ENOENT && (flags & O_CREAT)) {
12452     if (!cct->_conf->fuse_default_permissions) {
12453       r = may_create(parent, perms);
12454       if (r < 0)
12455         goto out;
12456     }
12457     r = _create(parent, name, flags, mode, in, fhp, 0, 0, 0, NULL, &created,
12458                 perms);
12459     if (r < 0)
12460       goto out;
12461   }
12462
12463   if (r < 0)
12464     goto out;
12465
12466   assert(*in);
12467
12468   ldout(cct, 20) << "_ll_create created = " << created << dendl;
12469   if (!created) {
12470     if (!cct->_conf->fuse_default_permissions) {
12471       r = may_open(in->get(), flags, perms);
12472       if (r < 0) {
12473         if (*fhp) {
12474           int release_r = _release_fh(*fhp);
12475           assert(release_r == 0);  // during create, no async data ops should have happened
12476         }
12477         goto out;
12478       }
12479     }
12480     if (*fhp == NULL) {
12481       r = _open(in->get(), flags, mode, fhp, perms);
12482       if (r < 0)
12483         goto out;
12484     }
12485   }
12486
12487 out:
12488   if (*fhp) {
12489     ll_unclosed_fh_set.insert(*fhp);
12490   }
12491
12492   ino_t ino = 0;
12493   if (r >= 0) {
12494     Inode *inode = in->get();
12495     if (use_faked_inos())
12496       ino = inode->faked_ino;
12497     else
12498       ino = inode->ino;
12499   }
12500
12501   tout(cct) << (unsigned long)*fhp << std::endl;
12502   tout(cct) << ino << std::endl;
12503   ldout(cct, 3) << "_ll_create " << vparent << " " << name << " 0" << oct <<
12504     mode << dec << " " << ceph_flags_sys2wire(flags) << " = " << r << " (" <<
12505     *fhp << " " << hex << ino << dec << ")" << dendl;
12506
12507   return r;
12508 }
12509
12510 int Client::ll_create(Inode *parent, const char *name, mode_t mode,
12511                       int flags, struct stat *attr, Inode **outp, Fh **fhp,
12512                       const UserPerm& perms)
12513 {
12514   Mutex::Locker lock(client_lock);
12515   InodeRef in;
12516
12517   if (unmounting)
12518     return -ENOTCONN;
12519
12520   int r = _ll_create(parent, name, mode, flags, &in, CEPH_STAT_CAP_INODE_ALL,
12521                       fhp, perms);
12522   if (r >= 0) {
12523     assert(in);
12524
12525     // passing an Inode in outp requires an additional ref
12526     if (outp) {
12527       _ll_get(in.get());
12528       *outp = in.get();
12529     }
12530     fill_stat(in, attr);
12531   } else {
12532     attr->st_ino = 0;
12533   }
12534
12535   return r;
12536 }
12537
12538 int Client::ll_createx(Inode *parent, const char *name, mode_t mode,
12539                         int oflags, Inode **outp, Fh **fhp,
12540                         struct ceph_statx *stx, unsigned want, unsigned lflags,
12541                         const UserPerm& perms)
12542 {
12543   unsigned caps = statx_to_mask(lflags, want);
12544   Mutex::Locker lock(client_lock);
12545   InodeRef in;
12546
12547   if (unmounting)
12548     return -ENOTCONN;
12549
12550   int r = _ll_create(parent, name, mode, oflags, &in, caps, fhp, perms);
12551   if (r >= 0) {
12552     assert(in);
12553
12554     // passing an Inode in outp requires an additional ref
12555     if (outp) {
12556       _ll_get(in.get());
12557       *outp = in.get();
12558     }
12559     fill_statx(in, caps, stx);
12560   } else {
12561     stx->stx_ino = 0;
12562     stx->stx_mask = 0;
12563   }
12564
12565   return r;
12566 }
12567
12568 loff_t Client::ll_lseek(Fh *fh, loff_t offset, int whence)
12569 {
12570   Mutex::Locker lock(client_lock);
12571   tout(cct) << "ll_lseek" << std::endl;
12572   tout(cct) << offset << std::endl;
12573   tout(cct) << whence << std::endl;
12574
12575   if (unmounting)
12576     return -ENOTCONN;
12577
12578   return _lseek(fh, offset, whence);
12579 }
12580
12581 int Client::ll_read(Fh *fh, loff_t off, loff_t len, bufferlist *bl)
12582 {
12583   Mutex::Locker lock(client_lock);
12584   ldout(cct, 3) << "ll_read " << fh << " " << fh->inode->ino << " " << " " << off << "~" << len << dendl;
12585   tout(cct) << "ll_read" << std::endl;
12586   tout(cct) << (unsigned long)fh << std::endl;
12587   tout(cct) << off << std::endl;
12588   tout(cct) << len << std::endl;
12589
12590   if (unmounting)
12591     return -ENOTCONN;
12592
12593   return _read(fh, off, len, bl);
12594 }
12595
12596 int Client::ll_read_block(Inode *in, uint64_t blockid,
12597                           char *buf,
12598                           uint64_t offset,
12599                           uint64_t length,
12600                           file_layout_t* layout)
12601 {
12602   Mutex::Locker lock(client_lock);
12603
12604   if (unmounting)
12605     return -ENOTCONN;
12606
12607   vinodeno_t vino = ll_get_vino(in);
12608   object_t oid = file_object_t(vino.ino, blockid);
12609   C_SaferCond onfinish;
12610   bufferlist bl;
12611
12612   objecter->read(oid,
12613                  object_locator_t(layout->pool_id),
12614                  offset,
12615                  length,
12616                  vino.snapid,
12617                  &bl,
12618                  CEPH_OSD_FLAG_READ,
12619                  &onfinish);
12620
12621   client_lock.Unlock();
12622   int r = onfinish.wait();
12623   client_lock.Lock();
12624
12625   if (r >= 0) {
12626       bl.copy(0, bl.length(), buf);
12627       r = bl.length();
12628   }
12629
12630   return r;
12631 }
12632
12633 /* It appears that the OSD doesn't return success unless the entire
12634    buffer was written, return the write length on success. */
12635
12636 int Client::ll_write_block(Inode *in, uint64_t blockid,
12637                            char* buf, uint64_t offset,
12638                            uint64_t length, file_layout_t* layout,
12639                            uint64_t snapseq, uint32_t sync)
12640 {
12641   Mutex flock("Client::ll_write_block flock");
12642   vinodeno_t vino = ll_get_vino(in);
12643   Cond cond;
12644   bool done;
12645   int r = 0;
12646   Context *onsafe = nullptr;
12647
12648   if (length == 0) {
12649     return -EINVAL;
12650   }
12651   if (true || sync) {
12652     /* if write is stable, the epilogue is waiting on
12653      * flock */
12654     onsafe = new C_SafeCond(&flock, &cond, &done, &r);
12655     done = false;
12656   } else {
12657     /* if write is unstable, we just place a barrier for
12658      * future commits to wait on */
12659     /*onsafe = new C_Block_Sync(this, vino.ino,
12660                               barrier_interval(offset, offset + length), &r);
12661     */
12662     done = true;
12663   }
12664   object_t oid = file_object_t(vino.ino, blockid);
12665   SnapContext fakesnap;
12666   bufferptr bp;
12667   if (length > 0) bp = buffer::copy(buf, length);
12668   bufferlist bl;
12669   bl.push_back(bp);
12670
12671   ldout(cct, 1) << "ll_block_write for " << vino.ino << "." << blockid
12672                 << dendl;
12673
12674   fakesnap.seq = snapseq;
12675
12676   /* lock just in time */
12677   client_lock.Lock();
12678   if (unmounting) {
12679     client_lock.Unlock();
12680     delete onsafe;
12681     return -ENOTCONN;
12682   }
12683
12684   objecter->write(oid,
12685                   object_locator_t(layout->pool_id),
12686                   offset,
12687                   length,
12688                   fakesnap,
12689                   bl,
12690                   ceph::real_clock::now(),
12691                   0,
12692                   onsafe);
12693
12694   client_lock.Unlock();
12695   if (!done /* also !sync */) {
12696     flock.Lock();
12697     while (! done)
12698       cond.Wait(flock);
12699     flock.Unlock();
12700   }
12701
12702   if (r < 0) {
12703     return r;
12704   } else {
12705     return length;
12706   }
12707 }
12708
12709 int Client::ll_commit_blocks(Inode *in,
12710                              uint64_t offset,
12711                              uint64_t length)
12712 {
12713     Mutex::Locker lock(client_lock);
12714     /*
12715     BarrierContext *bctx;
12716     vinodeno_t vino = ll_get_vino(in);
12717     uint64_t ino = vino.ino;
12718
12719     ldout(cct, 1) << "ll_commit_blocks for " << vino.ino << " from "
12720                   << offset << " to " << length << dendl;
12721
12722     if (length == 0) {
12723       return -EINVAL;
12724     }
12725
12726     map<uint64_t, BarrierContext*>::iterator p = barriers.find(ino);
12727     if (p != barriers.end()) {
12728       barrier_interval civ(offset, offset + length);
12729       p->second->commit_barrier(civ);
12730     }
12731     */
12732     return 0;
12733 }
12734
12735 int Client::ll_write(Fh *fh, loff_t off, loff_t len, const char *data)
12736 {
12737   Mutex::Locker lock(client_lock);
12738   ldout(cct, 3) << "ll_write " << fh << " " << fh->inode->ino << " " << off <<
12739     "~" << len << dendl;
12740   tout(cct) << "ll_write" << std::endl;
12741   tout(cct) << (unsigned long)fh << std::endl;
12742   tout(cct) << off << std::endl;
12743   tout(cct) << len << std::endl;
12744
12745   if (unmounting)
12746     return -ENOTCONN;
12747
12748   int r = _write(fh, off, len, data, NULL, 0);
12749   ldout(cct, 3) << "ll_write " << fh << " " << off << "~" << len << " = " << r
12750                 << dendl;
12751   return r;
12752 }
12753
12754 int Client::ll_flush(Fh *fh)
12755 {
12756   Mutex::Locker lock(client_lock);
12757   ldout(cct, 3) << "ll_flush " << fh << " " << fh->inode->ino << " " << dendl;
12758   tout(cct) << "ll_flush" << std::endl;
12759   tout(cct) << (unsigned long)fh << std::endl;
12760
12761   if (unmounting)
12762     return -ENOTCONN;
12763
12764   return _flush(fh);
12765 }
12766
12767 int Client::ll_fsync(Fh *fh, bool syncdataonly)
12768 {
12769   Mutex::Locker lock(client_lock);
12770   ldout(cct, 3) << "ll_fsync " << fh << " " << fh->inode->ino << " " << dendl;
12771   tout(cct) << "ll_fsync" << std::endl;
12772   tout(cct) << (unsigned long)fh << std::endl;
12773
12774   if (unmounting)
12775     return -ENOTCONN;
12776
12777   int r = _fsync(fh, syncdataonly);
12778   if (r) {
12779     // If we're returning an error, clear it from the FH
12780     fh->take_async_err();
12781   }
12782   return r;
12783 }
12784
12785 #ifdef FALLOC_FL_PUNCH_HOLE
12786
12787 int Client::_fallocate(Fh *fh, int mode, int64_t offset, int64_t length)
12788 {
12789   if (offset < 0 || length <= 0)
12790     return -EINVAL;
12791
12792   if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
12793     return -EOPNOTSUPP;
12794
12795   if ((mode & FALLOC_FL_PUNCH_HOLE) && !(mode & FALLOC_FL_KEEP_SIZE))
12796     return -EOPNOTSUPP;
12797
12798   Inode *in = fh->inode.get();
12799
12800   if (objecter->osdmap_pool_full(in->layout.pool_id) &&
12801       !(mode & FALLOC_FL_PUNCH_HOLE)) {
12802     return -ENOSPC;
12803   }
12804
12805   if (in->snapid != CEPH_NOSNAP)
12806     return -EROFS;
12807
12808   if ((fh->mode & CEPH_FILE_MODE_WR) == 0)
12809     return -EBADF;
12810
12811   uint64_t size = offset + length;
12812   if (!(mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE)) &&
12813       size > in->size &&
12814       is_quota_bytes_exceeded(in, size - in->size, fh->actor_perms)) {
12815     return -EDQUOT;
12816   }
12817
12818   int have;
12819   int r = get_caps(in, CEPH_CAP_FILE_WR, CEPH_CAP_FILE_BUFFER, &have, -1);
12820   if (r < 0)
12821     return r;
12822
12823   Mutex uninline_flock("Client::_fallocate_uninline_data flock");
12824   Cond uninline_cond;
12825   bool uninline_done = false;
12826   int uninline_ret = 0;
12827   Context *onuninline = NULL;
12828
12829   if (mode & FALLOC_FL_PUNCH_HOLE) {
12830     if (in->inline_version < CEPH_INLINE_NONE &&
12831         (have & CEPH_CAP_FILE_BUFFER)) {
12832       bufferlist bl;
12833       int len = in->inline_data.length();
12834       if (offset < len) {
12835         if (offset > 0)
12836           in->inline_data.copy(0, offset, bl);
12837         int size = length;
12838         if (offset + size > len)
12839           size = len - offset;
12840         if (size > 0)
12841           bl.append_zero(size);
12842         if (offset + size < len)
12843           in->inline_data.copy(offset + size, len - offset - size, bl);
12844         in->inline_data = bl;
12845         in->inline_version++;
12846       }
12847       in->mtime = ceph_clock_now();
12848       in->change_attr++;
12849       mark_caps_dirty(in, CEPH_CAP_FILE_WR);
12850     } else {
12851       if (in->inline_version < CEPH_INLINE_NONE) {
12852         onuninline = new C_SafeCond(&uninline_flock,
12853                                     &uninline_cond,
12854                                     &uninline_done,
12855                                     &uninline_ret);
12856         uninline_data(in, onuninline);
12857       }
12858
12859       Mutex flock("Client::_punch_hole flock");
12860       Cond cond;
12861       bool done = false;
12862       Context *onfinish = new C_SafeCond(&flock, &cond, &done);
12863
12864       unsafe_sync_write++;
12865       get_cap_ref(in, CEPH_CAP_FILE_BUFFER);
12866
12867       _invalidate_inode_cache(in, offset, length);
12868       filer->zero(in->ino, &in->layout,
12869                   in->snaprealm->get_snap_context(),
12870                   offset, length,
12871                   ceph::real_clock::now(),
12872                   0, true, onfinish);
12873       in->mtime = ceph_clock_now();
12874       in->change_attr++;
12875       mark_caps_dirty(in, CEPH_CAP_FILE_WR);
12876
12877       client_lock.Unlock();
12878       flock.Lock();
12879       while (!done)
12880         cond.Wait(flock);
12881       flock.Unlock();
12882       client_lock.Lock();
12883       _sync_write_commit(in);
12884     }
12885   } else if (!(mode & FALLOC_FL_KEEP_SIZE)) {
12886     uint64_t size = offset + length;
12887     if (size > in->size) {
12888       in->size = size;
12889       in->mtime = ceph_clock_now();
12890       in->change_attr++;
12891       mark_caps_dirty(in, CEPH_CAP_FILE_WR);
12892
12893       if (is_quota_bytes_approaching(in, fh->actor_perms)) {
12894         check_caps(in, CHECK_CAPS_NODELAY);
12895       } else if (is_max_size_approaching(in)) {
12896         check_caps(in, 0);
12897       }
12898     }
12899   }
12900
12901   if (onuninline) {
12902     client_lock.Unlock();
12903     uninline_flock.Lock();
12904     while (!uninline_done)
12905       uninline_cond.Wait(uninline_flock);
12906     uninline_flock.Unlock();
12907     client_lock.Lock();
12908
12909     if (uninline_ret >= 0 || uninline_ret == -ECANCELED) {
12910       in->inline_data.clear();
12911       in->inline_version = CEPH_INLINE_NONE;
12912       mark_caps_dirty(in, CEPH_CAP_FILE_WR);
12913       check_caps(in, 0);
12914     } else
12915       r = uninline_ret;
12916   }
12917
12918   put_cap_ref(in, CEPH_CAP_FILE_WR);
12919   return r;
12920 }
12921 #else
12922
12923 int Client::_fallocate(Fh *fh, int mode, int64_t offset, int64_t length)
12924 {
12925   return -EOPNOTSUPP;
12926 }
12927
12928 #endif
12929
12930
12931 int Client::ll_fallocate(Fh *fh, int mode, loff_t offset, loff_t length)
12932 {
12933   Mutex::Locker lock(client_lock);
12934   ldout(cct, 3) << "ll_fallocate " << fh << " " << fh->inode->ino << " " << dendl;
12935   tout(cct) << "ll_fallocate " << mode << " " << offset << " " << length << std::endl;
12936   tout(cct) << (unsigned long)fh << std::endl;
12937
12938   if (unmounting)
12939     return -ENOTCONN;
12940
12941   return _fallocate(fh, mode, offset, length);
12942 }
12943
12944 int Client::fallocate(int fd, int mode, loff_t offset, loff_t length)
12945 {
12946   Mutex::Locker lock(client_lock);
12947   tout(cct) << "fallocate " << " " << fd << mode << " " << offset << " " << length << std::endl;
12948
12949   if (unmounting)
12950     return -ENOTCONN;
12951
12952   Fh *fh = get_filehandle(fd);
12953   if (!fh)
12954     return -EBADF;
12955 #if defined(__linux__) && defined(O_PATH)
12956   if (fh->flags & O_PATH)
12957     return -EBADF;
12958 #endif
12959   return _fallocate(fh, mode, offset, length);
12960 }
12961
12962 int Client::ll_release(Fh *fh)
12963 {
12964   Mutex::Locker lock(client_lock);
12965   ldout(cct, 3) << "ll_release (fh)" << fh << " " << fh->inode->ino << " " <<
12966     dendl;
12967   tout(cct) << "ll_release (fh)" << std::endl;
12968   tout(cct) << (unsigned long)fh << std::endl;
12969
12970   if (unmounting)
12971     return -ENOTCONN;
12972
12973   if (ll_unclosed_fh_set.count(fh))
12974     ll_unclosed_fh_set.erase(fh);
12975   return _release_fh(fh);
12976 }
12977
12978 int Client::ll_getlk(Fh *fh, struct flock *fl, uint64_t owner)
12979 {
12980   Mutex::Locker lock(client_lock);
12981
12982   ldout(cct, 3) << "ll_getlk (fh)" << fh << " " << fh->inode->ino << dendl;
12983   tout(cct) << "ll_getk (fh)" << (unsigned long)fh << std::endl;
12984
12985   if (unmounting)
12986     return -ENOTCONN;
12987
12988   return _getlk(fh, fl, owner);
12989 }
12990
12991 int Client::ll_setlk(Fh *fh, struct flock *fl, uint64_t owner, int sleep)
12992 {
12993   Mutex::Locker lock(client_lock);
12994
12995   ldout(cct, 3) << "ll_setlk  (fh) " << fh << " " << fh->inode->ino << dendl;
12996   tout(cct) << "ll_setk (fh)" << (unsigned long)fh << std::endl;
12997
12998   if (unmounting)
12999     return -ENOTCONN;
13000
13001   return _setlk(fh, fl, owner, sleep);
13002 }
13003
13004 int Client::ll_flock(Fh *fh, int cmd, uint64_t owner)
13005 {
13006   Mutex::Locker lock(client_lock);
13007
13008   ldout(cct, 3) << "ll_flock  (fh) " << fh << " " << fh->inode->ino << dendl;
13009   tout(cct) << "ll_flock (fh)" << (unsigned long)fh << std::endl;
13010
13011   if (unmounting)
13012     return -ENOTCONN;
13013
13014   return _flock(fh, cmd, owner);
13015 }
13016
13017 class C_Client_RequestInterrupt : public Context  {
13018 private:
13019   Client *client;
13020   MetaRequest *req;
13021 public:
13022   C_Client_RequestInterrupt(Client *c, MetaRequest *r) : client(c), req(r) {
13023     req->get();
13024   }
13025   void finish(int r) override {
13026     Mutex::Locker l(client->client_lock);
13027     assert(req->head.op == CEPH_MDS_OP_SETFILELOCK);
13028     client->_interrupt_filelock(req);
13029     client->put_request(req);
13030   }
13031 };
13032
13033 void Client::ll_interrupt(void *d)
13034 {
13035   MetaRequest *req = static_cast<MetaRequest*>(d);
13036   ldout(cct, 3) << "ll_interrupt tid " << req->get_tid() << dendl;
13037   tout(cct) << "ll_interrupt tid " << req->get_tid() << std::endl;
13038   interrupt_finisher.queue(new C_Client_RequestInterrupt(this, req));
13039 }
13040
13041 // =========================================
13042 // layout
13043
13044 // expose file layouts
13045
13046 int Client::describe_layout(const char *relpath, file_layout_t *lp,
13047                             const UserPerm& perms)
13048 {
13049   Mutex::Locker lock(client_lock);
13050
13051   if (unmounting)
13052     return -ENOTCONN;
13053
13054   filepath path(relpath);
13055   InodeRef in;
13056   int r = path_walk(path, &in, perms);
13057   if (r < 0)
13058     return r;
13059
13060   *lp = in->layout;
13061
13062   ldout(cct, 3) << "describe_layout(" << relpath << ") = 0" << dendl;
13063   return 0;
13064 }
13065
13066 int Client::fdescribe_layout(int fd, file_layout_t *lp)
13067 {
13068   Mutex::Locker lock(client_lock);
13069
13070   if (unmounting)
13071     return -ENOTCONN;
13072
13073   Fh *f = get_filehandle(fd);
13074   if (!f)
13075     return -EBADF;
13076   Inode *in = f->inode.get();
13077
13078   *lp = in->layout;
13079
13080   ldout(cct, 3) << "fdescribe_layout(" << fd << ") = 0" << dendl;
13081   return 0;
13082 }
13083
13084 int64_t Client::get_default_pool_id()
13085 {
13086   Mutex::Locker lock(client_lock);
13087
13088   if (unmounting)
13089     return -ENOTCONN;
13090
13091   /* first data pool is the default */ 
13092   return mdsmap->get_first_data_pool(); 
13093 }
13094
13095 // expose osdmap
13096
13097 int64_t Client::get_pool_id(const char *pool_name)
13098 {
13099   Mutex::Locker lock(client_lock);
13100
13101   if (unmounting)
13102     return -ENOTCONN;
13103
13104   return objecter->with_osdmap(std::mem_fn(&OSDMap::lookup_pg_pool_name),
13105                                pool_name);
13106 }
13107
13108 string Client::get_pool_name(int64_t pool)
13109 {
13110   Mutex::Locker lock(client_lock);
13111
13112   if (unmounting)
13113     return string();
13114
13115   return objecter->with_osdmap([pool](const OSDMap& o) {
13116       return o.have_pg_pool(pool) ? o.get_pool_name(pool) : string();
13117     });
13118 }
13119
13120 int Client::get_pool_replication(int64_t pool)
13121 {
13122   Mutex::Locker lock(client_lock);
13123
13124   if (unmounting)
13125     return -ENOTCONN;
13126
13127   return objecter->with_osdmap([pool](const OSDMap& o) {
13128       return o.have_pg_pool(pool) ? o.get_pg_pool(pool)->get_size() : -ENOENT;
13129     });
13130 }
13131
13132 int Client::get_file_extent_osds(int fd, loff_t off, loff_t *len, vector<int>& osds)
13133 {
13134   Mutex::Locker lock(client_lock);
13135
13136   if (unmounting)
13137     return -ENOTCONN;
13138
13139   Fh *f = get_filehandle(fd);
13140   if (!f)
13141     return -EBADF;
13142   Inode *in = f->inode.get();
13143
13144   vector<ObjectExtent> extents;
13145   Striper::file_to_extents(cct, in->ino, &in->layout, off, 1, in->truncate_size, extents);
13146   assert(extents.size() == 1);
13147
13148   objecter->with_osdmap([&](const OSDMap& o) {
13149       pg_t pg = o.object_locator_to_pg(extents[0].oid, extents[0].oloc);
13150       o.pg_to_acting_osds(pg, osds);
13151     });
13152
13153   if (osds.empty())
13154     return -EINVAL;
13155
13156   /*
13157    * Return the remainder of the extent (stripe unit)
13158    *
13159    * If length = 1 is passed to Striper::file_to_extents we get a single
13160    * extent back, but its length is one so we still need to compute the length
13161    * to the end of the stripe unit.
13162    *
13163    * If length = su then we may get 1 or 2 objects back in the extents vector
13164    * which would have to be examined. Even then, the offsets are local to the
13165    * object, so matching up to the file offset is extra work.
13166    *
13167    * It seems simpler to stick with length = 1 and manually compute the
13168    * remainder.
13169    */
13170   if (len) {
13171     uint64_t su = in->layout.stripe_unit;
13172     *len = su - (off % su);
13173   }
13174
13175   return 0;
13176 }
13177
13178 int Client::get_osd_crush_location(int id, vector<pair<string, string> >& path)
13179 {
13180   Mutex::Locker lock(client_lock);
13181
13182   if (unmounting)
13183     return -ENOTCONN;
13184
13185   if (id < 0)
13186     return -EINVAL;
13187   return objecter->with_osdmap([&](const OSDMap& o) {
13188       return o.crush->get_full_location_ordered(id, path);
13189     });
13190 }
13191
13192 int Client::get_file_stripe_address(int fd, loff_t offset,
13193                                     vector<entity_addr_t>& address)
13194 {
13195   Mutex::Locker lock(client_lock);
13196
13197   if (unmounting)
13198     return -ENOTCONN;
13199
13200   Fh *f = get_filehandle(fd);
13201   if (!f)
13202     return -EBADF;
13203   Inode *in = f->inode.get();
13204
13205   // which object?
13206   vector<ObjectExtent> extents;
13207   Striper::file_to_extents(cct, in->ino, &in->layout, offset, 1,
13208                            in->truncate_size, extents);
13209   assert(extents.size() == 1);
13210
13211   // now we have the object and its 'layout'
13212   return objecter->with_osdmap([&](const OSDMap& o) {
13213       pg_t pg = o.object_locator_to_pg(extents[0].oid, extents[0].oloc);
13214       vector<int> osds;
13215       o.pg_to_acting_osds(pg, osds);
13216       if (osds.empty())
13217         return -EINVAL;
13218       for (unsigned i = 0; i < osds.size(); i++) {
13219         entity_addr_t addr = o.get_addr(osds[i]);
13220         address.push_back(addr);
13221       }
13222       return 0;
13223     });
13224 }
13225
13226 int Client::get_osd_addr(int osd, entity_addr_t& addr)
13227 {
13228   Mutex::Locker lock(client_lock);
13229
13230   if (unmounting)
13231     return -ENOTCONN;
13232
13233   return objecter->with_osdmap([&](const OSDMap& o) {
13234       if (!o.exists(osd))
13235         return -ENOENT;
13236
13237       addr = o.get_addr(osd);
13238       return 0;
13239     });
13240 }
13241
13242 int Client::enumerate_layout(int fd, vector<ObjectExtent>& result,
13243                              loff_t length, loff_t offset)
13244 {
13245   Mutex::Locker lock(client_lock);
13246
13247   if (unmounting)
13248     return -ENOTCONN;
13249
13250   Fh *f = get_filehandle(fd);
13251   if (!f)
13252     return -EBADF;
13253   Inode *in = f->inode.get();
13254
13255   // map to a list of extents
13256   Striper::file_to_extents(cct, in->ino, &in->layout, offset, length, in->truncate_size, result);
13257
13258   ldout(cct, 3) << "enumerate_layout(" << fd << ", " << length << ", " << offset << ") = 0" << dendl;
13259   return 0;
13260 }
13261
13262
13263 /*
13264  * find an osd with the same ip.  -1 if none.
13265  */
13266 int Client::get_local_osd()
13267 {
13268   Mutex::Locker lock(client_lock);
13269
13270   if (unmounting)
13271     return -ENOTCONN;
13272
13273   objecter->with_osdmap([this](const OSDMap& o) {
13274       if (o.get_epoch() != local_osd_epoch) {
13275         local_osd = o.find_osd_on_ip(messenger->get_myaddr());
13276         local_osd_epoch = o.get_epoch();
13277       }
13278     });
13279   return local_osd;
13280 }
13281
13282
13283
13284
13285
13286
13287 // ===============================
13288
13289 void Client::ms_handle_connect(Connection *con)
13290 {
13291   ldout(cct, 10) << "ms_handle_connect on " << con->get_peer_addr() << dendl;
13292 }
13293
13294 bool Client::ms_handle_reset(Connection *con)
13295 {
13296   ldout(cct, 0) << "ms_handle_reset on " << con->get_peer_addr() << dendl;
13297   return false;
13298 }
13299
13300 void Client::ms_handle_remote_reset(Connection *con)
13301 {
13302   ldout(cct, 0) << "ms_handle_remote_reset on " << con->get_peer_addr() << dendl;
13303   Mutex::Locker l(client_lock);
13304   switch (con->get_peer_type()) {
13305   case CEPH_ENTITY_TYPE_MDS:
13306     {
13307       // kludge to figure out which mds this is; fixme with a Connection* state
13308       mds_rank_t mds = MDS_RANK_NONE;
13309       MetaSession *s = NULL;
13310       for (map<mds_rank_t,MetaSession*>::iterator p = mds_sessions.begin();
13311            p != mds_sessions.end();
13312            ++p) {
13313         if (mdsmap->get_addr(p->first) == con->get_peer_addr()) {
13314           mds = p->first;
13315           s = p->second;
13316         }
13317       }
13318       if (mds >= 0) {
13319         assert (s != NULL);
13320         switch (s->state) {
13321         case MetaSession::STATE_CLOSING:
13322           ldout(cct, 1) << "reset from mds we were closing; we'll call that closed" << dendl;
13323           _closed_mds_session(s);
13324           break;
13325
13326         case MetaSession::STATE_OPENING:
13327           {
13328             ldout(cct, 1) << "reset from mds we were opening; retrying" << dendl;
13329             list<Context*> waiters;
13330             waiters.swap(s->waiting_for_open);
13331             _closed_mds_session(s);
13332             MetaSession *news = _get_or_open_mds_session(mds);
13333             news->waiting_for_open.swap(waiters);
13334           }
13335           break;
13336
13337         case MetaSession::STATE_OPEN:
13338           {
13339             const md_config_t *conf = cct->_conf;
13340             if (conf->client_reconnect_stale) {
13341               ldout(cct, 1) << "reset from mds we were open; close mds session for reconnect" << dendl;
13342               _closed_mds_session(s);
13343             } else {
13344               ldout(cct, 1) << "reset from mds we were open; mark session as stale" << dendl;
13345               s->state = MetaSession::STATE_STALE;
13346             }
13347           }
13348           break;
13349
13350         case MetaSession::STATE_NEW:
13351         case MetaSession::STATE_CLOSED:
13352         default:
13353           break;
13354         }
13355       }
13356     }
13357     break;
13358   }
13359 }
13360
13361 bool Client::ms_handle_refused(Connection *con)
13362 {
13363   ldout(cct, 1) << "ms_handle_refused on " << con->get_peer_addr() << dendl;
13364   return false;
13365 }
13366
13367 bool Client::ms_get_authorizer(int dest_type, AuthAuthorizer **authorizer, bool force_new)
13368 {
13369   if (dest_type == CEPH_ENTITY_TYPE_MON)
13370     return true;
13371   *authorizer = monclient->build_authorizer(dest_type);
13372   return true;
13373 }
13374
13375 Inode *Client::get_quota_root(Inode *in, const UserPerm& perms)
13376 {
13377   Inode *cur = in;
13378   utime_t now = ceph_clock_now();
13379
13380   while (cur) {
13381     if (cur != in && cur->quota.is_enable())
13382       break;
13383
13384     Inode *parent_in = NULL;
13385     if (!cur->dn_set.empty()) {
13386       for (auto p = cur->dn_set.begin(); p != cur->dn_set.end(); ++p) {
13387         Dentry *dn = *p;
13388         if (dn->lease_mds >= 0 &&
13389             dn->lease_ttl > now &&
13390             mds_sessions.count(dn->lease_mds)) {
13391           parent_in = dn->dir->parent_inode;
13392         } else {
13393           Inode *diri = dn->dir->parent_inode;
13394           if (diri->caps_issued_mask(CEPH_CAP_FILE_SHARED) &&
13395               diri->shared_gen == dn->cap_shared_gen) {
13396             parent_in = dn->dir->parent_inode;
13397           }
13398         }
13399         if (parent_in)
13400           break;
13401       }
13402     } else if (root_parents.count(cur)) {
13403       parent_in = root_parents[cur].get();
13404     }
13405
13406     if (parent_in) {
13407       cur = parent_in;
13408       continue;
13409     }
13410
13411     if (cur == root_ancestor)
13412       break;
13413
13414     // deleted inode
13415     if (cur->nlink == 0) {
13416       cur = root_ancestor;
13417       break;
13418     }
13419
13420     MetaRequest *req = new MetaRequest(CEPH_MDS_OP_LOOKUPNAME);
13421     filepath path(cur->ino);
13422     req->set_filepath(path);
13423     req->set_inode(cur);
13424
13425     InodeRef parent_ref;
13426     int ret = make_request(req, perms, &parent_ref);
13427     if (ret < 0) {
13428       ldout(cct, 1) << __func__ << " " << in->vino()
13429                     << " failed to find parent of " << cur->vino()
13430                     << " err " << ret <<  dendl;
13431       // FIXME: what to do?
13432       cur = root_ancestor;
13433       break;
13434     }
13435
13436     now = ceph_clock_now();
13437     if (cur == in)
13438       cur = parent_ref.get();
13439     else
13440       cur = in; // start over
13441   }
13442
13443   ldout(cct, 10) << __func__ << " " << in->vino() << " -> " << cur->vino() << dendl;
13444   return cur;
13445 }
13446
13447 /**
13448  * Traverse quota ancestors of the Inode, return true
13449  * if any of them passes the passed function
13450  */
13451 bool Client::check_quota_condition(Inode *in, const UserPerm& perms,
13452                                    std::function<bool (const Inode &in)> test)
13453 {
13454   while (true) {
13455     assert(in != NULL);
13456     if (test(*in)) {
13457       return true;
13458     }
13459
13460     if (in == root_ancestor) {
13461       // We're done traversing, drop out
13462       return false;
13463     } else {
13464       // Continue up the tree
13465       in = get_quota_root(in, perms);
13466     }
13467   }
13468
13469   return false;
13470 }
13471
13472 bool Client::is_quota_files_exceeded(Inode *in, const UserPerm& perms)
13473 {
13474   return check_quota_condition(in, perms,
13475       [](const Inode &in) {
13476         return in.quota.max_files && in.rstat.rsize() >= in.quota.max_files;
13477       });
13478 }
13479
13480 bool Client::is_quota_bytes_exceeded(Inode *in, int64_t new_bytes,
13481                                      const UserPerm& perms)
13482 {
13483   return check_quota_condition(in, perms,
13484       [&new_bytes](const Inode &in) {
13485         return in.quota.max_bytes && (in.rstat.rbytes + new_bytes)
13486                > in.quota.max_bytes;
13487       });
13488 }
13489
13490 bool Client::is_quota_bytes_approaching(Inode *in, const UserPerm& perms)
13491 {
13492   return check_quota_condition(in, perms,
13493       [](const Inode &in) {
13494         if (in.quota.max_bytes) {
13495           if (in.rstat.rbytes >= in.quota.max_bytes) {
13496             return true;
13497           }
13498
13499           assert(in.size >= in.reported_size);
13500           const uint64_t space = in.quota.max_bytes - in.rstat.rbytes;
13501           const uint64_t size = in.size - in.reported_size;
13502           return (space >> 4) < size;
13503         } else {
13504           return false;
13505         }
13506       });
13507 }
13508
13509 enum {
13510   POOL_CHECKED = 1,
13511   POOL_CHECKING = 2,
13512   POOL_READ = 4,
13513   POOL_WRITE = 8,
13514 };
13515
13516 int Client::check_pool_perm(Inode *in, int need)
13517 {
13518   if (!cct->_conf->client_check_pool_perm)
13519     return 0;
13520
13521   int64_t pool_id = in->layout.pool_id;
13522   std::string pool_ns = in->layout.pool_ns;
13523   std::pair<int64_t, std::string> perm_key(pool_id, pool_ns);
13524   int have = 0;
13525   while (true) {
13526     auto it = pool_perms.find(perm_key);
13527     if (it == pool_perms.end())
13528       break;
13529     if (it->second == POOL_CHECKING) {
13530       // avoid concurrent checkings
13531       wait_on_list(waiting_for_pool_perm);
13532     } else {
13533       have = it->second;
13534       assert(have & POOL_CHECKED);
13535       break;
13536     }
13537   }
13538
13539   if (!have) {
13540     if (in->snapid != CEPH_NOSNAP) {
13541       // pool permission check needs to write to the first object. But for snapshot,
13542       // head of the first object may have alread been deleted. To avoid creating
13543       // orphan object, skip the check for now.
13544       return 0;
13545     }
13546
13547     pool_perms[perm_key] = POOL_CHECKING;
13548
13549     char oid_buf[32];
13550     snprintf(oid_buf, sizeof(oid_buf), "%llx.00000000", (unsigned long long)in->ino);
13551     object_t oid = oid_buf;
13552
13553     SnapContext nullsnapc;
13554
13555     C_SaferCond rd_cond;
13556     ObjectOperation rd_op;
13557     rd_op.stat(NULL, (ceph::real_time*)nullptr, NULL);
13558
13559     objecter->mutate(oid, OSDMap::file_to_object_locator(in->layout), rd_op,
13560                      nullsnapc, ceph::real_clock::now(), 0, &rd_cond);
13561
13562     C_SaferCond wr_cond;
13563     ObjectOperation wr_op;
13564     wr_op.create(true);
13565
13566     objecter->mutate(oid, OSDMap::file_to_object_locator(in->layout), wr_op,
13567                      nullsnapc, ceph::real_clock::now(), 0, &wr_cond);
13568
13569     client_lock.Unlock();
13570     int rd_ret = rd_cond.wait();
13571     int wr_ret = wr_cond.wait();
13572     client_lock.Lock();
13573
13574     bool errored = false;
13575
13576     if (rd_ret == 0 || rd_ret == -ENOENT)
13577       have |= POOL_READ;
13578     else if (rd_ret != -EPERM) {
13579       ldout(cct, 10) << "check_pool_perm on pool " << pool_id << " ns " << pool_ns
13580                      << " rd_err = " << rd_ret << " wr_err = " << wr_ret << dendl;
13581       errored = true;
13582     }
13583
13584     if (wr_ret == 0 || wr_ret == -EEXIST)
13585       have |= POOL_WRITE;
13586     else if (wr_ret != -EPERM) {
13587       ldout(cct, 10) << "check_pool_perm on pool " << pool_id << " ns " << pool_ns
13588                      << " rd_err = " << rd_ret << " wr_err = " << wr_ret << dendl;
13589       errored = true;
13590     }
13591
13592     if (errored) {
13593       // Indeterminate: erase CHECKING state so that subsequent calls re-check.
13594       // Raise EIO because actual error code might be misleading for
13595       // userspace filesystem user.
13596       pool_perms.erase(perm_key);
13597       signal_cond_list(waiting_for_pool_perm);
13598       return -EIO;
13599     }
13600
13601     pool_perms[perm_key] = have | POOL_CHECKED;
13602     signal_cond_list(waiting_for_pool_perm);
13603   }
13604
13605   if ((need & CEPH_CAP_FILE_RD) && !(have & POOL_READ)) {
13606     ldout(cct, 10) << "check_pool_perm on pool " << pool_id << " ns " << pool_ns
13607                    << " need " << ccap_string(need) << ", but no read perm" << dendl;
13608     return -EPERM;
13609   }
13610   if ((need & CEPH_CAP_FILE_WR) && !(have & POOL_WRITE)) {
13611     ldout(cct, 10) << "check_pool_perm on pool " << pool_id << " ns " << pool_ns
13612                    << " need " << ccap_string(need) << ", but no write perm" << dendl;
13613     return -EPERM;
13614   }
13615
13616   return 0;
13617 }
13618
13619 int Client::_posix_acl_permission(Inode *in, const UserPerm& perms, unsigned want)
13620 {
13621   if (acl_type == POSIX_ACL) {
13622     if (in->xattrs.count(ACL_EA_ACCESS)) {
13623       const bufferptr& access_acl = in->xattrs[ACL_EA_ACCESS];
13624
13625       return posix_acl_permits(access_acl, in->uid, in->gid, perms, want);
13626     }
13627   }
13628   return -EAGAIN;
13629 }
13630
13631 int Client::_posix_acl_chmod(Inode *in, mode_t mode, const UserPerm& perms)
13632 {
13633   if (acl_type == NO_ACL)
13634     return 0;
13635
13636   int r = _getattr(in, CEPH_STAT_CAP_XATTR, perms, in->xattr_version == 0);
13637   if (r < 0)
13638     goto out;
13639
13640   if (acl_type == POSIX_ACL) {
13641     if (in->xattrs.count(ACL_EA_ACCESS)) {
13642       const bufferptr& access_acl = in->xattrs[ACL_EA_ACCESS];
13643       bufferptr acl(access_acl.c_str(), access_acl.length());
13644       r = posix_acl_access_chmod(acl, mode);
13645       if (r < 0)
13646         goto out;
13647       r = _do_setxattr(in, ACL_EA_ACCESS, acl.c_str(), acl.length(), 0, perms);
13648     } else {
13649       r = 0;
13650     }
13651   }
13652 out:
13653   ldout(cct, 10) << __func__ << " ino " << in->ino << " result=" << r << dendl;
13654   return r;
13655 }
13656
13657 int Client::_posix_acl_create(Inode *dir, mode_t *mode, bufferlist& xattrs_bl,
13658                               const UserPerm& perms)
13659 {
13660   if (acl_type == NO_ACL)
13661     return 0;
13662
13663   if (S_ISLNK(*mode))
13664     return 0;
13665
13666   int r = _getattr(dir, CEPH_STAT_CAP_XATTR, perms, dir->xattr_version == 0);
13667   if (r < 0)
13668     goto out;
13669
13670   if (acl_type == POSIX_ACL) {
13671     if (dir->xattrs.count(ACL_EA_DEFAULT)) {
13672       map<string, bufferptr> xattrs;
13673
13674       const bufferptr& default_acl = dir->xattrs[ACL_EA_DEFAULT];
13675       bufferptr acl(default_acl.c_str(), default_acl.length());
13676       r = posix_acl_inherit_mode(acl, mode);
13677       if (r < 0)
13678         goto out;
13679
13680       if (r > 0) {
13681         r = posix_acl_equiv_mode(acl.c_str(), acl.length(), mode);
13682         if (r < 0)
13683           goto out;
13684         if (r > 0)
13685           xattrs[ACL_EA_ACCESS] = acl;
13686       }
13687
13688       if (S_ISDIR(*mode))
13689         xattrs[ACL_EA_DEFAULT] = dir->xattrs[ACL_EA_DEFAULT];
13690
13691       r = xattrs.size();
13692       if (r > 0)
13693         ::encode(xattrs, xattrs_bl);
13694     } else {
13695       if (umask_cb)
13696         *mode &= ~umask_cb(callback_handle);
13697       r = 0;
13698     }
13699   }
13700 out:
13701   ldout(cct, 10) << __func__ << " dir ino " << dir->ino << " result=" << r << dendl;
13702   return r;
13703 }
13704
13705 void Client::set_filer_flags(int flags)
13706 {
13707   Mutex::Locker l(client_lock);
13708   assert(flags == 0 ||
13709          flags == CEPH_OSD_FLAG_LOCALIZE_READS);
13710   objecter->add_global_op_flags(flags);
13711 }
13712
13713 void Client::clear_filer_flags(int flags)
13714 {
13715   Mutex::Locker l(client_lock);
13716   assert(flags == CEPH_OSD_FLAG_LOCALIZE_READS);
13717   objecter->clear_global_op_flag(flags);
13718 }
13719
13720 /**
13721  * This is included in cap release messages, to cause
13722  * the MDS to wait until this OSD map epoch.  It is necessary
13723  * in corner cases where we cancel RADOS ops, so that
13724  * nobody else tries to do IO to the same objects in
13725  * the same epoch as the cancelled ops.
13726  */
13727 void Client::set_cap_epoch_barrier(epoch_t e)
13728 {
13729   ldout(cct, 5) << __func__ << " epoch = " << e << dendl;
13730   cap_epoch_barrier = e;
13731 }
13732
13733 const char** Client::get_tracked_conf_keys() const
13734 {
13735   static const char* keys[] = {
13736     "client_cache_size",
13737     "client_cache_mid",
13738     "client_acl_type",
13739     NULL
13740   };
13741   return keys;
13742 }
13743
13744 void Client::handle_conf_change(const struct md_config_t *conf,
13745                                 const std::set <std::string> &changed)
13746 {
13747   Mutex::Locker lock(client_lock);
13748
13749   if (changed.count("client_cache_mid")) {
13750     lru.lru_set_midpoint(cct->_conf->client_cache_mid);
13751   }
13752   if (changed.count("client_acl_type")) {
13753     acl_type = NO_ACL;
13754     if (cct->_conf->client_acl_type == "posix_acl")
13755       acl_type = POSIX_ACL;
13756   }
13757 }
13758
13759 void Client::init_groups(UserPerm *perms)
13760 {
13761   gid_t *sgids;
13762   int count = _getgrouplist(&sgids, perms->uid(), perms->gid());
13763   perms->init_gids(sgids, count);
13764 }
13765
13766 void intrusive_ptr_add_ref(Inode *in)
13767 {
13768   in->get();
13769 }
13770                 
13771 void intrusive_ptr_release(Inode *in)
13772 {
13773   in->client->put_inode(in);
13774 }
13775
13776 mds_rank_t Client::_get_random_up_mds() const
13777 {
13778   assert(client_lock.is_locked_by_me());
13779
13780   std::set<mds_rank_t> up;
13781   mdsmap->get_up_mds_set(up);
13782
13783   if (up.empty())
13784     return MDS_RANK_NONE;
13785   std::set<mds_rank_t>::const_iterator p = up.begin();
13786   for (int n = rand() % up.size(); n; n--)
13787     ++p;
13788   return *p;
13789 }
13790
13791
13792 StandaloneClient::StandaloneClient(Messenger *m, MonClient *mc)
13793     : Client(m, mc, new Objecter(m->cct, m, mc, NULL, 0, 0))
13794 {
13795   monclient->set_messenger(m);
13796   objecter->set_client_incarnation(0);
13797 }
13798
13799 StandaloneClient::~StandaloneClient()
13800 {
13801   delete objecter;
13802   objecter = nullptr;
13803 }
13804
13805 int StandaloneClient::init()
13806 {
13807   timer.init();
13808   objectcacher->start();
13809   objecter->init();
13810
13811   client_lock.Lock();
13812   assert(!initialized);
13813
13814   messenger->add_dispatcher_tail(objecter);
13815   messenger->add_dispatcher_tail(this);
13816
13817   monclient->set_want_keys(CEPH_ENTITY_TYPE_MDS | CEPH_ENTITY_TYPE_OSD);
13818   int r = monclient->init();
13819   if (r < 0) {
13820     // need to do cleanup because we're in an intermediate init state
13821     timer.shutdown();
13822     client_lock.Unlock();
13823     objecter->shutdown();
13824     objectcacher->stop();
13825     monclient->shutdown();
13826     return r;
13827   }
13828   objecter->start();
13829
13830   client_lock.Unlock();
13831   _finish_init();
13832
13833   return 0;
13834 }
13835
13836 void StandaloneClient::shutdown()
13837 {
13838   Client::shutdown();
13839   objecter->shutdown();
13840   monclient->shutdown();
13841 }
13842