[Libsysio-commit] HEAD: libsysio/drivers/native fs_native.c
Brought to you by:
lward
From: Lee W. <lw...@us...> - 2004-07-23 15:12:11
|
Update of /cvsroot/libsysio/libsysio/drivers/native In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26760 Modified Files: fs_native.c Log Message: Previous checkin introduced a memory leak -- Altered the implementation so that an additional malloc was unnecessary. Also, localized the cache refresh so that it was done whenever a stat was done, enpassant. Couldn't convince myself it was always updated before. Just too stupid to see that I suppose. While testing these changes, a new bug appeared. Under SuSE linux 9.1 with a 2.6.5-7.95 kernel, the /proc file system can have different objects with the same i-number! Ouch! The native driver assumed such a thing would *never* happen. It does not make this assumption anymore. Index: fs_native.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/drivers/native/fs_native.c,v retrieving revision 1.41 retrieving revision 1.42 diff -u -w -b -B -p -r1.41 -r1.42 --- fs_native.c 21 Jul 2004 21:22:23 -0000 1.41 +++ fs_native.c 23 Jul 2004 15:11:57 -0000 1.42 @@ -210,7 +210,7 @@ struct native_inode { int ni_oflags; /* flags, from open */ unsigned ni_nopens; /* soft ref count */ _SYSIO_OFF_T ni_fpos; /* current pos */ - struct __native_stat *ni_stat; /* cached copy of the stat */ + struct intnl_stat ni_stat; /* cached attrs */ }; /* @@ -329,15 +329,25 @@ static struct mount *native_internal_mou * stat -- by path. */ static int -native_stat(const char *path, struct intnl_stat *buf, struct __native_stat *stbuf) +native_stat(const char *path, struct native_inode *nino, struct intnl_stat *buf) { int err; + struct __native_stat stbuf; - err = syscall(__SYS_STAT, path, stbuf); - if (err) + err = syscall(__SYS_STAT, path, &stbuf); + if (err) { err = -errno; - COPY_STAT(stbuf, buf); + goto out; + } + if (!nino) { + COPY_STAT(&stbuf, buf); + goto out; + } + COPY_STAT(&stbuf, &nino->ni_stat); + if (&nino->ni_stat != buf) + (void )memcpy(buf, &nino->ni_stat, sizeof(struct intnl_stat)); +out: return err; } @@ -345,15 +355,25 @@ native_stat(const char *path, struct int * stat -- by fildes */ static int -native_fstat(int fd, struct intnl_stat *buf, struct __native_stat *stbuf) +native_fstat(int fd, struct native_inode *nino, struct intnl_stat *buf) { int err; + struct __native_stat stbuf; - err = syscall(__SYS_FSTAT, fd, stbuf); - if (err) + err = syscall(__SYS_FSTAT, fd, &stbuf); + if (err) { err = -errno; - COPY_STAT(stbuf, buf); + goto out; + } + if (!nino) { + COPY_STAT(&stbuf, buf); + goto out; + } + COPY_STAT(&stbuf, &nino->ni_stat); + if (&nino->ni_stat != buf) + (void )memcpy(buf, &nino->ni_stat, sizeof(struct intnl_stat)); +out: return err; } @@ -381,7 +401,7 @@ native_i_new(struct filesys *fs, struct nino->ni_oflags = 0; nino->ni_nopens = 0; nino->ni_fpos = 0; - nino->ni_stat = NULL; + (void )memcpy(&nino->ni_stat, buf, sizeof(struct intnl_stat)); ino = _sysio_i_new(fs, &nino->ni_fileid, @@ -429,8 +449,6 @@ create_internal_namespace() static struct qstr noname = { NULL, 0, 0 }; struct filesys *fs; struct intnl_stat stbuf; - struct __native_stat *ni_stat; - if (native_internal_mount) { /* @@ -439,8 +457,6 @@ create_internal_namespace() abort(); } - ni_stat = (struct __native_stat *)malloc(sizeof(struct __native_stat)); - /* * We maintain an artificial, internal, name space in order to * have access to fully qualified path names in the various routines. @@ -458,7 +474,7 @@ create_internal_namespace() /* * Get root i-node. */ - err = native_stat("/", &stbuf, ni_stat); + err = native_stat("/", NULL, &stbuf); if (err) goto error; rootino = native_i_new(fs, &stbuf); @@ -466,7 +482,6 @@ create_internal_namespace() err = -ENOMEM; goto error; } - I2NI(rootino)->ni_stat = ni_stat; /* * Generate base path-node for root. @@ -598,14 +613,11 @@ native_iget(struct filesys *fs, struct intnl_stat stbuf; struct native_inode_identifier ident; struct file_identifier fileid; - struct __native_stat *ni_stat; - - ni_stat = (struct __native_stat *)malloc(sizeof(struct __native_stat)); /* * Get file status. */ - err = native_stat(path, &stbuf, ni_stat); + err = native_stat(path, *inop ? I2NI(*inop) : NULL, &stbuf); if (err) { *inop = NULL; return err; @@ -635,9 +647,10 @@ native_iget(struct filesys *fs, fileid.fid_data = &ident; fileid.fid_len = sizeof(ident); ino = _sysio_i_find(fs, &fileid); - if (ino && forced) { + if (ino && + (forced || (ino->i_mode & S_IFMT) != (stbuf.st_mode & S_IFMT))) { /* - * Insertion was forced but it's already present! + * Insertion was forced or dup inum but it's already present! */ if (native_i_invalid(ino, stbuf)) { /* @@ -661,7 +674,6 @@ native_iget(struct filesys *fs, out: if (!err) *inop = ino; - I2NI(ino)->ni_stat = ni_stat; return err; } @@ -719,34 +731,35 @@ native_inop_lookup(struct pnode *pno, } static int -native_inop_getattr(struct pnode *pno, struct inode *ino, struct intnl_stat *stbuf) +native_inop_getattr(struct pnode *pno, + struct inode *ino, + struct intnl_stat *stbuf) { char *path; + struct native_inode *nino; int err; - struct __native_stat *ni_stat; - path = NULL; - ni_stat = (struct __native_stat *)malloc(sizeof(struct __native_stat)); - if (!ino || I2NI(ino)->ni_fd < 0) { - if (pno) + nino = ino ? I2NI(ino) : NULL; + err = 0; /* compiler cookie */ + if (!ino) { path = _sysio_pb_path(pno->p_base, '/'); - else if (ino) { - COPY_STAT(I2NI(ino)->ni_stat, stbuf); - return 0; - } if (!path) return -ENOMEM; - /* if no pno, copy stat and return success */ - } - err = - path - ? native_stat(path, stbuf, ni_stat) - : native_fstat(I2NI(ino)->ni_fd, stbuf, ni_stat); - if (path) + err = native_stat(path, nino, stbuf); free(path); - - /* Cache a copy of the stat */ - I2NI(ino)->ni_stat = ni_stat; + } else if (nino->ni_fd >= 0) + err = native_fstat(nino->ni_fd, nino, stbuf); + else { + /* + * Dev inodes don't open in this driver. We won't have + * a file descriptor with which to do the deed then. Satisfy + * the request from the cached copy of the attributes. + */ + (void )memcpy(stbuf, + &nino->ni_stat, + sizeof(struct intnl_stat)); + err = 0; + } return err; } @@ -758,13 +771,19 @@ native_inop_setattr(struct pnode *pno, struct intnl_stat *stbuf) { char *path; + struct native_inode *nino; int fd; - struct intnl_stat st; - struct __native_stat *ni_stat; + struct intnl_stat *stbp, _stbuf; int err; path = NULL; - fd = ino ? I2NI(ino)->ni_fd : -1; + nino = ino ? I2NI(ino) : NULL; + fd = -1; + stbp = &_stbuf; + if (nino) { + fd = nino->ni_fd; + stbp = &nino->ni_stat; + } if (fd < 0 || mask & (SETATTR_MTIME|SETATTR_ATIME)) { if (!pno) return -EEXIST; @@ -776,14 +795,10 @@ native_inop_setattr(struct pnode *pno, /* * Get current status for undo. */ - ni_stat = (struct __native_stat *)malloc(sizeof(struct __native_stat)); err = fd < 0 - ? native_stat(path, &st, ni_stat) - : native_fstat(fd, &st, ni_stat); - if (ino) - I2NI(ino)->ni_stat = ni_stat; - + ? native_stat(path, nino, stbp) + : native_fstat(fd, nino, stbp); if (err) goto out; @@ -809,8 +824,8 @@ native_inop_setattr(struct pnode *pno, /* * Alter access and/or modify time attributes. */ - ut.actime = st.st_atime; - ut.modtime = st.st_mtime; + ut.actime = stbuf->st_atime; + ut.modtime = stbuf->st_mtime; if (mask & SETATTR_MTIME) ut.modtime = stbuf->st_mtime; if (mask & SETATTR_ATIME) @@ -868,33 +883,40 @@ native_inop_setattr(struct pnode *pno, ? syscall(SYS_chown, path, mask & SETATTR_UID - ? st.st_uid + ? stbp->st_uid : (uid_t )-1, mask & SETATTR_GID - ? st.st_gid + ? stbp->st_gid : (gid_t )-1) : syscall(SYS_fchown, fd, mask & SETATTR_UID - ? st.st_uid + ? stbp->st_uid : (uid_t )-1, mask & SETATTR_GID - ? st.st_gid + ? stbp->st_gid : (gid_t )-1)); } if (mask & (SETATTR_MTIME|SETATTR_ATIME)) { struct utimbuf ut; - ut.actime = st.st_atime; - ut.modtime = st.st_mtime; + ut.actime = stbp->st_atime; + ut.modtime = stbp->st_mtime; (void )syscall(__SYS_UTIME, path, &ut); } if (mask & SETATTR_MODE) { fd < 0 - ? syscall(SYS_chmod, path, st.st_mode & 07777) - : syscall(SYS_fchmod, fd, st.st_mode & 07777); + ? syscall(SYS_chmod, path, stbp->st_mode & 07777) + : syscall(SYS_fchmod, stbp->st_mode & 07777); } out: + /* + * We must refresh the cached attributes on success. + */ + if (!err && (fd < 0 + ? native_stat(path, nino, stbp) + : native_fstat(fd, nino, stbp)) != 0) + abort(); if (path) free(path); return err; @@ -1738,9 +1760,6 @@ native_inop_gone(struct inode *ino) if (nino->ni_fd >= 0) (void )syscall(SYS_close, nino->ni_fd); - if (nino->ni_stat) - free(nino->ni_stat); - free(ino->i_private); } |