Whamcloud - gitweb
LU-1540 osd: add NUL terminator for long symlink
[fs/lustre-release.git] / lustre / osd-ldiskfs / osd_handler.c
index 58e4771..dc443f4 100644 (file)
@@ -2542,8 +2542,9 @@ static int osd_ldiskfs_writelink(struct inode *inode, char *buffer, int buflen)
         return 0;
 }
 
-static int osd_ldiskfs_write_record(struct inode *inode, void *buf, int bufsize,
-                                    loff_t *offs, handle_t *handle)
+static int
+osd_ldiskfs_write_record(struct inode *inode, void *buf, int bufsize,
+                         int write_NUL, loff_t *offs, handle_t *handle)
 {
         struct buffer_head *bh = NULL;
         loff_t offset = *offs;
@@ -2555,6 +2556,15 @@ static int osd_ldiskfs_write_record(struct inode *inode, void *buf, int bufsize,
         int boffs;
         int dirty_inode = 0;
 
+        if (write_NUL) {
+                /*
+                 * long symlink write does not count the NUL terminator in
+                 * bufsize, we write it, and the inode's file size does not
+                 * count the NUL terminator as well.
+                 */
+                ((char*)buf)[bufsize] = '\0';
+                ++bufsize;
+        }
         while (bufsize > 0) {
                 if (bh != NULL)
                         brelse(bh);
@@ -2591,6 +2601,8 @@ static int osd_ldiskfs_write_record(struct inode *inode, void *buf, int bufsize,
         if (bh)
                 brelse(bh);
 
+        if (write_NUL)
+                --new_size;
         /* correct in-core and on-disk sizes */
         if (new_size > i_size_read(inode)) {
                 spin_lock(&inode->i_lock);
@@ -2619,6 +2631,7 @@ static ssize_t osd_write(const struct lu_env *env, struct dt_object *dt,
         struct inode       *inode = obj->oo_inode;
         struct osd_thandle *oh;
         ssize_t            result = 0;
+        int                is_link;
 #ifdef HAVE_QUOTA_SUPPORT
         cfs_cap_t           save = cfs_curproc_cap_pack();
 #endif
@@ -2638,13 +2651,15 @@ static ssize_t osd_write(const struct lu_env *env, struct dt_object *dt,
 #endif
         /* Write small symlink to inode body as we need to maintain correct
          * on-disk symlinks for ldiskfs.
+         * Note: the buf->lb_buf contains a NUL terminator while buf->lb_len
+         * does not count it in.
          */
-        if(S_ISLNK(obj->oo_dt.do_lu.lo_header->loh_attr) &&
-           (buf->lb_len < sizeof (LDISKFS_I(inode)->i_data)))
+        is_link = S_ISLNK(dt->do_lu.lo_header->loh_attr);
+        if(is_link && (buf->lb_len < sizeof (LDISKFS_I(inode)->i_data)))
                 result = osd_ldiskfs_writelink(inode, buf->lb_buf, buf->lb_len);
         else
                 result = osd_ldiskfs_write_record(inode, buf->lb_buf,
-                                                  buf->lb_len, pos,
+                                                  buf->lb_len, is_link, pos,
                                                   oh->ot_handle);
 #ifdef HAVE_QUOTA_SUPPORT
         cfs_curproc_cap_unpack(save);