davem@bmers58.UUCP (Dave Mielke) (09/01/89)
How can I get stat information for an i-node? I would like to avoid the need to have a directory scanned for a name if I already know the file number.
chris@mimsy.UUCP (Chris Torek) (09/01/89)
In article <172@bmers58.UUCP> davem@bmers58.UUCP (Dave Mielke) writes: >How can I get stat information for an i-node? I would like to avoid the >need to have a directory scanned for a name if I already know the file >number. Then open the disk and read the on-disk copy of the inode. fstat() is a very cheap operation. stat() is a bit more expensive, but (with name cacheing) not all that bad. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
davem@bmers58.UUCP (Dave Mielke) (09/02/89)
In article <19362@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: >fstat() is a very cheap operation. stat() is a bit more expensive, but >(with name cacheing) not all that bad. The problem with fstat is that it requires an open which also does a name lookup. This proves to be very slow when the directories get large. I need a way to get the information that stat would return without the expense of a name lookup. The i-node is the obvious key to the data, but I am unaware of any primitive that gives an application program direct access to the data via its actual key. I would appreciate any assistence that anyone can offer.
chris@mimsy.UUCP (Chris Torek) (09/02/89)
>In article <19362@mimsy.UUCP> I suggested: >>fstat() is a very cheap operation. stat() is a bit more expensive, but >>(with name cacheing) not all that bad. In article <179@bmers58.UUCP> davem@bmers58.UUCP (Dave Mielke) writes: >The problem with fstat is that it requires an open which also does a >name lookup. This proves to be very slow when the directories get >large. I need a way to get the information that stat would return >without the expense of a name lookup. The i-node is the obvious key to >the data, but I am unaware of any primitive that gives an application >program direct access to the data via its actual key. I would >appreciate any assistence that anyone can offer. Okay, here it is (but you have to be root, and it does not work across NFS). Note that you would have to be root to use any `new' system call that gives information by <dev,ino> pairs anyway, because otherwise you could bypass system security. (Find an unreadable directory? Want to know what is in it? Guess what inodes are there, and look them up by number. This gives incomplete information, but it gives more than you get now.) Given the <dev_t dev, ino_t ino> pair, we want to find the inode on the disk device. Use the block device if you want to cooperate with the buffer cache, or the raw device if you do not. (Define RAW, or not, as appropriate.) /* NB: this code is untested */ #include <stdio.h> #include <sys/param.h> #ifdef NFS #include <sys/vfs.h> #include <sys/vnode.h> #include <ufs/fs.h> #include <ufs/inode.h> #else #include <sys/fs.h> #include <sys/inode.h> #endif /* * Given a dev_t value, open the corresponding block (or raw) device * by searching mtab and trying devices. */ int get_dev(dev) dev_t dev; { FILE *fp; register char *p1; #ifdef NFS char *p2; #endif int fd; struct stat st; char buf[BUFSIZ]; /* /etc/mtab changes, so just use the mount program */ fp = popen("mount", "r"); /* /etc/mount or /sbin/mount */ if (fp == NULL) return (-1); while (fgets(buf, sizeof buf, fp) != NULL) { #ifdef RAW if (strncmp(buf, "/dev/", 5) != 0) continue; /* strange line from mount */ #endif p1 = strchr(buf, ' '); if (p1 == NULL) break; if (strncmp(p1 + 1, " on ", 4) != 0) continue; /* strange line from mount */ #ifdef NFS p2 = strchr(buf, ':'); if (p2 != NULL && p2 < p1) continue; /* must be an NFS mount */ #endif *p1 = 0; /* buf now `/dev/ra0d', eg */ if ((fd = open(buf, 0)) < 0) continue; if (fstat(fd, &st)) panic("fstat fails"); if (st.st_dev == dev) { #ifdef RAW (void) close(fd); (void) sprintf(p1 + 1, "/dev/r%s", buf + 5); fd = open(p1 + 1, 0); #endif return (fd); } } (void) fclose(fp); return (-1); } /* * Given a <dev,ino> pair, find the inode. Store it through *dip. * Return -1 if not found, 0 if found. * * This version is BSD-specific. */ get_inode(dev, ino, dip) dev_t dev; ino_t ino; struct dinode *dip; { static int fd = -1; static dev_t lastdev; static long lastoff; long off; static char buf[DEV_BSIZE]; static union { struct fs usb; char ubuf[SBSIZE]; } u; #define sblock u.usb if (fd < 0 || dev != lastdev) { fd = get_dev(dev); if (fd < 0) return (-1); lastdev = dev; (void) lseek(fd, (long)BBSIZE, 0); if (read(fd, (char *)&sblock, SBSIZE) != SBSIZE || sblock.fs_magic != FS_MAGIC) { (void) close(fd); fd = -1; return (-1); } lastoff = 0; /* safe, because this is boot block */ } off = (long)fsbtodb(&sblock, itod(&sblock, ino)) * DEV_BSIZE; if (off != lastoff) { (void) lseek(fd, off, 0); if (read(fd, buf, sizeof buf) != sizeof buf) { lastoff = 0; return (-1); } lastoff = off; } *dip = ((struct dinode *)buf)[itoo(&sblock, ino)]; return (0); /* got it at last */ } /* For V7 file systems, such as those in SysV, the above is simpler, because the inodes are at a fixed offset, so the `itod'/`itoo' reduces to a single computation to find the inode offset. This should then be converted to a 512-byte block, and the inode fished out as above (except that itoo becomes a relatively simple `%'). */ -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
cpcahil@virtech.UUCP (Conor P. Cahill) (09/02/89)
In article <179@bmers58.UUCP>, davem@bmers58.UUCP (Dave Mielke) writes: > The problem with fstat is that it requires an open which also does a > name lookup. This proves to be very slow when the directories get > large. I need a way to get the information that stat would return > without the expense of a name lookup. The i-node is the obvious key to > the data, but I am unaware of any primitive that gives an application > program direct access to the data via its actual key. I would > appreciate any assistence that anyone can offer. There is no system call primitive that gives you the capability to access a file based upon it's inode number. In fact one of the *true* blessings of UNIX is it's concept of accessing everyting (including devices) through the same namespace. (Of course they broke this with the system V IPC implementations) If your problem is that it is taking too long to search a really big directory, you probably should change the software that is maintaining that directory so that it uses some sub-directories. I worked on a project that had the same problem with mail message attachments. These attachments were put into a single attachment directory on the system. Over time, this directory would grow to have thousands of entries which caused access time to be outragously high. The solution was to change the software to use a series of sub-directories (100 of them) which resulted in a significant performace gain. message attachments -- +-----------------------------------------------------------------------+ | Conor P. Cahill uunet!virtech!cpcahil 703-430-9247 ! | Virtual Technologies Inc., P. O. Box 876, Sterling, VA 22170 | +-----------------------------------------------------------------------+
mike@thor.acc.stolaf.edu (Mike Haertel) (09/03/89)
In article <179@bmers58.UUCP> davem@bmers58.UUCP (Dave Mielke) writes: >In article <19362@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: >>fstat() is a very cheap operation. stat() is a bit more expensive, but >>(with name cacheing) not all that bad. >The problem with fstat is that it requires an open which also does a >name lookup. This proves to be very slow when the directories get >large. I need a way to get the information that stat would return >without the expense of a name lookup. stat() in a simple file name in the current directory ought to be pretty fast. in 4.3BSD if you stat() the files of a directory in sequence of the actual directory entries, the kernel remembers where the previous search left off and does even better. -- Mike Haertel <mike@stolaf.edu> ``There's nothing remarkable about it. All one has to do is hit the right keys at the right time and the instrument plays itself.'' -- J. S. Bach
jbm@eos.UUCP (Jeffrey Mulligan) (09/06/89)
davem@bmers58.UUCP (Dave Mielke) writes:
+The problem with fstat is that it requires an open which also does a
+name lookup. This proves to be very slow when the directories get
+large. I need a way to get the information that stat would return
+without the expense of a name lookup. The i-node is the obvious key to
^ i-node number?
+the data, but I am unaware of any primitive that gives an application
+program direct access to the data via its actual key. I would
+appreciate any assistence that anyone can offer.
Well, if you can live with the security holes generated by having
your program run setuid root (or worse still, making /dev/disk readable),
you can just seek and read on the raw file system. See filsys(5).
--
Jeff Mulligan (jbm@aurora.arc.nasa.gov)
NASA/Ames Research Ctr., Mail Stop 239-3, Moffet Field CA, 94035
(415) 694-3745