Whamcloud - gitweb
LU-14905 lfsck: linkEA overflow handling fix
[fs/lustre-release.git] / lustre / obdclass / linkea.c
index a1bcc3d..2ea560f 100644 (file)
  * GPL HEADER END
  */
 /*
- * Copyright (c) 2013, 2016, Intel Corporation.
+ * Copyright (c) 2013, 2017, Intel Corporation.
  * Use is subject to license terms.
  *
  * Author: Di Wang <di.wang@intel.com>
  */
 
-#include <lustre/lustre_idl.h>
 #include <obd.h>
 #include <lustre_linkea.h>
 
@@ -127,11 +126,23 @@ void linkea_entry_unpack(const struct link_ea_entry *lee, int *reclen,
 }
 EXPORT_SYMBOL(linkea_entry_unpack);
 
+bool linkea_will_overflow(struct linkea_data *ldata,
+                         const struct lu_name *lname)
+{
+       struct link_ea_header *leh = ldata->ld_leh;
+       int reclen = lname->ln_namelen + sizeof(struct link_ea_entry);
+
+       if (unlikely(leh->leh_len + reclen > MAX_LINKEA_SIZE))
+               return true;
+       return false;
+}
+EXPORT_SYMBOL(linkea_will_overflow);
+
 /**
  * Add a record to the end of link ea buf
  **/
 int linkea_add_buf(struct linkea_data *ldata, const struct lu_name *lname,
-                  const struct lu_fid *pfid)
+                  const struct lu_fid *pfid, bool err_on_overflow)
 {
        struct link_ea_header *leh = ldata->ld_leh;
        int reclen;
@@ -144,17 +155,18 @@ int linkea_add_buf(struct linkea_data *ldata, const struct lu_name *lname,
        reclen = lname->ln_namelen + sizeof(struct link_ea_entry);
        if (unlikely(leh->leh_len + reclen > MAX_LINKEA_SIZE)) {
                /* Use 32-bits to save the overflow time, although it will
-                * shrink the cfs_time_current_sec() returned 64-bits value
+                * shrink the ktime_get_real_seconds() returned 64-bits value
                 * to 32-bits value, it is still quite large and can be used
-                * for about 140 years. That is enough. */
-               leh->leh_overflow_time = cfs_time_current_sec();
+                * for about 140 years. That is enough.
+                */
+               leh->leh_overflow_time = ktime_get_real_seconds();
                if (unlikely(leh->leh_overflow_time == 0))
                        leh->leh_overflow_time++;
 
                CDEBUG(D_INODE, "No enough space to hold linkea entry '"
                       DFID": %.*s' at %u\n", PFID(pfid), lname->ln_namelen,
                       lname->ln_name, leh->leh_overflow_time);
-               return 0;
+               return err_on_overflow ? -EOVERFLOW : 0;
        }
 
        if (leh->leh_len + reclen > ldata->ld_buf->lb_len) {
@@ -169,14 +181,20 @@ int linkea_add_buf(struct linkea_data *ldata, const struct lu_name *lname,
        ldata->ld_reclen = linkea_entry_pack(ldata->ld_lee, lname, pfid);
        leh->leh_len += ldata->ld_reclen;
        leh->leh_reccount++;
-       CDEBUG(D_INODE, "New link_ea name '"DFID":%.*s' is added\n",
-              PFID(pfid), lname->ln_namelen, lname->ln_name);
+       if (err_on_overflow)
+               CDEBUG(D_INODE,
+                      "New link_ea name '"DFID":<encrypted (%d)>' is added\n",
+                      PFID(pfid), lname->ln_namelen);
+       else
+               CDEBUG(D_INODE, "New link_ea name '"DFID":%.*s' is added\n",
+                      PFID(pfid), lname->ln_namelen, lname->ln_name);
        return 0;
 }
 EXPORT_SYMBOL(linkea_add_buf);
 
 /** Del the current record from the link ea buf */
-void linkea_del_buf(struct linkea_data *ldata, const struct lu_name *lname)
+void linkea_del_buf(struct linkea_data *ldata, const struct lu_name *lname,
+                   bool is_encrypted)
 {
        LASSERT(ldata->ld_leh != NULL && ldata->ld_lee != NULL);
        LASSERT(ldata->ld_leh->leh_reccount > 0);
@@ -186,8 +204,13 @@ void linkea_del_buf(struct linkea_data *ldata, const struct lu_name *lname)
        memmove(ldata->ld_lee, (char *)ldata->ld_lee + ldata->ld_reclen,
                (char *)ldata->ld_leh + ldata->ld_leh->leh_len -
                (char *)ldata->ld_lee);
-       CDEBUG(D_INODE, "Old link_ea name '%.*s' is removed\n",
-              lname->ln_namelen, lname->ln_name);
+       if (is_encrypted)
+               CDEBUG(D_INODE,
+                      "Old link_ea name '<encrypted (%d)>' is removed\n",
+                      lname->ln_namelen);
+       else
+               CDEBUG(D_INODE, "Old link_ea name '%.*s' is removed\n",
+                      lname->ln_namelen, lname->ln_name);
 
        if ((char *)ldata->ld_lee >= ((char *)ldata->ld_leh +
                                      ldata->ld_leh->leh_len))
@@ -202,7 +225,7 @@ int linkea_links_new(struct linkea_data *ldata, struct lu_buf *buf,
 
        rc = linkea_data_new(ldata, buf);
        if (!rc)
-               rc = linkea_add_buf(ldata, cname, pfid);
+               rc = linkea_add_buf(ldata, cname, pfid, false);
 
        return rc;
 }
@@ -236,7 +259,7 @@ int linkea_overflow_shrink(struct linkea_data *ldata)
        if (unlikely(leh->leh_reccount == 0))
                return 0;
 
-       leh->leh_overflow_time = cfs_time_current_sec();
+       leh->leh_overflow_time = ktime_get_real_seconds();
        if (unlikely(leh->leh_overflow_time == 0))
                leh->leh_overflow_time++;
        ldata->ld_reclen = 0;