Whamcloud - gitweb
b=9729
[fs/lustre-release.git] / lustre / mds / mds_audit_path.c
index 54b5c9d..637aeea 100644 (file)
@@ -54,7 +54,8 @@
 
 struct scan_dir_data {
         int               rc;
-        struct lustre_id *id;
+        __u32            i_num;
+        __u8             cross_ref;
         char             *name;
 };
 
@@ -72,7 +73,11 @@ static int filldir(void *__buf, const char *name, int namlen,
 
         LASSERT(sd != NULL);
 
-        if (ino == id_ino(sd->id)) {
+        /* skip non-cross_ref entries if we need cross-ref */
+        if (sd->cross_ref && !(d_type & 128))
+                RETURN(0);
+
+        if (ino == sd->i_num) {
                 strncpy(sd->name, name, namlen);
                 sd->rc = 0;
                 RETURN(-EINTR); /* break the readdir loop */
@@ -80,8 +85,8 @@ static int filldir(void *__buf, const char *name, int namlen,
         RETURN(0);
 }
 
-int 
-scan_name_in_parent(struct lustre_id *pid, struct lustre_id *id, char *name)
+static int scan_name_in_parent(struct lustre_id *pid, struct lustre_id *id,
+                               char *name, int cr)
 {
         struct file * file;
         char *pname;
@@ -103,13 +108,15 @@ scan_name_in_parent(struct lustre_id *pid, struct lustre_id *id, char *name)
                 GOTO(out, rc = PTR_ERR(file));
         }
         
-        sd.id = id;
+        sd.i_num = id_ino(id);
         sd.name = name;
+        sd.cross_ref = cr;
         sd.rc = -ENOENT;
-        vfs_readdir(file, filldir, &sd);
+        rc = vfs_readdir(file, filldir, &sd);
+        if (!rc) 
+                rc = sd.rc;
 
         filp_close(file, 0);
-        rc = sd.rc;
 
 out:
         OBD_FREE(pname, len);
@@ -141,8 +148,8 @@ id2pid(struct obd_device *obd, struct lustre_id *id, struct lustre_id *pid,
         }
         inode = dentry->d_inode;
 
-        if (S_ISDIR(id_type(id))) {
-                LASSERT(S_ISDIR(inode->i_mode));
+        if (S_ISDIR(inode->i_mode)) {
+                //LASSERT(S_ISDIR(id_type(id)));
                 rc = mds_md_get_attr(obd, inode, &mea, &mea_size);
                 if (rc)
                         GOTO(out, rc);
@@ -156,10 +163,11 @@ id2pid(struct obd_device *obd, struct lustre_id *id, struct lustre_id *pid,
                 } else {
                         *type = PP_SPLIT_SLAVE;
                         *pid = mea->mea_ids[mea->mea_master];
+                        LASSERT(id_fid(pid));
                 }
                                 
         } else {
-                LASSERT(!S_ISDIR(inode->i_mode));
+                //LASSERT(!S_ISDIR(id_type(id)));
                 *type = PP_FILE;
 read_pid:
                 rc = mds_read_inode_pid(obd, inode, pid);
@@ -185,29 +193,26 @@ out:
 static int local_parse_id(struct obd_device *obd, struct parseid_pkg *pkg)
 {
         struct lvfs_run_ctxt saved;
-        int rc = 0;
+        int rc = 0, cross_ref = 0;
         ENTRY;
 
         pkg->pp_rc = 0;
         pkg->pp_type = 0;
         memset(pkg->pp_name, 0, sizeof(pkg->pp_name));
 
-        LASSERT(obd->u.mds.mds_num == id_group(&pkg->pp_id1));
-
         /* pp_id2 is present, which indicating we want to scan parent 
          * dir(pp_id2) to find the cross-ref entry(pp_id1) */
         if (id_fid(&pkg->pp_id2)) {
-                LASSERT(S_ISDIR(id_type(&pkg->pp_id1)));
-                LASSERT(S_ISDIR(id_type(&pkg->pp_id2)));
-
+                LASSERT(obd->u.mds.mds_num == id_group(&pkg->pp_id2));
                 pkg->pp_type = PP_DIR;
-                goto scan;
+                cross_ref = 1;                
+        } else {
+                LASSERT(obd->u.mds.mds_num == id_group(&pkg->pp_id1));
+                rc = id2pid(obd, &pkg->pp_id1, &pkg->pp_id2, &pkg->pp_type);
+                if (rc)
+                        GOTO(out, rc);
         }
 
-        rc = id2pid(obd, &pkg->pp_id1, &pkg->pp_id2, &pkg->pp_type);
-        if (rc)
-                GOTO(out, rc);
-scan:
         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
         
         switch (pkg->pp_type) {
@@ -215,7 +220,7 @@ scan:
         case PP_DIR:
         case PP_SPLIT_MASTER:
                 rc = scan_name_in_parent(&pkg->pp_id2, &pkg->pp_id1,
-                                         pkg->pp_name);
+                                         pkg->pp_name, cross_ref);
                 if (rc) 
                         CERROR("scan "LPU64" in parent failed. rc=%d\n",
                                id_ino(&pkg->pp_id1), rc);
@@ -272,6 +277,10 @@ static int parse_id(struct obd_device *obd, struct parseid_pkg *pkg)
         int mds_num = id_group(&pkg->pp_id1);
         ENTRY;
         
+        //for cross-ref dir we should send request to parent's MDS
+        if (pkg->pp_type == PP_CROSS_DIR)
+                mds_num = id_group(&pkg->pp_id2);
+        
         LASSERT(mds_num >= 0);
 
         if (mds_num == obd->u.mds.mds_num) {
@@ -281,8 +290,17 @@ static int parse_id(struct obd_device *obd, struct parseid_pkg *pkg)
                 struct lmv_obd *lmv = &obd->u.mds.mds_md_obd->u.lmv;
                 struct parseid_pkg *body;
                 int size = sizeof(*body);
-                struct obd_export *exp = lmv->tgts[mds_num].ltd_exp;
+                struct obd_export *exp;
                 
+                /* make sure connection established */
+                rc = obd_set_info(obd->u.mds.mds_md_exp, strlen("chkconnect"),
+                                  "chkconnect", 0, NULL);
+                if (rc)
+                        RETURN(rc);
+
+                exp = lmv->tgts[mds_num].ltd_exp;
+                LASSERTF(exp, "No export for MDS #%i\n", mds_num);
+
                 req = ptlrpc_prep_req(class_exp2cliimp(exp), 
                                       LUSTRE_MDS_VERSION, MDS_PARSE_ID, 1, 
                                       &size, NULL);
@@ -351,15 +369,14 @@ mds_id2name(struct obd_device *obd, struct lustre_id *id,
                         INIT_LIST_HEAD(&item->link);
                         list_add(&item->link, list);
                         memcpy(item->name, pkg->pp_name, sizeof(item->name));
-                        
+
                 case PP_SPLIT_SLAVE:
                         pkg->pp_id1 = pkg->pp_id2;
                         memset(&pkg->pp_id2, 0, sizeof(struct lustre_id));
-                        break;
                 case PP_CROSS_DIR:
                         break;
                 default:
-                        LBUG();
+                        CERROR("Wrong id = %i\n", pkg->pp_type);
                         break;
                 }
                 
@@ -382,25 +399,23 @@ scan_audit_log_cb(struct llog_handle *llh, struct llog_rec_hdr *rec, void *data)
                 CERROR("log is not plain\n");
                 RETURN(-EINVAL);
         }
-        if (rec->lrh_type != SMFS_AUDIT_NAME_REC &&
-            rec->lrh_type != LLOG_GEN_REC) {
+        
+        if (rec->lrh_type != SMFS_AUDIT_NAME_REC)
                 RETURN(0);
-        }
-
-        ad_rec = (struct audit_record *)((char *)rec + sizeof(*rec));
-
-        if (ad_rec->result || 
-            ad_rec->opcode != AUDIT_UNLINK ||
-            ad_rec->opcode != AUDIT_RENAME)
+        
+        ad_rec = (struct audit_record *)(rec + 1);
+        if (ad_rec->result ||
+            (ad_rec->opcode != AUDIT_UNLINK &&
+             ad_rec->opcode != AUDIT_RENAME))
                 RETURN(0);
 
-        cid_rec = (struct audit_id_record *)((char *)ad_rec + sizeof(*ad_rec));
+        cid_rec = (struct audit_id_record *)(ad_rec + 1);
         pid_rec = cid_rec + 1;
-        nm_rec = (struct audit_name_record *)
-                ((char *)pid_rec + sizeof(*pid_rec));
-        
+        nm_rec = (struct audit_name_record *)(pid_rec + 1);
+                
         if (cid_rec->au_num == id_ino(&pkg->pp_id1) &&
             cid_rec->au_gen == id_gen(&pkg->pp_id1)) {
+                LASSERT(pid_rec->au_fid);
                 /* get parent id */
                 id_ino(&pkg->pp_id2) = pid_rec->au_num;
                 id_gen(&pkg->pp_id2) = pid_rec->au_gen;
@@ -410,7 +425,6 @@ scan_audit_log_cb(struct llog_handle *llh, struct llog_rec_hdr *rec, void *data)
                 /* get name */
                 memcpy(pkg->pp_name, nm_rec->name, 
                        le32_to_cpu(nm_rec->name_len));
-
                 RETURN(LLOG_PROC_BREAK);
         }
         RETURN(0);
@@ -425,18 +439,23 @@ local_scan_audit_log(struct obd_device *obd, struct parseid_pkg *pkg)
         int rc = 0;
         ENTRY;
 
+        pkg->pp_rc = 0;
         if (ctxt)
                 llh = ctxt->loc_handle;
 
         if (llh == NULL)
-                RETURN(-ENOENT);
+                GOTO(out, rc = -ENOENT);
 
         rc = llog_cat_process(llh, (llog_cb_t)&scan_audit_log_cb, (void *)pkg);
         if (rc != LLOG_PROC_BREAK) {
                 CWARN("process catalog log failed: rc(%d)\n", rc);
-                RETURN(-ENOENT);
+                rc = -ENOENT;
+        } else {
+                rc = 0;
         }
-        RETURN(0);
+out:
+        pkg->pp_rc = rc;
+        RETURN(rc);
 }
 
 static int 
@@ -462,8 +481,17 @@ scan_audit_log(struct obd_device *obd, struct lustre_id *cur_id,
                 struct lmv_obd *lmv = &obd->u.mds.mds_md_obd->u.lmv;
                 struct parseid_pkg *body;
                 int size = sizeof(*body);
-                struct obd_export *exp = lmv->tgts[mds_num].ltd_exp;
+                struct obd_export *exp;
                 
+                /* make sure connection established */
+                rc = obd_set_info(obd->u.mds.mds_md_exp, strlen("chkconnect"),
+                                  "chkconnect", 0, NULL);
+                if (rc)
+                        RETURN(rc);
+
+                exp = lmv->tgts[mds_num].ltd_exp;
+                LASSERTF(exp, "No export for MDS #%i\n", mds_num);
+
                 req = ptlrpc_prep_req(class_exp2cliimp(exp), 
                                       LUSTRE_MDS_VERSION, MDS_PARSE_ID, 1, 
                                       &size, NULL);
@@ -523,15 +551,18 @@ mds_audit_id2name(struct obd_device *obd, char **name, int *namelen,
         INIT_LIST_HEAD(&list);
 
         cur_id = *id;
+        if (!id_ino(&cur_id)) {
+                CERROR("Invalid id!\n");
+                RETURN(-EINVAL);
+        }
         if (id_fid(&cur_id) == ROOT_FID)
                 RETURN(0);
+        
 next:
         memset(&parent_id, 0, sizeof(parent_id));
-
         rc = mds_id2name(obd, &cur_id, &list, &parent_id);
         if (rc == -ENOENT) {
                 /* can't reconstruct name from id, turn to audit log */
-                LASSERT(id_fid(&parent_id));
                 cur_id = parent_id;
                 memset(&parent_id, 0, sizeof(parent_id));
 
@@ -554,18 +585,23 @@ next:
                 item = list_entry(pos, struct name_item, link);
                 *namelen += strlen(item->name) + 1;
         }
+        
+        (*namelen)++;     /* for the ending '\0' of string */
         OBD_ALLOC(*name, *namelen);
         if (*name == NULL)
                 rc = -ENOMEM;
 out:
         list_for_each_safe (pos, n, &list) {
                 item = list_entry(pos, struct name_item, link);
+                
                 if (!rc) {
                         strcat(*name, "/");
                         strcat(*name, item->name);
                 }
                 list_del_init(&item->link);
                 OBD_FREE(item, sizeof(*item));
+                if (*name)
+                        LASSERT(strlen(*name) < *namelen);
         }
         RETURN(rc);
 }