Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / llite / dir.c
index 87be848..b84b877 100644 (file)
 #include <linux/version.h>
 #include <linux/smp_lock.h>
 #include <asm/uaccess.h>
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-# include <linux/locks.h>   // for wait_on_buffer
-#else
-# include <linux/buffer_head.h>   // for wait_on_buffer
-#endif
+#include <linux/buffer_head.h>   // for wait_on_buffer
 
 #define DEBUG_SUBSYSTEM S_LLITE
 
@@ -171,7 +167,7 @@ static int ll_dir_readpage(struct file *file, struct page *page)
                 LASSERT_REPSWABBED(request, REPLY_REC_OFF);
 
                 if (body->valid & OBD_MD_FLSIZE)
-                        inode->i_size = body->size;
+                        i_size_write(inode, body->size);
                 SetPageUptodate(page);
         }
         ptlrpc_req_finished(request);
@@ -187,7 +183,7 @@ struct address_space_operations ll_dir_aops = {
 
 static inline unsigned long dir_pages(struct inode *inode)
 {
-        return (inode->i_size + CFS_PAGE_SIZE - 1) >> CFS_PAGE_SHIFT;
+        return (i_size_read(inode) + CFS_PAGE_SIZE - 1) >> CFS_PAGE_SHIFT;
 }
 
 static inline unsigned ll_chunk_size(struct inode *inode)
@@ -297,6 +293,8 @@ static struct page *ll_get_dir_page(struct inode *dir, __u32 hash, int exact,
         rc = md_lock_match(ll_i2sbi(dir)->ll_md_exp, LDLM_FL_BLOCK_GRANTED,
                            ll_inode2fid(dir), LDLM_IBITS, &policy, mode, &lockh);
         if (!rc) {
+                struct ldlm_enqueue_info einfo = { LDLM_IBITS, mode,
+                       ll_md_blocking_ast, ldlm_completion_ast, NULL, dir };
                 struct lookup_intent it = { .it_op = IT_READDIR };
                 struct ptlrpc_request *request;
                 struct md_op_data *op_data;
@@ -306,10 +304,8 @@ static struct page *ll_get_dir_page(struct inode *dir, __u32 hash, int exact,
                 if (IS_ERR(op_data))
                         return (void *)op_data;
 
-                rc = md_enqueue(ll_i2sbi(dir)->ll_md_exp, LDLM_IBITS, &it,
-                                mode, op_data, &lockh, NULL, 0,
-                                ldlm_completion_ast, ll_md_blocking_ast, dir,
-                                0);
+                rc = md_enqueue(ll_i2sbi(dir)->ll_md_exp, &einfo, &it,
+                                op_data, &lockh, NULL, 0, 0);
 
                 ll_finish_md_op_data(op_data);
 
@@ -416,7 +412,7 @@ int ll_readdir(struct file *filp, void *cookie, filldir_t filldir)
 
         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p) pos %lu/%llu\n",
                inode->i_ino, inode->i_generation, inode,
-               (unsigned long)pos, inode->i_size);
+               (unsigned long)pos, i_size_read(inode));
 
         if (pos == DIR_END_OFF)
                 /*
@@ -440,7 +436,7 @@ int ll_readdir(struct file *filp, void *cookie, filldir_t filldir)
                          * If page is empty (end of directoryis reached),
                          * use this value. 
                          */
-                        __u32 hash = DIR_END_OFF; 
+                        __u32 hash = DIR_END_OFF;
                         __u32 next;
 
                         dp = page_address(page);
@@ -528,12 +524,52 @@ do {                                    \
         Q_COPY(out, in, qc_dqblk);      \
 } while (0)
 
-int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump)
+int ll_send_mgc_param(struct obd_export *mgc, char *string)
+{
+        struct mgs_send_param *msp;
+        int rc = 0;
+
+        OBD_ALLOC_PTR(msp);
+        if (!msp)
+                return -ENOMEM;
+
+        strncpy(msp->mgs_param, string, MGS_PARAM_MAXLEN);
+        rc = obd_set_info_async(mgc, strlen(KEY_SET_INFO), KEY_SET_INFO,
+                                sizeof(struct mgs_send_param), msp, NULL);
+        if (rc)
+                CERROR("Failed to set parameter: %d\n", rc);
+        OBD_FREE_PTR(msp);
+
+        return rc;
+}
+
+char *ll_get_fsname(struct inode *inode)
+{
+        struct lustre_sb_info *lsi = s2lsi(inode->i_sb);
+        char *ptr, *fsname;
+        int len;
+
+        OBD_ALLOC(fsname, MGS_PARAM_MAXLEN);
+        len = strlen(lsi->lsi_lmd->lmd_profile);
+        ptr = strrchr(lsi->lsi_lmd->lmd_profile, '-');
+        if (ptr && (strcmp(ptr, "-client") == 0))
+                len -= 7;
+        strncpy(fsname, lsi->lsi_lmd->lmd_profile, len);
+        fsname[len] = '\0';
+
+        return fsname;
+}
+
+int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump,
+                     int set_default)
 {
         struct ll_sb_info *sbi = ll_i2sbi(inode);
         struct md_op_data *op_data;
         struct ptlrpc_request *req = NULL;
         int rc = 0;
+        struct lustre_sb_info *lsi = s2lsi(inode->i_sb);
+        struct obd_device *mgc = lsi->lsi_mgc;
+        char *fsname = NULL, *param = NULL;
 
         /*
          * This is coming from userspace, so should be in
@@ -553,15 +589,46 @@ int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump)
 
         /* swabbing is done in lov_setstripe() on server side */
         rc = md_setattr(sbi->ll_md_exp, op_data, lump, sizeof(*lump),
-                        NULL, 0, &req);
+                        NULL, 0, &req, NULL);
         ll_finish_md_op_data(op_data);
         ptlrpc_req_finished(req);
         if (rc) {
                 if (rc != -EPERM && rc != -EACCES)
                         CERROR("mdc_setattr fails: rc = %d\n", rc);
         }
