Whamcloud - gitweb
b=20826
[fs/lustre-release.git] / lustre / lclient / lcommon_cl.c
index d68ba37..dd04f9b 100644 (file)
@@ -144,7 +144,7 @@ void *ccc_key_init(const struct lu_context *ctx,
 {
         struct ccc_thread_info *info;
 
-        OBD_SLAB_ALLOC_PTR(info, ccc_thread_kmem);
+        OBD_SLAB_ALLOC_PTR_GFP(info, ccc_thread_kmem, CFS_ALLOC_IO);
         if (info == NULL)
                 info = ERR_PTR(-ENOMEM);
         return info;
@@ -162,7 +162,7 @@ void *ccc_session_key_init(const struct lu_context *ctx,
 {
         struct ccc_session *session;
 
-        OBD_SLAB_ALLOC_PTR(session, ccc_session_kmem);
+        OBD_SLAB_ALLOC_PTR_GFP(session, ccc_session_kmem, CFS_ALLOC_IO);
         if (session == NULL)
                 session = ERR_PTR(-ENOMEM);
         return session;
@@ -280,7 +280,7 @@ int ccc_req_init(const struct lu_env *env, struct cl_device *dev,
         struct ccc_req *vrq;
         int result;
 
-        OBD_SLAB_ALLOC_PTR(vrq, ccc_req_kmem);
+        OBD_SLAB_ALLOC_PTR_GFP(vrq, ccc_req_kmem, CFS_ALLOC_IO);
         if (vrq != NULL) {
                 cl_req_slice_add(req, &vrq->crq_cl, dev, &ccc_req_ops);
                 result = 0;
@@ -337,7 +337,7 @@ void ccc_global_fini(struct lu_device_type *device_type)
  */
 
 struct lu_object *ccc_object_alloc(const struct lu_env *env,
-                                   const struct lu_object_header *_,
+                                   const struct lu_object_header *unused,
                                    struct lu_device *dev,
                                    const struct cl_object_operations *clops,
                                    const struct lu_object_operations *luops)
@@ -345,7 +345,7 @@ struct lu_object *ccc_object_alloc(const struct lu_env *env,
         struct ccc_object *vob;
         struct lu_object  *obj;
 
-        OBD_SLAB_ALLOC_PTR(vob, ccc_object_kmem);
+        OBD_SLAB_ALLOC_PTR_GFP(vob, ccc_object_kmem, CFS_ALLOC_IO);
         if (vob != NULL) {
                 struct cl_object_header *hdr;
 
@@ -405,7 +405,7 @@ void ccc_object_free(const struct lu_env *env, struct lu_object *obj)
 
 int ccc_lock_init(const struct lu_env *env,
                   struct cl_object *obj, struct cl_lock *lock,
-                  const struct cl_io *_,
+                  const struct cl_io *unused,
                   const struct cl_lock_operations *lkops)
 {
         struct ccc_lock *clk;
@@ -413,7 +413,7 @@ int ccc_lock_init(const struct lu_env *env,
 
         CLOBINVRNT(env, obj, ccc_object_invariant(obj));
 
-        OBD_SLAB_ALLOC_PTR(clk, ccc_lock_kmem);
+        OBD_SLAB_ALLOC_PTR_GFP(clk, ccc_lock_kmem, CFS_ALLOC_IO);
         if (clk != NULL) {
                 cl_lock_slice_add(lock, &clk->clk_cl, obj, lkops);
                 result = 0;
@@ -465,7 +465,7 @@ int ccc_page_is_under_lock(const struct lu_env *env,
                            const struct cl_page_slice *slice,
                            struct cl_io *io)
 {
-        struct ccc_io        *vio  = ccc_env_io(env);
+        struct ccc_io        *cio  = ccc_env_io(env);
         struct cl_lock_descr *desc = &ccc_env_info(env)->cti_descr;
         struct cl_page       *page = slice->cpl_page;
 
@@ -475,7 +475,7 @@ int ccc_page_is_under_lock(const struct lu_env *env,
 
         if (io->ci_type == CIT_READ || io->ci_type == CIT_WRITE ||
             io->ci_type == CIT_FAULT) {
-                if (vio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED)
+                if (cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED)
                         result = -EBUSY;
                 else {
                         desc->cld_start = page->cp_index;
@@ -503,37 +503,39 @@ void ccc_transient_page_verify(const struct cl_page *page)
 {
 }
 
-void ccc_transient_page_own(const struct lu_env *env,
+int ccc_transient_page_own(const struct lu_env *env,
                                    const struct cl_page_slice *slice,
-                                   struct cl_io *_)
+                                   struct cl_io *unused,
+                                   int nonblock)
 {
         ccc_transient_page_verify(slice->cpl_page);
+        return 0;
 }
 
 void ccc_transient_page_assume(const struct lu_env *env,
                                       const struct cl_page_slice *slice,
-                                      struct cl_io *_)
+                                      struct cl_io *unused)
 {
         ccc_transient_page_verify(slice->cpl_page);
 }
 
 void ccc_transient_page_unassume(const struct lu_env *env,
                                         const struct cl_page_slice *slice,
-                                        struct cl_io *_)
+                                        struct cl_io *unused)
 {
         ccc_transient_page_verify(slice->cpl_page);
 }
 
 void ccc_transient_page_disown(const struct lu_env *env,
                                       const struct cl_page_slice *slice,
-                                      struct cl_io *_)
+                                      struct cl_io *unused)
 {
         ccc_transient_page_verify(slice->cpl_page);
 }
 
 void ccc_transient_page_discard(const struct lu_env *env,
                                        const struct cl_page_slice *slice,
-                                       struct cl_io *_)
+                                       struct cl_io *unused)
 {
         struct cl_page *page = slice->cpl_page;
 
@@ -547,7 +549,7 @@ void ccc_transient_page_discard(const struct lu_env *env,
 
 int ccc_transient_page_prep(const struct lu_env *env,
                                    const struct cl_page_slice *slice,
-                                   struct cl_io *_)
+                                   struct cl_io *unused)
 {
         ENTRY;
         /* transient page should always be sent. */
@@ -560,17 +562,21 @@ int ccc_transient_page_prep(const struct lu_env *env,
  *
  */
 
+void ccc_lock_delete(const struct lu_env *env,
+                     const struct cl_lock_slice *slice)
+{
+        CLOBINVRNT(env, slice->cls_obj, ccc_object_invariant(slice->cls_obj));
+}
+
 void ccc_lock_fini(const struct lu_env *env, struct cl_lock_slice *slice)
 {
         struct ccc_lock *clk = cl2ccc_lock(slice);
-
-        CLOBINVRNT(env, slice->cls_obj, ccc_object_invariant(slice->cls_obj));
         OBD_SLAB_FREE_PTR(clk, ccc_lock_kmem);
 }
 
 int ccc_lock_enqueue(const struct lu_env *env,
                      const struct cl_lock_slice *slice,
-                     struct cl_io *_, __u32 enqflags)
+                     struct cl_io *unused, __u32 enqflags)
 {
         CLOBINVRNT(env, slice->cls_obj, ccc_object_invariant(slice->cls_obj));
         return 0;
@@ -595,7 +601,6 @@ int ccc_lock_wait(const struct lu_env *env, const struct cl_lock_slice *slice)
  * cached lock "fits" into io.
  *
  * \param slice lock to be checked
- *
  * \param io    IO that wants a lock.
  *
  * \see lov_lock_fits_into().
@@ -620,6 +625,7 @@ int ccc_lock_fits_into(const struct lu_env *env,
          */
         if (cio->cui_glimpse)
                 result = descr->cld_mode != CLM_WRITE;
+
         /*
          * Also, don't match incomplete write locks for read, otherwise read
          * would enqueue missing sub-locks in the write mode.
@@ -661,7 +667,7 @@ void ccc_lock_state(const struct lu_env *env,
 
                 obj   = slice->cls_obj;
                 inode = ccc_object_inode(obj);
-                attr  = &ccc_env_info(env)->cti_attr;
+                attr  = ccc_env_thread_attr(env);
 
                 /* vmtruncate()->ll_truncate() first sets the i_size and then
                  * the kms under both a DLM lock and the
@@ -712,8 +718,8 @@ int ccc_io_one_lock_index(const struct lu_env *env, struct cl_io *io,
                           __u32 enqflags, enum cl_lock_mode mode,
                           pgoff_t start, pgoff_t end)
 {
-        struct ccc_io          *vio   = ccc_env_io(env);
-        struct cl_lock_descr   *descr = &vio->cui_link.cill_descr;
+        struct ccc_io          *cio   = ccc_env_io(env);
+        struct cl_lock_descr   *descr = &cio->cui_link.cill_descr;
         struct cl_object       *obj   = io->ci_obj;
 
         CLOBINVRNT(env, obj, ccc_object_invariant(obj));
@@ -721,23 +727,52 @@ int ccc_io_one_lock_index(const struct lu_env *env, struct cl_io *io,
 
         CDEBUG(D_VFSTRACE, "lock: %i [%lu, %lu]\n", mode, start, end);
 
-        memset(&vio->cui_link, 0, sizeof vio->cui_link);
+        memset(&cio->cui_link, 0, sizeof cio->cui_link);
         descr->cld_mode  = mode;
         descr->cld_obj   = obj;
         descr->cld_start = start;
         descr->cld_end   = end;
 
-        vio->cui_link.cill_enq_flags = enqflags;
-        cl_io_lock_add(env, io, &vio->cui_link);
+        cio->cui_link.cill_enq_flags = enqflags;
+        cl_io_lock_add(env, io, &cio->cui_link);
         RETURN(0);
 }
 
+void ccc_io_update_iov(const struct lu_env *env,
+                       struct ccc_io *cio, struct cl_io *io)
+{
+        int i;
+        size_t size = io->u.ci_rw.crw_count;
+
+        cio->cui_iov_olen = 0;
+        if (cl_io_is_sendfile(io) || size == cio->cui_tot_count)
+                return;
+
+        if (cio->cui_tot_nrsegs == 0)
+                cio->cui_tot_nrsegs =  cio->cui_nrsegs;
+
+        for (i = 0; i < cio->cui_tot_nrsegs; i++) {
+                struct iovec *iv = &cio->cui_iov[i];
+
+                if (iv->iov_len < size)
+                        size -= iv->iov_len;
+                else {
+                        if (iv->iov_len > size) {
+                                cio->cui_iov_olen = iv->iov_len;
+                                iv->iov_len = size;
+                        }
+                        break;
+                }
+        }
+
+        cio->cui_nrsegs = i + 1;
+}
+
 int ccc_io_one_lock(const struct lu_env *env, struct cl_io *io,
                     __u32 enqflags, enum cl_lock_mode mode,
                     loff_t start, loff_t end)
 {
         struct cl_object *obj = io->ci_obj;
-
         return ccc_io_one_lock_index(env, io, enqflags, mode,
                                      cl_index(obj, start), cl_index(obj, end));
 }
@@ -748,6 +783,38 @@ void ccc_io_end(const struct lu_env *env, const struct cl_io_slice *ios)
                    ccc_object_invariant(ios->cis_io->ci_obj));
 }
 
+void ccc_io_advance(const struct lu_env *env,
+                    const struct cl_io_slice *ios,
+                    size_t nob)
+{
+        struct ccc_io    *cio = cl2ccc_io(env, ios);
+        struct cl_io     *io  = ios->cis_io;
+        struct cl_object *obj = ios->cis_io->ci_obj;
+
+        CLOBINVRNT(env, obj, ccc_object_invariant(obj));
+
+        if (!cl_io_is_sendfile(io) && io->ci_continue) {
+                /* update the iov */
+                LASSERT(cio->cui_tot_nrsegs >= cio->cui_nrsegs);
+                LASSERT(cio->cui_tot_count  >= nob);
+
+                cio->cui_iov        += cio->cui_nrsegs;
+                cio->cui_tot_nrsegs -= cio->cui_nrsegs;
+                cio->cui_tot_count  -= nob;
+
+                if (cio->cui_iov_olen) {
+                        struct iovec *iv;
+
+                        cio->cui_iov--;
+                        cio->cui_tot_nrsegs++;
+                        iv = &cio->cui_iov[0];
+                        iv->iov_base += iv->iov_len;
+                        LASSERT(cio->cui_iov_olen > iv->iov_len);
+                        iv->iov_len = cio->cui_iov_olen - iv->iov_len;
+                }
+        }
+}
+
 static void ccc_object_size_lock(struct cl_object *obj, int vfslock)
 {
         struct inode *inode = ccc_object_inode(obj);
@@ -781,10 +848,12 @@ static void ccc_object_size_unlock(struct cl_object *obj, int vfslock)
  * the resulting races.
  */
 int ccc_prep_size(const struct lu_env *env, struct cl_object *obj,
-                  struct cl_io *io, loff_t pos, int vfslock)
+                  struct cl_io *io, loff_t start, size_t count, int vfslock,
+                  int *exceed)
 {
-        struct cl_attr *attr  = &ccc_env_info(env)->cti_attr;
+        struct cl_attr *attr  = ccc_env_thread_attr(env);
         struct inode   *inode = ccc_object_inode(obj);
+        loff_t          pos   = start + count - 1;
         loff_t kms;
         int result;
 
@@ -818,7 +887,21 @@ int ccc_prep_size(const struct lu_env *env, struct cl_object *obj,
                          * of the buffer (C)
                          */
                         ccc_object_size_unlock(obj, vfslock);
-                        return cl_glimpse_lock(env, io, inode, obj);
+                        result = cl_glimpse_lock(env, io, inode, obj);
+                        if (result == 0 && exceed != NULL) {
+                                /* If objective page index exceed end-of-file
+                                 * page index, return directly. Do not expect
+                                 * kernel will check such case correctly.
+                                 * linux-2.6.18-128.1.1 miss to do that.
+                                 * --bug 17336 */
+                                loff_t size = cl_isize_read(inode);
+                                unsigned long cur_index = start >> CFS_PAGE_SHIFT;
+
+                                if ((size == 0 && cur_index != 0) ||
+                                    (((size - 1) >> CFS_PAGE_SHIFT) < cur_index))
+                                *exceed = 1;
+                        }
+                        return result;
                 } else {
                         /*
                          * region is within kms and, hence, within real file
@@ -978,6 +1061,7 @@ int cl_setattr_ost(struct inode *inode, struct obd_capa *capa)
 
                 oinfo.oi_oa = oa;
                 oinfo.oi_md = lsm;
+                oinfo.oi_capa = capa;
 
                 /* XXX: this looks unnecessary now. */
                 rc = obd_setattr_rqset(cl_i2sbi(inode)->ll_dt_exp, &oinfo,
@@ -1155,7 +1239,6 @@ void cl_inode_fini(struct inode *inode)
         int emergency;
 
         if (clob != NULL) {
-                struct lu_object_header *head = clob->co_lu.lo_header;
                 void                    *cookie;
 
                 cookie = cl_env_reenter();
@@ -1174,8 +1257,6 @@ void cl_inode_fini(struct inode *inode)
                  */
                 cl_object_kill(env, clob);
                 lu_object_ref_del(&clob->co_lu, "inode", inode);
-                /* XXX temporary: this is racy */
-                LASSERT(atomic_read(&head->loh_ref) == 1);
                 cl_object_put(env, clob);
                 lli->lli_clob = NULL;
                 if (emergency) {
@@ -1186,3 +1267,65 @@ void cl_inode_fini(struct inode *inode)
                 cl_env_reexit(cookie);
         }
 }
+
+/**
+ * return IF_* type for given lu_dirent entry.
+ * IF_* flag shld be converted to particular OS file type in
+ * platform llite module.
+ */
+__u16 ll_dirent_type_get(struct lu_dirent *ent)
+{
+        __u16 type = 0;
+        struct luda_type *lt;
+        int len = 0;
+
+        if (le32_to_cpu(ent->lde_attrs) & LUDA_TYPE) {
+                const unsigned align = sizeof(struct luda_type) - 1;
+
+                len = le16_to_cpu(ent->lde_namelen);
+                len = (len + align) & ~align;
+                lt = (void *) ent->lde_name + len;
+                type = CFS_IFTODT(le16_to_cpu(lt->lt_type));
+        }
+        return type;
+}
+
+/**
+ * build inode number from passed @fid */
+ino_t cl_fid_build_ino(struct lu_fid *fid)
+{
+        ino_t ino;
+        ENTRY;
+
+        if (fid_is_igif(fid)) {
+                ino = lu_igif_ino(fid);
+                RETURN(ino);
+        }
+
+        /* Very stupid and having many downsides inode allocation algorithm
+         * based on fid. */
+        ino = fid_flatten(fid) & 0xFFFFFFFF;
+
+        if (unlikely(ino == 0))
+                /* the first result ino is 0xFFC001, so this is rarely used */
+                ino = 0xffbcde;
+        ino = ino | 0x80000000;
+        RETURN(ino);
+}
+
+/**
+ * build inode generation from passed @fid.  If our FID overflows the 32-bit
+ * inode number then return a non-zero generation to distinguish them. */
+__u32 cl_fid_build_gen(struct lu_fid *fid)
+{
+        __u32 gen;
+        ENTRY;
+
+        if (fid_is_igif(fid)) {
+                gen = lu_igif_gen(fid);
+                RETURN(gen);
+        }
+
+        gen = (fid_flatten(fid) >> 32);
+        RETURN(gen);
+}