home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / kernel-s / v1.1 / kdiffs-1.002 / kdiffs-1.1.58-quota+acct
Text File  |  1994-10-28  |  92KB  |  3,012 lines

  1. diff -ru --new-file linux_1.1.58/arch/i386/config.in linux_1.1.58_owld/arch/i386/config.in
  2. --- linux_1.1.58/arch/i386/config.in    Sun Oct 16 00:26:27 1994
  3. +++ linux_1.1.58_owld/arch/i386/config.in    Wed Oct 26 21:02:12 1994
  4. @@ -162,6 +162,7 @@
  5.  bool 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS n
  6.  bool 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS n
  7.  bool 'System V and Coherent filesystem support' CONFIG_SYSV_FS n
  8. +bool 'Disk QUOTA support' CONFIG_QUOTA y
  9.  
  10.  comment 'character devices'
  11.  
  12. diff -ru --new-file linux_1.1.58/fs/Makefile linux_1.1.58_owld/fs/Makefile
  13. --- linux_1.1.58/fs/Makefile    Sun Oct 16 00:26:31 1994
  14. +++ linux_1.1.58_owld/fs/Makefile    Sun Oct 16 00:28:21 1994
  15. @@ -56,9 +56,9 @@
  16.  .s.o:
  17.      $(AS) -o $*.o $<
  18.  
  19. -OBJS=    open.o read_write.o inode.o devices.o file_table.o buffer.o super.o \
  20. -    block_dev.o stat.o exec.o pipe.o namei.o fcntl.o ioctl.o \
  21. -    select.o fifo.o locks.o filesystems.o dcache.o $(BINFMTS)
  22. +OBJS=    open.o read_write.o inode.o devices.o file_table.o fileio.o buffer.o \
  23. +    super.o block_dev.o stat.o exec.o pipe.o namei.o fcntl.o ioctl.o \
  24. +    select.o fifo.o locks.o dcache.o dquot.o filesystems.o $(BINFMTS)
  25.  
  26.  all: fs.o filesystems.a modules
  27.  
  28. diff -ru --new-file linux_1.1.58/fs/binfmt_elf.c linux_1.1.58_owld/fs/binfmt_elf.c
  29. --- linux_1.1.58/fs/binfmt_elf.c    Fri Oct 21 09:57:32 1994
  30. +++ linux_1.1.58_owld/fs/binfmt_elf.c    Fri Oct 21 09:57:56 1994
  31. @@ -497,6 +497,8 @@
  32.      current->mm->end_code = 0;
  33.      current->mm->start_mmap = ELF_START_MMAP;
  34.      current->mm->mmap = NULL;
  35. +    current->flags &= ~PF_FORKNOEXEC; /* accounting flags */
  36. +        current->io_usage = 0;
  37.      elf_entry = (unsigned int) elf_ex.e_entry;
  38.      
  39.      /* Do this so that we can load the interpreter, if need be.  We will
  40. diff -ru --new-file linux_1.1.58/fs/buffer.c linux_1.1.58_owld/fs/buffer.c
  41. --- linux_1.1.58/fs/buffer.c    Mon Oct 24 19:56:07 1994
  42. +++ linux_1.1.58_owld/fs/buffer.c    Mon Oct 24 20:01:48 1994
  43. @@ -217,6 +217,9 @@
  44.      sync_supers(dev);
  45.      sync_inodes(dev);
  46.      sync_buffers(dev, 0);
  47. +#ifdef CONFIG_QUOTA
  48. +    sync_dquots(dev, -1);
  49. +#endif
  50.  }
  51.  
  52.  int fsync_dev(dev_t dev)
  53. @@ -224,6 +227,9 @@
  54.      sync_buffers(dev, 0);
  55.      sync_supers(dev);
  56.      sync_inodes(dev);
  57. +#ifdef CONFIG_QUOTA
  58. +    sync_dquots(dev, -1);
  59. +#endif
  60.      return sync_buffers(dev, 1);
  61.  }
  62.  
  63. diff -ru --new-file linux_1.1.58/fs/dquot.c linux_1.1.58_owld/fs/dquot.c
  64. --- linux_1.1.58/fs/dquot.c    Thu Jan  1 01:00:00 1970
  65. +++ linux_1.1.58_owld/fs/dquot.c    Thu Oct 27 12:40:28 1994
  66. @@ -0,0 +1,1007 @@
  67. +/*
  68. + * QUOTA    An implementation of the diskquota system for the LINUX operating
  69. + *          system. QUOTA is implemented using the BSD systemcall interface as
  70. + *          the means of communication with the user level. Should work for all
  71. + *          filesystems because of integration into the VFS layer of the
  72. + *          operating system. This is based on the Melbourne quota system wich
  73. + *          uses both user and group quota files.
  74. + * 
  75. + *          Main layer of quota management
  76. + * 
  77. + * Version: $Id: dquot.c,v 3.11 1994/10/17 09:52:47 mvw Exp mvw $
  78. + * 
  79. + * Authors: Marco van Wieringen <v892273@si.hhs.nl> <mvw@mcs.ow.org>
  80. + *          Edvard Tuinder <v892231@si.hhs.nl> <ed@delirium.ow.org>
  81. + *          Linus Torvalds <Linus.Torvalds@cc.helsinki.FI>
  82. + * 
  83. + *          This program is free software; you can redistribute it and/or
  84. + *          modify it under the terms of the GNU General Public License as
  85. + *          published by the Free Software Foundation; either version 2 of the
  86. + *          License, or (at your option) any later version.
  87. + */
  88. +
  89. +#include <linux/errno.h>
  90. +#include <linux/kernel.h>
  91. +#include <linux/sched.h>
  92. +#include <linux/config.h>
  93. +
  94. +#ifdef CONFIG_QUOTA
  95. +#include <linux/types.h>
  96. +#include <linux/string.h>
  97. +#include <linux/fcntl.h>
  98. +#include <linux/stat.h>
  99. +#include <linux/segment.h>
  100. +#include <linux/tty.h>
  101. +#include <linux/malloc.h>
  102. +#include <linux/mount.h>
  103. +#include <linux/fileio.h>
  104. +
  105. +#include <asm/segment.h>
  106. +#include <sys/sysmacros.h>
  107. +
  108. +static char quotamessage[MAX_QUOTA_MESSAGE];
  109. +static char *quotatypes[] = INITQFNAMES;
  110. +
  111. +static int nr_dquots = 0, nr_free_dquots = 0;
  112. +static struct dquot *hash_table[NR_DQHASH];
  113. +static struct dquot *first_dquot;
  114. +
  115. +static struct wait_queue *dquot_wait = (struct wait_queue *)NULL;
  116. +
  117. +extern void add_dquot_ref(dev_t dev, short type);
  118. +extern void reset_dquot_ptrs(dev_t dev, short type);
  119. +extern void close_fp(struct file *filp, int fd);
  120. +
  121. +#ifndef min
  122. +#define min(a,b) ((a) < (b)) ? (a) : (b)
  123. +#endif
  124. +
  125. +/*
  126. + * Functions for management of the hashlist.
  127. + */
  128. +static inline int const hashfn(dev_t dev, unsigned int id, short type)
  129. +{
  130. +   return ((dev ^ id) * (MAXQUOTAS - type)) % NR_DQHASH;
  131. +}
  132. +
  133. +static inline struct dquot **const hash(dev_t dev, unsigned int id, short type)
  134. +{
  135. +   return hash_table + hashfn(dev, id, type);
  136. +}
  137. +
  138. +static void insert_dquot_free(struct dquot *dquot)
  139. +{
  140. +   dquot->dq_next = first_dquot;
  141. +   dquot->dq_prev = first_dquot->dq_prev;
  142. +   dquot->dq_next->dq_prev = dquot;
  143. +   dquot->dq_prev->dq_next = dquot;
  144. +   first_dquot = dquot;
  145. +}
  146. +
  147. +static void remove_dquot_free(struct dquot *dquot)
  148. +{
  149. +   if (first_dquot == dquot)
  150. +      first_dquot = first_dquot->dq_next;
  151. +   if (dquot->dq_next)
  152. +      dquot->dq_next->dq_prev = dquot->dq_prev;
  153. +   if (dquot->dq_prev)
  154. +      dquot->dq_prev->dq_next = dquot->dq_next;
  155. +   dquot->dq_next = dquot->dq_prev = NODQUOT;
  156. +}
  157. +
  158. +static void insert_dquot_hash(struct dquot *dquot)
  159. +{
  160. +   struct dquot **h;
  161. +
  162. +   h = hash(dquot->dq_dev, dquot->dq_id, dquot->dq_type);
  163. +   dquot->dq_hash_next = *h;
  164. +   dquot->dq_hash_prev = NODQUOT;
  165. +   if (dquot->dq_hash_next)
  166. +      dquot->dq_hash_next->dq_hash_prev = dquot;
  167. +   *h = dquot;
  168. +}
  169. +
  170. +static void remove_dquot_hash(struct dquot *dquot)
  171. +{
  172. +   struct dquot **h;
  173. +
  174. +   h = hash(dquot->dq_dev, dquot->dq_id, dquot->dq_type);
  175. +   if (*h == dquot)
  176. +      *h = dquot->dq_hash_next;
  177. +   if (dquot->dq_hash_next)
  178. +      dquot->dq_hash_next->dq_hash_prev = dquot->dq_hash_prev;
  179. +   if (dquot->dq_hash_prev)
  180. +      dquot->dq_hash_prev->dq_hash_next = dquot->dq_hash_next;
  181. +   dquot->dq_hash_prev = dquot->dq_hash_next = NODQUOT;
  182. +}
  183. +
  184. +static void put_last_free(struct dquot *dquot)
  185. +{
  186. +   remove_dquot_free(dquot);
  187. +   dquot->dq_prev = first_dquot->dq_prev;
  188. +   dquot->dq_prev->dq_next = dquot;
  189. +   dquot->dq_next = first_dquot;
  190. +   dquot->dq_next->dq_prev = dquot;
  191. +}
  192. +
  193. +static void grow_dquots(void)
  194. +{
  195. +   struct dquot *dquot;
  196. +   int i;
  197. +
  198. +   if (!(dquot = (struct dquot*) get_free_page(GFP_KERNEL)))
  199. +      return;
  200. +   i = PAGE_SIZE / sizeof(struct dquot);
  201. +   nr_dquots += i;
  202. +   nr_free_dquots += i;
  203. +   if (!first_dquot)
  204. +      dquot->dq_next = dquot->dq_prev = first_dquot = dquot++, i--;
  205. +   for ( ; i ; i-- )
  206. +      insert_dquot_free(dquot++);
  207. +}
  208. +
  209. +/*
  210. + * Functions for locking and waiting on dquots.
  211. + */
  212. +static void __wait_on_dquot(struct dquot *dquot)
  213. +{
  214. +   struct wait_queue wait = {current, NULL};
  215. +
  216. +   add_wait_queue(&dquot->dq_wait, &wait);
  217. +repeat:
  218. +   current->state = TASK_UNINTERRUPTIBLE;
  219. +   if (dquot->dq_flags & DQ_LOCKED) {
  220. +      dquot->dq_flags |= DQ_WANT;
  221. +      schedule();
  222. +      goto repeat;
  223. +   }
  224. +   remove_wait_queue(&dquot->dq_wait, &wait);
  225. +   current->state = TASK_RUNNING;
  226. +}
  227. +
  228. +static inline void wait_on_dquot(struct dquot *dquot)
  229. +{
  230. +   if (dquot->dq_flags & DQ_LOCKED)
  231. +      __wait_on_dquot(dquot);
  232. +}
  233. +
  234. +static inline void lock_dquot(struct dquot *dquot)
  235. +{
  236. +   wait_on_dquot(dquot);
  237. +   dquot->dq_flags |= DQ_LOCKED;
  238. +}
  239. +
  240. +static inline void unlock_dquot(struct dquot *dquot)
  241. +{
  242. +   dquot->dq_flags &= ~DQ_LOCKED;
  243. +   if (dquot->dq_flags & DQ_WANT) {
  244. +      dquot->dq_flags &= ~DQ_WANT;
  245. +      wake_up(&dquot->dq_wait);
  246. +   }
  247. +}
  248. +/*
  249. + * Note that we don't want to disturb any wait-queues when we discard
  250. + * an dquot.
  251. + *
  252. + * FIXME: As soon as we have a nice solution for the inode problem we
  253. + *        can also fix this one. I.e. the volatile part.
  254. + */
  255. +static void clear_dquot(struct dquot * dquot)
  256. +{
  257. +   struct wait_queue *wait;
  258. +
  259. +   wait_on_dquot(dquot);
  260. +   remove_dquot_hash(dquot);
  261. +   remove_dquot_free(dquot);
  262. +   wait = ((volatile struct dquot *) dquot)->dq_wait;
  263. +   if (dquot->dq_count)
  264. +      nr_free_dquots++;
  265. +   memset(dquot, 0, sizeof(*dquot));
  266. +   ((volatile struct dquot *) dquot)->dq_wait = wait;
  267. +   insert_dquot_free(dquot);
  268. +}
  269. +
  270. +static void write_dquot(struct dquot *dquot)
  271. +{
  272. +   short type = dquot->dq_type;
  273. +   struct file *filp = dquot->dq_mnt->mnt_quotas[type];
  274. +   unsigned short fs;
  275. +
  276. +   if (!(dquot->dq_flags & DQ_MOD) || (filp == (struct file *)0))
  277. +      return;
  278. +   lock_dquot(dquot);
  279. +   down(&dquot->dq_mnt->mnt_sem);
  280. +   if (filp->f_op->lseek) {
  281. +      if (filp->f_op->lseek(filp->f_inode, filp,
  282. +          dqoff(dquot->dq_id), 0) != dqoff(dquot->dq_id)) {
  283. +         up(&dquot->dq_mnt->mnt_sem);
  284. +         return;
  285. +      }
  286. +   } else
  287. +      filp->f_pos = dqoff(dquot->dq_id);
  288. +   fs = get_fs();
  289. +   set_fs(KERNEL_DS);
  290. +   if (filp->f_op->write(filp->f_inode, filp,
  291. +       (char *)&dquot->dq_dqb, sizeof(struct dqblk)) == sizeof(struct dqblk))
  292. +      dquot->dq_flags &= ~DQ_MOD;
  293. +   up(&dquot->dq_mnt->mnt_sem);
  294. +   set_fs(fs);
  295. +   unlock_dquot(dquot);
  296. +}
  297. +
  298. +static void read_dquot(struct dquot *dquot)
  299. +{
  300. +   short type = dquot->dq_type;
  301. +   struct file *filp = dquot->dq_mnt->mnt_quotas[type];
  302. +   unsigned short fs;
  303. +
  304. +   if (filp == (struct file *)0)
  305. +      return;
  306. +   lock_dquot(dquot);
  307. +   down(&dquot->dq_mnt->mnt_sem);
  308. +   if (filp->f_op->lseek) {
  309. +      if (filp->f_op->lseek(filp->f_inode, filp,
  310. +          dqoff(dquot->dq_id),0) != dqoff(dquot->dq_id)) {
  311. +         up(&dquot->dq_mnt->mnt_sem);
  312. +         return;
  313. +      }
  314. +   } else
  315. +      filp->f_pos = dqoff(dquot->dq_id);
  316. +   fs = get_fs();
  317. +   set_fs(KERNEL_DS);
  318. +   filp->f_op->read(filp->f_inode, filp,
  319. +                    (char *)&dquot->dq_dqb, sizeof(struct dqblk));
  320. +   up(&dquot->dq_mnt->mnt_sem);
  321. +   set_fs(fs);
  322. +   if (dquot->dq_bhardlimit == 0 && dquot->dq_bsoftlimit == 0 &&
  323. +       dquot->dq_ihardlimit == 0 && dquot->dq_isoftlimit == 0)
  324. +      dquot->dq_flags |= DQ_FAKE;
  325. +   unlock_dquot(dquot);
  326. +}
  327. +
  328. +int sync_dquots(dev_t dev, short type)
  329. +{
  330. +   struct dquot *dquot = first_dquot;
  331. +   int i;
  332. +
  333. +   for(i = 0; i < nr_dquots * 2; i++, dquot = dquot->dq_next) {
  334. +      if (!dquot->dq_count || (dev && dquot->dq_dev != dev))
  335. +         continue;
  336. +      if (type != -1 && dquot->dq_type != type)
  337. +         continue;
  338. +      wait_on_dquot(dquot);
  339. +      if (dquot->dq_flags & DQ_MOD)
  340. +         write_dquot(dquot);
  341. +   }
  342. +   return 0;
  343. +   /* NOTREACHED */
  344. +}
  345. +
  346. +/*
  347. + * Trash the cache for a certain type on a device.
  348. + */
  349. +void invalidate_dquots(dev_t dev, short type)
  350. +{
  351. +   struct dquot *dquot, *next;
  352. +   int i;
  353. +
  354. +   next = first_dquot;
  355. +   for(i = nr_dquots ; i > 0 ; i--) {
  356. +      dquot = next;
  357. +      next = dquot->dq_next;
  358. +      if (dquot->dq_dev != dev || dquot->dq_type != type)
  359. +         continue;
  360. +      if (dquot->dq_flags & DQ_LOCKED) {
  361. +         printk("VFS: dquot busy on removed device %d/%d\n", MAJOR(dev), MINOR(dev));
  362. +         continue;
  363. +      }
  364. +      if (dquot->dq_flags & DQ_MOD)
  365. +         write_dquot(dquot);
  366. +      clear_dquot(dquot);
  367. +   }
  368. +}
  369. +
  370. +/*
  371. + * Check quota for inodes. Returns QUOTA_OK if can allocate and
  372. + * NO_QUOTA if it can't.
  373. + */
  374. +static int check_idq(struct dquot *dquot, int id, short type, u_long wanted_inodes)
  375. +{
  376. +   if (wanted_inodes == 0 || dquot->dq_flags & DQ_FAKE)
  377. +      return QUOTA_OK;
  378. +   if (dquot->dq_ihardlimit &&
  379. +      (dquot->dq_curinodes + wanted_inodes) >= dquot->dq_ihardlimit) {
  380. +      if (!(dquot->dq_flags & DQ_INODES)) {
  381. +         sprintf(quotamessage,
  382. +                "File LIMIT reached on %s for %s %d. !! NO MORE !!\n\r",
  383. +                dquot->dq_mnt->mnt_devname, quotatypes[type], id);
  384. +         tty_write_message(current->tty, quotamessage);
  385. +         dquot->dq_flags |= DQ_INODES;
  386. +      }
  387. +      return NO_QUOTA;
  388. +   }
  389. +   if (dquot->dq_isoftlimit &&
  390. +      (dquot->dq_curinodes + wanted_inodes) >= dquot->dq_isoftlimit &&
  391. +       dquot->dq_itime && CURRENT_TIME >= dquot->dq_itime) {
  392. +      sprintf(quotamessage,
  393. +              "File QUOTA exceeded TOO long on %s for %s %d. !! NO MORE !!\n\r",
  394. +              dquot->dq_mnt->mnt_devname, quotatypes[type], id);
  395. +      tty_write_message(current->tty, quotamessage);
  396. +      return NO_QUOTA;
  397. +   }
  398. +   if (dquot->dq_isoftlimit &&
  399. +      (dquot->dq_curinodes + wanted_inodes) >= dquot->dq_isoftlimit &&
  400. +       dquot->dq_itime == 0) {
  401. +      sprintf(quotamessage,
  402. +              "File QUOTA exceeded on %s for %s %d\n\r",
  403. +              dquot->dq_mnt->mnt_devname, quotatypes[type], id);
  404. +      tty_write_message(current->tty, quotamessage);
  405. +      dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_iexp[type];
  406. +   }
  407. +   return QUOTA_OK;
  408. +   /* NOTREACHED */
  409. +}
  410. +
  411. +/*
  412. + * Check quota for blocks. Returns QUOTA_OK if can allocate and
  413. + * NO_QUOTA if it can't. When we can't allocate wanted_blocks you get
  414. + * the number we can allocate in avail_blocks.
  415. + */
  416. +static int check_bdq(struct dquot *dquot, int id, short type,
  417. +                     u_long wanted_blocks, u_long *avail_blocks)
  418. +{
  419. +   *avail_blocks = wanted_blocks;
  420. +   if (wanted_blocks == 0 || dquot->dq_flags & DQ_FAKE)
  421. +      return QUOTA_OK;
  422. +   if (dquot->dq_bhardlimit &&
  423. +      (dquot->dq_curblocks + wanted_blocks) >= dquot->dq_bhardlimit) {
  424. +      if ((dquot->dq_flags & DQ_BLKS) == 0) {
  425. +         sprintf(quotamessage,
  426. +                 "Block LIMIT reached on %s for %s %d. !! NO MORE !!\n\r",
  427. +                 dquot->dq_mnt->mnt_devname, quotatypes[type], id);
  428. +         tty_write_message(current->tty, quotamessage);
  429. +         dquot->dq_flags |= DQ_BLKS;
  430. +      }
  431. +      if (dquot->dq_curblocks < dquot->dq_bhardlimit) {
  432. +         *avail_blocks = dquot->dq_bhardlimit - dquot->dq_curblocks;
  433. +         return QUOTA_OK;
  434. +      } else
  435. +         return NO_QUOTA;
  436. +   }
  437. +   if (dquot->dq_bsoftlimit &&
  438. +      (dquot->dq_curblocks + wanted_blocks) >= dquot->dq_bsoftlimit &&
  439. +       dquot->dq_btime && CURRENT_TIME >= dquot->dq_btime) {
  440. +      sprintf(quotamessage,
  441. +              "Block QUOTA exceeded TOO long on %s for %s %d. !! NO MORE !!\n\r",
  442. +              dquot->dq_mnt->mnt_devname, quotatypes[type], id);
  443. +      tty_write_message(current->tty, quotamessage);
  444. +      return NO_QUOTA;
  445. +   }
  446. +   if (dquot->dq_bsoftlimit &&
  447. +      (dquot->dq_curblocks + wanted_blocks) >= dquot->dq_bsoftlimit &&
  448. +       dquot->dq_btime == 0) {
  449. +      sprintf(quotamessage,
  450. +              "Block QUOTA exceeded on %s for %s %d\n\r",
  451. +              dquot->dq_mnt->mnt_devname, quotatypes[type], id);
  452. +      tty_write_message(current->tty, quotamessage);
  453. +      dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_bexp[type];
  454. +   }
  455. +   return QUOTA_OK;
  456. +   /* NOTREACHED */
  457. +}
  458. +
  459. +/*
  460. + * Add a number of inodes and blocks to a diskquota.
  461. + */
  462. +static inline void incr_quota(struct dquot *dquot, u_long inodes, u_long blocks)
  463. +{
  464. +   lock_dquot(dquot);
  465. +   dquot->dq_curinodes += inodes;
  466. +   dquot->dq_curblocks += blocks;
  467. +   dquot->dq_flags |= DQ_MOD;
  468. +   unlock_dquot(dquot);
  469. +}
  470. +
  471. +/*
  472. + * Remove a number of inodes and blocks from a quota.
  473. + * Reset gracetimes if under softlimit.
  474. + */
  475. +static inline void decr_quota(struct dquot *dquot, u_long inodes, u_long blocks)
  476. +{
  477. +   lock_dquot(dquot);
  478. +   if (dquot->dq_curinodes >= inodes)
  479. +      dquot->dq_curinodes -= inodes;
  480. +   else
  481. +      dquot->dq_curinodes = 0;
  482. +   if (dquot->dq_curinodes < dquot->dq_isoftlimit)
  483. +      dquot->dq_itime = (time_t) 0;
  484. +   dquot->dq_flags &= ~DQ_INODES;
  485. +   if (dquot->dq_curblocks >= blocks)
  486. +      dquot->dq_curblocks -= blocks;
  487. +   else
  488. +      dquot->dq_curblocks = 0;
  489. +   if (dquot->dq_curblocks < dquot->dq_bsoftlimit)
  490. +      dquot->dq_btime = (time_t) 0;
  491. +   dquot->dq_flags &= ~DQ_BLKS;
  492. +   dquot->dq_flags |= DQ_MOD;
  493. +   unlock_dquot(dquot);
  494. +}
  495. +
  496. +/*
  497. + * Initialize a dquot-struct with new quota info. This is used by the
  498. + * systemcall interface functions.
  499. + */ 
  500. +static int set_dqblk(dev_t dev, int id, short type, int flags, struct dqblk *dqblk)
  501. +{
  502. +   struct dquot *dquot;
  503. +   struct dqblk dq_dqblk;
  504. +   int error;
  505. +
  506. +   if (dqblk == (struct dqblk *)0)
  507. +      return -EFAULT;
  508. +
  509. +   if (flags & QUOTA_SYSCALL) {
  510. +      if ((error = verify_area(VERIFY_READ, dqblk, sizeof(struct dqblk))) != 0)
  511. +         return error;
  512. +      memcpy_fromfs(&dq_dqblk, dqblk, sizeof(struct dqblk));
  513. +   } else {
  514. +      memcpy(&dq_dqblk, dqblk, sizeof(struct dqblk));
  515. +   }
  516. +   if ((dquot = dqget(dev, id, type)) != NODQUOT) {
  517. +      lock_dquot(dquot);
  518. +      if (id > 0 && ((flags & SET_QUOTA) || (flags & SET_QLIMIT))) {
  519. +         dquot->dq_bhardlimit = dq_dqblk.dqb_bhardlimit;
  520. +         dquot->dq_bsoftlimit = dq_dqblk.dqb_bsoftlimit;
  521. +         dquot->dq_ihardlimit = dq_dqblk.dqb_ihardlimit;
  522. +         dquot->dq_isoftlimit = dq_dqblk.dqb_isoftlimit;
  523. +      }
  524. +      if ((flags & SET_QUOTA) || (flags & SET_USE)) {
  525. +         if (dquot->dq_isoftlimit &&
  526. +             dquot->dq_curinodes < dquot->dq_isoftlimit &&
  527. +             dq_dqblk.dqb_curinodes >= dquot->dq_isoftlimit)
  528. +            dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_iexp[type];
  529. +         dquot->dq_curinodes = dq_dqblk.dqb_curinodes;
  530. +         if (dquot->dq_curinodes < dquot->dq_isoftlimit)
  531. +            dquot->dq_flags &= ~DQ_INODES;
  532. +         if (dquot->dq_bsoftlimit &&
  533. +             dquot->dq_curblocks < dquot->dq_bsoftlimit &&
  534. +             dq_dqblk.dqb_curblocks >= dquot->dq_bsoftlimit)
  535. +            dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_bexp[type];
  536. +         dquot->dq_curblocks = dq_dqblk.dqb_curblocks;
  537. +         if (dquot->dq_curblocks < dquot->dq_bsoftlimit)
  538. +            dquot->dq_flags &= ~DQ_BLKS;
  539. +      }
  540. +      if (id == 0) {
  541. +         /* 
  542. +          * Change in expiretimes, change them in dq_mnt.
  543. +          */
  544. +         dquot->dq_mnt->mnt_bexp[type] = dquot->dq_btime = dq_dqblk.dqb_btime;
  545. +         dquot->dq_mnt->mnt_iexp[type] = dquot->dq_itime = dq_dqblk.dqb_itime;
  546. +      }
  547. +      if (dq_dqblk.dqb_bhardlimit == 0 && dq_dqblk.dqb_bsoftlimit == 0 &&
  548. +          dq_dqblk.dqb_ihardlimit == 0 && dq_dqblk.dqb_isoftlimit == 0)
  549. +         dquot->dq_flags |= DQ_FAKE; /* No limits, only usage */
  550. +      dquot->dq_flags |= DQ_MOD;
  551. +      unlock_dquot(dquot);
  552. +      dqput(dquot);
  553. +   }
  554. +   return 0;
  555. +}
  556. +
  557. +static int get_quota(dev_t dev, int id, short type, struct dqblk * dqblk)
  558. +{
  559. +   struct vfsmount *vfsmnt;
  560. +   struct dquot *dquot;
  561. +   int error;
  562. +
  563. +   if ((vfsmnt = lookup_vfsmnt(dev)) != (struct vfsmount *)0 &&
  564. +        vfsmnt->mnt_quotas[type] != (struct file *)0) {
  565. +      if (dqblk == (struct dqblk *) 0)
  566. +         return -EFAULT;
  567. +
  568. +      if ((error = verify_area(VERIFY_WRITE, dqblk, sizeof(struct dqblk))) != 0)
  569. +         return (error);
  570. +
  571. +      if ((dquot = dqget(dev, id, type)) != NODQUOT) {
  572. +         memcpy_tofs(dqblk, (char *)&dquot->dq_dqb, sizeof(struct dqblk));
  573. +         dqput(dquot);
  574. +         return 0;
  575. +      }
  576. +   }
  577. +   return -ESRCH;
  578. +}
  579. +
  580. +/*
  581. + * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
  582. + */
  583. +int quota_off(dev_t dev, short type)
  584. +{
  585. +   struct vfsmount *vfsmnt;
  586. +   short cnt;
  587. +
  588. +   for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  589. +      if (type != -1 && cnt != type)
  590. +         continue;
  591. +      if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)0 ||
  592. +           vfsmnt->mnt_quotas[cnt] == (struct file *)0)
  593. +         continue;
  594. +      vfsmnt->mnt_flags |= QF_CLOSING;
  595. +      reset_dquot_ptrs(dev, cnt);
  596. +      invalidate_dquots(dev, cnt);
  597. +      close_fp(vfsmnt->mnt_quotas[cnt], 0);
  598. +      vfsmnt->mnt_quotas[cnt] = (struct file *)0;
  599. +      vfsmnt->mnt_iexp[cnt] = vfsmnt->mnt_bexp[cnt] = (time_t)0;
  600. +      vfsmnt->mnt_flags &= ~QF_CLOSING;
  601. +   }
  602. +   return 0;
  603. +}
  604. +
  605. +static int quota_on(dev_t dev, short type, char *path)
  606. +{
  607. +   struct file *filp = (struct file *)0;
  608. +   struct vfsmount *vfsmnt;
  609. +   struct inode *inode;
  610. +   struct dquot *dquot;
  611. +   char *tmp;
  612. +   int error;
  613. +
  614. +   if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)0)
  615. +      return -ENODEV;
  616. +   if (vfsmnt->mnt_quotas[type] != (struct file *)0)
  617. +      return -EBUSY;
  618. +   if ((error = getname(path, &tmp)) != 0)
  619. +      return (error);
  620. +   vfsmnt->mnt_flags |= QF_OPENING;
  621. +   error = open_namei(tmp, O_RDWR, 0600, &inode, 0);
  622. +   putname(tmp);
  623. +   if (error) {
  624. +      vfsmnt->mnt_flags &= ~QF_OPENING;
  625. +      return (error);
  626. +   }
  627. +   if (!S_ISREG(inode->i_mode)) {
  628. +      vfsmnt->mnt_flags &= ~QF_OPENING;
  629. +      iput(inode);
  630. +      return -EACCES;
  631. +   }
  632. +   if (!inode->i_op || !inode->i_op->default_file_ops)
  633. +      goto end_quotaon;
  634. +   if ((filp = get_empty_filp()) == (struct file *)0)
  635. +      goto end_quotaon;
  636. +   filp->f_mode = (O_RDWR + 1) & O_ACCMODE;
  637. +   filp->f_flags = O_RDWR;
  638. +   filp->f_inode = inode;
  639. +   filp->f_pos = 0;
  640. +   filp->f_reada = 0;
  641. +   filp->f_op = inode->i_op->default_file_ops;
  642. +   if (filp->f_op->open)
  643. +      if (filp->f_op->open(filp->f_inode, filp))
  644. +         goto end_quotaon;
  645. +   if (!filp->f_op->read || !filp->f_op->write)
  646. +      goto end_quotaon;
  647. +   vfsmnt->mnt_quotas[type] = filp;
  648. +   vfs_open(filp);
  649. +   vfsmnt->mnt_flags &= ~QF_OPENING;
  650. +   dquot = dqget(dev, 0, type);
  651. +   vfsmnt->mnt_iexp[type] = (dquot) ? dquot->dq_itime : MAX_IQ_TIME;
  652. +   vfsmnt->mnt_bexp[type] = (dquot) ? dquot->dq_btime : MAX_DQ_TIME;
  653. +   dqput(dquot);
  654. +   add_dquot_ref(dev, type);
  655. +   return 0;
  656. +end_quotaon:
  657. +   vfsmnt->mnt_flags &= ~QF_OPENING;
  658. +   if (filp != (struct file *)0)
  659. +      filp->f_count--;
  660. +   iput(inode);
  661. +   return -EIO;
  662. +}
  663. +
  664. +/*
  665. + * Just like iput, decrement referencecount of dquot.
  666. + */
  667. +void dqput(struct dquot *dquot)
  668. +{
  669. +   if (!dquot)
  670. +      return;
  671. +   /*
  672. +    * If the dq_mnt pointer isn't initialized this entry needs no
  673. +    * checking and doesn't need to be written. It just an empty
  674. +    * dquot that is put back into the freelist.
  675. +    */
  676. +   if (dquot->dq_mnt != (struct vfsmount *)0) {
  677. +      wait_on_dquot(dquot);
  678. +      if (!dquot->dq_count) {
  679. +         printk("VFS: iput: trying to free free dquot\n");
  680. +         printk("VFS: device %d/%d, dquot of %s %d\n",
  681. +                MAJOR(dquot->dq_dev), MINOR(dquot->dq_dev),
  682. +                quotatypes[dquot->dq_type], dquot->dq_id);
  683. +         return;
  684. +      }
  685. +repeat:
  686. +      if (dquot->dq_count > 1) {
  687. +         dquot->dq_count--;
  688. +         return;
  689. +      }
  690. +      wake_up(&dquot_wait);
  691. +      if (dquot->dq_flags & DQ_MOD) {
  692. +         write_dquot(dquot);   /* we can sleep - so do again */
  693. +         wait_on_dquot(dquot);
  694. +         goto repeat;
  695. +      }
  696. +   }
  697. +   if (dquot->dq_count) {
  698. +      dquot->dq_count--;
  699. +      nr_free_dquots++;
  700. +   }
  701. +   return;
  702. +}
  703. +
  704. +static struct dquot *get_empty_dquot(void)
  705. +{
  706. +   struct dquot *dquot, *best;
  707. +   int i;
  708. +
  709. +   if (nr_dquots < NR_DQUOTS && nr_free_dquots < (nr_dquots >> 2))
  710. +      grow_dquots();
  711. +
  712. +repeat:
  713. +   dquot = first_dquot;
  714. +   best = NODQUOT;
  715. +   for (i = 0; i < nr_dquots; dquot = dquot->dq_next, i++) {
  716. +      if (!dquot->dq_count) {
  717. +         if (!best)
  718. +            best = dquot;
  719. +         if (!(dquot->dq_flags & DQ_MOD) && !(dquot->dq_flags & DQ_LOCKED)) {
  720. +            best = dquot;
  721. +            break;
  722. +         }
  723. +      }
  724. +   }
  725. +   if (!best || best->dq_flags & DQ_MOD || best->dq_flags & DQ_LOCKED)
  726. +      if (nr_dquots < NR_DQUOTS) {
  727. +         grow_dquots();
  728. +         goto repeat;
  729. +      }
  730. +   dquot = best;
  731. +   if (!dquot) {
  732. +      printk("VFS: No free dquots - contact mvw@mcs.ow.org\n");
  733. +      sleep_on(&dquot_wait);
  734. +      goto repeat;
  735. +   }
  736. +   if (dquot->dq_flags & DQ_LOCKED) {
  737. +      wait_on_dquot(dquot);
  738. +      goto repeat;
  739. +   }
  740. +   if (dquot->dq_flags & DQ_MOD) {
  741. +      write_dquot(dquot);
  742. +      goto repeat;
  743. +   }
  744. +   if (dquot->dq_count)
  745. +      goto repeat;
  746. +   clear_dquot(dquot);
  747. +   dquot->dq_count = 1;
  748. +   nr_free_dquots--;
  749. +   if (nr_free_dquots < 0) {
  750. +      printk ("VFS: get_empty_dquot: bad free dquot count.\n");
  751. +      nr_free_dquots = 0;
  752. +   }
  753. +   return dquot;
  754. +}
  755. +
  756. +/*
  757. + * Just like iget, increment referencecount of a dquot and return
  758. + * pointer to it in the hashqueue.
  759. + */
  760. +struct dquot *dqget(dev_t dev, unsigned int id, short type)
  761. +{
  762. +   struct dquot *dquot, *empty;
  763. +   struct vfsmount *vfsmnt;
  764. +
  765. +   if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)0 ||
  766. +       (vfsmnt->mnt_flags & (QF_OPENING | QF_CLOSING)) ||
  767. +       (vfsmnt->mnt_quotas[type] == (struct file *)0))
  768. +      return (NODQUOT);
  769. +   empty = get_empty_dquot();
  770. +repeat:
  771. +   dquot = *(hash(dev, id, type));
  772. +   while (dquot) {
  773. +      if (dquot->dq_dev != dev || dquot->dq_id != id) {
  774. +         dquot = dquot->dq_hash_next;
  775. +         continue;
  776. +      }
  777. +      wait_on_dquot(dquot);
  778. +      if (dquot->dq_dev != dev || dquot->dq_id != id)
  779. +         goto repeat;
  780. +      if (!dquot->dq_count)
  781. +         nr_free_dquots--;
  782. +      dquot->dq_count++;
  783. +      if (empty)
  784. +         dqput(empty);
  785. +      return dquot;
  786. +   }
  787. +   if (!empty)
  788. +      return (NODQUOT);
  789. +   dquot = empty;
  790. +   dquot->dq_id = id;
  791. +   dquot->dq_type = type;
  792. +   dquot->dq_dev = dev;
  793. +   dquot->dq_mnt = vfsmnt;
  794. +   put_last_free(dquot);
  795. +   insert_dquot_hash(dquot);
  796. +   read_dquot(dquot);
  797. +   return dquot;
  798. +}
  799. +
  800. +/*
  801. + * Initialize pointer in a inode to the right dquots.
  802. + * Be smart and increment count only if already valid pointervalue.
  803. + */
  804. +void getinoquota(struct inode *inode, short type)
  805. +{
  806. +   unsigned int id = 0;
  807. +   short cnt;
  808. +
  809. +   for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  810. +      if (type != -1 && cnt != type)
  811. +         continue;
  812. +      if (inode->i_dquot[cnt] != NODQUOT) {
  813. +         inode->i_dquot[cnt]->dq_count++;
  814. +         continue;
  815. +      }
  816. +      switch (cnt) {
  817. +         case USRQUOTA:
  818. +            id = inode->i_uid;
  819. +            break;
  820. +         case GRPQUOTA:
  821. +            id = inode->i_gid;
  822. +            break;
  823. +      }
  824. +      inode->i_dquot[cnt] = dqget(inode->i_dev, id, cnt);
  825. +   }
  826. +}
  827. +
  828. +void putinoquota(struct inode *inode)
  829. +{
  830. +   short cnt;
  831. +
  832. +   for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  833. +      if (inode->i_dquot[cnt] == NODQUOT)
  834. +         continue;
  835. +      dqput(inode->i_dquot[cnt]);
  836. +      if (!inode->i_writecount)
  837. +         inode->i_dquot[cnt] = NODQUOT;
  838. +   }
  839. +}
  840. +
  841. +/*
  842. + * This are two simple algorithms that calculates the size of a file in blocks
  843. + * and from a number of blocks to a isize.
  844. + * It is not perfect but works most of the time.
  845. + */
  846. +u_long isize_to_blocks(size_t isize, size_t blksize)
  847. +{
  848. +   u_long blocks;
  849. +   u_long indirect;
  850. +
  851. +   if (!blksize)
  852. +      blksize = BLOCK_SIZE;
  853. +   blocks = (isize / blksize) + ((isize % blksize) ? 1 : 0);
  854. +   if (blocks > 10) {
  855. +      indirect = ((blocks - 11) >> 8) + 1; /* single indirect blocks */
  856. +      if (blocks > (10 + 256)) {
  857. +         indirect += ((blocks - 267) >> 16) + 1; /* double indirect blocks */
  858. +         if (blocks > (10 + 256 + (256 << 8)))
  859. +            indirect++; /* triple indirect blocks */
  860. +      }
  861. +      blocks += indirect;
  862. +   }
  863. +   return blocks;
  864. +}
  865. +
  866. +size_t blocks_to_isize(u_long blocks, size_t blksize)
  867. +{
  868. +   size_t isize;
  869. +   u_long indirect;
  870. +
  871. +   if (!blksize)
  872. +      blksize = BLOCK_SIZE;
  873. +   isize = blocks * blksize;
  874. +   if (blocks > 10) {
  875. +      indirect = ((blocks - 11) >> 8) + 1; /* single indirect blocks */
  876. +      if (blocks > (10 + 256)) {
  877. +         indirect += ((blocks - 267) >> 16) + 1; /* double indirect blocks */
  878. +         if (blocks > (10 + 256 + (256 << 8)))
  879. +            indirect++; /* triple indirect blocks */
  880. +      }
  881. +      isize -= indirect * blksize;
  882. +   }
  883. +   return isize;
  884. +}
  885. +
  886. +/*
  887. + * Allocate the number of inodes and blocks from a diskquota.
  888. + */
  889. +int quota_alloc(struct inode *inode, u_long wanted_inodes, u_long wanted_blocks,
  890. +                u_long *avail_blocks)
  891. +{
  892. +   u_long availblocks, local_avail;
  893. +   unsigned short cnt;
  894. +
  895. +   availblocks = wanted_blocks;
  896. +   if (wanted_inodes > 0 || wanted_blocks > 0) {
  897. +      for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  898. +         if (inode->i_dquot[cnt] == NODQUOT)
  899. +            continue;
  900. +         if (check_idq(inode->i_dquot[cnt], inode->i_dquot[cnt]->dq_id,
  901. +                       cnt, wanted_inodes) == NO_QUOTA ||
  902. +             check_bdq(inode->i_dquot[cnt], inode->i_dquot[cnt]->dq_id,
  903. +                       cnt, wanted_blocks, &local_avail) == NO_QUOTA)
  904. +            return NO_QUOTA;
  905. +         availblocks = min(availblocks, local_avail);
  906. +      }
  907. +      for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  908. +         if (inode->i_dquot[cnt] == NODQUOT)
  909. +            continue;
  910. +         incr_quota(inode->i_dquot[cnt], wanted_inodes, availblocks);
  911. +      }
  912. +   }
  913. +   if (avail_blocks != (u_long *)0)
  914. +      *avail_blocks = availblocks;
  915. +   return QUOTA_OK;
  916. +   /* NOTREACHED */
  917. +}
  918. +
  919. +/*
  920. + * Remove the number of inodes and blocks from a diskquota.
  921. + */
  922. +void quota_remove(struct inode *inode, u_long inodes, u_long blocks)
  923. +{
  924. +   short cnt;
  925. +
  926. +   if (inodes > 0 || blocks > 0) {
  927. +      for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  928. +         if (inode->i_dquot[cnt] == NODQUOT)
  929. +            continue;
  930. +         decr_quota(inode->i_dquot[cnt], inodes, blocks);
  931. +      }
  932. +   }
  933. +}
  934. +
  935. +/*
  936. + * Transfer the number of inode and blocks from one diskquota to an other.
  937. + */
  938. +int quota_transfer(struct inode *inode, uid_t newuid, gid_t newgid,
  939. +                   u_long inodes, u_long blocks)
  940. +{
  941. +   struct dquot *transfer_to[MAXQUOTAS];
  942. +   u_long availblocks;
  943. +   unsigned int id = 0;
  944. +   short cnt, disc;
  945. +
  946. +   if (inodes > 0 || blocks > 0) {
  947. +      for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  948. +         transfer_to[cnt] = NODQUOT;
  949. +         switch(cnt) {
  950. +            case USRQUOTA:
  951. +               if (inode->i_uid == newuid)
  952. +                  continue;
  953. +               id = newuid;
  954. +               break;
  955. +            case GRPQUOTA:
  956. +               if (inode->i_gid == newgid)
  957. +                  continue;
  958. +               id = newgid;
  959. +               break;
  960. +         }
  961. +         if ((transfer_to[cnt] = dqget(inode->i_dev, id, cnt)) == NODQUOT)
  962. +            continue;
  963. +
  964. +         if (check_idq(transfer_to[cnt], id, cnt, inodes) == NO_QUOTA ||
  965. +             check_bdq(transfer_to[cnt], id, cnt, blocks, &availblocks) == NO_QUOTA ||
  966. +             availblocks != blocks) {
  967. +            for (disc = 0; disc <= cnt; disc++)
  968. +               dqput(transfer_to[disc]);
  969. +            return NO_QUOTA;
  970. +         }
  971. +      }
  972. +      for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  973. +         if (transfer_to[cnt] == NODQUOT)
  974. +            continue;
  975. +         decr_quota(inode->i_dquot[cnt], inodes, blocks);
  976. +         incr_quota(transfer_to[cnt], inodes, blocks);
  977. +         transfer_to[cnt]->dq_count += inode->i_writecount;
  978. +         inode->i_dquot[cnt]->dq_count -= inode->i_writecount;
  979. +         dqput(inode->i_dquot[cnt]);
  980. +         inode->i_dquot[cnt] = transfer_to[cnt];
  981. +      }
  982. +   }
  983. +   return QUOTA_OK;
  984. +   /* NOTREACHED */
  985. +}
  986. +
  987. +void quota_init(void)
  988. +{
  989. +   memset(hash_table, 0, sizeof(hash_table));
  990. +   first_dquot = NODQUOT;
  991. +}
  992. +
  993. +/*
  994. + * Ok this is the systemcall interface, this communicates with
  995. + * the userlevel programs.
  996. + */
  997. +asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
  998. +{
  999. +   int cmds = 0, type = 0, flags = 0;
  1000. +   struct vfsmount *vfsmnt;
  1001. +   struct inode *ino;
  1002. +   dev_t dev;
  1003. +
  1004. +   cmds = cmd >> SUBCMDSHIFT;
  1005. +   type = cmd & SUBCMDMASK;
  1006. +
  1007. +   if ((u_int) type >= MAXQUOTAS)
  1008. +      return -EINVAL;
  1009. +   switch (cmds) {
  1010. +      case Q_SYNC:
  1011. +         break;
  1012. +      case Q_GETQUOTA:
  1013. +         if (((type == USRQUOTA && current->uid != id) ||
  1014. +              (type == GRPQUOTA && current->gid != id)) && !suser())
  1015. +            return -EPERM;
  1016. +         break;
  1017. +      default:
  1018. +         if (!suser())
  1019. +            return -EPERM;
  1020. +   }
  1021. +
  1022. +   if (special == (char *)0 && cmds == Q_SYNC)
  1023. +      dev = 0;
  1024. +   else {
  1025. +      if (namei(special, &ino))
  1026. +         return -EINVAL;
  1027. +      dev = ino->i_rdev;
  1028. +      if (!S_ISBLK(ino->i_mode)) {
  1029. +         iput(ino);
  1030. +         return -ENOTBLK;
  1031. +      }
  1032. +      iput(ino);
  1033. +   }
  1034. +
  1035. +   switch (cmds) {
  1036. +      case Q_QUOTAON:
  1037. +         return quota_on(dev, type, (char *) addr);
  1038. +      case Q_QUOTAOFF:
  1039. +         return quota_off(dev, type);
  1040. +      case Q_GETQUOTA:
  1041. +         return get_quota(dev, id, type, (struct dqblk *) addr);
  1042. +      case Q_SETQUOTA:
  1043. +         flags |= SET_QUOTA;
  1044. +         break;
  1045. +      case Q_SETUSE:
  1046. +         flags |= SET_USE;
  1047. +         break;
  1048. +      case Q_SETQLIM:
  1049. +         flags |= SET_QLIMIT;
  1050. +         break;
  1051. +      case Q_SYNC:
  1052. +         return sync_dquots(dev, type);
  1053. +      default:
  1054. +         return -EINVAL;
  1055. +   }
  1056. +
  1057. +   flags |= QUOTA_SYSCALL;
  1058. +   if ((vfsmnt = lookup_vfsmnt(dev)) != (struct vfsmount *)0 &&
  1059. +        vfsmnt->mnt_quotas[type] != (struct file *)0)
  1060. +      return set_dqblk(dev, id, type, flags, (struct dqblk *) addr);
  1061. +   return -ESRCH;
  1062. +   /* NOTREACHED */
  1063. +}
  1064. +
  1065. +#else
  1066. +
  1067. +asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
  1068. +{
  1069. +   return -ENOSYS;
  1070. +}
  1071. +
  1072. +#endif /* CONFIG_QUOTA */
  1073. +
  1074. diff -ru --new-file linux_1.1.58/fs/exec.c linux_1.1.58_owld/fs/exec.c
  1075. --- linux_1.1.58/fs/exec.c    Sun Oct 23 00:23:21 1994
  1076. +++ linux_1.1.58_owld/fs/exec.c    Sun Oct 23 00:23:50 1994
  1077. @@ -43,6 +43,7 @@
  1078.  
  1079.  #include <linux/binfmts.h>
  1080.  #include <linux/personality.h>
  1081. +#include <linux/fileio.h>
  1082.  
  1083.  #include <asm/segment.h>
  1084.  #include <asm/system.h>
  1085. @@ -137,6 +138,7 @@
  1086.              return error;
  1087.          }
  1088.      }
  1089. +    vfs_open(f);
  1090.      inode->i_count++;
  1091.      return fd;
  1092.  }
  1093. @@ -146,7 +148,7 @@
  1094.   * macros to write out all the necessary info.
  1095.   */
  1096.  #define DUMP_WRITE(addr,nr) \
  1097. -while (file.f_op->write(inode,&file,(char *)(addr),(nr)) != (nr)) goto close_coredump
  1098. +while (vfs_write(inode,&file,(char *)(addr),(nr)) != (nr)) goto close_coredump
  1099.  
  1100.  #define DUMP_SEEK(offset) \
  1101.  if (file.f_op->lseek) { \
  1102. @@ -154,6 +156,8 @@
  1103.           goto close_coredump; \
  1104.  } else file.f_pos = (offset)        
  1105.  
  1106. +extern int close_fp(struct file *filp, unsigned int fd);
  1107. +
  1108.  /*
  1109.   * Routine writes a core dump image in the current directory.
  1110.   * Currently only a stub-function.
  1111. @@ -207,9 +211,11 @@
  1112.      if (file.f_op->open)
  1113.          if (file.f_op->open(inode,&file))
  1114.              goto end_coredump;
  1115. +    vfs_open(&file);
  1116.      if (!file.f_op->write)
  1117.          goto close_coredump;
  1118.      has_dumped = 1;
  1119. +    current->flags |= PF_DUMPCORE;
  1120.  /* changed the size calculations - should hopefully work better. lbt */
  1121.      dump.magic = CMAGIC;
  1122.      dump.start_code = 0;
  1123. @@ -271,8 +277,9 @@
  1124.      set_fs(KERNEL_DS);
  1125.      DUMP_WRITE(current,sizeof(*current));
  1126.  close_coredump:
  1127. -    if (file.f_op->release)
  1128. -        file.f_op->release(inode,&file);
  1129. +    close_fp(&file, 0);
  1130. +    set_fs(fs);
  1131. +    return has_dumped;
  1132.  end_coredump:
  1133.      set_fs(fs);
  1134.      iput(inode);
  1135. @@ -820,6 +827,8 @@
  1136.      current->mm->mmap = NULL;
  1137.      current->suid = current->euid = current->fsuid = bprm->e_uid;
  1138.      current->sgid = current->egid = current->fsgid = bprm->e_gid;
  1139. +    current->flags &= ~PF_FORKNOEXEC; /* accounting flags */
  1140. +    current->io_usage = 0;
  1141.      if (N_MAGIC(ex) == OMAGIC) {
  1142.          do_mmap(NULL, 0, ex.a_text+ex.a_data,
  1143.              PROT_READ|PROT_WRITE|PROT_EXEC,
  1144. diff -ru --new-file linux_1.1.58/fs/ext2/super.c linux_1.1.58_owld/fs/ext2/super.c
  1145. --- linux_1.1.58/fs/ext2/super.c    Wed Oct 26 15:35:54 1994
  1146. +++ linux_1.1.58_owld/fs/ext2/super.c    Wed Oct 26 15:36:58 1994
  1147. @@ -260,11 +260,8 @@
  1148.                  return 0;
  1149.              }
  1150.          }
  1151. -        else {
  1152. -            printk ("EXT2-fs: Unrecognized mount option %s\n", this_char);
  1153. -            return 0;
  1154. +        else return 1;
  1155.          }
  1156. -    }
  1157.      return 1;
  1158.  }
  1159.  
  1160. diff -ru --new-file linux_1.1.58/fs/fcntl.c linux_1.1.58_owld/fs/fcntl.c
  1161. --- linux_1.1.58/fs/fcntl.c    Wed Oct 26 15:35:54 1994
  1162. +++ linux_1.1.58_owld/fs/fcntl.c    Wed Oct 26 15:36:58 1994
  1163. @@ -12,6 +12,7 @@
  1164.  #include <linux/stat.h>
  1165.  #include <linux/fcntl.h>
  1166.  #include <linux/string.h>
  1167. +#include <linux/fileio.h>
  1168.  
  1169.  extern int fcntl_getlk(unsigned int, struct flock *);
  1170.  extern int fcntl_setlk(unsigned int, unsigned int, struct flock *);
  1171. @@ -32,6 +33,7 @@
  1172.          return -EMFILE;
  1173.      FD_CLR(arg, ¤t->files->close_on_exec);
  1174.      (current->files->fd[arg] = current->files->fd[fd])->f_count++;
  1175. +       vfs_open(current->files->fd[fd]);
  1176.      return arg;
  1177.  }
  1178.  
  1179. diff -ru --new-file linux_1.1.58/fs/file_table.c linux_1.1.58_owld/fs/file_table.c
  1180. --- linux_1.1.58/fs/file_table.c    Sun Oct 23 00:23:21 1994
  1181. +++ linux_1.1.58_owld/fs/file_table.c    Sun Oct 23 00:23:50 1994
  1182. @@ -7,6 +7,7 @@
  1183.  #include <linux/fs.h>
  1184.  #include <linux/string.h>
  1185.  #include <linux/mm.h>
  1186. +#include <linux/config.h>
  1187.  
  1188.  struct file * first_file;
  1189.  int nr_files = 0;
  1190. @@ -88,3 +89,34 @@
  1191.      }
  1192.      return NULL;
  1193.  }
  1194. +
  1195. +#ifdef CONFIG_QUOTA
  1196. +void add_dquot_ref(dev_t dev, short type)
  1197. +{
  1198. +    struct file *filp;
  1199. +    int i;
  1200. +
  1201. +    /* Check files that are currently opened for writing. */
  1202. +    for (filp = first_file, i = 0; i < nr_files; i++, filp = filp->f_next) {
  1203. +        if (!filp->f_count || !filp->f_inode || filp->f_inode->i_dev != dev)
  1204. +            continue;
  1205. +        if (filp->f_inode->i_writecount > 0) {
  1206. +            getinoquota(filp->f_inode, type);
  1207. +            if (filp->f_inode->i_dquot[type] != NODQUOT)
  1208. +                filp->f_inode->i_dquot[type]->dq_count +=
  1209. +                (filp->f_inode->i_writecount - 1);
  1210. +        }
  1211. +    }
  1212. +}
  1213. +
  1214. +void reset_dquot_ptrs(dev_t dev, short type)
  1215. +{
  1216. +    struct file *filp;
  1217. +    int i;
  1218. +
  1219. +    for (filp = first_file, i = 0; i < nr_files; i++, filp = filp->f_next)
  1220. +        if (filp->f_count && filp->f_inode &&
  1221. +            filp->f_inode->i_writecount && filp->f_inode->i_dev == dev)
  1222. +            filp->f_inode->i_dquot[type] = NODQUOT;
  1223. +}
  1224. +#endif
  1225. diff -ru --new-file linux_1.1.58/fs/fileio.c linux_1.1.58_owld/fs/fileio.c
  1226. --- linux_1.1.58/fs/fileio.c    Thu Jan  1 01:00:00 1970
  1227. +++ linux_1.1.58_owld/fs/fileio.c    Thu Oct 27 12:39:04 1994
  1228. @@ -0,0 +1,397 @@
  1229. +/*
  1230. + *
  1231. + * Simple VFS definitions for fileio.
  1232. + *
  1233. + * Authors: Marco van Wieringen <v892273@si.hhs.nl> <mvw@mcs.ow.org>
  1234. + *          Edvard Tuinder <v892231@si.hhs.nl> <ed@delirium.ow.org>
  1235. + *
  1236. + * Version: $Id: fileio.c,v 1.11 1994/10/24 21:16:40 mvw Exp mvw $
  1237. + *
  1238. + */
  1239. +
  1240. +#include <linux/config.h>
  1241. +#include <linux/kernel.h>
  1242. +#include <linux/sched.h>
  1243. +#include <linux/stat.h>
  1244. +#include <linux/string.h>
  1245. +#include <linux/fcntl.h>
  1246. +
  1247. +#ifdef CONFIG_QUOTA
  1248. +extern int lookup(struct inode *, const char *, int, struct inode **);
  1249. +
  1250. +int vfs_write(struct inode *inode, struct file *filp, char *addr, size_t bytes)
  1251. +{
  1252. +   size_t written;
  1253. +   u_long cur_blocks, wanted_blocks = 0, avail_blocks = 0;
  1254. +
  1255. +   if (S_ISREG(inode->i_mode)) {
  1256. +      cur_blocks = isize_to_blocks(inode->i_size, inode->i_blksize);
  1257. +      if ((filp->f_pos + bytes) > inode->i_size) {
  1258. +         wanted_blocks = isize_to_blocks(filp->f_pos + bytes,
  1259. +                         inode->i_blksize) - cur_blocks;
  1260. +         if (wanted_blocks && quota_alloc(inode, 0, wanted_blocks,
  1261. +                                          &avail_blocks) == NO_QUOTA)
  1262. +            return -EDQUOT;
  1263. +         if (wanted_blocks && (avail_blocks < wanted_blocks))
  1264. +            bytes = blocks_to_isize((cur_blocks + avail_blocks),
  1265. +                    inode->i_blksize) - filp->f_pos;
  1266. +      }
  1267. +      if ((written = filp->f_op->write(inode, filp, addr, bytes)) != bytes) {
  1268. +         quota_remove(inode, 0, avail_blocks -
  1269. +                     (isize_to_blocks(inode->i_size, inode->i_blksize) -
  1270. +                      isize_to_blocks((inode->i_size - written), inode->i_blksize)));
  1271. +      }
  1272. +      current->io_usage += written;
  1273. +      if (wanted_blocks && (avail_blocks < wanted_blocks))
  1274. +         return -EDQUOT;
  1275. +
  1276. +      return written;
  1277. +   } else {
  1278. +      current->io_usage += bytes;
  1279. +      return filp->f_op->write(inode, filp, (char *)addr, bytes);
  1280. +   }
  1281. +}
  1282. +
  1283. +int vfs_create(struct inode *dir, const char *basename,
  1284. +               int namelen, int mode, struct inode **res_ino)
  1285. +{
  1286. +   int error;
  1287. +   struct inode new_inode;
  1288. +
  1289. +   memset(&new_inode, 0, sizeof(struct inode));
  1290. +   new_inode.i_dev = dir->i_dev;
  1291. +   new_inode.i_uid = current->fsuid;
  1292. +   new_inode.i_gid = current->fsgid;
  1293. +   getinoquota(&new_inode, -1);
  1294. +
  1295. +   if (quota_alloc(&new_inode, 1, 0, (u_long *)0) == NO_QUOTA) {
  1296. +      putinoquota(&new_inode);
  1297. +      return -EDQUOT;
  1298. +   }
  1299. +   error = dir->i_op->create(dir, basename, namelen, mode, res_ino);
  1300. +   if (error)
  1301. +      quota_remove(&new_inode, 1, 0);
  1302. +   putinoquota(&new_inode);
  1303. +
  1304. +   return error;
  1305. +}
  1306. +
  1307. +int vfs_truncate(struct inode *inode, size_t length)
  1308. +{
  1309. +   int error;
  1310. +   size_t old_isize;
  1311. +   struct iattr newattrs;
  1312. +
  1313. +   old_isize = inode->i_size;
  1314. +   inode->i_size = newattrs.ia_size = length;
  1315. +   if (inode->i_op && inode->i_op->truncate)
  1316. +      inode->i_op->truncate(inode);
  1317. +   newattrs.ia_ctime = newattrs.ia_mtime = CURRENT_TIME;
  1318. +   newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME | ATTR_MTIME;
  1319. +   if ((error = notify_change(inode, &newattrs)))
  1320. +      return error;
  1321. +   getinoquota(inode, -1);
  1322. +   quota_remove(inode, 0, isize_to_blocks(old_isize, inode->i_blksize));
  1323. +   putinoquota(inode);
  1324. +   inode->i_dirt = 1;
  1325. +   return 0;
  1326. +}
  1327. +
  1328. +int vfs_mknod(struct inode *dir, const char *basename,
  1329. +              int namelen, int mode, dev_t dev)
  1330. +{
  1331. +   int error;
  1332. +   struct inode new_inode;
  1333. +
  1334. +   memset(&new_inode, 0, sizeof(struct inode));
  1335. +   new_inode.i_dev = dir->i_dev;
  1336. +   new_inode.i_uid = current->fsuid;
  1337. +   new_inode.i_gid = current->fsgid;
  1338. +   getinoquota(&new_inode, -1);
  1339. +
  1340. +   if (quota_alloc(&new_inode, 1, 0, (u_long *)0) == NO_QUOTA) {
  1341. +      putinoquota(&new_inode);
  1342. +      iput(dir);
  1343. +      return -EDQUOT;
  1344. +   }
  1345. +   dir->i_count++;
  1346. +   error = dir->i_op->mknod(dir, basename, namelen, mode, dev);
  1347. +   if (error)
  1348. +      quota_remove(&new_inode, 1, 0);
  1349. +   putinoquota(&new_inode);
  1350. +   iput(dir);
  1351. +
  1352. +   return error;
  1353. +}
  1354. +
  1355. +int vfs_mkdir(struct inode *dir, const char *basename, int namelen, int mode)
  1356. +{
  1357. +   int error;
  1358. +   struct inode new_inode;
  1359. +
  1360. +   memset(&new_inode, 0, sizeof(struct inode));
  1361. +   new_inode.i_dev = dir->i_dev;
  1362. +   new_inode.i_uid = current->fsuid;
  1363. +   new_inode.i_gid = current->fsgid;
  1364. +   getinoquota(&new_inode, -1);
  1365. +
  1366. +   if (quota_alloc(&new_inode, 1, 1, (u_long *)0) == NO_QUOTA) {
  1367. +      putinoquota(&new_inode);
  1368. +      iput(dir);
  1369. +      return -EDQUOT;
  1370. +   }
  1371. +   dir->i_count++;
  1372. +   error = dir->i_op->mkdir(dir, basename, namelen, mode);
  1373. +   if (error)
  1374. +      quota_remove(&new_inode, 1, 1);
  1375. +   putinoquota(&new_inode);
  1376. +   iput(dir);
  1377. +
  1378. +   return error;
  1379. +}
  1380. +
  1381. +int vfs_rmdir(struct inode *dir, const char *basename, int namelen)
  1382. +{
  1383. +   int error;
  1384. +   struct inode *old_inode;
  1385. +
  1386. +   /*
  1387. +    * Need inode entry of directory for quota operations
  1388. +    */
  1389. +   dir->i_count++;
  1390. +   if ((error = lookup(dir, basename, namelen, &old_inode))) {
  1391. +      iput(dir);
  1392. +      return error;
  1393. +   }
  1394. +   getinoquota(old_inode, -1);
  1395. +   if (!(error = dir->i_op->rmdir(dir, basename, namelen)))
  1396. +      quota_remove(old_inode, 1, 1);
  1397. +   putinoquota(old_inode);
  1398. +   iput(old_inode);
  1399. +
  1400. +   return error;
  1401. +}
  1402. +
  1403. +int vfs_unlink(struct inode *dir, const char *basename, int namelen)
  1404. +{
  1405. +   int error;
  1406. +   struct inode *old_inode;
  1407. +
  1408. +   /*
  1409. +    * Need inode info of to remove file for quota operations.
  1410. +    */
  1411. +   dir->i_count++;
  1412. +   if ((error = lookup(dir, basename, namelen, &old_inode))) {
  1413. +      iput(dir);
  1414. +      return error;
  1415. +   }
  1416. +   getinoquota(old_inode, -1);
  1417. +   error = dir->i_op->unlink(dir, basename, namelen);
  1418. +   /*
  1419. +    * Remove blocks and inode. Only if link-count is 0 !
  1420. +    */
  1421. +   if (!error && old_inode->i_nlink == 0)
  1422. +      quota_remove(old_inode, 1,
  1423. +                   isize_to_blocks(old_inode->i_size, old_inode->i_blksize));
  1424. +   putinoquota(old_inode);
  1425. +   iput(old_inode);
  1426. +
  1427. +   return error;
  1428. +}
  1429. +
  1430. +int vfs_symlink(struct inode *dir, const char *basename,
  1431. +                int namelen, const char *oldname)
  1432. +{
  1433. +   int error;
  1434. +   struct inode new_inode;
  1435. +
  1436. +   memset(&new_inode, 0, sizeof(struct inode));
  1437. +   new_inode.i_dev = dir->i_dev;
  1438. +   new_inode.i_uid = current->fsuid;
  1439. +   new_inode.i_gid = current->fsgid;
  1440. +   getinoquota(&new_inode, -1);
  1441. +
  1442. +   if (quota_alloc(&new_inode, 1, 1, (u_long *)0) == NO_QUOTA) {
  1443. +      putinoquota(&new_inode);
  1444. +      iput(dir);
  1445. +      return -EDQUOT;
  1446. +   }
  1447. +   dir->i_count++;
  1448. +   if (!(error = dir->i_op->symlink(dir, basename, namelen, oldname)))
  1449. +      quota_remove(&new_inode, 1, 1);
  1450. +   putinoquota(&new_inode);
  1451. +   iput(dir);
  1452. +
  1453. +   return error;
  1454. +}
  1455. +
  1456. +int vfs_chown(struct inode *inode, uid_t uid, gid_t gid)
  1457. +{
  1458. +   int error;
  1459. +   uid_t olduid, oldgid;
  1460. +   struct iattr newattrs;
  1461. +
  1462. +   if (IS_RDONLY(inode))
  1463. +      return -EROFS;
  1464. +   olduid = inode->i_uid;
  1465. +   oldgid = inode->i_gid;
  1466. +   getinoquota(inode, -1);
  1467. +   if (uid == (uid_t) -1)
  1468. +      uid = inode->i_uid;
  1469. +   if (gid == (gid_t) -1)
  1470. +      gid = inode->i_gid;
  1471. +   if (quota_transfer(inode, uid, gid, 1,
  1472. +                      isize_to_blocks(inode->i_size,
  1473. +                      inode->i_blksize)) == NO_QUOTA) {
  1474. +      putinoquota(inode);
  1475. +      return -EDQUOT;
  1476. +   }
  1477. +   newattrs.ia_uid = uid;
  1478. +   newattrs.ia_gid = gid;
  1479. +   newattrs.ia_ctime = CURRENT_TIME;
  1480. +   newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
  1481. +   /*
  1482. +    * If the owner has been changed, remove the setuid bit
  1483. +    */
  1484. +   if (uid != inode->i_uid && inode->i_mode & S_ISUID) {
  1485. +      newattrs.ia_mode = inode->i_mode & ~S_ISUID;
  1486. +      newattrs.ia_valid |= ATTR_MODE;
  1487. +   }
  1488. +   /*
  1489. +    * If the group has been changed, remove the setgid bit
  1490. +    */
  1491. +   if (gid != inode->i_gid && inode->i_mode & S_ISGID) {
  1492. +      newattrs.ia_mode = inode->i_mode & ~S_ISGID;
  1493. +      newattrs.ia_valid |= ATTR_MODE;
  1494. +   }
  1495. +   if ((error = notify_change(inode, &newattrs)))
  1496. +      quota_transfer(inode, olduid, oldgid, 1,
  1497. +                     isize_to_blocks(inode->i_size, inode->i_blksize));
  1498. +   putinoquota(inode);
  1499. +   inode->i_dirt = 1;
  1500. +   return error;
  1501. +}
  1502. +
  1503. +int vfs_rename(struct inode *old_dir, const char *old_base, int old_len,
  1504. +               struct inode *new_dir, const char *new_base, int new_len)
  1505. +{
  1506. +   int error;
  1507. +   struct inode *old_inode, *new_inode;
  1508. +
  1509. +   /*
  1510. +    * Check if target file already exists, drop quota of file if
  1511. +    * it already exists and is overwritten. Extra check needed for
  1512. +    * renames of file to the same file.
  1513. +    */
  1514. +   old_dir->i_count++;
  1515. +   if ((error = lookup(old_dir, old_base, old_len, &old_inode))) {
  1516. +      iput(old_dir);
  1517. +      iput(new_dir);
  1518. +      return error;
  1519. +   }
  1520. +   new_dir->i_count++;
  1521. +   if (!lookup(new_dir, new_base, new_len, &new_inode)) {
  1522. +      if (old_dir != new_dir && old_inode != new_inode) {
  1523. +         iput(old_inode);
  1524. +         error = old_dir->i_op->rename(old_dir, old_base, old_len, 
  1525. +                                       new_dir, new_base, new_len);
  1526. +         if (!error) {
  1527. +            getinoquota(new_inode, -1);
  1528. +            quota_remove(new_inode, 1,
  1529. +                         isize_to_blocks(new_inode->i_size, new_inode->i_blksize));
  1530. +            putinoquota(new_inode);
  1531. +            iput(new_inode);
  1532. +         }
  1533. +         return error;
  1534. +      }
  1535. +      iput(new_inode);
  1536. +   }
  1537. +   iput(old_inode);
  1538. +   return old_dir->i_op->rename(old_dir, old_base, old_len, 
  1539. +                                new_dir, new_base, new_len);
  1540. +}
  1541. +
  1542. +void vfs_open(struct file *filp)
  1543. +{
  1544. +   if (filp->f_inode && S_ISREG(filp->f_inode->i_mode) && (filp->f_mode & 2)) {
  1545. +      filp->f_inode->i_writecount++;
  1546. +      getinoquota(filp->f_inode, -1); 
  1547. +   }
  1548. +}
  1549. +
  1550. +void vfs_close(struct file *filp)
  1551. +{
  1552. +   if (filp->f_inode && S_ISREG(filp->f_inode->i_mode) && (filp->f_mode & 2)) {
  1553. +      filp->f_inode->i_writecount--;
  1554. +      putinoquota(filp->f_inode); 
  1555. +   }
  1556. +}
  1557. +
  1558. +#else /* CONFIG_QUOTA */
  1559. +
  1560. +int vfs_truncate(struct inode *inode, size_t length)
  1561. +{
  1562. +   int error;
  1563. +   struct iattr newattrs;
  1564. +
  1565. +   inode->i_size = newattrs.ia_size = length;
  1566. +   if (inode->i_op && inode->i_op->truncate)
  1567. +      if ((error = inode->i_op->truncate(inode)))
  1568. +         return(error);
  1569. +   newattrs.ia_ctime = newattrs.ia_mtime = CURRENT_TIME;
  1570. +   newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME | ATTR_MTIME;
  1571. +   if ((error = notify_change(inode, &newattrs)))
  1572. +      return(error);
  1573. +   inode->i_dirt = 1;
  1574. +   return(error);
  1575. +}
  1576. +
  1577. +int vfs_chown(struct inode *inode, uid_t uid, gid_t gid)
  1578. +{
  1579. +   int error;
  1580. +   struct iattr newattrs;
  1581. +
  1582. +   if (IS_RDONLY(inode))
  1583. +      return -EROFS;
  1584. +   newattrs.ia_uid = uid;
  1585. +   newattrs.ia_gid = gid;
  1586. +   newattrs.ia_ctime = CURRENT_TIME;
  1587. +   newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
  1588. +   if (uid == (uid_t) -1)
  1589. +      uid = inode->i_uid;
  1590. +   if (gid == (gid_t) -1)
  1591. +      gid = inode->i_gid;
  1592. +   /*
  1593. +    * If the owner has been changed, remove the setuid bit
  1594. +    */
  1595. +   if (uid != inode->i_uid && inode->i_mode & S_ISUID) {
  1596. +      newattrs.ia_mode = inode->i_mode & ~S_ISUID;
  1597. +      newattrs.ia_valid |= ATTR_MODE;
  1598. +   }
  1599. +   /*
  1600. +    * If the group has been changed, remove the setgid bit
  1601. +    */
  1602. +   if (gid != inode->i_gid && inode->i_mode & S_ISGID) {
  1603. +      newattrs.ia_mode = inode->i_mode & ~S_ISGID;
  1604. +      newattrs.ia_valid |= ATTR_MODE;
  1605. +   }
  1606. +   if (error = notify_change(ino, &newattrs))
  1607. +      return error;
  1608. +   inode->i_dirt = 1;
  1609. +   return 0;
  1610. +}
  1611. +
  1612. +void vfs_open(struct file *filp)
  1613. +{
  1614. +   if (filp->f_inode && S_ISREG(filp->f_inode->i_mode) && (filp->f_mode & 2))
  1615. +      filp->f_inode->i_writecount++;
  1616. +}
  1617. +
  1618. +void vfs_close(struct file *filp)
  1619. +{
  1620. +   if (filp->f_inode && S_ISREG(filp->f_inode->i_mode) && (filp->f_mode & 2))
  1621. +      filp->f_inode->i_writecount--;
  1622. +}
  1623. +
  1624. +#endif /* CONFIG_QUOTA */
  1625. +
  1626. diff -ru --new-file linux_1.1.58/fs/inode.c linux_1.1.58_owld/fs/inode.c
  1627. --- linux_1.1.58/fs/inode.c    Mon Oct 24 19:56:07 1994
  1628. +++ linux_1.1.58_owld/fs/inode.c    Mon Oct 24 20:01:48 1994
  1629. @@ -487,6 +487,7 @@
  1630.      struct inode_hash_entry * h;
  1631.      struct inode * inode;
  1632.      struct inode * empty = NULL;
  1633. +    short cnt;
  1634.  
  1635.      if (!sb)
  1636.          panic("VFS: iget with sb==NULL");
  1637. @@ -515,8 +516,11 @@
  1638.      goto return_it;
  1639.  
  1640.  found_it:
  1641. -    if (!inode->i_count)
  1642. +    if (!inode->i_count) {
  1643.          nr_free_inodes--;
  1644. +        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
  1645. +            inode->i_dquot[cnt] = NODQUOT;
  1646. +    }
  1647.      inode->i_count++;
  1648.      wait_on_inode(inode);
  1649.      if (inode->i_dev != sb->s_dev || inode->i_ino != nr) {
  1650. diff -ru --new-file linux_1.1.58/fs/isofs/inode.c linux_1.1.58_owld/fs/isofs/inode.c
  1651. --- linux_1.1.58/fs/isofs/inode.c    Thu Aug 11 15:40:16 1994
  1652. +++ linux_1.1.58_owld/fs/isofs/inode.c    Thu Aug 11 15:42:27 1994
  1653. @@ -124,7 +124,7 @@
  1654.              break;
  1655.            }
  1656.          }
  1657. -        else return 0;
  1658. +        else return 1;
  1659.      }
  1660.      return 1;
  1661.  }
  1662. diff -ru --new-file linux_1.1.58/fs/msdos/inode.c linux_1.1.58_owld/fs/msdos/inode.c
  1663. --- linux_1.1.58/fs/msdos/inode.c    Mon Oct 24 19:56:07 1994
  1664. +++ linux_1.1.58_owld/fs/msdos/inode.c    Mon Oct 24 20:01:49 1994
  1665. @@ -133,7 +133,7 @@
  1666.              if (value) return 0;
  1667.              *quiet = 1;
  1668.          }
  1669. -        else return 0;
  1670. +        else return 1;
  1671.      }
  1672.      return 1;
  1673.  }
  1674. diff -ru --new-file linux_1.1.58/fs/namei.c linux_1.1.58_owld/fs/namei.c
  1675. --- linux_1.1.58/fs/namei.c    Mon Oct 24 19:56:08 1994
  1676. +++ linux_1.1.58_owld/fs/namei.c    Thu Oct 27 12:38:46 1994
  1677. @@ -16,6 +16,7 @@
  1678.  #include <linux/string.h>
  1679.  #include <linux/fcntl.h>
  1680.  #include <linux/stat.h>
  1681. +#include <linux/fileio.h>
  1682.  
  1683.  #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
  1684.  
  1685. @@ -345,7 +346,7 @@
  1686.              error = -EROFS;
  1687.          else {
  1688.              dir->i_count++;        /* create eats the dir */
  1689. -            error = dir->i_op->create(dir,basename,namelen,mode,res_inode);
  1690. +            error = vfs_create(dir,basename,namelen,mode,res_inode);
  1691.              up(&dir->i_sem);
  1692.              iput(dir);
  1693.              return error;
  1694. @@ -397,6 +398,7 @@
  1695.              }
  1696.           }
  1697.       }
  1698. +
  1699.      /*
  1700.       * An append-only file must be opened in append mode for writing
  1701.       */
  1702. @@ -404,20 +406,9 @@
  1703.          iput(inode);
  1704.          return -EPERM;
  1705.      }
  1706. -    if (flag & O_TRUNC) {
  1707. -        struct iattr newattrs;
  1708. -
  1709. -        newattrs.ia_size = 0;
  1710. -        newattrs.ia_valid = ATTR_SIZE;
  1711. -        if ((error = notify_change(inode, &newattrs))) {
  1712. -            iput(inode);
  1713. +    if (flag & O_TRUNC)
  1714. +        if ((error = vfs_truncate(inode, 0)))
  1715.              return error;
  1716. -        }
  1717. -        inode->i_size = 0;
  1718. -        if (inode->i_op && inode->i_op->truncate)
  1719. -            inode->i_op->truncate(inode);
  1720. -        inode->i_dirt = 1;
  1721. -    }
  1722.      *res_inode = inode;
  1723.      return 0;
  1724.  }
  1725. @@ -450,7 +441,7 @@
  1726.      }
  1727.      dir->i_count++;
  1728.      down(&dir->i_sem);
  1729. -    error = dir->i_op->mknod(dir,basename,namelen,mode,dev);
  1730. +    error = vfs_mknod(dir,basename,namelen,mode,dev);
  1731.      up(&dir->i_sem);
  1732.      iput(dir);
  1733.      return error;
  1734. @@ -507,7 +498,7 @@
  1735.      }
  1736.      dir->i_count++;
  1737.      down(&dir->i_sem);
  1738. -    error = dir->i_op->mkdir(dir,basename,namelen,mode);
  1739. +    error = vfs_mkdir(dir,basename,namelen,mode);
  1740.      up(&dir->i_sem);
  1741.      iput(dir);
  1742.      return error;
  1743. @@ -558,7 +549,7 @@
  1744.          iput(dir);
  1745.          return -EPERM;
  1746.      }
  1747. -    return dir->i_op->rmdir(dir,basename,namelen);
  1748. +    return vfs_rmdir(dir,basename,namelen);
  1749.  }
  1750.  
  1751.  asmlinkage int sys_rmdir(const char * pathname)
  1752. @@ -606,7 +597,7 @@
  1753.          iput(dir);
  1754.          return -EPERM;
  1755.      }
  1756. -    return dir->i_op->unlink(dir,basename,namelen);
  1757. +    return vfs_unlink(dir,basename,namelen);
  1758.  }
  1759.  
  1760.  asmlinkage int sys_unlink(const char * pathname)
  1761. @@ -649,7 +640,7 @@
  1762.      }
  1763.      dir->i_count++;
  1764.      down(&dir->i_sem);
  1765. -    error = dir->i_op->symlink(dir,basename,namelen,oldname);
  1766. +    error = vfs_symlink(dir,basename,namelen,oldname);
  1767.      up(&dir->i_sem);
  1768.      iput(dir);
  1769.      return error;
  1770. @@ -804,7 +795,7 @@
  1771.      }
  1772.      new_dir->i_count++;
  1773.      down(&new_dir->i_sem);
  1774. -    error = old_dir->i_op->rename(old_dir, old_base, old_len, 
  1775. +    error = vfs_rename(old_dir, old_base, old_len, 
  1776.          new_dir, new_base, new_len);
  1777.      up(&new_dir->i_sem);
  1778.      iput(new_dir);
  1779. diff -ru --new-file linux_1.1.58/fs/open.c linux_1.1.58_owld/fs/open.c
  1780. --- linux_1.1.58/fs/open.c    Mon Oct 24 19:56:08 1994
  1781. +++ linux_1.1.58_owld/fs/open.c    Thu Oct 27 12:36:07 1994
  1782. @@ -16,6 +16,7 @@
  1783.  #include <linux/signal.h>
  1784.  #include <linux/tty.h>
  1785.  #include <linux/time.h>
  1786. +#include <linux/fileio.h>
  1787.  
  1788.  #include <asm/segment.h>
  1789.  
  1790. @@ -69,7 +70,6 @@
  1791.  {
  1792.      struct inode * inode;
  1793.      int error;
  1794. -    struct iattr newattrs;
  1795.  
  1796.      error = namei(path,&inode);
  1797.      if (error)
  1798. @@ -86,13 +86,7 @@
  1799.          iput(inode);
  1800.          return -EPERM;
  1801.      }
  1802. -    inode->i_size = newattrs.ia_size = length;
  1803. -    if (inode->i_op && inode->i_op->truncate)
  1804. -        inode->i_op->truncate(inode);
  1805. -    newattrs.ia_ctime = newattrs.ia_mtime = CURRENT_TIME;
  1806. -    newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME | ATTR_MTIME;
  1807. -    inode->i_dirt = 1;
  1808. -    error = notify_change(inode, &newattrs);
  1809. +    error = vfs_truncate(inode, length);
  1810.      iput(inode);
  1811.      return error;
  1812.  }
  1813. @@ -101,7 +95,6 @@
  1814.  {
  1815.      struct inode * inode;
  1816.      struct file * file;
  1817. -    struct iattr newattrs;
  1818.  
  1819.      if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
  1820.          return -EBADF;
  1821. @@ -111,13 +104,7 @@
  1822.          return -EACCES;
  1823.      if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  1824.          return -EPERM;
  1825. -    inode->i_size = newattrs.ia_size = length;
  1826. -    if (inode->i_op && inode->i_op->truncate)
  1827. -        inode->i_op->truncate(inode);
  1828. -    newattrs.ia_ctime = newattrs.ia_mtime = CURRENT_TIME;
  1829. -    newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME | ATTR_MTIME;
  1830. -    inode->i_dirt = 1;
  1831. -    return notify_change(inode, &newattrs);
  1832. +    return vfs_truncate(inode, length);
  1833.  }
  1834.  
  1835.  /* If times==NULL, set access and modification to current time,
  1836. @@ -300,79 +287,25 @@
  1837.  {
  1838.      struct inode * inode;
  1839.      struct file * file;
  1840. -    struct iattr newattrs;
  1841.  
  1842.      if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
  1843.          return -EBADF;
  1844.      if (!(inode = file->f_inode))
  1845.          return -ENOENT;
  1846. -    if (IS_RDONLY(inode))
  1847. -        return -EROFS;
  1848. -    if (user == (uid_t) -1)
  1849. -        user = inode->i_uid;
  1850. -    if (group == (gid_t) -1)
  1851. -        group = inode->i_gid;
  1852. -    newattrs.ia_uid = user;
  1853. -    newattrs.ia_gid = group;
  1854. -    newattrs.ia_ctime = CURRENT_TIME;
  1855. -    newattrs.ia_valid =  ATTR_UID | ATTR_GID | ATTR_CTIME;
  1856. -    /*
  1857. -     * If the owner has been changed, remove the setuid bit
  1858. -     */
  1859. -    if (user != inode->i_uid && inode->i_mode & S_ISUID) {
  1860. -        newattrs.ia_mode = inode->i_mode & ~S_ISUID;
  1861. -        newattrs.ia_valid |= ATTR_MODE;
  1862. -    }
  1863. -    /*
  1864. -     * If the group has been changed, remove the setgid bit
  1865. -     */
  1866. -    if (group != inode->i_gid && inode->i_mode & S_ISGID) {
  1867. -        newattrs.ia_mode = inode->i_mode & ~S_ISGID;
  1868. -        newattrs.ia_valid |= ATTR_MODE;
  1869. -    }
  1870. -    inode->i_dirt = 1;
  1871. -    return notify_change(inode, &newattrs);
  1872. +    return vfs_chown(inode, user, group);
  1873.  }
  1874.  
  1875.  asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
  1876.  {
  1877.      struct inode * inode;
  1878.      int error;
  1879. -    struct iattr newattrs;
  1880.  
  1881.      error = lnamei(filename,&inode);
  1882.      if (error)
  1883.          return error;
  1884. -    if (IS_RDONLY(inode)) {
  1885. -        iput(inode);
  1886. -        return -EROFS;
  1887. -    }
  1888. -    if (user == (uid_t) -1)
  1889. -        user = inode->i_uid;
  1890. -    if (group == (gid_t) -1)
  1891. -        group = inode->i_gid;
  1892. -    newattrs.ia_uid = user;
  1893. -    newattrs.ia_gid = group;
  1894. -    newattrs.ia_ctime = CURRENT_TIME;
  1895. -    newattrs.ia_valid =  ATTR_UID | ATTR_GID | ATTR_CTIME;
  1896. -    /*
  1897. -     * If the owner has been changed, remove the setuid bit
  1898. -     */
  1899. -    if (user != inode->i_uid && inode->i_mode & S_ISUID) {
  1900. -        newattrs.ia_mode = inode->i_mode & ~S_ISUID;
  1901. -        newattrs.ia_valid |= ATTR_MODE;
  1902. -    }
  1903. -    /*
  1904. -     * If the group has been changed, remove the setgid bit
  1905. -     */
  1906. -    if (group != inode->i_gid && inode->i_mode & S_ISGID) {
  1907. -        newattrs.ia_mode = inode->i_mode & ~S_ISGID;
  1908. -        newattrs.ia_valid |= ATTR_MODE;
  1909. -    }
  1910. -    inode->i_dirt = 1;
  1911. -    error = notify_change(inode, &newattrs);
  1912. +    error = vfs_chown(inode, user, group);
  1913.      iput(inode);
  1914. -    return(error);
  1915. +    return error;
  1916.  }
  1917.  
  1918.  /*
  1919. @@ -433,6 +366,7 @@
  1920.              return error;
  1921.          }
  1922.      }
  1923. +    vfs_open(f);
  1924.      f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
  1925.      return (fd);
  1926.  }
  1927. @@ -466,6 +400,7 @@
  1928.      inode = filp->f_inode;
  1929.      if (inode)
  1930.          fcntl_remove_locks(current, filp, fd);
  1931. +    vfs_close(filp);
  1932.      if (filp->f_count > 1) {
  1933.          filp->f_count--;
  1934.          return 0;
  1935. diff -ru --new-file linux_1.1.58/fs/read_write.c linux_1.1.58_owld/fs/read_write.c
  1936. --- linux_1.1.58/fs/read_write.c    Mon Oct 24 19:56:08 1994
  1937. +++ linux_1.1.58_owld/fs/read_write.c    Mon Oct 24 20:09:36 1994
  1938. @@ -9,6 +9,7 @@
  1939.  #include <linux/stat.h>
  1940.  #include <linux/kernel.h>
  1941.  #include <linux/sched.h>
  1942. +#include <linux/fileio.h>
  1943.  
  1944.  #include <asm/segment.h>
  1945.  
  1946. @@ -132,6 +133,7 @@
  1947.      error = verify_area(VERIFY_WRITE,buf,count);
  1948.      if (error)
  1949.          return error;
  1950. +    current->io_usage += count;
  1951.      return file->f_op->read(inode,file,buf,count);
  1952.  }
  1953.  
  1954. @@ -140,6 +142,7 @@
  1955.      int error;
  1956.      struct file * file;
  1957.      struct inode * inode;
  1958. +    struct iattr newattrs;
  1959.      int written;
  1960.      
  1961.      if (fd>=NR_OPEN || !(file=current->files->fd[fd]) || !(inode=file->f_inode))
  1962. @@ -159,7 +162,6 @@
  1963.       * the setgid bits
  1964.       */
  1965.      if (written > 0 && !suser() && (inode->i_mode & (S_ISUID | S_ISGID))) {
  1966. -        struct iattr newattrs;
  1967.          newattrs.ia_mode = inode->i_mode & ~(S_ISUID | S_ISGID);
  1968.          newattrs.ia_valid = ATTR_MODE;
  1969.          notify_change(inode, &newattrs);
  1970. diff -ru --new-file linux_1.1.58/fs/super.c linux_1.1.58_owld/fs/super.c
  1971. --- linux_1.1.58/fs/super.c    Thu Oct  6 21:16:23 1994
  1972. +++ linux_1.1.58_owld/fs/super.c    Thu Oct  6 21:37:27 1994
  1973. @@ -2,16 +2,20 @@
  1974.   *  linux/fs/super.c
  1975.   *
  1976.   *  Copyright (C) 1991, 1992  Linus Torvalds
  1977. + *
  1978. + *  super.c contains code to handle: - mount structures
  1979. + *                                   - super-block tables.
  1980. + *                                   - mount systemcall
  1981. + *                                   - umount systemcall
  1982.   */
  1983.  
  1984. -/*
  1985. - * super.c contains code to handle the super-block tables.
  1986. - */
  1987.  #include <stdarg.h>
  1988.  
  1989.  #include <linux/config.h>
  1990.  #include <linux/sched.h>
  1991.  #include <linux/kernel.h>
  1992. +#include <linux/mount.h>
  1993. +#include <linux/malloc.h>
  1994.  #include <linux/major.h>
  1995.  #include <linux/stat.h>
  1996.  #include <linux/errno.h>
  1997. @@ -21,23 +25,112 @@
  1998.  #include <asm/system.h>
  1999.  #include <asm/segment.h>
  2000.  #include <asm/bitops.h>
  2001. +
  2002.  extern struct file_operations * get_blkfops(unsigned int);
  2003. -extern struct file_operations * get_chrfops(unsigned int);
  2004.  
  2005.  extern void wait_for_keypress(void);
  2006.  extern void fcntl_init_locks(void);
  2007.  
  2008.  extern int root_mountflags;
  2009.  
  2010. -struct super_block super_blocks[NR_SUPER];
  2011. -
  2012.  static int do_remount_sb(struct super_block *sb, int flags, char * data);
  2013.  
  2014. -/* this is initialized in init/main.c */
  2015. +/*
  2016. + * This is initialized in init/main.c
  2017. + */
  2018.  dev_t ROOT_DEV = 0;
  2019.  
  2020. -static struct file_system_type * file_systems = NULL;
  2021. +struct super_block super_blocks[NR_SUPER];
  2022. +static struct file_system_type *file_systems = (struct file_system_type *) NULL;
  2023. +static struct vfsmount *vfsmntlist = (struct vfsmount *) NULL,
  2024. +                       *vfsmnttail = (struct vfsmount *) NULL,
  2025. +                       *mru_vfsmnt = (struct vfsmount *) NULL;
  2026. +
  2027. +/* 
  2028. + * This part handles the management of the list of mounted filesystems.
  2029. + * Superblock retrieval is also done with this list.
  2030. + */
  2031. +struct vfsmount *lookup_vfsmnt(dev_t dev)
  2032. +{
  2033. +    register struct vfsmount *lptr;
  2034. +
  2035. +    if (vfsmntlist == (struct vfsmount *) 0)
  2036. +        return ((struct vfsmount *) 0);
  2037. +
  2038. +    if (mru_vfsmnt != (struct vfsmount *) 0 && mru_vfsmnt->mnt_dev == dev)
  2039. +        return (mru_vfsmnt);
  2040. +
  2041. +    for (lptr = vfsmntlist; lptr != (struct vfsmount *)0; lptr = lptr->mnt_next)
  2042. +        if (lptr->mnt_dev == dev)
  2043. +            return (lptr);
  2044. +
  2045. +    return ((struct vfsmount *) 0);
  2046. +    /* NOTREACHED */
  2047. +}
  2048. +
  2049. +static struct vfsmount *add_vfsmnt(dev_t dev, const char *dev_name,
  2050. +                   const char *dir_name)
  2051. +{
  2052. +    register struct vfsmount *lptr;
  2053. +    char *tmp;
  2054. +
  2055. +    if ((lptr = (struct vfsmount *)
  2056. +         kmalloc(sizeof(struct vfsmount), GFP_KERNEL)) == (struct vfsmount *) 0)
  2057. +        panic("VFS: Unable to allocate memory for vfsmount devicelist");
  2058. +
  2059. +    memset(lptr, 0, sizeof(struct vfsmount));
  2060. +    lptr->mnt_dev = dev;
  2061. +    if (dev_name) {
  2062. +        if (!getname(dev_name, &tmp)) {
  2063. +            if ((lptr->mnt_devname =
  2064. +                (char *) kmalloc(strlen(tmp), GFP_KERNEL)) != (char *)0)
  2065. +                strcpy(lptr->mnt_devname, tmp);
  2066. +            putname(tmp);
  2067. +        }
  2068. +    }
  2069. +    if (dir_name) {
  2070. +        if (!getname(dir_name, &tmp)) {
  2071. +            if ((lptr->mnt_dirname =
  2072. +                (char *) kmalloc(strlen(tmp), GFP_KERNEL)) != (char *)0)
  2073. +            strcpy(lptr->mnt_dirname, tmp);
  2074. +            putname(tmp);
  2075. +        }
  2076. +    }
  2077. +
  2078. +    if (vfsmntlist == (struct vfsmount *)0)
  2079. +        vfsmntlist = vfsmnttail = lptr;
  2080. +    else {
  2081. +        vfsmnttail->mnt_next = lptr;
  2082. +        vfsmnttail = lptr;
  2083. +    }
  2084. +    return (lptr);
  2085. +}
  2086. +
  2087. +static void remove_vfsmnt(dev_t dev)
  2088. +{
  2089. +    register struct vfsmount *lptr, *tofree;
  2090. +
  2091. +    if (vfsmntlist == (struct vfsmount *) 0)
  2092. +        return;
  2093. +    lptr = vfsmntlist;
  2094. +    if (lptr->mnt_dev == dev) {
  2095. +        tofree = lptr;
  2096. +        vfsmntlist = lptr->mnt_next;
  2097. +    } else {
  2098. +        while (lptr->mnt_next != (struct vfsmount *) 0) {
  2099. +            if (lptr->mnt_next->mnt_dev == dev)
  2100. +                break;
  2101. +            lptr = lptr->mnt_next;
  2102. +        }
  2103. +        tofree = lptr->mnt_next;
  2104. +        if (vfsmnttail->mnt_dev == dev)
  2105. +            vfsmnttail = lptr;
  2106. +        lptr->mnt_next = lptr->mnt_next->mnt_next;
  2107. +    }
  2108. +    kfree(tofree->mnt_devname);
  2109. +    kfree(tofree->mnt_dirname);
  2110. +    kfree_s(tofree, sizeof(struct vfsmount));
  2111. +}
  2112.  
  2113.  int register_filesystem(struct file_system_type * fs)
  2114.  {
  2115. @@ -319,17 +412,30 @@
  2116.              MAJOR(dev), MINOR(dev));
  2117.  }
  2118.  
  2119. +extern void acct_auto_close(dev_t dev);
  2120. +
  2121.  static int do_umount(dev_t dev)
  2122.  {
  2123.      struct super_block * sb;
  2124.      int retval;
  2125.      
  2126.      if (dev==ROOT_DEV) {
  2127. -        /* Special case for "unmounting" root.  We just try to remount
  2128. -           it readonly, and sync() the device. */
  2129. +        /*
  2130. +         * Special case for "unmounting" root. We just try to remount
  2131. +         * it readonly, and sync() the device.
  2132. +         */
  2133.          if (!(sb=get_super(dev)))
  2134.              return -ENOENT;
  2135.          if (!(sb->s_flags & MS_RDONLY)) {
  2136. +#ifdef CONFIG_QUOTA
  2137. +            /*
  2138. +             * Make sure all quotas are turned off on this device we need to mount
  2139. +             * it readonly so no more writes by the quotasystem.
  2140. +             * If later on the remount fails to bad there are no quotas running
  2141. +             * anymore. Turn them on again by hand.
  2142. +             */
  2143. +            (void) quota_off(dev, -1);
  2144. +#endif
  2145.              fsync_dev(dev);
  2146.              retval = do_remount_sb(sb, MS_RDONLY, 0);
  2147.              if (retval)
  2148. @@ -342,6 +448,18 @@
  2149.      if (!sb->s_covered->i_mount)
  2150.          printk("VFS: umount(%d/%d): mounted inode has i_mount=NULL\n",
  2151.                              MAJOR(dev), MINOR(dev));
  2152. +#ifdef CONFIG_QUOTA
  2153. +    /*
  2154. +     * Before checking if the filesystem is still busy make sure the kernel
  2155. +     * doesn't hold any quotafiles open on that device. If the umount fails
  2156. +     * to bad there are no quotas running anymore. Turn them on again by hand.
  2157. +     */
  2158. +    (void) quota_off(dev, -1);
  2159. +#endif
  2160. +    /*
  2161. +     * The same as for quota is also true for the accounting file.
  2162. +     */
  2163. +    acct_auto_close(dev);
  2164.      if (!fs_may_umount(dev, sb->s_mounted))
  2165.          return -EBUSY;
  2166.      sb->s_covered->i_mount = NULL;
  2167. @@ -352,6 +470,7 @@
  2168.      if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
  2169.          sb->s_op->write_super(sb);
  2170.      put_super(dev);
  2171. +    remove_vfsmnt(dev);
  2172.      return 0;
  2173.  }
  2174.  
  2175. @@ -427,13 +546,15 @@
  2176.   * We also have to flush all inode-data for this device, as the new mount
  2177.   * might need new info.
  2178.   */
  2179. -static int do_mount(dev_t dev, const char * dir, char * type, int flags, void * data)
  2180. +static int do_mount(dev_t dev, const char * dev_name, const char * dir_name,
  2181. +            char * type, int flags, void * data)
  2182.  {
  2183.      struct inode * dir_i;
  2184.      struct super_block * sb;
  2185. +    struct vfsmount *vfsmnt;
  2186.      int error;
  2187.  
  2188. -    error = namei(dir,&dir_i);
  2189. +    error = namei(dir_name,&dir_i);
  2190.      if (error)
  2191.          return error;
  2192.      if (dir_i->i_count != 1 || dir_i->i_mount) {
  2193. @@ -453,6 +574,9 @@
  2194.          iput(dir_i);
  2195.          return -EBUSY;
  2196.      }
  2197. +    vfsmnt = add_vfsmnt(dev, dev_name, dir_name);
  2198. +    vfsmnt->mnt_sb = sb;
  2199. +    vfsmnt->mnt_sem.count = 1;
  2200.      sb->s_covered = dir_i;
  2201.      dir_i->i_mount = sb->s_mounted;
  2202.      return 0;        /* we don't iput(dir_i) - see umount */
  2203. @@ -623,7 +747,7 @@
  2204.              return retval;
  2205.          }
  2206.      }
  2207. -    retval = do_mount(dev,dir_name,t,flags,(void *) page);
  2208. +    retval = do_mount(dev,dev_name,dir_name,t,flags,(void *) page);
  2209.      free_page(page);
  2210.      if (retval && fops && fops->release)
  2211.          fops->release(inode, NULL);
  2212. @@ -635,10 +759,11 @@
  2213.  {
  2214.      struct file_system_type * fs_type;
  2215.      struct super_block * sb;
  2216. +    struct vfsmount *vfsmnt;
  2217.      struct inode * inode, d_inode;
  2218.      struct file filp;
  2219.      int retval;
  2220. -
  2221. +  
  2222.      memset(super_blocks, 0, sizeof(super_blocks));
  2223.      fcntl_init_locks();
  2224.      if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
  2225. @@ -664,9 +789,9 @@
  2226.      for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {
  2227.          if(retval)
  2228.              break;
  2229. -        if (!fs_type->requires_dev)
  2230. -            continue;
  2231. -        sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1);
  2232. +          if (!fs_type->requires_dev)
  2233. +              continue;
  2234. +          sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1);
  2235.          if (sb) {
  2236.              inode = sb->s_mounted;
  2237.              inode->i_count += 3 ;    /* NOTE! it is logically used 4 times, not 1 */
  2238. @@ -677,6 +802,9 @@
  2239.              printk ("VFS: Mounted root (%s filesystem)%s.\n",
  2240.                  fs_type->name,
  2241.                  (sb->s_flags & MS_RDONLY) ? " readonly" : "");
  2242. +            vfsmnt = add_vfsmnt(ROOT_DEV, "rootfs", "/");
  2243. +            vfsmnt->mnt_sb = sb;
  2244. +            vfsmnt->mnt_sem.count = 1;
  2245.              return;
  2246.          }
  2247.      }
  2248. diff -ru --new-file linux_1.1.58/ibcs/binfmt_coff.c linux_1.1.58_owld/ibcs/binfmt_coff.c
  2249. --- linux_1.1.58/ibcs/binfmt_coff.c    Wed Aug 10 23:29:32 1994
  2250. +++ linux_1.1.58_owld/ibcs/binfmt_coff.c    Wed Aug 10 23:30:10 1994
  2251. @@ -455,6 +455,8 @@
  2252.  /*
  2253.   *  Do the end processing once the stack has been constructed
  2254.   */
  2255. +            current->flags          &= ~PF_FORKNOEXEC; /* accounting flags */
  2256. +            current->io_usage        = 0;
  2257.          current->mm->start_code  = text_vaddr & PAGE_MASK;
  2258.          current->mm->end_code    = text_vaddr + text_size;
  2259.          current->mm->end_data    = data_vaddr + data_size;
  2260. diff -ru --new-file linux_1.1.58/include/linux/acct.h linux_1.1.58_owld/include/linux/acct.h
  2261. --- linux_1.1.58/include/linux/acct.h    Thu Jan  1 01:00:00 1970
  2262. +++ linux_1.1.58_owld/include/linux/acct.h    Wed May  4 17:34:46 1994
  2263. @@ -0,0 +1,28 @@
  2264. +#ifndef __LINUX_ACCT_H
  2265. +#define __LINUX_ACCT_H
  2266. +
  2267. +#define ACCT_COMM 16
  2268. +
  2269. +struct acct
  2270. +{
  2271. +   char          ac_comm[ACCT_COMM];    /* Accounting command name */
  2272. +   time_t        ac_utime;        /* Accounting user time */
  2273. +   time_t        ac_stime;        /* Accounting system time */
  2274. +   time_t        ac_etime;        /* Accounting elapsed time */
  2275. +   time_t        ac_btime;        /* Beginning time */
  2276. +   uid_t         ac_uid;        /* Accounting user ID */
  2277. +   gid_t         ac_gid;        /* Accounting group ID */
  2278. +   dev_t         ac_tty;        /* controlling tty */
  2279. +   char          ac_flag;        /* Accounting flag */
  2280. +   unsigned long ac_mem;        /* Pages of memory used */
  2281. +   unsigned long ac_io;            /* Number of bytes read/written */
  2282. +};
  2283. +
  2284. +#define AFORK    0001    /* has executed fork, but no exec */
  2285. +#define ASU    0002    /* used super-user privileges */
  2286. +#define ACORE    0004    /* dumped core */
  2287. +#define AXSIG    0010    /* killed by a signal */
  2288. +
  2289. +#define AHZ     100
  2290. +
  2291. +#endif
  2292. diff -ru --new-file linux_1.1.58/include/linux/fileio.h linux_1.1.58_owld/include/linux/fileio.h
  2293. --- linux_1.1.58/include/linux/fileio.h    Thu Jan  1 01:00:00 1970
  2294. +++ linux_1.1.58_owld/include/linux/fileio.h    Mon Oct 24 22:18:57 1994
  2295. @@ -0,0 +1,70 @@
  2296. +/*
  2297. + *
  2298. + * Simple VFS definitions for fileio.
  2299. + *
  2300. + * Authors: Marco van Wieringen <v892273@si.hhs.nl> <mvw@mcs.ow.org>
  2301. + *          Edvard Tuinder <v892231@si.hhs.nl> <ed@delirium.ow.org>
  2302. + *
  2303. + * Version: $Id: fileio.h,v 1.6 1994/10/24 21:18:20 mvw Exp mvw $
  2304. + *
  2305. + */
  2306. +#ifndef _LINUX_FILEIO_H
  2307. +#define _LINUX_FILEIO_H
  2308. +
  2309. +#include <linux/config.h>
  2310. +#include <linux/stat.h>
  2311. +
  2312. +#ifdef CONFIG_QUOTA
  2313. +
  2314. +int vfs_write(struct inode *ino, struct file *file, char *addr, size_t bytes);
  2315. +int vfs_create(struct inode *dir, const char *basename,
  2316. +               int namelen, int mode, struct inode **res_ino);
  2317. +int vfs_truncate(struct inode *ino, size_t length);
  2318. +int vfs_mknod(struct inode *dir, const char *basename,
  2319. +              int namelen, int mode, dev_t dev);
  2320. +int vfs_mkdir(struct inode *dir, const char *basename, int namelen, int mode);
  2321. +int vfs_rmdir(struct inode *dir, const char *basename, int namelen);
  2322. +int vfs_unlink(struct inode *dir, const char *basename, int namelen);
  2323. +int vfs_symlink(struct inode *dir, const char *basename,
  2324. +                int namelen, const char *oldname);
  2325. +int vfs_chown(struct inode *ino, uid_t uid, gid_t gid);
  2326. +int vfs_rename(struct inode *old_dir, const char *old_base, int old_len,
  2327. +               struct inode *new_dir, const char *mew_base, int new_len);
  2328. +void vfs_open(struct file *filp);
  2329. +void vfs_close(struct file *filp);
  2330. +
  2331. +#else /* CONFIG_QUOTA */
  2332. +
  2333. +#define vfs_write(ino, file, addr, bytes) \
  2334. +(file)->f_op->write((ino),(file),(addr),(bytes))
  2335. +
  2336. +#define vfs_create(dir, basename, namelen, mode, res_ino) \
  2337. +(dir)->i_op->create((dir),(basename),(namelen),(mode),(res_ino))
  2338. +
  2339. +int vfs_truncate(struct inode *ino, size_t length);
  2340. +
  2341. +#define vfs_mknod(dir, basename, namelen, mode, dev) \
  2342. +(dir)->i_op->mknod((dir),(basename),(namelen),(mode),(dev))
  2343. +
  2344. +#define vfs_mkdir(dir, basename, namelen, mode) \
  2345. +(dir)->i_op->mkdir((dir),(basename),(namelen),(mode))
  2346. +
  2347. +#define vfs_rmdir(dir, basename, namelen) \
  2348. +(dir)->i_op->rmdir((dir),(basename),(namelen))
  2349. +
  2350. +#define vfs_unlink(dir, basename, namelen) \
  2351. +(dir)->i_op->unlink((dir),(basename),(namelen))
  2352. +
  2353. +#define vfs_symlink(dir, basename, namelen, oldname) \
  2354. +(dir)->i_op->symlink((dir),(basename),(namelen),(oldname))
  2355. +
  2356. +int vfs_chown(struct inode *ino, uid_t uid, gid_t gid);
  2357. +
  2358. +#define vfs_rename(old_dir, old_base, old_len, new_dir, new_base, new_len) \
  2359. +(old_dir)->i_op->rename((old_dir),(old_base),(old_len),(new_dir),(new_base),(new_len))
  2360. +
  2361. +void vfs_open(struct file *filp);
  2362. +void vfs_close(struct file *filp);
  2363. +
  2364. +#endif /* CONFIG_QUOTA */
  2365. +#endif /* _LINUX_FILEIO_H */
  2366. diff -ru --new-file linux_1.1.58/include/linux/fs.h linux_1.1.58_owld/include/linux/fs.h
  2367. --- linux_1.1.58/include/linux/fs.h    Mon Oct 24 19:56:10 1994
  2368. +++ linux_1.1.58_owld/include/linux/fs.h    Mon Oct 24 20:01:51 1994
  2369. @@ -164,6 +164,7 @@
  2370.  #include <linux/nfs_fs_i.h>
  2371.  #include <linux/xia_fs_i.h>
  2372.  #include <linux/sysv_fs_i.h>
  2373. +#include <linux/quota.h>
  2374.  
  2375.  #ifdef __KERNEL__
  2376.  
  2377. @@ -225,7 +226,9 @@
  2378.      struct inode * i_bound_to, * i_bound_by;
  2379.      struct inode * i_mount;
  2380.      struct socket * i_socket;
  2381. +    struct dquot * i_dquot[MAXQUOTAS];
  2382.      unsigned short i_count;
  2383. +    unsigned short i_writecount;
  2384.      unsigned short i_flags;
  2385.      unsigned char i_lock;
  2386.      unsigned char i_dirt;
  2387. diff -ru --new-file linux_1.1.58/include/linux/kernel.h linux_1.1.58_owld/include/linux/kernel.h
  2388. --- linux_1.1.58/include/linux/kernel.h    Fri Aug 12 13:00:28 1994
  2389. +++ linux_1.1.58_owld/include/linux/kernel.h    Fri Aug 12 13:01:20 1994
  2390. @@ -54,19 +54,6 @@
  2391.  asmlinkage int printk(const char * fmt, ...)
  2392.      __attribute__ ((format (printf, 1, 2)));
  2393.  
  2394. -/*
  2395. - * This is defined as a macro, but at some point this might become a
  2396. - * real subroutine that sets a flag if it returns true (to do
  2397. - * BSD-style accounting where the process is flagged if it uses root
  2398. - * privs).  The implication of this is that you should do normal
  2399. - * permissions checks first, and check suser() last.
  2400. - *
  2401. - * "suser()" checks against the effective user id, while "fsuser()"
  2402. - * is used for file permission checking and checks against the fsuid..
  2403. - */
  2404. -#define suser() (current->euid == 0)
  2405. -#define fsuser() (current->fsuid == 0)
  2406. -
  2407.  extern int splx (int new_ipl);
  2408.  #endif /* __KERNEL__ */
  2409.  
  2410. diff -ru --new-file linux_1.1.58/include/linux/mount.h linux_1.1.58_owld/include/linux/mount.h
  2411. --- linux_1.1.58/include/linux/mount.h    Thu Jan  1 01:00:00 1970
  2412. +++ linux_1.1.58_owld/include/linux/mount.h    Wed Sep  7 23:08:40 1994
  2413. @@ -0,0 +1,34 @@
  2414. +/*
  2415. + *
  2416. + * Definitions for mount interface. This describes the in the kernel build 
  2417. + * linkedlist with mounted filesystems.
  2418. + *
  2419. + * Authors: Marco van Wieringen <v892273@si.hhs.nl> <mvw@mcs.ow.org>
  2420. + *          Edvard Tuinder <v892231@si.hhs.nl> <ed@delirium.ow.org>
  2421. + *
  2422. + * Version: $Id: mount.h,v 1.3 1994/07/20 22:01:00 mvw Exp mvw $
  2423. + *
  2424. + */
  2425. +#ifndef _LINUX_MOUNT_H
  2426. +#define _LINUX_MOUNT_H
  2427. +
  2428. +#define QF_OPENING  0x01        /* Quotafile is in progress of being opened */
  2429. +#define QF_CLOSING  0x02        /* Quotafile is in progress of being closed */
  2430. +
  2431. +struct vfsmount
  2432. +{
  2433. +   dev_t mnt_dev;                      /* Device this applies to */
  2434. +   char *mnt_devname;                  /* Name of device e.g. /dev/dsk/hda1 */
  2435. +   char *mnt_dirname;                  /* Name of directory mounted on */
  2436. +   unsigned int mnt_flags;             /* Flags of this device see above */
  2437. +   struct semaphore mnt_sem;           /* lock device while I/O in progress */
  2438. +   struct super_block *mnt_sb;         /* pointer to superblock */
  2439. +   struct file *mnt_quotas[MAXQUOTAS]; /* fp's to quotafiles */
  2440. +   time_t mnt_iexp[MAXQUOTAS];         /* expiretime for inodes */
  2441. +   time_t mnt_bexp[MAXQUOTAS];         /* expiretime for blocks */
  2442. +   struct vfsmount *mnt_next;          /* pointer to next in linkedlist */
  2443. +};
  2444. +
  2445. +struct vfsmount *lookup_vfsmnt(dev_t dev);
  2446. +
  2447. +#endif /* _LINUX_MOUNT_H */
  2448. diff -ru --new-file linux_1.1.58/include/linux/quota.h linux_1.1.58_owld/include/linux/quota.h
  2449. --- linux_1.1.58/include/linux/quota.h    Thu Jan  1 01:00:00 1970
  2450. +++ linux_1.1.58_owld/include/linux/quota.h    Wed May  4 17:34:46 1994
  2451. @@ -0,0 +1,208 @@
  2452. +/*
  2453. + * Copyright (c) 1982, 1986 Regents of the University of California.
  2454. + * All rights reserved.
  2455. + *
  2456. + * This code is derived from software contributed to Berkeley by
  2457. + * Robert Elz at The University of Melbourne.
  2458. + *
  2459. + * Redistribution and use in source and binary forms, with or without
  2460. + * modification, are permitted provided that the following conditions
  2461. + * are met:
  2462. + * 1. Redistributions of source code must retain the above copyright
  2463. + *    notice, this list of conditions and the following disclaimer.
  2464. + * 2. Redistributions in binary form must reproduce the above copyright
  2465. + *    notice, this list of conditions and the following disclaimer in the
  2466. + *    documentation and/or other materials provided with the distribution.
  2467. + * 3. All advertising materials mentioning features or use of this software
  2468. + *    must display the following acknowledgement:
  2469. + *   This product includes software developed by the University of
  2470. + *   California, Berkeley and its contributors.
  2471. + * 4. Neither the name of the University nor the names of its contributors
  2472. + *    may be used to endorse or promote products derived from this software
  2473. + *    without specific prior written permission.
  2474. + *
  2475. + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  2476. + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  2477. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  2478. + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  2479. + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  2480. + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  2481. + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  2482. + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  2483. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  2484. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  2485. + * SUCH DAMAGE.
  2486. + *
  2487. + * Version: $Id: quota.h,v 1.5 1994/01/06 20:45:20 mvw Exp mvw $
  2488. + */
  2489. +
  2490. +#ifndef _LINUX_QUOTA_
  2491. +#define _LINUX_QUOTA_
  2492. +
  2493. +#include <linux/errno.h>
  2494. +
  2495. +/*
  2496. + * Convert diskblocks to blocks and the other way around.
  2497. + * currently only to fool the BSD source. :-)
  2498. + */
  2499. +#define dbtob(num) (num << 10)
  2500. +#define btodb(num) (num >> 10)
  2501. +
  2502. +/*
  2503. + * Definitions for disk quotas imposed on the average user
  2504. + * (big brother finally hits Linux).
  2505. + *
  2506. + * The following constants define the amount of time given a user
  2507. + * before the soft limits are treated as hard limits (usually resulting
  2508. + * in an allocation failure). The timer is started when the user crosses
  2509. + * their soft limit, it is reset when they go below their soft limit.
  2510. + */
  2511. +#define MAX_IQ_TIME  604800    /* (7*24*60*60) 1 week */
  2512. +#define MAX_DQ_TIME  604800    /* (7*24*60*60) 1 week */
  2513. +
  2514. +#define MAXQUOTAS 2
  2515. +#define USRQUOTA  0        /* element used for user quotas */
  2516. +#define GRPQUOTA  1        /* element used for group quotas */
  2517. +
  2518. +/*
  2519. + * Definitions for the default names of the quotas files.
  2520. + */
  2521. +#define INITQFNAMES { \
  2522. +   "user",      /* USRQUOTA */ \
  2523. +   "group",   /* GRPQUOTA */ \
  2524. +   "undefined", \
  2525. +};
  2526. +
  2527. +#define QUOTAFILENAME "quota"
  2528. +#define QUOTAGROUP "staff"
  2529. +
  2530. +#define NR_DQHASH 43            /* Just an arbitrary number any suggestions ? */
  2531. +#define NR_DQUOTS 256           /* Number of quotas active at one time */
  2532. +
  2533. +/*
  2534. + * Command definitions for the 'quotactl' system call.
  2535. + * The commands are broken into a main command defined below
  2536. + * and a subcommand that is used to convey the type of
  2537. + * quota that is being manipulated (see above).
  2538. + */
  2539. +#define SUBCMDMASK  0x00ff
  2540. +#define SUBCMDSHIFT 8
  2541. +#define QCMD(cmd, type)  (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK))
  2542. +
  2543. +#define Q_QUOTAON  0x0100    /* enable quotas */
  2544. +#define Q_QUOTAOFF 0x0200    /* disable quotas */
  2545. +#define Q_GETQUOTA 0x0300    /* get limits and usage */
  2546. +#define Q_SETQUOTA 0x0400    /* set limits and usage */
  2547. +#define Q_SETUSE   0x0500    /* set usage */
  2548. +#define Q_SYNC     0x0600    /* sync disk copy of a filesystems quotas */
  2549. +#define Q_SETQLIM  0x0700    /* set limits */
  2550. +
  2551. +/*
  2552. + * The following structure defines the format of the disk quota file
  2553. + * (as it appears on disk) - the file is an array of these structures
  2554. + * indexed by user or group number.
  2555. + */
  2556. +struct dqblk
  2557. +  {
  2558. +    u_long dqb_bhardlimit;    /* absolute limit on disk blks alloc */
  2559. +    u_long dqb_bsoftlimit;    /* preferred limit on disk blks */
  2560. +    u_long dqb_curblocks;    /* current block count */
  2561. +    u_long dqb_ihardlimit;    /* maximum # allocated inodes */
  2562. +    u_long dqb_isoftlimit;    /* preferred inode limit */
  2563. +    u_long dqb_curinodes;    /* current # allocated inodes */
  2564. +    time_t dqb_btime;        /* time limit for excessive disk use */
  2565. +    time_t dqb_itime;        /* time limit for excessive files */
  2566. +  };
  2567. +
  2568. +/*
  2569. + * Shorthand notation.
  2570. + */
  2571. +#define    dq_bhardlimit    dq_dqb.dqb_bhardlimit
  2572. +#define    dq_bsoftlimit    dq_dqb.dqb_bsoftlimit
  2573. +#define    dq_curblocks    dq_dqb.dqb_curblocks
  2574. +#define    dq_ihardlimit    dq_dqb.dqb_ihardlimit
  2575. +#define    dq_isoftlimit    dq_dqb.dqb_isoftlimit
  2576. +#define    dq_curinodes    dq_dqb.dqb_curinodes
  2577. +#define    dq_btime    dq_dqb.dqb_btime
  2578. +#define    dq_itime    dq_dqb.dqb_itime
  2579. +
  2580. +#define dqoff(UID)      ((off_t)((UID) * sizeof (struct dqblk)))
  2581. +
  2582. +#ifdef __KERNEL__
  2583. +
  2584. +/*
  2585. + * Maximum lenght of a message generated in the quota system,
  2586. + * that needs to be kicked onto the tty.
  2587. + */
  2588. +#define MAX_QUOTA_MESSAGE 75
  2589. +
  2590. +#define DQ_LOCKED     0x01    /* locked for update */
  2591. +#define DQ_WANT       0x02    /* wanted for update */
  2592. +#define DQ_MOD        0x04    /* dquot modified since read */
  2593. +#define DQ_BLKS       0x10    /* uid/gid has been warned about blk limit */
  2594. +#define DQ_INODES     0x20    /* uid/gid has been warned about inode limit */
  2595. +#define DQ_FAKE       0x40    /* no limits only usage */
  2596. +
  2597. +struct dquot
  2598. +{
  2599. +   unsigned int dq_id;        /* id this applies to (uid, gid) */
  2600. +   short dq_type;        /* type of quota */
  2601. +   dev_t dq_dev;                /* Device this applies to */
  2602. +   short dq_flags;        /* see DQ_* */
  2603. +   short dq_count;        /* reference count */
  2604. +   struct vfsmount *dq_mnt;     /* vfsmountpoint this applies to */
  2605. +   struct dqblk dq_dqb;         /* diskquota usage */
  2606. +   struct wait_queue *dq_wait;    /* pointer to waitqueue */
  2607. +   struct dquot *dq_prev;    /* pointer to prev dquot */
  2608. +   struct dquot *dq_next;    /* pointer to next dquot */
  2609. +   struct dquot *dq_hash_prev;    /* pointer to prev dquot */
  2610. +   struct dquot *dq_hash_next;    /* pointer to next dquot */
  2611. +};
  2612. +
  2613. +#define NODQUOT (struct dquot *)NULL
  2614. +
  2615. +/*
  2616. + * Flags used for set_dqblk.
  2617. + */
  2618. +#define QUOTA_SYSCALL     0x01
  2619. +#define SET_QUOTA         0x02
  2620. +#define SET_USE           0x04
  2621. +#define SET_QLIMIT        0x08
  2622. +
  2623. +/*
  2624. + * Return values when requesting quota.
  2625. + */
  2626. +#define NO_QUOTA 0        /* no more quota available */
  2627. +#define QUOTA_OK 1        /* can allocate the space */
  2628. +
  2629. +/*
  2630. + * declaration of quota_function calls in kernel.
  2631. + */
  2632. +struct dquot *dqget (dev_t dev, unsigned int id, short type);
  2633. +void dqput (struct dquot *dquot);
  2634. +
  2635. +int quota_off (dev_t dev, short type);
  2636. +int sync_dquots (dev_t dev, short type);
  2637. +
  2638. +u_long isize_to_blocks (size_t isize, size_t blksize);
  2639. +size_t blocks_to_isize (u_long blocks, size_t blksize);
  2640. +
  2641. +void quota_remove (struct inode *inode, u_long inodes, u_long blocks);
  2642. +int quota_alloc (struct inode *inode, u_long wantedinodes,
  2643. +                 u_long wantedblocks, u_long * availblocks);
  2644. +int quota_transfer (struct inode *inode, uid_t newuid,
  2645. +                    gid_t newgid, u_long inodes, u_long blocks);
  2646. +
  2647. +void getinoquota (struct inode *inode, short type);
  2648. +void putinoquota (struct inode *inode);
  2649. +
  2650. +#else
  2651. +
  2652. +#include <sys/cdefs.h>
  2653. +
  2654. +__BEGIN_DECLS
  2655. +int quotactl __P ((int, const char *, int, caddr_t));
  2656. +__END_DECLS
  2657. +
  2658. +#endif /* __KERNEL__ */
  2659. +#endif /* _QUOTA_ */
  2660. diff -ru --new-file linux_1.1.58/include/linux/sched.h linux_1.1.58_owld/include/linux/sched.h
  2661. --- linux_1.1.58/include/linux/sched.h    Fri Aug 19 18:59:35 1994
  2662. +++ linux_1.1.58_owld/include/linux/sched.h    Fri Aug 19 19:00:31 1994
  2663. @@ -280,6 +280,7 @@
  2664.      long utime, stime, cutime, cstime, start_time;
  2665.      struct rlimit rlim[RLIM_NLIMITS]; 
  2666.      unsigned short used_math;
  2667. +    unsigned long io_usage; /* number of bytes read/written */
  2668.      char comm[16];
  2669.  /* virtual 86 mode stuff */
  2670.      struct vm86_struct * vm86_info;
  2671. @@ -310,6 +311,10 @@
  2672.                      /* Not implemented yet, only for 486*/
  2673.  #define PF_PTRACED    0x00000010    /* set if ptrace (0) has been called. */
  2674.  #define PF_TRACESYS    0x00000020    /* tracing system calls */
  2675. +#define PF_FORKNOEXEC    0x00000040    /* forked but didn't exec */
  2676. +#define PF_SUPERPREV    0x00000100    /* used super-user privileges */
  2677. +#define PF_DUMPCORE    0x00000200    /* dumped core */
  2678. +#define PF_SIGNALED    0x00000400    /* killed by a signal */
  2679.  
  2680.  /*
  2681.   * cloning flags:
  2682. @@ -340,6 +345,7 @@
  2683.            {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX},  \
  2684.            {       0, LONG_MAX}, {LONG_MAX, LONG_MAX}}, \
  2685.  /* math */    0, \
  2686. +/* io_usage */  0, \
  2687.  /* comm */    "swapper", \
  2688.  /* vm86_info */    NULL, 0, 0, 0, 0, \
  2689.  /* fs info */    0,NULL, \
  2690. @@ -449,6 +455,29 @@
  2691.  
  2692.  #define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base )
  2693.  #define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 )
  2694. +
  2695. +/*
  2696. + * This has now become a routine instead of a macro, it sets a flag if
  2697. + * it returns true (to do BSD-style accounting where the process is flagged
  2698. + * if it uses root privs). The implication of this is that you should do
  2699. + * normal permissions checks first, and check suser() last.
  2700. + *
  2701. + * "suser()" checks against the effective user id, while "fsuser()"
  2702. + * is used for file permission checking and checks against the fsuid..
  2703. + */
  2704. +extern inline int suser(void)
  2705. +{
  2706. +    if (current->euid == 0)
  2707. +        current->flags |= PF_SUPERPREV;
  2708. +    return (current->euid == 0);
  2709. +}
  2710. +
  2711. +extern inline int fsuser(void)
  2712. +{
  2713. +    if (current->fsuid == 0)
  2714. +        current->flags |= PF_SUPERPREV;
  2715. +    return (current->fsuid == 0);
  2716. +}
  2717.  
  2718.  /*
  2719.   * The wait-queues are circular lists, and you have to be *very* sure
  2720. diff -ru --new-file linux_1.1.58/include/linux/sys.h linux_1.1.58_owld/include/linux/sys.h
  2721. --- linux_1.1.58/include/linux/sys.h    Mon Apr 18 22:42:22 1994
  2722. +++ linux_1.1.58_owld/include/linux/sys.h    Wed May  4 17:34:46 1994
  2723. @@ -32,6 +32,5 @@
  2724.   * These are system calls that haven't been implemented yet
  2725.   * but have an entry in the table for future expansion..
  2726.   */
  2727. -#define _sys_quotactl    _sys_ni_syscall
  2728.  
  2729.  #endif
  2730. diff -ru --new-file linux_1.1.58/include/linux/tty.h linux_1.1.58_owld/include/linux/tty.h
  2731. --- linux_1.1.58/include/linux/tty.h    Fri Oct 21 09:57:34 1994
  2732. +++ linux_1.1.58_owld/include/linux/tty.h    Fri Oct 21 09:57:58 1994
  2733. @@ -292,6 +292,7 @@
  2734.  extern int tty_unregister_driver(struct tty_driver *driver);
  2735.  extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
  2736.                   int buflen);
  2737. +extern void tty_write_message(struct tty_struct *tty, char *msg);
  2738.  
  2739.  extern int is_orphaned_pgrp(int pgrp);
  2740.  extern int is_ignored(int sig);
  2741. diff -ru --new-file linux_1.1.58/init/main.c linux_1.1.58_owld/init/main.c
  2742. --- linux_1.1.58/init/main.c    Mon Oct 24 19:56:10 1994
  2743. +++ linux_1.1.58_owld/init/main.c    Mon Oct 24 20:01:52 1994
  2744. @@ -103,6 +103,9 @@
  2745.  #ifdef CONFIG_SYSVIPC
  2746.  extern void ipc_init(void);
  2747.  #endif
  2748. +#ifdef CONFIG_QUOTA
  2749. +extern void quota_init(void);
  2750. +#endif
  2751.  #ifdef CONFIG_SCSI
  2752.  extern unsigned long scsi_dev_init(unsigned long, unsigned long);
  2753.  #endif
  2754. @@ -462,6 +465,9 @@
  2755.      sock_init();
  2756.  #ifdef CONFIG_SYSVIPC
  2757.      ipc_init();
  2758. +#endif
  2759. +#ifdef CONFIG_QUOTA
  2760. +    quota_init();
  2761.  #endif
  2762.      sti();
  2763.  
  2764. diff -ru --new-file linux_1.1.58/kernel/exit.c linux_1.1.58_owld/kernel/exit.c
  2765. --- linux_1.1.58/kernel/exit.c    Wed Aug 10 23:29:34 1994
  2766. +++ linux_1.1.58_owld/kernel/exit.c    Wed Aug 10 23:30:13 1994
  2767. @@ -19,6 +19,7 @@
  2768.  #include <asm/segment.h>
  2769.  extern void shm_exit (void);
  2770.  extern void sem_exit (void);
  2771. +extern void acct_process (void);
  2772.  
  2773.  int getrusage(struct task_struct *, int, struct rusage *);
  2774.  
  2775. @@ -411,6 +412,7 @@
  2776.          intr_count = 0;
  2777.      }
  2778.  fake_volatile:
  2779. +    acct_process();
  2780.      if (current->semun)
  2781.          sem_exit();
  2782.      if (current->shm)
  2783. diff -ru --new-file linux_1.1.58/kernel/fork.c linux_1.1.58_owld/kernel/fork.c
  2784. --- linux_1.1.58/kernel/fork.c    Thu Jul 28 12:37:51 1994
  2785. +++ linux_1.1.58_owld/kernel/fork.c    Thu Jul 28 12:45:27 1994
  2786. @@ -2,9 +2,7 @@
  2787.   *  linux/kernel/fork.c
  2788.   *
  2789.   *  Copyright (C) 1991, 1992  Linus Torvalds
  2790. - */
  2791. -
  2792. -/*
  2793. + *
  2794.   *  'fork.c' contains the help-routines for the 'fork' system call
  2795.   * (see also system_call.s).
  2796.   * Fork is rather simple, once you get the hang of it, but the memory
  2797. @@ -21,6 +19,7 @@
  2798.  #include <linux/ptrace.h>
  2799.  #include <linux/malloc.h>
  2800.  #include <linux/ldt.h>
  2801. +#include <linux/fileio.h>
  2802.  
  2803.  #include <asm/segment.h>
  2804.  #include <asm/system.h>
  2805. @@ -84,6 +83,7 @@
  2806.                  new_file->f_count = 0;
  2807.                  new_file = NULL;
  2808.              }
  2809. +            vfs_open(new_file);
  2810.          }
  2811.      }
  2812.      return new_file;
  2813. @@ -124,8 +124,10 @@
  2814.                  p->files->fd[i] = copy_fd(f);
  2815.      } else {
  2816.          for (i=0; i<NR_OPEN;i++)
  2817. -            if ((f = p->files->fd[i]) != NULL)
  2818. +            if ((f = p->files->fd[i]) != NULL) {
  2819.                  f->f_count++;
  2820. +                vfs_open(f);
  2821. +            }
  2822.      }
  2823.  }
  2824.  
  2825. @@ -188,7 +190,9 @@
  2826.      p->did_exec = 0;
  2827.      p->kernel_stack_page = 0;
  2828.      p->state = TASK_UNINTERRUPTIBLE;
  2829. -    p->flags &= ~(PF_PTRACED|PF_TRACESYS);
  2830. +    p->flags &= ~(PF_PTRACED|PF_TRACESYS|PF_SUPERPREV);
  2831. +    p->flags |= PF_FORKNOEXEC;
  2832. +    p->io_usage = 0; /* Child doesn't inherit parent's I/O usage */
  2833.      p->pid = last_pid;
  2834.      p->p_pptr = p->p_opptr = current;
  2835.      p->p_cptr = NULL;
  2836. diff -ru --new-file linux_1.1.58/kernel/printk.c linux_1.1.58_owld/kernel/printk.c
  2837. --- linux_1.1.58/kernel/printk.c    Sun Aug  7 20:54:32 1994
  2838. +++ linux_1.1.58_owld/kernel/printk.c    Sun Aug  7 20:56:05 1994
  2839. @@ -19,6 +19,8 @@
  2840.  #include <linux/errno.h>
  2841.  #include <linux/sched.h>
  2842.  #include <linux/kernel.h>
  2843. +#include <linux/tty.h>
  2844. +#include <linux/tty_driver.h>
  2845.  
  2846.  #define LOG_BUF_LEN    4096
  2847.  
  2848. @@ -226,4 +228,17 @@
  2849.              msg_level = -1;
  2850.          j = 0;
  2851.      }
  2852. +}
  2853. +
  2854. +/*
  2855. + * Write a message to a certain tty, not just the console. This is used for
  2856. + * messages that need to be redirected to a specific tty.
  2857. + * We don't put it into the syslog queue right now maybe in the future if
  2858. + * really needed.
  2859. + */
  2860. +void tty_write_message(struct tty_struct *tty, char *msg)
  2861. +{
  2862. +    if (tty && tty->driver.write)
  2863. +        tty->driver.write(tty, 0, msg, strlen(msg));
  2864. +    return;
  2865.  }
  2866. diff -ru --new-file linux_1.1.58/kernel/sys.c linux_1.1.58_owld/kernel/sys.c
  2867. --- linux_1.1.58/kernel/sys.c    Sun Oct 23 00:23:21 1994
  2868. +++ linux_1.1.58_owld/kernel/sys.c    Sun Oct 23 00:23:51 1994
  2869. @@ -17,6 +17,10 @@
  2870.  #include <linux/ptrace.h>
  2871.  #include <linux/stat.h>
  2872.  #include <linux/mman.h>
  2873. +#include <linux/tty.h>
  2874. +#include <linux/fcntl.h>
  2875. +#include <linux/acct.h>
  2876. +#include <linux/fileio.h>
  2877.  
  2878.  #include <asm/segment.h>
  2879.  #include <asm/io.h>
  2880. @@ -251,9 +255,128 @@
  2881.      return 0;
  2882.  }
  2883.  
  2884. -asmlinkage int sys_acct(void)
  2885. +static char acct_active = 0;
  2886. +static struct file *acct_file;
  2887. +#define    KSTK_ESP(stack)    (((unsigned long *) stack)[1022])
  2888. +
  2889. +int acct_process(void)
  2890. +{
  2891. +    struct acct ac;
  2892. +    unsigned short fs;
  2893. +    unsigned long vsize, esp;
  2894. +
  2895. +    if (acct_active) {
  2896. +        memset(&ac, 0, sizeof(struct acct));
  2897. +        strncpy(ac.ac_comm, current->comm, ACCT_COMM);
  2898. +        ac.ac_comm[ACCT_COMM] = '\0';
  2899. +        ac.ac_utime = current->utime;
  2900. +        ac.ac_stime = current->stime;
  2901. +        ac.ac_btime = CT_TO_SECS(current->start_time) + (xtime.tv_sec - (jiffies / HZ));
  2902. +        ac.ac_etime = CURRENT_TIME - ac.ac_btime;
  2903. +        ac.ac_uid   = current->uid;
  2904. +        ac.ac_gid   = current->gid;
  2905. +        ac.ac_tty   = (current->tty) ? MKDEV(4, current->tty->device) : MKDEV(4, -1);
  2906. +        ac.ac_flag  = 0;
  2907. +        if (current->flags & PF_FORKNOEXEC)
  2908. +            ac.ac_flag |= AFORK;
  2909. +        if (current->flags & PF_SUPERPREV)
  2910. +            ac.ac_flag |= ASU;
  2911. +        if (current->flags & PF_DUMPCORE)
  2912. +            ac.ac_flag |= ACORE;
  2913. +        if (current->flags & PF_SIGNALED)
  2914. +            ac.ac_flag |= AXSIG;
  2915. +        ac.ac_io    = current->io_usage;
  2916. +
  2917. +        /* Figure out the vsize of the current process and divide by the
  2918. +         * page size to calculate AC_MEM.  This is the approved method
  2919. +         * from the proc filesystem.
  2920. +         */
  2921. +        vsize = current->kernel_stack_page;
  2922. +        if (vsize) {
  2923. +            esp = KSTK_ESP(vsize);
  2924. +            vsize = current->mm->brk - current->mm->start_code + (PAGE_SIZE - 1);
  2925. +            if (esp)
  2926. +                vsize += TASK_SIZE - esp;
  2927. +        }
  2928. +        /* now vsize contains the number of bytes used -- we want to
  2929. +         * find out the number of pages, so divide it by the page size
  2930. +         * and round up.
  2931. +         */
  2932. +        ac.ac_mem = (vsize / PAGE_SIZE) + ((vsize % PAGE_SIZE) != 0);
  2933. +
  2934. +        /* Kernel segment override */
  2935. +        fs = get_fs();
  2936. +        set_fs(KERNEL_DS);
  2937. +
  2938. +        acct_file->f_op->write(acct_file->f_inode, acct_file,
  2939. +                      (char *)&ac, sizeof(struct acct));
  2940. +
  2941. +        set_fs(fs);
  2942. +    }
  2943. +    return 0;
  2944. +}
  2945. +
  2946. +extern void close_fp(struct file *, int);
  2947. +
  2948. +asmlinkage int sys_acct(const char *name)
  2949.  {
  2950. -    return -ENOSYS;
  2951. +    struct inode *inode = (struct inode *)0;
  2952. +    char *tmp;
  2953. +    int error;
  2954. +
  2955. +    if (!suser())
  2956. +        return -EPERM;
  2957. +
  2958. +    if (name == (char *)0) {
  2959. +        if (acct_active) {
  2960. +            acct_process(); 
  2961. +            acct_active = 0;
  2962. +            close_fp(acct_file, 0);
  2963. +        }
  2964. +        return 0;
  2965. +    } else {
  2966. +        if (!acct_active) {
  2967. +            if ((error = getname(name, &tmp)) != 0)
  2968. +                return (error);
  2969. +            error = open_namei(tmp, O_RDWR, 0600, &inode, 0);
  2970. +            putname(tmp);
  2971. +            if (error)
  2972. +                return (error);
  2973. +            if (!S_ISREG(inode->i_mode)) {
  2974. +                iput(inode);
  2975. +                return -EACCES;
  2976. +            }
  2977. +            if (!inode->i_op || !inode->i_op->default_file_ops || 
  2978. +                !inode->i_op->default_file_ops->write) {
  2979. +                iput(inode);
  2980. +                return -EIO;
  2981. +            }
  2982. +            if ((acct_file = get_empty_filp()) == (struct file *)0)
  2983. +                return -EUSERS;
  2984. +            acct_file->f_mode = (O_WRONLY + 1) & O_ACCMODE;
  2985. +            acct_file->f_flags = O_WRONLY;
  2986. +            acct_file->f_inode = inode;
  2987. +            acct_file->f_pos = inode->i_size;
  2988. +            acct_file->f_reada = 0;
  2989. +            acct_file->f_op = inode->i_op->default_file_ops;
  2990. +            if (acct_file->f_op->open)
  2991. +                if (acct_file->f_op->open(acct_file->f_inode, acct_file)) {
  2992. +                    iput(inode);
  2993. +                    return -EIO;
  2994. +                }
  2995. +
  2996. +            vfs_open(acct_file);
  2997. +            acct_active = 1;
  2998. +            return 0;
  2999. +        } else
  3000. +            return -EBUSY;
  3001. +    }
  3002. +}
  3003. +
  3004. +void acct_auto_close(dev_t dev)
  3005. +{
  3006. +    if (acct_active && acct_file && acct_file->f_inode->i_dev == dev)
  3007. +        sys_acct((char *)0);
  3008.  }
  3009.  
  3010.  asmlinkage int sys_phys(void)
  3011.