NTFS: Fix compilation when configured read-only.
Anton Altaparmakov [Thu, 17 Mar 2005 10:51:33 +0000 (10:51 +0000)]
- Add ifdef NTFS_RW around write specific code if fs/ntfs/runlist.[hc] and
  fs/ntfs/attrib.[hc].
- Minor bugfix to fs/ntfs/attrib.c::ntfs_attr_make_non_resident() where the
  runlist was not freed in all error cases.
- Add fs/ntfs/runlist.[hc]::ntfs_rl_find_vcn_nolock().

Signed-off-by: Anton Altaparmakov <aia21@cantab.net>

fs/ntfs/attrib.c
fs/ntfs/attrib.h
fs/ntfs/lcnalloc.c
fs/ntfs/runlist.c
fs/ntfs/runlist.h

index 97e6fb0..1b95f39 100644 (file)
@@ -1057,6 +1057,8 @@ void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx)
        return;
 }
 
+#ifdef NTFS_RW
+
 /**
  * ntfs_attr_find_in_attrdef - find an attribute in the $AttrDef system file
  * @vol:       ntfs volume to which the attribute belongs
@@ -1243,6 +1245,13 @@ int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size)
  *     -ENOSPC - Not enough disk space.
  *     -EINVAL - Attribute not defined on the volume.
  *     -EIO    - I/o error or other error.
+ * Note that -ENOSPC is also returned in the case that there is not enough
+ * space in the mft record to do the conversion.  This can happen when the mft
+ * record is already very full.  The caller is responsible for trying to make
+ * space in the mft record and trying again.  FIXME: Do we need a separate
+ * error return code for this kind of -ENOSPC or is it always worth trying
+ * again in case the attribute may then fit in a resident state so no need to
+ * make it non-resident at all?  Ho-hum...  (AIA)
  *
  * NOTE to self: No changes in the attribute list are required to move from
  *              a resident to a non-resident attribute.
@@ -1520,13 +1529,13 @@ err_out:
 rl_err_out:
        if (rl) {
                if (ntfs_cluster_free_from_rl(vol, rl) < 0) {
-                       ntfs_free(rl);
                        ntfs_error(vol->sb, "Failed to release allocated "
                                        "cluster(s) in error code path.  Run "
                                        "chkdsk to recover the lost "
                                        "cluster(s).");
                        NVolSetErrors(vol);
                }
+               ntfs_free(rl);
 page_err_out:
                unlock_page(page);
                page_cache_release(page);
@@ -1680,3 +1689,5 @@ done:
        ntfs_debug("Done.");
        return 0;
 }
+
+#endif /* NTFS_RW */
index d733851..0e4ac6d 100644 (file)
@@ -89,6 +89,8 @@ extern ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni,
                MFT_RECORD *mrec);
 extern void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx);
 
+#ifdef NTFS_RW
+
 extern int ntfs_attr_size_bounds_check(const ntfs_volume *vol,
                const ATTR_TYPE type, const s64 size);
 extern int ntfs_attr_can_be_non_resident(const ntfs_volume *vol,
@@ -103,4 +105,6 @@ extern int ntfs_attr_make_non_resident(ntfs_inode *ni);
 extern int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt,
                const u8 val);
 
+#endif /* NTFS_RW */
+
 #endif /* _LINUX_NTFS_ATTRIB_H */
index 71bf087..7087b5b 100644 (file)
@@ -848,7 +848,6 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
 
        total_freed = real_freed = 0;
 
-       /* This returns with ni->runlist locked for reading on success. */
        down_read(&ni->runlist.lock);
        rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, FALSE);
        if (IS_ERR(rl)) {
index 3f479f1..396d767 100644 (file)
@@ -980,6 +980,39 @@ LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn)
        return LCN_ENOENT;
 }
 
+#ifdef NTFS_RW
+
+/**
+ * ntfs_rl_find_vcn_nolock - find a vcn in a runlist
+ * @rl:                runlist to search
+ * @vcn:       vcn to find
+ *
+ * Find the virtual cluster number @vcn in the runlist @rl and return the
+ * address of the runlist element containing the @vcn on success.
+ *
+ * Return NULL if @rl is NULL or @vcn is in an unmapped part/out of bounds of
+ * the runlist.
+ *
+ * Locking: The runlist must be locked on entry.
+ */
+runlist_element *ntfs_rl_find_vcn_nolock(runlist_element *rl, const VCN vcn)
+{
+       BUG_ON(vcn < 0);
+       if (unlikely(!rl || vcn < rl[0].vcn))
+               return NULL;
+       while (likely(rl->length)) {
+               if (unlikely(vcn < rl[1].vcn)) {
+                       if (likely(rl->lcn >= LCN_HOLE))
+                               return rl;
+                       return NULL;
+               }
+               rl++;
+       }
+       if (likely(rl->lcn == LCN_ENOENT))
+               return rl;
+       return NULL;
+}
+
 /**
  * ntfs_get_nr_significant_bytes - get number of bytes needed to store a number
  * @n:         number for which to get the number of bytes for
@@ -1452,3 +1485,5 @@ int ntfs_rl_truncate_nolock(const ntfs_volume *vol, runlist *const runlist,
        ntfs_debug("Done.");
        return 0;
 }
+
+#endif /* NTFS_RW */
index 60c42f3..cf5c1b4 100644 (file)
@@ -2,7 +2,7 @@
  * runlist.h - Defines for runlist handling in NTFS Linux kernel driver.
  *            Part of the Linux-NTFS project.
  *
- * Copyright (c) 2001-2004 Anton Altaparmakov
+ * Copyright (c) 2001-2005 Anton Altaparmakov
  * Copyright (c) 2002 Richard Russon
  *
  * This program/include file is free software; you can redistribute it and/or
@@ -78,6 +78,11 @@ extern runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol,
 
 extern LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn);
 
+#ifdef NTFS_RW
+
+extern runlist_element *ntfs_rl_find_vcn_nolock(runlist_element *rl,
+               const VCN vcn);
+
 extern int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
                const runlist_element *rl, const VCN start_vcn);
 
@@ -88,4 +93,6 @@ extern int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst,
 extern int ntfs_rl_truncate_nolock(const ntfs_volume *vol,
                runlist *const runlist, const s64 new_length);
 
+#endif /* NTFS_RW */
+
 #endif /* _LINUX_NTFS_RUNLIST_H */