Whamcloud - gitweb
LU-15880 quota: fix issues in reserving quota
[fs/lustre-release.git] / lustre / osd-ldiskfs / osd_handler.c
index d206292..ab7facf 100644 (file)
@@ -517,11 +517,18 @@ struct inode *osd_iget(struct osd_thread_info *info, struct osd_device *dev,
                iput(inode);
                inode = ERR_PTR(-ESTALE);
        } else if (is_bad_inode(inode)) {
-               rc = -ENOENT;
                CWARN("%s: bad inode: ino = %u: rc = %d\n",
-                     osd_dev2name(dev), id->oii_ino, rc);
+                     osd_dev2name(dev), id->oii_ino, -ENOENT);
                iput(inode);
-               inode = ERR_PTR(rc);
+               inode = ERR_PTR(-ENOENT);
+       } else  if (osd_is_ea_inode(inode)) {
+               /*
+                * EA inode is internal ldiskfs object, should don't visible
+                * on osd
+                */
+               CDEBUG(D_INODE, "EA inode: ino = %u\n", id->oii_ino);
+               iput(inode);
+               inode = ERR_PTR(-ENOENT);
        } else if ((rc = osd_attach_jinode(inode))) {
                iput(inode);
                inode = ERR_PTR(rc);
@@ -634,7 +641,7 @@ static struct inode *osd_iget_check(struct osd_thread_info *info,
         */
 
 again:
-       inode = osd_ldiskfs_iget(osd_sb(dev), id->oii_ino);
+       inode = osd_iget(info, dev, id);
        if (IS_ERR(inode)) {
                rc = PTR_ERR(inode);
                if (!trusted && (rc == -ENOENT || rc == -ESTALE))
@@ -645,40 +652,6 @@ again:
                GOTO(put, rc);
        }
 
-       if (is_bad_inode(inode)) {
-               rc = -ENOENT;
-               if (!trusted)
-                       goto check_oi;
-
-               CDEBUG(D_INODE, "bad inode for FID: "DFID", ino = %u\n",
-                      PFID(fid), id->oii_ino);
-               GOTO(put, rc);
-       }
-
-       if (id->oii_gen != OSD_OII_NOGEN &&
-           inode->i_generation != id->oii_gen) {
-               rc = -ESTALE;
-               if (!trusted)
-                       goto check_oi;
-
-               CDEBUG(D_INODE, "unmatched inode for FID: "DFID", ino = %u, "
-                      "oii_gen = %u, i_generation = %u\n", PFID(fid),
-                      id->oii_ino, id->oii_gen, inode->i_generation);
-               GOTO(put, rc);
-       }
-
-       if (inode->i_nlink == 0) {
-               rc = -ENOENT;
-               if (!trusted)
-                       goto check_oi;
-
-               CDEBUG(D_INODE, "stale inode for FID: "DFID", ino = %u\n",
-                      PFID(fid), id->oii_ino);
-               GOTO(put, rc);
-       }
-
-       ldiskfs_clear_inode_state(inode, LDISKFS_STATE_LUSTRE_DESTROY);
-
 check_oi:
        if (rc != 0) {
                __u32 saved_ino = id->oii_ino;
@@ -752,19 +725,6 @@ check_oi:
                        rc = -ENOENT;
                else
                        rc = -EREMCHG;
-       } else {
-               if (id->oii_gen == OSD_OII_NOGEN)
-                       osd_id_gen(id, inode->i_ino, inode->i_generation);
-
-               /*
-                * Do not update file c/mtime in ldiskfs.
-                * NB: we don't have any lock to protect this because we don't
-                * have reference on osd_object now, but contention with
-                * another lookup + attr_set can't happen in the tiny window
-                * between if (...) and set S_NOCMTIME.
-                */
-               if (!(inode->i_flags & S_NOCMTIME))
-                       inode->i_flags |= S_NOCMTIME;
        }
 
        GOTO(put, rc);
@@ -1179,7 +1139,7 @@ static int osd_fid_lookup(const struct lu_env *env, struct osd_object *obj,
        /* Search order: 3. OI files. */
        result = osd_oi_lookup(info, dev, fid, id, OI_CHECK_FLD);
        if (result == -ENOENT) {
-               if (!(fid_is_norm(fid) || fid_is_igif(fid)) ||
+               if (!fid_is_norm(fid) ||
                    fid_is_on_ost(info, dev, fid, OI_CHECK_FLD) ||
                    !ldiskfs_test_bit(osd_oi_fid2idx(dev, fid),
                                      sf->sf_oi_bitmap))
@@ -2581,23 +2541,20 @@ const int osd_dto_credits_noquota[DTO_NR] = {
 /* reserve or free quota for some operation */
 static int osd_reserve_or_free_quota(const struct lu_env *env,
                                     struct dt_device *dev,
-                                    enum quota_type type, __u64 uid,
-                                    __u64 gid, __s64 count, bool is_md)
+                                    struct lquota_id_info *qi)
 {
-       int rc;
        struct osd_device       *osd = osd_dt_dev(dev);
-       struct osd_thread_info  *info = osd_oti_get(env);
-       struct lquota_id_info   *qi = &info->oti_qi;
        struct qsd_instance     *qsd = NULL;
+       int rc;
 
        ENTRY;
 
-       if (is_md)
-               qsd = osd->od_quota_slave_md;
-       else
+       if (qi->lqi_is_blk)
                qsd = osd->od_quota_slave_dt;
+       else
+               qsd = osd->od_quota_slave_md;
 
-       rc = quota_reserve_or_free(env, qsd, qi, type, uid, gid, count, is_md);
+       rc = qsd_reserve_or_free_quota(env, qsd, qi);
        RETURN(rc);
 }
 
@@ -3468,7 +3425,6 @@ static void osd_ah_init(const struct lu_env *env, struct dt_allocation_hint *ah,
        LASSERT(ah);
 
        ah->dah_parent = parent;
-       ah->dah_mode = child_mode;
 
        if (parent != NULL && !dt_object_remote(parent)) {
                /* will help to find FID->ino at dt_insert("..") */
@@ -4309,7 +4265,7 @@ static int osd_ref_add(const struct lu_env *env, struct dt_object *dt,
                /* inc_nlink from 0 may cause WARN_ON */
                set_nlink(inode, 1);
        else {
-               ldiskfs_inc_count(oh->ot_handle, inode);
+               osd_ldiskfs_inc_count(oh->ot_handle, inode);
                if (!S_ISDIR(inode->i_mode))
                        LASSERT(inode->i_nlink <= LDISKFS_LINK_MAX);
        }
@@ -4388,7 +4344,7 @@ static int osd_ref_del(const struct lu_env *env, struct dt_object *dt,
        CDEBUG(D_INODE, DFID" decrease nlink %d\n",
               PFID(lu_object_fid(&dt->do_lu)), inode->i_nlink);
 
-       ldiskfs_dec_count(oh->ot_handle, inode);
+       osd_ldiskfs_dec_count(oh->ot_handle, inode);
        spin_unlock(&obj->oo_guard);
 
        osd_dirty_inode(inode, I_DIRTY_DATASYNC);
@@ -4491,8 +4447,18 @@ static int osd_xattr_get(const struct lu_env *env, struct dt_object *dt,
                        ol->ol_comp_id = 0;
                }
        } else {
-               rc = __osd_xattr_get(inode, dentry, name,
-                                    buf->lb_buf, buf->lb_len);
+               /* Get enc context xattr directly from ldiskfs instead of going
+                * through the VFS, as there is no xattr handler for
+                * "encryption.".
+                */
+               if (strcmp(name, LL_XATTR_NAME_ENCRYPTION_CONTEXT) == 0)
+                       rc = ldiskfs_xattr_get(inode,
+                                         LDISKFS_XATTR_INDEX_ENCRYPTION,
+                                         LDISKFS_XATTR_NAME_ENCRYPTION_CONTEXT,
+                                         buf->lb_buf, buf->lb_len);
+               else
+                       rc = __osd_xattr_get(inode, dentry, name,
+                                            buf->lb_buf, buf->lb_len);
        }
 
        if (cache_xattr) {
@@ -4860,7 +4826,27 @@ static int osd_xattr_set(const struct lu_env *env, struct dt_object *dt,
        if (fl & LU_XATTR_CREATE)
                fs_flags |= XATTR_CREATE;
 
-       rc = __osd_xattr_set(info, inode, name, buf->lb_buf, len, fs_flags);
+       if (strcmp(name, LL_XATTR_NAME_ENCRYPTION_CONTEXT) == 0) {
+               /* Set enc context xattr directly in ldiskfs instead of going
+                * through the VFS, as there is no xattr handler for
+                * "encryption.".
+                */
+               struct osd_thandle *oth = container_of(handle,
+                                                      struct osd_thandle,
+                                                      ot_super);
+
+               if (!oth->ot_handle)
+                       /* this should be already part of a transaction */
+                       RETURN(-EPROTO);
+
+               rc = ldiskfs_xattr_set_handle(oth->ot_handle, inode,
+                                         LDISKFS_XATTR_INDEX_ENCRYPTION,
+                                         LDISKFS_XATTR_NAME_ENCRYPTION_CONTEXT,
+                                         buf->lb_buf, len, fs_flags);
+       } else {
+               rc = __osd_xattr_set(info, inode, name,
+                                    buf->lb_buf, len, fs_flags);
+       }
        osd_trans_exec_check(env, handle, OSD_OT_XATTR_SET);
 
        if (rc == 0 &&
@@ -4878,9 +4864,11 @@ static int osd_xattr_list(const struct lu_env *env, struct dt_object *dt,
                          const struct lu_buf *buf)
 {
        struct osd_object *obj = osd_dt_obj(dt);
+       struct osd_device *dev = osd_obj2dev(obj);
        struct inode *inode = obj->oo_inode;
        struct osd_thread_info *info = osd_oti_get(env);
        struct dentry *dentry = &info->oti_obj_dentry;
+       int rc;
 
        if (!dt_object_exists(dt))
                return -ENOENT;
@@ -4891,7 +4879,31 @@ static int osd_xattr_list(const struct lu_env *env, struct dt_object *dt,
 
        dentry->d_inode = inode;
        dentry->d_sb = inode->i_sb;
-       return inode->i_op->listxattr(dentry, buf->lb_buf, buf->lb_len);
+       rc = inode->i_op->listxattr(dentry, buf->lb_buf, buf->lb_len);
+
+       if (rc < 0 || buf->lb_buf == NULL)
+               return rc;
+
+       /* Hide virtual project ID xattr from list if disabled */
+       if (!dev->od_enable_projid_xattr) {
+               char *end = (char *)buf->lb_buf + rc;
+               char *p = buf->lb_buf;
+
+               while (p < end) {
+                       char *next = p + strlen(p) + 1;
+
+                       if (strcmp(p, XATTR_NAME_PROJID) == 0) {
+                               if (end - next > 0)
+                                       memmove(p, next, end - next);
+                               rc -= next - p;
+                               break;
+                       }
+
+                       p = next;
+               }
+       }
+
+       return rc;
 }
 
 static int osd_declare_xattr_del(const struct lu_env *env,
@@ -5394,15 +5406,7 @@ static void osd_take_care_of_agent(const struct lu_env *env,
 static int obj_name2lu_name(struct osd_object *obj, const char *name,
                            int len, struct lu_name *ln)
 {
-       struct lu_fid namefid;
-
-       fid_zero(&namefid);
-
-       if (name[0] == '[')
-               sscanf(name + 1, SFID, RFID(&namefid));
-
-       if (fid_is_sane(&namefid) || name_is_dot_or_dotdot(name, len) ||
-           !(obj->oo_lma_flags & LUSTRE_ENCRYPT_FL)) {
+       if (!(obj->oo_lma_flags & LUSTRE_ENCRYPT_FL)) {
                ln->ln_name = name;
                ln->ln_namelen = len;
        } else {
@@ -6851,34 +6855,31 @@ struct osd_filldir_cbs {
  * \retval 1 on buffer full
  */
 #ifdef HAVE_FILLDIR_USE_CTX
-static int osd_ldiskfs_filldir(struct dir_context *buf,
+static int osd_ldiskfs_filldir(struct dir_context *ctx,
 #else
-static int osd_ldiskfs_filldir(void *buf,
+static int osd_ldiskfs_filldir(void *ctx,
 #endif
                               const char *name, int namelen,
                               loff_t offset, __u64 ino, unsigned int d_type)
 {
-       struct osd_it_ea *it = ((struct osd_filldir_cbs *)buf)->it;
+       struct osd_it_ea *it = ((struct osd_filldir_cbs *)ctx)->it;
        struct osd_object *obj = it->oie_obj;
        struct osd_it_ea_dirent *ent = it->oie_dirent;
        struct lu_fid *fid = &ent->oied_fid;
+       char *buf = it->oie_buf;
        struct osd_fid_pack *rec;
-       struct lu_fid namefid;
-
        ENTRY;
 
-/* this should never happen */
+       /* this should never happen */
        if (unlikely(namelen == 0 || namelen > LDISKFS_NAME_LEN)) {
                CERROR("ldiskfs return invalid namelen %d\n", namelen);
                RETURN(-EIO);
        }
 
-       if ((void *)ent - it->oie_buf + sizeof(*ent) + namelen >
-           OSD_IT_EA_BUFSIZE)
+       /* Check for enough space. Note oied_name is not NUL terminated. */
+       if (&ent->oied_name[namelen] > buf + OSD_IT_EA_BUFSIZE)
                RETURN(1);
 
-       fid_zero(&namefid);
-
        /* "." is just the object itself. */
        if (namelen == 1 && name[0] == '.') {
                if (obj != NULL)
@@ -6899,30 +6900,30 @@ static int osd_ldiskfs_filldir(void *buf,
                *fid = obj->oo_dt.do_lu.lo_header->loh_fid;
        }
 
-       if (name[0] == '[')
-               sscanf(name + 1, SFID, RFID(&namefid));
-       if (fid_is_sane(&namefid) || name_is_dot_or_dotdot(name, namelen) ||
-           !obj || !(obj->oo_lma_flags & LUSTRE_ENCRYPT_FL)) {
+       if (obj == NULL || !(obj->oo_lma_flags & LUSTRE_ENCRYPT_FL)) {
+               ent->oied_namelen = namelen;
                memcpy(ent->oied_name, name, namelen);
        } else {
-               int presented_len = critical_chars(name, namelen);
+               int encoded_namelen = critical_chars(name, namelen);
+
+               /* Check again for enough space. */
+               if (&ent->oied_name[encoded_namelen] > buf + OSD_IT_EA_BUFSIZE)
+                       RETURN(1);
 
-               if (presented_len == namelen)
+               ent->oied_namelen = encoded_namelen;
+
+               if (encoded_namelen == namelen)
                        memcpy(ent->oied_name, name, namelen);
                else
-                       namelen = critical_encode(name, namelen,
-                                                 ent->oied_name);
-
-               ent->oied_name[namelen] = '\0';
+                       critical_encode(name, namelen, ent->oied_name);
        }
 
        ent->oied_ino     = ino;
        ent->oied_off     = offset;
-       ent->oied_namelen = namelen;
        ent->oied_type    = d_type;
 
        it->oie_rd_dirent++;
-       it->oie_dirent = (void *)ent + cfs_size_round(sizeof(*ent) + namelen);
+       it->oie_dirent = (void *)ent + cfs_size_round(sizeof(*ent) + ent->oied_namelen);
        RETURN(0);
 }
 
@@ -7758,6 +7759,8 @@ static void osd_key_exit(const struct lu_context *ctx,
        LASSERT(info->oti_r_locks == 0);
        LASSERT(info->oti_w_locks == 0);
        LASSERT(info->oti_txns    == 0);
+       LASSERTF(info->oti_dio_pages_used == 0, "%d\n",
+                info->oti_dio_pages_used);
 }
 
 /* type constructor/destructor: osd_type_init, osd_type_fini */
@@ -8133,6 +8136,7 @@ static int osd_device_init0(const struct lu_env *env,
 
        o->od_read_cache = 1;
        o->od_writethrough_cache = 1;
+       o->od_enable_projid_xattr = 0;
        o->od_readcache_max_filesize = OSD_MAX_CACHE_SIZE;
        o->od_readcache_max_iosize = OSD_READCACHE_MAX_IO_MB << 20;
        o->od_writethrough_max_iosize = OSD_WRITECACHE_MAX_IO_MB << 20;