static void __cap_delay_requeue(struct ceph_mds_client *mdsc,
struct ceph_inode_info *ci)
{
- struct ceph_client *client = mdsc->client;
- ci->i_hold_caps_until = round_jiffies(jiffies + client->mount_args.caps_delay * HZ);
+ struct ceph_mount_args *ma = &mdsc->client->mount_args;
+
+ ci->i_hold_caps_min = round_jiffies(jiffies +
+ ma->caps_wanted_delay_min * HZ);
+ ci->i_hold_caps_max = round_jiffies(jiffies +
+ ma->caps_wanted_delay_max * HZ);
dout(10, "__cap_delay_requeue %p at %lu\n", &ci->vfs_inode,
- ci->i_hold_caps_until);
+ ci->i_hold_caps_max);
if (!mdsc->stopping) {
spin_lock(&mdsc->cap_delay_lock);
if (!list_empty(&ci->i_cap_delay_list))
* have cached pages, but don't want them, then try to invalidate.
* If we fail, it's because pages are locked.... try again later.
*/
- if ((!time_before(jiffies, ci->i_hold_caps_until) || mdsc->stopping) &&
+ if ((!time_before(jiffies, ci->i_hold_caps_max) || mdsc->stopping) &&
ci->i_wrbuffer_ref == 0 && /* no dirty pages... */
ci->i_rdcache_gen && /* may have cached pages */
file_wanted == 0 && /* no open files */
/* delay cap release for a bit? */
if (!is_delayed &&
- time_before(jiffies, ci->i_hold_caps_until)) {
+ time_before(jiffies, ci->i_hold_caps_max)) {
dout(30, "delaying cap release\n");
continue;
}
if (ci->i_dirty_caps && ci->i_auth_cap) {
struct ceph_cap *cap = ci->i_auth_cap;
int used = __ceph_caps_used(ci);
+ int want = __ceph_caps_wanted(ci);
if (!session) {
spin_unlock(&inode->i_lock);
ci->i_flushing_caps |= flushing;
ci->i_dirty_caps = 0;
+ /* don't release wanted unless we've waited a bit. */
+ if (time_before(jiffies, ci->i_hold_caps_min))
+ want = cap->mds_wanted;
+ else if (!want)
+ __cap_delay_cancel(mdsc, ci);
+
/* __send_cap drops i_lock */
- __send_cap(mdsc, cap, CEPH_CAP_OP_UPDATE, used, cap->mds_wanted,
+ __send_cap(mdsc, cap, CEPH_CAP_OP_UPDATE, used, want,
cap->issued | cap->implemented, flushing);
goto out_unlocked;
}
ci = list_first_entry(&mdsc->cap_delay_list,
struct ceph_inode_info,
i_cap_delay_list);
- if (time_before(jiffies, ci->i_hold_caps_until))
+ if (time_before(jiffies, ci->i_hold_caps_max))
break;
list_del_init(&ci->i_cap_delay_list);
spin_unlock(&mdsc->cap_delay_lock);
INIT_LIST_HEAD(&ci->i_dirty_item);
INIT_LIST_HEAD(&ci->i_sync_item);
init_waitqueue_head(&ci->i_cap_wq);
- ci->i_hold_caps_until = 0;
+ ci->i_hold_caps_min = 0;
+ ci->i_hold_caps_max = 0;
INIT_LIST_HEAD(&ci->i_cap_delay_list);
ci->i_cap_exporting_mds = 0;
ci->i_cap_exporting_mseq = 0;
Opt_rsize,
Opt_osdtimeout,
Opt_mount_timeout,
- Opt_caps_delay,
+ Opt_caps_wanted_delay_min,
+ Opt_caps_wanted_delay_max,
/* int args above */
Opt_ip,
Opt_noshare,
{Opt_rsize, "rsize=%d"},
{Opt_osdtimeout, "osdtimeout=%d"},
{Opt_mount_timeout, "mount_timeout=%d"},
- {Opt_caps_delay, "caps_delay=%d"},
+ {Opt_caps_wanted_delay_min, "caps_wanted_delay_min=%d"},
+ {Opt_caps_wanted_delay_max, "caps_wanted_delay_max=%d"},
/* int args above */
{Opt_ip, "ip=%s"},
{Opt_debug_console, "debug_console"},
args->flags = CEPH_MOUNT_DEFAULT;
args->osd_timeout = 5; /* seconds */
args->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT; /* seconds */
- args->caps_delay = CEPH_CAP_DELAY_DEFAULT; /* seconds */
+ args->caps_wanted_delay_min = CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT;
+ args->caps_wanted_delay_max = CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT;
args->snapdir_name = ".snap";
args->cap_release_safety = CAPS_PER_RELEASE * 4;
case Opt_mount_timeout:
args->mount_timeout = intval;
break;
- case Opt_caps_delay:
- args->caps_delay = intval;
+ case Opt_caps_wanted_delay_min:
+ args->caps_wanted_delay_min = intval;
+ break;
+ case Opt_caps_wanted_delay_max:
+ args->caps_wanted_delay_max = intval;
break;
case Opt_noshare:
#define CEPH_BLOCK (1 << CEPH_BLOCK_SHIFT)
#define CEPH_MOUNT_TIMEOUT_DEFAULT 60
-#define CEPH_CAP_DELAY_DEFAULT 60 /* cap release delay */
+
+/*
+ * Delay telling the MDS we no longer wnat caps, in case we reopen
+ * the file. Delay a minimum amount of time, even if we send a cap
+ * message for some other reason. Otherwise, take the oppotunity to
+ * update the mds to avoid sending another message later.
+ */
+#define CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT 5 /* cap release delay */
+#define CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT 60 /* cap release delay */
/*
* subtract jiffies
int sb_flags;
int flags;
int mount_timeout;
- int caps_delay;
+ int caps_wanted_delay_min, caps_wanted_delay_max;
ceph_fsid_t fsid;
struct ceph_entity_addr my_addr;
int num_mon;
unsigned i_dirty_caps, i_flushing_caps; /* mask of dirtied fields */
struct list_head i_dirty_item, i_sync_item;
wait_queue_head_t i_cap_wq; /* threads waiting on a capability */
- unsigned long i_hold_caps_until; /* jiffies */
+ unsigned long i_hold_caps_min; /* jiffies */
+ unsigned long i_hold_caps_max; /* jiffies */
struct list_head i_cap_delay_list; /* for delayed cap release to mds */
int i_cap_exporting_mds; /* to handle cap migration between */
unsigned i_cap_exporting_mseq; /* mds's. */