patch-2.1.122 linux/fs/umsdos/inode.c

Next file: linux/fs/umsdos/ioctl.c
Previous file: linux/fs/umsdos/file.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.121/linux/fs/umsdos/inode.c linux/fs/umsdos/inode.c
@@ -19,6 +19,7 @@
 #include <linux/umsdos_fs.h>
 #include <linux/list.h>
 
+extern struct dentry_operations umsdos_dentry_operations;
 extern struct inode_operations umsdos_rdir_inode_operations;
 
 
@@ -59,7 +60,7 @@
 void fill_new_filp (struct file *filp, struct dentry *dentry)
 {
 	if (!dentry)
-		printk("fill_new_filp: NULL dentry!\n");
+		printk(KERN_ERR "fill_new_filp: NULL dentry!\n");
 
 	memset (filp, 0, sizeof (struct file));
 	filp->f_reada = 1;
@@ -133,7 +134,7 @@
 		 ,inode->u.umsdos_i.i_emd_owner, inode->u.umsdos_i.pos
 		 ,inode->u.umsdos_i.i_emd_dir, inode->i_count));
 
-	if (inode && pseudo_root && inode == pseudo_root) {
+	if (inode == pseudo_root) {
 		printk (KERN_ERR "Umsdos: Oops releasing pseudo_root."
 			" Notify jacques@solucorp.qc.ca\n");
 	}
@@ -151,23 +152,6 @@
 
 
 /*
- * Call msdos_lookup, but set back the original msdos function table.
- * Return 0 if OK, or a negative error code if not.
- * Dentry will hold inode of the file, if successful
- */
-int umsdos_real_lookup (struct inode *dir, struct dentry *dentry)
-{
-	int ret;
-
-	PRINTK ((KERN_DEBUG "umsdos_real_lookup: looking for %s/%s /",
-		dentry->d_parent->d_name.name, dentry->d_name.name));
-	ret = msdos_lookup (dir, dentry);
-	PRINTK (("/ returned %d\n", ret));
-
-	return ret;
-}
-
-/*
  * Complete the setup of an directory dentry.
  * First, it completes the function pointers, then
  * it locates the EMD file. If the EMD is there, then plug the
@@ -230,6 +214,32 @@
 /*
  * Add some info into an inode so it can find its owner quickly
  */
+void umsdos_set_dirinfo_new (struct dentry *dentry, off_t f_pos)
+{
+	struct inode *inode = dentry->d_inode;
+	struct dentry *demd;
+
+	inode->u.umsdos_i.i_emd_owner = 0;
+	inode->u.umsdos_i.pos = f_pos;
+
+	/* now check the EMD file */
+	demd = umsdos_get_emd_dentry(dentry->d_parent);
+	if (IS_ERR(demd)) {
+		goto out;
+	}
+	if (demd->d_inode) {
+		inode->u.umsdos_i.i_emd_owner = demd->d_inode->i_ino;
+	}
+	dput (demd);
+out:
+	return;
+}
+
+
+/*
+ * Add some info into an inode so it can find its owner quickly
+ * Note: Deprecated; use above function if possible.
+ */
 void umsdos_set_dirinfo (struct inode *inode, struct inode *dir, off_t f_pos)
 {
 	struct inode *emd_owner = umsdos_emd_dir_lookup (dir, 1);
@@ -238,7 +248,6 @@
 		goto out;
 	Printk (("umsdos_set_dirinfo: emd_owner is %lu for dir %lu\n", 
 		emd_owner->i_ino, dir->i_ino));
-	inode->u.umsdos_i.i_dir_owner = dir->i_ino;
 	inode->u.umsdos_i.i_emd_owner = emd_owner->i_ino;
 	inode->u.umsdos_i.pos = f_pos;
 	iput (emd_owner);
@@ -405,20 +414,23 @@
 }
 
 
-/* #Specification: notify_change / i_nlink > 0
- * notify change is only done for inode with nlink > 0. An inode
- * with nlink == 0 is no longer associated with any entry in
- * the EMD file, so there is nothing to update.
- */
-static int internal_notify_change (struct inode *inode, struct iattr *attr)
+int UMSDOS_notify_change (struct dentry *dentry, struct iattr *attr)
 {
-	unsigned long i_emd_owner = inode->u.umsdos_i.i_emd_owner;
+	struct inode *inode = dentry->d_inode;
+	struct dentry *demd;
 	int ret;
+	struct file filp;
+	struct umsdos_dirent entry;
 
-	Printk ((KERN_DEBUG "UMSDOS_notify_change: entering\n"));
+Printk(("UMSDOS_notify_change: entering for %s/%s\n",
+dentry->d_parent->d_name.name, dentry->d_name.name));
 
-	if ((ret = inode_change_ok (inode, attr)) != 0)
+	ret = inode_change_ok (inode, attr);
+	if (ret) {
+printk("UMSDOS_notify_change: %s/%s change not OK, ret=%d\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, ret);
 		goto out;
+	}
 
 	if (inode->i_nlink == 0)
 		goto out_nolink;
@@ -426,61 +438,77 @@
 	if (inode->i_ino == UMSDOS_ROOT_INO)
 		goto out_nolink;
 
-	if (i_emd_owner != 0xffffffff && i_emd_owner != 0) {
-		/* This inode is not a EMD file nor an inode used internally
-		 * by MSDOS, so we can update its status.
-		 * See emd.c
-		 */
-		struct inode *emd_owner;
-		struct file filp;
-		struct umsdos_dirent entry;
-		struct dentry *emd_dentry;
-
-		Printk (("notify change %p ", inode));
-		ret = -EPERM;
-		emd_owner = iget (inode->i_sb, i_emd_owner);
-		if (!emd_owner) {
-			printk ("UMSDOS: emd_owner = NULL ???");
-			goto out_nolink;
-		}
-		emd_dentry = geti_dentry (emd_owner); /* FIXME? */
-		fill_new_filp (&filp, emd_dentry);
+	/* get the EMD file dentry */
+	demd = umsdos_get_emd_dentry(dentry->d_parent);
+	ret = PTR_ERR(demd);
+	if (IS_ERR(demd))
+		goto out_nolink;
+	ret = -EPERM;
+	if (!demd->d_inode) {
+		printk(KERN_WARNING
+			"UMSDOS_notify_change: no EMD file %s/%s\n",
+			demd->d_parent->d_name.name, demd->d_name.name);
+		goto out_dput;
+	}
+
+	ret = 0;
+	/* don't do anything if this is the EMD itself */
+	if (inode == demd->d_inode)
+		goto out_dput;
+
+	/* This inode is not a EMD file nor an inode used internally
+	 * by MSDOS, so we can update its status.
+	 * See emd.c
+	 */
 
-		filp.f_pos = inode->u.umsdos_i.pos;
-		filp.f_reada = 0;
-		Printk (("pos = %Lu ", filp.f_pos));
-		/* Read only the start of the entry since we don't touch */
-		/* the name */
-		ret = umsdos_emd_dir_read (&filp, (char *) &entry, 
-						UMSDOS_REC_SIZE);
-		if (!ret) {
-			if (attr->ia_valid & ATTR_UID)
-				entry.uid = attr->ia_uid;
-			if (attr->ia_valid & ATTR_GID)
-				entry.gid = attr->ia_gid;
-			if (attr->ia_valid & ATTR_MODE)
-				entry.mode = attr->ia_mode;
-			if (attr->ia_valid & ATTR_ATIME)
-				entry.atime = attr->ia_atime;
-			if (attr->ia_valid & ATTR_MTIME)
-				entry.mtime = attr->ia_mtime;
-			if (attr->ia_valid & ATTR_CTIME)
-				entry.ctime = attr->ia_ctime;
-
-			entry.nlink = inode->i_nlink;
-			filp.f_pos = inode->u.umsdos_i.pos;
-			ret = umsdos_emd_dir_write (&filp, (char *) &entry,
-							 UMSDOS_REC_SIZE);
-
-			Printk (("notify pos %lu ret %d nlink %d ",
-				inode->u.umsdos_i.pos, ret, entry.nlink));
-			/* #Specification: notify_change / msdos fs
-			 * notify_change operation are done only on the
-			 * EMD file. The msdos fs is not even called.
-			 */
-		}
-		iput(emd_owner);
-	}
+	fill_new_filp (&filp, demd);
+	filp.f_pos = inode->u.umsdos_i.pos;
+Printk(("UMSDOS_notify_change: %s/%s reading at %u\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, filp.f_pos));
+
+	/* Read only the start of the entry since we don't touch the name */
+	ret = umsdos_emd_dir_read (&filp, (char *) &entry, UMSDOS_REC_SIZE);
+	if (ret) {
+		printk(KERN_WARNING
+			"umsdos_notify_change: %s/%s EMD read error, ret=%d\n",
+			dentry->d_parent->d_name.name, dentry->d_name.name,ret);
+		goto out_dput;
+	}
+	if (attr->ia_valid & ATTR_UID)
+		entry.uid = attr->ia_uid;
+	if (attr->ia_valid & ATTR_GID)
+		entry.gid = attr->ia_gid;
+	if (attr->ia_valid & ATTR_MODE)
+		entry.mode = attr->ia_mode;
+	if (attr->ia_valid & ATTR_ATIME)
+		entry.atime = attr->ia_atime;
+	if (attr->ia_valid & ATTR_MTIME)
+		entry.mtime = attr->ia_mtime;
+	if (attr->ia_valid & ATTR_CTIME)
+		entry.ctime = attr->ia_ctime;
+
+	entry.nlink = inode->i_nlink;
+	filp.f_pos = inode->u.umsdos_i.pos;
+	ret = umsdos_emd_dir_write (&filp, (char *) &entry, UMSDOS_REC_SIZE);
+	if (ret)
+		printk(KERN_WARNING
+			"umsdos_notify_change: %s/%s EMD write error, ret=%d\n",
+			dentry->d_parent->d_name.name, dentry->d_name.name,ret);
+
+	Printk (("notify pos %lu ret %d nlink %d ",
+		inode->u.umsdos_i.pos, ret, entry.nlink));
+	/* #Specification: notify_change / msdos fs
+	 * notify_change operation are done only on the
+	 * EMD file. The msdos fs is not even called.
+	 */
+#ifdef UMSDOS_DEBUG_VERBOSE
+if (entry.flags & UMSDOS_HIDDEN)
+printk("umsdos_notify_change: %s/%s hidden, nlink=%d, ret=%d\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, entry.nlink, ret);
+#endif
+
+out_dput:
+	dput(demd);
 out_nolink:
 	if (ret == 0)
 		inode_setattr (inode, attr);
@@ -489,11 +517,6 @@
 }
 
 
-int UMSDOS_notify_change (struct dentry *dentry, struct iattr *attr)
-{
-	return internal_notify_change (dentry->d_inode, attr);
-}
-
 /*
  * Update the disk with the inode content
  */
@@ -551,16 +574,15 @@
 	if (!res)
 		goto out_fail;
 
-	printk (KERN_INFO "UMSDOS dentry-WIP-Beta 0.82-7 "
+	printk (KERN_INFO "UMSDOS dentry-Beta 0.83 "
 		"(compatibility level %d.%d, fast msdos)\n", 
 		UMSDOS_VERSION, UMSDOS_RELEASE);
 
 	sb->s_op = &umsdos_sops;
 	MSDOS_SB(sb)->options.dotsOK = 0;	/* disable hidden==dotfile */
 
-	/* FIXME:?? clear d_op on root so it will not be inherited */
-	sb->s_root->d_op = NULL;
-
+	/* install our dentry operations ... */
+	sb->s_root->d_op = &umsdos_dentry_operations;
 	pseudo = sb->s_root->d_inode;
 	umsdos_setup_dir(sb->s_root);
 
@@ -599,7 +621,7 @@
 	sbin = creat_dentry ("sbin", 4, NULL, root);
 
 	Printk ((KERN_DEBUG "Mounting root\n"));
-	if (umsdos_real_lookup (pseudo, root) == 0
+	if (msdos_lookup (pseudo, root) == 0
 	    && (root->d_inode != NULL)
 	    && S_ISDIR (root->d_inode->i_mode)) {
 
@@ -609,7 +631,7 @@
 		etc = creat_dentry ("etc", 3, NULL, root);
 
 
-		if (umsdos_real_lookup (pseudo, etc) == 0
+		if (msdos_lookup (pseudo, etc) == 0
 		    && S_ISDIR (etc->d_inode->i_mode)) {
 
 Printk ((KERN_DEBUG "/%s/etc is there\n", UMSDOS_PSDROOT_NAME));
@@ -617,9 +639,9 @@
 			init = creat_dentry ("init", 4, NULL, etc);
 			etc_rc = creat_dentry ("rc", 2, NULL, etc);
 
-			if ((umsdos_real_lookup (pseudo, init) == 0
+			if ((msdos_lookup (pseudo, init) == 0
 			     && S_ISREG (init->d_inode->i_mode))
-			    || (umsdos_real_lookup (pseudo, etc_rc) == 0
+			    || (msdos_lookup (pseudo, etc_rc) == 0
 			 && S_ISREG (etc_rc->d_inode->i_mode))) {
 				pseudo_ok = 1;
 			}
@@ -629,12 +651,12 @@
 			/* iput(rc); */
 		}
 		if (!pseudo_ok
-		/* && umsdos_real_lookup (pseudo, "sbin", 4, sbin)==0 */
-		    && umsdos_real_lookup (pseudo, sbin) == 0
+		/* && msdos_lookup (pseudo, "sbin", 4, sbin)==0 */
+		    && msdos_lookup (pseudo, sbin) == 0
 		    && S_ISDIR (sbin->d_inode->i_mode)) {
 
 Printk ((KERN_DEBUG "/%s/sbin is there\n", UMSDOS_PSDROOT_NAME));
-			if (umsdos_real_lookup (pseudo, init) == 0
+			if (msdos_lookup (pseudo, init) == 0
 			    && S_ISREG (init->d_inode->i_mode)) {
 				pseudo_ok = 1;
 			}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov