Commit 6b805185 authored by Sage Weil's avatar Sage Weil

ceph: allocate and parse mount args before client instance

This simplifies much of the error handling during mount.  It also means
that we have the mount args before client creation, and we can initialize
based on those options.
Signed-off-by: default avatarSage Weil <sage@newdream.net>
parent e53c2fe0
......@@ -600,8 +600,8 @@ static int ceph_writepages_start(struct address_space *mapping,
pr_warning("writepage_start %p on forced umount\n", inode);
return -EIO; /* we're in a forced umount, don't write! */
}
if (client->mount_args.wsize && client->mount_args.wsize < wsize)
wsize = client->mount_args.wsize;
if (client->mount_args->wsize && client->mount_args->wsize < wsize)
wsize = client->mount_args->wsize;
if (wsize < PAGE_CACHE_SIZE)
wsize = PAGE_CACHE_SIZE;
max_pages_ever = wsize >> PAGE_CACHE_SHIFT;
......
......@@ -270,7 +270,7 @@ static void put_cap(struct ceph_cap *cap,
* lots of free/alloc churn.
*/
if (caps_avail_count >= caps_reserve_count +
ceph_client(cap->ci->vfs_inode.i_sb)->mount_args.max_readdir) {
ceph_client(cap->ci->vfs_inode.i_sb)->mount_args->max_readdir) {
caps_total_count--;
kmem_cache_free(ceph_cap_cachep, cap);
} else {
......@@ -388,7 +388,7 @@ static void __insert_cap_node(struct ceph_inode_info *ci,
static void __cap_set_timeouts(struct ceph_mds_client *mdsc,
struct ceph_inode_info *ci)
{
struct ceph_mount_args *ma = &mdsc->client->mount_args;
struct ceph_mount_args *ma = mdsc->client->mount_args;
ci->i_hold_caps_min = round_jiffies(jiffies +
ma->caps_wanted_delay_min * HZ);
......
......@@ -225,7 +225,7 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
int err;
u32 ftype;
struct ceph_mds_reply_info_parsed *rinfo;
const int max_entries = client->mount_args.max_readdir;
const int max_entries = client->mount_args->max_readdir;
dout("readdir %p filp %p frag %u off %u\n", inode, filp, frag, off);
if (fi->at_end)
......@@ -479,7 +479,8 @@ struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
/* .snap dir? */
if (err == -ENOENT &&
ceph_vino(parent).ino != CEPH_INO_ROOT && /* no .snap in root dir */
strcmp(dentry->d_name.name, client->mount_args.snapdir_name) == 0) {
strcmp(dentry->d_name.name,
client->mount_args->snapdir_name) == 0) {
struct inode *inode = ceph_get_snapdir(parent);
dout("ENOENT on snapdir %p '%.*s', linking to snapdir %p\n",
dentry, dentry->d_name.len, dentry->d_name.name, inode);
......@@ -550,7 +551,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
spin_lock(&dir->i_lock);
dout(" dir %p flags are %d\n", dir, ci->i_ceph_flags);
if (strncmp(dentry->d_name.name,
client->mount_args.snapdir_name,
client->mount_args->snapdir_name,
dentry->d_name.len) &&
(ci->i_ceph_flags & CEPH_I_COMPLETE) &&
(__ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1))) {
......
......@@ -943,7 +943,7 @@ static int add_cap_releases(struct ceph_mds_client *mdsc,
int err = -ENOMEM;
if (extra < 0)
extra = mdsc->client->mount_args.cap_release_safety;
extra = mdsc->client->mount_args->cap_release_safety;
spin_lock(&session->s_cap_lock);
......@@ -2601,7 +2601,7 @@ static void wait_requests(struct ceph_mds_client *mdsc)
mutex_unlock(&mdsc->mutex);
dout("wait_requests waiting for requests\n");
wait_for_completion_timeout(&mdsc->safe_umount_waiters,
client->mount_args.mount_timeout * HZ);
client->mount_args->mount_timeout * HZ);
mutex_lock(&mdsc->mutex);
/* tear down remaining requests */
......@@ -2693,7 +2693,7 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
int i;
int n;
struct ceph_client *client = mdsc->client;
unsigned long started, timeout = client->mount_args.mount_timeout * HZ;
unsigned long started, timeout = client->mount_args->mount_timeout * HZ;
dout("close_sessions\n");
......
......@@ -527,6 +527,40 @@ static void delayed_work(struct work_struct *work)
mutex_unlock(&monc->mutex);
}
/*
* On startup, we build a temporary monmap populated with the IPs
* provided by mount(2).
*/
static int build_initial_monmap(struct ceph_mon_client *monc)
{
struct ceph_mount_args *args = monc->client->mount_args;
struct ceph_entity_addr *mon_addr = args->mon_addr;
int num_mon = args->num_mon;
int i;
/* build initial monmap */
monc->monmap = kzalloc(sizeof(*monc->monmap) +
num_mon*sizeof(monc->monmap->mon_inst[0]),
GFP_KERNEL);
if (!monc->monmap)
return -ENOMEM;
for (i = 0; i < num_mon; i++) {
monc->monmap->mon_inst[i].addr = mon_addr[i];
monc->monmap->mon_inst[i].addr.erank = 0;
monc->monmap->mon_inst[i].addr.nonce = 0;
monc->monmap->mon_inst[i].name.type =
CEPH_ENTITY_TYPE_MON;
monc->monmap->mon_inst[i].name.num = cpu_to_le64(i);
}
monc->monmap->num_mon = num_mon;
/* release addr memory */
kfree(args->mon_addr);
args->mon_addr = NULL;
args->num_mon = 0;
return 0;
}
int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl)
{
int err = 0;
......@@ -537,6 +571,10 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl)
monc->monmap = NULL;
mutex_init(&monc->mutex);
err = build_initial_monmap(monc);
if (err)
goto out;
monc->con = NULL;
/* msg pools */
......
......@@ -444,7 +444,7 @@ static void register_request(struct ceph_osd_client *osdc,
osdc->num_requests++;
req->r_timeout_stamp =
jiffies + osdc->client->mount_args.osd_timeout*HZ;
jiffies + osdc->client->mount_args->osd_timeout*HZ;
if (osdc->num_requests == 1) {
osdc->timeout_tid = req->r_tid;
......@@ -609,7 +609,7 @@ static int __send_request(struct ceph_osd_client *osdc,
reqhead->flags |= cpu_to_le32(req->r_flags); /* e.g., RETRY */
reqhead->reassert_version = req->r_reassert_version;
req->r_timeout_stamp = jiffies+osdc->client->mount_args.osd_timeout*HZ;
req->r_timeout_stamp = jiffies+osdc->client->mount_args->osd_timeout*HZ;
ceph_msg_get(req->r_request); /* send consumes a ref */
ceph_con_send(&req->r_osd->o_con, req->r_request);
......@@ -632,7 +632,7 @@ static void handle_timeout(struct work_struct *work)
container_of(work, struct ceph_osd_client, timeout_work.work);
struct ceph_osd_request *req;
struct ceph_osd *osd;
unsigned long timeout = osdc->client->mount_args.osd_timeout * HZ;
unsigned long timeout = osdc->client->mount_args->osd_timeout * HZ;
unsigned long next_timeout = timeout + jiffies;
struct rb_node *p;
......
......@@ -110,7 +110,7 @@ static int ceph_syncfs(struct super_block *sb, int wait)
static int ceph_show_options(struct seq_file *m, struct vfsmount *mnt)
{
struct ceph_client *client = ceph_sb_to_client(mnt->mnt_sb);
struct ceph_mount_args *args = &client->mount_args;
struct ceph_mount_args *args = client->mount_args;
if (args->flags & CEPH_OPT_FSID)
seq_printf(m, ",fsidmajor=%llu,fsidminor%llu",
......@@ -307,24 +307,24 @@ static match_table_t arg_tokens = {
};
static int parse_mount_args(struct ceph_client *client,
int flags, char *options, const char *dev_name,
static struct ceph_mount_args *parse_mount_args(int flags, char *options,
const char *dev_name,
const char **path)
{
struct ceph_mount_args *args = &client->mount_args;
struct ceph_mount_args *args;
const char *c;
int err;
int err = -ENOMEM;
substring_t argstr[MAX_OPT_ARGS];
int num_mon;
struct ceph_entity_addr *mon_addr;
int i;
dout("parse_mount_args dev_name '%s'\n", dev_name);
memset(args, 0, sizeof(*args));
args = kzalloc(sizeof(*args), GFP_KERNEL);
if (!args)
return ERR_PTR(-ENOMEM);
args->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*args->mon_addr),
GFP_KERNEL);
if (!args->mon_addr)
goto out;
mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*mon_addr), GFP_KERNEL);
if (!mon_addr)
return -ENOMEM;
dout("parse_mount_args %p, dev_name '%s'\n", args, dev_name);
/* start with defaults */
args->sb_flags = flags;
......@@ -350,29 +350,11 @@ static int parse_mount_args(struct ceph_client *client,
}
/* get mon ip(s) */
err = ceph_parse_ips(dev_name, *path, mon_addr,
CEPH_MAX_MON, &num_mon);
err = ceph_parse_ips(dev_name, *path, args->mon_addr,
CEPH_MAX_MON, &args->num_mon);
if (err < 0)
goto out;
/* build initial monmap */
err = -ENOMEM;
client->monc.monmap = kzalloc(sizeof(*client->monc.monmap) +
num_mon*sizeof(client->monc.monmap->mon_inst[0]),
GFP_KERNEL);
if (!client->monc.monmap)
goto out;
for (i = 0; i < num_mon; i++) {
client->monc.monmap->mon_inst[i].addr = mon_addr[i];
client->monc.monmap->mon_inst[i].addr.erank = 0;
client->monc.monmap->mon_inst[i].addr.nonce = 0;
client->monc.monmap->mon_inst[i].name.type =
CEPH_ENTITY_TYPE_MON;
client->monc.monmap->mon_inst[i].name.num = cpu_to_le64(i);
}
client->monc.monmap->num_mon = num_mon;
memset(&args->my_addr.in_addr, 0, sizeof(args->my_addr.in_addr));
/* path on server */
*path += 2;
dout("server path '%s'\n", *path);
......@@ -415,7 +397,7 @@ static int parse_mount_args(struct ceph_client *client,
&args->my_addr,
1, NULL);
if (err < 0)
return err;
goto out;
args->flags |= CEPH_OPT_MYIP;
break;
......@@ -481,25 +463,28 @@ static int parse_mount_args(struct ceph_client *client,
BUG_ON(token);
}
}
err = 0;
return args;
out:
kfree(mon_addr);
return err;
kfree(args->mon_addr);
kfree(args);
return ERR_PTR(err);
}
static void release_mount_args(struct ceph_mount_args *args)
static void destroy_mount_args(struct ceph_mount_args *args)
{
dout("destroy_mount_args %p\n", args);
kfree(args->snapdir_name);
args->snapdir_name = NULL;
kfree(args->secret);
args->secret = NULL;
kfree(args);
}
/*
* create a fresh client instance
*/
static struct ceph_client *ceph_create_client(void)
static struct ceph_client *ceph_create_client(struct ceph_mount_args *args)
{
struct ceph_client *client;
int err = -ENOMEM;
......@@ -515,6 +500,7 @@ static struct ceph_client *ceph_create_client(void)
client->sb = NULL;
client->mount_state = CEPH_MOUNT_MOUNTING;
client->whoami = -1;
client->mount_args = args;
client->msgr = NULL;
......@@ -577,7 +563,7 @@ static void ceph_destroy_client(struct ceph_client *client)
if (client->wb_pagevec_pool)
mempool_destroy(client->wb_pagevec_pool);
release_mount_args(&client->mount_args);
destroy_mount_args(client->mount_args);
kfree(client);
dout("destroy_client %p done\n", client);
......@@ -613,7 +599,7 @@ static struct dentry *open_root_dentry(struct ceph_client *client,
req->r_ino1.ino = CEPH_INO_ROOT;
req->r_ino1.snap = CEPH_NOSNAP;
req->r_started = started;
req->r_timeout = client->mount_args.mount_timeout * HZ;
req->r_timeout = client->mount_args->mount_timeout * HZ;
req->r_args.getattr.mask = cpu_to_le32(CEPH_STAT_CAP_INODE);
req->r_num_caps = 2;
err = ceph_mdsc_do_request(mdsc, NULL, req);
......@@ -641,7 +627,7 @@ static int ceph_mount(struct ceph_client *client, struct vfsmount *mnt,
{
struct ceph_entity_addr *myaddr = NULL;
int err;
unsigned long timeout = client->mount_args.mount_timeout * HZ;
unsigned long timeout = client->mount_args->mount_timeout * HZ;
unsigned long started = jiffies; /* note the start time */
struct dentry *root;
......@@ -651,7 +637,7 @@ static int ceph_mount(struct ceph_client *client, struct vfsmount *mnt,
/* initialize the messenger */
if (client->msgr == NULL) {
if (ceph_test_opt(client, MYIP))
myaddr = &client->mount_args.my_addr;
myaddr = &client->mount_args->my_addr;
client->msgr = ceph_messenger_create(myaddr);
if (IS_ERR(client->msgr)) {
err = PTR_ERR(client->msgr);
......@@ -727,7 +713,7 @@ static int ceph_set_super(struct super_block *s, void *data)
dout("set_super %p data %p\n", s, data);
s->s_flags = client->mount_args.sb_flags;
s->s_flags = client->mount_args->sb_flags;
s->s_maxbytes = 1ULL << 40; /* temp value until we get mdsmap */
s->s_fs_info = client;
......@@ -756,7 +742,7 @@ static int ceph_set_super(struct super_block *s, void *data)
static int ceph_compare_super(struct super_block *sb, void *data)
{
struct ceph_client *new = data;
struct ceph_mount_args *args = &new->mount_args;
struct ceph_mount_args *args = new->mount_args;
struct ceph_client *other = ceph_sb_to_client(sb);
int i;
......@@ -778,7 +764,7 @@ static int ceph_compare_super(struct super_block *sb, void *data)
}
dout("mon ip matches existing sb %p\n", sb);
}
if (args->sb_flags != other->mount_args.sb_flags) {
if (args->sb_flags != other->mount_args->sb_flags) {
dout("flags differ\n");
return 0;
}
......@@ -798,9 +784,9 @@ static int ceph_init_bdi(struct super_block *sb, struct ceph_client *client)
sb->s_bdi = &client->backing_dev_info;
/* set ra_pages based on rsize mount option? */
if (client->mount_args.rsize >= PAGE_CACHE_SIZE)
if (client->mount_args->rsize >= PAGE_CACHE_SIZE)
client->backing_dev_info.ra_pages =
(client->mount_args.rsize + PAGE_CACHE_SIZE - 1)
(client->mount_args->rsize + PAGE_CACHE_SIZE - 1)
>> PAGE_SHIFT;
err = bdi_register_dev(&client->backing_dev_info, sb->s_dev);
......@@ -816,19 +802,23 @@ static int ceph_get_sb(struct file_system_type *fs_type,
int err;
int (*compare_super)(struct super_block *, void *) = ceph_compare_super;
const char *path = 0;
struct ceph_mount_args *args;
dout("ceph_get_sb\n");
args = parse_mount_args(flags, data, dev_name, &path);
if (IS_ERR(args)) {
err = PTR_ERR(args);
goto out_final;
}
/* create client (which we may/may not use) */
client = ceph_create_client();
if (IS_ERR(client))
return PTR_ERR(client);
err = parse_mount_args(client, flags, data, dev_name, &path);
if (err < 0)
goto out;
client = ceph_create_client(args);
if (IS_ERR(client)) {
err = PTR_ERR(client);
goto out_final;
}
if (client->mount_args.flags & CEPH_OPT_NOSHARE)
if (client->mount_args->flags & CEPH_OPT_NOSHARE)
compare_super = NULL;
sb = sget(fs_type, compare_super, ceph_set_super, client);
if (IS_ERR(sb)) {
......@@ -846,7 +836,7 @@ static int ceph_get_sb(struct file_system_type *fs_type,
/* set up mempools */
err = -ENOMEM;
client->wb_pagevec_pool = mempool_create_kmalloc_pool(10,
client->mount_args.wsize >> PAGE_CACHE_SHIFT);
client->mount_args->wsize >> PAGE_CACHE_SHIFT);
if (!client->wb_pagevec_pool)
goto out_splat;
......
......@@ -42,13 +42,15 @@
#define CEPH_OPT_DEFAULT (CEPH_OPT_RBYTES)
#define ceph_set_opt(client, opt) \
(client)->mount_args.flags |= CEPH_OPT_##opt;
(client)->mount_args->flags |= CEPH_OPT_##opt;
#define ceph_test_opt(client, opt) \
(!!((client)->mount_args.flags & CEPH_OPT_##opt))
(!!((client)->mount_args->flags & CEPH_OPT_##opt))
struct ceph_mount_args {
int sb_flags;
int num_mon;
struct ceph_entity_addr *mon_addr;
int flags;
int mount_timeout;
int caps_wanted_delay_min, caps_wanted_delay_max;
......@@ -115,7 +117,7 @@ struct ceph_client {
struct dentry *debugfs_dir, *debugfs_dentry_lru, *debugfs_caps;
struct mutex mount_mutex; /* serialize mount attempts */
struct ceph_mount_args mount_args;
struct ceph_mount_args *mount_args;
struct ceph_fsid fsid;
struct super_block *sb;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment