Whamcloud - gitweb
Branch: HEAD
[fs/lustre-release.git] / lustre / obdfilter / filter.c
index 8b3fd41..fdccecc 100644 (file)
@@ -202,12 +202,9 @@ static int filter_export_stats_init(struct obd_device *obd,
                                     struct obd_export *exp,
                                     void *client_nid)
 {
-        struct filter_export_data *fed = &exp->exp_filter_data;
         int rc, newnid = 0;
         ENTRY;
 
-        init_brw_stats(&fed->fed_brw_stats);
-
         if (obd_uuid_equals(&exp->exp_client_uuid, &obd->obd_uuid))
                 /* Self-export gets no proc entry */
                 RETURN(0);
@@ -357,12 +354,13 @@ static int filter_client_add(struct obd_device *obd, struct obd_export *exp,
         RETURN(0);
 }
 
+struct lsd_client_data zero_lcd; /* globals are implicitly zeroed */
+
 static int filter_client_free(struct obd_export *exp)
 {
         struct filter_export_data *fed = &exp->exp_filter_data;
         struct filter_obd *filter = &exp->exp_obd->u.filter;
         struct obd_device *obd = exp->exp_obd;
-        struct lsd_client_data zero_lcd;
         struct lvfs_run_ctxt saved;
         int rc;
         loff_t off;
@@ -399,23 +397,26 @@ static int filter_client_free(struct obd_export *exp)
         }
 
         if (!(exp->exp_flags & OBD_OPT_FAILOVER)) {
-                memset(&zero_lcd, 0, sizeof zero_lcd);
+                /* Don't force sync on disconnect if aborting recovery,
+                 * or it does num_clients * num_osts.  b=17194 */
+                int need_sync = (!exp->exp_libclient || exp->exp_need_sync) &&
+                                 !(exp->exp_flags&OBD_OPT_ABORT_RECOV);
                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
                 rc = fsfilt_write_record(obd, filter->fo_rcvd_filp, &zero_lcd,
-                                         sizeof(zero_lcd), &off,
-                                         (!exp->exp_libclient ||
-                                          exp->exp_need_sync));
+                                         sizeof(zero_lcd), &off, 0);
+
+                /* Make sure the server's last_transno is up to date. Do this
+                 * after the client is freed so we know all the client's
+                 * transactions have been committed. */
                 if (rc == 0)
-                        /* update server's transno */
                         filter_update_server_data(obd, filter->fo_rcvd_filp,
-                                                  filter->fo_fsd,
-                                                  !exp->exp_libclient);
+                                                  filter->fo_fsd, need_sync);
                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
 
                 CDEBUG(rc == 0 ? D_INFO : D_ERROR,
-                       "zeroing out client %s at idx %u (%llu) in %s rc %d\n",
+                       "zero out client %s at idx %u/%llu in %s %ssync rc %d\n",
                        fed->fed_lcd->lcd_uuid, fed->fed_lr_idx, fed->fed_lr_off,
-                       LAST_RCVD, rc);
+                       LAST_RCVD, need_sync ? "" : "a", rc);
         }
 
         if (!test_and_clear_bit(fed->fed_lr_idx, filter->fo_last_rcvd_slots)) {
@@ -541,7 +542,7 @@ struct filter_mod_data *filter_fmd_get(struct obd_export *exp,
         struct filter_export_data *fed = &exp->exp_filter_data;
         struct filter_mod_data *found = NULL, *fmd_new = NULL;
 
-        OBD_SLAB_ALLOC(fmd_new, ll_fmd_cachep, CFS_ALLOC_IO, sizeof(*fmd_new));
+        OBD_SLAB_ALLOC_PTR_GFP(fmd_new, ll_fmd_cachep, CFS_ALLOC_IO);
 
         spin_lock(&fed->fed_lock);
         found = filter_fmd_find_nolock(&exp->exp_obd->u.filter,fed,objid,group);
@@ -2012,7 +2013,11 @@ int filter_common_setup(struct obd_device *obd, struct lustre_cfg* lcfg,
         if (rc != 0)
                 GOTO(err_ops, rc);
 
-        LASSERT(!lvfs_check_rdonly(lvfs_sbdev(mnt->mnt_sb)));
+        if (lvfs_check_rdonly(lvfs_sbdev(mnt->mnt_sb))) {
+                CERROR("%s: Underlying device is marked as read-only. "
+                       "Setup failed\n", obd->obd_name);
+                GOTO(err_ops, rc = -EROFS);
+        }
 
         /* failover is the default */
         obd->obd_replayable = 1;
@@ -2665,7 +2670,13 @@ static int filter_connect_internal(struct obd_export *exp,
         exp->exp_connect_flags = data->ocd_connect_flags;
         data->ocd_version = LUSTRE_VERSION_CODE;
 
+        /* Kindly make sure the SKIP_ORPHAN flag is from MDS. */
+        if (!ergo(data->ocd_connect_flags & OBD_CONNECT_SKIP_ORPHAN,
+                  data->ocd_connect_flags & OBD_CONNECT_MDS))
+                RETURN(-EPROTO);
+
         if (exp->exp_connect_flags & OBD_CONNECT_GRANT) {
+                struct filter_obd *filter = &exp->exp_obd->u.filter;
                 obd_size left, want;
 
                 spin_lock(&exp->exp_obd->obd_osfs_lock);
@@ -2679,6 +2690,8 @@ static int filter_connect_internal(struct obd_export *exp,
                        LPU64" left: "LPU64"\n", exp->exp_obd->obd_name,
                        exp->exp_client_uuid.uuid, exp,
                        data->ocd_grant, want, left);
+                
+                filter->fo_tot_granted_clients ++;
         }
 
         if (data->ocd_connect_flags & OBD_CONNECT_INDEX) {
@@ -2765,34 +2778,35 @@ static int filter_reconnect(const struct lu_env *env,
 
 /* nearly identical to mds_connect */
 static int filter_connect(const struct lu_env *env,
-                          struct lustre_handle *conn, struct obd_device *obd,
+                          struct obd_export **exp, struct obd_device *obd,
                           struct obd_uuid *cluuid,
                           struct obd_connect_data *data, void *localdata)
 {
         struct lvfs_run_ctxt saved;
-        struct obd_export *exp;
+        struct lustre_handle conn = { 0 };
+        struct obd_export *lexp;
         struct filter_export_data *fed;
         struct lsd_client_data *lcd = NULL;
         __u32 group;
         int rc;
         ENTRY;
 
-        if (conn == NULL || obd == NULL || cluuid == NULL)
+        if (exp == NULL || obd == NULL || cluuid == NULL)
                 RETURN(-EINVAL);
 
-        rc = class_connect(conn, obd, cluuid);
+        rc = class_connect(&conn, obd, cluuid);
         if (rc)
                 RETURN(rc);
-        exp = class_conn2export(conn);
-        LASSERT(exp != NULL);
+        lexp = class_conn2export(&conn);
+        LASSERT(lexp != NULL);
 
-        fed = &exp->exp_filter_data;
+        fed = &lexp->exp_filter_data;
 
-        rc = filter_connect_internal(exp, data);
+        rc = filter_connect_internal(lexp, data);
         if (rc)
                 GOTO(cleanup, rc);
 
-        filter_export_stats_init(obd, exp, localdata);
+        filter_export_stats_init(obd, lexp, localdata);
         if (obd->obd_replayable) {
                 OBD_ALLOC(lcd, sizeof(*lcd));
                 if (!lcd) {
@@ -2802,7 +2816,7 @@ static int filter_connect(const struct lu_env *env,
 
                 memcpy(lcd->lcd_uuid, cluuid, sizeof(lcd->lcd_uuid));
                 fed->fed_lcd = lcd;
-                rc = filter_client_add(obd, exp, -1);
+                rc = filter_client_add(obd, lexp, -1);
                 if (rc)
                         GOTO(cleanup, rc);
         }
@@ -2810,7 +2824,7 @@ static int filter_connect(const struct lu_env *env,
         group = data->ocd_group;
 
         CWARN("%s: Received MDS connection ("LPX64"); group %d\n",
-              obd->obd_name, exp->exp_handle.h_cookie, group);
+              obd->obd_name, lexp->exp_handle.h_cookie, group);
 
         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
         rc = filter_read_groups(obd, group, 1);
@@ -2828,9 +2842,10 @@ cleanup:
                         OBD_FREE_PTR(lcd);
                         fed->fed_lcd = NULL;
                 }
-                class_disconnect(exp);
+                class_disconnect(lexp);
+                *exp = NULL;
         } else {
-                class_export_put(exp);
+                *exp = lexp;
         }
 
         RETURN(rc);
@@ -2974,6 +2989,12 @@ static int filter_destroy_export(struct obd_export *exp)
         filter_grant_discard(exp);
         filter_fmd_cleanup(exp);
 
+        if (exp->exp_connect_flags & OBD_CONNECT_GRANT_SHRINK) {
+                struct filter_obd *filter = &exp->exp_obd->u.filter;
+                if (filter->fo_tot_granted_clients > 0)
+                        filter->fo_tot_granted_clients --;
+        }
+
         if (!(exp->exp_flags & OBD_OPT_FORCE))
                 filter_grant_sanity_check(exp->exp_obd, __FUNCTION__);
 
@@ -3051,6 +3072,8 @@ static int filter_disconnect(struct obd_export *exp)
         /* Flush any remaining cancel messages out to the target */
         filter_sync_llogs(obd, exp);
 
+        lquota_clearinfo(filter_quota_interface_ref, exp, exp->exp_obd);
+
         /* Disconnect early so that clients can't keep using export */
         rc = class_disconnect(exp);
         if (exp->exp_obd->obd_namespace != NULL)
@@ -3482,11 +3505,12 @@ static int filter_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp,
 
 /* caller must hold fo_create_locks[oa->o_gr] */
 static int filter_destroy_precreated(struct obd_export *exp, struct obdo *oa,
-                                      struct filter_obd *filter)
+                                     struct filter_obd *filter)
 {
         struct obdo doa; /* XXX obdo on stack */
         obd_id last, id;
-        int rc;
+        int rc = 0;
+        int skip_orphan;
         ENTRY;
 
         LASSERT(oa);
@@ -3508,8 +3532,11 @@ static int filter_destroy_precreated(struct obd_export *exp, struct obdo *oa,
 
         last = filter_last_id(filter, doa.o_gr);
 
-        CWARN("%s: deleting orphan objects from "LPU64" to "LPU64"\n",
-               exp->exp_obd->obd_name, oa->o_id + 1, last);
+        skip_orphan = !!(exp->exp_connect_flags & OBD_CONNECT_SKIP_ORPHAN);
+
+        CWARN("%s: deleting orphan objects from "LPU64" to "LPU64"%s\n",
+               exp->exp_obd->obd_name, oa->o_id + 1, last,
+               skip_orphan ? ", orphan objids won't be reused any more." : ".");
 
         for (id = last; id > oa->o_id; id--) {
                 doa.o_id = id;
@@ -3517,17 +3544,26 @@ static int filter_destroy_precreated(struct obd_export *exp, struct obdo *oa,
                 if (rc && rc != -ENOENT) /* this is pretty fatal... */
                         CEMERG("error destroying precreate objid "LPU64": %d\n",
                                id, rc);
-                filter_set_last_id(filter, id - 1, doa.o_gr);
+
                 /* update last_id on disk periodically so that if we restart
                  * we don't need to re-scan all of the just-deleted objects. */
-                if ((id & 511) == 0)
+                if ((id & 511) == 0 && !skip_orphan) {
+                        filter_set_last_id(filter, id - 1, doa.o_gr);
                         filter_update_last_objid(exp->exp_obd, doa.o_gr, 0);
+                }
         }
 
         CDEBUG(D_HA, "%s: after destroy: set last_objids["LPU64"] = "LPU64"\n",
                exp->exp_obd->obd_name, doa.o_gr, oa->o_id);
 
-        rc = filter_update_last_objid(exp->exp_obd, doa.o_gr, 1);
+        if (!skip_orphan) {
+                filter_set_last_id(filter, id, doa.o_gr);
+                rc = filter_update_last_objid(exp->exp_obd, doa.o_gr, 1);
+        } else {
+                /* don't reuse orphan object, return last used objid */
+                oa->o_id = last;
+                rc = 0;
+        }
         clear_bit(doa.o_gr, &filter->fo_destroys_in_progress);
 
         RETURN(rc);
@@ -3546,6 +3582,8 @@ static int filter_handle_precreate(struct obd_export *exp, struct obdo *oa,
 
         /* delete orphans request */
         if ((oa->o_valid & OBD_MD_FLFLAGS) && (oa->o_flags & OBD_FL_DELORPHAN)){
+                obd_id last = filter_last_id(filter, group);
+
                 if (oti->oti_conn_cnt < exp->exp_conn_cnt) {
                         CERROR("%s: dropping old orphan cleanup request\n",
                                obd->obd_name);
@@ -3560,14 +3598,14 @@ static int filter_handle_precreate(struct obd_export *exp, struct obdo *oa,
                         up(&filter->fo_create_locks[group]);
                         RETURN(0);
                 }
-                diff = oa->o_id - filter_last_id(filter, group);
+                diff = oa->o_id - last;
                 CDEBUG(D_HA, "filter_last_id() = "LPU64" -> diff = %d\n",
-                       filter_last_id(filter, group), diff);
+                       last, diff);
 
                 if (-diff > OST_MAX_PRECREATE) {
                         CERROR("%s: ignoring bogus orphan destroy request: "
                                "obdid "LPU64" last_id "LPU64"\n", obd->obd_name,
-                               oa->o_id, filter_last_id(filter, group));
+                               oa->o_id, last);
                         /* FIXME: should reset precreate_next_id on MDS */
                         GOTO(out, rc = -EINVAL);
                 }
@@ -4252,14 +4290,10 @@ static int filter_get_info(struct obd_export *exp, __u32 keylen,
                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
                 rc = fsfilt_iocontrol(obd, dentry->d_inode, NULL,
                                       EXT3_IOC_FIEMAP, (long)fiemap);
-                if (rc) {
-                        f_dput(dentry);
-                        RETURN(rc);
-                }
                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
 
                 f_dput(dentry);
-                RETURN(0);
+                RETURN(rc);
         }
 
         CDEBUG(D_IOCTL, "invalid key\n");
@@ -4319,6 +4353,15 @@ static int filter_set_info_async(struct obd_export *exp, __u32 keylen,
                 RETURN(0);
         }
 
+        if (KEY_IS(KEY_GRANT_SHRINK)) {
+                struct ost_body *body = (struct ost_body *)val;
+                /* handle shrink grant */
+                spin_lock(&exp->exp_obd->obd_osfs_lock);
+                filter_grant_incoming(exp, &body->oa);
+                spin_unlock(&exp->exp_obd->obd_osfs_lock);
+                RETURN(rc);
+        }
+
         if (!KEY_IS(KEY_MDS_CONN))
                 RETURN(-EINVAL);
 
@@ -4327,9 +4370,11 @@ static int filter_set_info_async(struct obd_export *exp, __u32 keylen,
         obd->u.filter.fo_mdc_conn.cookie = exp->exp_handle.h_cookie;
 
         /* setup llog imports */
-        LASSERT(val != NULL);
+        if (val != NULL)
+                group = (int)(*(__u32 *)val);
+        else
+                group = 0; /* default value */
 
-        group = (int)(*(__u32 *)val);
         LASSERT_MDS_GROUP(group);
         rc = filter_setup_llog_group(exp, obd, group);
         if (rc)
@@ -4453,8 +4498,8 @@ static int filter_process_config(struct obd_device *obd, obd_count len,
 
                 rc = class_process_proc_param(PARAM_OST, lvars.obd_vars,
                                               lcfg, obd);
-               if (rc > 0)
-                       rc = 0;
+                if (rc > 0)
+                        rc = 0;
                 break;
         }