Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libperfuse Fix memory leak when we discard a voided seta...



details:   https://anonhg.NetBSD.org/src/rev/05a0ac2b242f
branches:  trunk
changeset: 779733:05a0ac2b242f
user:      manu <manu%NetBSD.org@localhost>
date:      Thu Jun 14 05:58:22 2012 +0000

description:
Fix memory leak when we discard a voided setattr operation

diffstat:

 lib/libperfuse/ops.c |  161 +++++++++++++++++++++++++++-----------------------
 1 files changed, 86 insertions(+), 75 deletions(-)

diffs (236 lines):

diff -r a22a9b612922 -r 05a0ac2b242f lib/libperfuse/ops.c
--- a/lib/libperfuse/ops.c      Thu Jun 14 05:14:41 2012 +0000
+++ b/lib/libperfuse/ops.c      Thu Jun 14 05:58:22 2012 +0000
@@ -1,4 +1,4 @@
-/*  $NetBSD: ops.c,v 1.56 2012/06/13 01:45:56 manu Exp $ */
+/*  $NetBSD: ops.c,v 1.57 2012/06/14 05:58:22 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -1696,6 +1696,7 @@
        struct fuse_attr_out *fao;
        struct vattr *old_va;
        int error;
+       int valid;
 #ifdef PERFUSE_DEBUG
        struct vattr *old_vap;
        int resize_debug = 0;
@@ -1719,39 +1720,94 @@
        }
 
        old_va = puffs_pn_getvap((struct puffs_node *)opc);
+       valid = 0;
 
        /*
         * Check for permission to change size
         */
-       if ((vap->va_size != (u_quad_t)PUFFS_VNOVAL) &&
-           (error = mode_access(opc, pcr, PUFFS_VWRITE)) != 0)
-               return error;
+       if ((vap->va_size != (u_quad_t)PUFFS_VNOVAL)) {
+               if ((error = mode_access(opc, pcr, PUFFS_VWRITE)) != 0)
+                       return error;
+               valid |= FUSE_FATTR_SIZE;
+       }
+
+       /*
+        * Check for permission to change owner and group
+        */
+       if ((vap->va_uid != (uid_t)PUFFS_VNOVAL) ||
+           (vap->va_gid != (gid_t)PUFFS_VNOVAL)) {
+               if (puffs_access_chown(old_va->va_uid, old_va->va_gid,
+                                      vap->va_uid, vap->va_gid, pcr) != 0)
+                       return EACCES;
+
+               if (vap->va_uid != (uid_t)PUFFS_VNOVAL)
+                       valid |= FUSE_FATTR_UID;
+
+               if (vap->va_gid != (uid_t)PUFFS_VNOVAL)
+                       valid |= FUSE_FATTR_GID;
+       }
+
+       /*
+        * Check for permission to change permissions
+        */
+       if (vap->va_mode != (mode_t)PUFFS_VNOVAL) {
+               if (puffs_access_chmod(old_va->va_uid, old_va->va_gid,
+                               old_va->va_type, vap->va_mode, pcr) != 0)
+                       return EACCES;
+               valid |= FUSE_FATTR_MODE;
+       }
 
        /*
         * Check for permission to change dates
         */
-       if (((vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL) ||
-            (vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL)) &&
-           (puffs_access_times(old_va->va_uid, old_va->va_gid,
-                               old_va->va_mode, 0, pcr) != 0))
-               return EACCES;
+       if ((vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL) ||
+           (vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL)) {
+               if (vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL)
+                       valid |= FUSE_FATTR_ATIME;
+
+               if (vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL)
+                       valid |= FUSE_FATTR_MTIME;
+
+               /*
+                * ftruncate() sends only va_size, and metadata cache
+                * flush adds va_atime and va_mtime. Some FUSE
+                * filesystems will attempt to detect ftruncate by 
+                * checking for FATTR_SIZE being set without
+                * FATTR_UID|FATTR_GID|FATTR_ATIME|FATTR_MTIME|FATTR_MODE
+                * 
+                * Try to adapt and remove FATTR_ATIME|FATTR_MTIME
+                * if we suspect a ftruncate().
+                */ 
+               if ((valid & FUSE_FATTR_SIZE) &&
+                   !(valid & (FUSE_FATTR_UID|FUSE_FATTR_GID|FUSE_FATTR_MODE)))
+                       valid &= ~(FUSE_FATTR_ATIME|FUSE_FATTR_MTIME);
+
+               /*
+                * There is the same mess with fchmod()
+                */
+               if ((valid & FUSE_FATTR_MODE) &&
+                   !(valid & (FUSE_FATTR_UID|FUSE_FATTR_GID)))
+                       valid &= ~(FUSE_FATTR_ATIME|FUSE_FATTR_MTIME);
+
+               /*
+                * And if a change on atime/mtime remains, check permissions.
+                */
+               if ((valid & (FUSE_FATTR_ATIME|FUSE_FATTR_MTIME)) &&
+                   (puffs_access_times(old_va->va_uid, old_va->va_gid,
+                                       old_va->va_mode, 0, pcr) != 0))
+                       return EACCES;
+       }
 
        /*
-        * Check for permission to change owner and group
+        * If nothing remain, discard the operation. This happend when
+        * only ctime is changed.
         */