-        return rc;
 
+        if (set_default && mgc->u.cli.cl_mgc_mgsexp) {
+                OBD_ALLOC(param, MGS_PARAM_MAXLEN);
+
+                /* Get fsname and assume devname to be -MDT0000. */
+                fsname = ll_get_fsname(inode);
+                /* Set root stripesize */
+                sprintf(param, "%s-MDT0000.lov.stripesize=%u", fsname,
+                        lump->lmm_stripe_size);
+                rc = ll_send_mgc_param(mgc->u.cli.cl_mgc_mgsexp, param);
+                if (rc)
+                        goto end;
+
+                /* Set root stripecount */
+                sprintf(param, "%s-MDT0000.lov.stripecount=%u", fsname,
+                        lump->lmm_stripe_count);
+                rc = ll_send_mgc_param(mgc->u.cli.cl_mgc_mgsexp, param);
+                if (rc)
+                        goto end;
+
+                /* Set root stripeoffset */
+                sprintf(param, "%s-MDT0000.lov.stripeoffset=%u", fsname,
+                        lump->lmm_stripe_offset);
+                rc = ll_send_mgc_param(mgc->u.cli.cl_mgc_mgsexp, param);
+                if (rc)
+                        goto end;
+end:
+                if (fsname)
+                        OBD_FREE(fsname, MGS_PARAM_MAXLEN);
+                if (param)
+                        OBD_FREE(param, MGS_PARAM_MAXLEN);
+        }
+        return rc;
 }
 
 int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmmp, 
@@ -690,6 +757,7 @@ static int ll_dir_ioctl(struct inode *inode, struct file *file,
         case LL_IOC_LOV_SETSTRIPE: {
                 struct lov_user_md lum, *lump = (struct lov_user_md *)arg;
                 int rc = 0;
+                int set_default = 0;
 
                 LASSERT(sizeof(lum) == sizeof(*lump));
                 LASSERT(sizeof(lum.lmm_objects[0]) ==
@@ -698,7 +766,10 @@ static int ll_dir_ioctl(struct inode *inode, struct file *file,
                 if (rc)
                         RETURN(-EFAULT);
 
-                rc = ll_dir_setstripe(inode, &lum);
+                if (inode->i_sb->s_root == file->f_dentry)
+                        set_default = 1;
+
+                rc = ll_dir_setstripe(inode, &lum, set_default);
 
                 RETURN(rc);
         }