-       if (((vap->va_uid != (uid_t)PUFFS_VNOVAL) ||
-            (vap->va_gid != (gid_t)PUFFS_VNOVAL)) &&
-           (puffs_access_chown(old_va->va_uid, old_va->va_gid,
-                               vap->va_uid, vap->va_gid, pcr)) != 0)
-               return EACCES;
-
-       /*
-        * Check for permission to change permissions
-        */
-       if ((vap->va_mode != (mode_t)PUFFS_VNOVAL) &&
-           (puffs_access_chmod(old_va->va_uid, old_va->va_gid,
-                               old_va->va_type, vap->va_mode, pcr)) != 0)
-               return EACCES;
+       if (!(valid & (FUSE_FATTR_SIZE|FUSE_FATTR_ATIME|FUSE_FATTR_MTIME|
+                      FUSE_FATTR_MODE|FUSE_FATTR_UID|FUSE_FATTR_GID))) {
+               error = 0;
+               goto out;
+       }
+
        
        pm = ps->ps_new_msg(pu, opc, FUSE_SETATTR, sizeof(*fsi), pcr);
        fsi = GET_INPAYLOAD(ps, pm, fuse_setattr_in);
@@ -1766,7 +1822,7 @@
                fsi->valid |= FUSE_FATTR_FH;
        }
 
-       if (vap->va_size != (u_quad_t)PUFFS_VNOVAL) {
+       if (valid & FUSE_FATTR_SIZE) {
                fsi->size = vap->va_size;
                fsi->valid |= FUSE_FATTR_SIZE;
 
@@ -1787,10 +1843,8 @@
         * dates being reset to Epoch on glusterfs. If one
         * is missing, use the old value.
         */
-       if ((vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL) || 
-           (vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL)) {
-               
-               if (vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL) {
+       if (valid & (FUSE_FATTR_ATIME|FUSE_FATTR_MTIME)) {
+               if (valid & FUSE_FATTR_ATIME) {
                        fsi->atime = vap->va_atime.tv_sec;
                        fsi->atimensec = (uint32_t)vap->va_atime.tv_nsec;
                } else {
@@ -1798,7 +1852,7 @@
                        fsi->atimensec = (uint32_t)old_va->va_atime.tv_nsec;
                }
 
-               if (vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL) {
+               if (valid & FUSE_FATTR_MTIME) {
                        fsi->mtime = vap->va_mtime.tv_sec;
                        fsi->mtimensec = (uint32_t)vap->va_mtime.tv_nsec;
                } else {
@@ -1809,17 +1863,17 @@
                fsi->valid |= (FUSE_FATTR_MTIME|FUSE_FATTR_ATIME);
        }
 
-       if (vap->va_mode != (mode_t)PUFFS_VNOVAL) {
+       if (valid & FUSE_FATTR_MODE) {
                fsi->mode = vap->va_mode; 
                fsi->valid |= FUSE_FATTR_MODE;
        }
        
-       if (vap->va_uid != (uid_t)PUFFS_VNOVAL) {
+       if (valid & FUSE_FATTR_UID) {
                fsi->uid = vap->va_uid;
                fsi->valid |= FUSE_FATTR_UID;
        }
 
-       if (vap->va_gid != (gid_t)PUFFS_VNOVAL) {
+       if (valid & FUSE_FATTR_GID) {
                fsi->gid = vap->va_gid;
                fsi->valid |= FUSE_FATTR_GID;
        }
@@ -1829,49 +1883,6 @@
                fsi->valid |= FUSE_FATTR_LOCKOWNER;
        }
 
-       /*
-        * ftruncate() sends only va_size, and metadata cache
-        * flush adds va_atime and va_mtime. Some FUSE
-        * filesystems will attempt to detect ftruncate by 
-        * checking for FATTR_SIZE being set without
-        * FATTR_UID|FATTR_GID|FATTR_ATIME|FATTR_MTIME|FATTR_MODE
-        * 
-        * Try to adapt and remove FATTR_ATIME|FATTR_MTIME
-        * if we suspect a ftruncate().
-        */ 
-       if ((vap->va_size != (u_quad_t)PUFFS_VNOVAL) &&
-           ((vap->va_mode == (mode_t)PUFFS_VNOVAL) &&
-            (vap->va_uid == (uid_t)PUFFS_VNOVAL) &&
-            (vap->va_gid == (gid_t)PUFFS_VNOVAL))) {
-               fsi->atime = 0;
-               fsi->atimensec = 0;
-               fsi->mtime = 0;
-               fsi->mtimensec = 0;
-               fsi->valid &= ~(FUSE_FATTR_ATIME|FUSE_FATTR_MTIME);
-       }
-
-       /*
-        * There is the same mess with fchmod()
-        */
-       if ((vap->va_mode != (mode_t)PUFFS_VNOVAL) &&
-           (vap->va_uid == (uid_t)PUFFS_VNOVAL) &&
-           (vap->va_gid == (gid_t)PUFFS_VNOVAL)) {
-               fsi->atime = 0;
-               fsi->atimensec = 0;
-               fsi->mtime = 0;
-               fsi->mtimensec = 0;
-               fsi->valid &= ~(FUSE_FATTR_ATIME|FUSE_FATTR_MTIME);
-       }
-                   
-       /*
-        * If nothing remain, discard the operation.
-        */
-       if (!(fsi->valid & (FUSE_FATTR_SIZE|FUSE_FATTR_ATIME|FUSE_FATTR_MTIME|
-                           FUSE_FATTR_MODE|FUSE_FATTR_UID|FUSE_FATTR_GID))) {
-               ps->ps_destroy_msg(pm);
-               error = 0;
-               goto out;
-       }
 
 #ifdef PERFUSE_DEBUG
        old_vap = puffs_pn_getvap((struct puffs_node *)opc);



Home | Main Index | Thread Index | Old Index